Browse Source

Fixing Arguments tests

Sebastien Ros 12 years ago
parent
commit
7f407c54c8

+ 1 - 0
Jint.Tests.Ecma/Ecma/10.4.3.cs

@@ -2,6 +2,7 @@ using Xunit;
 
 namespace Jint.Tests.Ecma
 {
+    [Trait("Category", "Pass")]
     public class Test_10_4_3 : EcmaTest
     {
         [Fact]

+ 1 - 0
Jint.Tests.Ecma/Ecma/10.4A1.1.cs

@@ -2,6 +2,7 @@ using Xunit;
 
 namespace Jint.Tests.Ecma
 {
+    [Trait("Category", "Pass")]
     public class Test_10_4A1_1 : EcmaTest
     {
         [Fact]

+ 1 - 0
Jint.Tests.Ecma/Ecma/10.5.cs

@@ -2,6 +2,7 @@ using Xunit;
 
 namespace Jint.Tests.Ecma
 {
+    [Trait("Category", "Pass")]
     public class Test_10_5 : EcmaTest
     {
         [Fact]

+ 1 - 0
Jint.Tests.Ecma/Ecma/10.6.cs

@@ -2,6 +2,7 @@ using Xunit;
 
 namespace Jint.Tests.Ecma
 {
+    [Trait("Category", "Pass")]
     public class Test_10_6 : EcmaTest
     {
         [Fact]

+ 90 - 3
Jint/Native/Argument/ArgumentsObject.cs

@@ -19,6 +19,8 @@ namespace Jint.Native.Argument
             // todo: complete implementation
         }
 
+        public bool Strict { get; set; }
+
         public static ArgumentsInstance CreateArgumentsObject(Engine engine, FunctionInstance func, string[] names, object[] args, EnvironmentRecord env, bool strict)
         {
             var len = args.Length;
@@ -26,6 +28,7 @@ namespace Jint.Native.Argument
             obj.Prototype = engine.Object.PrototypeObject;
             obj.Extensible = true;
             obj.FastAddProperty("length", len, true, false, true);
+            obj.Strict = strict;
             var map = engine.Object.Construct(Arguments.Empty);
             var mappedNamed = new List<string>();
             var indx = len - 1;
@@ -40,22 +43,27 @@ namespace Jint.Native.Argument
                     if (!strict && !mappedNamed.Contains(name))
                     {
                         mappedNamed.Add(name);
-                        Func<string, object> g = n => env.GetBindingValue(name, false);
-                        var p = new Action<string, object>((n, o) => env.SetMutableBinding(name, o, true));
+                        Func<object, object> g = n => env.GetBindingValue(name, false);
+                        var p = new Action<object, object>((n, o) => env.SetMutableBinding(name, o, true));
 
-                        map.DefineOwnProperty(indxStr, new ClrAccessDescriptor<string>(engine, g, p) { Configurable = true }, false);
+                        map.DefineOwnProperty(indxStr, new ClrAccessDescriptor<object>(engine, g, p) { Configurable = true }, false);
                     }
                 }
                 indx--;
             }
+
+            // step 12
             if (mappedNamed.Count > 0)
             {
                 obj.ParameterMap = map;
             }
+
+            // step 13
             if (!strict)
             {
                 obj.FastAddProperty("callee",func, true, false, true);
             }
+            // step 14
             else
             {
                 var thrower = engine.Function.ThrowTypeError;
@@ -77,6 +85,85 @@ namespace Jint.Native.Argument
         }
 
 
+        public override PropertyDescriptor GetOwnProperty(string propertyName)
+        {
+            if (!Strict && ParameterMap != null)
+            {
+                var desc = base.GetOwnProperty(propertyName);
+                if (desc == PropertyDescriptor.Undefined)
+                {
+                    return desc;
+                }
+
+                var isMapped = ParameterMap.GetOwnProperty(propertyName);
+                if (isMapped != PropertyDescriptor.Undefined)
+                {
+                    desc.As<DataDescriptor>().Value = ParameterMap.Get(propertyName);
+                }
+
+                return desc;
+            }
+
+            return base.GetOwnProperty(propertyName);
+        }
+
+        public override bool DefineOwnProperty(string propertyName, PropertyDescriptor desc, bool throwOnError)
+        {
+            if (!Strict && ParameterMap != null)
+            {
+                var map = ParameterMap;
+                var isMapped = map.GetOwnProperty(propertyName);
+                var allowed = base.DefineOwnProperty(propertyName, desc, false);
+                if (!allowed)
+                {
+                    if (throwOnError)
+                    {
+                        throw new JavaScriptException(Engine.TypeError);
+                    }
+                }
+                if (isMapped != PropertyDescriptor.Undefined)
+                {
+                    if (desc.IsAccessorDescriptor())
+                    {
+                        map.Delete(propertyName, false);
+                    }
+                    else
+                    {
+                        if (desc.As<DataDescriptor>().Value != null)
+                        {
+                            map.Put(propertyName, desc.As<DataDescriptor>().Value, throwOnError);
+                        }
+
+                        if (desc.As<DataDescriptor>().Writable.HasValue == false)
+                        {
+                            map.Delete(propertyName, false);
+                        }
+                    }
+                }
+
+                return true;
+            }
+
+            return base.DefineOwnProperty(propertyName, desc, throwOnError);
+        }
+
+        public override bool Delete(string propertyName, bool throwOnError)
+        {
+            if (!Strict && ParameterMap != null)
+            {
+                var map = ParameterMap;
+                var isMapped = map.GetOwnProperty(propertyName);
+                var result = base.Delete(propertyName, throwOnError);
+                if (result && isMapped != PropertyDescriptor.Undefined)
+                {
+                    map.Delete(propertyName, false);
+                }
+
+                return result;
+            }
 
+            return base.Delete(propertyName, throwOnError);
+        }
     }
 }
+ 

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

@@ -260,7 +260,7 @@ namespace Jint.Native.Object
         /// <param name="propertyName"></param>
         /// <param name="throwOnError"></param>
         /// <returns></returns>
-        public bool Delete(string propertyName, bool throwOnError)
+        public virtual bool Delete(string propertyName, bool throwOnError)
         {
             var desc = GetOwnProperty(propertyName);
             

+ 72 - 53
Jint/Native/String/StringPrototype.cs

@@ -1,7 +1,9 @@
 using System;
-using System.Globalization;
+using System.Collections.Generic;
 using System.Text;
+using System.Text.RegularExpressions;
 using Jint.Native.Array;
+using Jint.Native.Function;
 using Jint.Native.Object;
 using Jint.Native.RegExp;
 using Jint.Runtime;
@@ -43,7 +45,7 @@ namespace Jint.Native.String
             FastAddProperty("lastIndexOf", new ClrFunctionInstance<object, double>(Engine, LastIndexOf, 1), true, false, true);
             FastAddProperty("localeCompare", new ClrFunctionInstance<object, double>(Engine, LocaleCompare), true, false, true);
             FastAddProperty("match", new ClrFunctionInstance<object, object>(Engine, Match, 1), true, false, true);
-            FastAddProperty("replace", new ClrFunctionInstance<object, object>(Engine, Replace), true, false, true);
+            FastAddProperty("replace", new ClrFunctionInstance<object, object>(Engine, Replace, 2), true, false, true);
             FastAddProperty("search", new ClrFunctionInstance<object, double>(Engine, Search, 1), true, false, true);
             FastAddProperty("slice", new ClrFunctionInstance<object, string>(Engine, Slice, 2), true, false, true);
             FastAddProperty("split", new ClrFunctionInstance<object, ArrayInstance>(Engine, Split, 2), true, false, true);
@@ -134,10 +136,8 @@ namespace Jint.Native.String
             var l = arguments.At(1);
 
             var a = (ArrayInstance) Engine.Array.Construct(Arguments.Empty);
-            var lengthA = 0;
             var limit = l == Undefined.Instance ? UInt32.MaxValue : TypeConverter.ToUint32(l);
             var len = s.Length;
-            var p = 0;
             
             if (limit == 0)
             {
@@ -247,35 +247,27 @@ namespace Jint.Native.String
 
         private object Replace(object thisObj, object[] arguments)
         {
-            throw new NotImplementedException();
-            /*
             TypeConverter.CheckObjectCoercible(Engine, thisObj);
 
-            var s = TypeConverter.ToString(thisObj);
+            var thisString = TypeConverter.ToString(thisObj);
             var searchValue = arguments.At(0);
             var replaceValue = arguments.At(1);
 
-            var rx = TypeConverter.ToObject(Engine, searchValue) as RegExpInstance;
-            if (rx != null)
+            var replaceFunction = replaceValue as FunctionInstance;
+            if (replaceFunction == null)
             {
-
-
-
-
-
-
-                // Check if the replacement string contains any patterns.
-                bool replaceTextContainsPattern = replaceText.IndexOf('$') >= 0;
-
-                // Replace the input string with replaceText, recording the last match found.
-                Match lastMatch = null;
-                string result = rx.Value.Replace(s, match =>
+                replaceFunction = new ClrFunctionInstance<object, string>(Engine, (self, args) =>
                 {
-                    lastMatch = match;
+                    var replaceString = TypeConverter.ToString(replaceValue);
+                    var matchValue = TypeConverter.ToString(args.At(0));
+                    var matchIndex = (int)TypeConverter.ToInteger(args.At(args.Length-2));
+
+                    // Check if the replacement string contains any patterns.
+                    bool replaceTextContainsPattern = replaceString.IndexOf('$') >= 0;
 
                     // If there is no pattern, replace the pattern as is.
                     if (replaceTextContainsPattern == false)
-                        return replaceText;
+                        return replaceString;
 
                     // Patterns
                     // $$	Inserts a "$".
@@ -283,41 +275,41 @@ namespace Jint.Native.String
                     // $`	Inserts the portion of the string that precedes the matched substring.
                     // $'	Inserts the portion of the string that follows the matched substring.
                     // $n or $nn	Where n or nn are decimal digits, inserts the nth parenthesized submatch string, provided the first argument was a RegExp object.
-                    var replacementBuilder = new System.Text.StringBuilder();
-                    for (int i = 0; i < replaceText.Length; i++)
+                    var replacementBuilder = new StringBuilder();
+                    for (int i = 0; i < replaceString.Length; i++)
                     {
-                        char c = replaceText[i];
-                        if (c == '$' && i < replaceText.Length - 1)
+                        char c = replaceString[i];
+                        if (c == '$' && i < replaceString.Length - 1)
                         {
-                            c = replaceText[++i];
+                            c = replaceString[++i];
                             if (c == '$')
                                 replacementBuilder.Append('$');
                             else if (c == '&')
-                                replacementBuilder.Append(match.Value);
+                                replacementBuilder.Append(matchValue);
                             else if (c == '`')
-                                replacementBuilder.Append(input.Substring(0, match.Index));
+                                replacementBuilder.Append(thisString.Substring(0, matchIndex));
                             else if (c == '\'')
-                                replacementBuilder.Append(input.Substring(match.Index + match.Length));
+                                replacementBuilder.Append(thisString.Substring(matchIndex + matchValue.Length));
                             else if (c >= '0' && c <= '9')
                             {
                                 int matchNumber1 = c - '0';
 
                                 // The match number can be one or two digits long.
                                 int matchNumber2 = 0;
-                                if (i < replaceText.Length - 1 && replaceText[i + 1] >= '0' && replaceText[i + 1] <= '9')
-                                    matchNumber2 = matchNumber1*10 + (replaceText[i + 1] - '0');
+                                if (i < replaceString.Length - 1 && replaceString[i + 1] >= '0' && replaceString[i + 1] <= '9')
+                                    matchNumber2 = matchNumber1 * 10 + (replaceString[i + 1] - '0');
 
                                 // Try the two digit capture first.
-                                if (matchNumber2 > 0 && matchNumber2 < match.Groups.Count)
+                                if (matchNumber2 > 0 && matchNumber2 < args.Length - 3)
                                 {
                                     // Two digit capture replacement.
-                                    replacementBuilder.Append(match.Groups[matchNumber2].Value);
+                                    replacementBuilder.Append(TypeConverter.ToString(args[matchNumber2 + 1]));
                                     i++;
                                 }
-                                else if (matchNumber1 > 0 && matchNumber1 < match.Groups.Count)
+                                else if (matchNumber1 > 0 && matchNumber1 < args.Length - 3)
                                 {
                                     // Single digit capture replacement.
-                                    replacementBuilder.Append(match.Groups[matchNumber1].Value);
+                                    replacementBuilder.Append(TypeConverter.ToString(args[matchNumber1 + 1]));
                                 }
                                 else
                                 {
@@ -338,36 +330,63 @@ namespace Jint.Native.String
                     }
 
                     return replacementBuilder.ToString();
-                }, this.Global == true ? -1 : 1);
+                });
+            }
+
+            // searchValue is a regular expression
+            var rx = TypeConverter.ToObject(Engine, searchValue) as RegExpInstance;
+            if (rx != null)
+            {
+                // Replace the input string with replaceText, recording the last match found.
+                string result = rx.Value.Replace(thisString, match =>
+                {
+                    var args = new List<object>();
+                    args.Add(match.Value);
+                    for (var k = 0; k < match.Groups.Count; k++)
+                    {
+                        var group = match.Groups[k];
+                        if (group.Success)
+                            args.Add(group.Value);
+                    }
+                    
+                    args.Add(match.Index);
+                    args.Add(thisString);
+
+                    return TypeConverter.ToString(replaceFunction.Call(Undefined.Instance, args.ToArray()));
+                }, rx.Global == true ? -1 : 1);
 
                 // Set the deprecated RegExp properties if at least one match was found.
-                if (lastMatch != null)
-                    this.Engine.RegExp.SetDeprecatedProperties(input, lastMatch);
+                //if (lastMatch != null)
+                //    this.Engine.RegExp.SetDeprecatedProperties(input, lastMatch);
 
                 return result;
             }
+
+            // searchValue is a string
             else
             {
-                var searchString = TypeConverter.ToString(searchValue);
-                var m = 0;
+                var substr = TypeConverter.ToString(searchValue);
 
                 // Find the first occurrance of substr.
-                int start = thisObject.IndexOf(substr, StringComparison.Ordinal);
+                int start = thisString.IndexOf(substr, StringComparison.Ordinal);
                 if (start == -1)
-                    return thisObject;
+                    return thisString;
                 int end = start + substr.Length;
 
-                // Replace only the first match.
-                var result = new System.Text.StringBuilder(thisObject.Length + (replaceText.Length - substr.Length));
-                result.Append(thisObject, 0, start);
-                result.Append(replaceText);
-                result.Append(thisObject, end, thisObject.Length - end);
-                return result.ToString();
-
+                var args = new List<object>();
+                args.Add(substr);
+                args.Add(start);
+                args.Add(thisString);
 
+                var replaceString = TypeConverter.ToString(replaceFunction.Call(Undefined.Instance, args.ToArray()));
 
+                // Replace only the first match.
+                var result = new StringBuilder(thisString.Length + (substr.Length - substr.Length));
+                result.Append(thisString, 0, start);
+                result.Append(replaceString);
+                result.Append(thisString, end, thisString.Length - end);
+                return result.ToString();
             }
-             * */
         }
 
         private object Match(object thisObj, object[] arguments)
@@ -409,7 +428,7 @@ namespace Jint.Native.String
                         var thisIndex = (double) rx.Get("lastIndex");
                         if (thisIndex == previousLastIndex)
                         {
-                            rx.Put("lastIndex", (double) thisIndex + 1, false);
+                            rx.Put("lastIndex", thisIndex + 1, false);
                             previousLastIndex = thisIndex;
                         }