Marko Lahma 7 лет назад
Родитель
Сommit
e63a0222b8
51 измененных файлов с 482 добавлено и 443 удалено
  1. 0 3
      Jint.Tests/Runtime/Domain/Company.cs
  2. 1 7
      Jint.Tests/Runtime/Domain/IPerson.cs
  3. 2 2
      Jint.Tests/Runtime/InteropTests.cs
  4. 50 86
      Jint/Engine.cs
  5. 5 11
      Jint/JsValueExtensions.cs
  6. 2 2
      Jint/Native/Argument/ArgumentsInstance.cs
  7. 3 4
      Jint/Native/Array/ArrayConstructor.cs
  8. 8 8
      Jint/Native/Array/ArrayInstance.cs
  9. 18 10
      Jint/Native/Array/ArrayPrototype.cs
  10. 2 1
      Jint/Native/Boolean/BooleanPrototype.cs
  11. 2 2
      Jint/Native/Date/DateConstructor.cs
  12. 2 1
      Jint/Native/Date/DateInstance.cs
  13. 17 27
      Jint/Native/Date/DatePrototype.cs
  14. 1 1
      Jint/Native/Error/ErrorPrototype.cs
  15. 3 3
      Jint/Native/Function/BindFunctionInstance.cs
  16. 3 2
      Jint/Native/Function/EvalFunctionInstance.cs
  17. 6 6
      Jint/Native/Function/FunctionConstructor.cs
  18. 3 3
      Jint/Native/Function/FunctionInstance.cs
  19. 5 5
      Jint/Native/Function/FunctionPrototype.cs
  20. 2 1
      Jint/Native/Function/ThrowTypeError.cs
  21. 14 14
      Jint/Native/Global/GlobalObject.cs
  22. 7 18
      Jint/Native/JsValue.cs
  23. 16 16
      Jint/Native/Json/JsonParser.cs
  24. 3 4
      Jint/Native/Json/JsonSerializer.cs
  25. 8 8
      Jint/Native/Number/NumberPrototype.cs
  26. 18 14
      Jint/Native/Object/ObjectConstructor.cs
  27. 13 12
      Jint/Native/Object/ObjectInstance.cs
  28. 1 1
      Jint/Native/Object/ObjectPrototype.cs
  29. 3 4
      Jint/Native/RegExp/RegExpConstructor.cs
  30. 2 2
      Jint/Native/RegExp/RegExpPrototype.cs
  31. 3 3
      Jint/Native/String/StringPrototype.cs
  32. 4 3
      Jint/Native/Symbol/SymbolConstructor.cs
  33. 3 3
      Jint/Native/Symbol/SymbolPrototype.cs
  34. 7 9
      Jint/Runtime/Descriptors/PropertyDescriptor.cs
  35. 3 3
      Jint/Runtime/Descriptors/Specialized/IndexDescriptor.cs
  36. 2 2
      Jint/Runtime/Environments/DeclarativeEnvironmentRecord.cs
  37. 1 1
      Jint/Runtime/Environments/ObjectEnvironmentRecord.cs
  38. 120 0
      Jint/Runtime/ExceptionHelper.cs
  39. 50 73
      Jint/Runtime/ExpressionIntepreter.cs
  40. 2 1
      Jint/Runtime/Interop/ClrFunctionInstance.cs
  41. 7 6
      Jint/Runtime/Interop/DefaultTypeConverter.cs
  42. 1 1
      Jint/Runtime/Interop/DelegateWrapper.cs
  43. 3 2
      Jint/Runtime/Interop/MethodInfoFunctionInstance.cs
  44. 5 4
      Jint/Runtime/Interop/NamespaceReference.cs
  45. 2 2
      Jint/Runtime/Interop/ObjectWrapper.cs
  46. 6 6
      Jint/Runtime/Interop/TypeReference.cs
  47. 1 1
      Jint/Runtime/Interop/TypeReferencePrototype.cs
  48. 2 7
      Jint/Runtime/RefStack.cs
  49. 15 1
      Jint/Runtime/References/Reference.cs
  50. 4 9
      Jint/Runtime/StatementInterpreter.cs
  51. 21 28
      Jint/Runtime/TypeConverter.cs

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

@@ -1,8 +1,5 @@
 using System;
 using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
 
 namespace Jint.Tests.Runtime.Domain
 {

+ 1 - 7
Jint.Tests/Runtime/Domain/IPerson.cs

@@ -1,10 +1,4 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-
-namespace Jint.Tests.Runtime.Domain
+namespace Jint.Tests.Runtime.Domain
 {
     public interface IPerson
     {

+ 2 - 2
Jint.Tests/Runtime/InteropTests.cs

@@ -1335,8 +1335,8 @@ namespace Jint.Tests.Runtime
         public void ShouldReturnUndefinedProperty()
         {
             _engine.SetValue("uo", new { foo = "bar" });
-            _engine.SetValue("ud", new Dictionary<string, object>() { {"foo", "bar"} });
-            _engine.SetValue("ul", new List<string>() { "foo", "bar" });
+            _engine.SetValue("ud", new Dictionary<string, object> { {"foo", "bar"} });
+            _engine.SetValue("ul", new List<string> { "foo", "bar" });
 
             RunTest(@"
                 assert(!uo.undefinedProperty);

+ 50 - 86
Jint/Engine.cs

@@ -405,38 +405,7 @@ namespace Jint
 
         public Completion ExecuteStatement(Statement statement)
         {
-            if (_maxStatements > 0 && _statementsCount++ > _maxStatements)
-            {
-                ThrowStatementsCountOverflowException();
-            }
-
-            if (_timeoutTicks > 0 && _timeoutTicks < DateTime.UtcNow.Ticks)
-            {
-                ThrowTimeoutException();
-            }
-
-            if (Options._MemoryLimit > 0)
-            {
-                if (GetAllocatedBytesForCurrentThread != null)
-                {
-                    var memoryUsage = GetAllocatedBytesForCurrentThread() - _initialMemoryUsage;
-                    if (memoryUsage > Options._MemoryLimit)
-                    {
-                        throw new MemoryLimitExceededException($"Script has allocated {memoryUsage} but is limited to {Options._MemoryLimit}");
-                    }
-                }
-                else
-                {
-                    throw new PlatformNotSupportedException("The current platform doesn't support MemoryLimit.");
-                }
-            }
-
-            _lastSyntaxNode = statement;
-
-            if (_isDebugMode)
-            {
-                DebugHandler.OnStep(statement);
-            }
+            BeforeExecuteStatement(statement);
 
             switch (statement.Type)
             {
@@ -501,11 +470,47 @@ namespace Jint
                     return _statements.ExecuteProgram((Program) statement);
 
                 default:
-                    ThrowArgumentOutOfRange();
+                    ExceptionHelper.ThrowArgumentOutOfRangeException();
                     return new Completion(CompletionType.Normal, null, null);
             }
         }
 
+        private void BeforeExecuteStatement(Statement statement)
+        {
+            if (_maxStatements > 0 && _statementsCount++ > _maxStatements)
+            {
+                ExceptionHelper.ThrowStatementsCountOverflowException();
+            }
+
+            if (_timeoutTicks > 0 && _timeoutTicks < DateTime.UtcNow.Ticks)
+            {
+                ExceptionHelper.ThrowTimeoutException();
+            }
+
+            if (Options._MemoryLimit > 0)
+            {
+                if (GetAllocatedBytesForCurrentThread != null)
+                {
+                    var memoryUsage = GetAllocatedBytesForCurrentThread() - _initialMemoryUsage;
+                    if (memoryUsage > Options._MemoryLimit)
+                    {
+                        ExceptionHelper.ThrowMemoryLimitExceededException($"Script has allocated {memoryUsage} but is limited to {Options._MemoryLimit}");
+                    }
+                }
+                else
+                {
+                    ExceptionHelper.ThrowPlatformNotSupportedException("The current platform doesn't support MemoryLimit.");
+                }
+            }
+
+            _lastSyntaxNode = statement;
+
+            if (_isDebugMode)
+            {
+                DebugHandler.OnStep(statement);
+            }
+        }
+
         public object EvaluateExpression(INode expression)
         {
             _lastSyntaxNode = expression;
@@ -561,7 +566,7 @@ namespace Jint
                     return _expressions.EvaluateUnaryExpression((UnaryExpression) expression);
 
                 default:
-                    ThrowArgumentOutOfRange();
+                    ExceptionHelper.ThrowArgumentOutOfRangeException();
                     return null;
             }
         }
@@ -621,7 +626,7 @@ namespace Jint
                 {
                     return val;
                 }
-                throw new JavaScriptException(ReferenceError, reference.GetReferencedName() + " is not defined");
+                ExceptionHelper.ThrowReferenceError(this, reference.GetReferencedName() + " is not defined");
             }
 
             var baseValue = reference.GetBase();
@@ -673,7 +678,7 @@ namespace Jint
             var record = (EnvironmentRecord) baseValue;
             if (ReferenceEquals(record, null))
             {
-                throw new ArgumentException();
+                ExceptionHelper.ThrowArgumentException();
             }
 
             var bindingValue = record.GetBindingValue(reference.GetReferencedName(), reference.IsStrict());
@@ -697,7 +702,7 @@ namespace Jint
             {
                 if (reference.IsStrict())
                 {
-                    ThrowReferenceError();
+                    ExceptionHelper.ThrowReferenceError(this);
                 }
 
                 Global.Put(reference.GetReferencedName(), value, false);
@@ -717,13 +722,7 @@ namespace Jint
             else
             {
                 var baseValue = reference.GetBase();
-                if (!(baseValue is EnvironmentRecord record))
-                {
-                    ThrowArgumentNullException();
-                    return;
-                }
-
-                record.SetMutableBinding(reference.GetReferencedName(), value, reference.IsStrict());
+                ((EnvironmentRecord) baseValue).SetMutableBinding(reference.GetReferencedName(), value, reference.IsStrict());
             }
         }
 
@@ -737,7 +736,7 @@ namespace Jint
             {
                 if (throwOnError)
                 {
-                    ThrowTypeError();
+                    ExceptionHelper.ThrowTypeError(this);
                 }
                 return;
             }
@@ -748,7 +747,7 @@ namespace Jint
             {
                 if (throwOnError)
                 {
-                    ThrowTypeError();
+                    ExceptionHelper.ThrowTypeError(this);
                 }
                 return;
             }
@@ -764,7 +763,7 @@ namespace Jint
             {
                 if (throwOnError)
                 {
-                    ThrowTypeError();
+                    ExceptionHelper.ThrowTypeError(this);
                 }
             }
         }
@@ -814,12 +813,7 @@ namespace Jint
         /// <returns>The value returned by the function call.</returns>
         public JsValue Invoke(JsValue value, object thisObj, object[] arguments)
         {
-            var callable = value.TryCast<ICallable>();
-
-            if (callable == null)
-            {
-                throw new ArgumentException("Can only invoke functions");
-            }
+            var callable = value as ICallable ?? ExceptionHelper.ThrowArgumentException<ICallable>("Can only invoke functions");
 
             var items = JsValueArrayPool.RentArray(arguments.Length);
             for (int i = 0; i < arguments.Length; ++i)
@@ -926,7 +920,7 @@ namespace Jint
                         {
                             if (existingProp.IsAccessorDescriptor() || !existingProp.Enumerable)
                             {
-                                throw new JavaScriptException(TypeError);
+                                ExceptionHelper.ThrowTypeError(this);
                             }
                         }
                     }
@@ -947,7 +941,7 @@ namespace Jint
 
                     if (ReferenceEquals(declEnv, null))
                     {
-                        throw new ArgumentException();
+                        ExceptionHelper.ThrowArgumentException();
                     }
 
                     declEnv.CreateImmutableBinding("arguments", argsObj);
@@ -984,43 +978,13 @@ namespace Jint
         {
             _executionContexts.ReplaceTopLexicalEnvironment(newEnv);
         }
-
-        private static void ThrowTimeoutException()
-        {
-            throw new TimeoutException();
-        }
-
-        private static void ThrowStatementsCountOverflowException()
-        {
-            throw new StatementsCountOverflowException();
-        }
-
-        private static void ThrowArgumentOutOfRange()
-        {
-            throw new ArgumentOutOfRangeException();
-        }
-        
-        private static void ThrowArgumentNullException()
-        {
-            throw new ArgumentNullException();
-        }
-        
-        private void ThrowReferenceError()
-        {
-            throw new JavaScriptException(ReferenceError);
-        }
         
         private static void AssertNotNullOrEmpty(string propertyname, string propertyValue)
         {
             if (string.IsNullOrEmpty(propertyValue))
             {
-                throw new ArgumentException(propertyname);
+                ExceptionHelper.ThrowArgumentException(propertyname);
             }
         }
-        
-        private void ThrowTypeError()
-        {
-            throw new JavaScriptException(TypeError);
-        }
     }
 }

