Browse Source

Improve engine creation performance (#625)

Fixes #615
Marko Lahma 6 years ago
parent
commit
5e0b3bb917
46 changed files with 925 additions and 714 deletions
  1. 24 0
      Jint.Benchmark/EngineConstructionBenchmark.cs
  2. 6 4
      Jint.Benchmark/Jint.Benchmark.csproj
  3. 66 89
      Jint/Engine.cs
  4. 3 17
      Jint/Native/Argument/ArgumentsInstance.cs
  5. 19 16
      Jint/Native/Array/ArrayConstructor.cs
  6. 41 35
      Jint/Native/Array/ArrayPrototype.cs
  7. 6 8
      Jint/Native/Boolean/BooleanConstructor.cs
  8. 18 10
      Jint/Native/Boolean/BooleanPrototype.cs
  9. 18 10
      Jint/Native/Date/DateConstructor.cs
  10. 56 50
      Jint/Native/Date/DatePrototype.cs
  11. 12 14
      Jint/Native/Error/ErrorConstructor.cs
  12. 8 3
      Jint/Native/Error/ErrorInstance.cs
  13. 13 8
      Jint/Native/Error/ErrorPrototype.cs
  14. 1 1
      Jint/Native/Function/ArrowFunctionInstance.cs
  15. 3 2
      Jint/Native/Function/EvalFunctionInstance.cs
  16. 13 14
      Jint/Native/Function/FunctionConstructor.cs
  17. 30 18
      Jint/Native/Function/FunctionInstance.cs
  18. 19 15
      Jint/Native/Function/FunctionPrototype.cs
  19. 3 6
      Jint/Native/Function/ScriptFunctionInstance.cs
  20. 4 2
      Jint/Native/Function/ThrowTypeError.cs
  21. 42 42
      Jint/Native/Global/GlobalObject.cs
  22. 5 6
      Jint/Native/Iterator/IteratorConstructor.cs
  23. 3 1
      Jint/Native/Iterator/IteratorInstance.cs
  24. 10 6
      Jint/Native/Iterator/IteratorPrototype.cs
  25. 12 6
      Jint/Native/Json/JsonInstance.cs
  26. 20 21
      Jint/Native/Map/MapConstructor.cs
  27. 24 25
      Jint/Native/Map/MapPrototype.cs
  28. 53 50
      Jint/Native/Math/MathInstance.cs
  29. 34 28
      Jint/Native/Number/NumberConstructor.cs
  30. 16 9
      Jint/Native/Number/NumberPrototype.cs
  31. 23 18
      Jint/Native/Object/ObjectConstructor.cs
  32. 18 2
      Jint/Native/Object/ObjectInstance.cs
  33. 20 11
      Jint/Native/Object/ObjectPrototype.cs
  34. 10 10
      Jint/Native/RegExp/RegExpConstructor.cs
  35. 22 14
      Jint/Native/RegExp/RegExpPrototype.cs
  36. 19 21
      Jint/Native/Set/SetConstructor.cs
  37. 23 24
      Jint/Native/Set/SetPrototype.cs
  38. 21 11
      Jint/Native/String/StringConstructor.cs
  39. 47 39
      Jint/Native/String/StringPrototype.cs
  40. 30 26
      Jint/Native/Symbol/SymbolConstructor.cs
  41. 21 13
      Jint/Native/Symbol/SymbolPrototype.cs
  42. 39 6
      Jint/Runtime/Descriptors/PropertyDescriptor.cs
  43. 21 0
      Jint/Runtime/Descriptors/Specialized/GetSetPropertyDescriptor.cs
  44. 23 0
      Jint/Runtime/Descriptors/Specialized/LazyPropertyDescriptor.cs
  45. 5 2
      Jint/Runtime/Interop/ClrFunctionInstance.cs
  46. 1 1
      Jint/Runtime/Interop/TypeReference.cs

+ 24 - 0
Jint.Benchmark/EngineConstructionBenchmark.cs

@@ -0,0 +1,24 @@
+using BenchmarkDotNet.Attributes;
+using Esprima;
+
+namespace Jint.Benchmark
+{
+    [MemoryDiagnoser]
+    public class EngineConstructionBenchmark
+    {
+        private readonly Esprima.Ast.Program _program;
+
+        public EngineConstructionBenchmark()
+        {
+            var parser = new JavaScriptParser("return [].length + ''.length");
+            _program = parser.ParseProgram();
+        }
+
+        [Benchmark]
+        public double BuildEngine()
+        {
+            var engine = new Engine();
+            return engine.Execute(_program).GetCompletionValue().AsNumber();
+        }
+    }
+}

+ 6 - 4
Jint.Benchmark/Jint.Benchmark.csproj

@@ -19,10 +19,12 @@
     <None Include="..\Jint.Tests.CommonScripts\Scripts\**" CopyToOutputDirectory="PreserveNewest" LinkBase="SunSpider" />
   </ItemGroup>
   <ItemGroup>
-    <PackageReference Include="BenchmarkDotNet" Version="0.11.4" />
     <ProjectReference Include="..\Jint\Jint.csproj" />
-    <PackageReference Include="Jurassic" Version="3.0.0-alpha2" />
-    <PackageReference Include="Newtonsoft.Json" Version="12.0.1" />
-    <PackageReference Include="NiL.JS.NetCore" Version="2.5.1200" />
+  </ItemGroup>
+  <ItemGroup>
+    <PackageReference Include="BenchmarkDotNet" Version="0.11.5" />
+    <PackageReference Include="Jurassic" Version="3.0.0" />
+    <PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
+    <PackageReference Include="NiL.JS.NetCore" Version="2.5.1327" />
   </ItemGroup>
 </Project>

+ 66 - 89
Jint/Engine.cs

@@ -25,6 +25,7 @@ using Jint.Runtime;
 using Jint.Runtime.CallStack;
 using Jint.Runtime.Debugger;
 using Jint.Runtime.Descriptors;
+using Jint.Runtime.Descriptors.Specialized;
 using Jint.Runtime.Environments;
 using Jint.Runtime.Interop;
 using Jint.Runtime.Interpreter;
@@ -41,6 +42,15 @@ namespace Jint
             Loc = true
         };
 
+
+        private static readonly JsString _errorFunctionName = new JsString("Error");
+        private static readonly JsString _evalErrorFunctionName = new JsString("EvalError");
+        private static readonly JsString _rangeErrorFunctionName = new JsString("RangeError");
+        private static readonly JsString _referenceErrorFunctionName = new JsString("ReferenceError");
+        private static readonly JsString _syntaxErrorFunctionName = new JsString("SyntaxError");
+        private static readonly JsString _typeErrorFunctionName = new JsString("TypeError");
+        private static readonly JsString _uriErrorFunctionName = new JsString("URIError");
+
         private readonly ExecutionContextStack _executionContexts;
         private JsValue _completionValue = JsValue.Undefined;
         private int _statementsCount;
@@ -48,6 +58,17 @@ namespace Jint
         private long _timeoutTicks;
         internal INode _lastSyntaxNode;
 
+        // lazy properties
+        private ErrorConstructor _error;
+        private ErrorConstructor _evalError;
+        private ErrorConstructor _rangeError;
+        private ErrorConstructor _referenceError;
+        private ErrorConstructor _syntaxError;
+        private ErrorConstructor _typeError;
+        private ErrorConstructor _uriError;
+        private DebugHandler _debugHandler;
+        private List<BreakPoint> _breakPoints;
+
         // cached access
         private readonly bool _isDebugMode;
         internal readonly bool _isStrict;
@@ -59,32 +80,35 @@ namespace Jint
         internal readonly ArgumentsInstancePool _argumentsInstancePool;
         internal readonly JsValueArrayPool _jsValueArrayPool;
 
-        public ITypeConverter ClrTypeConverter;
+        public readonly ITypeConverter ClrTypeConverter;
 
         // cache of types used when resolving CLR type names
-        internal Dictionary<string, Type> TypeCache = new Dictionary<string, Type>();
+        internal readonly Dictionary<string, Type> TypeCache = new Dictionary<string, Type>();
 
         internal static Dictionary<Type, Func<Engine, object, JsValue>> TypeMappers = new Dictionary<Type, Func<Engine, object, JsValue>>
         {
-            { typeof(bool), (Engine engine, object v) => (bool) v ? JsBoolean.True : JsBoolean.False },
-            { typeof(byte), (Engine engine, object v) => JsNumber.Create((byte)v) },
-            { typeof(char), (Engine engine, object v) => JsString.Create((char)v) },
-            { typeof(DateTime), (Engine engine, object v) => engine.Date.Construct((DateTime)v) },
-            { typeof(DateTimeOffset), (Engine engine, object v) => engine.Date.Construct((DateTimeOffset)v) },
-            { typeof(decimal), (Engine engine, object v) => (JsValue) (double)(decimal)v },
-            { typeof(double), (Engine engine, object v) => (JsValue)(double)v },
-            { typeof(Int16), (Engine engine, object v) => JsNumber.Create((Int16)v) },
-            { typeof(Int32), (Engine engine, object v) => JsNumber.Create((Int32)v) },
-            { typeof(Int64), (Engine engine, object v) => (JsValue)(Int64)v },
-            { typeof(SByte), (Engine engine, object v) => JsNumber.Create((SByte)v) },
-            { typeof(Single), (Engine engine, object v) => (JsValue)(Single)v },
-            { typeof(string), (Engine engine, object v) => (JsValue) (string)v },
-            { typeof(UInt16), (Engine engine, object v) => JsNumber.Create((UInt16)v) },
-            { typeof(UInt32), (Engine engine, object v) => JsNumber.Create((UInt32)v) },
-            { typeof(UInt64), (Engine engine, object v) => JsNumber.Create((UInt64)v) },
-            { typeof(System.Text.RegularExpressions.Regex), (Engine engine, object v) => engine.RegExp.Construct((System.Text.RegularExpressions.Regex)v, "") }
+            { typeof(bool), (engine, v) => (bool) v ? JsBoolean.True : JsBoolean.False },
+            { typeof(byte), (engine, v) => JsNumber.Create((byte)v) },
+            { typeof(char), (engine, v) => JsString.Create((char)v) },
+            { typeof(DateTime), (engine, v) => engine.Date.Construct((DateTime)v) },
+            { typeof(DateTimeOffset), (engine, v) => engine.Date.Construct((DateTimeOffset)v) },
+            { typeof(decimal), (engine, v) => (JsValue) (double)(decimal)v },
+            { typeof(double), (engine, v) => (JsValue)(double)v },
+            { typeof(Int16), (engine, v) => JsNumber.Create((Int16)v) },
+            { typeof(Int32), (engine, v) => JsNumber.Create((Int32)v) },
+            { typeof(Int64), (engine, v) => (JsValue)(Int64)v },
+            { typeof(SByte), (engine, v) => JsNumber.Create((SByte)v) },
+            { typeof(Single), (engine, v) => (JsValue)(Single)v },
+            { typeof(string), (engine, v) => (JsValue) (string)v },
+            { typeof(UInt16), (engine, v) => JsNumber.Create((UInt16)v) },
+            { typeof(UInt32), (engine, v) => JsNumber.Create((UInt32)v) },
+            { typeof(UInt64), (engine, v) => JsNumber.Create((UInt64)v) },
+            { typeof(System.Text.RegularExpressions.Regex), (engine, v) => engine.RegExp.Construct((System.Text.RegularExpressions.Regex)v, "") }
         };
 
+        // shared frozen version
+        internal readonly PropertyDescriptor _getSetThrower;
+
         internal struct ClrPropertyDescriptorFactoriesKey : IEquatable<ClrPropertyDescriptorFactoriesKey>
         {
             public ClrPropertyDescriptorFactoriesKey(Type type, string propertyName)
@@ -93,8 +117,8 @@ namespace Jint
                 PropertyName = propertyName;
             }
 
