Bladeren bron

Implementing error objects and exceptions management

Sebastien Ros 12 jaren geleden
bovenliggende
commit
f5319612ca
35 gewijzigde bestanden met toevoegingen van 298 en 143 verwijderingen
  1. 25 0
      Jint.Tests/Runtime/EngineTests.cs
  2. 34 10
      Jint/Engine.cs
  3. 3 4
      Jint/Jint.csproj
  4. 7 7
      Jint/Native/Array/ArrayConstructor.cs
  5. 1 1
      Jint/Native/Array/ArrayInstance.cs
  6. 4 4
      Jint/Native/Boolean/BooleanConstructor.cs
  7. 2 2
      Jint/Native/Boolean/BooleanInstance.cs
  8. 4 4
      Jint/Native/Date/DateConstructor.cs
  9. 2 2
      Jint/Native/Date/DateInstance.cs
  10. 54 0
      Jint/Native/Error/ErrorConstructor.cs
  11. 63 0
      Jint/Native/Error/ErrorInstance.cs
  12. 0 8
      Jint/Native/Errors/Error.cs
  13. 0 8
      Jint/Native/Errors/ReferenceError.cs
  14. 0 8
      Jint/Native/Errors/SyntaxError.cs
  15. 0 8
      Jint/Native/Errors/TypeError.cs
  16. 1 1
      Jint/Native/Function/ArgumentsObject.cs
  17. 1 5
      Jint/Native/Function/EvalFunctionInstance.cs
  18. 1 1
      Jint/Native/Function/FunctionConstructor.cs
  19. 3 4
      Jint/Native/Function/FunctionInstance.cs
  20. 7 3
      Jint/Native/Function/ScriptFunctionInstance.cs
  21. 6 3
      Jint/Native/Global/GlobalObject.cs
  22. 7 4
      Jint/Native/Math/MathInstance.cs
  23. 2 2
      Jint/Native/Number/NumberConstructor.cs
  24. 2 2
      Jint/Native/Number/NumberInstance.cs
  25. 1 1
      Jint/Native/Object/ObjectConstructor.cs
  26. 15 13
      Jint/Native/Object/ObjectInstance.cs
  27. 2 2
      Jint/Native/String/StringConstructor.cs
  28. 5 2
      Jint/Native/String/StringInstance.cs
  29. 3 3
      Jint/Runtime/Environments/LexicalEnvironment.cs
  30. 4 4
      Jint/Runtime/Environments/ObjectEnvironmentRecord.cs
  31. 14 15
      Jint/Runtime/ExpressionIntepreter.cs
  32. 16 0
      Jint/Runtime/JavaScriptException.cs
  33. 0 1
      Jint/Runtime/References/Reference.cs
  34. 6 7
      Jint/Runtime/StatementInterpreter.cs
  35. 3 4
      Jint/Runtime/TypeConverter.cs

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

@@ -396,6 +396,31 @@ namespace Jint.Tests.Runtime
             ");
         }
 
