Browse Source

Merge branch 'dev'

Sebastien Ros 7 years ago
parent
commit
b2860eb824

+ 1 - 1
Common.props

@@ -12,7 +12,7 @@
     <GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
     <GenerateAssemblyCopyrightAttribute>false</GenerateAssemblyCopyrightAttribute>
     <GenerateAssemblyVersionAttribute>false</GenerateAssemblyVersionAttribute>
-    <GenerateAssemblyFileVersionAttribute>false</GenerateAssemblyFileVersionAttribute>
+    <GenerateAssemblyFileVersionAttribute>true</GenerateAssemblyFileVersionAttribute>
   </PropertyGroup>
 
 </Project>

+ 5 - 4
Jint.Tests/Jint.Tests.csproj

@@ -21,10 +21,11 @@
     <ProjectReference Include="..\Jint\Jint.csproj" />
   </ItemGroup>
   <ItemGroup>
-    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0" />
-    <PackageReference Include="xunit" Version="2.2.0" />
-    <PackageReference Include="xunit.runner.visualstudio" Version="2.2.0" />
-    <PackageReference Include="xunit.analyzers" Version="0.3.0" />
+    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.3.0" />
+    <PackageReference Include="xunit" Version="2.3.1" />
+    <PackageReference Include="xunit.runner.visualstudio" Version="2.3.1" />
+    <PackageReference Include="xunit.analyzers" Version="0.7.0" />
+    <PackageReference Include="xunit.runner.console" Version="2.3.1" />
   </ItemGroup>
   <ItemGroup Condition=" '$(TargetFramework)' == 'net451' ">
     <Reference Include="System" />

+ 8 - 6
Jint.Tests/Parser/JavascriptParserTests.cs

@@ -56,7 +56,7 @@ namespace Jint.Tests.Parser
             var body = program.Body;
 
             Assert.NotNull(body);
-            Assert.Equal(1, body.Count());
+            Assert.Single(body);
             Assert.Equal(SyntaxNodes.ThisExpression, body.First().As<ExpressionStatement>().Expression.Type);
         }
 
@@ -67,7 +67,7 @@ namespace Jint.Tests.Parser
             var body = program.Body;
 
             Assert.NotNull(body);
-            Assert.Equal(1, body.Count());
+            Assert.Single(body);
             Assert.Equal(SyntaxNodes.Literal, body.First().As<ExpressionStatement>().Expression.Type);
             Assert.Equal(null, body.First().As<ExpressionStatement>().Expression.As<Literal>().Value);
             Assert.Equal("null", body.First().As<ExpressionStatement>().Expression.As<Literal>().Raw);
@@ -83,7 +83,7 @@ namespace Jint.Tests.Parser
             var body = program.Body;
 
             Assert.NotNull(body);
-            Assert.Equal(1, body.Count());
+            Assert.Single(body);
             Assert.Equal(SyntaxNodes.Literal, body.First().As<ExpressionStatement>().Expression.Type);
             Assert.Equal(42d, body.First().As<ExpressionStatement>().Expression.As<Literal>().Value);
             Assert.Equal("42", body.First().As<ExpressionStatement>().Expression.As<Literal>().Raw);
@@ -98,7 +98,7 @@ namespace Jint.Tests.Parser
             var body = program.Body;
 
             Assert.NotNull(body);
-            Assert.Equal(1, body.Count());
+            Assert.Single(body);
             Assert.NotNull(binary = body.First().As<ExpressionStatement>().Expression.As<BinaryExpression>());
             Assert.Equal(3d, binary.Right.As<Literal>().Value);
             Assert.Equal(BinaryOperator.Times, binary.Operator);
@@ -125,6 +125,8 @@ namespace Jint.Tests.Parser
         [InlineData(02, "02")]
         [InlineData(10, "012")]
         [InlineData(10, "0012")]
