Explorar o código

Merge remote-tracking branch 'upstream/master'

Conflicts:
	Jint.Tests/Runtime/EngineTests.cs
	Jint/Engine.cs
	Jint/Options.cs
auz34 %!s(int64=11) %!d(string=hai) anos
pai
achega
92be200b1d
Modificáronse 33 ficheiros con 1777 adicións e 148 borrados
  1. 1 0
      .gitignore
  2. 4 0
      .nuget/packages.config
  3. 1 1
      Jint.Benchmark/Program.cs
  4. 3 0
      Jint.Tests.CommonScripts/Jint.Tests.CommonScripts.csproj
  5. 26 26
      Jint.Tests.CommonScripts/SunSpiderTests.cs
  6. 3 2
      Jint.Tests.Ecma/EcmaTest.cs
  7. 3 0
      Jint.Tests.Ecma/Jint.Tests.Ecma.csproj
  8. 8 0
      Jint.Tests/Jint.Tests.csproj
  9. 1 0
      Jint.Tests/Parser/JavascriptParserTests.cs
  10. 983 0
      Jint.Tests/Parser/Scripts/handlebars.js
  11. 24 0
      Jint.Tests/Runtime/Domain/A.cs
  12. 36 0
      Jint.Tests/Runtime/Domain/Company.cs
  13. 8 0
      Jint.Tests/Runtime/Domain/ICompany.cs
  14. 186 5
      Jint.Tests/Runtime/EngineTests.cs
  15. 139 1
      Jint.Tests/Runtime/InteropTests.cs
  16. 1 1
      Jint.sln
  17. 17 0
      Jint/Engine.cs
  18. 75 47
      Jint/Native/Date/DateConstructor.cs
  19. 35 25
      Jint/Native/Date/DatePrototype.cs
  20. 19 2
      Jint/Native/Json/JsonParser.cs
  21. 1 1
      Jint/Native/RegExp/RegExpPrototype.cs
  22. 26 16
      Jint/Options.cs
  23. 8 8
      Jint/Parser/JavascriptParser.cs
  24. 1 1
      Jint/Runtime/Descriptors/Specialized/FieldInfoDescriptor.cs
  25. 13 5
      Jint/Runtime/Descriptors/Specialized/IndexDescriptor.cs
  26. 1 1
      Jint/Runtime/Descriptors/Specialized/PropertyInfoDescriptor.cs
  27. 101 0
      Jint/Runtime/Interop/DefaultTypeConverter.cs
  28. 1 1
      Jint/Runtime/Interop/DelegateWrapper.cs
  29. 6 1
      Jint/Runtime/Interop/MethodInfoFunctionInstance.cs
  30. 38 0
      Jint/Runtime/Interop/ObjectWrapper .cs
  31. 1 1
      Jint/Runtime/Interop/TypeReference.cs
  32. 2 2
      Jint/Runtime/TypeConverter.cs
  33. 5 1
      README.md

+ 1 - 0
.gitignore

@@ -151,3 +151,4 @@ $RECYCLE.BIN/
 
 # Mac crap
 .DS_Store