-            internal readonly Type Type;
-            internal readonly string PropertyName;
+            private readonly Type Type;
+            private readonly string PropertyName;
 
             public bool Equals(ClrPropertyDescriptorFactoriesKey other)
             {
@@ -122,7 +146,7 @@ namespace Jint
         internal readonly Dictionary<ClrPropertyDescriptorFactoriesKey, Func<Engine, object, PropertyDescriptor>> ClrPropertyDescriptorFactories =
             new Dictionary<ClrPropertyDescriptorFactoriesKey, Func<Engine, object, PropertyDescriptor>>();
 
-        internal JintCallStack CallStack = new JintCallStack();
+        internal readonly JintCallStack CallStack = new JintCallStack();
 
         static Engine()
         {
@@ -146,12 +170,13 @@ namespace Jint
 
             Object = ObjectConstructor.CreateObjectConstructor(this);
             Function = FunctionConstructor.CreateFunctionConstructor(this);
+            _getSetThrower = new GetSetPropertyDescriptor.ThrowerPropertyDescriptor(Function.ThrowTypeError);
 
             Symbol = SymbolConstructor.CreateSymbolConstructor(this);
             Array = ArrayConstructor.CreateArrayConstructor(this);
             Map = MapConstructor.CreateMapConstructor(this);
             Set = SetConstructor.CreateSetConstructor(this);
-            Iterator= IteratorConstructor.CreateIteratorConstructor(this);
+            Iterator = IteratorConstructor.CreateIteratorConstructor(this);
             String = StringConstructor.CreateStringConstructor(this);
             RegExp = RegExpConstructor.CreateRegExpConstructor(this);
             Number = NumberConstructor.CreateNumberConstructor(this);
@@ -160,62 +185,14 @@ namespace Jint
             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");
-
             GlobalSymbolRegistry = new GlobalSymbolRegistry();
 
             // Because the properties might need some of the built-in object
             // their configuration is delayed to a later step
 
-            Global.Configure();
-
-            Object.Configure();
-            Object.PrototypeObject.Configure();
-
-            Symbol.Configure();
-            Symbol.PrototypeObject.Configure();
-
-            Function.Configure();
-            Function.PrototypeObject.Configure();
-
-            Array.Configure();
-            Array.PrototypeObject.Configure();
-
-            Map.Configure();
-            Map.PrototypeObject.Configure();
-
-            Set.Configure();
-            Set.PrototypeObject.Configure();
-
-            Iterator.Configure();
-            Iterator.PrototypeObject.Configure();
-
-            String.Configure();
-            String.PrototypeObject.Configure();
-
-            RegExp.Configure();
-            RegExp.PrototypeObject.Configure();
-
-            Number.Configure();
-            Number.PrototypeObject.Configure();
-
-            Boolean.Configure();
-            Boolean.PrototypeObject.Configure();
-
-            Date.Configure();
-            Date.PrototypeObject.Configure();
-
-            Math.Configure();
-            Json.Configure();
-
-            Error.Configure();
-            Error.PrototypeObject.Configure();
+            // this is implementation dependent, and only to pass some unit tests
+            Global.Prototype = Object.PrototypeObject;
+            Object.Prototype = Function.PrototypeObject;
 
             // create the global environment http://www.ecma-international.org/ecma-262/5.1/#sec-10.2.3
             GlobalEnvironment = LexicalEnvironment.NewObjectEnvironment(this, Global, null, false);
@@ -243,20 +220,18 @@ namespace Jint
             _jsValueArrayPool = new JsValueArrayPool();
 
             Eval = new EvalFunctionInstance(this, System.ArrayExt.Empty<string>(), LexicalEnvironment.NewDeclarativeEnvironment(this, ExecutionContext.LexicalEnvironment), StrictModeScope.IsStrictModeCode);
-            Global.FastAddProperty("eval", Eval, true, false, true);
+            Global._properties["eval"] = new PropertyDescriptor(Eval, true, false, true);
 
             if (Options._IsClrAllowed)
             {
-                Global.FastAddProperty("System", new NamespaceReference(this, "System"), false, false, false);
-                Global.FastAddProperty("importNamespace", new ClrFunctionInstance(
+                Global._properties["System"] = new PropertyDescriptor(new NamespaceReference(this, "System"), false, false, false);
+                Global._properties["importNamespace"] = new PropertyDescriptor(new ClrFunctionInstance(
                     this,
                     "importNamespace",
                     (thisObj, arguments) => new NamespaceReference(this, TypeConverter.ToString(arguments.At(0)))), false, false, false);
             }
 
             ClrTypeConverter = new DefaultTypeConverter(this);
-            BreakPoints = new System.Collections.Generic.List<BreakPoint>();
-            DebugHandler = new DebugHandler(this);
         }
 
         public LexicalEnvironment GlobalEnvironment { get; }
@@ -277,18 +252,18 @@ namespace Jint
         public SymbolConstructor Symbol { get; }
         public EvalFunctionInstance Eval { get; }
 
-        public ErrorConstructor Error { get; }
-        public ErrorConstructor EvalError { get; }
-        public ErrorConstructor SyntaxError { get; }
-        public ErrorConstructor TypeError { get; }
-        public ErrorConstructor RangeError { get; }
-        public ErrorConstructor ReferenceError { get; }
-        public ErrorConstructor UriError { get; }
+        public ErrorConstructor Error => _error ?? (_error = ErrorConstructor.CreateErrorConstructor(this, _errorFunctionName));
+        public ErrorConstructor EvalError => _evalError ?? (_evalError = ErrorConstructor.CreateErrorConstructor(this, _evalErrorFunctionName));
+        public ErrorConstructor SyntaxError => _syntaxError ?? (_syntaxError = ErrorConstructor.CreateErrorConstructor(this, _syntaxErrorFunctionName));
+        public ErrorConstructor TypeError => _typeError ?? (_typeError = ErrorConstructor.CreateErrorConstructor(this, _typeErrorFunctionName));
+        public ErrorConstructor RangeError => _rangeError ?? (_rangeError = ErrorConstructor.CreateErrorConstructor(this, _rangeErrorFunctionName));
+        public ErrorConstructor ReferenceError => _referenceError ?? (_referenceError = ErrorConstructor.CreateErrorConstructor(this, _referenceErrorFunctionName));
+        public ErrorConstructor UriError => _uriError ?? (_uriError = ErrorConstructor.CreateErrorConstructor(this, _uriErrorFunctionName));
 
         public ref readonly ExecutionContext ExecutionContext
         {
             [MethodImpl(MethodImplOptions.AggressiveInlining)]
-            get { return ref _executionContexts.Peek(); }
+            get => ref _executionContexts.Peek();
         }
 
         public GlobalSymbolRegistry GlobalSymbolRegistry { get; }
@@ -300,8 +275,10 @@ namespace Jint
         public delegate StepMode BreakDelegate(object sender, DebugInformation e);
         public event DebugStepDelegate Step;
         public event BreakDelegate Break;
-        internal DebugHandler DebugHandler { get; private set; }
-        public System.Collections.Generic.List<BreakPoint> BreakPoints { get; private set; }
+
+        internal DebugHandler DebugHandler => _debugHandler ?? (_debugHandler = new DebugHandler(this));
+
+        public List<BreakPoint> BreakPoints => _breakPoints ?? (_breakPoints = new List<BreakPoint>());
 
         internal StepMode? InvokeStepEvent(DebugInformation info)
         {

+ 3 - 17
Jint/Native/Argument/ArgumentsInstance.cs

@@ -47,19 +47,7 @@ namespace Jint.Native.Argument
             _initialized = false;
         }
 
-        protected override void EnsureInitialized()
-        {
-            if (_initialized)
-            {
-                return;
-            }
-
-            _initialized = true;
-
-            BuildProperties();
-        }
-
-        private void BuildProperties()
+        protected override void Initialize()
         {
             var args = _args;
             SetOwnProperty("length", new PropertyDescriptor(args.Length, PropertyFlag.NonEnumerable));
@@ -97,10 +85,8 @@ namespace Jint.Native.Argument
             // step 14
             else
             {
-                var thrower = Engine.Function.ThrowTypeError;
-                const PropertyFlag flags = PropertyFlag.EnumerableSet | PropertyFlag.ConfigurableSet;
-                DefineOwnProperty("caller", new GetSetPropertyDescriptor(get: thrower, set: thrower, flags), false);
-                DefineOwnProperty("callee", new GetSetPropertyDescriptor(get: thrower, set: thrower, flags), false);
+                DefineOwnProperty("caller", _engine._getSetThrower, false);
+                DefineOwnProperty("callee", _engine._getSetThrower, false);
             }
         }
 

+ 19 - 16
Jint/Native/Array/ArrayConstructor.cs

@@ -1,5 +1,6 @@
 using System.Collections;
 using System.Runtime.CompilerServices;
+using Jint.Collections;
 using Jint.Native.Function;
 using Jint.Native.Iterator;
 using Jint.Native.Object;
@@ -13,7 +14,9 @@ namespace Jint.Native.Array
 {
     public sealed class ArrayConstructor : FunctionInstance, IConstructor
     {
-        private ArrayConstructor(Engine engine) :  base(engine, "Array", null, null, false)
+        private static readonly JsString _functionName = new JsString("Array");
+
+        private ArrayConstructor(Engine engine) :  base(engine, _functionName, false)
         {
         }
 
@@ -21,32 +24,32 @@ namespace Jint.Native.Array
 
         public static ArrayConstructor CreateArrayConstructor(Engine engine)
         {
-            var obj = new ArrayConstructor(engine);
-            obj.Extensible = true;
+            var obj = new ArrayConstructor(engine)
+            {
+                Extensible = true,
+                Prototype = engine.Function.PrototypeObject
+            };
 
             // 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.SetOwnProperty("length", new PropertyDescriptor(1, PropertyFlag.Configurable));
+            obj._length = new PropertyDescriptor(1, PropertyFlag.Configurable);
 
             // The initial value of Array.prototype is the Array prototype object
-            obj.SetOwnProperty("prototype", new PropertyDescriptor(obj.PrototypeObject, PropertyFlag.AllForbidden));
-
-            obj.SetOwnProperty(GlobalSymbolRegistry.Species._value,
-                new GetSetPropertyDescriptor(
-                    get: new ClrFunctionInstance(engine, "get [Symbol.species]", Species, 0, PropertyFlag.Configurable),
-                    set: Undefined,
-                    PropertyFlag.Configurable));
+            obj._prototype = new PropertyDescriptor(obj.PrototypeObject, PropertyFlag.AllForbidden);
 
             return obj;
         }
 
-        public void Configure()
+        protected override void Initialize()
         {
-            SetOwnProperty("from",new PropertyDescriptor(new ClrFunctionInstance(Engine, "from", From, 1, PropertyFlag.Configurable), PropertyFlag.NonEnumerable));
-            SetOwnProperty("isArray", new PropertyDescriptor(new ClrFunctionInstance(Engine, "isArray", IsArray, 1), PropertyFlag.NonEnumerable));
-            SetOwnProperty("of", new PropertyDescriptor(new ClrFunctionInstance(Engine, "of", Of, 0, PropertyFlag.Configurable), PropertyFlag.NonEnumerable));
+            _properties = new StringDictionarySlim<PropertyDescriptor>(5)
+            {
+                [GlobalSymbolRegistry.Species._value] = new GetSetPropertyDescriptor(get: new ClrFunctionInstance(Engine, "get [Symbol.species]", Species, 0, PropertyFlag.Configurable), set: Undefined,PropertyFlag.Configurable),
+                ["from"] = new PropertyDescriptor(new PropertyDescriptor(new ClrFunctionInstance(Engine, "from", From, 1, PropertyFlag.Configurable), PropertyFlag.NonEnumerable)),
+                ["isArray"] = new PropertyDescriptor(new PropertyDescriptor(new ClrFunctionInstance(Engine, "isArray", IsArray, 1), PropertyFlag.NonEnumerable)),
+                ["of"] = new PropertyDescriptor(new PropertyDescriptor(new ClrFunctionInstance(Engine, "of", Of, 0, PropertyFlag.Configurable), PropertyFlag.NonEnumerable))
+            };
         }
 
         private JsValue From(JsValue thisObj, JsValue[] arguments)

+ 41 - 35
Jint/Native/Array/ArrayPrototype.cs

@@ -1,5 +1,6 @@
 using System;
 using System.Collections.Generic;
+using Jint.Collections;
 using Jint.Native.Number;
 using Jint.Native.Object;
 using Jint.Native.Symbol;
@@ -18,6 +19,8 @@ namespace Jint.Native.Array
     /// </summary>
     public sealed class ArrayPrototype : ArrayInstance
     {
+        private ArrayConstructor _arrayConstructor;
+
         private ArrayPrototype(Engine engine) : base(engine)
         {
         }
@@ -27,48 +30,51 @@ namespace Jint.Native.Array
             var obj = new ArrayPrototype(engine)
             {
                 Extensible = true,
-                Prototype = engine.Object.PrototypeObject
+                Prototype = engine.Object.PrototypeObject,
+                _length = new PropertyDescriptor(JsNumber.PositiveZero, PropertyFlag.Writable),
+                _arrayConstructor = arrayConstructor,
             };
 
-            obj.SetOwnProperty("length", new PropertyDescriptor(0, PropertyFlag.Writable));
-            obj.SetOwnProperty("constructor", new PropertyDescriptor(arrayConstructor, PropertyFlag.NonEnumerable));
 
             return obj;
         }
 
-        public void Configure()
+        protected override void Initialize()
         {
-            FastAddProperty("toString", new ClrFunctionInstance(Engine, "toString", ToString, 0, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("toLocaleString", new ClrFunctionInstance(Engine, "toLocaleString", ToLocaleString, 0, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("concat", new ClrFunctionInstance(Engine, "concat", Concat, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("copyWithin", new ClrFunctionInstance(Engine, "copyWithin", CopyWithin, 2, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("entries", new ClrFunctionInstance(Engine, "entries", Iterator, 0, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("fill", new ClrFunctionInstance(Engine, "fill", Fill, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("join", new ClrFunctionInstance(Engine, "join", Join, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("pop", new ClrFunctionInstance(Engine, "pop", Pop, 0, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("push", new ClrFunctionInstance(Engine, "push", Push, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("reverse", new ClrFunctionInstance(Engine, "reverse", Reverse, 0, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("shift", new ClrFunctionInstance(Engine, "shift", Shift, 0, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("slice", new ClrFunctionInstance(Engine, "slice", Slice, 2, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("sort", new ClrFunctionInstance(Engine, "sort", Sort, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("splice", new ClrFunctionInstance(Engine, "splice", Splice, 2, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("unshift", new ClrFunctionInstance(Engine, "unshift", Unshift, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("includes", new ClrFunctionInstance(Engine, "includes", Includes, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("indexOf", new ClrFunctionInstance(Engine, "indexOf", IndexOf, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("lastIndexOf", new ClrFunctionInstance(Engine, "lastIndexOf", LastIndexOf, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("every", new ClrFunctionInstance(Engine, "every", Every, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("some", new ClrFunctionInstance(Engine, "some", Some, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("forEach", new ClrFunctionInstance(Engine, "forEach", ForEach, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("map", new ClrFunctionInstance(Engine, "map", Map, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("filter", new ClrFunctionInstance(Engine, "filter", Filter, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("reduce", new ClrFunctionInstance(Engine, "reduce", Reduce, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("reduceRight", new ClrFunctionInstance(Engine, "reduceRight", ReduceRight, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("find", new ClrFunctionInstance(Engine, "find", Find, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("findIndex", new ClrFunctionInstance(Engine, "findIndex", FindIndex, 1, PropertyFlag.Configurable), true, false, true);
-
-            FastAddProperty("keys", new ClrFunctionInstance(Engine, "keys", Keys, 0, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("values", new ClrFunctionInstance(Engine, "values", Values, 0, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty(GlobalSymbolRegistry.Iterator._value, new ClrFunctionInstance(Engine, "iterator", Values, 1), true, false, true);
+            _properties = new StringDictionarySlim<PropertyDescriptor>(35)
+            {
+                ["constructor"] = new PropertyDescriptor(_arrayConstructor, PropertyFlag.NonEnumerable),
+                ["toString"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "toString", ToString, 0, PropertyFlag.Configurable), true, false, true),
+                ["toLocaleString"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "toLocaleString", ToLocaleString, 0, PropertyFlag.Configurable), true, false, true),
+                ["concat"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "concat", Concat, 1, PropertyFlag.Configurable), true, false, true),
+                ["copyWithin"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "copyWithin", CopyWithin, 2, PropertyFlag.Configurable), true, false, true),
+                ["entries"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "entries", Iterator, 0, PropertyFlag.Configurable), true, false, true),
+                ["fill"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "fill", Fill, 1, PropertyFlag.Configurable), true, false, true),
+                ["join"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "join", Join, 1, PropertyFlag.Configurable), true, false, true),
+                ["pop"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "pop", Pop, 0, PropertyFlag.Configurable), true, false, true),
+                ["push"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "push", Push, 1, PropertyFlag.Configurable), true, false, true),
+                ["reverse"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "reverse", Reverse, 0, PropertyFlag.Configurable), true, false, true),
+                ["shift"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "shift", Shift, 0, PropertyFlag.Configurable), true, false, true),
+                ["slice"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "slice", Slice, 2, PropertyFlag.Configurable), true, false, true),
+                ["sort"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "sort", Sort, 1, PropertyFlag.Configurable), true, false, true),
+                ["splice"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "splice", Splice, 2, PropertyFlag.Configurable), true, false, true),
+                ["unshift"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "unshift", Unshift, 1, PropertyFlag.Configurable), true, false, true),
+                ["includes"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "includes", Includes, 1, PropertyFlag.Configurable), true, false, true),
+                ["indexOf"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "indexOf", IndexOf, 1, PropertyFlag.Configurable), true, false, true),
+                ["lastIndexOf"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "lastIndexOf", LastIndexOf, 1, PropertyFlag.Configurable), true, false, true),
+                ["every"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "every", Every, 1, PropertyFlag.Configurable), true, false, true),
+                ["some"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "some", Some, 1, PropertyFlag.Configurable), true, false, true),
+                ["forEach"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "forEach", ForEach, 1, PropertyFlag.Configurable), true, false, true),
+                ["map"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "map", Map, 1, PropertyFlag.Configurable), true, false, true),
+                ["filter"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "filter", Filter, 1, PropertyFlag.Configurable), true, false, true),
+                ["reduce"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "reduce", Reduce, 1, PropertyFlag.Configurable), true, false, true),
+                ["reduceRight"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "reduceRight", ReduceRight, 1, PropertyFlag.Configurable), true, false, true),
+                ["find"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "find", Find, 1, PropertyFlag.Configurable), true, false, true),
+                ["findIndex"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "findIndex", FindIndex, 1, PropertyFlag.Configurable), true, false, true),
+                ["keys"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "keys", Keys, 0, PropertyFlag.Configurable), true, false, true),
+                ["values"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "values", Values, 0, PropertyFlag.Configurable), true, false, true),
+                [GlobalSymbolRegistry.Iterator._value] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "iterator", Values, 1), true, false, true)
+            };
         }
         
         private ObjectInstance Keys(JsValue thisObj, JsValue[] arguments)

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

@@ -7,7 +7,10 @@ namespace Jint.Native.Boolean
 {
     public sealed class BooleanConstructor : FunctionInstance, IConstructor
     {
-        private BooleanConstructor(Engine engine): base(engine, "Boolean", null, null, false)
+        private static readonly JsString _functionName = new JsString("Boolean");
+
+        private BooleanConstructor(Engine engine)
+            : base(engine, _functionName, strict: false)
         {
         }
 
@@ -20,19 +23,14 @@ namespace Jint.Native.Boolean
             obj.Prototype = engine.Function.PrototypeObject;
             obj.PrototypeObject = BooleanPrototype.CreatePrototypeObject(engine, obj);
 
-            obj.SetOwnProperty("length", new PropertyDescriptor(1, PropertyFlag.AllForbidden));
+            obj._length = PropertyDescriptor.AllForbiddenDescriptor.NumberOne;
 
             // The initial value of Boolean.prototype is the Boolean prototype object
-            obj.SetOwnProperty("prototype", new PropertyDescriptor(obj.PrototypeObject, PropertyFlag.AllForbidden));
+            obj._prototype = new PropertyDescriptor(obj.PrototypeObject, PropertyFlag.AllForbidden);
 
             return obj;
         }
 
-        public void Configure()
-        {
-
-        }
-
         public override JsValue Call(JsValue thisObject, JsValue[] arguments)
         {
             if (arguments.Length == 0)

+ 18 - 10
Jint/Native/Boolean/BooleanPrototype.cs

@@ -1,4 +1,5 @@
-using Jint.Runtime;
+using Jint.Collections;
+using Jint.Runtime;
 using Jint.Runtime.Descriptors;
 using Jint.Runtime.Interop;
 
@@ -9,26 +10,33 @@ namespace Jint.Native.Boolean
     /// </summary>
     public sealed class BooleanPrototype : BooleanInstance
     {
+        private BooleanConstructor _booleanConstructor;
+
         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.Extensible = true;
-
-            obj.SetOwnProperty("constructor", new PropertyDescriptor(booleanConstructor, PropertyFlag.NonEnumerable));
+            var obj = new BooleanPrototype(engine)
+            {
+                Prototype = engine.Object.PrototypeObject,
+                PrimitiveValue = false,
+                Extensible = true,
+                _booleanConstructor = booleanConstructor
+            };
 
             return obj;
         }
 
-        public void Configure()
+        protected override void Initialize()
         {
-            FastAddProperty("toString", new ClrFunctionInstance(Engine, "toString", ToBooleanString, 0, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("valueOf", new ClrFunctionInstance(Engine, "valueOf", ValueOf, 0, PropertyFlag.Configurable), true, false, true);
+            _properties = new StringDictionarySlim<PropertyDescriptor>(3)
+            {
+                ["constructor"] = new PropertyDescriptor(_booleanConstructor, PropertyFlag.NonEnumerable),
+                ["toString"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "toString", ToBooleanString, 0, PropertyFlag.Configurable), true, false, true),
+                ["valueOf"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "valueOf", ValueOf, 0, PropertyFlag.Configurable), true, false, true)
+            };
         }
 
         private JsValue ValueOf(JsValue thisObj, JsValue[] arguments)

+ 18 - 10
Jint/Native/Date/DateConstructor.cs

@@ -1,5 +1,6 @@
 using System;
 using System.Globalization;
+using Jint.Collections;
 using Jint.Native.Function;
 using Jint.Native.Object;
 using Jint.Runtime;
@@ -51,32 +52,39 @@ namespace Jint.Native.Date
             "THHK"
         };
 
-        public DateConstructor(Engine engine) : base(engine, "Date", null, null, false)
+        private static readonly JsString _functionName = new JsString("Date");
+
+        public DateConstructor(Engine engine) : base(engine, _functionName, strict: false)
         {
         }
 
         public static DateConstructor CreateDateConstructor(Engine engine)
         {
-            var obj = new DateConstructor(engine);
-            obj.Extensible = true;
+            var obj = new DateConstructor(engine)
+            {
+                Extensible = true,
+                Prototype = engine.Function.PrototypeObject
+            };
 
             // 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);
 
-            obj.SetOwnProperty("length", new PropertyDescriptor(7, PropertyFlag.AllForbidden));
+            obj._length = new PropertyDescriptor(7, PropertyFlag.AllForbidden);
 
             // The initial value of Date.prototype is the Date prototype object
-            obj.SetOwnProperty("prototype", new PropertyDescriptor(obj.PrototypeObject, PropertyFlag.AllForbidden));
+            obj._prototype = new PropertyDescriptor(obj.PrototypeObject, PropertyFlag.AllForbidden);
 
             return obj;
         }
 
-        public void Configure()
+        protected override void Initialize()
         {
-            FastAddProperty("parse", new ClrFunctionInstance(Engine, "parse", Parse, 1), true, false, true);
-            FastAddProperty("UTC", new ClrFunctionInstance(Engine, "utc", Utc, 7), true, false, true);
-            FastAddProperty("now", new ClrFunctionInstance(Engine, "now", Now, 0), true, false, true);
+            _properties = new StringDictionarySlim<PropertyDescriptor>(3)
+            {
+                ["parse"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "parse", Parse, 1), true, false, true),
+                ["UTC"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "utc", Utc, 7), true, false, true),
+                ["now"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "now", Now, 0), true, false, true)
+            };
         }
 
         private JsValue Parse(JsValue thisObj, JsValue[] arguments)

+ 56 - 50
Jint/Native/Date/DatePrototype.cs

@@ -1,5 +1,6 @@
 using System;
 using System.Globalization;
+using Jint.Collections;
 using Jint.Runtime;
 using Jint.Runtime.Descriptors;
 using Jint.Runtime.Interop;
@@ -11,6 +12,8 @@ namespace Jint.Native.Date
     /// </summary>
     public sealed class DatePrototype : DateInstance
     {
+        private DateConstructor _dateConstructor;
+
         private DatePrototype(Engine engine)
             : base(engine)
         {
@@ -22,61 +25,64 @@ namespace Jint.Native.Date
             {
                 Prototype = engine.Object.PrototypeObject,
                 Extensible = true,
-                PrimitiveValue = double.NaN
+                PrimitiveValue = double.NaN,
+                _dateConstructor = dateConstructor
             };
 
-            obj.SetOwnProperty("constructor", new PropertyDescriptor(dateConstructor, PropertyFlag.NonEnumerable));
-
             return obj;
         }
 
-        public void Configure()
-        {
-            FastAddProperty("toString", new ClrFunctionInstance(Engine, "toString", ToString, 0), true, false, true);
-            FastAddProperty("toDateString", new ClrFunctionInstance(Engine, "toDateString", ToDateString, 0), true, false, true);
-            FastAddProperty("toTimeString", new ClrFunctionInstance(Engine, "toTimeString", ToTimeString, 0), true, false, true);
-            FastAddProperty("toLocaleString", new ClrFunctionInstance(Engine, "toLocaleString", ToLocaleString, 0), true, false, true);
-            FastAddProperty("toLocaleDateString", new ClrFunctionInstance(Engine, "toLocaleDateString", ToLocaleDateString, 0), true, false, true);
-            FastAddProperty("toLocaleTimeString", new ClrFunctionInstance(Engine, "toLocaleTimeString", ToLocaleTimeString, 0), true, false, true);
-            FastAddProperty("valueOf", new ClrFunctionInstance(Engine, "valueOf", ValueOf, 0), true, false, true);
-            FastAddProperty("getTime", new ClrFunctionInstance(Engine, "getTime", GetTime, 0), true, false, true);
-            FastAddProperty("getFullYear", new ClrFunctionInstance(Engine, "getFullYear", GetFullYear, 0), true, false, true);
-            FastAddProperty("getYear", new ClrFunctionInstance(Engine, "getYear", GetYear, 0), true, false, true);
-            FastAddProperty("getUTCFullYear", new ClrFunctionInstance(Engine, "getUTCFullYear", GetUTCFullYear, 0), true, false, true);
-            FastAddProperty("getMonth", new ClrFunctionInstance(Engine, "getMonth", GetMonth, 0), true, false, true);
-            FastAddProperty("getUTCMonth", new ClrFunctionInstance(Engine, "getUTCMonth", GetUTCMonth, 0), true, false, true);
-            FastAddProperty("getDate", new ClrFunctionInstance(Engine, "getDate", GetDate, 0), true, false, true);
-            FastAddProperty("getUTCDate", new ClrFunctionInstance(Engine, "getUTCDate", GetUTCDate, 0), true, false, true);
-            FastAddProperty("getDay", new ClrFunctionInstance(Engine, "getDay", GetDay, 0), true, false, true);
-            FastAddProperty("getUTCDay", new ClrFunctionInstance(Engine, "getUTCDay", GetUTCDay, 0), true, false, true);
-            FastAddProperty("getHours", new ClrFunctionInstance(Engine, "getHours", GetHours, 0), true, false, true);
-            FastAddProperty("getUTCHours", new ClrFunctionInstance(Engine, "getUTCHours", GetUTCHours, 0), true, false, true);
-            FastAddProperty("getMinutes", new ClrFunctionInstance(Engine, "getMinutes", GetMinutes, 0), true, false, true);
-            FastAddProperty("getUTCMinutes", new ClrFunctionInstance(Engine, "getUTCMInutes", GetUTCMinutes, 0), true, false, true);
-            FastAddProperty("getSeconds", new ClrFunctionInstance(Engine, "getSeconds", GetSeconds, 0), true, false, true);
-            FastAddProperty("getUTCSeconds", new ClrFunctionInstance(Engine, "getUTCSeconds", GetUTCSeconds, 0), true, false, true);
-            FastAddProperty("getMilliseconds", new ClrFunctionInstance(Engine, "getMilliseconds", GetMilliseconds, 0), true, false, true);
-            FastAddProperty("getUTCMilliseconds", new ClrFunctionInstance(Engine, "getUTCMilliseconds", GetUTCMilliseconds, 0), true, false, true);
-            FastAddProperty("getTimezoneOffset", new ClrFunctionInstance(Engine, "getTimezoneOffset", GetTimezoneOffset, 0), true, false, true);
-            FastAddProperty("setTime", new ClrFunctionInstance(Engine, "setTime", SetTime, 1), true, false, true);
-            FastAddProperty("setMilliseconds", new ClrFunctionInstance(Engine, "setMilliseconds", SetMilliseconds, 1), true, false, true);
-            FastAddProperty("setUTCMilliseconds", new ClrFunctionInstance(Engine, "setUTCMilliseconds", SetUTCMilliseconds, 1), true, false, true);
-            FastAddProperty("setSeconds", new ClrFunctionInstance(Engine, "setSeconds", SetSeconds, 2), true, false, true);
-            FastAddProperty("setUTCSeconds", new ClrFunctionInstance(Engine, "setUTCSeconds", SetUTCSeconds, 2), true, false, true);
-            FastAddProperty("setMinutes", new ClrFunctionInstance(Engine, "setMinutes", SetMinutes, 3), true, false, true);
-            FastAddProperty("setUTCMinutes", new ClrFunctionInstance(Engine, "setUTCMinutes", SetUTCMinutes, 3), true, false, true);
-            FastAddProperty("setHours", new ClrFunctionInstance(Engine, "setHours", SetHours, 4), true, false, true);
-            FastAddProperty("setUTCHours", new ClrFunctionInstance(Engine, "setUTCHours", SetUTCHours, 4), true, false, true);
-            FastAddProperty("setDate", new ClrFunctionInstance(Engine, "setDate", SetDate, 1), true, false, true);
-            FastAddProperty("setUTCDate", new ClrFunctionInstance(Engine, "setUTCDate", SetUTCDate, 1), true, false, true);
-            FastAddProperty("setMonth", new ClrFunctionInstance(Engine, "setMonth", SetMonth, 2), true, false, true);
-            FastAddProperty("setUTCMonth", new ClrFunctionInstance(Engine, "setUTCMonth", SetUTCMonth, 2), true, false, true);
-            FastAddProperty("setFullYear", new ClrFunctionInstance(Engine, "setFullYear", SetFullYear, 3), true, false, true);
-            FastAddProperty("setYear", new ClrFunctionInstance(Engine, "setYear", SetYear, 1), true, false, true);
-            FastAddProperty("setUTCFullYear", new ClrFunctionInstance(Engine, "setUTCFullYear     ", SetUTCFullYear, 3), true, false, true);
-            FastAddProperty("toUTCString", new ClrFunctionInstance(Engine, "toUTCString", ToUtcString, 0), true, false, true);
-            FastAddProperty("toISOString", new ClrFunctionInstance(Engine, "toISOString", ToISOString, 0), true, false, true);
-            FastAddProperty("toJSON", new ClrFunctionInstance(Engine, "toJSON", ToJSON, 1), true, false, true);
+        protected override  void Initialize()
+        {
+            _properties = new StringDictionarySlim<PropertyDescriptor>(50)
+            {
+                ["constructor"] = new PropertyDescriptor(_dateConstructor, PropertyFlag.NonEnumerable),
+                ["toString"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "toString", ToString, 0), true, false, true),
+                ["toDateString"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "toDateString", ToDateString, 0), true, false, true),
+                ["toTimeString"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "toTimeString", ToTimeString, 0), true, false, true),
+                ["toLocaleString"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "toLocaleString", ToLocaleString, 0), true, false, true),
+                ["toLocaleDateString"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "toLocaleDateString", ToLocaleDateString, 0), true, false, true),
+                ["toLocaleTimeString"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "toLocaleTimeString", ToLocaleTimeString, 0), true, false, true),
+                ["valueOf"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "valueOf", ValueOf, 0), true, false, true),
+                ["getTime"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "getTime", GetTime, 0), true, false, true),
+                ["getFullYear"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "getFullYear", GetFullYear, 0), true, false, true),
+                ["getYear"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "getYear", GetYear, 0), true, false, true),
+                ["getUTCFullYear"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "getUTCFullYear", GetUTCFullYear, 0), true, false, true),
+                ["getMonth"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "getMonth", GetMonth, 0), true, false, true),
+                ["getUTCMonth"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "getUTCMonth", GetUTCMonth, 0), true, false, true),
+                ["getDate"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "getDate", GetDate, 0), true, false, true),
+                ["getUTCDate"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "getUTCDate", GetUTCDate, 0), true, false, true),
+                ["getDay"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "getDay", GetDay, 0), true, false, true),
+                ["getUTCDay"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "getUTCDay", GetUTCDay, 0), true, false, true),
+                ["getHours"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "getHours", GetHours, 0), true, false, true),
+                ["getUTCHours"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "getUTCHours", GetUTCHours, 0), true, false, true),
+                ["getMinutes"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "getMinutes", GetMinutes, 0), true, false, true),
+                ["getUTCMinutes"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "getUTCMInutes", GetUTCMinutes, 0), true, false, true),
+                ["getSeconds"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "getSeconds", GetSeconds, 0), true, false, true),
+                ["getUTCSeconds"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "getUTCSeconds", GetUTCSeconds, 0), true, false, true),
+                ["getMilliseconds"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "getMilliseconds", GetMilliseconds, 0), true, false, true),
+                ["getUTCMilliseconds"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "getUTCMilliseconds", GetUTCMilliseconds, 0), true, false, true),
+                ["getTimezoneOffset"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "getTimezoneOffset", GetTimezoneOffset, 0), true, false, true),
+                ["setTime"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "setTime", SetTime, 1), true, false, true),
+                ["setMilliseconds"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "setMilliseconds", SetMilliseconds, 1), true, false, true),
+                ["setUTCMilliseconds"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "setUTCMilliseconds", SetUTCMilliseconds, 1), true, false, true),
+                ["setSeconds"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "setSeconds", SetSeconds, 2), true, false, true),
+                ["setUTCSeconds"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "setUTCSeconds", SetUTCSeconds, 2), true, false, true),
+                ["setMinutes"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "setMinutes", SetMinutes, 3), true, false, true),
+                ["setUTCMinutes"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "setUTCMinutes", SetUTCMinutes, 3), true, false, true),
+                ["setHours"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "setHours", SetHours, 4), true, false, true),
+                ["setUTCHours"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "setUTCHours", SetUTCHours, 4), true, false, true),
+                ["setDate"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "setDate", SetDate, 1), true, false, true),
+                ["setUTCDate"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "setUTCDate", SetUTCDate, 1), true, false, true),
+                ["setMonth"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "setMonth", SetMonth, 2), true, false, true),
+                ["setUTCMonth"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "setUTCMonth", SetUTCMonth, 2), true, false, true),
+                ["setFullYear"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "setFullYear", SetFullYear, 3), true, false, true),
+                ["setYear"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "setYear", SetYear, 1), true, false, true),
+                ["setUTCFullYear"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "setUTCFullYear     ", SetUTCFullYear, 3), true, false, true),
+                ["toUTCString"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "toUTCString", ToUtcString, 0), true, false, true),
+                ["toISOString"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "toISOString", ToISOString, 0), true, false, true),
+                ["toJSON"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "toJSON", ToJSON, 1), true, false, true)
+            };
         }
 
         private JsValue ValueOf(JsValue thisObj, JsValue[] arguments)

