Explorar el Código

Implementing JsValue

Sebastien Ros hace 11 años
padre
commit
1227c2992f
Se han modificado 64 ficheros con 1702 adiciones y 1660 borrados
  1. 1 1
      Jint.Repl/Program.cs
  2. 20 20
      Jint/Engine.cs
  3. 2 3
      Jint/Jint.csproj
  4. 8 8
      Jint/Native/Argument/ArgumentsObject.cs
  5. 10 10
      Jint/Native/Array/ArrayConstructor.cs
  6. 15 15
      Jint/Native/Array/ArrayInstance.cs
  7. 157 165
      Jint/Native/Array/ArrayPrototype.cs
  8. 4 6
      Jint/Native/Boolean/BooleanConstructor.cs
  9. 5 6
      Jint/Native/Boolean/BooleanInstance.cs
  10. 7 7
      Jint/Native/Boolean/BooleanPrototype.cs
  11. 24 24
      Jint/Native/Date/DateConstructor.cs
  12. 193 193
      Jint/Native/Date/DatePrototype.cs
  13. 2 2
      Jint/Native/Error/ErrorConstructor.cs
  14. 3 3
      Jint/Native/Error/ErrorPrototype.cs
  15. 13 17
      Jint/Native/Function/BindFunctionInstance.cs
  16. 5 5
      Jint/Native/Function/EvalFunctionInstance.cs
  17. 10 10
      Jint/Native/Function/FunctionConstructor.cs
  18. 4 9
      Jint/Native/Function/FunctionInstance.cs
  19. 24 27
      Jint/Native/Function/FunctionPrototype.cs
  20. 1 1
      Jint/Native/Function/FunctionShim.cs
  21. 8 9
      Jint/Native/Function/ScriptFunctionInstance.cs
  22. 2 3
      Jint/Native/Function/ThrowTypeError.cs
  23. 26 26
      Jint/Native/Global/GlobalObject.cs
  24. 1 1
      Jint/Native/ICallable.cs
  25. 2 2
      Jint/Native/IConstructor.cs
  26. 2 2
      Jint/Native/IPrimitiveInstance.cs
  27. 0 45
      Jint/Native/JsObject.cs
  28. 340 0
      Jint/Native/JsValue.cs
  29. 5 5
      Jint/Native/Json/JsonInstance.cs
  30. 11 10
      Jint/Native/Json/JsonParser.cs
  31. 52 47
      Jint/Native/Json/JsonSerializer.cs
  32. 58 58
      Jint/Native/Math/MathInstance.cs
  33. 0 29
      Jint/Native/Null.cs
  34. 4 4
      Jint/Native/Number/NumberConstructor.cs
  35. 4 4
      Jint/Native/Number/NumberInstance.cs
  36. 19 19
      Jint/Native/Number/NumberPrototype.cs
  37. 92 102
      Jint/Native/Object/ObjectConstructor.cs
  38. 65 65
      Jint/Native/Object/ObjectInstance.cs
  39. 26 28
      Jint/Native/Object/ObjectPrototype.cs
  40. 8 8
      Jint/Native/RegExp/RegExpConstructor.cs
  41. 30 28
      Jint/Native/RegExp/RegExpPrototype.cs
  42. 5 5
      Jint/Native/String/StringConstructor.cs
  43. 9 9
      Jint/Native/String/StringInstance.cs
  44. 95 99
      Jint/Native/String/StringPrototype.cs
  45. 0 29
      Jint/Native/Undefined.cs
  46. 9 4
      Jint/Runtime/Arguments.cs
  47. 5 3
      Jint/Runtime/Completion.cs
  48. 50 117
      Jint/Runtime/Descriptors/PropertyDescriptor.cs
  49. 6 5
      Jint/Runtime/Descriptors/Specialized/ClrAccessDescriptor.cs
  50. 4 3
      Jint/Runtime/Descriptors/Specialized/ClrDataDescriptor.cs
  51. 4 2
      Jint/Runtime/Environments/Binding.cs
  52. 7 7
      Jint/Runtime/Environments/DeclarativeEnvironmentRecord.cs
  53. 11 5
      Jint/Runtime/Environments/EnvironmentRecord.cs
  54. 4 2
      Jint/Runtime/Environments/ExecutionContext.cs
  55. 5 5
      Jint/Runtime/Environments/ObjectEnvironmentRecord.cs
  56. 90 92
      Jint/Runtime/ExpressionIntepreter.cs
  57. 7 6
      Jint/Runtime/Interop/ClrFunctionInstance.cs
  58. 2 3
      Jint/Runtime/Interop/DelegateWrapper.cs
  59. 6 5
      Jint/Runtime/Interop/GetterFunctionInstance.cs
  60. 5 5
      Jint/Runtime/Interop/SetterFunctionInstance.cs
  61. 5 4
      Jint/Runtime/JavaScriptException.cs
  62. 7 15
      Jint/Runtime/References/Reference.cs
  63. 29 31
      Jint/Runtime/StatementInterpreter.cs
  64. 74 177
      Jint/Runtime/TypeConverter.cs

+ 1 - 1
Jint.Repl/Program.cs

@@ -25,7 +25,7 @@ namespace Jint.Repl
                 try
                 {
                     var result = engine.GetValue(engine.Execute(input));
-                    var str = engine.Json.Stringify(engine.Json, Arguments.From(result, Undefined.Instance, "  "));
+                    var str = engine.Json.Stringify(engine.Json, Arguments.From(result, Undefined.Instance, "  ")).AsString();
                     Console.ForegroundColor = ConsoleColor.Magenta;
                     Console.WriteLine("=> {0}", str);
                 }

+ 20 - 20
Jint/Engine.cs

@@ -151,7 +151,7 @@ namespace Jint
 
         public Options Options { get; private set; }
 