+        [Fact]
+        public void TryCatchBlockStatement()
+        {
+            RunTest(@"
+                var x, y, z;
+                try {
+                    x = 1;
+                    throw new TypeError();
+                    x = 2;
+                }
+                catch(e) {
+                    assert(x == 1);
+                    assert(e instanceof TypeError);
+                    y = 1;
+                }
+                finally {
+                    assert(x == 1);
+                    z = 1;
+                }
+                
+                assert(x == 1);
+                assert(y == 1);
+                assert(z == 1);
+            ");
+        }
         /*
                         [Fact]
                         public void ()

+ 34 - 10
Jint/Engine.cs

@@ -5,7 +5,7 @@ using Jint.Native;
 using Jint.Native.Array;
 using Jint.Native.Boolean;
 using Jint.Native.Date;
-using Jint.Native.Errors;
+using Jint.Native.Error;
 using Jint.Native.Function;
 using Jint.Native.Global;
 using Jint.Native.Math;
@@ -36,7 +36,7 @@ namespace Jint
         {
             _executionContexts = new Stack<ExecutionContext>();
 
-            RootObject = new ObjectInstance(null);
+            RootObject = new ObjectInstance(this, null);
             RootFunction = new FunctionShim(this, RootObject, null, null);
 
             Object = new ObjectConstructor(this);
@@ -49,6 +49,14 @@ namespace Jint
             Date = new DateConstructor(this);
             Math = MathInstance.CreateMathObject(this, RootObject);
 
+            Error = new ErrorConstructor(this, "Error");
+            EvalError = new ErrorConstructor(this, "EvalError");
+            RangeError = new ErrorConstructor(this, "RangeError");
+            ReferenceError = new ErrorConstructor(this, "ReferenceError");
+            SyntaxError = new ErrorConstructor(this, "SyntaxError");
+            TypeError = new ErrorConstructor(this, "TypeError");
+            URIError = new ErrorConstructor(this, "URIError");
+
             Global.FastAddProperty("Object", Object, true, false, true);
             Global.FastAddProperty("Function", Function, true, false, true);
             Global.FastAddProperty("Array", Array, true, false, true);
@@ -58,8 +66,16 @@ namespace Jint
             Global.FastAddProperty("Date", Date, true, false, true);
             Global.FastAddProperty("Math", Math, true, false, true);
 
+            Global.FastAddProperty("Error", Error, true, false, true);
+            Global.FastAddProperty("EvalError", EvalError, true, false, true);
+            Global.FastAddProperty("RangeError", RangeError, true, false, true);
+            Global.FastAddProperty("ReferenceError", ReferenceError, true, false, true);
+            Global.FastAddProperty("SyntaxError", SyntaxError, true, false, true);
+            Global.FastAddProperty("TypeError", TypeError, true, false, true);
+            Global.FastAddProperty("URIError", URIError, true, false, true);
+
             // create the global environment http://www.ecma-international.org/ecma-262/5.1/#sec-10.2.3
-            GlobalEnvironment = LexicalEnvironment.NewObjectEnvironment(Global, null, true);
+            GlobalEnvironment = LexicalEnvironment.NewObjectEnvironment(this, Global, null, true);
             
             // create the global execution context http://www.ecma-international.org/ecma-262/5.1/#sec-10.4.1.1
             EnterExecutionContext(GlobalEnvironment, GlobalEnvironment, Global);
@@ -79,7 +95,7 @@ namespace Jint
                 }
             }
 
-            Eval = new EvalFunctionInstance(this, new ObjectInstance(null), new Identifier[0], LexicalEnvironment.NewDeclarativeEnvironment(ExecutionContext.LexicalEnvironment), Options.IsStrict());
+            Eval = new EvalFunctionInstance(this, new ObjectInstance(this, null), new Identifier[0], LexicalEnvironment.NewDeclarativeEnvironment(this, ExecutionContext.LexicalEnvironment), Options.IsStrict());
             Global.FastAddProperty("eval", Eval, true, false, true);
 
             _statements = new StatementInterpreter(this);
@@ -102,6 +118,14 @@ namespace Jint
         public MathInstance Math { get; private set; }
         public EvalFunctionInstance Eval { get; private set; }
 
+        public ErrorConstructor Error { get; private set; }
+        public ErrorConstructor EvalError { get; private set; }
+        public ErrorConstructor SyntaxError { get; private set; }
+        public ErrorConstructor TypeError { get; private set; }
+        public ErrorConstructor RangeError { get; private set; }
+        public ErrorConstructor ReferenceError { get; private set; }
+        public ErrorConstructor URIError { get; private set; }
+
         public ExecutionContext ExecutionContext { get { return _executionContexts.Peek(); } }
 
         public Options Options { get; private set; }
@@ -284,7 +308,7 @@ namespace Jint
 
             if (reference.IsUnresolvableReference())
             {
-                throw new ReferenceError();
+                throw new JavaScriptException(ReferenceError);
             }
 
             var baseValue = reference.GetBase();
@@ -311,7 +335,7 @@ namespace Jint
             {
                 if (reference.IsStrict())
                 {
-                    throw new ReferenceError();
+                    throw new JavaScriptException(ReferenceError);
                 }
 
                 Global.Put(reference.GetReferencedName(), value, false);
@@ -351,7 +375,7 @@ namespace Jint
             {
                 if (throwOnError)
                 {
-                    throw new TypeError();
+                    throw new JavaScriptException(TypeError);
                 }
 
                 return;
@@ -363,7 +387,7 @@ namespace Jint
             {
                 if (throwOnError)
                 {
-                    throw new TypeError();
+                    throw new JavaScriptException(TypeError);
                 }
 
                 return;
@@ -380,7 +404,7 @@ namespace Jint
             {
                 if (throwOnError)
                 {
-                    throw new TypeError();
+                    throw new JavaScriptException(TypeError);
                 }
             }
         }
@@ -431,7 +455,7 @@ namespace Jint
                         {
                             if (existingProp.IsAccessorDescriptor() || (!existingProp.Enumerable))
                             {
-                                throw new TypeError();
+                                throw new JavaScriptException(TypeError);
                             }
                         }
                     }

+ 3 - 4
Jint/Jint.csproj

@@ -43,10 +43,8 @@
     <Compile Include="Native\Boolean\BooleanInstance.cs" />
     <Compile Include="Native\Date\DateConstructor.cs" />
     <Compile Include="Native\Date\DateInstance.cs" />
-    <Compile Include="Native\Errors\Error.cs" />
-    <Compile Include="Native\Errors\SyntaxError.cs" />
-    <Compile Include="Native\Errors\ReferenceError.cs" />
-    <Compile Include="Native\Errors\TypeError.cs" />
+    <Compile Include="Native\Error\ErrorConstructor.cs" />
+    <Compile Include="Native\Error\ErrorInstance.cs" />
     <Compile Include="Native\Function\ArgumentsObject.cs" />
     <Compile Include="Native\Function\EvalFunctionInstance.cs" />
     <Compile Include="Native\Function\FunctionConstructor.cs" />
@@ -142,6 +140,7 @@
     <Compile Include="Runtime\Interop\SetterFunctionInstance.cs" />
     <Compile Include="Runtime\Interop\GetterFunctionInstance.cs" />
     <Compile Include="Runtime\Interop\DelegateWrapper.cs" />
+    <Compile Include="Runtime\JavaScriptException.cs" />
     <Compile Include="Runtime\References\Reference.cs" />
     <Compile Include="Runtime\StatementInterpreter.cs" />
     <Compile Include="Runtime\TypeConverter.cs" />

+ 7 - 7
Jint/Native/Array/ArrayConstructor.cs

@@ -9,20 +9,20 @@ namespace Jint.Native.Array
     {
         private readonly Engine _engine;
 
-        public ArrayConstructor(Engine engine) :  base(engine, new ObjectInstance(engine.RootFunction), null, null, false)
+        public ArrayConstructor(Engine engine) :  base(engine, new ObjectInstance(engine, engine.RootFunction), null, null, false)
         {
             _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(this.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);
                                   
             // Array prototype properties
-            this.Prototype.DefineOwnProperty("length", new ClrAccessDescriptor<ArrayInstance>(_engine, x => x.Length), false);
+            Prototype.DefineOwnProperty("length", new ClrAccessDescriptor<ArrayInstance>(_engine, x => x.Length), false);
 
             // Array prototype functions
-            this.Prototype.DefineOwnProperty("push", new ClrDataDescriptor<ArrayInstance, object>(engine, Push), false);
-            this.Prototype.DefineOwnProperty("pop", new ClrDataDescriptor<ArrayInstance, object>(engine, Pop), false);
+            Prototype.DefineOwnProperty("push", new ClrDataDescriptor<ArrayInstance, object>(engine, Push), false);
+            Prototype.DefineOwnProperty("pop", new ClrDataDescriptor<ArrayInstance, object>(engine, Pop), false);
         }
 
         public override object Call(object thisObject, object[] arguments)
@@ -32,7 +32,7 @@ namespace Jint.Native.Array
 
         public ObjectInstance Construct(object[] arguments)
         {
-            var instance = new ArrayInstance(Prototype);
+            var instance = new ArrayInstance(_engine, Prototype);
 
             foreach (var arg in arguments)
             {

+ 1 - 1
Jint/Native/Array/ArrayInstance.cs

@@ -7,7 +7,7 @@ namespace Jint.Native.Array
     {
         private readonly Stack<object> _array = new Stack<object>();
  
-        public ArrayInstance(ObjectInstance prototype) : base(prototype)
+        public ArrayInstance(Engine engine, ObjectInstance prototype) : base(engine, prototype)
         {
         }
 

+ 4 - 4
Jint/Native/Boolean/BooleanConstructor.cs

@@ -10,13 +10,13 @@ namespace Jint.Native.Boolean
         private readonly Engine _engine;
 
         public BooleanConstructor(Engine engine)
-            : base(engine, new ObjectInstance(engine.Object), null, null, false)
+            : base(engine, new ObjectInstance(engine, engine.Object), null, null, false)
         {
             _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);
 
         }
 
@@ -37,7 +37,7 @@ namespace Jint.Native.Boolean
 
         public BooleanInstance Construct(bool value)
         {
-            var instance = new BooleanInstance(Prototype);
+            var instance = new BooleanInstance(_engine, Prototype);
             instance.PrimitiveValue = value;
             return instance;
         }

+ 2 - 2
Jint/Native/Boolean/BooleanInstance.cs

@@ -5,8 +5,8 @@ namespace Jint.Native.Boolean
 {
     public sealed class BooleanInstance : ObjectInstance, IPrimitiveType
     {
-        public BooleanInstance(ObjectInstance prototype)
-            : base(prototype)
+        public BooleanInstance(Engine engine, ObjectInstance prototype)
+            : base(engine, prototype)
         {
         }
 

+ 4 - 4
Jint/Native/Date/DateConstructor.cs

@@ -11,13 +11,13 @@ namespace Jint.Native.Date
         private readonly Engine _engine;
 
         public DateConstructor(Engine engine)
-            : base(engine, new ObjectInstance(engine.Object), null, null, false)
+            : base(engine, new ObjectInstance(engine, engine.Object), null, null, false)
         {
             _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);
 
         }
 
@@ -72,7 +72,7 @@ namespace Jint.Native.Date
 
         public DateInstance Construct(DateTime value)
         {
-            var instance = new DateInstance(Prototype);
+            var instance = new DateInstance(_engine, Prototype);
             instance.PrimitiveValue = value;
             return instance;
         }

+ 2 - 2
Jint/Native/Date/DateInstance.cs

@@ -5,8 +5,8 @@ namespace Jint.Native.Date
 {
     public sealed class DateInstance : ObjectInstance, IPrimitiveType
     {
-        public DateInstance(ObjectInstance prototype)
-            : base(prototype)
+        public DateInstance(Engine engine, ObjectInstance prototype)
+            : base(engine, prototype)
         {
         }
 

+ 54 - 0
Jint/Native/Error/ErrorConstructor.cs

@@ -0,0 +1,54 @@
+using Jint.Native.Function;
+using Jint.Native.Object;
+using Jint.Runtime;
+using Jint.Runtime.Descriptors;
+using Jint.Runtime.Descriptors.Specialized;
+
+namespace Jint.Native.Error
+{
+    public sealed class ErrorConstructor : FunctionInstance, IConstructor
+    {
+        private readonly Engine _engine;
+
+        public ErrorConstructor(Engine engine, string name)
+            : base(engine, new ErrorInstance(engine, null, name), null, null, false)
+        {
+            _engine = engine;
+
+            // the constructor is the function constructor of an object
+            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);
+                                  
+            // Error prototype properties
+            Prototype.DefineOwnProperty("message", new ClrAccessDescriptor<ErrorInstance>(_engine, x => x.Message), false);
+            Prototype.DefineOwnProperty("name", new ClrAccessDescriptor<ErrorInstance>(_engine, x => x.Name), false);
+
+            // Error prototype functions
+            Prototype.DefineOwnProperty("toString", new ClrDataDescriptor<ErrorInstance, object>(engine, ToErrorString), false);
+
+        }
+
+        public override object Call(object thisObject, object[] arguments)
+        {
+            return Construct(arguments);
+        }
+
+        public ObjectInstance Construct(object[] arguments)
+        {
+            var instance = new ErrorInstance(_engine, Prototype, null) {Extensible = true};
+
+            if (arguments.Length > 0 && arguments[0] != Undefined.Instance)
+            {
+                instance.Message = TypeConverter.ToString(arguments[0]);
+            }
+
+            return instance;
+        }
+
+        private static object ToErrorString(ErrorInstance thisObject, object[] arguments)
+        {
+            return thisObject.ToErrorString();
+        }
+
+    }
+}

+ 63 - 0
Jint/Native/Error/ErrorInstance.cs

@@ -0,0 +1,63 @@
+using Jint.Native.Object;
+using Jint.Runtime;
+
+namespace Jint.Native.Error
+{
+    public sealed class ErrorInstance : ObjectInstance
+    {
+        public ErrorInstance(Engine engine, ObjectInstance prototype, string name)
+            : base(engine, prototype)
+        {
+            Name = name;
+            Message = "";
+        }
+
+        public override string Class
+        {
+            get
+            {
+                return "Error";
+            }
+        }
+
+        public object Message { get; set; }
+
+        public object Name { get; set; }
+
+        public string ToErrorString()
+        {
+            string name;
+            string msg;
+
+            if (Name == Undefined.Instance)
+            {
+                name = "Error";
+            }
+            else
+            {
+                name = TypeConverter.ToString(Name);
+            }
+
+            if (Message == Undefined.Instance)
+            {
+                msg = "";
+            }
+            else
+            {
+                msg = TypeConverter.ToString(Message);
+            }
+
+            if (name == "")
+            {
+                return msg;
+            }
+
+            if (msg == "")
+            {
+                return name;
+            }
+
+            return name + ":" + msg;
+        }
+    }
+}

+ 0 - 8
Jint/Native/Errors/Error.cs

@@ -1,8 +0,0 @@
-using System;
-
-namespace Jint.Native.Errors
-{
-    public class Error : Exception
-    {
-    }
-}

+ 0 - 8
Jint/Native/Errors/ReferenceError.cs

@@ -1,8 +0,0 @@
-using System;
-
-namespace Jint.Native.Errors
-{
-    public class ReferenceError : Error
-    {
-    }
-}

+ 0 - 8
Jint/Native/Errors/SyntaxError.cs

@@ -1,8 +0,0 @@
-using System;
-
-namespace Jint.Native.Errors
-{
-    public class SyntaxError : Error
-    {
-    }
-}

+ 0 - 8
Jint/Native/Errors/TypeError.cs

@@ -1,8 +0,0 @@
-using System;
-
-namespace Jint.Native.Errors
-{
-    public class TypeError : Error
-    {
-    }
-}

+ 1 - 1
Jint/Native/Function/ArgumentsObject.cs

@@ -7,7 +7,7 @@ namespace Jint.Native.Function
     /// </summary>
     public class ArgumentsInstance : ObjectInstance
     {
-        public ArgumentsInstance(ObjectInstance prototype) : base(prototype)
+        public ArgumentsInstance(Engine engine, ObjectInstance prototype) : base(engine, prototype)
         {
             // todo: complete implementation
         }

+ 1 - 5
Jint/Native/Function/EvalFunctionInstance.cs

@@ -1,8 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using Jint.Native.Object;
+using Jint.Native.Object;
 using Jint.Parser;
 using Jint.Parser.Ast;
 using Jint.Runtime;

+ 1 - 1
Jint/Native/Function/FunctionConstructor.cs

@@ -49,7 +49,7 @@ namespace Jint.Native.Function
                 functionDeclaration,
                 _engine.Function.Prototype /* instancePrototype */,
                 _engine.Object.Construct(Arguments.Empty) /* functionPrototype */,
-                LexicalEnvironment.NewDeclarativeEnvironment(_engine.ExecutionContext.LexicalEnvironment),
+                LexicalEnvironment.NewDeclarativeEnvironment(_engine, _engine.ExecutionContext.LexicalEnvironment),
                 functionDeclaration.Strict
                 ) { Extensible = true };
 

