Browse Source

Implementing Array.prototype.indexOf

Sebastien Ros 12 years ago
parent
commit
de29b7289d

+ 0 - 1
Fix.playlist

@@ -1 +0,0 @@
-<Playlist Version="1.0"><Add Test="Jint.Tests.Ecma.Test_9_8_1.ReturnTheStringConsistingOfTheMostSignificantDigitOfTheDecimalRepresentationOfSFollowedByADecimalPointFollowedByTheRemainingK1DigitsOfTheDecimalRepresentationOfSFollowedByTheLowercaseCharacterEFollowedByAPlusSignOrMinusSignAccordingToWhetherN1IsPositiveOrNegativeFollowedByTheDecimalRepresentationOfTheIntegerAbsN1WithNoLeadingZeros" /><Add Test="Jint.Tests.Ecma.Test_9_8_1.If1S1E21Or1E21S1ReturnTheStringConsistingOfTheKDigitsOfTheDecimalRepresentationOfSInOrderWithNoLeadingZeroesFollowedByNKOccurrencesOfTheCharacter0" /><Add Test="Jint.Tests.Ecma.Test_9_8_1.If1S1And6N0ReturnTheStringConsistingOfTheCharacter0FollowedByADecimalPointFollowedByNOccurrencesOfTheCharacter0FollowedByTheKDigitsOfTheDecimalRepresentationOfS" /><Add Test="Jint.Tests.Ecma.Test_9_8_1.ReturnTheStringConsistingOfTheSingleDigitOfSFollowedByLowercaseCharacterEFollowedByAPlusSignOrMinusSignAccordingToWhetherN1IsPositiveOrNegativeFollowedByTheDecimalRepresentationOfTheIntegerAbsN1WithNoLeadingZeros" /><Add Test="Jint.Tests.Ecma.Test_9_8_1.ReturnTheStringConsistingOfTheSingleDigitOfSFollowedByLowercaseCharacterEFollowedByAPlusSignOrMinusSignAccordingToWhetherN1IsPositiveOrNegativeFollowedByTheDecimalRepresentationOfTheIntegerAbsN1WithNoLeadingZeros2" /><Add Test="Jint.Tests.Ecma.Test_9_8_1.IfMIsNanReturnTheStringNan" /><Add Test="Jint.Tests.Ecma.Test_9_8_1.IfMIs0Or0ReturnTheString0" /><Add Test="Jint.Tests.Ecma.Test_9_8_1.IfMIsLessThanZeroReturnTheStringConcatenationOfTheStringAndTostringM" /><Add Test="Jint.Tests.Ecma.Test_9_8_1.IfMIsInfinityReturnTheStringInfinity" /><Add Test="Jint.Tests.Ecma.Test_9_8_1.If1S1E21Or1E21S1AndSHasAFractionalComponentReturnTheStringConsistingOfTheMostSignificantNDigitsOfTheDecimalRepresentationOfSFollowedByADecimalPointFollowedByTheRemainingKNDigitsOfTheDecimalRepresentationOfS" /></Playlist>

+ 13 - 4
Jint.Repl/Program.cs

@@ -20,10 +20,19 @@ namespace Jint.Repl
                     return;
                     return;
                 }
                 }
 
 
-                var result = engine.GetValue(engine.Execute(input));
-                var str = engine.Json.Stringify(engine.Json, Arguments.From(result, Undefined.Instance, "  "));
-                Console.ForegroundColor = ConsoleColor.Magenta;
-                Console.WriteLine("=> {0}", str);
+                try
+                {
+                    var result = engine.GetValue(engine.Execute(input));
+                    var str = engine.Json.Stringify(engine.Json, Arguments.From(result, Undefined.Instance, "  "));
+                    Console.ForegroundColor = ConsoleColor.Magenta;
+                    Console.WriteLine("=> {0}", str);
+                }
+                catch (JavaScriptException je)
+                {
+                    Console.ForegroundColor = ConsoleColor.Red;
+                    Console.WriteLine("Error => {0}", engine.Json.Stringify(engine.Json, Arguments.From(je.Error, Undefined.Instance, "  ")));
+                }
+                
             }
             }
         }
         }
     }
     }

