Browse Source

Fix string indexing detecting $ as NaN and thus 0 (#699)

Marko Lahma 5 years ago
parent
commit
4544bdb663

+ 15 - 0
Jint.Tests/Runtime/EngineTests.cs

@@ -2786,6 +2786,21 @@ x.test = {
             Assert.Throws<JavaScriptException>(() => engine.Execute("c.Name"));
             Assert.Throws<JavaScriptException>(() => engine.Execute("c.Name"));
         }
         }
 
 
+        [Fact]
+        public void ShouldAllowDollarPrefixForProperties()
+        {
+            _engine.SetValue("str", "Hello");
+            _engine.Execute("equal(undefined, str.$ref);");
+            _engine.Execute("equal(undefined, str.ref);");
+            _engine.Execute("equal(undefined, str.$foo);");
+            _engine.Execute("equal(undefined, str.foo);");
+            _engine.Execute("equal(undefined, str['$foo']);");
+            _engine.Execute("equal(undefined, str['foo']);");
+
+            _engine.Execute("equal(false, str.hasOwnProperty('$foo'));");
+            _engine.Execute("equal(false, str.hasOwnProperty('foo'));");
+        }
+
         private class Wrapper
         private class Wrapper
         {
         {
             public Testificate Test { get; set; }
             public Testificate Test { get; set; }

+ 10 - 17
Jint/Native/String/StringInstance.cs

@@ -20,15 +20,9 @@ namespace Jint.Native.String
 
 
         public JsString PrimitiveValue { get; set; }
         public JsString PrimitiveValue { get; set; }
 
 
-        private static bool IsInt(double d)
+        private static bool IsInt32(double d)
         {
         {
-            if (d >= long.MinValue && d <= long.MaxValue)
-            {
-                var l = (long) d;
-                return l >= int.MinValue && l <= int.MaxValue;
-            }
-
-            return false;
+            return d >= int.MinValue && d <= int.MaxValue && ((int) d) == d;
         }
         }
 
 
         public override PropertyDescriptor GetOwnProperty(in Key propertyName)
         public override PropertyDescriptor GetOwnProperty(in Key propertyName)
@@ -54,21 +48,20 @@ namespace Jint.Native.String
                 return PropertyDescriptor.Undefined;
                 return PropertyDescriptor.Undefined;
             }
             }
 
 
-            var integer = TypeConverter.ToInteger(propertyName);
-            var str = PrimitiveValue;
-            var dIndex = integer;
-            if (!IsInt(dIndex))
+            var number = TypeConverter.ToNumber(propertyName.Name);
+            if (!IsInt32(number))
+            {
                 return PropertyDescriptor.Undefined;
                 return PropertyDescriptor.Undefined;
+            }
 
 
-            var index = (int) dIndex;
-            var len = str.AsStringWithoutTypeCheck().Length;
-            if (len <= index || index < 0)
+            var index = (int) number;
+            var str = PrimitiveValue.AsStringWithoutTypeCheck();
+            if (index < 0 || str.Length <= index)
             {
             {
                 return PropertyDescriptor.Undefined;
                 return PropertyDescriptor.Undefined;
             }
             }
 
 
-            var resultStr = TypeConverter.ToString(str.AsStringWithoutTypeCheck()[index]);
-            return new PropertyDescriptor(resultStr, PropertyFlag.OnlyEnumerable);
+            return new PropertyDescriptor(str[index], PropertyFlag.OnlyEnumerable);
         }
         }
 
 
         public override IEnumerable<KeyValuePair<Key, PropertyDescriptor>> GetOwnProperties()
         public override IEnumerable<KeyValuePair<Key, PropertyDescriptor>> GetOwnProperties()

+ 1 - 1
Jint/Runtime/Interpreter/Expressions/JintMemberExpression.cs

@@ -72,7 +72,7 @@ namespace Jint.Runtime.Interpreter.Expressions
 
 
             var propertyName = _determinedPropertyName.Name.Length > 0
             var propertyName = _determinedPropertyName.Name.Length > 0
                 ? _determinedPropertyName
                 ? _determinedPropertyName
-                : (Key) TypeConverter.ToPropertyKey(_propertyExpression.GetValue());
+                : TypeConverter.ToPropertyKey(_propertyExpression.GetValue());
 
 
             TypeConverter.CheckObjectCoercible(_engine, baseValue, (MemberExpression) _expression, baseReferenceName);
             TypeConverter.CheckObjectCoercible(_engine, baseValue, (MemberExpression) _expression, baseReferenceName);
 
 

+ 5 - 12
Jint/Runtime/TypeConverter.cs

@@ -208,25 +208,18 @@ namespace Jint.Runtime
             }
             }
         }
         }
 
 
-        internal static bool CanBeIndex(string input)
+        internal static bool CanBeIndex(in Key input)
         {
         {
-            if (string.IsNullOrEmpty(input))
-            {
-                return false;
-            }
-
-            char first = input[0];
-            if (first < 32 || (first > 57 && first != 73))
+            if (input.Name.Length == 0)
             {
             {
-                // does not start with space, +, -, number or I
                 return false;
                 return false;
             }
             }
 
 
-            // might be
-            return true;
+            var c = input.Name[0];
+            return char.IsDigit(c) || c == ' ' || c == '+' || c == '-' || c == 'I';
         }
         }
 
 
-        private static double ToNumber(string input)
+        internal static double ToNumber(string input)
         {
         {
             // eager checks to save time and trimming
             // eager checks to save time and trimming
             if (string.IsNullOrEmpty(input))
             if (string.IsNullOrEmpty(input))