Browse Source

Refactoring prototype chain construction

Sebastien Ros 12 years ago
parent
commit
c0c320e41c
43 changed files with 873 additions and 294 deletions
  1. 1 1
      Jint.Repl/Program.cs
  2. 43 3
      Jint.Tests/Runtime/EngineTests.cs
  3. 2 1
      Jint.Tests/Runtime/SunSpiderTests.cs
  4. 29 29
      Jint/Engine.cs
  5. 8 0
      Jint/Jint.csproj
  6. 3 2
      Jint/Native/Argument/ArgumentsObject.cs
  7. 23 50
      Jint/Native/Array/ArrayConstructor.cs
  8. 2 3
      Jint/Native/Array/ArrayInstance.cs
  9. 65 0
      Jint/Native/Array/ArrayPrototype.cs
  10. 22 8
      Jint/Native/Boolean/BooleanConstructor.cs
  11. 3 3
      Jint/Native/Boolean/BooleanInstance.cs
  12. 25 0
      Jint/Native/Boolean/BooleanPrototype.cs
  13. 21 9
      Jint/Native/Date/DateConstructor.cs
  14. 3 3
      Jint/Native/Date/DateInstance.cs
  15. 25 0
      Jint/Native/Date/DatePrototype.cs
  16. 19 20
      Jint/Native/Error/ErrorConstructor.cs
  17. 2 2
      Jint/Native/Error/ErrorInstance.cs
  18. 38 0
      Jint/Native/Error/ErrorPrototype.cs
  19. 1 1
      Jint/Native/Function/EvalFunctionInstance.cs
  20. 23 17
      Jint/Native/Function/FunctionConstructor.cs
  21. 14 2
      Jint/Native/Function/FunctionInstance.cs
  22. 78 0
      Jint/Native/Function/FunctionPrototype.cs
  23. 2 7
      Jint/Native/Function/FunctionShim.cs
  24. 47 23
      Jint/Native/Function/ScriptFunctionInstance.cs
  25. 1 1
      Jint/Native/Function/ThrowTypeError.cs
  26. 6 8
      Jint/Native/Global/GlobalObject.cs
  27. 2 0
      Jint/Native/IConstructor.cs
  28. 3 3
      Jint/Native/Json/JsonInstance.cs
  29. 6 7
      Jint/Native/Math/MathInstance.cs
  30. 22 14
      Jint/Native/Number/NumberConstructor.cs
  31. 3 3
      Jint/Native/Number/NumberInstance.cs
  32. 32 0
      Jint/Native/Number/NumberPrototype.cs
  33. 132 19
      Jint/Native/Object/ObjectConstructor.cs
  34. 20 24
      Jint/Native/Object/ObjectInstance.cs
  35. 60 0
      Jint/Native/Object/ObjectPrototype.cs
  36. 22 10
      Jint/Native/String/StringConstructor.cs
  37. 3 3
      Jint/Native/String/StringInstance.cs
  38. 26 0
      Jint/Native/String/StringPrototype.cs
  39. 32 14
      Jint/Runtime/ExpressionIntepreter.cs
  40. 1 1
      Jint/Runtime/Interop/ClrFunctionInstance.cs
  41. 1 1
      Jint/Runtime/Interop/DelegateWrapper.cs
  42. 1 1
      Jint/Runtime/Interop/GetterFunctionInstance.cs
  43. 1 1
      Jint/Runtime/Interop/SetterFunctionInstance.cs

+ 1 - 1
Jint.Repl/Program.cs

@@ -21,7 +21,7 @@ namespace Jint.Repl
                 }
 
                 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, "  "));
                 Console.ForegroundColor = ConsoleColor.Magenta;
                 Console.WriteLine("=> {0}", str);
             }

+ 43 - 3
Jint.Tests/Runtime/EngineTests.cs

@@ -109,6 +109,39 @@ namespace Jint.Tests.Runtime
             ");
         }
 