+ 6 - 0
Jint/Engine.cs

@@ -12,6 +12,7 @@ using Jint.Native.Json;
 using Jint.Native.Math;
 using Jint.Native.Math;
 using Jint.Native.Number;
 using Jint.Native.Number;
 using Jint.Native.Object;
 using Jint.Native.Object;
+using Jint.Native.RegExp;
 using Jint.Native.String;
 using Jint.Native.String;
 using Jint.Parser;
 using Jint.Parser;
 using Jint.Parser.Ast;
 using Jint.Parser.Ast;
@@ -44,6 +45,7 @@ namespace Jint
 
 
             Array = ArrayConstructor.CreateArrayConstructor(this);
             Array = ArrayConstructor.CreateArrayConstructor(this);
             String = StringConstructor.CreateStringConstructor(this);
             String = StringConstructor.CreateStringConstructor(this);
+            RegExp = RegExpConstructor.CreateRegExpConstructor(this);
             Number = NumberConstructor.CreateNumberConstructor(this);
             Number = NumberConstructor.CreateNumberConstructor(this);
             Boolean = BooleanConstructor.CreateBooleanConstructor(this);
             Boolean = BooleanConstructor.CreateBooleanConstructor(this);
             Date = DateConstructor.CreateDateConstructor(this);
             Date = DateConstructor.CreateDateConstructor(this);
@@ -75,6 +77,9 @@ namespace Jint
             String.Configure();
             String.Configure();
             String.PrototypeObject.Configure();
             String.PrototypeObject.Configure();
 
 
+            RegExp.Configure();
+            RegExp.PrototypeObject.Configure();
+
             Number.Configure();
             Number.Configure();
             Number.PrototypeObject.Configure();
             Number.PrototypeObject.Configure();
 
 
@@ -124,6 +129,7 @@ namespace Jint
         public FunctionConstructor Function { get; private set; }
         public FunctionConstructor Function { get; private set; }
         public ArrayConstructor Array { get; private set; }
         public ArrayConstructor Array { get; private set; }
         public StringConstructor String { get; private set; }
         public StringConstructor String { get; private set; }
+        public RegExpConstructor RegExp { get; private set; }
         public BooleanConstructor Boolean { get; private set; }
         public BooleanConstructor Boolean { get; private set; }
         public NumberConstructor Number { get; private set; }
         public NumberConstructor Number { get; private set; }
         public DateConstructor Date { get; private set; }
         public DateConstructor Date { get; private set; }

+ 3 - 0
Jint/Jint.csproj

@@ -43,6 +43,9 @@
     <Compile Include="Native\Boolean\BooleanPrototype.cs" />
     <Compile Include="Native\Boolean\BooleanPrototype.cs" />
     <Compile Include="Native\Boolean\BooleanConstructor.cs" />
     <Compile Include="Native\Boolean\BooleanConstructor.cs" />
     <Compile Include="Native\Boolean\BooleanInstance.cs" />
     <Compile Include="Native\Boolean\BooleanInstance.cs" />
+    <Compile Include="Native\RegExp\RegExpConstructor.cs" />
+    <Compile Include="Native\RegExp\RegExpInstance.cs" />
+    <Compile Include="Native\RegExp\RegExpPrototype.cs" />
     <Compile Include="Native\Date\DatePrototype.cs" />
     <Compile Include="Native\Date\DatePrototype.cs" />
     <Compile Include="Native\Date\DateConstructor.cs" />
     <Compile Include="Native\Date\DateConstructor.cs" />
     <Compile Include="Native\Date\DateInstance.cs" />
     <Compile Include="Native\Date\DateInstance.cs" />

+ 44 - 3
Jint/Native/Array/ArrayPrototype.cs