+ 12 - 14
Jint/Native/Error/ErrorConstructor.cs

@@ -7,35 +7,33 @@ namespace Jint.Native.Error
 {
     public sealed class ErrorConstructor : FunctionInstance, IConstructor
     {
-        private string _name;
+        private JsString _name;
+        private static readonly JsString _functionName = new JsString("Error");
 
-        public ErrorConstructor(Engine engine) : base(engine, "Error", null, null, false)
+        public ErrorConstructor(Engine engine) : base(engine, _functionName, strict: false)
         {
         }
 
-        public static ErrorConstructor CreateErrorConstructor(Engine engine, string name)
+        public static ErrorConstructor CreateErrorConstructor(Engine engine, JsString name)
         {
-            var obj = new ErrorConstructor(engine);
-            obj.Extensible = true;
-            obj._name = name;
+            var obj = new ErrorConstructor(engine)
+            {
+                Extensible = true,
+                _name = name,
+                Prototype = engine.Function.PrototypeObject
+            };
 
             // The value of the [[Prototype]] internal property of the Error constructor is the Function prototype object (15.11.3)
-            obj.Prototype = engine.Function.PrototypeObject;
             obj.PrototypeObject = ErrorPrototype.CreatePrototypeObject(engine, obj, name);
 
-            obj.SetOwnProperty("length", new PropertyDescriptor(1, PropertyFlag.AllForbidden));
+            obj._length = PropertyDescriptor.AllForbiddenDescriptor.NumberOne;
 
             // The initial value of Error.prototype is the Error prototype object
-            obj.SetOwnProperty("prototype", new PropertyDescriptor(obj.PrototypeObject, PropertyFlag.AllForbidden));
+            obj._prototype = new PropertyDescriptor(obj.PrototypeObject, PropertyFlag.AllForbidden);
 
             return obj;
         }
 
-        public void Configure()
-        {
-
-        }
-
         public override JsValue Call(JsValue thisObject, JsValue[] arguments)
         {
             return Construct(arguments);

+ 8 - 3
Jint/Native/Error/ErrorInstance.cs

@@ -1,14 +1,19 @@
-using Jint.Native.Object;
+using Jint.Collections;
+using Jint.Native.Object;
 using Jint.Runtime;
+using Jint.Runtime.Descriptors;
 
 namespace Jint.Native.Error
 {
     public class ErrorInstance : ObjectInstance
     {
-        public ErrorInstance(Engine engine, string name)
+        public ErrorInstance(Engine engine, JsString name)
             : base(engine, objectClass: "Error")
         {
-            FastAddProperty("name", name, true, false, true);
+            _properties = new StringDictionarySlim<PropertyDescriptor>(2)
+            {
+                ["name"] = new PropertyDescriptor(name, true, false, true)
+            };
         }
 
         public override string ToString()

+ 13 - 8
Jint/Native/Error/ErrorPrototype.cs

@@ -10,16 +10,20 @@ namespace Jint.Native.Error
     /// </summary>
     public sealed class ErrorPrototype : ErrorInstance
     {
-        private ErrorPrototype(Engine engine, string name)
+        private ErrorConstructor _errorConstructor;
+
+        private ErrorPrototype(Engine engine, JsString name)
             : base(engine, name)
         {
         }
 
-        public static ErrorPrototype CreatePrototypeObject(Engine engine, ErrorConstructor errorConstructor, string name)
+        public static ErrorPrototype CreatePrototypeObject(Engine engine, ErrorConstructor errorConstructor, JsString name)
         {
-            var obj = new ErrorPrototype(engine, name) { Extensible = true };
-            obj.SetOwnProperty("constructor", new PropertyDescriptor(errorConstructor, PropertyFlag.NonEnumerable));
-            obj.FastAddProperty("message", "", true, false, true);
+            var obj = new ErrorPrototype(engine, name)
+            {
+                Extensible = true,
+                _errorConstructor = errorConstructor,
+            };
 
             if (name != "Error")
             {
@@ -33,10 +37,11 @@ namespace Jint.Native.Error
             return obj;
         }
 
-        public void Configure()
+        protected override void Initialize()
         {
-            // Error prototype functions
-            FastAddProperty("toString", new ClrFunctionInstance(Engine, "toString", ToString), true, false, true);
+            _properties["constructor"] = new PropertyDescriptor(_errorConstructor, PropertyFlag.NonEnumerable);
+            _properties["message"] = new PropertyDescriptor("", true, false, true);
+            _properties["toString"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "toString", ToString), true, false, true);
         }
 
         public JsValue ToString(JsValue thisObject, JsValue[] arguments)

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

@@ -29,7 +29,7 @@ namespace Jint.Native.Function
             JintFunctionDefinition function,
             LexicalEnvironment scope,
             bool strict)
-            : base(engine, "", function._parameterNames, scope, strict)
+            : base(engine, (string) null, function._parameterNames, scope, strict)
         {
             _function = function;
 

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

@@ -9,12 +9,13 @@ namespace Jint.Native.Function
     public sealed class EvalFunctionInstance : FunctionInstance
     {
         private static readonly ParserOptions ParserOptions = new ParserOptions { AdaptRegexp = true, Tolerant = false };
+        private static readonly JsString _functionName = new JsString("eval");
 
         public EvalFunctionInstance(Engine engine, string[] parameters, LexicalEnvironment scope, bool strict) 
-            : base(engine, "eval", parameters, scope, strict)
+            : base(engine, _functionName, parameters, scope, strict)
         {
             Prototype = Engine.Function.PrototypeObject;
-            SetOwnProperty("length", new PropertyDescriptor(1, PropertyFlag.AllForbidden));
+            _length = PropertyDescriptor.AllForbiddenDescriptor.NumberOne;
         }
 
         public override JsValue Call(JsValue thisObject, JsValue[] arguments)

+ 13 - 14
Jint/Native/Function/FunctionConstructor.cs

@@ -10,33 +10,35 @@ namespace Jint.Native.Function
     public sealed class FunctionConstructor : FunctionInstance, IConstructor
     {
         private static readonly ParserOptions ParserOptions = new ParserOptions { AdaptRegexp = true, Tolerant = false };
+        private static readonly JsString _functionName = new JsString("Function");
 
-        private FunctionConstructor(Engine engine):base(engine, "Function", null, null, false)
+        private FunctionInstance _throwTypeError;
+        private static readonly char[] ArgumentNameSeparator = new[] { ',' };
+
+        private FunctionConstructor(Engine engine)
+            : base(engine, _functionName, strict: false)
         {
         }
 
         public static FunctionConstructor CreateFunctionConstructor(Engine engine)
         {
-            var obj = new FunctionConstructor(engine);
-            obj.Extensible = true;
+            var obj = new FunctionConstructor(engine)
+            {
+                Extensible = true,
+                PrototypeObject = FunctionPrototype.CreatePrototypeObject(engine)
+            };
 
             // The initial value of Function.prototype is the standard built-in Function prototype object
-            obj.PrototypeObject = FunctionPrototype.CreatePrototypeObject(engine);
 
             // The value of the [[Prototype]] internal property of the Function constructor is the standard built-in Function prototype object
             obj.Prototype = obj.PrototypeObject;
 
-            obj.SetOwnProperty("prototype", new PropertyDescriptor(obj.PrototypeObject, PropertyFlag.AllForbidden));
-            obj.SetOwnProperty("length", new PropertyDescriptor(1, PropertyFlag.AllForbidden));
+            obj._prototype = new PropertyDescriptor(obj.PrototypeObject, PropertyFlag.AllForbidden);
+            obj._length =  PropertyDescriptor.AllForbiddenDescriptor.NumberOne;
 
             return obj;
         }
 
-        public void Configure()
-        {
-
-        }
-
         public FunctionPrototype PrototypeObject { get; private set; }
 
         public override JsValue Call(JsValue thisObject, JsValue[] arguments)
@@ -112,9 +114,6 @@ namespace Jint.Native.Function
             return functionObject;
         }
 
-        private FunctionInstance _throwTypeError;
-        private static readonly char[] ArgumentNameSeparator = new[] { ',' };
-
         public FunctionInstance ThrowTypeError
         {
             get

+ 30 - 18
Jint/Native/Function/FunctionInstance.cs

@@ -18,7 +18,8 @@ namespace Jint.Native.Function
 
         private const string PropertyNameName = "name";
         private const int PropertyNameNameLength = 4;
-        private PropertyDescriptor _name;
+        private JsValue _name;
+        private PropertyDescriptor _nameDescriptor;
 
         protected readonly LexicalEnvironment _scope;
         protected internal readonly string[] _formalParameters;
@@ -29,26 +30,33 @@ namespace Jint.Native.Function
             string name,
             string[] parameters,
             LexicalEnvironment scope,
-            bool strict)
-            : this(engine, name, parameters, scope, strict, objectClass: "Function")
+            bool strict,
+            string objectClass = "Function")
+            : this(engine, !string.IsNullOrWhiteSpace(name) ? new JsString(name) : null, parameters, scope, strict, objectClass)
         {
         }
 
-        protected FunctionInstance(
+        internal FunctionInstance(
             Engine engine,
-            string name,
+            JsString name,
             string[] parameters,
             LexicalEnvironment scope,
             bool strict,
-            string objectClass)
-            : base(engine, objectClass)
+            string objectClass = "Function")
+            : this(engine, name, strict, objectClass)
         {
-            if (!string.IsNullOrWhiteSpace(name))
-            {
-                _name = new PropertyDescriptor(name, PropertyFlag.Configurable);
-            }
             _formalParameters = parameters;
             _scope = scope;
+        }
+
+        internal FunctionInstance(
+            Engine engine,
+            JsString name,
+            bool strict,
+            string objectClass = "Function")
+            : base(engine, objectClass)
+        {
+            _name = name;
             _strict = strict;
         }
 
@@ -132,9 +140,9 @@ namespace Jint.Native.Function
             {
                 yield return new KeyValuePair<string, PropertyDescriptor>(PropertyNameLength, _length);
             }
-            if (_name != null)
+            if (!(_name is null))
             {
-                yield return new KeyValuePair<string, PropertyDescriptor>(PropertyNameName, _name);
+                yield return new KeyValuePair<string, PropertyDescriptor>(PropertyNameName, GetOwnProperty(PropertyNameName));
             }
 
             foreach (var entry in base.GetOwnProperties())
@@ -155,7 +163,9 @@ namespace Jint.Native.Function
             }
             if (propertyName.Length == PropertyNameNameLength && propertyName == PropertyNameName)
             {
-                return _name ?? PropertyDescriptor.Undefined;
+                return !(_name is null)
+                    ? _nameDescriptor ?? (_nameDescriptor = new PropertyDescriptor(_name, PropertyFlag.Configurable))
+                    :  PropertyDescriptor.Undefined;
             }
 
             return base.GetOwnProperty(propertyName);
@@ -173,7 +183,8 @@ namespace Jint.Native.Function
             }
             else if (propertyName.Length == PropertyNameNameLength && propertyName == PropertyNameName)
             {
-                _name = desc;
+                _name = desc._value;
+                _nameDescriptor = desc;
             }
             else
             {
@@ -193,7 +204,7 @@ namespace Jint.Native.Function
             }
             if (propertyName.Length == PropertyNameNameLength && propertyName == PropertyNameName)
             {
-                return _name != null;
+                return !(_name is null);
             }
 
             return base.HasOwnProperty(propertyName);
@@ -212,6 +223,7 @@ namespace Jint.Native.Function
             if (propertyName.Length == PropertyNameNameLength && propertyName == PropertyNameName)
             {
                 _name = null;
+                _nameDescriptor = null;
             }
 
             base.RemoveOwnProperty(propertyName);
@@ -219,9 +231,9 @@ namespace Jint.Native.Function
 
         internal void SetFunctionName(string name, bool throwIfExists = false)
         {
-            if (!HasOwnProperty("name"))
+            if (_name is null)
             {
-                _name = new PropertyDescriptor(name, PropertyFlag.Configurable);
+                _name = name;
             }
             else if (throwIfExists)
             {

+ 19 - 15
Jint/Native/Function/FunctionPrototype.cs

@@ -1,9 +1,9 @@
 using System;
+using Jint.Collections;
 using Jint.Native.Array;
 using Jint.Native.Object;
 using Jint.Runtime;
 using Jint.Runtime.Descriptors;
-using Jint.Runtime.Descriptors.Specialized;
 using Jint.Runtime.Interop;
 
 namespace Jint.Native.Function
@@ -13,8 +13,10 @@ namespace Jint.Native.Function
     /// </summary>
     public sealed class FunctionPrototype : FunctionInstance
     {
+        private static readonly JsString _functionName = new JsString("Function");
+
         private FunctionPrototype(Engine engine)
-            : base(engine, "Function", null, null, false)
+            : base(engine, _functionName, strict: false)
         {
         }
 
@@ -24,20 +26,24 @@ namespace Jint.Native.Function
             {
                 Extensible = true,
                 // The value of the [[Prototype]] internal property of the Function prototype object is the standard built-in Object prototype object
-                Prototype = engine.Object.PrototypeObject
+                Prototype = engine.Object.PrototypeObject,
+                _length = PropertyDescriptor.AllForbiddenDescriptor.NumberZero
             };
 
-            obj.SetOwnProperty("length", new PropertyDescriptor(0, PropertyFlag.AllForbidden));
             return obj;
         }
 
-        public void Configure()
+        protected override void Initialize()
         {
-            SetOwnProperty("constructor", new PropertyDescriptor(Engine.Function, PropertyFlag.NonEnumerable));
-            FastAddProperty("toString", new ClrFunctionInstance(Engine, "toString", ToString), true, false, true);
-            FastAddProperty("apply", new ClrFunctionInstance(Engine, "apply", Apply, 2), true, false, true);
-            FastAddProperty("call", new ClrFunctionInstance(Engine, "call", CallImpl, 1), true, false, true);
-            FastAddProperty("bind", new ClrFunctionInstance(Engine, "bind", Bind, 1), true, false, true);
+            _properties = new StringDictionarySlim<PropertyDescriptor>(5)
+            {
+                ["constructor"] = new PropertyDescriptor(Engine.Function, PropertyFlag.NonEnumerable),
+                ["toString"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "toString", ToString), true, false, true),
+                ["apply"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "apply", Apply, 2), true, false, true),
+                ["call"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "call", CallImpl, 1), true, false, true),
+                ["bind"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "bind", Bind, 1), true, false, true)
+            };
+
         }
 
         private JsValue Bind(JsValue thisObj, JsValue[] arguments)
@@ -64,13 +70,11 @@ namespace Jint.Native.Function
             }
             else
             {
-                f.SetOwnProperty("length", new PropertyDescriptor(0, PropertyFlag.AllForbidden));
+                f.SetOwnProperty("length", PropertyDescriptor.AllForbiddenDescriptor.NumberZero);
             }
 
-            var thrower = Engine.Function.ThrowTypeError;
-            const PropertyFlag flags = PropertyFlag.EnumerableSet | PropertyFlag.ConfigurableSet;
-            f.DefineOwnProperty("caller", new GetSetPropertyDescriptor(thrower, thrower, flags), false);
-            f.DefineOwnProperty("arguments", new GetSetPropertyDescriptor(thrower, thrower, flags), false);
+            f.DefineOwnProperty("caller", _engine._getSetThrower, false);
+            f.DefineOwnProperty("arguments", _engine._getSetThrower, false);
 
             return f;
         }

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