+ 5 - 11
Jint/JsValueExtensions.cs

@@ -1,5 +1,4 @@
-using System;
-using System.Runtime.CompilerServices;
+using System.Runtime.CompilerServices;
 using Jint.Native;
 using Jint.Runtime;
 
@@ -12,7 +11,7 @@ namespace Jint
         {
             if (value._type != Types.Boolean)
             {
-                ThrowWrongTypeException("The value is not a boolean");
+                ExceptionHelper.ThrowArgumentException("The value is not a boolean");
             }
 
             return ((JsBoolean) value)._value;
@@ -23,7 +22,7 @@ namespace Jint
         {
             if (value._type != Types.Number)
             {
-                ThrowWrongTypeException("The value is not a number");
+                ExceptionHelper.ThrowArgumentException("The value is not a number");
             }
 
             return ((JsNumber) value)._value;
@@ -34,7 +33,7 @@ namespace Jint
         {
             if (value._type != Types.String)
             {
-                ThrowWrongTypeException("The value is not a string");
+                ExceptionHelper.ThrowArgumentException("The value is not a string");
             }
 
             return AsStringWithoutTypeCheck(value);
@@ -51,15 +50,10 @@ namespace Jint
         {
             if (value._type != Types.Symbol)
             {
-                ThrowWrongTypeException("The value is not a symbol");
+                ExceptionHelper.ThrowArgumentException("The value is not a symbol");
             }
 
             return ((JsSymbol) value)._value;
         }
-        
-        private static void ThrowWrongTypeException(string message)
-        {
-            throw new ArgumentException(message);
-        }
     }
 }

+ 2 - 2
Jint/Native/Argument/ArgumentsInstance.cs

@@ -136,7 +136,7 @@ namespace Jint.Native.Argument
             {
                 if (throwOnError)
                 {
-                    throw new JavaScriptException(Engine.TypeError);
+                    ExceptionHelper.ThrowTypeError(Engine);
                 }
 
                 return;
@@ -179,7 +179,7 @@ namespace Jint.Native.Argument
                 {
                     if (throwOnError)
                     {
-                        throw new JavaScriptException(Engine.TypeError);
+                        ExceptionHelper.ThrowTypeError(Engine);
                     }
                 }
 

+ 3 - 4
Jint/Native/Array/ArrayConstructor.cs

@@ -1,5 +1,4 @@
-using System;
-using System.Collections;
+using System.Collections;
 using Jint.Native.Function;
 using Jint.Native.Object;
 using Jint.Runtime;
@@ -74,7 +73,7 @@ namespace Jint.Native.Array
         {
             if (capacity < 0)
             {
-                throw new ArgumentException("invalid array length", nameof(capacity));
+                ExceptionHelper.ThrowArgumentException("invalid array length", nameof(capacity));
             }
             return Construct(System.Array.Empty<JsValue>(), (uint) capacity);
         }
@@ -95,7 +94,7 @@ namespace Jint.Native.Array
                 var length = TypeConverter.ToUint32(arguments.At(0));
                 if (!TypeConverter.ToNumber(arguments[0]).Equals(length))
                 {
-                    throw new JavaScriptException(Engine.RangeError, "Invalid array length");
+                    ExceptionHelper.ThrowRangeError(_engine, "Invalid array length");
                 }
 
                 instance.SetOwnProperty("length", new PropertyDescriptor(length, PropertyFlag.OnlyWritable));

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

@@ -69,7 +69,7 @@ namespace Jint.Native.Array
             {
                 if (throwOnError)
                 {
-                    throw new JavaScriptException(Engine.TypeError);
+                    ExceptionHelper.ThrowTypeError(Engine);
                 }
 
                 return;
@@ -116,7 +116,7 @@ namespace Jint.Native.Array
                 uint newLen = TypeConverter.ToUint32(value);
                 if (newLen != TypeConverter.ToNumber(value))
                 {
-                    throw new JavaScriptException(_engine.RangeError);
+                    ExceptionHelper.ThrowRangeError(_engine);
                 }
 
                 newLenDesc.Value = newLen;
@@ -129,7 +129,7 @@ namespace Jint.Native.Array
                 {
                     if (throwOnError)
                     {
-                        throw new JavaScriptException(_engine.TypeError);
+                        ExceptionHelper.ThrowTypeError(_engine);
                     }
 
                     return false;
@@ -180,7 +180,7 @@ namespace Jint.Native.Array
 
                                     if (throwOnError)
                                     {
-                                        throw new JavaScriptException(_engine.TypeError);
+                                        ExceptionHelper.ThrowTypeError(_engine);
                                     }
 
                                     return false;
@@ -214,7 +214,7 @@ namespace Jint.Native.Array
 
                                     if (throwOnError)
                                     {
-                                        throw new JavaScriptException(_engine.TypeError);
+                                        ExceptionHelper.ThrowTypeError(_engine);
                                     }
 
                                     return false;
@@ -242,7 +242,7 @@ namespace Jint.Native.Array
 
                             if (throwOnError)
                             {
-                                throw new JavaScriptException(_engine.TypeError);
+                                ExceptionHelper.ThrowTypeError(_engine);
                             }
 
                             return false;
@@ -263,7 +263,7 @@ namespace Jint.Native.Array
                 {
                     if (throwOnError)
                     {
-                        throw new JavaScriptException(_engine.TypeError);
+                        ExceptionHelper.ThrowTypeError(_engine);
                     }
 
                     return false;
@@ -274,7 +274,7 @@ namespace Jint.Native.Array
                 {
                     if (throwOnError)
                     {
-                        throw new JavaScriptException(_engine.TypeError);
+                        ExceptionHelper.ThrowTypeError(_engine);
                     }
 
                     return false;

+ 18 - 10
Jint/Native/Array/ArrayPrototype.cs

@@ -116,7 +116,7 @@ namespace Jint.Native.Array
 
             if (len == 0 && arguments.Length < 2)
             {
-                throw new JavaScriptException(Engine.TypeError);
+                ExceptionHelper.ThrowTypeError(Engine);
             }
 
             var k = 0;
@@ -140,7 +140,7 @@ namespace Jint.Native.Array
 
                 if (kPresent == false)
                 {
-                    throw new JavaScriptException(Engine.TypeError);
+                    ExceptionHelper.ThrowTypeError(Engine);
                 }
             }
 
@@ -496,7 +496,7 @@ namespace Jint.Native.Array
         {
             if (!thisObj.IsObject())
             {
-                throw new JavaScriptException(Engine.TypeError, "Array.prorotype.sort can only be applied on objects");
+                ExceptionHelper.ThrowTypeError(_engine, "Array.prorotype.sort can only be applied on objects");
             }
 
             var obj = ArrayOperations.For(thisObj.AsObject());
@@ -511,7 +511,7 @@ namespace Jint.Native.Array
             ICallable compareFn = null;
             if (!compareArg.IsUndefined())
             {
-                compareFn = compareArg.TryCast<ICallable>(x => throw new JavaScriptException(Engine.TypeError, "The sort argument must be a function"));
+                compareFn = compareArg.TryCast<ICallable>(x => ExceptionHelper.ThrowTypeError(_engine, "The sort argument must be a function"));
             }
 
             int Comparer(JsValue x, JsValue y)
@@ -758,7 +758,7 @@ namespace Jint.Native.Array
             else
             {
                 var elementObj = TypeConverter.ToObject(Engine, firstElement);
-                var func = elementObj.Get("toLocaleString").TryCast<ICallable>(x => throw new JavaScriptException(Engine.TypeError));
+                var func = elementObj.Get("toLocaleString") as ICallable ?? ExceptionHelper.ThrowTypeError<ICallable>(_engine);
 
                 r = func.Call(elementObj, Arguments.Empty);
             }
@@ -773,7 +773,7 @@ namespace Jint.Native.Array
                 else
                 {
                     var elementObj = TypeConverter.ToObject(Engine, nextElement);
-                    var func = elementObj.Get("toLocaleString").TryCast<ICallable>(x => throw new JavaScriptException(Engine.TypeError));
+                    var func = elementObj.Get("toLocaleString") as ICallable ?? ExceptionHelper.ThrowTypeError<ICallable>(_engine);
                     r = func.Call(elementObj, Arguments.Empty);
                 }
 
@@ -833,7 +833,10 @@ namespace Jint.Native.Array
         {
             var array = TypeConverter.ToObject(Engine, thisObj);
             ICallable func;
-            func = array.Get("join").TryCast<ICallable>(x => { func = Engine.Object.PrototypeObject.Get("toString").TryCast<ICallable>(y => throw new ArgumentException()); });
+            func = array.Get("join").TryCast<ICallable>(x =>
+            {
+                func = Engine.Object.PrototypeObject.Get("toString").TryCast<ICallable>(y => ExceptionHelper.ThrowArgumentException());
+            });
 
             return func.Call(array, Arguments.Empty);
         }
@@ -851,7 +854,7 @@ namespace Jint.Native.Array
 
             if (len == 0 && arguments.Length < 2)
             {
-                throw new JavaScriptException(Engine.TypeError);
+                ExceptionHelper.ThrowTypeError(Engine);
             }
 
             int k = (int) len - 1;
@@ -877,10 +880,11 @@ namespace Jint.Native.Array
 
                 if (kPresent == false)
                 {
-                    throw new JavaScriptException(Engine.TypeError);
+                    ExceptionHelper.ThrowTypeError(Engine);
                 }
             }
 
+            var jsValues = new JsValue[4];
             for (; k >= 0; k--)
             {
                 var pk = TypeConverter.ToString(k);
@@ -888,7 +892,11 @@ namespace Jint.Native.Array
                 if (kPresent)
                 {
                     var kvalue = o.Get(pk);
-                    accumulator = callable.Call(Undefined, new[] {accumulator, kvalue, k, o});
+                    jsValues[0] = accumulator;
+                    jsValues[1] = kvalue;
+                    jsValues[2] = k;
+                    jsValues[3] = o;
+                    accumulator = callable.Call(Undefined, jsValues);
                 }
             }
 

+ 2 - 1
Jint/Native/Boolean/BooleanPrototype.cs

@@ -45,7 +45,8 @@ namespace Jint.Native.Boolean
                 return o.PrimitiveValue;
             }
 
-            throw new JavaScriptException(Engine.TypeError);
+            ExceptionHelper.ThrowTypeError(Engine);
+            return null;
         }
 
         private JsValue ToBooleanString(JsValue thisObj, JsValue[] arguments)

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

@@ -86,7 +86,7 @@ namespace Jint.Native.Date
             if (!DateTime.TryParseExact(date, DefaultFormats, CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal, out var result))
             {
                 if (!DateTime.TryParseExact(date, SecondaryFormats, CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal, out result))
-                {
+            {
                     if (!DateTime.TryParse(date, Engine.Options._Culture, DateTimeStyles.AdjustToUniversal, out result))
                     {
                         if (!DateTime.TryParse(date, CultureInfo.InvariantCulture, DateTimeStyles.AdjustToUniversal, out result))
@@ -147,7 +147,7 @@ namespace Jint.Native.Date
         {
             if (arguments.Length < 2)
             {
-                throw new ArgumentOutOfRangeException(nameof(arguments), "There must be at least two arguments.");
+                ExceptionHelper.ThrowArgumentOutOfRangeException(nameof(arguments), "There must be at least two arguments.");
             }
 
             var y = TypeConverter.ToNumber(arguments[0]);

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

@@ -21,7 +21,8 @@ namespace Jint.Native.Date
         {
             if (double.IsNaN(PrimitiveValue) || PrimitiveValue > Max || PrimitiveValue < Min)
             {
-                throw new JavaScriptException(Engine.RangeError);
+                ExceptionHelper.ThrowRangeError(Engine);
+                return DateTime.MinValue;
             }
             else
             {

+ 17 - 27
Jint/Native/Date/DatePrototype.cs

@@ -92,7 +92,7 @@ namespace Jint.Native.Date
         {
             return thisObj.TryCast<DateInstance>(value =>
                {
-                   throw new JavaScriptException(Engine.TypeError, "Invalid Date");
+                   ExceptionHelper.ThrowTypeError(_engine, "Invalid Date");
                });
         }
 
@@ -523,9 +523,9 @@ namespace Jint.Native.Date
         private JsValue ToUtcString(JsValue thisObj, JsValue[] arguments)
         {
             return thisObj.TryCast<DateInstance>(x =>
-            {
-                throw new JavaScriptException(Engine.TypeError);
-            } )
+                {
+                    ExceptionHelper.ThrowTypeError(_engine);
+                } )
             .ToDateTime().ToUniversalTime().ToString("ddd MMM dd yyyy HH:mm:ss 'GMT'", CultureInfo.InvariantCulture);
         }
 
@@ -533,12 +533,12 @@ namespace Jint.Native.Date
         {
             var t = thisObj.TryCast<DateInstance>(x =>
             {
-                throw new JavaScriptException(Engine.TypeError);
+                ExceptionHelper.ThrowTypeError(_engine);
             }).PrimitiveValue;
 
             if (double.IsInfinity(t) || double.IsNaN(t))
             {
-                throw new JavaScriptException(Engine.RangeError);
+                ExceptionHelper.ThrowRangeError(_engine);
             }
             double h = HourFromTime(t);
             double m = MinFromTime(t);
@@ -548,14 +548,7 @@ namespace Jint.Native.Date
             if (m < 0) { m += MinutesPerHour; }
             if (s < 0) { s += SecondsPerMinute; }
             if (ms < 0) { ms += MsPerSecond; }
-            return string.Format("{0:0000}-{1:00}-{2:00}T{3:00}:{4:00}:{5:00}.{6:000}Z",
-                YearFromTime(t),
-                MonthFromTime(t)+1,
-                DateFromTime(t),
-                h,
-                m,
-                s,
-                ms);
+            return $"{YearFromTime(t):0000}-{MonthFromTime(t) + 1:00}-{DateFromTime(t):00}T{h:00}:{m:00}:{s:00}.{ms:000}Z";
         }
 
         private JsValue ToJSON(JsValue thisObj, JsValue[] arguments)
@@ -570,7 +563,7 @@ namespace Jint.Native.Date
             var toIso = o.Get("toISOString");
             if (!toIso.Is<ICallable>())
             {
-                throw new JavaScriptException(Engine.TypeError);
+                ExceptionHelper.ThrowTypeError(Engine);
             }
 
             return toIso.TryCast<ICallable>().Call(o, Arguments.Empty);
@@ -717,7 +710,8 @@ namespace Jint.Native.Date
                 return 1;
             }
 
-            throw new ArgumentException();
+            ExceptionHelper.ThrowArgumentException();
+            return 0;
         }
 
         /// <summary>
@@ -788,7 +782,8 @@ namespace Jint.Native.Date
                 return 11;
             }
 
-            throw new InvalidOperationException();
+            ExceptionHelper.ThrowInvalidOperationException();
+            return 0;
         }
 
         public static double DayWithinYear(double t)
@@ -861,7 +856,8 @@ namespace Jint.Native.Date
                 return dayWithinYear - 333 - InLeapYear(t);
             }
 
-            throw new InvalidOperationException();
+            ExceptionHelper.ThrowInvalidOperationException();
+            return 0;
         }
 
         /// <summary>
@@ -872,13 +868,7 @@ namespace Jint.Native.Date
             return (Day(t) + 4)%7;
         }
 
-        public double LocalTza
-        {
-            get
-            {
-                return Engine.Options._LocalTimeZone.BaseUtcOffset.TotalMilliseconds;
-            }
-        }
+        public double LocalTza => Engine.Options._LocalTimeZone.BaseUtcOffset.TotalMilliseconds;
 
         public double DaylightSavingTa(double t)
         {
@@ -1025,8 +1015,8 @@ namespace Jint.Native.Date
                 case 1:
                     return 28 + leap;
                 default:
-                    throw new ArgumentOutOfRangeException(nameof(month));
-
+                    ExceptionHelper.ThrowArgumentOutOfRangeException(nameof(month), "invalid month");
+                    return 0;
             }
         }
 

+ 1 - 1
Jint/Native/Error/ErrorPrototype.cs

@@ -44,7 +44,7 @@ namespace Jint.Native.Error
             var o = thisObject.TryCast<ObjectInstance>();
             if (ReferenceEquals(o, null))
             {
-                throw new JavaScriptException(Engine.TypeError);
+                ExceptionHelper.ThrowTypeError(Engine);
             }
 
             var name = TypeConverter.ToString(o.Get("name"));

+ 3 - 3
Jint/Native/Function/BindFunctionInstance.cs

@@ -20,7 +20,7 @@ namespace Jint.Native.Function
         {
             var f = TargetFunction.TryCast<FunctionInstance>(x =>
             {
-                throw new JavaScriptException(Engine.TypeError);
+                ExceptionHelper.ThrowTypeError(Engine);
             });
 
             return f.Call(BoundThis, BoundArgs.Union(arguments).ToArray());
@@ -30,7 +30,7 @@ namespace Jint.Native.Function
         {
             var target = TargetFunction.TryCast<IConstructor>(x =>
             {
-                throw new JavaScriptException(Engine.TypeError);
+                ExceptionHelper.ThrowTypeError(Engine);
             });
 
             return target.Construct(BoundArgs.Union(arguments).ToArray());
@@ -40,7 +40,7 @@ namespace Jint.Native.Function
         {
             var f = TargetFunction.TryCast<FunctionInstance>(x =>
             {
-                throw new JavaScriptException(Engine.TypeError);
+                ExceptionHelper.ThrowTypeError(Engine);
             });
 
             return f.HasInstance(v);

+ 3 - 2
Jint/Native/Function/EvalFunctionInstance.cs

@@ -100,10 +100,11 @@ namespace Jint.Native.Function
             {
                 if (e.Description == Messages.InvalidLHSInAssignment)
                 {
-                    throw new JavaScriptException(Engine.ReferenceError);
+                    ExceptionHelper.ThrowReferenceError(_engine);
                 }
 
-                throw new JavaScriptException(Engine.SyntaxError);
+                ExceptionHelper.ThrowSyntaxError(_engine);
+                return null;
             }
         }
     }

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

@@ -1,5 +1,4 @@
-using System;
-using Esprima;
+using Esprima;
 using Esprima.Ast;
 using Jint.Native.Object;
 using Jint.Runtime;
@@ -77,7 +76,8 @@ namespace Jint.Native.Function
             }
             catch (ParserException)
             {
-                throw new JavaScriptException(Engine.SyntaxError);
+                ExceptionHelper.ThrowSyntaxError(_engine);
+                return null;
             }
 
             var functionObject = new ScriptFunctionInstance(
@@ -129,7 +129,7 @@ namespace Jint.Native.Function
         {
             if (arguments.Length != 2)
             {
-                throw new ArgumentException("Apply has to be called with two arguments.");
+                ExceptionHelper.ThrowArgumentException("Apply has to be called with two arguments.");
             }
 
             var func = thisObject.TryCast<ICallable>();
@@ -138,7 +138,7 @@ namespace Jint.Native.Function
 
             if (func == null)
             {
-                throw new JavaScriptException(Engine.TypeError);
+                ExceptionHelper.ThrowTypeError(Engine);
             }
 
             if (argArray.IsNull() || argArray.IsUndefined())
@@ -149,7 +149,7 @@ namespace Jint.Native.Function
             var argArrayObj = argArray.TryCast<ObjectInstance>();
             if (ReferenceEquals(argArrayObj, null))
             {
-                throw new JavaScriptException(Engine.TypeError);
+                ExceptionHelper.ThrowTypeError(Engine);
             }
 
             var len = argArrayObj.Get("length");

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

@@ -58,14 +58,14 @@ namespace Jint.Native.Function
             var po = Get("prototype");
             if (!po.IsObject())
             {
-                throw new JavaScriptException(_engine.TypeError, $"Function has non-object prototype '{TypeConverter.ToString(po)}' in instanceof check");
+                ExceptionHelper.ThrowTypeError(_engine, $"Function has non-object prototype '{TypeConverter.ToString(po)}' in instanceof check");
             }
 
             var o = po.AsObject();
 
             if (ReferenceEquals(o, null))
             {
-                throw new JavaScriptException(_engine.TypeError);
+                ExceptionHelper.ThrowTypeError(_engine);
             }
 
             while (true)
@@ -97,7 +97,7 @@ namespace Jint.Native.Function
                 && propertyName == "caller"
                 && ((v.As<FunctionInstance>()?.Strict).GetValueOrDefault()))
             {
-                throw new JavaScriptException(_engine.TypeError);
+                ExceptionHelper.ThrowTypeError(_engine);
             }
 
             return v;

+ 5 - 5
Jint/Native/Function/FunctionPrototype.cs

@@ -41,7 +41,7 @@ namespace Jint.Native.Function
         {
             var target = thisObj.TryCast<ICallable>(x =>
             {
-                throw new JavaScriptException(Engine.TypeError);
+                ExceptionHelper.ThrowTypeError(Engine);
             });
 
             var thisArg = arguments.At(0);
@@ -77,7 +77,7 @@ namespace Jint.Native.Function
 
             if (ReferenceEquals(func, null))
             {
-                throw new JavaScriptException(Engine.TypeError, "Function object expected.");
+                ExceptionHelper.ThrowTypeError(_engine, "Function object expected.");
             }
 
             return "function() {{ ... }}";
@@ -91,7 +91,7 @@ namespace Jint.Native.Function
 
             if (func == null)
             {
-                throw new JavaScriptException(Engine.TypeError);
+                ExceptionHelper.ThrowTypeError(Engine);
             }
 
             if (argArray.IsNull() || argArray.IsUndefined())
@@ -102,7 +102,7 @@ namespace Jint.Native.Function
             var argArrayObj = argArray.TryCast<ObjectInstance>();
             if (ReferenceEquals(argArrayObj, null))
             {
-                throw new JavaScriptException(Engine.TypeError);
+                ExceptionHelper.ThrowTypeError(Engine);
             }
 
             var len = ((JsNumber) argArrayObj.Get("length"))._value;
@@ -130,7 +130,7 @@ namespace Jint.Native.Function
             var func = thisObject.TryCast<ICallable>();
             if (func == null)
             {
-                throw new JavaScriptException(Engine.TypeError);
+                ExceptionHelper.ThrowTypeError(Engine);
             }
 
             return func.Call(arguments.At(0), arguments.Length == 0 ? arguments : arguments.Skip(1));

+ 2 - 1
Jint/Native/Function/ThrowTypeError.cs

@@ -13,7 +13,8 @@ namespace Jint.Native.Function
 
         public override JsValue Call(JsValue thisObject, JsValue[] arguments)
         {
-            throw new JavaScriptException(_engine.TypeError);
+            ExceptionHelper.ThrowTypeError(_engine);
+            return null;
         }
     }
 }

+ 14 - 14
Jint/Native/Global/GlobalObject.cs

@@ -414,7 +414,7 @@ namespace Jint.Native.Global
                 {
                     if (c >= 0xDC00 && c <= 0xDBFF)
                     {
-                        throw new JavaScriptException(Engine.UriError);
+                        ExceptionHelper.ThrowUriError(_engine);
                     }
 
                     int v;
@@ -427,19 +427,19 @@ namespace Jint.Native.Global
                         k++;
                         if (k == strLen)
                         {
-                            throw new JavaScriptException(Engine.UriError);
+                            ExceptionHelper.ThrowUriError(_engine);
                         }
 
                         var kChar = (int)uriString[k];
                         if (kChar < 0xDC00 || kChar > 0xDFFF)
                         {
-                            throw new JavaScriptException(Engine.UriError);
+                            ExceptionHelper.ThrowUriError(_engine);
                         }
 
                         v = (c - 0xD800) * 0x400 + (kChar - 0xDC00) + 0x10000;
                     }
 
-                    byte[] octets;
+                    byte[] octets = System.Array.Empty<byte>();
 
                     if (v >= 0 && v <= 0x007F)
                     {
@@ -467,7 +467,7 @@ namespace Jint.Native.Global
                     }
                     else if (v <= 0xDFFF)
                     {
-                        throw new JavaScriptException(Engine.UriError);
+                        ExceptionHelper.ThrowUriError(_engine);
                     }
                     else if (v <= 0xFFFF)
                     {
@@ -536,12 +536,12 @@ namespace Jint.Native.Global
                     var start = k;
                     if (k + 2 >= strLen)
                     {
-                        throw new JavaScriptException(Engine.UriError);
+                        ExceptionHelper.ThrowUriError(_engine);
                     }
 
                     if (!IsValidHexaChar(uriString[k + 1]) || !IsValidHexaChar(uriString[k + 2]))
                     {
-                        throw new JavaScriptException(Engine.UriError);
+                        ExceptionHelper.ThrowUriError(_engine);
                     }
 
                     var B = Convert.ToByte(uriString[k + 1].ToString() + uriString[k + 2], 16);
@@ -566,7 +566,7 @@ namespace Jint.Native.Global
 
                         if (n == 1 || n > 4)
                         {
-                            throw new JavaScriptException(Engine.UriError);
+                            ExceptionHelper.ThrowUriError(_engine);
                         }
 
                         var Octets = new byte[n];
@@ -574,7 +574,7 @@ namespace Jint.Native.Global
 
                         if (k + (3 * (n - 1)) >= strLen)
                         {
-                            throw new JavaScriptException(Engine.UriError);
+                            ExceptionHelper.ThrowUriError(_engine);
                         }
 
                         for (var j = 1; j < n; j++)
@@ -582,12 +582,12 @@ namespace Jint.Native.Global
                             k++;
                             if (uriString[k] != '%')
                             {
-                                throw new JavaScriptException(Engine.UriError);
+                                ExceptionHelper.ThrowUriError(_engine);
                             }
 
                             if (!IsValidHexaChar(uriString[k + 1]) || !IsValidHexaChar(uriString[k + 2]))
                             {
-                                throw new JavaScriptException(Engine.UriError);
+                                ExceptionHelper.ThrowUriError(_engine);
                             }
 
                             B = Convert.ToByte(uriString[k + 1].ToString() + uriString[k + 2], 16);
@@ -595,7 +595,7 @@ namespace Jint.Native.Global
                             // B & 11000000 != 10000000
                             if ((B & 0xC0) != 0x80)
                             {
-                                throw new JavaScriptException(Engine.UriError);
+                                ExceptionHelper.ThrowUriError(_engine);
                             }
 
                             k += 2;
@@ -633,11 +633,11 @@ namespace Jint.Native.Global
                 }
                 else if (c < 256)
                 {
-                    _stringBuilder.Append(string.Format("%{0}", ((int)c).ToString("X2")));
+                    _stringBuilder.Append($"%{((int) c):X2}");
                 }
                 else
                 {
-                    _stringBuilder.Append(string.Format("%u{0}", ((int)c).ToString("X4")));
+                    _stringBuilder.Append($"%u{((int) c):X4}");
                 }
             }
 