-        public ExecutionContext EnterExecutionContext(LexicalEnvironment lexicalEnvironment, LexicalEnvironment variableEnvironment, object thisBinding)
+        public ExecutionContext EnterExecutionContext(LexicalEnvironment lexicalEnvironment, LexicalEnvironment variableEnvironment, JsValue thisBinding)
         {
             var executionContext = new ExecutionContext
                 {
@@ -223,7 +223,7 @@ namespace Jint
                     return _statements.ExecuteForInStatement(statement.As<ForInStatement>());
 
                 case SyntaxNodes.FunctionDeclaration:
-                    return new Completion(Completion.Normal, null, null);
+                    return new Completion(Completion.Normal, Undefined.Instance, null);
                     
                 case SyntaxNodes.IfStatement:
                     return _statements.ExecuteIfStatement(statement.As<IfStatement>());
@@ -325,7 +325,7 @@ namespace Jint
         /// </summary>
         /// <param name="value"></param>
         /// <returns></returns>
-        public object GetValue(object value)
+        public JsValue GetValue(object value)
         {
             var reference = value as Reference;
 
@@ -338,30 +338,30 @@ namespace Jint
                     return GetValue(completion.Value);
                 }
 
-                return value;
+                return (JsValue)value;
             }
 
-            var baseValue = reference.GetBase();
-
             if (reference.IsUnresolvableReference())
             {
                 throw new JavaScriptException(ReferenceError);
             }
 
+            var baseValue = reference.GetBase();
+
             if (reference.IsPropertyReference())
             {
                 if (reference.HasPrimitiveBase() == false)
                 {
-                    var o = TypeConverter.ToObject(this, baseValue);
+                    var o = TypeConverter.ToObject(this, baseValue).AsObject();
                     return o.Get(reference.GetReferencedName());
                 }
                 else
                 {
-                    var o = TypeConverter.ToObject(this, baseValue);
+                    var o = TypeConverter.ToObject(this, baseValue).AsObject();
                     var desc = o.GetProperty(reference.GetReferencedName());
                     if (desc == PropertyDescriptor.Undefined)
                     {
-                        return Undefined.Instance;
+                        return JsValue.Undefined;
                     }
                     
                     if (desc.IsDataDescriptor())
@@ -375,13 +375,13 @@ namespace Jint
                         return Undefined.Instance;
                     }
 
-                    var callable = (ICallable)getter;
+                    var callable = (ICallable)getter.AsObject();
                     return callable.Call(baseValue, Arguments.Empty);
                 }
             }
             else
             {
-                var record = baseValue as EnvironmentRecord;
+                var record = baseValue.As<EnvironmentRecord>();
 
                 if (record == null)
                 {
@@ -397,7 +397,7 @@ namespace Jint
         /// </summary>
         /// <param name="reference"></param>
         /// <param name="value"></param>
-        public void PutValue(Reference reference, object value)
+        public void PutValue(Reference reference, JsValue value)
         {
             if (reference.IsUnresolvableReference())
             {
@@ -413,7 +413,7 @@ namespace Jint
                 var baseValue = reference.GetBase();
                 if (!reference.HasPrimitiveBase())
                 {
-                    ((ObjectInstance)baseValue).Put(reference.GetReferencedName(), value, reference.IsStrict());
+                    baseValue.AsObject().Put(reference.GetReferencedName(), value, reference.IsStrict());
                 }
                 else
                 {
@@ -423,7 +423,7 @@ namespace Jint
             else
             {
                 var baseValue = reference.GetBase();
-                var record = baseValue as EnvironmentRecord;
+                var record = baseValue.As<EnvironmentRecord>();
 
                 if (record == null)
                 {
@@ -441,9 +441,9 @@ namespace Jint
         /// <param name="name"></param>
         /// <param name="value"></param>
         /// <param name="throwOnError"></param>
-        public void PutPrimitiveBase(object b, string name, object value, bool throwOnError)
+        public void PutPrimitiveBase(JsValue b, string name, JsValue value, bool throwOnError)
         {
-            var o = TypeConverter.ToObject(this, b);
+            var o = TypeConverter.ToObject(this, b).AsObject();
             if (!o.CanPut(name))
             {
                 if (throwOnError)
@@ -470,7 +470,7 @@ namespace Jint
 
             if (desc.IsAccessorDescriptor())
             {
-                var setter = (ICallable)desc.Set.Value;
+                var setter = (ICallable)desc.Set.Value.AsObject();
                 setter.Call(b, new[] { value });
             }
             else
@@ -494,7 +494,7 @@ namespace Jint
         }
 
         //  http://www.ecma-international.org/ecma-262/5.1/#sec-10.5
-        public void DeclarationBindingInstantiation(DeclarationBindingType declarationBindingType, IList<FunctionDeclaration> functionDeclarations, IList<VariableDeclaration> variableDeclarations, FunctionInstance functionInstance, object[] arguments)
+        public void DeclarationBindingInstantiation(DeclarationBindingType declarationBindingType, IList<FunctionDeclaration> functionDeclarations, IList<VariableDeclaration> variableDeclarations, FunctionInstance functionInstance, JsValue[] arguments)
         {
             var env = ExecutionContext.VariableEnvironment.Record;
             bool configurableBindings = declarationBindingType == DeclarationBindingType.EvalCode;
@@ -533,7 +533,7 @@ namespace Jint
                     {
                         var go = Global;
                         var existingProp = go.GetProperty(fn);
-                        if (existingProp.Configurable.Value)
+                        if (existingProp.Configurable.Value.AsBoolean())
                         {
                             go.DefineOwnProperty(fn,
                                                  new PropertyDescriptor(
@@ -545,7 +545,7 @@ namespace Jint
                         }
                         else
                         {
-                            if (existingProp.IsAccessorDescriptor() || (!existingProp.Enumerable.Value))
+                            if (existingProp.IsAccessorDescriptor() || (!existingProp.Enumerable.Value.AsBoolean()))
                             {
                                 throw new JavaScriptException(TypeError);
                             }

+ 2 - 3
Jint/Jint.csproj

@@ -51,6 +51,8 @@
     <Compile Include="Native\Boolean\BooleanConstructor.cs" />
     <Compile Include="Native\Boolean\BooleanInstance.cs" />
     <Compile Include="Native\Function\BindFunctionInstance.cs" />
+    <Compile Include="Native\IPrimitiveInstance.cs" />
+    <Compile Include="Native\JsValue.cs" />
     <Compile Include="Native\RegExp\RegExpConstructor.cs" />
     <Compile Include="Native\RegExp\RegExpInstance.cs" />
     <Compile Include="Native\RegExp\RegExpPrototype.cs" />
@@ -71,11 +73,9 @@
     <Compile Include="Native\ICallable.cs" />
     <Compile Include="Native\Function\ScriptFunctionInstance.cs" />
     <Compile Include="Native\IConstructor.cs" />
-    <Compile Include="Native\IPrimitiveType.cs" />
     <Compile Include="Native\Json\JsonInstance.cs" />
     <Compile Include="Native\Json\JsonSerializer.cs" />
     <Compile Include="Native\Math\MathInstance.cs" />
-    <Compile Include="Native\Null.cs" />
     <Compile Include="Native\Number\NumberPrototype.cs" />
     <Compile Include="Native\Number\NumberConstructor.cs" />
     <Compile Include="Native\Number\NumberInstance.cs" />
@@ -85,7 +85,6 @@
     <Compile Include="Native\String\StringPrototype.cs" />
     <Compile Include="Native\String\StringConstructor.cs" />
     <Compile Include="Native\String\StringInstance.cs" />
-    <Compile Include="Native\Undefined.cs" />
     <Compile Include="Options.cs" />
     <Compile Include="Parser\Ast\ArrayExpression.cs" />
     <Compile Include="Parser\Ast\AssignmentExpression.cs" />

+ 8 - 8
Jint/Native/Argument/ArgumentsObject.cs

@@ -21,7 +21,7 @@ namespace Jint.Native.Argument
 
         public bool Strict { get; set; }
 
-        public static ArgumentsInstance CreateArgumentsObject(Engine engine, FunctionInstance func, string[] names, object[] args, EnvironmentRecord env, bool strict)
+        public static ArgumentsInstance CreateArgumentsObject(Engine engine, FunctionInstance func, string[] names, JsValue[] args, EnvironmentRecord env, bool strict)
         {
             var len = args.Length;
             var obj = new ArgumentsInstance(engine);
@@ -34,7 +34,7 @@ namespace Jint.Native.Argument
             var indx = len - 1;
             while (indx >= 0)
             {
-                var indxStr = TypeConverter.ToString(indx);
+                var indxStr = TypeConverter.ToString(indx).AsString();
                 var val = args[indx];
                 obj.FastAddProperty(indxStr, val, true, true, true);
                 if (indx < names.Length)
@@ -43,10 +43,10 @@ namespace Jint.Native.Argument
                     if (!strict && !mappedNamed.Contains(name))
                     {
                         mappedNamed.Add(name);
-                        Func<object, object> g = n => env.GetBindingValue(name, false);
-                        var p = new Action<object, object>((n, o) => env.SetMutableBinding(name, o, true));
+                        Func<JsValue, JsValue> g = n => env.GetBindingValue(name, false);
+                        var p = new Action<JsValue, JsValue>((n, o) => env.SetMutableBinding(name, o, true));
 
-                        map.DefineOwnProperty(indxStr, new ClrAccessDescriptor<object>(engine, g, p) { Configurable = new Field<bool>(true) }, false);
+                        map.DefineOwnProperty(indxStr, new ClrAccessDescriptor(engine, g, p) { Configurable = true }, false);
                     }
                 }
                 indx--;
@@ -98,7 +98,7 @@ namespace Jint.Native.Argument
                 var isMapped = ParameterMap.GetOwnProperty(propertyName);
                 if (isMapped != PropertyDescriptor.Undefined)
                 {
-                    desc.Value = new Field<object>(ParameterMap.Get(propertyName));
+                    desc.Value = ParameterMap.Get(propertyName);
                 }
 
                 return desc;
@@ -129,12 +129,12 @@ namespace Jint.Native.Argument
                     }
                     else
                     {
-                        if (desc.Value.Value != null)
+                        if (desc.Value.HasValue && desc.Value.Value != Undefined.Instance)
                         {
                             map.Put(propertyName, desc.Value.Value, throwOnError);
                         }
 
-                        if (desc.Writable.IsAbsent)
+                        if (!desc.Writable.HasValue)
                         {
                             map.Delete(propertyName, false);
                         }

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

@@ -1,5 +1,4 @@
-using System;
-using Jint.Native.Function;
+using Jint.Native.Function;
 using Jint.Native.Object;
 using Jint.Runtime;
 using Jint.Runtime.Interop;
@@ -33,35 +32,36 @@ namespace Jint.Native.Array
 
         public void Configure()
         {
-            FastAddProperty("isArray", new ClrFunctionInstance<object, object>(Engine, IsArray, 1), true, false, true);
+            FastAddProperty("isArray", new ClrFunctionInstance(Engine, IsArray, 1), true, false, true);
         }
 
-        private object IsArray(object thisObj, object[] arguments)
+        private JsValue IsArray(JsValue thisObj, JsValue[] arguments)
         {
             if (arguments.Length == 0)
             {
                 return false;
             }
 
-            var o = arguments[0] as ObjectInstance;
-            return o != null && o.Class == "Array";
+            var o = arguments.At(0);
+
+            return o.IsObject() && o.AsObject().Class == "Array";
         }
 
-        public override object Call(object thisObject, object[] arguments)
+        public override JsValue Call(JsValue thisObject, JsValue[] arguments)
         {
             return Construct(arguments);
         }
 
-        public ObjectInstance Construct(object[] arguments)
+        public ObjectInstance Construct(JsValue[] arguments)
         {
             var instance = new ArrayInstance(Engine);
             instance.Prototype = PrototypeObject;
             instance.Extensible = true;
 
-            if (arguments.Length == 1 && TypeConverter.GetType(arguments[0]) == Types.Number)
+            if (arguments.Length == 1 && arguments.At(0).IsNumber())
             {
                 var length = TypeConverter.ToUint32(arguments[0]);
-                if (TypeConverter.ToNumber(arguments[0]) != length)
+                if (TypeConverter.ToNumber(arguments[0]).AsNumber() != length)
                 {
                     throw new JavaScriptException(Engine.RangeError);
                 }

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

@@ -25,27 +25,27 @@ namespace Jint.Native.Array
         public override bool DefineOwnProperty(string propertyName, PropertyDescriptor desc, bool throwOnError)
         {
             var oldLenDesc = GetOwnProperty("length");
-            var oldLen = TypeConverter.ToNumber(oldLenDesc.Value.Value);
+            var oldLen = TypeConverter.ToNumber(oldLenDesc.Value.Value).AsNumber();
             if (propertyName == "length")
             {
-                if (desc.Value.IsAbsent)
+                if (!desc.Value.HasValue)
                 {
                     return base.DefineOwnProperty("length", desc, throwOnError);
                 }
 
                 var newLenDesc = new PropertyDescriptor(desc);
                 uint newLen = TypeConverter.ToUint32(desc.Value.Value);
-                if (newLen != TypeConverter.ToNumber(desc.Value.Value))
+                if (newLen != TypeConverter.ToNumber(desc.Value.Value).AsNumber())
                 {
                     throw new JavaScriptException(_engine.RangeError);
                 }
 
-                newLenDesc.Value = new Field<object>(newLen);
+                newLenDesc.Value = newLen;
                 if (newLen >= oldLen)
                 {
                     return base.DefineOwnProperty("length", newLenDesc, throwOnError);
                 }
-                if (!oldLenDesc.Writable.Value)
+                if (!oldLenDesc.Writable.Value.AsBoolean())
                 {
                     if (throwOnError)
                     {
@@ -55,14 +55,14 @@ namespace Jint.Native.Array
                     return false;
                 }
                 bool newWritable;
-                if (newLenDesc.Writable.IsAbsent || newLenDesc.Writable.Value)
+                if (!newLenDesc.Writable.HasValue || newLenDesc.Writable.Value.AsBoolean())
                 {
                     newWritable = true;
                 }
                 else
                 {
                     newWritable = false;
-                    newLenDesc.Writable = new Field<bool>(true);
+                    newLenDesc.Writable = true;
                 }
                 
                 var succeeded = base.DefineOwnProperty("length", newLenDesc, throwOnError);
@@ -85,10 +85,10 @@ namespace Jint.Native.Array
                             var deleteSucceeded = Delete(key, false);
                             if (!deleteSucceeded)
                             {
-                                newLenDesc.Value = new Field<object>(index + 1);
+                                newLenDesc.Value = new JsValue(index + 1);
                                 if (!newWritable)
                                 {
-                                    newLenDesc.Writable = new Field<bool>(false);
+                                    newLenDesc.Writable = JsValue.False;
                                 }
                                 base.DefineOwnProperty("length", newLenDesc, false);
                                 if (throwOnError)
@@ -107,13 +107,13 @@ namespace Jint.Native.Array
                     {
                         // algorithm as per the spec
                         oldLen--;
-                        var deleteSucceeded = Delete(TypeConverter.ToString(oldLen), false);
+                        var deleteSucceeded = Delete(TypeConverter.ToString(oldLen).AsString(), false);
                         if (!deleteSucceeded)
                         {
-                            newLenDesc.Value = new Field<object>(oldLen + 1);
+                            newLenDesc.Value = oldLen + 1;
                             if (!newWritable)
                             {
-                                newLenDesc.Writable = new Field<bool>(false);
+                                newLenDesc.Writable = false;
                             }
                             base.DefineOwnProperty("length", newLenDesc, false);
                             if (throwOnError)
@@ -134,7 +134,7 @@ namespace Jint.Native.Array
             else if (IsArrayIndex(propertyName))
             {
                 var index = TypeConverter.ToUint32(propertyName);
-                if (index >= oldLen && !oldLenDesc.Writable.Value)
+                if (index >= oldLen && !oldLenDesc.Writable.Value.AsBoolean())
                 {
                     if (throwOnError)
                     {
@@ -155,7 +155,7 @@ namespace Jint.Native.Array
                 }
                 if (index >= oldLen)
                 {
-                    oldLenDesc.Value = new Field<object>(index + 1);
+                    oldLenDesc.Value = index + 1;
                     base.DefineOwnProperty("length", oldLenDesc, false);
                 }
                 return true;
@@ -164,7 +164,7 @@ namespace Jint.Native.Array
             return base.DefineOwnProperty(propertyName, desc, throwOnError);
         }
 
-        public static bool IsArrayIndex(object p)
+        public static bool IsArrayIndex(JsValue p)
         {
             return TypeConverter.ToString(TypeConverter.ToUint32(p)) == TypeConverter.ToString(p) && TypeConverter.ToUint32(p) != uint.MaxValue;
         }

+ 157 - 165
Jint/Native/Array/ArrayPrototype.cs

@@ -33,32 +33,32 @@ namespace Jint.Native.Array
 
         public void Configure()
         {
-            FastAddProperty("toString", new ClrFunctionInstance<object, object>(Engine, ToString, 0), true, false, true);
-            FastAddProperty("toLocaleString", new ClrFunctionInstance<object, object>(Engine, ToLocaleString), true, false, true);
-            FastAddProperty("concat", new ClrFunctionInstance<object, object>(Engine, Concat, 1), true, false, true);
-            FastAddProperty("join", new ClrFunctionInstance<object, object>(Engine, Join, 1), true, false, true);
-            FastAddProperty("pop", new ClrFunctionInstance<object, object>(Engine, Pop), true, false, true);
-            FastAddProperty("push", new ClrFunctionInstance<object, object>(Engine, Push, 1), true, false, true);
-            FastAddProperty("reverse", new ClrFunctionInstance<object, object>(Engine, Reverse), true, false, true);
-            FastAddProperty("shift", new ClrFunctionInstance<object, object>(Engine, Shift), true, false, true);
-            FastAddProperty("slice", new ClrFunctionInstance<object, object>(Engine, Slice, 2), true, false, true);
-            FastAddProperty("sort", new ClrFunctionInstance<object, ObjectInstance>(Engine, Sort, 1), true, false, true);
-            FastAddProperty("splice", new ClrFunctionInstance<object, ObjectInstance>(Engine, Splice, 2), true, false, true);
-            FastAddProperty("unshift", new ClrFunctionInstance<object, uint>(Engine, Unshift, 1), true, false, true);
-            FastAddProperty("indexOf", new ClrFunctionInstance<object, double>(Engine, IndexOf, 1), true, false, true);
-            FastAddProperty("lastIndexOf", new ClrFunctionInstance<object, double>(Engine, LastIndexOf, 1), true, false, true);
-            FastAddProperty("every", new ClrFunctionInstance<object, bool>(Engine, Every, 1), true, false, true);
-            FastAddProperty("some", new ClrFunctionInstance<object, bool>(Engine, Some, 1), true, false, true);
-            FastAddProperty("forEach", new ClrFunctionInstance<object, object>(Engine, ForEach, 1), true, false, true);
-            FastAddProperty("map", new ClrFunctionInstance<object, ArrayInstance>(Engine, Map, 1), true, false, true);
-            FastAddProperty("filter", new ClrFunctionInstance<object, ArrayInstance>(Engine, Filter, 1), true, false, true);
-            FastAddProperty("reduce", new ClrFunctionInstance<object, object>(Engine, Reduce, 1), true, false, true);
-            FastAddProperty("reduceRight", new ClrFunctionInstance<object, object>(Engine, ReduceRight, 1), true, false, true);
+            FastAddProperty("toString", new ClrFunctionInstance(Engine, ToString, 0), true, false, true);
+            FastAddProperty("toLocaleString", new ClrFunctionInstance(Engine, ToLocaleString), true, false, true);
+            FastAddProperty("concat", new ClrFunctionInstance(Engine, Concat, 1), true, false, true);
+            FastAddProperty("join", new ClrFunctionInstance(Engine, Join, 1), true, false, true);
+            FastAddProperty("pop", new ClrFunctionInstance(Engine, Pop), true, false, true);
+            FastAddProperty("push", new ClrFunctionInstance(Engine, Push, 1), true, false, true);
+            FastAddProperty("reverse", new ClrFunctionInstance(Engine, Reverse), true, false, true);
+            FastAddProperty("shift", new ClrFunctionInstance(Engine, Shift), true, false, true);
+            FastAddProperty("slice", new ClrFunctionInstance(Engine, Slice, 2), true, false, true);
+            FastAddProperty("sort", new ClrFunctionInstance(Engine, Sort, 1), true, false, true);
+            FastAddProperty("splice", new ClrFunctionInstance(Engine, Splice, 2), true, false, true);
+            FastAddProperty("unshift", new ClrFunctionInstance(Engine, Unshift, 1), true, false, true);
+            FastAddProperty("indexOf", new ClrFunctionInstance(Engine, IndexOf, 1), true, false, true);
+            FastAddProperty("lastIndexOf", new ClrFunctionInstance(Engine, LastIndexOf, 1), true, false, true);
+            FastAddProperty("every", new ClrFunctionInstance(Engine, Every, 1), true, false, true);
+            FastAddProperty("some", new ClrFunctionInstance(Engine, Some, 1), true, false, true);
+            FastAddProperty("forEach", new ClrFunctionInstance(Engine, ForEach, 1), true, false, true);
+            FastAddProperty("map", new ClrFunctionInstance(Engine, Map, 1), true, false, true);
+            FastAddProperty("filter", new ClrFunctionInstance(Engine, Filter, 1), true, false, true);
+            FastAddProperty("reduce", new ClrFunctionInstance(Engine, Reduce, 1), true, false, true);
+            FastAddProperty("reduceRight", new ClrFunctionInstance(Engine, ReduceRight, 1), true, false, true);
         }
 
-        private double LastIndexOf(object thisObj, object[] arguments)
+        private JsValue LastIndexOf(JsValue thisObj, JsValue[] arguments)
         {
-            var o = TypeConverter.ToObject(Engine, thisObj);
+            var o = TypeConverter.ToObject(Engine, thisObj).AsObject();
             var lenValue = o.Get("length");
             var len = TypeConverter.ToUint32(lenValue);
             if (len == 0)
@@ -66,7 +66,7 @@ namespace Jint.Native.Array
                 return -1;
             }
 
-            var n = arguments.Length > 1 ? TypeConverter.ToInteger(arguments[1]) : len - 1;
+            var n = arguments.Length > 1 ? TypeConverter.ToInteger(arguments[1]).AsNumber() : len - 1;
             double k;
             if (n >= 0)
             {
@@ -76,10 +76,10 @@ namespace Jint.Native.Array
             {
                 k = len - System.Math.Abs(n);
             }
-            var searchElement = arguments.Length > 0 ? arguments[0] : Undefined.Instance;
+            var searchElement = arguments.At(0);
             for (; k >= 0; k--)
             {
-                var kString = TypeConverter.ToString(k);
+                var kString = TypeConverter.ToString(k).AsString();
                 var kPresent = o.HasProperty(kString);
                 if (kPresent)
                 {
@@ -94,20 +94,19 @@ namespace Jint.Native.Array
             return -1;
         }
 
-        private object Reduce(object thisObj, object[] arguments)
+        private JsValue Reduce(JsValue thisObj, JsValue[] arguments)
         {
-            var callbackfn = arguments.Length > 0 ? arguments[0] : Undefined.Instance;
-            var initialValue = arguments.Length > 1 ? arguments[1] : Undefined.Instance;
+            var callbackfn = arguments.At(0);
+            var initialValue = arguments.At(1);
 
-            var o = TypeConverter.ToObject(Engine, thisObj);
+            var o = TypeConverter.ToObject(Engine, thisObj).AsObject();
             var lenValue = o.Get("length");
             var len = TypeConverter.ToUint32(lenValue);
 
-            var callable = callbackfn as ICallable;
-            if (callable == null)
+            var callable = callbackfn.TryCast<ICallable>(x =>
             {
                 throw new JavaScriptException(Engine.TypeError, "Argument must be callable");
-            }
+            });
 
             if (len == 0 && arguments.Length < 2)
             {
@@ -115,7 +114,7 @@ namespace Jint.Native.Array
             }
 
             var k = 0;
-            object accumulator = Undefined.Instance;
+            JsValue accumulator = Undefined.Instance;
             if (arguments.Length > 1)
             {
                 accumulator = initialValue;
@@ -154,20 +153,20 @@ namespace Jint.Native.Array
             return accumulator;
         }
 
-        private ArrayInstance Filter(object thisObj, object[] arguments)
+        private JsValue Filter(JsValue thisObj, JsValue[] arguments)
         {
-            var callbackfn = arguments.Length > 0 ? arguments[0] : Undefined.Instance;
-            var thisArg = arguments.Length > 1 ? arguments[1] : Undefined.Instance;
+            var callbackfn = arguments.At(0);
+            var thisArg = arguments.At(1);
 
-            var o = TypeConverter.ToObject(Engine, thisObj);
+            var o = TypeConverter.ToObject(Engine, thisObj).AsObject();
             var lenValue = o.Get("length");
             var len = TypeConverter.ToUint32(lenValue);
 
-            var callable = callbackfn as ICallable;
-            if (callable == null)
+            var callable = callbackfn.TryCast<ICallable>(x =>
             {
-                throw new JavaScriptException(Engine.TypeError, "Argument must be callable");
-            }
+                throw new JavaScriptException(Engine.TypeError,
+                    "Argument must be callable");
+            });
 
             var a = (ArrayInstance)Engine.Array.Construct(Arguments.Empty);
 
@@ -180,7 +179,7 @@ namespace Jint.Native.Array
                 {
                     var kvalue = o.Get(pk);
                     var selected = callable.Call(thisArg, new [] { kvalue, k, o });
-                    if (TypeConverter.ToBoolean(selected))
+                    if (TypeConverter.ToBoolean(selected).AsBoolean())
                     {
                         a.DefineOwnProperty(to.ToString(), new PropertyDescriptor(kvalue, true, true, true), false);
                         to++;
@@ -191,22 +190,21 @@ namespace Jint.Native.Array
             return a;
         }
 
-        private ArrayInstance Map(object thisObj, object[] arguments)
+        private JsValue Map(JsValue thisObj, JsValue[] arguments)
         {
-            var callbackfn = arguments.Length > 0 ? arguments[0] : Undefined.Instance;
-            var thisArg = arguments.Length > 1 ? arguments[1] : Undefined.Instance;
+            var callbackfn = arguments.At(0);
+            var thisArg = arguments.At(1);
 
-            var o = TypeConverter.ToObject(Engine, thisObj);
+            var o = TypeConverter.ToObject(Engine, thisObj).AsObject();
             var lenValue = o.Get("length");
             var len = TypeConverter.ToUint32(lenValue);
 
-            var callable = callbackfn as ICallable;
-            if (callable == null)
+            var callable = callbackfn.TryCast<ICallable>(x =>
             {
                 throw new JavaScriptException(Engine.TypeError, "Argument must be callable");
-            }
+            });
 
-            var a = (ArrayInstance)Engine.Array.Construct(new object[] {len});
+            var a = Engine.Array.Construct(new JsValue[] {len});
 
             for (var k = 0; k < len; k++)
             {
@@ -223,20 +221,19 @@ namespace Jint.Native.Array
             return a;
         }
 
-        private object ForEach(object thisObj, object[] arguments)
+        private JsValue ForEach(JsValue thisObj, JsValue[] arguments)
         {
-            var callbackfn = arguments.Length > 0 ? arguments[0] : Undefined.Instance;
-            var thisArg = arguments.Length > 1 ? arguments[1] : Undefined.Instance;
+            var callbackfn = arguments.At(0);
+            var thisArg = arguments.At(1);
 
-            var o = TypeConverter.ToObject(Engine, thisObj);
+            var o = TypeConverter.ToObject(Engine, thisObj).AsObject();
             var lenValue = o.Get("length");
             var len = TypeConverter.ToUint32(lenValue);
 
-            var callable = callbackfn as ICallable;
-            if (callable == null)
+            var callable = callbackfn.TryCast<ICallable>(x =>
             {
                 throw new JavaScriptException(Engine.TypeError, "Argument must be callable");
-            }
+            });
 
             for (var k = 0; k < len; k++)
             {
@@ -252,20 +249,19 @@ namespace Jint.Native.Array
             return Undefined.Instance;
         }
 
-        private bool Some(object thisObj, object[] arguments)
+        private JsValue Some(JsValue thisObj, JsValue[] arguments)
         {
-            var callbackfn = arguments.Length > 0 ? arguments[0] : Undefined.Instance;
-            var thisArg = arguments.Length > 1 ? arguments[1] : Undefined.Instance;
+            var callbackfn = arguments.At(0);
+            var thisArg = arguments.At(1);
 
-            var o = TypeConverter.ToObject(Engine, thisObj);
+            var o = TypeConverter.ToObject(Engine, thisObj).AsObject();
             var lenValue = o.Get("length");
             var len = TypeConverter.ToUint32(lenValue);
 
-            var callable = callbackfn as ICallable;
-            if (callable == null)
+            var callable = callbackfn.TryCast<ICallable>(x =>
             {
                 throw new JavaScriptException(Engine.TypeError, "Argument must be callable");
-            }
+            });
 
             for (var k = 0; k < len; k++)
             {
@@ -275,7 +271,7 @@ namespace Jint.Native.Array
                 {
                     var kvalue = o.Get(pk);
                     var testResult = callable.Call(thisArg, new [] { kvalue, k, o });
-                    if (TypeConverter.ToBoolean(testResult))
+                    if (TypeConverter.ToBoolean(testResult).AsBoolean())
                     {
                         return true;
                     }
@@ -285,20 +281,19 @@ namespace Jint.Native.Array
             return false;
         }
 
-        private bool Every(object thisObj, object[] arguments)
+        private JsValue Every(JsValue thisObj, JsValue[] arguments)
         {
-            var callbackfn = arguments.Length > 0 ? arguments[0] : Undefined.Instance;
-            var thisArg = arguments.Length > 1 ? arguments[1] : Undefined.Instance;
+            var callbackfn = arguments.At(0);
+            var thisArg = arguments.At(1);
 
-            var o = TypeConverter.ToObject(Engine, thisObj);
+            var o = TypeConverter.ToObject(Engine, thisObj).AsObject();
             var lenValue = o.Get("length");
             var len = TypeConverter.ToUint32(lenValue);
 
-            var callable = callbackfn as ICallable;
-            if (callable == null)
+            var callable = callbackfn.TryCast<ICallable>(x =>
             {
                 throw new JavaScriptException(Engine.TypeError, "Argument must be callable");
-            }
+            });
 
             for (var k = 0; k < len; k++)
             {
@@ -310,17 +305,17 @@ namespace Jint.Native.Array
                     var testResult = callable.Call(thisArg, new [] { kvalue, k, o });
                     if (false == TypeConverter.ToBoolean(testResult))
                     {
-                        return false;
+                        return JsValue.False;
                     }
                 }
             }
 
-            return true;
+            return JsValue.True;
         }
 
-        private double IndexOf(object thisObj, object[] arguments)
+        private JsValue IndexOf(JsValue thisObj, JsValue[] arguments)
         {
-            var o = TypeConverter.ToObject(Engine, thisObj);
+            var o = TypeConverter.ToObject(Engine, thisObj).AsObject();
             var lenValue = o.Get("length");
             var len = TypeConverter.ToUint32(lenValue);
             if (len == 0)
@@ -328,7 +323,7 @@ namespace Jint.Native.Array
                 return -1;
             }
 
-            var n = arguments.Length > 1 ? TypeConverter.ToInteger(arguments[1]) : 0;
+            var n = arguments.Length > 1 ? TypeConverter.ToInteger(arguments[1]).AsNumber() : 0;
             if (n >= len)
             {
                 return -1;
@@ -346,10 +341,10 @@ namespace Jint.Native.Array
                     k = 0;
                 }
             }
-            var searchElement = arguments.Length > 0 ? arguments[0] : Undefined.Instance;
+            var searchElement = arguments.At(0);
             for (; k < len; k++)
             {
-                var kString = TypeConverter.ToString(k);
+                var kString = TypeConverter.ToString(k).AsString();
                 var kPresent = o.HasProperty(kString);
                 if (kPresent)
                 {
@@ -364,16 +359,16 @@ namespace Jint.Native.Array
             return -1;
         }
 
-        private ObjectInstance Splice(object thisObj, object[] arguments)
+        private JsValue Splice(JsValue thisObj, JsValue[] arguments)
         {
-            var start = arguments.Length > 0 ? arguments[0] : Undefined.Instance;
-            var deleteCount = arguments.Length > 1 ? arguments[1] : Undefined.Instance;
+            var start = arguments.At(0);
+            var deleteCount = arguments.At(1);
 
-            var o = TypeConverter.ToObject(Engine, thisObj);
+            var o = TypeConverter.ToObject(Engine, thisObj).AsObject();
             var a = Engine.Array.Construct(Arguments.Empty);
             var lenVal = o.Get("length");
             var len = TypeConverter.ToUint32(lenVal);
-            var relativeStart = TypeConverter.ToInteger(start);
+            var relativeStart = TypeConverter.ToInteger(start).AsNumber();
 
             uint actualStart;
             if (relativeStart < 0)
@@ -385,7 +380,7 @@ namespace Jint.Native.Array
                 actualStart = (uint)System.Math.Min(relativeStart, len);
             }
 
-            var actualDeleteCount = System.Math.Min(System.Math.Max(TypeConverter.ToInteger(deleteCount), 0), len - actualStart);
+            var actualDeleteCount = System.Math.Min(System.Math.Max(TypeConverter.ToInteger(deleteCount).AsNumber(), 0), len - actualStart);
             for (var k = 0; k < actualDeleteCount; k++)
             {
                 var from = (actualStart + k).ToString();
@@ -449,9 +444,9 @@ namespace Jint.Native.Array
             return a;
         }
 
-        private uint Unshift(object thisObj, object[] arguments)
+        private JsValue Unshift(JsValue thisObj, JsValue[] arguments)
         {
-            var o = TypeConverter.ToObject(Engine, thisObj);
+            var o = TypeConverter.ToObject(Engine, thisObj).AsObject();
             var lenVal = o.Get("length");
             var len = TypeConverter.ToUint32(lenVal);
             var argCount = (uint)arguments.Length;
@@ -478,15 +473,15 @@ namespace Jint.Native.Array
             return len + argCount;
         }
 
-        private ObjectInstance Sort(object thisObj, object[] arguments)
+        private JsValue Sort(JsValue thisObj, JsValue[] arguments)
         {
-            var obj = thisObj as ObjectInstance;
-
-            if(obj == null)
+            if (!thisObj.IsObject())
             {
                 throw new JavaScriptException(Engine.TypeError, "Array.prorotype.sort can only be applied on objects");  
             }
 
+            var obj = thisObj.AsObject();
+
             var len = obj.Get("length");
             var lenVal = TypeConverter.ToInt32(len);
             if (lenVal <= 1)
@@ -494,16 +489,17 @@ namespace Jint.Native.Array
                 return obj;
             }
 
-            var compareArg = arguments.Length > 0 ? arguments[0] : Undefined.Instance;
-
-            if (compareArg != Undefined.Instance && !(compareArg is ICallable))
+            var compareArg = arguments.At(0);
+            ICallable compareFn = null;
+            if (compareArg != Undefined.Instance)
             {
-                throw new JavaScriptException(Engine.TypeError, "The sort argument must be a function");
+                compareFn = compareArg.TryCast<ICallable>(x =>
+                {
+                    throw new JavaScriptException(Engine.TypeError, "The sort argument must be a function");
+                });
             }
 
-            var compareFn = compareArg as ICallable;
-
-            Comparison<object> comparer = (x, y) =>
+            Comparison<JsValue> comparer = (x, y) =>
                 {
                     if (x == Undefined.Instance && y == Undefined.Instance)
                     {
@@ -529,7 +525,7 @@ namespace Jint.Native.Array
                     var xString = TypeConverter.ToString(x);
                     var yString = TypeConverter.ToString(y);
 
-                    var r = System.String.CompareOrdinal(xString, yString);
+                    var r = System.String.CompareOrdinal(xString.AsString(), yString.AsString());
                     return r;
                 };
 
@@ -553,17 +549,17 @@ namespace Jint.Native.Array
             return obj;
         }
 
-        private object Slice(object thisObj, object[] arguments)
+        private JsValue Slice(JsValue thisObj, JsValue[] arguments)
         {
-            var start = arguments.Length > 0 ? arguments[0] : Undefined.Instance;
-            var end = arguments.Length > 1 ? arguments[1] : Undefined.Instance;
+            var start = arguments.At(0);
+            var end = arguments.At(1);
 
-            var o = TypeConverter.ToObject(Engine, thisObj);
+            var o = TypeConverter.ToObject(Engine, thisObj).AsObject();
             var a = Engine.Array.Construct(Arguments.Empty);
             var lenVal = o.Get("length");
             var len = TypeConverter.ToUint32(lenVal);
 
-            var relativeStart = TypeConverter.ToInteger(start);
+            var relativeStart = TypeConverter.ToInteger(start).AsNumber();
             uint k;
             if (relativeStart < 0)
             {
@@ -571,7 +567,7 @@ namespace Jint.Native.Array
             }
             else
             {
-                k = (uint)System.Math.Min(TypeConverter.ToInteger(start), len);
+                k = (uint)System.Math.Min(TypeConverter.ToInteger(start).AsNumber(), len);
             }
 
             uint final;
@@ -581,26 +577,26 @@ namespace Jint.Native.Array
             }
             else
             {
-                double relativeEnd = TypeConverter.ToInteger(end);
+                double relativeEnd = TypeConverter.ToInteger(end).AsNumber();
                 if (relativeEnd < 0)
                 {
                     final = (uint)System.Math.Max(len + relativeEnd, 0);
                 }
                 else
                 {
-                    final = (uint)System.Math.Min(TypeConverter.ToInteger(relativeEnd), len);
+                    final = (uint)System.Math.Min(TypeConverter.ToInteger(relativeEnd).AsNumber(), len);
                 }
             }
 
             var n = 0;
             for (; k < final; k++)
             {
-                var pk = TypeConverter.ToString(k);
+                var pk = TypeConverter.ToString(k).AsString();
                 var kPresent = o.HasProperty(pk);
                 if (kPresent)
                 {
                     var kValue = o.Get(pk);
-                    a.DefineOwnProperty(TypeConverter.ToString(n),
+                    a.DefineOwnProperty(TypeConverter.ToString(n).AsString(),
                                         new PropertyDescriptor(kValue, true, true, true), false);
                 }
                 n++;
@@ -609,9 +605,9 @@ namespace Jint.Native.Array
             return a;
         }
 
-        private object Shift(object thisObj, object[] arg2)
+        private JsValue Shift(JsValue thisObj, JsValue[] arg2)
         {
-            var o = TypeConverter.ToObject(Engine, thisObj);
+            var o = TypeConverter.ToObject(Engine, thisObj).AsObject();
             var lenVal = o.Get("length");
             var len = TypeConverter.ToUint32(lenVal);
             if (len == 0)
@@ -622,8 +618,8 @@ namespace Jint.Native.Array
             var first = o.Get("0");
             for (var k = 1; k < len; k++)
             {
-                var from = TypeConverter.ToString(k);
-                var to = TypeConverter.ToString(k - 1);
+                var from = TypeConverter.ToString(k).AsString();
+                var to = TypeConverter.ToString(k - 1).AsString();
                 var fromPresent = o.HasProperty(from);
                 if (fromPresent)
                 {
@@ -635,15 +631,15 @@ namespace Jint.Native.Array
                     o.Delete(to, true);
                 }
             }
-            o.Delete(TypeConverter.ToString(len - 1), true);
+            o.Delete(TypeConverter.ToString(len - 1).AsString(), true);
             o.Put("length", len-1, true);
 
             return first;
         }
 
-        private object Reverse(object thisObj, object[] arguments)
+        private JsValue Reverse(JsValue thisObj, JsValue[] arguments)
         {
-            var o = TypeConverter.ToObject(Engine, thisObj);
+            var o = TypeConverter.ToObject(Engine, thisObj).AsObject();
             var lenVal = o.Get("length");
             var len = TypeConverter.ToUint32(lenVal);
             var middle = (uint)System.Math.Floor(len/2);
@@ -651,8 +647,8 @@ namespace Jint.Native.Array
             while (lower != middle)
             {
                 var upper = len - lower - 1;
-                var upperP = TypeConverter.ToString(upper);
-                var lowerP = TypeConverter.ToString(lower);
+                var upperP = TypeConverter.ToString(upper).AsString();
+                var lowerP = TypeConverter.ToString(lower).AsString();
                 var lowerValue = o.Get(lowerP);
                 var upperValue = o.Get(upperP);
                 var lowerExists = o.HasProperty(lowerP);
@@ -679,10 +675,10 @@ namespace Jint.Native.Array
             return o;
         }
 
-        private object Join(object thisObj, object[] arguments)
+        private JsValue Join(JsValue thisObj, JsValue[] arguments)
         {
-            var separator = arguments.Length > 0 ? arguments[0] : Undefined.Instance;
-            var o = TypeConverter.ToObject(Engine, thisObj);
+            var separator = arguments.At(0);
+            var o = TypeConverter.ToObject(Engine, thisObj).AsObject();
             var lenVal = o.Get("length");
             var len = TypeConverter.ToUint32(lenVal);
             if (separator == Undefined.Instance)
@@ -700,22 +696,22 @@ namespace Jint.Native.Array
             var element0 = o.Get("0");
             string r = element0 == Undefined.Instance || element0 == Null.Instance
                                   ? ""
-                                  : TypeConverter.ToString(element0);
+                                  : TypeConverter.ToString(element0).AsString();
             for (var k = 1; k < len; k++)
             {
                 var s = r + sep;
                 var element = o.Get(k.ToString());
                 string next = element == Undefined.Instance || element == Null.Instance
                                   ? ""
-                                  : TypeConverter.ToString(element);
+                                  : TypeConverter.ToString(element).AsString();
                 r = s + next;
             }
             return r;
         }
 
-        private object ToLocaleString(object thisObj, object[] arguments)
+        private JsValue ToLocaleString(JsValue thisObj, JsValue[] arguments)
         {
-            var array = TypeConverter.ToObject(Engine, thisObj);
+            var array = TypeConverter.ToObject(Engine, thisObj).AsObject();
             var arrayLen = array.Get("length");
             var len = TypeConverter.ToUint32(arrayLen);
             const string separator = ",";
@@ -723,7 +719,7 @@ namespace Jint.Native.Array
             {
                 return "";
             }
-            object r;
+            JsValue r;
             var firstElement = array.Get("0");
             if (firstElement == Null.Instance || firstElement == Undefined.Instance)
             {
@@ -731,12 +727,12 @@ namespace Jint.Native.Array
             }
             else
             {
-                var elementObj = TypeConverter.ToObject(Engine, firstElement);
-                var func = elementObj.Get("toLocaleString") as ICallable;
-                if (func == null)
+                var elementObj = TypeConverter.ToObject(Engine, firstElement).AsObject();
+                var func = elementObj.Get("toLocaleString").TryCast<ICallable>(x =>
                 {
                     throw new JavaScriptException(Engine.TypeError);
-                }
+                });
+
                 r = func.Call(elementObj, Arguments.Empty);
             }
             for (var k = 1; k < len; k++)
@@ -749,12 +745,11 @@ namespace Jint.Native.Array
                 }
                 else
                 {
-                    var elementObj = TypeConverter.ToObject(Engine, nextElement);
-                    var func = elementObj.Get("toLocaleString") as ICallable;
-                    if (func == null)
+                    var elementObj = TypeConverter.ToObject(Engine, nextElement).AsObject();
+                    var func = elementObj.Get("toLocaleString").TryCast<ICallable>(x =>
                     {
                         throw new JavaScriptException(Engine.TypeError);
-                    }
+                    });
                     r = func.Call(elementObj, Arguments.Empty);
                 }
                 r = s + r;
@@ -764,17 +759,17 @@ namespace Jint.Native.Array
 
         }
 
-        private object Concat(object thisObj, object[] arguments)
+        private JsValue Concat(JsValue thisObj, JsValue[] arguments)
         {
             var o = TypeConverter.ToObject(Engine, thisObj);
             var a = Engine.Array.Construct(Arguments.Empty);
             var n = 0;
-            var items = new List<object> {o};
+            var items = new List<JsValue> {o};
             items.AddRange(arguments);
 
             foreach (var e in items)
             {
-                var eArray = e as ArrayInstance;
+                var eArray = e.TryCast<ArrayInstance>();
                 if (eArray != null)
                 {
                     var len =  TypeConverter.ToUint32(eArray.Get("length"));
@@ -785,14 +780,14 @@ namespace Jint.Native.Array
                         if (exists)
                         {
                             var subElement = eArray.Get(p);
-                            a.DefineOwnProperty(TypeConverter.ToString(n), new PropertyDescriptor(subElement, true, true, true), false);
+                            a.DefineOwnProperty(TypeConverter.ToString(n).AsString(), new PropertyDescriptor(subElement, true, true, true), false);
                         }
                         n++;
                     }
                 }
                 else
                 {
-                    a.DefineOwnProperty(TypeConverter.ToString(n), new PropertyDescriptor(e, true, true, true ), false);
+                    a.DefineOwnProperty(TypeConverter.ToString(n).AsString(), new PropertyDescriptor(e, true, true, true ), false);
                     n++;
                 }
             }
@@ -804,37 +799,34 @@ namespace Jint.Native.Array
             return a;
         }
 
-        private object ToString(object thisObj, object[] arguments)
+        private JsValue ToString(JsValue thisObj, JsValue[] arguments)
         {
-            var array = TypeConverter.ToObject(Engine, thisObj);
-            var func = array.Get("join") as ICallable;
-            if (func == null)
+            var array = TypeConverter.ToObject(Engine, thisObj).AsObject();
+            ICallable func;
+            func = array.Get("join").TryCast<ICallable>(x =>
             {
-                func = Engine.Object.PrototypeObject.Get("toString") as ICallable;
-                
-                if (func == null)
+                func = Engine.Object.PrototypeObject.Get("toString").TryCast<ICallable>(y =>
                 {
                     throw new ArgumentException();
-                }
-            }
+                });
+            });
 
             return func.Call(array, Arguments.Empty);
         }
 
-        private object ReduceRight(object thisObj, object[] arguments)
+        private JsValue ReduceRight(JsValue thisObj, JsValue[] arguments)
         {
             var callbackfn = arguments.At(0);
             var initialValue = arguments.At(1);
 
-            var o = TypeConverter.ToObject(Engine, thisObj);
+            var o = TypeConverter.ToObject(Engine, thisObj).AsObject();
             var lenValue = o.Get("length");
             var len = TypeConverter.ToUint32(lenValue);
 
-            var callable = callbackfn as ICallable;
-            if (callable == null)
+            var callable = callbackfn.TryCast<ICallable>(x =>
             {
                 throw new JavaScriptException(Engine.TypeError, "Argument must be callable");
-            }
+            });
 
             if (len == 0 && arguments.Length < 2)
             {
@@ -842,7 +834,7 @@ namespace Jint.Native.Array
             }
 
             int k = (int)len - 1;
-            object accumulator = Undefined.Instance;
+            JsValue accumulator = Undefined.Instance;
             if (arguments.Length > 1)
             {
                 accumulator = initialValue;
@@ -880,16 +872,16 @@ namespace Jint.Native.Array
             return accumulator;
         }
 
-        public object Push(object thisObject, object[] arguments)
+        public JsValue Push(JsValue thisObject, JsValue[] arguments)
         {
-            ObjectInstance o = TypeConverter.ToObject(Engine, thisObject);
-            object lenVal = o.Get("length");
+            ObjectInstance o = TypeConverter.ToObject(Engine, thisObject).AsObject();
+            var lenVal = o.Get("length").AsNumber();
             
             // cast to double as we need to prevent an overflow
             double n = TypeConverter.ToUint32(lenVal);
-            foreach (object e in arguments)
+            foreach (JsValue e in arguments)
             {
-                o.Put(TypeConverter.ToString(n), e, true);
+                o.Put(TypeConverter.ToString(n).AsString(), e, true);
                 n++;
             }
 
@@ -898,10 +890,10 @@ namespace Jint.Native.Array
             return n;
         }
 
-        public object Pop(object thisObject, object[] arguments)
+        public JsValue Pop(JsValue thisObject, JsValue[] arguments)
         {
-            ObjectInstance o = TypeConverter.ToObject(Engine, thisObject);
-            object lenVal = o.Get("length");
+            ObjectInstance o = TypeConverter.ToObject(Engine, thisObject).AsObject();
+            var lenVal = o.Get("length").AsNumber();
             uint len = TypeConverter.ToUint32(lenVal);
             if (len == 0)
             {
@@ -911,8 +903,8 @@ namespace Jint.Native.Array
             else
             {
                 len = len - 1;
-                string indx = TypeConverter.ToString(len);
-                object element = o.Get(indx);
+                string indx = TypeConverter.ToString(len).AsString();
+                JsValue element = o.Get(indx);
                 o.Delete(indx, true);
                 o.Put("length", len, true);
                 return element;

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

@@ -6,8 +6,6 @@ namespace Jint.Native.Boolean
 {
     public sealed class BooleanConstructor : FunctionInstance, IConstructor
     {
-        private readonly Engine _engine;
-
         private BooleanConstructor(Engine engine): base(engine, null, null, false)
         {
         }
@@ -34,7 +32,7 @@ namespace Jint.Native.Boolean
 
         }
 
-        public override object Call(object thisObject, object[] arguments)
+        public override JsValue Call(JsValue thisObject, JsValue[] arguments)
         {
             if (arguments.Length == 0)
             {
@@ -49,16 +47,16 @@ namespace Jint.Native.Boolean
         /// </summary>
         /// <param name="arguments"></param>
         /// <returns></returns>
-        public ObjectInstance Construct(object[] arguments)
+        public ObjectInstance Construct(JsValue[] arguments)
         {
-            return Construct(TypeConverter.ToBoolean(arguments.Length > 0 ? arguments[0] : Undefined.Instance));
+            return Construct(TypeConverter.ToBoolean(arguments.At(0)).AsBoolean());
         }
 
         public BooleanPrototype PrototypeObject { get; private set; }
 
         public BooleanInstance Construct(bool value)
         {
-            var instance = new BooleanInstance(_engine);
+            var instance = new BooleanInstance(Engine);
             instance.Prototype = PrototypeObject;
             instance.PrimitiveValue = value;
             instance.Extensible = true;

+ 5 - 6
Jint/Native/Boolean/BooleanInstance.cs

@@ -1,10 +1,9 @@
-using System;
-using Jint.Native.Object;
+using Jint.Native.Object;
 using Jint.Runtime;
 
 namespace Jint.Native.Boolean
 {
-    public class BooleanInstance : ObjectInstance, IPrimitiveType
+    public class BooleanInstance : ObjectInstance, IPrimitiveInstance
     {
         public BooleanInstance(Engine engine)
             : base(engine)
@@ -19,16 +18,16 @@ namespace Jint.Native.Boolean
             }
         }
 
-        Types IPrimitiveType.Type
+        Types IPrimitiveInstance.Type
         {
             get { return Types.Boolean; }
         }
 
-        object IPrimitiveType.PrimitiveValue
+        JsValue IPrimitiveInstance.PrimitiveValue
         {
             get { return PrimitiveValue; }
         }
 
-        public bool PrimitiveValue { get; set; }
+        public JsValue PrimitiveValue { get; set; }
     }
 }

+ 7 - 7
Jint/Native/Boolean/BooleanPrototype.cs

@@ -26,21 +26,21 @@ namespace Jint.Native.Boolean
 
         public void Configure()
         {
-            FastAddProperty("toString", new ClrFunctionInstance<object, string>(Engine, ToBooleanString), true, false, true);
-            FastAddProperty("valueOf", new ClrFunctionInstance<object, bool>(Engine, ValueOf), true, false, true);
+            FastAddProperty("toString", new ClrFunctionInstance(Engine, ToBooleanString), true, false, true);
+            FastAddProperty("valueOf", new ClrFunctionInstance(Engine, ValueOf), true, false, true);
         }
 
-        private bool ValueOf(object thisObj, object[] arguments)
+        private JsValue ValueOf(JsValue thisObj, JsValue[] arguments)
         {
             var B = thisObj;
             object b;
-            if (TypeConverter.GetType(B) == Types.Boolean)
+            if (B.IsBoolean())
             {
                 b = B;
             }
             else
             {
-                var o = B as BooleanInstance;
+                var o = B.TryCast<BooleanInstance>();
                 if (o != null)
                 {
                     return o.PrimitiveValue;
@@ -54,10 +54,10 @@ namespace Jint.Native.Boolean
             return (bool)b;
         }
 
-        private string ToBooleanString(object thisObj, object[] arguments)
+        private JsValue ToBooleanString(JsValue thisObj, JsValue[] arguments)
         {
             var b = ValueOf(thisObj, Arguments.Empty);
-            return b ? "true" : "false";
+            return b.AsBoolean() ? "true" : "false";
         }
     }
 }

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

@@ -40,15 +40,15 @@ namespace Jint.Native.Date
 
         public void Configure()
         {
-            FastAddProperty("parse", new ClrFunctionInstance<object, object>(Engine, Parse, 1), true, false, true);
-            FastAddProperty("UTC", new ClrFunctionInstance<object, object>(Engine, Utc, 7), true, false, true);
-            FastAddProperty("now", new ClrFunctionInstance<object, object>(Engine, Now, 0), true, false, true);
+            FastAddProperty("parse", new ClrFunctionInstance(Engine, Parse, 1), true, false, true);
+            FastAddProperty("UTC", new ClrFunctionInstance(Engine, Utc, 7), true, false, true);
+            FastAddProperty("now", new ClrFunctionInstance(Engine, Now, 0), true, false, true);
         }
 
-        private object Parse(object thisObj, object[] arguments)
+        private JsValue Parse(JsValue thisObj, JsValue[] arguments)
         {
             DateTime result;
-            var date = TypeConverter.ToString(arguments.At(0));
+            var date = TypeConverter.ToString(arguments.At(0)).AsString();
 
 
             if (!DateTime.TryParseExact(date, new[] { "yyyy-MM-ddTH:m:s.fffK", "yyyy-MM-dd", "yyyy-MM", "yyyy", "THH:m:s.fff", "TH:mm:sm", "THH:mm", "THH" }, CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal, out result))
@@ -59,20 +59,20 @@ namespace Jint.Native.Date
             return Construct(result);
         }
 
-        private object Utc(object thisObj, object[] arguments)
+        private JsValue Utc(JsValue thisObj, JsValue[] arguments)
         {
             var local = (DateInstance) Construct(arguments);
             return local.PrimitiveValue;
         }
 
-        private object Now(object thisObj, object[] arguments)
+        private JsValue Now(JsValue thisObj, JsValue[] arguments)
         {
             return (DateTime.UtcNow - Origin).TotalMilliseconds;
         }
 
-        public override object Call(object thisObject, object[] arguments)
+        public override JsValue Call(JsValue thisObject, JsValue[] arguments)
         {
-            return PrototypeObject.ToString((DateInstance) Construct(Arguments.Empty), Arguments.Empty);
+            return PrototypeObject.ToString(Construct(Arguments.Empty), Arguments.Empty);
         }
 
         /// <summary>
@@ -80,7 +80,7 @@ namespace Jint.Native.Date
         /// </summary>
         /// <param name="arguments"></param>
         /// <returns></returns>
-        public ObjectInstance Construct(object[] arguments)
+        public ObjectInstance Construct(JsValue[] arguments)
         {
             if (arguments.Length == 0)
             {
@@ -89,32 +89,32 @@ namespace Jint.Native.Date
             else if (arguments.Length == 1)
             {
                 var v = TypeConverter.ToPrimitive(arguments[0]);
-                if (TypeConverter.GetType(v) == Types.String)
+                if (v.IsString())
                 {
-                    return (ObjectInstance) Parse(Undefined.Instance, Arguments.From(v));
+                    return Parse(Undefined.Instance, Arguments.From(v)).AsObject();
                 }
 
-                return Construct(TypeConverter.ToNumber(v));
+                return Construct(TypeConverter.ToNumber(v).AsNumber());
             }
             else
             {
-                var y = TypeConverter.ToNumber(arguments[0]);
-                var m = (int) TypeConverter.ToInteger(arguments[1]);
-                var date = arguments.Length > 2 ? (int)TypeConverter.ToInteger(arguments[2]) : 1;
-                var hours = arguments.Length > 3 ? (int)TypeConverter.ToInteger(arguments[3]) : 0;
-                var minutes = arguments.Length > 4 ? (int)TypeConverter.ToInteger(arguments[4]) : 0;
-                var seconds = arguments.Length > 5 ? (int)TypeConverter.ToInteger(arguments[5]) : 0;
-                var ms = arguments.Length > 6 ? (int)TypeConverter.ToInteger(arguments[6]) : 0;
+                var y = TypeConverter.ToNumber(arguments[0]).AsNumber();
+                var m = (int)TypeConverter.ToInteger(arguments[1]).AsNumber();
+                var date = arguments.Length > 2 ? (int)TypeConverter.ToInteger(arguments[2]).AsNumber() : 1;
+                var hours = arguments.Length > 3 ? (int)TypeConverter.ToInteger(arguments[3]).AsNumber() : 0;
+                var minutes = arguments.Length > 4 ? (int)TypeConverter.ToInteger(arguments[4]).AsNumber() : 0;
+                var seconds = arguments.Length > 5 ? (int)TypeConverter.ToInteger(arguments[5]).AsNumber() : 0;
+                var ms = arguments.Length > 6 ? (int)TypeConverter.ToInteger(arguments[6]).AsNumber() : 0;
 
                 for (int i = 2; i < arguments.Length; i++)
                 {
-                    if (double.IsNaN(TypeConverter.ToNumber(arguments[i])))
+                    if (double.IsNaN(TypeConverter.ToNumber(arguments[i]).AsNumber()))
                     {
                         return Construct(double.NaN);
                     }
                 }
 
-                if ((!double.IsNaN(y)) && (0 <= TypeConverter.ToInteger(y)) && (TypeConverter.ToInteger(y) <= 99))
+                if ((!double.IsNaN(y)) && (0 <= TypeConverter.ToInteger(y).AsNumber()) && (TypeConverter.ToInteger(y).AsNumber() <= 99))
                 {
                     y += 1900;
                 }
@@ -177,9 +177,9 @@ namespace Jint.Native.Date
             if (System.Math.Abs(time) > 8640000000000000)
             {
                 return double.NaN;
-            } 
+            }
 
-            return TypeConverter.ToInteger(time);
+            return TypeConverter.ToInteger(time).AsNumber();
         }
 
         public static double FromDateTime(DateTime dt)

+ 193 - 193
Jint/Native/Date/DatePrototype.cs

@@ -28,400 +28,400 @@ namespace Jint.Native.Date
 
         public void Configure()
         {
-            FastAddProperty("toString", new ClrFunctionInstance<DateInstance, string>(Engine, ToString, 0), true, false, true);
-            FastAddProperty("toDateString", new ClrFunctionInstance<DateInstance, string>(Engine, ToDateString, 0), true, false, true);
-            FastAddProperty("toTimeString", new ClrFunctionInstance<DateInstance, string>(Engine, ToTimeString, 0), true, false, true);
-            FastAddProperty("toLocaleString", new ClrFunctionInstance<DateInstance, string>(Engine, ToLocaleString, 0), true, false, true);
-            FastAddProperty("toLocaleDateString", new ClrFunctionInstance<DateInstance, string>(Engine, ToLocaleDateString, 0), true, false, true);
-            FastAddProperty("toLocaleTimeString", new ClrFunctionInstance<DateInstance, string>(Engine, ToLocaleTimeString, 0), true, false, true);
-            FastAddProperty("valueOf", new ClrFunctionInstance<DateInstance, double>(Engine, ValueOf, 0), true, false, true);
-            FastAddProperty("getTime", new ClrFunctionInstance<DateInstance, double>(Engine, GetTime, 0), true, false, true);
-            FastAddProperty("getFullYear", new ClrFunctionInstance<DateInstance, double>(Engine, GetFullYear, 0), true, false, true);
-            FastAddProperty("getUTCFullYear", new ClrFunctionInstance<DateInstance, double>(Engine, GetUTCFullYear, 0), true, false, true);
-            FastAddProperty("getMonth", new ClrFunctionInstance<DateInstance, double>(Engine, GetMonth, 0), true, false, true);
-            FastAddProperty("getUTCMonth", new ClrFunctionInstance<DateInstance, double>(Engine, GetUTCMonth, 0), true, false, true);
-            FastAddProperty("getDate", new ClrFunctionInstance<DateInstance, double>(Engine, GetDate, 0), true, false, true);
-            FastAddProperty("getUTCDate", new ClrFunctionInstance<DateInstance, double>(Engine, GetUTCDate, 0), true, false, true);
-            FastAddProperty("getDay", new ClrFunctionInstance<DateInstance, double>(Engine, GetDay, 0), true, false, true);
-            FastAddProperty("getUTCDay", new ClrFunctionInstance<DateInstance, double>(Engine, GetUTCDay, 0), true, false, true);
-            FastAddProperty("getHours", new ClrFunctionInstance<DateInstance, double>(Engine, GetHours, 0), true, false, true);
-            FastAddProperty("getUTCHours", new ClrFunctionInstance<DateInstance, double>(Engine, GetUTCHours, 0), true, false, true);
-            FastAddProperty("getMinutes", new ClrFunctionInstance<DateInstance, double>(Engine, GetMinutes, 0), true, false, true);
-            FastAddProperty("getUTCMinutes", new ClrFunctionInstance<DateInstance, double>(Engine, GetUTCMinutes, 0), true, false, true);
-            FastAddProperty("getSeconds", new ClrFunctionInstance<DateInstance, double>(Engine, GetSeconds, 0), true, false, true);
-            FastAddProperty("getUTCSeconds", new ClrFunctionInstance<DateInstance, double>(Engine, GetUTCSeconds, 0), true, false, true);
-            FastAddProperty("getMilliseconds", new ClrFunctionInstance<DateInstance, double>(Engine, GetMilliseconds, 0), true, false, true);
-            FastAddProperty("getUTCMilliseconds", new ClrFunctionInstance<DateInstance, double>(Engine, GetUTCMilliseconds, 0), true, false, true);
-            FastAddProperty("getTimezoneOffset", new ClrFunctionInstance<DateInstance, double>(Engine, GetTimezoneOffset, 0), true, false, true);
-            FastAddProperty("setTime", new ClrFunctionInstance<DateInstance, double>(Engine, SetTime, 1), true, false, true);
-            FastAddProperty("setMilliseconds", new ClrFunctionInstance<DateInstance, double>(Engine, SetMilliseconds, 1), true, false, true);
-            FastAddProperty("setUTCMilliseconds", new ClrFunctionInstance<DateInstance, double>(Engine, SetUTCMilliseconds, 1), true, false, true);
-            FastAddProperty("setSeconds", new ClrFunctionInstance<DateInstance, double>(Engine, SetSeconds, 2), true, false, true);
-            FastAddProperty("setUTCSeconds", new ClrFunctionInstance<DateInstance, double>(Engine, SetUTCSeconds, 2), true, false, true);
-            FastAddProperty("setMinutes", new ClrFunctionInstance<DateInstance, double>(Engine, SetMinutes, 3), true, false, true);
-            FastAddProperty("setUTCMinutes", new ClrFunctionInstance<DateInstance, double>(Engine, SetUTCMinutes, 3), true, false, true);
-            FastAddProperty("setHours", new ClrFunctionInstance<DateInstance, double>(Engine, SetHours, 4), true, false, true);
-            FastAddProperty("setUTCHours", new ClrFunctionInstance<DateInstance, double>(Engine, SetUTCHours, 4), true, false, true);
-            FastAddProperty("setDate", new ClrFunctionInstance<DateInstance, double>(Engine, SetDate, 1), true, false, true);
-            FastAddProperty("setUTCDate", new ClrFunctionInstance<DateInstance, double>(Engine, SetUTCDate, 1), true, false, true);
-            FastAddProperty("setMonth", new ClrFunctionInstance<DateInstance, double>(Engine, SetMonth, 2), true, false, true);
-            FastAddProperty("setUTCMonth", new ClrFunctionInstance<DateInstance, double>(Engine, SetUTCMonth, 2), true, false, true);
-            FastAddProperty("setFullYear", new ClrFunctionInstance<DateInstance, double>(Engine, SetFullYear, 3), true, false, true);
-            FastAddProperty("setUTCFullYear", new ClrFunctionInstance<DateInstance, double>(Engine, SetUTCFullYear, 3), true, false, true);
-            FastAddProperty("toUTCString", new ClrFunctionInstance<DateInstance, string>(Engine, ToUTCString, 0), true, false, true);
-            FastAddProperty("toISOString", new ClrFunctionInstance<DateInstance, string>(Engine, ToISOString, 0), true, false, true);
-            FastAddProperty("toJSON", new ClrFunctionInstance<DateInstance, string>(Engine, ToJSON, 1), true, false, true);
+            FastAddProperty("toString", new ClrFunctionInstance(Engine, ToString, 0), true, false, true);
+            FastAddProperty("toDateString", new ClrFunctionInstance(Engine, ToDateString, 0), true, false, true);
+            FastAddProperty("toTimeString", new ClrFunctionInstance(Engine, ToTimeString, 0), true, false, true);
+            FastAddProperty("toLocaleString", new ClrFunctionInstance(Engine, ToLocaleString, 0), true, false, true);
+            FastAddProperty("toLocaleDateString", new ClrFunctionInstance(Engine, ToLocaleDateString, 0), true, false, true);
+            FastAddProperty("toLocaleTimeString", new ClrFunctionInstance(Engine, ToLocaleTimeString, 0), true, false, true);
+            FastAddProperty("valueOf", new ClrFunctionInstance(Engine, ValueOf, 0), true, false, true);
+            FastAddProperty("getTime", new ClrFunctionInstance(Engine, GetTime, 0), true, false, true);
+            FastAddProperty("getFullYear", new ClrFunctionInstance(Engine, GetFullYear, 0), true, false, true);
+            FastAddProperty("getUTCFullYear", new ClrFunctionInstance(Engine, GetUTCFullYear, 0), true, false, true);
+            FastAddProperty("getMonth", new ClrFunctionInstance(Engine, GetMonth, 0), true, false, true);
+            FastAddProperty("getUTCMonth", new ClrFunctionInstance(Engine, GetUTCMonth, 0), true, false, true);
+            FastAddProperty("getDate", new ClrFunctionInstance(Engine, GetDate, 0), true, false, true);
+            FastAddProperty("getUTCDate", new ClrFunctionInstance(Engine, GetUTCDate, 0), true, false, true);
+            FastAddProperty("getDay", new ClrFunctionInstance(Engine, GetDay, 0), true, false, true);
+            FastAddProperty("getUTCDay", new ClrFunctionInstance(Engine, GetUTCDay, 0), true, false, true);
+            FastAddProperty("getHours", new ClrFunctionInstance(Engine, GetHours, 0), true, false, true);
+            FastAddProperty("getUTCHours", new ClrFunctionInstance(Engine, GetUTCHours, 0), true, false, true);
+            FastAddProperty("getMinutes", new ClrFunctionInstance(Engine, GetMinutes, 0), true, false, true);
+            FastAddProperty("getUTCMinutes", new ClrFunctionInstance(Engine, GetUTCMinutes, 0), true, false, true);
+            FastAddProperty("getSeconds", new ClrFunctionInstance(Engine, GetSeconds, 0), true, false, true);
+            FastAddProperty("getUTCSeconds", new ClrFunctionInstance(Engine, GetUTCSeconds, 0), true, false, true);
+            FastAddProperty("getMilliseconds", new ClrFunctionInstance(Engine, GetMilliseconds, 0), true, false, true);
+            FastAddProperty("getUTCMilliseconds", new ClrFunctionInstance(Engine, GetUTCMilliseconds, 0), true, false, true);
+            FastAddProperty("getTimezoneOffset", new ClrFunctionInstance(Engine, GetTimezoneOffset, 0), true, false, true);
+            FastAddProperty("setTime", new ClrFunctionInstance(Engine, SetTime, 1), true, false, true);
+            FastAddProperty("setMilliseconds", new ClrFunctionInstance(Engine, SetMilliseconds, 1), true, false, true);
+            FastAddProperty("setUTCMilliseconds", new ClrFunctionInstance(Engine, SetUTCMilliseconds, 1), true, false, true);
+            FastAddProperty("setSeconds", new ClrFunctionInstance(Engine, SetSeconds, 2), true, false, true);
+            FastAddProperty("setUTCSeconds", new ClrFunctionInstance(Engine, SetUTCSeconds, 2), true, false, true);
+            FastAddProperty("setMinutes", new ClrFunctionInstance(Engine, SetMinutes, 3), true, false, true);
+            FastAddProperty("setUTCMinutes", new ClrFunctionInstance(Engine, SetUTCMinutes, 3), true, false, true);
+            FastAddProperty("setHours", new ClrFunctionInstance(Engine, SetHours, 4), true, false, true);
+            FastAddProperty("setUTCHours", new ClrFunctionInstance(Engine, SetUTCHours, 4), true, false, true);
+            FastAddProperty("setDate", new ClrFunctionInstance(Engine, SetDate, 1), true, false, true);
+            FastAddProperty("setUTCDate", new ClrFunctionInstance(Engine, SetUTCDate, 1), true, false, true);
+            FastAddProperty("setMonth", new ClrFunctionInstance(Engine, SetMonth, 2), true, false, true);
+            FastAddProperty("setUTCMonth", new ClrFunctionInstance(Engine, SetUTCMonth, 2), true, false, true);
+            FastAddProperty("setFullYear", new ClrFunctionInstance(Engine, SetFullYear, 3), true, false, true);
+            FastAddProperty("setUTCFullYear", new ClrFunctionInstance(Engine, SetUTCFullYear, 3), true, false, true);
+            FastAddProperty("toUTCString", new ClrFunctionInstance(Engine, ToUTCString, 0), true, false, true);
+            FastAddProperty("toISOString", new ClrFunctionInstance(Engine, ToISOString, 0), true, false, true);
+            FastAddProperty("toJSON", new ClrFunctionInstance(Engine, ToJSON, 1), true, false, true);
         }
 
-        private double ValueOf(DateInstance thisObj, object[] arguments)
+        private JsValue ValueOf(JsValue thisObj, JsValue[] arguments)
         {
-            return thisObj.PrimitiveValue;
+            return thisObj.TryCast<DateInstance>().PrimitiveValue;
         }
 
-        public string ToString(DateInstance thisObj, object[] arg2)
+        public JsValue ToString(JsValue thisObj, JsValue[] arg2)
         {
-            return thisObj.ToDateTime().ToString("F", CultureInfo.InvariantCulture);
+            return thisObj.TryCast<DateInstance>().ToDateTime().ToString("F", CultureInfo.InvariantCulture);
         }
 
-        private string ToDateString(DateInstance thisObj, object[] arguments)
+        private JsValue ToDateString(JsValue thisObj, JsValue[] arguments)
         {
-            return thisObj.ToDateTime().ToString("D", CultureInfo.InvariantCulture);
+            return thisObj.TryCast<DateInstance>().ToDateTime().ToString("D", CultureInfo.InvariantCulture);
         }
 
-        private string ToTimeString(DateInstance thisObj, object[] arguments)
+        private JsValue ToTimeString(JsValue thisObj, JsValue[] arguments)
         {
-            return thisObj.ToDateTime().ToString("T", CultureInfo.InvariantCulture);
+            return thisObj.TryCast<DateInstance>().ToDateTime().ToString("T", CultureInfo.InvariantCulture);
         }
 
-        private string ToLocaleString(DateInstance thisObj, object[] arguments)
+        private JsValue ToLocaleString(JsValue thisObj, JsValue[] arguments)
         {
-            return thisObj.ToDateTime().ToString("F");
+            return thisObj.TryCast<DateInstance>().ToDateTime().ToString("F");
         }
 
-        private string ToLocaleDateString(DateInstance thisObj, object[] arguments)
+        private JsValue ToLocaleDateString(JsValue thisObj, JsValue[] arguments)
         {
-            return thisObj.ToDateTime().ToString("D");
+            return thisObj.TryCast<DateInstance>().ToDateTime().ToString("D");
         }
 
-        private string ToLocaleTimeString(DateInstance thisObj, object[] arguments)
+        private JsValue ToLocaleTimeString(JsValue thisObj, JsValue[] arguments)
         {
-            return thisObj.ToDateTime().ToString("T");
+            return thisObj.TryCast<DateInstance>().ToDateTime().ToString("T");
         }
 
-        private double GetTime(DateInstance thisObj, object[] arguments)
+        private JsValue GetTime(JsValue thisObj, JsValue[] arguments)
         {
-            if (double.IsNaN(thisObj.PrimitiveValue))
+            if (double.IsNaN(thisObj.TryCast<DateInstance>().PrimitiveValue))
             {
                 return double.NaN;
             }
 
-            return thisObj.PrimitiveValue;
+            return thisObj.TryCast<DateInstance>().PrimitiveValue;
         }
 
-        private double GetFullYear(DateInstance thisObj, object[] arguments)
+        private JsValue GetFullYear(JsValue thisObj, JsValue[] arguments)
         {
-            if (double.IsNaN(thisObj.PrimitiveValue))
+            if (double.IsNaN(thisObj.TryCast<DateInstance>().PrimitiveValue))
             {
                 return double.NaN;
             }
 
-            return thisObj.ToDateTime().ToLocalTime().Year;
+            return thisObj.TryCast<DateInstance>().ToDateTime().ToLocalTime().Year;
         }
 
-        private double GetUTCFullYear(DateInstance thisObj, object[] arguments)
+        private JsValue GetUTCFullYear(JsValue thisObj, JsValue[] arguments)
         {
-            if (double.IsNaN(thisObj.PrimitiveValue))
+            if (double.IsNaN(thisObj.TryCast<DateInstance>().PrimitiveValue))
             {
                 return double.NaN;
             }
 
-            return thisObj.ToDateTime().ToUniversalTime().Year;
+            return thisObj.TryCast<DateInstance>().ToDateTime().ToUniversalTime().Year;
         }
 
-        private double GetMonth(DateInstance thisObj, object[] arguments)
+        private JsValue GetMonth(JsValue thisObj, JsValue[] arguments)
         {
-            if (double.IsNaN(thisObj.PrimitiveValue))
+            if (double.IsNaN(thisObj.TryCast<DateInstance>().PrimitiveValue))
             {
                 return double.NaN;
             }
 
-            return thisObj.ToDateTime().ToLocalTime().Month - 1;
+            return thisObj.TryCast<DateInstance>().ToDateTime().ToLocalTime().Month - 1;
         }
 
-        private double GetUTCMonth(DateInstance thisObj, object[] arguments)
+        private JsValue GetUTCMonth(JsValue thisObj, JsValue[] arguments)
         {
-            if (double.IsNaN(thisObj.PrimitiveValue))
+            if (double.IsNaN(thisObj.TryCast<DateInstance>().PrimitiveValue))
             {
                 return double.NaN;
             }
 
-            return thisObj.ToDateTime().ToUniversalTime().Month;
+            return thisObj.TryCast<DateInstance>().ToDateTime().ToUniversalTime().Month;
         }
 
-        private double GetDate(DateInstance thisObj, object[] arguments)
+        private JsValue GetDate(JsValue thisObj, JsValue[] arguments)
         {
-            if (double.IsNaN(thisObj.PrimitiveValue))
+            if (double.IsNaN(thisObj.TryCast<DateInstance>().PrimitiveValue))
             {
                 return double.NaN;
             }
 
-            return thisObj.ToDateTime().ToLocalTime().Day;
+            return thisObj.TryCast<DateInstance>().ToDateTime().ToLocalTime().Day;
         }
 
-        private double GetUTCDate(DateInstance thisObj, object[] arguments)
+        private JsValue GetUTCDate(JsValue thisObj, JsValue[] arguments)
         {
-            if (double.IsNaN(thisObj.PrimitiveValue))
+            if (double.IsNaN(thisObj.TryCast<DateInstance>().PrimitiveValue))
             {
                 return double.NaN;
             }
 
-            return thisObj.ToDateTime().ToUniversalTime().Day;
+            return thisObj.TryCast<DateInstance>().ToDateTime().ToUniversalTime().Day;
         }
 
-        private double GetDay(DateInstance thisObj, object[] arguments)
+        private JsValue GetDay(JsValue thisObj, JsValue[] arguments)
         {
-            if (double.IsNaN(thisObj.PrimitiveValue))
+            if (double.IsNaN(thisObj.TryCast<DateInstance>().PrimitiveValue))
             {
                 return double.NaN;
             }
 
-            return (int)thisObj.ToDateTime().ToLocalTime().DayOfWeek;
+            return (int)thisObj.TryCast<DateInstance>().ToDateTime().ToLocalTime().DayOfWeek;
         }
 
-        private double GetUTCDay(DateInstance thisObj, object[] arguments)
+        private JsValue GetUTCDay(JsValue thisObj, JsValue[] arguments)
         {
-            if (double.IsNaN(thisObj.PrimitiveValue))
+            if (double.IsNaN(thisObj.TryCast<DateInstance>().PrimitiveValue))
             {
                 return double.NaN;
             }
 
-            return (int)thisObj.ToDateTime().ToUniversalTime().DayOfWeek;
+            return (int)thisObj.TryCast<DateInstance>().ToDateTime().ToUniversalTime().DayOfWeek;
         }
 
-        private double GetHours(DateInstance thisObj, object[] arguments)
+        private JsValue GetHours(JsValue thisObj, JsValue[] arguments)
         {
-            if (double.IsNaN(thisObj.PrimitiveValue))
+            if (double.IsNaN(thisObj.TryCast<DateInstance>().PrimitiveValue))
             {
                 return double.NaN;
             }
 
-            return thisObj.ToDateTime().ToLocalTime().Hour;
+            return thisObj.TryCast<DateInstance>().ToDateTime().ToLocalTime().Hour;
         }
 
-        private double GetUTCHours(DateInstance thisObj, object[] arguments)
+        private JsValue GetUTCHours(JsValue thisObj, JsValue[] arguments)
         {
-            if (double.IsNaN(thisObj.PrimitiveValue))
+            if (double.IsNaN(thisObj.TryCast<DateInstance>().PrimitiveValue))
             {
                 return double.NaN;
             }
 
-            return thisObj.ToDateTime().ToUniversalTime().Hour;
+            return thisObj.TryCast<DateInstance>().ToDateTime().ToUniversalTime().Hour;
         }
 
-        private double GetMinutes(DateInstance thisObj, object[] arguments)
+        private JsValue GetMinutes(JsValue thisObj, JsValue[] arguments)
         {
-            if (double.IsNaN(thisObj.PrimitiveValue))
+            if (double.IsNaN(thisObj.TryCast<DateInstance>().PrimitiveValue))
             {
                 return double.NaN;
             }
 
-            return thisObj.ToDateTime().ToLocalTime().Minute;
+            return thisObj.TryCast<DateInstance>().ToDateTime().ToLocalTime().Minute;
         }
 
-        private double GetUTCMinutes(DateInstance thisObj, object[] arguments)
+        private JsValue GetUTCMinutes(JsValue thisObj, JsValue[] arguments)
         {
-            if (double.IsNaN(thisObj.PrimitiveValue))
+            if (double.IsNaN(thisObj.TryCast<DateInstance>().PrimitiveValue))
             {
                 return double.NaN;
             }
 
-            return thisObj.ToDateTime().ToUniversalTime().Minute;
+            return thisObj.TryCast<DateInstance>().ToDateTime().ToUniversalTime().Minute;
         }
 
-        private double GetSeconds(DateInstance thisObj, object[] arguments)
+        private JsValue GetSeconds(JsValue thisObj, JsValue[] arguments)
         {
-            if (double.IsNaN(thisObj.PrimitiveValue))
+            if (double.IsNaN(thisObj.TryCast<DateInstance>().PrimitiveValue))
             {
                 return double.NaN;
             }
 
-            return thisObj.ToDateTime().ToLocalTime().Second;
+            return thisObj.TryCast<DateInstance>().ToDateTime().ToLocalTime().Second;
         }
 
-        private double GetUTCSeconds(DateInstance thisObj, object[] arguments)
+        private JsValue GetUTCSeconds(JsValue thisObj, JsValue[] arguments)
         {
-            if (double.IsNaN(thisObj.PrimitiveValue))
+            if (double.IsNaN(thisObj.TryCast<DateInstance>().PrimitiveValue))
             {
                 return double.NaN;
             }
 
-            return thisObj.ToDateTime().ToUniversalTime().Second;
+            return thisObj.TryCast<DateInstance>().ToDateTime().ToUniversalTime().Second;
         }
 
-        private double GetMilliseconds(DateInstance thisObj, object[] arguments)
+        private JsValue GetMilliseconds(JsValue thisObj, JsValue[] arguments)
         {
-            if (double.IsNaN(thisObj.PrimitiveValue))
+            if (double.IsNaN(thisObj.TryCast<DateInstance>().PrimitiveValue))
             {
                 return double.NaN;
             }
 
-            return thisObj.ToDateTime().ToLocalTime().Millisecond;
+            return thisObj.TryCast<DateInstance>().ToDateTime().ToLocalTime().Millisecond;
         }
 
-        private double GetUTCMilliseconds(DateInstance thisObj, object[] arguments)
+        private JsValue GetUTCMilliseconds(JsValue thisObj, JsValue[] arguments)
         {
-            if (double.IsNaN(thisObj.PrimitiveValue))
+            if (double.IsNaN(thisObj.TryCast<DateInstance>().PrimitiveValue))
             {
                 return double.NaN;
             }
 
-            return thisObj.ToDateTime().ToUniversalTime().Second;
+            return thisObj.TryCast<DateInstance>().ToDateTime().ToUniversalTime().Second;
         }
 
-        private double GetTimezoneOffset(DateInstance thisObj, object[] arguments)
+        private JsValue GetTimezoneOffset(JsValue thisObj, JsValue[] arguments)
         {
-            if (double.IsNaN(thisObj.PrimitiveValue))
+            if (double.IsNaN(thisObj.TryCast<DateInstance>().PrimitiveValue))
             {
                 return double.NaN;
             }
 
-            return - TimeZoneInfo.Local.GetUtcOffset(thisObj.ToDateTime()).Hours*60;
+            return - TimeZoneInfo.Local.GetUtcOffset(thisObj.TryCast<DateInstance>().ToDateTime()).Hours*60;
         }
 
-        private double SetTime(DateInstance thisObj, object[] arguments)
+        private JsValue SetTime(JsValue thisObj, JsValue[] arguments)
         {
-            return thisObj.PrimitiveValue = DateConstructor.TimeClip(TypeConverter.ToNumber(arguments.At(0)));
+            return thisObj.TryCast<DateInstance>().PrimitiveValue = DateConstructor.TimeClip(TypeConverter.ToNumber(arguments.At(0)).AsNumber());
         }
 
-        private double SetMilliseconds(DateInstance thisObj, object[] arguments)
+        private JsValue SetMilliseconds(JsValue thisObj, JsValue[] arguments)
         {
-            var dt = thisObj.ToDateTime();
-            dt = new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour,dt.Minute,dt.Second,(int)TypeConverter.ToNumber(arguments.At(0)), DateTimeKind.Local);
-            return thisObj.PrimitiveValue = DateConstructor.FromDateTime(dt);
+            var dt = thisObj.TryCast<DateInstance>().ToDateTime();
+            dt = new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, dt.Second, (int)TypeConverter.ToNumber(arguments.At(0)).AsNumber(), DateTimeKind.Local);
+            return thisObj.TryCast<DateInstance>().PrimitiveValue = DateConstructor.FromDateTime(dt);
         }
 
-        private double SetUTCMilliseconds(DateInstance thisObj, object[] arguments)
+        private JsValue SetUTCMilliseconds(JsValue thisObj, JsValue[] arguments)
         {
-            var dt = thisObj.ToDateTime().ToUniversalTime();
-            dt = new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, dt.Second, (int)TypeConverter.ToNumber(arguments.At(0)), DateTimeKind.Utc);
-            return thisObj.PrimitiveValue = DateConstructor.FromDateTime(dt);
+            var dt = thisObj.TryCast<DateInstance>().ToDateTime().ToUniversalTime();
+            dt = new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, dt.Second, (int)TypeConverter.ToNumber(arguments.At(0)).AsNumber(), DateTimeKind.Utc);
+            return thisObj.TryCast<DateInstance>().PrimitiveValue = DateConstructor.FromDateTime(dt);
         }
 
-        private double SetSeconds(DateInstance thisObj, object[] arguments)
+        private JsValue SetSeconds(JsValue thisObj, JsValue[] arguments)
         {
-            var dt = thisObj.ToDateTime().ToLocalTime();
-            var ms = arguments.At(1) == Undefined.Instance ? dt.Millisecond : TypeConverter.ToNumber(arguments.At(1));
-            dt = new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, (int)TypeConverter.ToNumber(arguments.At(0)), (int) ms, DateTimeKind.Local);
-            return thisObj.PrimitiveValue = DateConstructor.FromDateTime(dt);
+            var dt = thisObj.TryCast<DateInstance>().ToDateTime().ToLocalTime();
+            var ms = arguments.At(1) == Undefined.Instance ? dt.Millisecond : TypeConverter.ToNumber(arguments.At(1)).AsNumber();
+            dt = new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, (int)TypeConverter.ToNumber(arguments.At(0)).AsNumber(), (int)ms, DateTimeKind.Local);
+            return thisObj.TryCast<DateInstance>().PrimitiveValue = DateConstructor.FromDateTime(dt);
         }
 
-        private double SetUTCSeconds(DateInstance thisObj, object[] arguments)
+        private JsValue SetUTCSeconds(JsValue thisObj, JsValue[] arguments)
         {
-            var dt = thisObj.ToDateTime().ToUniversalTime();
-            var ms = arguments.At(1) == Undefined.Instance ? dt.Millisecond : TypeConverter.ToNumber(arguments.At(1));
-            dt = new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, (int)TypeConverter.ToNumber(arguments.At(0)), (int) ms, DateTimeKind.Utc);
-            return thisObj.PrimitiveValue = DateConstructor.FromDateTime(dt);
+            var dt = thisObj.TryCast<DateInstance>().ToDateTime().ToUniversalTime();
+            var ms = arguments.At(1) == Undefined.Instance ? dt.Millisecond : TypeConverter.ToNumber(arguments.At(1)).AsNumber();
+            dt = new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, (int)TypeConverter.ToNumber(arguments.At(0)).AsNumber(), (int)ms, DateTimeKind.Utc);
+            return thisObj.TryCast<DateInstance>().PrimitiveValue = DateConstructor.FromDateTime(dt);
         }
 
-        private double SetMinutes(DateInstance thisObj, object[] arguments)
+        private JsValue SetMinutes(JsValue thisObj, JsValue[] arguments)
         {
-            var dt = thisObj.ToDateTime().ToLocalTime();
-            var s = arguments.At(1) == Undefined.Instance ? dt.Second : TypeConverter.ToNumber(arguments.At(1));
-            var ms = arguments.At(2) == Undefined.Instance ? dt.Millisecond : TypeConverter.ToNumber(arguments.At(2));
-            dt = new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, (int)TypeConverter.ToNumber(arguments.At(0)), (int) s, (int) ms, DateTimeKind.Local);
-            return thisObj.PrimitiveValue = DateConstructor.FromDateTime(dt);
+            var dt = thisObj.TryCast<DateInstance>().ToDateTime().ToLocalTime();
+            var s = arguments.At(1) == Undefined.Instance ? dt.Second : TypeConverter.ToNumber(arguments.At(1)).AsNumber();
+            var ms = arguments.At(2) == Undefined.Instance ? dt.Millisecond : TypeConverter.ToNumber(arguments.At(2)).AsNumber();
+            dt = new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, (int)TypeConverter.ToNumber(arguments.At(0)).AsNumber(), (int)s, (int)ms, DateTimeKind.Local);
+            return thisObj.TryCast<DateInstance>().PrimitiveValue = DateConstructor.FromDateTime(dt);
         }
 
-        private double SetUTCMinutes(DateInstance thisObj, object[] arguments)
+        private JsValue SetUTCMinutes(JsValue thisObj, JsValue[] arguments)
         {
-            var dt = thisObj.ToDateTime().ToUniversalTime();
-            var s = arguments.At(1) == Undefined.Instance ? dt.Second : TypeConverter.ToNumber(arguments.At(1));
-            var ms = arguments.At(2) == Undefined.Instance ? dt.Millisecond : TypeConverter.ToNumber(arguments.At(2));
-            dt = new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, (int)TypeConverter.ToNumber(arguments.At(0)), (int)s, (int)ms, DateTimeKind.Utc);
-            return thisObj.PrimitiveValue = DateConstructor.FromDateTime(dt);
+            var dt = thisObj.TryCast<DateInstance>().ToDateTime().ToUniversalTime();
+            var s = arguments.At(1) == Undefined.Instance ? dt.Second : TypeConverter.ToNumber(arguments.At(1)).AsNumber();
+            var ms = arguments.At(2) == Undefined.Instance ? dt.Millisecond : TypeConverter.ToNumber(arguments.At(2)).AsNumber();
+            dt = new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, (int)TypeConverter.ToNumber(arguments.At(0)).AsNumber(), (int)s, (int)ms, DateTimeKind.Utc);
+            return thisObj.TryCast<DateInstance>().PrimitiveValue = DateConstructor.FromDateTime(dt);
         }
 
-        private double SetHours(DateInstance thisObj, object[] arguments)
+        private JsValue SetHours(JsValue thisObj, JsValue[] arguments)
         {
-            var dt = thisObj.ToDateTime().ToLocalTime();
-            var min = arguments.At(1) == Undefined.Instance ? dt.Minute : TypeConverter.ToNumber(arguments.At(1));
-            var s = arguments.At(2) == Undefined.Instance ? dt.Second : TypeConverter.ToNumber(arguments.At(2));
-            var ms = arguments.At(3) == Undefined.Instance ? dt.Millisecond : TypeConverter.ToNumber(arguments.At(3));
-            dt = new DateTime(dt.Year, dt.Month, dt.Day, (int)TypeConverter.ToNumber(arguments.At(0)), (int) min, (int)s, (int)ms, DateTimeKind.Local);
-            return thisObj.PrimitiveValue = DateConstructor.FromDateTime(dt);
+            var dt = thisObj.TryCast<DateInstance>().ToDateTime().ToLocalTime();
+            var min = arguments.At(1) == Undefined.Instance ? dt.Minute : TypeConverter.ToNumber(arguments.At(1)).AsNumber();
+            var s = arguments.At(2) == Undefined.Instance ? dt.Second : TypeConverter.ToNumber(arguments.At(2)).AsNumber();
+            var ms = arguments.At(3) == Undefined.Instance ? dt.Millisecond : TypeConverter.ToNumber(arguments.At(3)).AsNumber();
+            dt = new DateTime(dt.Year, dt.Month, dt.Day, (int)TypeConverter.ToNumber(arguments.At(0)).AsNumber(), (int)min, (int)s, (int)ms, DateTimeKind.Local);
+            return thisObj.TryCast<DateInstance>().PrimitiveValue = DateConstructor.FromDateTime(dt);
         }
 
-        private double SetUTCHours(DateInstance thisObj, object[] arguments)
+        private JsValue SetUTCHours(JsValue thisObj, JsValue[] arguments)
         {
-            var dt = thisObj.ToDateTime().ToUniversalTime();
-            var min = arguments.At(1) == Undefined.Instance ? dt.Minute : TypeConverter.ToNumber(arguments.At(1));
-            var s = arguments.At(2) == Undefined.Instance ? dt.Second : TypeConverter.ToNumber(arguments.At(2));
-            var ms = arguments.At(3) == Undefined.Instance ? dt.Millisecond : TypeConverter.ToNumber(arguments.At(3));
-            dt = new DateTime(dt.Year, dt.Month, dt.Day, (int)TypeConverter.ToNumber(arguments.At(0)), (int)min, (int)s, (int)ms, DateTimeKind.Utc);
-            return thisObj.PrimitiveValue = DateConstructor.FromDateTime(dt);
+            var dt = thisObj.TryCast<DateInstance>().ToDateTime().ToUniversalTime();
+            var min = arguments.At(1) == Undefined.Instance ? dt.Minute : TypeConverter.ToNumber(arguments.At(1)).AsNumber();
+            var s = arguments.At(2) == Undefined.Instance ? dt.Second : TypeConverter.ToNumber(arguments.At(2)).AsNumber();
+            var ms = arguments.At(3) == Undefined.Instance ? dt.Millisecond : TypeConverter.ToNumber(arguments.At(3)).AsNumber();
+            dt = new DateTime(dt.Year, dt.Month, dt.Day, (int)TypeConverter.ToNumber(arguments.At(0)).AsNumber(), (int)min, (int)s, (int)ms, DateTimeKind.Utc);
+            return thisObj.TryCast<DateInstance>().PrimitiveValue = DateConstructor.FromDateTime(dt);
         }
 
-        private double SetDate(DateInstance thisObj, object[] arguments)
+        private JsValue SetDate(JsValue thisObj, JsValue[] arguments)
         {
-            var dt = thisObj.ToDateTime().ToLocalTime();
-            dt = new DateTime(dt.Year, dt.Month, (int)TypeConverter.ToNumber(arguments.At(0)), dt.Hour, dt.Minute, dt.Second, dt.Second, DateTimeKind.Local);
-            return thisObj.PrimitiveValue = DateConstructor.FromDateTime(dt);
+            var dt = thisObj.TryCast<DateInstance>().ToDateTime().ToLocalTime();
+            dt = new DateTime(dt.Year, dt.Month, (int)TypeConverter.ToNumber(arguments.At(0)).AsNumber(), dt.Hour, dt.Minute, dt.Second, dt.Second, DateTimeKind.Local);
+            return thisObj.TryCast<DateInstance>().PrimitiveValue = DateConstructor.FromDateTime(dt);
         }
 
-        private double SetUTCDate(DateInstance thisObj, object[] arguments)
+        private JsValue SetUTCDate(JsValue thisObj, JsValue[] arguments)
         {
-            var dt = thisObj.ToDateTime().ToUniversalTime();
-            dt = new DateTime(dt.Year, dt.Month, (int)TypeConverter.ToNumber(arguments.At(0)), dt.Hour, dt.Minute, dt.Second, dt.Second, DateTimeKind.Utc);
-            return thisObj.PrimitiveValue = DateConstructor.FromDateTime(dt);
+            var dt = thisObj.TryCast<DateInstance>().ToDateTime().ToUniversalTime();
+            dt = new DateTime(dt.Year, dt.Month, (int)TypeConverter.ToNumber(arguments.At(0)).AsNumber(), dt.Hour, dt.Minute, dt.Second, dt.Second, DateTimeKind.Utc);
+            return thisObj.TryCast<DateInstance>().PrimitiveValue = DateConstructor.FromDateTime(dt);
         }
 
-        private double SetMonth(DateInstance thisObj, object[] arguments)
+        private JsValue SetMonth(JsValue thisObj, JsValue[] arguments)
         {
-            var dt = thisObj.ToDateTime().ToUniversalTime();
-            var date = arguments.At(1) == Undefined.Instance ? dt.Day : TypeConverter.ToNumber(arguments.At(1));
-            dt = new DateTime(dt.Year, (int)TypeConverter.ToNumber(arguments.At(0)), (int) date, dt.Hour, dt.Minute, dt.Second, dt.Second, DateTimeKind.Local);
-            return thisObj.PrimitiveValue = DateConstructor.FromDateTime(dt);
+            var dt = thisObj.TryCast<DateInstance>().ToDateTime().ToUniversalTime();
+            var date = arguments.At(1) == Undefined.Instance ? dt.Day : TypeConverter.ToNumber(arguments.At(1)).AsNumber();
+            dt = new DateTime(dt.Year, (int)TypeConverter.ToNumber(arguments.At(0)).AsNumber(), (int)date, dt.Hour, dt.Minute, dt.Second, dt.Second, DateTimeKind.Local);
+            return thisObj.TryCast<DateInstance>().PrimitiveValue = DateConstructor.FromDateTime(dt);
         }
 
-        private double SetUTCMonth(DateInstance thisObj, object[] arguments)
+        private JsValue SetUTCMonth(JsValue thisObj, JsValue[] arguments)
         {
-            var dt = thisObj.ToDateTime().ToUniversalTime();
-            var date = arguments.At(1) == Undefined.Instance ? dt.Day : TypeConverter.ToNumber(arguments.At(1));
-            dt = new DateTime(dt.Year, (int)TypeConverter.ToNumber(arguments.At(0)), (int) date, dt.Hour, dt.Minute, dt.Second, dt.Second, DateTimeKind.Utc);
-            return thisObj.PrimitiveValue = DateConstructor.FromDateTime(dt);
+            var dt = thisObj.TryCast<DateInstance>().ToDateTime().ToUniversalTime();
+            var date = arguments.At(1) == Undefined.Instance ? dt.Day : TypeConverter.ToNumber(arguments.At(1)).AsNumber();
+            dt = new DateTime(dt.Year, (int)TypeConverter.ToNumber(arguments.At(0)).AsNumber(), (int)date, dt.Hour, dt.Minute, dt.Second, dt.Second, DateTimeKind.Utc);
+            return thisObj.TryCast<DateInstance>().PrimitiveValue = DateConstructor.FromDateTime(dt);
         }
 
-        private double SetFullYear(DateInstance thisObj, object[] arguments)
+        private JsValue SetFullYear(JsValue thisObj, JsValue[] arguments)
         {
-            var dt = thisObj.ToDateTime().ToLocalTime();
-            var month = arguments.At(1) == Undefined.Instance ? dt.Month : TypeConverter.ToNumber(arguments.At(1));
-            var date = arguments.At(2) == Undefined.Instance ? dt.Day : TypeConverter.ToNumber(arguments.At(2));
-            dt = new DateTime((int)TypeConverter.ToNumber(arguments.At(0)), (int)month, (int)date, dt.Hour, dt.Minute, dt.Second, dt.Second, DateTimeKind.Local);
-            return thisObj.PrimitiveValue = DateConstructor.FromDateTime(dt);
+            var dt = thisObj.TryCast<DateInstance>().ToDateTime().ToLocalTime();
+            var month = arguments.At(1) == Undefined.Instance ? dt.Month : TypeConverter.ToNumber(arguments.At(1)).AsNumber();
+            var date = arguments.At(2) == Undefined.Instance ? dt.Day : TypeConverter.ToNumber(arguments.At(2)).AsNumber();
+            dt = new DateTime((int)TypeConverter.ToNumber(arguments.At(0)).AsNumber(), (int)month, (int)date, dt.Hour, dt.Minute, dt.Second, dt.Second, DateTimeKind.Local);
+            return thisObj.TryCast<DateInstance>().PrimitiveValue = DateConstructor.FromDateTime(dt);
         }
 
-        private double SetUTCFullYear(DateInstance thisObj, object[] arguments)
+        private JsValue SetUTCFullYear(JsValue thisObj, JsValue[] arguments)
         {
-            var dt = thisObj.ToDateTime().ToUniversalTime();
-            var month = arguments.At(1) == Undefined.Instance ? dt.Month : TypeConverter.ToNumber(arguments.At(1));
-            var date = arguments.At(2) == Undefined.Instance ? dt.Day : TypeConverter.ToNumber(arguments.At(2));
-            dt = new DateTime((int)TypeConverter.ToNumber(arguments.At(0)), (int)month,(int)date, dt.Hour, dt.Minute, dt.Second, dt.Second, DateTimeKind.Utc);
-            return thisObj.PrimitiveValue = DateConstructor.FromDateTime(dt);
+            var dt = thisObj.TryCast<DateInstance>().ToDateTime().ToUniversalTime();
+            var month = arguments.At(1) == Undefined.Instance ? dt.Month : TypeConverter.ToNumber(arguments.At(1)).AsNumber();
+            var date = arguments.At(2) == Undefined.Instance ? dt.Day : TypeConverter.ToNumber(arguments.At(2)).AsNumber();
+            dt = new DateTime((int)TypeConverter.ToNumber(arguments.At(0)).AsNumber(), (int)month, (int)date, dt.Hour, dt.Minute, dt.Second, dt.Second, DateTimeKind.Utc);
+            return thisObj.TryCast<DateInstance>().PrimitiveValue = DateConstructor.FromDateTime(dt);
         }
 
-        private string ToUTCString(DateInstance thisObj, object[] arguments)
+        private JsValue ToUTCString(JsValue thisObj, JsValue[] arguments)
         {
-            return thisObj.ToDateTime().ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffZ");
+            return thisObj.TryCast<DateInstance>().ToDateTime().ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffZ");
         }
 
-        private string ToISOString(DateInstance thisObj, object[] arguments)
+        private JsValue ToISOString(JsValue thisObj, JsValue[] arguments)
         {
-            return thisObj.ToDateTime().ToLocalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffZ");
+            return thisObj.TryCast<DateInstance>().ToDateTime().ToLocalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffZ");
         }
 
-        private string ToJSON(DateInstance thisObj, object[] arguments)
+        private JsValue ToJSON(JsValue thisObj, JsValue[] arguments)
         {
-            return thisObj.ToDateTime().ToString("yyyy-MM-ddTHH:mm:ss.fffZ");
+            return thisObj.TryCast<DateInstance>().ToDateTime().ToString("yyyy-MM-ddTHH:mm:ss.fffZ");
         }
     }
 }

+ 2 - 2
Jint/Native/Error/ErrorConstructor.cs

@@ -35,12 +35,12 @@ namespace Jint.Native.Error
             
         }
 
-        public override object Call(object thisObject, object[] arguments)
+        public override JsValue Call(JsValue thisObject, JsValue[] arguments)
         {
             return Construct(arguments);
         }
 
-        public ObjectInstance Construct(object[] arguments)
+        public ObjectInstance Construct(JsValue[] arguments)
         {
             var instance = new ErrorInstance(Engine, _name);
             instance.Prototype = PrototypeObject;

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

@@ -30,12 +30,12 @@ namespace Jint.Native.Error
         public void Configure()
         {
             // Error prototype functions
-            FastAddProperty("toString", new ClrFunctionInstance<object, object>(Engine, ToString), true, false, true);
+            FastAddProperty("toString", new ClrFunctionInstance(Engine, ToString), true, false, true);
         }
 
-        private object ToString(object thisObject, object[] arguments)
+        private JsValue ToString(JsValue thisObject, JsValue[] arguments)
         {
-            var o = thisObject as ObjectInstance;
+            var o = thisObject.TryCast<ObjectInstance>();
             if (o == null)
             {
                 throw new JavaScriptException(Engine.TypeError);

+ 13 - 17
Jint/Native/Function/BindFunctionInstance.cs

@@ -1,5 +1,4 @@
-using System;
-using System.Linq;
+using System.Linq;
 using Jint.Native.Object;
 using Jint.Runtime;
 
@@ -11,42 +10,39 @@ namespace Jint.Native.Function
         {
         }
 
-        public object TargetFunction { get; set; }
+        public JsValue TargetFunction { get; set; }
 
-        public object BoundThis { get; set; }
+        public JsValue BoundThis { get; set; }
 
-        public object[] BoundArgs { get; set; }
+        public JsValue[] BoundArgs { get; set; }
 
-        public override object Call(object thisObject, object[] arguments)
+        public override JsValue Call(JsValue thisObject, JsValue[] arguments)
         {
-            var f = TargetFunction as FunctionInstance;
-            if (f == null)
+            var f = TargetFunction.TryCast<FunctionInstance>(x =>
             {
                 throw new JavaScriptException(Engine.TypeError);
-            }
+            });
 
             return f.Call(BoundThis, BoundArgs.Union(arguments).ToArray());
         }
 
-        public ObjectInstance Construct(object[] arguments)
+        public ObjectInstance Construct(JsValue[] arguments)
         {
-            var target = TargetFunction as IConstructor;
-            if (target == null)
+            var target = TargetFunction.TryCast<IConstructor>(x =>
             {
                 throw new JavaScriptException(Engine.TypeError);
-            }
+            });
 
             return target.Construct(BoundArgs.Union(arguments).ToArray());
         }
 
         public override bool HasInstance(object v)
         {
-            var f = TargetFunction as FunctionInstance;
-            if (f == null)
+            var f = TargetFunction.TryCast<FunctionInstance>(x =>
             {
                 throw new JavaScriptException(Engine.TypeError);
-            }
-
+            });
+              
             return f.HasInstance(v);
         }
     }

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

@@ -15,19 +15,19 @@ namespace Jint.Native.Function
             FastAddProperty("length", 1, false, false, false);
         }
 
-        public override object Call(object thisObject, object[] arguments)
+        public override JsValue Call(JsValue thisObject, JsValue[] arguments)
         {
             return Call(thisObject, arguments, false);
         }
 
-        public object Call(object thisObject, object[] arguments, bool directCall)
+        public JsValue Call(JsValue thisObject, JsValue[] arguments, bool directCall)
         {
-            if (TypeConverter.GetType(arguments.At(0)) != Types.String)
+            if (arguments.At(0).Type != Types.String)
             {
                 return arguments.At(0);
             }
 
-            var code = TypeConverter.ToString(arguments.At(0));
+            var code = TypeConverter.ToString(arguments.At(0)).AsString();
 
             try
             {
@@ -62,7 +62,7 @@ namespace Jint.Native.Function
                             }
                             else
                             {
-                                return result.Value ?? Undefined.Instance;
+                                return result.Value;
                             }
                         }
                         finally

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

@@ -40,12 +40,12 @@ namespace Jint.Native.Function
 
         public FunctionPrototype PrototypeObject { get; private set; }
 
-        public override object Call(object thisObject, object[] arguments)
+        public override JsValue Call(JsValue thisObject, JsValue[] arguments)
         {
             return Construct(arguments);
         }
 
-        public ObjectInstance Construct(object[] arguments)
+        public ObjectInstance Construct(JsValue[] arguments)
         {
             var argCount = arguments.Length;
             string p = "";
@@ -53,21 +53,21 @@ namespace Jint.Native.Function
 
             if (argCount == 1)
             {
-                body = TypeConverter.ToString(arguments[0]);
+                body = TypeConverter.ToString(arguments[0]).AsString();
             }
             else if (argCount > 1)
             {
                 var firstArg = arguments[0];
-                p = TypeConverter.ToString(firstArg);
+                p = TypeConverter.ToString(firstArg).AsString();
                 for (var k = 1; k < argCount - 1; k++)
                 {
                     var nextArg = arguments[k];
                     p += "," + TypeConverter.ToString(nextArg);
                 }
 
-                body = TypeConverter.ToString(arguments[argCount-1]);
+                body = TypeConverter.ToString(arguments[argCount-1]).AsString();
             }
-            body = TypeConverter.ToString(body);
+            body = TypeConverter.ToString(body).AsString();
             
             // todo: ensure parsable as parameter list
             var parameters = p.Split(new [] {','}, StringSplitOptions.RemoveEmptyEntries);
@@ -143,14 +143,14 @@ namespace Jint.Native.Function
             }
         }
 
-        public object Apply(object thisObject, object[] arguments)
+        public object Apply(JsValue thisObject, JsValue[] arguments)
         {
             if (arguments.Length != 2)
             {
                 throw new ArgumentException("Apply has to be called with two arguments.");
             }
 
-            var func = thisObject as ICallable;
+            var func = thisObject.TryCast<ICallable>();
             var thisArg = arguments[0];
             var argArray = arguments[1];
 
@@ -164,7 +164,7 @@ namespace Jint.Native.Function
                 return func.Call(thisArg, Arguments.Empty);
             }
 
-            var argArrayObj = argArray as ObjectInstance;
+            var argArrayObj = argArray.TryCast<ObjectInstance>();
             if (argArrayObj == null)
             {
                 throw new JavaScriptException(Engine.TypeError);
@@ -172,7 +172,7 @@ namespace Jint.Native.Function
 
             var len = argArrayObj.Get("length");
             var n = TypeConverter.ToUint32(len);
-            var argList = new List<object>();
+            var argList = new List<JsValue>();
             for (var index = 0; index < n; index++)
             {
                 var indexName = index.ToString();

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

@@ -22,18 +22,13 @@ namespace Jint.Native.Function
         /// <param name="thisObject"></param>
         /// <param name="arguments"></param>
         /// <returns></returns>
-        public abstract object Call(object thisObject, object[] arguments);
+        public abstract JsValue Call(JsValue thisObject, JsValue[] arguments);
 
         public LexicalEnvironment Scope { get; private set; }
         
         public string[] FormalParameters { get; private set; }
         public bool Strict { get; private set; }
 
-        /// <summary>
-        /// http://www.ecma-international.org/ecma-262/5.1/#sec-15.3.5.3
-        /// </summary>
-        /// <param name="instance"></param>
-        /// <returns></returns>
         public virtual bool HasInstance(object v)
         {
             var vObj = v as ObjectInstance;
@@ -42,7 +37,7 @@ namespace Jint.Native.Function
                 return false;
             }
 
-            var o = Get("prototype") as ObjectInstance;
+            var o = Get("prototype").AsObject();
             
             if (o == null)
             {
@@ -77,11 +72,11 @@ namespace Jint.Native.Function
         /// </summary>
         /// <param name="propertyName"></param>
         /// <returns></returns>
-        public override object Get(string propertyName)
+        public override JsValue Get(string propertyName)
         {
             var v = base.Get(propertyName);
 
-            var f = v as FunctionInstance;
+            var f = v.As<FunctionInstance>();
             if (propertyName == "caller" && f != null && f.Strict)
             {
                 throw new JavaScriptException(_engine.TypeError);

+ 24 - 27
Jint/Native/Function/FunctionPrototype.cs

@@ -1,5 +1,4 @@
-using System;
-using System.Collections.Generic;
+using System.Collections.Generic;
 using System.Linq;
 using Jint.Native.Object;
 using Jint.Runtime;
@@ -33,24 +32,22 @@ namespace Jint.Native.Function
         public void Configure()
         {
             FastAddProperty("constructor", Engine.Function, true, false, true);
-            FastAddProperty("toString", new ClrFunctionInstance<object, object>(Engine, ToString), true, false, true);
-            FastAddProperty("apply", new ClrFunctionInstance<object, object>(Engine, Apply), true, false, true);
-            FastAddProperty("call", new ClrFunctionInstance<object, object>(Engine, Call, 1), true, false, true);
-            FastAddProperty("bind", new ClrFunctionInstance<object, object>(Engine, Bind, 1), true, false, true);
+            FastAddProperty("toString", new ClrFunctionInstance(Engine, ToString), true, false, true);
+            FastAddProperty("apply", new ClrFunctionInstance(Engine, Apply), true, false, true);
+            FastAddProperty("call", new ClrFunctionInstance(Engine, Call, 1), true, false, true);
+            FastAddProperty("bind", new ClrFunctionInstance(Engine, Bind, 1), true, false, true);
         }
 
-        private object Bind(object thisObj, object[] arguments)
+        private JsValue Bind(JsValue thisObj, JsValue[] arguments)
         {
-            var target = thisObj as ICallable;
-
-            if (target == null)
+            var target = thisObj.TryCast<ICallable>(x =>
             {
                 throw new JavaScriptException(Engine.TypeError);
-            }
+            });
             
-            object thisArg = arguments.At(0);
+            var thisArg = arguments.At(0);
             var f = new BindFunctionInstance(Engine) {Extensible = true};
-            f.TargetFunction = target;
+            f.TargetFunction = thisObj;
             f.BoundThis = thisArg;
             f.BoundArgs = arguments.Skip(1).ToArray();
             f.Prototype = Engine.Function.PrototypeObject;
@@ -58,7 +55,7 @@ namespace Jint.Native.Function
             var o = target as FunctionInstance;
             if (o != null)
             {
-                var l = TypeConverter.ToNumber(o.Get("length")) - (arguments.Length - 1);
+                var l = TypeConverter.ToNumber(o.Get("length")).AsNumber() - (arguments.Length - 1);
                 f.FastAddProperty("length", System.Math.Max(l, 0), false, false, false); 
             }
             else
@@ -75,9 +72,9 @@ namespace Jint.Native.Function
             return f;
         }
 
-        private object ToString(object thisObj, object[] arguments)
+        private JsValue ToString(JsValue thisObj, JsValue[] arguments)
         {
-            var func = thisObj as FunctionInstance;
+            var func = thisObj.TryCast<FunctionInstance>();
 
             if (func == null)
             {
@@ -87,11 +84,11 @@ namespace Jint.Native.Function
             return System.String.Format("function() {{ ... }}");
         }
 
-        public object Apply(object thisObject, object[] arguments)
+        public JsValue Apply(JsValue thisObject, JsValue[] arguments)
         {
-            var func = thisObject as ICallable;
-            object thisArg = arguments.At(0);
-            object argArray = arguments.At(1);
+            var func = thisObject.TryCast<ICallable>();
+            var thisArg = arguments.At(0);
+            var argArray = arguments.At(1);
 
             if (func == null)
             {
@@ -103,30 +100,30 @@ namespace Jint.Native.Function
                 return func.Call(thisArg, Arguments.Empty);
             }
 
-            var argArrayObj = argArray as ObjectInstance;
+            var argArrayObj = argArray.TryCast<ObjectInstance>();
             if (argArrayObj == null)
             {
                 throw new JavaScriptException(Engine.TypeError);
             }
 
-            object len = argArrayObj.Get("length");
+            var len = argArrayObj.Get("length").AsNumber();
             uint n = TypeConverter.ToUint32(len);
-            var argList = new List<object>();
+            var argList = new List<JsValue>();
             for (int index = 0; index < n; index++)
             {
                 string indexName = index.ToString();
-                object nextArg = argArrayObj.Get(indexName);
+                var nextArg = argArrayObj.Get(indexName);
                 argList.Add(nextArg);
             }
             return func.Call(thisArg, argList.ToArray());
         }
 
-        public override object Call(object thisObject, object[] arguments)
+        public override JsValue Call(JsValue thisObject, JsValue[] arguments)
         {
-            var func = thisObject as ICallable;
+            var func = thisObject.TryCast<ICallable>();
             if (func == null)
             {
-                return new JavaScriptException(Engine.TypeError);
+                throw new JavaScriptException(Engine.TypeError);
             }
 
             return func.Call(arguments.At(0), arguments.Length == 0 ? arguments : arguments.Skip(1).ToArray());

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

@@ -8,7 +8,7 @@ namespace Jint.Native.Function
         {
         }
 
-        public override object Call(object thisObject, object[] arguments)
+        public override JsValue Call(JsValue thisObject, JsValue[] arguments)
         {
             return Undefined.Instance;
         }

+ 8 - 9
Jint/Native/Function/ScriptFunctionInstance.cs

@@ -33,12 +33,12 @@ namespace Jint.Native.Function
             Extensible = true;
             Prototype = engine.Function.PrototypeObject;
 
-            DefineOwnProperty("length", new PropertyDescriptor(FormalParameters.Length, false, false, false ), false);
+            DefineOwnProperty("length", new PropertyDescriptor(new JsValue(FormalParameters.Length), false, false, false ), false);
 
             var proto = engine.Object.Construct(Arguments.Empty);
             proto.DefineOwnProperty("constructor", new PropertyDescriptor(this, true, false, true), false);
             DefineOwnProperty("prototype", new PropertyDescriptor(proto, true, false, false ), false);
-            DefineOwnProperty("name", new PropertyDescriptor(_functionDeclaration.Id, null, null, null), false);
+            DefineOwnProperty("name", new PropertyDescriptor(_functionDeclaration.Id.Name, null, null, null), false);
             
             if (strict)
             {
@@ -54,13 +54,12 @@ namespace Jint.Native.Function
         /// <param name="thisArg"></param>
         /// <param name="arguments"></param>
         /// <returns></returns>
-        public override object Call(object thisArg, object[] arguments)
+        public override JsValue Call(JsValue thisArg, JsValue[] arguments)
         {
-            object thisBinding;
-
             using (new StrictModeScope(Strict, true))
             {
                 // setup new execution context http://www.ecma-international.org/ecma-262/5.1/#sec-10.4.3
+                JsValue thisBinding;
                 if (StrictModeScope.IsStrictModeCode)
                 {
                     thisBinding = thisArg;
@@ -69,7 +68,7 @@ namespace Jint.Native.Function
                 {
                     thisBinding = Engine.Global;
                 }
-                else if (TypeConverter.GetType(thisArg) != Types.Object)
+                else if (thisArg.IsObject())
                 {
                     thisBinding = TypeConverter.ToObject(Engine, thisArg);
                 }
@@ -117,14 +116,14 @@ namespace Jint.Native.Function
         /// </summary>
         /// <param name="arguments"></param>
         /// <returns></returns>
-        public ObjectInstance Construct(object[] arguments)
+        public ObjectInstance Construct(JsValue[] arguments)
         {
-            var proto = Get("prototype") as ObjectInstance;
+            var proto = Get("prototype").TryCast<ObjectInstance>();
             var obj = new ObjectInstance(Engine);
             obj.Extensible = true;
             obj.Prototype = proto ?? Engine.Object.PrototypeObject;
 
-            var result = Call(obj, arguments) as ObjectInstance;
+            var result = Call(obj, arguments).TryCast<ObjectInstance>();
             if (result != null)
             {
                 return result;

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

@@ -1,5 +1,4 @@
-using Jint.Parser.Ast;
-using Jint.Runtime;
+using Jint.Runtime;
 using Jint.Runtime.Descriptors;
 
 namespace Jint.Native.Function
@@ -15,7 +14,7 @@ namespace Jint.Native.Function
             Extensible = false;
         }
 
-        public override object Call(object thisObject, object[] arguments)
+        public override JsValue Call(JsValue thisObject, JsValue[] arguments)
         {
             throw new JavaScriptException(_engine.TypeError);
         }

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

@@ -50,22 +50,22 @@ namespace Jint.Native.Global
             FastAddProperty("undefined", Undefined.Instance, false, false, false);
 
             // Global object functions
-            FastAddProperty("parseInt", new ClrFunctionInstance<object, double>(Engine, ParseInt, 2), true, false, true);
-            FastAddProperty("parseFloat", new ClrFunctionInstance<object, double>(Engine, ParseFloat, 1), true, false, true);
-            FastAddProperty("isNaN", new ClrFunctionInstance<object, bool>(Engine, IsNaN, 1), true, false, true);
-            FastAddProperty("isFinite", new ClrFunctionInstance<object, bool>(Engine, IsFinite, 1), true, false, true);
-            FastAddProperty("decodeURI", new ClrFunctionInstance<object, string>(Engine, DecodeUri, 1), true, false, true);
-            FastAddProperty("decodeURIComponent", new ClrFunctionInstance<object, string>(Engine, DecodeUriComponent, 1), true, false, true);
-            FastAddProperty("encodeURI", new ClrFunctionInstance<object, string>(Engine, EncodeUri, 1), true, false, true);
-            FastAddProperty("encodeURIComponent", new ClrFunctionInstance<object, string>(Engine, EncodeUriComponent, 1), true, false, true);
+            FastAddProperty("parseInt", new ClrFunctionInstance(Engine, ParseInt, 2), true, false, true);
+            FastAddProperty("parseFloat", new ClrFunctionInstance(Engine, ParseFloat, 1), true, false, true);
+            FastAddProperty("isNaN", new ClrFunctionInstance(Engine, IsNaN, 1), true, false, true);
+            FastAddProperty("isFinite", new ClrFunctionInstance(Engine, IsFinite, 1), true, false, true);
+            FastAddProperty("decodeURI", new ClrFunctionInstance(Engine, DecodeUri, 1), true, false, true);
+            FastAddProperty("decodeURIComponent", new ClrFunctionInstance(Engine, DecodeUriComponent, 1), true, false, true);
+            FastAddProperty("encodeURI", new ClrFunctionInstance(Engine, EncodeUri, 1), true, false, true);
+            FastAddProperty("encodeURIComponent", new ClrFunctionInstance(Engine, EncodeUriComponent, 1), true, false, true);
         }
 
         /// <summary>
         /// http://www.ecma-international.org/ecma-262/5.1/#sec-15.1.2.2
         /// </summary>
-        public static double ParseInt(object thisObject, object[] arguments)
+        public static JsValue ParseInt(JsValue thisObject, JsValue[] arguments)
         {
-            string inputString = TypeConverter.ToString(arguments.At(0));
+            string inputString = TypeConverter.ToString(arguments.At(0)).AsString();
             var s = inputString.Trim();
 
             var sign = 1;
@@ -113,7 +113,7 @@ namespace Jint.Native.Global
 
             try
             {
-                return sign * Parse(s, radix);
+                return sign * Parse(s, radix).AsNumber();
             }
             catch
             {
@@ -122,7 +122,7 @@ namespace Jint.Native.Global
 
         }
 
-        private static double Parse(string number, int radix)
+        private static JsValue Parse(string number, int radix)
         {
             if (number == "")
             {
@@ -164,9 +164,9 @@ namespace Jint.Native.Global
         /// <summary>
         /// http://www.ecma-international.org/ecma-262/5.1/#sec-15.1.2.3
         /// </summary>
-        public static double ParseFloat(object thisObject, object[] arguments)
+        public static JsValue ParseFloat(JsValue thisObject, JsValue[] arguments)
         {
-            var inputString = TypeConverter.ToString(arguments.At(0));
+            var inputString = TypeConverter.ToString(arguments.At(0)).AsString();
             var trimmedString = inputString.TrimStart();
 
             var sign = 1;
@@ -315,23 +315,23 @@ namespace Jint.Native.Global
         /// <summary>
         /// http://www.ecma-international.org/ecma-262/5.1/#sec-15.1.2.4
         /// </summary>
-        public static bool IsNaN(object thisObject, object[] arguments)
+        public static JsValue IsNaN(JsValue thisObject, JsValue[] arguments)
         {
-            var x = TypeConverter.ToNumber(arguments[0]);
+            var x = TypeConverter.ToNumber(arguments[0]).AsNumber();
             return double.IsNaN(x);
         }
 
         /// <summary>
         /// http://www.ecma-international.org/ecma-262/5.1/#sec-15.1.2.5
         /// </summary>
-        public static bool IsFinite(object thisObject, object[] arguments)
+        public static JsValue IsFinite(JsValue thisObject, JsValue[] arguments)
         {
             if (arguments.Length != 1)
             {
                 return false;
             }
 
-            var n = TypeConverter.ToNumber(arguments[0]);
+            var n = TypeConverter.ToNumber(arguments[0]).AsNumber();
             if (double.IsNaN(n) || double.IsInfinity(n))
             {
                 return false;
@@ -365,9 +365,9 @@ namespace Jint.Native.Global
         /// <param name="thisObject"></param>
         /// <param name="arguments"></param>
         /// <returns></returns>
-        public string EncodeUri(object thisObject, object[] arguments)
+        public JsValue EncodeUri(JsValue thisObject, JsValue[] arguments)
         {
-            var uriString = TypeConverter.ToString(arguments.At(0));
+            var uriString = TypeConverter.ToString(arguments.At(0)).AsString();
             var unescapedUriSet = UriReserved.Concat(UriUnescaped).Concat(new [] {'#'}).ToArray();
 
             return Encode(uriString, unescapedUriSet);
@@ -380,9 +380,9 @@ namespace Jint.Native.Global
         /// <param name="thisObject"></param>
         /// <param name="arguments"></param>
         /// <returns></returns>
-        public string EncodeUriComponent(object thisObject, object[] arguments)
+        public JsValue EncodeUriComponent(JsValue thisObject, JsValue[] arguments)
         {
-            var uriString = TypeConverter.ToString(arguments.At(0));
+            var uriString = TypeConverter.ToString(arguments.At(0)).AsString();
 
             return Encode(uriString, UriUnescaped);
         }
@@ -490,17 +490,17 @@ namespace Jint.Native.Global
             return r.ToString();
         }
 
-        public string DecodeUri(object thisObject, object[] arguments)
+        public JsValue DecodeUri(JsValue thisObject, JsValue[] arguments)
         {
-            var uriString = TypeConverter.ToString(arguments.At(0));
+            var uriString = TypeConverter.ToString(arguments.At(0)).AsString();
             var reservedUriSet = UriReserved.Concat(new[] { '#' }).ToArray();
 
             return Decode(uriString, reservedUriSet);
         }
 
-        public string DecodeUriComponent(object thisObject, object[] arguments)
+        public JsValue DecodeUriComponent(JsValue thisObject, JsValue[] arguments)
         {
-            var componentString = TypeConverter.ToString(arguments.At(0));
+            var componentString = TypeConverter.ToString(arguments.At(0)).AsString();
             var reservedUriComponentSet = new char[0];
 
             return Decode(componentString, reservedUriComponentSet);

+ 1 - 1
Jint/Native/ICallable.cs

@@ -2,6 +2,6 @@
 {
     public interface ICallable
     {
-        object Call(object thisObject, object[] arguments);
+        JsValue Call(JsValue thisObject, JsValue[] arguments);
     }
 }

+ 2 - 2
Jint/Native/IConstructor.cs

@@ -4,7 +4,7 @@ namespace Jint.Native
 {
     public interface IConstructor
     {
-        object Call(object thisObject, object[] arguments);
-        ObjectInstance Construct(object[] arguments);
+        JsValue Call(JsValue thisObject, JsValue[] arguments);
+        ObjectInstance Construct(JsValue[] arguments);
     }
 }

+ 2 - 2
Jint/Native/IPrimitiveType.cs → Jint/Native/IPrimitiveInstance.cs

@@ -2,9 +2,9 @@
 
 namespace Jint.Native
 {
-    public interface IPrimitiveType
+    public interface IPrimitiveInstance
     {
         Types Type { get; } 
-        object PrimitiveValue { get; }
+        JsValue PrimitiveValue { get; }
     }
 }

+ 0 - 45
Jint/Native/JsObject.cs

@@ -1,45 +0,0 @@
-using Jint.Native.Object;
-using Jint.Runtime;
-
-namespace Jint.Native
-{
-    public struct JsObject
-    {
-        public JsObject(bool value)
-        {
-            _bool = value;
-            _double = null;
-            _object = null;
-            _string = null;
-            _type = Types.Boolean;
-        }
-
-        public JsObject(double value)
-        {
-            _bool = null;
-            _double = value;
-            _object = null;
-            _string = null;
-            _type = Types.Number;
-        }
-
-        public JsObject(ObjectInstance value)
-        {
-            _bool = null;
-            _double = null;
-            _object = value;
-            _string = null;
-            _type = Types.Object;
-        }
-
-        private bool? _bool;
-
-        private double? _double;
-
-        private ObjectInstance _object;
-
-        private string _string;
-
-        private Types _type;
-    };
-}

+ 340 - 0
Jint/Native/JsValue.cs

@@ -0,0 +1,340 @@
+using System;
+using System.Diagnostics;
+using System.Diagnostics.Contracts;
+using Jint.Native.Object;
+using Jint.Runtime;
+
+namespace Jint.Native
+{
+    [DebuggerTypeProxy(typeof(JsValueDebugView))]
+    public struct JsValue : IEquatable<JsValue>
+    {
+        public static JsValue Undefined = new JsValue(Types.Undefined);
+        public static JsValue Null = new JsValue(Types.Null);
+        public static JsValue False = new JsValue(false);
+        public static JsValue True = new JsValue(true);
+
+        public JsValue(bool value)
+        {
+            _bool = value;
+            _double = null;
+            _object = null;
+            _string = null;
+            _type = Types.Boolean;
+        }
+
+        public JsValue(double value)
+        {
+            _bool = null;
+            _double = value;
+            _object = null;
+            _string = null;
+            _type = Types.Number;
+        }
+
+        public JsValue(string value)
+        {
+            _bool = null;
+            _double = null;
+            _object = null;
+            _string = value;
+            _type = Types.String;
+        }
+
+        public JsValue(ObjectInstance value)
+        {
+            _bool = null;
+            _double = null;
+            _object = value;
+            _string = null;
+            _type = Types.Object;
+        }
+
+        private JsValue(Types type)
+        {
+            _bool = null;
+            _double = null;
+            _object = null;
+            _string = null;
+            _type = type;
+        }
+
+        private readonly bool? _bool;
+
+        private readonly double? _double;
+
+        private readonly ObjectInstance _object;
+
+        private readonly string _string;
+
+        private readonly Types _type;
+
+        [Pure]
+        public bool IsPrimitive()
+        {
+            return _type != Types.Object && _type != Types.None;
+        }
+
+        [Pure]
+        public bool IsUndefined()
+        {
+            return _type == Types.Undefined;
+        }
+        
+        [Pure]
+        public bool IsObject()
+        {
+            return _type == Types.Object;
+        }
+        
+        [Pure]
+        public bool IsString()
+        {
+            return _type == Types.String;
+        }
+
+        [Pure]
+        public bool IsNumber()
+        {
+            return _type == Types.Number;
+        }
+
+        [Pure]
+        public bool IsBoolean()
+        {
+            return _type == Types.Boolean;
+        }
+
+        [Pure]
+        public bool IsNull()
+        {
+            return _type == Types.Null;
+        }
+
+        [Pure]
+        public ObjectInstance AsObject()
+        {
+            if (_type != Types.Object)
+            {
+                throw new ArgumentException("The value is not an object");
+            }
+
+            return _object;
+        }
+
+        public T TryCast<T>(Action<JsValue> fail = null) where T: class
+        {
+            if (!this.IsObject())
+            {
+                return null;
+            }
+
+            var o = this.AsObject();
+            var t = o as T;
+            if (t != null)
+            {
+                return t;
+            }
+            
+            if (fail != null)
+            {
+                fail(this);
+            }
+
+            return null;
+        }
+
+        public bool Is<T>() where T : ObjectInstance
+        {
+            return IsObject() && AsObject() is T;
+        }
+
+        public T As<T>() where T : ObjectInstance
+        {
+            return _object as T;
+        }
+        
+        [Pure]
+        public bool AsBoolean()
+        {
+            if (_type != Types.Boolean)
+            {
+                throw new ArgumentException("The value is not a boolean");
+            }
+
+            if (!_bool.HasValue)
+            {
+                throw new ArgumentException("The value is not defined");
+            }
+
+            return _bool.Value;
+        }
+
+        [Pure]
+        public string AsString()
+        {
+            if (_type != Types.String)
+            {
+                throw new ArgumentException("The value is not a string");
+            }
+
+            if (_string == null)
+            {
+                throw new ArgumentException("The value is not defined");
+            }
+
+            return _string;
+        }
+
+        [Pure]
+        public double AsNumber()
+        {
+            if (_type != Types.Number)
+            {
+                throw new ArgumentException("The value is not a number");
+            }
+
+            if (!_double.HasValue)
+            {
+                throw new ArgumentException("The value is not defined");
+            }
+
+            return _double.Value;
+        }
+
+        public bool Equals(JsValue other)
+        {
+            if (_type != other._type)
+            {
+                return false;
+            }
+
+            switch (_type)
+            {
+                case Types.None:
+                    return false;
+                case Types.Undefined:
+                    return true;
+                case Types.Null:
+                    return true;
+                case Types.Boolean:
+                    return _bool == other._bool;
+                case Types.String:
+                    return _string == other._string;
+                case Types.Number:
+                    return _double == other._double;
+                case Types.Object:
+                    return _object == other._object;
+                default:
+                    throw new ArgumentOutOfRangeException();
+            }
+        }
+
+        public Types Type
+        {
+            get { return _type; }
+        }
+
+        private static readonly Type[] NumberTypes = { typeof(double), typeof(int), typeof(float), typeof(uint), typeof(byte), typeof(short), typeof(ushort), typeof(long), typeof(ulong) };
+        public static JsValue FromObject(object value)
+        {
+            var s = value as string;
+            if (s != null)
+            {
+                return s;
+            }
+
+            if (System.Array.IndexOf(NumberTypes, value.GetType()) != -1)
+            {
+                return (double) value;
+            }
+
+            if (value is bool)
+            {
+                return (bool) value;
+            }
+
+            return Undefined;
+        }
+
+        public static bool operator ==(JsValue a, JsValue b)
+        {
+            return a.Equals(b);
+        }
+
+        public static bool operator !=(JsValue a, JsValue b)
+        {
+            return !a.Equals(b);
+        }
+
+        static public implicit operator JsValue(double value)
+        {
+            return new JsValue(value);
+        }
+
+        static public implicit operator JsValue(bool value)
+        {
+            return new JsValue(value);
+        }
+
+        static public implicit operator JsValue(string value)
+        {
+            return new JsValue(value);
+        }
+
+        static public implicit operator JsValue(ObjectInstance value)
+        {
+            return new JsValue(value);
+        }
+
+        internal class JsValueDebugView
+        {
+            public string Value;
+            public JsValueDebugView(JsValue value)
+            {
+
+                switch (value.Type)
+                {
+                    case Types.None:
+                        Value = "None";
+                        break;
+                    case Types.Undefined:
+                        Value = "undefined";
+                        break;
+                    case Types.Null:
+                        Value = "null";
+                        break;
+                    case Types.Boolean:
+                        Value = value.AsBoolean() + " (bool)";
+                        break;
+                    case Types.String:
+                        Value = value.AsString() + " (string)";
+                        break;
+                    case Types.Number:
+                        Value = value.AsNumber() + " (number)";
+                        break;
+                    case Types.Object:
+                        Value = value.AsObject().GetType().Name;
+                        break;
+                    default:
+                        Value = "Unknown";
+                        break;
+                }
+            }
+        }
+    }
+
+    public static class Undefined
+    {
+        public static JsValue Instance = JsValue.Undefined;
+        public static string Text = "undefined";
+    }
+
+    public static class Null
+    {
+        public static JsValue Instance = JsValue.Null;
+        public static string Text = "null";
+    }
+
+
+}

+ 5 - 5
Jint/Native/Json/JsonInstance.cs

@@ -32,20 +32,20 @@ namespace Jint.Native.Json
         public void Configure()
         {
 
-            FastAddProperty("parse", new ClrFunctionInstance<JsonInstance, object>(Engine, Parse), true, false, true);
-            FastAddProperty("stringify", new ClrFunctionInstance<JsonInstance, object>(Engine, Stringify), true, false, true);
+            FastAddProperty("parse", new ClrFunctionInstance(Engine, Parse), true, false, true);
+            FastAddProperty("stringify", new ClrFunctionInstance(Engine, Stringify), true, false, true);
         }
 
-        public object Parse(JsonInstance thisObject, object[] arguments)
+        public JsValue Parse(JsValue thisObject, JsValue[] arguments)
         {
             var parser = new JsonParser(_engine);
 
             return parser.Parse(arguments[0].ToString());
         }
 
-        public object Stringify(JsonInstance thisObject, object[] arguments)
+        public JsValue Stringify(JsValue thisObject, JsValue[] arguments)
         {
-            object 
+            JsValue 
                 value = Undefined.Instance, 
                 replacer = Undefined.Instance,
                 space = Undefined.Instance;

+ 11 - 10
Jint/Native/Json/JsonParser.cs

@@ -6,7 +6,6 @@ using Jint.Native.Object;
 using Jint.Parser;
 using Jint.Parser.Ast;
 using Jint.Runtime;
-using Jint.Runtime.Descriptors;
 
 namespace Jint.Native.Json
 {
@@ -503,7 +502,7 @@ namespace Jint.Native.Json
             return node;
         }
 
-        public ObjectInstance CreateArrayInstance(IEnumerable<object> values)
+        public ObjectInstance CreateArrayInstance(IEnumerable<JsValue> values)
         {
             return _engine.Array.Construct(values.ToArray());
         }
@@ -582,7 +581,7 @@ namespace Jint.Native.Json
         
         private ObjectInstance ParseJsonArray()
         {
-            var elements = new List<object>();
+            var elements = new List<JsValue>();
 
             Expect("[");
 
@@ -591,7 +590,7 @@ namespace Jint.Native.Json
                 if (Match(","))
                 {
                     Lex();
-                    elements.Add(null);
+                    elements.Add(Null.Instance);
                 }
                 else
                 {
@@ -642,7 +641,7 @@ namespace Jint.Native.Json
             return obj;
         }
 
-        private object ParseJsonValue()
+        private JsValue ParseJsonValue()
         {
             Tokens type = _lookahead.Type;
             MarkStart();
@@ -654,12 +653,12 @@ namespace Jint.Native.Json
             
             if (type == Tokens.String)
             {
-                return Lex().Value;
+                return JsValue.FromObject(Lex().Value);
             }
             
             if (type == Tokens.Number)
             {
-                return Lex().Value;
+                return JsValue.FromObject(Lex().Value);
             }
             
             if (type == Tokens.BooleanLiteral)
@@ -678,15 +677,17 @@ namespace Jint.Native.Json
             }
 
             ThrowUnexpected(Lex());
-            return null; // can't be reached
+
+            // can't be reached
+            return Null.Instance; 
         }
 
-        public object Parse(string code)
+        public JsValue Parse(string code)
         {
             return Parse(code, null);
         }
 
-        public object Parse(string code, ParserOptions options)
+        public JsValue Parse(string code, ParserOptions options)
         {
             _source = code;
             _index = 0;

+ 52 - 47
Jint/Native/Json/JsonSerializer.cs

@@ -21,21 +21,21 @@ namespace Jint.Native.Json
         Stack<object> _stack;
         string _indent, _gap;
         List<string> _propertyList;
-        object _replacerFunction = Undefined.Instance;
+        JsValue _replacerFunction = Undefined.Instance;
 
-        public object Serialize(object value, object replacer, object space)
+        public JsValue Serialize(JsValue value, JsValue replacer, JsValue space)
         {
             _stack = new Stack<object>();
 
-            if (TypeConverter.GetType(replacer) == Types.Object)
+            if (replacer.IsObject())
             {
-                if (replacer is ICallable)
+                if (replacer.AsObject() is ICallable)
                 {
                     _replacerFunction = replacer;
                 }
                 else
                 {
-                    var replacerObj = (ObjectInstance) replacer;
+                    var replacerObj = replacer.AsObject();
                     if (replacerObj.Class == "Array")
                     {
                         _propertyList = new List<string>();
@@ -43,23 +43,22 @@ namespace Jint.Native.Json
 
                     foreach (var property in replacerObj.Properties.Values)
                     {
-                        object v = _engine.GetValue(property);
+                        JsValue v = _engine.GetValue(property);
                         string item = null;
-                        var type = TypeConverter.GetType(v);
-                        if (type == Types.String)
+                        if (v.IsString())
                         {
-                            item = (string)v;
+                            item = v.AsString();
                         }
-                        else if (type == Types.Number)
+                        else if (v.IsNumber())
                         {
-                            item = TypeConverter.ToString(v);
+                            item = TypeConverter.ToString(v).AsString();
                         }
-                        else if (type == Types.Object)
+                        else if (v.IsObject())
                         {
-                            var propertyObj = (ObjectInstance) v;
+                            var propertyObj = v.AsObject();
                             if (propertyObj.Class == "String" || propertyObj.Class == "Number")
                             {
-                                item = TypeConverter.ToString(propertyObj);
+                                item = TypeConverter.ToString(v).AsString();
                             }
                         }
 
@@ -72,12 +71,12 @@ namespace Jint.Native.Json
                 }
             }
 
-            var spaceObj = space as ObjectInstance;
-            if (spaceObj != null)
+            if (space.IsObject())
             {
+                var spaceObj = space.AsObject();
                 if (spaceObj.Class == "Number")
                 {
-                    space = TypeConverter.ToNumber(spaceObj);
+                    space = TypeConverter.ToNumber(spaceObj).AsNumber();
                 }
                 else if (spaceObj.Class == "String")
                 {
@@ -86,13 +85,13 @@ namespace Jint.Native.Json
             }
 
             // defining the gap
-            if (TypeConverter.GetType(space) == Types.Number)
+            if (space.IsNumber())
             {
-                _gap = new System.String(' ', (int) System.Math.Min(10, (double) space));
+                _gap = new System.String(' ', (int) System.Math.Min(10, space.AsNumber()));
             }
-            else if (TypeConverter.GetType(space) == Types.String)
+            else if (space.IsString())
             {
-                var stringSpace = (string) space;
+                var stringSpace = space.AsString();
                 _gap = stringSpace.Length <= 10 ? stringSpace : stringSpace.Substring(0, 10);
             }
             else
@@ -109,35 +108,39 @@ namespace Jint.Native.Json
         private string Str(string key, ObjectInstance holder)
         {
             var value = holder.Get(key);
-            var valueObj = value as ObjectInstance;
-            if (valueObj != null)
+            if (value.IsObject())
             {
-                var toJson = valueObj.Get("toJSON") as ICallable;
-                if (toJson != null)
+                var toJson = value.AsObject().Get("toJSON");
+                if (toJson.IsObject())
                 {
-                    value = toJson.Call(value, Arguments.From(key));
+                    var callableToJson = toJson.AsObject() as ICallable;
+                    if (callableToJson != null)
+                    {
+                        value = callableToJson.Call(value, Arguments.From(key));
+                    }
                 }
             }
             
             if (_replacerFunction != Undefined.Instance)
             {
-                var replacerFunctionCallable = (ICallable)_replacerFunction;
+                var replacerFunctionCallable = (ICallable)_replacerFunction.AsObject();
                 value = replacerFunctionCallable.Call(holder, Arguments.From(key));
             }
 
-            valueObj = value as ObjectInstance;
-            if (valueObj != null)
+            
+            if (value.IsObject())
             {
+                var valueObj = value.AsObject();
                 switch (valueObj.Class)
                 {
                     case "Number":
-                        value = TypeConverter.ToNumber(value);
+                        value = TypeConverter.ToNumber(value).AsNumber();
                         break;
                     case "String":
                         value = TypeConverter.ToString(value);
                         break;
                     case "Boolean":
-                        value = ((IPrimitiveType) value).PrimitiveValue;
+                        value = TypeConverter.ToPrimitive(value);
                         break;
                 }
             }
@@ -147,41 +150,43 @@ namespace Jint.Native.Json
                 return "null";
             }
 
-            if (true.Equals(value))
+            if (value.IsBoolean() && value.AsBoolean())
             {
                 return "true";
             }
 
-            if (false.Equals(value))
+            if (value.IsBoolean() && !value.AsBoolean())
             {
                 return "false";
             }
 
-            if (TypeConverter.GetType(value) == Types.String)
+            if (value.IsString())
             {
-                return Quote((string) value);
+                return Quote(value.AsString());
             }
 
-            if (TypeConverter.GetType(value) == Types.Number)
+            if (value.IsNumber())
             {
-                if (GlobalObject.IsFinite(this, Arguments.From(value)))
+                if (GlobalObject.IsFinite(Undefined.Instance, Arguments.From(value)).AsBoolean())
                 {
-                    return TypeConverter.ToString(value);
+                    return TypeConverter.ToString(value).AsString();
                 }
                 
                 return "null";
             }
 
-            valueObj = value as ObjectInstance;
-            var valueCallable = valueObj as ICallable;
-            if (valueObj != null && valueCallable == null)
+            if (value.IsObject())
             {
-                if (valueObj.Class == "Array")
+                var valueCallable = value.AsObject() as ICallable;
+                if (valueCallable != null)
                 {
-                    return SerializeArray((ArrayInstance)value);
+                    if (value.AsObject().Class == "Array")
+                    {
+                        return SerializeArray(value.As<ArrayInstance>());
+                    }
+
+                    return SerializeObject(value.AsObject());
                 }
-                
-                return SerializeObject(valueObj);
             }
 
             return "null";
@@ -242,7 +247,7 @@ namespace Jint.Native.Json
             var len = TypeConverter.ToUint32(value.Get("length"));
             for (int i = 0; i < len; i++)
             {
-                var strP = Str(TypeConverter.ToString(i), value);
+                var strP = Str(TypeConverter.ToString(i).AsString(), value);
                 partial.Add(strP);
             }
             if (partial.Count == 0)
@@ -293,7 +298,7 @@ namespace Jint.Native.Json
             var k = _propertyList;
             if (k == null)
             {
-                k = value.Properties.Where(x => x.Value.Enumerable.Value).Select(x => x.Key).ToList();
+                k = value.Properties.Where(x => x.Value.Enumerable.Value.AsBoolean()).Select(x => x.Key).ToList();
             }
             var partial = new List<string>();
             foreach (var p in k)

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

@@ -32,24 +32,24 @@ namespace Jint.Native.Math
 
         public void Configure()
         {
-            FastAddProperty("abs", new ClrFunctionInstance<object, double>(Engine, Abs), true, false, true);
-            FastAddProperty("acos", new ClrFunctionInstance<object, double>(Engine, Acos), true, false, true);
-            FastAddProperty("asin", new ClrFunctionInstance<object, double>(Engine, Asin), true, false, true);
-            FastAddProperty("atan", new ClrFunctionInstance<object, double>(Engine, Atan), true, false, true);
-            FastAddProperty("atan2", new ClrFunctionInstance<object, double>(Engine, Atan2), true, false, true);
-            FastAddProperty("ceil", new ClrFunctionInstance<object, double>(Engine, Ceil), true, false, true);
-            FastAddProperty("cos", new ClrFunctionInstance<object, double>(Engine, Cos), true, false, true);
-            FastAddProperty("exp", new ClrFunctionInstance<object, double>(Engine, Exp), true, false, true);
-            FastAddProperty("floor", new ClrFunctionInstance<object, double>(Engine, Floor), true, false, true);
-            FastAddProperty("log", new ClrFunctionInstance<object, double>(Engine, Log), true, false, true);
-            FastAddProperty("max", new ClrFunctionInstance<object, double>(Engine, Max, 2), true, false, true);
-            FastAddProperty("min", new ClrFunctionInstance<object, double>(Engine, Min, 2), true, false, true);
-            FastAddProperty("pow", new ClrFunctionInstance<object, double>(Engine, Pow, 2), true, false, true);
-            FastAddProperty("random", new ClrFunctionInstance<object, double>(Engine, Random), true, false, true);
-            FastAddProperty("round", new ClrFunctionInstance<object, double>(Engine, Round), true, false, true);
-            FastAddProperty("sin", new ClrFunctionInstance<object, double>(Engine, Sin), true, false, true);
-            FastAddProperty("sqrt", new ClrFunctionInstance<object, double>(Engine, Sqrt), true, false, true);
-            FastAddProperty("tan", new ClrFunctionInstance<object, double>(Engine, Tan), true, false, true);
+            FastAddProperty("abs", new ClrFunctionInstance(Engine, Abs), true, false, true);
+            FastAddProperty("acos", new ClrFunctionInstance(Engine, Acos), true, false, true);
+            FastAddProperty("asin", new ClrFunctionInstance(Engine, Asin), true, false, true);
+            FastAddProperty("atan", new ClrFunctionInstance(Engine, Atan), true, false, true);
+            FastAddProperty("atan2", new ClrFunctionInstance(Engine, Atan2), true, false, true);
+            FastAddProperty("ceil", new ClrFunctionInstance(Engine, Ceil), true, false, true);
+            FastAddProperty("cos", new ClrFunctionInstance(Engine, Cos), true, false, true);
+            FastAddProperty("exp", new ClrFunctionInstance(Engine, Exp), true, false, true);
+            FastAddProperty("floor", new ClrFunctionInstance(Engine, Floor), true, false, true);
+            FastAddProperty("log", new ClrFunctionInstance(Engine, Log), true, false, true);
+            FastAddProperty("max", new ClrFunctionInstance(Engine, Max, 2), true, false, true);
+            FastAddProperty("min", new ClrFunctionInstance(Engine, Min, 2), true, false, true);
+            FastAddProperty("pow", new ClrFunctionInstance(Engine, Pow, 2), true, false, true);
+            FastAddProperty("random", new ClrFunctionInstance(Engine, Random), true, false, true);
+            FastAddProperty("round", new ClrFunctionInstance(Engine, Round), true, false, true);
+            FastAddProperty("sin", new ClrFunctionInstance(Engine, Sin), true, false, true);
+            FastAddProperty("sqrt", new ClrFunctionInstance(Engine, Sqrt), true, false, true);
+            FastAddProperty("tan", new ClrFunctionInstance(Engine, Tan), true, false, true);
 
             FastAddProperty("E", System.Math.E, false, false, false);
             FastAddProperty("LN10", System.Math.Log(10), false, false, false);
@@ -62,34 +62,34 @@ namespace Jint.Native.Math
 
         }
 
-        private static double Abs(object thisObject, object[] arguments)
+        private static JsValue Abs(JsValue thisObject, JsValue[] arguments)
         {
-            var x = TypeConverter.ToNumber(arguments[0]);
+            var x = TypeConverter.ToNumber(arguments[0]).AsNumber();
             return System.Math.Abs(x);
         }
 
-        private static double Acos(object thisObject, object[] arguments)
+        private static JsValue Acos(JsValue thisObject, JsValue[] arguments)
         {
-            var x = TypeConverter.ToNumber(arguments[0]);
+            var x = TypeConverter.ToNumber(arguments[0]).AsNumber();
             return System.Math.Acos(x);
         }
 
-        private static double Asin(object thisObject, object[] arguments)
+        private static JsValue Asin(JsValue thisObject, JsValue[] arguments)
         {
-            var x = TypeConverter.ToNumber(arguments[0]);
+            var x = TypeConverter.ToNumber(arguments[0]).AsNumber();
             return System.Math.Asin(x);
         }
 
-        private static double Atan(object thisObject, object[] arguments)
+        private static JsValue Atan(JsValue thisObject, JsValue[] arguments)
         {
-            var x = TypeConverter.ToNumber(arguments[0]);
+            var x = TypeConverter.ToNumber(arguments[0]).AsNumber();
             return System.Math.Atan(x);
         }
 
-        private static double Atan2(object thisObject, object[] arguments)
+        private static JsValue Atan2(JsValue thisObject, JsValue[] arguments)
         {
-            var y = TypeConverter.ToNumber(arguments[0]);
-            var x = TypeConverter.ToNumber(arguments[1]);
+            var y = TypeConverter.ToNumber(arguments[0]).AsNumber();
+            var x = TypeConverter.ToNumber(arguments[1]).AsNumber();
 
             // If either x or y is NaN, the result is NaN.
             if (double.IsNaN(x) || double.IsNaN(y))
@@ -234,70 +234,70 @@ namespace Jint.Native.Math
             return System.Math.Atan2(y, x);
         }
 
-        private static double Ceil(object thisObject, object[] arguments)
+        private static JsValue Ceil(JsValue thisObject, JsValue[] arguments)
         {
-            var x = TypeConverter.ToNumber(arguments[0]);
+            var x = TypeConverter.ToNumber(arguments[0]).AsNumber();
             return System.Math.Ceiling(x);
         }
 
-        private static double Cos(object thisObject, object[] arguments)
+        private static JsValue Cos(JsValue thisObject, JsValue[] arguments)
         {
-            var x = TypeConverter.ToNumber(arguments[0]);
+            var x = TypeConverter.ToNumber(arguments[0]).AsNumber();
             return System.Math.Cos(x);
         }
 
-        private static double Exp(object thisObject, object[] arguments)
+        private static JsValue Exp(JsValue thisObject, JsValue[] arguments)
         {
-            var x = TypeConverter.ToNumber(arguments[0]);
+            var x = TypeConverter.ToNumber(arguments[0]).AsNumber();
             return System.Math.Exp(x);
         }
 
-        private static double Floor(object thisObject, object[] arguments)
+        private static JsValue Floor(JsValue thisObject, JsValue[] arguments)
         {
-            var x = TypeConverter.ToNumber(arguments[0]);
+            var x = TypeConverter.ToNumber(arguments[0]).AsNumber();
             return System.Math.Floor(x);
         }
 
-        private static double Log(object thisObject, object[] arguments)
+        private static JsValue Log(JsValue thisObject, JsValue[] arguments)
         {
-            var x = TypeConverter.ToNumber(arguments[0]);
+            var x = TypeConverter.ToNumber(arguments[0]).AsNumber();
             return System.Math.Log(x);
         }
 
-        private static double Max(object thisObject, object[] arguments)
+        private static JsValue Max(JsValue thisObject, JsValue[] arguments)
         {
             if (arguments.Length == 0)
             {
                 return Double.NegativeInfinity;
             }
 
-            double max = TypeConverter.ToNumber(arguments[0]);
+            double max = TypeConverter.ToNumber(arguments[0]).AsNumber();
             for (int i = 0; i < arguments.Length; i++)
             {
-                max = System.Math.Max(max, TypeConverter.ToNumber(arguments[i]));
+                max = System.Math.Max(max, TypeConverter.ToNumber(arguments[i]).AsNumber());
             }
             return max;
         }
 
-        private static double Min(object thisObject, object[] arguments)
+        private static JsValue Min(JsValue thisObject, JsValue[] arguments)
         {
             if (arguments.Length == 0)
             {
                 return Double.PositiveInfinity;
             }
-            
-            double min = TypeConverter.ToNumber(arguments[0]);
+
+            double min = TypeConverter.ToNumber(arguments[0]).AsNumber();
             for (int i = 0; i < arguments.Length; i++)
             {
-                min = System.Math.Min(min, TypeConverter.ToNumber(arguments[i]));
+                min = System.Math.Min(min, TypeConverter.ToNumber(arguments[i]).AsNumber());
             }
             return min;
         }
 
-        private static double Pow(object thisObject, object[] arguments)
+        private static JsValue Pow(JsValue thisObject, JsValue[] arguments)
         {
-            var x = TypeConverter.ToNumber(arguments[0]);
-            var y = TypeConverter.ToNumber(arguments[1]);
+            var x = TypeConverter.ToNumber(arguments[0]).AsNumber();
+            var y = TypeConverter.ToNumber(arguments[1]).AsNumber();
 
             if (double.IsNaN(y))
             {
@@ -436,14 +436,14 @@ namespace Jint.Native.Math
             return System.Math.Pow(x, y);
         }
 
-        private static double Random(object thisObject, object[] arguments)
+        private static JsValue Random(JsValue thisObject, JsValue[] arguments)
         {
             return new Random().NextDouble();
         }
 
-        private static double Round(object thisObject, object[] arguments)
+        private static JsValue Round(JsValue thisObject, JsValue[] arguments)
         {
-            var x = TypeConverter.ToNumber(arguments[0]);
+            var x = TypeConverter.ToNumber(arguments[0]).AsNumber();
             var round = System.Math.Round(x);
             if (round == x - 0.5)
             {
@@ -453,21 +453,21 @@ namespace Jint.Native.Math
             return round;
         }
 
-        private static double Sin(object thisObject, object[] arguments)
+        private static JsValue Sin(JsValue thisObject, JsValue[] arguments)
         {
-            var x = TypeConverter.ToNumber(arguments[0]);
+            var x = TypeConverter.ToNumber(arguments[0]).AsNumber();
             return System.Math.Sin(x);
         }
 
-        private static double Sqrt(object thisObject, object[] arguments)
+        private static JsValue Sqrt(JsValue thisObject, JsValue[] arguments)
         {
-            var x = TypeConverter.ToNumber(arguments[0]);
+            var x = TypeConverter.ToNumber(arguments[0]).AsNumber();
             return System.Math.Sqrt(x);
         }
 
-        private static double Tan(object thisObject, object[] arguments)
+        private static JsValue Tan(JsValue thisObject, JsValue[] arguments)
         {
-            var x = TypeConverter.ToNumber(arguments[0]);
+            var x = TypeConverter.ToNumber(arguments[0]).AsNumber();
             return System.Math.Tan(x);
         }
 

+ 0 - 29
Jint/Native/Null.cs

@@ -1,29 +0,0 @@
-using System;
-using Jint.Runtime;
-
-namespace Jint.Native
-{
-    public sealed class Null : IPrimitiveType
-    {
-        public static object Instance = new Null();
-
-        private Null()
-        {   
-        }
-
-        public override string ToString()
-        {
-            return "null";
-        }
-
-        public Types Type
-        {
-            get { return Types.Null; }
-        }
-
-        public object PrimitiveValue
-        {
-            get { return Instance; }
-        }
-    }
-}

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

@@ -40,14 +40,14 @@ namespace Jint.Native.Number
             FastAddProperty("POSITIVE_INFINITY", double.PositiveInfinity, false, false, false);
         }
 
-        public override object Call(object thisObject, object[] arguments)
+        public override JsValue Call(JsValue thisObject, JsValue[] arguments)
         {
             if (arguments.Length == 0)
             {
                 return 0d;
             }
 
-            return TypeConverter.ToNumber(arguments[0]);
+            return TypeConverter.ToNumber(arguments[0]).AsNumber();
         }
 
         /// <summary>
@@ -55,9 +55,9 @@ namespace Jint.Native.Number
         /// </summary>
         /// <param name="arguments"></param>
         /// <returns></returns>
-        public ObjectInstance Construct(object[] arguments)
+        public ObjectInstance Construct(JsValue[] arguments)
         {
-            return Construct(arguments.Length > 0 ? TypeConverter.ToNumber(arguments[0]) : 0);
+            return Construct(arguments.Length > 0 ? TypeConverter.ToNumber(arguments[0]).AsNumber() : 0);
         }
 
         public NumberPrototype PrototypeObject { get; private set; }

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

@@ -4,7 +4,7 @@ using Jint.Runtime;
 
 namespace Jint.Native.Number
 {
-    public class NumberInstance : ObjectInstance, IPrimitiveType
+    public class NumberInstance : ObjectInstance, IPrimitiveInstance
     {
         private static readonly long NegativeZeroBits = BitConverter.DoubleToInt64Bits(-0.0);
 
@@ -21,17 +21,17 @@ namespace Jint.Native.Number
             }
         }
 
-        Types IPrimitiveType.Type
+        Types IPrimitiveInstance.Type
         {
             get { return Types.Number; }
         }
 
-        object IPrimitiveType.PrimitiveValue
+        JsValue IPrimitiveInstance.PrimitiveValue
         {
             get { return PrimitiveValue; }
         }
 
-        public double PrimitiveValue { get; set; }
+        public JsValue PrimitiveValue { get; set; }
 
         public static bool IsNegativeZero(double x)
         {

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

@@ -28,22 +28,22 @@ namespace Jint.Native.Number
 
         public void Configure()
         {
-            FastAddProperty("toString", new ClrFunctionInstance<object, string>(Engine, ToNumberString), true, false, true);
-            FastAddProperty("toLocaleString", new ClrFunctionInstance<object, object>(Engine, ToLocaleString), true, false, true);
-            FastAddProperty("valueOf", new ClrFunctionInstance<object, double>(Engine, ValueOf), true, false, true);
-            FastAddProperty("toFixed", new ClrFunctionInstance<object, object>(Engine, ToFixed, 1), true, false, true);
-            FastAddProperty("toExponential", new ClrFunctionInstance<object, object>(Engine, ToExponential), true, false, true);
-            FastAddProperty("toPrecision", new ClrFunctionInstance<object, object>(Engine, ToPrecision), true, false, true);
+            FastAddProperty("toString", new ClrFunctionInstance(Engine, ToNumberString), true, false, true);
+            FastAddProperty("toLocaleString", new ClrFunctionInstance(Engine, ToLocaleString), true, false, true);
+            FastAddProperty("valueOf", new ClrFunctionInstance(Engine, ValueOf), true, false, true);
+            FastAddProperty("toFixed", new ClrFunctionInstance(Engine, ToFixed, 1), true, false, true);
+            FastAddProperty("toExponential", new ClrFunctionInstance(Engine, ToExponential), true, false, true);
+            FastAddProperty("toPrecision", new ClrFunctionInstance(Engine, ToPrecision), true, false, true);
         }
 
-        private object ToLocaleString(object thisObj, object[] arguments)
+        private JsValue ToLocaleString(JsValue thisObj, JsValue[] arguments)
         {
             throw new System.NotImplementedException();
         }
 
-        private double ValueOf(object thisObj, object[] arguments)
+        private JsValue ValueOf(JsValue thisObj, JsValue[] arguments)
         {
-            var number = thisObj as NumberInstance;
+            var number = thisObj.TryCast<NumberInstance>();
             if (number == null)
             {
                 throw new JavaScriptException(Engine.TypeError);
@@ -52,15 +52,15 @@ namespace Jint.Native.Number
             return number.PrimitiveValue;
         }
 
-        private object ToFixed(object thisObj, object[] arguments)
+        private JsValue ToFixed(JsValue thisObj, JsValue[] arguments)
         {
-            var f = (int) TypeConverter.ToInteger(arguments.At(0, 0));
+            var f = (int)TypeConverter.ToInteger(arguments.At(0, 0)).AsNumber();
             if (f < 0 || f > 20)
             {
                 throw new JavaScriptException(Engine.RangeError, "fractionDigits argument must be between 0 and 20");
             }
 
-            var x = TypeConverter.ToNumber(thisObj);
+            var x = TypeConverter.ToNumber(thisObj).AsNumber();
 
             if (double.IsNaN(x))
             {
@@ -77,7 +77,7 @@ namespace Jint.Native.Number
             string m = "";
             if (x >= System.Math.Pow(10, 21))
             {
-                m = TypeConverter.ToString(x);
+                m = TypeConverter.ToString(x).AsString();
             }
             else
             {
@@ -114,27 +114,27 @@ namespace Jint.Native.Number
             return sign + m;
         }
 
-        private object ToExponential(object thisObj, object[] arguments)
+        private JsValue ToExponential(JsValue thisObj, JsValue[] arguments)
         {
             throw new System.NotImplementedException();
         }
 
-        private object ToPrecision(object thisObj, object[] arguments)
+        private JsValue ToPrecision(JsValue thisObj, JsValue[] arguments)
         {
             throw new System.NotImplementedException();
         }
 
-        private string ToNumberString(object thisObject, object[] arguments)
+        private JsValue ToNumberString(JsValue thisObject, JsValue[] arguments)
         {
-            if (TypeConverter.GetType(thisObject) != Types.Number && !(thisObject is NumberInstance))
+            if (!thisObject.IsNumber() && (thisObject.TryCast<NumberInstance>() == null))
             {
                 throw new JavaScriptException(Engine.TypeError);
             }
 
-            return ToNumberString(TypeConverter.ToNumber(thisObject));
+            return ToNumberString(TypeConverter.ToNumber(thisObject).AsNumber());
         }
 
-        public static string ToNumberString(double m) 
+        public static JsValue ToNumberString(double m) 
         {
             if (double.IsNaN(m))
             {

+ 92 - 102
Jint/Native/Object/ObjectConstructor.cs

@@ -1,5 +1,4 @@
-using System;
-using System.Collections.Generic;
+using System.Collections.Generic;
 using System.Linq;
 using Jint.Native.Function;
 using Jint.Native.String;
@@ -35,19 +34,19 @@ namespace Jint.Native.Object
         {
             Prototype = Engine.Function.PrototypeObject;
 
-            FastAddProperty("getPrototypeOf", new ClrFunctionInstance<object, object>(Engine, GetPrototypeOf, 1), true, false, true);
-            FastAddProperty("getOwnPropertyDescriptor", new ClrFunctionInstance<object, object>(Engine, GetOwnPropertyDescriptor, 2), true, false, true);
-            FastAddProperty("getOwnPropertyNames", new ClrFunctionInstance<object, object>(Engine, GetOwnPropertyNames, 1), true, false, true);
-            FastAddProperty("create", new ClrFunctionInstance<object, object>(Engine, Create, 2), true, false, true);
-            FastAddProperty("defineProperty", new ClrFunctionInstance<object, object>(Engine, DefineProperty), true, false, true);
-            FastAddProperty("defineProperties", new ClrFunctionInstance<object, object>(Engine, DefineProperties), true, false, true);
-            FastAddProperty("seal", new ClrFunctionInstance<object, object>(Engine, Seal, 1), true, false, true);
-            FastAddProperty("freeze", new ClrFunctionInstance<object, object>(Engine, Freeze, 1), true, false, true);
-            FastAddProperty("preventExtensions", new ClrFunctionInstance<object, object>(Engine, PreventExtensions, 1), true, false, true);
-            FastAddProperty("isSealed", new ClrFunctionInstance<object, object>(Engine, IsSealed, 1), true, false, true);
-            FastAddProperty("isFrozen", new ClrFunctionInstance<object, object>(Engine, IsFrozen, 1), true, false, true);
-            FastAddProperty("isExtensible", new ClrFunctionInstance<object, object>(Engine, IsExtensible, 1), true, false, true);
-            FastAddProperty("keys", new ClrFunctionInstance<object, object>(Engine, Keys), true, false, true);
+            FastAddProperty("getPrototypeOf", new ClrFunctionInstance(Engine, GetPrototypeOf, 1), true, false, true);
+            FastAddProperty("getOwnPropertyDescriptor", new ClrFunctionInstance(Engine, GetOwnPropertyDescriptor, 2), true, false, true);
+            FastAddProperty("getOwnPropertyNames", new ClrFunctionInstance(Engine, GetOwnPropertyNames, 1), true, false, true);
+            FastAddProperty("create", new ClrFunctionInstance(Engine, Create, 2), true, false, true);
+            FastAddProperty("defineProperty", new ClrFunctionInstance(Engine, DefineProperty), true, false, true);
+            FastAddProperty("defineProperties", new ClrFunctionInstance(Engine, DefineProperties), true, false, true);
+            FastAddProperty("seal", new ClrFunctionInstance(Engine, Seal, 1), true, false, true);
+            FastAddProperty("freeze", new ClrFunctionInstance(Engine, Freeze, 1), true, false, true);
+            FastAddProperty("preventExtensions", new ClrFunctionInstance(Engine, PreventExtensions, 1), true, false, true);
+            FastAddProperty("isSealed", new ClrFunctionInstance(Engine, IsSealed, 1), true, false, true);
+            FastAddProperty("isFrozen", new ClrFunctionInstance(Engine, IsFrozen, 1), true, false, true);
+            FastAddProperty("isExtensible", new ClrFunctionInstance(Engine, IsExtensible, 1), true, false, true);
+            FastAddProperty("keys", new ClrFunctionInstance(Engine, Keys), true, false, true);
         }
 
         public ObjectPrototype PrototypeObject { get; private set; }
@@ -58,7 +57,7 @@ namespace Jint.Native.Object
         /// <param name="thisObject"></param>
         /// <param name="arguments"></param>
         /// <returns></returns>
-        public override object Call(object thisObject, object[] arguments)
+        public override JsValue Call(JsValue thisObject, JsValue[] arguments)
         {
             if (arguments.Length == 0)
             {
@@ -78,20 +77,20 @@ namespace Jint.Native.Object
         /// </summary>
         /// <param name="arguments"></param>
         /// <returns></returns>
-        public ObjectInstance Construct(object[] arguments)
+        public ObjectInstance Construct(JsValue[] arguments)
         {
             if (arguments.Length > 0)
             {
                 var value = arguments[0];
-                var valueObj = value as ObjectInstance;
+                var valueObj = value.TryCast<ObjectInstance>();
                 if (valueObj != null)
                 {
                     return valueObj;
                 }
-                var type = TypeConverter.GetType(value);
+                var type = value.Type;
                 if (type == Types.String || type == Types.Number || type == Types.Boolean)
                 {
-                    return TypeConverter.ToObject(_engine, value);
+                    return TypeConverter.ToObject(_engine, value).AsObject();
                 }
             }
 
@@ -104,53 +103,50 @@ namespace Jint.Native.Object
             return obj;
         }
 
-        public object GetPrototypeOf(object thisObject, object[] arguments)
+        public JsValue GetPrototypeOf(JsValue thisObject, JsValue[] arguments)
         {
-            var oArg = arguments.Length > 0 ? arguments[0] : Undefined.Instance;
-            if (TypeConverter.GetType(oArg) != Types.Object)
+            var oArg = arguments.At(0);
+            var o = oArg.TryCast<ObjectInstance>();
+            if (o == null)
             {
                 throw new JavaScriptException(Engine.TypeError);
             }
-
-            var o = oArg as ObjectInstance;
-
+            
             return o.Prototype ?? Null.Instance;
         }
 
-        public object GetOwnPropertyDescriptor(object thisObject, object[] arguments)
+        public JsValue GetOwnPropertyDescriptor(JsValue thisObject, JsValue[] arguments)
         {
-            var oArg = arguments.Length > 0 ? arguments[0] : Undefined.Instance;
-            if (TypeConverter.GetType(oArg) != Types.Object)
+            var oArg = arguments.At(0);
+            var o = oArg.TryCast<ObjectInstance>();
+            if (o == null)
             {
                 throw new JavaScriptException(Engine.TypeError);
             }
 
-            var o = oArg as ObjectInstance;
-
-            var p = arguments.Length > 1 ? arguments[1] : Undefined.Instance;
-            var name = TypeConverter.ToString(p);
+            var p = arguments.At(1);
+            var name = TypeConverter.ToString(p).AsString();
 
             var desc = o.GetOwnProperty(name);
             return PropertyDescriptor.FromPropertyDescriptor(Engine, desc);
         }
 
-        public object GetOwnPropertyNames(object thisObject, object[] arguments)
+        public JsValue GetOwnPropertyNames(JsValue thisObject, JsValue[] arguments)
         {
-            var oArg = arguments.Length > 0 ? arguments[0] : Undefined.Instance;
-            if (TypeConverter.GetType(oArg) != Types.Object)
+            var oArg = arguments.At(0);
+            var o = oArg.TryCast<ObjectInstance>();
+            if (o == null)
             {
                 throw new JavaScriptException(Engine.TypeError);
             }
 
-            var o = oArg as ObjectInstance;
-
             var array = Engine.Array.Construct(Arguments.Empty);
             var n = 0;
 
             var s = o as StringInstance;
             if (s != null)
             {
-                for (var i = 0; i < s.PrimitiveValue.Length; i++)
+                for (var i = 0; i < s.PrimitiveValue.AsString().Length; i++)
                 {
                     array.DefineOwnProperty(n.ToString(), new PropertyDescriptor(i.ToString(), true, true, true), false);
                     n++;
@@ -166,18 +162,19 @@ namespace Jint.Native.Object
             return array;
         }
 
-        public object Create(object thisObject, object[] arguments)
+        public JsValue Create(JsValue thisObject, JsValue[] arguments)
         {
             var oArg = arguments.At(0);
-            if (TypeConverter.GetType(oArg) != Types.Object && oArg != Null.Instance)
+            var o = oArg.TryCast<ObjectInstance>();
+            if (o == null)
             {
                 throw new JavaScriptException(Engine.TypeError);
             }
 
             var obj = Engine.Object.Construct(Arguments.Empty);
-            obj.Prototype = oArg as ObjectInstance;
+            obj.Prototype = o;
 
-            var properties = arguments.Length > 1 ? arguments[1] : Undefined.Instance;
+            var properties = arguments.At(1);
             if (properties != Undefined.Instance)
             {
                 DefineProperties(thisObject, new [] {obj, properties});
@@ -186,40 +183,40 @@ namespace Jint.Native.Object
             return obj;
         }
 
-        public object DefineProperty(object thisObject, object[] arguments)
+        public JsValue DefineProperty(JsValue thisObject, JsValue[] arguments)
         {
-            var o = arguments.At(0);
-            if (TypeConverter.GetType(o) != Types.Object)
+            var oArg = arguments.At(0);
+            var o = oArg.TryCast<ObjectInstance>();
+            if (o == null)
             {
                 throw new JavaScriptException(Engine.TypeError);
             }
 
             var p = arguments.At(1);
-            var name = TypeConverter.ToString(p);
+            var name = TypeConverter.ToString(p).AsString();
 
             var attributes = arguments.At(2);
             var desc = PropertyDescriptor.ToPropertyDescriptor(Engine, attributes);
 
-            ((ObjectInstance)o).DefineOwnProperty(name, desc, true);
+            o.DefineOwnProperty(name, desc, true);
             return o;
         }
 
-        public object DefineProperties(object thisObject, object[] arguments)
+        public JsValue DefineProperties(JsValue thisObject, JsValue[] arguments)
         {
-            var oArg = arguments.Length > 0 ? arguments[0] : Undefined.Instance;
-            if (TypeConverter.GetType(oArg) != Types.Object)
+            var oArg = arguments.At(0);
+            var o = oArg.TryCast<ObjectInstance>();
+            if (o == null)
             {
                 throw new JavaScriptException(Engine.TypeError);
             }
 
-            var o = oArg as ObjectInstance;
-
-            var properties = arguments.Length > 1 ? arguments[1] : Undefined.Instance;
-            var props = TypeConverter.ToObject(Engine, properties);
+            var properties = arguments.At(1);
+            var props = TypeConverter.ToObject(Engine, properties).AsObject();
             var descriptors = new List<KeyValuePair<string, PropertyDescriptor>>();
             foreach (var p in props.Properties)
             {
-                if (!p.Value.Enumerable.IsPresent)
+                if (!p.Value.Enumerable.HasValue)
                 {
                     continue;
                 }
@@ -236,21 +233,20 @@ namespace Jint.Native.Object
             return o;
         }
 
-        public object Seal(object thisObject, object[] arguments)
+        public JsValue Seal(JsValue thisObject, JsValue[] arguments)
         {
-            var oArg = arguments.Length > 0 ? arguments[0] : Undefined.Instance;
-            if (TypeConverter.GetType(oArg) != Types.Object)
+            var oArg = arguments.At(0);
+            var o = oArg.TryCast<ObjectInstance>();
+            if (o == null)
             {
                 throw new JavaScriptException(Engine.TypeError);
             }
 
-            var o = oArg as ObjectInstance;
-
             foreach (var prop in o.Properties)
             {
-                if (prop.Value.Configurable.Value == true)
+                if (prop.Value.Configurable.HasValue && prop.Value.Configurable.Value.AsBoolean())
                 {
-                    prop.Value.Configurable = new Field<bool>(false);
+                    prop.Value.Configurable = JsValue.False;
                 }
 
                 o.DefineOwnProperty(prop.Key, prop.Value, true);
@@ -261,30 +257,29 @@ namespace Jint.Native.Object
             return o;
         }
 
-        public object Freeze(object thisObject, object[] arguments)
+        public JsValue Freeze(JsValue thisObject, JsValue[] arguments)
         {
-            var oArg = arguments.Length > 0 ? arguments[0] : Undefined.Instance;
-            if (TypeConverter.GetType(oArg) != Types.Object)
+            var oArg = arguments.At(0);
+            var o = oArg.TryCast<ObjectInstance>();
+            if (o == null)
             {
                 throw new JavaScriptException(Engine.TypeError);
             }
 
-            var o = (ObjectInstance)oArg;
-
             var keys = o.Properties.Keys.ToArray();
             foreach (var key in keys)
             {
                 var prop = o.Properties[key];
                 if (prop.IsDataDescriptor())
                 {
-                    if (prop.Writable.IsPresent)
+                    if (prop.Writable.HasValue)
                     {
-                        prop.Writable = new Field<bool>(false);
+                        prop.Writable = JsValue.False;
                     }
                 }
-                if (prop.Configurable.Value == true)
+                if (prop.Configurable.HasValue && prop.Configurable.Value.AsBoolean())
                 {
-                    prop.Configurable = new Field<bool>(false);
+                    prop.Configurable = JsValue.False;
                 }
                 o.DefineOwnProperty(key, prop, true);
             }
@@ -294,31 +289,29 @@ namespace Jint.Native.Object
             return o;
         }
 
-        public object PreventExtensions(object thisObject, object[] arguments)
+        public JsValue PreventExtensions(JsValue thisObject, JsValue[] arguments)
         {
-            var oArg = arguments.Length > 0 ? arguments[0] : Undefined.Instance;
-            if (TypeConverter.GetType(oArg) != Types.Object)
+            var oArg = arguments.At(0);
+            var o = oArg.TryCast<ObjectInstance>();
+            if (o == null)
             {
                 throw new JavaScriptException(Engine.TypeError);
             }
 
-            var o = oArg as ObjectInstance;
-
             o.Extensible = false;
 
             return o;
         }
 
-        public object IsSealed(object thisObject, object[] arguments)
+        public JsValue IsSealed(JsValue thisObject, JsValue[] arguments)
         {
-            var oArg = arguments.Length > 0 ? arguments[0] : Undefined.Instance;
-            if (TypeConverter.GetType(oArg) != Types.Object)
+            var oArg = arguments.At(0);
+            var o = oArg.TryCast<ObjectInstance>();
+            if (o == null)
             {
                 throw new JavaScriptException(Engine.TypeError);
             }
 
-            var o = oArg as ObjectInstance;
-
             foreach (var prop in o.Properties)
             {
                 if (prop.Value.Configurable.Value == true)
@@ -335,26 +328,25 @@ namespace Jint.Native.Object
             return false;
         }
 
-        public object IsFrozen(object thisObject, object[] arguments)
+        public JsValue IsFrozen(JsValue thisObject, JsValue[] arguments)
         {
-            var oArg = arguments.Length > 0 ? arguments[0] : Undefined.Instance;
-            if (TypeConverter.GetType(oArg) != Types.Object)
+            var oArg = arguments.At(0);
+            var o = oArg.TryCast<ObjectInstance>();
+            if (o == null)
             {
                 throw new JavaScriptException(Engine.TypeError);
             }
 
-            var o = oArg as ObjectInstance;
-
             foreach (var prop in o.Properties)
             {
                 if (prop.Value.IsDataDescriptor())
                 {
-                    if (prop.Value.Writable.IsPresent)
+                    if (prop.Value.Writable.HasValue)
                     {
                         return false;
                     }
                 }
-                if (prop.Value.Configurable.Value == true)
+                if (prop.Value.Configurable.HasValue && prop.Value.Configurable.Value.AsBoolean())
                 {
                     return false;
                 }
@@ -368,33 +360,31 @@ namespace Jint.Native.Object
             return false;
         }
 
-        public object IsExtensible(object thisObject, object[] arguments)
+        public JsValue IsExtensible(JsValue thisObject, JsValue[] arguments)
         {
-            var oArg = arguments.Length > 0 ? arguments[0] : Undefined.Instance;
-            if (TypeConverter.GetType(oArg) != Types.Object)
+            var oArg = arguments.At(0);
+            var o = oArg.TryCast<ObjectInstance>();
+            if (o == null)
             {
                 throw new JavaScriptException(Engine.TypeError);
             }
 
-            var o = oArg as ObjectInstance;
-
             return o.Extensible;
         }
 
-        public object Keys(object thisObject, object[] arguments)
+        public JsValue Keys(JsValue thisObject, JsValue[] arguments)
         {
-            var oArg = arguments.Length > 0 ? arguments[0] : Undefined.Instance;
-            if (TypeConverter.GetType(oArg) != Types.Object)
+            var oArg = arguments.At(0);
+            var o = oArg.TryCast<ObjectInstance>();
+            if (o == null)
             {
                 throw new JavaScriptException(Engine.TypeError);
             }
 
-            var o = oArg as ObjectInstance;
-
-            var n = o.Properties.Values.Count(x => x.Enumerable.Value);
-            var array = Engine.Array.Construct(new object[] {n});
+            var n = o.Properties.Values.Count(x => x.Enumerable.HasValue && x.Enumerable.Value.AsBoolean());
+            var array = Engine.Array.Construct(new JsValue[] {n});
             var index = 0;
-            foreach (var prop in o.Properties.Where(x => x.Value.Enumerable.Value))
+            foreach (var prop in o.Properties.Where(x => x.Value.Enumerable.HasValue && x.Value.Enumerable.Value.AsBoolean()))
             {
                 array.DefineOwnProperty(index.ToString(), new PropertyDescriptor(prop.Key, true, true, true), false);
                 index++;

+ 65 - 65
Jint/Native/Object/ObjectInstance.cs

@@ -44,13 +44,13 @@ namespace Jint.Native.Object
         /// </summary>
         /// <param name="propertyName"></param>
         /// <returns></returns>
-        public virtual object Get(string propertyName)
+        public virtual JsValue Get(string propertyName)
         {
             var desc = GetProperty(propertyName);
 
             if (desc == PropertyDescriptor.Undefined)
             {
-                return Undefined.Instance;
+                return JsValue.Undefined;
             }
 
             if (desc.IsDataDescriptor())
@@ -60,17 +60,17 @@ namespace Jint.Native.Object
 
             var getter = desc.Get.Value;
 
-            if (getter == Undefined.Instance || getter == null)
+            if (getter.IsUndefined())
             {
                 return Undefined.Instance;
             }
 
             // if getter is not undefined it must be ICallable
-            var callable = (ICallable)getter;
+            var callable = (ICallable)(getter.AsObject());
             return callable.Call(this, Arguments.Empty);
         }
 
-        public void Set(string name, object value)
+        public void Set(string name, JsValue value)
         {
 
             if (!HasProperty(name))
@@ -147,7 +147,7 @@ namespace Jint.Native.Object
         /// <param name="propertyName"></param>
         /// <param name="value"></param>
         /// <param name="throwOnError"></param>
-        public void Put(string propertyName, object value, bool throwOnError)
+        public void Put(string propertyName, JsValue value, bool throwOnError)
         {
             if (!CanPut(propertyName))
             {
@@ -163,7 +163,7 @@ namespace Jint.Native.Object
 
             if (ownDesc.IsDataDescriptor())
             {
-                var valueDesc = new PropertyDescriptor(value, null, null, null);
+                var valueDesc = new PropertyDescriptor(value: value, writable: null, enumerable:null, configurable:null);
                 DefineOwnProperty(propertyName, valueDesc, throwOnError);
                 return;
             }
@@ -173,8 +173,8 @@ namespace Jint.Native.Object
 
             if (desc.IsAccessorDescriptor())
             {
-                var setter = (ICallable)desc.Set.Value;
-                setter.Call(this, new [] {value});
+                var setter = (ICallable)desc.Set.Value.AsObject();
+                setter.Call(new JsValue(this), new [] {value});
             }
             else
             {
@@ -199,7 +199,7 @@ namespace Jint.Native.Object
             {
                 if (desc.IsAccessorDescriptor())
                 {
-                    if (desc.Set.Value == Undefined.Instance)
+                    if (desc.Set.Value.IsUndefined())
                     {
                         return false;
                     }
@@ -207,7 +207,7 @@ namespace Jint.Native.Object
                     return true;
                 }
 
-                return desc.Writable.Value;
+                return desc.Writable.Value.AsBoolean();
             }
 
             if (Prototype == null)
@@ -224,7 +224,7 @@ namespace Jint.Native.Object
 
             if (inherited.IsAccessorDescriptor())
             {
-                if (inherited.Set.Value == Undefined.Instance)
+                if (inherited.Set.Value.IsUndefined())
                 {
                     return false;
                 }
@@ -238,7 +238,7 @@ namespace Jint.Native.Object
             }
             else
             {
-                return inherited.Writable.Value;
+                return inherited.Writable.Value.AsBoolean();
             }
         }
 
@@ -271,7 +271,7 @@ namespace Jint.Native.Object
                 return true;
             }
 
-            if (desc.Configurable.Value)
+            if (desc.Configurable.Value.AsBoolean())
             {
                 Properties.Remove(propertyName);
                 return true;
@@ -293,27 +293,27 @@ namespace Jint.Native.Object
         /// </summary>
         /// <param name="hint"></param>
         /// <returns></returns>
-        public object DefaultValue(Types hint)
+        public JsValue DefaultValue(Types hint)
         {
             if ((hint == Types.String) || (hint == Types.None && this is StringInstance) || this is DateInstance)
             {
-                var toString = Get("toString");
+                var toString = Get("toString").AsObject();
                 var callable = toString as ICallable;
                 if (callable != null)
                 {
-                    var str = callable.Call(this, Arguments.Empty);
-                    if (TypeConverter.IsPrimitiveValue(str))
+                    var str = callable.Call(new JsValue(this), Arguments.Empty);
+                    if (str.IsPrimitive())
                     {
                         return str;
                     }
                 }
 
-                var valueOf = Get("valueOf");
+                var valueOf = Get("valueOf").AsObject();
                 callable = valueOf as ICallable;
                 if (callable != null)
                 {
-                    var val = callable.Call(this, Arguments.Empty);
-                    if (TypeConverter.IsPrimitiveValue(val))
+                    var val = callable.Call(new JsValue(this), Arguments.Empty);
+                    if (val.IsPrimitive())
                     {
                         return val;
                     }
@@ -324,23 +324,23 @@ namespace Jint.Native.Object
 
             if ((hint == Types.Number) || (hint == Types.None))
             {
-                var valueOf = Get("valueOf");
+                var valueOf = Get("valueOf").AsObject();
                 var callable = valueOf as ICallable;
                 if (callable != null)
                 {
-                    var val = callable.Call(this, Arguments.Empty);
-                    if (TypeConverter.IsPrimitiveValue(val))
+                    var val = callable.Call(new JsValue(this), Arguments.Empty);
+                    if (val.IsPrimitive())
                     {
                         return val;
                     }
                 }
 
-                var toString = Get("toString");
+                var toString = Get("toString").AsObject();
                 callable = toString as ICallable;
                 if (callable != null)
                 {
-                    var str = callable.Call(this, Arguments.Empty);
-                    if (TypeConverter.IsPrimitiveValue(str))
+                    var str = callable.Call(new JsValue(this), Arguments.Empty);
+                    if (str.IsPrimitive())
                     {
                         return str;
                     }
@@ -392,22 +392,22 @@ namespace Jint.Native.Object
             }
 
             // Step 5
-            if(!current.Configurable.IsPresent && !current.Enumerable.IsPresent && !(current.IsDataDescriptor() && current.Writable.IsPresent))
+            if (!current.Configurable.HasValue && !current.Enumerable.HasValue && !(current.IsDataDescriptor() && current.Writable.HasValue))
             {
-                if (!desc.IsDataDescriptor() || desc.Value.Value == null)
+                if (!desc.IsDataDescriptor())
                 {
                     return true;
                 }
             }
 
             // Step 6
-            var configurableIsSame = current.Configurable.IsPresent
-                ? desc.Configurable.IsPresent && (current.Configurable.Value == desc.Configurable.Value)
-                : !desc.Configurable.IsPresent;
+            var configurableIsSame = current.Configurable.HasValue
+                ? desc.Configurable.HasValue && (current.Configurable.Value == desc.Configurable.Value)
+                : !desc.Configurable.HasValue;
 
-            var enumerableIsSame = current.Enumerable.IsPresent
-                ? desc.Enumerable.IsPresent && (current.Enumerable.Value == desc.Enumerable.Value)
-                : !desc.Enumerable.IsPresent;
+            var enumerableIsSame = current.Enumerable.HasValue
+                ? desc.Enumerable.HasValue && (current.Enumerable.Value == desc.Enumerable.Value)
+                : !desc.Enumerable.HasValue;
 
             var writableIsSame = true;
             var valueIsSame = true;
@@ -416,19 +416,19 @@ namespace Jint.Native.Object
             {
                 var currentDataDescriptor = current;
                 var descDataDescriptor = desc;
-                writableIsSame = currentDataDescriptor.Writable.IsPresent
-                ? descDataDescriptor.Writable.IsPresent && (currentDataDescriptor.Writable.Value == descDataDescriptor.Writable.Value)
-                : !descDataDescriptor.Writable.IsPresent;
+                writableIsSame = currentDataDescriptor.Writable.HasValue
+                ? descDataDescriptor.Writable.HasValue && (currentDataDescriptor.Writable.Value == descDataDescriptor.Writable.Value)
+                : !descDataDescriptor.Writable.HasValue;
 
-                valueIsSame = ExpressionInterpreter.SameValue(currentDataDescriptor.Value, descDataDescriptor.Value);
+                valueIsSame = ExpressionInterpreter.SameValue(currentDataDescriptor.Value.Value, descDataDescriptor.Value.Value);
             }
             else if (current.IsAccessorDescriptor() && desc.IsAccessorDescriptor())
             {
                 var currentAccessorDescriptor = current;
                 var descAccessorDescriptor = desc;
 
-                valueIsSame = ExpressionInterpreter.SameValue(currentAccessorDescriptor.Get, descAccessorDescriptor.Get)
-                              && ExpressionInterpreter.SameValue(currentAccessorDescriptor.Set, descAccessorDescriptor.Set);
+                valueIsSame = ExpressionInterpreter.SameValue(currentAccessorDescriptor.Get.Value, descAccessorDescriptor.Get.Value)
+                              && ExpressionInterpreter.SameValue(currentAccessorDescriptor.Set.Value, descAccessorDescriptor.Set.Value);
             }
             else
             {
@@ -440,9 +440,9 @@ namespace Jint.Native.Object
                 return true;
             }
 
-            if (current.Configurable.Value == false)
+            if (!current.Configurable.HasValue || !current.Configurable.Value.AsBoolean())
             {
-                if (desc.Configurable.Value)
+                if (desc.Configurable.HasValue && desc.Configurable.Value.AsBoolean())
                 {
                     if (throwOnError)
                     {
@@ -452,7 +452,7 @@ namespace Jint.Native.Object
                     return false;
                 }
 
-                if (desc.Enumerable.IsPresent && desc.Enumerable.Value != current.Enumerable.Value)
+                if (desc.Enumerable.HasValue && desc.Enumerable.Value != current.Enumerable.Value)
                 {
                     if (throwOnError)
                     {
@@ -468,7 +468,7 @@ namespace Jint.Native.Object
 
                 if (current.IsDataDescriptor() != desc.IsDataDescriptor())
                 {
-                    if (!current.Configurable.Value)
+                    if (!current.Configurable.Value.AsBoolean())
                     {
                         if (throwOnError)
                         {
@@ -483,8 +483,8 @@ namespace Jint.Native.Object
                         Properties[propertyName] = current = new PropertyDescriptor(
                             get: Undefined.Instance,
                             set: Undefined.Instance,
-                            enumerable: current.Enumerable.Value, 
-                            configurable: current.Configurable.Value
+                            enumerable: current.Enumerable.Value.AsBoolean(), 
+                            configurable: current.Configurable.Value.AsBoolean()
                             );
                     }
                     else
@@ -492,16 +492,16 @@ namespace Jint.Native.Object
                         Properties[propertyName] = current = new PropertyDescriptor(
                             value: Undefined.Instance, 
                             writable: null,
-                            enumerable: current.Enumerable.Value, 
-                            configurable: current.Configurable.Value
+                            enumerable: current.Enumerable.Value.AsBoolean(), 
+                            configurable: current.Configurable.Value.AsBoolean()
                             );
                     }
                 }
                 else if (current.IsDataDescriptor() && desc.IsDataDescriptor())
                 {
-                    if (current.Configurable.Value == false)
+                    if (current.Configurable.Value.AsBoolean() == false)
                     {
-                        if (!current.Writable.Value && desc.Writable.Value)
+                        if (!current.Writable.Value.AsBoolean() && desc.Writable.Value.AsBoolean())
                         {
                             if (throwOnError)
                             {
@@ -511,9 +511,9 @@ namespace Jint.Native.Object
                             return false;
                         }
 
-                        if (!current.Writable.Value)
+                        if (!current.Writable.Value.AsBoolean())
                         {
-                            if (desc.Value.IsPresent && !valueIsSame)
+                            if (desc.Value.HasValue && !valueIsSame)
                             {
                                 if (throwOnError)
                                 {
@@ -525,19 +525,19 @@ namespace Jint.Native.Object
                         }
                     }
 
-                    if (desc.Writable.IsAbsent && current.Writable.IsPresent)
+                    if (!desc.Writable.HasValue && current.Writable.HasValue)
                     {
                         desc.Enumerable = current.Enumerable;
                     }
                 }
                 else if (current.IsAccessorDescriptor() && desc.IsAccessorDescriptor())
                 {
-                    if (current.Configurable.Value == false)
+                    if (!current.Configurable.HasValue || !current.Configurable.Value.AsBoolean())
                     {
-                        if ((desc.Set.Value != Undefined.Instance &&
+                        if ((desc.Set.HasValue && desc.Set.Value != Undefined.Instance &&
                              !ExpressionInterpreter.SameValue(desc.Set.Value, current.Set.Value))
                             ||
-                            (desc.Get.Value != Undefined.Instance &&
+                            (desc.Get.HasValue && desc.Get.Value != Undefined.Instance &&
                              !ExpressionInterpreter.SameValue(desc.Get.Value, current.Get.Value)))
                         {
                             if (throwOnError)
@@ -551,32 +551,32 @@ namespace Jint.Native.Object
                 }
             }
 
-            if (desc.Value.IsPresent)
+            if (desc.Value.HasValue)
             {
                 current.Value = desc.Value;
             }
 
-            if (desc.Writable.IsPresent)
+            if (desc.Writable.HasValue)
             {
                 current.Writable = desc.Writable;
             }
 
-            if (desc.Enumerable.IsPresent)
+            if (desc.Enumerable.HasValue)
             {
                 current.Enumerable = desc.Enumerable;
             }
 
-            if (desc.Configurable.IsPresent)
+            if (desc.Configurable.HasValue)
             {
                 current.Configurable = desc.Configurable;
             }
 
-            if (desc.Get.IsPresent)
+            if (desc.Get.HasValue)
             {
                 current.Get = desc.Get;
             }
 
-            if (desc.Set.IsPresent)
+            if (desc.Set.HasValue)
             {
                 current.Set = desc.Set;
             }
@@ -592,7 +592,7 @@ namespace Jint.Native.Object
         /// <param name="writable"></param>
         /// <param name="configurable"></param>
         /// <param name="enumerable"></param>
-        public void FastAddProperty(string name, object value, bool writable, bool enumerable, bool configurable)
+        public void FastAddProperty(string name, JsValue value, bool writable, bool enumerable, bool configurable)
         {
             Properties.Add(name, new PropertyDescriptor(value, writable, enumerable, configurable));
         }
@@ -609,7 +609,7 @@ namespace Jint.Native.Object
 
         public override string ToString()
         {
-            return TypeConverter.ToString(this);
+            return TypeConverter.ToString(this).AsString();
         }
     }
 }

+ 26 - 28
Jint/Native/Object/ObjectPrototype.cs

@@ -1,5 +1,4 @@
-using System;
-using Jint.Runtime;
+using Jint.Runtime;
 using Jint.Runtime.Descriptors;
 using Jint.Runtime.Interop;
 
@@ -22,36 +21,36 @@ namespace Jint.Native.Object
 
         public void Configure()
         {
-            FastAddProperty("toString", new ClrFunctionInstance<object, string>(Engine, ToObjectString), true, false, true);
-            FastAddProperty("toLocaleString", new ClrFunctionInstance<object, object>(Engine, ToLocaleString), true, false, true);
-            FastAddProperty("valueOf", new ClrFunctionInstance<object, object>(Engine, ValueOf), true, false, true);
-            FastAddProperty("hasOwnProperty", new ClrFunctionInstance<object, bool>(Engine, HasOwnProperty), true, false, true);
-            FastAddProperty("isPrototypeOf", new ClrFunctionInstance<object, bool>(Engine, IsPrototypeOf), true, false, true);
-            FastAddProperty("propertyIsEnumerable", new ClrFunctionInstance<object, bool>(Engine, PropertyIsEnumerable), true, false, true);
+            FastAddProperty("toString", new ClrFunctionInstance(Engine, ToObjectString), true, false, true);
+            FastAddProperty("toLocaleString", new ClrFunctionInstance(Engine, ToLocaleString), true, false, true);
+            FastAddProperty("valueOf", new ClrFunctionInstance(Engine, ValueOf), true, false, true);
+            FastAddProperty("hasOwnProperty", new ClrFunctionInstance(Engine, HasOwnProperty), true, false, true);
+            FastAddProperty("isPrototypeOf", new ClrFunctionInstance(Engine, IsPrototypeOf), true, false, true);
+            FastAddProperty("propertyIsEnumerable", new ClrFunctionInstance(Engine, PropertyIsEnumerable), true, false, true);
         }
 
-        private bool PropertyIsEnumerable(object thisObject, object[] arguments)
+        private JsValue PropertyIsEnumerable(JsValue thisObject, JsValue[] arguments)
         {
-            var p = TypeConverter.ToString(arguments[0]);
-            var o = TypeConverter.ToObject(Engine, thisObject);
+            var p = TypeConverter.ToString(arguments[0]).AsString();
+            var o = TypeConverter.ToObject(Engine, thisObject).AsObject();
             var desc = o.GetOwnProperty(p);
             if (desc == PropertyDescriptor.Undefined)
             {
                 return false;
             }
-            return desc.Enumerable.Value;
+            return desc.Enumerable.HasValue && desc.Enumerable.Value.AsBoolean();
         }
 
-        private object ValueOf(object thisObject, object[] arguments)
+        private JsValue ValueOf(JsValue thisObject, JsValue[] arguments)
         {
             var o = TypeConverter.ToObject(Engine, thisObject);
             return o;
         }
 
-        private bool IsPrototypeOf(object thisObject, object[] arguments)
+        private JsValue IsPrototypeOf(JsValue thisObject, JsValue[] arguments)
         {
-            var v = arguments[0] as ObjectInstance;
-            if (v == null)
+            var v = arguments[0];
+            if (!v.IsObject())
             {
                 return false;
             }
@@ -59,8 +58,7 @@ namespace Jint.Native.Object
             var o = TypeConverter.ToObject(Engine, thisObject);
             while (true)
             {
-                v = v.Prototype;
-                if (v == null)
+                if (v.AsObject().Prototype == null)
                 {
                     return false;
                 }
@@ -72,14 +70,14 @@ namespace Jint.Native.Object
             }
         }
 
-        private object ToLocaleString(object thisObject, object[] arguments)
+        private JsValue ToLocaleString(JsValue thisObject, JsValue[] arguments)
         {
-            var o = TypeConverter.ToObject(Engine, thisObject);
-            var toString = o.Get("toString") as ICallable;
-            if (toString == null)
+            var o = TypeConverter.ToObject(Engine, thisObject).AsObject();
+            var toString = o.Get("toString").TryCast<ICallable>(x =>
             {
                 throw new JavaScriptException(Engine.TypeError);
-            }
+            });
+
             return toString.Call(o, Arguments.Empty);
         }
 
@@ -89,7 +87,7 @@ namespace Jint.Native.Object
         /// <param name="thisObject"></param>
         /// <param name="arguments"></param>
         /// <returns></returns>
-        public string ToObjectString(object thisObject, object[] arguments)
+        public JsValue ToObjectString(JsValue thisObject, JsValue[] arguments)
         {
             if (thisObject == Undefined.Instance)
             {
@@ -101,7 +99,7 @@ namespace Jint.Native.Object
                 return "[object Null]";
             }
 
-            var o = TypeConverter.ToObject(Engine, thisObject);
+            var o = TypeConverter.ToObject(Engine, thisObject).AsObject();
             return "[object " + o.Class + "]";
         }
 
@@ -111,10 +109,10 @@ namespace Jint.Native.Object
         /// <param name="thisObject"></param>
         /// <param name="arguments"></param>
         /// <returns></returns>
-        public bool HasOwnProperty(object thisObject, object[] arguments)
+        public JsValue HasOwnProperty(JsValue thisObject, JsValue[] arguments)
         {
-            var p = TypeConverter.ToString(arguments[0]);
-            var o = TypeConverter.ToObject(Engine, thisObject);
+            var p = TypeConverter.ToString(arguments[0]).AsString();
+            var o = TypeConverter.ToObject(Engine, thisObject).AsObject();
             var desc = o.GetOwnProperty(p);
             return desc != PropertyDescriptor.Undefined;
         }

+ 8 - 8
Jint/Native/RegExp/RegExpConstructor.cs

@@ -34,12 +34,12 @@ namespace Jint.Native.RegExp
         {
         }
 
-        public override object Call(object thisObject, object[] arguments)
+        public override JsValue Call(JsValue thisObject, JsValue[] arguments)
         {
             var pattern = arguments.At(0);
             var flags = arguments.At(1);
 
-            if (pattern != Undefined.Instance && flags == Undefined.Instance && TypeConverter.ToObject(Engine, pattern).Class == "Regex")
+            if (pattern != Undefined.Instance && flags == Undefined.Instance && TypeConverter.ToObject(Engine, pattern).AsObject().Class == "Regex")
             {
                 return pattern;
             }
@@ -52,7 +52,7 @@ namespace Jint.Native.RegExp
         /// </summary>
         /// <param name="arguments"></param>
         /// <returns></returns>
-        public ObjectInstance Construct(object[] arguments)
+        public ObjectInstance Construct(JsValue[] arguments)
         {
             string p;
             string f;
@@ -60,20 +60,20 @@ namespace Jint.Native.RegExp
             var pattern = arguments.At(0);
             var flags = arguments.At(1);
 
-            var r = pattern as RegExpInstance;
-            if (pattern != null && flags == Undefined.Instance && r != null)
+            var r = pattern.TryCast<RegExpInstance>();
+            if (pattern.AsString() != null && flags == Undefined.Instance && r != null)
             {
                 p = r.Pattern;
                 f = r.Flags;
             }
-            else if (pattern != null && flags != Undefined.Instance && r != null)
+            else if (pattern.AsString() != null && flags != Undefined.Instance && r != null)
             {
                 throw new JavaScriptException(Engine.TypeError);
             }
             else
             {
-                p = pattern != Undefined.Instance ? TypeConverter.ToString(pattern) : "";
-                f = flags != Undefined.Instance ? TypeConverter.ToString(flags) : "";
+                p = pattern != Undefined.Instance ? TypeConverter.ToString(pattern).AsString() : "";
+                f = flags != Undefined.Instance ? TypeConverter.ToString(flags).AsString() : "";
             }
 
             r = new RegExpInstance(Engine);

+ 30 - 28
Jint/Native/RegExp/RegExpPrototype.cs

@@ -25,48 +25,50 @@ namespace Jint.Native.RegExp
 
         public void Configure()
         {
-            FastAddProperty("toString", new ClrFunctionInstance<RegExpInstance, object>(Engine, ToRegExpString), true, false, true);
-            FastAddProperty("exec", new ClrFunctionInstance<object, object>(Engine, Exec, 1), true, false, true);
-            FastAddProperty("test", new ClrFunctionInstance<object, bool>(Engine, Test, 1), true, false, true);
-
-            FastAddProperty("global", new ClrFunctionInstance<RegExpInstance, bool>(Engine, GetGlobal, 1), false, false, false);
-            FastAddProperty("ignoreCase", new ClrFunctionInstance<RegExpInstance, bool>(Engine, GetIgnoreCase, 1), false, false, false);
-            FastAddProperty("multiline", new ClrFunctionInstance<RegExpInstance, bool>(Engine, GetMultiLine, 1), false, false, false);
-            FastAddProperty("source", new ClrFunctionInstance<RegExpInstance, string>(Engine, GetSource, 1), false, false, false);
+            FastAddProperty("toString", new ClrFunctionInstance(Engine, ToRegExpString), true, false, true);
+            FastAddProperty("exec", new ClrFunctionInstance(Engine, Exec, 1), true, false, true);
+            FastAddProperty("test", new ClrFunctionInstance(Engine, Test, 1), true, false, true);
+
+            FastAddProperty("global", new ClrFunctionInstance(Engine, GetGlobal, 1), false, false, false);
+            FastAddProperty("ignoreCase", new ClrFunctionInstance(Engine, GetIgnoreCase, 1), false, false, false);
+            FastAddProperty("multiline", new ClrFunctionInstance(Engine, GetMultiLine, 1), false, false, false);
+            FastAddProperty("source", new ClrFunctionInstance(Engine, GetSource, 1), false, false, false);
         }
 
-        private bool GetGlobal(RegExpInstance thisObj, object[] arguments)
+        private JsValue GetGlobal(JsValue thisObj, JsValue[] arguments)
         {
-            return thisObj.Global;
+            return thisObj.TryCast<RegExpInstance>().Global;
         }
-        private bool GetMultiLine(RegExpInstance thisObj, object[] arguments)
+        private JsValue GetMultiLine(JsValue thisObj, JsValue[] arguments)
         {
-            return thisObj.Multiline;
+            return thisObj.TryCast<RegExpInstance>().Multiline;
         }
 
-        private bool GetIgnoreCase(RegExpInstance thisObj, object[] arguments)
+        private JsValue GetIgnoreCase(JsValue thisObj, JsValue[] arguments)
         {
-            return thisObj.IgnoreCase;
+            return thisObj.TryCast<RegExpInstance>().IgnoreCase;
         }
 
-        private string GetSource(RegExpInstance thisObj, object[] arguments)
+        private JsValue GetSource(JsValue thisObj, JsValue[] arguments)
         {
-            return thisObj.Source;
+            return thisObj.TryCast<RegExpInstance>().Source;
         }
 
-        private object ToRegExpString(RegExpInstance thisObj, object[] arguments)
+        private JsValue ToRegExpString(JsValue thisObj, JsValue[] arguments)
         {
-            return "/" + thisObj.Source + "/" 
-                + (thisObj.Flags.Contains("g") ? "g" : "")
-                + (thisObj.Flags.Contains("i") ? "i" : "")
-                + (thisObj.Flags.Contains("m") ? "m" : "")
+            var regExp = thisObj.TryCast<RegExpInstance>();
+
+            return "/" + regExp.Source + "/"
+                + (regExp.Flags.Contains("g") ? "g" : "")
+                + (regExp.Flags.Contains("i") ? "i" : "")
+                + (regExp.Flags.Contains("m") ? "m" : "")
                 ;
         }
 
-        private bool Test(object thisObj, object[] arguments)
+        private JsValue Test(JsValue thisObj, JsValue[] arguments)
         {
             var r = TypeConverter.ToObject(Engine, thisObj);
-            if (r.Class != "RegExp")
+            if (r.AsObject().Class != "RegExp")
             {
                 throw new JavaScriptException(Engine.TypeError);
             }
@@ -75,18 +77,18 @@ namespace Jint.Native.RegExp
             return match != Null.Instance;
         }
 
-        internal object Exec(object thisObj, object[] arguments)
+        internal JsValue Exec(JsValue thisObj, JsValue[] arguments)
         {
-            var R = TypeConverter.ToObject(Engine, thisObj) as RegExpInstance;
+            var R = TypeConverter.ToObject(Engine, thisObj).TryCast<RegExpInstance>();
             if (R == null)
             {
                 throw new JavaScriptException(Engine.TypeError);
             }
 
-            var s = TypeConverter.ToString(arguments.Length > 0 ? arguments[0] : Undefined.Instance);
+            var s = TypeConverter.ToString(arguments.At(0)).AsString();
             var length = s.Length;
-            var lastIndex = TypeConverter.ToNumber(R.Get("lastIndex"));
-            var i = TypeConverter.ToInteger(lastIndex);
+            var lastIndex = TypeConverter.ToNumber(R.Get("lastIndex")).AsNumber();
+            var i = TypeConverter.ToInteger(lastIndex).AsNumber();
             var global = R.Global;
             
             if (!global)

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

@@ -31,10 +31,10 @@ namespace Jint.Native.String
 
         public void Configure()
         {
-            FastAddProperty("fromCharCode", new ClrFunctionInstance<object, string>(Engine, FromCharCode, 1), true, false, true);
+            FastAddProperty("fromCharCode", new ClrFunctionInstance(Engine, FromCharCode, 1), true, false, true);
         }
 
-        private static string FromCharCode(object thisObj, object[] arguments)
+        private static JsValue FromCharCode(JsValue thisObj, JsValue[] arguments)
         {
             var chars = new char[arguments.Length];
             for (var i = 0; i < chars.Length; i++ )
@@ -45,7 +45,7 @@ namespace Jint.Native.String
             return new System.String(chars);
         }
 
-        public override object Call(object thisObject, object[] arguments)
+        public override JsValue Call(JsValue thisObject, JsValue[] arguments)
         {
             if (arguments.Length == 0)
             {
@@ -60,9 +60,9 @@ namespace Jint.Native.String
         /// </summary>
         /// <param name="arguments"></param>
         /// <returns></returns>
-        public ObjectInstance Construct(object[] arguments)
+        public ObjectInstance Construct(JsValue[] arguments)
         {
-            return Construct(arguments.Length > 0 ? TypeConverter.ToString(arguments[0]) : "");
+            return Construct(arguments.Length > 0 ? TypeConverter.ToString(arguments[0]).AsString() : "");
         }
 
         public StringPrototype PrototypeObject { get; private set; }

+ 9 - 9
Jint/Native/String/StringInstance.cs

@@ -4,7 +4,7 @@ using Jint.Runtime.Descriptors;
 
 namespace Jint.Native.String
 {
-    public class StringInstance : ObjectInstance, IPrimitiveType
+    public class StringInstance : ObjectInstance, IPrimitiveInstance
     {
         public StringInstance(Engine engine)
             : base(engine)
@@ -19,17 +19,17 @@ namespace Jint.Native.String
             }
         }
 
-        Types IPrimitiveType.Type
+        Types IPrimitiveInstance.Type
         {
             get { return Types.String; }
         }
 
-        object IPrimitiveType.PrimitiveValue
+        JsValue IPrimitiveInstance.PrimitiveValue
         {
             get { return PrimitiveValue; }
         }
 
-        public string PrimitiveValue { get; set; }
+        public JsValue PrimitiveValue { get; set; }
 
         public override PropertyDescriptor GetOwnProperty(string propertyName)
         {
@@ -39,20 +39,20 @@ namespace Jint.Native.String
                 return desc;
             }
 
-            if (propertyName != System.Math.Abs(TypeConverter.ToInteger(propertyName)).ToString())
+            if (propertyName != System.Math.Abs(TypeConverter.ToInteger(propertyName).AsNumber()).ToString())
             {
                 return PropertyDescriptor.Undefined;
             }
 
             var str = PrimitiveValue;
-            var index = (int)TypeConverter.ToInteger(propertyName);
-            var len = str.Length;
+            var index = (int)TypeConverter.ToInteger(propertyName).AsNumber();
+            var len = str.AsString().Length;
             if (len <= index)
             {
                 return PropertyDescriptor.Undefined;
             }
-            var resultStr = str[index].ToString();
-            return new PropertyDescriptor(resultStr, false, true, false);
+            var resultStr = str.AsString()[index].ToString();
+            return new PropertyDescriptor(new JsValue(resultStr), false, true, false);
         }
     }
 }

+ 95 - 99
Jint/Native/String/StringPrototype.cs

@@ -35,30 +35,30 @@ namespace Jint.Native.String
 
         public void Configure()
         {
-            FastAddProperty("toString", new ClrFunctionInstance<object, string>(Engine, ToStringString), true, false, true);
-            FastAddProperty("valueOf", new ClrFunctionInstance<object, string>(Engine, ValueOf), true, false, true);
-            FastAddProperty("charAt", new ClrFunctionInstance<object, object>(Engine, CharAt, 1), true, false, true);
-            FastAddProperty("charCodeAt", new ClrFunctionInstance<object, object>(Engine, CharCodeAt, 1), true, false, true);
-            FastAddProperty("concat", new ClrFunctionInstance<object, string>(Engine, Concat, 1), true, false, true);
-            FastAddProperty("indexOf", new ClrFunctionInstance<object, double>(Engine, IndexOf, 1), true, false, true);
-            FastAddProperty("lastIndexOf", new ClrFunctionInstance<object, double>(Engine, LastIndexOf, 1), true, false, true);
-            FastAddProperty("localeCompare", new ClrFunctionInstance<object, double>(Engine, LocaleCompare), true, false, true);
-            FastAddProperty("match", new ClrFunctionInstance<object, object>(Engine, Match, 1), true, false, true);
-            FastAddProperty("replace", new ClrFunctionInstance<object, object>(Engine, Replace, 2), true, false, true);
-            FastAddProperty("search", new ClrFunctionInstance<object, double>(Engine, Search, 1), true, false, true);
-            FastAddProperty("slice", new ClrFunctionInstance<object, string>(Engine, Slice, 2), true, false, true);
-            FastAddProperty("split", new ClrFunctionInstance<object, ArrayInstance>(Engine, Split, 2), true, false, true);
-            FastAddProperty("substring", new ClrFunctionInstance<object, string>(Engine, Substring, 2), true, false, true);
-            FastAddProperty("toLowerCase", new ClrFunctionInstance<object, string>(Engine, ToLowerCase), true, false, true);
-            FastAddProperty("toLocaleLowerCase", new ClrFunctionInstance<object, string>(Engine, ToLocaleLowerCase), true, false, true);
-            FastAddProperty("toUpperCase", new ClrFunctionInstance<object, string>(Engine, ToUpperCase), true, false, true);
-            FastAddProperty("toLocaleUpperCase", new ClrFunctionInstance<object, string>(Engine, ToLocaleUpperCase), true, false, true);
-            FastAddProperty("trim", new ClrFunctionInstance<object, string>(Engine, Trim), true, false, true);
+            FastAddProperty("toString", new ClrFunctionInstance(Engine, ToStringString), true, false, true);
+            FastAddProperty("valueOf", new ClrFunctionInstance(Engine, ValueOf), true, false, true);
+            FastAddProperty("charAt", new ClrFunctionInstance(Engine, CharAt, 1), true, false, true);
+            FastAddProperty("charCodeAt", new ClrFunctionInstance(Engine, CharCodeAt, 1), true, false, true);
+            FastAddProperty("concat", new ClrFunctionInstance(Engine, Concat, 1), true, false, true);
+            FastAddProperty("indexOf", new ClrFunctionInstance(Engine, IndexOf, 1), true, false, true);
+            FastAddProperty("lastIndexOf", new ClrFunctionInstance(Engine, LastIndexOf, 1), true, false, true);
+            FastAddProperty("localeCompare", new ClrFunctionInstance(Engine, LocaleCompare), true, false, true);
+            FastAddProperty("match", new ClrFunctionInstance(Engine, Match, 1), true, false, true);
+            FastAddProperty("replace", new ClrFunctionInstance(Engine, Replace, 2), true, false, true);
+            FastAddProperty("search", new ClrFunctionInstance(Engine, Search, 1), true, false, true);
+            FastAddProperty("slice", new ClrFunctionInstance(Engine, Slice, 2), true, false, true);
+            FastAddProperty("split", new ClrFunctionInstance(Engine, Split, 2), true, false, true);
+            FastAddProperty("substring", new ClrFunctionInstance(Engine, Substring, 2), true, false, true);
+            FastAddProperty("toLowerCase", new ClrFunctionInstance(Engine, ToLowerCase), true, false, true);
+            FastAddProperty("toLocaleLowerCase", new ClrFunctionInstance(Engine, ToLocaleLowerCase), true, false, true);
+            FastAddProperty("toUpperCase", new ClrFunctionInstance(Engine, ToUpperCase), true, false, true);
+            FastAddProperty("toLocaleUpperCase", new ClrFunctionInstance(Engine, ToLocaleUpperCase), true, false, true);
+            FastAddProperty("trim", new ClrFunctionInstance(Engine, Trim), true, false, true);
         }
 
-        private string ToStringString(object thisObj, object[] arguments)
+        private JsValue ToStringString(JsValue thisObj, JsValue[] arguments)
         {
-            var s = TypeConverter.ToObject(Engine, thisObj) as StringInstance;
+            var s = TypeConverter.ToObject(Engine, thisObj).TryCast<StringInstance>();
             if (s == null)
             {
                 throw new JavaScriptException(Engine.TypeError);
@@ -67,44 +67,44 @@ namespace Jint.Native.String
             return s.PrimitiveValue;
         }
 
-        private string Trim(object thisObj, object[] arguments)
+        private JsValue Trim(JsValue thisObj, JsValue[] arguments)
         {
             TypeConverter.CheckObjectCoercible(Engine, thisObj);
-            var s = TypeConverter.ToString(thisObj);
+            var s = TypeConverter.ToString(thisObj).AsString();
             return s.Trim();
         }
 
-        private static string ToLocaleUpperCase(object thisObj, object[] arguments)
+        private static JsValue ToLocaleUpperCase(JsValue thisObj, JsValue[] arguments)
         {
-            var s = TypeConverter.ToString(thisObj);
+            var s = TypeConverter.ToString(thisObj).AsString();
             return s.ToUpper();
         }
 
-        private static string ToUpperCase(object thisObj, object[] arguments)
+        private static JsValue ToUpperCase(JsValue thisObj, JsValue[] arguments)
         {
-            var s = TypeConverter.ToString(thisObj);
+            var s = TypeConverter.ToString(thisObj).AsString();
             return s.ToUpperInvariant();
         }
 
-        private static string ToLocaleLowerCase(object thisObj, object[] arguments)
+        private static JsValue ToLocaleLowerCase(JsValue thisObj, JsValue[] arguments)
         {
-            var s = TypeConverter.ToString(thisObj);
+            var s = TypeConverter.ToString(thisObj).AsString();
             return s.ToLower();
         }
 
-        private static string ToLowerCase(object thisObj, object[] arguments)
+        private static JsValue ToLowerCase(JsValue thisObj, JsValue[] arguments)
         {
-            var s = TypeConverter.ToString(thisObj);
+            var s = TypeConverter.ToString(thisObj).AsString();
             return s.ToLowerInvariant();
         }
 
-        private string Substring(object thisObj, object[] arguments)
+        private JsValue Substring(JsValue thisObj, JsValue[] arguments)
         {
             TypeConverter.CheckObjectCoercible(Engine, thisObj);
 
-            var s = TypeConverter.ToString(thisObj);
-            var start = TypeConverter.ToNumber(arguments.At(0));
-            var end = TypeConverter.ToNumber(arguments.At(1));
+            var s = TypeConverter.ToString(thisObj).AsString();
+            var start = TypeConverter.ToNumber(arguments.At(0)).AsNumber();
+            var end = TypeConverter.ToNumber(arguments.At(1)).AsNumber();
 
             if (double.IsNaN(start) || start < 0)
             {
@@ -117,8 +117,8 @@ namespace Jint.Native.String
             }
 
             var len = s.Length;
-            var intStart = (int) TypeConverter.ToInteger(start);
-            var intEnd = arguments.At(1) == Undefined.Instance ? len : (int) TypeConverter.ToInteger(end);
+            var intStart = (int)TypeConverter.ToInteger(start).AsNumber();
+            var intEnd = arguments.At(1) == Undefined.Instance ? len : (int)TypeConverter.ToInteger(end).AsNumber();
             var finalStart = System.Math.Min(len, System.Math.Max(intStart, 0));
             var finalEnd = System.Math.Min(len, System.Math.Max(intEnd, 0));
             var from = System.Math.Min(finalStart, finalEnd);
@@ -126,10 +126,10 @@ namespace Jint.Native.String
             return s.Substring(from, to - from);
         }
 
-        private ArrayInstance Split(object thisObj, object[] arguments)
+        private JsValue Split(JsValue thisObj, JsValue[] arguments)
         {
             TypeConverter.CheckObjectCoercible(Engine, thisObj);
-            var s = TypeConverter.ToString(thisObj);
+            var s = TypeConverter.ToString(thisObj).AsString();
 
             var separator = arguments.At(0);
             var l = arguments.At(1);
@@ -148,7 +148,7 @@ namespace Jint.Native.String
                 return (ArrayInstance) Engine.Array.Construct(Arguments.From(s));
             }
 
-            var rx = TypeConverter.ToObject(Engine, separator) as RegExpInstance;
+            var rx = TypeConverter.ToObject(Engine, separator).TryCast<RegExpInstance>();
             if (rx != null)
             {
                 var match = rx.Value.Match(s, 0);
@@ -175,7 +175,7 @@ namespace Jint.Native.String
                     for (int i = 1; i < match.Groups.Count; i++)
                     {
                         var group = match.Groups[i];
-                        object item = Undefined.Instance;
+                        var item = Undefined.Instance;
                         if (group.Captures.Count > 0)
                         {
                             item = match.Groups[i].Value;
@@ -199,7 +199,7 @@ namespace Jint.Native.String
                 var sep = TypeConverter.ToString(separator);
 
 
-                var segments = s.Split(new [] { sep }, StringSplitOptions.None);
+                var segments = s.Split(new [] { sep.AsString() }, StringSplitOptions.None);
                 for (int i = 0; i < segments.Length && i < limit; i++)
                 {
                     a.DefineOwnProperty(i.ToString(), new PropertyDescriptor(segments[i], true, true, true), false);
@@ -210,16 +210,16 @@ namespace Jint.Native.String
             
         }
 
-        private string Slice(object thisObj, object[] arguments)
+        private JsValue Slice(JsValue thisObj, JsValue[] arguments)
         {
             TypeConverter.CheckObjectCoercible(Engine, thisObj);
 
-            var s = TypeConverter.ToString(thisObj);
-            var start = TypeConverter.ToNumber(arguments.At(0));
-            var end = TypeConverter.ToNumber(arguments.At(1));
+            var s = TypeConverter.ToString(thisObj).AsString();
+            var start = TypeConverter.ToNumber(arguments.At(0)).AsNumber();
+            var end = TypeConverter.ToNumber(arguments.At(1)).AsNumber();
             var len = s.Length;
-            var intStart = (int)TypeConverter.ToInteger(start);
-            var intEnd = arguments.At(1) == Undefined.Instance ? len : (int)TypeConverter.ToInteger(end);
+            var intStart = (int)TypeConverter.ToInteger(start).AsNumber();
+            var intEnd = arguments.At(1) == Undefined.Instance ? len : (int)TypeConverter.ToInteger(end).AsNumber();
             var from = intStart < 0 ? System.Math.Max(len + intStart, 0) : System.Math.Min(intStart, len);
             var to = intEnd < 0 ? System.Math.Max(len + intEnd, 0) : System.Math.Min(intEnd, len);
             var span = System.Math.Max(to - from, 0);
@@ -227,14 +227,14 @@ namespace Jint.Native.String
             return s.Substring(from, span);
         }
 
-        private double Search(object thisObj, object[] arguments)
+        private JsValue Search(JsValue thisObj, JsValue[] arguments)
         {
             TypeConverter.CheckObjectCoercible(Engine, thisObj);
 
-            var s = TypeConverter.ToString(thisObj);
+            var s = TypeConverter.ToString(thisObj).AsString();
 
             var regex = arguments.At(0);
-            var rx = TypeConverter.ToObject(Engine, regex) as RegExpInstance ?? (RegExpInstance)Engine.RegExp.Construct(new[] { regex });
+            var rx = TypeConverter.ToObject(Engine, regex).TryCast<RegExpInstance>() ?? (RegExpInstance)Engine.RegExp.Construct(new[] { regex });
             var match = rx.Value.Match(s);
             if (!match.Success)
             {
@@ -244,22 +244,22 @@ namespace Jint.Native.String
             return match.Index;
         }
 
-        private object Replace(object thisObj, object[] arguments)
+        private JsValue Replace(JsValue thisObj, JsValue[] arguments)
         {
             TypeConverter.CheckObjectCoercible(Engine, thisObj);
 
-            var thisString = TypeConverter.ToString(thisObj);
+            var thisString = TypeConverter.ToString(thisObj).AsString();
             var searchValue = arguments.At(0);
             var replaceValue = arguments.At(1);
 
-            var replaceFunction = replaceValue as FunctionInstance;
+            var replaceFunction = replaceValue.TryCast<FunctionInstance>();
             if (replaceFunction == null)
             {
-                replaceFunction = new ClrFunctionInstance<object, string>(Engine, (self, args) =>
+                replaceFunction = new ClrFunctionInstance(Engine, (self, args) =>
                 {
-                    var replaceString = TypeConverter.ToString(replaceValue);
-                    var matchValue = TypeConverter.ToString(args.At(0));
-                    var matchIndex = (int)TypeConverter.ToInteger(args.At(args.Length-2));
+                    var replaceString = TypeConverter.ToString(replaceValue).AsString();
+                    var matchValue = TypeConverter.ToString(args.At(0)).AsString();
+                    var matchIndex = (int)TypeConverter.ToInteger(args.At(args.Length - 2)).AsNumber();
 
                     // Check if the replacement string contains any patterns.
                     bool replaceTextContainsPattern = replaceString.IndexOf('$') >= 0;
@@ -333,13 +333,13 @@ namespace Jint.Native.String
             }
 
             // searchValue is a regular expression
-            var rx = TypeConverter.ToObject(Engine, searchValue) as RegExpInstance;
+            var rx = TypeConverter.ToObject(Engine, searchValue).TryCast<RegExpInstance>();
             if (rx != null)
             {
                 // Replace the input string with replaceText, recording the last match found.
                 string result = rx.Value.Replace(thisString, match =>
                 {
-                    var args = new List<object>();
+                    var args = new List<JsValue>();
                     args.Add(match.Value);
                     for (var k = 0; k < match.Groups.Count; k++)
                     {
@@ -351,7 +351,7 @@ namespace Jint.Native.String
                     args.Add(match.Index);
                     args.Add(thisString);
 
-                    return TypeConverter.ToString(replaceFunction.Call(Undefined.Instance, args.ToArray()));
+                    return TypeConverter.ToString(replaceFunction.Call(Undefined.Instance, args.ToArray())).AsString();
                 }, rx.Global == true ? -1 : 1);
 
                 // Set the deprecated RegExp properties if at least one match was found.
@@ -364,7 +364,7 @@ namespace Jint.Native.String
             // searchValue is a string
             else
             {
-                var substr = TypeConverter.ToString(searchValue);
+                var substr = TypeConverter.ToString(searchValue).AsString();
 
                 // Find the first occurrance of substr.
                 int start = thisString.IndexOf(substr, StringComparison.Ordinal);
@@ -372,12 +372,12 @@ namespace Jint.Native.String
                     return thisString;
                 int end = start + substr.Length;
 
-                var args = new List<object>();
+                var args = new List<JsValue>();
                 args.Add(substr);
                 args.Add(start);
                 args.Add(thisString);
 
-                var replaceString = TypeConverter.ToString(replaceFunction.Call(Undefined.Instance, args.ToArray()));
+                var replaceString = TypeConverter.ToString(replaceFunction.Call(Undefined.Instance, args.ToArray())).AsString();
 
                 // Replace only the first match.
                 var result = new StringBuilder(thisString.Length + (substr.Length - substr.Length));
@@ -388,43 +388,39 @@ namespace Jint.Native.String
             }
         }
 
-        private object Match(object thisObj, object[] arguments)
+        private JsValue Match(JsValue thisObj, JsValue[] arguments)
         {
             TypeConverter.CheckObjectCoercible(Engine, thisObj);
 
             var s = TypeConverter.ToString(thisObj);
 
             var regex = arguments.At(0);
-            RegExpInstance rx = null;
-            if (TypeConverter.GetType(regex) == Types.Object)
-            {
-                rx = regex as RegExpInstance;
-            }
+            var rx = regex.TryCast<RegExpInstance>();
 
             rx = rx ?? (RegExpInstance) Engine.RegExp.Construct(new[] {regex});
 
-            var global = (bool) rx.Get("global");
+            var global = rx.Get("global").AsBoolean();
             if (!global)
             {
                 return Engine.RegExp.PrototypeObject.Exec(rx, Arguments.From(s));
             }
             else
             {
-                rx.Put("lastIndex", (double) 0, false);
+                rx.Put("lastIndex", 0, false);
                 var a = Engine.Array.Construct(Arguments.Empty);
                 double previousLastIndex = 0;
                 var n = 0;
                 var lastMatch = true;
                 while (lastMatch)
                 {
-                    var result = Engine.RegExp.PrototypeObject.Exec(rx, Arguments.From(s)) as ObjectInstance;
+                    var result = Engine.RegExp.PrototypeObject.Exec(rx, Arguments.From(s)).TryCast<ObjectInstance>();
                     if (result == null)
                     {
                         lastMatch = false;
                     }
                     else
                     {
-                        var thisIndex = (double) rx.Get("lastIndex");
+                        var thisIndex = rx.Get("lastIndex").AsNumber();
                         if (thisIndex == previousLastIndex)
                         {
                             rx.Put("lastIndex", thisIndex + 1, false);
@@ -432,7 +428,7 @@ namespace Jint.Native.String
                         }
 
                         var matchStr = result.Get("0");
-                        a.DefineOwnProperty(TypeConverter.ToString(n), new PropertyDescriptor(matchStr, true, true, true), false);
+                        a.DefineOwnProperty(TypeConverter.ToString(n).AsString(), new PropertyDescriptor(matchStr, true, true, true), false);
                         n++;
                     }
                 }
@@ -445,24 +441,24 @@ namespace Jint.Native.String
 
         }
 
-        private double LocaleCompare(object thisObj, object[] arguments)
+        private JsValue LocaleCompare(JsValue thisObj, JsValue[] arguments)
         {
             TypeConverter.CheckObjectCoercible(Engine, thisObj);
 
-            var s = TypeConverter.ToString(thisObj);
-            var that = TypeConverter.ToString(arguments.Length > 0 ? arguments[0] : Undefined.Instance);
+            var s = TypeConverter.ToString(thisObj).AsString();
+            var that = TypeConverter.ToString(arguments.At(0)).AsString();
 
             return string.CompareOrdinal(s, that);
         }
 
-        private double LastIndexOf(object thisObj, object[] arguments)
+        private JsValue LastIndexOf(JsValue thisObj, JsValue[] arguments)
         {
             TypeConverter.CheckObjectCoercible(Engine, thisObj);
 
-            var s = TypeConverter.ToString(thisObj);
-            var searchStr = TypeConverter.ToString(arguments.At(0));
-            double numPos = arguments.At(0) == Undefined.Instance ? double.NaN : TypeConverter.ToNumber(arguments.At(0));
-            double pos = double.IsNaN(numPos) ? double.PositiveInfinity : TypeConverter.ToInteger(numPos);
+            var s = TypeConverter.ToString(thisObj).AsString();
+            var searchStr = TypeConverter.ToString(arguments.At(0)).AsString();
+            double numPos = arguments.At(0) == Undefined.Instance ? double.NaN : TypeConverter.ToNumber(arguments.At(0)).AsNumber();
+            double pos = double.IsNaN(numPos) ? double.PositiveInfinity : TypeConverter.ToInteger(numPos).AsNumber();
             var len = s.Length;
             var start = System.Math.Min(len, System.Math.Max(pos, 0));
             var searchLen = searchStr.Length;
@@ -470,16 +466,16 @@ namespace Jint.Native.String
             return s.LastIndexOf(searchStr, len - (int) start, StringComparison.Ordinal);
         }
 
-        private double IndexOf(object thisObj, object[] arguments)
+        private JsValue IndexOf(JsValue thisObj, JsValue[] arguments)
         {
             TypeConverter.CheckObjectCoercible(Engine, thisObj);
 
-            var s = TypeConverter.ToString(thisObj);
-            var searchStr = TypeConverter.ToString(arguments.Length > 0 ? arguments[0] : Undefined.Instance);
+            var s = TypeConverter.ToString(thisObj).AsString();
+            var searchStr = TypeConverter.ToString(arguments.At(0)).AsString();
             double pos = 0;
             if (arguments.Length > 1 && arguments[1] != Undefined.Instance)
             {
-                pos = TypeConverter.ToInteger(arguments[1]);
+                pos = TypeConverter.ToInteger(arguments[1]).AsNumber();
             }
 
             if (pos >= s.Length)
@@ -495,11 +491,11 @@ namespace Jint.Native.String
             return s.IndexOf(searchStr, (int) pos, StringComparison.Ordinal);
         }
 
-        private string Concat(object thisObj, object[] arguments)
+        private JsValue Concat(JsValue thisObj, JsValue[] arguments)
         {
             TypeConverter.CheckObjectCoercible(Engine, thisObj);
 
-            var s = TypeConverter.ToString(thisObj);
+            var s = TypeConverter.ToString(thisObj).AsString();
             var sb = new StringBuilder(s);
             for (int i = 0; i < arguments.Length; i++)
             {
@@ -509,25 +505,25 @@ namespace Jint.Native.String
             return sb.ToString();
         }
 
-        private object CharCodeAt(object thisObj, object[] arguments)
+        private JsValue CharCodeAt(JsValue thisObj, JsValue[] arguments)
         {
             TypeConverter.CheckObjectCoercible(Engine, thisObj);
 
-            object pos = arguments.Length > 0 ? arguments[0] : 0;
-            var s = TypeConverter.ToString(thisObj);
-            var position = (int)TypeConverter.ToInteger(pos);
+            JsValue pos = arguments.Length > 0 ? arguments[0] : 0;
+            var s = TypeConverter.ToString(thisObj).AsString();
+            var position = (int)TypeConverter.ToInteger(pos).AsNumber();
             if (position < 0 || position >= s.Length)
             {
                 return double.NaN;
             }
-            return (uint)s[position];
+            return s[position];
         }
 
-        private object CharAt(object thisObj, object[] arguments)
+        private JsValue CharAt(JsValue thisObj, JsValue[] arguments)
         {
             TypeConverter.CheckObjectCoercible(Engine, thisObj);
-            var s = TypeConverter.ToString(thisObj);
-            var position = TypeConverter.ToInteger(arguments.At(0));
+            var s = TypeConverter.ToString(thisObj).AsString();
+            var position = TypeConverter.ToInteger(arguments.At(0)).AsNumber();
             var size = s.Length;
             if (position >= size || position < 0)
             {
@@ -537,9 +533,9 @@ namespace Jint.Native.String
 
         }
 
-        private string ValueOf(object thisObj, object[] arguments)
+        private JsValue ValueOf(JsValue thisObj, JsValue[] arguments)
         {
-            var s = thisObj as StringInstance;
+            var s = thisObj.TryCast<StringInstance>();
             if (s == null)
             {
                 throw new JavaScriptException(Engine.TypeError);

+ 0 - 29
Jint/Native/Undefined.cs

@@ -1,29 +0,0 @@
-using System;
-using Jint.Runtime;
-
-namespace Jint.Native
-{
-    public class Undefined : IPrimitiveType
-    {
-        public static object Instance = new Undefined();
-
-        private Undefined()
-        {   
-        }
-
-        public override string ToString()
-        {
-            return "undefined";
-        }
-
-        public Types Type
-        {
-            get { return Types.Undefined; }
-        }
-
-        public object PrimitiveValue
-        {
-            get { return Instance; }
-        }
-    }
-}

+ 9 - 4
Jint/Runtime/Arguments.cs

@@ -4,9 +4,9 @@ namespace Jint.Runtime
 {
     public static class Arguments
     {
-        public static object[] Empty = new object[0];
+        public static JsValue[] Empty = new JsValue[0];
 
-        public static object[] From(params object[] o)
+        public static JsValue[] From(params JsValue[] o)
         {
             return o;
         }
@@ -18,9 +18,14 @@ namespace Jint.Runtime
         /// <param name="index">The index of the parameter to return</param>
         /// <param name="undefinedValue">The value to return is the parameter is not provided</param>
         /// <returns></returns>
-        public static object At(this object[] args, int index, object undefinedValue = null)
+        public static JsValue At(this JsValue[] args, int index, JsValue undefinedValue)
         {
-            return args.Length > index ? args[index] : undefinedValue ?? Undefined.Instance;
+            return args.Length > index ? args[index] : undefinedValue;
+        }
+
+        public static JsValue At(this JsValue[] args, int index)
+        {
+            return At(args, index, Undefined.Instance);
         }
     }
 }

+ 5 - 3
Jint/Runtime/Completion.cs

@@ -1,4 +1,6 @@
-namespace Jint.Runtime
+using Jint.Native;
+
+namespace Jint.Runtime
 {
     /// <summary>
     /// http://www.ecma-international.org/ecma-262/5.1/#sec-8.9
@@ -11,7 +13,7 @@
         public static string Return = "return";
         public static string Throw = "throw";
 
-        public Completion(string type, object value, string identifier)
+        public Completion(string type, JsValue value, string identifier)
         {
             Type = type;
             Value = value;
@@ -20,7 +22,7 @@
 
 
         public string Type { get; private set; }
-        public object Value { get; private set; }
+        public JsValue Value { get; private set; }
         public string Identifier { get; private set; }
 
     }

+ 50 - 117
Jint/Runtime/Descriptors/PropertyDescriptor.cs

@@ -1,5 +1,4 @@
-using System.Collections.Generic;
-using Jint.Native;
+using Jint.Native;
 using Jint.Native.Object;
 
 namespace Jint.Runtime.Descriptors
@@ -13,99 +12,49 @@ namespace Jint.Runtime.Descriptors
         Writable,
         Value
     }
-
-    public interface IPropertyField
-    {
-        bool IsPresent { get; }
-
-        bool IsAbsent { get; }
-
-        object Value { get; }
-    }
-
-    public struct Field<T> : IPropertyField
+    
+    public class PropertyDescriptor
     {
-        private readonly T _field;
-        private readonly bool _present;
-
-        public Field(T value)
-        {
-            _field = value;
-            _present = true;
-        }
+        public static PropertyDescriptor Undefined = new PropertyDescriptor();
 
-        public bool IsPresent
+        public PropertyDescriptor()
         {
-            get { return _present; }
         }
 
-        public bool IsAbsent
+        public PropertyDescriptor(JsValue? value, bool? writable, bool? enumerable, bool? configurable)
         {
-            get { return !_present; }
-        }
+            Value = value;
 
-        public T Value
-        {
-            get
+            if (writable.HasValue)
             {
-                return _field;
+                Writable = new JsValue(writable.Value);
             }
-        }
-
-        bool IPropertyField.IsPresent
-        {
-            get { return IsPresent; }
-        }
 
-        bool IPropertyField.IsAbsent
-        {
-            get { return IsAbsent; }
-        }
-
-        object IPropertyField.Value
-        {
-            get
+            if (enumerable.HasValue)
             {
-                return Value;
+                Enumerable = new JsValue(enumerable.Value);
             }
-        }
-    }
 
-    public class PropertyDescriptor
-    {
-        public static PropertyDescriptor Undefined = new PropertyDescriptor();
-
-        public PropertyDescriptor()
-        {
-            Get = new Field<object>();
-            Set = new Field<object>();
-            Value = new Field<object>();
-            Enumerable = new Field<bool>();
-            Configurable = new Field<bool>();
-            Writable = new Field<bool>();
-        }
-
-        public PropertyDescriptor(object value, bool? writable, bool? enumerable, bool? configurable)
-        {
-            Value = value == null ? new Field<object>() : new Field<object>(value);
-            Writable = writable == null ? new Field<bool>() : new Field<bool>(writable.Value);
-            Enumerable = enumerable == null ? new Field<bool>() : new Field<bool>(enumerable.Value);
-            Configurable = configurable == null ? new Field<bool>() : new Field<bool>(configurable.Value);
-
-            Get = new Field<object>();
-            Set = new Field<object>();
+            if (configurable.HasValue)
+            {
+                Configurable = new JsValue(configurable.Value);
+            }
         }
 
-        public PropertyDescriptor(object get, object set, bool? enumerable = null, bool? configurable = null)
+        public PropertyDescriptor(JsValue? get, JsValue? set, bool? enumerable = null, bool? configurable = null)
         {
-            Get = get == null ? new Field<object>() : new Field<object>(get);
-            Set = set == null ? new Field<object>() : new Field<object>(set);
+            Get = get;
+            Set = set;
 
-            Enumerable = enumerable == null ? new Field<bool>() : new Field<bool>(enumerable.Value);
-            Configurable = configurable == null ? new Field<bool>() : new Field<bool>(configurable.Value);
+            if (enumerable.HasValue)
+            {
+                Enumerable = new JsValue(enumerable.Value);
+            }
 
-            Value = new Field<object>();
-            Writable = new Field<bool>();
+            if (configurable.HasValue)
+            {
+                Configurable = new JsValue(configurable.Value);
+            }
         }
 
         public PropertyDescriptor(PropertyDescriptor descriptor)
@@ -118,32 +67,16 @@ namespace Jint.Runtime.Descriptors
             Writable = descriptor.Writable;
         }
 
-        public Field<object> Get { get; set; }
-        public Field<object> Set { get; set; }
-        public Field<bool> Enumerable { get; set; }
-        public Field<bool> Writable { get; set; }
-        public Field<bool> Configurable { get; set; }
-        public Field<object> Value { get; set; }
-
-        public IDictionary<string, IPropertyField> AllFields
-        {
-            get
-            {
-                return new Dictionary<string, IPropertyField>
-                {
-                    {"Get", Get},
-                    {"Set", Set},
-                    {"Enumerable", Enumerable},
-                    {"Configurable", Configurable},
-                    {"Writable", Writable},
-                    {"Value", Value},
-                };
-            }
-        }
-
+        public JsValue? Get { get; set; }
+        public JsValue? Set { get; set; }
+        public JsValue? Enumerable { get; set; }
+        public JsValue? Writable { get; set; }
+        public JsValue? Configurable { get; set; }
+        public JsValue? Value { get; set; }
+        
         public bool IsAccessorDescriptor()
         {
-            if (Get.IsAbsent && Set.IsAbsent)
+            if (!Get.HasValue && !Get.HasValue)
             {
                 return false;
             }
@@ -153,7 +86,7 @@ namespace Jint.Runtime.Descriptors
 
         public bool IsDataDescriptor()
         {
-            if (Writable.IsAbsent && Value.IsAbsent)
+            if (!Writable.HasValue && !Value.HasValue)
             {
                 return false;
             }
@@ -189,33 +122,33 @@ namespace Jint.Runtime.Descriptors
 
             if (obj.HasProperty("enumerable"))
             {
-                desc.Enumerable = new Field<bool>(TypeConverter.ToBoolean(obj.Get("enumerable")));
+                desc.Enumerable = TypeConverter.ToBoolean(obj.Get("enumerable"));
             }
 
             if (obj.HasProperty("configurable"))
             {
-                desc.Configurable = new Field<bool>(TypeConverter.ToBoolean(obj.Get("configurable")));
+                desc.Configurable = TypeConverter.ToBoolean(obj.Get("configurable"));
             }
 
             if (obj.HasProperty("value"))
             {
                 var value = obj.Get("value");
-                desc.Value = new Field<object>(value);
+                desc.Value = value;
             }
 
             if (obj.HasProperty("writable"))
             {
-                desc.Writable = new Field<bool>(TypeConverter.ToBoolean(obj.Get("writable")));
+                desc.Writable = TypeConverter.ToBoolean(obj.Get("writable"));
             }
 
             if (obj.HasProperty("get"))
             {
                 var getter = obj.Get("get");
-                if (getter != Native.Undefined.Instance && !(getter is ICallable))
+                if (getter != JsValue.Undefined && !(getter is ICallable))
                 {
                     throw new JavaScriptException(engine.TypeError);
                 }
-                desc.Get = new Field<object>(getter);
+                desc.Get = getter;
             }
 
             if (obj.HasProperty("set"))
@@ -225,12 +158,12 @@ namespace Jint.Runtime.Descriptors
                 {
                     throw new JavaScriptException(engine.TypeError);
                 }
-                desc.Set = new Field<object>(setter);
+                desc.Set = setter;
             }
 
-            if (desc.Get.IsPresent || desc.Get.IsPresent)
+            if (desc.Get.HasValue || desc.Get.HasValue)
             {
-                if (desc.Value.IsPresent || desc.Writable.IsPresent)
+                if (desc.Value.HasValue || desc.Writable.HasValue)
                 {
                     throw new JavaScriptException(engine.TypeError);
                 }
@@ -239,7 +172,7 @@ namespace Jint.Runtime.Descriptors
             return desc;
         }
 
-        public static object FromPropertyDescriptor(Engine engine, PropertyDescriptor desc)
+        public static JsValue FromPropertyDescriptor(Engine engine, PropertyDescriptor desc)
         {
             if (desc == Undefined)
             {
@@ -251,16 +184,16 @@ namespace Jint.Runtime.Descriptors
             if (desc.IsDataDescriptor())
             {
                 obj.DefineOwnProperty("value", new PropertyDescriptor(value: desc.Value.Value, writable: true, enumerable: true, configurable: true ), false);
-                obj.DefineOwnProperty("writable", new PropertyDescriptor(value: desc.Writable.IsPresent && desc.Writable.Value, writable: true, enumerable: true, configurable: true ), false);
+                obj.DefineOwnProperty("writable", new PropertyDescriptor(value: desc.Writable.HasValue && desc.Writable.Value.AsBoolean(), writable: true, enumerable: true, configurable: true), false);
             }
             else
             {
-                obj.DefineOwnProperty("get", new PropertyDescriptor(desc.Get.Value ?? Native.Undefined.Instance, writable: true, enumerable: true, configurable: true ), false);
-                obj.DefineOwnProperty("set", new PropertyDescriptor(desc.Set.Value ?? Native.Undefined.Instance, writable: true, enumerable: true, configurable: true), false);
+                obj.DefineOwnProperty("get", new PropertyDescriptor(desc.Get ?? Native.Undefined.Instance, writable: true, enumerable: true, configurable: true ), false);
+                obj.DefineOwnProperty("set", new PropertyDescriptor(desc.Set ?? Native.Undefined.Instance, writable: true, enumerable: true, configurable: true), false);
             }
 
-            obj.DefineOwnProperty("enumerable", new PropertyDescriptor(value: desc.Enumerable.IsPresent && desc.Enumerable.Value, writable: true, enumerable: true, configurable: true), false);
-            obj.DefineOwnProperty("configurable", new PropertyDescriptor(value: desc.Configurable.IsPresent && desc.Configurable.Value, writable: true, enumerable: true, configurable: true), false);
+            obj.DefineOwnProperty("enumerable", new PropertyDescriptor(value: desc.Enumerable.HasValue && desc.Enumerable.Value.AsBoolean(), writable: true, enumerable: true, configurable: true), false);
+            obj.DefineOwnProperty("configurable", new PropertyDescriptor(value: desc.Configurable.HasValue && desc.Configurable.Value.AsBoolean(), writable: true, enumerable: true, configurable: true), false);
 
             return obj;
         }

+ 6 - 5
Jint/Runtime/Descriptors/Specialized/ClrAccessDescriptor.cs

@@ -1,19 +1,20 @@
 using System;
+using Jint.Native;
 using Jint.Runtime.Interop;
 
 namespace Jint.Runtime.Descriptors.Specialized
 {
-    public sealed class ClrAccessDescriptor<T> : PropertyDescriptor
+    public sealed class ClrAccessDescriptor : PropertyDescriptor
     {
-        public ClrAccessDescriptor(Engine engine, Func<T, object> get)
+        public ClrAccessDescriptor(Engine engine, Func<JsValue, JsValue> get)
             : this(engine, get, null)
         {
         }
 
-        public ClrAccessDescriptor(Engine engine, Func<T, object> get, Action<T, object> set)
+        public ClrAccessDescriptor(Engine engine, Func<JsValue, JsValue> get, Action<JsValue, JsValue> set)
             : base(
-                get: new GetterFunctionInstance<T>(engine, get),
-                set: set == null ? Native.Undefined.Instance : new SetterFunctionInstance<T>(engine, set)
+                get: new GetterFunctionInstance(engine, get),
+                set: set == null ? Native.Undefined.Instance : new SetterFunctionInstance(engine, set)
                 )
         {
         }

+ 4 - 3
Jint/Runtime/Descriptors/Specialized/ClrDataDescriptor.cs

@@ -1,12 +1,13 @@
 using System;
+using Jint.Native;
 using Jint.Runtime.Interop;
 
 namespace Jint.Runtime.Descriptors.Specialized
 {
-    public sealed class ClrDataDescriptor<TObject, TResult> : PropertyDescriptor
+    public sealed class ClrDataDescriptor : PropertyDescriptor
     {
-        public ClrDataDescriptor(Engine engine, Func<TObject, object[], TResult> func)
-            : base(value: new ClrFunctionInstance<TObject, TResult>(engine, func), writable: null, enumerable: null, configurable: null)
+        public ClrDataDescriptor(Engine engine, Func<JsValue, JsValue[], JsValue> func)
+            : base(value: new ClrFunctionInstance(engine, func), writable: null, enumerable: null, configurable: null)
         {
         }
     }

+ 4 - 2
Jint/Runtime/Environments/Binding.cs

@@ -1,8 +1,10 @@
-namespace Jint.Runtime.Environments
+using Jint.Native;
+
+namespace Jint.Runtime.Environments
 {
     public class Binding
     {
-        public object Value;
+        public JsValue Value;
         public bool CanBeDeleted;
         public bool Mutable;
     }

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

@@ -12,7 +12,7 @@ namespace Jint.Runtime.Environments
         private readonly Engine _engine;
         private readonly IDictionary<string, Binding> _bindings = new Dictionary<string, Binding>();
 
-        public DeclarativeEnvironmentRecord(Engine engine)
+        public DeclarativeEnvironmentRecord(Engine engine) : base(engine)
         {
             _engine = engine;
         }
@@ -32,7 +32,7 @@ namespace Jint.Runtime.Environments
                 });
         }
 
-        public override void SetMutableBinding(string name, object value, bool strict)
+        public override void SetMutableBinding(string name, JsValue value, bool strict)
         {
             var binding = _bindings[name];
             if (binding.Mutable)
@@ -48,11 +48,11 @@ namespace Jint.Runtime.Environments
             }
         }
 
-        public override object GetBindingValue(string name, bool strict)
+        public override JsValue GetBindingValue(string name, bool strict)
         {
             var binding = _bindings[name];
 
-            if (!binding.Mutable && binding.Value == null)
+            if (!binding.Mutable && binding.Value == Undefined.Instance)
             {
                 if (strict)
                 {
@@ -83,7 +83,7 @@ namespace Jint.Runtime.Environments
             return true;
         }
 
-        public override object ImplicitThisValue()
+        public override JsValue ImplicitThisValue()
         {
             return Undefined.Instance;
         }
@@ -96,7 +96,7 @@ namespace Jint.Runtime.Environments
         {
             _bindings.Add(name, new Binding
                 {
-                    Value = null,
+                    Value = Undefined.Instance,
                     Mutable = false,
                     CanBeDeleted = false
                 });
@@ -107,7 +107,7 @@ namespace Jint.Runtime.Environments
         /// </summary>
         /// <param name="name">The identifier of the binding.</param>
         /// <param name="value">The value of the binding.</param>
-        public void InitializeImmutableBinding(string name, object value)
+        public void InitializeImmutableBinding(string name, JsValue value)
         {
             var binding = _bindings[name];
             binding.Value = value;

+ 11 - 5
Jint/Runtime/Environments/EnvironmentRecord.cs

@@ -1,11 +1,17 @@
-namespace Jint.Runtime.Environments
+using Jint.Native;
+using Jint.Native.Object;
+
+namespace Jint.Runtime.Environments
 {
     /// <summary>
     /// Base implementation of an Environment Record
     /// http://www.ecma-international.org/ecma-262/5.1/#sec-10.2.1
     /// </summary>
-    public abstract class EnvironmentRecord
+    public abstract class EnvironmentRecord : ObjectInstance
     {
+        protected EnvironmentRecord(Engine engine) : base(engine)
+        {
+        }
 
         /// <summary>
         /// Determines if an environment record has a binding for an identifier. 
@@ -27,7 +33,7 @@
         /// <param name="name">The identifier of the binding</param>
         /// <param name="value">The value of the binding.</param>
         /// <param name="strict">The identify strict mode references.</param>
-        public abstract void SetMutableBinding(string name, object value, bool strict);
+        public abstract void SetMutableBinding(string name, JsValue value, bool strict);
         
         /// <summary>
         /// Returns the value of an already existing binding from an environment record. 
@@ -35,7 +41,7 @@
         /// <param name="name">The identifier of the binding</param>
         /// <param name="strict">The identify strict mode references.</param>
         /// <return>The value of an already existing binding from an environment record.</return>
-        public abstract object GetBindingValue(string name, bool strict);
+        public abstract JsValue GetBindingValue(string name, bool strict);
 
         /// <summary>
         /// Delete a binding from an environment record. The String value N is the text of the bound name If a binding for N exists, remove the binding and return true. If the binding exists but cannot be removed return false. If the binding does not exist return true.
@@ -48,7 +54,7 @@
         /// Returns the value to use as the <c>this</c> value on calls to function objects that are obtained as binding values from this environment record.
         /// </summary>
         /// <returns>The value to use as <c>this</c>.</returns>
-        public abstract object ImplicitThisValue();
+        public abstract JsValue ImplicitThisValue();
 
 
     }

+ 4 - 2
Jint/Runtime/Environments/ExecutionContext.cs

@@ -1,10 +1,12 @@
-namespace Jint.Runtime.Environments
+using Jint.Native;
+
+namespace Jint.Runtime.Environments
 {
     public sealed class ExecutionContext
     {
         public LexicalEnvironment LexicalEnvironment { get; set; }
         public LexicalEnvironment VariableEnvironment { get; set; }
-        public object ThisBinding { get; set; }
+        public JsValue ThisBinding { get; set; }
 
     }
 }

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

@@ -14,7 +14,7 @@ namespace Jint.Runtime.Environments
         private readonly ObjectInstance _bindingObject;
         private readonly bool _provideThis;
 
-        public ObjectEnvironmentRecord(Engine engine, ObjectInstance bindingObject, bool provideThis)
+        public ObjectEnvironmentRecord(Engine engine, ObjectInstance bindingObject, bool provideThis) : base(engine)
         {
             _engine = engine;
             _bindingObject = bindingObject;
@@ -36,12 +36,12 @@ namespace Jint.Runtime.Environments
             _bindingObject.DefineOwnProperty(name, new PropertyDescriptor(Undefined.Instance, true, true, configurable), true);
         }
 
-        public override void SetMutableBinding(string name, object value, bool strict)
+        public override void SetMutableBinding(string name, JsValue value, bool strict)
         {
             _bindingObject.Put(name, value, strict);
         }
 
-        public override object GetBindingValue(string name, bool strict)
+        public override JsValue GetBindingValue(string name, bool strict)
         {
             // todo: can be optimized
 
@@ -63,11 +63,11 @@ namespace Jint.Runtime.Environments
             return _bindingObject.Delete(name, false);
         }
 
-        public override object ImplicitThisValue()
+        public override JsValue ImplicitThisValue()
         {
             if (_provideThis)
             {
-                return _bindingObject;
+                return new JsValue(_bindingObject);
             }
 
             return Undefined.Instance;

+ 90 - 92
Jint/Runtime/ExpressionIntepreter.cs

@@ -3,7 +3,6 @@ using System.Linq;
 using Jint.Native;
 using Jint.Native.Function;
 using Jint.Native.Number;
-using Jint.Native.Object;
 using Jint.Parser.Ast;
 using Jint.Runtime.Descriptors;
 using Jint.Runtime.Environments;
@@ -25,10 +24,10 @@ namespace Jint.Runtime
             return _engine.EvaluateExpression(expression);
         }
 
-        public object EvaluateConditionalExpression(ConditionalExpression conditionalExpression)
+        public JsValue EvaluateConditionalExpression(ConditionalExpression conditionalExpression)
         {
             var lref = _engine.EvaluateExpression(conditionalExpression.Test);
-            if (TypeConverter.ToBoolean(_engine.GetValue(lref)))
+            if (TypeConverter.ToBoolean(_engine.GetValue(lref)).AsBoolean())
             {
                 var trueRef = _engine.EvaluateExpression(conditionalExpression.Consequent);
                 return _engine.GetValue(trueRef);
@@ -40,9 +39,9 @@ namespace Jint.Runtime
             }
         }
 
-        public object EvaluateAssignmentExpression(AssignmentExpression assignmentExpression)
+        public JsValue EvaluateAssignmentExpression(AssignmentExpression assignmentExpression)
         {
-            object rval = _engine.GetValue(EvaluateExpression(assignmentExpression.Right));
+            JsValue rval = _engine.GetValue(EvaluateExpression(assignmentExpression.Right));
 
             var lref = EvaluateExpression(assignmentExpression.Left) as Reference;
 
@@ -54,7 +53,7 @@ namespace Jint.Runtime
             if (assignmentExpression.Operator == "=")
             {
  
-                if(lref.IsStrict() && lref.GetBase() is EnvironmentRecord && (lref.GetReferencedName() == "eval" || lref.GetReferencedName() == "arguments"))
+                if(lref.IsStrict() && lref.GetBase().TryCast<EnvironmentRecord>() != null && (lref.GetReferencedName() == "eval" || lref.GetReferencedName() == "arguments"))
                 {
                     throw new JavaScriptException(_engine.SyntaxError);
                 }
@@ -63,26 +62,25 @@ namespace Jint.Runtime
                 return rval;
             }
 
-            object lval = _engine.GetValue(lref);
+            JsValue lval = _engine.GetValue(lref);
 
             switch (assignmentExpression.Operator)
             {
                 case "+=":
                     var lprim = TypeConverter.ToPrimitive(lval);
                     var rprim = TypeConverter.ToPrimitive(rval);
-                    if (TypeConverter.GetType(lprim) == Types.String ||
-                        TypeConverter.GetType(rprim) == Types.String)
+                    if (lprim.IsString() || rprim.IsString())
                     {
-                        lval = TypeConverter.ToString(lprim) + TypeConverter.ToString(rprim);
+                        lval = TypeConverter.ToString(lprim).AsString() + TypeConverter.ToString(rprim).AsString();
                     }
                     else
                     {
-                        lval = TypeConverter.ToNumber(lprim) + TypeConverter.ToNumber(rprim);
+                        lval = TypeConverter.ToNumber(lprim).AsNumber() + TypeConverter.ToNumber(rprim).AsNumber();
                     }
                     break;
 
                 case "-=":
-                    lval = TypeConverter.ToNumber(lval) - TypeConverter.ToNumber(rval);
+                    lval = TypeConverter.ToNumber(lval).AsNumber() - TypeConverter.ToNumber(rval).AsNumber();
                     break;
 
                 case "*=":
@@ -92,7 +90,7 @@ namespace Jint.Runtime
                     }
                     else
                     {
-                        lval = TypeConverter.ToNumber(lval) * TypeConverter.ToNumber(rval);
+                        lval = TypeConverter.ToNumber(lval).AsNumber() * TypeConverter.ToNumber(rval).AsNumber();
                     }
                     break;
 
@@ -107,7 +105,7 @@ namespace Jint.Runtime
                     }
                     else
                     {
-                        lval = TypeConverter.ToNumber(lval) % TypeConverter.ToNumber(rval);
+                        lval = TypeConverter.ToNumber(lval).AsNumber() % TypeConverter.ToNumber(rval).AsNumber();
                     }
                     break;
 
@@ -145,7 +143,7 @@ namespace Jint.Runtime
             return lval;
         }
 
-        private object Divide(object lval, object rval)
+        private JsValue Divide(JsValue lval, JsValue rval)
         {
             if (lval == Undefined.Instance || rval == Undefined.Instance)
             {
@@ -153,8 +151,8 @@ namespace Jint.Runtime
             }
             else
             {
-                var lN = TypeConverter.ToNumber(lval);
-                var rN = TypeConverter.ToNumber(rval);
+                var lN = TypeConverter.ToNumber(lval).AsNumber();
+                var rN = TypeConverter.ToNumber(rval).AsNumber();
 
                 if (double.IsNaN(rN) || double.IsNaN(lN))
                 {
@@ -195,29 +193,29 @@ namespace Jint.Runtime
             }
         }
 
-        public object EvaluateBinaryExpression(BinaryExpression expression)
+        public JsValue EvaluateBinaryExpression(BinaryExpression expression)
         {
-            object left = _engine.GetValue(EvaluateExpression(expression.Left));
-            object right = _engine.GetValue(EvaluateExpression(expression.Right));
-            object value;
+            JsValue left = _engine.GetValue(EvaluateExpression(expression.Left));
+            JsValue right = _engine.GetValue(EvaluateExpression(expression.Right));
+            JsValue value;
 
             switch (expression.Operator)
             {
                 case "+":
                     var lprim = TypeConverter.ToPrimitive(left);
                     var rprim = TypeConverter.ToPrimitive(right);
-                    if (TypeConverter.GetType(lprim) == Types.String || TypeConverter.GetType(rprim) == Types.String)
+                    if (lprim.IsString() || rprim.IsString())
                     {
-                        value = TypeConverter.ToString(lprim) + TypeConverter.ToString(rprim);
+                        value = TypeConverter.ToString(lprim).AsString() + TypeConverter.ToString(rprim).AsString();
                     }
                     else
                     {
-                        value = TypeConverter.ToNumber(lprim) + TypeConverter.ToNumber(rprim);
+                        value = TypeConverter.ToNumber(lprim).AsNumber() + TypeConverter.ToNumber(rprim).AsNumber();
                     }
                     break;
                 
                 case "-":
-                    value = TypeConverter.ToNumber(left) - TypeConverter.ToNumber(right);
+                    value = TypeConverter.ToNumber(left).AsNumber() - TypeConverter.ToNumber(right).AsNumber();
                     break;
                 
                 case "*":
@@ -227,7 +225,7 @@ namespace Jint.Runtime
                     }
                     else
                     {
-                        value = TypeConverter.ToNumber(left) * TypeConverter.ToNumber(right);
+                        value = TypeConverter.ToNumber(left).AsNumber() * TypeConverter.ToNumber(right).AsNumber();
                     }
                     break;
                 
@@ -242,7 +240,7 @@ namespace Jint.Runtime
                     }
                     else
                     {
-                        value = TypeConverter.ToNumber(left) % TypeConverter.ToNumber(right);
+                        value = TypeConverter.ToNumber(left).AsNumber() % TypeConverter.ToNumber(right).AsNumber();
                     }
                     break;
 
@@ -264,7 +262,7 @@ namespace Jint.Runtime
 
                 case ">=":
                     value = Compare(left, right);
-                    if (value == Undefined.Instance || (bool) value)
+                    if (value == Undefined.Instance || value.AsBoolean())
                     {
                         value = false;
                     }
@@ -284,7 +282,7 @@ namespace Jint.Runtime
                 
                 case "<=":
                     value = Compare(right, left, false);
-                    if (value == Undefined.Instance || (bool) value)
+                    if (value == Undefined.Instance || value.AsBoolean())
                     {
                         value = false;
                     }
@@ -319,7 +317,7 @@ namespace Jint.Runtime
                     return (uint)TypeConverter.ToInt32(left) >> (int)(TypeConverter.ToUint32(right) & 0x1F);
 
                 case "instanceof":
-                    var f = right as FunctionInstance;
+                    var f = right.TryCast<FunctionInstance>();
 
                     if (f == null)
                     {
@@ -330,14 +328,12 @@ namespace Jint.Runtime
                     break;
                 
                 case "in":
-                    var o = right as ObjectInstance;
-
-                    if (o == null)
+                    if (!right.IsObject())
                     {
                         throw new JavaScriptException(_engine.TypeError, "in can only be used with an object");
                     }
 
-                    value = o.HasProperty(TypeConverter.ToString(left));
+                    value = right.AsObject().HasProperty(TypeConverter.ToString(left).AsString());
                     break;
                 
                 default:
@@ -347,7 +343,7 @@ namespace Jint.Runtime
             return value;
         }
 
-        public object EvaluateLogicalExpression(LogicalExpression logicalExpression)
+        public JsValue EvaluateLogicalExpression(LogicalExpression logicalExpression)
         {
             var left = _engine.GetValue(EvaluateExpression(logicalExpression.Left));
 
@@ -355,7 +351,7 @@ namespace Jint.Runtime
             {
 
                 case "&&":
-                    if (!TypeConverter.ToBoolean(left))
+                    if (!TypeConverter.ToBoolean(left).AsBoolean())
                     {
                         return left;
                     }
@@ -363,7 +359,7 @@ namespace Jint.Runtime
                     return _engine.GetValue(EvaluateExpression(logicalExpression.Right));
 
                 case "||":
-                    if (TypeConverter.ToBoolean(left))
+                    if (TypeConverter.ToBoolean(left).AsBoolean())
                     {
                         return left;
                     }
@@ -375,10 +371,10 @@ namespace Jint.Runtime
             }
         }
 
-        public static bool Equal(object x, object y)
+        public static bool Equal(JsValue x, JsValue y)
         {
-            var typex = TypeConverter.GetType(x);
-            var typey = TypeConverter.GetType(y);
+            var typex = x.Type;
+            var typey = y.Type;
 
             if (typex == typey)
             {
@@ -389,8 +385,8 @@ namespace Jint.Runtime
 
                 if (typex == Types.Number)
                 {
-                    var nx = TypeConverter.ToNumber(x);
-                    var ny = TypeConverter.ToNumber(y);
+                    var nx = TypeConverter.ToNumber(x).AsNumber();
+                    var ny = TypeConverter.ToNumber(y).AsNumber();
 
                     if (double.IsNaN(nx) || double.IsNaN(ny))
                     {
@@ -412,7 +408,7 @@ namespace Jint.Runtime
 
                 if (typex == Types.Boolean)
                 {
-                    return (bool) x == (bool) y;
+                    return x.AsBoolean() == y.AsBoolean();
                 }
 
                 return x == y;
@@ -461,10 +457,10 @@ namespace Jint.Runtime
             return false;
         }
 
-        public static bool StriclyEqual(object x, object y)
+        public static bool StriclyEqual(JsValue x, JsValue y)
         {
-            var typea = TypeConverter.GetType(x);
-            var typeb = TypeConverter.GetType(y);
+            var typea = x.Type;
+            var typeb = y.Type;
 
             if (typea != typeb)
             {
@@ -482,8 +478,9 @@ namespace Jint.Runtime
             }
             if (typea == Types.Number)
             {
-                var nx = TypeConverter.ToNumber(x);
-                var ny = TypeConverter.ToNumber(y);
+                var nx = TypeConverter.ToNumber(x).AsNumber();
+                var ny = TypeConverter.ToNumber(y).AsNumber();
+
                 if (double.IsNaN(nx) || double.IsNaN(ny))
                 {
                     return false;
@@ -507,10 +504,10 @@ namespace Jint.Runtime
             return x == y;
         }
 
-        public static bool SameValue(object x, object y)
+        public static bool SameValue(JsValue x, JsValue y)
         {
-            var typea = TypeConverter.GetType(x);
-            var typeb = TypeConverter.GetType(y);
+            var typea = x.Type;
+            var typeb = y.Type;
 
             if (typea != typeb)
             {
@@ -523,8 +520,9 @@ namespace Jint.Runtime
             }
             if (typea == Types.Number)
             {
-                var nx = TypeConverter.ToNumber(x);
-                var ny = TypeConverter.ToNumber(y);
+                var nx = TypeConverter.ToNumber(x).AsNumber();
+                var ny = TypeConverter.ToNumber(y).AsNumber();
+
                 if (double.IsNaN(nx) && double.IsNaN(ny))
                 {
                     return true;
@@ -554,9 +552,9 @@ namespace Jint.Runtime
             return x == y;
         }
 
-        public static object Compare(object x, object y, bool leftFirst = true)
+        public static JsValue Compare(JsValue x, JsValue y, bool leftFirst = true)
         {
-            object px, py;
+            JsValue px, py;
             if (leftFirst)
             {
                 px = TypeConverter.ToPrimitive(x, Types.Number);
@@ -568,13 +566,13 @@ namespace Jint.Runtime
                 px = TypeConverter.ToPrimitive(x, Types.Number);
             }
 
-            var typea = TypeConverter.GetType(px);
-            var typeb = TypeConverter.GetType(py);
+            var typea = px.Type;
+            var typeb = py.Type;
 
             if (typea != Types.String || typeb != Types.String)
             {
-                var nx = TypeConverter.ToNumber(px);
-                var ny = TypeConverter.ToNumber(py);
+                var nx = TypeConverter.ToNumber(px).AsNumber();
+                var ny = TypeConverter.ToNumber(py).AsNumber();
 
                 if (double.IsNaN(nx) || double.IsNaN(ny))
                 {
@@ -610,7 +608,7 @@ namespace Jint.Runtime
             }
             else
             {
-                return String.CompareOrdinal(TypeConverter.ToString(x), TypeConverter.ToString(y)) < 0;
+                return String.CompareOrdinal(TypeConverter.ToString(x).AsString(), TypeConverter.ToString(y).AsString()) < 0;
             }
         }
 
@@ -622,17 +620,17 @@ namespace Jint.Runtime
             return LexicalEnvironment.GetIdentifierReference(env, identifier.Name, strict);
         }
 
-        public object EvaluateLiteral(Literal literal)
+        public JsValue EvaluateLiteral(Literal literal)
         {
             if (literal.Type == SyntaxNodes.RegularExpressionLiteral)
             {
                 return _engine.RegExp.Construct(literal.Raw);
             }
 
-            return literal.Value ?? Null.Instance;
+            return JsValue.FromObject(literal.Value);
         }
 
-        public object EvaluateObjectExpression(ObjectExpression objectExpression)
+        public JsValue EvaluateObjectExpression(ObjectExpression objectExpression)
         {
             // http://www.ecma-international.org/ecma-262/5.1/#sec-11.1.5
 
@@ -718,12 +716,12 @@ namespace Jint.Runtime
 
                     if (previous.IsAccessorDescriptor() && propDesc.IsAccessorDescriptor())
                     {
-                        if (propDesc.Set.IsPresent && previous.Set.IsPresent)
+                        if (propDesc.Set.HasValue && previous.Set.HasValue)
                         {
                             throw new JavaScriptException(_engine.SyntaxError);
                         }
-                        
-                        if (propDesc.Get.IsPresent && previous.Get.IsPresent)
+
+                        if (propDesc.Get.HasValue && previous.Get.HasValue)
                         {
                             throw new JavaScriptException(_engine.SyntaxError);
                         }
@@ -741,7 +739,7 @@ namespace Jint.Runtime
         /// </summary>
         /// <param name="memberExpression"></param>
         /// <returns></returns>
-        public object EvaluateMemberExpression(MemberExpression memberExpression)
+        public Reference EvaluateMemberExpression(MemberExpression memberExpression)
         {
             var baseReference = EvaluateExpression(memberExpression.Object);
             var baseValue = _engine.GetValue(baseReference);
@@ -756,12 +754,12 @@ namespace Jint.Runtime
             var propertyNameReference = EvaluateExpression(expression);
             var propertyNameValue = _engine.GetValue(propertyNameReference);
             TypeConverter.CheckObjectCoercible(_engine, baseValue);
-            var propertyNameString = TypeConverter.ToString(propertyNameValue);
+            var propertyNameString = TypeConverter.ToString(propertyNameValue).AsString();
 
             return new Reference(baseValue, propertyNameString, StrictModeScope.IsStrictModeCode);
         }
 
-        public object EvaluateFunctionExpression(FunctionExpression functionExpression)
+        public JsValue EvaluateFunctionExpression(FunctionExpression functionExpression)
         {
             var funcEnv = LexicalEnvironment.NewDeclarativeEnvironment(_engine, _engine.ExecutionContext.LexicalEnvironment);
             var envRec = (DeclarativeEnvironmentRecord)funcEnv.Record;
@@ -786,11 +784,11 @@ namespace Jint.Runtime
             return closure;
         }
 
-        public object EvaluateCallExpression(CallExpression callExpression)
+        public JsValue EvaluateCallExpression(CallExpression callExpression)
         {
             var callee = EvaluateExpression(callExpression.Callee);
 
-            object thisObject;
+            JsValue thisObject;
 
             // todo: implement as in http://www.ecma-international.org/ecma-262/5.1/#sec-11.2.4
             var arguments = callExpression.Arguments.Select(EvaluateExpression).Select(_engine.GetValue).ToArray();
@@ -802,12 +800,12 @@ namespace Jint.Runtime
                 throw new JavaScriptException(_engine.TypeError);
             }
 
-            if (TypeConverter.GetType(func) != Types.Object)
+            if (func.IsObject())
             {
                 throw new JavaScriptException(_engine.TypeError);
             }
 
-            var callable = func as ICallable;
+            var callable = func.TryCast<ICallable>();
             if (callable == null)
             {
                 throw new JavaScriptException(_engine.TypeError);
@@ -822,7 +820,7 @@ namespace Jint.Runtime
                 }
                 else
                 {
-                    var env = r.GetBase() as EnvironmentRecord;
+                    var env = r.GetBase().TryCast<EnvironmentRecord>();
                     thisObject = env.ImplicitThisValue();
                 }
             }
@@ -840,7 +838,7 @@ namespace Jint.Runtime
             return callable.Call(thisObject, arguments);
         }
 
-        public object EvaluateSequenceExpression(SequenceExpression sequenceExpression)
+        public JsValue EvaluateSequenceExpression(SequenceExpression sequenceExpression)
         {
             var result = Undefined.Instance;
             foreach (var expression in sequenceExpression.Expressions)
@@ -851,7 +849,7 @@ namespace Jint.Runtime
             return result;
         }
 
-        public object EvaluateUpdateExpression(UpdateExpression updateExpression)
+        public JsValue EvaluateUpdateExpression(UpdateExpression updateExpression)
         {
             var value = _engine.EvaluateExpression(updateExpression.Argument);
             Reference r;
@@ -862,13 +860,13 @@ namespace Jint.Runtime
                     r = value as Reference;
                     if (r != null
                         && r.IsStrict()
-                        && (r.GetBase() is EnvironmentRecord)
+                        && (r.GetBase().TryCast<EnvironmentRecord>() != null)
                         && (Array.IndexOf(new[] { "eval", "arguments" }, r.GetReferencedName()) != -1))
                     {
                         throw new JavaScriptException(_engine.SyntaxError);
                     }
 
-                    var oldValue = TypeConverter.ToNumber(_engine.GetValue(value));
+                    var oldValue = TypeConverter.ToNumber(_engine.GetValue(value)).AsNumber();
                     var newValue = oldValue + 1;
                     _engine.PutValue(r, newValue);
 
@@ -878,13 +876,13 @@ namespace Jint.Runtime
                     r = value as Reference;
                     if (r != null
                         && r.IsStrict()
-                        && (r.GetBase() is EnvironmentRecord)
+                        && (r.GetBase().TryCast<EnvironmentRecord>() != null)
                         && (Array.IndexOf(new[] { "eval", "arguments" }, r.GetReferencedName()) != -1))
                     {
                         throw new JavaScriptException(_engine.SyntaxError);
                     }
 
-                    oldValue = TypeConverter.ToNumber(_engine.GetValue(value));
+                    oldValue = TypeConverter.ToNumber(_engine.GetValue(value)).AsNumber();
                     newValue = oldValue - 1;
                     _engine.PutValue(r, newValue);
 
@@ -895,17 +893,17 @@ namespace Jint.Runtime
 
         }
 
-        public object EvaluateThisExpression(ThisExpression thisExpression)
+        public JsValue EvaluateThisExpression(ThisExpression thisExpression)
         {
             return _engine.ExecutionContext.ThisBinding;
         }
 
-        public object EvaluateNewExpression(NewExpression newExpression)
+        public JsValue EvaluateNewExpression(NewExpression newExpression)
         {
             var arguments = newExpression.Arguments.Select(EvaluateExpression).Select(_engine.GetValue).ToArray();
             
             // todo: optimize by defining a common abstract class or interface
-            var callee = _engine.GetValue(EvaluateExpression(newExpression.Callee)) as IConstructor;
+            var callee = _engine.GetValue(EvaluateExpression(newExpression.Callee)).TryCast<IConstructor>();
             
             if (callee == null)
             {
@@ -918,9 +916,9 @@ namespace Jint.Runtime
             return instance;
         }
 
-        public object EvaluateArrayExpression(ArrayExpression arrayExpression)
+        public JsValue EvaluateArrayExpression(ArrayExpression arrayExpression)
         {
-            var a = _engine.Array.Construct(new object[] { arrayExpression.Elements.Count() });
+            var a = _engine.Array.Construct(new JsValue[] { arrayExpression.Elements.Count() });
             var n = 0;
             foreach (var expr in arrayExpression.Elements)
             {
@@ -936,7 +934,7 @@ namespace Jint.Runtime
             return a;
         }
 
-        public object EvaluateUnaryExpression(UnaryExpression unaryExpression)
+        public JsValue EvaluateUnaryExpression(UnaryExpression unaryExpression)
         {
             var value = _engine.EvaluateExpression(unaryExpression.Argument);
             Reference r;
@@ -947,14 +945,14 @@ namespace Jint.Runtime
                     return TypeConverter.ToNumber(_engine.GetValue(value));
                     
                 case "-":
-                    var n = TypeConverter.ToNumber(_engine.GetValue(value));
+                    var n = TypeConverter.ToNumber(_engine.GetValue(value)).AsNumber();
                     return double.IsNaN(n) ? double.NaN : n*-1;
                 
                 case "~":
                     return ~TypeConverter.ToInt32(_engine.GetValue(value));
                 
                 case "!":
-                    return !TypeConverter.ToBoolean(_engine.GetValue(value));
+                    return !TypeConverter.ToBoolean(_engine.GetValue(value)).AsBoolean();
                 
                 case "delete":
                     r = value as Reference;
@@ -973,14 +971,14 @@ namespace Jint.Runtime
                     }
                     if (r.IsPropertyReference())
                     {
-                        var o = TypeConverter.ToObject(_engine, r.GetBase());
+                        var o = TypeConverter.ToObject(_engine, r.GetBase()).AsObject();
                         return o.Delete(r.GetReferencedName(), r.IsStrict());
                     }
                     if (r.IsStrict())
                     {
                         throw new JavaScriptException(_engine.SyntaxError);
                     }
-                    var bindings = r.GetBase() as EnvironmentRecord;
+                    var bindings = r.GetBase().TryCast<EnvironmentRecord>();
                     return bindings.DeleteBinding(r.GetReferencedName());
                 
                 case "void":
@@ -1005,13 +1003,13 @@ namespace Jint.Runtime
                     {
                         return "object";
                     }
-                    switch (TypeConverter.GetType(v))
+                    switch (v.Type)
                     {
                         case Types.Boolean: return "boolean";
                         case Types.Number: return "number";
                         case Types.String: return "string";
                     }
-                    if (v is ICallable)
+                    if (v.TryCast<ICallable>() != null)
                     {
                         return "function";
                     }

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

@@ -1,4 +1,5 @@
 using System;
+using Jint.Native;
 using Jint.Native.Function;
 
 namespace Jint.Runtime.Interop
@@ -6,11 +7,11 @@ namespace Jint.Runtime.Interop
     /// <summary>
     /// Wraps a Clr method into a FunctionInstance
     /// </summary>
-    public sealed class ClrFunctionInstance<TObject, TResult> : FunctionInstance
+    public sealed class ClrFunctionInstance : FunctionInstance
     {
-        private readonly Func<TObject, object[], TResult> _func;
+        private readonly Func<JsValue, JsValue[], JsValue> _func;
 
-        public ClrFunctionInstance(Engine engine, Func<TObject, object[], TResult> func, int length)
+        public ClrFunctionInstance(Engine engine, Func<JsValue, JsValue[], JsValue> func, int length)
             : base(engine, null, null, false)
         {
             _func = func;
@@ -18,16 +19,16 @@ namespace Jint.Runtime.Interop
             FastAddProperty("length", length, false, false, false);
         }
 
-        public ClrFunctionInstance(Engine engine, Func<TObject, object[], TResult> func)
+        public ClrFunctionInstance(Engine engine, Func<JsValue, JsValue[], JsValue> func)
             : this(engine, func, 0)
         {
         }
 
-        public override object Call(object thisObject, object[] arguments)
+        public override JsValue Call(JsValue thisObject, JsValue[] arguments)
         {
             try
             {
-                var result = _func((TObject) thisObject, arguments);
+                var result = _func(thisObject, arguments);
                 return result;
             }
             catch (InvalidCastException)

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

@@ -19,10 +19,9 @@ namespace Jint.Runtime.Interop
             _d = d;
         }
 
-        public override object Call(object thisObject, object[] arguments)
+        public override JsValue Call(JsValue thisObject, JsValue[] arguments)
         {
-            var result = _d.DynamicInvoke(arguments);
-            return new Completion(Completion.Normal, result, null);
+            return JsValue.FromObject(_d.DynamicInvoke(arguments));
         }
     }
 }

+ 6 - 5
Jint/Runtime/Interop/GetterFunctionInstance.cs

@@ -1,4 +1,5 @@
 using System;
+using Jint.Native;
 using Jint.Native.Function;
 
 namespace Jint.Runtime.Interop
@@ -6,19 +7,19 @@ namespace Jint.Runtime.Interop
     /// <summary>
     /// Represents a FunctionInstance wrapping a Clr getter.
     /// </summary>
-    public sealed class GetterFunctionInstance<T> : FunctionInstance
+    public sealed class GetterFunctionInstance: FunctionInstance
     {
-        private readonly Func<T, object> _getter;
+        private readonly Func<JsValue, JsValue> _getter;
 
-        public GetterFunctionInstance(Engine engine, Func<T, object> getter)
+        public GetterFunctionInstance(Engine engine, Func<JsValue, JsValue> getter)
             : base(engine,  null, null, false)
         {
             _getter = getter;
         }
 
-        public override object Call(object thisObject, object[] arguments)
+        public override JsValue Call(JsValue thisObject, JsValue[] arguments)
         {
-            return _getter((T)thisObject);
+            return _getter(thisObject);
         }
     }
 }

+ 5 - 5
Jint/Runtime/Interop/SetterFunctionInstance.cs

@@ -7,19 +7,19 @@ namespace Jint.Runtime.Interop
     /// <summary>
     /// Represents a FunctionInstance wrapping a Clr setter.
     /// </summary>
-    public sealed class SetterFunctionInstance<T> : FunctionInstance
+    public sealed class SetterFunctionInstance : FunctionInstance
     {
-        private readonly Action<T, object> _setter;
+        private readonly Action<JsValue, JsValue> _setter;
 
-        public SetterFunctionInstance(Engine engine, Action<T, object> setter)
+        public SetterFunctionInstance(Engine engine, Action<JsValue, JsValue> setter)
             : base(engine, null, null, false)
         {
             _setter = setter;
         }
 
-        public override object Call(object thisObject, object[] arguments)
+        public override JsValue Call(JsValue thisObject, JsValue[] arguments)
         {
-            _setter((T)thisObject, arguments[0]);
+            _setter(thisObject, arguments[0]);
             
             return Null.Instance;
         }

+ 5 - 4
Jint/Runtime/JavaScriptException.cs

@@ -1,11 +1,12 @@
 using System;
+using Jint.Native;
 using Jint.Native.Error;
 
 namespace Jint.Runtime
 {
     public class JavaScriptException : Exception
     {
-        private readonly object _errorObject;
+        private readonly JsValue _errorObject;
 
         public JavaScriptException(ErrorConstructor errorConstructor) : base("")
         {
@@ -15,15 +16,15 @@ namespace Jint.Runtime
         public JavaScriptException(ErrorConstructor errorConstructor, string message)
             : base(message)
         {
-            _errorObject = errorConstructor.Construct(new object[] { message });
+            _errorObject = errorConstructor.Construct(new JsValue[] { message });
         }
 
-        public JavaScriptException(object error)
+        public JavaScriptException(JsValue error)
             : base("")
         {
             _errorObject = error;
         }
 
-        public object Error { get { return _errorObject; } }
+        public JsValue Error { get { return _errorObject; } }
     }
 }

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

@@ -1,6 +1,4 @@
-using System;
-using Jint.Native;
-using Jint.Native.Object;
+using Jint.Native;
 
 namespace Jint.Runtime.References
 {
@@ -10,19 +8,18 @@ namespace Jint.Runtime.References
     /// </summary>
     public class Reference
     {
-
-        private readonly object _baseValue;
+        private readonly JsValue _baseValue;
         private readonly string _name;
         private readonly bool _strict;
 
-        public Reference(object baseValue, string name, bool strict)
+        public Reference(JsValue baseValue, string name, bool strict)
         {
             _baseValue = baseValue;
             _name = name;
             _strict = strict;
         }
 
-        public object GetBase()
+        public JsValue GetBase()
         {
             return _baseValue;
         }
@@ -39,23 +36,18 @@ namespace Jint.Runtime.References
 
         public bool HasPrimitiveBase()
         {
-            var type = TypeConverter.GetType(_baseValue);
-
-            return (type == Types.Boolean)
-                || (type == Types.String)
-                || (type == Types.Number)
-                ;
+            return _baseValue.IsPrimitive();
         }
 
         public bool IsUnresolvableReference()
         {
-            return _baseValue == Undefined.Instance;
+            return _baseValue.IsUndefined();
         }
 
         public bool IsPropertyReference()
         {
             // http://www.ecma-international.org/ecma-262/5.1/#sec-8.7
-            return _baseValue is ObjectInstance || HasPrimitiveBase();
+            return _baseValue.IsObject() || HasPrimitiveBase();
         }
     }
 }

+ 29 - 31
Jint/Runtime/StatementInterpreter.cs

@@ -2,7 +2,6 @@
 using System.Collections.Generic;
 using System.Linq;
 using Jint.Native;
-using Jint.Native.Object;
 using Jint.Parser.Ast;
 using Jint.Runtime.Environments;
 using Jint.Runtime.References;
@@ -25,7 +24,7 @@ namespace Jint.Runtime
 
         public Completion ExecuteEmptyStatement(EmptyStatement emptyStatement)
         {
-            return new Completion(Completion.Normal, null, null);
+            return new Completion(Completion.Normal, Undefined.Instance, null);
         }
 
         public Completion ExecuteExpressionStatement(ExpressionStatement expressionStatement)
@@ -39,7 +38,7 @@ namespace Jint.Runtime
             var exprRef = _engine.EvaluateExpression(ifStatement.Test);
             Completion result;
 
-            if (TypeConverter.ToBoolean(_engine.GetValue(exprRef)))
+            if (TypeConverter.ToBoolean(_engine.GetValue(exprRef)).AsBoolean())
             {
                 result = ExecuteStatement(ifStatement.Consequent);
             }
@@ -49,7 +48,7 @@ namespace Jint.Runtime
             }
             else
             {
-                return new Completion(Completion.Normal, null, null);
+                return new Completion(Completion.Normal, Null.Instance, null);
             }
 
             return result;
@@ -74,13 +73,13 @@ namespace Jint.Runtime
         /// <returns></returns>
         public Completion ExecuteDoWhileStatement(DoWhileStatement doWhileStatement)
         {
-            object v = null;
+            JsValue v = Null.Instance;
             bool iterating;
 
             do
             {
                 var stmt = ExecuteStatement(doWhileStatement.Body);
-                if (stmt.Value != null)
+                if (stmt.Value != Undefined.Instance)
                 {
                     v = stmt.Value;
                 }
@@ -97,7 +96,7 @@ namespace Jint.Runtime
                     }
                 }
                 var exprRef = _engine.EvaluateExpression(doWhileStatement.Test);
-                iterating = TypeConverter.ToBoolean(_engine.GetValue(exprRef));
+                iterating = TypeConverter.ToBoolean(_engine.GetValue(exprRef)).AsBoolean();
 
             } while (iterating);
 
@@ -111,19 +110,19 @@ namespace Jint.Runtime
         /// <returns></returns>
         public Completion ExecuteWhileStatement(WhileStatement whileStatement)
         {
-            object v = null; 
+            JsValue v = Null.Instance; 
             while (true)
             {
                 var exprRef = _engine.EvaluateExpression(whileStatement.Test);
 
-                if (!TypeConverter.ToBoolean(_engine.GetValue(exprRef)))
+                if (!TypeConverter.ToBoolean(_engine.GetValue(exprRef)).AsBoolean())
                 {
                     return new Completion(Completion.Normal, v, null);
                 }
 
                 var stmt = ExecuteStatement(whileStatement.Body);
 
-                if (stmt.Value != null)
+                if (stmt.Value != Null.Instance)
                 {
                     v = stmt.Value;
                 }
@@ -163,20 +162,20 @@ namespace Jint.Runtime
                 }
             }
 
-            object v = null;
+            JsValue v = Null.Instance;
             while (true)
             {
                 if (forStatement.Test != null)
                 {
                     var testExprRef = _engine.EvaluateExpression(forStatement.Test);
-                    if (!TypeConverter.ToBoolean(_engine.GetValue(testExprRef)))
+                    if (!TypeConverter.ToBoolean(_engine.GetValue(testExprRef)).AsBoolean())
                     {
                         return new Completion(Completion.Normal, v, null);
                     }
                 }
 
                 var stmt = ExecuteStatement(forStatement.Body);
-                if (stmt.Value != null)
+                if (stmt.Value != Null.Instance)
                 {
                     v = stmt.Value;
                 }
@@ -215,12 +214,12 @@ namespace Jint.Runtime
             var experValue = _engine.GetValue(exprRef);
             if (experValue == Undefined.Instance || experValue == Null.Instance)
             {
-                return new Completion(Completion.Normal, null, null);
+                return new Completion(Completion.Normal, Null.Instance, null);
             }
 
 
-            var obj = TypeConverter.ToObject(_engine, experValue);
-            object v = null;
+            var obj = TypeConverter.ToObject(_engine, experValue).AsObject();
+            JsValue v = Null.Instance;
             
             // keys are constructed using the prototype chain
             var cursor = obj;
@@ -245,7 +244,7 @@ namespace Jint.Runtime
                     }
 
                     var value = cursor.Properties[p];
-                    if (!value.Enumerable.Value)
+                    if (!value.Enumerable.HasValue || !value.Enumerable.Value.AsBoolean())
                     {
                         continue;
                     }
@@ -253,7 +252,7 @@ namespace Jint.Runtime
                     _engine.PutValue(varRef, p);
 
                     var stmt = ExecuteStatement(forInStatement.Body);
-                    if (stmt.Value != null)
+                    if (stmt.Value != Null.Instance)
                     {
                         v = stmt.Value;
                     }
@@ -283,7 +282,7 @@ namespace Jint.Runtime
         /// <returns></returns>
         public Completion ExecuteContinueStatement(ContinueStatement continueStatement)
         {
-            return new Completion(Completion.Continue, null, continueStatement.Label != null ? continueStatement.Label.Name : null);
+            return new Completion(Completion.Continue, Null.Instance, continueStatement.Label != null ? continueStatement.Label.Name : null);
         }
 
         /// <summary>
@@ -293,7 +292,7 @@ namespace Jint.Runtime
         /// <returns></returns>
         public Completion ExecuteBreakStatement(BreakStatement breakStatement)
         {
-            return new Completion(Completion.Break, null, breakStatement.Label != null ? breakStatement.Label.Name : null);
+            return new Completion(Completion.Break, Null.Instance, breakStatement.Label != null ? breakStatement.Label.Name : null);
         }
 
         /// <summary>
@@ -320,7 +319,7 @@ namespace Jint.Runtime
         public Completion ExecuteWithStatement(WithStatement withStatement)
         {
             var val = _engine.EvaluateExpression(withStatement.Object);
-            var obj = TypeConverter.ToObject(_engine, _engine.GetValue(val));
+            var obj = TypeConverter.ToObject(_engine, _engine.GetValue(val)).AsObject();
             var oldEnv = _engine.ExecutionContext.LexicalEnvironment;
             var newEnv = LexicalEnvironment.NewObjectEnvironment(_engine, obj, oldEnv, true);
             _engine.ExecutionContext.LexicalEnvironment = newEnv;
@@ -358,9 +357,9 @@ namespace Jint.Runtime
             return r;
         }
 
-        public Completion ExecuteSwitchBlock(IEnumerable<SwitchCase> switchBlock, object input)
+        public Completion ExecuteSwitchBlock(IEnumerable<SwitchCase> switchBlock, JsValue input)
         {
-            object v = null;
+            JsValue v = Null.Instance;
             SwitchCase defaultCase = null;
             bool hit = false;
             foreach (var clause in switchBlock)
@@ -406,7 +405,7 @@ namespace Jint.Runtime
 
         public Completion ExecuteStatementList(IEnumerable<Statement> statementList)
         {
-            var c = new Completion(Completion.Normal, null, null);
+            var c = new Completion(Completion.Normal, Null.Instance, null);
             Completion sl = c;
 
             try
@@ -416,7 +415,7 @@ namespace Jint.Runtime
                     c = ExecuteStatement(statement);
                     if (c.Type != Completion.Normal)
                     {
-                        return new Completion(c.Type, c.Value ?? sl.Value, c.Identifier);
+                        return new Completion(c.Type, c.Value != Null.Instance ? c.Value : sl.Value, c.Identifier);
                     }
 
                     sl = c;
@@ -427,7 +426,7 @@ namespace Jint.Runtime
                 return new Completion(Completion.Throw, v.Error, null);
             }
 
-            return new Completion(c.Type, c.Value ?? sl.Value, c.Identifier);
+            return new Completion(c.Type, c.Value != Null.Instance ? c.Value : sl.Value, c.Identifier);
         }
 
         /// <summary>
@@ -489,7 +488,6 @@ namespace Jint.Runtime
 
         public Completion ExecuteVariableDeclaration(VariableDeclaration statement)
         {
-            string lastIdentifier = null;
             foreach (var declaration in statement.Declarations)
             {
                 if (declaration.Init != null)
@@ -501,19 +499,19 @@ namespace Jint.Runtime
                         throw new ArgumentException();
                     }
 
-                    if (lhs.IsStrict() && lhs.GetBase() is EnvironmentRecord &&
+                    if (lhs.IsStrict() && lhs.GetBase().TryCast<EnvironmentRecord>() != null &&
                         (lhs.GetReferencedName() == "eval" || lhs.GetReferencedName() == "arguments"))
                     {
                         throw new JavaScriptException(_engine.SyntaxError);
                     }
 
-                    lastIdentifier = lhs.GetReferencedName();
+                    lhs.GetReferencedName();
                     var value = _engine.GetValue(_engine.EvaluateExpression(declaration.Init));
                     _engine.PutValue(lhs, value);
                 }
             }
 
-            return new Completion(Completion.Normal, null, null);
+            return new Completion(Completion.Normal, Null.Instance, null);
         }
 
         public Completion ExecuteBlockStatement(BlockStatement blockStatement)
@@ -530,7 +528,7 @@ namespace Jint.Runtime
             
             System.Diagnostics.Debugger.Break();
 
-            return new Completion(Completion.Normal, null, null);
+            return new Completion(Completion.Normal, Null.Instance, null);
         }
     }
 }

+ 74 - 177
Jint/Runtime/TypeConverter.cs

@@ -2,7 +2,6 @@
 using System.Globalization;
 using Jint.Native;
 using Jint.Native.Number;
-using Jint.Native.Object;
 
 namespace Jint.Runtime
 {
@@ -25,99 +24,75 @@ namespace Jint.Runtime
         /// <param name="input"></param>
         /// <param name="preferredType"></param>
         /// <returns></returns>
-        public static object ToPrimitive(object input, Types preferredType = Types.None)
+        public static JsValue ToPrimitive(JsValue input, Types preferredType = Types.None)
         {
             if (input == Null.Instance || input == Undefined.Instance)
             {
                 return input;
             }
 
-            var primitive = input as IPrimitiveType;
-            if (primitive != null)
-            {
-                return primitive.PrimitiveValue;
-            }
-
-            var o = input as ObjectInstance;
-
-            if (o == null)
+            if (input.IsPrimitive())
             {
                 return input;
             }
 
-            return o.DefaultValue(preferredType);
+            return input.AsObject().DefaultValue(preferredType);
         }
 
-        public static bool IsPrimitiveValue(object o)
-        {
-            return o is string
-                   || o is double
-                   || o is bool
-                   || o is Undefined
-                   || o is Null;
-        }
     
         /// <summary>
         /// http://www.ecma-international.org/ecma-262/5.1/#sec-9.2
         /// </summary>
         /// <param name="o"></param>
         /// <returns></returns>
-        public static bool ToBoolean(object o)
+        public static JsValue ToBoolean(JsValue o)
         {
-            if (o is bool)
+            if (o.IsObject())
             {
-                return (bool)o;
+                var p = o.AsObject() as IPrimitiveInstance;
+                if (p != null)
+                {
+                    o = p.PrimitiveValue;
+                }
             }
-            
+
             if (o == Undefined.Instance || o == Null.Instance)
             {
-                return false;
+                return JsValue.False;
             }
-
-
-            var p = o as IPrimitiveType;
-            if (p != null)
+            
+            if (o.IsBoolean())
             {
-                o = ToBoolean(p.PrimitiveValue);
+                return o;
             }
 
-            if (o is double)
+            if (o.IsNumber())
             {
-                var n = (double) o;
+                var n = o.AsNumber();
                 if (n == 0 || double.IsNaN(n))
                 {
-                    return false;
+                    return JsValue.False;
                 }
                 else
                 {
-                    return true;
+                    return JsValue.True;
                 }
             }
 
-            var s = o as string;
-            if (s != null)
+            if (o.IsString())
             {
+                var s = o.AsString();
                 if (String.IsNullOrEmpty(s))
                 {
-                    return false;
+                    return JsValue.False;
                 }
                 else
                 {
-                    return true;
+                    return JsValue.True;
                 }
             }
-
-            if (o is int)
-            {
-                return ToBoolean((double)(int)o);
-            }
-
-            if (o is uint)
-            {
-                return ToBoolean((double)(uint)o);
-            }
-
-            return true;
+            
+            return JsValue.True;
         }
 
         /// <summary>
@@ -125,26 +100,20 @@ namespace Jint.Runtime
         /// </summary>
         /// <param name="o"></param>
         /// <returns></returns>
-        public static double ToNumber(object o)
+        public static JsValue ToNumber(JsValue o)
         {
-            if (o is double)
-            {
-                return (double)o;
-            }
-
-            if (o is int)
-            {
-                return (int) o;
-            }
-
-            if (o is uint)
+            if (o.IsObject())
             {
-                return (uint)o;
+                var p = o.AsObject() as IPrimitiveInstance;
+                if (p != null)
+                {
+                    o = p.PrimitiveValue;
+                }
             }
 
-            if (o is DateTime)
+            if (o.IsNumber())
             {
-                return ((DateTime)o).Ticks;
+                return o;
             }
 
             if (o == Undefined.Instance)
@@ -157,16 +126,15 @@ namespace Jint.Runtime
                 return 0;
             }
 
-            if (o is bool)
+            if (o.IsBoolean())
             {
-                return (bool)o ? 1 : 0;
+                return o.AsBoolean() ? 1 : 0;
             }
 
-            var s = o as string;
-            if (s != null)
+            if (o.IsString())
             {
                 double n;
-                s = s.Trim();
+                var s = o.AsString().Trim();
 
                 if (String.IsNullOrEmpty(s))
                 {
@@ -230,9 +198,9 @@ namespace Jint.Runtime
         /// </summary>
         /// <param name="o"></param>
         /// <returns></returns>
-        public static double ToInteger(object o)
+        public static JsValue ToInteger(JsValue o)
         {
-            var number = ToNumber(o);
+            var number = ToNumber(o).AsNumber();
 
             if (double.IsNaN(number))
             {
@@ -252,14 +220,9 @@ namespace Jint.Runtime
         /// </summary>
         /// <param name="o"></param>
         /// <returns></returns>
-        public static int ToInt32(object o)
+        public static int ToInt32(JsValue o)
         {
-            if (o is int)
-            {
-                return (int)o;
-            }
-                
-            return (int)(uint)ToNumber(o);
+            return (int)(uint)ToNumber(o).AsNumber();
         }
 
         /// <summary>
@@ -267,14 +230,9 @@ namespace Jint.Runtime
         /// </summary>
         /// <param name="o"></param>
         /// <returns></returns>
-        public static uint ToUint32(object o)
+        public static uint ToUint32(JsValue o)
         {
-            if (o is uint)
-            {
-                return (uint)o;
-            }
-                
-            return (uint)ToNumber(o);
+            return (uint)ToNumber(o).AsNumber();
         }
 
         /// <summary>
@@ -282,9 +240,9 @@ namespace Jint.Runtime
         /// </summary>
         /// <param name="o"></param>
         /// <returns></returns>
-        public static ushort ToUint16(object o)
+        public static ushort ToUint16(JsValue o)
         {
-            return (ushort)(uint)ToNumber(o);
+            return (ushort)(uint)ToNumber(o).AsNumber();
         }
 
         /// <summary>
@@ -292,65 +250,50 @@ namespace Jint.Runtime
         /// </summary>
         /// <param name="o"></param>
         /// <returns></returns>
-        public static string ToString(object o)
+        public static JsValue ToString(JsValue o)
         {
-            var str = o as string;
-            if (str != null)
-            {
-                return str;
-            }
-
-            if (o == Undefined.Instance)
-            {
-                return Undefined.Instance.ToString();
-            }
-
-            if (o == Null.Instance)
-            {
-                return Null.Instance.ToString();
-            }
-
-            var p = o as IPrimitiveType;
-            if (p != null)
+            if (o.IsObject())
             {
-                o = p.PrimitiveValue;
+                var p = o.AsObject() as IPrimitiveInstance;
+                if (p != null)
+                {
+                    o = p.PrimitiveValue;
+                }
             }
 
-            if (o is bool)
+            if (o.IsString())
             {
-                return (bool) o ? "true" : "false";
+                return o;
             }
 
-            if (o is double)
+            if (o == Undefined.Instance)
             {
-                var m = (double) o;
-                return NumberPrototype.ToNumberString(m);
+                return Undefined.Text;
             }
 
-            if (o is int)
+            if (o == Null.Instance)
             {
-                return ToString((double)(int)o);
+                return Null.Text;
             }
-
-            if (o is uint)
+            
+            if (o.IsBoolean())
             {
-                return ToString((double)(uint)o);
+                return o.AsBoolean() ? "true" : "false";
             }
 
-            if (o is DateTime)
+            if (o.IsNumber())
             {
-                return o.ToString();
+                return NumberPrototype.ToNumberString(o.AsNumber());
             }
 
             return ToString(ToPrimitive(o, Types.String));
         }
 
-        public static ObjectInstance ToObject(Engine engine, object value)
+        public static JsValue ToObject(Engine engine, JsValue value)
         {
-            var o = value as ObjectInstance;
-            if (o != null)
+            if (value.IsObject())
             {
-                return o;
+                return value;
             }
 
             if (value == Undefined.Instance)
@@ -363,71 +306,25 @@ namespace Jint.Runtime
                 throw new JavaScriptException(engine.TypeError);
             }
 
-            if (value is bool)
-            {
-                return engine.Boolean.Construct((bool) value);
-            }
-
-            if (value is int)
+            if (value.IsBoolean())
             {
-                return engine.Number.Construct((int) value);
+                return engine.Boolean.Construct(value.AsBoolean());
             }
 
-            if (value is uint)
+            if (value.IsNumber())
             {
-                return engine.Number.Construct((uint) value);
+                return engine.Number.Construct(value.AsNumber());
             }
 
-            if (value is DateTime)
+            if (value.IsString())
             {
-                return engine.Date.Construct((DateTime)value);
-            }
-
-            if (value is double)
-            {
-                return engine.Number.Construct((double) value);
-            }
-
-            var s = value as string;
-            if (s != null)
-            {
-                return engine.String.Construct(s);
+                return engine.String.Construct(value.AsString());
             }
 
             throw new JavaScriptException(engine.TypeError);
         }
 
-        public static Types GetType(object value)
-        {
-            if (value == null || value == Null.Instance)
-            {
-                return Types.Null;
-            }
-
-            if (value == Undefined.Instance)
-            {
-                return Types.Undefined;
-            }
-
-            if (value is string)
-            {
-                return Types.String;
-            }
-
-            if (value is double || value is int || value is uint || value is ushort)
-            {
-                return Types.Number;
-            }
-
-            if (value is bool)
-            {
-                return Types.Boolean;
-            }
-
-            return Types.Object;
-        }
-
-        public static void CheckObjectCoercible(Engine engine, object o)
+        public static void CheckObjectCoercible(Engine engine, JsValue o)
         {
             if (o == Undefined.Instance || o == Null.Instance)
             {