@@ -3,7 +3,6 @@ using Esprima.Ast;
 using Jint.Native.Object;
 using Jint.Runtime;
 using Jint.Runtime.Descriptors;
-using Jint.Runtime.Descriptors.Specialized;
 using Jint.Runtime.Environments;
 using Jint.Runtime.Interpreter;
 
@@ -30,7 +29,7 @@ namespace Jint.Native.Function
             JintFunctionDefinition function,
             LexicalEnvironment scope,
             bool strict)
-            : base(engine, function._name ?? "", function._parameterNames, scope, strict)
+            : base(engine, function._name, function._parameterNames, scope, strict)
         {
             _function = function;
 
@@ -49,10 +48,8 @@ namespace Jint.Native.Function
 
             if (strict)
             {
-                var thrower = engine.Function.ThrowTypeError;
-                const PropertyFlag flags = PropertyFlag.EnumerableSet | PropertyFlag.ConfigurableSet;
-                DefineOwnProperty("caller", new GetSetPropertyDescriptor(thrower, thrower, flags), false);
-                DefineOwnProperty("arguments", new GetSetPropertyDescriptor(thrower, thrower, flags), false);
+                DefineOwnProperty("caller", engine._getSetThrower, false);
+                DefineOwnProperty("arguments", engine._getSetThrower, false);
             }
         }
 

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

@@ -5,10 +5,12 @@ namespace Jint.Native.Function
 {
     public sealed class ThrowTypeError : FunctionInstance
     {
+        private static readonly JsString _functionName = new JsString("throwTypeError");
+
         public ThrowTypeError(Engine engine)
-            : base(engine, "throwTypeError", System.ArrayExt.Empty<string>(), engine.GlobalEnvironment, false)
+            : base(engine, _functionName, System.ArrayExt.Empty<string>(), engine.GlobalEnvironment, false)
         {
-            DefineOwnProperty("length", new PropertyDescriptor(0, PropertyFlag.AllForbidden), false);
+            _length = PropertyDescriptor.AllForbiddenDescriptor.NumberZero;
             Extensible = false;
         }
 

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

@@ -3,10 +3,12 @@ using System.Collections.Generic;
 using System.Globalization;
 using System.Linq;
 using System.Text;
+using Jint.Collections;
 using Jint.Native.Object;
 using Jint.Native.String;
 using Jint.Runtime;
 using Jint.Runtime.Descriptors;
+using Jint.Runtime.Descriptors.Specialized;
 using Jint.Runtime.Interop;
 
 namespace Jint.Native.Global
@@ -21,54 +23,52 @@ namespace Jint.Native.Global
 
         public static GlobalObject CreateGlobalObject(Engine engine)
         {
-            var global = new GlobalObject(engine) { Prototype = null, Extensible = true };
+            var global = new GlobalObject(engine)
+            {
+                Prototype = null,
+                Extensible = true,
+                _properties = new StringDictionarySlim<PropertyDescriptor>(35)
+            };
 
             return global;
         }
 
-        public void Configure()
+        protected override void Initialize()
         {
-            // this is implementation dependent, and only to pass some unit tests
-            Prototype = Engine.Object.PrototypeObject;
-
             // Global object properties
-            FastAddProperty("Object", Engine.Object, true, false, true);
-            FastAddProperty("Function", Engine.Function, true, false, true);
-            FastAddProperty("Symbol", Engine.Symbol, true, false, true);
-            FastAddProperty("Array", Engine.Array, true, false, true);
-            FastAddProperty("Map", Engine.Map, true, false, true);
-            FastAddProperty("Set", Engine.Set, true, false, true);
-            FastAddProperty("String", Engine.String, true, false, true);
-            FastAddProperty("RegExp", Engine.RegExp, true, false, true);
-            FastAddProperty("Number", Engine.Number, true, false, true);
-            FastAddProperty("Boolean", Engine.Boolean, true, false, true);
-            FastAddProperty("Date", Engine.Date, true, false, true);
-            FastAddProperty("Math", Engine.Math, true, false, true);
-            FastAddProperty("JSON", Engine.Json, true, false, true);
-
-            FastAddProperty("Error", Engine.Error, true, false, true);
-            FastAddProperty("EvalError", Engine.EvalError, true, false, true);
-            FastAddProperty("RangeError", Engine.RangeError, true, false, true);
-            FastAddProperty("ReferenceError", Engine.ReferenceError, true, false, true);
-            FastAddProperty("SyntaxError", Engine.SyntaxError, true, false, true);
-            FastAddProperty("TypeError", Engine.TypeError, true, false, true);
-            FastAddProperty("URIError", Engine.UriError, true, false, true);
-
-            FastAddProperty("NaN", double.NaN, false, false, false);
-            FastAddProperty("Infinity", double.PositiveInfinity, false, false, false);
-            FastAddProperty("undefined", Undefined, false, false, false);
-
-            // Global object functions
-            FastAddProperty("parseInt", new ClrFunctionInstance(Engine, "parseInt", ParseInt, 2, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("parseFloat", new ClrFunctionInstance(Engine, "parseFloat", ParseFloat, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("isNaN", new ClrFunctionInstance(Engine, "isNaN", IsNaN, 1), true, false, true);
-            FastAddProperty("isFinite", new ClrFunctionInstance(Engine, "isFinite", IsFinite, 1), true, false, true);
-            FastAddProperty("decodeURI", new ClrFunctionInstance(Engine, "decodeURI", DecodeUri, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("decodeURIComponent", new ClrFunctionInstance(Engine, "decodeURIComponent", DecodeUriComponent, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("encodeURI", new ClrFunctionInstance(Engine, "encodeURI", EncodeUri, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("encodeURIComponent", new ClrFunctionInstance(Engine, "encodeURIComponent", EncodeUriComponent, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("escape", new ClrFunctionInstance(Engine, "escape", Escape, 1), true, false, true);
-            FastAddProperty("unescape", new ClrFunctionInstance(Engine, "unescape", Unescape, 1), true, false, true);
+            _properties["Object"] = new PropertyDescriptor(Engine.Object, true, false, true);
+            _properties["Function"] = new PropertyDescriptor(Engine.Function, true, false, true);
+            _properties["Symbol"] = new PropertyDescriptor(Engine.Symbol, true, false, true);
+            _properties["Array"] = new PropertyDescriptor(Engine.Array, true, false, true);
+            _properties["Map"] = new PropertyDescriptor(Engine.Map, true, false, true);
+            _properties["Set"] = new PropertyDescriptor(Engine.Set, true, false, true);
+            _properties["String"] = new PropertyDescriptor(Engine.String, true, false, true);
+            _properties["RegExp"] = new PropertyDescriptor(Engine.RegExp, true, false, true);
+            _properties["Number"] = new PropertyDescriptor(Engine.Number, true, false, true);
+            _properties["Boolean"] = new PropertyDescriptor(Engine.Boolean, true, false, true);
+            _properties["Date"] = new PropertyDescriptor(Engine.Date, true, false, true);
+            _properties["Math"] = new PropertyDescriptor(Engine.Math, true, false, true);
+            _properties["JSON"] = new PropertyDescriptor(Engine.Json, true, false, true);
+            _properties["Error"] = new LazyPropertyDescriptor(() => Engine.Error, true, false, true);
+            _properties["EvalError"] = new LazyPropertyDescriptor(() => Engine.EvalError, true, false, true);
+            _properties["RangeError"] = new LazyPropertyDescriptor(() => Engine.RangeError, true, false, true);
+            _properties["ReferenceError"] = new LazyPropertyDescriptor(() => Engine.ReferenceError, true, false, true);
+            _properties["SyntaxError"] = new LazyPropertyDescriptor(() => Engine.SyntaxError, true, false, true);
+            _properties["TypeError"] = new LazyPropertyDescriptor(() => Engine.TypeError, true, false, true);
+            _properties["URIError"] = new LazyPropertyDescriptor(() => Engine.UriError, true, false, true);
+            _properties["NaN"] = new PropertyDescriptor(double.NaN, false, false, false);
+            _properties["Infinity"] = new PropertyDescriptor(double.PositiveInfinity, false, false, false);
+            _properties["undefined"] = new PropertyDescriptor(Undefined, false, false, false);
+            _properties["parseInt"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "parseInt", ParseInt, 2, PropertyFlag.Configurable), true, false, true);
+            _properties["parseFloat"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "parseFloat", ParseFloat, 1, PropertyFlag.Configurable), true, false, true);
+            _properties["isNaN"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "isNaN", IsNaN, 1), true, false, true);
+            _properties["isFinite"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "isFinite", IsFinite, 1), true, false, true);
+            _properties["decodeURI"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "decodeURI", DecodeUri, 1, PropertyFlag.Configurable), true, false, true);
+            _properties["decodeURIComponent"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "decodeURIComponent", DecodeUriComponent, 1, PropertyFlag.Configurable), true, false, true);
+            _properties["encodeURI"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "encodeURI", EncodeUri, 1, PropertyFlag.Configurable), true, false, true);
+            _properties["encodeURIComponent"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "encodeURIComponent", EncodeUriComponent, 1, PropertyFlag.Configurable), true, false, true);
+            _properties["escape"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "escape", Escape, 1), true, false, true);
+            _properties["unescape"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "unescape", Unescape, 1), true, false, true);
         }
 
         /// <summary>

+ 5 - 6
Jint/Native/Iterator/IteratorConstructor.cs

@@ -10,8 +10,10 @@ namespace Jint.Native.Iterator
 {
     public sealed class IteratorConstructor : FunctionInstance, IConstructor
     {
+        private static readonly JsString _functionName = new JsString("iterator");
+
         private IteratorConstructor(Engine engine)
-            : base(engine, "iterator", null, null, false)
+            : base(engine, _functionName, strict: false)
         {
         }
 
@@ -26,17 +28,14 @@ namespace Jint.Native.Iterator
             obj.Prototype = engine.Function.PrototypeObject;
             obj.PrototypeObject = IteratorPrototype.CreatePrototypeObject(engine, obj);
 
-            obj.SetOwnProperty("length", new PropertyDescriptor(0, PropertyFlag.Configurable));
+            obj._length = new PropertyDescriptor(0, PropertyFlag.Configurable);
 
             // The initial value of Map.prototype is the Map prototype object
-            obj.SetOwnProperty("prototype", new PropertyDescriptor(obj.PrototypeObject, PropertyFlag.AllForbidden));
+            obj._prototype = new PropertyDescriptor(obj.PrototypeObject, PropertyFlag.AllForbidden);
 
             return obj;
         }
 
-        public void Configure()
-        {
-        }
 
         public override JsValue Call(JsValue thisObject, JsValue[] arguments)
         {

+ 3 - 1
Jint/Native/Iterator/IteratorInstance.cs

@@ -63,7 +63,9 @@ namespace Jint.Native.Iterator
                     arrayInstance.SetIndexValue(1, value, false);
                     SetOwnProperty("value", new PropertyDescriptor(arrayInstance, PropertyFlag.AllForbidden));
                 }
-                SetOwnProperty("done", new PropertyDescriptor(done, PropertyFlag.AllForbidden));
+                SetOwnProperty(
+                    "done",
+                    done ? PropertyDescriptor.AllForbiddenDescriptor.BooleanTrue : PropertyDescriptor.AllForbiddenDescriptor.BooleanFalse);
             }
         }
 

+ 10 - 6
Jint/Native/Iterator/IteratorPrototype.cs

@@ -1,4 +1,5 @@
-using Jint.Runtime.Descriptors;
+using Jint.Collections;
+using Jint.Runtime.Descriptors;
 using Jint.Runtime.Interop;
 
 namespace Jint.Native.Iterator
@@ -13,17 +14,20 @@ namespace Jint.Native.Iterator
         {
             var obj = new IteratorPrototype(engine)
             {
-                Extensible = true, Prototype = engine.Object.PrototypeObject
+                Extensible = true,
+                Prototype = engine.Object.PrototypeObject
             };
 
-            obj.SetOwnProperty("name", new PropertyDescriptor("Map", PropertyFlag.Configurable));
-
             return obj;
         }
 
-        public void Configure()
+        protected override void Initialize()
         {
-            FastAddProperty("next", new ClrFunctionInstance(Engine, "next", Next, 0, PropertyFlag.Configurable), true, false, true);
+            _properties = new StringDictionarySlim<PropertyDescriptor>(2)
+            {
+                ["name"] = new PropertyDescriptor("Map", PropertyFlag.Configurable),
+                ["next"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "next", Next, 0, PropertyFlag.Configurable), true, false, true)
+            };
         }
 
         private JsValue Next(JsValue thisObj, JsValue[] arguments)

+ 12 - 6
Jint/Native/Json/JsonInstance.cs

@@ -1,4 +1,5 @@
-using Jint.Native.Object;
+using Jint.Collections;
+using Jint.Native.Object;
 using Jint.Runtime;
 using Jint.Runtime.Descriptors;
 using Jint.Runtime.Interop;
@@ -17,15 +18,20 @@ namespace Jint.Native.Json
 
         public static JsonInstance CreateJsonObject(Engine engine)
         {
-            var json = new JsonInstance(engine);
-            json.Prototype = engine.Object.PrototypeObject;
+            var json = new JsonInstance(engine)
+            {
+                Prototype = engine.Object.PrototypeObject
+            };
             return json;
         }
 
-        public void Configure()
+        protected override void Initialize()
         {
-            FastAddProperty("parse", new ClrFunctionInstance(Engine, "parse", Parse, 2), true, false, true);
-            FastAddProperty("stringify", new ClrFunctionInstance(Engine, "stringify", Stringify, 3), true, false, true);
+            _properties = new StringDictionarySlim<PropertyDescriptor>(2)
+            {
+                ["parse"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "parse", Parse, 2), true, false, true),
+                ["stringify"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "stringify", Stringify, 3), true, false, true)
+            };
         }
 
         private JsValue AbstractWalkOperation(ObjectInstance thisObject, string prop)