+Jint.sln.ide/*

+ 4 - 0
.nuget/packages.config

@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<packages>
+  <package id="xunit.runners" version="1.9.2" />
+</packages>

+ 1 - 1
Jint.Benchmark/Program.cs

@@ -30,7 +30,7 @@ namespace Jint.Benchmark
             const bool runJint = true;
             const bool runJurassic = true;
 
-            const int iterations = 100;
+            const int iterations = 1000;
             const bool reuseEngine = false;
 
             var watch = new Stopwatch();

+ 3 - 0
Jint.Tests.CommonScripts/Jint.Tests.CommonScripts.csproj

@@ -59,6 +59,9 @@
       <Name>Jint</Name>
     </ProjectReference>
   </ItemGroup>
+  <ItemGroup>
+    <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+  </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
   <Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 

+ 26 - 26
Jint.Tests.CommonScripts/SunSpiderTests.cs

@@ -30,7 +30,7 @@ namespace Jint.Tests.CommonScripts
         }
 
         [Theory]
-        [InlineData("3d-cube", "https://raw.github.com/WebKit/webkit/master/PerformanceTests/SunSpider/tests/sunspider-1.0.1/3d-cube.js")]
+        [InlineData("3d-cube", "https://raw.githubusercontent.com/WebKit/webkit/master/PerformanceTests/SunSpider/tests/sunspider-1.0.2/3d-cube.js")]
         public void ThreeDCube(string name, string url)
         {
             var content = new WebClient().DownloadString(url);
@@ -38,7 +38,7 @@ namespace Jint.Tests.CommonScripts
         }
 
         [Theory]
-        [InlineData("3d-morph", "https://raw.github.com/WebKit/webkit/master/PerformanceTests/SunSpider/tests/sunspider-1.0.1/3d-morph.js")]
+        [InlineData("3d-morph", "https://raw.githubusercontent.com/WebKit/webkit/master/PerformanceTests/SunSpider/tests/sunspider-1.0.2/3d-morph.js")]
         public void ThreeDMorph(string name, string url)
         {
             var content = new WebClient().DownloadString(url);
@@ -46,7 +46,7 @@ namespace Jint.Tests.CommonScripts
         }
 
         [Theory]
-        [InlineData("3d-raytrace", "https://raw.github.com/WebKit/webkit/master/PerformanceTests/SunSpider/tests/sunspider-1.0.1/3d-raytrace.js")]
+        [InlineData("3d-raytrace", "https://raw.githubusercontent.com/WebKit/webkit/master/PerformanceTests/SunSpider/tests/sunspider-1.0.2/3d-raytrace.js")]
         public void ThreeDRaytrace(string name, string url)
         {
             var content = new WebClient().DownloadString(url);
@@ -54,7 +54,7 @@ namespace Jint.Tests.CommonScripts
         }
 
         [Theory]
-        [InlineData("access-binary-trees", "https://raw.github.com/WebKit/webkit/master/PerformanceTests/SunSpider/tests/sunspider-1.0.1/access-binary-trees.js")]
+        [InlineData("access-binary-trees", "https://raw.githubusercontent.com/WebKit/webkit/master/PerformanceTests/SunSpider/tests/sunspider-1.0.2/access-binary-trees.js")]
         public void AccessBinaryTrees(string name, string url)
         {
             var content = new WebClient().DownloadString(url);
@@ -62,7 +62,7 @@ namespace Jint.Tests.CommonScripts
         }
 
         [Theory]
-        [InlineData("access-fannkuch", "https://raw.github.com/WebKit/webkit/master/PerformanceTests/SunSpider/tests/sunspider-1.0.1/access-fannkuch.js")]
+        [InlineData("access-fannkuch", "https://raw.githubusercontent.com/WebKit/webkit/master/PerformanceTests/SunSpider/tests/sunspider-1.0.2/access-fannkuch.js")]
         public void AccessFannkych(string name, string url)
         {
             var content = new WebClient().DownloadString(url);
@@ -70,7 +70,7 @@ namespace Jint.Tests.CommonScripts
         }
 
         [Theory]
-        [InlineData("access-nbody", "https://raw.github.com/WebKit/webkit/master/PerformanceTests/SunSpider/tests/sunspider-1.0.1/access-nbody.js")]
+        [InlineData("access-nbody", "https://raw.githubusercontent.com/WebKit/webkit/master/PerformanceTests/SunSpider/tests/sunspider-1.0.2/access-nbody.js")]
         public void AccessNBody(string name, string url)
         {
             var content = new WebClient().DownloadString(url);
@@ -78,14 +78,14 @@ namespace Jint.Tests.CommonScripts
         }
 
         [Theory]
-        [InlineData("access-nsieve", "https://raw.github.com/WebKit/webkit/master/PerformanceTests/SunSpider/tests/sunspider-1.0.1/access-nsieve.js")]
+        [InlineData("access-nsieve", "https://raw.githubusercontent.com/WebKit/webkit/master/PerformanceTests/SunSpider/tests/sunspider-1.0.2/access-nsieve.js")]
         public void AccessNSieve(string name, string url)
         {
             var content = new WebClient().DownloadString(url);
             RunTest(content);
         }
 
-        [InlineData("bitops-3bit-bits-in-byte", "https://raw.github.com/WebKit/webkit/master/PerformanceTests/SunSpider/tests/sunspider-1.0.1/bitops-3bit-bits-in-byte.js")]
+        [InlineData("bitops-3bit-bits-in-byte", "https://raw.githubusercontent.com/WebKit/webkit/master/PerformanceTests/SunSpider/tests/sunspider-1.0.2/bitops-3bit-bits-in-byte.js")]
         public void Bitops3BitBitsInByte(string name, string url)
         {
             var content = new WebClient().DownloadString(url);
@@ -93,7 +93,7 @@ namespace Jint.Tests.CommonScripts
         }
 
         [Theory]
-        [InlineData("bitops-bits-in-byte", "https://raw.github.com/WebKit/webkit/master/PerformanceTests/SunSpider/tests/sunspider-1.0.1/bitops-bits-in-byte.js")]
+        [InlineData("bitops-bits-in-byte", "https://raw.githubusercontent.com/WebKit/webkit/master/PerformanceTests/SunSpider/tests/sunspider-1.0.2/bitops-bits-in-byte.js")]
         public void BitopsBitsInByte(string name, string url)
         {
             var content = new WebClient().DownloadString(url);
@@ -101,7 +101,7 @@ namespace Jint.Tests.CommonScripts
         }
 
         [Theory]
-        [InlineData("bitops-bitwise-and", "https://raw.github.com/WebKit/webkit/master/PerformanceTests/SunSpider/tests/sunspider-1.0.1/bitops-bitwise-and.js")]
+        [InlineData("bitops-bitwise-and", "https://raw.githubusercontent.com/WebKit/webkit/master/PerformanceTests/SunSpider/tests/sunspider-1.0.2/bitops-bitwise-and.js")]
         public void BitopsBitwiseAnd(string name, string url)
         {
             var content = new WebClient().DownloadString(url);
@@ -109,7 +109,7 @@ namespace Jint.Tests.CommonScripts
         }
 
         [Theory]
-        [InlineData("bitops-nsieve-bits", "https://raw.github.com/WebKit/webkit/master/PerformanceTests/SunSpider/tests/sunspider-1.0.1/bitops-nsieve-bits.js")]
+        [InlineData("bitops-nsieve-bits", "https://raw.githubusercontent.com/WebKit/webkit/master/PerformanceTests/SunSpider/tests/sunspider-1.0.2/bitops-nsieve-bits.js")]
         public void BitopsNSieveBits(string name, string url)
         {
             var content = new WebClient().DownloadString(url);
@@ -117,7 +117,7 @@ namespace Jint.Tests.CommonScripts
         }
 
         [Theory]
-        [InlineData("controlflow-recursive", "https://raw.github.com/WebKit/webkit/master/PerformanceTests/SunSpider/tests/sunspider-1.0.1/controlflow-recursive.js")]
+        [InlineData("controlflow-recursive", "https://raw.githubusercontent.com/WebKit/webkit/master/PerformanceTests/SunSpider/tests/sunspider-1.0.2/controlflow-recursive.js")]
         public void ControlFlowRecursive(string name, string url)
         {
             var t = new Thread(() =>
@@ -131,7 +131,7 @@ namespace Jint.Tests.CommonScripts
         }
 
         [Theory]
-        [InlineData("crypto-aes", "https://raw.github.com/WebKit/webkit/master/PerformanceTests/SunSpider/tests/sunspider-1.0.1/crypto-aes.js")]
+        [InlineData("crypto-aes", "https://raw.githubusercontent.com/WebKit/webkit/master/PerformanceTests/SunSpider/tests/sunspider-1.0.2/crypto-aes.js")]
         public void CryptoAES(string name, string url)
         {
             var content = new WebClient().DownloadString(url);
@@ -139,14 +139,14 @@ namespace Jint.Tests.CommonScripts
         }
 
         [Theory]
-        [InlineData("crypto-md5", "https://raw.github.com/WebKit/webkit/master/PerformanceTests/SunSpider/tests/sunspider-1.0.1/crypto-md5.js")]
+        [InlineData("crypto-md5", "https://raw.githubusercontent.com/WebKit/webkit/master/PerformanceTests/SunSpider/tests/sunspider-1.0.2/crypto-md5.js")]
         public void CryptoMD5(string name, string url)
         {
             var content = new WebClient().DownloadString(url);
             RunTest(content);
         }
 
-        [InlineData("crypto-sha1", "https://raw.github.com/WebKit/webkit/master/PerformanceTests/SunSpider/tests/sunspider-1.0.1/crypto-sha1.js")]
+        [InlineData("crypto-sha1", "https://raw.githubusercontent.com/WebKit/webkit/master/PerformanceTests/SunSpider/tests/sunspider-1.0.2/crypto-sha1.js")]
         public void CryptoSha1(string name, string url)
         {
             var content = new WebClient().DownloadString(url);
@@ -154,7 +154,7 @@ namespace Jint.Tests.CommonScripts
         }
 
         [Theory]
-        [InlineData("date-format-tofte", "https://raw.github.com/WebKit/webkit/master/PerformanceTests/SunSpider/tests/sunspider-1.0.1/date-format-tofte.js")]
+        [InlineData("date-format-tofte", "https://raw.githubusercontent.com/WebKit/webkit/master/PerformanceTests/SunSpider/tests/sunspider-1.0.2/date-format-tofte.js")]
         public void DateFormatTofte(string name, string url)
         {
             var content = new WebClient().DownloadString(url);
@@ -162,14 +162,14 @@ namespace Jint.Tests.CommonScripts
         }
 
         [Theory]
-        [InlineData("date-format-xparb", "https://raw.github.com/WebKit/webkit/master/PerformanceTests/SunSpider/tests/sunspider-1.0.1/date-format-xparb.js")]
+        [InlineData("date-format-xparb", "https://raw.githubusercontent.com/WebKit/webkit/master/PerformanceTests/SunSpider/tests/sunspider-1.0.2/date-format-xparb.js")]
         public void DateFormatXParb(string name, string url)
         {
             var content = new WebClient().DownloadString(url);
             RunTest(content);
         }
 
-        [InlineData("math-cordic", "https://raw.github.com/WebKit/webkit/master/PerformanceTests/SunSpider/tests/sunspider-1.0.1/math-cordic.js")]
+        [InlineData("math-cordic", "https://raw.githubusercontent.com/WebKit/webkit/master/PerformanceTests/SunSpider/tests/sunspider-1.0.2/math-cordic.js")]
         public void MathCordic(string name, string url)
         {
             var content = new WebClient().DownloadString(url);
@@ -177,7 +177,7 @@ namespace Jint.Tests.CommonScripts
         }
 
         [Theory]
-        [InlineData("math-partial-sums", "https://raw.github.com/WebKit/webkit/master/PerformanceTests/SunSpider/tests/sunspider-1.0.1/math-partial-sums.js")]
+        [InlineData("math-partial-sums", "https://raw.githubusercontent.com/WebKit/webkit/master/PerformanceTests/SunSpider/tests/sunspider-1.0.2/math-partial-sums.js")]
         public void MathPartialSums(string name, string url)
         {
             var content = new WebClient().DownloadString(url);
@@ -185,7 +185,7 @@ namespace Jint.Tests.CommonScripts
         }
 
         [Theory]
-        [InlineData("math-spectral-norm", "https://raw.github.com/WebKit/webkit/master/PerformanceTests/SunSpider/tests/sunspider-1.0.1/math-spectral-norm.js")]
+        [InlineData("math-spectral-norm", "https://raw.githubusercontent.com/WebKit/webkit/master/PerformanceTests/SunSpider/tests/sunspider-1.0.2/math-spectral-norm.js")]
         public void MathSpectralNorm(string name, string url)
         {
             var content = new WebClient().DownloadString(url);
@@ -193,7 +193,7 @@ namespace Jint.Tests.CommonScripts
         }
 
         [Theory]
-        [InlineData("regexp-dna", "https://raw.github.com/WebKit/webkit/master/PerformanceTests/SunSpider/tests/sunspider-1.0.1/regexp-dna.js")]
+        [InlineData("regexp-dna", "https://raw.githubusercontent.com/WebKit/webkit/master/PerformanceTests/SunSpider/tests/sunspider-1.0.2/regexp-dna.js")]
         public void RegexpDna(string name, string url)
         {
             var content = new WebClient().DownloadString(url);
@@ -201,14 +201,14 @@ namespace Jint.Tests.CommonScripts
         }
 
         [Theory]
-        [InlineData("string-base64", "https://raw.github.com/WebKit/webkit/master/PerformanceTests/SunSpider/tests/sunspider-1.0.1/string-base64.js")]
+        [InlineData("string-base64", "https://raw.githubusercontent.com/WebKit/webkit/master/PerformanceTests/SunSpider/tests/sunspider-1.0.2/string-base64.js")]
         public void StringBase64(string name, string url)
         {
             var content = new WebClient().DownloadString(url);
             RunTest(content);
         }
 
-        [InlineData("string-fasta", "https://raw.github.com/WebKit/webkit/master/PerformanceTests/SunSpider/tests/sunspider-1.0.1/string-fasta.js")]
+        [InlineData("string-fasta", "https://raw.githubusercontent.com/WebKit/webkit/master/PerformanceTests/SunSpider/tests/sunspider-1.0.2/string-fasta.js")]
         public void StringFasta(string name, string url)
         {
             var content = new WebClient().DownloadString(url);
@@ -216,7 +216,7 @@ namespace Jint.Tests.CommonScripts
         }
 
         [Theory]
-        [InlineData("string-tagcloud", "https://raw.github.com/WebKit/webkit/master/PerformanceTests/SunSpider/tests/sunspider-1.0.1/string-tagcloud.js")]
+        [InlineData("string-tagcloud", "https://raw.githubusercontent.com/WebKit/webkit/master/PerformanceTests/SunSpider/tests/sunspider-1.0.2/string-tagcloud.js")]
         public void StringTagCloud(string name, string url)
         {
             var content = new WebClient().DownloadString(url);
@@ -224,7 +224,7 @@ namespace Jint.Tests.CommonScripts
         }
 
         [Theory]
-        [InlineData("string-unpack-code", "https://raw.github.com/WebKit/webkit/master/PerformanceTests/SunSpider/tests/sunspider-1.0.1/string-unpack-code.js")]
+        [InlineData("string-unpack-code", "https://raw.githubusercontent.com/WebKit/webkit/master/PerformanceTests/SunSpider/tests/sunspider-1.0.2/string-unpack-code.js")]
         public void StringUnpackCode(string name, string url)
         {
             var content = new WebClient().DownloadString(url);
@@ -232,7 +232,7 @@ namespace Jint.Tests.CommonScripts
         }
 
         [Theory]
-        [InlineData("string-validate-input", "https://raw.github.com/WebKit/webkit/master/PerformanceTests/SunSpider/tests/sunspider-1.0.1/string-validate-input.js")]
+        [InlineData("string-validate-input", "https://raw.githubusercontent.com/WebKit/webkit/master/PerformanceTests/SunSpider/tests/sunspider-1.0.2/string-validate-input.js")]
         public void StringValidateInput(string name, string url)
         {
             var content = new WebClient().DownloadString(url);

+ 3 - 2
Jint.Tests.Ecma/EcmaTest.cs

@@ -25,8 +25,9 @@ namespace Jint.Tests.Ecma
         {
             _lastError = null;
 
-            var engine = new Engine();
-
+            //NOTE: The Date tests in test262 assume the local timezone is Pacific Standard Time
+            var pacificTimeZone = TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time");
+            var engine = new Engine(cfg => cfg.LocalTimeZone(pacificTimeZone));
 
             // loading driver
 

+ 3 - 0
Jint.Tests.Ecma/Jint.Tests.Ecma.csproj

@@ -12038,6 +12038,9 @@
   <ItemGroup>
     <None Include="packages.config" />
   </ItemGroup>
+  <ItemGroup>
+    <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+  </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
   <Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 

+ 8 - 0
Jint.Tests/Jint.Tests.csproj

@@ -59,6 +59,8 @@
     <Compile Include="Runtime\Domain\ClassWithField.cs" />
     <Compile Include="Runtime\Domain\ClassWithStaticFields.cs" />
     <Compile Include="Runtime\Domain\Colors.cs" />
+    <Compile Include="Runtime\Domain\Company.cs" />
+    <Compile Include="Runtime\Domain\ICompany.cs" />
     <Compile Include="Runtime\Domain\IPerson.cs" />
     <Compile Include="Runtime\Domain\Person.cs" />
     <Compile Include="Runtime\Domain\Shape.cs" />
@@ -96,6 +98,12 @@
   <ItemGroup>
     <EmbeddedResource Include="Parser\Scripts\JSXTransformer.js" />
   </ItemGroup>
+  <ItemGroup>
+    <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+  </ItemGroup>
+  <ItemGroup>
+    <EmbeddedResource Include="Parser\Scripts\handlebars.js" />
+  </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
   <Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 

+ 1 - 0
Jint.Tests/Parser/JavascriptParserTests.cs

@@ -21,6 +21,7 @@ namespace Jint.Tests.Parser
         [InlineData("mootools.js", "1.4.5")]
         [InlineData("angular.js", "1.2.5")]
         [InlineData("JSXTransformer.js", "0.10.0")]
+        [InlineData("handlebars.js", "2.0.0")]
         public void ShouldParseScriptFile(string file, string version)
         {
             const string prefix = "Jint.Tests.Parser.Scripts.";

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 983 - 0
Jint.Tests/Parser/Scripts/handlebars.js


+ 24 - 0
Jint.Tests/Runtime/Domain/A.cs

@@ -45,5 +45,29 @@ namespace Jint.Tests.Runtime.Domain
 
             return callback(thisArg, arguments).ToString();
         }
+
+        public bool Call7(string str, Func<string, bool> predicate)
+        {
+            return predicate(str);
+        }
+
+        public string Call8(Func<string> predicate)
+        {
+            return predicate();
+        }
+
+        public void Call9(Action predicate)
+        {
+            predicate();
+        }
+        public void Call10(string str, Action<string> predicate)
+        {
+            predicate(str);
+        }
+        public void Call11(string str, string str2, Action<string, string> predicate)
+        {
+            predicate(str, str2);
+        }
+
     }
 }

+ 36 - 0
Jint.Tests/Runtime/Domain/Company.cs

@@ -0,0 +1,36 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Jint.Tests.Runtime.Domain
+{
+    public class Company : ICompany, IComparable<ICompany>
+    {
+        private string _name;
+        private readonly Dictionary<string, string> _dictionary = new Dictionary<string, string>();
+
+        public Company(string name)
+        {
+            _name = name;
+        }
+
+        string ICompany.Name
+        {
+            get { return _name; }
+            set { _name = value; }
+        }
+
+        string ICompany.this[string key]
+        {
+            get { return _dictionary[key]; }
+            set { _dictionary[key] = value; }
+        }
+
+        int IComparable<ICompany>.CompareTo(ICompany other)
+        {
+            return string.Compare(_name, other.Name, StringComparison.CurrentCulture);
+        }
+    }
+}

+ 8 - 0
Jint.Tests/Runtime/Domain/ICompany.cs

@@ -0,0 +1,8 @@
+namespace Jint.Tests.Runtime.Domain
+{
+    public interface ICompany
+    {
+        string Name { get; set; }
+        string this[string key] { get; set; }
+    }
+}

+ 186 - 5
Jint.Tests/Runtime/EngineTests.cs

@@ -9,6 +9,7 @@ using Jint.Parser.Ast;
 using Jint.Runtime;
 using Xunit;
 using Xunit.Extensions;
+using System.Net;
 
 namespace Jint.Tests.Runtime
 {
@@ -31,7 +32,6 @@ namespace Jint.Tests.Runtime
 
         private void RunTest(string source)
         {
-
             _engine.Execute(source);
         }
 
@@ -594,9 +594,9 @@ namespace Jint.Tests.Runtime
         [Fact]
         public void ShouldNotExecuteDebuggerStatement()
         {
-            new Engine().Execute("debugger"); 
+            new Engine().Execute("debugger");
         }
-       
+
         [Fact]
         public void ShouldThrowStatementCountOverflow()
         {
@@ -604,6 +604,15 @@ namespace Jint.Tests.Runtime
                 () => new Engine(cfg => cfg.MaxStatements(100)).Execute("while(true);")
             );
         }
+        
+        [Fact]
+        public void ShouldThrowTimeout()
+        {
+            Assert.Throws<TimeoutException>(
+                () => new Engine(cfg => cfg.TimeoutInterval(new TimeSpan(0, 0, 0, 0, 500))).Execute("while(true);")
+            );
+        }
+
 
         [Fact]
         public void ShouldDiscardRecursion()
@@ -795,7 +804,7 @@ namespace Jint.Tests.Runtime
                 assert(regex.test('a/b') === true);
                 assert(regex.test('a\\/b') === false);
             ");
-      }
+        }
 
         [Fact]
         public void ShouldComputeFractionInBase()
@@ -842,6 +851,42 @@ namespace Jint.Tests.Runtime
             Assert.Equal(expected, result);
         }
 
+        [Fact]
+        public void JsonParserShouldParseNegativeNumber()
+        {
+            RunTest(@"
+                var a = JSON.parse('{ ""x"":-1 }');
+                assert(a.x === -1);
+
+                var b = JSON.parse('{ ""x"": -1 }');
+                assert(b.x === -1);
+            ");
+        }
+
+        [Fact]
+        public void JsonParserShouldDetectInvalidNegativeNumberSyntax()
+        {
+            RunTest(@"
+                try {
+                    JSON.parse('{ ""x"": -.1 }'); // Not allowed
+                    assert(false);
+                }
+                catch(ex) {
+                    assert(ex instanceof SyntaxError);
+                }
+            ");
+
+            RunTest(@"
+                try {
+                    JSON.parse('{ ""x"": - 1 }'); // Not allowed
+                    assert(false);
+                }
+                catch(ex) {
+                    assert(ex instanceof SyntaxError);
+                }
+            ");
+        }
+
         [Fact]
         public void ShouldBeCultureInvariant()
         {
@@ -849,7 +894,7 @@ namespace Jint.Tests.Runtime
             Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo("fr-FR");
 
             var engine = new Engine();
-            
+
             var result = engine.Execute("1.2 + 2.1").GetCompletionValue().AsNumber();
             Assert.Equal(3.3d, result);
 
@@ -883,5 +928,141 @@ namespace Jint.Tests.Runtime
             }
         }
 
+        [Fact]
+        public void ParseShouldReturnNumber()
+        {
+            var engine = new Engine();
+
+            var result = engine.Execute("Date.parse('1970-01-01');").GetCompletionValue().AsNumber();
+            Assert.Equal(0, result);
+        }
+
+        [Fact]
+        public void UtcShouldUseUtc()
+        {
+            const string customName = "Custom Time";
+            var customTimeZone = TimeZoneInfo.CreateCustomTimeZone(customName, new TimeSpan(7, 11, 0), customName, customName, customName, null, false);
+            var engine = new Engine(cfg => cfg.LocalTimeZone(customTimeZone));
+
+            var result = engine.Execute("Date.UTC(1970,0,1)").GetCompletionValue().AsNumber();
+            Assert.Equal(0, result);
+        }
+
+        [Fact]
+        public void ShouldUseLocalTimeZoneOverride()
+        {
+            const string customName = "Custom Time";
+            var customTimeZone = TimeZoneInfo.CreateCustomTimeZone(customName, new TimeSpan(0, 11, 0), customName, customName, customName, null, false);
+
+            var engine = new Engine(cfg => cfg.LocalTimeZone(customTimeZone));
+
+            var epochGetLocalMinutes = engine.Execute("var d = new Date(0); d.getMinutes();").GetCompletionValue().AsNumber();
+            Assert.Equal(11, epochGetLocalMinutes);
+
+            var localEpochGetUtcMinutes = engine.Execute("var d = new Date(1970,0,1); d.getUTCMinutes();").GetCompletionValue().AsNumber();
+            Assert.Equal(-11, localEpochGetUtcMinutes);
+
+            var parseLocalEpoch = engine.Execute("Date.parse('January 1, 1970');").GetCompletionValue().AsNumber();
+            Assert.Equal(-11 * 60 * 1000, parseLocalEpoch);
+
+            var epochToLocalString = engine.Execute("var d = new Date(0); d.toString();").GetCompletionValue().AsString();
+            Assert.Equal("Thu Jan 01 1970 00:11:00 GMT", epochToLocalString);
+        }
+
+        [Theory]
+        [InlineData("1970")]
+        [InlineData("1970-01")]
+        [InlineData("1970-01-01")]
+        [InlineData("1970-01-01T00:00")]
+        [InlineData("1970-01-01T00:00:00")]
+        [InlineData("1970-01-01T00:00:00.000")]
+        [InlineData("1970Z")]
+        [InlineData("1970-1Z")]
+        [InlineData("1970-1-1Z")]
+        [InlineData("1970-1-1T0:0Z")]
+        [InlineData("1970-1-1T0:0:0Z")]
+        [InlineData("1970-1-1T0:0:0.0Z")]
+        [InlineData("1970/1Z")]
+        [InlineData("1970/1/1Z")]
+        [InlineData("1970/1/1 0:0Z")]
+        [InlineData("1970/1/1 0:0:0Z")]
+        [InlineData("1970/1/1 0:0:0.0Z")]
+        [InlineData("January 1, 1970 GMT")]
+        [InlineData("1970-01-01T00:00:00.000-00:00")]
+        public void ShouldParseAsUtc(string date)
+        {
+            const string customName = "Custom Time";
+            var customTimeZone = TimeZoneInfo.CreateCustomTimeZone(customName, new TimeSpan(7, 11, 0), customName, customName, customName, null, false);
+            var engine = new Engine(cfg => cfg.LocalTimeZone(customTimeZone));
+
+            engine.SetValue("d", date);
+            var result = engine.Execute("Date.parse(d);").GetCompletionValue().AsNumber();
+
+            Assert.Equal(0, result);
+        }
+
+        [Theory]
+        [InlineData("1970/01")]
+        [InlineData("1970/01/01")]
+        [InlineData("1970/01/01T00:00")]
+        [InlineData("1970/01/01 00:00")]
+        [InlineData("1970-1")]
+        [InlineData("1970-1-1")]
+        [InlineData("1970-1-1T0:0")]
+        [InlineData("1970-1-1 0:0")]
+        [InlineData("1970/1")]
+        [InlineData("1970/1/1")]
+        [InlineData("1970/1/1T0:0")]
+        [InlineData("1970/1/1 0:0")]
+        [InlineData("01-1970")]
+        [InlineData("01-01-1970")]
+        [InlineData("January 1, 1970")]
+        [InlineData("1970-01-01T00:00:00.000+00:11")]
+        public void ShouldParseAsLocalTime(string date)
+        {
+            const string customName = "Custom Time";
+            var customTimeZone = TimeZoneInfo.CreateCustomTimeZone(customName, new TimeSpan(0, 11, 0), customName, customName, customName, null, false);
+            var engine = new Engine(cfg => cfg.LocalTimeZone(customTimeZone)).SetValue("d", date);
+
+            var result = engine.Execute("Date.parse(d);").GetCompletionValue().AsNumber();
+
+            Assert.Equal(-11 * 60 * 1000, result);
+        }
+
+        [Fact]
+        public void EmptyStringShouldMatchRegex()
+        {
+            RunTest(@"
+                var regex = /^(?:$)/g;
+                assert(''.match(regex) instanceof Array);
+            ");
+        }
+
+        [Fact]
+        public void ShouldExecuteHandlebars()
+        {
+            var url = "http://cdnjs.cloudflare.com/ajax/libs/handlebars.js/2.0.0/handlebars.js";
+            var content = new WebClient().DownloadString(url);
+
+            RunTest(content);
+
+            RunTest(@"
+                var source = 'Hello {{name}}';
+                var template = Handlebars.compile(source);
+                var context = {name: 'Paul'};
+                var html = template(context);
+
+                assert('Hello Paul' == html);
+            ");
+        }
+
+        [Fact]
+        public void DateParseReturnsNaN()
+        {
+            RunTest(@"
+                var d = Date.parse('not a date');
+                assert(isNaN(d));
+            ");
+        }
     }
 }

+ 139 - 1
Jint.Tests/Runtime/InteropTests.cs

@@ -560,6 +560,86 @@ namespace Jint.Tests.Runtime
             ");
         }
 
+        [Fact]
+        public void ShouldExecuteFunctionCallBackAsPredicate()
+        {
+            _engine.SetValue("a", new A());
+            
+            // Func<>
+            RunTest(@"
+                assert(a.Call8(function(){ return 'foo'; }) === 'foo');
+            ");
+        }
+
+        [Fact]
+        public void ShouldExecuteFunctionWithParameterCallBackAsPredicate()
+        {
+            _engine.SetValue("a", new A());
+
+            // Func<,>
+            RunTest(@"
+                assert(a.Call7('foo', function(a){ return a === 'foo'; }) === true);
+            ");
+        }
+
+        [Fact]
+        public void ShouldExecuteActionCallBackAsPredicate()
+        {
+            _engine.SetValue("a", new A());
+
+            // Action
+            RunTest(@"
+                var value;
+                a.Call9(function(){ value = 'foo'; });
+                assert(value === 'foo');
+            ");
+        }
+
+        [Fact]
+        public void ShouldExecuteActionWithParameterCallBackAsPredicate()
+        {
+            _engine.SetValue("a", new A());
+
+            // Action<>
+            RunTest(@"
+                var value;
+                a.Call10('foo', function(b){ value = b; });
+                assert(value === 'foo');
+            ");
+        }
+
+        [Fact]
+        public void ShouldExecuteActionWithMultipleParametersCallBackAsPredicate()
+        {
+            _engine.SetValue("a", new A());
+
+            // Action<,>
+            RunTest(@"
+                var value;
+                a.Call11('foo', 'bar', function(a,b){ value = a + b; });
+                assert(value === 'foobar');
+            ");
+        }
+
+        [Fact]
+        public void ShouldExecuteActionCallbackOnEventChanged()
+        {
+            var collection = new System.Collections.ObjectModel.ObservableCollection<string>();
+            Assert.True(collection.Count == 0);
+
+            _engine.SetValue("collection", collection);
+
+            RunTest(@"
+                var eventAction;
+                collection.add_CollectionChanged(function(sender, eventArgs) { eventAction = eventArgs.Action; } );
+                collection.Add('test');
+            ");
+
+            var eventAction = _engine.GetValue("eventAction").AsNumber();
+            Assert.True(eventAction == 0);
+            Assert.True(collection.Count == 1);
+        }
+
         [Fact]
         public void ShouldUseSystemIO()
         {
@@ -859,7 +939,65 @@ namespace Jint.Tests.Runtime
             ");
 
             Assert.Equal(Colors.Blue | Colors.Green, s.Color);
-        }
+        }
+
+        [Fact]
+        public void ShouldUseExplicitPropertyGetter()
+        {
+            _engine.SetValue("c", new Company("ACME"));
+
+            RunTest(@"
+                assert(c.Name === 'ACME');
+            ");
+        }
+
+        [Fact]
+        public void ShouldUseExplicitIndexerPropertyGetter()
+        {
+            var company = new Company("ACME");
+            ((ICompany)company)["Foo"] = "Bar";
+            _engine.SetValue("c", company);
+
+            RunTest(@"
+                assert(c.Foo === 'Bar');
+            ");
+        }
+
+
+        [Fact]
+        public void ShouldUseExplicitPropertySetter()
+        {
+            _engine.SetValue("c", new Company("ACME"));
+
+            RunTest(@"
+                c.Name = 'Foo';
+                assert(c.Name === 'Foo');
+            ");
+        }
+
+        [Fact]
+        public void ShouldUseExplicitIndexerPropertySetter()
+        {
+            var company = new Company("ACME");
+            ((ICompany)company)["Foo"] = "Bar";
+            _engine.SetValue("c", company);
+
+            RunTest(@"
+                c.Foo = 'Baz';
+                assert(c.Foo === 'Baz');
+            ");
+        }
+
+
+        [Fact]
+        public void ShouldUseExplicitMethod()
+        {
+            _engine.SetValue("c", new Company("ACME"));
+
+            RunTest(@"
+                assert(0 === c.CompareTo(c));
+            ");
+        }
 
     }
 }

+ 1 - 1
Jint.sln

@@ -1,7 +1,7 @@
 
 Microsoft Visual Studio Solution File, Format Version 12.00
 # Visual Studio 2013
-VisualStudioVersion = 12.0.30110.0
+VisualStudioVersion = 12.0.30723.0
 MinimumVisualStudioVersion = 10.0.40219.1
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jint.Tests", "Jint.Tests\Jint.Tests.csproj", "{37C7D4E0-8770-4E2A-8B6D-E53087868354}"
 EndProject

+ 17 - 0
Jint/Engine.cs

@@ -32,7 +32,10 @@ namespace Jint
         private readonly Stack<ExecutionContext> _executionContexts;
         private JsValue _completionValue = JsValue.Undefined;
         private int _statementsCount;
+        private long _timeoutTicks;
         private SyntaxNode _lastSyntaxNode = null;
+        
+        public ITypeConverter ClrTypeConverter;
 
         // cache of types used when resolving CLR type names
         internal Dictionary<string, Type> TypeCache = new Dictionary<string, Type>();
@@ -131,6 +134,8 @@ namespace Jint
                     return new NamespaceReference(this, TypeConverter.ToString(arguments.At(0)));
                 }), false, false, false);
             }
+
+            ClrTypeConverter = new DefaultTypeConverter(this);
         }
 
         public LexicalEnvironment GlobalEnvironment;
@@ -217,6 +222,12 @@ namespace Jint
         {
             _statementsCount = 0;
         }
+        
+        public void ResetTimeoutTicks()
+        {
+            var timeoutIntervalTicks = Options.GetTimeoutInterval().Ticks;
+            _timeoutTicks = timeoutIntervalTicks > 0 ? DateTime.UtcNow.Ticks + timeoutIntervalTicks : 0;
+        }
 
         /// <summary>
         /// Initializes list of references of called functions
@@ -241,6 +252,7 @@ namespace Jint
         public Engine Execute(Program program)
         {
             ResetStatementsCount();
+            ResetTimeoutTicks();
             ResetLastStatement();
             ResetCallStack();
 
@@ -281,6 +293,11 @@ namespace Jint
                 throw new StatementsCountOverflowException();
             }
 
+            if (_timeoutTicks > 0 && _timeoutTicks < DateTime.UtcNow.Ticks)
+            {
+                throw new TimeoutException();
+            }
+
             _lastSyntaxNode = statement;
 
             switch (statement.Type)

+ 75 - 47
Jint/Native/Date/DateConstructor.cs

@@ -46,48 +46,53 @@ namespace Jint.Native.Date
 
             if (!DateTime.TryParseExact(date, new[]
             {
-                "yyyy/MM/ddTH:m:s.fff",
-                "yyyy/MM/dd",
-                "yyyy/MM",
-                "yyyy-MM-ddTH:m:s.fff",
+                "yyyy-MM-ddTHH:mm:ss.FFF",
+                "yyyy-MM-ddTHH:mm:ss",
+                "yyyy-MM-ddTHH:mm",
                 "yyyy-MM-dd",
                 "yyyy-MM",
-                "yyyy",
-                "THH:m:s.fff",
-                "TH:mm:sm",
-                "THH:mm",
-                "THH"
+                "yyyy"
             }, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal, out result))
             {
                 if (!DateTime.TryParseExact(date, new[]
                 {
-                    "yyyy/MM/ddTH:m:s.fffK",
-                    "yyyy/MM/ddK",
-                    "yyyy/MMK",
-                    "yyyy-MM-ddTH:m:s.fffK",
-                    "yyyy-MM-ddK",
-                    "yyyy-MMK",
+                    "yyyy-M-dTH:m:s.FFFK",
+                    "yyyy/M/dTH:m:s.FFFK",
+                    "yyyy-M-dTH:m:sK",
+                    "yyyy/M/dTH:m:sK",
+                    "yyyy-M-dTH:mK",
+                    "yyyy/M/dTH:mK",
+                    "yyyy-M-d H:m:s.FFFK",
+                    "yyyy/M/d H:m:s.FFFK",
+                    "yyyy-M-d H:m:sK",
+                    "yyyy/M/d H:m:sK",
+                    "yyyy-M-d H:mK",
+                    "yyyy/M/d H:mK",
+                    "yyyy-M-dK",
+                    "yyyy/M/dK",
+                    "yyyy-MK",
+                    "yyyy/MK",
                     "yyyyK",
-                    "THH:m:s.fffK",
-                    "TH:mm:smK",
+                    "THH:mm:ss.FFFK",
+                    "THH:mm:ssK",
                     "THH:mmK",
                     "THHK"
                 }, CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal, out result))
                 {
                     if (!DateTime.TryParse(date, CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal,out result))
                     {
-                        throw new JavaScriptException(Engine.SyntaxError, "Invalid date");
+                        // unrecognized dates should return NaN (15.9.4.2)
+                        return double.NaN;
                     }
                 }
             }
 
-            return Construct(result);
+            return FromDateTime(result);
         }
 
         private JsValue Utc(JsValue thisObj, JsValue[] arguments)
         {
-            var local = (DateInstance) Construct(arguments);
-            return local.PrimitiveValue;
+            return TimeClip(ConstructTimeValue(arguments, useUtc: true));
         }
 
         private JsValue Now(JsValue thisObj, JsValue[] arguments)
@@ -109,46 +114,56 @@ namespace Jint.Native.Date
         {
             if (arguments.Length == 0)
             {
-                return Construct(DateTime.Now);
+                return Construct(DateTime.UtcNow);
             }
             else if (arguments.Length == 1)
             {
                 var v = TypeConverter.ToPrimitive(arguments[0]);
                 if (v.IsString())
                 {
-                    return Parse(Undefined.Instance, Arguments.From(v)).AsObject();
+                    return Construct(Parse(Undefined.Instance, Arguments.From(v)).AsNumber());
                 }
 
-                return Construct(DatePrototype.TimeClip(TypeConverter.ToNumber(v)));
+                return Construct(TypeConverter.ToNumber(v));
             }
             else
             {
-                var y = TypeConverter.ToNumber(arguments[0]);
-                var m = (int)TypeConverter.ToInteger(arguments[1]);
-                var dt = arguments.Length > 2 ? (int)TypeConverter.ToInteger(arguments[2]) : 1;
-                var h = arguments.Length > 3 ? (int)TypeConverter.ToInteger(arguments[3]) : 0;
-                var min = arguments.Length > 4 ? (int)TypeConverter.ToInteger(arguments[4]) : 0;
-                var s = arguments.Length > 5 ? (int)TypeConverter.ToInteger(arguments[5]) : 0;
-                var milli = arguments.Length > 6 ? (int)TypeConverter.ToInteger(arguments[6]) : 0;
-
-                for (int i = 2; i < arguments.Length; i++)
-                {
-                    if (double.IsNaN(TypeConverter.ToNumber(arguments[i])))
-                    {
-                        return Construct(double.NaN);
-                    }
-                }
+                return Construct(ConstructTimeValue(arguments, useUtc: false));
+            }
+        }
 
-                if ((!double.IsNaN(y)) && (0 <= TypeConverter.ToInteger(y)) && (TypeConverter.ToInteger(y) <= 99))
+        private double ConstructTimeValue(JsValue[] arguments, bool useUtc)
+        {
+            if (arguments.Length < 2)
+            {
+                throw new ArgumentOutOfRangeException("arguments", "There must be at least two arguments.");
+            }
+
+            var y = TypeConverter.ToNumber(arguments[0]);
+            var m = (int)TypeConverter.ToInteger(arguments[1]);
+            var dt = arguments.Length > 2 ? (int)TypeConverter.ToInteger(arguments[2]) : 1;
+            var h = arguments.Length > 3 ? (int)TypeConverter.ToInteger(arguments[3]) : 0;
+            var min = arguments.Length > 4 ? (int)TypeConverter.ToInteger(arguments[4]) : 0;
+            var s = arguments.Length > 5 ? (int)TypeConverter.ToInteger(arguments[5]) : 0;
+            var milli = arguments.Length > 6 ? (int)TypeConverter.ToInteger(arguments[6]) : 0;
+
+            for (int i = 2; i < arguments.Length; i++)
+            {
+                if (double.IsNaN(TypeConverter.ToNumber(arguments[i])))
                 {
-                    y += 1900;
+                    return double.NaN;
                 }
+            }
 
-                var finalDate = DatePrototype.MakeDate(DatePrototype.MakeDay(y, m, dt),
-                    DatePrototype.MakeTime(h, min, s, milli));
-
-                return Construct(DatePrototype.TimeClip(DatePrototype.Utc(finalDate)));
+            if ((!double.IsNaN(y)) && (0 <= TypeConverter.ToInteger(y)) && (TypeConverter.ToInteger(y) <= 99))
+            {
+                y += 1900;
             }
+
+            var finalDate = DatePrototype.MakeDate(DatePrototype.MakeDay(y, m, dt),
+                DatePrototype.MakeTime(h, min, s, milli));
+
+            return useUtc ? finalDate : PrototypeObject.Utc(finalDate);
         }
 
         public DatePrototype PrototypeObject { get; private set; }
@@ -197,9 +212,22 @@ namespace Jint.Native.Date
             return TypeConverter.ToInteger(time);
         }
 
-        public static double FromDateTime(DateTime dt)
+        public double FromDateTime(DateTime dt)
         {
-            return System.Math.Floor((dt.ToUniversalTime() - Epoch).TotalMilliseconds);
+            var convertToUtcAfter = (dt.Kind == DateTimeKind.Unspecified);
+
+            var dateAsUtc = dt.Kind == DateTimeKind.Local
+                ? dt.ToUniversalTime()
+                : DateTime.SpecifyKind(dt, DateTimeKind.Utc);
+
+            var result = (dateAsUtc - Epoch).TotalMilliseconds;
+
+            if (convertToUtcAfter)
+            {
+                result = PrototypeObject.Utc(result);
+            }
+
+            return System.Math.Floor(result);
         }
     }
 }

+ 35 - 25
Jint/Native/Date/DatePrototype.cs

@@ -85,7 +85,7 @@ namespace Jint.Native.Date
 
         public JsValue ToString(JsValue thisObj, JsValue[] arg2)
         {
-            return thisObj.TryCast<DateInstance>().ToDateTime().ToLocalTime().ToString("ddd MMM dd yyyy HH:mm:ss 'GMT'K", CultureInfo.InvariantCulture);
+            return ToLocalTime(thisObj.TryCast<DateInstance>().ToDateTime()).ToString("ddd MMM dd yyyy HH:mm:ss 'GMT'K", CultureInfo.InvariantCulture);
         }
 
         private static JsValue ToDateString(JsValue thisObj, JsValue[] arguments)
@@ -123,7 +123,7 @@ namespace Jint.Native.Date
             return thisObj.TryCast<DateInstance>().PrimitiveValue;
         }
 
-        private static JsValue GetFullYear(JsValue thisObj, JsValue[] arguments)
+        private JsValue GetFullYear(JsValue thisObj, JsValue[] arguments)
         {
             var t = thisObj.TryCast<DateInstance>().PrimitiveValue;
             if (double.IsNaN(t))
@@ -134,7 +134,7 @@ namespace Jint.Native.Date
             return YearFromTime(LocalTime(t));
         }
 
-        private static JsValue GetYear(JsValue thisObj, JsValue[] arguments)
+        private JsValue GetYear(JsValue thisObj, JsValue[] arguments)
         {
             var t = thisObj.TryCast<DateInstance>().PrimitiveValue;
             if (double.IsNaN(t))
@@ -156,7 +156,7 @@ namespace Jint.Native.Date
             return YearFromTime(t);
         }
 
-        private static JsValue GetMonth(JsValue thisObj, JsValue[] arguments)
+        private JsValue GetMonth(JsValue thisObj, JsValue[] arguments)
         {
             var t = thisObj.TryCast<DateInstance>().PrimitiveValue;
             if (double.IsNaN(t))
@@ -178,7 +178,7 @@ namespace Jint.Native.Date
             return MonthFromTime(t);
         }
 
-        private static JsValue GetDate(JsValue thisObj, JsValue[] arguments)
+        private JsValue GetDate(JsValue thisObj, JsValue[] arguments)
         {
             var t = thisObj.TryCast<DateInstance>().PrimitiveValue;
             if (double.IsNaN(t))
@@ -200,7 +200,7 @@ namespace Jint.Native.Date
             return DateFromTime(t);
         }
 
-        private static JsValue GetDay(JsValue thisObj, JsValue[] arguments)
+        private JsValue GetDay(JsValue thisObj, JsValue[] arguments)
         {
             var t = thisObj.TryCast<DateInstance>().PrimitiveValue;
             if (double.IsNaN(t))
@@ -222,7 +222,7 @@ namespace Jint.Native.Date
             return WeekDay(t);
         }
 
-        private static JsValue GetHours(JsValue thisObj, JsValue[] arguments)
+        private JsValue GetHours(JsValue thisObj, JsValue[] arguments)
         {
             var t = thisObj.TryCast<DateInstance>().PrimitiveValue;
             if (double.IsNaN(t))
@@ -244,7 +244,7 @@ namespace Jint.Native.Date
             return HourFromTime(t);
         }
 
-        private static JsValue GetMinutes(JsValue thisObj, JsValue[] arguments)
+        private JsValue GetMinutes(JsValue thisObj, JsValue[] arguments)
         {
             var t = thisObj.TryCast<DateInstance>().PrimitiveValue;
             if (double.IsNaN(t))
@@ -266,7 +266,7 @@ namespace Jint.Native.Date
             return MinFromTime(t);
         }
 
-        private static JsValue GetSeconds(JsValue thisObj, JsValue[] arguments)
+        private JsValue GetSeconds(JsValue thisObj, JsValue[] arguments)
         {
             var t = thisObj.TryCast<DateInstance>().PrimitiveValue;
             if (double.IsNaN(t))
@@ -288,7 +288,7 @@ namespace Jint.Native.Date
             return SecFromTime(t);
         }
 
-        private static JsValue GetMilliseconds(JsValue thisObj, JsValue[] arguments)
+        private JsValue GetMilliseconds(JsValue thisObj, JsValue[] arguments)
         {
             var t = thisObj.TryCast<DateInstance>().PrimitiveValue;
             if (double.IsNaN(t))
@@ -310,7 +310,7 @@ namespace Jint.Native.Date
             return MsFromTime(t);
         }
 
-        private static JsValue GetTimezoneOffset(JsValue thisObj, JsValue[] arguments)
+        private JsValue GetTimezoneOffset(JsValue thisObj, JsValue[] arguments)
         {
             var t = thisObj.TryCast<DateInstance>().PrimitiveValue;
             if (double.IsNaN(t))
@@ -326,7 +326,7 @@ namespace Jint.Native.Date
             return thisObj.As<DateInstance>().PrimitiveValue = TimeClip(TypeConverter.ToNumber(arguments.At(0)));
         }
 
-        private static JsValue SetMilliseconds(JsValue thisObj, JsValue[] arguments)
+        private JsValue SetMilliseconds(JsValue thisObj, JsValue[] arguments)
         {
             var t = LocalTime(thisObj.As<DateInstance>().PrimitiveValue);
             var time = MakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), TypeConverter.ToNumber(arguments.At(0)));
@@ -344,7 +344,7 @@ namespace Jint.Native.Date
             return u;
         }
 
-        private static JsValue SetSeconds(JsValue thisObj, JsValue[] arguments)
+        private JsValue SetSeconds(JsValue thisObj, JsValue[] arguments)
         {
             var t = LocalTime(thisObj.As<DateInstance>().PrimitiveValue);
             var s = TypeConverter.ToNumber(arguments.At(0));
@@ -366,7 +366,7 @@ namespace Jint.Native.Date
             return u;
         }
 
-        private static JsValue SetMinutes(JsValue thisObj, JsValue[] arguments)
+        private JsValue SetMinutes(JsValue thisObj, JsValue[] arguments)
         {
             var t = LocalTime(thisObj.As<DateInstance>().PrimitiveValue);
             var m = TypeConverter.ToNumber(arguments.At(0));
@@ -390,7 +390,7 @@ namespace Jint.Native.Date
             return u;
         }
 
-        private static JsValue SetHours(JsValue thisObj, JsValue[] arguments)
+        private JsValue SetHours(JsValue thisObj, JsValue[] arguments)
         {
             var t = LocalTime(thisObj.As<DateInstance>().PrimitiveValue);
             var h = TypeConverter.ToNumber(arguments.At(0));
@@ -416,7 +416,7 @@ namespace Jint.Native.Date
             return u;
         }
 
-        private static JsValue SetDate(JsValue thisObj, JsValue[] arguments)
+        private JsValue SetDate(JsValue thisObj, JsValue[] arguments)
         {
             var t = LocalTime(thisObj.As<DateInstance>().PrimitiveValue);
             var dt = TypeConverter.ToNumber(arguments.At(0));
@@ -436,7 +436,7 @@ namespace Jint.Native.Date
             return u;
         }
 
-        private static JsValue SetMonth(JsValue thisObj, JsValue[] arguments)
+        private JsValue SetMonth(JsValue thisObj, JsValue[] arguments)
         {
             var t = LocalTime(thisObj.As<DateInstance>().PrimitiveValue);
             var m = TypeConverter.ToNumber(arguments.At(0));
@@ -458,7 +458,7 @@ namespace Jint.Native.Date
             return u;
         }
 
-        private static JsValue SetFullYear(JsValue thisObj, JsValue[] arguments)
+        private JsValue SetFullYear(JsValue thisObj, JsValue[] arguments)
         {
             var thisTime = thisObj.As<DateInstance>().PrimitiveValue;
             var t = double.IsNaN(thisTime) ? +0 : LocalTime(thisTime);
@@ -471,7 +471,7 @@ namespace Jint.Native.Date
             return u;
         }
 
-        private static JsValue SetYear(JsValue thisObj, JsValue[] arguments)
+        private JsValue SetYear(JsValue thisObj, JsValue[] arguments)
         {
             var thisTime = thisObj.As<DateInstance>().PrimitiveValue;
             var t = double.IsNaN(thisTime) ? +0 : LocalTime(thisTime);
@@ -830,15 +830,15 @@ namespace Jint.Native.Date
             return (Day(t) + 4)%7;
         }
 
-        public static double LocalTza
+        public double LocalTza
         {
             get
             {
-                return TimeZoneInfo.Local.BaseUtcOffset.TotalMilliseconds;
+                return Engine.Options.GetLocalTimeZone().BaseUtcOffset.TotalMilliseconds;
             }
         }
 
-        public static double DaylightSavingTa(double t)
+        public double DaylightSavingTa(double t)
         {
             var timeInYear = t - TimeFromYear(YearFromTime(t));
 
@@ -861,15 +861,25 @@ namespace Jint.Native.Date
 
             var dateTime = new DateTime((int)year, 1, 1).AddMilliseconds(timeInYear);
 
-            return TimeZoneInfo.Local.IsDaylightSavingTime(dateTime) ? MsPerHour : 0;
+            return Engine.Options.GetLocalTimeZone().IsDaylightSavingTime(dateTime) ? MsPerHour : 0;
         }
 
-        public static double LocalTime(double t)
+        public DateTime ToLocalTime(DateTime t)
+        {
+            if (t.Kind == DateTimeKind.Unspecified)
+            {
+                return t;
+            }
+
+            return TimeZoneInfo.ConvertTime(t, Engine.Options.GetLocalTimeZone());
+        }
+
+        public double LocalTime(double t)
         {
             return t + LocalTza + DaylightSavingTa(t);
         }
 
-        public static double Utc(double t)
+        public double Utc(double t)
         {
             return t - LocalTza - DaylightSavingTa(t - LocalTza);
         }

+ 19 - 2
Jint/Native/Json/JsonParser.cs

@@ -161,9 +161,17 @@ namespace Jint.Native.Json
 
             int start = _index;
             string number = "";
+            
+            // Number start with a -
+            if (ch == '-')
+            {
+                number += _source.CharCodeAt(_index++).ToString();
+                ch = _source.CharCodeAt(_index);
+            }
+
             if (ch != '.')
             {
-                number = _source.CharCodeAt(_index++).ToString();
+                number += _source.CharCodeAt(_index++).ToString();
                 ch = _source.CharCodeAt(_index);
 
                 // Hex number starts with '0x'.
@@ -219,7 +227,7 @@ namespace Jint.Native.Json
             return new Token
                 {
                     Type = Tokens.Number,
-                    Value = Double.Parse(number, NumberStyles.AllowDecimalPoint | NumberStyles.AllowExponent, CultureInfo.InvariantCulture),
+                    Value = Double.Parse(number, NumberStyles.AllowLeadingSign | NumberStyles.AllowDecimalPoint | NumberStyles.AllowExponent, CultureInfo.InvariantCulture),
                     LineNumber = _lineNumber,
                     LineStart = _lineStart,
                     Range = new[] {start, _index}
@@ -447,6 +455,15 @@ namespace Jint.Native.Json
                 return ScanPunctuator();
             }
 
+            if (ch == '-') // Negative Number
+            {
+                if (IsDecimalDigit(_source.CharCodeAt(_index + 1)))
+                {
+                    return ScanNumericLiteral();
+                }
+                return ScanPunctuator();
+            }
+
             if (IsDecimalDigit(ch))
             {
                 return ScanNumericLiteral();

+ 1 - 1
Jint/Native/RegExp/RegExpPrototype.cs

@@ -86,7 +86,7 @@ namespace Jint.Native.RegExp
             }
 
             Match r = null;
-            if (i < 0 || i >= length)
+            if (i < 0 || i > length)
             {
                 R.Put("lastIndex", (double) 0, true);
                 return Null.Instance;

+ 26 - 16
Jint/Options.cs

@@ -1,4 +1,5 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
 using System.Globalization;
 using System.Linq;
 using System.Reflection;
@@ -14,11 +15,12 @@ namespace Jint
         private bool _strict;
         private bool _allowDebuggerStatement;
         private bool _allowClr;
-        private ITypeConverter _typeConverter = new DefaultTypeConverter();
         private readonly List<IObjectConverter> _objectConverters = new List<IObjectConverter>();
         private int _maxStatements;
         private int _maxRecursionDepth;
+        private TimeSpan _timeoutInterval;
         private CultureInfo _culture = CultureInfo.CurrentCulture;
+        private TimeZoneInfo _localTimeZone = TimeZoneInfo.Local;
         private List<Assembly> _lookupAssemblies = new List<Assembly>(); 
 
         /// <summary>
@@ -63,15 +65,6 @@ namespace Jint
             return this;
         }
 
-        /// <summary>
-        /// Sets a <see cref="ITypeConverter"/> instance to use when converting CLR types
-        /// </summary>
-        public Options SetTypeConverter(ITypeConverter typeConverter)
-        {
-            _typeConverter = typeConverter;
-            return this;
-        }
-
         /// <summary>
          /// Adds a <see cref="IObjectConverter"/> instance to convert CLR types to <see cref="JsValue"/>
         /// </summary>
@@ -97,6 +90,12 @@ namespace Jint
             _maxStatements = maxStatements;
             return this;
         }
+        
+        public Options TimeoutInterval(TimeSpan timeoutInterval)
+        {
+            _timeoutInterval = timeoutInterval;
+            return this;
+        }
 
         public Options MaxRecursionDepth(int maxRecursionDepth = 0)
         {
@@ -110,6 +109,12 @@ namespace Jint
             return this;
         }
 
+        public Options LocalTimeZone(TimeZoneInfo timeZoneInfo)
+        {
+            _localTimeZone = timeZoneInfo;
+            return this;
+        }
+
         internal bool GetDiscardGlobal()
         {
             return _discardGlobal;
@@ -135,11 +140,6 @@ namespace Jint
             return _lookupAssemblies;
         }
 
-        internal ITypeConverter GetTypeConverter()
-        {
-            return _typeConverter;
-        }
-
         internal IEnumerable<IObjectConverter> GetObjectConverters()
         {
             return _objectConverters;
@@ -160,9 +160,19 @@ namespace Jint
             return !_discardRecursion;
         }
 
+        internal TimeSpan GetTimeoutInterval()
+        {
+            return _timeoutInterval;
+        }
+
         internal CultureInfo GetCulture()
         {
             return _culture;
         }
+
+        internal TimeZoneInfo GetLocalTimeZone()
+        {
+            return _localTimeZone;
+        }
     }
 }

+ 8 - 8
Jint/Parser/JavascriptParser.cs

@@ -1,4 +1,4 @@
-using System;
+using System;
 using System.Collections.Generic;
 using System.Globalization;
 using System.Linq;
@@ -10,7 +10,7 @@ namespace Jint.Parser
 {
     public class JavaScriptParser
     {
-        private static readonly object[] Keywords =
+        private static readonly HashSet<string> Keywords = new HashSet<string>
         {
             "if", "in", "do", "var", "for", "new", "try", "let",
             "this", "else", "case", "void", "with", "enum",
@@ -20,7 +20,7 @@ namespace Jint.Parser
             "function", "continue", "debugger", "instanceof"
         };
 
-        private static readonly object[] StrictModeReservedWords =
+        private static readonly HashSet<string> StrictModeReservedWords = new HashSet<string>
         {
             "implements",
             "interface",
@@ -33,7 +33,7 @@ namespace Jint.Parser
             "let"
         };
 
-        private static readonly object[] FutureReservedWords =
+        private static readonly HashSet<string> FutureReservedWords = new HashSet<string>
         {
             "class",
             "enum",
@@ -145,12 +145,12 @@ namespace Jint.Parser
 
         private static bool IsFutureReservedWord(string id)
         {
-            return Array.IndexOf(FutureReservedWords, id) >= 0;
+            return FutureReservedWords.Contains(id);
         }
 
         private static bool IsStrictModeReservedWord(string id)
         {
-            return Array.IndexOf(StrictModeReservedWords, id) >= 0;
+            return StrictModeReservedWords.Contains(id);
         }
 
         private static bool IsRestrictedWord(string id)
@@ -170,8 +170,8 @@ namespace Jint.Parser
             // 'const' is specialized as Keyword in V8.
             // 'yield' and 'let' are for compatiblity with SpiderMonkey and ES.next.
             // Some others are from future reserved words.
-            
-            return Array.IndexOf(Keywords, id) >= 0;
+
+            return Keywords.Contains(id);
         }
 
         // 7.4 Comments

+ 1 - 1
Jint/Runtime/Descriptors/Specialized/FieldInfoDescriptor.cs

@@ -40,7 +40,7 @@ namespace Jint.Runtime.Descriptors.Specialized
                     obj = currentValue.ToObject();
                     if (obj.GetType() != _fieldInfo.FieldType)
                     {
-                        obj = _engine.Options.GetTypeConverter().Convert(obj, _fieldInfo.FieldType, CultureInfo.InvariantCulture);
+                        obj = _engine.ClrTypeConverter.Convert(obj, _fieldInfo.FieldType, CultureInfo.InvariantCulture);
                     }
                 }
                 

+ 13 - 5
Jint/Runtime/Descriptors/Specialized/IndexDescriptor.cs

@@ -1,4 +1,5 @@
-using System.Globalization;
+using System;
+using System.Globalization;
 using System.Reflection;
 using Jint.Native;
 
@@ -12,19 +13,26 @@ namespace Jint.Runtime.Descriptors.Specialized
         private readonly MethodInfo _getter;
         private readonly MethodInfo _setter;
 
-        public IndexDescriptor(Engine engine, string key, object item)
+        public IndexDescriptor(Engine engine, Type targetType, string key, object item)
         {
             _engine = engine;
             _item = item;
 
-            _getter = item.GetType().GetMethod("get_Item", BindingFlags.Instance | BindingFlags.Public);
-            _setter = item.GetType().GetMethod("set_Item", BindingFlags.Instance | BindingFlags.Public);
+            _getter = targetType.GetMethod("get_Item", BindingFlags.Instance | BindingFlags.Public);
+            _setter = targetType.GetMethod("set_Item", BindingFlags.Instance | BindingFlags.Public);
 
-            _key = _engine.Options.GetTypeConverter().Convert(key, _getter.GetParameters()[0].ParameterType, CultureInfo.InvariantCulture);
+            _key = _engine.ClrTypeConverter.Convert(key, _getter.GetParameters()[0].ParameterType, CultureInfo.InvariantCulture);
 
             Writable = true;
         }
 
+
+        public IndexDescriptor(Engine engine, string key, object item)
+            : this(engine, item.GetType(), key, item)
+        {
+            
+        }
+
         public override JsValue? Value
         {
             get

+ 1 - 1
Jint/Runtime/Descriptors/Specialized/PropertyInfoDescriptor.cs

@@ -40,7 +40,7 @@ namespace Jint.Runtime.Descriptors.Specialized
                     obj = currentValue.ToObject();
                     if (obj.GetType() != _propertyInfo.PropertyType)
                     {
-                        obj = _engine.Options.GetTypeConverter().Convert(obj, _propertyInfo.PropertyType, CultureInfo.InvariantCulture);
+                        obj = _engine.ClrTypeConverter.Convert(obj, _propertyInfo.PropertyType, CultureInfo.InvariantCulture);
                     }
                 }
                 

+ 101 - 0
Jint/Runtime/Interop/DefaultTypeConverter.cs

@@ -1,9 +1,20 @@
 using System;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Linq.Expressions;
+using Jint.Native;
 
 namespace Jint.Runtime.Interop
 {
     public class DefaultTypeConverter : ITypeConverter
     {
+        private readonly Engine _engine;
+
+        public DefaultTypeConverter(Engine engine)
+        {
+            _engine = engine;
+        }
+
         public object Convert(object value, Type type, IFormatProvider formatProvider)
         {
             // don't try to convert if value is derived from type
@@ -23,6 +34,96 @@ namespace Jint.Runtime.Interop
                 return Enum.ToObject(type, integer);
             }
 
+            var valueType = value.GetType();
+            // is the javascript value an ICallable instance ?
+            if (valueType == typeof (Func<JsValue, JsValue[], JsValue>))
+            {
+                var function = (Func<JsValue, JsValue[], JsValue>) value;
+
+                if (type.IsGenericType)
+                {
+                    var genericType = type.GetGenericTypeDefinition();
+
+                    // create the requested Delegate
+                    if (genericType.Name.StartsWith("Action"))
+                    {
+                        var genericArguments = type.GetGenericArguments();
+
+                        var @params = new ParameterExpression[genericArguments.Count()];
+                        for (var i = 0; i < @params.Count(); i++)
+                        {
+                            @params[i] = Expression.Parameter(genericArguments[i], genericArguments[i].Name + i);
+                        }
+                        var @vars = Expression.NewArrayInit(typeof(JsValue), @params.Select(p => Expression.Call(null, typeof(JsValue).GetMethod("FromObject"), Expression.Constant(_engine, typeof(Engine)), p)));
+
+                        var callExpresion = Expression.Block(Expression.Call(
+                                                Expression.Call(Expression.Constant(function.Target),
+                                                    function.Method,
+                                                    Expression.Constant(JsValue.Undefined, typeof(JsValue)),
+                                                    @vars),
+                                                typeof(JsValue).GetMethod("ToObject")), Expression.Empty());
+
+                        return Expression.Lambda(callExpresion, new ReadOnlyCollection<ParameterExpression>(@params));
+                    }
+                    else if (genericType.Name.StartsWith("Func"))
+                    {
+                        var genericArguments = type.GetGenericArguments();
+                        var returnType = genericArguments.Last();
+                        
+                        var @params = new ParameterExpression[genericArguments.Count() - 1];
+                        for (var i = 0; i < @params.Count(); i++)
+                        {
+                            @params[i] = Expression.Parameter(genericArguments[i], genericArguments[i].Name + i);
+                        }
+                        var @vars = Expression.NewArrayInit(typeof(JsValue), @params.Select(p => Expression.Call(null, typeof(JsValue).GetMethod("FromObject"), Expression.Constant(_engine, typeof(Engine)), p)));
+
+                        var callExpresion = Expression.Convert(
+                                                Expression.Call(
+                                                    Expression.Call(Expression.Constant(function.Target),
+                                                            function.Method,
+                                                            Expression.Constant(JsValue.Undefined, typeof(JsValue)),
+                                                            @vars),
+                                                    typeof(JsValue).GetMethod("ToObject")),
+                                                returnType);
+
+                        return Expression.Lambda(callExpresion, new ReadOnlyCollection<ParameterExpression>(@params));
+                    }
+                }
+                else
+                {
+                    if (type == typeof (Action))
+                    {
+                        return (Action)(() => function(JsValue.Undefined, new JsValue[0]));
+                    }
+                    else if (type.IsSubclassOf(typeof(System.MulticastDelegate)))
+                    {
+                        var method = type.GetMethod("Invoke");
+                        var arguments = method.GetParameters();
+
+                        var @params = new ParameterExpression[arguments.Count()];
+                        for (var i = 0; i < @params.Count(); i++)
+                        {
+                            @params[i] = Expression.Parameter(typeof(object), arguments[i].Name);
+                        }
+                        var @vars = Expression.NewArrayInit(typeof(JsValue), @params.Select(p => Expression.Call(null, typeof(JsValue).GetMethod("FromObject"), Expression.Constant(_engine, typeof(Engine)), p)));
+
+                        var callExpression = Expression.Block(
+                                                Expression.Call(
+                                                    Expression.Call(Expression.Constant(function.Target),
+                                                        function.Method,
+                                                        Expression.Constant(JsValue.Undefined, typeof(JsValue)),
+                                                        @vars),
+                                                    typeof(JsValue).GetMethod("ToObject")),
+                                                Expression.Empty());
+
+                        var dynamicExpression = Expression.Invoke(Expression.Lambda(callExpression, new ReadOnlyCollection<ParameterExpression>(@params)), new ReadOnlyCollection<ParameterExpression>(@params));
+
+                        return Expression.Lambda(type, dynamicExpression, new ReadOnlyCollection<ParameterExpression>(@params));
+                    }
+                }
+
+            }
+
             return System.Convert.ChangeType(value, type, formatProvider);
         }
     }

+ 1 - 1
Jint/Runtime/Interop/DelegateWrapper.cs

@@ -35,7 +35,7 @@ namespace Jint.Runtime.Interop
                 }
                 else
                 {
-                    parameters[i] = Engine.Options.GetTypeConverter().Convert(
+                    parameters[i] = Engine.ClrTypeConverter.Convert(
                         arguments[i].ToObject(),
                         parameterType,
                         CultureInfo.InvariantCulture);

+ 6 - 1
Jint/Runtime/Interop/MethodInfoFunctionInstance.cs

@@ -43,10 +43,15 @@ namespace Jint.Runtime.Interop
                         }
                         else
                         {
-                            parameters[i] = Engine.Options.GetTypeConverter().Convert(
+                            parameters[i] = Engine.ClrTypeConverter.Convert(
                                 arguments[i].ToObject(),
                                 parameterType,
                                 CultureInfo.InvariantCulture);
+
+                            if (typeof(System.Linq.Expressions.LambdaExpression).IsAssignableFrom(parameters[i].GetType()))
+                            {
+                                parameters[i] = (parameters[i] as System.Linq.Expressions.LambdaExpression).Compile();
+                            }
                         }
                     }
 

+ 38 - 0
Jint/Runtime/Interop/ObjectWrapper .cs

@@ -95,6 +95,44 @@ namespace Jint.Runtime.Interop
             {
                 return new IndexDescriptor(Engine, propertyName, Target);
             }
+
+            var interfaces = type.GetInterfaces();
+
+            // try to find a single explicit property implementation
+            var explicitProperties = (from iface in interfaces
+                                      from iprop in iface.GetProperties()
+                                      where propertyName.Equals(iprop.Name)
+                                      select iprop).ToList();
+
+            if (explicitProperties.Count == 1)
+            {
+                var descriptor = new PropertyInfoDescriptor(Engine, explicitProperties[0], Target);
+                Properties.Add(propertyName, descriptor);
+                return descriptor;
+            }
+
+            // try to find explicit method implementations
+            var explicitMethods = (from iface in interfaces
+                                   from imethod in iface.GetMethods()
+                                   where propertyName.Equals(imethod.Name)
+                                   select imethod).ToList();
+
+            if (explicitMethods.Count > 0)
+            {
+                return new PropertyDescriptor(new MethodInfoFunctionInstance(Engine, explicitMethods.ToArray()), false, true, false);
+            }
+
+            // try to find explicit indexer implementations
+            var explicitIndexers =
+                (from iface in interfaces
+                 from iprop in iface.GetProperties()
+                 where iprop.GetIndexParameters().Length != 0
+                 select iprop).ToList();
+
+            if (explicitIndexers.Count == 1)
+            {
+                return new IndexDescriptor(Engine, explicitIndexers[0].DeclaringType, propertyName, Target);
+            }
 
             return PropertyDescriptor.Undefined;
         }

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

@@ -63,7 +63,7 @@ namespace Jint.Runtime.Interop
                         }
                         else
                         {
-                            parameters[i] = Engine.Options.GetTypeConverter().Convert(
+                            parameters[i] = Engine.ClrTypeConverter.Convert(
                                 arguments[i].ToObject(),
                                 parameterType,
                                 CultureInfo.InvariantCulture);

+ 2 - 2
Jint/Runtime/TypeConverter.cs

@@ -388,8 +388,8 @@ namespace Jint.Runtime
                 {
                     for (var i = 0; i < arguments.Length; i++)
                     {
-                        parameters[i] = engine.Options.GetTypeConverter().Convert(
-                            arguments[i].ToObject(),
+                        parameters[i] = engine.ClrTypeConverter.Convert(
+                            objectArguments[i],
                             method.GetParameters()[i].ParameterType,
                             CultureInfo.InvariantCulture);
                     }

+ 5 - 1
README.md

@@ -1,4 +1,4 @@
-[![Build status](https://ci.appveyor.com/api/projects/status/c84b8rdswh2w4744/branch/master)](https://ci.appveyor.com/project/SebastienRos/jint)
+[![Build status](http://teamcity.codebetter.com/app/rest/builds/buildType:(id:Jint_Master)/statusIcon)](http://teamcity.codebetter.com/project.html?projectId=Jint&tab=projectOverview)
 
 # Jint
 
@@ -124,3 +124,7 @@ Generic types are also supported. Here is how to declare, instantiate and use a
   - boolean -> bool
   - Regex -> RegExp
   - Function -> Delegate
+
+Continuous Integration kindly provided by  
+[![](http://www.jetbrains.com/img/banners/Codebetter300x250.png)](http://www.jetbrains.com/teamcity)
+

Algúns arquivos non se mostraron porque demasiados arquivos cambiaron neste cambio