Преглед на файлове

Fixing primitive object function calls

Sebastien Ros преди 12 години
родител
ревизия
6fe243f4eb

+ 1 - 0
Jint.Benchmark/Jint.Benchmark.csproj

@@ -77,6 +77,7 @@
       <Name>Jint</Name>
     </ProjectReference>
   </ItemGroup>
+  <ItemGroup />
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
        Other similar extension points exist, see Microsoft.Common.targets.

+ 75 - 35
Jint.Benchmark/Program.cs

@@ -1,11 +1,14 @@
 using System;
 using System.Diagnostics;
+using System.IO;
+using System.Net;
+using Jint.Runtime;
 
 namespace Jint.Benchmark
 {
     class Program
     {
-        private const string script = @"
+        private const string simple = @"
             var o = {};
             o.Foo = 'bar';
             o.Baz = 42;
@@ -22,61 +25,98 @@ namespace Jint.Benchmark
             fib(3);
         ";
 
+        private static readonly string[] Sunspider = new string[]
+            {
+                "https://gist.github.com/sebastienros/6274930/raw/bf0ab41e788eb9b978a29180f5cb4d614bc00dc5/gistfile1.js"
+            };
+
         static void Main(string[] args)
         {
-            const int iterations = 1000;
+            bool runIronJs = true;
+            bool runJint = true;
+            bool runJurassic = true;
+
+            const int iterations = 100;
             const bool reuseEngine = false;
 
             var watch = new Stopwatch();
 
-            // warming up engines
-            var jurassic = new Jurassic.ScriptEngine();
-            jurassic.Execute(script);
+            foreach (var url in Sunspider)
+            {
+                var script = new WebClient().DownloadString(url);
 
-            var jint = new Jint.Engine();
-            jint.Execute(script);
+                // warming up engines
+                Jurassic.ScriptEngine jurassic;
+                if (runJurassic)
+                {
+                    jurassic = new Jurassic.ScriptEngine();
+                    jurassic.Execute(script);
+                }
 
-            var ironjs = new IronJS.Hosting.CSharp.Context();
-            ironjs.Execute(script);
+                Jint.Engine jint;
+                if (runJint)
+                {
+                    jint = new Jint.Engine();
+                    jint.Execute(script);
+                }
 
-            watch.Restart();
-            for (var i = 0; i < iterations; i++)
-            {
-                if (!reuseEngine)
+                IronJS.Hosting.CSharp.Context ironjs;
+                if (runIronJs)
                 {
                     ironjs = new IronJS.Hosting.CSharp.Context();
+                    ironjs.Execute(script);
                 }
 
-                jurassic.Execute(script);
-            }
-
-            Console.WriteLine("IronJs: {0} iterations in {1} ms", iterations, watch.ElapsedMilliseconds);
-
-            watch.Restart();
-            for (var i = 0; i < iterations; i++)
-            {
-                if (!reuseEngine)
+                if (runIronJs)
                 {
-                    jint = new Jint.Engine();
+                    watch.Restart();
+                    for (var i = 0; i < iterations; i++)
+                    {
+                        if (!reuseEngine)
+                        {
+                            ironjs = new IronJS.Hosting.CSharp.Context();
+                        }
+
+                        ironjs.Execute(script);
+                    }
+
+                    Console.WriteLine("{2} | IronJs: {0} iterations in {1} ms", iterations, watch.ElapsedMilliseconds,
+                                      Path.GetFileName(url));
                 }
 
-                jint.Execute(script);
-            }
+                if (runJint)
+                {
+                watch.Restart();
+                for (var i = 0; i < iterations; i++)
+                {
+                    if (!reuseEngine)
+                    {
+                        jint = new Jint.Engine();
+                    }
 
-            Console.WriteLine("Jint: {0} iterations in {1} ms", iterations, watch.ElapsedMilliseconds);
+                    jint.Execute(script);
+                }
 
-            watch.Restart();
-            for (var i = 0; i < iterations; i++)
-            {
-                if (!reuseEngine)
-                {
-                    jurassic = new Jurassic.ScriptEngine();
+                Console.WriteLine("{2} | Jint: {0} iterations in {1} ms", iterations, watch.ElapsedMilliseconds, Path.GetFileName(url));
                 }
 
-                jurassic.Execute(script);
+                if (runJurassic)
+                {
+                    watch.Restart();
+                    for (var i = 0; i < iterations; i++)
+                    {
+                        if (!reuseEngine)
+                        {
+                            jurassic = new Jurassic.ScriptEngine();
+                        }
+
+                        jurassic.Execute(script);
+                    }
+
+                    Console.WriteLine("{2} | Jurassic: {0} iterations in {1} ms", iterations, watch.ElapsedMilliseconds,
+                                      Path.GetFileName(url));
+                }
             }
-
-            Console.WriteLine("Jurassic: {0} iterations in {1} ms", iterations, watch.ElapsedMilliseconds);
         }
     }
 }

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

@@ -44,8 +44,8 @@ namespace Jint.Tests.Ecma
             {
                 try
                 {
-                    var result = engine.Execute(code + Environment.NewLine + NegativeDriver);
-                    Assert.True(_lastError != null || result.Type == Completion.Throw);
+                    engine.Execute(code + Environment.NewLine + NegativeDriver);
+                    Assert.True(_lastError != null);
                     Assert.False(true);
                 }
                 catch
@@ -56,9 +56,7 @@ namespace Jint.Tests.Ecma
             }
             else
             {
-                Completion result = null;
-                Assert.DoesNotThrow(() => result = engine.Execute(code + Environment.NewLine + Driver));
-                Assert.True((result == null) || (result.Type != Completion.Throw));
+                Assert.DoesNotThrow(() => engine.Execute(code + Environment.NewLine + Driver));
                 Assert.Null(_lastError);
             }
         }

+ 19 - 1
Jint.Tests/Runtime/EngineTests.cs

@@ -379,7 +379,7 @@ namespace Jint.Tests.Runtime
         public void StringFunctionCreatesString()
         {
             RunTest(@"
-                assert(Strint(NaN) === 'NaN');
+                assert(String(NaN) === 'NaN');
             ");
         }
 
@@ -430,6 +430,24 @@ namespace Jint.Tests.Runtime
             ");
         }
 
+        [Fact]
+        public void FunctionsCanBeAssigned()
+        {
+            RunTest(@"
+                var sin = Math.sin;
+                assert(sin(0) == 0);
+            ");
+        }
+
+        [Fact]
+        public void PrimitiveValueFunctions()
+        {
+            RunTest(@"
+                var s = (1).toString();
+                assert(s == '1');
+            ");
+        }
+
         [Theory]
         [InlineData(double.NaN, "parseInt(NaN)")]
         [InlineData(double.NaN, "parseInt(null)")]

+ 3 - 0
Jint.sln

@@ -47,4 +47,7 @@ Global
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
 	EndGlobalSection
+	GlobalSection(Performance) = preSolution
+		HasPerformanceSessions = true
+	EndGlobalSection
 EndGlobal

+ 9 - 3
Jint/Engine.cs

@@ -152,15 +152,21 @@ namespace Jint
             _executionContexts.Pop();
         }
 
-        public Completion Execute(string source)
+        public object Execute(string source)
         {
             var parser = new JavaScriptParser();
             return Execute(parser.Parse(source));
         }
 
-        public Completion Execute(Program program)
+        public object Execute(Program program)
         {
-            return _statements.ExecuteProgram(program);
+            var result = _statements.ExecuteProgram(program);
+            if (result.Type == Completion.Throw)
+            {
+                throw new JavaScriptException(result.Value);
+            }
+
+            return GetValue(result.Value);
         }
 
         public Completion ExecuteStatement(Statement statement)

+ 6 - 1
Jint/Native/Boolean/BooleanConstructor.cs

@@ -22,7 +22,12 @@ namespace Jint.Native.Boolean
 
         public override object Call(object thisObject, object[] arguments)
         {
-            return Construct(arguments);
+            if (arguments.Length == 0)
+            {
+                return false;
+            }
+
+            return TypeConverter.ToBoolean(arguments[0]);
         }
 
         /// <summary>

+ 36 - 36
Jint/Native/Math/MathInstance.cs

@@ -26,24 +26,24 @@ namespace Jint.Native.Math
         public static MathInstance CreateMathObject(Engine engine, ObjectInstance prototype)
         {
             var math = new MathInstance(engine, prototype);
-            math.DefineOwnProperty("abs", new ClrDataDescriptor<MathInstance, double>(engine, Abs), false);
-            math.DefineOwnProperty("acos", new ClrDataDescriptor<MathInstance, double>(engine, Acos), false);
-            math.DefineOwnProperty("asin", new ClrDataDescriptor<MathInstance, double>(engine, Asin), false);
-            math.DefineOwnProperty("atan", new ClrDataDescriptor<MathInstance, double>(engine, Atan), false);
-            math.DefineOwnProperty("atan2", new ClrDataDescriptor<MathInstance, double>(engine, Atan2), false);
-            math.DefineOwnProperty("ceil", new ClrDataDescriptor<MathInstance, double>(engine, Ceil), false);
-            math.DefineOwnProperty("cos", new ClrDataDescriptor<MathInstance, double>(engine, Cos), false);
-            math.DefineOwnProperty("exp", new ClrDataDescriptor<MathInstance, double>(engine, Exp), false);
-            math.DefineOwnProperty("floor", new ClrDataDescriptor<MathInstance, double>(engine, Floor), false);
-            math.DefineOwnProperty("log", new ClrDataDescriptor<MathInstance, double>(engine, Log), false);
-            math.DefineOwnProperty("max", new ClrDataDescriptor<MathInstance, double>(engine, Max), false);
-            math.DefineOwnProperty("min", new ClrDataDescriptor<MathInstance, double>(engine, Min), false);
-            math.DefineOwnProperty("pow", new ClrDataDescriptor<MathInstance, double>(engine, Pow), false);
-            math.DefineOwnProperty("random", new ClrDataDescriptor<MathInstance, double>(engine, Random), false);
-            math.DefineOwnProperty("round", new ClrDataDescriptor<MathInstance, double>(engine, Round), false);
-            math.DefineOwnProperty("sin", new ClrDataDescriptor<MathInstance, double>(engine, Sin), false);
-            math.DefineOwnProperty("sqrt", new ClrDataDescriptor<MathInstance, double>(engine, Sqrt), false);
-            math.DefineOwnProperty("tan", new ClrDataDescriptor<MathInstance, double>(engine, Tan), false);
+            math.DefineOwnProperty("abs", new ClrDataDescriptor<object, double>(engine, Abs), false);
+            math.DefineOwnProperty("acos", new ClrDataDescriptor<object, double>(engine, Acos), false);
+            math.DefineOwnProperty("asin", new ClrDataDescriptor<object, double>(engine, Asin), false);
+            math.DefineOwnProperty("atan", new ClrDataDescriptor<object, double>(engine, Atan), false);
+            math.DefineOwnProperty("atan2", new ClrDataDescriptor<object, double>(engine, Atan2), false);
+            math.DefineOwnProperty("ceil", new ClrDataDescriptor<object, double>(engine, Ceil), false);
+            math.DefineOwnProperty("cos", new ClrDataDescriptor<object, double>(engine, Cos), false);
+            math.DefineOwnProperty("exp", new ClrDataDescriptor<object, double>(engine, Exp), false);
+            math.DefineOwnProperty("floor", new ClrDataDescriptor<object, double>(engine, Floor), false);
+            math.DefineOwnProperty("log", new ClrDataDescriptor<object, double>(engine, Log), false);
+            math.DefineOwnProperty("max", new ClrDataDescriptor<object, double>(engine, Max), false);
+            math.DefineOwnProperty("min", new ClrDataDescriptor<object, double>(engine, Min), false);
+            math.DefineOwnProperty("pow", new ClrDataDescriptor<object, double>(engine, Pow), false);
+            math.DefineOwnProperty("random", new ClrDataDescriptor<object, double>(engine, Random), false);
+            math.DefineOwnProperty("round", new ClrDataDescriptor<object, double>(engine, Round), false);
+            math.DefineOwnProperty("sin", new ClrDataDescriptor<object, double>(engine, Sin), false);
+            math.DefineOwnProperty("sqrt", new ClrDataDescriptor<object, double>(engine, Sqrt), false);
+            math.DefineOwnProperty("tan", new ClrDataDescriptor<object, double>(engine, Tan), false);
 
             math.FastAddProperty("E", System.Math.E, false, false, false);
             math.FastAddProperty("LN10", System.Math.Log(10), false, false, false);
@@ -57,68 +57,68 @@ namespace Jint.Native.Math
             return math;
         }
 
-        private static double Abs(MathInstance thisObject, object[] arguments)
+        private static double Abs(object thisObject, object[] arguments)
         {
             var x = TypeConverter.ToNumber(arguments[0]);
             return System.Math.Abs(x);
         }
 
-        private static double Acos(MathInstance thisObject, object[] arguments)
+        private static double Acos(object thisObject, object[] arguments)
         {
             var x = TypeConverter.ToNumber(arguments[0]);
             return System.Math.Acos(x);
         }
 
-        private static double Asin(MathInstance thisObject, object[] arguments)
+        private static double Asin(object thisObject, object[] arguments)
         {
             var x = TypeConverter.ToNumber(arguments[0]);
             return System.Math.Asin(x);
         }
 
-        private static double Atan(MathInstance thisObject, object[] arguments)
+        private static double Atan(object thisObject, object[] arguments)
         {
             var x = TypeConverter.ToNumber(arguments[0]);
             return System.Math.Atan(x);
         }
 
-        private static double Atan2(MathInstance thisObject, object[] arguments)
+        private static double Atan2(object thisObject, object[] arguments)
         {
             var x = TypeConverter.ToNumber(arguments[0]);
             var y = TypeConverter.ToNumber(arguments[1]);
             return System.Math.Atan2(x, y);
         }
 
-        private static double Ceil(MathInstance thisObject, object[] arguments)
+        private static double Ceil(object thisObject, object[] arguments)
         {
             var x = TypeConverter.ToNumber(arguments[0]);
             return System.Math.Ceiling(x);
         }
 
-        private static double Cos(MathInstance thisObject, object[] arguments)
+        private static double Cos(object thisObject, object[] arguments)
         {
             var x = TypeConverter.ToNumber(arguments[0]);
             return System.Math.Cos(x);
         }
 
-        private static double Exp(MathInstance thisObject, object[] arguments)
+        private static double Exp(object thisObject, object[] arguments)
         {
             var x = TypeConverter.ToNumber(arguments[0]);
             return System.Math.Exp(x);
         }
 
-        private static double Floor(MathInstance thisObject, object[] arguments)
+        private static double Floor(object thisObject, object[] arguments)
         {
             var x = TypeConverter.ToNumber(arguments[0]);
             return System.Math.Floor(x);
         }
 
-        private static double Log(MathInstance thisObject, object[] arguments)
+        private static double Log(object thisObject, object[] arguments)
         {
             var x = TypeConverter.ToNumber(arguments[0]);
             return System.Math.Log(x);
         }
 
-        private static double Max(MathInstance thisObject, object[] arguments)
+        private static double Max(object thisObject, object[] arguments)
         {
             double max = TypeConverter.ToNumber(arguments[0]);
             for (int i = 0; i < arguments.Length; i++)
@@ -128,7 +128,7 @@ namespace Jint.Native.Math
             return max;
         }
 
-        private static double Min(MathInstance thisObject, object[] arguments)
+        private static double Min(object thisObject, object[] arguments)
         {
             double min = TypeConverter.ToNumber(arguments[0]);
             for (int i = 0; i < arguments.Length; i++)
@@ -138,37 +138,37 @@ namespace Jint.Native.Math
             return min;
         }
 
-        private static double Pow(MathInstance thisObject, object[] arguments)
+        private static double Pow(object thisObject, object[] arguments)
         {
             var x = TypeConverter.ToNumber(arguments[0]);
             var y = TypeConverter.ToNumber(arguments[1]);
             return System.Math.Pow(x, y);
         }
 
-        private static double Random(MathInstance thisObject, object[] arguments)
+        private static double Random(object thisObject, object[] arguments)
         {
             return new Random().NextDouble();
         }
 
-        private static double Round(MathInstance thisObject, object[] arguments)
+        private static double Round(object thisObject, object[] arguments)
         {
             var x = TypeConverter.ToNumber(arguments[0]);
             return System.Math.Round(x);
         }
 
-        private static double Sin(MathInstance thisObject, object[] arguments)
+        private static double Sin(object thisObject, object[] arguments)
         {
             var x = TypeConverter.ToNumber(arguments[0]);
             return System.Math.Sin(x);
         }
 
-        private static double Sqrt(MathInstance thisObject, object[] arguments)
+        private static double Sqrt(object thisObject, object[] arguments)
         {
             var x = TypeConverter.ToNumber(arguments[0]);
             return System.Math.Sqrt(x);
         }
 
-        private static double Tan(MathInstance thisObject, object[] arguments)
+        private static double Tan(object thisObject, object[] arguments)
         {
             var x = TypeConverter.ToNumber(arguments[0]);
             return System.Math.Tan(x);

+ 6 - 1
Jint/Native/Number/NumberConstructor.cs

@@ -30,7 +30,12 @@ namespace Jint.Native.Number
 
         public override object Call(object thisObject, object[] arguments)
         {
-            return Construct(arguments);
+            if (arguments.Length == 0)
+            {
+                return 0d;
+            }
+
+            return TypeConverter.ToNumber(arguments[0]);
         }
 
         /// <summary>

+ 9 - 18
Jint/Native/Object/ObjectConstructor.cs

@@ -12,8 +12,8 @@ namespace Jint.Native.Object
         public ObjectConstructor(Engine engine) : base(engine, engine.RootFunction, null, null, false)
         {
             _engine = engine;
-            engine.RootFunction.DefineOwnProperty("hasOwnProperty", new ClrDataDescriptor<ObjectInstance, bool>(engine, HasOwnProperty), false);
-            engine.RootFunction.DefineOwnProperty("toString", new ClrDataDescriptor<ObjectInstance, string>(engine, ToString), false);
+            engine.RootFunction.DefineOwnProperty("hasOwnProperty", new ClrDataDescriptor<object, bool>(engine, HasOwnProperty), false);
+            engine.RootFunction.DefineOwnProperty("toString", new ClrDataDescriptor<object, string>(engine, ToString), false);
         }
 
         public override object Call(object thisObject, object[] arguments)
@@ -31,27 +31,18 @@ namespace Jint.Native.Object
             return instance;
         }
 
-        private static bool HasOwnProperty(ObjectInstance thisObject, object[] arguments)
+        private bool HasOwnProperty(object thisObject, object[] arguments)
         {
-            var propertyName = TypeConverter.ToString(arguments[0]);
-            var desc = thisObject.GetOwnProperty(propertyName);
+            var p = TypeConverter.ToString(arguments[0]);
+            var o = TypeConverter.ToObject(_engine, thisObject);
+            var desc = o.GetOwnProperty(p);
             return desc != PropertyDescriptor.Undefined;
         }
 
-        private static string ToString(ObjectInstance thisObject, object[] arguments)
+        private static string ToString(object thisObject, object[] arguments)
         {
-            if (thisObject == null || thisObject == Undefined.Instance)
-            {
-                return "[object Undefined]";
-            }
-
-            if (thisObject == Null.Instance)
-            {
-                return "[object Null]";
-            }
-
-            return string.Format("[object {0}]", thisObject.Class);
-        
+            return TypeConverter.ToString(thisObject);
+
         }
 
     }

+ 8 - 3
Jint/Native/String/StringConstructor.cs

@@ -15,14 +15,19 @@ namespace Jint.Native.String
             _engine = engine;
 
             // the constructor is the function constructor of an object
-            this.Prototype.DefineOwnProperty("constructor", new DataDescriptor(this) { Writable = true, Enumerable = false, Configurable = false }, false);
-            this.Prototype.DefineOwnProperty("prototype", new DataDescriptor(Prototype) { Writable = true, Enumerable = false, Configurable = false }, false);
+            Prototype.DefineOwnProperty("constructor", new DataDescriptor(this) { Writable = true, Enumerable = false, Configurable = false }, false);
+            Prototype.DefineOwnProperty("prototype", new DataDescriptor(Prototype) { Writable = true, Enumerable = false, Configurable = false }, false);
 
         }
 
         public override object Call(object thisObject, object[] arguments)
         {
-            return Construct(arguments);
+            if (arguments.Length == 0)
+            {
+                return "";
+            }
+
+            return TypeConverter.ToString(arguments[0]);
         }
 
         /// <summary>

+ 7 - 4
Jint/Runtime/References/Reference.cs

@@ -1,4 +1,5 @@
-using Jint.Native;
+using System;
+using Jint.Native;
 using Jint.Native.Boolean;
 using Jint.Native.Number;
 using Jint.Native.Object;
@@ -45,9 +46,11 @@ namespace Jint.Runtime.References
 
         public bool HasPrimitiveBase()
         {
-            return (_baseValue is BooleanInstance)
-                || (_baseValue is StringInstance)
-                || (_baseValue is NumberInstance)
+            var type = TypeConverter.GetType(_baseValue);
+
+            return (type == TypeCode.Boolean)
+                || (type == TypeCode.String)
+                || (type == TypeCode.Double)
                 ;
         }