+ 20 - 21
Jint/Native/Map/MapConstructor.cs

@@ -1,4 +1,5 @@
-using Jint.Native.Function;
+using Jint.Collections;
+using Jint.Native.Function;
 using Jint.Native.Iterator;
 using Jint.Native.Object;
 using Jint.Native.Symbol;
@@ -11,7 +12,10 @@ namespace Jint.Native.Map
 {
     public sealed class MapConstructor : FunctionInstance, IConstructor
     {
-        private MapConstructor(Engine engine, string name) : base(engine, name, null, null, false)
+        private static readonly JsString _functionName = new JsString("Map");
+
+        private MapConstructor(Engine engine)
+            : base(engine, _functionName, strict: false)
         {
         }
 
@@ -19,35 +23,30 @@ namespace Jint.Native.Map
 
         public static MapConstructor CreateMapConstructor(Engine engine)
         {
-            MapConstructor CreateMapConstructorTemplate(string name)
+            var obj = new MapConstructor(engine)
             {
-                var mapConstructor = new MapConstructor(engine, name);
-                mapConstructor.Extensible = true;
-
-                // The value of the [[Prototype]] internal property of the Map constructor is the Function prototype object
-                mapConstructor.Prototype = engine.Function.PrototypeObject;
-                mapConstructor.PrototypeObject = MapPrototype.CreatePrototypeObject(engine, mapConstructor);
+                Extensible = true,
+                Prototype = engine.Function.PrototypeObject
+            };
 
-                mapConstructor.SetOwnProperty("length", new PropertyDescriptor(0, PropertyFlag.Configurable));
-                return mapConstructor;
-            }
+            // The value of the [[Prototype]] internal property of the Map constructor is the Function prototype object
+            obj.PrototypeObject = MapPrototype.CreatePrototypeObject(engine, obj);
 
-            var obj = CreateMapConstructorTemplate("Map");
+            obj._length = new PropertyDescriptor(0, PropertyFlag.Configurable);
 
             // The initial value of Map.prototype is the Map prototype object
-            obj.SetOwnProperty("prototype", new PropertyDescriptor(obj.PrototypeObject, PropertyFlag.AllForbidden));
-
-            obj.SetOwnProperty(GlobalSymbolRegistry.Species._value,
-                new GetSetPropertyDescriptor(
-                    get: new ClrFunctionInstance(engine, "get [Symbol.species]", Species, 0, PropertyFlag.Configurable),
-                    set: Undefined,
-                    PropertyFlag.Configurable));
+            obj._prototype = new PropertyDescriptor(obj.PrototypeObject, PropertyFlag.AllForbidden);
 
             return obj;
         }
 
-        public void Configure()
+        protected override void Initialize()
         {
+            _properties = new StringDictionarySlim<PropertyDescriptor>(2)
+            {
+                [GlobalSymbolRegistry.Species._value] = new GetSetPropertyDescriptor(get: new ClrFunctionInstance(_engine, "get [Symbol.species]", Species, 0, PropertyFlag.Configurable), set: Undefined, PropertyFlag.Configurable)
+            };
+
         }
 
         private static JsValue Species(JsValue thisObject, JsValue[] arguments)

+ 24 - 25
Jint/Native/Map/MapPrototype.cs

@@ -1,4 +1,5 @@
-using Jint.Native.Object;
+using Jint.Collections;
+using Jint.Native.Object;
 using Jint.Native.Symbol;
 using Jint.Runtime;
 using Jint.Runtime.Descriptors;
@@ -12,6 +13,8 @@ namespace Jint.Native.Map
     /// </summary>
     public sealed class MapPrototype : ObjectInstance
     {
+        private MapConstructor _mapConstructor;
+
         private MapPrototype(Engine engine) : base(engine)
         {
         }
@@ -21,36 +24,32 @@ namespace Jint.Native.Map
             var obj = new MapPrototype(engine)
             {
                 Extensible = true,
-                Prototype = engine.Object.PrototypeObject
+                Prototype = engine.Object.PrototypeObject,
+                _mapConstructor = mapConstructor
             };
 
-            obj.SetOwnProperty("length", new PropertyDescriptor(0, PropertyFlag.Configurable));
-            obj.SetOwnProperty("constructor", new PropertyDescriptor(mapConstructor, PropertyFlag.NonEnumerable));
-
             return obj;
         }
 
-        public void Configure()
+        protected override void Initialize()
         {
-            FastAddProperty(GlobalSymbolRegistry.Iterator._value, new ClrFunctionInstance(Engine, "iterator", Iterator, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty(GlobalSymbolRegistry.ToStringTag._value, "Map", false, false, true);
-
-            FastAddProperty("clear", new ClrFunctionInstance(Engine, "clear", Clear, 0, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("delete", new ClrFunctionInstance(Engine, "delete", Delete, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("entries", new ClrFunctionInstance(Engine, "entries", Iterator, 0, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("forEach", new ClrFunctionInstance(Engine, "forEach", ForEach, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("get", new ClrFunctionInstance(Engine, "get", Get, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("has", new ClrFunctionInstance(Engine, "has", Has, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("keys", new ClrFunctionInstance(Engine, "keys", Keys, 0, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("set", new ClrFunctionInstance(Engine, "set", Set, 2, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("values", new ClrFunctionInstance(Engine, "values", Values, 0, PropertyFlag.Configurable), true, false, true);
-
-            AddProperty(
-                "size",
-                new GetSetPropertyDescriptor(
-                    get: new ClrFunctionInstance(Engine, "get size", Size, 0, PropertyFlag.Configurable),
-                    set: null,
-                    PropertyFlag.Configurable));
+            _properties = new StringDictionarySlim<PropertyDescriptor>(15)
+            {
+                ["length"] = new PropertyDescriptor(0, PropertyFlag.Configurable),
+                ["constructor"] = new PropertyDescriptor(_mapConstructor, PropertyFlag.NonEnumerable),
+                [GlobalSymbolRegistry.Iterator._value] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "iterator", Iterator, 1, PropertyFlag.Configurable), true, false, true),
+                [GlobalSymbolRegistry.ToStringTag._value] = new PropertyDescriptor("Map", false, false, true),
+                ["clear"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "clear", Clear, 0, PropertyFlag.Configurable), true, false, true),
+                ["delete"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "delete", Delete, 1, PropertyFlag.Configurable), true, false, true),
+                ["entries"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "entries", Iterator, 0, PropertyFlag.Configurable), true, false, true),
+                ["forEach"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "forEach", ForEach, 1, PropertyFlag.Configurable), true, false, true),
+                ["get"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "get", Get, 1, PropertyFlag.Configurable), true, false, true),
+                ["has"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "has", Has, 1, PropertyFlag.Configurable), true, false, true),
+                ["keys"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "keys", Keys, 0, PropertyFlag.Configurable), true, false, true),
+                ["set"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "set", Set, 2, PropertyFlag.Configurable), true, false, true),
+                ["values"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "values", Values, 0, PropertyFlag.Configurable), true, false, true),
+                ["size"] = new GetSetPropertyDescriptor(get: new ClrFunctionInstance(Engine, "get size", Size, 0, PropertyFlag.Configurable), set: null, PropertyFlag.Configurable)
+            };
         }
 
         private JsValue Size(JsValue thisObj, JsValue[] arguments)

+ 53 - 50
Jint/Native/Math/MathInstance.cs

@@ -1,4 +1,5 @@
 using System;
+using Jint.Collections;
 using Jint.Native.Number;
 using Jint.Native.Object;
 using Jint.Runtime;
@@ -17,61 +18,63 @@ namespace Jint.Native.Math
 
         public static MathInstance CreateMathObject(Engine engine)
         {
-            var math = new MathInstance(engine);
-            math.Extensible = true;
-            math.Prototype = engine.Object.PrototypeObject;
+            var math = new MathInstance(engine)
+            {
+                Extensible = true,
+                Prototype = engine.Object.PrototypeObject
+            };
 
             return math;
         }
 
-        public void Configure()
+        protected override void Initialize()
         {
-            FastAddProperty("abs", new ClrFunctionInstance(Engine, "abs", Abs, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("acos", new ClrFunctionInstance(Engine, "acos", Acos, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("acosh", new ClrFunctionInstance(Engine, "acosh", Acosh, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("asin", new ClrFunctionInstance(Engine, "asin", Asin, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("asinh", new ClrFunctionInstance(Engine, "asinh", Asinh, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("atan", new ClrFunctionInstance(Engine, "atan", Atan, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("atanh", new ClrFunctionInstance(Engine, "atanh", Atanh, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("atan2", new ClrFunctionInstance(Engine, "atan2", Atan2, 2, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("ceil", new ClrFunctionInstance(Engine, "ceil", Ceil, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("cos", new ClrFunctionInstance(Engine, "cos", Cos, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("cosh", new ClrFunctionInstance(Engine, "cosh", Cosh, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("exp", new ClrFunctionInstance(Engine, "exp", Exp, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("expm1", new ClrFunctionInstance(Engine, "expm1", Expm1, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("floor", new ClrFunctionInstance(Engine, "floor", Floor, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("log", new ClrFunctionInstance(Engine, "log", Log, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("log1p", new ClrFunctionInstance(Engine, "log1p", Log1p, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("log2", new ClrFunctionInstance(Engine, "log2", Log2, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("log10", new ClrFunctionInstance(Engine, "log10", Log10, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("max", new ClrFunctionInstance(Engine, "max", Max, 2, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("min", new ClrFunctionInstance(Engine, "min", Min, 2, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("pow", new ClrFunctionInstance(Engine, "pow", Pow, 2, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("random", new ClrFunctionInstance(Engine, "random", Random, 0, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("round", new ClrFunctionInstance(Engine, "round", Round, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("fround", new ClrFunctionInstance(Engine, "fround", Fround, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("sin", new ClrFunctionInstance(Engine, "sin", Sin, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("sinh", new ClrFunctionInstance(Engine, "sinh", Sinh, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("sqrt", new ClrFunctionInstance(Engine, "sqrt", Sqrt, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("tan", new ClrFunctionInstance(Engine, "tan", Tan, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("tanh", new ClrFunctionInstance(Engine, "tanh", Tanh, 1, PropertyFlag.Configurable), true, false, true);
-
-            FastAddProperty("trunc", new ClrFunctionInstance(Engine, "trunc", Truncate, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("sign", new ClrFunctionInstance(Engine, "sign", Sign, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("cbrt", new ClrFunctionInstance(Engine, "cbrt", Cbrt, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("hypot", new ClrFunctionInstance(Engine, "hypot", Hypot, 2, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("imul", new ClrFunctionInstance(Engine, "imul", Imul, 2, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("clz32", new ClrFunctionInstance(Engine, "clz32", Clz32, 1, PropertyFlag.Configurable), true, false, true);
-
-            FastAddProperty("E", System.Math.E, false, false, false);
-            FastAddProperty("LN10", System.Math.Log(10), false, false, false);
-            FastAddProperty("LN2", System.Math.Log(2), false, false, false);
-            FastAddProperty("LOG2E", System.Math.Log(System.Math.E, 2), false, false, false);
-            FastAddProperty("LOG10E", System.Math.Log(System.Math.E, 10), false, false, false);
-            FastAddProperty("PI", System.Math.PI, false, false, false);
-            FastAddProperty("SQRT1_2", System.Math.Sqrt(0.5), false, false, false);
-            FastAddProperty("SQRT2", System.Math.Sqrt(2), false, false, false);
-
+            _properties = new StringDictionarySlim<PropertyDescriptor>(45)
+            {
+                ["abs"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "abs", Abs, 1, PropertyFlag.Configurable), true, false, true),
+                ["acos"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "acos", Acos, 1, PropertyFlag.Configurable), true, false, true),
+                ["acosh"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "acosh", Acosh, 1, PropertyFlag.Configurable), true, false, true),
+                ["asin"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "asin", Asin, 1, PropertyFlag.Configurable), true, false, true),
+                ["asinh"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "asinh", Asinh, 1, PropertyFlag.Configurable), true, false, true),
+                ["atan"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "atan", Atan, 1, PropertyFlag.Configurable), true, false, true),
+                ["atanh"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "atanh", Atanh, 1, PropertyFlag.Configurable), true, false, true),
+                ["atan2"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "atan2", Atan2, 2, PropertyFlag.Configurable), true, false, true),
+                ["ceil"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "ceil", Ceil, 1, PropertyFlag.Configurable), true, false, true),
+                ["cos"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "cos", Cos, 1, PropertyFlag.Configurable), true, false, true),
+                ["cosh"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "cosh", Cosh, 1, PropertyFlag.Configurable), true, false, true),
+                ["exp"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "exp", Exp, 1, PropertyFlag.Configurable), true, false, true),
+                ["expm1"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "expm1", Expm1, 1, PropertyFlag.Configurable), true, false, true),
+                ["floor"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "floor", Floor, 1, PropertyFlag.Configurable), true, false, true),
+                ["log"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "log", Log, 1, PropertyFlag.Configurable), true, false, true),
+                ["log1p"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "log1p", Log1p, 1, PropertyFlag.Configurable), true, false, true),
+                ["log2"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "log2", Log2, 1, PropertyFlag.Configurable), true, false, true),
+                ["log10"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "log10", Log10, 1, PropertyFlag.Configurable), true, false, true),
+                ["max"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "max", Max, 2, PropertyFlag.Configurable), true, false, true),
+                ["min"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "min", Min, 2, PropertyFlag.Configurable), true, false, true),
+                ["pow"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "pow", Pow, 2, PropertyFlag.Configurable), true, false, true),
+                ["random"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "random", Random, 0, PropertyFlag.Configurable), true, false, true),
+                ["round"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "round", Round, 1, PropertyFlag.Configurable), true, false, true),
+                ["fround"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "fround", Fround, 1, PropertyFlag.Configurable), true, false, true),
+                ["sin"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "sin", Sin, 1, PropertyFlag.Configurable), true, false, true),
+                ["sinh"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "sinh", Sinh, 1, PropertyFlag.Configurable), true, false, true),
+                ["sqrt"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "sqrt", Sqrt, 1, PropertyFlag.Configurable), true, false, true),
+                ["tan"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "tan", Tan, 1, PropertyFlag.Configurable), true, false, true),
+                ["tanh"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "tanh", Tanh, 1, PropertyFlag.Configurable), true, false, true),
+                ["trunc"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "trunc", Truncate, 1, PropertyFlag.Configurable), true, false, true),
+                ["sign"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "sign", Sign, 1, PropertyFlag.Configurable), true, false, true),
+                ["cbrt"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "cbrt", Cbrt, 1, PropertyFlag.Configurable), true, false, true),
+                ["hypot"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "hypot", Hypot, 2, PropertyFlag.Configurable), true, false, true),
+                ["imul"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "imul", Imul, 2, PropertyFlag.Configurable), true, false, true),
+                ["clz32"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "clz32", Clz32, 1, PropertyFlag.Configurable), true, false, true),
+                ["E"] = new PropertyDescriptor(System.Math.E, false, false, false),
+                ["LN10"] = new PropertyDescriptor(System.Math.Log(10), false, false, false),
+                ["LN2"] = new PropertyDescriptor(System.Math.Log(2), false, false, false),
+                ["LOG2E"] = new PropertyDescriptor(System.Math.Log(System.Math.E, 2), false, false, false),
+                ["LOG10E"] = new PropertyDescriptor(System.Math.Log(System.Math.E, 10), false, false, false),
+                ["PI"] = new PropertyDescriptor(System.Math.PI, false, false, false),
+                ["SQRT1_2"] = new PropertyDescriptor(System.Math.Sqrt(0.5), false, false, false),
+                ["SQRT2"] = new PropertyDescriptor(System.Math.Sqrt(2), false, false, false)
+            };
         }
 
         private static JsValue Abs(JsValue thisObject, JsValue[] arguments)

+ 34 - 28
Jint/Native/Number/NumberConstructor.cs

@@ -1,4 +1,5 @@
-using Jint.Native.Function;
+using Jint.Collections;
+using Jint.Native.Function;
 using Jint.Native.Object;
 using Jint.Runtime;
 using Jint.Runtime.Descriptors;
@@ -8,53 +9,58 @@ namespace Jint.Native.Number
 {
     public sealed class NumberConstructor : FunctionInstance, IConstructor
     {
+        private static readonly JsString _functionName = new JsString("Number");
+
         private const long MinSafeInteger = -9007199254740991;
         internal const long MaxSafeInteger = 9007199254740991;
 
         public NumberConstructor(Engine engine)
-            : base(engine, "Number", null, null, false)
+            : base(engine, _functionName, strict: false)
         {
 
         }
 
         public static NumberConstructor CreateNumberConstructor(Engine engine)
         {
-            var obj = new NumberConstructor(engine);
-            obj.Extensible = true;
+            var obj = new NumberConstructor(engine)
+            {
+                Extensible = true,
+                Prototype = engine.Function.PrototypeObject
+            };
 
             // 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);
 
-            obj.SetOwnProperty("length", new PropertyDescriptor(1, PropertyFlag.AllForbidden));
+            obj._length = new PropertyDescriptor(1, PropertyFlag.AllForbidden);
 
             // The initial value of Number.prototype is the Number prototype object
-            obj.SetOwnProperty("prototype", new PropertyDescriptor(obj.PrototypeObject, PropertyFlag.AllForbidden));
+            obj._prototype = new PropertyDescriptor(obj.PrototypeObject, PropertyFlag.AllForbidden);
 
             return obj;
         }
 
-        public void Configure()
+        protected override void Initialize()
         {
-            SetOwnProperty("MAX_VALUE", new PropertyDescriptor(double.MaxValue, PropertyFlag.AllForbidden));
-            SetOwnProperty("MIN_VALUE", new PropertyDescriptor(double.Epsilon, PropertyFlag.AllForbidden));
-            SetOwnProperty("NaN", new PropertyDescriptor(double.NaN, PropertyFlag.AllForbidden));
-            SetOwnProperty("NEGATIVE_INFINITY", new PropertyDescriptor(double.NegativeInfinity, PropertyFlag.AllForbidden));
-            SetOwnProperty("POSITIVE_INFINITY", new PropertyDescriptor(double.PositiveInfinity, PropertyFlag.AllForbidden));
-            SetOwnProperty("EPSILON", new PropertyDescriptor(JsNumber.JavaScriptEpsilon, PropertyFlag.AllForbidden));
-            SetOwnProperty("MIN_SAFE_INTEGER", new PropertyDescriptor(MinSafeInteger, PropertyFlag.AllForbidden));
-            SetOwnProperty("MAX_SAFE_INTEGER", new PropertyDescriptor(MaxSafeInteger, PropertyFlag.AllForbidden));
-
-            FastAddProperty("isFinite", new ClrFunctionInstance(Engine, "isFinite", IsFinite, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("isInteger", new ClrFunctionInstance(Engine, "isInteger", IsInteger, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("isNaN", new ClrFunctionInstance(Engine, "isNaN", IsNaN, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("isSafeInteger", new ClrFunctionInstance(Engine, "isSafeInteger", IsSafeInteger, 1, PropertyFlag.Configurable), true, false, true);
-
-            FastAddProperty("parseFloat", new ClrFunctionInstance(Engine, "parseFloat", _engine.Global.ParseFloat, 0, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("parseInt", new ClrFunctionInstance(Engine, "parseInt", _engine.Global.ParseInt, 0, PropertyFlag.Configurable), true, false, true);
+            _properties = new StringDictionarySlim<PropertyDescriptor>(15)
+            {
+                ["MAX_VALUE"] = new PropertyDescriptor(new PropertyDescriptor(double.MaxValue, PropertyFlag.AllForbidden)),
+                ["MIN_VALUE"] = new PropertyDescriptor(new PropertyDescriptor(double.Epsilon, PropertyFlag.AllForbidden)),
+                ["NaN"] = new PropertyDescriptor(new PropertyDescriptor(double.NaN, PropertyFlag.AllForbidden)),
+                ["NEGATIVE_INFINITY"] = new PropertyDescriptor(new PropertyDescriptor(double.NegativeInfinity, PropertyFlag.AllForbidden)),
+                ["POSITIVE_INFINITY"] = new PropertyDescriptor(new PropertyDescriptor(double.PositiveInfinity, PropertyFlag.AllForbidden)),
+                ["EPSILON"] = new PropertyDescriptor(new PropertyDescriptor(JsNumber.JavaScriptEpsilon, PropertyFlag.AllForbidden)),
+                ["MIN_SAFE_INTEGER"] = new PropertyDescriptor(new PropertyDescriptor(MinSafeInteger, PropertyFlag.AllForbidden)),
+                ["MAX_SAFE_INTEGER"] = new PropertyDescriptor(new PropertyDescriptor(MaxSafeInteger, PropertyFlag.AllForbidden)),
+                ["isFinite"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "isFinite", IsFinite, 1, PropertyFlag.Configurable), true, false, true),
+                ["isInteger"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "isInteger", IsInteger, 1, PropertyFlag.Configurable), true, false, true),
+                ["isNaN"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "isNaN", IsNaN, 1, PropertyFlag.Configurable), true, false, true),
+                ["isSafeInteger"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "isSafeInteger", IsSafeInteger, 1, PropertyFlag.Configurable), true, false, true),
+                ["parseFloat"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "parseFloat", _engine.Global.ParseFloat, 0, PropertyFlag.Configurable), true, false, true),
+                ["parseInt"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "parseInt", _engine.Global.ParseInt, 0, PropertyFlag.Configurable), true, false, true)
+            };
         }
 
-        private JsValue IsFinite(JsValue thisObj, JsValue[] arguments)
+        private static JsValue IsFinite(JsValue thisObj, JsValue[] arguments)
         {
             if (!(arguments.At(0) is JsNumber num))
             {
@@ -64,7 +70,7 @@ namespace Jint.Native.Number
             return double.IsInfinity(num._value) || double.IsNaN(num._value) ? JsBoolean.False : JsBoolean.True;
         }
 
-        private JsValue IsInteger(JsValue thisObj, JsValue[] arguments)
+        private static JsValue IsInteger(JsValue thisObj, JsValue[] arguments)
         {
             if (!(arguments.At(0) is JsNumber num))
             {
@@ -81,7 +87,7 @@ namespace Jint.Native.Number
             return integer == num._value;
         }
 
-        private JsValue IsNaN(JsValue thisObj, JsValue[] arguments)
+        private static JsValue IsNaN(JsValue thisObj, JsValue[] arguments)
         {
             if (!(arguments.At(0) is JsNumber num))
             {
@@ -91,7 +97,7 @@ namespace Jint.Native.Number
             return double.IsNaN(num._value);
         }
 
-        private JsValue IsSafeInteger(JsValue thisObj, JsValue[] arguments)
+        private static JsValue IsSafeInteger(JsValue thisObj, JsValue[] arguments)
         {
             if (!(arguments.At(0) is JsNumber num))
             {

+ 16 - 9
Jint/Native/Number/NumberPrototype.cs

@@ -1,6 +1,7 @@
 using System.Diagnostics;
 using System.Globalization;
 using System.Text;
+using Jint.Collections;
 using Jint.Native.Number.Dtoa;
 using Jint.Pooling;
 using Jint.Runtime;
@@ -14,6 +15,8 @@ namespace Jint.Native.Number
     /// </summary>
     public sealed class NumberPrototype : NumberInstance
     {
+        private NumberConstructor _numberConstructor;
+
         private NumberPrototype(Engine engine)
             : base(engine)
         {
@@ -25,22 +28,26 @@ namespace Jint.Native.Number
             {
                 Prototype = engine.Object.PrototypeObject,
                 NumberData = JsNumber.Create(0),
-                Extensible = true
+                Extensible = true,
+                _numberConstructor = numberConstructor
             };
 
-            obj.FastAddProperty("constructor", numberConstructor, true, false, true);
 
             return obj;
         }
 
-        public void Configure()
+        protected override void Initialize()
         {
-            FastAddProperty("toString", new ClrFunctionInstance(Engine, "toString", ToNumberString, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("toLocaleString", new ClrFunctionInstance(Engine, "toLocaleString", ToLocaleString, 0, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("valueOf", new ClrFunctionInstance(Engine, "valueOf", ValueOf, 0, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("toFixed", new ClrFunctionInstance(Engine, "toFixed", ToFixed, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("toExponential", new ClrFunctionInstance(Engine, "toExponential", ToExponential, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("toPrecision", new ClrFunctionInstance(Engine, "toPrecision", ToPrecision, 1, PropertyFlag.Configurable), true, false, true);
+            _properties = new StringDictionarySlim<PropertyDescriptor>(8)
+            {
+                ["constructor"] = new PropertyDescriptor(_numberConstructor, true, false, true),
+                ["toString"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "toString", ToNumberString, 1, PropertyFlag.Configurable), true, false, true),
+                ["toLocaleString"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "toLocaleString", ToLocaleString, 0, PropertyFlag.Configurable), true, false, true),
+                ["valueOf"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "valueOf", ValueOf, 0, PropertyFlag.Configurable), true, false, true),
+                ["toFixed"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "toFixed", ToFixed, 1, PropertyFlag.Configurable), true, false, true),
+                ["toExponential"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "toExponential", ToExponential, 1, PropertyFlag.Configurable), true, false, true),
+                ["toPrecision"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "toPrecision", ToPrecision, 1, PropertyFlag.Configurable), true, false, true)
+            };
         }
 
         private JsValue ToLocaleString(JsValue thisObject, JsValue[] arguments)

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

@@ -19,34 +19,39 @@ namespace Jint.Native.Object
 
         public static ObjectConstructor CreateObjectConstructor(Engine engine)
         {
-            var obj = new ObjectConstructor(engine);
-            obj.Extensible = true;
+            var obj = new ObjectConstructor(engine)
+            {
+                Extensible = true
+            };
 
             obj.PrototypeObject = ObjectPrototype.CreatePrototypeObject(engine, obj);
 
-            obj.SetOwnProperty("length", new PropertyDescriptor(1, PropertyFlag.AllForbidden));
-            obj.SetOwnProperty("prototype", new PropertyDescriptor(obj.PrototypeObject, PropertyFlag.AllForbidden));
+            obj._length = PropertyDescriptor.AllForbiddenDescriptor.NumberOne;
+            obj._prototype = new PropertyDescriptor(obj.PrototypeObject, PropertyFlag.AllForbidden);
 
             return obj;
         }
 
-        public void Configure()
+        protected override void Initialize()
         {
             Prototype = Engine.Function.PrototypeObject;
 
-            FastAddProperty("getPrototypeOf", new ClrFunctionInstance(Engine, "getPrototypeOf", GetPrototypeOf, 1), true, false, true);
-            FastAddProperty("getOwnPropertyDescriptor", new ClrFunctionInstance(Engine, "getOwnPropertyDescriptor", GetOwnPropertyDescriptor, 2), true, false, true);
-            FastAddProperty("getOwnPropertyNames", new ClrFunctionInstance(Engine, "getOwnPropertyNames", GetOwnPropertyNames, 1), true, false, true);
-            FastAddProperty("create", new ClrFunctionInstance(Engine, "create", Create, 2), true, false, true);
-            FastAddProperty("defineProperty", new ClrFunctionInstance(Engine, "defineProperty", DefineProperty, 3), true, false, true);
-            FastAddProperty("defineProperties", new ClrFunctionInstance(Engine, "defineProperties", DefineProperties, 2), true, false, true);
-            FastAddProperty("seal", new ClrFunctionInstance(Engine, "seal", Seal, 1), true, false, true);
-            FastAddProperty("freeze", new ClrFunctionInstance(Engine, "freeze", Freeze, 1), true, false, true);
-            FastAddProperty("preventExtensions", new ClrFunctionInstance(Engine, "preventExtensions", PreventExtensions, 1), true, false, true);
-            FastAddProperty("isSealed", new ClrFunctionInstance(Engine, "isSealed", IsSealed, 1), true, false, true);
-            FastAddProperty("isFrozen", new ClrFunctionInstance(Engine, "isFrozen", IsFrozen, 1), true, false, true);
-            FastAddProperty("isExtensible", new ClrFunctionInstance(Engine, "isExtensible", IsExtensible, 1), true, false, true);
-            FastAddProperty("keys", new ClrFunctionInstance(Engine, "keys", Keys, 1), true, false, true);
+            _properties = new StringDictionarySlim<PropertyDescriptor>(15)
+            {
+                ["getPrototypeOf"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "getPrototypeOf", GetPrototypeOf, 1), true, false, true),
+                ["getOwnPropertyDescriptor"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "getOwnPropertyDescriptor", GetOwnPropertyDescriptor, 2), true, false, true),
+                ["getOwnPropertyNames"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "getOwnPropertyNames", GetOwnPropertyNames, 1), true, false, true),
+                ["create"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "create", Create, 2), true, false, true),
+                ["defineProperty"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "defineProperty", DefineProperty, 3), true, false, true),
+                ["defineProperties"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "defineProperties", DefineProperties, 2), true, false, true),
+                ["seal"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "seal", Seal, 1), true, false, true),
+                ["freeze"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "freeze", Freeze, 1), true, false, true),
+                ["preventExtensions"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "preventExtensions", PreventExtensions, 1), true, false, true),
+                ["isSealed"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "isSealed", IsSealed, 1), true, false, true),
+                ["isFrozen"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "isFrozen", IsFrozen, 1), true, false, true),
+                ["isExtensible"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "isExtensible", IsExtensible, 1), true, false, true),
+                ["keys"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "keys", Keys, 1), true, false, true)
+            };
         }
 
         public ObjectPrototype PrototypeObject { get; private set; }

+ 18 - 2
Jint/Native/Object/ObjectInstance.cs

@@ -25,8 +25,9 @@ namespace Jint.Native.Object
 
         internal StringDictionarySlim<PropertyDescriptor> _properties;
 
+        private bool _initialized;
         private readonly string _class;
-        protected internal readonly Engine _engine;
+        protected readonly Engine _engine;
 
         public ObjectInstance(Engine engine) : this(engine, "Object")
         {
@@ -734,6 +735,11 @@ namespace Jint.Native.Object
             SetOwnProperty(name, new PropertyDescriptor(value, writable, enumerable, configurable));
         }
 
+        internal void FastAddProperty(string name, JsValue value, PropertyFlag flags)
+        {
+            SetOwnProperty(name, new PropertyDescriptor(value, flags));
+        }
+
         /// <summary>
         /// Optimized version of [[Put]] when the property is known to be already declared
         /// </summary>
@@ -744,7 +750,17 @@ namespace Jint.Native.Object
             SetOwnProperty(name, value);
         }
 
-        protected virtual void EnsureInitialized()
+        protected void EnsureInitialized()
+        {
+            if (!_initialized)
+            {
+                // we need to set flag eagerly to prevent wrong recursion
+                _initialized = true;
+                Initialize();
+            }
+        }
+
+        protected virtual void Initialize()
         {
         }
 

+ 20 - 11
Jint/Native/Object/ObjectPrototype.cs

@@ -1,4 +1,5 @@
-using Jint.Runtime;
+using Jint.Collections;
+using Jint.Runtime;
 using Jint.Runtime.Descriptors;
 using Jint.Runtime.Interop;
 
@@ -6,27 +7,35 @@ namespace Jint.Native.Object
 {
     public sealed class ObjectPrototype : ObjectInstance
     {
+        private ObjectConstructor _objectConstructor;
+
         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, true, false, true);
+            var obj = new ObjectPrototype(engine)
+            {
+                Extensible = true,
+                _objectConstructor = objectConstructor
+            };
 
             return obj;
         }
 
-        public void Configure()
+        protected override void Initialize()
         {
-            FastAddProperty("toString", new ClrFunctionInstance(Engine, "toString", ToObjectString), true, false, true);
-            FastAddProperty("toLocaleString", new ClrFunctionInstance(Engine, "toLocaleString", ToLocaleString), true, false, true);
-            FastAddProperty("valueOf", new ClrFunctionInstance(Engine, "valueOF", ValueOf), true, false, true);
-            FastAddProperty("hasOwnProperty", new ClrFunctionInstance(Engine, "hasOwnProperty", HasOwnProperty, 1), true, false, true);
-            FastAddProperty("isPrototypeOf", new ClrFunctionInstance(Engine, "isPrototypeOf", IsPrototypeOf, 1), true, false, true);
-            FastAddProperty("propertyIsEnumerable", new ClrFunctionInstance(Engine, "propertyIsEnumerable", PropertyIsEnumerable, 1), true, false, true);
+            _properties = new StringDictionarySlim<PropertyDescriptor>(8)
+            {
+                ["constructor"] = new PropertyDescriptor(_objectConstructor, true, false, true),
+                ["toString"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "toString", ToObjectString), true, false, true),
+                ["toLocaleString"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "toLocaleString", ToLocaleString), true, false, true),
+                ["valueOf"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "valueOF", ValueOf), true, false, true),
+                ["hasOwnProperty"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "hasOwnProperty", HasOwnProperty, 1), true, false, true),
+                ["isPrototypeOf"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "isPrototypeOf", IsPrototypeOf, 1), true, false, true),
+                ["propertyIsEnumerable"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "propertyIsEnumerable", PropertyIsEnumerable, 1), true, false, true)
+            };
         }
 
         private JsValue PropertyIsEnumerable(JsValue thisObject, JsValue[] arguments)

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

@@ -10,32 +10,32 @@ namespace Jint.Native.RegExp
 {
     public sealed class RegExpConstructor : FunctionInstance, IConstructor
     {
+        private static readonly JsString _functionName = new JsString("RegExp");
+
         public RegExpConstructor(Engine engine)
-            : base(engine, "RegExp", null, null, false)
+            : base(engine, _functionName, strict: false)
         {
         }
 
         public static RegExpConstructor CreateRegExpConstructor(Engine engine)
         {
-            var obj = new RegExpConstructor(engine);
-            obj.Extensible = true;
+            var obj = new RegExpConstructor(engine)
+            {
+                Extensible = true,
+                Prototype = engine.Function.PrototypeObject
+            };
 
             // The value of the [[Prototype]] internal property of the RegExp constructor is the Function prototype object
-            obj.Prototype = engine.Function.PrototypeObject;
             obj.PrototypeObject = RegExpPrototype.CreatePrototypeObject(engine, obj);
 
-            obj.SetOwnProperty("length", new PropertyDescriptor(2, PropertyFlag.AllForbidden));
+            obj._length = new PropertyDescriptor(2, PropertyFlag.AllForbidden);
 
             // The initial value of RegExp.prototype is the RegExp prototype object
-            obj.SetOwnProperty("prototype", new PropertyDescriptor(obj.PrototypeObject, PropertyFlag.AllForbidden));
+            obj._prototype= new PropertyDescriptor(obj.PrototypeObject, PropertyFlag.AllForbidden);
 
             return obj;
         }
 
-        public void Configure()
-        {
-        }
-
         public override JsValue Call(JsValue thisObject, JsValue[] arguments)
         {
             var pattern = arguments.At(0);

+ 22 - 14
Jint/Native/RegExp/RegExpPrototype.cs

@@ -1,4 +1,5 @@
 using System.Text.RegularExpressions;
+using Jint.Collections;
 using Jint.Native.Array;
 using Jint.Runtime;
 using Jint.Runtime.Descriptors;
@@ -8,6 +9,8 @@ namespace Jint.Native.RegExp
 {
     public sealed class RegExpPrototype : RegExpInstance
     {
+        private RegExpConstructor _regExpConstructor;
+
         private RegExpPrototype(Engine engine)
             : base(engine)
         {
@@ -15,25 +18,30 @@ namespace Jint.Native.RegExp
 
         public static RegExpPrototype CreatePrototypeObject(Engine engine, RegExpConstructor regExpConstructor)
         {
-            var obj = new RegExpPrototype(engine);
-            obj.Prototype = engine.Object.PrototypeObject;
-            obj.Extensible = true;
+            var obj = new RegExpPrototype(engine)
+            {
+                Prototype = engine.Object.PrototypeObject,
+                Extensible = true,
+                _regExpConstructor = regExpConstructor
+            };
 
-            obj.FastAddProperty("constructor", regExpConstructor, true, false, true);
             return obj;
         }
 
-        public void Configure()
+        protected override void Initialize()
         {
-            FastAddProperty("toString", new ClrFunctionInstance(Engine, "toString", ToRegExpString), true, false, true);
-            FastAddProperty("exec", new ClrFunctionInstance(Engine, "exec", Exec, 1), true, false, true);
-            FastAddProperty("test", new ClrFunctionInstance(Engine, "test", Test, 1), true, false, true);
-
-            FastAddProperty("global", false, false, false, false);
-            FastAddProperty("ignoreCase", false, false, false, false);
-            FastAddProperty("multiline", false, false, false, false);
-            FastAddProperty("source", "(?:)", false, false, false);
-            FastAddProperty("lastIndex", 0, true, false, false);
+            _properties = new StringDictionarySlim<PropertyDescriptor>(10)
+            {
+                ["constructor"] = new PropertyDescriptor(_regExpConstructor, true, false, true),
+                ["toString"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "toString", ToRegExpString), true, false, true),
+                ["exec"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "exec", Exec, 1), true, false, true),
+                ["test"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "test", Test, 1), true, false, true),
+                ["global"] = new PropertyDescriptor(false, false, false, false),
+                ["ignoreCase"] = new PropertyDescriptor(false, false, false, false),
+                ["multiline"] = new PropertyDescriptor(false, false, false, false),
+                ["source"] = new PropertyDescriptor("(?:)", false, false, false),
+                ["lastIndex"] = new PropertyDescriptor(0, true, false, false)
+            };
         }
 
         private static JsValue ToRegExpString(JsValue thisObj, JsValue[] arguments)

+ 19 - 21
Jint/Native/Set/SetConstructor.cs

@@ -1,4 +1,5 @@
-using Jint.Native.Function;
+using Jint.Collections;
+using Jint.Native.Function;
 using Jint.Native.Iterator;
 using Jint.Native.Object;
 using Jint.Native.Symbol;
@@ -11,7 +12,10 @@ namespace Jint.Native.Set
 {
     public sealed class SetConstructor : FunctionInstance, IConstructor
     {
-        private SetConstructor(Engine engine, string name) : base(engine, name, null, null, false)
+        private static readonly JsString _functionName = new JsString("Set");
+
+        private SetConstructor(Engine engine)
+            : base(engine, _functionName, false)
         {
         }
 
@@ -19,35 +23,29 @@ namespace Jint.Native.Set
 
         public static SetConstructor CreateSetConstructor(Engine engine)
         {
-            SetConstructor CreateSetConstructorTemplate(string name)
+            var obj = new SetConstructor(engine)
             {
-                var ctr = new SetConstructor(engine, name);
-                ctr.Extensible = true;
-
-                // The value of the [[Prototype]] internal property of the Set constructor is the Function prototype object
-                ctr.Prototype = engine.Function.PrototypeObject;
-                ctr.PrototypeObject = SetPrototype.CreatePrototypeObject(engine, ctr);
+                Extensible = true,
+                Prototype = engine.Function.PrototypeObject
+            };
 
-                ctr.SetOwnProperty("length", new PropertyDescriptor(0, PropertyFlag.Configurable));
-                return ctr;
-            }
+            // The value of the [[Prototype]] internal property of the Set constructor is the Function prototype object
+            obj.PrototypeObject = SetPrototype.CreatePrototypeObject(engine, obj);
 
-            var obj = CreateSetConstructorTemplate("Set");
+            obj._length = new PropertyDescriptor(0, PropertyFlag.Configurable);
 
             // The initial value of Set.prototype is the Set prototype object
-            obj.SetOwnProperty("prototype", new PropertyDescriptor(obj.PrototypeObject, PropertyFlag.AllForbidden));
-
-            obj.SetOwnProperty(GlobalSymbolRegistry.Species._value,
-                new GetSetPropertyDescriptor(
-                    get: new ClrFunctionInstance(engine, "get [Symbol.species]", Species, 0, PropertyFlag.Configurable),
-                    set: Undefined,
-                    PropertyFlag.Configurable));
+            obj._prototype = new PropertyDescriptor(obj.PrototypeObject, PropertyFlag.AllForbidden);
 
             return obj;
         }
 
-        public void Configure()
+        protected override void Initialize()
         {
+            _properties = new StringDictionarySlim<PropertyDescriptor>(2)
+            {
+                [GlobalSymbolRegistry.Species._value] = new GetSetPropertyDescriptor(get: new ClrFunctionInstance(_engine, "get [Symbol.species]", Species, 0, PropertyFlag.Configurable), set: Undefined, PropertyFlag.Configurable)
+            };
         }
 
         private static JsValue Species(JsValue thisObject, JsValue[] arguments)

+ 23 - 24
Jint/Native/Set/SetPrototype.cs

@@ -1,4 +1,5 @@
-using Jint.Native.Object;
+using Jint.Collections;
+using Jint.Native.Object;
 using Jint.Native.Symbol;
 using Jint.Runtime;
 using Jint.Runtime.Descriptors;
@@ -12,6 +13,8 @@ namespace Jint.Native.Set
     /// </summary>
     public sealed class SetPrototype : ObjectInstance
     {
+        private SetConstructor _mapConstructor;
+
         private SetPrototype(Engine engine) : base(engine)
         {
         }
@@ -21,35 +24,31 @@ namespace Jint.Native.Set
             var obj = new SetPrototype(engine)
             {
                 Extensible = true, 
-                Prototype = engine.Object.PrototypeObject
+                Prototype = engine.Object.PrototypeObject,
+                _mapConstructor = mapConstructor
             };
 
-            obj.SetOwnProperty("length", new PropertyDescriptor(0, PropertyFlag.Configurable));
-            obj.SetOwnProperty("constructor", new PropertyDescriptor(mapConstructor, PropertyFlag.NonEnumerable));
-
             return obj;
         }
 
-        public void Configure()
+        protected override void Initialize()
         {
-            FastAddProperty(GlobalSymbolRegistry.Iterator._value, new ClrFunctionInstance(Engine, "iterator", Values, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty(GlobalSymbolRegistry.ToStringTag._value, "Set", false, false, true);
-
-            FastAddProperty("add", new ClrFunctionInstance(Engine, "add", Add, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("clear", new ClrFunctionInstance(Engine, "clear", Clear, 0, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("delete", new ClrFunctionInstance(Engine, "delete", Delete, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("entries", new ClrFunctionInstance(Engine, "entries", Entries, 0, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("forEach", new ClrFunctionInstance(Engine, "forEach", ForEach, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("has", new ClrFunctionInstance(Engine, "has", Has, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("keys", new ClrFunctionInstance(Engine, "keys", Values, 0, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("values", new ClrFunctionInstance(Engine, "values", Values, 0, PropertyFlag.Configurable), true, false, true);
-
-            AddProperty(
-                "size", 
-                new GetSetPropertyDescriptor(
-                    get: new ClrFunctionInstance(Engine, "get size", Size, 0, PropertyFlag.Configurable), 
-                    set: null,
-                    PropertyFlag.Configurable));
+            _properties = new StringDictionarySlim<PropertyDescriptor>(15)
+            {
+                ["length"] = new PropertyDescriptor(0, PropertyFlag.Configurable),
+                ["constructor"] = new PropertyDescriptor(_mapConstructor, PropertyFlag.NonEnumerable),
+                [GlobalSymbolRegistry.Iterator._value] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "iterator", Values, 1, PropertyFlag.Configurable), true, false, true),
+                [GlobalSymbolRegistry.ToStringTag._value] = new PropertyDescriptor("Set", false, false, true),
+                ["add"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "add", Add, 1, PropertyFlag.Configurable), true, false, true),
+                ["clear"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "clear", Clear, 0, PropertyFlag.Configurable), true, false, true),
+                ["delete"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "delete", Delete, 1, PropertyFlag.Configurable), true, false, true),
+                ["entries"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "entries", Entries, 0, PropertyFlag.Configurable), true, false, true),
+                ["forEach"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "forEach", ForEach, 1, PropertyFlag.Configurable), true, false, true),
+                ["has"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "has", Has, 1, PropertyFlag.Configurable), true, false, true),
+                ["keys"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "keys", Values, 0, PropertyFlag.Configurable), true, false, true),
+                ["values"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "values", Values, 0, PropertyFlag.Configurable), true, false, true),
+                ["size"] = new GetSetPropertyDescriptor(get: new ClrFunctionInstance(Engine, "get size", Size, 0, PropertyFlag.Configurable), set: null, PropertyFlag.Configurable)
+            };
         }
         
         private JsValue Size(JsValue thisObj, JsValue[] arguments)

+ 21 - 11
Jint/Native/String/StringConstructor.cs

@@ -1,4 +1,5 @@
 using System.Collections.Generic;
+using Jint.Collections;
 using Jint.Native.Array;
 using Jint.Native.Function;
 using Jint.Native.Object;
@@ -11,33 +12,40 @@ namespace Jint.Native.String
 {
     public sealed class StringConstructor : FunctionInstance, IConstructor
     {
+        private static readonly JsString _functionName = new JsString("String");
+
         public StringConstructor(Engine engine)
-            : base(engine, "String", null, null, false)
+            : base(engine, _functionName, strict: false)
         {
         }
 
         public static StringConstructor CreateStringConstructor(Engine engine)
         {
-            var obj = new StringConstructor(engine);
-            obj.Extensible = true;
+            var obj = new StringConstructor(engine)
+            {
+                Extensible = true,
+                Prototype = engine.Function.PrototypeObject
+            };
 
             // 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.SetOwnProperty("length", new PropertyDescriptor(1, PropertyFlag.AllForbidden));
+            obj._length = PropertyDescriptor.AllForbiddenDescriptor.NumberOne;
 
             // The initial value of String.prototype is the String prototype object
-            obj.SetOwnProperty("prototype", new PropertyDescriptor(obj.PrototypeObject, PropertyFlag.AllForbidden));
+            obj._prototype = new PropertyDescriptor(obj.PrototypeObject, PropertyFlag.AllForbidden);
 
             return obj;
         }
 
-        public void Configure()
+        protected override void Initialize()
         {
-            SetOwnProperty("fromCharCode", new PropertyDescriptor(new ClrFunctionInstance(Engine, "fromCharCode", FromCharCode, 1), PropertyFlag.NonEnumerable));
-            SetOwnProperty("fromCodePoint", new PropertyDescriptor(new ClrFunctionInstance(Engine, "fromCodePoint", FromCodePoint, 1, PropertyFlag.Configurable), PropertyFlag.NonEnumerable));
-            SetOwnProperty("raw", new PropertyDescriptor(new ClrFunctionInstance(Engine, "raw", Raw, 1, PropertyFlag.Configurable), PropertyFlag.NonEnumerable));
+            _properties = new StringDictionarySlim<PropertyDescriptor>(3)
+            {
+                ["fromCharCode"] = new PropertyDescriptor(new PropertyDescriptor(new ClrFunctionInstance(Engine, "fromCharCode", FromCharCode, 1), PropertyFlag.NonEnumerable)),
+                ["fromCodePoint"] = new PropertyDescriptor(new PropertyDescriptor(new ClrFunctionInstance(Engine, "fromCodePoint", FromCodePoint, 1, PropertyFlag.Configurable), PropertyFlag.NonEnumerable)),
+                ["raw"] = new PropertyDescriptor(new PropertyDescriptor(new ClrFunctionInstance(Engine, "raw", Raw, 1, PropertyFlag.Configurable), PropertyFlag.NonEnumerable))
+            };
         }
 
         private static JsValue FromCharCode(JsValue thisObj, JsValue[] arguments)
@@ -170,7 +178,9 @@ namespace Jint.Native.String
                 Prototype = PrototypeObject,
                 PrimitiveValue = value,
                 Extensible = true,
-                _length = new PropertyDescriptor(value.Length, PropertyFlag.AllForbidden)
+                _length = value.Length == 0
+                    ? PropertyDescriptor.AllForbiddenDescriptor.NumberZero
+                    : new PropertyDescriptor(value.Length, PropertyFlag.AllForbidden)
             };
 
             return instance;

+ 47 - 39
Jint/Native/String/StringPrototype.cs

@@ -2,6 +2,7 @@
 using System.Linq;
 using System.Runtime.CompilerServices;
 using System.Text;
+using Jint.Collections;
 using Jint.Native.Array;
 using Jint.Native.Function;
 using Jint.Native.Object;
@@ -19,6 +20,8 @@ namespace Jint.Native.String
     /// </summary>
     public sealed class StringPrototype : StringInstance
     {
+        private StringConstructor _stringConstructor;
+
         private StringPrototype(Engine engine)
             : base(engine)
         {
@@ -26,50 +29,55 @@ namespace Jint.Native.String
 
         public static StringPrototype CreatePrototypeObject(Engine engine, StringConstructor stringConstructor)
         {
-            var obj = new StringPrototype(engine);
-            obj.Prototype = engine.Object.PrototypeObject;
-            obj.PrimitiveValue = JsString.Empty;
-            obj.Extensible = true;
-            obj.SetOwnProperty("length", new PropertyDescriptor(0, PropertyFlag.AllForbidden));
-            obj.SetOwnProperty("constructor", new PropertyDescriptor(stringConstructor, PropertyFlag.NonEnumerable));
+            var obj = new StringPrototype(engine)
+            {
+                Prototype = engine.Object.PrototypeObject,
+                PrimitiveValue = JsString.Empty,
+                Extensible = true,
+                _length = PropertyDescriptor.AllForbiddenDescriptor.NumberZero,
+                _stringConstructor = stringConstructor,
+            };
 
             return obj;
         }
 
-        public void Configure()
+        protected override void Initialize()
         {
-            FastAddProperty("toString", new ClrFunctionInstance(Engine, "toString", ToStringString, 0, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("valueOf", new ClrFunctionInstance(Engine, "valueOf", ValueOf, 0, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("charAt", new ClrFunctionInstance(Engine, "charAt", CharAt, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("charCodeAt", new ClrFunctionInstance(Engine, "charCodeAt", CharCodeAt, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("codePointAt", new ClrFunctionInstance(Engine, "codePointAt", CodePointAt, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("concat", new ClrFunctionInstance(Engine, "concat", Concat, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("indexOf", new ClrFunctionInstance(Engine, "indexOf", IndexOf, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("endsWith", new ClrFunctionInstance(Engine, "endsWith", EndsWith, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("startsWith", new ClrFunctionInstance(Engine, "startsWith", StartsWith, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("lastIndexOf", new ClrFunctionInstance(Engine, "lastIndexOf", LastIndexOf, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("localeCompare", new ClrFunctionInstance(Engine, "localeCompare", LocaleCompare, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("match", new ClrFunctionInstance(Engine, "match", Match, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("replace", new ClrFunctionInstance(Engine, "replace", Replace, 2, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("search", new ClrFunctionInstance(Engine, "search", Search, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("slice", new ClrFunctionInstance(Engine, "slice", Slice, 2, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("split", new ClrFunctionInstance(Engine, "split", Split, 2, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("substr", new ClrFunctionInstance(Engine, "substr", Substr, 2), true, false, true);
-            FastAddProperty("substring", new ClrFunctionInstance(Engine, "substring", Substring, 2, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("toLowerCase", new ClrFunctionInstance(Engine, "toLowerCase", ToLowerCase, 0, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("toLocaleLowerCase", new ClrFunctionInstance(Engine, "toLocaleLowerCase", ToLocaleLowerCase, 0, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("toUpperCase", new ClrFunctionInstance(Engine, "toUpperCase", ToUpperCase, 0, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("toLocaleUpperCase", new ClrFunctionInstance(Engine, "toLocaleUpperCase", ToLocaleUpperCase, 0, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("trim", new ClrFunctionInstance(Engine, "trim", Trim, 0, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("trimStart", new ClrFunctionInstance(Engine, "trimStart", TrimStart, 0, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("trimEnd", new ClrFunctionInstance(Engine, "trimEnd", TrimEnd, 0, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("padStart", new ClrFunctionInstance(Engine, "padStart", PadStart, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("padEnd", new ClrFunctionInstance(Engine, "padEnd", PadEnd, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("includes", new ClrFunctionInstance(Engine, "includes", Includes, 1, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("normalize", new ClrFunctionInstance(Engine, "normalize", Normalize, 0, PropertyFlag.Configurable), true, false, true);
-            FastAddProperty("repeat", new ClrFunctionInstance(Engine, "repeat", Repeat, 1, PropertyFlag.Configurable), true, false, true);
-
-            FastAddProperty(GlobalSymbolRegistry.Iterator._value, new ClrFunctionInstance(Engine, "[Symbol.iterator]", Iterator, 0, PropertyFlag.Configurable), true, false, true);
+            _properties = new StringDictionarySlim<PropertyDescriptor>(40)
+            {
+                ["constructor"] = new PropertyDescriptor(_stringConstructor, PropertyFlag.NonEnumerable),
+                ["toString"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "toString", ToStringString, 0, PropertyFlag.Configurable), true, false, true),
+                ["valueOf"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "valueOf", ValueOf, 0, PropertyFlag.Configurable), true, false, true),
+                ["charAt"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "charAt", CharAt, 1, PropertyFlag.Configurable), true, false, true),
+                ["charCodeAt"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "charCodeAt", CharCodeAt, 1, PropertyFlag.Configurable), true, false, true),
+                ["codePointAt"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "codePointAt", CodePointAt, 1, PropertyFlag.Configurable), true, false, true),
+                ["concat"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "concat", Concat, 1, PropertyFlag.Configurable), true, false, true),
+                ["indexOf"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "indexOf", IndexOf, 1, PropertyFlag.Configurable), true, false, true),
+                ["endsWith"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "endsWith", EndsWith, 1, PropertyFlag.Configurable), true, false, true),
+                ["startsWith"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "startsWith", StartsWith, 1, PropertyFlag.Configurable), true, false, true),
+                ["lastIndexOf"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "lastIndexOf", LastIndexOf, 1, PropertyFlag.Configurable), true, false, true),
+                ["localeCompare"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "localeCompare", LocaleCompare, 1, PropertyFlag.Configurable), true, false, true),
+                ["match"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "match", Match, 1, PropertyFlag.Configurable), true, false, true),
+                ["replace"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "replace", Replace, 2, PropertyFlag.Configurable), true, false, true),
+                ["search"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "search", Search, 1, PropertyFlag.Configurable), true, false, true),
+                ["slice"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "slice", Slice, 2, PropertyFlag.Configurable), true, false, true),
+                ["split"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "split", Split, 2, PropertyFlag.Configurable), true, false, true),
+                ["substr"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "substr", Substr, 2), true, false, true),
+                ["substring"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "substring", Substring, 2, PropertyFlag.Configurable), true, false, true),
+                ["toLowerCase"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "toLowerCase", ToLowerCase, 0, PropertyFlag.Configurable), true, false, true),
+                ["toLocaleLowerCase"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "toLocaleLowerCase", ToLocaleLowerCase, 0, PropertyFlag.Configurable), true, false, true),
+                ["toUpperCase"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "toUpperCase", ToUpperCase, 0, PropertyFlag.Configurable), true, false, true),
+                ["toLocaleUpperCase"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "toLocaleUpperCase", ToLocaleUpperCase, 0, PropertyFlag.Configurable), true, false, true),
+                ["trim"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "trim", Trim, 0, PropertyFlag.Configurable), true, false, true),
+                ["trimStart"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "trimStart", TrimStart, 0, PropertyFlag.Configurable), true, false, true),
+                ["trimEnd"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "trimEnd", TrimEnd, 0, PropertyFlag.Configurable), true, false, true),
+                ["padStart"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "padStart", PadStart, 1, PropertyFlag.Configurable), true, false, true),
+                ["padEnd"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "padEnd", PadEnd, 1, PropertyFlag.Configurable), true, false, true),
+                ["includes"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "includes", Includes, 1, PropertyFlag.Configurable), true, false, true),
+                ["normalize"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "normalize", Normalize, 0, PropertyFlag.Configurable), true, false, true),
+                ["repeat"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "repeat", Repeat, 1, PropertyFlag.Configurable), true, false, true),
+                [GlobalSymbolRegistry.Iterator._value] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "[Symbol.iterator]", Iterator, 0, PropertyFlag.Configurable), true, false, true)
+            };
         }
 
         private ObjectInstance Iterator(JsValue thisObj, JsValue[] arguments)

+ 30 - 26
Jint/Native/Symbol/SymbolConstructor.cs

@@ -1,4 +1,5 @@
-using Jint.Native.Function;
+using Jint.Collections;
+using Jint.Native.Function;
 using Jint.Native.Object;
 using Jint.Runtime;
 using Jint.Runtime.Descriptors;
@@ -12,48 +13,51 @@ namespace Jint.Native.Symbol
     /// </summary>
     public sealed class SymbolConstructor : FunctionInstance, IConstructor
     {
+        private static readonly JsString _functionName = new JsString("Symbol");
+
         public SymbolConstructor(Engine engine)
-            : base(engine, "Symbol", null, null, false)
+            : base(engine, _functionName, strict: false)
         {
         }
 
         public static SymbolConstructor CreateSymbolConstructor(Engine engine)
         {
-            var obj = new SymbolConstructor(engine);
-            obj.Extensible = true;
+            var obj = new SymbolConstructor(engine)
+            {
+                Extensible = true,
+                Prototype = engine.Function.PrototypeObject
+            };
 
             // The value of the [[Prototype]] internal property of the Symbol constructor is the Function prototype object
-            obj.Prototype = engine.Function.PrototypeObject;
             obj.PrototypeObject = SymbolPrototype.CreatePrototypeObject(engine, obj);
 
-            obj.SetOwnProperty("length", new PropertyDescriptor(0, PropertyFlag.AllForbidden));
+            obj._length = PropertyDescriptor.AllForbiddenDescriptor.NumberZero;
 
             // The initial value of String.prototype is the String prototype object
-            obj.SetOwnProperty("prototype", new PropertyDescriptor(obj.PrototypeObject, PropertyFlag.AllForbidden));
-
-
-            obj.SetOwnProperty("species", new PropertyDescriptor(GlobalSymbolRegistry.Species, PropertyFlag.AllForbidden));
+            obj._prototype = new PropertyDescriptor(obj.PrototypeObject, PropertyFlag.AllForbidden);
 
             return obj;
         }
 
-        public void Configure()
+        protected override void Initialize()
         {
-            FastAddProperty("for", new ClrFunctionInstance(Engine, "for", For, 1), true, false, true);
-            FastAddProperty("keyFor", new ClrFunctionInstance(Engine, "keyFor", KeyFor, 1), true, false, true);
-
-            FastAddProperty("hasInstance", GlobalSymbolRegistry.HasInstance, false, false, false);
-            FastAddProperty("isConcatSpreadable", GlobalSymbolRegistry.IsConcatSpreadable, false, false, false);
-            FastAddProperty("iterator", GlobalSymbolRegistry.Iterator, false, false, false);
-            FastAddProperty("match", GlobalSymbolRegistry.Match, false, false, false);
-            FastAddProperty("replace", GlobalSymbolRegistry.Replace, false, false, false);
-            FastAddProperty("search", GlobalSymbolRegistry.Search, false, false, false);
-            FastAddProperty("species", GlobalSymbolRegistry.Species, false, false, false);
-            FastAddProperty("split", GlobalSymbolRegistry.Split, false, false, false);
-            FastAddProperty("toPrimitive", GlobalSymbolRegistry.ToPrimitive, false, false, false);
-            FastAddProperty("toStringTag", GlobalSymbolRegistry.ToStringTag, false, false, false);
-            FastAddProperty("unscopables", GlobalSymbolRegistry.Unscopables, false, false, false);
-
+            _properties = new StringDictionarySlim<PropertyDescriptor>(15)
+            {
+                ["species"] = new PropertyDescriptor(GlobalSymbolRegistry.Species, PropertyFlag.AllForbidden),
+                ["for"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "for", For, 1), true, false, true),
+                ["keyFor"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "keyFor", KeyFor, 1), true, false, true),
+                ["hasInstance"] = new PropertyDescriptor(GlobalSymbolRegistry.HasInstance, false, false, false),
+                ["isConcatSpreadable"] = new PropertyDescriptor(GlobalSymbolRegistry.IsConcatSpreadable, false, false, false),
+                ["iterator"] = new PropertyDescriptor(GlobalSymbolRegistry.Iterator, false, false, false),
+                ["match"] = new PropertyDescriptor(GlobalSymbolRegistry.Match, false, false, false),
+                ["replace"] = new PropertyDescriptor(GlobalSymbolRegistry.Replace, false, false, false),
+                ["search"] = new PropertyDescriptor(GlobalSymbolRegistry.Search, false, false, false),
+                ["species"] = new PropertyDescriptor(GlobalSymbolRegistry.Species, false, false, false),
+                ["split"] = new PropertyDescriptor(GlobalSymbolRegistry.Split, false, false, false),
+                ["toPrimitive"] = new PropertyDescriptor(GlobalSymbolRegistry.ToPrimitive, false, false, false),
+                ["toStringTag"] = new PropertyDescriptor(GlobalSymbolRegistry.ToStringTag, false, false, false),
+                ["unscopables"] = new PropertyDescriptor(GlobalSymbolRegistry.Unscopables, false, false, false)
+            };
         }
 
         /// <summary>

+ 21 - 13
Jint/Native/Symbol/SymbolPrototype.cs

@@ -1,4 +1,5 @@
-using Jint.Native.Object;
+using Jint.Collections;
+using Jint.Native.Object;
 using Jint.Runtime;
 using Jint.Runtime.Descriptors;
 using Jint.Runtime.Interop;
@@ -10,6 +11,8 @@ namespace Jint.Native.Symbol
     /// </summary>
     public sealed class SymbolPrototype : ObjectInstance
     {
+        private SymbolConstructor _symbolConstructor;
+
         private SymbolPrototype(Engine engine)
             : base(engine)
         {
@@ -17,23 +20,28 @@ namespace Jint.Native.Symbol
 
         public static SymbolPrototype CreatePrototypeObject(Engine engine, SymbolConstructor symbolConstructor)
         {
-            var obj = new SymbolPrototype(engine);
-            obj.Prototype = engine.Object.PrototypeObject;
-            obj.Extensible = true;
-            obj.SetOwnProperty("length", new PropertyDescriptor(0, PropertyFlag.AllForbidden));
-            obj.FastAddProperty("constructor", symbolConstructor, true, false, true);
+            var obj = new SymbolPrototype(engine)
+            {
+                Prototype = engine.Object.PrototypeObject,
+                Extensible = true,
+                _symbolConstructor = symbolConstructor
+            };
 
             return obj;
         }
 
-        public void Configure()
+        protected override void Initialize()
         {
-            FastAddProperty("toString", new ClrFunctionInstance(Engine, "toString", ToSymbolString), true, false, true);
-            FastAddProperty("valueOf", new ClrFunctionInstance(Engine, "valueOf", ValueOf), true, false, true);
-            FastAddProperty("toStringTag", new JsString("Symbol"), false, false, true);
-
-            FastAddProperty(GlobalSymbolRegistry.ToPrimitive._value, new ClrFunctionInstance(Engine, "toPrimitive", ToPrimitive), false, false, true);
-            FastAddProperty(GlobalSymbolRegistry.ToStringTag._value, new JsString("Symbol"), false, false, true);
+            _properties = new StringDictionarySlim<PropertyDescriptor>(8)
+            {
+                ["length"] = PropertyDescriptor.AllForbiddenDescriptor.NumberZero,
+                ["constructor"] = new PropertyDescriptor(_symbolConstructor, true, false, true),
+                ["toString"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "toString", ToSymbolString), true, false, true),
+                ["valueOf"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "valueOf", ValueOf), true, false, true),
+                ["toStringTag"] = new PropertyDescriptor(new JsString("Symbol"), false, false, true),
+                [GlobalSymbolRegistry.ToPrimitive._value] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "toPrimitive", ToPrimitive), false, false, true),
+                [GlobalSymbolRegistry.ToStringTag._value] = new PropertyDescriptor(new JsString("Symbol"), false, false, true)
+            };
         }
 
         public string SymbolDescriptiveString(JsSymbol sym)

+ 39 - 6
Jint/Runtime/Descriptors/PropertyDescriptor.cs

@@ -1,4 +1,5 @@
 using System.Runtime.CompilerServices;
+using Jint.Collections;
 using Jint.Native;
 using Jint.Native.Object;
 using Jint.Runtime.Descriptors.Specialized;
@@ -307,20 +308,21 @@ namespace Jint.Runtime.Descriptors
             }
 
             var obj = engine.Object.Construct(Arguments.Empty);
+            obj._properties = new StringDictionarySlim<PropertyDescriptor>(4);
 
             if (desc.IsDataDescriptor())
             {
-                obj.SetOwnProperty("value", new PropertyDescriptor(desc.Value ?? Native.Undefined.Instance, PropertyFlag.ConfigurableEnumerableWritable));
-                obj.SetOwnProperty("writable", new PropertyDescriptor(desc.Writable, PropertyFlag.ConfigurableEnumerableWritable));
+                obj._properties["value"] =  new PropertyDescriptor(desc.Value ?? Native.Undefined.Instance, PropertyFlag.ConfigurableEnumerableWritable);
+                obj._properties["writable"] = new PropertyDescriptor(desc.Writable, PropertyFlag.ConfigurableEnumerableWritable);
             }
             else
             {
-                obj.SetOwnProperty("get", new PropertyDescriptor(desc.Get ?? Native.Undefined.Instance, PropertyFlag.ConfigurableEnumerableWritable));
-                obj.SetOwnProperty("set", new PropertyDescriptor(desc.Set ?? Native.Undefined.Instance, PropertyFlag.ConfigurableEnumerableWritable));
+                obj._properties["get"] = new PropertyDescriptor(desc.Get ?? Native.Undefined.Instance, PropertyFlag.ConfigurableEnumerableWritable);
+                obj._properties["set"] = new PropertyDescriptor(desc.Set ?? Native.Undefined.Instance, PropertyFlag.ConfigurableEnumerableWritable);
             }
 
-            obj.SetOwnProperty("enumerable", new PropertyDescriptor(desc.Enumerable, PropertyFlag.ConfigurableEnumerableWritable));
-            obj.SetOwnProperty("configurable", new PropertyDescriptor(desc.Configurable, PropertyFlag.ConfigurableEnumerableWritable));
+            obj._properties["enumerable"] = new PropertyDescriptor(desc.Enumerable, PropertyFlag.ConfigurableEnumerableWritable);
+            obj._properties["configurable"] = new PropertyDescriptor(desc.Configurable, PropertyFlag.ConfigurableEnumerableWritable);
 
             return obj;
         }
@@ -395,5 +397,36 @@ namespace Jint.Runtime.Descriptors
                 set => ExceptionHelper.ThrowInvalidOperationException("making changes to undefined property's descriptor is not allowed");
             }
         }
+
+        internal sealed class AllForbiddenDescriptor : PropertyDescriptor
+        {
+            public static readonly AllForbiddenDescriptor NumberZero = new AllForbiddenDescriptor(JsNumber.Create(0));
+            public static readonly AllForbiddenDescriptor NumberOne = new AllForbiddenDescriptor(JsNumber.Create(1));
+            public static readonly AllForbiddenDescriptor NumberTwo = new AllForbiddenDescriptor(JsNumber.Create(2));
+
+            public static readonly AllForbiddenDescriptor BooleanFalse = new AllForbiddenDescriptor(JsBoolean.False);
+            public static readonly AllForbiddenDescriptor BooleanTrue = new AllForbiddenDescriptor(JsBoolean.True);
+
+            private AllForbiddenDescriptor(JsValue value)
+                : base(PropertyFlag.AllForbidden)
+            {
+                _value = value;
+            }
+
+            public static PropertyDescriptor ForNumber(int number)
+            {
+                switch (number)
+                {
+                    case 2:
+                        return NumberTwo;
+                    case 1:
+                        return NumberOne;
+                    case 0:
+                        return NumberZero;
+                    default:
+                        return new PropertyDescriptor(number, PropertyFlag.AllForbidden);
+                }
+            }
+        }
     }
 }

+ 21 - 0
Jint/Runtime/Descriptors/Specialized/GetSetPropertyDescriptor.cs

@@ -39,5 +39,26 @@ namespace Jint.Runtime.Descriptors.Specialized
         {
             _set = setter;
         }
+
+        internal sealed class ThrowerPropertyDescriptor : PropertyDescriptor
+        {
+            private readonly JsValue _get;
+            private readonly JsValue _set;
+
+            public ThrowerPropertyDescriptor(JsValue functionThrowTypeError)
+                : base(PropertyFlag.EnumerableSet | PropertyFlag.ConfigurableSet | PropertyFlag.CustomJsValue)
+            {
+                _get = functionThrowTypeError;
+                _set = functionThrowTypeError;
+            }
+
+            public override JsValue Get => _get;
+            public override JsValue Set => _set;
+
+            protected internal override JsValue CustomValue
+            {
+                set => ExceptionHelper.ThrowInvalidOperationException("making changes to throw type error property's descriptor is not allowed");
+            }
+        }
     }
 }

+ 23 - 0
Jint/Runtime/Descriptors/Specialized/LazyPropertyDescriptor.cs

@@ -0,0 +1,23 @@
+using System;
+using Jint.Native;
+
+namespace Jint.Runtime.Descriptors.Specialized
+{
+    internal sealed class LazyPropertyDescriptor : PropertyDescriptor
+    {
+        private readonly Func<JsValue> _resolver;
+
+        internal LazyPropertyDescriptor(Func<JsValue> resolver, bool? writable, bool? enumerable, bool? configurable)
+            : base(null, writable, enumerable, configurable)
+        {
+            _flags |= PropertyFlag.CustomJsValue;
+            _resolver = resolver;
+        }
+
+        protected internal override JsValue CustomValue
+        {
+            get => _value ?? (_value = _resolver());
+            set => _value = value;
+        }
+    }
+}

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

@@ -17,14 +17,17 @@ namespace Jint.Runtime.Interop
             string name,
             Func<JsValue, JsValue[], JsValue> func,
             int length = 0,
-            PropertyFlag lengthFlags = PropertyFlag.AllForbidden) : base(engine, name, null, null, false)
+            PropertyFlag lengthFlags = PropertyFlag.AllForbidden)
+            : base(engine, new JsString(name), strict: false)
         {
             _func = func;
 
             Prototype = engine.Function.PrototypeObject;
             Extensible = true;
 
-            _length = new PropertyDescriptor(length, lengthFlags);
+            _length = lengthFlags == PropertyFlag.AllForbidden
+                ? PropertyDescriptor.AllForbiddenDescriptor.ForNumber(length)
+                : new PropertyDescriptor(JsNumber.Create(length), lengthFlags);
         }
 
         public override JsValue Call(JsValue thisObject, JsValue[] arguments)

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

@@ -27,7 +27,7 @@ namespace Jint.Runtime.Interop
 
             // The value of the [[Prototype]] internal property of the TypeReference constructor is the Function prototype object
             obj.Prototype = engine.Function.PrototypeObject;
-            obj._length = new PropertyDescriptor(0, PropertyFlag.AllForbidden);
+            obj._length = PropertyDescriptor.AllForbiddenDescriptor.NumberZero;
 
             // The initial value of Boolean.prototype is the Boolean prototype object
             obj._prototype = new PropertyDescriptor(engine.Object.PrototypeObject, PropertyFlag.AllForbidden);