+        [InlineData(1.189008226412092e+38, "0x5973772948c653ac1971f1576e03c4d4")]
+        [InlineData(18446744073709552000d, "0xffffffffffffffff")]
         public void ShouldParseNumericLiterals(object expected, string source)
         {
             Literal literal;
@@ -133,7 +135,7 @@ namespace Jint.Tests.Parser
             var body = program.Body;
 
             Assert.NotNull(body);
-            Assert.Equal(1, body.Count());
+            Assert.Single(body);
             Assert.NotNull(literal = body.First().As<ExpressionStatement>().Expression.As<Literal>());
             Assert.Equal(Convert.ToDouble(expected), Convert.ToDouble(literal.Value));
         }
@@ -153,7 +155,7 @@ namespace Jint.Tests.Parser
             var body = program.Body;
 
             Assert.NotNull(body);
-            Assert.Equal(1, body.Count());
+            Assert.Single(body);
             Assert.NotNull(literal = body.First().As<ExpressionStatement>().Expression.As<Literal>());
             Assert.Equal(expected, literal.Value);
         }

+ 49 - 4
Jint.Tests/Runtime/EngineTests.cs

@@ -2,14 +2,12 @@
 using System.Globalization;
 using System.IO;
 using System.Reflection;
-using System.Threading;
 using Jint.Native.Number;
 using Jint.Parser;
 using Jint.Parser.Ast;
 using Jint.Runtime;
 using Jint.Runtime.Debugger;
 using Xunit;
-using System.Net;
 
 namespace Jint.Tests.Runtime
 {
@@ -1479,7 +1477,7 @@ namespace Jint.Tests.Runtime
             Assert.NotNull(debugInfo.CurrentStatement);
             Assert.NotNull(debugInfo.Locals);
 
-            Assert.Equal(1, debugInfo.CallStack.Count);
+            Assert.Single(debugInfo.CallStack);
             Assert.Equal("func1()", debugInfo.CallStack.Peek());
             Assert.Contains(debugInfo.Globals, kvp => kvp.Key.Equals("global", StringComparison.Ordinal) && kvp.Value.AsBoolean() == true);
             Assert.Contains(debugInfo.Globals, kvp => kvp.Key.Equals("local", StringComparison.Ordinal) && kvp.Value.AsBoolean() == false);
@@ -1954,7 +1952,6 @@ namespace Jint.Tests.Runtime
         [InlineData("%uE", "unescape('%uE')")]
         [InlineData("%uf", "unescape('%uf')")]
         [InlineData("%uF", "unescape('%uF')")]
-        [InlineData("%u00", "unescape('%u00')")]
         [InlineData("%u01", "unescape('%u01')")]
         [InlineData("%u02", "unescape('%u02')")]
         [InlineData("%u03", "unescape('%u03')")]
@@ -2133,5 +2130,53 @@ namespace Jint.Tests.Runtime
 
             Assert.Equal(expected, result);
         }
+
+        [Theory]
+        [InlineData("new Date(1969,0,1,19,45,30,500).getHours()", 19)]
+        [InlineData("new Date(1970,0,1,19,45,30,500).getHours()", 19)]
+        [InlineData("new Date(1971,0,1,19,45,30,500).getHours()", 19)]
+        [InlineData("new Date(1969,0,1,19,45,30,500).getMinutes()", 45)]
+        [InlineData("new Date(1970,0,1,19,45,30,500).getMinutes()", 45)]
+        [InlineData("new Date(1971,0,1,19,45,30,500).getMinutes()", 45)]
+        [InlineData("new Date(1969,0,1,19,45,30,500).getSeconds()", 30)]
+        [InlineData("new Date(1970,0,1,19,45,30,500).getSeconds()", 30)]
+        [InlineData("new Date(1971,0,1,19,45,30,500).getSeconds()", 30)]
+        //[InlineData("new Date(1969,0,1,19,45,30,500).getMilliseconds()", 500)]
+        //[InlineData("new Date(1970,0,1,19,45,30,500).getMilliseconds()", 500)]
+        //[InlineData("new Date(1971,0,1,19,45,30,500).getMilliseconds()", 500)]
+        public void ShouldExtractDateParts(string source, double expected)
+        {
+            var engine = new Engine();
+            var result = engine.Execute(source).GetCompletionValue().ToObject();
+
+            Assert.Equal(expected, result);
+        }
+
+        [Theory]
+        [InlineData("'abc'.padStart(10)", "       abc")]
+        [InlineData("'abc'.padStart(10, \"foo\")", "foofoofabc")]
+        [InlineData("'abc'.padStart(6, \"123456\")", "123abc")]
+        [InlineData("'abc'.padStart(8, \"0\")", "00000abc")]
+        [InlineData("'abc'.padStart(1)", "abc")]
+        public void ShouldPadStart(string source, object expected)
+        {
+            var engine = new Engine();
+            var result = engine.Execute(source).GetCompletionValue().ToObject();
+
+            Assert.Equal(expected, result);
+        }
+
+        [Theory]
+        [InlineData("'abc'.padEnd(10)", "abc       ")]
+        [InlineData("'abc'.padEnd(10, \"foo\")", "abcfoofoof")]
+        [InlineData("'abc'.padEnd(6, \"123456\")", "abc123")]
+        [InlineData("'abc'.padEnd(1)", "abc")]
+        public void ShouldPadEnd(string source, object expected)
+        {
+            var engine = new Engine();
+            var result = engine.Execute(source).GetCompletionValue().ToObject();
+
+            Assert.Equal(expected, result);
+        }
     }
 }