@@ -45,7 +45,7 @@ namespace Jint.Native.Array
             FastAddProperty("sort", new ClrFunctionInstance<object, ObjectInstance>(Engine, Sort, 1), true, false, true);
             FastAddProperty("sort", new ClrFunctionInstance<object, ObjectInstance>(Engine, Sort, 1), true, false, true);
             FastAddProperty("splice", new ClrFunctionInstance<object, ObjectInstance>(Engine, Splice, 2), true, false, true);
             FastAddProperty("splice", new ClrFunctionInstance<object, ObjectInstance>(Engine, Splice, 2), true, false, true);
             FastAddProperty("unshift", new ClrFunctionInstance<object, uint>(Engine, Unshift, 1), true, false, true);
             FastAddProperty("unshift", new ClrFunctionInstance<object, uint>(Engine, Unshift, 1), true, false, true);
-            FastAddProperty("indexOf", new ClrFunctionInstance<ArrayInstance, object>(Engine, IndexOf), true, false, true);
+            FastAddProperty("indexOf", new ClrFunctionInstance<object, int>(Engine, IndexOf, 1), true, false, true);
             FastAddProperty("lastIndexOf", new ClrFunctionInstance<ArrayInstance, object>(Engine, LastIndexOf), true, false, true);
             FastAddProperty("lastIndexOf", new ClrFunctionInstance<ArrayInstance, object>(Engine, LastIndexOf), true, false, true);
             FastAddProperty("every", new ClrFunctionInstance<ArrayInstance, object>(Engine, Every), true, false, true);
             FastAddProperty("every", new ClrFunctionInstance<ArrayInstance, object>(Engine, Every), true, false, true);
             FastAddProperty("some", new ClrFunctionInstance<ArrayInstance, object>(Engine, Some), true, false, true);
             FastAddProperty("some", new ClrFunctionInstance<ArrayInstance, object>(Engine, Some), true, false, true);
@@ -91,9 +91,50 @@ namespace Jint.Native.Array
             throw new NotImplementedException();
             throw new NotImplementedException();
         }
         }
 
 
-        private object IndexOf(ArrayInstance arg1, object[] arg2)
+        private int IndexOf(object thisObj, object[] arguments)
         {
         {
-            throw new NotImplementedException();
+            var o = TypeConverter.ToObject(Engine, thisObj);
+            var lenValue = o.Get("length");
+            var len = TypeConverter.ToUint32(lenValue);
+            if (len == 0)
+            {
+                return -1;
+            }
+
+            var n = arguments.Length > 1 ? (int)TypeConverter.ToInteger(arguments[1]) : 0;
+            if (n >= len)
+            {
+                return -1;
+            }
+            int k;
+            if (n >= 0)
+            {
+                k = n;
+            }
+            else
+            {
+                k = (int)len - System.Math.Abs(n);
+                if (k < 0)
+                {
+                    k = 0;
+                }
+            }
+            var searchElement = arguments.Length > 0 ? arguments[0] : Undefined.Instance;
+            for (; k < len; k++)
+            {
+                var kString = TypeConverter.ToString(k);
+                var kPresent = o.HasProperty(kString);
+                if (kPresent)
+                {
+                    var elementK = o.Get(kString);
+                    var same = ExpressionInterpreter.StriclyEqual(elementK, searchElement);
+                    if (same)
+                    {
+                        return k;
+                    }
+                }
+            }
+            return -1;
         }
         }
 
 
         private ObjectInstance Splice(object thisObj, object[] arguments)
         private ObjectInstance Splice(object thisObj, object[] arguments)

+ 1 - 0
Jint/Native/Boolean/BooleanPrototype.cs

@@ -19,6 +19,7 @@ namespace Jint.Native.Boolean
             var obj = new BooleanPrototype(engine);
             var obj = new BooleanPrototype(engine);
             obj.Prototype = engine.Object.PrototypeObject;
             obj.Prototype = engine.Object.PrototypeObject;
             obj.PrimitiveValue = false;
             obj.PrimitiveValue = false;
+            obj.Extensible = true;
 
 
             obj.FastAddProperty("constructor", booleanConstructor, false, false, false);
             obj.FastAddProperty("constructor", booleanConstructor, false, false, false);
 
 

+ 1 - 0
Jint/Native/Date/DatePrototype.cs