+ 7 - 18
Jint/Native/JsValue.cs

@@ -116,7 +116,7 @@ namespace Jint.Native
         {
             if (!IsObject())
             {
-                ThrowArgumentException("The value is not an object");
+                ExceptionHelper.ThrowArgumentException("The value is not an object");
             }
             return this as ObjectInstance;
         }
@@ -127,7 +127,7 @@ namespace Jint.Native
         {
             if (!IsObject())
             {
-                ThrowArgumentException("The value is not an object");
+                ExceptionHelper.ThrowArgumentException("The value is not an object");
             }
             return this as TInstance;
         }
@@ -138,7 +138,7 @@ namespace Jint.Native
         {
             if (!IsArray())
             {
-                ThrowArgumentException("The value is not an array");
+                ExceptionHelper.ThrowArgumentException("The value is not an array");
             }
             return this as ArrayInstance;
         }
@@ -149,7 +149,7 @@ namespace Jint.Native
         {
             if (!IsDate())
             {
-                ThrowArgumentException("The value is not a date");
+                ExceptionHelper.ThrowArgumentException("The value is not a date");
             }
             return this as DateInstance;
         }
@@ -159,7 +159,7 @@ namespace Jint.Native
         {
             if (!IsRegExp())
             {
-                ThrowArgumentException("The value is not a regex");
+                ExceptionHelper.ThrowArgumentException("The value is not a regex");
             }
 
             return this as RegExpInstance;
@@ -170,7 +170,7 @@ namespace Jint.Native
         {
             if (_type != Types.Completion)
             {
-                ThrowArgumentException("The value is not a completion record");
+                ExceptionHelper.ThrowArgumentException("The value is not a completion record");
             }
 
             // TODO not implemented
@@ -333,13 +333,7 @@ namespace Jint.Native
         /// <returns>The value returned by the function call.</returns>
         public JsValue Invoke(JsValue thisObj, JsValue[] arguments)
         {
-            var callable = TryCast<ICallable>();
-
-            if (callable == null)
-            {
-                throw new ArgumentException("Can only invoke functions");
-            }
-
+            var callable = this as ICallable ?? ExceptionHelper.ThrowArgumentException<ICallable>("Can only invoke functions");
             return callable.Call(thisObj, arguments);
         }
 
@@ -361,11 +355,6 @@ namespace Jint.Native
             return false;
         }
 
-        private static void ThrowArgumentException(string message)
-        {
-            throw new ArgumentException(message);
-        }
-
         public override string ToString()
         {
             return "None";

+ 16 - 16
Jint/Native/Json/JsonParser.cs

@@ -98,7 +98,7 @@ namespace Jint.Native.Json
                 }
                 else
                 {
-                    throw new JavaScriptException(_engine.SyntaxError, string.Format("Expected hexadecimal digit:{0}", _source));
+                    ExceptionHelper.ThrowSyntaxError(_engine, $"Expected hexadecimal digit:{_source}");
                 }
             }
             return (char)code;
