Browse Source

Fetch from upstream, resolve conflicts

Fetch from upstream, resolve conflicts
h15ter 11 năm trước cách đây
mục cha
commit
f27fc879ce
33 tập tin đã thay đổi với 1793 bổ sung166 xóa
  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. 185 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. 17 8
      Jint/Runtime/Descriptors/Specialized/IndexDescriptor.cs
  26. 1 1
      Jint/Runtime/Descriptors/Specialized/PropertyInfoDescriptor.cs
  27. 109 10
      Jint/Runtime/Interop/DefaultTypeConverter.cs
  28. 1 1
      Jint/Runtime/Interop/DelegateWrapper.cs
  29. 10 5
      Jint/Runtime/Interop/MethodInfoFunctionInstance.cs
  30. 38 0
      Jint/Runtime/Interop/ObjectWrapper .cs
  31. 1 1
      Jint/Runtime/Interop/TypeReference.cs
  32. 3 3
      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.";

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 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; }
+    }
+}

+ 185 - 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()
         {
@@ -605,6 +605,14 @@ namespace Jint.Tests.Runtime
             );
         }
 
+        [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 ShouldConvertDoubleToStringWithoutLosingPrecision()
         {
@@ -650,7 +658,7 @@ namespace Jint.Tests.Runtime
                 assert(regex.test('a/b') === true);
                 assert(regex.test('a\\/b') === false);
             ");
-      }
+        }
 
         [Fact]
         public void ShouldComputeFractionInBase()
@@ -697,6 +705,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()
         {
@@ -704,7 +748,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);
 
@@ -738,5 +782,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>(); 
@@ -129,6 +132,8 @@ namespace Jint
                     return new NamespaceReference(this, TypeConverter.ToString(arguments.At(0)));
                 }), false, false, false);
             }
+
+            ClrTypeConverter = new DefaultTypeConverter(this);
         }
 
         public LexicalEnvironment GlobalEnvironment;
@@ -216,6 +221,12 @@ namespace Jint
             _statementsCount = 0;
         }
 
+        public void ResetTimeoutTicks()
+        {
+            var timeoutIntervalTicks = Options.GetTimeoutInterval().Ticks;
+            _timeoutTicks = timeoutIntervalTicks > 0 ? DateTime.UtcNow.Ticks + timeoutIntervalTicks : 0;
+        }
+
         public Engine Execute(string source)
         {
             var parser = new JavaScriptParser();
@@ -231,6 +242,7 @@ namespace Jint
         public Engine Execute(Program program)
         {
             ResetStatementsCount();
+            ResetTimeoutTicks();
             ResetLastStatement();
 
             using (new StrictModeScope(Options.IsStrict() || program.Strict))
@@ -270,6 +282,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;
@@ -13,10 +14,11 @@ 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 TimeSpan _timeoutInterval;
         private CultureInfo _culture = CultureInfo.CurrentCulture;
+        private TimeZoneInfo _localTimeZone = TimeZoneInfo.Local;
         private List<Assembly> _lookupAssemblies = new List<Assembly>(); 
 
         /// <summary>
@@ -51,15 +53,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>
@@ -86,12 +79,24 @@ namespace Jint
             return this;
         }
 
+        public Options TimeoutInterval(TimeSpan timeoutInterval)
+        {
+            _timeoutInterval = timeoutInterval;
+            return this;
+        }
+
         public Options Culture(CultureInfo cultureInfo)
         {
             _culture = cultureInfo;
             return this;
         }
 
+        public Options LocalTimeZone(TimeZoneInfo timeZoneInfo)
+        {
+            _localTimeZone = timeZoneInfo;
+            return this;
+        }
+
         internal bool GetDiscardGlobal()
         {
             return _discardGlobal;
@@ -117,11 +122,6 @@ namespace Jint
             return _lookupAssemblies;
         }
 
-        internal ITypeConverter GetTypeConverter()
-        {
-            return _typeConverter;
-        }
-
         internal IEnumerable<IObjectConverter> GetObjectConverters()
         {
             return _objectConverters;
@@ -132,9 +132,19 @@ namespace Jint
             return _maxStatements;
         }
 
+        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);
                     }
                 }
                 

+ 17 - 8
Jint/Runtime/Descriptors/Specialized/IndexDescriptor.cs

@@ -13,19 +13,16 @@ namespace Jint.Runtime.Descriptors.Specialized
         private readonly object _item;
         private readonly PropertyInfo _indexer;
 