@@ -16,6 +16,7 @@ namespace Jint.Native.Date
         {
         {
             var obj = new DatePrototype(engine);
             var obj = new DatePrototype(engine);
             obj.Prototype = engine.Object.PrototypeObject;
             obj.Prototype = engine.Object.PrototypeObject;
+            obj.Extensible = true;
 
 
             obj.FastAddProperty("constructor", dateConstructor, false, false, false);
             obj.FastAddProperty("constructor", dateConstructor, false, false, false);
 
 

+ 1 - 0
Jint/Native/Global/GlobalObject.cs

@@ -28,6 +28,7 @@ namespace Jint.Native.Global
             FastAddProperty("Function", Engine.Function, true, false, true);
             FastAddProperty("Function", Engine.Function, true, false, true);
             FastAddProperty("Array", Engine.Array, true, false, true);
             FastAddProperty("Array", Engine.Array, true, false, true);
             FastAddProperty("String", Engine.String, true, false, true);
             FastAddProperty("String", Engine.String, true, false, true);
+            FastAddProperty("RegExp", Engine.RegExp, true, false, true);
             FastAddProperty("Number", Engine.Number, true, false, true);
             FastAddProperty("Number", Engine.Number, true, false, true);
             FastAddProperty("Boolean", Engine.Boolean, true, false, true);
             FastAddProperty("Boolean", Engine.Boolean, true, false, true);
             FastAddProperty("Date", Engine.Date, true, false, true);
             FastAddProperty("Date", Engine.Date, true, false, true);

+ 1 - 0
Jint/Native/Number/NumberPrototype.cs

@@ -18,6 +18,7 @@ namespace Jint.Native.Number
             var obj = new NumberPrototype(engine);
             var obj = new NumberPrototype(engine);
             obj.Prototype = engine.Object.PrototypeObject;
             obj.Prototype = engine.Object.PrototypeObject;
             obj.PrimitiveValue = 0;
             obj.PrimitiveValue = 0;
+            obj.Extensible = true;
 
 
             obj.FastAddProperty("constructor", numberConstructor, false, false, false);
             obj.FastAddProperty("constructor", numberConstructor, false, false, false);
 
 

+ 2 - 2
Jint/Native/Object/ObjectInstance.cs

@@ -60,7 +60,7 @@ namespace Jint.Native.Object
 
 
             var getter = desc.As<AccessorDescriptor>().Get;
             var getter = desc.As<AccessorDescriptor>().Get;
 
 
-            return getter.Call(this, null);
+            return getter.Call(this, Arguments.Empty);
         }
         }
 
 
         public void Set(string name, object value)
         public void Set(string name, object value)
@@ -212,7 +212,7 @@ namespace Jint.Native.Object
 
 
             if (inherited == PropertyDescriptor.Undefined)
             if (inherited == PropertyDescriptor.Undefined)
             {
             {
-                return Prototype.Extensible;
+                return Extensible;
             }
             }
 
 
             if (inherited.IsAccessorDescriptor())
             if (inherited.IsAccessorDescriptor())

+ 68 - 0
Jint/Native/RegExp/RegExpConstructor.cs

@@ -0,0 +1,68 @@
+using Jint.Native.Function;
+using Jint.Native.Object;
+using Jint.Runtime;
+using Jint.Runtime.Interop;
+
+namespace Jint.Native.RegExp
+{
+    public sealed class RegExpConstructor : FunctionInstance, IConstructor
+    {
+        public RegExpConstructor(Engine engine)
+            : base(engine, null, null, false)
+        {
+        }
+
+        public static RegExpConstructor CreateRegExpConstructor(Engine engine)
+        {
+            var obj = new RegExpConstructor(engine);
+            obj.Extensible = true;
+
+            // The value of the [[Prototype]] internal property of the RegExp constructor is the Function prototype object 
+            obj.Prototype = engine.Function.PrototypeObject;
+            obj.PrototypeObject = RegExpPrototype.CreatePrototypeObject(engine, obj);
+
+            obj.FastAddProperty("length", 1, false, false, false);
+
+            // The initial value of RegExp.prototype is the RegExp prototype object
+            obj.FastAddProperty("prototype", obj.PrototypeObject, false, false, false);
+
+            return obj;
+        }
+
+        public void Configure()
+        {
+        }
+
+        public override object Call(object thisObject, object[] arguments)
+        {
+            if (arguments.Length == 0)
+            {
+                return "";
+            }
+
+            return TypeConverter.ToString(arguments[0]);
+        }
+
+        /// <summary>
+        /// http://www.ecma-international.org/ecma-262/5.1/#sec-15.7.2.1
+        /// </summary>
+        /// <param name="arguments"></param>
+        /// <returns></returns>
+        public ObjectInstance Construct(object[] arguments)
+        {
+            return Construct(arguments.Length > 0 ? TypeConverter.ToString(arguments[0]) : "");
+        }
+
+        public RegExpPrototype PrototypeObject { get; private set; }
+
+        public RegExpInstance Construct(string value)
+        {
+            var instance = new RegExpInstance(Engine);
+            instance.Prototype = PrototypeObject;
+            instance.PrimitiveValue = value;
+            instance.Extensible = true;
+
+            return instance;
+        }
+    }
+}