@@ -152,7 +152,9 @@ namespace Jint.Native.Json
                             Range = new[] {start, _index}
                         };
             }
-            throw new JavaScriptException(_engine.SyntaxError, string.Format(Messages.UnexpectedToken, code));
+
+            ExceptionHelper.ThrowSyntaxError(_engine, string.Format(Messages.UnexpectedToken, code));
+            return null;
         }
 
         private Token ScanNumericLiteral()
@@ -181,7 +183,7 @@ namespace Jint.Native.Json
                     // decimal number starts with '0' such as '09' is illegal.
                     if (ch > 0 && IsDecimalDigit(ch))
                     {
-                        throw new Exception(Messages.UnexpectedToken);
+                        ExceptionHelper.ThrowArgumentException(Messages.UnexpectedToken);
                     }
                 }
 
@@ -220,7 +222,7 @@ namespace Jint.Native.Json
                 }
                 else
                 {
-                    throw new Exception(Messages.UnexpectedToken);
+                    ExceptionHelper.ThrowArgumentException(Messages.UnexpectedToken);
                 }
             }
 
@@ -255,10 +257,9 @@ namespace Jint.Native.Json
                     Range = new[] { start, _index }
                 };
             }
-            else
-            {
-                throw new JavaScriptException(_engine.SyntaxError, string.Format(Messages.UnexpectedToken, s));
-            }
+
+            ExceptionHelper.ThrowSyntaxError(_engine, string.Format(Messages.UnexpectedToken, s));
+            return null;
         }
 
         private Token ScanNullLiteral()
@@ -282,10 +283,9 @@ namespace Jint.Native.Json
                     Range = new[] { start, _index }
                 };
             }
-            else
-            {
-                throw new JavaScriptException(_engine.SyntaxError, string.Format(Messages.UnexpectedToken, s));
-            }
+
+            ExceptionHelper.ThrowSyntaxError(_engine, string.Format(Messages.UnexpectedToken, s));
+            return null;
         }
 
         private Token ScanStringLiteral()
@@ -309,7 +309,7 @@ namespace Jint.Native.Json
 
                 if (ch <= 31)
                 {
-                    throw new JavaScriptException(_engine.SyntaxError, string.Format("Invalid character '{0}', position:{1}, string:{2}", ch, _index, _source));
+                    ExceptionHelper.ThrowSyntaxError(_engine, $"Invalid character '{ch}', position:{_index}, string:{_source}");
                 }
 
                 if (ch == '\\')
@@ -401,7 +401,7 @@ namespace Jint.Native.Json
 
             if (quote != 0)
             {
-                throw new JavaScriptException(_engine.SyntaxError, string.Format(Messages.UnexpectedToken, _source));
+                ExceptionHelper.ThrowSyntaxError(_engine, string.Format(Messages.UnexpectedToken, _source));
             }
 
             return new Token
@@ -738,7 +738,7 @@ namespace Jint.Native.Json
                 var name = Lex().Value.ToString();
                 if (PropertyNameContainsInvalidChar0To31(name))
                 {
-                    throw new JavaScriptException(_engine.SyntaxError, string.Format("Invalid character in property name '{0}'", name));
+                    ExceptionHelper.ThrowSyntaxError(_engine, $"Invalid character in property name '{name}'");
                 }
 
                 Expect(":");
@@ -864,7 +864,7 @@ namespace Jint.Native.Json
                 object value = _lookahead.Value;
                 if(_lookahead.Type != Tokens.EOF)
                 {
-                    throw new JavaScriptException(_engine.SyntaxError, string.Format("Unexpected {0} {1}", _lookahead.Type, _lookahead.Value));
+                    ExceptionHelper.ThrowSyntaxError(_engine, $"Unexpected {_lookahead.Type} {_lookahead.Value}");
                 }
                 return jsv;
             }

+ 3 - 4
Jint/Native/Json/JsonSerializer.cs

@@ -1,5 +1,4 @@
-using System;
-using System.Collections.Generic;
+using System.Collections.Generic;
 using System.Linq;
 using Jint.Native.Array;
 using Jint.Native.Global;
@@ -297,12 +296,12 @@ namespace Jint.Native.Json
         {
             if (value == null)
             {
-                throw new ArgumentNullException("value");
+                ExceptionHelper.ThrowArgumentNullException(nameof(value));
             }
 
             if (_stack.Contains(value))
             {
-                throw new JavaScriptException(_engine.TypeError, "Cyclic reference detected.");
+                ExceptionHelper.ThrowTypeError(_engine, "Cyclic reference detected.");
             }
         }
 

+ 8 - 8
Jint/Native/Number/NumberPrototype.cs

@@ -45,7 +45,7 @@ namespace Jint.Native.Number
         {
             if (!thisObject.IsNumber() && ReferenceEquals(thisObject.TryCast<NumberInstance>(), null))
             {
-                throw new JavaScriptException(Engine.TypeError);
+                ExceptionHelper.ThrowTypeError(Engine);
             }
 
             var m = TypeConverter.ToNumber(thisObject);
@@ -83,7 +83,7 @@ namespace Jint.Native.Number
             var number = thisObj.TryCast<NumberInstance>();
             if (ReferenceEquals(number, null))
             {
-                throw new JavaScriptException(Engine.TypeError);
+                ExceptionHelper.ThrowTypeError(Engine);
             }
 
             return number.NumberData;
@@ -96,7 +96,7 @@ namespace Jint.Native.Number
             var f = (int)TypeConverter.ToInteger(arguments.At(0, 0));
             if (f < 0 || f > 20)
             {
-                throw new JavaScriptException(Engine.RangeError, "fractionDigits argument must be between 0 and 20");
+                ExceptionHelper.ThrowRangeError(_engine, "fractionDigits argument must be between 0 and 20");
             }
 
             var x = TypeConverter.ToNumber(thisObj);
@@ -119,7 +119,7 @@ namespace Jint.Native.Number
             var f = (int)TypeConverter.ToInteger(arguments.At(0, 16));
             if (f < 0 || f > 20)
             {
-                throw new JavaScriptException(Engine.RangeError, "fractionDigits argument must be between 0 and 20");
+                ExceptionHelper.ThrowRangeError(_engine, "fractionDigits argument must be between 0 and 20");
             }
 
             var x = TypeConverter.ToNumber(thisObj);
@@ -129,7 +129,7 @@ namespace Jint.Native.Number
                 return "NaN";
             }
 
