Browse Source

Implementing error objects and exceptions management

Sebastien Ros 12 năm trước cách đây
mục cha
commit
f5319612ca
35 tập tin đã thay đổi với 298 bổ sung143 xóa
  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)