+ 36 - 0
Jint/Native/RegExp/RegExpInstance.cs

@@ -0,0 +1,36 @@
+using System;
+using Jint.Native.Object;
+
+namespace Jint.Native.RegExp
+{
+    public class RegExpInstance : ObjectInstance, IPrimitiveType
+    {
+        private readonly Engine _engine;
+
+        public RegExpInstance(Engine engine)
+            : base(engine)
+        {
+            _engine = engine;
+        }
+
+        public override string Class
+        {
+            get
+            {
+                return "RegExp";
+            }
+        }
+
+        TypeCode IPrimitiveType.TypeCode
+        {
+            get { return TypeCode.Boolean; }
+        }
+
+        object IPrimitiveType.PrimitiveValue
+        {
+            get { return PrimitiveValue; }
+        }
+
+        public string PrimitiveValue { get; set; }
+    }
+}

+ 26 - 0
Jint/Native/RegExp/RegExpPrototype.cs

@@ -0,0 +1,26 @@
+namespace Jint.Native.RegExp
+{
+    public sealed class RegExpPrototype : RegExpInstance
+    {
+        private RegExpPrototype(Engine engine)
+            : base(engine)
+        {
+        }
+
+        public static RegExpPrototype CreatePrototypeObject(Engine engine, RegExpConstructor regExpConstructor)
+        {
+            var obj = new RegExpPrototype(engine);
+            obj.Prototype = engine.Object.PrototypeObject;
+            obj.PrimitiveValue = "";
+            obj.Extensible = true;
+
+            obj.FastAddProperty("constructor", regExpConstructor, false, false, false);
+
+            return obj;
+        }
+
+        public void Configure()
+        {
+        }
+    }
+}

+ 2 - 0
Jint/Native/String/StringConstructor.cs

@@ -74,6 +74,8 @@ namespace Jint.Native.String
             instance.PrimitiveValue = value;
             instance.PrimitiveValue = value;
             instance.Extensible = true;
             instance.Extensible = true;
 
 
+            instance.FastAddProperty("length", value.Length, false, false, false);
+
             return instance;
             return instance;
         }
         }
     }
     }

+ 22 - 3
Jint/Native/String/StringInstance.cs

@@ -1,5 +1,7 @@
 using System;
 using System;
 using Jint.Native.Object;
 using Jint.Native.Object;
+using Jint.Runtime;
+using Jint.Runtime.Descriptors;
 
 
 namespace Jint.Native.String
 namespace Jint.Native.String
 {
 {
@@ -33,11 +35,28 @@ namespace Jint.Native.String
 
 
         public string PrimitiveValue { get; set; }
         public string PrimitiveValue { get; set; }
 
 
-        public override Runtime.Descriptors.PropertyDescriptor GetOwnProperty(string propertyName)
+        public override PropertyDescriptor GetOwnProperty(string propertyName)
         {
         {
-            // todo: http://www.ecma-international.org/ecma-262/5.1/#sec-15.5.5.2
+            var desc = base.GetOwnProperty(propertyName);
+            if (desc != PropertyDescriptor.Undefined)
+            {
+                return desc;
+            }
 
 
-            return base.GetOwnProperty(propertyName);
+            if (propertyName != System.Math.Abs(TypeConverter.ToInteger(propertyName)).ToString())
+            {
+                return PropertyDescriptor.Undefined;
+            }
+
+            var str = PrimitiveValue;
+            var index = (int)TypeConverter.ToInteger(propertyName);
+            var len = str.Length;
+            if (len <= index)
+            {
+                return PropertyDescriptor.Undefined;
+            }
+            var resultStr = str[index].ToString();
+            return new DataDescriptor(resultStr) {Enumerable = true, Writable = false, Configurable = false};
         }
         }
     }
     }
 }
 }