-            string format = System.String.Concat("#.", new System.String('0', f), "e+0");
+            string format = string.Concat("#.", new string('0', f), "e+0");
             return x.ToString(format, CultureInfo.InvariantCulture);
         }
 
@@ -151,7 +151,7 @@ namespace Jint.Native.Number
 
             if (p < 1 || p > 21)
             {
-                throw new JavaScriptException(Engine.RangeError, "precision must be between 1 and 21");
+                ExceptionHelper.ThrowRangeError(_engine, "precision must be between 1 and 21");
             }
 
             // Get the number of decimals
@@ -169,7 +169,7 @@ namespace Jint.Native.Number
         {
             if (!thisObject.IsNumber() && (ReferenceEquals(thisObject.TryCast<NumberInstance>(), null)))
             {
-                throw new JavaScriptException(Engine.TypeError);
+                ExceptionHelper.ThrowTypeError(_engine);
             }
 
             var radix = arguments.At(0).IsUndefined() 
@@ -178,7 +178,7 @@ namespace Jint.Native.Number
 
             if (radix < 2 || radix > 36)
             {
-                throw new JavaScriptException(Engine.RangeError, "radix must be between 2 and 36");
+                ExceptionHelper.ThrowRangeError(_engine, "radix must be between 2 and 36");
             }
 
             var x = TypeConverter.ToNumber(thisObject);

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

@@ -107,7 +107,7 @@ namespace Jint.Native.Object
             var o = oArg.TryCast<ObjectInstance>();
             if (ReferenceEquals(o, null))
             {
-                throw new JavaScriptException(Engine.TypeError);
+                ExceptionHelper.ThrowTypeError(Engine);
             }
 
             return o.Prototype ?? Null;
@@ -119,7 +119,7 @@ namespace Jint.Native.Object
             var o = oArg.TryCast<ObjectInstance>();
             if (ReferenceEquals(o, null))
             {
-                throw new JavaScriptException(Engine.TypeError);
+                ExceptionHelper.ThrowTypeError(Engine);
             }
 
             var p = arguments.At(1);
@@ -135,7 +135,7 @@ namespace Jint.Native.Object
             var o = oArg.TryCast<ObjectInstance>();
             if (ReferenceEquals(o, null))
             {
-                throw new JavaScriptException(Engine.TypeError);
+                ExceptionHelper.ThrowTypeError(Engine);
             }
 
             uint n = 0;
@@ -172,7 +172,7 @@ namespace Jint.Native.Object
             var o = oArg.TryCast<ObjectInstance>();
             if (ReferenceEquals(o, null) && !oArg.IsNull())
             {
-                throw new JavaScriptException(Engine.TypeError);
+                ExceptionHelper.ThrowTypeError(Engine);
             }
 
             var obj = Engine.Object.Construct(Arguments.Empty);
@@ -181,7 +181,11 @@ namespace Jint.Native.Object
             var properties = arguments.At(1);
             if (!properties.IsUndefined())
             {
-                DefineProperties(thisObject, new [] {obj, properties});
+                var jsValues = _engine.JsValueArrayPool.RentArray(2);
+                jsValues[0] = obj;
+                jsValues[1] = properties;
+                DefineProperties(thisObject, jsValues);
+               _engine.JsValueArrayPool.ReturnArray(jsValues);
             }
 
             return obj;
@@ -193,7 +197,7 @@ namespace Jint.Native.Object
             var o = oArg.TryCast<ObjectInstance>();
             if (ReferenceEquals(o, null))
             {
-                throw new JavaScriptException(Engine.TypeError);
+                ExceptionHelper.ThrowTypeError(Engine);
             }
 
             var p = arguments.At(1);
@@ -212,7 +216,7 @@ namespace Jint.Native.Object
             var o = oArg.TryCast<ObjectInstance>();
             if (ReferenceEquals(o, null))
             {
-                throw new JavaScriptException(Engine.TypeError);
+                ExceptionHelper.ThrowTypeError(Engine);
             }
 
             var properties = arguments.At(1);
@@ -243,7 +247,7 @@ namespace Jint.Native.Object
             var o = oArg.TryCast<ObjectInstance>();
             if (ReferenceEquals(o, null))
             {
-                throw new JavaScriptException(Engine.TypeError);
+                ExceptionHelper.ThrowTypeError(Engine);
             }
 
             var properties = new List<KeyValuePair<string, PropertyDescriptor>>(o.GetOwnProperties());
@@ -270,7 +274,7 @@ namespace Jint.Native.Object
             var o = oArg.TryCast<ObjectInstance>();
             if (ReferenceEquals(o, null))
             {
-                throw new JavaScriptException(Engine.TypeError);
+                ExceptionHelper.ThrowTypeError(Engine);
             }
 
             var properties = new List<KeyValuePair<string, PropertyDescriptor>>(o.GetOwnProperties());
@@ -306,7 +310,7 @@ namespace Jint.Native.Object
             var o = oArg.TryCast<ObjectInstance>();
             if (ReferenceEquals(o, null))
             {
-                throw new JavaScriptException(Engine.TypeError);
+                ExceptionHelper.ThrowTypeError(Engine);
             }
 
             o.Extensible = false;
@@ -320,7 +324,7 @@ namespace Jint.Native.Object
             var o = oArg.TryCast<ObjectInstance>();
             if (ReferenceEquals(o, null))
             {
-                throw new JavaScriptException(Engine.TypeError);
+                ExceptionHelper.ThrowTypeError(Engine);
             }
 
             foreach (var prop in o.GetOwnProperties())
@@ -345,7 +349,7 @@ namespace Jint.Native.Object
             var o = oArg.TryCast<ObjectInstance>();
             if (ReferenceEquals(o, null))
             {
-                throw new JavaScriptException(Engine.TypeError);
+                ExceptionHelper.ThrowTypeError(Engine);
             }
 
             foreach (var pair in o.GetOwnProperties())
@@ -378,7 +382,7 @@ namespace Jint.Native.Object
             var o = oArg.TryCast<ObjectInstance>();
             if (ReferenceEquals(o, null))
             {
-                throw new JavaScriptException(Engine.TypeError);
+                ExceptionHelper.ThrowTypeError(Engine);
             }
 
             return o.Extensible;
@@ -390,7 +394,7 @@ namespace Jint.Native.Object
             var o = oArg.TryCast<ObjectInstance>();
             if (ReferenceEquals(o, null))
             {
-                throw new JavaScriptException(Engine.TypeError);
+                ExceptionHelper.ThrowTypeError(Engine);
             }
 
             var enumerableProperties = o.GetOwnProperties()

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

@@ -279,7 +279,7 @@ namespace Jint.Native.Object
             {
                 if (throwOnError)
                 {
-                    throw new JavaScriptException(Engine.TypeError);
+                    ExceptionHelper.ThrowTypeError(Engine);
                 }
 
                 return;
@@ -411,7 +411,7 @@ namespace Jint.Native.Object
             {
                 if (throwOnError)
                 {
-                    throw new JavaScriptException(Engine.TypeError);
+                    ExceptionHelper.ThrowTypeError(Engine);
                 }
 
                 return false;
@@ -450,7 +450,7 @@ namespace Jint.Native.Object
                     }
                 }
 
-                throw new JavaScriptException(Engine.TypeError);
+                ExceptionHelper.ThrowTypeError(Engine);
             }
 
             if (hint == Types.Number || hint == Types.None)
@@ -475,7 +475,7 @@ namespace Jint.Native.Object
                     }
                 }
 
-                throw new JavaScriptException(Engine.TypeError);
+                ExceptionHelper.ThrowTypeError(Engine);
             }
 
             return ToString();