+ 10 - 0
Jint.Tests/Runtime/InteropTests.cs

@@ -861,6 +861,16 @@ namespace Jint.Tests.Runtime
             ");
         }
 
+        [Fact]
+        public void ShouldBeInstanceOfTypeReferenceType()
+        {
+            _engine.SetValue("A", typeof(A));
+            RunTest(@"
+                var a = new A();
+                assert(a instanceof A);
+            ");
+        }
+
         [Fact]
         public void ShouldImportNamespace()
         {

+ 6 - 6
Jint.Tests/Runtime/NullPropogation.cs → Jint.Tests/Runtime/NullPropagation.cs

@@ -8,9 +8,9 @@ using Xunit;
 
 namespace Jint.Tests.Runtime
 {
-    public class NullPropogation
+    public class NullPropagation
     {
-        public class NullPropgationReferenceResolver : IReferenceResolver
+        public class NullPropagationReferenceResolver : IReferenceResolver
         {
             public bool TryUnresolvableReference(Engine engine, Reference reference, out JsValue value)
             {
@@ -38,9 +38,9 @@ namespace Jint.Tests.Runtime
         }
 
         [Fact]
-        public void NullPropagation()
+        public void NullPropagationTest()
         {
-            var engine = new Engine(cfg => cfg.SetReferencesResolver(new NullPropgationReferenceResolver()));
+            var engine = new Engine(cfg => cfg.SetReferencesResolver(new NullPropagationReferenceResolver()));
 
             const string Script = @"
 var input = { 
@@ -75,7 +75,7 @@ var output = {
         [Fact]
         public void NullPropagationFromArg()
         {
-            var engine = new Engine(cfg => cfg.SetReferencesResolver(new NullPropgationReferenceResolver()));
+            var engine = new Engine(cfg => cfg.SetReferencesResolver(new NullPropagationReferenceResolver()));
 
 
             const string Script = @"
@@ -100,7 +100,7 @@ function test2(arg) {
         [Fact]
         public void NullPropagationShouldNotAffectOperators()
         {
-            var engine = new Engine(cfg => cfg.SetReferencesResolver(new NullPropgationReferenceResolver()));
+            var engine = new Engine(cfg => cfg.SetReferencesResolver(new NullPropagationReferenceResolver()));
 
             var jsObject = engine.Object.Construct(Arguments.Empty);
             jsObject.Put("NullField", JsValue.Null, true);

+ 1 - 0
Jint/Directory.Build.props

@@ -4,6 +4,7 @@
     <PackageId>Jint</PackageId>
     <AssemblyTitle>Jint</AssemblyTitle>
     <Description>Javascript interpreter for .NET which provides full ECMA 5.1 compliance.</Description>
+    <BuildNumber Condition="'$(BuildNumber)' == ''">0</BuildNumber>
     <VersionPrefix>2.11.$(BuildNumber)</VersionPrefix>
     <VersionSuffix></VersionSuffix>
     <PackageId>Jint</PackageId>

+ 3 - 2
Jint/Jint.csproj

@@ -2,7 +2,7 @@
 
   <PropertyGroup>
     <NeutralLanguage>en-US</NeutralLanguage>
-    <TargetFrameworks>net40;net45;net451;netstandard1.3</TargetFrameworks>
+    <TargetFrameworks>net40;net45;net451;netstandard1.3;netstandard2.0</TargetFrameworks>
     <AssemblyOriginatorKeyFile>Jint.snk</AssemblyOriginatorKeyFile>
     <SignAssembly>true</SignAssembly>
   </PropertyGroup>
@@ -26,5 +26,6 @@
     <PackageReference Include="System.Runtime.InteropServices" Version="4.3.0" />
     <PackageReference Include="System.Xml.XmlDocument" Version="4.3.0" />
   </ItemGroup>
-
+  <ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' ">
+  </ItemGroup>
 </Project>

+ 3 - 2
Jint/Native/Date/DateConstructor.cs

@@ -169,10 +169,11 @@ namespace Jint.Native.Date
                 y += 1900;
             }
 
-            var finalDate = DatePrototype.MakeDate(DatePrototype.MakeDay(y, m, dt),
+            var finalDate = DatePrototype.MakeDate(
+                DatePrototype.MakeDay(y, m, dt),
                 DatePrototype.MakeTime(h, min, s, milli));
 
-            return useUtc ? finalDate : PrototypeObject.Utc(finalDate);
+            return TimeClip(useUtc ? finalDate : PrototypeObject.Utc(finalDate));
         }
 
         public DatePrototype PrototypeObject { get; private set; }

+ 32 - 4
Jint/Native/Date/DatePrototype.cs

@@ -930,22 +930,50 @@ namespace Jint.Native.Date
 
         public static double HourFromTime(double t)
         {
-            return System.Math.Floor(t / MsPerHour) % HoursPerDay;
+            var hours = System.Math.Floor(t / MsPerHour) % HoursPerDay;
+
+            if (hours < 0)
+            {
+                hours += HoursPerDay;
+            }
+
+            return hours;
         }
 
         public static double MinFromTime(double t)
         {
-            return System.Math.Floor(t / MsPerMinute) % MinutesPerHour;
+            var minutes = System.Math.Floor(t / MsPerMinute) % MinutesPerHour;
+
+            if (minutes < 0)
+            {
+                minutes += MinutesPerHour;
+            }
+
+            return minutes;
         }
 
         public static double SecFromTime(double t)
         {
-            return System.Math.Floor(t / MsPerSecond) % SecondsPerMinute;
+            var seconds = System.Math.Floor(t / MsPerSecond) % SecondsPerMinute;
+
+            if (seconds < 0)
+            {
+                seconds += SecondsPerMinute;
+            }
+
+            return seconds;
         }
 
         public static double MsFromTime(double t)
         {
-            return t % MsPerSecond;
+            var milli = t % MsPerSecond;
+
+            if (milli < 0)
+            {
+                milli += MsPerSecond;
+            }
+
+            return milli;
         }
 
         public static double DayFromMonth(double year, double month)

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

@@ -58,6 +58,8 @@ namespace Jint.Native.String
             FastAddProperty("toUpperCase", new ClrFunctionInstance(Engine, ToUpperCase), true, false, true);
             FastAddProperty("toLocaleUpperCase", new ClrFunctionInstance(Engine, ToLocaleUpperCase), true, false, true);
             FastAddProperty("trim", new ClrFunctionInstance(Engine, Trim), true, false, true);
+            FastAddProperty("padStart", new ClrFunctionInstance(Engine, PadStart), true, false, true);
+            FastAddProperty("padEnd", new ClrFunctionInstance(Engine, PadEnd), true, false, true);
         }
 
         private JsValue ToStringString(JsValue thisObj, JsValue[] arguments)
@@ -742,5 +744,54 @@ namespace Jint.Native.String
 
             return s.PrimitiveValue;
         }
+
+        /// <summary>
+        /// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padStart
+        /// </summary>
+        /// <param name="thisObj">The original string object</param>
+        /// <param name="arguments">
+        ///     argument[0] is the target length of the output string
+        ///     argument[1] is the string to pad with
+        /// </param>
+        /// <returns></returns>
+        private JsValue PadStart(JsValue thisObj, JsValue[] arguments)
+        {
+            return Pad(thisObj, arguments, true);
+        }
+
+        /// <summary>
+        /// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padEnd
+        /// </summary>
+        /// <param name="thisObj">The original string object</param>
+        /// <param name="arguments">
+        ///     argument[0] is the target length of the output string
+        ///     argument[1] is the string to pad with
+        /// </param>
+        /// <returns></returns>
+        private JsValue PadEnd(JsValue thisObj, JsValue[] arguments)
+        {
+            return Pad(thisObj, arguments, false);
+        }
+
+        private JsValue Pad(JsValue thisObj, JsValue[] arguments, bool padStart)
+        {
+            TypeConverter.CheckObjectCoercible(Engine, thisObj);
+            var targetLength = TypeConverter.ToInt32(arguments.At(0));
+            var padString = TypeConverter.ToString(arguments.At(1, new JsValue(" ")));
+
+            var s = TypeConverter.ToString(thisObj);
+            if (s.Length > targetLength)
+            {
+                return s;
+            }
+
+            targetLength = targetLength - s.Length;
+            if (targetLength > padString.Length)
+            {
+                padString = string.Join("", Enumerable.Repeat(padString, (targetLength / padString.Length) + 1));
+            }
+
+            return padStart ? $"{padString.Substring(0, targetLength)}{s}" : $"{s}{padString.Substring(0, targetLength)}";
+        }
     }
 }

+ 32 - 1
Jint/Parser/JavascriptParser.cs

@@ -759,10 +759,41 @@ namespace Jint.Parser
                 ThrowError(null, Messages.UnexpectedToken, "ILLEGAL");
             }
 
+            double value = 0;
+
+            if (number.Length < 16)
+            {
+                value = Convert.ToUInt64(number, 16);
+            }
+            else if(number.Length > 255)
+            {
+                value = double.PositiveInfinity;
+            }
+            else
+            {
+                double modulo = 1;
+                var literal = number.ToLowerInvariant();
+                for (var i = literal.Length - 1; i >= 0; i--)
+                {
+                    var c = literal[i];
+
+                    if (c <= '9')
+                    {
+                        value += modulo * (c - '0');
+                    }
+                    else
+                    {
+                        value += modulo * (c - 'a' + 10);
+                    }
+                    
+                    modulo *= 16;
+                }
+            }
+            
             return new Token
                 {
                     Type = Tokens.NumericLiteral,
-                    Value = Convert.ToInt64(number, 16),
+                    Value = value,
                     LineNumber = _lineNumber,
                     LineStart = _lineStart,
                     Range = new[] {start, _index}

+ 13 - 1
Jint/Runtime/Interop/TypeReference.cs

@@ -63,7 +63,7 @@ namespace Jint.Runtime.Interop
                 {
                     for (var i = 0; i < arguments.Length; i++)
                     {
-                        var parameterType =  method.GetParameters()[i].ParameterType;
+                        var parameterType = method.GetParameters()[i].ParameterType;
 
                         if (parameterType == typeof(JsValue))
                         {
@@ -96,6 +96,18 @@ namespace Jint.Runtime.Interop
 
         }
 
+        public override bool HasInstance(JsValue v)
+        {
+            ObjectWrapper wrapper = v.As<ObjectWrapper>();
+
+            if (wrapper == null)
+            {
+                return base.HasInstance(v);
+            }
+
+            return wrapper.Target.GetType() == this.Type;
+        }
+
         public override bool DefineOwnProperty(string propertyName, PropertyDescriptor desc, bool throwOnError)
         {
             if (throwOnError)