-        public IndexDescriptor(Engine engine, string key, object item)
+        public IndexDescriptor(Engine engine, Type targetType, string key, object item)
         {
             _engine = engine;
             _item = item;
 
             // get all instance indexers with exactly 1 argument
-            var indexers = item
-                .GetType()
+            var indexers = targetType
                 .GetProperties(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public)
                 .Where(x => x.GetIndexParameters().Length == 1);
 
-            var converter = _engine.Options.GetTypeConverter();
-
             // try to find first indexer having either public getter or setter with matching argument type
             foreach (var indexer in indexers)
             {
@@ -33,7 +30,7 @@ namespace Jint.Runtime.Descriptors.Specialized
                 {
                     var paramType = indexer.GetIndexParameters()[0].ParameterType;
 
-                    if (converter.TryConvert(key, paramType, CultureInfo.InvariantCulture, out _key))
+                    if (_engine.ClrTypeConverter.TryConvert(key, paramType, CultureInfo.InvariantCulture, out _key))
                     {
                         _indexer = indexer;
                         break;
@@ -43,19 +40,29 @@ namespace Jint.Runtime.Descriptors.Specialized
             }
 
             // throw if no indexer found
-            if(_indexer == null)
+            if (_indexer == null)
+            {
                 throw new InvalidOperationException("No matching indexer found.");
+            }
 
             Writable = true;
         }
 
+
+        public IndexDescriptor(Engine engine, string key, object item)
+            : this(engine, item.GetType(), key, item)
+        {
+        }
+
         public override JsValue? Value
         {
             get
             {
                 var getter = _indexer.GetGetMethod();
-                if(getter == null)
+                if (getter == null)
+                {
                     throw new InvalidOperationException("Indexer has no public getter.");
+                }
 
                 object[] parameters = { _key };
                 return JsValue.FromObject(_engine, getter.Invoke(_item, parameters));
@@ -65,7 +72,9 @@ namespace Jint.Runtime.Descriptors.Specialized
             {
                 var setter = _indexer.GetSetMethod();
                 if (setter == null)
+                {
                     throw new InvalidOperationException("Indexer has no public setter.");
+                }
 
                 object[] parameters = { _key, value.HasValue ? value.Value.ToObject() : null };
                 setter.Invoke(_item, parameters);

+ 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);
                     }
                 }
                 

+ 109 - 10
Jint/Runtime/Interop/DefaultTypeConverter.cs

@@ -1,15 +1,24 @@
 using System;
-using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Linq.Expressions;
 using Jint.Native;
+using System.Collections.Generic;
 
 namespace Jint.Runtime.Interop
 {
     public class DefaultTypeConverter : ITypeConverter
     {
-        private static readonly Dictionary<string, bool> KnownConversions = new Dictionary<string, bool>();
-        private static readonly object LockObject = new object();
+        private readonly Engine _engine;
+        private static readonly Dictionary<string, bool> _knownConversions = new Dictionary<string, bool>();
+        private static readonly object _lockObject = new object();
+
+        public DefaultTypeConverter(Engine engine)
+        {
+            _engine = engine;
+        }
 
-        public object Convert(object value, Type type, IFormatProvider formatProvider)
+        public virtual object Convert(object value, Type type, IFormatProvider formatProvider)
         {
             // don't try to convert if value is derived from type
             if (type.IsInstanceOfType(value))
@@ -28,30 +37,120 @@ 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);
         }
 
-        public bool TryConvert(object value, Type type, IFormatProvider formatProvider, out object converted)
+        public virtual bool TryConvert(object value, Type type, IFormatProvider formatProvider, out object converted)
         {
             bool canConvert;
             var key = value == null ? String.Format("Null->{0}", type) : String.Format("{0}->{1}", value.GetType(), type);
 
-            if (!KnownConversions.TryGetValue(key, out canConvert))
+            if (!_knownConversions.TryGetValue(key, out canConvert))
             {
-                lock (LockObject)
+                lock (_lockObject)
                 {
-                    if (!KnownConversions.TryGetValue(key, out canConvert))
+                    if (!_knownConversions.TryGetValue(key, out canConvert))
                     {
                         try
                         {
                             converted = Convert(value, type, formatProvider);
-                            KnownConversions.Add(key, true);
+                            _knownConversions.Add(key, true);
                             return true;
                         }
                         catch
                         {
                             converted = null;
-                            KnownConversions.Add(key, false);
+                            _knownConversions.Add(key, false);
                             return false;
                         }
                     }

+ 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);

+ 10 - 5
Jint/Runtime/Interop/MethodInfoFunctionInstance.cs

@@ -25,12 +25,13 @@ namespace Jint.Runtime.Interop
         public JsValue Invoke(MethodInfo[] methodInfos, JsValue thisObject, JsValue[] arguments)
         {
             var methods = TypeConverter.FindBestMatch(Engine, methodInfos, arguments).ToList();
-            var converter = Engine.Options.GetTypeConverter();
+            var converter = Engine.ClrTypeConverter;
 
             foreach (var method in methods)
             {
                 var parameters = new object[arguments.Length];
                 var argumentsMatch = true;
+
                 for (var i = 0; i < arguments.Length; i++)
                 {
                     var parameterType = method.GetParameters()[i].ParameterType;
@@ -46,17 +47,21 @@ namespace Jint.Runtime.Interop
                             argumentsMatch = false;
                             break;
                         }
+
+                        if (typeof(System.Linq.Expressions.LambdaExpression).IsAssignableFrom(parameters[i].GetType()))
+                        {
+                            parameters[i] = (parameters[i] as System.Linq.Expressions.LambdaExpression).Compile();
+                        }
                     }
                 }
 
                 if (!argumentsMatch)
+                { 
                     continue;
-
-                var result = JsValue.FromObject(Engine, method.Invoke(thisObject.ToObject(), parameters.ToArray()));
+                }
 
                 // todo: cache method info
-
-                return result;
+                return JsValue.FromObject(Engine, method.Invoke(thisObject.ToObject(), parameters.ToArray()));
             }
 
             throw new JavaScriptException(Engine.TypeError, "No public methods with the specified arguments were found.");

+ 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);

+ 3 - 3
Jint/Runtime/TypeConverter.cs

@@ -350,8 +350,7 @@ namespace Jint.Runtime
         {
             methods = methods
                 .Where(m => m.GetParameters().Count() == arguments.Length)
-                .ToArray()
-                ;
+                .ToArray();
 
             if (methods.Length == 1 && !methods[0].GetParameters().Any())
             {
@@ -392,8 +391,9 @@ namespace Jint.Runtime
             }
 
             foreach (var method in methods)
+            {
                 yield return method;
+            }
         }
-
     }
 }

+ 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)
+

Một số tệp đã không được hiển thị bởi vì quá nhiều tập tin thay đổi trong này khác