@@ -506,7 +506,7 @@ namespace Jint.Native.Object
                 {
                     if (throwOnError)
                     {
-                        throw new JavaScriptException(Engine.TypeError);
+                        ExceptionHelper.ThrowTypeError(Engine);
                     }
 
                     return false;
@@ -579,7 +579,7 @@ namespace Jint.Native.Object
                 {
                     if (throwOnError)
                     {
-                        throw new JavaScriptException(Engine.TypeError);
+                        ExceptionHelper.ThrowTypeError(Engine);
                     }
 
                     return false;
@@ -589,7 +589,7 @@ namespace Jint.Native.Object
                 {
                     if (throwOnError)
                     {
-                        throw new JavaScriptException(Engine.TypeError);
+                        ExceptionHelper.ThrowTypeError(Engine);
                     }
 
                     return false;
@@ -604,7 +604,7 @@ namespace Jint.Native.Object
                     {
                         if (throwOnError)
                         {
-                            throw new JavaScriptException(Engine.TypeError);
+                            ExceptionHelper.ThrowTypeError(Engine);
                         }
 
                         return false;
@@ -636,7 +636,7 @@ namespace Jint.Native.Object
                         {
                             if (throwOnError)
                             {
-                                throw new JavaScriptException(Engine.TypeError);
+                                ExceptionHelper.ThrowTypeError(Engine);
                             }
 
                             return false;
@@ -648,7 +648,7 @@ namespace Jint.Native.Object
                             {
                                 if (throwOnError)
                                 {
-                                    throw new JavaScriptException(Engine.TypeError);
+                                    ExceptionHelper.ThrowTypeError(Engine);
                                 }
 
                                 return false;
@@ -666,7 +666,7 @@ namespace Jint.Native.Object
                         {
                             if (throwOnError)
                             {
-                                throw new JavaScriptException(Engine.TypeError);
+                                ExceptionHelper.ThrowTypeError(Engine);
                             }
 
                             return false;
@@ -937,7 +937,8 @@ namespace Jint.Native.Object
                 return callable;
             }
 
-            throw new JavaScriptException(Engine.TypeError, "Argument must be callable");
+            ExceptionHelper.ThrowTypeError(_engine, "Argument must be callable");
+            return null;
         }
 
         public override bool Equals(JsValue obj)

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

@@ -80,7 +80,7 @@ namespace Jint.Native.Object
             var o = TypeConverter.ToObject(Engine, thisObject);
             var toString = o.Get("toString").TryCast<ICallable>(x =>
             {
-                throw new JavaScriptException(Engine.TypeError);
+                ExceptionHelper.ThrowTypeError(Engine);
             });
 
             return toString.Call(o, Arguments.Empty);

+ 3 - 4
Jint/Native/RegExp/RegExpConstructor.cs

@@ -73,7 +73,7 @@ namespace Jint.Native.RegExp
 
             if (!flags.IsUndefined() && !ReferenceEquals(r, null))
             {
-                throw new JavaScriptException(Engine.TypeError);
+                ExceptionHelper.ThrowTypeError(Engine);
             }
 
             if (pattern.IsUndefined())
@@ -98,11 +98,10 @@ namespace Jint.Native.RegExp
             }
             catch (Exception e)
             {
-                throw new JavaScriptException(Engine.SyntaxError, e.Message);
+                ExceptionHelper.ThrowSyntaxError(_engine, e.Message);
             }
 
-            string s;
-            s = p;
+            var s = p;
 
             if (string.IsNullOrEmpty(s))
             {

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

@@ -52,7 +52,7 @@ namespace Jint.Native.RegExp
             var r = TypeConverter.ToObject(Engine, thisObj);
             if (r.Class != "RegExp")
             {
-                throw new JavaScriptException(Engine.TypeError);
+                ExceptionHelper.ThrowTypeError(Engine);
             }
 
             var match = Exec(r, arguments);
@@ -64,7 +64,7 @@ namespace Jint.Native.RegExp
             var R = TypeConverter.ToObject(Engine, thisObj) as RegExpInstance;
             if (ReferenceEquals(R, null))
             {
-                throw new JavaScriptException(Engine.TypeError);
+                ExceptionHelper.ThrowTypeError(Engine);
             }
 
             var s = TypeConverter.ToString(arguments.At(0));

+ 3 - 3
Jint/Native/String/StringPrototype.cs

@@ -65,7 +65,7 @@ namespace Jint.Native.String
             var s = TypeConverter.ToObject(Engine, thisObj) as StringInstance;
             if (ReferenceEquals(s, null))
             {
-                throw new JavaScriptException(Engine.TypeError);
+                ExceptionHelper.ThrowTypeError(Engine);
             }
 
             return s.PrimitiveValue;
@@ -818,7 +818,7 @@ namespace Jint.Native.String
             var s = thisObj.TryCast<StringInstance>();
             if (ReferenceEquals(s, null))
             {
-                throw new JavaScriptException(Engine.TypeError);
+                ExceptionHelper.ThrowTypeError(Engine);
             }
 
             return s.PrimitiveValue;
@@ -894,7 +894,7 @@ namespace Jint.Native.String
             {
                 if (searchString.IsRegExp())
                 {
-                    throw new JavaScriptException(Engine.TypeError);
+                    ExceptionHelper.ThrowTypeError(Engine);
                 }
             }
 

+ 4 - 3
Jint/Native/Symbol/SymbolConstructor.cs

@@ -66,7 +66,7 @@ namespace Jint.Native.Symbol
 
             var value = new JsSymbol(description.AsString());
 
-            if (JsValue.ReturnOnAbruptCompletion(ref descString))
+            if (ReturnOnAbruptCompletion(ref descString))
             {
                 return descString;
             }
@@ -95,7 +95,7 @@ namespace Jint.Native.Symbol
 
             if (!sym.IsSymbol())
             {
-                throw new JavaScriptException(Engine.TypeError);
+                ExceptionHelper.ThrowTypeError(Engine);
             }
 
             JsSymbol symbol;
@@ -109,7 +109,8 @@ namespace Jint.Native.Symbol
 
         public ObjectInstance Construct(JsValue[] arguments)
         {
-            throw new JavaScriptException(Engine.TypeError);
+            ExceptionHelper.ThrowTypeError(Engine);
+            return null;
         }
 
         public SymbolInstance Construct(string description)

+ 3 - 3
Jint/Native/Symbol/SymbolPrototype.cs

@@ -45,7 +45,7 @@ namespace Jint.Native.Symbol
         {
             if (!thisObject.IsSymbol())
             {
-                throw new JavaScriptException(Engine.TypeError);
+                ExceptionHelper.ThrowTypeError(Engine);
             }
 
             return SymbolDescriptiveString((JsSymbol)thisObject);
@@ -56,7 +56,7 @@ namespace Jint.Native.Symbol
             var sym = thisObject.TryCast<SymbolInstance>();
             if (ReferenceEquals(sym, null))
             {
-                throw new JavaScriptException(Engine.TypeError);
+                ExceptionHelper.ThrowTypeError(Engine);
             }
 
             return sym.SymbolData;
@@ -73,7 +73,7 @@ namespace Jint.Native.Symbol
             var o = thisObject.AsInstance<SymbolInstance>();
             if (ReferenceEquals(o, null))
             {
-                throw new JavaScriptException(Engine.TypeError);
+                ExceptionHelper.ThrowTypeError(Engine);
             }
 
             return o.SymbolData;

+ 7 - 9
Jint/Runtime/Descriptors/PropertyDescriptor.cs

@@ -1,5 +1,4 @@
-using System;
-using System.Runtime.CompilerServices;
+using System.Runtime.CompilerServices;
 using Jint.Native;
 using Jint.Native.Object;
 using Jint.Runtime.Descriptors.Specialized;
@@ -18,7 +17,6 @@ namespace Jint.Runtime.Descriptors
             _flags = flags;
         }
         
-        
         protected internal PropertyDescriptor(JsValue value, PropertyFlag flags) : this(flags)
         {
             Value = value;
@@ -201,7 +199,7 @@ namespace Jint.Runtime.Descriptors
         protected virtual JsValue CustomValue
         {
             get => null;
-            set => throw new NotImplementedException();
+            set => ExceptionHelper.ThrowNotImplementedException();
         }
 
         internal PropertyFlag Flags
@@ -215,7 +213,7 @@ namespace Jint.Runtime.Descriptors
             var obj = o.TryCast<ObjectInstance>();
             if (ReferenceEquals(obj, null))
             {
-                throw new JavaScriptException(engine.TypeError);
+                ExceptionHelper.ThrowTypeError(engine);
             }
 
             var getProperty = obj.GetProperty("get");
@@ -226,7 +224,7 @@ namespace Jint.Runtime.Descriptors
             if ((obj.HasProperty("value") || obj.HasProperty("writable")) &&
                 (hasGetProperty || hasSetProperty))
             {
-                throw new JavaScriptException(engine.TypeError);
+                ExceptionHelper.ThrowTypeError(engine);
             }
 
             var desc = hasGetProperty || hasSetProperty
@@ -265,7 +263,7 @@ namespace Jint.Runtime.Descriptors
                 var getter = obj.UnwrapJsValue(getProperty);
                 if (!getter.IsUndefined() && getter.TryCast<ICallable>() == null)
                 {
-                    throw new JavaScriptException(engine.TypeError);
+                    ExceptionHelper.ThrowTypeError(engine);
                 }
 
                 ((GetSetPropertyDescriptor) desc).SetGet(getter);
@@ -276,7 +274,7 @@ namespace Jint.Runtime.Descriptors
                 var setter = obj.UnwrapJsValue(setProperty);
                 if (!setter.IsUndefined() && setter.TryCast<ICallable>() == null)
                 {
-                    throw new JavaScriptException(engine.TypeError);
+                    ExceptionHelper.ThrowTypeError(engine);
                 }
 
                 ((GetSetPropertyDescriptor) desc).SetSet(setter);
@@ -286,7 +284,7 @@ namespace Jint.Runtime.Descriptors
             {
                 if (!ReferenceEquals(desc.Value, null) || desc.WritableSet)
                 {
-                    throw new JavaScriptException(engine.TypeError);
+                    ExceptionHelper.ThrowTypeError(engine);
                 }
             }
 

+ 3 - 3
Jint/Runtime/Descriptors/Specialized/IndexDescriptor.cs

@@ -42,7 +42,7 @@ namespace Jint.Runtime.Descriptors.Specialized
             // throw if no indexer found
             if (_indexer == null)
             {
-                throw new InvalidOperationException("No matching indexer found.");
+                ExceptionHelper.ThrowInvalidOperationException("No matching indexer found.");
             }
 
             Writable = true;
@@ -61,7 +61,7 @@ namespace Jint.Runtime.Descriptors.Specialized
 
                 if (getter == null)
                 {
-                    throw new InvalidOperationException("Indexer has no public getter.");
+                    ExceptionHelper.ThrowInvalidOperationException("Indexer has no public getter.");
                 }
 
                 object[] parameters = {_key};
@@ -89,7 +89,7 @@ namespace Jint.Runtime.Descriptors.Specialized
                 var setter = _indexer.GetSetMethod();
                 if (setter == null)
                 {
-                    throw new InvalidOperationException("Indexer has no public setter.");
+                    ExceptionHelper.ThrowInvalidOperationException("Indexer has no public setter.");
                 }
 
                 object[] parameters = {_key, value?.ToObject()};

+ 2 - 2
Jint/Runtime/Environments/DeclarativeEnvironmentRecord.cs

@@ -68,7 +68,7 @@ namespace Jint.Runtime.Environments
             {
                 if (strict)
                 {
-                    throw new JavaScriptException(_engine.TypeError, "Can't update the value of an immutable binding.");
+                    ExceptionHelper.ThrowTypeError(_engine, "Can't update the value of an immutable binding.");
                 }
             }
         }
@@ -81,7 +81,7 @@ namespace Jint.Runtime.Environments
             {
                 if (strict)
                 {
-                    throw new JavaScriptException(_engine.ReferenceError, "Can't access anm uninitiazed immutable binding.");
+                    ExceptionHelper.ThrowReferenceError(_engine, "Can't access an uninitialized immutable binding.");
                 }
 
                 return Undefined;

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

@@ -48,7 +48,7 @@ namespace Jint.Runtime.Environments
             var desc = _bindingObject.GetProperty(name);
             if (strict && desc == PropertyDescriptor.Undefined)
             {
-                throw new JavaScriptException(_engine.ReferenceError);
+                ExceptionHelper.ThrowReferenceError(_engine);
             }
 
             return UnwrapJsValue(desc);

+ 120 - 0
Jint/Runtime/ExceptionHelper.cs

@@ -0,0 +1,120 @@
+using System;
+using Jint.Runtime.CallStack;
+
+namespace Jint.Runtime
+{
+    internal static class ExceptionHelper
+    {
+        public static void ThrowSyntaxError(Engine engine, string message = null)
+        {
+            throw new JavaScriptException(engine.SyntaxError, message);
+        }
+
+        public static T ThrowArgumentException<T>(string message = null)
+        {
+            ThrowArgumentException(message);
+            return default;
+        }
+
+        public static void ThrowArgumentException(string message = null)
+        {
+            ThrowArgumentException(message, null);
+        }
+
+        public static void ThrowArgumentException(string message, string paramName)
+        {
+            throw new ArgumentException(message, paramName);
+        }
+
+        public static void ThrowReferenceError(Engine engine, string message = null)
+        {
+            throw new JavaScriptException(engine.ReferenceError, message);
+        }
+
+        public static T ThrowTypeError<T>(Engine engine, string message = null, Exception exception = null)
+        {
+            ThrowTypeError(engine, message, exception);
+            return default;
+        }
+
+        public static void ThrowTypeError(Engine engine, string message = null, Exception exception = null)
+        {
+            throw new JavaScriptException(engine.TypeError, message, exception);
+        }
+
+        public static void ThrowRangeError(Engine engine, string message = null)
+        {
+            throw new JavaScriptException(engine.RangeError, message);
+        }
+
+        public static void ThrowUriError(Engine engine)
+        {
+            throw new JavaScriptException(engine.UriError);
+        }
+
+        public static void ThrowNotImplementedException()
+        {
+            throw new NotImplementedException();
+        }
+
+        public static void ThrowArgumentOutOfRangeException(string paramName, string message)
+        {
+            throw new ArgumentOutOfRangeException(paramName, message);
+        }
+
+        public static void ThrowTimeoutException()
+        {
+            throw new TimeoutException();
+        }
+
+        public static void ThrowStatementsCountOverflowException()
+        {
+            throw new StatementsCountOverflowException();
+        }
+
+        public static void ThrowArgumentOutOfRangeException()
+        {
+            throw new ArgumentOutOfRangeException();
+        }
+
+        public static void ThrowNotSupportedException(string message = null)
+        {
+            throw new NotSupportedException(message);
+        }
+
+        public static void ThrowInvalidOperationException(string message = null)
+        {
+            throw new InvalidOperationException(message);
+        }
+
+        public static void ThrowJavaScriptException(string message)
+        {
+            throw new JavaScriptException("TypeError");
+        }
+
+        public static void ThrowRecursionDepthOverflowException(JintCallStack currentStack, string currentExpressionReference)
+        {
+            throw new RecursionDepthOverflowException(currentStack, currentExpressionReference);
+        }
+
+        public static void ThrowArgumentNullException(string paramName)
+        {
+            throw new ArgumentNullException(paramName);
+        }
+
+        public static void ThrowError(Engine engine, string message)
+        {
+            throw new JavaScriptException(engine.Error, message);
+        }
+
+        public static void ThrowPlatformNotSupportedException(string message)
+        {
+            throw new PlatformNotSupportedException(message);
+        }
+
+        public static void ThrowMemoryLimitExceededException(string message)
+        {
+            throw new MemoryLimitExceededException(message);
+        }
+    }
+}

+ 50 - 73
Jint/Runtime/ExpressionIntepreter.cs

@@ -57,18 +57,12 @@ namespace Jint.Runtime
 
             if (lref == null)
             {
-                throw new JavaScriptException(_engine.ReferenceError);
+                ExceptionHelper.ThrowReferenceError(_engine);
             }
 
             if (assignmentExpression.Operator == AssignmentOperator.Assign) // "="
             {
-
-                if(lref.IsStrict()
-                   && lref.GetBase() is EnvironmentRecord
-                   && (lref.GetReferencedName() == "eval" || lref.GetReferencedName() == "arguments"))
-                {
-                    throw new JavaScriptException(_engine.SyntaxError);
-                }
+                lref.AssertValid(_engine);
 
                 _engine.PutValue(lref, rval);
                 _engine.ReferencePool.Return(lref);
@@ -151,8 +145,8 @@ namespace Jint.Runtime
                     break;
 
                 default:
-                    throw new NotImplementedException();
-
+                    ExceptionHelper.ThrowNotImplementedException();
+                    return null;
             }
 
             _engine.PutValue(lref, lval);
@@ -356,7 +350,7 @@ namespace Jint.Runtime
                     var f = right.TryCast<FunctionInstance>();
                     if (ReferenceEquals(f, null))
                     {
-                        throw new JavaScriptException(_engine.TypeError, "instanceof can only be used with a function object");
+                        ExceptionHelper.ThrowTypeError(_engine, "instanceof can only be used with a function object");
                     }
                     value = f.HasInstance(left);
                     break;
@@ -364,14 +358,15 @@ namespace Jint.Runtime
                 case BinaryOperator.In:
                     if (!right.IsObject())
                     {
-                        throw new JavaScriptException(_engine.TypeError, "in can only be used with an object");
+                        ExceptionHelper.ThrowTypeError(_engine, "in can only be used with an object");
                     }
 
                     value = right.AsObject().HasProperty(TypeConverter.ToString(left));
                     break;
 
                 default:
-                    throw new NotImplementedException();
+                    ExceptionHelper.ThrowNotImplementedException();
+                    return null;
             }
 
             return value;
@@ -383,7 +378,6 @@ namespace Jint.Runtime
 
             switch (binaryExpression.Operator)
             {
-
                 case BinaryOperator.LogicalAnd:
                     if (!TypeConverter.ToBoolean(left))
                     {
@@ -401,7 +395,8 @@ namespace Jint.Runtime
                     return _engine.GetValue(EvaluateExpression(binaryExpression.Right), true);
 
                 default:
-                    throw new NotImplementedException();
+                    ExceptionHelper.ThrowNotImplementedException();
+                    return null;
             }
         }
 
@@ -643,7 +638,7 @@ namespace Jint.Runtime
             {
                 case TokenType.BooleanLiteral:
                     // bool is fast enough
-                    return (JsValue) (literal.CachedValue = literal.CachedValue ?? (literal.NumericValue != 0.0 ? JsBoolean.True : JsBoolean.False));
+                    return literal.NumericValue > 0.0 ? JsBoolean.True : JsBoolean.False;
                 
                 case TokenType.NullLiteral:
                     // and so is null
@@ -653,7 +648,7 @@ namespace Jint.Runtime
                     return (JsValue) (literal.CachedValue = literal.CachedValue ?? JsNumber.Create(literal.NumericValue));
                 
                 case TokenType.StringLiteral:
-                    return (JsValue) (literal.CachedValue = literal.CachedValue ?? (literal.CachedValue = JsString.Create((string) literal.Value)));
+                    return (JsValue) (literal.CachedValue = literal.CachedValue ?? JsString.Create((string) literal.Value));
                 
                 case TokenType.RegularExpression:
                     // should not cache
@@ -694,7 +689,7 @@ namespace Jint.Runtime
 
                         if (getter == null)
                         {
-                            throw new JavaScriptException(_engine.SyntaxError);
+                            ExceptionHelper.ThrowSyntaxError(_engine);
                         }
 
                         ScriptFunctionInstance get;
@@ -716,7 +711,7 @@ namespace Jint.Runtime
 
                         if (setter == null)
                         {
-                            throw new JavaScriptException(_engine.SyntaxError);
+                            ExceptionHelper.ThrowSyntaxError(_engine);
                         }
 
                         ScriptFunctionInstance set;
@@ -734,36 +729,37 @@ namespace Jint.Runtime
                         break;
 
                     default:
-                        throw new ArgumentOutOfRangeException();
+                        ExceptionHelper.ThrowArgumentOutOfRangeException();
+                        return null;
                 }
 
                 if (previous != PropertyDescriptor.Undefined)
                 {
                     if (StrictModeScope.IsStrictModeCode && previous.IsDataDescriptor() && propDesc.IsDataDescriptor())
                     {
-                        throw new JavaScriptException(_engine.SyntaxError);
+                        ExceptionHelper.ThrowSyntaxError(_engine);
                     }
 
                     if (previous.IsDataDescriptor() && propDesc.IsAccessorDescriptor())
                     {
-                        throw new JavaScriptException(_engine.SyntaxError);
+                        ExceptionHelper.ThrowSyntaxError(_engine);
                     }
 
                     if (previous.IsAccessorDescriptor() && propDesc.IsDataDescriptor())
                     {
-                        throw new JavaScriptException(_engine.SyntaxError);
+                        ExceptionHelper.ThrowSyntaxError(_engine);
                     }
 
                     if (previous.IsAccessorDescriptor() && propDesc.IsAccessorDescriptor())
                     {
                         if (!ReferenceEquals(propDesc.Set, null) && !ReferenceEquals(previous.Set, null))
                         {
-                            throw new JavaScriptException(_engine.SyntaxError);
+                            ExceptionHelper.ThrowSyntaxError(_engine);
                         }
 
                         if (!ReferenceEquals(propDesc.Get, null) && !ReferenceEquals(previous.Get, null))
                         {
-                            throw new JavaScriptException(_engine.SyntaxError);
+                            ExceptionHelper.ThrowSyntaxError(_engine);
                         }
                     }
                 }
@@ -880,20 +876,20 @@ namespace Jint.Runtime
                 if (recursionDepth > _maxRecursionDepth)
                 {
                     _engine.CallStack.Pop();
-                    throw new RecursionDepthOverflowException(_engine.CallStack, stackItem.ToString());
+                    ExceptionHelper.ThrowRecursionDepthOverflowException(_engine.CallStack, stackItem.ToString());
                 }
             }
 
             if (func.IsUndefined())
             {
-                throw new JavaScriptException(_engine.TypeError, r == null ? "" : string.Format("Object has no method '{0}'", r.GetReferencedName()));
+                ExceptionHelper.ThrowTypeError(_engine, r == null ? "" : $"Object has no method '{r.GetReferencedName()}'");
             }
 
             if (!func.IsObject())
             {
                 if (_referenceResolver == null || !_referenceResolver.TryGetCallable(_engine, callee, out func))
                 {
-                    throw new JavaScriptException(_engine.TypeError,
+                    ExceptionHelper.ThrowTypeError(_engine,
                         r == null ? "" : $"Property '{r.GetReferencedName()}' of object is not a function");
                 }
             }
@@ -901,7 +897,7 @@ namespace Jint.Runtime
             var callable = func.TryCast<ICallable>();
             if (callable == null)
             {
-                throw new JavaScriptException(_engine.TypeError);
+                ExceptionHelper.ThrowTypeError(_engine);
             }
 
             if (r != null)
@@ -922,9 +918,9 @@ namespace Jint.Runtime
             }
 
             // is it a direct call to eval ? http://www.ecma-international.org/ecma-262/5.1/#sec-15.1.2.1.1
-            if (r != null && r.GetReferencedName() == "eval" && callable is EvalFunctionInstance)
+            if (r != null && r.GetReferencedName() == "eval" && callable is EvalFunctionInstance instance)
             {
-                var value = ((EvalFunctionInstance) callable).Call(thisObject, arguments, true);
+                var value = instance.Call(thisObject, arguments, true);
                 _engine.ReferencePool.Return(r);
                 return value;
             }
@@ -966,48 +962,28 @@ namespace Jint.Runtime
         public JsValue EvaluateUpdateExpression(UpdateExpression updateExpression)
         {
             var value = _engine.EvaluateExpression(updateExpression.Argument);
-            Reference r;
-
-            switch (updateExpression.Operator)
-            {
-                case UnaryOperator.Increment:
-                    r = value as Reference;
-                    if (r != null
-                        && r.IsStrict()
-                        && r.GetBase() is EnvironmentRecord
-                        && ("eval" == r.GetReferencedName() || "arguments" == r.GetReferencedName()))
-                    {
-                        throw new JavaScriptException(_engine.SyntaxError);
-                    }
 
-                    var oldValue = TypeConverter.ToNumber(_engine.GetValue(value));
-                    var newValue = oldValue + 1;
-                    _engine.PutValue(r, newValue);
+            var r = (Reference) value;
+            r.AssertValid(_engine);
 
-                    _engine.ReferencePool.Return(r);
-                    return updateExpression.Prefix ? newValue : oldValue;
-
-                case UnaryOperator.Decrement:
-                    r = value as Reference;
-                    if (r != null
-                        && r.IsStrict()
-                        && r.GetBase() is EnvironmentRecord
-                        && ("eval" == r.GetReferencedName() || "arguments" == r.GetReferencedName()))
-                    {
-                        throw new JavaScriptException(_engine.SyntaxError);
-                    }
-
-                    oldValue = TypeConverter.ToNumber(_engine.GetValue(value));
-                    newValue = oldValue - 1;
-
-                    _engine.PutValue(r, newValue);
-                    _engine.ReferencePool.Return(r);
-
-                    return updateExpression.Prefix ? newValue : oldValue;
-                default:
-                    throw new ArgumentException();
+            var oldValue = TypeConverter.ToNumber(_engine.GetValue(value));
+            double newValue = 0;
+            if (updateExpression.Operator == UnaryOperator.Increment)
+            {
+                newValue = oldValue + 1;
+            }
+            else if (updateExpression.Operator == UnaryOperator.Decrement)
+            {
+                newValue = oldValue - 1;
+            }
+            else
+            {
+                ExceptionHelper.ThrowArgumentException();
             }
 
+            _engine.PutValue(r, newValue);
+            _engine.ReferencePool.Return(r);
+            return updateExpression.Prefix ? newValue : oldValue;
         }
 
         public JsValue EvaluateThisExpression(ThisExpression thisExpression)
@@ -1025,7 +1001,7 @@ namespace Jint.Runtime
 
             if (callee == null)
             {
-                throw new JavaScriptException(_engine.TypeError, "The object can't be used as constructor.");
+                ExceptionHelper.ThrowTypeError(_engine, "The object can't be used as constructor.");
             }
 
             // construct the new instance using the Function's constructor method
@@ -1089,7 +1065,7 @@ namespace Jint.Runtime
                     {
                         if (r.IsStrict())
                         {
-                            throw new JavaScriptException(_engine.SyntaxError);
+                            ExceptionHelper.ThrowSyntaxError(_engine);
                         }
 
                         _engine.ReferencePool.Return(r);
@@ -1104,7 +1080,7 @@ namespace Jint.Runtime
                     }
                     if (r.IsStrict())
                     {
-                        throw new JavaScriptException(_engine.SyntaxError);
+                        ExceptionHelper.ThrowSyntaxError(_engine);
                     }
 
                     var bindings = r.GetBase().TryCast<EnvironmentRecord>();
@@ -1151,7 +1127,8 @@ namespace Jint.Runtime
                     return "object";
 
                 default:
-                    throw new ArgumentException();
+                    ExceptionHelper.ThrowArgumentException();
+                    return null;
             }
         }
 

+ 2 - 1
Jint/Runtime/Interop/ClrFunctionInstance.cs

@@ -35,7 +35,8 @@ namespace Jint.Runtime.Interop
             }
             catch (InvalidCastException)
             {
-                throw new JavaScriptException(Engine.TypeError);
+                ExceptionHelper.ThrowTypeError(Engine);
+                return null;
             }
         }
     }