+ 3 - 4
Jint/Native/Function/FunctionInstance.cs

@@ -1,5 +1,4 @@
-using Jint.Native.Errors;
-using Jint.Native.Object;
+using Jint.Native.Object;
 using Jint.Parser.Ast;
 using Jint.Runtime;
 using Jint.Runtime.Environments;
@@ -10,7 +9,7 @@ namespace Jint.Native.Function
     {
         private readonly Engine _engine;
 
-        protected FunctionInstance(Engine engine, ObjectInstance prototype, Identifier[] parameters, LexicalEnvironment scope, bool strict) : base(prototype)
+        protected FunctionInstance(Engine engine, ObjectInstance prototype, Identifier[] parameters, LexicalEnvironment scope, bool strict) : base(engine, prototype)
         {
             _engine = engine;
             FormalParameters = parameters;
@@ -85,7 +84,7 @@ namespace Jint.Native.Function
             var f = v as FunctionInstance;
             if (propertyName == "caller" && f != null && f.Strict)
             {
-                throw new TypeError();
+                throw new JavaScriptException(_engine.TypeError);
             }
 
             return v;

+ 7 - 3
Jint/Native/Function/ScriptFunctionInstance.cs

@@ -1,6 +1,5 @@
 using System;
 using System.Linq;
-using Jint.Native.Errors;
 using Jint.Native.Object;
 using Jint.Parser;
 using Jint.Runtime;
@@ -61,7 +60,7 @@ namespace Jint.Native.Function
                 thisBinding = thisArg;
             }
 
-            var localEnv = LexicalEnvironment.NewDeclarativeEnvironment(Scope);
+            var localEnv = LexicalEnvironment.NewDeclarativeEnvironment(_engine, Scope);
             
             _engine.EnterExecutionContext(localEnv, localEnv, thisBinding);
 
@@ -92,7 +91,7 @@ namespace Jint.Native.Function
             if (!argumentsAlreadyDeclared)
             {
                 // todo: ArgumentsInstance implementation
-                var argsObj = new ArgumentsInstance(null);
+                var argsObj = new ArgumentsInstance(_engine, null);
 
                 if (Strict)
                 {
@@ -114,6 +113,11 @@ namespace Jint.Native.Function
             
             _engine.LeaveExecutionContext();
 
+            if (result.Type == Completion.Throw)
+            {
+                throw new JavaScriptException(result.Value);
+            }
+
             return result;
         }
 

+ 6 - 3
Jint/Native/Global/GlobalObject.cs

@@ -7,14 +7,17 @@ namespace Jint.Native.Global
 {
     public sealed class GlobalObject : ObjectInstance
     {
-        private GlobalObject(ObjectInstance prototype)
-            : base(prototype)
+        private readonly Engine _engine;
+
+        private GlobalObject(Engine engine, ObjectInstance prototype)
+            : base(engine, prototype)
         {
+            _engine = engine;
         }
 
         public static GlobalObject CreateGlobalObject(Engine engine, ObjectInstance prototype)
         {
-            var global = new GlobalObject(prototype);
+            var global = new GlobalObject(engine, prototype);
             
             // Global object properties
             global.DefineOwnProperty("NaN", new DataDescriptor(double.NaN), false);

+ 7 - 4
Jint/Native/Math/MathInstance.cs

@@ -6,10 +6,13 @@ using Jint.Runtime.Descriptors.Specialized;
 namespace Jint.Native.Math
 {
     public sealed class MathInstance : ObjectInstance
-    {   
-        public MathInstance(ObjectInstance prototype)
-            : base(prototype)
+    {
+        private readonly Engine _engine;
+
+        public MathInstance(Engine engine, ObjectInstance prototype)
+            : base(engine, prototype)
         {
+            _engine = engine;
         }
 
         public override string Class
@@ -22,7 +25,7 @@ namespace Jint.Native.Math
 
         public static MathInstance CreateMathObject(Engine engine, ObjectInstance prototype)
         {
-            var math = new MathInstance(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);

+ 2 - 2
Jint/Native/Number/NumberConstructor.cs

@@ -11,7 +11,7 @@ namespace Jint.Native.Number
         private readonly Engine _engine;
 
         public NumberConstructor(Engine engine)
-            : base(engine, new ObjectInstance(engine.Object), null, null, false)
+            : base(engine, new ObjectInstance(engine, engine.Object), null, null, false)
         {
             _engine = engine;
 
@@ -45,7 +45,7 @@ namespace Jint.Native.Number
 
         public NumberInstance Construct(double value)
         {
-            var instance = new NumberInstance(Prototype);
+            var instance = new NumberInstance(_engine, Prototype);
             instance.PrimitiveValue = value;
             return instance;
         }

+ 2 - 2
Jint/Native/Number/NumberInstance.cs

@@ -5,8 +5,8 @@ namespace Jint.Native.Number
 {
     public sealed class NumberInstance : ObjectInstance, IPrimitiveType
     {
-        public NumberInstance(ObjectInstance prototype)
-            : base(prototype)
+        public NumberInstance(Engine engine, ObjectInstance prototype)
+            : base(engine, prototype)
         {
         }
 

+ 1 - 1
Jint/Native/Object/ObjectConstructor.cs

@@ -23,7 +23,7 @@ namespace Jint.Native.Object
 
         public ObjectInstance Construct(object[] arguments)
         {
-            var instance = new ObjectInstance(this.Prototype);
+            var instance = new ObjectInstance(_engine, this.Prototype);
 
             // the constructor is the function constructor of an object
             instance.DefineOwnProperty("constructor", new DataDescriptor(this) { Writable = true, Enumerable = false, Configurable = false }, false);

+ 15 - 13
Jint/Native/Object/ObjectInstance.cs

@@ -1,6 +1,5 @@
 using System;
 using System.Collections.Generic;
-using Jint.Native.Errors;
 using Jint.Native.String;
 using Jint.Runtime;
 using Jint.Runtime.Descriptors;
@@ -9,8 +8,11 @@ namespace Jint.Native.Object
 {
     public class ObjectInstance
     {
-        public ObjectInstance(ObjectInstance prototype)
+        private readonly Engine _engine;
+
+        public ObjectInstance(Engine engine, ObjectInstance prototype)
         {
+            _engine = engine;
             Properties = new Dictionary<string, PropertyDescriptor>();
             Extensible = true;
             Prototype = prototype;
@@ -148,7 +150,7 @@ namespace Jint.Native.Object
             {
                 if (throwOnError)
                 {
-                    throw new TypeError();
+                    throw new JavaScriptException(_engine.TypeError);
                 }
 
                 return;
@@ -168,7 +170,7 @@ namespace Jint.Native.Object
                 {
                     if (throwOnError)
                     {
-                        throw new TypeError();
+                        throw new JavaScriptException(_engine.TypeError);
                     }
 
                     return;
@@ -290,7 +292,7 @@ namespace Jint.Native.Object
             {
                 if (throwOnError)
                 {
-                    throw new TypeError();
+                    throw new JavaScriptException(_engine.TypeError);
                 }
 
                 return false;
@@ -329,7 +331,7 @@ namespace Jint.Native.Object
                     }
                 }
 
-                throw new TypeError();
+                throw new JavaScriptException(_engine.TypeError);
             }
 
             if ((hint == TypeCode.Double) || (hint == TypeCode.Empty))
@@ -356,7 +358,7 @@ namespace Jint.Native.Object
                     }
                 }
 
-                throw new TypeError();
+                throw new JavaScriptException(_engine.TypeError);
             }
 
             return ToString();
@@ -381,7 +383,7 @@ namespace Jint.Native.Object
                 {
                     if (throwOnError)
                     {
-                        throw new TypeError();
+                        throw new JavaScriptException(_engine.TypeError);
                     }
 
                     return false;
@@ -409,7 +411,7 @@ namespace Jint.Native.Object
                 {
                     if (throwOnError)
                     {
-                        throw new TypeError();
+                        throw new JavaScriptException(_engine.TypeError);
                     }
 
                     return false;
@@ -419,7 +421,7 @@ namespace Jint.Native.Object
                 {
                     if (throwOnError)
                     {
-                        throw new TypeError();
+                        throw new JavaScriptException(_engine.TypeError);
                     }
 
                     return false;
@@ -437,7 +439,7 @@ namespace Jint.Native.Object
                 {
                     if (throwOnError)
                     {
-                        throw new TypeError();
+                        throw new JavaScriptException(_engine.TypeError);
                     }
 
                     return false;
@@ -459,7 +461,7 @@ namespace Jint.Native.Object
                     {
                         if (throwOnError)
                         {
-                            throw new TypeError();
+                            throw new JavaScriptException(_engine.TypeError);
                         }
 
                         return false;
@@ -478,7 +480,7 @@ namespace Jint.Native.Object
                     {
                         if (throwOnError)
                         {
-                            throw new TypeError();
+                            throw new JavaScriptException(_engine.TypeError);
                         }
 
                         return false;

+ 2 - 2
Jint/Native/String/StringConstructor.cs

@@ -10,7 +10,7 @@ namespace Jint.Native.String
         private readonly Engine _engine;
 
         public StringConstructor(Engine engine)
-            : base(engine, new ObjectInstance(engine.Object), null, null, false)
+            : base(engine, new ObjectInstance(engine, engine.Object), null, null, false)
         {
             _engine = engine;
 
@@ -37,7 +37,7 @@ namespace Jint.Native.String
 
         public StringInstance Construct(string value)
         {
-            var instance = new StringInstance(Prototype);
+            var instance = new StringInstance(_engine, Prototype);
             instance.PrimitiveValue = value;
             return instance;
         }

+ 5 - 2
Jint/Native/String/StringInstance.cs

@@ -5,9 +5,12 @@ namespace Jint.Native.String
 {
     public sealed class StringInstance : ObjectInstance, IPrimitiveType
     {
-        public StringInstance(ObjectInstance prototype)
-            : base(prototype)
+        private readonly Engine _engine;
+
+        public StringInstance(Engine engine, ObjectInstance prototype)
+            : base(engine, prototype)
         {
+            _engine = engine;
         }
 
         public override string Class

+ 3 - 3
Jint/Runtime/Environments/LexicalEnvironment.cs

@@ -45,14 +45,14 @@ namespace Jint.Runtime.Environments
             return Outer.GetIdentifierReference(name, strict);
         }
 
-        public static LexicalEnvironment NewDeclarativeEnvironment(LexicalEnvironment outer = null)
+        public static LexicalEnvironment NewDeclarativeEnvironment(Engine engine, LexicalEnvironment outer = null)
         {
             return new LexicalEnvironment(new DeclarativeEnvironmentRecord(), outer);
         }
 
-        public static LexicalEnvironment NewObjectEnvironment(ObjectInstance objectInstance, LexicalEnvironment outer, bool provideThis)
+        public static LexicalEnvironment NewObjectEnvironment(Engine engine, ObjectInstance objectInstance, LexicalEnvironment outer, bool provideThis)
         {
-            return new LexicalEnvironment(new ObjectEnvironmentRecord(objectInstance, provideThis), outer);
+            return new LexicalEnvironment(new ObjectEnvironmentRecord(engine, objectInstance, provideThis), outer);
         }
     }
 

+ 4 - 4
Jint/Runtime/Environments/ObjectEnvironmentRecord.cs

@@ -1,5 +1,4 @@
 using Jint.Native;
-using Jint.Native.Errors;
 using Jint.Native.Object;
 using Jint.Runtime.Descriptors;
 
@@ -11,16 +10,17 @@ namespace Jint.Runtime.Environments
     /// </summary>
     public sealed class ObjectEnvironmentRecord : EnvironmentRecord
     {
+        private readonly Engine _engine;
         private readonly ObjectInstance _bindingObject;
         private readonly bool _provideThis;
 
-        public ObjectEnvironmentRecord(ObjectInstance bindingObject, bool provideThis)
+        public ObjectEnvironmentRecord(Engine engine, ObjectInstance bindingObject, bool provideThis)
         {
+            _engine = engine;
             _bindingObject = bindingObject;
             _provideThis = provideThis;
         }
 
-
         public override bool HasBinding(string name)
         {
             return _bindingObject.HasProperty(name);
@@ -59,7 +59,7 @@ namespace Jint.Runtime.Environments
                     return Undefined.Instance;
                 }
 
-                throw new ReferenceError();
+                throw new JavaScriptException(_engine.ReferenceError);
             }
 
             return _bindingObject.Get(name);

+ 14 - 15
Jint/Runtime/ExpressionIntepreter.cs

@@ -1,7 +1,6 @@
 using System;
 using System.Linq;
 using Jint.Native;
-using Jint.Native.Errors;
 using Jint.Native.Function;
 using Jint.Parser.Ast;
 using Jint.Runtime.Descriptors;
@@ -42,7 +41,7 @@ namespace Jint.Runtime
             {
                 if(lref != null && lref.IsStrict() && lref.GetBase() is EnvironmentRecord && (lref.GetReferencedName() == "eval" || lref.GetReferencedName() == "arguments"))
                 {
-                    throw new SyntaxError();
+                    throw new JavaScriptException(_engine.SyntaxError);
                 }
 
                 _engine.PutValue(lref, rval);
@@ -326,7 +325,7 @@ namespace Jint.Runtime
 
                         if (getter == null)
                         {
-                            throw new SyntaxError();
+                            throw new JavaScriptException(_engine.SyntaxError);
                         }
 
                         var get = new ScriptFunctionInstance(
@@ -346,7 +345,7 @@ namespace Jint.Runtime
 
                         if (setter == null)
                         {
-                            throw new SyntaxError();
+                            throw new JavaScriptException(_engine.SyntaxError);
                         }
 
                         var set = new ScriptFunctionInstance(
@@ -374,22 +373,22 @@ namespace Jint.Runtime
 
                     if (_engine.Options.IsStrict() && previousIsData && propIsData)
                     {
-                        throw new SyntaxError();
+                        throw new JavaScriptException(_engine.SyntaxError);
                     }
 
                     if (previousIsData && propIsAccessor)
                     {
-                        throw new SyntaxError();
+                        throw new JavaScriptException(_engine.SyntaxError);
                     }
 
                     if (previousIsAccessor && propIsData)
                     {
-                        throw new SyntaxError();
+                        throw new JavaScriptException(_engine.SyntaxError);
                     }
 
                     if (previousIsAccessor && propIsAccessor && ((previous.As<AccessorDescriptor>().Get != null && propDesc.As<AccessorDescriptor>().Get != null) || (previous.As<AccessorDescriptor>().Set != null && propDesc.As<AccessorDescriptor>().Set != null)))
                     {
-                        throw new SyntaxError();
+                        throw new JavaScriptException(_engine.SyntaxError);
                     }
                 }
 
@@ -419,7 +418,7 @@ namespace Jint.Runtime
                 functionExpression,
                 _engine.Function.Prototype,
                 _engine.Object.Construct(Arguments.Empty),
-                LexicalEnvironment.NewDeclarativeEnvironment(_engine.ExecutionContext.LexicalEnvironment),
+                LexicalEnvironment.NewDeclarativeEnvironment(_engine, _engine.ExecutionContext.LexicalEnvironment),
                 functionExpression.Strict
                 );
         }
@@ -435,13 +434,13 @@ namespace Jint.Runtime
 
             if (TypeConverter.GetType(func) != TypeCode.Object)
             {
-                throw new TypeError();
+                throw new JavaScriptException(_engine.TypeError);
             }
 
             var callable = func as ICallable;
             if (callable == null)
             {
-                throw new TypeError();
+                throw new JavaScriptException(_engine.TypeError);
             }
 
             var r = callee as Reference;
@@ -544,7 +543,7 @@ namespace Jint.Runtime
                         && (r.GetBase() is EnvironmentRecord )
                         && (Array.IndexOf(new []{"eval", "arguments"}, r.GetReferencedName()) != -1) )
                     {
-                        throw new SyntaxError();
+                        throw new JavaScriptException(_engine.SyntaxError);
                     }
 
                     var oldValue = _engine.GetValue(value);
@@ -560,7 +559,7 @@ namespace Jint.Runtime
                         && (r.GetBase() is EnvironmentRecord )
                         && (Array.IndexOf(new []{"eval", "arguments"}, r.GetReferencedName()) != -1) )
                     {
-                        throw new SyntaxError();
+                        throw new JavaScriptException(_engine.SyntaxError);
                     }
 
                     oldValue = _engine.GetValue(value);
@@ -592,7 +591,7 @@ namespace Jint.Runtime
                     {
                         if (r.IsStrict())
                         {
-                            throw new SyntaxError();
+                            throw new JavaScriptException(_engine.SyntaxError);
                         }
 
                         return true;
@@ -604,7 +603,7 @@ namespace Jint.Runtime
                     }
                     if (r.IsStrict())
                     {
-                        throw new SyntaxError();
+                        throw new JavaScriptException(_engine.SyntaxError);
                     }
                     var bindings = r.GetBase() as EnvironmentRecord;
                     return bindings.DeleteBinding(r.GetReferencedName());

+ 16 - 0
Jint/Runtime/JavaScriptException.cs

@@ -0,0 +1,16 @@
+using System;
+
+namespace Jint.Runtime
+{
+    public class JavaScriptException : Exception
+    {
+        private readonly object _errorObject;
+
+        public JavaScriptException(object errorObject)
+        {
+            _errorObject = errorObject;
+        }
+
+        public object Error { get { return _errorObject; } }
+    }
+}

+ 0 - 1
Jint/Runtime/References/Reference.cs

@@ -1,6 +1,5 @@
 using Jint.Native;
 using Jint.Native.Boolean;
-using Jint.Native.Errors;
 using Jint.Native.Number;
 using Jint.Native.Object;
 using Jint.Native.String;

+ 6 - 7
Jint/Runtime/StatementInterpreter.cs

@@ -1,7 +1,6 @@
 using System.Collections.Generic;
 using System.Linq;
 using Jint.Native;
-using Jint.Native.Errors;
 using Jint.Parser.Ast;
 using Jint.Runtime.Environments;
 using Jint.Runtime.References;
@@ -290,7 +289,7 @@ namespace Jint.Runtime
             var val = _engine.EvaluateExpression(withStatement.Object);
             var obj = TypeConverter.ToObject(_engine, _engine.GetValue(val));
             var oldEnv = _engine.ExecutionContext.LexicalEnvironment;
-            var newEnv = LexicalEnvironment.NewObjectEnvironment(obj, oldEnv, true);
+            var newEnv = LexicalEnvironment.NewObjectEnvironment(_engine, obj, oldEnv, true);
             _engine.ExecutionContext.LexicalEnvironment = newEnv;
 
             Completion c;
@@ -298,9 +297,9 @@ namespace Jint.Runtime
             {
                 c = ExecuteStatement(withStatement.Body);
             }
-            catch (Error v)
+            catch (JavaScriptException e)
             {
-                c = new Completion(Completion.Throw, v, null);
+                c = new Completion(Completion.Throw, e.Error, null);
             }
             finally
             {
@@ -382,9 +381,9 @@ namespace Jint.Runtime
                     }
                 }
             }
-            catch(Error v)
+            catch(JavaScriptException v)
             {
-                return new Completion(Completion.Throw, v, null);
+                return new Completion(Completion.Throw, v.Error, null);
             }
 
             return c;
@@ -418,7 +417,7 @@ namespace Jint.Runtime
                     {
                         var c = _engine.GetValue(b);
                         var oldEnv = _engine.ExecutionContext.LexicalEnvironment;
-                        var catchEnv = LexicalEnvironment.NewDeclarativeEnvironment(oldEnv);
+                        var catchEnv = LexicalEnvironment.NewDeclarativeEnvironment(_engine, oldEnv);
                         catchEnv.Record.CreateMutableBinding(catchClause.Param.Name);
                         catchEnv.Record.SetMutableBinding(catchClause.Param.Name, c, false);
                         _engine.ExecutionContext.LexicalEnvironment = catchEnv;

+ 3 - 4
Jint/Runtime/TypeConverter.cs

@@ -1,6 +1,5 @@
 using System;
 using Jint.Native;
-using Jint.Native.Errors;
 using Jint.Native.Object;
 
 namespace Jint.Runtime
@@ -276,12 +275,12 @@ namespace Jint.Runtime
 
             if (value == Undefined.Instance)
             {
-                throw new TypeError();
+                throw new JavaScriptException(engine.TypeError);
             }
 
             if (value == Null.Instance)
             {
-                throw new TypeError();
+                throw new JavaScriptException(engine.TypeError);
             }
 
             if (value is bool)
@@ -310,7 +309,7 @@ namespace Jint.Runtime
                 return engine.String.Construct(s);
             }
 
-            throw new TypeError();
+            throw new JavaScriptException(engine.TypeError);
         }
 
         public static TypeCode GetType(object value)