+ 1 - 0
Jint/Native/String/StringPrototype.cs

@@ -19,6 +19,7 @@ namespace Jint.Native.String
             var obj = new StringPrototype(engine);
             var obj = new StringPrototype(engine);
             obj.Prototype = engine.Object.PrototypeObject;
             obj.Prototype = engine.Object.PrototypeObject;
             obj.PrimitiveValue = "";
             obj.PrimitiveValue = "";
+            obj.Extensible = true;
 
 
             obj.FastAddProperty("constructor", stringConstructor, false, false, false);
             obj.FastAddProperty("constructor", stringConstructor, false, false, false);
 
 

+ 43 - 2
Jint/Runtime/ExpressionIntepreter.cs

@@ -447,7 +447,7 @@ namespace Jint.Runtime
 
 
             return false;
             return false;
         }
         }
-        
+
         public static bool StriclyEqual(object x, object y)
         public static bool StriclyEqual(object x, object y)
         {
         {
             var typea = TypeConverter.GetType(x);
             var typea = TypeConverter.GetType(x);
@@ -456,7 +456,7 @@ namespace Jint.Runtime
             if (typea != typeb)
             if (typea != typeb)
             {
             {
                 return false;
                 return false;
-            }    
+            }
 
 
             if (typea == TypeCode.Empty)
             if (typea == TypeCode.Empty)
             {
             {
@@ -471,6 +471,47 @@ namespace Jint.Runtime
                     return false;
                     return false;
                 }
                 }
 
 
+                if (nx == ny)
+                {
+                    return true;
+                }
+
+                return false;
+            }
+            if (typea == TypeCode.String)
+            {
+                return TypeConverter.ToString(x) == TypeConverter.ToString(y);
+            }
+            if (typea == TypeCode.Boolean)
+            {
+                return TypeConverter.ToBoolean(x) == TypeConverter.ToBoolean(y);
+            }
+            return x == y;
+        }
+
+        public static bool SameValue(object x, object y)
+        {
+            var typea = TypeConverter.GetType(x);
+            var typeb = TypeConverter.GetType(y);
+
+            if (typea != typeb)
+            {
+                return false;
+            }
+
+            if (typea == TypeCode.Empty)
+            {
+                return true;
+            }
+            if (typea == TypeCode.Double)
+            {
+                var nx = TypeConverter.ToNumber(x);
+                var ny = TypeConverter.ToNumber(y);
+                if (double.IsNaN(nx) && double.IsNaN(ny))
+                {
+                    return true;
+                }
+
                 if (nx == ny)
                 if (nx == ny)
                 {
                 {
                     if (nx == 0)
                     if (nx == 0)

+ 6 - 0
Jint/Runtime/TypeConverter.cs

@@ -176,6 +176,12 @@ namespace Jint.Runtime
                 {
                 {
                     if (!s.StartsWith("0x", StringComparison.OrdinalIgnoreCase))
                     if (!s.StartsWith("0x", StringComparison.OrdinalIgnoreCase))
                     {
                     {
+                        var start = s[0];
+                        if (start != '+' && start != '-' && start != '.' && !char.IsDigit(start))
+                        {
+                            return double.NaN;
+                        }
+
                         n = Double.Parse(s,
                         n = Double.Parse(s,
                                          NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign |
                                          NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign |
                                          NumberStyles.AllowLeadingWhite | NumberStyles.AllowTrailingWhite |
                                          NumberStyles.AllowLeadingWhite | NumberStyles.AllowTrailingWhite |