+ 7 - 6
Jint/Runtime/Interop/DefaultTypeConverter.cs

@@ -31,7 +31,7 @@ namespace Jint.Runtime.Interop
                     return null;
                 }
 
-                throw new NotSupportedException(string.Format("Unable to convert null to '{0}'", type.FullName));
+                ExceptionHelper.ThrowNotSupportedException($"Unable to convert null to '{type.FullName}'");
             }
 
             // don't try to convert if value is derived from type
@@ -45,7 +45,7 @@ namespace Jint.Runtime.Interop
                 var integer = System.Convert.ChangeType(value, typeof(int), formatProvider);
                 if (integer == null)
                 {
-                    throw new ArgumentOutOfRangeException();
+                    ExceptionHelper.ThrowArgumentOutOfRangeException();
                 }
 
                 return Enum.ToObject(type, integer);
@@ -181,7 +181,9 @@ namespace Jint.Runtime.Interop
             {
                 var source = value as object[];
                 if (source == null)
-                    throw new ArgumentException(String.Format("Value of object[] type is expected, but actual type is {0}.", value.GetType()));
+                {
+                    ExceptionHelper.ThrowArgumentException($"Value of object[] type is expected, but actual type is {value.GetType()}.");
+                }
 
                 var targetElementType = type.GetElementType();
                 var itemsConverted = new object[source.Length];
@@ -204,10 +206,9 @@ namespace Jint.Runtime.Interop
 
         public virtual bool TryConvert(object value, Type type, IFormatProvider formatProvider, out object converted)
         {
-            bool canConvert;
-            var key = value == null ? String.Format("Null->{0}", type) : String.Format("{0}->{1}", value.GetType(), type);
+            var key = value == null ? $"Null->{type}" : $"{value.GetType()}->{type}";
 
-            if (!_knownConversions.TryGetValue(key, out canConvert))
+            if (!_knownConversions.TryGetValue(key, out var canConvert))
             {
                 lock (_lockObject)
                 {

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

@@ -103,7 +103,7 @@ namespace Jint.Runtime.Interop
 
                 if (handler != null && handler(meaningfulException))
                 {
-                    throw new JavaScriptException(Engine.Error, meaningfulException.Message);
+                    ExceptionHelper.ThrowError(_engine, meaningfulException.Message);
                 }
 
                 throw meaningfulException;         

+ 3 - 2
Jint/Runtime/Interop/MethodInfoFunctionInstance.cs

@@ -87,14 +87,15 @@ namespace Jint.Runtime.Interop
 
                     if (handler != null && handler(meaningfulException))
                     {
-                        throw new JavaScriptException(Engine.Error, meaningfulException.Message);
+                        ExceptionHelper.ThrowError(_engine, meaningfulException.Message);
                     }
 
                     throw meaningfulException;
                 }
             }
 
-            throw new JavaScriptException(Engine.TypeError, "No public methods with the specified arguments were found.");
+            ExceptionHelper.ThrowTypeError(_engine, "No public methods with the specified arguments were found.");
+            return null;
         }
 
         /// <summary>

+ 5 - 4
Jint/Runtime/Interop/NamespaceReference.cs

@@ -27,7 +27,7 @@ namespace Jint.Runtime.Interop
         {
             if (throwOnError)
             {
-                throw new JavaScriptException(Engine.TypeError, "Can't define a property of a NamespaceReference");
+                ExceptionHelper.ThrowTypeError(_engine, "Can't define a property of a NamespaceReference");
             }
 
             return false;
@@ -37,7 +37,7 @@ namespace Jint.Runtime.Interop
         {
             if (throwOnError)
             {
-                throw new JavaScriptException(Engine.TypeError, "Can't delete a property of a NamespaceReference");
+                ExceptionHelper.ThrowTypeError(_engine, "Can't delete a property of a NamespaceReference");
             }
 
             return false;
@@ -54,7 +54,7 @@ namespace Jint.Runtime.Interop
                     || !genericTypeReference.IsObject() 
                     || genericTypeReference.AsObject().Class != "TypeReference")
                 {
-                    throw new JavaScriptException(Engine.TypeError, "Invalid generic type parameter on " + _path + ", if this is not a generic type / method, are you missing a lookup assembly?");
+                    ExceptionHelper.ThrowTypeError(_engine, "Invalid generic type parameter on " + _path + ", if this is not a generic type / method, are you missing a lookup assembly?");
                 }
 
                 genericTypes[i] = arguments.At(i).As<TypeReference>().ReferenceType;
@@ -75,7 +75,8 @@ namespace Jint.Runtime.Interop
             }
             catch (Exception e)
             {
-                throw new JavaScriptException(Engine.TypeError, "Invalid generic type parameter on " + _path + ", if this is not a generic type / method, are you missing a lookup assembly?", e);
+                ExceptionHelper.ThrowTypeError(_engine, "Invalid generic type parameter on " + _path + ", if this is not a generic type / method, are you missing a lookup assembly?", e);
+                return null;
             }
         }
 