+        [Fact]
+        public void PrototypeFunctionIsInherited()
+        {
+            RunTest(@"
+                function Body(mass){
+                   this.mass = mass;
+                }
+
+                Body.prototype.offsetMass = function(dm) {
+                   this.mass += dm;
+                   return this;
+                }
+
+                var b = new Body(36);
+                b.offsetMass(6);
+                assert(b.mass == 42);
+            ");
+
+        }
+
+        [Fact]
+        public void FunctionConstructorCall()
+        {
+            RunTest(@"
+                function Body(mass){
+                   this.mass = mass;
+                }
+                
+                var john = new Body(36);
+                assert(john.mass == 36);
+            ");
+        }
+
         [Fact]
         public void NewObjectsShouldUsePrivateProperties()
         {
@@ -136,11 +169,19 @@ namespace Jint.Tests.Runtime
         {
             RunTest(@"
                 var o = new Object();
-                assert(o instanceof Object);
                 assert(o.constructor == Object);
             ");
         }
 
+        [Fact]
+        public void NewObjectsIntanceOfConstructorObject()
+        {
+            RunTest(@"
+                var o = new Object();
+                assert(o instanceof Object);
+            ");
+        }
+
         [Fact]
         public void NewObjectsConstructorShouldBeConstructorObject()
         {
@@ -152,7 +193,7 @@ namespace Jint.Tests.Runtime
         }
 
         [Fact]
-        public void NewObjectsIntanceOfConstructorObject()
+        public void NewObjectsIntanceOfConstructorFunction()
         {
             RunTest(@"
                 var Vehicle = function () {};
@@ -258,7 +299,6 @@ namespace Jint.Tests.Runtime
             RunTest(@"
                 var o = [];
                 assert(o.constructor == Array);
-                assert(o.hasOwnProperty('constructor') == false);
             ");
         }
 

+ 2 - 1
Jint.Tests/Runtime/SunSpiderTests.cs

@@ -60,7 +60,8 @@ namespace Jint.Tests.Runtime
         }
 
         [Theory]
-        [InlineData("access-nbody", "https://raw.github.com/WebKit/webkit/master/PerformanceTests/SunSpider/tests/sunspider-1.0.1/access-nbody.js")]
+        //[InlineData("access-nbody", "https://raw.github.com/WebKit/webkit/master/PerformanceTests/SunSpider/tests/sunspider-1.0.1/access-nbody.js")]
+        [InlineData("access-nbody", "https://gist.github.com/sebastienros/6284478/raw/gistfile1.js")]
         public void AccessNBody(string name, string url)
         {
             var content = new WebClient().DownloadString(url);

+ 29 - 29
Jint/Engine.cs

@@ -37,27 +37,25 @@ namespace Jint
         {
             _executionContexts = new Stack<ExecutionContext>();
 
-            RootObject = new ObjectInstance(this, null);
-            RootFunction = new FunctionShim(this, RootObject, null, null);
-
-            Object = new ObjectConstructor(this);
-            Global = GlobalObject.CreateGlobalObject(this, Object);
-            Function = new FunctionConstructor(this);
-            Array = new ArrayConstructor(this);
-            String = new StringConstructor(this);
-            Number = new NumberConstructor(this);
-            Boolean = new BooleanConstructor(this);
-            Date = new DateConstructor(this);
-            Math = MathInstance.CreateMathObject(this, RootObject);
-            JSON = JsonInstance.CreateJsonObject(this);
-
-            Error = new ErrorConstructor(this, "Error");
-            EvalError = new ErrorConstructor(this, "EvalError");
-            RangeError = new ErrorConstructor(this, "RangeError");
-            ReferenceError = new ErrorConstructor(this, "ReferenceError");
-            SyntaxError = new ErrorConstructor(this, "SyntaxError");
-            TypeError = new ErrorConstructor(this, "TypeError");
-            URIError = new ErrorConstructor(this, "URIError");
+            Object = ObjectConstructor.CreateObjectConstructor(this);
+
+            Global = GlobalObject.CreateGlobalObject(this);
+            Function = FunctionConstructor.CreateFunctionConstructor(this);
+            Array = ArrayConstructor.CreateArrayConstructor(this);
+            String = StringConstructor.CreateStringConstructor(this);
+            Number = NumberConstructor.CreateNumberConstructor(this);
+            Boolean = BooleanConstructor.CreateBooleanConstructor(this);
+            Date = DateConstructor.CreateDateConstructor(this);
+            Math = MathInstance.CreateMathObject(this);
+            Json = JsonInstance.CreateJsonObject(this);
+
+            Error = ErrorConstructor.CreateErrorConstructor(this, "Error");
+            EvalError = ErrorConstructor.CreateErrorConstructor(this, "EvalError");
+            RangeError = ErrorConstructor.CreateErrorConstructor(this, "RangeError");
+            ReferenceError = ErrorConstructor.CreateErrorConstructor(this, "ReferenceError");
+            SyntaxError = ErrorConstructor.CreateErrorConstructor(this, "SyntaxError");
+            TypeError = ErrorConstructor.CreateErrorConstructor(this, "TypeError");
+            UriError = ErrorConstructor.CreateErrorConstructor(this, "URIError");
 
             Global.FastAddProperty("Object", Object, true, false, true);
             Global.FastAddProperty("Function", Function, true, false, true);
@@ -67,7 +65,7 @@ namespace Jint
             Global.FastAddProperty("Boolean", Boolean, true, false, true);
             Global.FastAddProperty("Date", Date, true, false, true);
             Global.FastAddProperty("Math", Math, true, false, true);
-            Global.FastAddProperty("JSON", JSON, true, false, true);
+            Global.FastAddProperty("JSON", Json, true, false, true);
 
             Global.FastAddProperty("Error", Error, true, false, true);
             Global.FastAddProperty("EvalError", EvalError, true, false, true);
@@ -75,7 +73,7 @@ namespace Jint
             Global.FastAddProperty("ReferenceError", ReferenceError, true, false, true);
             Global.FastAddProperty("SyntaxError", SyntaxError, true, false, true);
             Global.FastAddProperty("TypeError", TypeError, true, false, true);
-            Global.FastAddProperty("URIError", URIError, true, false, true);
+            Global.FastAddProperty("URIError", UriError, true, false, true);
 
             // create the global environment http://www.ecma-international.org/ecma-262/5.1/#sec-10.2.3
             GlobalEnvironment = LexicalEnvironment.NewObjectEnvironment(this, Global, null, true);
@@ -98,7 +96,7 @@ namespace Jint
                 }
             }
 
-            Eval = new EvalFunctionInstance(this, new ObjectInstance(this, null), new string[0], LexicalEnvironment.NewDeclarativeEnvironment(this, ExecutionContext.LexicalEnvironment), Options.IsStrict());
+            Eval = new EvalFunctionInstance(this, new ObjectInstance(this), new string[0], LexicalEnvironment.NewDeclarativeEnvironment(this, ExecutionContext.LexicalEnvironment), Options.IsStrict());
             Global.FastAddProperty("eval", Eval, true, false, true);
 
             _statements = new StatementInterpreter(this);
@@ -107,9 +105,6 @@ namespace Jint
 
         public LexicalEnvironment GlobalEnvironment;
 
-        public ObjectInstance RootObject { get; private set; }
-        public FunctionInstance RootFunction { get; private set; }
-
         public ObjectInstance Global { get; private set; }
         public ObjectConstructor Object { get; private set; }
         public FunctionConstructor Function { get; private set; }
@@ -119,7 +114,7 @@ namespace Jint
         public NumberConstructor Number { get; private set; }
         public DateConstructor Date { get; private set; }
         public MathInstance Math { get; private set; }
-        public JsonInstance JSON { get; private set; }
+        public JsonInstance Json { get; private set; }
         public EvalFunctionInstance Eval { get; private set; }
 
         public ErrorConstructor Error { get; private set; }
@@ -128,7 +123,7 @@ namespace Jint
         public ErrorConstructor TypeError { get; private set; }
         public ErrorConstructor RangeError { get; private set; }
         public ErrorConstructor ReferenceError { get; private set; }
-        public ErrorConstructor URIError { get; private set; }
+        public ErrorConstructor UriError { get; private set; }
 
         public ExecutionContext ExecutionContext { get { return _executionContexts.Peek(); } }
 
@@ -367,6 +362,11 @@ namespace Jint
                 var baseValue = reference.GetBase();
                 var record = baseValue as EnvironmentRecord;
 
+                if (record == null)
+                {
+                    throw new ArgumentNullException();
+                }
+
                 record.SetMutableBinding(reference.GetReferencedName(), value, reference.IsStrict());
             }
         }

+ 8 - 0
Jint/Jint.csproj

@@ -39,13 +39,18 @@
     <Compile Include="Engine.cs" />
     <Compile Include="Native\Array\ArrayConstructor.cs" />
     <Compile Include="Native\Array\ArrayInstance.cs" />
+    <Compile Include="Native\Array\ArrayPrototype.cs" />
+    <Compile Include="Native\Boolean\BooleanPrototype.cs" />
     <Compile Include="Native\Boolean\BooleanConstructor.cs" />
     <Compile Include="Native\Boolean\BooleanInstance.cs" />
+    <Compile Include="Native\Date\DatePrototype.cs" />
     <Compile Include="Native\Date\DateConstructor.cs" />
     <Compile Include="Native\Date\DateInstance.cs" />
+    <Compile Include="Native\Error\ErrorPrototype.cs" />
     <Compile Include="Native\Error\ErrorConstructor.cs" />
     <Compile Include="Native\Error\ErrorInstance.cs" />
     <Compile Include="Native\Argument\ArgumentsObject.cs" />
+    <Compile Include="Native\Function\FunctionPrototype.cs" />
     <Compile Include="Native\Function\ThrowTypeError.cs" />
     <Compile Include="Native\Function\EvalFunctionInstance.cs" />
     <Compile Include="Native\Function\FunctionConstructor.cs" />
@@ -60,10 +65,13 @@
     <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" />
     <Compile Include="Native\Object\ObjectConstructor.cs" />
     <Compile Include="Native\Object\ObjectInstance.cs" />
+    <Compile Include="Native\Object\ObjectPrototype.cs" />
+    <Compile Include="Native\String\StringPrototype.cs" />
     <Compile Include="Native\String\StringConstructor.cs" />
     <Compile Include="Native\String\StringInstance.cs" />
     <Compile Include="Native\Undefined.cs" />

+ 3 - 2
Jint/Native/Argument/ArgumentsObject.cs

@@ -14,7 +14,7 @@ namespace Jint.Native.Argument
     /// </summary>
     public class ArgumentsInstance : ObjectInstance
     {
-        public ArgumentsInstance(Engine engine, ObjectInstance prototype) : base(engine, prototype)
+        public ArgumentsInstance(Engine engine) : base(engine)
         {
             // todo: complete implementation
         }
@@ -22,7 +22,8 @@ namespace Jint.Native.Argument
         public static ArgumentsInstance CreateArgumentsObject(Engine engine, FunctionInstance func, string[] names, object[] args, EnvironmentRecord env, bool strict)
         {
             var len = args.Length;
-            var obj = new ArgumentsInstance(engine, engine.Object);
+            var obj = new ArgumentsInstance(engine);
+            obj.Prototype = engine.Object.PrototypeObject;
             obj.DefineOwnProperty("length", new DataDescriptor(len) { Writable = true, Enumerable = false, Configurable = true }, false);
             var map = engine.Object.Construct(Arguments.Empty);
             var mappedNamed = new List<string>();

+ 23 - 50
Jint/Native/Array/ArrayConstructor.cs

@@ -1,28 +1,33 @@
 using System;
-using System.Linq;
 using Jint.Native.Function;
 using Jint.Native.Object;
 using Jint.Runtime;
-using Jint.Runtime.Descriptors;
-using Jint.Runtime.Descriptors.Specialized;
 
 namespace Jint.Native.Array
 {
     public sealed class ArrayConstructor : FunctionInstance, IConstructor
     {
-        private readonly Engine _engine;
+        private ArrayConstructor(Engine engine) :  base(engine, null, null, false)
+        {
+        }
+
+        public ObjectInstance PrototypeObject { get; private set; }
 
-        public ArrayConstructor(Engine engine) :  base(engine, new ObjectInstance(engine, engine.RootFunction), null, null, false)
+        public static ArrayConstructor CreateArrayConstructor(Engine engine)
         {
-            _engine = engine;
+            var obj = new ArrayConstructor(engine);
+            obj.Extensible = true;
+
+            // The value of the [[Prototype]] internal property of the Array constructor is the Function prototype object 
+            obj.Prototype = engine.Function.PrototypeObject;
+            obj.PrototypeObject = ArrayPrototype.CreatePrototypeObject(engine, obj);
+
+            obj.FastAddProperty("length", 1, false, false, false);
 
-            // the constructor is the function constructor of an object
-            Prototype.DefineOwnProperty("constructor", new DataDescriptor(this) { Writable = true, Enumerable = false, Configurable = false }, false);
-            Prototype.DefineOwnProperty("prototype", new DataDescriptor(Prototype) { Writable = true, Enumerable = false, Configurable = false }, false);
-                                  
-            // Array prototype functions
-            Prototype.DefineOwnProperty("push", new ClrDataDescriptor<ArrayInstance, object>(engine, Push), false);
-            Prototype.DefineOwnProperty("pop", new ClrDataDescriptor<ArrayInstance, object>(engine, Pop), false);
+            // The initial value of Array.prototype is the Array prototype object
+            obj.FastAddProperty("prototype", obj.PrototypeObject, false, false, false);
+
+            return obj;
         }
 
         public override object Call(object thisObject, object[] arguments)
@@ -32,8 +37,10 @@ namespace Jint.Native.Array
 
         public ObjectInstance Construct(object[] arguments)
         {
-            var instance = new ArrayInstance(_engine, Prototype);
-            
+            var instance = new ArrayInstance(Engine);
+            instance.Prototype = PrototypeObject;
+            instance.Extensible = true;
+
             if (arguments.Length == 1 && TypeConverter.GetType(arguments[0]) == TypeCode.Double)
             {
                 var length = TypeConverter.ToNumber(arguments[0]);
@@ -42,45 +49,11 @@ namespace Jint.Native.Array
             else
             {
                 instance.FastAddProperty("length", 0, true, false, true);
-                Push(instance, arguments);
+                ((ArrayPrototype)PrototypeObject).Push(instance, arguments);
             }
 
             return instance;
         }
 
-        private object Push(object thisObject, object[] arguments)
-        {
-            var o = TypeConverter.ToObject(_engine, thisObject);
-            var lenVal = o.Get("length");
-            var n = TypeConverter.ToUint32(lenVal);
-            foreach (var e in arguments)
-            {
-                o.Put(TypeConverter.ToString(n), e, true);
-                n++;
-            }
-            o.Put("length", n, true);
-
-            return n;
-        }
-
-        private object Pop(object thisObject, object[] arguments)
-        {
-            var o = TypeConverter.ToObject(_engine, thisObject);
-            var lenVal = o.Get("length");
-            var len = TypeConverter.ToUint32(lenVal);
-            if (len == 0)
-            {
-                o.Put("length", 0, true);
-                return Undefined.Instance;
-            }
-            else
-            {
-                var indx = TypeConverter.ToString(len - 1);
-                var element = o.Get(indx);
-                o.Delete(indx, true);
-                o.Put("length", indx, true);
-                return element;
-            }
-        }
     }
 }

+ 2 - 3
Jint/Native/Array/ArrayInstance.cs

@@ -1,5 +1,4 @@
-using System.Collections.Generic;
-using Jint.Native.Object;
+using Jint.Native.Object;
 using Jint.Runtime;
 using Jint.Runtime.Descriptors;
 
@@ -9,7 +8,7 @@ namespace Jint.Native.Array
     {
         private readonly Engine _engine;
  
-        public ArrayInstance(Engine engine, ObjectInstance prototype) : base(engine, prototype)
+        public ArrayInstance(Engine engine) : base(engine)
         {
             _engine = engine;
         }

+ 65 - 0
Jint/Native/Array/ArrayPrototype.cs

@@ -0,0 +1,65 @@
+using Jint.Native.Object;
+using Jint.Runtime;
+using Jint.Runtime.Interop;
+
+namespace Jint.Native.Array
+{
+    /// <summary>
+    /// http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4
+    /// </summary>
+    public sealed class ArrayPrototype : ObjectInstance
+    {
+        private ArrayPrototype(Engine engine) : base(engine)
+        {
+        }
+
+        public static ArrayPrototype CreatePrototypeObject(Engine engine, ArrayConstructor arrayConstructor)
+        {
+            var obj = new ArrayPrototype(engine) { Extensible = true };
+
+            obj.FastAddProperty("constructor", arrayConstructor, false, false, false);
+
+            // Array prototype functions
+            obj.FastAddProperty("push", new ClrFunctionInstance<ArrayInstance, object>(engine, obj.Push), false, false, false);
+            obj.FastAddProperty("pop", new ClrFunctionInstance<ArrayInstance, object>(engine, obj.Pop), false, false, false);
+
+            return obj;
+        }
+
+
+        public object Push(object thisObject, object[] arguments)
+        {
+            var o = TypeConverter.ToObject(Engine, thisObject);
+            var lenVal = o.Get("length");
+            var n = TypeConverter.ToUint32(lenVal);
+            foreach (var e in arguments)
+            {
+                o.Put(TypeConverter.ToString(n), e, true);
+                n++;
+            }
+            o.Put("length", n, true);
+
+            return n;
+        }
+
+        public object Pop(object thisObject, object[] arguments)
+        {
+            var o = TypeConverter.ToObject(Engine, thisObject);
+            var lenVal = o.Get("length");
+            var len = TypeConverter.ToUint32(lenVal);
+            if (len == 0)
+            {
+                o.Put("length", 0, true);
+                return Undefined.Instance;
+            }
+            else
+            {
+                var indx = TypeConverter.ToString(len - 1);
+                var element = o.Get(indx);
+                o.Delete(indx, true);
+                o.Put("length", indx, true);
+                return element;
+            }
+        }
+    }
+}

+ 22 - 8
Jint/Native/Boolean/BooleanConstructor.cs

@@ -1,7 +1,6 @@
 using Jint.Native.Function;
 using Jint.Native.Object;
 using Jint.Runtime;
-using Jint.Runtime.Descriptors;
 
 namespace Jint.Native.Boolean
 {
@@ -9,15 +8,25 @@ namespace Jint.Native.Boolean
     {
         private readonly Engine _engine;
 
-        public BooleanConstructor(Engine engine)
-            : base(engine, new ObjectInstance(engine, engine.Object), null, null, false)
+        private BooleanConstructor(Engine engine): base(engine, null, null, false)
         {
-            _engine = engine;
+        }
+
+        public static BooleanConstructor CreateBooleanConstructor(Engine engine)
+        {
+            var obj = new BooleanConstructor(engine);
+            obj.Extensible = true;
+
+            // The value of the [[Prototype]] internal property of the Boolean constructor is the Function prototype object 
+            obj.Prototype = engine.Function.PrototypeObject;
+            obj.PrototypeObject = BooleanPrototype.CreatePrototypeObject(engine, obj);
 
-            // the constructor is the function constructor of an object
-            Prototype.DefineOwnProperty("constructor", new DataDescriptor(this) { Writable = true, Enumerable = false, Configurable = false }, false);
-            Prototype.DefineOwnProperty("prototype", new DataDescriptor(Prototype) { Writable = true, Enumerable = false, Configurable = false }, false);
+            obj.FastAddProperty("length", 1, false, false, false);
 
+            // The initial value of Boolean.prototype is the Boolean prototype object
+            obj.FastAddProperty("prototype", obj.PrototypeObject, false, false, false);
+
+            return obj;
         }
 
         public override object Call(object thisObject, object[] arguments)
@@ -40,10 +49,15 @@ namespace Jint.Native.Boolean
             return Construct(TypeConverter.ToBoolean(arguments[0]));
         }
 
+        public ObjectInstance PrototypeObject { get; private set; }
+
         public BooleanInstance Construct(bool value)
         {
-            var instance = new BooleanInstance(_engine, Prototype);
+            var instance = new BooleanInstance(_engine);
+            instance.Prototype = PrototypeObject;
             instance.PrimitiveValue = value;
+            instance.Extensible = true;
+
             return instance;
         }
     }

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

@@ -3,10 +3,10 @@ using Jint.Native.Object;
 
 namespace Jint.Native.Boolean
 {
-    public sealed class BooleanInstance : ObjectInstance, IPrimitiveType
+    public class BooleanInstance : ObjectInstance, IPrimitiveType
     {
-        public BooleanInstance(Engine engine, ObjectInstance prototype)
-            : base(engine, prototype)
+        public BooleanInstance(Engine engine)
+            : base(engine)
         {
         }
 

+ 25 - 0
Jint/Native/Boolean/BooleanPrototype.cs

@@ -0,0 +1,25 @@
+namespace Jint.Native.Boolean
+{
+    /// <summary>
+    /// http://www.ecma-international.org/ecma-262/5.1/#sec-15.6.4
+    /// </summary>
+    public sealed class BooleanPrototype : BooleanInstance
+    {
+        private BooleanPrototype(Engine engine) : base(engine)
+        {
+        }
+
+        public static BooleanPrototype CreatePrototypeObject(Engine engine, BooleanConstructor booleanConstructor)
+        {
+            var obj = new BooleanPrototype(engine);
+            obj.Prototype = engine.Object.PrototypeObject;
+            obj.PrimitiveValue = false;
+
+            obj.FastAddProperty("constructor", booleanConstructor, false, false, false);
+
+            return obj;
+        }
+
+
+    }
+}

+ 21 - 9
Jint/Native/Date/DateConstructor.cs

@@ -2,23 +2,30 @@
 using Jint.Native.Function;
 using Jint.Native.Object;
 using Jint.Runtime;
-using Jint.Runtime.Descriptors;
 
 namespace Jint.Native.Date
 {
     public sealed class DateConstructor : FunctionInstance, IConstructor
     {
-        private readonly Engine _engine;
+        public DateConstructor(Engine engine) : base(engine, null, null, false)
+        {
+        }
 
-        public DateConstructor(Engine engine)
-            : base(engine, new ObjectInstance(engine, engine.Object), null, null, false)
+        public static DateConstructor CreateDateConstructor(Engine engine)
         {
-            _engine = engine;
+            var obj = new DateConstructor(engine);
+            obj.Extensible = true;
+
+            // The value of the [[Prototype]] internal property of the Date constructor is the Function prototype object 
+            obj.Prototype = engine.Function.PrototypeObject;
+            obj.PrototypeObject = DatePrototype.CreatePrototypeObject(engine, obj);
 
-            // the constructor is the function constructor of an object
-            Prototype.DefineOwnProperty("constructor", new DataDescriptor(this) { Writable = true, Enumerable = false, Configurable = false }, false);
-            Prototype.DefineOwnProperty("prototype", new DataDescriptor(Prototype) { Writable = true, Enumerable = false, Configurable = false }, false);
+            obj.FastAddProperty("length", 1, false, false, false);
 
+            // The initial value of Date.prototype is the Boolean prototype object
+            obj.FastAddProperty("prototype", obj.PrototypeObject, false, false, false);
+
+            return obj;
         }
 
         public override object Call(object thisObject, object[] arguments)
@@ -70,10 +77,15 @@ namespace Jint.Native.Date
             }
         }
 
+        public ObjectInstance PrototypeObject { get; private set; }
+
         public DateInstance Construct(DateTime value)
         {
-            var instance = new DateInstance(_engine, Prototype);
+            var instance = new DateInstance(Engine);
+            instance.Prototype = PrototypeObject;
             instance.PrimitiveValue = value;
+            instance.Extensible = true;
+
             return instance;
         }
 

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

@@ -3,10 +3,10 @@ using Jint.Native.Object;
 
 namespace Jint.Native.Date
 {
-    public sealed class DateInstance : ObjectInstance, IPrimitiveType
+    public class DateInstance : ObjectInstance, IPrimitiveType
     {
-        public DateInstance(Engine engine, ObjectInstance prototype)
-            : base(engine, prototype)
+        public DateInstance(Engine engine)
+            : base(engine)
         {
         }
 

+ 25 - 0
Jint/Native/Date/DatePrototype.cs

@@ -0,0 +1,25 @@
+namespace Jint.Native.Date
+{
+    /// <summary>
+    /// http://www.ecma-international.org/ecma-262/5.1/#sec-15.9.5
+    /// </summary>
+    public sealed class DatePrototype : DateInstance
+    {
+        private DatePrototype(Engine engine)
+            : base(engine)
+        {
+        }
+
+        public static DatePrototype CreatePrototypeObject(Engine engine, DateConstructor dateConstructor)
+        {
+            var obj = new DatePrototype(engine);
+            obj.Prototype = engine.Object.PrototypeObject;
+
+            obj.FastAddProperty("constructor", dateConstructor, false, false, false);
+
+            return obj;
+        }
+
+
+    }
+}

+ 19 - 20
Jint/Native/Error/ErrorConstructor.cs

@@ -1,31 +1,30 @@
 using Jint.Native.Function;
 using Jint.Native.Object;
 using Jint.Runtime;
-using Jint.Runtime.Descriptors;
-using Jint.Runtime.Descriptors.Specialized;
 
 namespace Jint.Native.Error
 {
     public sealed class ErrorConstructor : FunctionInstance, IConstructor
     {
-        private readonly Engine _engine;
+        public ErrorConstructor(Engine engine) : base(engine, null, null, false)
+        {
+        }
 
-        public ErrorConstructor(Engine engine, string name)
-            : base(engine, new ErrorInstance(engine, null, name), null, null, false)
+        public static ErrorConstructor CreateErrorConstructor(Engine engine, string name)
         {
-            _engine = engine;
+            var obj = new ErrorConstructor(engine);
+            obj.Extensible = true;
+
+            // The value of the [[Prototype]] internal property of the Error constructor is the Function prototype object 
+            obj.Prototype = engine.Function.PrototypeObject;
+            obj.PrototypeObject = ErrorPrototype.CreatePrototypeObject(engine, obj, name);
 
-            // the constructor is the function constructor of an object
-            Prototype.DefineOwnProperty("constructor", new DataDescriptor(this) { Writable = true, Enumerable = false, Configurable = false }, false);
-            Prototype.DefineOwnProperty("prototype", new DataDescriptor(Prototype) { Writable = true, Enumerable = false, Configurable = false }, false);
-                                  
-            // Error prototype properties
-            Prototype.DefineOwnProperty("message", new ClrAccessDescriptor<ErrorInstance>(_engine, x => x.Message), false);
-            Prototype.DefineOwnProperty("name", new ClrAccessDescriptor<ErrorInstance>(_engine, x => x.Name), false);
+            obj.FastAddProperty("length", 1, false, false, false);
 
-            // Error prototype functions
-            Prototype.DefineOwnProperty("toString", new ClrDataDescriptor<ErrorInstance, object>(engine, ToErrorString), false);
+            // The initial value of Date.prototype is the Boolean prototype object
+            obj.FastAddProperty("prototype", obj.PrototypeObject, false, false, false);
 
+            return obj;
         }
 
         public override object Call(object thisObject, object[] arguments)
@@ -35,7 +34,9 @@ namespace Jint.Native.Error
 
         public ObjectInstance Construct(object[] arguments)
         {
-            var instance = new ErrorInstance(_engine, Prototype, null) {Extensible = true};
+            var instance = new ErrorInstance(Engine, null);
+            instance.Prototype = PrototypeObject;
+            instance.Extensible = true;
 
             if (arguments.Length > 0 && arguments[0] != Undefined.Instance)
             {
@@ -45,10 +46,8 @@ namespace Jint.Native.Error
             return instance;
         }
 
-        private static object ToErrorString(ErrorInstance thisObject, object[] arguments)
-        {
-            return thisObject.ToErrorString();
-        }
+        public ObjectInstance PrototypeObject { get; private set; }
+
 
     }
 }

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

@@ -5,8 +5,8 @@ namespace Jint.Native.Error
 {
     public sealed class ErrorInstance : ObjectInstance
     {
-        public ErrorInstance(Engine engine, ObjectInstance prototype, string name)
-            : base(engine, prototype)
+        public ErrorInstance(Engine engine, string name)
+            : base(engine)
         {
             Name = name;
             Message = "";

+ 38 - 0
Jint/Native/Error/ErrorPrototype.cs

@@ -0,0 +1,38 @@
+using Jint.Native.Object;
+using Jint.Runtime.Descriptors.Specialized;
+
+namespace Jint.Native.Error
+{
+    /// <summary>
+    /// http://www.ecma-international.org/ecma-262/5.1/#sec-15.11.4
+    /// </summary>
+    public sealed class ErrorPrototype : ObjectInstance
+    {
+        private ErrorPrototype(Engine engine)
+            : base(engine)
+        {
+        }
+
+        public static ErrorPrototype CreatePrototypeObject(Engine engine, ErrorConstructor errorConstructor, string name)
+        {
+            var obj = new ErrorPrototype(engine) { Extensible = true };
+
+            obj.FastAddProperty("constructor", errorConstructor, false, false, false);
+
+            // Error prototype properties
+            obj.DefineOwnProperty("message", new ClrAccessDescriptor<ErrorInstance>(engine, x => x.Message), false);
+            obj.DefineOwnProperty("name", new ClrAccessDescriptor<ErrorInstance>(engine, x => x.Name), false);
+
+            // Error prototype functions
+            obj.DefineOwnProperty("toString", new ClrDataDescriptor<ErrorInstance, object>(engine, ToErrorString), false);
+
+
+            return obj;
+        }
+
+        private static object ToErrorString(ErrorInstance thisObject, object[] arguments)
+        {
+            return thisObject.ToErrorString();
+        }
+    }
+}

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

@@ -10,7 +10,7 @@ namespace Jint.Native.Function
     {
         private readonly Engine _engine;
 
-        public EvalFunctionInstance(Engine engine, ObjectInstance prototype, string[] parameters, LexicalEnvironment scope, bool strict) : base(engine, prototype, parameters, scope, strict)
+        public EvalFunctionInstance(Engine engine, ObjectInstance prototype, string[] parameters, LexicalEnvironment scope, bool strict) : base(engine, parameters, scope, strict)
         {
             _engine = engine;
         }

+ 23 - 17
Jint/Native/Function/FunctionConstructor.cs

@@ -4,7 +4,6 @@ using Jint.Native.Object;
 using Jint.Parser.Ast;
 using Jint.Runtime;
 using Jint.Runtime.Descriptors;
-using Jint.Runtime.Descriptors.Specialized;
 using Jint.Runtime.Environments;
 
 namespace Jint.Native.Function
@@ -14,19 +13,27 @@ namespace Jint.Native.Function
     /// </summary>
     public sealed class FunctionConstructor : FunctionInstance, IConstructor
     {
-        private readonly Engine _engine;
+        private FunctionConstructor(Engine engine):base(engine, null, null, false)
+        {
+        }
 
-        public FunctionConstructor(Engine engine)
-            : base(engine, engine.RootFunction, null, null, false)
+        public static FunctionConstructor CreateFunctionConstructor(Engine engine)
         {
-            _engine = engine;
-            // http://www.ecma-international.org/ecma-262/5.1/#sec-13.2
+            var obj = new FunctionConstructor(engine);
+
+            // The value of the [[Prototype]] internal property of the Function constructor is the standard built-in Function prototype object 
+            obj.Prototype = FunctionPrototype.CreatePrototypeObject(engine);
+
+            // The initial value of Function.prototype is the standard built-in Function prototype object
+            obj.PrototypeObject = obj.Prototype;
+            obj.FastAddProperty("prototype", obj.PrototypeObject, false, false, false);
 
-            Extensible = true;
+            obj.FastAddProperty("length", 1, false, false, false);
 
-            // Function.prototype properties
-            engine.RootFunction.DefineOwnProperty("apply", new ClrDataDescriptor<object, object>(engine, Apply), false);
+            return obj;
         }
+        
+        public ObjectInstance PrototypeObject { get; private set; }
 
         public override object Call(object thisObject, object[] arguments)
         {
@@ -35,7 +42,8 @@ namespace Jint.Native.Function
 
         public ObjectInstance Construct(object[] arguments)
         {
-            var instance = new FunctionShim(_engine, Prototype, null, _engine.GlobalEnvironment);
+            var instance = new FunctionShim(Engine, null, Engine.GlobalEnvironment);
+            instance.Extensible = true;
             instance.DefineOwnProperty("constructor", new DataDescriptor(Prototype) { Writable = true, Enumerable = false, Configurable = false }, false);
 
             return instance;
@@ -49,11 +57,9 @@ namespace Jint.Native.Function
         public FunctionInstance CreateFunctionObject(FunctionDeclaration functionDeclaration)
         {
             var functionObject = new ScriptFunctionInstance(
-                _engine,
+                Engine,
                 functionDeclaration,
-                _engine.Function.Prototype /* instancePrototype */,
-                _engine.Object.Construct(Arguments.Empty) /* functionPrototype */,
-                LexicalEnvironment.NewDeclarativeEnvironment(_engine, _engine.ExecutionContext.LexicalEnvironment),
+                LexicalEnvironment.NewDeclarativeEnvironment(Engine, Engine.ExecutionContext.LexicalEnvironment),
                 functionDeclaration.Strict
                 ) { Extensible = true };
 
@@ -71,7 +77,7 @@ namespace Jint.Native.Function
                     return _throwTypeError;
                 }
 
-                _throwTypeError = new ThrowTypeError(_engine);
+                _throwTypeError = new ThrowTypeError(Engine);
                 return _throwTypeError;
             }
         }
@@ -89,7 +95,7 @@ namespace Jint.Native.Function
 
             if (func == null)
             {
-                throw new JavaScriptException(_engine.TypeError);
+                throw new JavaScriptException(Engine.TypeError);
             }
 
             if (argArray == Null.Instance || argArray == Undefined.Instance)
@@ -100,7 +106,7 @@ namespace Jint.Native.Function
             var argArrayObj = argArray as ObjectInstance;
             if (argArrayObj == null)
             {
-                throw new JavaScriptException(_engine.TypeError);
+                throw new JavaScriptException(Engine.TypeError);
             }
 
             var len = argArrayObj.Get("length");

+ 14 - 2
Jint/Native/Function/FunctionInstance.cs

@@ -8,7 +8,7 @@ namespace Jint.Native.Function
     {
         private readonly Engine _engine;
 
-        protected FunctionInstance(Engine engine, ObjectInstance prototype, string[] parameters, LexicalEnvironment scope, bool strict) : base(engine, prototype)
+        protected FunctionInstance(Engine engine, string[] parameters, LexicalEnvironment scope, bool strict) : base(engine)
         {
             _engine = engine;
             FormalParameters = parameters;
@@ -38,6 +38,11 @@ namespace Jint.Native.Function
         // todo: implement
         public object BoundArgs { get; set; }
 
+        /// <summary>
+        /// http://www.ecma-international.org/ecma-262/5.1/#sec-15.3.5.3
+        /// </summary>
+        /// <param name="instance"></param>
+        /// <returns></returns>
         public bool HasInstance(object instance)
         {
             var v = instance as ObjectInstance;
@@ -46,6 +51,13 @@ namespace Jint.Native.Function
                 return false;
             }
 
+            var o = v.Get("prototype") as ObjectInstance;
+            
+            if (o == null)
+            {
+                throw new JavaScriptException(_engine.TypeError);    
+            }
+
             while (true)
             {
                 v = v.Prototype;
@@ -54,7 +66,7 @@ namespace Jint.Native.Function
                 {
                     return false;
                 }
-                if (v == this.Prototype)
+                if (v == o)
                 {
                     return true;
                 }

+ 78 - 0
Jint/Native/Function/FunctionPrototype.cs

@@ -0,0 +1,78 @@
+using System;
+using System.Collections.Generic;
+using Jint.Native.Object;
+using Jint.Runtime;
+using Jint.Runtime.Descriptors.Specialized;
+using Jint.Runtime.Interop;
+
+namespace Jint.Native.Function
+{
+    /// <summary>
+    /// http://www.ecma-international.org/ecma-262/5.1/#sec-15.3.4
+    /// </summary>
+    public sealed class FunctionPrototype : FunctionInstance
+    {
+        private FunctionPrototype(Engine engine):base(engine, null, null, false)
+        {
+
+        }
+
+        public static FunctionPrototype CreatePrototypeObject(Engine engine)
+        {
+            var obj = new FunctionPrototype(engine);
+
+            // The value of the [[Prototype]] internal property of the Function prototype object is the standard built-in Object prototype object
+            obj.Prototype = engine.Object.PrototypeObject;
+
+            obj.FastAddProperty("length", 0, false, false, false);
+
+            obj.FastAddProperty("apply", new ClrFunctionInstance<object, object>(engine, obj.Apply), false, false, false);
+
+            return obj;
+        }
+
+        public object Apply(object thisObject, object[] arguments)
+        {
+            if (arguments.Length != 2)
+            {
+                throw new ArgumentException("Apply has to be called with two arguments.");
+            }
+
+            var func = thisObject as ICallable;
+            var thisArg = arguments[0];
+            var argArray = arguments[1];
+
+            if (func == null)
+            {
+                throw new JavaScriptException(Engine.TypeError);
+            }
+
+            if (argArray == Null.Instance || argArray == Undefined.Instance)
+            {
+                return func.Call(thisArg, Arguments.Empty);
+            }
+
+            var argArrayObj = argArray as ObjectInstance;
+            if (argArrayObj == null)
+            {
+                throw new JavaScriptException(Engine.TypeError);
+            }
+
+            var len = argArrayObj.Get("length");
+            var n = TypeConverter.ToUint32(len);
+            var argList = new List<object>();
+            for (var index = 0; index < n; index++)
+            {
+                var indexName = index.ToString();
+                var nextArg = argArrayObj.Get(indexName);
+                argList.Add(nextArg);
+            }
+            return func.Call(thisArg, argList.ToArray());
+        }
+
+        public override object Call(object thisObject, object[] arguments)
+        {
+            return Undefined.Instance;
+        }
+    }
+}

+ 2 - 7
Jint/Native/Function/FunctionShim.cs

@@ -1,16 +1,11 @@
-using Jint.Native.Object;
-using Jint.Parser.Ast;
-using Jint.Runtime.Environments;
+using Jint.Runtime.Environments;
 
 namespace Jint.Native.Function
 {
     public sealed class FunctionShim : FunctionInstance
     {
-        private readonly Engine _engine;
-
-        public FunctionShim(Engine engine, ObjectInstance prototype, string[] parameters, LexicalEnvironment scope) : base(engine, prototype, parameters, scope, false)
+        public FunctionShim(Engine engine, string[] parameters, LexicalEnvironment scope) : base(engine, parameters, scope, false)
         {
-            _engine = engine;
         }
 
         public override object Call(object thisObject, object[] arguments)

+ 47 - 23
Jint/Native/Function/ScriptFunctionInstance.cs

@@ -14,24 +14,33 @@ namespace Jint.Native.Function
     /// </summary>
     public sealed class ScriptFunctionInstance : FunctionInstance, IConstructor
     {
-        private readonly Engine _engine;
+        private readonly Engine Engine;
         private readonly IFunctionDeclaration _functionDeclaration;
-        
-        public ScriptFunctionInstance(Engine engine, IFunctionDeclaration functionDeclaration, ObjectInstance instancePrototype, ObjectInstance functionPrototype, LexicalEnvironment scope, bool strict)
-            : base(engine, instancePrototype, functionDeclaration.Parameters.Select(x => x.Name).ToArray(), scope, strict)
+
+        /// <summary>
+        /// http://www.ecma-international.org/ecma-262/5.1/#sec-13.2
+        /// </summary>
+        /// <param name="engine"></param>
+        /// <param name="functionDeclaration"></param>
+        /// <param name="scope"></param>
+        /// <param name="strict"></param>
+        public ScriptFunctionInstance(Engine engine, IFunctionDeclaration functionDeclaration, LexicalEnvironment scope, bool strict)
+            : base(engine, functionDeclaration.Parameters.Select(x => x.Name).ToArray(), scope, strict)
         {
-            // http://www.ecma-international.org/ecma-262/5.1/#sec-13.2
 
-            _engine = engine;
+            Engine = engine;
             _functionDeclaration = functionDeclaration;
             Extensible = true;
+            
             var len = functionDeclaration.Parameters.Count();
-
             DefineOwnProperty("length", new DataDescriptor(len) { Writable = false, Enumerable = false, Configurable = false }, false);
-            DefineOwnProperty("name", new DataDescriptor(_functionDeclaration.Id), false);
-            instancePrototype.DefineOwnProperty("constructor", new DataDescriptor(this) { Writable = true, Enumerable = true, Configurable = true }, false);
-            DefineOwnProperty("prototype", new DataDescriptor(functionPrototype) { Writable = true, Enumerable = true, Configurable = true }, false);
 
+            var proto = engine.Object.Construct(Arguments.Empty);
+            proto.DefineOwnProperty("constructor", new DataDescriptor(this) { Writable = true, Enumerable = false, Configurable = true }, false);
+            DefineOwnProperty("prototype", new DataDescriptor(proto) { Writable = true, Enumerable = false, Configurable = false }, false);
+
+            DefineOwnProperty("name", new DataDescriptor(_functionDeclaration.Id), false);
+            
             if (strict)
             {
                 var thrower = engine.Function.ThrowTypeError;
@@ -51,26 +60,26 @@ namespace Jint.Native.Function
             object thisBinding;
 
             // setup new execution context http://www.ecma-international.org/ecma-262/5.1/#sec-10.4.3
-            if (_engine.Options.IsStrict())
+            if (Engine.Options.IsStrict())
             {
                 thisBinding = thisArg;
             }
             else if (thisArg == Undefined.Instance || thisArg == Null.Instance)
             {
-                thisBinding = _engine.Global;
+                thisBinding = Engine.Global;
             }
             else if (TypeConverter.GetType(thisArg) != TypeCode.Object)
             {
-                thisBinding = TypeConverter.ToObject(_engine, thisArg);
+                thisBinding = TypeConverter.ToObject(Engine, thisArg);
             }
             else
             {
                 thisBinding = thisArg;
             }
 
-            var localEnv = LexicalEnvironment.NewDeclarativeEnvironment(_engine, Scope);
+            var localEnv = LexicalEnvironment.NewDeclarativeEnvironment(Engine, Scope);
             
-            _engine.EnterExecutionContext(localEnv, localEnv, thisBinding);
+            Engine.EnterExecutionContext(localEnv, localEnv, thisBinding);
 
             // Declaration Binding Instantiation http://www.ecma-international.org/ecma-262/5.1/#sec-10.5
             var env = localEnv.Record;
@@ -92,13 +101,13 @@ namespace Jint.Native.Function
                 env.SetMutableBinding(argName, v, Strict);
             }
 
-            _engine.FunctionDeclarationBindings(_functionDeclaration, localEnv, true, Strict);
+            Engine.FunctionDeclarationBindings(_functionDeclaration, localEnv, true, Strict);
 
             var argumentsAlreadyDeclared = env.HasBinding("arguments");
 
             if (!argumentsAlreadyDeclared)
             {
-                var argsObj = ArgumentsInstance.CreateArgumentsObject(_engine, this, _functionDeclaration.Parameters.Select(x => x.Name).ToArray(), arguments, env, Strict);
+                var argsObj = ArgumentsInstance.CreateArgumentsObject(Engine, this, _functionDeclaration.Parameters.Select(x => x.Name).ToArray(), arguments, env, Strict);
 
                 if (Strict)
                 {
@@ -114,11 +123,11 @@ namespace Jint.Native.Function
             }
 
             // process all variable declarations in the current parser scope
-            _engine.VariableDeclarationBinding(_functionDeclaration, env, configurableBindings, Strict);
+            Engine.VariableDeclarationBinding(_functionDeclaration, env, configurableBindings, Strict);
 
-            var result = _engine.ExecuteStatement(_functionDeclaration.Body);
+            var result = Engine.ExecuteStatement(_functionDeclaration.Body);
             
-            _engine.LeaveExecutionContext();
+            Engine.LeaveExecutionContext();
 
             if (result.Type == Completion.Throw)
             {
@@ -128,12 +137,27 @@ namespace Jint.Native.Function
             return result;
         }
 
+        /// <summary>
+        /// http://www.ecma-international.org/ecma-262/5.1/#sec-13.2.2
+        /// </summary>
+        /// <param name="arguments"></param>
+        /// <returns></returns>
         public ObjectInstance Construct(object[] arguments)
         {
-            // todo: http://www.ecma-international.org/ecma-262/5.1/#sec-13.2.2
+            var proto = Get("prototype") as ObjectInstance;
+            var obj = new ObjectInstance(Engine);
+            obj.Extensible = true;
+            obj.Prototype = proto ?? Engine.Object;
 
-            var instance = new FunctionShim(_engine, Prototype, null, null);
-            return instance;
+            var result = Call(obj, arguments) as ObjectInstance;
+            if (result != null)
+            {
+                return result;
+            }
+            
+            return obj;
         }
+
+        public ObjectInstance PrototypeObject { get; private set; }
     }
 }

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

@@ -8,7 +8,7 @@ namespace Jint.Native.Function
     {
         private readonly Engine _engine;
 
-        public ThrowTypeError(Engine engine): base(engine, engine.Function, new string[0], engine.GlobalEnvironment, false)
+        public ThrowTypeError(Engine engine): base(engine, new string[0], engine.GlobalEnvironment, false)
         {
             _engine = engine;
             DefineOwnProperty("length", new DataDescriptor(0) { Writable = false, Enumerable = false, Configurable = false }, false);

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

@@ -9,17 +9,15 @@ namespace Jint.Native.Global
 {
     public sealed class GlobalObject : ObjectInstance
     {
-        private readonly Engine _engine;
-
-        private GlobalObject(Engine engine, ObjectInstance prototype)
-            : base(engine, prototype)
+        private GlobalObject(Engine engine) : base(engine)
         {
-            _engine = engine;
         }
 
-        public static GlobalObject CreateGlobalObject(Engine engine, ObjectInstance prototype)
+        public static GlobalObject CreateGlobalObject(Engine engine)
         {
-            var global = new GlobalObject(engine, prototype);
+            var global = new GlobalObject(engine);
+            global.Prototype = null;
+            global.Extensible = true;
             
             // Global object properties
             global.DefineOwnProperty("NaN", new DataDescriptor(double.NaN), false);
@@ -27,7 +25,7 @@ namespace Jint.Native.Global
             global.DefineOwnProperty("undefined", new DataDescriptor(Undefined.Instance), false);
 
             // Global object functions
-            global.DefineOwnProperty("parseInt", new ClrDataDescriptor<object, object>(engine, ParseInt) { }, false);
+            global.DefineOwnProperty("parseInt", new ClrDataDescriptor<object, object>(engine, ParseInt), false);
             global.DefineOwnProperty("parseFloat", new ClrDataDescriptor<object, object>(engine, ParseFloat), false);
             global.DefineOwnProperty("isNaN", new ClrDataDescriptor<object, bool>(engine, IsNaN), false);
             global.DefineOwnProperty("isFinite", new ClrDataDescriptor<object, bool>(engine, IsFinite), false);

+ 2 - 0
Jint/Native/IConstructor.cs

@@ -6,5 +6,7 @@ namespace Jint.Native
     {
         object Call(object thisObject, object[] arguments);
         ObjectInstance Construct(object[] arguments);
+
+        ObjectInstance PrototypeObject { get; }
     }
 }

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

@@ -7,8 +7,8 @@ namespace Jint.Native.Json
     {
         private readonly Engine _engine;
 
-        private JsonInstance(Engine engine, ObjectInstance prototype)
-            : base(engine, prototype)
+        private JsonInstance(Engine engine)
+            : base(engine)
         {
             _engine = engine;
             Extensible = true;
@@ -24,7 +24,7 @@ namespace Jint.Native.Json
 
         public static JsonInstance CreateJsonObject(Engine engine)
         {
-            var json = new JsonInstance(engine, engine.Object.Prototype);
+            var json = new JsonInstance(engine);
             json.DefineOwnProperty("parse", new ClrDataDescriptor<JsonInstance, object>(engine, json.Parse), false);
             json.DefineOwnProperty("stringify", new ClrDataDescriptor<JsonInstance, object>(engine, json.Stringify), false);
 

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

@@ -7,12 +7,8 @@ namespace Jint.Native.Math
 {
     public sealed class MathInstance : ObjectInstance
     {
-        private readonly Engine _engine;
-
-        public MathInstance(Engine engine, ObjectInstance prototype)
-            : base(engine, prototype)
+        private MathInstance(Engine engine):base(engine)
         {
-            _engine = engine;
         }
 
         public override string Class
@@ -23,9 +19,12 @@ namespace Jint.Native.Math
             }
         }
 
-        public static MathInstance CreateMathObject(Engine engine, ObjectInstance prototype)
+        public static MathInstance CreateMathObject(Engine engine)
         {
-            var math = new MathInstance(engine, prototype);
+            var math = new MathInstance(engine);
+            math.Extensible = true;
+            math.Prototype = engine.Object.Prototype;
+
             math.DefineOwnProperty("abs", new ClrDataDescriptor<object, double>(engine, Abs), false);
             math.DefineOwnProperty("acos", new ClrDataDescriptor<object, double>(engine, Acos), false);
             math.DefineOwnProperty("asin", new ClrDataDescriptor<object, double>(engine, Asin), false);

+ 22 - 14
Jint/Native/Number/NumberConstructor.cs

@@ -8,24 +8,27 @@ namespace Jint.Native.Number
 {
     public sealed class NumberConstructor : FunctionInstance, IConstructor
     {
-        private readonly Engine _engine;
-
         public NumberConstructor(Engine engine)
-            : base(engine, new ObjectInstance(engine, engine.Object), null, null, false)
+            : base(engine, null, null, false)
+        {
+            
+        }
+
+        public static NumberConstructor CreateNumberConstructor(Engine engine)
         {
-            _engine = engine;
+            var obj = new NumberConstructor(engine);
+            obj.Extensible = true;
 
-            // the constructor is the function constructor of an object
-            this.Prototype.DefineOwnProperty("constructor", new DataDescriptor(this) { Writable = true, Enumerable = false, Configurable = false }, false);
-            this.Prototype.DefineOwnProperty("prototype", new DataDescriptor(Prototype) { Writable = true, Enumerable = false, Configurable = false }, false);
+            // The value of the [[Prototype]] internal property of the Number constructor is the Function prototype object 
+            obj.Prototype = engine.Function.PrototypeObject;
+            obj.PrototypeObject = NumberPrototype.CreatePrototypeObject(engine, obj);
 
-            // Number prototype properties
-            this.Prototype.DefineOwnProperty("NaN", new DataDescriptor(double.NaN), false);
-            this.Prototype.DefineOwnProperty("MAX_VALUE", new DataDescriptor(double.MaxValue), false);
-            this.Prototype.DefineOwnProperty("MIN_VALUE", new DataDescriptor(double.MinValue), false);
-            this.Prototype.DefineOwnProperty("POSITIVE_INFINITY", new DataDescriptor(double.PositiveInfinity), false);
-            this.Prototype.DefineOwnProperty("NEGATIVE_INFINITY", new DataDescriptor(double.NegativeInfinity), false);
+            obj.FastAddProperty("length", 1, false, false, false);
 
+            // The initial value of Number.prototype is the Number prototype object
+            obj.FastAddProperty("prototype", obj.PrototypeObject, false, false, false);
+
+            return obj;
         }
 
         public override object Call(object thisObject, object[] arguments)
@@ -48,10 +51,15 @@ namespace Jint.Native.Number
             return Construct(arguments.Length > 0 ? TypeConverter.ToNumber(arguments[0]) : 0);
         }
 
+        public ObjectInstance PrototypeObject { get; private set; }
+
         public NumberInstance Construct(double value)
         {
-            var instance = new NumberInstance(_engine, Prototype);
+            var instance = new NumberInstance(Engine);
+            instance.Prototype = PrototypeObject;
             instance.PrimitiveValue = value;
+            instance.Extensible = true;
+
             return instance;
         }
 

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

@@ -3,10 +3,10 @@ using Jint.Native.Object;
 
 namespace Jint.Native.Number
 {
-    public sealed class NumberInstance : ObjectInstance, IPrimitiveType
+    public class NumberInstance : ObjectInstance, IPrimitiveType
     {
-        public NumberInstance(Engine engine, ObjectInstance prototype)
-            : base(engine, prototype)
+        public NumberInstance(Engine engine)
+            : base(engine)
         {
         }
 

+ 32 - 0
Jint/Native/Number/NumberPrototype.cs

@@ -0,0 +1,32 @@
+namespace Jint.Native.Number
+{
+    /// <summary>
+    /// http://www.ecma-international.org/ecma-262/5.1/#sec-15.7.4
+    /// </summary>
+    public sealed class NumberPrototype : NumberInstance
+    {
+        private NumberPrototype(Engine engine)
+            : base(engine)
+        {
+        }
+
+        public static NumberPrototype CreatePrototypeObject(Engine engine, NumberConstructor numberConstructor)
+        {
+            var obj = new NumberPrototype(engine);
+            obj.Prototype = engine.Object.PrototypeObject;
+            obj.PrimitiveValue = 0;
+
+            obj.FastAddProperty("constructor", numberConstructor, false, false, false);
+
+            obj.FastAddProperty("NaN", double.NaN, false, false, false);
+            obj.FastAddProperty("MAX_VALUE", double.MaxValue, false, false, false);
+            obj.FastAddProperty("MIN_VALUE", double.MinValue, false, false, false);
+            obj.FastAddProperty("POSITIVE_INFINITY", double.PositiveInfinity, false, false, false);
+            obj.FastAddProperty("NEGATIVE_INFINITY", double.NegativeInfinity, false, false, false);
+
+            return obj;
+        }
+
+
+    }
+}

+ 132 - 19
Jint/Native/Object/ObjectConstructor.cs

@@ -1,7 +1,7 @@
-using Jint.Native.Function;
+using System;
+using Jint.Native.Function;
 using Jint.Runtime;
-using Jint.Runtime.Descriptors;
-using Jint.Runtime.Descriptors.Specialized;
+using Jint.Runtime.Interop;
 
 namespace Jint.Native.Object
 {
@@ -9,41 +9,154 @@ namespace Jint.Native.Object
     {
         private readonly Engine _engine;
 
-        public ObjectConstructor(Engine engine) : base(engine, engine.RootFunction, null, null, false)
+        private ObjectConstructor(Engine engine) : base(engine, null, null, false)
         {
             _engine = engine;
-            engine.RootFunction.DefineOwnProperty("hasOwnProperty", new ClrDataDescriptor<object, bool>(engine, HasOwnProperty), false);
-            engine.RootFunction.DefineOwnProperty("toString", new ClrDataDescriptor<object, string>(engine, ToString), false);
         }
 
+        public static ObjectConstructor CreateObjectConstructor(Engine engine)
+        {
+            var obj = new ObjectConstructor(engine);
+            // obj.Prototype = engine.Function.PrototypeObject;
+            obj.PrototypeObject = ObjectPrototype.CreatePrototypeObject(engine, obj);
+
+            obj.FastAddProperty("length", 1, false, false, false);
+            obj.FastAddProperty("prototype", obj.PrototypeObject, false, false, false);
+
+            obj.FastAddProperty("getPrototypeOf", new ClrFunctionInstance<object, object>(engine, obj.GetPrototypeOf), false, false, false);
+            obj.FastAddProperty("getOwnPropertyDescriptor", new ClrFunctionInstance<object, object>(engine, obj.GetOwnPropertyDescriptor), false, false, false);
+            obj.FastAddProperty("getOwnPropertyNames", new ClrFunctionInstance<object, object>(engine, obj.GetOwnPropertyNames), false, false, false);
+            obj.FastAddProperty("create", new ClrFunctionInstance<object, object>(engine, obj.Create), false, false, false);
+            obj.FastAddProperty("defineProperty", new ClrFunctionInstance<object, object>(engine, obj.DefineProperty), false, false, false);
+            obj.FastAddProperty("defineProperties", new ClrFunctionInstance<object, object>(engine, obj.DefineProperties), false, false, false);
+            obj.FastAddProperty("seal", new ClrFunctionInstance<object, object>(engine, obj.Seal), false, false, false);
+            obj.FastAddProperty("freeze", new ClrFunctionInstance<object, object>(engine, obj.Freeze), false, false, false);
+            obj.FastAddProperty("preventExtensions", new ClrFunctionInstance<object, object>(engine, obj.PreventExtensions), false, false, false);
+            obj.FastAddProperty("isSealed", new ClrFunctionInstance<object, object>(engine, obj.IsSealed), false, false, false);
+            obj.FastAddProperty("isFrozen", new ClrFunctionInstance<object, object>(engine, obj.IsFrozen), false, false, false);
+            obj.FastAddProperty("isExtensible", new ClrFunctionInstance<object, object>(engine, obj.IsExtensible), false, false, false);
+            obj.FastAddProperty("keys", new ClrFunctionInstance<object, object>(engine, obj.Keys), false, false, false);
+
+            return obj;
+        }
+
+        public ObjectInstance PrototypeObject { get; private set; }
+
+        /// <summary>
+        /// http://www.ecma-international.org/ecma-262/5.1/#sec-15.2.1.1
+        /// </summary>
+        /// <param name="thisObject"></param>
+        /// <param name="arguments"></param>
+        /// <returns></returns>
         public override object Call(object thisObject, object[] arguments)
         {
-            return Undefined.Instance;
+            if (arguments.Length == 0)
+            {
+                return Construct(arguments);
+            } 
+            
+            if(arguments[0] == Null.Instance || arguments[0] == Undefined.Instance)
+            {
+                return Construct(arguments);
+            }
+
+            return TypeConverter.ToObject(_engine, arguments[0]);
         }
 
+        /// <summary>
+        /// http://www.ecma-international.org/ecma-262/5.1/#sec-15.2.2.1
+        /// </summary>
+        /// <param name="arguments"></param>
+        /// <returns></returns>
         public ObjectInstance Construct(object[] arguments)
         {
-            var instance = new ObjectInstance(_engine, this.Prototype);
+            if (arguments.Length > 0)
+            {
+                var value = arguments[0];
+                var valueObj = value as ObjectInstance;
+                if (valueObj != null)
+                {
+                    return valueObj;
+                }
+                var type = TypeConverter.GetType(value);
+                if (type == TypeCode.String || type == TypeCode.Double || type == TypeCode.Boolean)
+                {
+                    return TypeConverter.ToObject(_engine, value);
+                }
+            }
+
+            var obj = new ObjectInstance(_engine)
+                {
+                    Extensible = true,
+                    Prototype = Engine.Object.PrototypeObject
+                };
+
+            return obj;
+        }
+
+        public object GetPrototypeOf(object thisObject, object[] arguments)
+        {
+            throw new NotImplementedException();
+        }
+
+        public object GetOwnPropertyDescriptor(object thisObject, object[] arguments)
+        {
+            throw new NotImplementedException();
+        }
+
+        public object GetOwnPropertyNames(object thisObject, object[] arguments)
+        {
+            throw new NotImplementedException();
+        }
+
+        public object Create(object thisObject, object[] arguments)
+        {
+            throw new NotImplementedException();
+        }
+
+        public object DefineProperty(object thisObject, object[] arguments)
+        {
+            throw new NotImplementedException();
+        }
+
+        public object DefineProperties(object thisObject, object[] arguments)
+        {
+            throw new NotImplementedException();
+        }
+
+        public object Seal(object thisObject, object[] arguments)
+        {
+            throw new NotImplementedException();
+        }
+
+        public object Freeze(object thisObject, object[] arguments)
+        {
+            throw new NotImplementedException();
+        }
 
-            // the constructor is the function constructor of an object
-            instance.DefineOwnProperty("constructor", new DataDescriptor(this) { Writable = true, Enumerable = false, Configurable = false }, false);
-            instance.DefineOwnProperty("prototype", new DataDescriptor(this.Prototype) { Writable = false, Enumerable = false, Configurable = false }, false);
-            return instance;
+        public object PreventExtensions(object thisObject, object[] arguments)
+        {
+            throw new NotImplementedException();
         }
 
-        private bool HasOwnProperty(object thisObject, object[] arguments)
+        public object IsSealed(object thisObject, object[] arguments)
         {
-            var p = TypeConverter.ToString(arguments[0]);
-            var o = TypeConverter.ToObject(_engine, thisObject);
-            var desc = o.GetOwnProperty(p);
-            return desc != PropertyDescriptor.Undefined;
+            throw new NotImplementedException();
         }
 
-        private static string ToString(object thisObject, object[] arguments)
+        public object IsFrozen(object thisObject, object[] arguments)
         {
-            return TypeConverter.ToString(thisObject);
+            throw new NotImplementedException();
+        }
 
+        public object IsExtensible(object thisObject, object[] arguments)
+        {
+            throw new NotImplementedException();
         }
 
+        public object Keys(object thisObject, object[] arguments)
+        {
+            throw new NotImplementedException();
+        }
     }
 }

+ 20 - 24
Jint/Native/Object/ObjectInstance.cs

@@ -8,24 +8,20 @@ namespace Jint.Native.Object
 {
     public class ObjectInstance
     {
-        private readonly Engine _engine;
-
-        public ObjectInstance(Engine engine, ObjectInstance prototype)
+        public ObjectInstance(Engine engine)
         {
-            _engine = engine;
+            Engine = engine;
             Properties = new Dictionary<string, PropertyDescriptor>();
-            Extensible = true;
-            Prototype = prototype;
-            FastAddProperty("prototype", prototype, false, false, false);
         }
 
+        public Engine Engine { get; set; }
+
         public IDictionary<string, PropertyDescriptor> Properties { get; private set; }
 
         /// <summary>
         /// The prototype of this object.
         /// </summary>
-        public ObjectInstance Prototype { get; private set; }
-
+        public ObjectInstance Prototype { get; set; }
         
         /// <summary>
         /// If true, own properties may be added to the 
@@ -150,7 +146,7 @@ namespace Jint.Native.Object
             {
                 if (throwOnError)
                 {
-                    throw new JavaScriptException(_engine.TypeError);
+                    throw new JavaScriptException(Engine.TypeError);
                 }
 
                 return;
@@ -170,7 +166,7 @@ namespace Jint.Native.Object
                 {
                     if (throwOnError)
                     {
-                        throw new JavaScriptException(_engine.TypeError);
+                        throw new JavaScriptException(Engine.TypeError);
                     }
 
                     return;
@@ -292,7 +288,7 @@ namespace Jint.Native.Object
             {
                 if (throwOnError)
                 {
-                    throw new JavaScriptException(_engine.TypeError);
+                    throw new JavaScriptException(Engine.TypeError);
                 }
 
                 return false;
@@ -309,7 +305,7 @@ namespace Jint.Native.Object
         {
             if ((hint == TypeCode.String) || (hint == TypeCode.Empty && this is StringInstance))
             {
-                var toString = this.Get("toString");
+                var toString = Get("toString");
                 var callable = toString as ICallable;
                 if (callable != null)
                 {
@@ -320,7 +316,7 @@ namespace Jint.Native.Object
                     }
                 }
 
-                var valueOf = this.Get("valueOf");
+                var valueOf = Get("valueOf");
                 callable = valueOf as ICallable;
                 if (callable != null)
                 {
@@ -331,12 +327,12 @@ namespace Jint.Native.Object
                     }
                 }
 
-                throw new JavaScriptException(_engine.TypeError);
+                throw new JavaScriptException(Engine.TypeError);
             }
 
             if ((hint == TypeCode.Double) || (hint == TypeCode.Empty))
             {
-                var valueOf = this.Get("valueOf");
+                var valueOf = Get("valueOf");
                 var callable = valueOf as ICallable;
                 if (callable != null)
                 {
@@ -347,7 +343,7 @@ namespace Jint.Native.Object
                     }
                 }
 
-                var toString = this.Get("toString");
+                var toString = Get("toString");
                 callable = toString as ICallable;
                 if (callable != null)
                 {
@@ -358,7 +354,7 @@ namespace Jint.Native.Object
                     }
                 }
 
-                throw new JavaScriptException(_engine.TypeError);
+                throw new JavaScriptException(Engine.TypeError);
             }
 
             return ToString();
@@ -383,7 +379,7 @@ namespace Jint.Native.Object
                 {
                     if (throwOnError)
                     {
-                        throw new JavaScriptException(_engine.TypeError);
+                        throw new JavaScriptException(Engine.TypeError);
                     }
 
                     return false;
@@ -411,7 +407,7 @@ namespace Jint.Native.Object
                 {
                     if (throwOnError)
                     {
-                        throw new JavaScriptException(_engine.TypeError);
+                        throw new JavaScriptException(Engine.TypeError);
                     }
 
                     return false;
@@ -421,7 +417,7 @@ namespace Jint.Native.Object
                 {
                     if (throwOnError)
                     {
-                        throw new JavaScriptException(_engine.TypeError);
+                        throw new JavaScriptException(Engine.TypeError);
                     }
 
                     return false;
@@ -439,7 +435,7 @@ namespace Jint.Native.Object
                 {
                     if (throwOnError)
                     {
-                        throw new JavaScriptException(_engine.TypeError);
+                        throw new JavaScriptException(Engine.TypeError);
                     }
 
                     return false;
@@ -461,7 +457,7 @@ namespace Jint.Native.Object
                     {
                         if (throwOnError)
                         {
-                            throw new JavaScriptException(_engine.TypeError);
+                            throw new JavaScriptException(Engine.TypeError);
                         }
 
                         return false;
@@ -480,7 +476,7 @@ namespace Jint.Native.Object
                     {
                         if (throwOnError)
                         {
-                            throw new JavaScriptException(_engine.TypeError);
+                            throw new JavaScriptException(Engine.TypeError);
                         }
 
                         return false;

+ 60 - 0
Jint/Native/Object/ObjectPrototype.cs

@@ -0,0 +1,60 @@
+using Jint.Runtime;
+using Jint.Runtime.Descriptors;
+using Jint.Runtime.Interop;
+
+namespace Jint.Native.Object
+{
+    public sealed class ObjectPrototype : ObjectInstance
+    {
+        private ObjectPrototype(Engine engine) : base(engine)
+        {
+        }
+
+        public static ObjectPrototype CreatePrototypeObject(Engine engine, ObjectConstructor objectConstructor)
+        {
+            var obj = new ObjectPrototype(engine) { Extensible = true };
+
+            obj.FastAddProperty("constructor", objectConstructor, false, false, false);
+            obj.FastAddProperty("toString", new ClrFunctionInstance<object, string>(engine, obj.ToString), false, false, false);
+            obj.FastAddProperty("hasOwnProperty", new ClrFunctionInstance<object, bool>(engine, obj.HasOwnProperty), false, false, false);
+
+            return obj;
+        }
+
+        /// <summary>
+        /// http://www.ecma-international.org/ecma-262/5.1/#sec-15.2.4.2
+        /// </summary>
+        /// <param name="thisObject"></param>
+        /// <param name="arguments"></param>
+        /// <returns></returns>
+        public string ToString(object thisObject, object[] arguments)
+        {
+            if (thisObject == Undefined.Instance)
+            {
+                return "[object Undefined]";
+            }
+
+            if (thisObject == Null.Instance)
+            {
+                return "[object Null]";
+            }
+
+            var o = TypeConverter.ToObject(Engine, thisObject);
+            return "[object " + o.Class + "]";
+        }
+
+        /// <summary>
+        /// http://www.ecma-international.org/ecma-262/5.1/#sec-15.2.4.5
+        /// </summary>
+        /// <param name="thisObject"></param>
+        /// <param name="arguments"></param>
+        /// <returns></returns>
+        public bool HasOwnProperty(object thisObject, object[] arguments)
+        {
+            var p = TypeConverter.ToString(arguments[0]);
+            var o = TypeConverter.ToObject(Engine, thisObject);
+            var desc = o.GetOwnProperty(p);
+            return desc != PropertyDescriptor.Undefined;
+        }
+    }
+}

+ 22 - 10
Jint/Native/String/StringConstructor.cs

@@ -1,25 +1,32 @@
 using Jint.Native.Function;
 using Jint.Native.Object;
 using Jint.Runtime;
-using Jint.Runtime.Descriptors;
 
 namespace Jint.Native.String
 {
     public sealed class StringConstructor : FunctionInstance, IConstructor
     {
-        private readonly Engine _engine;
-
         public StringConstructor(Engine engine)
-            : base(engine, new ObjectInstance(engine, engine.Object), null, null, false)
+            : base(engine, null, null, false)
         {
-            _engine = engine;
+        }
 
-            // the constructor is the function constructor of an object
-            Prototype.DefineOwnProperty("constructor", new DataDescriptor(this) { Writable = true, Enumerable = false, Configurable = false }, false);
-            Prototype.DefineOwnProperty("prototype", new DataDescriptor(Prototype) { Writable = true, Enumerable = false, Configurable = false }, false);
+        public static StringConstructor CreateStringConstructor(Engine engine)
+        {
+            var obj = new StringConstructor(engine);
+            obj.Extensible = true;
 
-        }
+            // The value of the [[Prototype]] internal property of the String constructor is the Function prototype object 
+            obj.Prototype = engine.Function.PrototypeObject;
+            obj.PrototypeObject = StringPrototype.CreatePrototypeObject(engine, obj);
+
+            obj.FastAddProperty("length", 1, false, false, false);
 
+            // The initial value of String.prototype is the String prototype object
+            obj.FastAddProperty("prototype", obj.PrototypeObject, false, false, false);
+
+            return obj;
+        }
         public override object Call(object thisObject, object[] arguments)
         {
             if (arguments.Length == 0)
@@ -40,10 +47,15 @@ namespace Jint.Native.String
             return Construct(arguments.Length > 0 ? TypeConverter.ToString(arguments[0]) : "");
         }
 
+        public ObjectInstance PrototypeObject { get; private set; }
+
         public StringInstance Construct(string value)
         {
-            var instance = new StringInstance(_engine, Prototype);
+            var instance = new StringInstance(Engine);
+            instance.Prototype = PrototypeObject;
             instance.PrimitiveValue = value;
+            instance.Extensible = true;
+
             return instance;
         }
     }

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

@@ -3,12 +3,12 @@ using Jint.Native.Object;
 
 namespace Jint.Native.String
 {
-    public sealed class StringInstance : ObjectInstance, IPrimitiveType
+    public class StringInstance : ObjectInstance, IPrimitiveType
     {
         private readonly Engine _engine;
 
-        public StringInstance(Engine engine, ObjectInstance prototype)
-            : base(engine, prototype)
+        public StringInstance(Engine engine)
+            : base(engine)
         {
             _engine = engine;
         }

+ 26 - 0
Jint/Native/String/StringPrototype.cs

@@ -0,0 +1,26 @@
+namespace Jint.Native.String
+{
+    /// <summary>
+    /// http://www.ecma-international.org/ecma-262/5.1/#sec-15.5.4
+    /// </summary>
+    public sealed class StringPrototype : StringInstance
+    {
+        private StringPrototype(Engine engine)
+            : base(engine)
+        {
+        }
+
+        public static StringPrototype CreatePrototypeObject(Engine engine, StringConstructor stringConstructor)
+        {
+            var obj = new StringPrototype(engine);
+            obj.Prototype = engine.Object.PrototypeObject;
+            obj.PrimitiveValue = "";
+
+            obj.FastAddProperty("constructor", stringConstructor, false, false, false);
+
+            return obj;
+        }
+
+
+    }
+}

+ 32 - 14
Jint/Runtime/ExpressionIntepreter.cs

@@ -2,6 +2,7 @@
 using System.Linq;
 using Jint.Native;
 using Jint.Native.Function;
+using Jint.Native.Object;
 using Jint.Parser.Ast;
 using Jint.Runtime.Descriptors;
 using Jint.Runtime.Environments;
@@ -148,8 +149,7 @@ namespace Jint.Runtime
                 case "+":
                     var lprim = TypeConverter.ToPrimitive(left);
                     var rprim = TypeConverter.ToPrimitive(right);
-                    if (TypeConverter.GetType(lprim) == TypeCode.String ||
-                        TypeConverter.GetType(rprim) == TypeCode.String)
+                    if (TypeConverter.GetType(lprim) == TypeCode.String || TypeConverter.GetType(rprim) == TypeCode.String)
                     {
                         value = TypeConverter.ToString(lprim) + TypeConverter.ToString(rprim);
                     }
@@ -245,10 +245,27 @@ namespace Jint.Runtime
                     return (uint)TypeConverter.ToInt32(left) >> (int)(TypeConverter.ToUint32(right) & 0x1F);
 
                 case "instanceof":
-                    var f = (FunctionInstance)right;
+                    var f = right as FunctionInstance;
+
+                    if (f == null)
+                    {
+                        throw new JavaScriptException(_engine.TypeError, "instanceof can only be used with a function object");
+                    }
+
                     value = f.HasInstance(left);
                     break;
                 
+                case "in":
+                    var o = right as ObjectInstance;
+
+                    if (o == null)
+                    {
+                        throw new JavaScriptException(_engine.TypeError, "in can only be used with an object");
+                    }
+
+                    value = o.HasProperty(TypeConverter.ToString(left));
+                    break;
+                
                 default:
                     throw new NotImplementedException();
             }
@@ -449,8 +466,6 @@ namespace Jint.Runtime
                         var get = new ScriptFunctionInstance(
                             _engine,
                             getter,
-                            _engine.Function.Prototype,
-                            _engine.Object.Construct(Arguments.Empty),
                             _engine.ExecutionContext.LexicalEnvironment,
                             getter.Strict || _engine.Options.IsStrict()
                             );
@@ -469,8 +484,6 @@ namespace Jint.Runtime
                         var set = new ScriptFunctionInstance(
                             _engine,
                             setter,
-                            _engine.Function.Prototype,
-                            _engine.Object.Construct(Arguments.Empty),
                             _engine.ExecutionContext.LexicalEnvironment,
                             setter.Strict || _engine.Options.IsStrict()
                             );
@@ -544,12 +557,9 @@ namespace Jint.Runtime
 
         public object EvaluateFunctionExpression(FunctionExpression functionExpression)
         {
-            string identifier = functionExpression.Id != null ? functionExpression.Id.Name : null;
             return new ScriptFunctionInstance(
                 _engine,
                 functionExpression,
-                _engine.Function.Prototype,
-                _engine.Object.Construct(Arguments.Empty),
                 LexicalEnvironment.NewDeclarativeEnvironment(_engine, _engine.ExecutionContext.LexicalEnvironment),
                 functionExpression.Strict
                 );
@@ -557,8 +567,19 @@ namespace Jint.Runtime
 
         public object EvaluateCallExpression(CallExpression callExpression)
         {
-            var callee = EvaluateExpression(callExpression.Callee);
+            var callee = EvaluateExpression(callExpression.Callee) as Reference;
+
+            if (callee == null)
+            {
+                throw new ArgumentException("Callee should be a reference");    
+            }
+
             var func = _engine.GetValue(callee);
+
+            if (func == Undefined.Instance)
+            {
+                throw new JavaScriptException(_engine.TypeError, "object has no method '" + callee.GetReferencedName() + "'" );
+            }
             object thisObject;
 
             // todo: implement as in http://www.ecma-international.org/ecma-262/5.1/#sec-11.2.4
@@ -665,9 +686,6 @@ namespace Jint.Runtime
             // construct the new instance using the Function's constructor method
             var instance = callee.Construct(arguments);
 
-            // initializes the new instance by executing the Function
-            callee.Call(instance, arguments.ToArray());
-
             return instance;
         }
 

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

@@ -11,7 +11,7 @@ namespace Jint.Runtime.Interop
         private readonly Func<TObject, object[], TResult> _func;
 
         public ClrFunctionInstance(Engine engine, Func<TObject, object[], TResult> func)
-            : base(engine, engine.Function, null, null, false)
+            : base(engine, null, null, false)
         {
             _func = func;
         }

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

@@ -13,7 +13,7 @@ namespace Jint.Runtime.Interop
         private readonly Engine _engine;
         private readonly Delegate _d;
 
-        public DelegateWrapper(Engine engine, Delegate d) : base(engine, null, null, null, false)
+        public DelegateWrapper(Engine engine, Delegate d) : base(engine, null, null, false)
         {
             _engine = engine;
             _d = d;

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

@@ -11,7 +11,7 @@ namespace Jint.Runtime.Interop
         private readonly Func<T, object> _getter;
 
         public GetterFunctionInstance(Engine engine, Func<T, object> getter)
-            : base(engine, null, null, null, false)
+            : base(engine,  null, null, false)
         {
             _getter = getter;
         }

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

@@ -12,7 +12,7 @@ namespace Jint.Runtime.Interop
         private readonly Action<T, object> _setter;
 
         public SetterFunctionInstance(Engine engine, Action<T, object> setter)
-            : base(engine, null, null, null, false)
+            : base(engine, null, null, false)
         {
             _setter = setter;
         }