+ 2 - 2
Jint/Runtime/Interop/ObjectWrapper.cs

@@ -27,7 +27,7 @@ namespace Jint.Runtime.Interop
             {
                 if (throwOnError)
                 {
-                    throw new JavaScriptException(Engine.TypeError);
+                    ExceptionHelper.ThrowTypeError(Engine);
                 }
 
                 return;
@@ -39,7 +39,7 @@ namespace Jint.Runtime.Interop
             {
                 if (throwOnError)
                 {
-                    throw new JavaScriptException(Engine.TypeError, "Unknown member: " + propertyName);
+                    ExceptionHelper.ThrowTypeError(_engine, "Unknown member: " + propertyName);
                 }
                 else
                 {

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

@@ -92,8 +92,8 @@ namespace Jint.Runtime.Interop
                 }
             }
 
-            throw new JavaScriptException(Engine.TypeError, "No public methods with the specified arguments were found.");
-
+            ExceptionHelper.ThrowTypeError(_engine, "No public methods with the specified arguments were found.");
+            return null;
         }
 
         public override bool HasInstance(JsValue v)
@@ -112,7 +112,7 @@ namespace Jint.Runtime.Interop
         {
             if (throwOnError)
             {
-                throw new JavaScriptException(Engine.TypeError, "Can't define a property of a TypeReference");
+                ExceptionHelper.ThrowTypeError(_engine, "Can't define a property of a TypeReference");
             }
 
             return false;
@@ -122,7 +122,7 @@ namespace Jint.Runtime.Interop
         {
             if (throwOnError)
             {
-                throw new JavaScriptException(Engine.TypeError, "Can't delete a property of a TypeReference");
+                ExceptionHelper.ThrowTypeError(_engine, "Can't delete a property of a TypeReference");
             }
 
             return false;
@@ -134,7 +134,7 @@ namespace Jint.Runtime.Interop
             {
                 if (throwOnError)
                 {
-                    throw new JavaScriptException(Engine.TypeError);
+                    ExceptionHelper.ThrowTypeError(Engine);
                 }
 
                 return;
@@ -146,7 +146,7 @@ namespace Jint.Runtime.Interop
             {
                 if (throwOnError)
                 {
-                    throw new JavaScriptException(Engine.TypeError, "Unknown member: " + propertyName);
+                    ExceptionHelper.ThrowTypeError(_engine, "Unknown member: " + propertyName);
                 }
                 else
                 {

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

@@ -31,7 +31,7 @@
 //            var typeReference = thisObj.As<TypeReference>();
 //            if (typeReference == null)
 //            {
-//                throw new JavaScriptException(Engine.TypeError);
+//                ExceptionHelper.ThrowTypeError(Engine);
 //            }
 
 //            return typeReference.Type.FullName;

+ 2 - 7
Jint/Runtime/RefStack.cs

@@ -22,7 +22,7 @@ namespace Jint.Runtime
         {
             if (_size == 0)
             {
-                ThrowEmptyStackException();
+                ExceptionHelper.ThrowInvalidOperationException("stack is empty");
             }
             return ref _array[_size - 1];
         }
@@ -32,7 +32,7 @@ namespace Jint.Runtime
         {
             if (_size == 0)
             {
-                ThrowEmptyStackException();
+                ExceptionHelper.ThrowInvalidOperationException("stack is empty");
             }
             _size--;
         }
@@ -51,11 +51,6 @@ namespace Jint.Runtime
             _array[_size++] = item;
         }
 
-        private static void ThrowEmptyStackException()
-        {
-            throw new InvalidOperationException("stack is empty");
-        }
-
         public void ReplaceTopLexicalEnvironment(LexicalEnvironment newEnv)
         {
             _array[_size - 1] = _array[_size - 1].UpdateLexicalEnvironment(newEnv);

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

@@ -55,7 +55,13 @@ namespace Jint.Runtime.References
         public bool IsPropertyReference()
         {
             // http://www.ecma-international.org/ecma-262/5.1/#sec-8.7
-            return _baseValue.IsPrimitive() || (_baseValue.IsObject() && !(_baseValue is EnvironmentRecord));
+            if (_baseValue._type != Types.Object && _baseValue._type != Types.None)
+            {
+                // primitive
+                return true;
+            }
+            
+            return _baseValue._type == Types.Object && !(_baseValue is EnvironmentRecord);
         }
 
         internal Reference Reassign(JsValue baseValue, string name, bool strict)
@@ -66,5 +72,13 @@ namespace Jint.Runtime.References
 
             return this;
         }
+
+        internal void AssertValid(Engine engine)
+        {
+            if(_strict && (_name == "eval" || _name == "arguments") && _baseValue is EnvironmentRecord)
+            {
+                ExceptionHelper.ThrowSyntaxError(engine);
+            }
+        }
     }
 }

+ 4 - 9
Jint/Runtime/StatementInterpreter.cs

@@ -1,5 +1,4 @@
-using System;
-using System.Collections.Generic;
+using System.Collections.Generic;
 using Esprima.Ast;
 using Jint.Native;
 using Jint.Runtime.Descriptors;
@@ -518,15 +517,11 @@ namespace Jint.Runtime
                 {
                     if (!(_engine.EvaluateExpression(declaration.Id) is Reference lhs))
                     {
-                        throw new ArgumentException();
+                        ExceptionHelper.ThrowArgumentException();
+                        return new Completion();
                     }
 
-                    if (lhs.IsStrict()
-                        && lhs.GetBase() is EnvironmentRecord
-                        && (lhs.GetReferencedName() == "eval" || lhs.GetReferencedName() == "arguments"))
-                    {
-                        throw new JavaScriptException(_engine.SyntaxError);
-                    }
+                    lhs.AssertValid(_engine);
 
                     var value = _engine.GetValue(_engine.EvaluateExpression(declaration.Init), true);
                     _engine.PutValue(lhs, value);

+ 21 - 28
Jint/Runtime/TypeConverter.cs

@@ -16,15 +16,15 @@ namespace Jint.Runtime
 {
     public enum Types
     {
-        None,
-        Undefined,
-        Null,
-        Boolean,
-        String,
-        Number,
-        Object,
-        Completion,
-        Symbol
+        None = 0,
+        Undefined = 1,
+        Null = 2,
+        Boolean = 3,
+        String = 4,
+        Number = 5,
+        Symbol = 9,
+        Object = 10,
+        Completion = 20,
     }
 
     public class TypeConverter
@@ -55,7 +55,7 @@ namespace Jint.Runtime
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public static JsValue ToPrimitive(JsValue input, Types preferredType = Types.None)
         {
-            if (input._type == Types.Null || input._type == Types.Undefined || input.IsPrimitive())
+            if (input._type > Types.None && input._type < Types.Object) 
             {
                 return input;
             }
@@ -355,7 +355,7 @@ namespace Jint.Runtime
                     {
                         // TODO: throw a TypeError
                         // NB: But it requires an Engine reference
-                        throw new JavaScriptException(new JsString("TypeError"));
+                        ExceptionHelper.ThrowJavaScriptException("TypeError");
                     }
                 }
             }
@@ -408,18 +408,13 @@ namespace Jint.Runtime
 
             if (value.IsUndefined() || value.IsNull())
             {
-                ThrowTypeError(engine);
+                ExceptionHelper.ThrowTypeError(engine);
             }
             
-            ThrowTypeError(engine);
+            ExceptionHelper.ThrowTypeError(engine);
             return null;
         }
 
-        private static void ThrowTypeError(Engine engine)
-        {
-            throw new JavaScriptException(engine.TypeError);
-        }
-
         public static Types GetPrimitiveType(JsValue value)
         {
             if (value.IsObject())
@@ -452,28 +447,26 @@ namespace Jint.Runtime
                 return;
             }
 
-            string referencedName;
-            
+            ThrowTypeError(engine, o, expression, baseReference);
+        }
+
+        private static void ThrowTypeError(Engine engine, JsValue o, MemberExpression expression, object baseReference)
+        {
+            var referencedName = "The value";
             if (baseReference is Reference reference)
             {
                 referencedName = reference.GetReferencedName();
             }
-            else
-            {
-                referencedName = "The value";
-            }
             
             var message = $"{referencedName} is {o}";
-
-            throw new JavaScriptException(engine.TypeError, message)
-                .SetCallstack(engine, expression.Location);
+            throw new JavaScriptException(engine.TypeError, message).SetCallstack(engine, expression.Location);
         }
 
         public static void CheckObjectCoercible(Engine engine, JsValue o)
         {
             if (o.IsUndefined() || o.IsNull())
             {
-                throw new JavaScriptException(engine.TypeError);
+                ExceptionHelper.ThrowTypeError(engine);
             }
         }