Browse Source

Refactor internals to support realm concept (#907)

* add Realm and Intrinsics concept
* switch ExceptionHelper to take Realm
* make realm a function parameter
* require realm for prototypes, create base class for prototype
* add some obsolete members to allow easier migration path
* use JsonSerializer directly in REPL
* use faster property conversion for numeric property call sites
* make global CLR functions lazy stateless
Marko Lahma 4 years ago
parent
commit
c55a5e447b
100 changed files with 1923 additions and 1736 deletions
  1. 3 1
      Jint.Repl/Program.cs
  2. 2 2
      Jint.Tests.Ecma/TestCases/alltests.json
  3. 15 0
      Jint.Tests.Test262/BuiltIns/ErrorTests.cs
  4. 11 9
      Jint.Tests.Test262/Test262Test.cs
  5. 7 10
      Jint.Tests.Test262/test/built-ins/Function/internals/Call/class-ctor-realm.js
  6. 0 4
      Jint.Tests.Test262/test/skipped.json
  7. 2 2
      Jint.Tests/Runtime/Debugger/CallStackTests.cs
  8. 2 2
      Jint.Tests/Runtime/Domain/UuidConstructor.cs
  9. 2 2
      Jint.Tests/Runtime/Domain/UuidPrototype.cs
  10. 3 3
      Jint.Tests/Runtime/EngineTests.cs
  11. 1 1
      Jint.Tests/Runtime/InteropTests.cs
  12. 1 1
      Jint.Tests/Runtime/NullPropagation.cs
  13. 2 3
      Jint.Tests/Runtime/WeakSetMapTests.cs
  14. 48 0
      Jint/Engine.Obsolete.cs
  15. 87 181
      Jint/Engine.cs
  16. 15 10
      Jint/EsprimaExtensions.cs
  17. 16 9
      Jint/JsValueExtensions.cs
  18. 1 2
      Jint/Key.cs
  19. 12 10
      Jint/Native/Argument/ArgumentsInstance.cs
  20. 36 36
      Jint/Native/Array/ArrayConstructor.cs
  21. 13 13
      Jint/Native/Array/ArrayInstance.cs
  22. 6 6
      Jint/Native/Array/ArrayOperations.cs
  23. 102 96
      Jint/Native/Array/ArrayPrototype.cs
  24. 14 19
      Jint/Native/Boolean/BooleanConstructor.cs
  25. 16 17
      Jint/Native/Boolean/BooleanPrototype.cs
  26. 14 20
      Jint/Native/Date/DateConstructor.cs
  27. 7 3
      Jint/Native/Date/DateInstance.cs
  28. 31 26
      Jint/Native/Date/DatePrototype.cs
  29. 19 33
      Jint/Native/Error/ErrorConstructor.cs
  30. 6 3
      Jint/Native/Error/ErrorInstance.cs
  31. 16 25
      Jint/Native/Error/ErrorPrototype.cs
  32. 14 9
      Jint/Native/Function/BindFunctionInstance.cs
  33. 12 7
      Jint/Native/Function/ClassDefinition.cs
  34. 39 20
      Jint/Native/Function/EvalFunctionInstance.cs
  35. 31 29
      Jint/Native/Function/FunctionConstructor.cs
  36. 81 30
      Jint/Native/Function/FunctionInstance.cs
  37. 27 21
      Jint/Native/Function/FunctionPrototype.cs
  38. 32 24
      Jint/Native/Function/ScriptFunctionInstance.cs
  39. 8 4
      Jint/Native/Function/ThrowTypeError.cs
  40. 93 62
      Jint/Native/Global/GlobalObject.cs
  41. 23 25
      Jint/Native/Iterator/IteratorConstructor.cs
  42. 30 17
      Jint/Native/Iterator/IteratorInstance.cs
  43. 6 6
      Jint/Native/Iterator/IteratorProtocol.cs
  44. 13 16
      Jint/Native/Iterator/IteratorPrototype.cs
  45. 1 1
      Jint/Native/JsString.cs
  46. 26 19
      Jint/Native/JsValue.cs
  47. 17 14
      Jint/Native/Json/JsonInstance.cs
  48. 15 14
      Jint/Native/Json/JsonParser.cs
  49. 7 7
      Jint/Native/Json/JsonSerializer.cs
  50. 17 24
      Jint/Native/Map/MapConstructor.cs
  51. 6 4
      Jint/Native/Map/MapInstance.cs
  52. 12 16
      Jint/Native/Map/MapPrototype.cs
  53. 2 11
      Jint/Native/Math/MathInstance.cs
  54. 2 2
      Jint/Native/Number/Dtoa/DtoaNumberFormatter.cs
  55. 4 4
      Jint/Native/Number/Dtoa/FastDtoa.cs
  56. 15 23
      Jint/Native/Number/NumberConstructor.cs
  57. 25 27
      Jint/Native/Number/NumberPrototype.cs
  58. 46 47
      Jint/Native/Object/ObjectConstructor.cs
  59. 35 23
      Jint/Native/Object/ObjectInstance.cs
  60. 25 26
      Jint/Native/Object/ObjectPrototype.cs
  61. 39 42
      Jint/Native/Promise/PromiseConstructor.cs
  62. 2 3
      Jint/Native/Promise/PromiseInstance.cs
  63. 25 24
      Jint/Native/Promise/PromisePrototype.cs
  64. 15 0
      Jint/Native/Prototype.cs
  65. 12 15
      Jint/Native/Proxy/ProxyConstructor.cs
  66. 50 45
      Jint/Native/Proxy/ProxyInstance.cs
  67. 43 42
      Jint/Native/Reflect/ReflectInstance.cs
  68. 19 26
      Jint/Native/RegExp/RegExpConstructor.cs
  69. 40 40
      Jint/Native/RegExp/RegExpPrototype.cs
  70. 20 26
      Jint/Native/Set/SetConstructor.cs
  71. 2 2
      Jint/Native/Set/SetInstance.cs
  72. 16 20
      Jint/Native/Set/SetPrototype.cs
  73. 15 25
      Jint/Native/String/StringConstructor.cs
  74. 38 35
      Jint/Native/String/StringPrototype.cs
  75. 16 24
      Jint/Native/Symbol/SymbolConstructor.cs
  76. 13 17
      Jint/Native/Symbol/SymbolPrototype.cs
  77. 18 25
      Jint/Native/WeakMap/WeakMapConstructor.cs
  78. 1 1
      Jint/Native/WeakMap/WeakMapInstance.cs
  79. 14 18
      Jint/Native/WeakMap/WeakMapPrototype.cs
  80. 21 28
      Jint/Native/WeakSet/WeakSetConstructor.cs
  81. 1 1
      Jint/Native/WeakSet/WeakSetInstance.cs
  82. 14 18
      Jint/Native/WeakSet/WeakSetPrototype.cs
  83. 24 12
      Jint/Options.cs
  84. 1 1
      Jint/Pooling/ArgumentsInstancePool.cs
  85. 4 4
      Jint/Runtime/Descriptors/GetSetPropertyDescriptor.cs
  86. 7 7
      Jint/Runtime/Descriptors/PropertyDescriptor.cs
  87. 5 3
      Jint/Runtime/Descriptors/Specialized/LazyPropertyDescriptor.cs
  88. 8 8
      Jint/Runtime/Environments/DeclarativeEnvironmentRecord.cs
  89. 5 3
      Jint/Runtime/Environments/EnvironmentRecord.cs
  90. 17 5
      Jint/Runtime/Environments/ExecutionContext.cs
  91. 30 25
      Jint/Runtime/Environments/FunctionEnvironmentRecord.cs
  92. 21 15
      Jint/Runtime/Environments/GlobalEnvironmentRecord.cs
  93. 10 3
      Jint/Runtime/Environments/JintEnvironment.cs
  94. 9 9
      Jint/Runtime/Environments/ObjectEnvironmentRecord.cs
  95. 47 0
      Jint/Runtime/Environments/PrivateEnvironmentRecord.cs
  96. 23 76
      Jint/Runtime/ExceptionHelper.cs
  97. 96 0
      Jint/Runtime/Host.cs
  98. 3 3
      Jint/Runtime/Interop/ClrFunctionInstance.cs
  99. 4 3
      Jint/Runtime/Interop/DelegateWrapper.cs
  100. 1 1
      Jint/Runtime/Interop/GetterFunctionInstance.cs

+ 3 - 1
Jint.Repl/Program.cs

@@ -4,6 +4,7 @@ using System.IO;
 using System.Reflection;
 using System.Reflection;
 using Esprima;
 using Esprima;
 using Jint.Native;
 using Jint.Native;
+using Jint.Native.Json;
 using Jint.Runtime;
 using Jint.Runtime;
 
 
 namespace Jint.Repl
 namespace Jint.Repl
@@ -67,7 +68,8 @@ namespace Jint.Repl
                     var result = engine.Evaluate(input, parserOptions);
                     var result = engine.Evaluate(input, parserOptions);
                     if (!result.IsNull() && !result.IsUndefined())
                     if (!result.IsNull() && !result.IsUndefined())
                     {
                     {
-                        var str = TypeConverter.ToString(engine.Json.Stringify(engine.Json, Arguments.From(result, Undefined.Instance, "  ")));
+                        var serializer = new JsonSerializer(engine);
+                        var str = serializer.Serialize(result, Undefined.Instance, "  ");
                         Console.WriteLine(str);
                         Console.WriteLine(str);
                     }
                     }
                     else
                     else

+ 2 - 2
Jint.Tests.Ecma/TestCases/alltests.json

@@ -21935,8 +21935,8 @@
     source: "ch15/15.11/15.11.4/S15.11.4_A1.js"
     source: "ch15/15.11/15.11.4/S15.11.4_A1.js"
   },
   },
   {
   {
-    skip: false,
-    reason: "",
+    skip: true,
+    reason: "spec has changed",
     source: "ch15/15.11/15.11.4/S15.11.4_A2.js"
     source: "ch15/15.11/15.11.4/S15.11.4_A2.js"
   },
   },
   {
   {

+ 15 - 0
Jint.Tests.Test262/BuiltIns/ErrorTests.cs

@@ -0,0 +1,15 @@
+using Xunit;
+
+namespace Jint.Tests.Test262.BuiltIns
+{
+    public class ErrorTests : Test262Test
+    {
+        [Theory(DisplayName = "built-ins\\Error")]
+        [MemberData(nameof(SourceFiles), "built-ins\\Error", false)]
+        [MemberData(nameof(SourceFiles), "built-ins\\Error", true, Skip = "Skipped")]
+        protected void EncodeUri(SourceFile sourceFile)
+        {
+            RunTestInternal(sourceFile);
+        }
+    }
+}

+ 11 - 9
Jint.Tests.Test262/Test262Test.cs

@@ -24,11 +24,9 @@ namespace Jint.Tests.Test262
 
 
         private static readonly TimeZoneInfo _pacificTimeZone;
         private static readonly TimeZoneInfo _pacificTimeZone;
 
 
-        private static readonly Dictionary<string, string> _skipReasons =
-            new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
+        private static readonly Dictionary<string, string> _skipReasons = new(StringComparer.OrdinalIgnoreCase);
 
 
-        private static readonly HashSet<string> _strictSkips =
-            new HashSet<string>(StringComparer.OrdinalIgnoreCase);
+        private static readonly HashSet<string> _strictSkips = new(StringComparer.OrdinalIgnoreCase);
 
 
         static Test262Test()
         static Test262Test()
         {
         {
@@ -102,7 +100,7 @@ namespace Jint.Tests.Test262
             engine.SetValue("print",
             engine.SetValue("print",
                 new ClrFunctionInstance(engine, "print", (thisObj, args) => TypeConverter.ToString(args.At(0))));
                 new ClrFunctionInstance(engine, "print", (thisObj, args) => TypeConverter.ToString(args.At(0))));
 
 
-            var o = engine.Object.Construct(Arguments.Empty);
+            var o = engine.Realm.Intrinsics.Object.Construct(Arguments.Empty);
             o.FastSetProperty("evalScript", new PropertyDescriptor(new ClrFunctionInstance(engine, "evalScript",
             o.FastSetProperty("evalScript", new PropertyDescriptor(new ClrFunctionInstance(engine, "evalScript",
                 (thisObj, args) =>
                 (thisObj, args) =>
                 {
                 {
@@ -116,7 +114,15 @@ namespace Jint.Tests.Test262
                     var script = parser.ParseScript(strict);
                     var script = parser.ParseScript(strict);
 
 
                     return engine.Evaluate(script);
                     return engine.Evaluate(script);
+                }), true, true, true));   
+            o.FastSetProperty("createRealm", new PropertyDescriptor(new ClrFunctionInstance(engine, "createRealm",
+                (thisObj, args) =>
+                {
+                    var realm = engine._host.CreateRealm();
+                    realm.GlobalObject.Set("global", realm.GlobalObject);
+                    return realm.GlobalObject;
                 }), true, true, true));
                 }), true, true, true));
+
             engine.SetValue("$262", o);
             engine.SetValue("$262", o);
 
 
             var includes = Regex.Match(code, @"includes: \[(.+?)\]");
             var includes = Regex.Match(code, @"includes: \[(.+?)\]");
@@ -216,10 +222,6 @@ namespace Jint.Tests.Test262
                         switch (item)
                         switch (item)
                         {
                         {
                             // TODO implement
                             // TODO implement
-                            case "cross-realm":
-                                skip = true;
-                                reason = "realms not implemented";
-                                break;
                             case "tail-call-optimization":
                             case "tail-call-optimization":
                                 skip = true;
                                 skip = true;
                                 reason = "tail-calls not implemented";
                                 reason = "tail-calls not implemented";

+ 7 - 10
Jint.Tests.Test262/test/built-ins/Function/internals/Call/class-ctor-realm.js

@@ -2,19 +2,16 @@
 // This code is governed by the BSD license found in the LICENSE file.
 // This code is governed by the BSD license found in the LICENSE file.
 /*---
 /*---
 esid: sec-ecmascript-function-objects-call-thisargument-argumentslist
 esid: sec-ecmascript-function-objects-call-thisargument-argumentslist
-es6id: 9.2.1
 description: >
 description: >
-  Error when invoking a class constructor (honoring the Realm of the current
-  execution context)
-info: |
-  [...]
-  2. If F's [[FunctionKind]] internal slot is "classConstructor", throw a
-     TypeError exception.
+  Error when invoking a default class constructor, honoring the Realm
+  that the class was defined in.
 features: [cross-realm, class]
 features: [cross-realm, class]
 ---*/
 ---*/
 
 
-var C = $262.createRealm().global.eval('0, class {}');
+const realm = $262.createRealm();
+const C = realm.global.eval('(class {})');
+const TE = realm.global.eval('TypeError');
 
 
-assert.throws(TypeError, function() {
+assert.throws(TE, function() {
   C();
   C();
-});
+});

+ 0 - 4
Jint.Tests.Test262/test/skipped.json

@@ -170,10 +170,6 @@
     "source": "built-ins/Map/prototype/values/does-not-have-mapdata-internal-slot-weakmap.js",
     "source": "built-ins/Map/prototype/values/does-not-have-mapdata-internal-slot-weakmap.js",
     "reason": "WeakMap not implemented"
     "reason": "WeakMap not implemented"
   },
   },
-  {
-    "source": "built-ins/Set/proto-from-ctor-realm.js",
-    "reason": "realms not implemented"
-  },
   {
   {
     "source": "built-ins/Set/prototype/add/does-not-have-setdata-internal-slot-weakset.js",
     "source": "built-ins/Set/prototype/add/does-not-have-setdata-internal-slot-weakset.js",
     "reason": "WeakSet not implemented"
     "reason": "WeakSet not implemented"

+ 2 - 2
Jint.Tests/Runtime/Debugger/CallStackTests.cs

@@ -155,8 +155,8 @@ car.test();
             TestHelpers.TestAtBreak(script, (engine, info) =>
             TestHelpers.TestAtBreak(script, (engine, info) =>
             {
             {
                 Assert.Collection(info.CallStack,
                 Assert.Collection(info.CallStack,
-                    frame => Assert.Equal(engine.Global.Get("car"), frame.This),
-                    frame => Assert.Equal(engine.Global, frame.This)
+                    frame => Assert.Equal(engine.Realm.GlobalObject.Get("car"), frame.This),
+                    frame => Assert.Equal(engine.Realm.GlobalObject, frame.This)
                 );
                 );
             });
             });
         }
         }

+ 2 - 2
Jint.Tests/Runtime/Domain/UuidConstructor.cs

@@ -12,7 +12,7 @@ namespace Jint.Tests.Runtime.Domain
     {
     {
         private static readonly JsString _functionName = new JsString("Uuid");
         private static readonly JsString _functionName = new JsString("Uuid");
 
 
-        private UuidConstructor(Engine engine) : base(engine, _functionName)
+        private UuidConstructor(Engine engine) : base(engine, engine.Realm, _functionName)
         {
         {
         }
         }
 
 
@@ -41,7 +41,7 @@ namespace Jint.Tests.Runtime.Domain
             var obj = new UuidConstructor(engine)
             var obj = new UuidConstructor(engine)
             {
             {
                 // The value of the [[Prototype]] internal property of the Uuid constructor is the Function prototype object
                 // The value of the [[Prototype]] internal property of the Uuid constructor is the Function prototype object
-                _prototype = engine.Function.PrototypeObject
+                _prototype = engine.Realm.Intrinsics.Function.PrototypeObject
             };
             };
             obj.PrototypeObject = UuidPrototype.CreatePrototypeObject(engine, obj);
             obj.PrototypeObject = UuidPrototype.CreatePrototypeObject(engine, obj);
 
 

+ 2 - 2
Jint.Tests/Runtime/Domain/UuidPrototype.cs

@@ -14,7 +14,7 @@ namespace Jint.Tests.Runtime.Domain
         {
         {
             return thisObj.TryCast<UuidInstance>(value =>
             return thisObj.TryCast<UuidInstance>(value =>
             {
             {
-                throw new JavaScriptException(Engine.TypeError, "Invalid Uuid");
+                throw new JavaScriptException(Engine.Realm.Intrinsics.TypeError, "Invalid Uuid");
             });
             });
         }
         }
 
 
@@ -27,7 +27,7 @@ namespace Jint.Tests.Runtime.Domain
             var obj = new UuidPrototype(engine)
             var obj = new UuidPrototype(engine)
             {
             {
                 PrimitiveValue = JsUuid.Empty,
                 PrimitiveValue = JsUuid.Empty,
-                _prototype = engine.Object.PrototypeObject,
+                _prototype = engine.Realm.Intrinsics.Object.PrototypeObject,
             };
             };
 
 
             obj.FastAddProperty("constructor", ctor, false, false, true);
             obj.FastAddProperty("constructor", ctor, false, false, true);

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

@@ -1057,8 +1057,8 @@ myarr[0](0);
         [Fact]
         [Fact]
         public void ShouldComputeFractionInBase()
         public void ShouldComputeFractionInBase()
         {
         {
-            Assert.Equal("011", _engine.Number.PrototypeObject.ToFractionBase(0.375, 2));
-            Assert.Equal("14141414141414141414141414141414141414141414141414", _engine.Number.PrototypeObject.ToFractionBase(0.375, 5));
+            Assert.Equal("011", _engine.Realm.Intrinsics.Number.PrototypeObject.ToFractionBase(0.375, 2));
+            Assert.Equal("14141414141414141414141414141414141414141414141414", _engine.Realm.Intrinsics.Number.PrototypeObject.ToFractionBase(0.375, 5));
         }
         }
 
 
         [Fact]
         [Fact]
@@ -1143,7 +1143,7 @@ myarr[0](0);
         [InlineData("2qgpckvng1s", 10000000000000000L, 36)]
         [InlineData("2qgpckvng1s", 10000000000000000L, 36)]
         public void ShouldConvertNumbersToDifferentBase(string expected, long number, int radix)
         public void ShouldConvertNumbersToDifferentBase(string expected, long number, int radix)
         {
         {
-            var result = _engine.Number.PrototypeObject.ToBase(number, radix);
+            var result = _engine.Realm.Intrinsics.Number.PrototypeObject.ToBase(number, radix);
             Assert.Equal(expected, result);
             Assert.Equal(expected, result);
         }
         }
 
 

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

@@ -817,7 +817,7 @@ namespace Jint.Tests.Runtime
                     var instance = new ObjectWrapper(engine, target);
                     var instance = new ObjectWrapper(engine, target);
                     if (instance.IsArrayLike)
                     if (instance.IsArrayLike)
                     {
                     {
-                        instance.SetPrototypeOf(engine.Array.PrototypeObject);
+                        instance.SetPrototypeOf(engine.Realm.Intrinsics.Array.PrototypeObject);
                     }
                     }
                     return instance;
                     return instance;
                 })
                 })

+ 1 - 1
Jint.Tests/Runtime/NullPropagation.cs

@@ -99,7 +99,7 @@ function test2(arg) {
         {
         {
             var engine = new Engine(cfg => cfg.SetReferencesResolver(new NullPropagationReferenceResolver()));
             var engine = new Engine(cfg => cfg.SetReferencesResolver(new NullPropagationReferenceResolver()));
 
 
-            var jsObject = engine.Object.Construct(Arguments.Empty);
+            var jsObject = engine.Realm.Intrinsics.Object.Construct(Arguments.Empty);
             jsObject.Set("NullField", JsValue.Null);
             jsObject.Set("NullField", JsValue.Null);
 
 
             var script = @"
             var script = @"

+ 2 - 3
Jint.Tests/Runtime/WeakSetMapTests.cs

@@ -1,4 +1,3 @@
-using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
 using Jint.Native;
 using Jint.Native;
 using Jint.Native.Object;
 using Jint.Native.Object;
@@ -44,7 +43,7 @@ namespace Jint.Tests.Runtime
         [MemberData(nameof(PrimitiveKeys))]
         [MemberData(nameof(PrimitiveKeys))]
         public void WeakSetAddShouldThrowForPrimitiveKey(JsValue key) {
         public void WeakSetAddShouldThrowForPrimitiveKey(JsValue key) {
             var weakSet = new WeakSetInstance(_engine);
             var weakSet = new WeakSetInstance(_engine);
-            
+
             var e = Assert.Throws<JavaScriptException>(() => weakSet.WeakSetAdd(key));
             var e = Assert.Throws<JavaScriptException>(() => weakSet.WeakSetAdd(key));
             Assert.StartsWith("WeakSet value must be an object, got ", e.Message);
             Assert.StartsWith("WeakSet value must be an object, got ", e.Message);
 
 
@@ -55,7 +54,7 @@ namespace Jint.Tests.Runtime
         [MemberData(nameof(PrimitiveKeys))]
         [MemberData(nameof(PrimitiveKeys))]
         public void WeakMapSetShouldThrowForPrimitiveKey(JsValue key) {
         public void WeakMapSetShouldThrowForPrimitiveKey(JsValue key) {
             var weakMap = new WeakMapInstance(_engine);
             var weakMap = new WeakMapInstance(_engine);
-            
+
             var e = Assert.Throws<JavaScriptException>(() => weakMap.WeakMapSet(key, new ObjectInstance(_engine)));
             var e = Assert.Throws<JavaScriptException>(() => weakMap.WeakMapSet(key, new ObjectInstance(_engine)));
             Assert.StartsWith("WeakMap key must be an object, got ", e.Message);
             Assert.StartsWith("WeakMap key must be an object, got ", e.Message);
 
 

+ 48 - 0
Jint/Engine.Obsolete.cs

@@ -0,0 +1,48 @@
+using System;
+using Jint.Native;
+using Jint.Native.Array;
+using Jint.Native.Date;
+using Jint.Native.Error;
+using Jint.Native.Function;
+using Jint.Native.Json;
+using Jint.Native.Object;
+using Jint.Native.String;
+
+namespace Jint
+{
+    public partial class Engine
+    {
+        /// <summary>
+        /// Gets the last evaluated statement completion value
+        /// </summary>
+        [Obsolete("Prefer calling Evaluate which returns last completion value. Execute is for initialization and Evaluate returns final result.")]
+        public JsValue GetCompletionValue()
+        {
+            return _completionValue;
+        }
+
+        [Obsolete("Use active realms Intrinsics to access well-known object")]
+        public ArrayConstructor Array => Realm.Intrinsics.Array;
+
+        [Obsolete("Use active realms Intrinsics to access well-known object")]
+        public DateConstructor Date => Realm.Intrinsics.Date;
+
+        [Obsolete("Use active realms Intrinsics to access well-known object")]
+        public EvalFunctionInstance Eval => Realm.Intrinsics.Eval;
+
+        [Obsolete("Use active realms Intrinsics to access well-known object")]
+        public ErrorConstructor Error => Realm.Intrinsics.Error;
+
+        [Obsolete("Use active realms Intrinsics to access well-known object")]
+        public FunctionConstructor Function => Realm.Intrinsics.Function;
+
+        [Obsolete("Use active realms Intrinsics to access well-known object")]
+        public JsonInstance Json => Realm.Intrinsics.Json;
+
+        [Obsolete("Use active realms Intrinsics to access well-known object")]
+        public ObjectConstructor Object => Realm.Intrinsics.Object;
+
+        [Obsolete("Use active realms Intrinsics to access well-known object")]
+        public StringConstructor String => Realm.Intrinsics.String;
+    }
+}

+ 87 - 181
Jint/Engine.cs

@@ -5,27 +5,10 @@ using Esprima;
 using Esprima.Ast;
 using Esprima.Ast;
 using Jint.Native;
 using Jint.Native;
 using Jint.Native.Argument;
 using Jint.Native.Argument;
-using Jint.Native.Array;
-using Jint.Native.Boolean;
-using Jint.Native.Date;
-using Jint.Native.Error;
 using Jint.Native.Function;
 using Jint.Native.Function;
-using Jint.Native.Global;
-using Jint.Native.Iterator;
-using Jint.Native.Json;
-using Jint.Native.Map;
-using Jint.Native.Math;
-using Jint.Native.Number;
 using Jint.Native.Object;
 using Jint.Native.Object;
 using Jint.Native.Promise;
 using Jint.Native.Promise;
-using Jint.Native.Proxy;
-using Jint.Native.Reflect;
-using Jint.Native.RegExp;
-using Jint.Native.Set;
-using Jint.Native.String;
 using Jint.Native.Symbol;
 using Jint.Native.Symbol;
-using Jint.Native.WeakMap;
-using Jint.Native.WeakSet;
 using Jint.Pooling;
 using Jint.Pooling;
 using Jint.Runtime;
 using Jint.Runtime;
 using Jint.Runtime.CallStack;
 using Jint.Runtime.CallStack;
@@ -40,7 +23,7 @@ using Jint.Runtime.References;
 
 
 namespace Jint
 namespace Jint
 {
 {
-    public class Engine
+    public partial class Engine
     {
     {
         private static readonly ParserOptions DefaultParserOptions = new("<anonymous>")
         private static readonly ParserOptions DefaultParserOptions = new("<anonymous>")
         {
         {
@@ -48,14 +31,6 @@ namespace Jint
             Tolerant = true
             Tolerant = 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 readonly ExecutionContextStack _executionContexts;
         private JsValue _completionValue = JsValue.Undefined;
         private JsValue _completionValue = JsValue.Undefined;
         internal Node _lastSyntaxNode;
         internal Node _lastSyntaxNode;
@@ -63,13 +38,6 @@ namespace Jint
         private readonly EventLoop _eventLoop = new();
         private readonly EventLoop _eventLoop = new();
 
 
         // lazy properties
         // 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 DebugHandler _debugHandler;
 
 
         // cached access
         // cached access
@@ -91,8 +59,8 @@ namespace Jint
             {typeof(bool), (engine, v) => (bool) v ? JsBoolean.True : JsBoolean.False},
             {typeof(bool), (engine, v) => (bool) v ? JsBoolean.True : JsBoolean.False},
             {typeof(byte), (engine, v) => JsNumber.Create((byte) v)},
             {typeof(byte), (engine, v) => JsNumber.Create((byte) v)},
             {typeof(char), (engine, v) => JsString.Create((char) 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(DateTime), (engine, v) => engine.Realm.Intrinsics.Date.Construct((DateTime) v)},
+            {typeof(DateTimeOffset), (engine, v) => engine.Realm.Intrinsics.Date.Construct((DateTimeOffset) v)},
             {typeof(decimal), (engine, v) => (JsValue) (double) (decimal) v},
             {typeof(decimal), (engine, v) => (JsValue) (double) (decimal) v},
             {typeof(double), (engine, v) => (JsValue) (double) v},
             {typeof(double), (engine, v) => (JsValue) (double) v},
             {typeof(Int16), (engine, v) => JsNumber.Create((Int16) v)},
             {typeof(Int16), (engine, v) => JsNumber.Create((Int16) v)},
@@ -106,7 +74,7 @@ namespace Jint
             {typeof(UInt64), (engine, v) => JsNumber.Create((UInt64) v)},
             {typeof(UInt64), (engine, v) => JsNumber.Create((UInt64) v)},
             {
             {
                 typeof(System.Text.RegularExpressions.Regex),
                 typeof(System.Text.RegularExpressions.Regex),
-                (engine, v) => engine.RegExp.Construct((System.Text.RegularExpressions.Regex) v, "")
+                (engine, v) => engine.Realm.Intrinsics.RegExp.Construct((System.Text.RegularExpressions.Regex) v, "")
             }
             }
         };
         };
 
 
@@ -118,6 +86,10 @@ namespace Jint
 
 
         internal readonly JintCallStack CallStack;
         internal readonly JintCallStack CallStack;
 
 
+        // needed in initial engine setup, for example CLR function construction
+        internal Intrinsics _originalIntrinsics;
+        internal Host _host;
+
         /// <summary>
         /// <summary>
         /// Constructs a new engine instance.
         /// Constructs a new engine instance.
         /// </summary>
         /// </summary>
@@ -148,10 +120,6 @@ namespace Jint
         {
         {
             _executionContexts = new ExecutionContextStack(2);
             _executionContexts = new ExecutionContextStack(2);
 
 
-            Global = GlobalObject.CreateGlobalObject(this);
-
-            Object = ObjectConstructor.CreateObjectConstructor(this);
-            Function = FunctionConstructor.CreateFunctionConstructor(this);
             _callerCalleeArgumentsThrowerConfigurable = new GetSetPropertyDescriptor.ThrowerPropertyDescriptor(this,
             _callerCalleeArgumentsThrowerConfigurable = new GetSetPropertyDescriptor.ThrowerPropertyDescriptor(this,
                 PropertyFlag.Configurable | PropertyFlag.CustomJsValue,
                 PropertyFlag.Configurable | PropertyFlag.CustomJsValue,
                 "'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them");
                 "'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them");
@@ -159,50 +127,11 @@ namespace Jint
                 PropertyFlag.CustomJsValue,
                 PropertyFlag.CustomJsValue,
                 "'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them");
                 "'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them");
 
 
-            Symbol = SymbolConstructor.CreateSymbolConstructor(this);
-            Array = ArrayConstructor.CreateArrayConstructor(this);
-            Map = MapConstructor.CreateMapConstructor(this);
-            Set = SetConstructor.CreateSetConstructor(this);
-            WeakMap = WeakMapConstructor.CreateWeakMapConstructor(this);
-            WeakSet = WeakSetConstructor.CreateWeakSetConstructor(this);
-            Promise = PromiseConstructor.CreatePromiseConstructor(this);
-            Iterator = IteratorConstructor.CreateIteratorConstructor(this);
-            String = StringConstructor.CreateStringConstructor(this);
-            RegExp = RegExpConstructor.CreateRegExpConstructor(this);
-            Number = NumberConstructor.CreateNumberConstructor(this);
-            Boolean = BooleanConstructor.CreateBooleanConstructor(this);
-            Date = DateConstructor.CreateDateConstructor(this);
-            Math = MathInstance.CreateMathObject(this);
-            Json = JsonInstance.CreateJsonObject(this);
-            Proxy = ProxyConstructor.CreateProxyConstructor(this);
-            Reflect = ReflectInstance.CreateReflectObject(this);
-
-            GlobalSymbolRegistry = new GlobalSymbolRegistry();
-
-            // Because the properties might need some of the built-in object
-            // their configuration is delayed to a later step
-
-            // trigger initialization
-            Global.EnsureInitialized();
-
-            // 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 = JintEnvironment.NewGlobalEnvironment(this, Global, Global);
-
-            // create the global execution context http://www.ecma-international.org/ecma-262/5.1/#sec-10.4.1.1
-            EnterExecutionContext(GlobalEnvironment, GlobalEnvironment);
-
-            Eval = new EvalFunctionInstance(this);
-            Global.SetProperty(CommonProperties.Eval,
-                new PropertyDescriptor(Eval, PropertyFlag.Configurable | PropertyFlag.Writable));
-
             Options = new Options();
             Options = new Options();
-
             options?.Invoke(this, Options);
             options?.Invoke(this, Options);
 
 
+            Reset();
+
             // gather some options as fields for faster checks
             // gather some options as fields for faster checks
             _isDebugMode = Options.IsDebugMode;
             _isDebugMode = Options.IsDebugMode;
             _isStrict = Options.IsStrict;
             _isStrict = Options.IsStrict;
@@ -217,56 +146,25 @@ namespace Jint
             Options.Apply(this);
             Options.Apply(this);
         }
         }
 
 
-        internal GlobalEnvironmentRecord GlobalEnvironment { get; }
-        public GlobalObject Global { get; }
-        public ObjectConstructor Object { get; }
-        public FunctionConstructor Function { get; }
-        public ArrayConstructor Array { get; }
-        public MapConstructor Map { get; }
-        public SetConstructor Set { get; }
-        public WeakMapConstructor WeakMap { get; }
-        public WeakSetConstructor WeakSet { get; }
-        public PromiseConstructor Promise { get; }
-        public IteratorConstructor Iterator { get; }
-        public StringConstructor String { get; }
-        public RegExpConstructor RegExp { get; }
-        public BooleanConstructor Boolean { get; }
-        public NumberConstructor Number { get; }
-        public DateConstructor Date { get; }
-        public MathInstance Math { get; }
-        public JsonInstance Json { get; }
-        public ProxyConstructor Proxy { get; }
-        public ReflectInstance Reflect { get; }
-        public SymbolConstructor Symbol { get; }
-        public EvalFunctionInstance Eval { get; }
-
-        public ErrorConstructor Error => _error ??= ErrorConstructor.CreateErrorConstructor(this, _errorFunctionName);
-
-        public ErrorConstructor EvalError =>
-            _evalError ??= ErrorConstructor.CreateErrorConstructor(this, _evalErrorFunctionName);
-
-        public ErrorConstructor SyntaxError =>
-            _syntaxError ??= ErrorConstructor.CreateErrorConstructor(this, _syntaxErrorFunctionName);
-
-        public ErrorConstructor TypeError =>
-            _typeError ??= ErrorConstructor.CreateErrorConstructor(this, _typeErrorFunctionName);
-
-        public ErrorConstructor RangeError =>
-            _rangeError ??= ErrorConstructor.CreateErrorConstructor(this, _rangeErrorFunctionName);
-
-        public ErrorConstructor ReferenceError => _referenceError ??=
-            ErrorConstructor.CreateErrorConstructor(this, _referenceErrorFunctionName);
-
-        public ErrorConstructor UriError =>
-            _uriError ??= ErrorConstructor.CreateErrorConstructor(this, _uriErrorFunctionName);
-
-        public ref readonly ExecutionContext ExecutionContext
+        private void Reset()
+        {
+            _host = Options._hostFactory(this);
+            _host.Initialize(this);
+        }
+
+        internal ref readonly ExecutionContext ExecutionContext
         {
         {
             [MethodImpl(MethodImplOptions.AggressiveInlining)]
             [MethodImpl(MethodImplOptions.AggressiveInlining)]
             get => ref _executionContexts.Peek();
             get => ref _executionContexts.Peek();
         }
         }
 
 
-        public GlobalSymbolRegistry GlobalSymbolRegistry { get; }
+        // temporary state for realm so that we can easily pass it to functions while still not
+        // having a proper execution context established
+        internal Realm _realmInConstruction;
+
+        public Realm Realm => _realmInConstruction ?? ExecutionContext.Realm;
+
+        internal GlobalSymbolRegistry GlobalSymbolRegistry { get; } = new();
 
 
         internal long CurrentMemoryUsage { get; private set; }
         internal long CurrentMemoryUsage { get; private set; }
 
 
@@ -279,13 +177,19 @@ namespace Jint
 
 
         public DebugHandler DebugHandler => _debugHandler ??= new DebugHandler(this);
         public DebugHandler DebugHandler => _debugHandler ??= new DebugHandler(this);
 
 
-        public ExecutionContext EnterExecutionContext(
+
+        internal ExecutionContext EnterExecutionContext(
             EnvironmentRecord lexicalEnvironment,
             EnvironmentRecord lexicalEnvironment,
-            EnvironmentRecord variableEnvironment)
+            EnvironmentRecord variableEnvironment,
+            Realm realm,
+            PrivateEnvironmentRecord privateEnvironment)
         {
         {
             var context = new ExecutionContext(
             var context = new ExecutionContext(
                 lexicalEnvironment,
                 lexicalEnvironment,
-                variableEnvironment);
+                variableEnvironment,
+                privateEnvironment,
+                realm,
+                null);
 
 
             _executionContexts.Push(context);
             _executionContexts.Push(context);
             return context;
             return context;
@@ -299,7 +203,7 @@ namespace Jint
 
 
         public Engine SetValue(JsValue name, Delegate value)
         public Engine SetValue(JsValue name, Delegate value)
         {
         {
-            Global.FastAddProperty(name, new DelegateWrapper(this, value), true, false, true);
+            Realm.GlobalObject.FastAddProperty(name, new DelegateWrapper(this, value), true, false, true);
             return this;
             return this;
         }
         }
 
 
@@ -325,7 +229,7 @@ namespace Jint
 
 
         public Engine SetValue(JsValue name, JsValue value)
         public Engine SetValue(JsValue name, JsValue value)
         {
         {
-            Global.Set(name, value, Global);
+            Realm.GlobalObject.Set(name, value);
             return this;
             return this;
         }
         }
 
 
@@ -338,7 +242,7 @@ namespace Jint
             return SetValue(name, value);
             return SetValue(name, value);
         }
         }
 
 
-        public void LeaveExecutionContext()
+        internal void LeaveExecutionContext()
         {
         {
             _executionContexts.Pop();
             _executionContexts.Pop();
         }
         }
@@ -362,7 +266,7 @@ namespace Jint
             CallStack.Clear();
             CallStack.Clear();
         }
         }
 
 
-        public JsValue Evaluate(string source) 
+        public JsValue Evaluate(string source)
             => Execute(source, DefaultParserOptions)._completionValue;
             => Execute(source, DefaultParserOptions)._completionValue;
 
 
         public JsValue Evaluate(string source, ParserOptions parserOptions)
         public JsValue Evaluate(string source, ParserOptions parserOptions)
@@ -371,10 +275,10 @@ namespace Jint
         public JsValue Evaluate(Script script)
         public JsValue Evaluate(Script script)
             => Execute(script)._completionValue;
             => Execute(script)._completionValue;
 
 
-        public Engine Execute(string source) 
+        public Engine Execute(string source)
             => Execute(source, DefaultParserOptions);
             => Execute(source, DefaultParserOptions);
 
 
-        public Engine Execute(string source, ParserOptions parserOptions) 
+        public Engine Execute(string source, ParserOptions parserOptions)
             => Execute(new JavaScriptParser(source, parserOptions).ParseScript());
             => Execute(new JavaScriptParser(source, parserOptions).ParseScript());
 
 
         public Engine Execute(Script script)
         public Engine Execute(Script script)
@@ -386,7 +290,7 @@ namespace Jint
             {
             {
                 GlobalDeclarationInstantiation(
                 GlobalDeclarationInstantiation(
                     script,
                     script,
-                    GlobalEnvironment);
+                    Realm.GlobalEnv);
 
 
                 var list = new JintStatementList(this, null, script.Body);
                 var list = new JintStatementList(this, null, script.Body);
 
 
@@ -421,7 +325,7 @@ namespace Jint
 
 
         /// <summary>
         /// <summary>
         /// EXPERIMENTAL! Subject to change.
         /// EXPERIMENTAL! Subject to change.
-        /// 
+        ///
         /// Registers a promise within the currently running EventLoop (has to be called within "ExecuteWithEventLoop" call).
         /// Registers a promise within the currently running EventLoop (has to be called within "ExecuteWithEventLoop" call).
         /// Note that ExecuteWithEventLoop will not trigger "onFinished" callback until ALL manual promises are settled.
         /// Note that ExecuteWithEventLoop will not trigger "onFinished" callback until ALL manual promises are settled.
         ///
         ///
@@ -433,9 +337,9 @@ namespace Jint
         {
         {
             var promise = new PromiseInstance(this)
             var promise = new PromiseInstance(this)
             {
             {
-                _prototype = Promise.PrototypeObject 
+                _prototype = Realm.Intrinsics.Promise.PrototypeObject
             };
             };
-            
+
             var (resolve, reject) = promise.CreateResolvingFunctions();
             var (resolve, reject) = promise.CreateResolvingFunctions();
 
 
 
 
@@ -477,15 +381,6 @@ namespace Jint
             _lastSyntaxNode = null;
             _lastSyntaxNode = null;
         }
         }
 
 
-        /// <summary>
-        /// Gets the last evaluated statement completion value
-        /// </summary>
-        [Obsolete("Prefer calling Evaluate which returns last completion value. Execute is for initialization and Evaluate returns final result.")]
-        public JsValue GetCompletionValue()
-        {
-            return _completionValue;
-        }
-
         internal void RunBeforeExecuteStatementChecks(Statement statement)
         internal void RunBeforeExecuteStatementChecks(Statement statement)
         {
         {
             // Avoid allocating the enumerator because we run this loop very often.
             // Avoid allocating the enumerator because we run this loop very often.
@@ -534,7 +429,7 @@ namespace Jint
                     return val;
                     return val;
                 }
                 }
 
 
-                ExceptionHelper.ThrowReferenceError(this, reference);
+                ExceptionHelper.ThrowReferenceError(Realm, reference);
             }
             }
 
 
             if ((baseValue._type & InternalTypes.ObjectEnvironmentRecord) == 0
             if ((baseValue._type & InternalTypes.ObjectEnvironmentRecord) == 0
@@ -553,7 +448,7 @@ namespace Jint
 
 
                 if (baseValue.IsObject())
                 if (baseValue.IsObject())
                 {
                 {
-                    var o = TypeConverter.ToObject(this, baseValue);
+                    var o = TypeConverter.ToObject(Realm, baseValue);
                     var v = o.Get(property, reference.GetThisValue());
                     var v = o.Get(property, reference.GetThisValue());
                     return v;
                     return v;
                 }
                 }
@@ -571,7 +466,7 @@ namespace Jint
 
 
                     if (o is null)
                     if (o is null)
                     {
                     {
-                        o = TypeConverter.ToObject(this, baseValue);
+                        o = TypeConverter.ToObject(Realm, baseValue);
                     }
                     }
 
 
                     var desc = o.GetProperty(property);
                     var desc = o.GetProperty(property);
@@ -596,13 +491,13 @@ namespace Jint
                 }
                 }
             }
             }
 
 
-            if (baseValue is not EnvironmentRecord record)
+            var record = baseValue as EnvironmentRecord;
+            if (record is null)
             {
             {
-                return ExceptionHelper.ThrowArgumentException<JsValue>();
+                ExceptionHelper.ThrowArgumentException();
             }
             }
 
 
-            var bindingValue =
-                record.GetBindingValue(reference.GetReferencedName().ToString(), reference.IsStrictReference());
+            var bindingValue = record.GetBindingValue(reference.GetReferencedName().ToString(), reference.IsStrictReference());
 
 
             if (returnReferenceToPool)
             if (returnReferenceToPool)
             {
             {
@@ -639,7 +534,7 @@ namespace Jint
                 && char.IsLower(propertyString._value[0]))
                 && char.IsLower(propertyString._value[0]))
             {
             {
                 // trying to find property that's always in prototype
                 // trying to find property that's always in prototype
-                o = String.PrototypeObject;
+                o = Realm.Intrinsics.String.PrototypeObject;
             }
             }
 
 
             jsValue = JsValue.Undefined;
             jsValue = JsValue.Undefined;
@@ -656,22 +551,22 @@ namespace Jint
             {
             {
                 if (reference.IsStrictReference())
                 if (reference.IsStrictReference())
                 {
                 {
-                    ExceptionHelper.ThrowReferenceError(this, reference);
+                    ExceptionHelper.ThrowReferenceError(Realm, reference);
                 }
                 }
 
 
-                Global.Set(reference.GetReferencedName(), value, throwOnError: false);
+                Realm.GlobalObject.Set(reference.GetReferencedName(), value, throwOnError: false);
             }
             }
             else if (reference.IsPropertyReference())
             else if (reference.IsPropertyReference())
             {
             {
                 if (reference.HasPrimitiveBase())
                 if (reference.HasPrimitiveBase())
                 {
                 {
-                    baseValue = TypeConverter.ToObject(this, baseValue);
+                    baseValue = TypeConverter.ToObject(Realm, baseValue);
                 }
                 }
 
 
                 var succeeded = baseValue.Set(reference.GetReferencedName(), value, reference.GetThisValue());
                 var succeeded = baseValue.Set(reference.GetReferencedName(), value, reference.GetThisValue());
                 if (!succeeded && reference.IsStrictReference())
                 if (!succeeded && reference.IsStrictReference())
                 {
                 {
-                    ExceptionHelper.ThrowTypeError(this);
+                    ExceptionHelper.ThrowTypeError(Realm);
                 }
                 }
             }
             }
             else
             else
@@ -735,8 +630,11 @@ namespace Jint
         /// <returns>The value returned by the function call.</returns>
         /// <returns>The value returned by the function call.</returns>
         public JsValue Invoke(JsValue value, object thisObj, object[] arguments)
         public JsValue Invoke(JsValue value, object thisObj, object[] arguments)
         {
         {
-            var callable = value as ICallable ??
-                           ExceptionHelper.ThrowTypeError<ICallable>(this, "Can only invoke functions");
+            var callable = value as ICallable;
+            if (callable is null)
+            {
+                ExceptionHelper.ThrowTypeError(Realm, "Can only invoke functions");
+            }
 
 
             var items = _jsValueArrayPool.RentArray(arguments.Length);
             var items = _jsValueArrayPool.RentArray(arguments.Length);
             for (int i = 0; i < arguments.Length; ++i)
             for (int i = 0; i < arguments.Length; ++i)
@@ -756,8 +654,11 @@ namespace Jint
         internal JsValue Invoke(JsValue v, JsValue p, JsValue[] arguments)
         internal JsValue Invoke(JsValue v, JsValue p, JsValue[] arguments)
         {
         {
             var func = GetV(v, p);
             var func = GetV(v, p);
-            var callable = func as ICallable ??
-                           ExceptionHelper.ThrowTypeErrorNoEngine<ICallable>("Can only invoke functions");
+            var callable = func as ICallable;
+            if (callable is null)
+            {
+                ExceptionHelper.ThrowTypeErrorNoEngine("Can only invoke functions");
+            }
             return callable.Call(v, arguments);
             return callable.Call(v, arguments);
         }
         }
 
 
@@ -766,7 +667,7 @@ namespace Jint
         /// </summary>
         /// </summary>
         internal JsValue GetV(JsValue v, JsValue p)
         internal JsValue GetV(JsValue v, JsValue p)
         {
         {
-            var o = TypeConverter.ToObject(this, v);
+            var o = TypeConverter.ToObject(Realm, v);
             return o.Get(p);
             return o.Get(p);
         }
         }
 
 
@@ -776,7 +677,7 @@ namespace Jint
         /// <param name="propertyName">The name of the property to return.</param>
         /// <param name="propertyName">The name of the property to return.</param>
         public JsValue GetValue(string propertyName)
         public JsValue GetValue(string propertyName)
         {
         {
-            return GetValue(Global, new JsString(propertyName));
+            return GetValue(Realm.GlobalObject, new JsString(propertyName));
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -860,6 +761,8 @@ namespace Jint
             var declaredFunctionNames = new HashSet<string>();
             var declaredFunctionNames = new HashSet<string>();
             var declaredVarNames = new List<string>();
             var declaredVarNames = new List<string>();
 
 
+            var realm = Realm;
+
             if (functionDeclarations != null)
             if (functionDeclarations != null)
             {
             {
                 for (var i = functionDeclarations.Count - 1; i >= 0; i--)
                 for (var i = functionDeclarations.Count - 1; i >= 0; i--)
@@ -871,7 +774,7 @@ namespace Jint
                         var fnDefinable = env.CanDeclareGlobalFunction(fn);
                         var fnDefinable = env.CanDeclareGlobalFunction(fn);
                         if (!fnDefinable)
                         if (!fnDefinable)
                         {
                         {
-                            ExceptionHelper.ThrowTypeError(this);
+                            ExceptionHelper.ThrowTypeError(realm);
                         }
                         }
 
 
                         declaredFunctionNames.Add(fn);
                         declaredFunctionNames.Add(fn);
@@ -894,7 +797,7 @@ namespace Jint
 
 
                         if (env.HasLexicalDeclaration(vn))
                         if (env.HasLexicalDeclaration(vn))
                         {
                         {
-                            ExceptionHelper.ThrowSyntaxError(this, $"Identifier '{vn}' has already been declared");
+                            ExceptionHelper.ThrowSyntaxError(realm, $"Identifier '{vn}' has already been declared");
                         }
                         }
 
 
                         if (!declaredFunctionNames.Contains(vn))
                         if (!declaredFunctionNames.Contains(vn))
@@ -902,7 +805,7 @@ namespace Jint
                             var vnDefinable = env.CanDeclareGlobalVar(vn);
                             var vnDefinable = env.CanDeclareGlobalVar(vn);
                             if (!vnDefinable)
                             if (!vnDefinable)
                             {
                             {
-                                ExceptionHelper.ThrowTypeError(this);
+                                ExceptionHelper.ThrowTypeError(realm);
                             }
                             }
 
 
                             declaredVarNames.Add(vn);
                             declaredVarNames.Add(vn);
@@ -925,7 +828,7 @@ namespace Jint
                             || env.HasLexicalDeclaration(dn)
                             || env.HasLexicalDeclaration(dn)
                             || env.HasRestrictedGlobalProperty(dn))
                             || env.HasRestrictedGlobalProperty(dn))
                         {
                         {
-                            ExceptionHelper.ThrowSyntaxError(this, $"Identifier '{dn}' has already been declared");
+                            ExceptionHelper.ThrowSyntaxError(realm, $"Identifier '{dn}' has already been declared");
                         }
                         }
 
 
                         if (d.Kind == VariableDeclarationKind.Const)
                         if (d.Kind == VariableDeclarationKind.Const)
@@ -946,10 +849,10 @@ namespace Jint
 
 
                 if (env.HasLexicalDeclaration(fn))
                 if (env.HasLexicalDeclaration(fn))
                 {
                 {
-                    ExceptionHelper.ThrowSyntaxError(this, $"Identifier '{fn}' has already been declared");
+                    ExceptionHelper.ThrowSyntaxError(realm, $"Identifier '{fn}' has already been declared");
                 }
                 }
 
 
-                var fo = Function.InstantiateFunctionObject(f, env);
+                var fo = realm.Intrinsics.Function.InstantiateFunctionObject(f, env);
                 env.CreateGlobalFunctionBinding(fn, fo, canBeDeleted: false);
                 env.CreateGlobalFunctionBinding(fn, fo, canBeDeleted: false);
             }
             }
 
 
@@ -973,7 +876,7 @@ namespace Jint
             var envRec = (FunctionEnvironmentRecord) env;
             var envRec = (FunctionEnvironmentRecord) env;
             var strict = StrictModeScope.IsStrictModeCode;
             var strict = StrictModeScope.IsStrictModeCode;
 
 
-            var configuration = func.Initialize(this, functionInstance);
+            var configuration = func.Initialize(functionInstance);
             var parameterNames = configuration.ParameterNames;
             var parameterNames = configuration.ParameterNames;
             var hasDuplicates = configuration.HasDuplicates;
             var hasDuplicates = configuration.HasDuplicates;
             var simpleParameterList = configuration.IsSimpleParameterList;
             var simpleParameterList = configuration.IsSimpleParameterList;
@@ -1051,7 +954,7 @@ namespace Jint
                 }
                 }
             }
             }
 
 
-            // NOTE: Annex B.3.3.1 adds additional steps at this point. 
+            // NOTE: Annex B.3.3.1 adds additional steps at this point.
             // A https://tc39.es/ecma262/#sec-web-compat-functiondeclarationinstantiation
             // A https://tc39.es/ecma262/#sec-web-compat-functiondeclarationinstantiation
 
 
             EnvironmentRecord lexEnv;
             EnvironmentRecord lexEnv;
@@ -1090,10 +993,11 @@ namespace Jint
             EnvironmentRecord lexEnv,
             EnvironmentRecord lexEnv,
             DeclarativeEnvironmentRecord varEnvRec)
             DeclarativeEnvironmentRecord varEnvRec)
         {
         {
+            var realm = Realm;
             foreach (var f in functionsToInitialize)
             foreach (var f in functionsToInitialize)
             {
             {
                 var fn = f.Id.Name;
                 var fn = f.Id.Name;
-                var fo = Function.InstantiateFunctionObject(f, lexEnv);
+                var fo = realm.Intrinsics.Function.InstantiateFunctionObject(f, lexEnv);
                 varEnvRec.SetMutableBinding(fn, fo, strict: false);
                 varEnvRec.SetMutableBinding(fn, fo, strict: false);
             }
             }
         }
         }
@@ -1141,6 +1045,7 @@ namespace Jint
             Script script,
             Script script,
             EnvironmentRecord varEnv,
             EnvironmentRecord varEnv,
             EnvironmentRecord lexEnv,
             EnvironmentRecord lexEnv,
+            PrivateEnvironmentRecord privateEnv,
             bool strict)
             bool strict)
         {
         {
             var hoistingScope = HoistingScope.GetProgramLevelDeclarations(script);
             var hoistingScope = HoistingScope.GetProgramLevelDeclarations(script);
@@ -1148,6 +1053,8 @@ namespace Jint
             var lexEnvRec = (DeclarativeEnvironmentRecord) lexEnv;
             var lexEnvRec = (DeclarativeEnvironmentRecord) lexEnv;
             var varEnvRec = varEnv;
             var varEnvRec = varEnv;
 
 
+            var realm = Realm;
+
             if (!strict && hoistingScope._variablesDeclarations != null)
             if (!strict && hoistingScope._variablesDeclarations != null)
             {
             {
                 if (varEnvRec is GlobalEnvironmentRecord globalEnvironmentRecord)
                 if (varEnvRec is GlobalEnvironmentRecord globalEnvironmentRecord)
@@ -1159,8 +1066,7 @@ namespace Jint
                         var identifier = (Identifier) variablesDeclaration.Declarations[0].Id;
                         var identifier = (Identifier) variablesDeclaration.Declarations[0].Id;
                         if (globalEnvironmentRecord.HasLexicalDeclaration(identifier.Name))
                         if (globalEnvironmentRecord.HasLexicalDeclaration(identifier.Name))
                         {
                         {
-                            ExceptionHelper.ThrowSyntaxError(this,
-                                "Identifier '" + identifier.Name + "' has already been declared");
+                            ExceptionHelper.ThrowSyntaxError(realm, "Identifier '" + identifier.Name + "' has already been declared");
                         }
                         }
                     }
                     }
                 }
                 }
@@ -1178,7 +1084,7 @@ namespace Jint
                             var identifier = (Identifier) variablesDeclaration.Declarations[0].Id;
                             var identifier = (Identifier) variablesDeclaration.Declarations[0].Id;
                             if (thisEnvRec.HasBinding(identifier.Name))
                             if (thisEnvRec.HasBinding(identifier.Name))
                             {
                             {
-                                ExceptionHelper.ThrowSyntaxError(this);
+                                ExceptionHelper.ThrowSyntaxError(realm);
                             }
                             }
                         }
                         }
                     }
                     }
@@ -1204,7 +1110,7 @@ namespace Jint
                             var fnDefinable = ger.CanDeclareGlobalFunction(fn);
                             var fnDefinable = ger.CanDeclareGlobalFunction(fn);
                             if (!fnDefinable)
                             if (!fnDefinable)
                             {
                             {
-                                ExceptionHelper.ThrowTypeError(this);
+                                ExceptionHelper.ThrowTypeError(realm);
                             }
                             }
                         }
                         }
 
 
@@ -1233,7 +1139,7 @@ namespace Jint
                             var vnDefinable = ger.CanDeclareGlobalFunction(vn);
                             var vnDefinable = ger.CanDeclareGlobalFunction(vn);
                             if (!vnDefinable)
                             if (!vnDefinable)
                             {
                             {
-                                ExceptionHelper.ThrowTypeError(this);
+                                ExceptionHelper.ThrowTypeError(realm);
                             }
                             }
                         }
                         }
 
 
@@ -1266,7 +1172,7 @@ namespace Jint
             foreach (var f in functionsToInitialize)
             foreach (var f in functionsToInitialize)
             {
             {
                 var fn = f.Id.Name;
                 var fn = f.Id.Name;
-                var fo = Function.InstantiateFunctionObject(f, lexEnv);
+                var fo = realm.Intrinsics.Function.InstantiateFunctionObject(f, lexEnv);
                 if (varEnvRec is GlobalEnvironmentRecord ger)
                 if (varEnvRec is GlobalEnvironmentRecord ger)
                 {
                 {
                     ger.CreateGlobalFunctionBinding(fn, fo, canBeDeleted: true);
                     ger.CreateGlobalFunctionBinding(fn, fo, canBeDeleted: true);

+ 15 - 10
Jint/EsprimaExtensions.cs

@@ -32,7 +32,8 @@ namespace Jint
 
 
             if (!resolveComputed || !TryGetComputedPropertyKey(expression, engine, out var propertyKey))
             if (!resolveComputed || !TryGetComputedPropertyKey(expression, engine, out var propertyKey))
             {
             {
-                return ExceptionHelper.ThrowArgumentException<JsValue>("Unable to extract correct key, node type: " + expression.Type);
+                ExceptionHelper.ThrowArgumentException("Unable to extract correct key, node type: " + expression.Type);
+                return null;
             }
             }
 
 
             return propertyKey;
             return propertyKey;
@@ -60,9 +61,9 @@ namespace Jint
         internal static bool IsFunctionWithName<T>(this T node) where T : Node
         internal static bool IsFunctionWithName<T>(this T node) where T : Node
         {
         {
             var type = node.Type;
             var type = node.Type;
-            return type == Nodes.FunctionExpression 
-                   || type == Nodes.ArrowFunctionExpression 
-                   || type == Nodes.ArrowParameterPlaceHolder 
+            return type == Nodes.FunctionExpression
+                   || type == Nodes.ArrowFunctionExpression
+                   || type == Nodes.ArrowParameterPlaceHolder
                    || type == Nodes.ClassExpression;
                    || type == Nodes.ClassExpression;
         }
         }
 
 
@@ -89,7 +90,7 @@ namespace Jint
             }
             }
             return literal.Value as string ?? Convert.ToString(literal.Value, provider: null);
             return literal.Value as string ?? Convert.ToString(literal.Value, provider: null);
         }
         }
-        
+
         internal static void GetBoundNames(this VariableDeclaration variableDeclaration, List<string> target)
         internal static void GetBoundNames(this VariableDeclaration variableDeclaration, List<string> target)
         {
         {
             ref readonly var declarations = ref variableDeclaration.Declarations;
             ref readonly var declarations = ref variableDeclaration.Declarations;
@@ -106,7 +107,7 @@ namespace Jint
             {
             {
                 return;
                 return;
             }
             }
-            
+
             // try to get away without a loop
             // try to get away without a loop
             if (parameter is Identifier id)
             if (parameter is Identifier id)
             {
             {
@@ -176,7 +177,7 @@ namespace Jint
         }
         }
 
 
         internal static void BindingInitialization(
         internal static void BindingInitialization(
-            this Expression? expression, 
+            this Expression? expression,
             Engine engine,
             Engine engine,
             JsValue value,
             JsValue value,
             EnvironmentRecord env)
             EnvironmentRecord env)
@@ -203,11 +204,15 @@ namespace Jint
         {
         {
             var engine = obj.Engine;
             var engine = obj.Engine;
             var property = TypeConverter.ToPropertyKey(m.GetKey(engine));
             var property = TypeConverter.ToPropertyKey(m.GetKey(engine));
-            var prototype = functionPrototype ?? engine.Function.PrototypeObject;
-            var function = m.Value as IFunction ?? ExceptionHelper.ThrowSyntaxError<IFunction>(engine);
+            var prototype = functionPrototype ?? engine.Realm.Intrinsics.Function.PrototypeObject;
+            var function = m.Value as IFunction;
+            if (function is null)
+            {
+                ExceptionHelper.ThrowSyntaxError(engine.Realm);
+            }
             var functionDefinition = new JintFunctionDefinition(engine, function);
             var functionDefinition = new JintFunctionDefinition(engine, function);
             var functionThisMode = functionDefinition.Strict || engine._isStrict
             var functionThisMode = functionDefinition.Strict || engine._isStrict
-                ? FunctionThisMode.Strict 
+                ? FunctionThisMode.Strict
                 : FunctionThisMode.Global;
                 : FunctionThisMode.Global;
 
 
             var closure = new ScriptFunctionInstance(
             var closure = new ScriptFunctionInstance(

+ 16 - 9
Jint/JsValueExtensions.cs

@@ -45,14 +45,14 @@ namespace Jint
 
 
             return value.ToString();
             return value.ToString();
         }
         }
-        
+
         /// <summary>
         /// <summary>
         /// If the value is a Promise
         /// If the value is a Promise
         ///     1. If "Fulfilled" returns the value it was fulfilled with
         ///     1. If "Fulfilled" returns the value it was fulfilled with
         ///     2. If "Rejected" throws "PromiseRejectedException" with the rejection reason
         ///     2. If "Rejected" throws "PromiseRejectedException" with the rejection reason
         ///     3. If "Pending" throws "InvalidOperationException". Should be called only in "Settled" state
         ///     3. If "Pending" throws "InvalidOperationException". Should be called only in "Settled" state
         /// Else
         /// Else
-        ///     returns the value intact 
+        ///     returns the value intact
         /// </summary>
         /// </summary>
         /// <param name="value">value to unwrap</param>
         /// <param name="value">value to unwrap</param>
         /// <returns>inner value if Promise the value itself otherwise</returns>
         /// <returns>inner value if Promise the value itself otherwise</returns>
@@ -60,19 +60,26 @@ namespace Jint
         {
         {
             if (value is PromiseInstance promise)
             if (value is PromiseInstance promise)
             {
             {
-                return promise.State switch
+                switch (promise.State)
                 {
                 {
-                    PromiseState.Pending => ExceptionHelper.ThrowInvalidOperationException<JsValue>(
-                        "'UnwrapIfPromise' called before Promise was settled"),
-                    PromiseState.Fulfilled => promise.Value,
-                    PromiseState.Rejected => ExceptionHelper.ThrowPromiseRejectedException<JsValue>(promise.Value),
-                    _ => ExceptionHelper.ThrowArgumentOutOfRangeException<JsValue>()
-                };
+                    case PromiseState.Pending:
+                        ExceptionHelper.ThrowInvalidOperationException("'UnwrapIfPromise' called before Promise was settled");
+                        return null;
+                    case PromiseState.Fulfilled:
+                        return promise.Value;
+                    case PromiseState.Rejected:
+                        ExceptionHelper.ThrowPromiseRejectedException(promise.Value);
+                        return null;
+                    default:
+                        ExceptionHelper.ThrowArgumentOutOfRangeException();
+                        return null;
+                }
             }
             }
 
 
             return value;
             return value;
         }
         }
 
 
+        [MethodImpl(MethodImplOptions.NoInlining)]
         private static void ThrowWrongTypeException(JsValue value, string expectedType)
         private static void ThrowWrongTypeException(JsValue value, string expectedType)
         {
         {
             ExceptionHelper.ThrowArgumentException($"Expected {expectedType} but got {value._type}");
             ExceptionHelper.ThrowArgumentException($"Expected {expectedType} but got {value._type}");

+ 1 - 2
Jint/Key.cs

@@ -1,7 +1,6 @@
 using System;
 using System;
 using System.Diagnostics;
 using System.Diagnostics;
 using System.Runtime.CompilerServices;
 using System.Runtime.CompilerServices;
-using Jint.Runtime;
 
 
 namespace Jint
 namespace Jint
 {
 {
@@ -14,7 +13,7 @@ namespace Jint
     {
     {
         private Key(string name)
         private Key(string name)
         {
         {
-            Name = name ?? ExceptionHelper.ThrowArgumentException<string>("name cannot be null");
+            Name = name;
             HashCode = name.GetHashCode();
             HashCode = name.GetHashCode();
         }
         }
 
 

+ 12 - 10
Jint/Native/Argument/ArgumentsInstance.cs

@@ -32,9 +32,9 @@ namespace Jint.Native.Argument
         }
         }
 
 
         internal void Prepare(
         internal void Prepare(
-            FunctionInstance func, 
-            Key[] names, 
-            JsValue[] args, 
+            FunctionInstance func,
+            Key[] names,
+            JsValue[] args,
             DeclarativeEnvironmentRecord env,
             DeclarativeEnvironmentRecord env,
             bool hasRestParameter)
             bool hasRestParameter)
         {
         {
@@ -59,13 +59,13 @@ namespace Jint.Native.Argument
             {
             {
                 // unmapped
                 // unmapped
                 ParameterMap = null;
                 ParameterMap = null;
-                
+
                 for (uint i = 0; i < (uint) args.Length; i++)
                 for (uint i = 0; i < (uint) args.Length; i++)
                 {
                 {
                     var val = args[i];
                     var val = args[i];
-                    CreateDataProperty(JsNumber.Create(i), val);
+                    CreateDataProperty(JsString.Create(i), val);
                 }
                 }
-                
+
                 DefinePropertyOrThrow(CommonProperties.Callee, _engine._callerCalleeArgumentsThrowerNonConfigurable);
                 DefinePropertyOrThrow(CommonProperties.Callee, _engine._callerCalleeArgumentsThrowerNonConfigurable);
             }
             }
             else
             else
@@ -76,17 +76,17 @@ namespace Jint.Native.Argument
                     var mappedNamed = _mappedNamed.Value;
                     var mappedNamed = _mappedNamed.Value;
                     mappedNamed.Clear();
                     mappedNamed.Clear();
 
 
-                    map = Engine.Object.Construct(Arguments.Empty);
+                    map = Engine.Realm.Intrinsics.Object.Construct(Arguments.Empty);
 
 
                     for (uint i = 0; i < (uint) args.Length; i++)
                     for (uint i = 0; i < (uint) args.Length; i++)
                     {
                     {
-                        SetOwnProperty(i, new PropertyDescriptor(args[i], PropertyFlag.ConfigurableEnumerableWritable));
+                        SetOwnProperty(JsString.Create(i), new PropertyDescriptor(args[i], PropertyFlag.ConfigurableEnumerableWritable));
                         if (i < _names.Length)
                         if (i < _names.Length)
                         {
                         {
                             var name = _names[i];
                             var name = _names[i];
                             if (mappedNamed.Add(name))
                             if (mappedNamed.Add(name))
                             {
                             {
-                                map.SetOwnProperty(i, new ClrAccessDescriptor(_env, Engine, name));
+                                map.SetOwnProperty(JsString.Create(i), new ClrAccessDescriptor(_env, Engine, name));
                             }
                             }
                         }
                         }
                     }
                     }
@@ -98,12 +98,14 @@ namespace Jint.Native.Argument
                 DefinePropertyOrThrow(CommonProperties.Callee, new PropertyDescriptor(_func, PropertyFlag.NonEnumerable));
                 DefinePropertyOrThrow(CommonProperties.Callee, new PropertyDescriptor(_func, PropertyFlag.NonEnumerable));
             }
             }
 
 
-            var iteratorFunction = new ClrFunctionInstance(Engine, "iterator", _engine.Array.PrototypeObject.Values, 0, PropertyFlag.Configurable);
+            var iteratorFunction = new ClrFunctionInstance(Engine, "iterator", _engine.Realm.Intrinsics.Array.PrototypeObject.Values, 0, PropertyFlag.Configurable);
             DefinePropertyOrThrow(GlobalSymbolRegistry.Iterator, new PropertyDescriptor(iteratorFunction, PropertyFlag.Writable | PropertyFlag.Configurable));
             DefinePropertyOrThrow(GlobalSymbolRegistry.Iterator, new PropertyDescriptor(iteratorFunction, PropertyFlag.Writable | PropertyFlag.Configurable));
         }
         }
 
 
         public ObjectInstance ParameterMap { get; set; }
         public ObjectInstance ParameterMap { get; set; }
 
 
+        internal override bool IsIntegerIndexedArray => true;
+
         public override PropertyDescriptor GetOwnProperty(JsValue property)
         public override PropertyDescriptor GetOwnProperty(JsValue property)
         {
         {
             EnsureInitialized();
             EnsureInitialized();

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

@@ -16,29 +16,20 @@ namespace Jint.Native.Array
     {
     {
         private static readonly JsString _functionName = new JsString("Array");
         private static readonly JsString _functionName = new JsString("Array");
 
 
-        private ArrayConstructor(Engine engine) :  base(engine, _functionName)
+        internal ArrayConstructor(
+            Engine engine,
+            Realm realm,
+            FunctionPrototype functionPrototype,
+            ObjectPrototype objectPrototype)
+            : base(engine, realm, _functionName)
         {
         {
+            _prototype = functionPrototype;
+            PrototypeObject = new ArrayPrototype(engine, realm, this, objectPrototype);
+            _length = new PropertyDescriptor(1, PropertyFlag.Configurable);
+            _prototypeDescriptor = new PropertyDescriptor(PrototypeObject, PropertyFlag.AllForbidden);
         }
         }
 
 
-        public ArrayPrototype PrototypeObject { get; private set; }
-
-        public static ArrayConstructor CreateArrayConstructor(Engine engine)
-        {
-            var obj = new ArrayConstructor(engine)
-            {
-                _prototype = engine.Function.PrototypeObject
-            };
-
-            // The value of the [[Prototype]] internal property of the Array constructor is the Function prototype object
-            obj.PrototypeObject = ArrayPrototype.CreatePrototypeObject(engine, obj);
-
-            obj._length = new PropertyDescriptor(1, PropertyFlag.Configurable);
-
-            // The initial value of Array.prototype is the Array prototype object
-            obj._prototypeDescriptor = new PropertyDescriptor(obj.PrototypeObject, PropertyFlag.AllForbidden);
-
-            return obj;
-        }
+        public ArrayPrototype PrototypeObject { get; }
 
 
         protected override void Initialize()
         protected override void Initialize()
         {
         {
@@ -66,12 +57,12 @@ namespace Jint.Native.Array
 
 
             if (source.IsNullOrUndefined())
             if (source.IsNullOrUndefined())
             {
             {
-                ExceptionHelper.ThrowTypeError(_engine, "Cannot convert undefined or null to object");
+                ExceptionHelper.ThrowTypeError(_realm, "Cannot convert undefined or null to object");
             }
             }
 
 
             if (source is JsString jsString)
             if (source is JsString jsString)
             {
             {
-                var a = _engine.Array.ConstructFast((uint) jsString.Length);
+                var a = _realm.Intrinsics.Array.ConstructFast((uint) jsString.Length);
                 for (int i = 0; i < jsString._value.Length; i++)
                 for (int i = 0; i < jsString._value.Length; i++)
                 {
                 {
                     a.SetIndexValue((uint) i, JsString.Create(jsString._value[i]), updateLength: false);
                     a.SetIndexValue((uint) i, JsString.Create(jsString._value[i]), updateLength: false);
@@ -81,7 +72,7 @@ namespace Jint.Native.Array
 
 
             if (thisObj.IsNull() || !(source is ObjectInstance objectInstance))
             if (thisObj.IsNull() || !(source is ObjectInstance objectInstance))
             {
             {
-                return _engine.Array.ConstructFast(0);
+                return _realm.Intrinsics.Array.ConstructFast(0);
             }
             }
 
 
             if (objectInstance is IObjectWrapper wrapper && wrapper.Target is IEnumerable enumerable)
             if (objectInstance is IObjectWrapper wrapper && wrapper.Target is IEnumerable enumerable)
@@ -101,10 +92,10 @@ namespace Jint.Native.Array
             }
             }
             else
             else
             {
             {
-                instance = _engine.Array.ConstructFast(0);
+                instance = _realm.Intrinsics.Array.ConstructFast(0);
             }
             }
 
 
-            if (objectInstance.TryGetIterator(_engine, out var iterator))
+            if (objectInstance.TryGetIterator(_realm, out var iterator))
             {
             {
                 var protocol = new ArrayProtocol(_engine, thisArg, instance, iterator, callable);
                 var protocol = new ArrayProtocol(_engine, thisArg, instance, iterator, callable);
                 protocol.Execute();
                 protocol.Execute();
@@ -133,7 +124,7 @@ namespace Jint.Native.Array
             }
             }
             else
             else
             {
             {
-                a = _engine.Array.ConstructFast(length);
+                a = _realm.Intrinsics.Array.ConstructFast(length);
             }
             }
 
 
             var args = !ReferenceEquals(callable, null)
             var args = !ReferenceEquals(callable, null)
@@ -238,7 +229,7 @@ namespace Jint.Native.Array
             {
             {
                 // faster for real arrays
                 // faster for real arrays
                 ArrayInstance ai;
                 ArrayInstance ai;
-                a = ai = _engine.Array.Construct(len);
+                a = ai = _realm.Intrinsics.Array.Construct(len);
 
 
                 for (uint k = 0; k < arguments.Length; k++)
                 for (uint k = 0; k < arguments.Length; k++)
                 {
                 {
@@ -291,7 +282,9 @@ namespace Jint.Native.Array
                 newTarget = this;
                 newTarget = this;
             }
             }
 
 
-            var proto = GetPrototypeFromConstructor(newTarget, PrototypeObject);
+            var proto = GetPrototypeFromConstructor(
+                newTarget,
+                static intrinsics => intrinsics.Array.PrototypeObject);
 
 
             // check if we can figure out good size
             // check if we can figure out good size
             var capacity = arguments.Length > 0 ? (uint) arguments.Length : 0;
             var capacity = arguments.Length > 0 ? (uint) arguments.Length : 0;
@@ -374,7 +367,7 @@ namespace Jint.Native.Array
             {
             {
                 var jsItem = FromObject(Engine, item);
                 var jsItem = FromObject(Engine, item);
                 tempArray[0] = jsItem;
                 tempArray[0] = jsItem;
-                Engine.Array.PrototypeObject.Push(jsArray, tempArray);
+                _realm.Intrinsics.Array.PrototypeObject.Push(jsArray, tempArray);
             }
             }
 
 
             _engine._jsValueArrayPool.ReturnArray(tempArray);
             _engine._jsValueArrayPool.ReturnArray(tempArray);
@@ -423,11 +416,18 @@ namespace Jint.Native.Array
 
 
             var c = originalArray.Get(CommonProperties.Constructor);
             var c = originalArray.Get(CommonProperties.Constructor);
 
 
-            // If IsConstructor(C) is true, then
-            // Let thisRealm be the current Realm Record.
-            // Let realmC be ? GetFunctionRealm(C).
-            // If thisRealm and realmC are not the same Realm Record, then
-            // If SameValue(C, realmC.[[Intrinsics]].[[%Array%]]) is true, set C to undefined.
+            if (c.IsConstructor)
+            {
+                var thisRealm = _engine.ExecutionContext.Realm;
+                var realmC = GetFunctionRealm(c);
+                if (!ReferenceEquals(thisRealm, realmC))
+                {
+                    if (ReferenceEquals(c, realmC.Intrinsics.Array))
+                    {
+                        c = Undefined;
+                    }
+                }
+            }
 
 
             if (c is ObjectInstance oi)
             if (c is ObjectInstance oi)
             {
             {
@@ -445,7 +445,7 @@ namespace Jint.Native.Array
 
 
             if (!c.IsConstructor)
             if (!c.IsConstructor)
             {
             {
-                ExceptionHelper.ThrowTypeError(_engine);
+                ExceptionHelper.ThrowTypeError(_realm);
             }
             }
 
 
             return ((IConstructor) c).Construct(new JsValue[] { JsNumber.Create(length) }, c);
             return ((IConstructor) c).Construct(new JsValue[] { JsNumber.Create(length) }, c);
@@ -469,7 +469,7 @@ namespace Jint.Native.Array
         {
         {
             if (length < 0 || length > ArrayOperations.MaxArrayLength || ((long) length) != length)
             if (length < 0 || length > ArrayOperations.MaxArrayLength || ((long) length) != length)
             {
             {
-                ExceptionHelper.ThrowRangeError<object>(_engine, "Invalid array length");
+                ExceptionHelper.ThrowRangeError(_realm, "Invalid array length");
             }
             }
         }
         }
     }
     }

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

@@ -61,7 +61,7 @@ namespace Jint.Native.Array
         public override bool IsArrayLike => true;
         public override bool IsArrayLike => true;
 
 
         internal override bool HasOriginalIterator
         internal override bool HasOriginalIterator
-            => ReferenceEquals(Get(GlobalSymbolRegistry.Iterator), _engine.Array.PrototypeObject._originalIteratorFunction);
+            => ReferenceEquals(Get(GlobalSymbolRegistry.Iterator), _engine.Realm.Intrinsics.Array.PrototypeObject._originalIteratorFunction);
 
 
         public override bool DefineOwnProperty(JsValue property, PropertyDescriptor desc)
         public override bool DefineOwnProperty(JsValue property, PropertyDescriptor desc)
         {
         {
@@ -80,7 +80,7 @@ namespace Jint.Native.Array
                 uint newLen = TypeConverter.ToUint32(value);
                 uint newLen = TypeConverter.ToUint32(value);
                 if (newLen != TypeConverter.ToNumber(value))
                 if (newLen != TypeConverter.ToNumber(value))
                 {
                 {
-                    ExceptionHelper.ThrowRangeError(_engine);
+                    ExceptionHelper.ThrowRangeError(_engine.Realm);
                 }
                 }
 
 
                 newLenDesc.Value = newLen;
                 newLenDesc.Value = newLen;
@@ -230,7 +230,7 @@ namespace Jint.Native.Array
             {
             {
                 return 0;
                 return 0;
             }
             }
-            
+
             return (uint) ((JsNumber) _length._value)._value;
             return (uint) ((JsNumber) _length._value)._value;
         }
         }
 
 
@@ -353,7 +353,7 @@ namespace Jint.Native.Array
             var prop = GetOwnProperty(index);
             var prop = GetOwnProperty(index);
             if (prop == PropertyDescriptor.Undefined)
             if (prop == PropertyDescriptor.Undefined)
             {
             {
-                prop = Prototype?.GetProperty(index) ?? PropertyDescriptor.Undefined;
+                prop = Prototype?.GetProperty(JsString.Create(index)) ?? PropertyDescriptor.Undefined;
             }
             }
 
 
             return UnwrapJsValue(prop);
             return UnwrapJsValue(prop);
@@ -367,7 +367,7 @@ namespace Jint.Native.Array
             {
             {
                 return prop;
                 return prop;
             }
             }
-            return Prototype?.GetProperty(index) ?? PropertyDescriptor.Undefined;
+            return Prototype?.GetProperty(JsString.Create(index)) ?? PropertyDescriptor.Undefined;
         }
         }
 
 
         protected internal override void SetOwnProperty(JsValue property, PropertyDescriptor desc)
         protected internal override void SetOwnProperty(JsValue property, PropertyDescriptor desc)
@@ -538,7 +538,7 @@ namespace Jint.Native.Array
 
 
             if (!TryGetDescriptor(index, out var desc))
             if (!TryGetDescriptor(index, out var desc))
             {
             {
-                desc = GetProperty(index);
+                desc = GetProperty(JsString.Create(index));
             }
             }
 
 
             return desc.TryGetValue(this, out value);
             return desc.TryGetValue(this, out value);
@@ -548,7 +548,7 @@ namespace Jint.Native.Array
         {
         {
             if (!Delete(index))
             if (!Delete(index))
             {
             {
-                ExceptionHelper.ThrowTypeError(Engine);
+                ExceptionHelper.ThrowTypeError(_engine.Realm);
             }
             }
             return true;
             return true;
         }
         }
@@ -570,7 +570,7 @@ namespace Jint.Native.Array
 
 
             return false;
             return false;
         }
         }
-        
+
         internal bool DeleteAt(uint index)
         internal bool DeleteAt(uint index)
         {
         {
             var temp = _dense;
             var temp = _dense;
@@ -589,7 +589,7 @@ namespace Jint.Native.Array
 
 
             return false;
             return false;
         }
         }
-        
+
 
 
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         private bool TryGetDescriptor(uint index, out PropertyDescriptor descriptor)
         private bool TryGetDescriptor(uint index, out PropertyDescriptor descriptor)
@@ -721,7 +721,7 @@ namespace Jint.Native.Array
             {
             {
                 if (!Set(CommonProperties.Length, newLength, this))
                 if (!Set(CommonProperties.Length, newLength, this))
                 {
                 {
-                    ExceptionHelper.ThrowTypeError(_engine);
+                    ExceptionHelper.ThrowTypeError(_engine.Realm);
                 }
                 }
             }
             }
 
 
@@ -759,7 +759,7 @@ namespace Jint.Native.Array
             var len = GetLength();
             var len = GetLength();
 
 
             var callable = GetCallable(callbackfn);
             var callable = GetCallable(callbackfn);
-            var a = Engine.Array.ConstructFast(len);
+            var a = Engine.Realm.Intrinsics.Array.ConstructFast(len);
             var args = _engine._jsValueArrayPool.RentArray(3);
             var args = _engine._jsValueArrayPool.RentArray(3);
             args[2] = this;
             args[2] = this;
             for (uint k = 0; k < len; k++)
             for (uint k = 0; k < len; k++)
@@ -845,7 +845,7 @@ namespace Jint.Native.Array
         internal ArrayInstance ToArray(Engine engine)
         internal ArrayInstance ToArray(Engine engine)
         {
         {
             var length = GetLength();
             var length = GetLength();
-            var array = _engine.Array.ConstructFast(length);
+            var array = _engine.Realm.Intrinsics.Array.ConstructFast(length);
             for (uint i = 0; i < length; i++)
             for (uint i = 0; i < length; i++)
             {
             {
                 if (TryGetValue(i, out var kValue))
                 if (TryGetValue(i, out var kValue))
@@ -897,7 +897,7 @@ namespace Jint.Native.Array
                 }
                 }
             }
             }
         }
         }
-        
+
         public override string ToString()
         public override string ToString()
         {
         {
             // debugger can make things hard when evaluates computed values
             // debugger can make things hard when evaluates computed values

+ 6 - 6
Jint/Native/Array/ArrayOperations.cs

@@ -22,9 +22,9 @@ namespace Jint.Native.Array
             return new ObjectInstanceOperations(instance);
             return new ObjectInstanceOperations(instance);
         }
         }
 
 
-        public static ArrayOperations For(Engine engine, JsValue thisObj)
+        public static ArrayOperations For(Realm realm, JsValue thisObj)
         {
         {
-            var instance = TypeConverter.ToObject(engine, thisObj);
+            var instance = TypeConverter.ToObject(realm, thisObj);
             return For(instance);
             return For(instance);
         }
         }
 
 
@@ -51,7 +51,7 @@ namespace Jint.Native.Array
                 var jsValue = Get(i);
                 var jsValue = Get(i);
                 if ((jsValue.Type & elementTypes) == 0)
                 if ((jsValue.Type & elementTypes) == 0)
                 {
                 {
-                    ExceptionHelper.ThrowTypeErrorNoEngine<object>("invalid type");
+                    ExceptionHelper.ThrowTypeErrorNoEngine("invalid type");
                 }
                 }
 
 
                 jsValues[i] = jsValue;
                 jsValues[i] = jsValue;
@@ -91,9 +91,9 @@ namespace Jint.Native.Array
                 Reset();
                 Reset();
             }
             }
 
 
-            public JsValue Current 
+            public JsValue Current
             {
             {
-                get 
+                get
                 {
                 {
                     if (!_initialized)
                     if (!_initialized)
                     {
                     {
@@ -301,7 +301,7 @@ namespace Jint.Native.Array
                     var jsValue = _target.UnwrapJsValue(prop);
                     var jsValue = _target.UnwrapJsValue(prop);
                     if ((jsValue.Type & elementTypes) == 0)
                     if ((jsValue.Type & elementTypes) == 0)
                     {
                     {
-                        ExceptionHelper.ThrowTypeErrorNoEngine<object>("invalid type");
+                        ExceptionHelper.ThrowTypeErrorNoEngine("invalid type");
                     }
                     }
 
 
                     jsValues[i] = jsValue;
                     jsValues[i] = jsValue;

+ 102 - 96
Jint/Native/Array/ArrayPrototype.cs

@@ -20,22 +20,20 @@ namespace Jint.Native.Array
     /// </summary>
     /// </summary>
     public sealed class ArrayPrototype : ArrayInstance
     public sealed class ArrayPrototype : ArrayInstance
     {
     {
-        private ArrayConstructor _arrayConstructor;
+        private readonly Realm _realm;
+        private readonly ArrayConstructor _constructor;
         internal ClrFunctionInstance _originalIteratorFunction;
         internal ClrFunctionInstance _originalIteratorFunction;
 
 
-        private ArrayPrototype(Engine engine) : base(engine)
+        internal ArrayPrototype(
+            Engine engine,
+            Realm realm,
+            ArrayConstructor arrayConstructor,
+            ObjectPrototype objectPrototype) : base(engine)
         {
         {
-        }
-
-        public static ArrayPrototype CreatePrototypeObject(Engine engine, ArrayConstructor arrayConstructor)
-        {
-            var obj = new ArrayPrototype(engine)
-            {
-                _prototype = engine.Object.PrototypeObject,
-                _length = new PropertyDescriptor(JsNumber.PositiveZero, PropertyFlag.Writable),
-                _arrayConstructor = arrayConstructor,
-            };
-            return obj;
+            _prototype = objectPrototype;
+            _length = new PropertyDescriptor(JsNumber.PositiveZero, PropertyFlag.Writable);
+            _realm = realm;
+            _constructor = arrayConstructor;
         }
         }
 
 
         protected override void Initialize()
         protected override void Initialize()
@@ -55,16 +53,16 @@ namespace Jint.Native.Array
             unscopables.SetDataProperty("includes", JsBoolean.True);
             unscopables.SetDataProperty("includes", JsBoolean.True);
             unscopables.SetDataProperty("keys", JsBoolean.True);
             unscopables.SetDataProperty("keys", JsBoolean.True);
             unscopables.SetDataProperty("values", JsBoolean.True);
             unscopables.SetDataProperty("values", JsBoolean.True);
-            
+
             const PropertyFlag propertyFlags = PropertyFlag.Writable | PropertyFlag.Configurable;
             const PropertyFlag propertyFlags = PropertyFlag.Writable | PropertyFlag.Configurable;
             var properties = new PropertyDictionary(32, checkExistingKeys: false)
             var properties = new PropertyDictionary(32, checkExistingKeys: false)
             {
             {
-                ["constructor"] = new PropertyDescriptor(_arrayConstructor, PropertyFlag.NonEnumerable),
+                ["constructor"] = new PropertyDescriptor(_constructor, PropertyFlag.NonEnumerable),
                 ["toString"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "toString", ToString, 0, PropertyFlag.Configurable), propertyFlags),
                 ["toString"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "toString", ToString, 0, PropertyFlag.Configurable), propertyFlags),
                 ["toLocaleString"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "toLocaleString", ToLocaleString, 0, PropertyFlag.Configurable), propertyFlags),
                 ["toLocaleString"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "toLocaleString", ToLocaleString, 0, PropertyFlag.Configurable), propertyFlags),
                 ["concat"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "concat", Concat, 1, PropertyFlag.Configurable), propertyFlags),
                 ["concat"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "concat", Concat, 1, PropertyFlag.Configurable), propertyFlags),
                 ["copyWithin"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "copyWithin", CopyWithin, 2, PropertyFlag.Configurable), propertyFlags),
                 ["copyWithin"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "copyWithin", CopyWithin, 2, PropertyFlag.Configurable), propertyFlags),
-                ["entries"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "entries", Iterator, 0, PropertyFlag.Configurable), propertyFlags),
+                ["entries"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "entries", Entries, 0, PropertyFlag.Configurable), propertyFlags),
                 ["fill"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "fill", Fill, 1, PropertyFlag.Configurable), propertyFlags),
                 ["fill"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "fill", Fill, 1, PropertyFlag.Configurable), propertyFlags),
                 ["join"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "join", Join, 1, PropertyFlag.Configurable), propertyFlags),
                 ["join"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "join", Join, 1, PropertyFlag.Configurable), propertyFlags),
                 ["pop"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "pop", Pop, 0, PropertyFlag.Configurable), propertyFlags),
                 ["pop"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "pop", Pop, 0, PropertyFlag.Configurable), propertyFlags),
@@ -102,42 +100,45 @@ namespace Jint.Native.Array
             };
             };
             SetSymbols(symbols);
             SetSymbols(symbols);
         }
         }
-        
+
         private ObjectInstance Keys(JsValue thisObj, JsValue[] arguments)
         private ObjectInstance Keys(JsValue thisObj, JsValue[] arguments)
         {
         {
             if (thisObj is ObjectInstance oi && oi.IsArrayLike)
             if (thisObj is ObjectInstance oi && oi.IsArrayLike)
             {
             {
-                return _engine.Iterator.ConstructArrayLikeKeyIterator(oi);
+                return _realm.Intrinsics.Iterator.ConstructArrayLikeKeyIterator(oi);
             }
             }
 
 
-            return ExceptionHelper.ThrowTypeError<ObjectInstance>(_engine, "cannot construct iterator");
+            ExceptionHelper.ThrowTypeError(_realm, "cannot construct iterator");
+            return null;
         }
         }
 
 
         internal ObjectInstance Values(JsValue thisObj, JsValue[] arguments)
         internal ObjectInstance Values(JsValue thisObj, JsValue[] arguments)
         {
         {
             if (thisObj is ObjectInstance oi && oi.IsArrayLike)
             if (thisObj is ObjectInstance oi && oi.IsArrayLike)
             {
             {
-                return _engine.Iterator.ConstructArrayLikeValueIterator(oi);
+                return _realm.Intrinsics.Iterator.ConstructArrayLikeValueIterator(oi);
             }
             }
 
 
-            return ExceptionHelper.ThrowTypeError<ObjectInstance>(_engine, "cannot construct iterator");
+            ExceptionHelper.ThrowTypeError(_realm, "cannot construct iterator");
+            return null;
         }
         }
 
 
-        private ObjectInstance Iterator(JsValue thisObj, JsValue[] arguments)
+        private ObjectInstance Entries(JsValue thisObj, JsValue[] arguments)
         {
         {
             if (thisObj is ObjectInstance oi)
             if (thisObj is ObjectInstance oi)
             {
             {
-                return _engine.Iterator.Construct(oi);
+                return _realm.Intrinsics.Iterator.Construct(oi, intrinsics => intrinsics.Iterator.ArrayIteratorPrototypeObject);
             }
             }
 
 
-            return ExceptionHelper.ThrowTypeError<ObjectInstance>(_engine, "cannot construct iterator");
+            ExceptionHelper.ThrowTypeError(_realm, "cannot construct iterator");
+            return null;
         }
         }
 
 
         private JsValue Fill(JsValue thisObj, JsValue[] arguments)
         private JsValue Fill(JsValue thisObj, JsValue[] arguments)
         {
         {
             if (thisObj.IsNullOrUndefined())
             if (thisObj.IsNullOrUndefined())
             {
             {
-                ExceptionHelper.ThrowTypeError(_engine, "Cannot convert undefined or null to object");
+                ExceptionHelper.ThrowTypeError(_realm, "Cannot convert undefined or null to object");
             }
             }
 
 
             var operations = ArrayOperations.For(thisObj as ObjectInstance);
             var operations = ArrayOperations.For(thisObj as ObjectInstance);
@@ -183,7 +184,7 @@ namespace Jint.Native.Array
             // Steps 1-2.
             // Steps 1-2.
             if (thisObj.IsNullOrUndefined())
             if (thisObj.IsNullOrUndefined())
             {
             {
-                return ExceptionHelper.ThrowTypeError<JsValue>(_engine, "this is null or not defined");
+                ExceptionHelper.ThrowTypeError(_realm, "this is null or not defined");
             }
             }
 
 
             JsValue target = arguments.At(0);
             JsValue target = arguments.At(0);
@@ -216,7 +217,7 @@ namespace Jint.Native.Array
 
 
             var direction = 1;
             var direction = 1;
 
 
-            if (from < to && to < from + count) 
+            if (from < to && to < from + count)
             {
             {
                 direction = -1;
                 direction = -1;
                 from += (uint) count - 1;
                 from += (uint) count - 1;
@@ -262,15 +263,15 @@ namespace Jint.Native.Array
 
 
         private JsValue LastIndexOf(JsValue thisObj, JsValue[] arguments)
         private JsValue LastIndexOf(JsValue thisObj, JsValue[] arguments)
         {
         {
-            var o = ArrayOperations.For(Engine, thisObj);
+            var o = ArrayOperations.For(_realm, thisObj);
             var len = o.GetLongLength();
             var len = o.GetLongLength();
             if (len == 0)
             if (len == 0)
             {
             {
                 return -1;
                 return -1;
             }
             }
 
 
-            var n = arguments.Length > 1 
-                ? TypeConverter.ToInteger(arguments[1]) 
+            var n = arguments.Length > 1
+                ? TypeConverter.ToInteger(arguments[1])
                 : len - 1;
                 : len - 1;
             double k;
             double k;
             if (n >= 0)
             if (n >= 0)
@@ -316,14 +317,14 @@ namespace Jint.Native.Array
             var callbackfn = arguments.At(0);
             var callbackfn = arguments.At(0);
             var initialValue = arguments.At(1);
             var initialValue = arguments.At(1);
 
 
-            var o = ArrayOperations.For(Engine, thisObj);
+            var o = ArrayOperations.For(_realm, thisObj);
             var len = o.GetLength();
             var len = o.GetLength();
 
 
             var callable = GetCallable(callbackfn);
             var callable = GetCallable(callbackfn);
 
 
             if (len == 0 && arguments.Length < 2)
             if (len == 0 && arguments.Length < 2)
             {
             {
-                ExceptionHelper.ThrowTypeError(Engine);
+                ExceptionHelper.ThrowTypeError(_realm);
             }
             }
 
 
             var k = 0;
             var k = 0;
@@ -347,7 +348,7 @@ namespace Jint.Native.Array
 
 
                 if (kPresent == false)
                 if (kPresent == false)
                 {
                 {
-                    ExceptionHelper.ThrowTypeError(Engine);
+                    ExceptionHelper.ThrowTypeError(_realm);
                 }
                 }
             }
             }
 
 
@@ -375,12 +376,12 @@ namespace Jint.Native.Array
             var callbackfn = arguments.At(0);
             var callbackfn = arguments.At(0);
             var thisArg = arguments.At(1);
             var thisArg = arguments.At(1);
 
 
-            var o = ArrayOperations.For(Engine, thisObj);
+            var o = ArrayOperations.For(_realm, thisObj);
             var len = o.GetLength();
             var len = o.GetLength();
 
 
             var callable = GetCallable(callbackfn);
             var callable = GetCallable(callbackfn);
 
 
-            var a = Engine.Array.ArraySpeciesCreate(TypeConverter.ToObject(_engine, thisObj), 0);
+            var a = _realm.Intrinsics.Array.ArraySpeciesCreate(TypeConverter.ToObject(_realm, thisObj), 0);
             var operations = ArrayOperations.For(a);
             var operations = ArrayOperations.For(a);
 
 
             uint to = 0;
             uint to = 0;
@@ -414,19 +415,19 @@ namespace Jint.Native.Array
                 return arrayInstance.Map(arguments);
                 return arrayInstance.Map(arguments);
             }
             }
 
 
-            var o = ArrayOperations.For(Engine, thisObj);
+            var o = ArrayOperations.For(_realm, thisObj);
             var len = o.GetLongLength();
             var len = o.GetLongLength();
 
 
             if (len > ArrayOperations.MaxArrayLength)
             if (len > ArrayOperations.MaxArrayLength)
             {
             {
-                ExceptionHelper.ThrowRangeError(_engine, "Invalid array length");;
+                ExceptionHelper.ThrowRangeError(_realm, "Invalid array length");;
             }
             }
 
 
             var callbackfn = arguments.At(0);
             var callbackfn = arguments.At(0);
             var thisArg = arguments.At(1);
             var thisArg = arguments.At(1);
             var callable = GetCallable(callbackfn);
             var callable = GetCallable(callbackfn);
 
 
-            var a = ArrayOperations.For(Engine.Array.ArraySpeciesCreate(TypeConverter.ToObject(_engine, thisObj), (uint) len));
+            var a = ArrayOperations.For(_realm.Intrinsics.Array.ArraySpeciesCreate(TypeConverter.ToObject(_realm, thisObj), (uint) len));
             var args = _engine._jsValueArrayPool.RentArray(3);
             var args = _engine._jsValueArrayPool.RentArray(3);
             args[2] = o.Target;
             args[2] = o.Target;
             for (uint k = 0; k < len; k++)
             for (uint k = 0; k < len; k++)
@@ -448,7 +449,7 @@ namespace Jint.Native.Array
         /// </summary>
         /// </summary>
         private JsValue Flat(JsValue thisObj, JsValue[] arguments)
         private JsValue Flat(JsValue thisObj, JsValue[] arguments)
         {
         {
-            var O = TypeConverter.ToObject(_engine, thisObj);
+            var O = TypeConverter.ToObject(_realm, thisObj);
             var operations = ArrayOperations.For(O);
             var operations = ArrayOperations.For(O);
             var sourceLen = operations.GetLength();
             var sourceLen = operations.GetLength();
             double depthNum = 1;
             double depthNum = 1;
@@ -463,28 +464,28 @@ namespace Jint.Native.Array
                 depthNum = 0;
                 depthNum = 0;
             }
             }
 
 
-            var A = _engine.Array.ArraySpeciesCreate(O, 0);
+            var A = _realm.Intrinsics.Array.ArraySpeciesCreate(O, 0);
             FlattenIntoArray(A, O, sourceLen, 0, depthNum);
             FlattenIntoArray(A, O, sourceLen, 0, depthNum);
             return A;
             return A;
         }
         }
-        
+
         /// <summary>
         /// <summary>
         /// https://tc39.es/ecma262/#sec-array.prototype.flatmap
         /// https://tc39.es/ecma262/#sec-array.prototype.flatmap
         /// </summary>
         /// </summary>
         private JsValue FlatMap(JsValue thisObj, JsValue[] arguments)
         private JsValue FlatMap(JsValue thisObj, JsValue[] arguments)
         {
         {
-            var O = TypeConverter.ToObject(_engine, thisObj);
+            var O = TypeConverter.ToObject(_realm, thisObj);
             var mapperFunction = arguments.At(0);
             var mapperFunction = arguments.At(0);
             var thisArg = arguments.At(1);
             var thisArg = arguments.At(1);
-            
+
             var sourceLen = O.Length;
             var sourceLen = O.Length;
 
 
             if (!mapperFunction.IsCallable)
             if (!mapperFunction.IsCallable)
             {
             {
-                ExceptionHelper.ThrowTypeError(_engine, "flatMap mapper function is not callable");
+                ExceptionHelper.ThrowTypeError(_realm, "flatMap mapper function is not callable");
             }
             }
-            
-            var A = _engine.Array.ArraySpeciesCreate(O, 0);
+
+            var A = _realm.Intrinsics.Array.ArraySpeciesCreate(O, 0);
             FlattenIntoArray(A, O, sourceLen, 0, 1, (ICallable) mapperFunction, thisArg);
             FlattenIntoArray(A, O, sourceLen, 0, 1, (ICallable) mapperFunction, thisArg);
             return A;
             return A;
         }
         }
@@ -496,8 +497,8 @@ namespace Jint.Native.Array
             ObjectInstance target,
             ObjectInstance target,
             ObjectInstance source,
             ObjectInstance source,
             uint sourceLen,
             uint sourceLen,
-            long start, 
-            double depth, 
+            long start,
+            double depth,
             ICallable mapperFunction = null,
             ICallable mapperFunction = null,
             JsValue thisArg = null)
             JsValue thisArg = null)
         {
         {
@@ -545,7 +546,7 @@ namespace Jint.Native.Array
                     {
                     {
                         if (targetIndex >= NumberConstructor.MaxSafeInteger)
                         if (targetIndex >= NumberConstructor.MaxSafeInteger)
                         {
                         {
-                            ExceptionHelper.ThrowTypeError(_engine);
+                            ExceptionHelper.ThrowTypeError(_realm);
                         }
                         }
 
 
                         target.CreateDataPropertyOrThrow(targetIndex, element);
                         target.CreateDataPropertyOrThrow(targetIndex, element);
@@ -569,7 +570,7 @@ namespace Jint.Native.Array
             var callbackfn = arguments.At(0);
             var callbackfn = arguments.At(0);
             var thisArg = arguments.At(1);
             var thisArg = arguments.At(1);
 
 
-            var o = ArrayOperations.For(Engine, thisObj);
+            var o = ArrayOperations.For(_realm, thisObj);
             var len = o.GetLength();
             var len = o.GetLength();
 
 
             var callable = GetCallable(callbackfn);
             var callable = GetCallable(callbackfn);
@@ -592,7 +593,7 @@ namespace Jint.Native.Array
 
 
         private JsValue Includes(JsValue thisObj, JsValue[] arguments)
         private JsValue Includes(JsValue thisObj, JsValue[] arguments)
         {
         {
-            var o = ArrayOperations.For(Engine, thisObj);
+            var o = ArrayOperations.For(_realm, thisObj);
             var len = o.GetLongLength();
             var len = o.GetLongLength();
 
 
             if (len == 0)
             if (len == 0)
@@ -609,7 +610,7 @@ namespace Jint.Native.Array
                 : n;
                 : n;
 
 
             var k = (ulong) System.Math.Max(
             var k = (ulong) System.Math.Max(
-                n >= 0 
+                n >= 0
                     ? n
                     ? n
                     : len - System.Math.Abs(n), 0);
                     : len - System.Math.Abs(n), 0);
 
 
@@ -632,13 +633,13 @@ namespace Jint.Native.Array
 
 
         private JsValue Some(JsValue thisObj, JsValue[] arguments)
         private JsValue Some(JsValue thisObj, JsValue[] arguments)
         {
         {
-            var target = TypeConverter.ToObject(Engine, thisObj);
+            var target = TypeConverter.ToObject(_realm, thisObj);
             return target.FindWithCallback(arguments, out _, out _, false);
             return target.FindWithCallback(arguments, out _, out _, false);
         }
         }
 
 
         private JsValue Every(JsValue thisObj, JsValue[] arguments)
         private JsValue Every(JsValue thisObj, JsValue[] arguments)
         {
         {
-            var o = ArrayOperations.For(Engine, thisObj);
+            var o = ArrayOperations.For(_realm, thisObj);
             ulong len = o.GetLongLength();
             ulong len = o.GetLongLength();
 
 
             if (len == 0)
             if (len == 0)
@@ -672,7 +673,7 @@ namespace Jint.Native.Array
 
 
         private JsValue IndexOf(JsValue thisObj, JsValue[] arguments)
         private JsValue IndexOf(JsValue thisObj, JsValue[] arguments)
         {
         {
-            var o = ArrayOperations.For(Engine, thisObj);
+            var o = ArrayOperations.For(_realm, thisObj);
             var len = o.GetLongLength();
             var len = o.GetLongLength();
             if (len == 0)
             if (len == 0)
             {
             {
@@ -680,7 +681,7 @@ namespace Jint.Native.Array
             }
             }
 
 
             var startIndex = arguments.Length > 1
             var startIndex = arguments.Length > 1
-                ? TypeConverter.ToNumber(arguments[1]) 
+                ? TypeConverter.ToNumber(arguments[1])
                 : 0;
                 : 0;
 
 
             if (startIndex > uint.MaxValue)
             if (startIndex > uint.MaxValue)
@@ -736,14 +737,14 @@ namespace Jint.Native.Array
 
 
         private JsValue Find(JsValue thisObj, JsValue[] arguments)
         private JsValue Find(JsValue thisObj, JsValue[] arguments)
         {
         {
-            var target = TypeConverter.ToObject(Engine, thisObj);
+            var target = TypeConverter.ToObject(_realm, thisObj);
             target.FindWithCallback(arguments, out _, out var value, true);
             target.FindWithCallback(arguments, out _, out var value, true);
             return value;
             return value;
         }
         }
 
 
         private JsValue FindIndex(JsValue thisObj, JsValue[] arguments)
         private JsValue FindIndex(JsValue thisObj, JsValue[] arguments)
         {
         {
-            var target = TypeConverter.ToObject(Engine, thisObj);
+            var target = TypeConverter.ToObject(_realm, thisObj);
             if (target.FindWithCallback(arguments, out var index, out _, true))
             if (target.FindWithCallback(arguments, out var index, out _, true))
             {
             {
                 return index;
                 return index;
@@ -756,7 +757,7 @@ namespace Jint.Native.Array
             var start = arguments.At(0);
             var start = arguments.At(0);
             var deleteCount = arguments.At(1);
             var deleteCount = arguments.At(1);
 
 
-            var o = ArrayOperations.For(Engine, thisObj);
+            var o = ArrayOperations.For(_realm, thisObj);
             var len = o.GetLongLength();
             var len = o.GetLongLength();
             var relativeStart = TypeConverter.ToInteger(start);
             var relativeStart = TypeConverter.ToInteger(start);
 
 
@@ -799,10 +800,10 @@ namespace Jint.Native.Array
 
 
             if (len + insertCount - actualDeleteCount > ArrayOperations.MaxArrayLikeLength)
             if (len + insertCount - actualDeleteCount > ArrayOperations.MaxArrayLikeLength)
             {
             {
-                return ExceptionHelper.ThrowTypeError<JsValue>(_engine, "Invalid array length");
+                ExceptionHelper.ThrowTypeError(_realm, "Invalid array length");
             }
             }
 
 
-            var instance = Engine.Array.ArraySpeciesCreate(TypeConverter.ToObject(_engine, thisObj), actualDeleteCount);
+            var instance = _realm.Intrinsics.Array.ArraySpeciesCreate(TypeConverter.ToObject(_realm, thisObj), actualDeleteCount);
             var a = ArrayOperations.For(instance);
             var a = ArrayOperations.For(instance);
             for (uint k = 0; k < actualDeleteCount; k++)
             for (uint k = 0; k < actualDeleteCount; k++)
             {
             {
@@ -869,13 +870,13 @@ namespace Jint.Native.Array
 
 
         private JsValue Unshift(JsValue thisObj, JsValue[] arguments)
         private JsValue Unshift(JsValue thisObj, JsValue[] arguments)
         {
         {
-            var o = ArrayOperations.For(Engine, thisObj);
+            var o = ArrayOperations.For(_realm, thisObj);
             var len = o.GetLongLength();
             var len = o.GetLongLength();
             var argCount = (uint) arguments.Length;
             var argCount = (uint) arguments.Length;
 
 
             if (len + argCount > ArrayOperations.MaxArrayLikeLength)
             if (len + argCount > ArrayOperations.MaxArrayLikeLength)
             {
             {
-                return ExceptionHelper.ThrowTypeError<JsValue>(_engine, "Invalid array length");
+                ExceptionHelper.ThrowTypeError(_realm, "Invalid array length");
             }
             }
 
 
             o.EnsureCapacity(len + argCount);
             o.EnsureCapacity(len + argCount);
@@ -907,7 +908,7 @@ namespace Jint.Native.Array
         {
         {
             if (!thisObj.IsObject())
             if (!thisObj.IsObject())
             {
             {
-                ExceptionHelper.ThrowTypeError(_engine, "Array.prorotype.sort can only be applied on objects");
+                ExceptionHelper.ThrowTypeError(_realm, "Array.prorotype.sort can only be applied on objects");
             }
             }
 
 
             var obj = ArrayOperations.For(thisObj.AsObject());
             var obj = ArrayOperations.For(thisObj.AsObject());
@@ -918,7 +919,7 @@ namespace Jint.Native.Array
             {
             {
                 if (compareArg.IsNull() || !(compareArg is ICallable))
                 if (compareArg.IsNull() || !(compareArg is ICallable))
                 {
                 {
-                    ExceptionHelper.ThrowTypeError(_engine, "The comparison function must be either a function or undefined");
+                    ExceptionHelper.ThrowTypeError(_realm, "The comparison function must be either a function or undefined");
                 }
                 }
 
 
                 compareFn = (ICallable) compareArg;
                 compareFn = (ICallable) compareArg;
@@ -928,7 +929,7 @@ namespace Jint.Native.Array
             if (len <= 1)
             if (len <= 1)
             {
             {
                 return obj.Target;
                 return obj.Target;
-            }            
+            }
 
 
             // don't eat inner exceptions
             // don't eat inner exceptions
             try
             try
@@ -960,7 +961,7 @@ namespace Jint.Native.Array
             var start = arguments.At(0);
             var start = arguments.At(0);
             var end = arguments.At(1);
             var end = arguments.At(1);
 
 
-            var o = ArrayOperations.For(Engine, thisObj);
+            var o = ArrayOperations.For(_realm, thisObj);
             var len = o.GetLongLength();
             var len = o.GetLongLength();
 
 
             var relativeStart = TypeConverter.ToInteger(start);
             var relativeStart = TypeConverter.ToInteger(start);
@@ -994,11 +995,11 @@ namespace Jint.Native.Array
 
 
             if (k < final && final - k > ArrayOperations.MaxArrayLength)
             if (k < final && final - k > ArrayOperations.MaxArrayLength)
             {
             {
-                ExceptionHelper.ThrowRangeError(_engine, "Invalid array length");;
+                ExceptionHelper.ThrowRangeError(_realm, "Invalid array length");;
             }
             }
 
 
             var length = (uint) System.Math.Max(0, (long) final - (long) k);
             var length = (uint) System.Math.Max(0, (long) final - (long) k);
-            var a = Engine.Array.ArraySpeciesCreate(TypeConverter.ToObject(_engine, thisObj), length);
+            var a = _realm.Intrinsics.Array.ArraySpeciesCreate(TypeConverter.ToObject(_realm, thisObj), length);
             if (thisObj is ArrayInstance ai && a is ArrayInstance a2)
             if (thisObj is ArrayInstance ai && a is ArrayInstance a2)
             {
             {
                 a2.CopyValues(ai, (uint) k, 0, length);
                 a2.CopyValues(ai, (uint) k, 0, length);
@@ -1022,7 +1023,7 @@ namespace Jint.Native.Array
 
 
         private JsValue Shift(JsValue thisObj, JsValue[] arg2)
         private JsValue Shift(JsValue thisObj, JsValue[] arg2)
         {
         {
-            var o = ArrayOperations.For(Engine, thisObj);
+            var o = ArrayOperations.For(_realm, thisObj);
             var len = o.GetLength();
             var len = o.GetLength();
             if (len == 0)
             if (len == 0)
             {
             {
@@ -1052,7 +1053,7 @@ namespace Jint.Native.Array
 
 
         private JsValue Reverse(JsValue thisObj, JsValue[] arguments)
         private JsValue Reverse(JsValue thisObj, JsValue[] arguments)
         {
         {
-            var o = ArrayOperations.For(Engine, thisObj);
+            var o = ArrayOperations.For(_realm, thisObj);
             var len = o.GetLongLength();
             var len = o.GetLongLength();
             var middle = (ulong) System.Math.Floor(len / 2.0);
             var middle = (ulong) System.Math.Floor(len / 2.0);
             uint lower = 0;
             uint lower = 0;
@@ -1065,7 +1066,7 @@ namespace Jint.Native.Array
 
 
                 var upperExists = o.HasProperty(upper);
                 var upperExists = o.HasProperty(upper);
                 var upperValue = upperExists ? o.Get(upper) : null;
                 var upperValue = upperExists ? o.Get(upper) : null;
-                
+
                 if (lowerExists && upperExists)
                 if (lowerExists && upperExists)
                 {
                 {
                     o.Set(lower, upperValue, updateLength: true, throwOnError: true);
                     o.Set(lower, upperValue, updateLength: true, throwOnError: true);
@@ -1093,7 +1094,7 @@ namespace Jint.Native.Array
         private JsValue Join(JsValue thisObj, JsValue[] arguments)
         private JsValue Join(JsValue thisObj, JsValue[] arguments)
         {
         {
             var separator = arguments.At(0);
             var separator = arguments.At(0);
-            var o = ArrayOperations.For(Engine, thisObj);
+            var o = ArrayOperations.For(_realm, thisObj);
             var len = o.GetLength();
             var len = o.GetLength();
             if (separator.IsUndefined())
             if (separator.IsUndefined())
             {
             {
@@ -1136,7 +1137,7 @@ namespace Jint.Native.Array
 
 
         private JsValue ToLocaleString(JsValue thisObj, JsValue[] arguments)
         private JsValue ToLocaleString(JsValue thisObj, JsValue[] arguments)
         {
         {
-            var array = ArrayOperations.For(Engine, thisObj);
+            var array = ArrayOperations.For(_realm, thisObj);
             var len = array.GetLength();
             var len = array.GetLength();
             const string separator = ",";
             const string separator = ",";
             if (len == 0)
             if (len == 0)
@@ -1151,8 +1152,12 @@ namespace Jint.Native.Array
             }
             }
             else
             else
             {
             {
-                var elementObj = TypeConverter.ToObject(Engine, firstElement);
-                var func = elementObj.Get("toLocaleString", elementObj) as ICallable ?? ExceptionHelper.ThrowTypeError<ICallable>(_engine);
+                var elementObj = TypeConverter.ToObject(_realm, firstElement);
+                var func = elementObj.Get("toLocaleString", elementObj) as ICallable;
+                if (func is null)
+                {
+                    ExceptionHelper.ThrowTypeError(_realm);
+                }
 
 
                 r = func.Call(elementObj, Arguments.Empty);
                 r = func.Call(elementObj, Arguments.Empty);
             }
             }
@@ -1166,8 +1171,12 @@ namespace Jint.Native.Array
                 }
                 }
                 else
                 else
                 {
                 {
-                    var elementObj = TypeConverter.ToObject(Engine, nextElement);
-                    var func = elementObj.Get("toLocaleString", elementObj) as ICallable ?? ExceptionHelper.ThrowTypeError<ICallable>(_engine);
+                    var elementObj = TypeConverter.ToObject(_realm, nextElement);
+                    var func = elementObj.Get("toLocaleString", elementObj) as ICallable;
+                    if (func is null)
+                    {
+                        ExceptionHelper.ThrowTypeError(_realm);
+                    }
                     r = func.Call(elementObj, Arguments.Empty);
                     r = func.Call(elementObj, Arguments.Empty);
                 }
                 }
 
 
@@ -1179,7 +1188,7 @@ namespace Jint.Native.Array
 
 
         private JsValue Concat(JsValue thisObj, JsValue[] arguments)
         private JsValue Concat(JsValue thisObj, JsValue[] arguments)
         {
         {
-            var o = TypeConverter.ToObject(Engine, thisObj);
+            var o = TypeConverter.ToObject(_realm, thisObj);
             var items = new List<JsValue>(arguments.Length + 1) {o};
             var items = new List<JsValue>(arguments.Length + 1) {o};
             items.AddRange(arguments);
             items.AddRange(arguments);
 
 
@@ -1211,11 +1220,11 @@ namespace Jint.Native.Array
 
 
             if (capacity > NumberConstructor.MaxSafeInteger)
             if (capacity > NumberConstructor.MaxSafeInteger)
             {
             {
-                ExceptionHelper.ThrowTypeError(_engine, "Invalid array length");
+                ExceptionHelper.ThrowTypeError(_realm, "Invalid array length");
             }
             }
 
 
             uint n = 0;
             uint n = 0;
-            var a = Engine.Array.ArraySpeciesCreate(TypeConverter.ToObject(_engine, thisObj), capacity);
+            var a = _realm.Intrinsics.Array.ArraySpeciesCreate(TypeConverter.ToObject(_realm, thisObj), capacity);
             var aOperations = ArrayOperations.For(a);
             var aOperations = ArrayOperations.For(a);
             for (var i = 0; i < items.Count; i++)
             for (var i = 0; i < items.Count; i++)
             {
             {
@@ -1228,7 +1237,7 @@ namespace Jint.Native.Array
                     n += eArray.GetLength();
                     n += eArray.GetLength();
                 }
                 }
                 else if (hasObjectSpreadables
                 else if (hasObjectSpreadables
-                         && e is ObjectInstance oi 
+                         && e is ObjectInstance oi
                          && oi.IsConcatSpreadable)
                          && oi.IsConcatSpreadable)
                 {
                 {
                     var operations = ArrayOperations.For(oi);
                     var operations = ArrayOperations.For(oi);
@@ -1256,16 +1265,13 @@ namespace Jint.Native.Array
 
 
         private JsValue ToString(JsValue thisObj, JsValue[] arguments)
         private JsValue ToString(JsValue thisObj, JsValue[] arguments)
         {
         {
-            var array = TypeConverter.ToObject(Engine, thisObj);
+            var array = TypeConverter.ToObject(_realm, thisObj);
 
 
-            ICallable func;
-            func = array.Get("join", array).TryCast<ICallable>(x =>
+            ICallable func = array.Get("join", array) as ICallable;
+            if (func is null)
             {
             {
-                func = Engine.Object.PrototypeObject.Get("toString", array).TryCast<ICallable>(y => ExceptionHelper.ThrowArgumentException());
-            });
-
-            if (array.IsArrayLike == false || func == null)
-                return _engine.Object.PrototypeObject.ToObjectString(array, Arguments.Empty);
+                func = _realm.Intrinsics.Object.PrototypeObject.Get("toString", array) as ICallable;
+            }
 
 
             return func.Call(array, Arguments.Empty);
             return func.Call(array, Arguments.Empty);
         }
         }
@@ -1275,14 +1281,14 @@ namespace Jint.Native.Array
             var callbackfn = arguments.At(0);
             var callbackfn = arguments.At(0);
             var initialValue = arguments.At(1);
             var initialValue = arguments.At(1);
 
 
-            var o = ArrayOperations.For(TypeConverter.ToObject(_engine, thisObj));
+            var o = ArrayOperations.For(TypeConverter.ToObject(_realm, thisObj));
             var len = o.GetLongLength();
             var len = o.GetLongLength();
 
 
             var callable = GetCallable(callbackfn);
             var callable = GetCallable(callbackfn);
 
 
             if (len == 0 && arguments.Length < 2)
             if (len == 0 && arguments.Length < 2)
             {
             {
-                ExceptionHelper.ThrowTypeError(Engine);
+                ExceptionHelper.ThrowTypeError(_realm);
             }
             }
 
 
             long k = (long) (len - 1);
             long k = (long) (len - 1);
@@ -1306,7 +1312,7 @@ namespace Jint.Native.Array
 
 
                 if (kPresent == false)
                 if (kPresent == false)
                 {
                 {
-                    ExceptionHelper.ThrowTypeError(Engine);
+                    ExceptionHelper.ThrowTypeError(_realm);
                 }
                 }
             }
             }
 
 
@@ -1338,7 +1344,7 @@ namespace Jint.Native.Array
 
 
             if (n + (ulong) arguments.Length > ArrayOperations.MaxArrayLikeLength)
             if (n + (ulong) arguments.Length > ArrayOperations.MaxArrayLikeLength)
             {
             {
-                return ExceptionHelper.ThrowTypeError<JsValue>(_engine, "Invalid array length");
+                ExceptionHelper.ThrowTypeError(_realm, "Invalid array length");
             }
             }
 
 
             // cast to double as we need to prevent an overflow
             // cast to double as we need to prevent an overflow
@@ -1354,7 +1360,7 @@ namespace Jint.Native.Array
 
 
         public JsValue Pop(JsValue thisObject, JsValue[] arguments)
         public JsValue Pop(JsValue thisObject, JsValue[] arguments)
         {
         {
-            var o = ArrayOperations.For(Engine, thisObject);
+            var o = ArrayOperations.For(_realm, thisObject);
             ulong len = o.GetLongLength();
             ulong len = o.GetLongLength();
             if (len == 0)
             if (len == 0)
             {
             {
@@ -1404,7 +1410,7 @@ namespace Jint.Native.Array
                     {
                     {
                         return 0;
                         return 0;
                     }
                     }
-                    
+
                     return 1;
                     return 1;
                 }
                 }
                 else
                 else

+ 14 - 19
Jint/Native/Boolean/BooleanConstructor.cs

@@ -9,29 +9,21 @@ namespace Jint.Native.Boolean
     {
     {
         private static readonly JsString _functionName = new JsString("Boolean");
         private static readonly JsString _functionName = new JsString("Boolean");
 
 
-        private BooleanConstructor(Engine engine)
-            : base(engine, _functionName)
+        internal BooleanConstructor(
+            Engine engine,
+            Realm realm,
+            FunctionPrototype functionPrototype,
+            ObjectPrototype objectPrototype)
+            : base(engine, realm, _functionName)
         {
         {
+            _prototype = functionPrototype;
+            PrototypeObject = new BooleanPrototype(engine, realm, this, objectPrototype);
+            _length = new PropertyDescriptor(JsNumber.One, PropertyFlag.Configurable);
+            _prototypeDescriptor = new PropertyDescriptor(PrototypeObject, PropertyFlag.AllForbidden);
         }
         }
 
 
         public BooleanPrototype PrototypeObject { get; private set; }
         public BooleanPrototype PrototypeObject { get; private set; }
 
 
-        public static BooleanConstructor CreateBooleanConstructor(Engine engine)
-        {
-            var obj = new BooleanConstructor(engine);
-
-            // The value of the [[Prototype]] internal property of the Boolean constructor is the Function prototype object
-            obj._prototype = engine.Function.PrototypeObject;
-            obj.PrototypeObject = BooleanPrototype.CreatePrototypeObject(engine, obj);
-
-            obj._length = new PropertyDescriptor(JsNumber.One, PropertyFlag.Configurable);
-
-            // The initial value of Boolean.prototype is the Boolean prototype object
-            obj._prototypeDescriptor = new PropertyDescriptor(obj.PrototypeObject, PropertyFlag.AllForbidden);
-
-            return obj;
-        }
-
         public override JsValue Call(JsValue thisObject, JsValue[] arguments)
         public override JsValue Call(JsValue thisObject, JsValue[] arguments)
         {
         {
             if (arguments.Length == 0)
             if (arguments.Length == 0)
@@ -56,7 +48,10 @@ namespace Jint.Native.Boolean
                 return Construct(b);
                 return Construct(b);
             }
             }
 
 
-            var o = OrdinaryCreateFromConstructor(newTarget, PrototypeObject, static (engine, state) => new BooleanInstance(engine, (JsBoolean) state), b);
+            var o = OrdinaryCreateFromConstructor(
+                newTarget,
+                static intrinsics => intrinsics.Boolean.PrototypeObject,
+                static (engine, realm, state) => new BooleanInstance(engine, (JsBoolean) state), b);
             return o;
             return o;
         }
         }
 
 

+ 16 - 17
Jint/Native/Boolean/BooleanPrototype.cs

@@ -1,4 +1,5 @@
 using Jint.Collections;
 using Jint.Collections;
+using Jint.Native.Object;
 using Jint.Runtime;
 using Jint.Runtime;
 using Jint.Runtime.Descriptors;
 using Jint.Runtime.Descriptors;
 using Jint.Runtime.Interop;
 using Jint.Runtime.Interop;
@@ -10,29 +11,26 @@ namespace Jint.Native.Boolean
     /// </summary>
     /// </summary>
     public sealed class BooleanPrototype : BooleanInstance
     public sealed class BooleanPrototype : BooleanInstance
     {
     {
-        private BooleanConstructor _booleanConstructor;
-
-        private BooleanPrototype(Engine engine) : base(engine)
-        {
-        }
-
-        public static BooleanPrototype CreatePrototypeObject(Engine engine, BooleanConstructor booleanConstructor)
+        private readonly Realm _realm;
+        private readonly BooleanConstructor _constructor;
+
+        internal BooleanPrototype(
+            Engine engine,
+            Realm realm,
+            BooleanConstructor constructor,
+            ObjectPrototype objectPrototype) : base(engine)
         {
         {
-            var obj = new BooleanPrototype(engine)
-            {
-                _prototype = engine.Object.PrototypeObject,
-                PrimitiveValue = false,
-                _booleanConstructor = booleanConstructor
-            };
-
-            return obj;
+            _prototype = objectPrototype;
+            PrimitiveValue = JsBoolean.False;
+            _realm = realm;
+            _constructor = constructor;
         }
         }
 
 
         protected override void Initialize()
         protected override void Initialize()
         {
         {
             var properties = new PropertyDictionary(3, checkExistingKeys: false)
             var properties = new PropertyDictionary(3, checkExistingKeys: false)
             {
             {
-                ["constructor"] = new PropertyDescriptor(_booleanConstructor, PropertyFlag.NonEnumerable),
+                ["constructor"] = new PropertyDescriptor(_constructor, PropertyFlag.NonEnumerable),
                 ["toString"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "toString", ToBooleanString, 0, PropertyFlag.Configurable), true, false, true),
                 ["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)
                 ["valueOf"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "valueOf", ValueOf, 0, PropertyFlag.Configurable), true, false, true)
             };
             };
@@ -51,7 +49,8 @@ namespace Jint.Native.Boolean
                 return bi.PrimitiveValue;
                 return bi.PrimitiveValue;
             }
             }
 
 
-            return ExceptionHelper.ThrowTypeError<JsValue>(Engine);
+            ExceptionHelper.ThrowTypeError(_realm);
+            return Undefined;
         }
         }
 
 
         private JsValue ToBooleanString(JsValue thisObj, JsValue[] arguments)
         private JsValue ToBooleanString(JsValue thisObj, JsValue[] arguments)

+ 14 - 20
Jint/Native/Date/DateConstructor.cs

@@ -54,26 +54,17 @@ namespace Jint.Native.Date
 
 
         private static readonly JsString _functionName = new JsString("Date");
         private static readonly JsString _functionName = new JsString("Date");
 
 
-        public DateConstructor(Engine engine) : base(engine, _functionName)
+        internal DateConstructor(
+            Engine engine,
+            Realm realm,
+            FunctionPrototype functionPrototype,
+            ObjectPrototype objectPrototype)
+            : base(engine, realm, _functionName)
         {
         {
-        }
-
-        public static DateConstructor CreateDateConstructor(Engine engine)
-        {
-            var obj = new DateConstructor(engine)
-            {
-                _prototype = engine.Function.PrototypeObject
-            };
-
-            // The value of the [[Prototype]] internal property of the Date constructor is the Function prototype object
-            obj.PrototypeObject = DatePrototype.CreatePrototypeObject(engine, obj);
-
-            obj._length = new PropertyDescriptor(7, PropertyFlag.Configurable);
-
-            // The initial value of Date.prototype is the Date prototype object
-            obj._prototypeDescriptor = new PropertyDescriptor(obj.PrototypeObject, PropertyFlag.AllForbidden);
-
-            return obj;
+            _prototype = functionPrototype;
+            PrototypeObject = new DatePrototype(engine, realm, this, objectPrototype);
+            _length = new PropertyDescriptor(7, PropertyFlag.Configurable);
+            _prototypeDescriptor = new PropertyDescriptor(PrototypeObject, PropertyFlag.AllForbidden);
         }
         }
 
 
         protected override void Initialize()
         protected override void Initialize()
@@ -193,7 +184,10 @@ namespace Jint.Native.Date
                 dv = TimeClip(PrototypeObject.Utc(finalDate));
                 dv = TimeClip(PrototypeObject.Utc(finalDate));
             }
             }
 
 
-            var o = OrdinaryCreateFromConstructor(newTarget, PrototypeObject, static (engine, _) => new DateInstance(engine));
+            var o = OrdinaryCreateFromConstructor(
+                newTarget,
+                static intrinsics => intrinsics.Date.PrototypeObject,
+                static (engine, realm, _) => new DateInstance(engine));
             o.PrimitiveValue = dv;
             o.PrimitiveValue = dv;
             return o;
             return o;
         }
         }

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

@@ -21,9 +21,13 @@ namespace Jint.Native.Date
 
 
         public DateTime ToDateTime()
         public DateTime ToDateTime()
         {
         {
-            return DateTimeRangeValid 
-                ? DateConstructor.Epoch.AddMilliseconds(PrimitiveValue)
-                : ExceptionHelper.ThrowRangeError<DateTime>(Engine);
+            if (DateTimeRangeValid)
+            {
+                return DateConstructor.Epoch.AddMilliseconds(PrimitiveValue);
+            }
+
+            ExceptionHelper.ThrowRangeError(_engine.Realm);
+            return DateTime.MinValue;
         }
         }
 
 
         public double PrimitiveValue { get; set; }
         public double PrimitiveValue { get; set; }

+ 31 - 26
Jint/Native/Date/DatePrototype.cs

@@ -21,22 +21,19 @@ namespace Jint.Native.Date
         private const double MinMonth = -10000000.0;
         private const double MinMonth = -10000000.0;
         private const double MaxMonth = -MinMonth;
         private const double MaxMonth = -MinMonth;
 
 
-        private DateConstructor _dateConstructor;
-
-        private DatePrototype(Engine engine)
+        private readonly Realm _realm;
+        private readonly DateConstructor _constructor;
+
+        internal DatePrototype(
+            Engine engine,
+            Realm realm,
+            DateConstructor constructor,
+            ObjectPrototype objectPrototype)
             : base(engine)
             : base(engine)
         {
         {
-        }
-
-        public static DatePrototype CreatePrototypeObject(Engine engine, DateConstructor dateConstructor)
-        {
-            var obj = new DatePrototype(engine)
-            {
-                _prototype = engine.Object.PrototypeObject,
-                _dateConstructor = dateConstructor
-            };
-
-            return obj;
+            _prototype = objectPrototype;
+            _realm = realm;
+            _constructor = constructor;
         }
         }
 
 
         protected override  void Initialize()
         protected override  void Initialize()
@@ -46,7 +43,7 @@ namespace Jint.Native.Date
 
 
             var properties = new PropertyDictionary(50, checkExistingKeys: false)
             var properties = new PropertyDictionary(50, checkExistingKeys: false)
             {
             {
-                ["constructor"] = new PropertyDescriptor(_dateConstructor, PropertyFlag.NonEnumerable),
+                ["constructor"] = new PropertyDescriptor(_constructor, PropertyFlag.NonEnumerable),
                 ["toString"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "toString", ToString, 0, lengthFlags), propertyFlags),
                 ["toString"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "toString", ToString, 0, lengthFlags), propertyFlags),
                 ["toDateString"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "toDateString", ToDateString, 0, lengthFlags), propertyFlags),
                 ["toDateString"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "toDateString", ToDateString, 0, lengthFlags), propertyFlags),
                 ["toTimeString"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "toTimeString", ToTimeString, 0, lengthFlags), propertyFlags),
                 ["toTimeString"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "toTimeString", ToTimeString, 0, lengthFlags), propertyFlags),
@@ -104,15 +101,16 @@ namespace Jint.Native.Date
 
 
         private JsValue ToPrimitive(JsValue thisObject, JsValue[] arguments)
         private JsValue ToPrimitive(JsValue thisObject, JsValue[] arguments)
         {
         {
-            if (!(thisObject is ObjectInstance oi))
+            var oi = thisObject as ObjectInstance;
+            if (oi is null)
             {
             {
-                return ExceptionHelper.ThrowTypeError<JsValue>(_engine);
+                ExceptionHelper.ThrowTypeError(_realm);
             }
             }
 
 
             var hint = arguments.At(0);
             var hint = arguments.At(0);
             if (!hint.IsString())
             if (!hint.IsString())
             {
             {
-                return ExceptionHelper.ThrowTypeError<JsValue>(_engine);
+                ExceptionHelper.ThrowTypeError(_realm);
             }
             }
 
 
             var hintString = hint.ToString();
             var hintString = hint.ToString();
@@ -127,7 +125,7 @@ namespace Jint.Native.Date
             }
             }
             else
             else
             {
             {
-                return ExceptionHelper.ThrowTypeError<JsValue>(_engine);
+                ExceptionHelper.ThrowTypeError(_realm);
             }
             }
 
 
             return TypeConverter.OrdinaryToPrimitive(oi, tryFirst);
             return TypeConverter.OrdinaryToPrimitive(oi, tryFirst);
@@ -144,8 +142,13 @@ namespace Jint.Native.Date
         /// </summary>
         /// </summary>
         private DateInstance EnsureDateInstance(JsValue thisObj)
         private DateInstance EnsureDateInstance(JsValue thisObj)
         {
         {
-            return thisObj as DateInstance
-                   ?? ExceptionHelper.ThrowTypeError<DateInstance>(_engine, "this is not a Date object");
+            if (thisObj is DateInstance dateInstance)
+            {
+                return dateInstance;
+            }
+
+            ExceptionHelper.ThrowTypeError(_realm, "this is not a Date object");
+            return null;
         }
         }
 
 
         public JsValue ToString(JsValue thisObj, JsValue[] arg2)
         public JsValue ToString(JsValue thisObj, JsValue[] arg2)
@@ -661,7 +664,7 @@ namespace Jint.Native.Date
             var t = thisTime.PrimitiveValue;
             var t = thisTime.PrimitiveValue;
             if (!IsFinite(t))
             if (!IsFinite(t))
             {
             {
-                ExceptionHelper.ThrowRangeError(_engine);
+                ExceptionHelper.ThrowRangeError(_realm);
             }
             }
 
 
             if (thisTime.DateTimeRangeValid)
             if (thisTime.DateTimeRangeValid)
@@ -686,7 +689,7 @@ namespace Jint.Native.Date
 
 
         private JsValue ToJSON(JsValue thisObj, JsValue[] arguments)
         private JsValue ToJSON(JsValue thisObj, JsValue[] arguments)
         {
         {
-            var o = TypeConverter.ToObject(Engine, thisObj);
+            var o = TypeConverter.ToObject(_realm, thisObj);
             var tv = TypeConverter.ToPrimitive(o, Types.Number);
             var tv = TypeConverter.ToPrimitive(o, Types.Number);
             if (tv.IsNumber() && !IsFinite(((JsNumber) tv)._value))
             if (tv.IsNumber() && !IsFinite(((JsNumber) tv)._value))
             {
             {
@@ -694,9 +697,10 @@ namespace Jint.Native.Date
             }
             }
 
 
             var toIso = o.Get("toISOString", o);
             var toIso = o.Get("toISOString", o);
-            if (!(toIso is ICallable callable))
+            var callable = toIso as ICallable;
+            if (callable is null)
             {
             {
-                return ExceptionHelper.ThrowTypeError<JsValue>(Engine);
+                ExceptionHelper.ThrowTypeError(_realm);
             }
             }
 
 
             return callable.Call(o, Arguments.Empty);
             return callable.Call(o, Arguments.Empty);
@@ -806,7 +810,8 @@ namespace Jint.Native.Date
                 return 1;
                 return 1;
             }
             }
 
 
-            return ExceptionHelper.ThrowArgumentException<int>();
+            ExceptionHelper.ThrowArgumentException();
+            return 0;
         }
         }
 
 
         /// <summary>
         /// <summary>

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

@@ -7,35 +7,28 @@ namespace Jint.Native.Error
 {
 {
     public sealed class ErrorConstructor : FunctionInstance, IConstructor
     public sealed class ErrorConstructor : FunctionInstance, IConstructor
     {
     {
-        private JsString _name;
-        private static readonly JsString _functionName = new JsString("Error");
-
-        public ErrorConstructor(Engine engine, JsString functionName) : base(engine, functionName)
+        private readonly JsString _name;
+
+        internal ErrorConstructor(
+            Engine engine,
+            Realm realm,
+            ObjectInstance functionPrototype,
+            ObjectInstance objectPrototype,
+            JsString name)
+            : base(engine, realm, name)
         {
         {
+            _name = name;
+            _prototype = functionPrototype;
+            PrototypeObject = new ErrorPrototype(engine, realm, this, objectPrototype, name, ObjectClass.Object);
+            _length = PropertyDescriptor.AllForbiddenDescriptor.NumberOne;
+            _prototypeDescriptor = new PropertyDescriptor(PrototypeObject, PropertyFlag.AllForbidden);
         }
         }
 
 
-        public static ErrorConstructor CreateErrorConstructor(Engine engine, JsString name)
-        {
-            var obj = new ErrorConstructor(engine, name)
-            {
-                _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.PrototypeObject = ErrorPrototype.CreatePrototypeObject(engine, obj, name);
-
-            obj._length = PropertyDescriptor.AllForbiddenDescriptor.NumberOne;
-
-            // The initial value of Error.prototype is the Error prototype object
-            obj._prototypeDescriptor = new PropertyDescriptor(obj.PrototypeObject, PropertyFlag.AllForbidden);
-
-            return obj;
-        }
+        public ErrorPrototype PrototypeObject { get; }
 
 
         public override JsValue Call(JsValue thisObject, JsValue[] arguments)
         public override JsValue Call(JsValue thisObject, JsValue[] arguments)
         {
         {
-            return Construct(arguments, thisObject);
+            return Construct(arguments, this);
         }
         }
 
 
         public ObjectInstance Construct(JsValue[] arguments)
         public ObjectInstance Construct(JsValue[] arguments)
@@ -47,8 +40,8 @@ namespace Jint.Native.Error
         {
         {
             var o = OrdinaryCreateFromConstructor(
             var o = OrdinaryCreateFromConstructor(
                 newTarget,
                 newTarget,
-                PrototypeObject,
-                static (e, state) => new ErrorInstance(e, (JsString) state),
+                static intrinsics => intrinsics.Error.PrototypeObject,
+                static (engine, realm, state) => new ErrorInstance(engine, (JsString) state),
                 _name);
                 _name);
 
 
             var jsValue = arguments.At(0);
             var jsValue = arguments.At(0);
@@ -61,17 +54,10 @@ namespace Jint.Native.Error
 
 
             var lastSyntaxNode = _engine.GetLastSyntaxNode();
             var lastSyntaxNode = _engine.GetLastSyntaxNode();
             var stackString = lastSyntaxNode == null ? Undefined : _engine.CallStack.BuildCallStackString(lastSyntaxNode.Location);
             var stackString = lastSyntaxNode == null ? Undefined : _engine.CallStack.BuildCallStackString(lastSyntaxNode.Location);
-            var stackDesc = new PropertyDescriptor(stackString, true, false, true);
+            var stackDesc = new PropertyDescriptor(stackString, PropertyFlag.NonEnumerable);
             o.DefinePropertyOrThrow(CommonProperties.Stack, stackDesc);
             o.DefinePropertyOrThrow(CommonProperties.Stack, stackDesc);
 
 
             return o;
             return o;
         }
         }
-
-        public ErrorPrototype PrototypeObject { get; private set; }
-
-        protected internal override ObjectInstance GetPrototypeOf()
-        {
-            return _name._value != "Error" ? _engine.Error : _prototype;
-        }
     }
     }
 }
 }

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

@@ -9,8 +9,11 @@ namespace Jint.Native.Error
         private readonly JsString _name;
         private readonly JsString _name;
         private PropertyDescriptor _descriptor;
         private PropertyDescriptor _descriptor;
 
 
-        public ErrorInstance(Engine engine, JsString name)
-            : base(engine, ObjectClass.Error)
+        internal ErrorInstance(
+            Engine engine,
+            JsString name,
+            ObjectClass objectClass = ObjectClass.Error)
+            : base(engine, objectClass)
         {
         {
             _name = name;
             _name = name;
         }
         }
@@ -26,7 +29,7 @@ namespace Jint.Native.Error
 
 
         public override string ToString()
         public override string ToString()
         {
         {
-            return Engine.Error.PrototypeObject.ToString(this, Arguments.Empty).ToObject().ToString();
+            return Engine.Realm.Intrinsics.Error.PrototypeObject.ToString(this, Arguments.Empty).ToObject().ToString();
         }
         }
     }
     }
 }
 }

+ 16 - 25
Jint/Native/Error/ErrorPrototype.cs

@@ -11,39 +11,30 @@ namespace Jint.Native.Error
     /// </summary>
     /// </summary>
     public sealed class ErrorPrototype : ErrorInstance
     public sealed class ErrorPrototype : ErrorInstance
     {
     {
-        private ErrorConstructor _errorConstructor;
+        private readonly Realm _realm;
+        private readonly ErrorConstructor _constructor;
 
 
-        private ErrorPrototype(Engine engine, JsString name)
-            : base(engine, name)
+        internal ErrorPrototype(
+            Engine engine,
+            Realm realm,
+            ErrorConstructor constructor,
+            ObjectInstance prototype,
+            JsString name,
+            ObjectClass objectClass)
+            : base(engine, name, objectClass)
         {
         {
-        }
-
-        public static ErrorPrototype CreatePrototypeObject(Engine engine, ErrorConstructor errorConstructor, JsString name)
-        {
-            var obj = new ErrorPrototype(engine, name)
-            {
-                _errorConstructor = errorConstructor,
-            };
-
-            if (name._value != "Error")
-            {
-                obj._prototype = engine.Error.PrototypeObject;
-            }
-            else
-            {
-                obj._prototype = engine.Object.PrototypeObject;
-            }
-
-            return obj;
+            _realm = realm;
+            _constructor = constructor;
+            _prototype = prototype;
         }
         }
 
 
         protected override void Initialize()
         protected override void Initialize()
         {
         {
             var properties = new PropertyDictionary(3, checkExistingKeys: false)
             var properties = new PropertyDictionary(3, checkExistingKeys: false)
             {
             {
-                ["constructor"] = new PropertyDescriptor(_errorConstructor, PropertyFlag.NonEnumerable),
+                ["constructor"] = new PropertyDescriptor(_constructor, PropertyFlag.NonEnumerable),
                 ["message"] = new PropertyDescriptor("", PropertyFlag.Configurable | PropertyFlag.Writable),
                 ["message"] = new PropertyDescriptor("", PropertyFlag.Configurable | PropertyFlag.Writable),
-                ["toString"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "toString", ToString), PropertyFlag.Configurable | PropertyFlag.Writable)
+                ["toString"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "toString", ToString, 0, PropertyFlag.Configurable), PropertyFlag.Configurable | PropertyFlag.Writable)
             };
             };
             SetProperties(properties);
             SetProperties(properties);
         }
         }
@@ -53,7 +44,7 @@ namespace Jint.Native.Error
             var o = thisObject.TryCast<ObjectInstance>();
             var o = thisObject.TryCast<ObjectInstance>();
             if (ReferenceEquals(o, null))
             if (ReferenceEquals(o, null))
             {
             {
-                ExceptionHelper.ThrowTypeError(Engine);
+                ExceptionHelper.ThrowTypeError(_realm);
             }
             }
 
 
             var name = TypeConverter.ToString(o.Get("name", this));
             var name = TypeConverter.ToString(o.Get("name", this));

+ 14 - 9
Jint/Native/Function/BindFunctionInstance.cs

@@ -5,8 +5,10 @@ namespace Jint.Native.Function
 {
 {
     public sealed class BindFunctionInstance : FunctionInstance, IConstructor
     public sealed class BindFunctionInstance : FunctionInstance, IConstructor
     {
     {
-        public BindFunctionInstance(Engine engine)
-            : base(engine, name: null, thisMode: FunctionThisMode.Strict)
+        public BindFunctionInstance(
+            Engine engine,
+            Realm realm)
+            : base(engine, realm, name: null, thisMode: FunctionThisMode.Strict)
         {
         {
         }
         }
 
 
@@ -18,9 +20,10 @@ namespace Jint.Native.Function
 
 
         public override JsValue Call(JsValue thisObject, JsValue[] arguments)
         public override JsValue Call(JsValue thisObject, JsValue[] arguments)
         {
         {
-            if (!(TargetFunction is FunctionInstance f))
+            var f = TargetFunction as FunctionInstance;
+            if (f is null)
             {
             {
-                return ExceptionHelper.ThrowTypeError<ObjectInstance>(Engine);
+                ExceptionHelper.ThrowTypeError(_realm);
             }
             }
 
 
             var args = CreateArguments(arguments);
             var args = CreateArguments(arguments);
@@ -32,9 +35,10 @@ namespace Jint.Native.Function
 
 
         public ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
         public ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
         {
         {
-            if (!(TargetFunction is IConstructor target))
+            var target = TargetFunction as IConstructor;
+            if (target is null)
             {
             {
-                return ExceptionHelper.ThrowTypeError<ObjectInstance>(Engine);
+                ExceptionHelper.ThrowTypeError(_realm);
             }
             }
 
 
             var args = CreateArguments(arguments);
             var args = CreateArguments(arguments);
@@ -52,10 +56,11 @@ namespace Jint.Native.Function
 
 
         internal override bool OrdinaryHasInstance(JsValue v)
         internal override bool OrdinaryHasInstance(JsValue v)
         {
         {
-            var f = TargetFunction.TryCast<FunctionInstance>(x =>
+            var f = TargetFunction as FunctionInstance;
+            if (f is null)
             {
             {
-                ExceptionHelper.ThrowTypeError(Engine);
-            });
+                ExceptionHelper.ThrowTypeError(_realm);
+            }
 
 
             return f.OrdinaryHasInstance(v);
             return f.OrdinaryHasInstance(v);
         }
         }

+ 12 - 7
Jint/Native/Function/ClassDefinition.cs

@@ -52,7 +52,7 @@ namespace Jint.Native.Function
         {
         {
             // A class definition is always strict mode code.
             // A class definition is always strict mode code.
             using var _ = (new StrictModeScope(true, true));
             using var _ = (new StrictModeScope(true, true));
-            
+
             var classScope = JintEnvironment.NewDeclarativeEnvironment(engine, env);
             var classScope = JintEnvironment.NewDeclarativeEnvironment(engine, env);
 
 
             if (_className is not null)
             if (_className is not null)
@@ -64,8 +64,8 @@ namespace Jint.Native.Function
             ObjectInstance? constructorParent = null;
             ObjectInstance? constructorParent = null;
             if (_superClass is null)
             if (_superClass is null)
             {
             {
-                protoParent = engine.Object.PrototypeObject;
-                constructorParent = engine.Function.PrototypeObject;
+                protoParent = engine.Realm.Intrinsics.Object.PrototypeObject;
+                constructorParent = engine.Realm.Intrinsics.Function.PrototypeObject;
             }
             }
             else
             else
             {
             {
@@ -76,11 +76,11 @@ namespace Jint.Native.Function
                 if (superclass.IsNull())
                 if (superclass.IsNull())
                 {
                 {
                     protoParent = null;
                     protoParent = null;
-                    constructorParent = engine.Function.PrototypeObject;
+                    constructorParent = engine.Realm.Intrinsics.Function.PrototypeObject;
                 }
                 }
                 else if (!superclass.IsConstructor)
                 else if (!superclass.IsConstructor)
                 {
                 {
-                    ExceptionHelper.ThrowTypeError(engine, "super class is not a constructor");
+                    ExceptionHelper.ThrowTypeError(engine.Realm, "super class is not a constructor");
                 }
                 }
                 else
                 else
                 {
                 {
@@ -95,7 +95,7 @@ namespace Jint.Native.Function
                     }
                     }
                     else
                     else
                     {
                     {
-                        ExceptionHelper.ThrowTypeError(engine);
+                        ExceptionHelper.ThrowTypeError(engine.Realm);
                         return null!;
                         return null!;
                     }
                     }
 
 
@@ -182,13 +182,18 @@ namespace Jint.Native.Function
             else
             else
             {
             {
                 var propKey = TypeConverter.ToPropertyKey(method.GetKey(engine));
                 var propKey = TypeConverter.ToPropertyKey(method.GetKey(engine));
-                var function = method.Value as IFunction ?? ExceptionHelper.ThrowSyntaxError<IFunction>(obj.Engine);
+                var function = method.Value as IFunction;
+                if (function is null)
+                {
+                    ExceptionHelper.ThrowSyntaxError(obj.Engine.Realm);
+                }
 
 
                 var closure = new ScriptFunctionInstance(
                 var closure = new ScriptFunctionInstance(
                     obj.Engine,
                     obj.Engine,
                     function,
                     function,
                     obj.Engine.ExecutionContext.LexicalEnvironment,
                     obj.Engine.ExecutionContext.LexicalEnvironment,
                     true);
                     true);
+
                 closure.SetFunctionName(propKey, method.Kind == PropertyKind.Get ? "get" : "set");
                 closure.SetFunctionName(propKey, method.Kind == PropertyKind.Get ? "get" : "set");
                 closure.MakeMethod(obj);
                 closure.MakeMethod(obj);
 
 

+ 39 - 20
Jint/Native/Function/EvalFunctionInstance.cs

@@ -12,29 +12,40 @@ namespace Jint.Native.Function
         private static readonly ParserOptions ParserOptions = new ParserOptions { AdaptRegexp = true, Tolerant = false };
         private static readonly ParserOptions ParserOptions = new ParserOptions { AdaptRegexp = true, Tolerant = false };
         private static readonly JsString _functionName = new JsString("eval");
         private static readonly JsString _functionName = new JsString("eval");
 
 
-        public EvalFunctionInstance(Engine engine) 
-            : base(engine, _functionName, StrictModeScope.IsStrictModeCode ? FunctionThisMode.Strict : FunctionThisMode.Global)
+        public EvalFunctionInstance(
+            Engine engine,
+            Realm realm,
+            FunctionPrototype functionPrototype)
+            : base(
+                engine,
+                realm,
+                _functionName,
+                StrictModeScope.IsStrictModeCode ? FunctionThisMode.Strict : FunctionThisMode.Global)
         {
         {
-            _prototype = Engine.Function.PrototypeObject;
+            _prototype = functionPrototype;
             _length = PropertyDescriptor.AllForbiddenDescriptor.NumberOne;
             _length = PropertyDescriptor.AllForbiddenDescriptor.NumberOne;
         }
         }
 
 
         public override JsValue Call(JsValue thisObject, JsValue[] arguments)
         public override JsValue Call(JsValue thisObject, JsValue[] arguments)
         {
         {
-            var callerRealm = (object) null;
-            return PerformEval(arguments.At(0), callerRealm, StrictModeScope.IsStrictModeCode, false);
+            var callerRealm = _engine.ExecutionContext.Realm;
+            var x = arguments.At(0);
+            return PerformEval(x, callerRealm, false, false);
         }
         }
 
 
         /// <summary>
         /// <summary>
         /// https://tc39.es/ecma262/#sec-performeval
         /// https://tc39.es/ecma262/#sec-performeval
         /// </summary>
         /// </summary>
-        public JsValue PerformEval(JsValue x, object callerRealm, bool strictCaller, bool direct)
+        public JsValue PerformEval(JsValue x, Realm callerRealm, bool strictCaller, bool direct)
         {
         {
             if (!x.IsString())
             if (!x.IsString())
             {
             {
                 return x;
                 return x;
             }
             }
 
 
+            var evalRealm = _realm;
+            _engine._host.EnsureCanCompileStrings(callerRealm, evalRealm);
+
             var inFunction = false;
             var inFunction = false;
             var inMethod = false;
             var inMethod = false;
             var inDerivedConstructor = false;
             var inDerivedConstructor = false;
@@ -47,7 +58,7 @@ namespace Jint.Native.Function
                     var F = functionEnvironmentRecord._functionObject;
                     var F = functionEnvironmentRecord._functionObject;
                     inFunction = true;
                     inFunction = true;
                     inMethod = thisEnvRec.HasSuperBinding();
                     inMethod = thisEnvRec.HasSuperBinding();
-                    
+
                     if (F._constructorKind == ConstructorKind.Derived)
                     if (F._constructorKind == ConstructorKind.Derived)
                     {
                     {
                         inDerivedConstructor = true;
                         inDerivedConstructor = true;
@@ -56,16 +67,21 @@ namespace Jint.Native.Function
             }
             }
 
 
             var parser = new JavaScriptParser(x.ToString(), ParserOptions);
             var parser = new JavaScriptParser(x.ToString(), ParserOptions);
-            Script script;
+            Script script = null;
             try
             try
             {
             {
                 script = parser.ParseScript(strictCaller);
                 script = parser.ParseScript(strictCaller);
             }
             }
             catch (ParserException e)
             catch (ParserException e)
             {
             {
-                return e.Description == Messages.InvalidLHSInAssignment 
-                    ? ExceptionHelper.ThrowReferenceError<JsValue>(_engine)
-                    : ExceptionHelper.ThrowSyntaxError<JsValue>(_engine);
+                if (e.Description == Messages.InvalidLHSInAssignment)
+                {
+                    ExceptionHelper.ThrowReferenceError(callerRealm, (string) null);
+                }
+                else
+                {
+                    ExceptionHelper.ThrowSyntaxError(callerRealm);
+                }
             }
             }
 
 
             var body = script.Body;
             var body = script.Body;
@@ -77,15 +93,15 @@ namespace Jint.Native.Function
             if (!inFunction)
             if (!inFunction)
             {
             {
                 // if body Contains NewTarget, throw a SyntaxError exception.
                 // if body Contains NewTarget, throw a SyntaxError exception.
-            } 
+            }
             if (!inMethod)
             if (!inMethod)
             {
             {
                 // if body Contains SuperProperty, throw a SyntaxError exception.
                 // if body Contains SuperProperty, throw a SyntaxError exception.
-            } 
+            }
             if (!inDerivedConstructor)
             if (!inDerivedConstructor)
             {
             {
                 // if body Contains SuperCall, throw a SyntaxError exception.
                 // if body Contains SuperCall, throw a SyntaxError exception.
-            } 
+            }
 
 
             var strictEval = script.Strict || _engine._isStrict;
             var strictEval = script.Strict || _engine._isStrict;
             var ctx = _engine.ExecutionContext;
             var ctx = _engine.ExecutionContext;
@@ -94,15 +110,18 @@ namespace Jint.Native.Function
             {
             {
                 EnvironmentRecord lexEnv;
                 EnvironmentRecord lexEnv;
                 EnvironmentRecord varEnv;
                 EnvironmentRecord varEnv;
+                PrivateEnvironmentRecord privateEnv;
                 if (direct)
                 if (direct)
                 {
                 {
                     lexEnv = JintEnvironment.NewDeclarativeEnvironment(_engine, ctx.LexicalEnvironment);
                     lexEnv = JintEnvironment.NewDeclarativeEnvironment(_engine, ctx.LexicalEnvironment);
                     varEnv = ctx.VariableEnvironment;
                     varEnv = ctx.VariableEnvironment;
+                    privateEnv = ctx.PrivateEnvironment;
                 }
                 }
                 else
                 else
                 {
                 {
-                    lexEnv = JintEnvironment.NewDeclarativeEnvironment(_engine, Engine.GlobalEnvironment);
-                    varEnv = Engine.GlobalEnvironment;
+                    lexEnv = JintEnvironment.NewDeclarativeEnvironment(_engine, evalRealm.GlobalEnv);
+                    varEnv = evalRealm.GlobalEnv;
+                    privateEnv = null;
                 }
                 }
 
 
                 if (strictEval)
                 if (strictEval)
@@ -111,12 +130,12 @@ namespace Jint.Native.Function
                 }
                 }
 
 
                 // If ctx is not already suspended, suspend ctx.
                 // If ctx is not already suspended, suspend ctx.
-                
-                Engine.EnterExecutionContext(lexEnv, varEnv);
-                
+
+                Engine.EnterExecutionContext(lexEnv, varEnv, evalRealm, privateEnv);
+
                 try
                 try
                 {
                 {
-                    Engine.EvalDeclarationInstantiation(script, varEnv, lexEnv, strictEval);
+                    Engine.EvalDeclarationInstantiation(script, varEnv, lexEnv, privateEnv, strictEval);
 
 
                     var statement = new JintScript(_engine, script);
                     var statement = new JintScript(_engine, script);
                     var result = statement.Execute();
                     var result = statement.Execute();

+ 31 - 29
Jint/Native/Function/FunctionConstructor.cs

@@ -13,36 +13,28 @@ namespace Jint.Native.Function
         private static readonly JsString _functionName = new JsString("Function");
         private static readonly JsString _functionName = new JsString("Function");
         private static readonly JsString _functionNameAnonymous = new JsString("anonymous");
         private static readonly JsString _functionNameAnonymous = new JsString("anonymous");
 
 
-        private FunctionConstructor(Engine engine)
-            : base(engine, _functionName)
+        internal FunctionConstructor(
+            Engine engine,
+            Realm realm,
+            ObjectPrototype objectPrototype)
+            : base(engine, realm, _functionName)
         {
         {
+            PrototypeObject = new FunctionPrototype(engine, realm, objectPrototype);
+            _prototype = PrototypeObject;
+            _prototypeDescriptor = new PropertyDescriptor(PrototypeObject, PropertyFlag.AllForbidden);
+            _length = new PropertyDescriptor(JsNumber.One, PropertyFlag.Configurable);
         }
         }
 
 
-        public static FunctionConstructor CreateFunctionConstructor(Engine engine)
-        {
-            var obj = new FunctionConstructor(engine)
-            {
-                PrototypeObject = FunctionPrototype.CreatePrototypeObject(engine)
-            };
-
-            // The initial value of Function.prototype is the standard built-in Function prototype object
-
-            // The value of the [[Prototype]] internal property of the Function constructor is the standard built-in Function prototype object
-            obj._prototype = obj.PrototypeObject;
-
-            obj._prototypeDescriptor = new PropertyDescriptor(obj.PrototypeObject, PropertyFlag.AllForbidden);
-            obj._length = new PropertyDescriptor(JsNumber.One, PropertyFlag.Configurable);
-
-            return obj;
-        }
-
-        public FunctionPrototype PrototypeObject { get; private set; }
+        public FunctionPrototype PrototypeObject { get; }
 
 
         public override JsValue Call(JsValue thisObject, JsValue[] arguments)
         public override JsValue Call(JsValue thisObject, JsValue[] arguments)
         {
         {
             return Construct(arguments, thisObject);
             return Construct(arguments, thisObject);
         }
         }
 
 
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-createdynamicfunction
+        /// </summary>
         public ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
         public ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
         {
         {
             var argCount = arguments.Length;
             var argCount = arguments.Length;
@@ -66,7 +58,7 @@ namespace Jint.Native.Function
                 body = TypeConverter.ToString(arguments[argCount-1]);
                 body = TypeConverter.ToString(arguments[argCount-1]);
             }
             }
 
 
-            IFunction function;
+            IFunction function = null;
             try
             try
             {
             {
                 string functionExpression;
                 string functionExpression;
@@ -105,15 +97,22 @@ namespace Jint.Native.Function
             }
             }
             catch (ParserException)
             catch (ParserException)
             {
             {
-                return ExceptionHelper.ThrowSyntaxError<ObjectInstance>(_engine);
+                ExceptionHelper.ThrowSyntaxError(_realm);
             }
             }
 
 
+            // TODO generators etc, rewrite logic
+            var proto = GetPrototypeFromConstructor(newTarget, static intrinsics => intrinsics.Function.PrototypeObject);
+
             var functionObject = new ScriptFunctionInstance(
             var functionObject = new ScriptFunctionInstance(
                 Engine,
                 Engine,
                 function,
                 function,
-                _engine.GlobalEnvironment,
-                function.Strict);
-            
+                _realm.GlobalEnv,
+                function.Strict,
+                proto)
+            {
+                _realm = _realm
+            };
+
             functionObject.MakeConstructor();
             functionObject.MakeConstructor();
 
 
             // the function is not actually a named function
             // the function is not actually a named function
@@ -130,9 +129,12 @@ namespace Jint.Native.Function
             var functionObject = new ScriptFunctionInstance(
             var functionObject = new ScriptFunctionInstance(
                 Engine,
                 Engine,
                 functionDeclaration,
                 functionDeclaration,
-                env, 
-                functionDeclaration.Strict || _engine._isStrict);
-            
+                env,
+                functionDeclaration.Strict || _engine._isStrict)
+            {
+                _realm = _realm
+            };
+
             functionObject.MakeConstructor();
             functionObject.MakeConstructor();
 
 
             return functionObject;
             return functionObject;

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

@@ -3,6 +3,7 @@ using System.Collections.Generic;
 using System.Runtime.CompilerServices;
 using System.Runtime.CompilerServices;
 using Esprima.Ast;
 using Esprima.Ast;
 using Jint.Native.Object;
 using Jint.Native.Object;
+using Jint.Native.Proxy;
 using Jint.Runtime;
 using Jint.Runtime;
 using Jint.Runtime.Descriptors;
 using Jint.Runtime.Descriptors;
 using Jint.Runtime.Environments;
 using Jint.Runtime.Environments;
@@ -23,12 +24,28 @@ namespace Jint.Native.Function
         internal JsValue _homeObject = Undefined;
         internal JsValue _homeObject = Undefined;
         internal ConstructorKind _constructorKind = ConstructorKind.Base;
         internal ConstructorKind _constructorKind = ConstructorKind.Base;
 
 
+        internal Realm _realm;
+        private PrivateEnvironmentRecord  _privateEnvironment;
+
+        protected FunctionInstance(
+            Engine engine,
+            Realm realm,
+            JsString name)
+            : this(engine, realm, name, FunctionThisMode.Global, ObjectClass.Function)
+        {
+        }
+
         internal FunctionInstance(
         internal FunctionInstance(
             Engine engine,
             Engine engine,
+            Realm realm,
             JintFunctionDefinition function,
             JintFunctionDefinition function,
             EnvironmentRecord scope,
             EnvironmentRecord scope,
             FunctionThisMode thisMode)
             FunctionThisMode thisMode)
-            : this(engine, !string.IsNullOrWhiteSpace(function.Name) ? new JsString(function.Name) : null, thisMode)
+            : this(
+                engine,
+                realm,
+                !string.IsNullOrWhiteSpace(function.Name) ? new JsString(function.Name) : null,
+                thisMode)
         {
         {
             _functionDefinition = function;
             _functionDefinition = function;
             _environment = scope;
             _environment = scope;
@@ -36,6 +53,7 @@ namespace Jint.Native.Function
 
 
         internal FunctionInstance(
         internal FunctionInstance(
             Engine engine,
             Engine engine,
+            Realm realm,
             JsString name,
             JsString name,
             FunctionThisMode thisMode = FunctionThisMode.Global,
             FunctionThisMode thisMode = FunctionThisMode.Global,
             ObjectClass objectClass = ObjectClass.Function)
             ObjectClass objectClass = ObjectClass.Function)
@@ -45,16 +63,10 @@ namespace Jint.Native.Function
             {
             {
                 _nameDescriptor = new PropertyDescriptor(name, PropertyFlag.Configurable);
                 _nameDescriptor = new PropertyDescriptor(name, PropertyFlag.Configurable);
             }
             }
+            _realm = realm;
             _thisMode = thisMode;
             _thisMode = thisMode;
         }
         }
 
 
-        protected FunctionInstance(
-            Engine engine,
-            JsString name)
-            : this(engine, name, FunctionThisMode.Global, ObjectClass.Function)
-        {
-        }
-
         // for example RavenDB wants to inspect this
         // for example RavenDB wants to inspect this
         public IFunction FunctionDeclaration => _functionDefinition.Function;
         public IFunction FunctionDeclaration => _functionDefinition.Function;
 
 
@@ -212,29 +224,63 @@ namespace Jint.Native.Function
         /// </summary>
         /// </summary>
         /// <remarks>
         /// <remarks>
         /// Uses separate builder to get correct type with state support to prevent allocations.
         /// Uses separate builder to get correct type with state support to prevent allocations.
+        /// In spec intrinsicDefaultProto is string pointing to intrinsic, but we do a selector.
         /// </remarks>
         /// </remarks>
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         internal T OrdinaryCreateFromConstructor<T>(
         internal T OrdinaryCreateFromConstructor<T>(
             JsValue constructor,
             JsValue constructor,
-            ObjectInstance intrinsicDefaultProto,
-            Func<Engine, JsValue, T> objectCreator,
+            Func<Intrinsics, ObjectInstance> intrinsicDefaultProto,
+            Func<Engine, Realm, JsValue, T> objectCreator,
             JsValue state = null) where T : ObjectInstance
             JsValue state = null) where T : ObjectInstance
         {
         {
             var proto = GetPrototypeFromConstructor(constructor, intrinsicDefaultProto);
             var proto = GetPrototypeFromConstructor(constructor, intrinsicDefaultProto);
 
 
-            var obj = objectCreator(_engine, state);
+            var obj = objectCreator(_engine, _realm, state);
             obj._prototype = proto;
             obj._prototype = proto;
             return obj;
             return obj;
         }
         }
 
 
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-getprototypefromconstructor
+        /// </summary>
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        internal static ObjectInstance GetPrototypeFromConstructor(JsValue constructor, ObjectInstance intrinsicDefaultProto)
+        internal ObjectInstance GetPrototypeFromConstructor(JsValue constructor, Func<Intrinsics, ObjectInstance> intrinsicDefaultProto)
         {
         {
             var proto = constructor.Get(CommonProperties.Prototype, constructor) as ObjectInstance;
             var proto = constructor.Get(CommonProperties.Prototype, constructor) as ObjectInstance;
-            // If Type(proto) is not Object, then
-            //    Let realm be ? GetFunctionRealm(constructor).
-            //    Set proto to realm's intrinsic object named intrinsicDefaultProto.
-            return proto ?? intrinsicDefaultProto;
+            if (proto is null)
+            {
+                var realm = GetFunctionRealm(constructor);
+                proto = intrinsicDefaultProto(realm.Intrinsics);
+            }
+            return proto;
+        }
+
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-getfunctionrealm
+        /// </summary>
+        internal Realm GetFunctionRealm(JsValue obj)
+        {
+            if (obj is FunctionInstance functionInstance && functionInstance._realm is not null)
+            {
+                return functionInstance._realm;
+            }
+
+            if (obj is BindFunctionInstance bindFunctionInstance)
+            {
+                return GetFunctionRealm(bindFunctionInstance.TargetFunction);
+            }
+
+            if (obj is ProxyInstance proxyInstance)
+            {
+                if (proxyInstance._handler is null)
+                {
+                    ExceptionHelper.ThrowTypeErrorNoEngine();
+                }
+
+                return GetFunctionRealm(proxyInstance._target);
+            }
+
+            return _engine.ExecutionContext.Realm;
         }
         }
 
 
         internal void MakeMethod(ObjectInstance homeObject)
         internal void MakeMethod(ObjectInstance homeObject)
@@ -245,7 +291,7 @@ namespace Jint.Native.Function
         /// <summary>
         /// <summary>
         /// https://tc39.es/ecma262/#sec-ordinarycallbindthis
         /// https://tc39.es/ecma262/#sec-ordinarycallbindthis
         /// </summary>
         /// </summary>
-        protected void OrdinaryCallBindThis(ExecutionContext calleeContext, JsValue thisArgument)
+        internal void OrdinaryCallBindThis(ExecutionContext calleeContext, JsValue thisArgument)
         {
         {
             var thisMode = _thisMode;
             var thisMode = _thisMode;
             if (thisMode == FunctionThisMode.Lexical)
             if (thisMode == FunctionThisMode.Lexical)
@@ -253,7 +299,7 @@ namespace Jint.Native.Function
                 return;
                 return;
             }
             }
 
 
-            // Let calleeRealm be F.[[Realm]].
+            var calleeRealm = _realm;
 
 
             var localEnv = (FunctionEnvironmentRecord) calleeContext.LexicalEnvironment;
             var localEnv = (FunctionEnvironmentRecord) calleeContext.LexicalEnvironment;
 
 
@@ -266,20 +312,19 @@ namespace Jint.Native.Function
             {
             {
                 if (thisArgument.IsNullOrUndefined())
                 if (thisArgument.IsNullOrUndefined())
                 {
                 {
-                    // Let globalEnv be calleeRealm.[[GlobalEnv]].
-                    var globalEnv = _engine.GlobalEnvironment;
+                    var globalEnv = calleeRealm.GlobalEnv;
                     thisValue = globalEnv.GlobalThisValue;
                     thisValue = globalEnv.GlobalThisValue;
                 }
                 }
                 else
                 else
                 {
                 {
-                    thisValue = TypeConverter.ToObject(_engine, thisArgument);
+                    thisValue = TypeConverter.ToObject(calleeRealm, thisArgument);
                 }
                 }
             }
             }
 
 
             localEnv.BindThisValue(thisValue);
             localEnv.BindThisValue(thisValue);
         }
         }
 
 
-        protected Completion OrdinaryCallEvaluateBody(
+        internal Completion OrdinaryCallEvaluateBody(
             JsValue[] arguments,
             JsValue[] arguments,
             ExecutionContext calleeContext)
             ExecutionContext calleeContext)
         {
         {
@@ -299,20 +344,26 @@ namespace Jint.Native.Function
         /// <summary>
         /// <summary>
         /// https://tc39.es/ecma262/#sec-prepareforordinarycall
         /// https://tc39.es/ecma262/#sec-prepareforordinarycall
         /// </summary>
         /// </summary>
-        protected ExecutionContext PrepareForOrdinaryCall(JsValue newTarget)
+        internal ExecutionContext PrepareForOrdinaryCall(JsValue newTarget)
         {
         {
-            // ** PrepareForOrdinaryCall **
-            // var callerContext = _engine.ExecutionContext;
-            // Let calleeRealm be F.[[Realm]].
-            // Set the Realm of calleeContext to calleeRealm.
-            // Set the ScriptOrModule of calleeContext to F.[[ScriptOrModule]].
-            var calleeContext = JintEnvironment.NewFunctionEnvironment(_engine, this, newTarget);
+            var callerContext = _engine.ExecutionContext;
+
+            var localEnv = JintEnvironment.NewFunctionEnvironment(_engine, this, newTarget);
+            var calleeRealm = _realm;
+
+            var calleeContext = new ExecutionContext(
+                localEnv,
+                localEnv,
+                _privateEnvironment,
+                calleeRealm,
+                this);
+
             // If callerContext is not already suspended, suspend callerContext.
             // If callerContext is not already suspended, suspend callerContext.
             // Push calleeContext onto the execution context stack; calleeContext is now the running execution context.
             // Push calleeContext onto the execution context stack; calleeContext is now the running execution context.
             // NOTE: Any exception objects produced after this point are associated with calleeRealm.
             // NOTE: Any exception objects produced after this point are associated with calleeRealm.
             // Return calleeContext.
             // Return calleeContext.
 
 
-            return _engine.EnterExecutionContext(calleeContext, calleeContext);
+            return _engine.EnterExecutionContext(calleeContext);
         }
         }
 
 
         public override string ToString()
         public override string ToString()

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

@@ -13,21 +13,14 @@ namespace Jint.Native.Function
     /// </summary>
     /// </summary>
     public sealed class FunctionPrototype : FunctionInstance
     public sealed class FunctionPrototype : FunctionInstance
     {
     {
-        private FunctionPrototype(Engine engine)
-            : base(engine, JsString.Empty)
+        internal FunctionPrototype(
+            Engine engine,
+            Realm realm,
+            ObjectPrototype objectPrototype)
+            : base(engine, realm, JsString.Empty)
         {
         {
-        }
-
-        public static FunctionPrototype CreatePrototypeObject(Engine engine)
-        {
-            var obj = new FunctionPrototype(engine)
-            {
-                // The value of the [[Prototype]] internal property of the Function prototype object is the standard built-in Object prototype object
-                _prototype = engine.Object.PrototypeObject,
-                _length = PropertyDescriptor.AllForbiddenDescriptor.NumberZero
-            };
-
-            return obj;
+            _prototype = objectPrototype;
+            _length = PropertyDescriptor.AllForbiddenDescriptor.NumberZero;
         }
         }
 
 
         protected override void Initialize()
         protected override void Initialize()
@@ -36,7 +29,7 @@ namespace Jint.Native.Function
             const PropertyFlag lengthFlags = PropertyFlag.Configurable;
             const PropertyFlag lengthFlags = PropertyFlag.Configurable;
             var properties = new PropertyDictionary(7, checkExistingKeys: false)
             var properties = new PropertyDictionary(7, checkExistingKeys: false)
             {
             {
-                ["constructor"] = new PropertyDescriptor(Engine.Function, PropertyFlag.NonEnumerable),
+                ["constructor"] = new PropertyDescriptor(_realm.Intrinsics.Function, PropertyFlag.NonEnumerable),
                 ["toString"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "toString", ToString, 0, lengthFlags), propertyFlags),
                 ["toString"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "toString", ToString, 0, lengthFlags), propertyFlags),
                 ["apply"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "apply", Apply, 2, lengthFlags), propertyFlags),
                 ["apply"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "apply", Apply, 2, lengthFlags), propertyFlags),
                 ["call"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "call", CallImpl, 1, lengthFlags), propertyFlags),
                 ["call"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "call", CallImpl, 1, lengthFlags), propertyFlags),
@@ -67,7 +60,7 @@ namespace Jint.Native.Function
         {
         {
             if (thisObj is not ICallable)
             if (thisObj is not ICallable)
             {
             {
-                ExceptionHelper.ThrowTypeError(Engine, "Bind must be called on a function");
+                ExceptionHelper.ThrowTypeError(_realm, "Bind must be called on a function");
             }
             }
 
 
             var thisArg = arguments.At(0);
             var thisArg = arguments.At(0);
@@ -114,7 +107,7 @@ namespace Jint.Native.Function
         private FunctionInstance BoundFunctionCreate(ObjectInstance targetFunction, JsValue boundThis, JsValue[] boundArgs)
         private FunctionInstance BoundFunctionCreate(ObjectInstance targetFunction, JsValue boundThis, JsValue[] boundArgs)
         {
         {
             var proto = targetFunction.GetPrototypeOf();
             var proto = targetFunction.GetPrototypeOf();
-            var obj = new BindFunctionInstance(Engine)
+            var obj = new BindFunctionInstance(_engine, _realm)
             {
             {
                 _prototype = proto,
                 _prototype = proto,
                 TargetFunction = targetFunction,
                 TargetFunction = targetFunction,
@@ -131,12 +124,17 @@ namespace Jint.Native.Function
                 return thisObj.ToString();
                 return thisObj.ToString();
             }
             }
 
 
-            return ExceptionHelper.ThrowTypeError<FunctionInstance>(_engine, "Function.prototype.toString requires that 'this' be a Function");
+            ExceptionHelper.ThrowTypeError(_realm, "Function.prototype.toString requires that 'this' be a Function");
+            return null;
         }
         }
 
 
         internal JsValue Apply(JsValue thisObject, JsValue[] arguments)
         internal JsValue Apply(JsValue thisObject, JsValue[] arguments)
         {
         {
-            var func = thisObject as ICallable ?? ExceptionHelper.ThrowTypeError<ICallable>(Engine);
+            var func = thisObject as ICallable;
+            if (func is null)
+            {
+                ExceptionHelper.ThrowTypeError(_realm);
+            }
             var thisArg = arguments.At(0);
             var thisArg = arguments.At(0);
             var argArray = arguments.At(1);
             var argArray = arguments.At(1);
 
 
@@ -154,7 +152,11 @@ namespace Jint.Native.Function
 
 
         internal JsValue[] CreateListFromArrayLike(JsValue argArray, Types? elementTypes = null)
         internal JsValue[] CreateListFromArrayLike(JsValue argArray, Types? elementTypes = null)
         {
         {
-            var argArrayObj = argArray as ObjectInstance ?? ExceptionHelper.ThrowTypeError<ObjectInstance>(_engine);
+            var argArrayObj = argArray as ObjectInstance;
+            if (argArrayObj is null)
+            {
+                ExceptionHelper.ThrowTypeError(_realm);
+            }
             var operations = ArrayOperations.For(argArrayObj);
             var operations = ArrayOperations.For(argArrayObj);
             var allowedTypes = elementTypes ??
             var allowedTypes = elementTypes ??
                                Types.Undefined | Types.Null | Types.Boolean | Types.String | Types.Symbol | Types.Number | Types.Object;
                                Types.Undefined | Types.Null | Types.Boolean | Types.String | Types.Symbol | Types.Number | Types.Object;
@@ -165,7 +167,11 @@ namespace Jint.Native.Function
 
 
         private JsValue CallImpl(JsValue thisObject, JsValue[] arguments)
         private JsValue CallImpl(JsValue thisObject, JsValue[] arguments)
         {
         {
-            var func = thisObject as ICallable ?? ExceptionHelper.ThrowTypeError<ICallable>(Engine);
+            var func = thisObject as ICallable;
+            if (func is null)
+            {
+                ExceptionHelper.ThrowTypeError(_realm);
+            }
             JsValue[] values = System.Array.Empty<JsValue>();
             JsValue[] values = System.Array.Empty<JsValue>();
             if (arguments.Length > 1)
             if (arguments.Length > 1)
             {
             {

+ 32 - 24
Jint/Native/Function/ScriptFunctionInstance.cs

@@ -22,7 +22,12 @@ namespace Jint.Native.Function
             EnvironmentRecord scope,
             EnvironmentRecord scope,
             bool strict,
             bool strict,
             ObjectInstance proto = null)
             ObjectInstance proto = null)
-            : this(engine, new JintFunctionDefinition(engine, functionDeclaration), scope, strict ? FunctionThisMode.Strict : FunctionThisMode.Global, proto)
+            : this(
+                engine,
+                new JintFunctionDefinition(engine, functionDeclaration),
+                scope,
+                strict ? FunctionThisMode.Strict : FunctionThisMode.Global,
+                proto)
         {
         {
         }
         }
 
 
@@ -32,10 +37,10 @@ namespace Jint.Native.Function
             EnvironmentRecord scope,
             EnvironmentRecord scope,
             FunctionThisMode thisMode,
             FunctionThisMode thisMode,
             ObjectInstance proto = null)
             ObjectInstance proto = null)
-            : base(engine, function, scope, thisMode)
+            : base(engine, engine.Realm, function, scope, thisMode)
         {
         {
-            _prototype = proto ?? _engine.Function.PrototypeObject;
-            _length = new LazyPropertyDescriptor(() => JsNumber.Create(function.Initialize(engine, this).Length), PropertyFlag.Configurable);
+            _prototype = proto ?? _engine.Realm.Intrinsics.Function.PrototypeObject;
+            _length = new LazyPropertyDescriptor(null, _ => JsNumber.Create(function.Initialize(this).Length), PropertyFlag.Configurable);
 
 
             if (!function.Strict && !engine._isStrict && function.Function is not ArrowFunctionExpression)
             if (!function.Strict && !engine._isStrict && function.Function is not ArrowFunctionExpression)
             {
             {
@@ -49,22 +54,21 @@ namespace Jint.Native.Function
         /// </summary>
         /// </summary>
         public override JsValue Call(JsValue thisArgument, JsValue[] arguments)
         public override JsValue Call(JsValue thisArgument, JsValue[] arguments)
         {
         {
-            if (_isClassConstructor)
-            {
-                ExceptionHelper.ThrowTypeError(_engine, $"Class constructor {_functionDefinition.Name} cannot be invoked without 'new'");
-            }
-
-            var calleeContext = PrepareForOrdinaryCall(Undefined);
-
-            OrdinaryCallBindThis(calleeContext, thisArgument);
-
-            // actual call
-
             var strict = _thisMode == FunctionThisMode.Strict || _engine._isStrict;
             var strict = _thisMode == FunctionThisMode.Strict || _engine._isStrict;
             using (new StrictModeScope(strict, true))
             using (new StrictModeScope(strict, true))
             {
             {
                 try
                 try
                 {
                 {
+                    var calleeContext = PrepareForOrdinaryCall(Undefined);
+
+                    if (_isClassConstructor)
+                    {
+                        ExceptionHelper.ThrowTypeError(calleeContext.Realm, $"Class constructor {_functionDefinition.Name} cannot be invoked without 'new'");
+                    }
+
+                    OrdinaryCallBindThis(calleeContext, thisArgument);
+
+                    // actual call
                     var result = OrdinaryCallEvaluateBody(arguments, calleeContext);
                     var result = OrdinaryCallEvaluateBody(arguments, calleeContext);
 
 
                     if (result.Type == CompletionType.Throw)
                     if (result.Type == CompletionType.Throw)
@@ -98,7 +102,7 @@ namespace Jint.Native.Function
         }
         }
 
 
         internal override bool IsConstructor =>
         internal override bool IsConstructor =>
-            (_homeObject.IsUndefined() || _isClassConstructor) 
+            (_homeObject.IsUndefined() || _isClassConstructor)
             && _functionDefinition?.Function is not ArrowFunctionExpression;
             && _functionDefinition?.Function is not ArrowFunctionExpression;
 
 
         /// <summary>
         /// <summary>
@@ -106,13 +110,17 @@ namespace Jint.Native.Function
         /// </summary>
         /// </summary>
         public ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
         public ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
         {
         {
+            var callerContext = _engine.ExecutionContext;
             var kind = _constructorKind;
             var kind = _constructorKind;
 
 
             var thisArgument = Undefined;
             var thisArgument = Undefined;
-            
+
             if (kind == ConstructorKind.Base)
             if (kind == ConstructorKind.Base)
             {
             {
-                thisArgument = OrdinaryCreateFromConstructor(newTarget, _engine.Object.PrototypeObject, static (engine, _) => new ObjectInstance(engine));
+                thisArgument = OrdinaryCreateFromConstructor(
+                    newTarget,
+                    static intrinsics => intrinsics.Object.PrototypeObject,
+                    static (engine, realm, _) => new ObjectInstance(engine));
             }
             }
 
 
             var calleeContext = PrepareForOrdinaryCall(newTarget);
             var calleeContext = PrepareForOrdinaryCall(newTarget);
@@ -123,7 +131,7 @@ namespace Jint.Native.Function
             }
             }
 
 
             var constructorEnv = (FunctionEnvironmentRecord) calleeContext.LexicalEnvironment;
             var constructorEnv = (FunctionEnvironmentRecord) calleeContext.LexicalEnvironment;
-            
+
             var strict = _thisMode == FunctionThisMode.Strict || _engine._isStrict;
             var strict = _thisMode == FunctionThisMode.Strict || _engine._isStrict;
             using (new StrictModeScope(strict, force: true))
             using (new StrictModeScope(strict, force: true))
             {
             {
@@ -156,7 +164,7 @@ namespace Jint.Native.Function
 
 
                         if (!result.Value.IsUndefined())
                         if (!result.Value.IsUndefined())
                         {
                         {
-                            ExceptionHelper.ThrowTypeError(_engine);
+                            ExceptionHelper.ThrowTypeError(callerContext.Realm);
                         }
                         }
                     }
                     }
                     else if (result.Type == CompletionType.Throw)
                     else if (result.Type == CompletionType.Throw)
@@ -172,7 +180,7 @@ namespace Jint.Native.Function
 
 
             return (ObjectInstance) constructorEnv.GetThisBinding();
             return (ObjectInstance) constructorEnv.GetThisBinding();
         }
         }
-        
+
         internal void MakeConstructor(bool writableProperty = true, ObjectInstance prototype = null)
         internal void MakeConstructor(bool writableProperty = true, ObjectInstance prototype = null)
         {
         {
             _constructorKind = ConstructorKind.Base;
             _constructorKind = ConstructorKind.Base;
@@ -180,18 +188,18 @@ namespace Jint.Native.Function
             {
             {
                 prototype = new ObjectInstanceWithConstructor(_engine, this)
                 prototype = new ObjectInstanceWithConstructor(_engine, this)
                 {
                 {
-                    _prototype = _engine.Object.PrototypeObject
+                    _prototype = _realm.Intrinsics.Object.PrototypeObject
                 };
                 };
             }
             }
 
 
             _prototypeDescriptor = new PropertyDescriptor(prototype, writableProperty, enumerable: false, configurable: false);
             _prototypeDescriptor = new PropertyDescriptor(prototype, writableProperty, enumerable: false, configurable: false);
-        }        
+        }
 
 
         internal void MakeClassConstructor()
         internal void MakeClassConstructor()
         {
         {
             _isClassConstructor = true;
             _isClassConstructor = true;
         }
         }
-        
+
         private class ObjectInstanceWithConstructor : ObjectInstance
         private class ObjectInstanceWithConstructor : ObjectInstance
         {
         {
             private PropertyDescriptor _constructor;
             private PropertyDescriptor _constructor;

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

@@ -9,18 +9,22 @@ namespace Jint.Native.Function
 
 
         private readonly string _message;
         private readonly string _message;
 
 
-        public ThrowTypeError(Engine engine, string message = null)
-            : base(engine, _functionName)
+        public ThrowTypeError(
+            Engine engine,
+            Realm realm,
+            string message = null)
+            : base(engine, realm, _functionName)
         {
         {
             _message = message;
             _message = message;
             _length = PropertyDescriptor.AllForbiddenDescriptor.NumberZero;
             _length = PropertyDescriptor.AllForbiddenDescriptor.NumberZero;
-            _environment = engine.GlobalEnvironment;
+            _environment = realm.GlobalEnv;
             PreventExtensions();
             PreventExtensions();
         }
         }
 
 
         public override JsValue Call(JsValue thisObject, JsValue[] arguments)
         public override JsValue Call(JsValue thisObject, JsValue[] arguments)
         {
         {
-            return ExceptionHelper.ThrowTypeError<JsValue>(_engine, _message);
+            ExceptionHelper.ThrowTypeError(_realm, _message);
+            return null;
         }
         }
     }
     }
 }
 }

+ 93 - 62
Jint/Native/Global/GlobalObject.cs

@@ -16,65 +16,96 @@ namespace Jint.Native.Global
 {
 {
     public sealed class GlobalObject : ObjectInstance
     public sealed class GlobalObject : ObjectInstance
     {
     {
-        private readonly StringBuilder _stringBuilder = new StringBuilder();
+        private readonly Realm _realm;
+        private readonly StringBuilder _stringBuilder = new();
 
 
-        private GlobalObject(Engine engine) : base(engine)
+        internal GlobalObject(
+            Engine engine,
+            Realm realm) : base(engine)
         {
         {
-        }
-
-        public static GlobalObject CreateGlobalObject(Engine engine)
-        {
-            return new GlobalObject(engine);
+            _realm = realm;
+            // this is implementation dependent, and only to pass some unit tests
+            _prototype = realm.Intrinsics.Object.PrototypeObject;
         }
         }
 
 
         protected override void Initialize()
         protected override void Initialize()
         {
         {
             const PropertyFlag lengthFlags = PropertyFlag.Configurable;
             const PropertyFlag lengthFlags = PropertyFlag.Configurable;
             const PropertyFlag propertyFlags = PropertyFlag.Configurable | PropertyFlag.Writable;
             const PropertyFlag propertyFlags = PropertyFlag.Configurable | PropertyFlag.Writable;
-            var properties = new PropertyDictionary(42, checkExistingKeys: false)
+
+            var properties = new PropertyDictionary(40, checkExistingKeys: false)
             {
             {
-                ["Object"] = new PropertyDescriptor(Engine.Object, propertyFlags),
-                ["Function"] = new PropertyDescriptor(Engine.Function, propertyFlags),
-                ["Symbol"] = new PropertyDescriptor(Engine.Symbol, propertyFlags),
-                ["Array"] = new PropertyDescriptor(Engine.Array, propertyFlags),
-                ["Map"] = new PropertyDescriptor(Engine.Map, propertyFlags),
-                ["Set"] = new PropertyDescriptor(Engine.Set, propertyFlags),
-                ["WeakMap"] = new PropertyDescriptor(Engine.WeakMap, propertyFlags),
-                ["WeakSet"] = new PropertyDescriptor(Engine.WeakSet, propertyFlags),
-                ["Promise"] = new PropertyDescriptor(Engine.Promise, propertyFlags),
-                ["String"] = new PropertyDescriptor(Engine.String, propertyFlags),
-                ["RegExp"] = new PropertyDescriptor(Engine.RegExp, propertyFlags),
-                ["Number"] = new PropertyDescriptor(Engine.Number, propertyFlags),
-                ["Boolean"] = new PropertyDescriptor(Engine.Boolean, propertyFlags),
-                ["Date"] = new PropertyDescriptor(Engine.Date, propertyFlags),
-                ["Math"] = new PropertyDescriptor(Engine.Math, propertyFlags),
-                ["JSON"] = new PropertyDescriptor(Engine.Json, propertyFlags),
-                ["Error"] = new LazyPropertyDescriptor(() => Engine.Error, propertyFlags),
-                ["EvalError"] = new LazyPropertyDescriptor(() => Engine.EvalError, propertyFlags),
-                ["Proxy"] = new LazyPropertyDescriptor(() => Engine.Proxy, propertyFlags),
-                ["RangeError"] = new LazyPropertyDescriptor(() => Engine.RangeError, propertyFlags),
-                ["ReferenceError"] = new LazyPropertyDescriptor(() => Engine.ReferenceError, propertyFlags),
-                ["Reflect"] = new LazyPropertyDescriptor(() => Engine.Reflect, propertyFlags),
-                ["SyntaxError"] = new LazyPropertyDescriptor(() => Engine.SyntaxError, propertyFlags),
-                ["TypeError"] = new LazyPropertyDescriptor(() => Engine.TypeError, propertyFlags),
-                ["URIError"] = new LazyPropertyDescriptor(() => Engine.UriError, propertyFlags),
+                ["Object"] = new PropertyDescriptor(_realm.Intrinsics.Object, propertyFlags),
+                ["Function"] = new PropertyDescriptor(_realm.Intrinsics.Function, propertyFlags),
+                ["Symbol"] = new LazyPropertyDescriptor(this, static state => ((GlobalObject) state)._realm.Intrinsics.Symbol, propertyFlags),
+                ["Array"] = new LazyPropertyDescriptor(this, static state => ((GlobalObject) state)._realm.Intrinsics.Array, propertyFlags),
+                ["Map"] = new LazyPropertyDescriptor(this, static state => ((GlobalObject) state)._realm.Intrinsics.Map, propertyFlags),
+                ["Set"] = new LazyPropertyDescriptor(this, static state => ((GlobalObject) state)._realm.Intrinsics.Set, propertyFlags),
+                ["WeakMap"] = new LazyPropertyDescriptor(this, static state => ((GlobalObject) state)._realm.Intrinsics.WeakMap, propertyFlags),
+                ["WeakSet"] = new LazyPropertyDescriptor(this, static state => ((GlobalObject) state)._realm.Intrinsics.WeakSet, propertyFlags),
+                ["Promise"] = new LazyPropertyDescriptor(this, static state => ((GlobalObject) state)._realm.Intrinsics.Promise, propertyFlags),
+                ["String"] = new LazyPropertyDescriptor(this, static state => ((GlobalObject) state)._realm.Intrinsics.String, propertyFlags),
+                ["RegExp"] = new LazyPropertyDescriptor(this, static state => ((GlobalObject) state)._realm.Intrinsics.RegExp, propertyFlags),
+                ["Number"] = new LazyPropertyDescriptor(this, static state => ((GlobalObject) state)._realm.Intrinsics.Number, propertyFlags),
+                ["Boolean"] = new LazyPropertyDescriptor(this, static state => ((GlobalObject) state)._realm.Intrinsics.Boolean, propertyFlags),
+                ["Date"] = new LazyPropertyDescriptor(this, static state => ((GlobalObject) state)._realm.Intrinsics.Date, propertyFlags),
+                ["Math"] = new LazyPropertyDescriptor(this, static state => ((GlobalObject) state)._realm.Intrinsics.Math, propertyFlags),
+                ["JSON"] = new LazyPropertyDescriptor(this, static state => ((GlobalObject) state)._realm.Intrinsics.Json, propertyFlags),
+                ["Error"] = new LazyPropertyDescriptor(this, static state => ((GlobalObject) state)._realm.Intrinsics.Error, propertyFlags),
+                ["EvalError"] = new LazyPropertyDescriptor(this, static state => ((GlobalObject) state)._realm.Intrinsics.EvalError, propertyFlags),
+                ["Proxy"] = new LazyPropertyDescriptor(this, static state => ((GlobalObject) state)._realm.Intrinsics.Proxy, propertyFlags),
+                ["RangeError"] = new LazyPropertyDescriptor(this, static state => ((GlobalObject) state)._realm.Intrinsics.RangeError, propertyFlags),
+                ["ReferenceError"] = new LazyPropertyDescriptor(this, static state => ((GlobalObject) state)._realm.Intrinsics.ReferenceError, propertyFlags),
+                ["Reflect"] = new LazyPropertyDescriptor(this, static state => ((GlobalObject) state)._realm.Intrinsics.Reflect, propertyFlags),
+                ["SyntaxError"] = new LazyPropertyDescriptor(this, static state => ((GlobalObject) state)._realm.Intrinsics.SyntaxError, propertyFlags),
+                ["TypeError"] = new LazyPropertyDescriptor(this, static state => ((GlobalObject) state)._realm.Intrinsics.TypeError, propertyFlags),
+                ["URIError"] = new LazyPropertyDescriptor(this, static state => ((GlobalObject) state)._realm.Intrinsics.UriError, propertyFlags),
                 ["NaN"] = new PropertyDescriptor(double.NaN, PropertyFlag.None),
                 ["NaN"] = new PropertyDescriptor(double.NaN, PropertyFlag.None),
                 ["Infinity"] = new PropertyDescriptor(double.PositiveInfinity, PropertyFlag.None),
                 ["Infinity"] = new PropertyDescriptor(double.PositiveInfinity, PropertyFlag.None),
                 ["undefined"] = new PropertyDescriptor(Undefined, PropertyFlag.None),
                 ["undefined"] = new PropertyDescriptor(Undefined, PropertyFlag.None),
-                ["parseInt"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "parseInt", ParseInt, 2, lengthFlags), propertyFlags),
-                ["parseFloat"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "parseFloat", ParseFloat, 1, lengthFlags), propertyFlags),
-                ["isNaN"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "isNaN", IsNaN, 1, lengthFlags), propertyFlags),
-                ["isFinite"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "isFinite", IsFinite, 1, lengthFlags), propertyFlags),
-                ["decodeURI"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "decodeURI", DecodeUri, 1, lengthFlags), propertyFlags),
-                ["decodeURIComponent"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "decodeURIComponent", DecodeUriComponent, 1, lengthFlags), propertyFlags),
-                ["encodeURI"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "encodeURI", EncodeUri, 1, lengthFlags), propertyFlags),
-                ["encodeURIComponent"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "encodeURIComponent", EncodeUriComponent, 1, lengthFlags), propertyFlags),
-                ["escape"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "escape", Escape, 1, lengthFlags), propertyFlags),
-                ["unescape"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "unescape", Unescape, 1, lengthFlags), propertyFlags),
+                ["parseInt"] = new LazyPropertyDescriptor(this, static state => new ClrFunctionInstance(((GlobalObject) state)._engine, "parseInt", ParseInt, 2, lengthFlags), propertyFlags),
+                ["parseFloat"] = new LazyPropertyDescriptor(this, static state => new ClrFunctionInstance(((GlobalObject) state)._engine, "parseFloat", ParseFloat, 1, lengthFlags), propertyFlags),
+                ["isNaN"] = new LazyPropertyDescriptor(this, static state => new ClrFunctionInstance(((GlobalObject) state)._engine, "isNaN", IsNaN, 1, lengthFlags), propertyFlags),
+                ["isFinite"] = new LazyPropertyDescriptor(this, static state => new ClrFunctionInstance(((GlobalObject) state)._engine, "isFinite", IsFinite, 1, lengthFlags), propertyFlags),
+                ["decodeURI"] = new LazyPropertyDescriptor(this, static state =>
+                {
+                    var global = (GlobalObject) state;
+                    return new ClrFunctionInstance(global._engine, "decodeURI", global.DecodeUri, 1, lengthFlags);
+                }, propertyFlags),
+                ["decodeURIComponent"] = new LazyPropertyDescriptor(this, static state =>
+                {
+                    var global = (GlobalObject) state;
+                    return new ClrFunctionInstance(global._engine, "decodeURIComponent", global.DecodeUriComponent, 1, lengthFlags);
+                }, propertyFlags),
+                ["encodeURI"] = new LazyPropertyDescriptor(this, static state =>
+                {
+                    var global = (GlobalObject) state;
+                    return new ClrFunctionInstance(global._engine, "encodeURI", global.EncodeUri, 1, lengthFlags);
+                }, propertyFlags),
+                ["encodeURIComponent"] = new LazyPropertyDescriptor(this, static state =>
+                {
+                    var global = (GlobalObject) state;
+                    return new ClrFunctionInstance(global._engine, "encodeURIComponent", global.EncodeUriComponent, 1, lengthFlags);
+                }, propertyFlags),
+                ["escape"] = new LazyPropertyDescriptor(this, static state =>
+                {
+                    var global = (GlobalObject) state;
+                    return new ClrFunctionInstance(global._engine, "escape", global.Escape, 1, lengthFlags);
+                }, propertyFlags),
+                ["unescape"] = new LazyPropertyDescriptor(this, static state =>
+                {
+                    var global = (GlobalObject) state;
+                    return new ClrFunctionInstance(global._engine, "unescape", global.Unescape, 1, lengthFlags);
+                }, propertyFlags),
                 ["globalThis"] = new PropertyDescriptor(this, propertyFlags),
                 ["globalThis"] = new PropertyDescriptor(this, propertyFlags),
+                ["eval"] = new LazyPropertyDescriptor(this, static state => ((GlobalObject) state)._realm.Intrinsics.Eval, PropertyFlag.Configurable | PropertyFlag.Writable),
 
 
                 // toString is not mentioned or actually required in spec, but some tests rely on it
                 // toString is not mentioned or actually required in spec, but some tests rely on it
-                ["toString"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "toString", ToStringString, 1), propertyFlags)
+                ["toString"] = new LazyPropertyDescriptor(this, static state =>
+                {
+                    var global = (GlobalObject) state;
+                    return new ClrFunctionInstance(global._engine, "toString", global.ToStringString, 1);
+                }, propertyFlags)
             };
             };
 
 
             SetProperties(properties);
             SetProperties(properties);
@@ -82,7 +113,7 @@ namespace Jint.Native.Global
 
 
         private JsValue ToStringString(JsValue thisObj, JsValue[] arguments)
         private JsValue ToStringString(JsValue thisObj, JsValue[] arguments)
         {
         {
-            return _engine.Object.PrototypeObject.ToObjectString(thisObj, Arguments.Empty);
+            return _realm.Intrinsics.Object.PrototypeObject.ToObjectString(thisObj, Arguments.Empty);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -385,7 +416,7 @@ namespace Jint.Native.Global
 
 
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         private static bool IsValidHexaChar(char c) => Uri.IsHexDigit(c);
         private static bool IsValidHexaChar(char c) => Uri.IsHexDigit(c);
-        
+
         /// <summary>
         /// <summary>
         /// http://www.ecma-international.org/ecma-262/5.1/#sec-15.1.3.2
         /// http://www.ecma-international.org/ecma-262/5.1/#sec-15.1.3.2
         /// </summary>
         /// </summary>
@@ -431,7 +462,7 @@ namespace Jint.Native.Global
                 {
                 {
                     if (c >= 0xDC00 && c <= 0xDBFF)
                     if (c >= 0xDC00 && c <= 0xDBFF)
                     {
                     {
-                        ExceptionHelper.ThrowUriError(_engine);
+                        ExceptionHelper.ThrowUriError(_realm);
                     }
                     }
 
 
                     int v;
                     int v;
@@ -444,13 +475,13 @@ namespace Jint.Native.Global
                         k++;
                         k++;
                         if (k == strLen)
                         if (k == strLen)
                         {
                         {
-                            ExceptionHelper.ThrowUriError(_engine);
+                            ExceptionHelper.ThrowUriError(_realm);
                         }
                         }
 
 
                         var kChar = (int)uriString[k];
                         var kChar = (int)uriString[k];
                         if (kChar < 0xDC00 || kChar > 0xDFFF)
                         if (kChar < 0xDC00 || kChar > 0xDFFF)
                         {
                         {
-                            ExceptionHelper.ThrowUriError(_engine);
+                            ExceptionHelper.ThrowUriError(_realm);
                         }
                         }
 
 
                         v = (c - 0xD800) * 0x400 + (kChar - 0xDC00) + 0x10000;
                         v = (c - 0xD800) * 0x400 + (kChar - 0xDC00) + 0x10000;
@@ -484,7 +515,7 @@ namespace Jint.Native.Global
                     }
                     }
                     else if (v <= 0xDFFF)
                     else if (v <= 0xDFFF)
                     {
                     {
-                        ExceptionHelper.ThrowUriError(_engine);
+                        ExceptionHelper.ThrowUriError(_realm);
                     }
                     }
                     else if (v <= 0xFFFF)
                     else if (v <= 0xFFFF)
                     {
                     {
@@ -554,12 +585,12 @@ namespace Jint.Native.Global
                     var start = k;
                     var start = k;
                     if (k + 2 >= strLen)
                     if (k + 2 >= strLen)
                     {
                     {
-                        ExceptionHelper.ThrowUriError(_engine);
+                        ExceptionHelper.ThrowUriError(_realm);
                     }
                     }
 
 
                     if (!IsValidHexaChar(uriString[k + 1]) || !IsValidHexaChar(uriString[k + 2]))
                     if (!IsValidHexaChar(uriString[k + 1]) || !IsValidHexaChar(uriString[k + 2]))
                     {
                     {
-                        ExceptionHelper.ThrowUriError(_engine);
+                        ExceptionHelper.ThrowUriError(_realm);
                     }
                     }
 
 
                     var B = Convert.ToByte(uriString[k + 1].ToString() + uriString[k + 2], 16);
                     var B = Convert.ToByte(uriString[k + 1].ToString() + uriString[k + 2], 16);
@@ -584,7 +615,7 @@ namespace Jint.Native.Global
 
 
                         if (n == 1 || n > 4)
                         if (n == 1 || n > 4)
                         {
                         {
-                            ExceptionHelper.ThrowUriError(_engine);
+                            ExceptionHelper.ThrowUriError(_realm);
                         }
                         }
 
 
                         octets = octets.Length == n
                         octets = octets.Length == n
@@ -595,7 +626,7 @@ namespace Jint.Native.Global
 
 
                         if (k + (3 * (n - 1)) >= strLen)
                         if (k + (3 * (n - 1)) >= strLen)
                         {
                         {
-                            ExceptionHelper.ThrowUriError(_engine);
+                            ExceptionHelper.ThrowUriError(_realm);
                         }
                         }
 
 
                         for (var j = 1; j < n; j++)
                         for (var j = 1; j < n; j++)
@@ -603,12 +634,12 @@ namespace Jint.Native.Global
                             k++;
                             k++;
                             if (uriString[k] != '%')
                             if (uriString[k] != '%')
                             {
                             {
-                                ExceptionHelper.ThrowUriError(_engine);
+                                ExceptionHelper.ThrowUriError(_realm);
                             }
                             }
 
 
                             if (!IsValidHexaChar(uriString[k + 1]) || !IsValidHexaChar(uriString[k + 2]))
                             if (!IsValidHexaChar(uriString[k + 1]) || !IsValidHexaChar(uriString[k + 2]))
                             {
                             {
-                                ExceptionHelper.ThrowUriError(_engine);
+                                ExceptionHelper.ThrowUriError(_realm);
                             }
                             }
 
 
                             B = Convert.ToByte(uriString[k + 1].ToString() + uriString[k + 2], 16);
                             B = Convert.ToByte(uriString[k + 1].ToString() + uriString[k + 2], 16);
@@ -616,7 +647,7 @@ namespace Jint.Native.Global
                             // B & 11000000 != 10000000
                             // B & 11000000 != 10000000
                             if ((B & 0xC0) != 0x80)
                             if ((B & 0xC0) != 0x80)
                             {
                             {
-                                ExceptionHelper.ThrowUriError(_engine);
+                                ExceptionHelper.ThrowUriError(_realm);
                             }
                             }
 
 
                             k += 2;
                             k += 2;
@@ -707,7 +738,7 @@ namespace Jint.Native.Global
 
 
             return _stringBuilder.ToString();
             return _stringBuilder.ToString();
         }
         }
-        
+
         // optimized versions with string parameter and without virtual dispatch for global environment usage
         // optimized versions with string parameter and without virtual dispatch for global environment usage
 
 
         internal bool HasProperty(Key property)
         internal bool HasProperty(Key property)
@@ -721,7 +752,7 @@ namespace Jint.Native.Global
         {
         {
             if (!DefineOwnProperty(property, desc))
             if (!DefineOwnProperty(property, desc))
             {
             {
-                ExceptionHelper.ThrowTypeError(_engine);
+                ExceptionHelper.ThrowTypeError(_realm);
             }
             }
 
 
             return true;
             return true;
@@ -734,7 +765,7 @@ namespace Jint.Native.Global
             {
             {
                 return true;
                 return true;
             }
             }
-            
+
             // check fast path
             // check fast path
             if ((current._flags & PropertyFlag.MutableBinding) != 0)
             if ((current._flags & PropertyFlag.MutableBinding) != 0)
             {
             {
@@ -751,7 +782,7 @@ namespace Jint.Native.Global
             Properties.TryGetValue(property, out var descriptor);
             Properties.TryGetValue(property, out var descriptor);
             return descriptor ?? PropertyDescriptor.Undefined;
             return descriptor ?? PropertyDescriptor.Undefined;
         }
         }
-        
+
         internal bool Set(Key property, JsValue value)
         internal bool Set(Key property, JsValue value)
         {
         {
             // here we are called only from global environment record context
             // here we are called only from global environment record context
@@ -790,7 +821,7 @@ namespace Jint.Native.Global
 
 
             return true;
             return true;
         }
         }
-        
+
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         internal void SetOwnProperty(Key property, PropertyDescriptor desc)
         internal void SetOwnProperty(Key property, PropertyDescriptor desc)
         {
         {

+ 23 - 25
Jint/Native/Iterator/IteratorConstructor.cs

@@ -1,9 +1,11 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
 using System.Linq;
 using System.Linq;
 using Jint.Native.Function;
 using Jint.Native.Function;
 using Jint.Native.Map;
 using Jint.Native.Map;
 using Jint.Native.Object;
 using Jint.Native.Object;
 using Jint.Native.Set;
 using Jint.Native.Set;
+using Jint.Runtime;
 
 
 namespace Jint.Native.Iterator
 namespace Jint.Native.Iterator
 {
 {
@@ -11,30 +13,26 @@ namespace Jint.Native.Iterator
     {
     {
         private static readonly JsString _functionName = new JsString("iterator");
         private static readonly JsString _functionName = new JsString("iterator");
 
 
-        private IteratorConstructor(Engine engine)
-            : base(engine, _functionName)
+        internal IteratorConstructor(
+            Engine engine,
+            Realm realm,
+            ObjectPrototype objectPrototype)
+            : base(engine, realm, _functionName)
         {
         {
+            ArrayIteratorPrototypeObject = new IteratorPrototype(engine, realm, "Array Iterator", objectPrototype);
+            GenericIteratorPrototypeObject = new IteratorPrototype(engine, realm, null, objectPrototype);
+            MapIteratorPrototypeObject = new IteratorPrototype(engine, realm, "Map Iterator", objectPrototype);
+            RegExpStringIteratorPrototypeObject = new IteratorPrototype(engine, realm, "RegExp String Iterator", objectPrototype);
+            SetIteratorPrototypeObject = new IteratorPrototype(engine, realm, "Set Iterator", objectPrototype);
+            StringIteratorPrototypeObject = new IteratorPrototype(engine, realm, "String Iterator", objectPrototype);
         }
         }
 
 
-        private IteratorPrototype ArrayIteratorPrototypeObject { get; set; }
-        private IteratorPrototype GenericIteratorPrototypeObject { get; set; }
-        private IteratorPrototype MapIteratorPrototypeObject { get; set; }
-        private IteratorPrototype RegExpStringIteratorPrototypeObject { get; set; }
-        private IteratorPrototype SetIteratorPrototypeObject { get; set; }
-        private IteratorPrototype StringIteratorPrototypeObject { get; set; }
-
-        public static IteratorConstructor CreateIteratorConstructor(Engine engine)
-        {
-            var obj = new IteratorConstructor(engine);
-            obj.ArrayIteratorPrototypeObject = IteratorPrototype.CreatePrototypeObject(engine, "Array Iterator", obj);
-            obj.GenericIteratorPrototypeObject = IteratorPrototype.CreatePrototypeObject(engine, null, obj);
-            obj.MapIteratorPrototypeObject = IteratorPrototype.CreatePrototypeObject(engine, "Map Iterator", obj);
-            obj.RegExpStringIteratorPrototypeObject = IteratorPrototype.CreatePrototypeObject(engine, "RegExp String Iterator", obj);
-            obj.SetIteratorPrototypeObject = IteratorPrototype.CreatePrototypeObject(engine, "Set Iterator", obj);
-            obj.StringIteratorPrototypeObject = IteratorPrototype.CreatePrototypeObject(engine, "String Iterator", obj);
-            return obj;
-        }
-
+        internal IteratorPrototype ArrayIteratorPrototypeObject { get; }
+        internal IteratorPrototype GenericIteratorPrototypeObject { get; }
+        private IteratorPrototype MapIteratorPrototypeObject { get; }
+        private IteratorPrototype RegExpStringIteratorPrototypeObject { get; }
+        private IteratorPrototype SetIteratorPrototypeObject { get; }
+        private IteratorPrototype StringIteratorPrototypeObject { get; }
 
 
         public override JsValue Call(JsValue thisObject, JsValue[] arguments)
         public override JsValue Call(JsValue thisObject, JsValue[] arguments)
         {
         {
@@ -66,11 +64,11 @@ namespace Jint.Native.Iterator
             return instance;
             return instance;
         }
         }
 
 
-        internal ObjectInstance Construct(ObjectInstance array)
+        internal ObjectInstance Construct(ObjectInstance array, Func<Intrinsics, Prototype> prototypeSelector)
         {
         {
             var instance = new IteratorInstance.ArrayLikeIterator(Engine, array)
             var instance = new IteratorInstance.ArrayLikeIterator(Engine, array)
             {
             {
-                _prototype = GenericIteratorPrototypeObject
+                _prototype = prototypeSelector(_realm.Intrinsics)
             };
             };
 
 
             return instance;
             return instance;
@@ -125,7 +123,7 @@ namespace Jint.Native.Iterator
 
 
             return instance;
             return instance;
         }
         }
-       
+
         internal ObjectInstance CreateRegExpStringIterator(ObjectInstance iteratingRegExp, string iteratedString, bool global, bool unicode)
         internal ObjectInstance CreateRegExpStringIterator(ObjectInstance iteratingRegExp, string iteratedString, bool global, bool unicode)
         {
         {
             var instance = new IteratorInstance.RegExpStringIterator(Engine, iteratingRegExp, iteratedString, global, unicode)
             var instance = new IteratorInstance.RegExpStringIterator(Engine, iteratingRegExp, iteratedString, global, unicode)

+ 30 - 17
Jint/Native/Iterator/IteratorInstance.cs

@@ -56,7 +56,7 @@ namespace Jint.Native.Iterator
 
 
         private ObjectInstance CreateIterResultObject(JsValue value, bool done)
         private ObjectInstance CreateIterResultObject(JsValue value, bool done)
         {
         {
-            var obj = _engine.Object.Construct(2);
+            var obj = _engine.Realm.Intrinsics.Object.Construct(2);
             obj.SetDataProperty("value", value);
             obj.SetDataProperty("value", value);
             obj.SetDataProperty("done", done);
             obj.SetDataProperty("done", done);
             return obj;
             return obj;
@@ -71,7 +71,7 @@ namespace Jint.Native.Iterator
                 var done = ReferenceEquals(null, key) && ReferenceEquals(null, value);
                 var done = ReferenceEquals(null, key) && ReferenceEquals(null, value);
                 if (!done)
                 if (!done)
                 {
                 {
-                    var arrayInstance = engine.Array.ConstructFast(2);
+                    var arrayInstance = engine.Realm.Intrinsics.Array.ConstructFast(2);
                     arrayInstance.SetIndexValue(0, key, false);
                     arrayInstance.SetIndexValue(0, key, false);
                     arrayInstance.SetIndexValue(1, value, false);
                     arrayInstance.SetIndexValue(1, value, false);
                     SetProperty("value", new PropertyDescriptor(arrayInstance, PropertyFlag.AllForbidden));
                     SetProperty("value", new PropertyDescriptor(arrayInstance, PropertyFlag.AllForbidden));
@@ -132,10 +132,10 @@ namespace Jint.Native.Iterator
 
 
             public ArrayLikeIterator(Engine engine, JsValue target) : base(engine)
             public ArrayLikeIterator(Engine engine, JsValue target) : base(engine)
             {
             {
-                if (!(target is ObjectInstance objectInstance))
+                var objectInstance = target as ObjectInstance;
+                if (objectInstance is null)
                 {
                 {
-                    ExceptionHelper.ThrowTypeError(engine, "Target must be an object");
-                    return;
+                    ExceptionHelper.ThrowTypeError(engine.Realm, "Target must be an object");
                 }
                 }
 
 
                 _array = ArrayOperations.For(objectInstance);
                 _array = ArrayOperations.For(objectInstance);
@@ -239,7 +239,7 @@ namespace Jint.Native.Iterator
                 nextItem = KeyValueIteratorPosition.Done;
                 nextItem = KeyValueIteratorPosition.Done;
                 return false;
                 return false;
             }
             }
-        } 
+        }
 
 
         public class ArrayLikeKeyIterator : IteratorInstance
         public class ArrayLikeKeyIterator : IteratorInstance
         {
         {
@@ -304,8 +304,11 @@ namespace Jint.Native.Iterator
             public ObjectIterator(ObjectInstance target)
             public ObjectIterator(ObjectInstance target)
             {
             {
                 _target = target;
                 _target = target;
-                _nextMethod = target.Get(CommonProperties.Next, target) as ICallable
-                            ?? ExceptionHelper.ThrowTypeError<ICallable>(target.Engine);
+                _nextMethod = target.Get(CommonProperties.Next, target) as ICallable;
+                if (_nextMethod is null)
+                {
+                    ExceptionHelper.ThrowTypeError(target.Engine.Realm);
+                }
             }
             }
 
 
             public bool TryIteratorStep(out ObjectInstance result)
             public bool TryIteratorStep(out ObjectInstance result)
@@ -324,7 +327,13 @@ namespace Jint.Native.Iterator
             private ObjectInstance IteratorNext()
             private ObjectInstance IteratorNext()
             {
             {
                 var jsValue = _nextMethod.Call(_target, Arguments.Empty);
                 var jsValue = _nextMethod.Call(_target, Arguments.Empty);
-                return jsValue as ObjectInstance ?? ExceptionHelper.ThrowTypeError<ObjectInstance>(_target.Engine, "Iterator result " + jsValue + " is not an object");
+                var instance = jsValue as ObjectInstance;
+                if (instance is null)
+                {
+                    ExceptionHelper.ThrowTypeError(_target.Engine.Realm, "Iterator result " + jsValue + " is not an object");
+                }
+
+                return instance;
             }
             }
 
 
             public void Close(CompletionType completion)
             public void Close(CompletionType completion)
@@ -335,7 +344,11 @@ namespace Jint.Native.Iterator
                     return;
                     return;
                 }
                 }
 
 
-                var callable = func as ICallable ?? ExceptionHelper.ThrowTypeError<ICallable>(_target.Engine, func + " is not a function");
+                var callable = func as ICallable;
+                if (callable is null)
+                {
+                    ExceptionHelper.ThrowTypeError(_target.Engine.Realm, func + " is not a function");
+                }
 
 
                 var innerResult = Undefined;
                 var innerResult = Undefined;
                 try
                 try
@@ -351,7 +364,7 @@ namespace Jint.Native.Iterator
                 }
                 }
                 if (completion != CompletionType.Throw && !innerResult.IsObject())
                 if (completion != CompletionType.Throw && !innerResult.IsObject())
                 {
                 {
-                    ExceptionHelper.ThrowTypeError(_target.Engine);
+                    ExceptionHelper.ThrowTypeError(_target.Engine.Realm);
                 }
                 }
             }
             }
         }
         }
@@ -377,7 +390,7 @@ namespace Jint.Native.Iterator
                 return false;
                 return false;
             }
             }
         }
         }
-        
+
         internal class RegExpStringIterator : IteratorInstance
         internal class RegExpStringIterator : IteratorInstance
         {
         {
             private readonly RegExpInstance _iteratingRegExp;
             private readonly RegExpInstance _iteratingRegExp;
@@ -389,12 +402,12 @@ namespace Jint.Native.Iterator
 
 
             public RegExpStringIterator(Engine engine, ObjectInstance iteratingRegExp, string iteratedString, bool global, bool unicode) : base(engine)
             public RegExpStringIterator(Engine engine, ObjectInstance iteratingRegExp, string iteratedString, bool global, bool unicode) : base(engine)
             {
             {
-                if (!(iteratingRegExp is RegExpInstance r))
+                var r = iteratingRegExp as RegExpInstance;
+                if (r is null)
                 {
                 {
-                    ExceptionHelper.ThrowTypeError(engine);
-                    return;
+                    ExceptionHelper.ThrowTypeError(engine.Realm);
                 }
                 }
-                
+
                 _iteratingRegExp = r;
                 _iteratingRegExp = r;
                 _s = iteratedString;
                 _s = iteratedString;
                 _global = global;
                 _global = global;
@@ -408,7 +421,7 @@ namespace Jint.Native.Iterator
                     nextItem = CreateIterResultObject(Undefined, true);
                     nextItem = CreateIterResultObject(Undefined, true);
                     return false;
                     return false;
                 }
                 }
-                
+
                 var match  = RegExpPrototype.RegExpExec(_iteratingRegExp, _s);
                 var match  = RegExpPrototype.RegExpExec(_iteratingRegExp, _s);
                 if (match.IsNull())
                 if (match.IsNull())
                 {
                 {

+ 6 - 6
Jint/Native/Iterator/IteratorProtocol.cs

@@ -88,10 +88,10 @@ namespace Jint.Native.Iterator
 
 
         internal static void AddEntriesFromIterable(ObjectInstance target, IIterator iterable, object adder)
         internal static void AddEntriesFromIterable(ObjectInstance target, IIterator iterable, object adder)
         {
         {
-            if (!(adder is ICallable callable))
+            var callable = adder as ICallable;
+            if (callable is null)
             {
             {
-                ExceptionHelper.ThrowTypeError(target.Engine, "adder must be callable");
-                return;
+                ExceptionHelper.ThrowTypeError(target.Engine.Realm, "adder must be callable");
             }
             }
 
 
             var args = target.Engine._jsValueArrayPool.RentArray(2);
             var args = target.Engine._jsValueArrayPool.RentArray(2);
@@ -109,10 +109,10 @@ namespace Jint.Native.Iterator
                     var temp = nextItem.Get(CommonProperties.Value);
                     var temp = nextItem.Get(CommonProperties.Value);
 
 
                     skipClose = false;
                     skipClose = false;
-                    if (!(temp is ObjectInstance oi))
+                    var oi = temp as ObjectInstance;
+                    if (oi is null)
                     {
                     {
-                        ExceptionHelper.ThrowTypeError(target.Engine, "iterator's value must be an object");
-                        return;
+                        ExceptionHelper.ThrowTypeError(target.Engine.Realm, "iterator's value must be an object");
                     }
                     }
 
 
                     var k = oi.Get(JsString.NumberZeroString);
                     var k = oi.Get(JsString.NumberZeroString);

+ 13 - 16
Jint/Native/Iterator/IteratorPrototype.cs

@@ -1,4 +1,5 @@
 using Jint.Collections;
 using Jint.Collections;
+using Jint.Native.Object;
 using Jint.Native.Symbol;
 using Jint.Native.Symbol;
 using Jint.Runtime;
 using Jint.Runtime;
 using Jint.Runtime.Descriptors;
 using Jint.Runtime.Descriptors;
@@ -6,23 +7,18 @@ using Jint.Runtime.Interop;
 
 
 namespace Jint.Native.Iterator
 namespace Jint.Native.Iterator
 {
 {
-    internal sealed class IteratorPrototype : IteratorInstance
+    internal sealed class IteratorPrototype : Prototype
     {
     {
-        private string _name;
+        private readonly string _name;
 
 
-        private IteratorPrototype(Engine engine) : base(engine)
+        internal IteratorPrototype(
+            Engine engine,
+            Realm realm,
+            string name,
+            ObjectPrototype objectPrototype) : base(engine, realm)
         {
         {
-        }
-
-        public static IteratorPrototype CreatePrototypeObject(Engine engine, string name, IteratorConstructor iteratorConstructor)
-        {
-            var obj = new IteratorPrototype(engine)
-            {
-                _prototype = engine.Object.PrototypeObject,
-                _name = name
-            };
-
-            return obj;
+            _prototype = objectPrototype;
+            _name = name;
         }
         }
 
 
         protected override void Initialize()
         protected override void Initialize()
@@ -46,9 +42,10 @@ namespace Jint.Native.Iterator
 
 
         private JsValue Next(JsValue thisObj, JsValue[] arguments)
         private JsValue Next(JsValue thisObj, JsValue[] arguments)
         {
         {
-            if (!(thisObj is IteratorInstance iterator))
+            var iterator = thisObj as IteratorInstance;
+            if (iterator is null)
             {
             {
-                return ExceptionHelper.ThrowTypeError<JsValue>(_engine);
+                ExceptionHelper.ThrowTypeError(_engine.Realm);
             }
             }
 
 
             iterator.TryIteratorStep(out var result);
             iterator.TryIteratorStep(out var result);

+ 1 - 1
Jint/Native/JsString.cs

@@ -193,7 +193,7 @@ namespace Jint.Native
 
 
         public ArrayInstance ToArray(Engine engine)
         public ArrayInstance ToArray(Engine engine)
         {
         {
-            var array = engine.Array.ConstructFast((uint) _value.Length);
+            var array = engine.Realm.Intrinsics.Array.ConstructFast((uint) _value.Length);
             for (int i = 0; i < _value.Length; ++i)
             for (int i = 0; i < _value.Length; ++i)
             {
             {
                 array.SetIndexValue((uint) i, _value[i], updateLength: false);
                 array.SetIndexValue((uint) i, _value[i], updateLength: false);

+ 26 - 19
Jint/Native/JsValue.cs

@@ -183,11 +183,11 @@ namespace Jint.Native
 
 
         [Pure]
         [Pure]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        internal IIterator GetIterator(Engine engine)
+        internal IIterator GetIterator(Realm realm)
         {
         {
-            if (!TryGetIterator(engine, out var iterator))
+            if (!TryGetIterator(realm, out var iterator))
             {
             {
-                return ExceptionHelper.ThrowTypeError<IIterator>(engine, "The value is not iterable");
+                ExceptionHelper.ThrowTypeError(realm, "The value is not iterable");
             }
             }
 
 
             return iterator;
             return iterator;
@@ -195,9 +195,9 @@ namespace Jint.Native
 
 
         [Pure]
         [Pure]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        internal bool TryGetIterator(Engine engine, out IIterator iterator)
+        internal bool TryGetIterator(Realm realm, out IIterator iterator)
         {
         {
-            var objectInstance = TypeConverter.ToObject(engine, this);
+            var objectInstance = TypeConverter.ToObject(realm, this);
 
 
             if (!objectInstance.TryGetValue(GlobalSymbolRegistry.Iterator, out var value)
             if (!objectInstance.TryGetValue(GlobalSymbolRegistry.Iterator, out var value)
                 || !(value is ICallable callable))
                 || !(value is ICallable callable))
@@ -206,9 +206,11 @@ namespace Jint.Native
                 return false;
                 return false;
             }
             }
 
 
-            var obj = callable.Call(this, Arguments.Empty) as ObjectInstance
-                      ?? ExceptionHelper.ThrowTypeError<ObjectInstance>(engine,
-                          "Result of the Symbol.iterator method is not an object");
+            var obj = callable.Call(this, Arguments.Empty) as ObjectInstance;
+            if (obj is null)
+            {
+                ExceptionHelper.ThrowTypeError(realm, "Result of the Symbol.iterator method is not an object");
+            }
 
 
             if (obj is IIterator i)
             if (obj is IIterator i)
             {
             {
@@ -366,7 +368,7 @@ namespace Jint.Native
             var arrayLength = (uint) array.Length;
             var arrayLength = (uint) array.Length;
 
 
             var jsArray = new ArrayInstance(e, arrayLength);
             var jsArray = new ArrayInstance(e, arrayLength);
-            jsArray._prototype = e.Array.PrototypeObject;
+            jsArray._prototype = e.Realm.Intrinsics.Array.PrototypeObject;
 
 
             for (uint i = 0; i < arrayLength; ++i)
             for (uint i = 0; i < arrayLength; ++i)
             {
             {
@@ -393,8 +395,11 @@ namespace Jint.Native
         /// <returns>The value returned by the function call.</returns>
         /// <returns>The value returned by the function call.</returns>
         public JsValue Invoke(params JsValue[] arguments)
         public JsValue Invoke(params JsValue[] arguments)
         {
         {
-            var callable = this as ICallable ??
-                           ExceptionHelper.ThrowTypeErrorNoEngine<ICallable>("Can only invoke functions");
+            var callable = this as ICallable;
+            if (callable is null)
+            {
+                ExceptionHelper.ThrowTypeErrorNoEngine("Can only invoke functions");
+            }
             return callable.Call(Undefined, arguments);
             return callable.Call(Undefined, arguments);
         }
         }
 
 
@@ -419,7 +424,8 @@ namespace Jint.Native
         /// </summary>
         /// </summary>
         public virtual bool Set(JsValue property, JsValue value, JsValue receiver)
         public virtual bool Set(JsValue property, JsValue value, JsValue receiver)
         {
         {
-            return ExceptionHelper.ThrowNotSupportedException<bool>();
+            ExceptionHelper.ThrowNotSupportedException();
+            return false;
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -427,9 +433,10 @@ namespace Jint.Native
         /// </summary>
         /// </summary>
         internal bool InstanceofOperator(JsValue target)
         internal bool InstanceofOperator(JsValue target)
         {
         {
-            if (target is not ObjectInstance oi)
+            var oi = target as ObjectInstance;
+            if (oi is null)
             {
             {
-                return ExceptionHelper.ThrowTypeErrorNoEngine<bool>("not an object");
+                ExceptionHelper.ThrowTypeErrorNoEngine("not an object");
             }
             }
 
 
             var instOfHandler = oi.GetMethod(GlobalSymbolRegistry.HasInstance);
             var instOfHandler = oi.GetMethod(GlobalSymbolRegistry.HasInstance);
@@ -440,7 +447,7 @@ namespace Jint.Native
 
 
             if (!target.IsCallable)
             if (!target.IsCallable)
             {
             {
-                return ExceptionHelper.ThrowTypeErrorNoEngine<bool>("not callable");
+                ExceptionHelper.ThrowTypeErrorNoEngine("not callable");
             }
             }
 
 
             return target.OrdinaryHasInstance(this);
             return target.OrdinaryHasInstance(this);
@@ -626,8 +633,7 @@ namespace Jint.Native
             var p = Get(CommonProperties.Prototype);
             var p = Get(CommonProperties.Prototype);
             if (p is not ObjectInstance)
             if (p is not ObjectInstance)
             {
             {
-                ExceptionHelper.ThrowTypeError(o.Engine,
-                    $"Function has non-object prototype '{TypeConverter.ToString(p)}' in instanceof check");
+                ExceptionHelper.ThrowTypeError(o.Engine.Realm, $"Function has non-object prototype '{TypeConverter.ToString(p)}' in instanceof check");
             }
             }
 
 
             while (true)
             while (true)
@@ -700,9 +706,10 @@ namespace Jint.Native
 
 
         internal static IConstructor AssertConstructor(Engine engine, JsValue c)
         internal static IConstructor AssertConstructor(Engine engine, JsValue c)
         {
         {
-            if (!(c is IConstructor constructor))
+            var constructor = c as IConstructor;
+            if (constructor is null)
             {
             {
-                return ExceptionHelper.ThrowTypeError<IConstructor>(engine, c + " is not a constructor");
+                ExceptionHelper.ThrowTypeError(engine.Realm, c + " is not a constructor");
             }
             }
 
 
             return constructor;
             return constructor;

+ 17 - 14
Jint/Native/Json/JsonInstance.cs

@@ -1,4 +1,5 @@
-using Jint.Collections;
+using System;
+using Jint.Collections;
 using Jint.Native.Object;
 using Jint.Native.Object;
 using Jint.Native.Symbol;
 using Jint.Native.Symbol;
 using Jint.Runtime;
 using Jint.Runtime;
@@ -9,29 +10,29 @@ namespace Jint.Native.Json
 {
 {
     public sealed class JsonInstance : ObjectInstance
     public sealed class JsonInstance : ObjectInstance
     {
     {
-        private JsonInstance(Engine engine)
+        private readonly Realm _realm;
+
+        internal JsonInstance(
+            Engine engine,
+            Realm realm,
+            ObjectPrototype objectPrototype)
             : base(engine, objectClass: ObjectClass.JSON)
             : base(engine, objectClass: ObjectClass.JSON)
         {
         {
-        }
-
-        public static JsonInstance CreateJsonObject(Engine engine)
-        {
-            var json = new JsonInstance(engine)
-            {
-                _prototype = engine.Object.PrototypeObject
-            };
-            return json;
+            _realm = realm;
+            _prototype = objectPrototype;
         }
         }
 
 
         protected override void Initialize()
         protected override void Initialize()
         {
         {
             var properties = new PropertyDictionary(2, checkExistingKeys: false)
             var properties = new PropertyDictionary(2, checkExistingKeys: false)
             {
             {
+#pragma warning disable 618
                 ["parse"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "parse", Parse, 2), true, false, true),
                 ["parse"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "parse", Parse, 2), true, false, true),
                 ["stringify"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "stringify", Stringify, 3), true, false, true)
                 ["stringify"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "stringify", Stringify, 3), true, false, true)
+#pragma warning restore 618
             };
             };
             SetProperties(properties);
             SetProperties(properties);
-            
+
             var symbols = new SymbolDictionary(1)
             var symbols = new SymbolDictionary(1)
             {
             {
                 [GlobalSymbolRegistry.ToStringTag] = new PropertyDescriptor("JSON", false, false, true),
                 [GlobalSymbolRegistry.ToStringTag] = new PropertyDescriptor("JSON", false, false, true),
@@ -87,6 +88,7 @@ namespace Jint.Native.Json
         /// <summary>
         /// <summary>
         /// https://tc39.es/ecma262/#sec-json.parse
         /// https://tc39.es/ecma262/#sec-json.parse
         /// </summary>
         /// </summary>
+        [Obsolete("Method will be made private, use JsonParser directly")]
         public JsValue Parse(JsValue thisObject, JsValue[] arguments)
         public JsValue Parse(JsValue thisObject, JsValue[] arguments)
         {
         {
             var jsonString = TypeConverter.ToString(arguments.At(0));
             var jsonString = TypeConverter.ToString(arguments.At(0));
@@ -97,7 +99,7 @@ namespace Jint.Native.Json
 
 
             if (reviver.IsCallable)
             if (reviver.IsCallable)
             {
             {
-                var root = _engine.Object.Construct(Arguments.Empty);
+                var root = _realm.Intrinsics.Object.Construct(Arguments.Empty);
                 var rootName = JsString.Empty;
                 var rootName = JsString.Empty;
                 root.CreateDataPropertyOrThrow(rootName, unfiltered);
                 root.CreateDataPropertyOrThrow(rootName, unfiltered);
                 return InternalizeJSONProperty(root, rootName, (ICallable) reviver);
                 return InternalizeJSONProperty(root, rootName, (ICallable) reviver);
@@ -108,13 +110,14 @@ namespace Jint.Native.Json
             }
             }
         }
         }
 
 
+        [Obsolete("Method will be made private, use JsonSerializer directly")]
         public JsValue Stringify(JsValue thisObject, JsValue[] arguments)
         public JsValue Stringify(JsValue thisObject, JsValue[] arguments)
         {
         {
             var value = arguments.At(0);
             var value = arguments.At(0);
             var replacer = arguments.At(1);
             var replacer = arguments.At(1);
             var space = arguments.At(2);
             var space = arguments.At(2);
 
 
-            if (value.IsUndefined() && replacer.IsUndefined()) 
+            if (value.IsUndefined() && replacer.IsUndefined())
             {
             {
                 return Undefined;
                 return Undefined;
             }
             }

+ 15 - 14
Jint/Native/Json/JsonParser.cs

@@ -97,7 +97,7 @@ namespace Jint.Native.Json
                 }
                 }
                 else
                 else
                 {
                 {
-                    ExceptionHelper.ThrowSyntaxError(_engine, $"Expected hexadecimal digit:{_source}");
+                    ExceptionHelper.ThrowSyntaxError(_engine.Realm, $"Expected hexadecimal digit:{_source}");
                 }
                 }
             }
             }
             return (char)code;
             return (char)code;
@@ -152,7 +152,8 @@ namespace Jint.Native.Json
                         };
                         };
             }
             }
 
 
-            return ExceptionHelper.ThrowSyntaxError<Token>(_engine, string.Format(Messages.UnexpectedToken, code));
+            ExceptionHelper.ThrowSyntaxError(_engine.Realm, string.Format(Messages.UnexpectedToken, code));
+            return null;
         }
         }
 
 
         private Token ScanNumericLiteral()
         private Token ScanNumericLiteral()
@@ -181,7 +182,7 @@ namespace Jint.Native.Json
                     // decimal number starts with '0' such as '09' is illegal.
                     // decimal number starts with '0' such as '09' is illegal.
                     if (ch > 0 && IsDecimalDigit(ch))
                     if (ch > 0 && IsDecimalDigit(ch))
                     {
                     {
-                        ExceptionHelper.ThrowSyntaxError(_engine, string.Format(Messages.UnexpectedToken, ch));
+                        ExceptionHelper.ThrowSyntaxError(_engine.Realm, string.Format(Messages.UnexpectedToken, ch));
                     }
                     }
                 }
                 }
 
 
@@ -220,7 +221,7 @@ namespace Jint.Native.Json
                 }
                 }
                 else
                 else
                 {
                 {
-                    ExceptionHelper.ThrowSyntaxError(_engine, string.Format(Messages.UnexpectedToken, _source.CharCodeAt(_index)));
+                    ExceptionHelper.ThrowSyntaxError(_engine.Realm, string.Format(Messages.UnexpectedToken, _source.CharCodeAt(_index)));
                 }
                 }
             }
             }
 
 
@@ -256,7 +257,8 @@ namespace Jint.Native.Json
                 };
                 };
             }
             }
 
 
-            return ExceptionHelper.ThrowSyntaxError<Token>(_engine, string.Format(Messages.UnexpectedToken, s));
+            ExceptionHelper.ThrowSyntaxError(_engine.Realm, string.Format(Messages.UnexpectedToken, s));
+            return null;
         }
         }
 
 
         private Token ScanNullLiteral()
         private Token ScanNullLiteral()
@@ -281,7 +283,8 @@ namespace Jint.Native.Json
                 };
                 };
             }
             }
 
 
-            return ExceptionHelper.ThrowSyntaxError<Token>(_engine, string.Format(Messages.UnexpectedToken, s));
+            ExceptionHelper.ThrowSyntaxError(_engine.Realm, string.Format(Messages.UnexpectedToken, s));
+            return null;
         }
         }
 
 
         private Token ScanStringLiteral()
         private Token ScanStringLiteral()
@@ -305,7 +308,7 @@ namespace Jint.Native.Json
 
 
                 if (ch <= 31)
                 if (ch <= 31)
                 {
                 {
-                    ExceptionHelper.ThrowSyntaxError(_engine, $"Invalid character '{ch}', position:{_index}, string:{_source}");
+                    ExceptionHelper.ThrowSyntaxError(_engine.Realm, $"Invalid character '{ch}', position:{_index}, string:{_source}");
                 }
                 }
 
 
                 if (ch == '\\')
                 if (ch == '\\')
@@ -397,7 +400,7 @@ namespace Jint.Native.Json
 
 
             if (quote != 0)
             if (quote != 0)
             {
             {
-                ExceptionHelper.ThrowSyntaxError(_engine, string.Format(Messages.UnexpectedToken, _source));
+                ExceptionHelper.ThrowSyntaxError(_engine.Realm, string.Format(Messages.UnexpectedToken, _source));
             }
             }
 
 
             return new Token
             return new Token
@@ -599,8 +602,6 @@ namespace Jint.Native.Json
             return node;
             return node;
         }
         }
 
 
-        // Throw an exception
-
         private void ThrowError(Token token, string messageFormat, params object[] arguments)
         private void ThrowError(Token token, string messageFormat, params object[] arguments)
         {
         {
             string msg = System.String.Format(messageFormat, arguments);
             string msg = System.String.Format(messageFormat, arguments);
@@ -684,14 +685,14 @@ namespace Jint.Native.Json
 
 
             Expect("]");
             Expect("]");
 
 
-            return _engine.Array.ConstructFast(elements);
+            return _engine.Realm.Intrinsics.Array.ConstructFast(elements);
         }
         }
 
 
         public ObjectInstance ParseJsonObject()
         public ObjectInstance ParseJsonObject()
         {
         {
             Expect("{");
             Expect("{");
 
 
-            var obj = _engine.Object.Construct(Arguments.Empty);
+            var obj = _engine.Realm.Intrinsics.Object.Construct(Arguments.Empty);
 
 
             while (!Match("}"))
             while (!Match("}"))
             {
             {
@@ -704,7 +705,7 @@ namespace Jint.Native.Json
                 var name = Lex().Value.ToString();
                 var name = Lex().Value.ToString();
                 if (PropertyNameContainsInvalidCharacters(name))
                 if (PropertyNameContainsInvalidCharacters(name))
                 {
                 {
-                    ExceptionHelper.ThrowSyntaxError(_engine, $"Invalid character in property name '{name}'");
+                    ExceptionHelper.ThrowSyntaxError(_engine.Realm, $"Invalid character in property name '{name}'");
                 }
                 }
 
 
                 Expect(":");
                 Expect(":");
@@ -827,7 +828,7 @@ namespace Jint.Native.Json
 
 
                 if(_lookahead.Type != Tokens.EOF)
                 if(_lookahead.Type != Tokens.EOF)
                 {
                 {
-                    ExceptionHelper.ThrowSyntaxError(_engine, $"Unexpected {_lookahead.Type} {_lookahead.Value}");
+                    ExceptionHelper.ThrowSyntaxError(_engine.Realm, $"Unexpected {_lookahead.Type} {_lookahead.Value}");
                 }
                 }
                 return jsv;
                 return jsv;
             }
             }

+ 7 - 7
Jint/Native/Json/JsonSerializer.cs

@@ -16,10 +16,10 @@ namespace Jint.Native.Json
             _engine = engine;
             _engine = engine;
         }
         }
 
 
-        Stack<object> _stack;
-        string _indent, _gap;
-        List<JsValue> _propertyList;
-        JsValue _replacerFunction = Undefined.Instance;
+        private Stack<object> _stack;
+        private string _indent, _gap;
+        private List<JsValue> _propertyList;
+        private JsValue _replacerFunction = Undefined.Instance;
 
 
         public JsValue Serialize(JsValue value, JsValue replacer, JsValue space)
         public JsValue Serialize(JsValue value, JsValue replacer, JsValue space)
         {
         {
@@ -112,7 +112,7 @@ namespace Jint.Native.Json
                 _gap = string.Empty;
                 _gap = string.Empty;
             }
             }
 
 
-            var wrapper = _engine.Object.Construct(Arguments.Empty);
+            var wrapper = _engine.Realm.Intrinsics.Object.Construct(Arguments.Empty);
             wrapper.DefineOwnProperty(JsString.Empty, new PropertyDescriptor(value, PropertyFlag.ConfigurableEnumerableWritable));
             wrapper.DefineOwnProperty(JsString.Empty, new PropertyDescriptor(value, PropertyFlag.ConfigurableEnumerableWritable));
 
 
             return Str(JsString.Empty, wrapper);
             return Str(JsString.Empty, wrapper);
@@ -192,7 +192,7 @@ namespace Jint.Native.Json
 
 
             if (value.IsObject() && isCallable == false)
             if (value.IsObject() && isCallable == false)
             {
             {
-                return value.AsObject().Class == ObjectClass.Array 
+                return value.AsObject().Class == ObjectClass.Array
                     ? SerializeArray(value)
                     ? SerializeArray(value)
                     : SerializeObject(value.AsObject());
                     : SerializeObject(value.AsObject());
             }
             }
@@ -294,7 +294,7 @@ namespace Jint.Native.Json
 
 
             if (_stack.Contains(value))
             if (_stack.Contains(value))
             {
             {
-                ExceptionHelper.ThrowTypeError(_engine, "Cyclic reference detected.");
+                ExceptionHelper.ThrowTypeError(_engine.Realm, "Cyclic reference detected.");
             }
             }
         }
         }
 
 

+ 17 - 24
Jint/Native/Map/MapConstructor.cs

@@ -13,31 +13,21 @@ namespace Jint.Native.Map
     {
     {
         private static readonly JsString _functionName = new JsString("Map");
         private static readonly JsString _functionName = new JsString("Map");
 
 
-        private MapConstructor(Engine engine)
-            : base(engine, _functionName)
+        internal MapConstructor(
+            Engine engine,
+            Realm realm,
+            FunctionPrototype functionPrototype,
+            ObjectPrototype objectPrototype)
+            : base(engine, realm, _functionName)
         {
         {
+            _prototype = functionPrototype;
+            PrototypeObject = new MapPrototype(engine, realm, this, objectPrototype);
+            _length = new PropertyDescriptor(0, PropertyFlag.Configurable);
+            _prototypeDescriptor = new PropertyDescriptor(PrototypeObject, PropertyFlag.AllForbidden);
         }
         }
 
 
         public MapPrototype PrototypeObject { get; private set; }
         public MapPrototype PrototypeObject { get; private set; }
 
 
-        public static MapConstructor CreateMapConstructor(Engine engine)
-        {
-            var obj = new MapConstructor(engine)
-            {
-                _prototype = engine.Function.PrototypeObject
-            };
-
-            // The value of the [[Prototype]] internal property of the Map constructor is the Function prototype object
-            obj.PrototypeObject = MapPrototype.CreatePrototypeObject(engine, obj);
-
-            obj._length = new PropertyDescriptor(0, PropertyFlag.Configurable);
-
-            // The initial value of Map.prototype is the Map prototype object
-            obj._prototypeDescriptor = new PropertyDescriptor(obj.PrototypeObject, PropertyFlag.AllForbidden);
-
-            return obj;
-        }
-
         protected override void Initialize()
         protected override void Initialize()
         {
         {
             var symbols = new SymbolDictionary(1)
             var symbols = new SymbolDictionary(1)
@@ -54,7 +44,7 @@ namespace Jint.Native.Map
 
 
         public override JsValue Call(JsValue thisObject, JsValue[] arguments)
         public override JsValue Call(JsValue thisObject, JsValue[] arguments)
         {
         {
-            ExceptionHelper.ThrowTypeError(_engine, "Constructor Map requires 'new'");
+            ExceptionHelper.ThrowTypeError(_realm, "Constructor Map requires 'new'");
             return null;
             return null;
         }
         }
 
 
@@ -65,14 +55,17 @@ namespace Jint.Native.Map
         {
         {
             if (newTarget.IsUndefined())
             if (newTarget.IsUndefined())
             {
             {
-                ExceptionHelper.ThrowTypeError(_engine);
+                ExceptionHelper.ThrowTypeError(_realm);
             }
             }
 
 
-            var map = OrdinaryCreateFromConstructor(newTarget, PrototypeObject, static (engine, _) => new MapInstance(engine));
+            var map = OrdinaryCreateFromConstructor(
+                newTarget,
+                static intrinsics => intrinsics.Map.PrototypeObject,
+                static (engine, realm, _) => new MapInstance(engine, realm));
             if (arguments.Length > 0 && !arguments[0].IsNullOrUndefined())
             if (arguments.Length > 0 && !arguments[0].IsNullOrUndefined())
             {
             {
                 var adder = map.Get("set");
                 var adder = map.Get("set");
-                var iterator = arguments.At(0).GetIterator(_engine);
+                var iterator = arguments.At(0).GetIterator(_realm);
 
 
                 IteratorProtocol.AddEntriesFromIterable(map, iterator, adder);
                 IteratorProtocol.AddEntriesFromIterable(map, iterator, adder);
             }
             }

+ 6 - 4
Jint/Native/Map/MapInstance.cs

@@ -7,11 +7,13 @@ namespace Jint.Native.Map
 {
 {
     public class MapInstance : ObjectInstance
     public class MapInstance : ObjectInstance
     {
     {
+        private readonly Realm _realm;
         internal readonly OrderedDictionary<JsValue, JsValue> _map;
         internal readonly OrderedDictionary<JsValue, JsValue> _map;
 
 
-        public MapInstance(Engine engine)
+        public MapInstance(Engine engine, Realm realm)
             : base(engine, objectClass: ObjectClass.Map)
             : base(engine, objectClass: ObjectClass.Map)
         {
         {
+            _realm = realm;
             _map = new OrderedDictionary<JsValue, JsValue>();
             _map = new OrderedDictionary<JsValue, JsValue>();
         }
         }
 
 
@@ -83,17 +85,17 @@ namespace Jint.Native.Map
 
 
         internal ObjectInstance Iterator()
         internal ObjectInstance Iterator()
         {
         {
-            return _engine.Iterator.Construct(this);
+            return _realm.Intrinsics.Iterator.Construct(this);
         }
         }
 
 
         internal ObjectInstance Keys()
         internal ObjectInstance Keys()
         {
         {
-            return _engine.Iterator.Construct(_map.Keys);
+            return _realm.Intrinsics.Iterator.Construct(_map.Keys);
         }
         }
 
 
         internal ObjectInstance Values()
         internal ObjectInstance Values()
         {
         {
-            return _engine.Iterator.Construct(_map.Values);
+            return _realm.Intrinsics.Iterator.Construct(_map.Values);
         }
         }
 
 
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]

+ 12 - 16
Jint/Native/Map/MapPrototype.cs

@@ -10,23 +10,18 @@ namespace Jint.Native.Map
     /// <summary>
     /// <summary>
     /// https://www.ecma-international.org/ecma-262/6.0/#sec-map-objects
     /// https://www.ecma-international.org/ecma-262/6.0/#sec-map-objects
     /// </summary>
     /// </summary>
-    public sealed class MapPrototype : ObjectInstance
+    public sealed class MapPrototype : Prototype
     {
     {
-        private MapConstructor _mapConstructor;
+        private readonly MapConstructor _mapConstructor;
 
 
-        private MapPrototype(Engine engine) : base(engine)
+        internal MapPrototype(
+            Engine engine,
+            Realm realm,
+            MapConstructor mapConstructor,
+            ObjectPrototype objectPrototype) : base(engine, realm)
         {
         {
-        }
-
-        public static MapPrototype CreatePrototypeObject(Engine engine, MapConstructor mapConstructor)
-        {
-            var obj = new MapPrototype(engine)
-            {
-                _prototype = engine.Object.PrototypeObject,
-                _mapConstructor = mapConstructor
-            };
-
-            return obj;
+            _prototype = objectPrototype;
+            _mapConstructor = mapConstructor;
         }
         }
 
 
         protected override void Initialize()
         protected override void Initialize()
@@ -132,9 +127,10 @@ namespace Jint.Native.Map
 
 
         private MapInstance AssertMapInstance(JsValue thisObj)
         private MapInstance AssertMapInstance(JsValue thisObj)
         {
         {
-            if (!(thisObj is MapInstance map))
+            var map = thisObj as MapInstance;
+            if (map is null)
             {
             {
-                return ExceptionHelper.ThrowTypeError<MapInstance>(_engine, "object must be a Map");
+                ExceptionHelper.ThrowTypeError(_realm, "object must be a Map");
             }
             }
 
 
             return map;
             return map;

+ 2 - 11
Jint/Native/Math/MathInstance.cs

@@ -13,18 +13,9 @@ namespace Jint.Native.Math
     {
     {
         private Random _random;
         private Random _random;
 
 
-        private MathInstance(Engine engine) : base(engine, ObjectClass.Math)
+        internal MathInstance(Engine engine, ObjectPrototype objectPrototype) : base(engine, ObjectClass.Math)
         {
         {
-        }
-
-        public static MathInstance CreateMathObject(Engine engine)
-        {
-            var math = new MathInstance(engine)
-            {
-                _prototype = engine.Object.PrototypeObject
-            };
-
-            return math;
+            _prototype = objectPrototype;
         }
         }
 
 
         protected override void Initialize()
         protected override void Initialize()

+ 2 - 2
Jint/Native/Number/Dtoa/DtoaNumberFormatter.cs

@@ -25,7 +25,7 @@ namespace Jint.Native.Number.Dtoa
             {
             {
                 negative = true;
                 negative = true;
                 v = -v;
                 v = -v;
-            } 
+            }
 
 
             if (v == 0)
             if (v == 0)
             {
             {
@@ -52,7 +52,7 @@ namespace Jint.Native.Number.Dtoa
                     fast_worked = FastDtoa.NumberToString(v, DtoaMode.Precision, requested_digits, out point, buffer);
                     fast_worked = FastDtoa.NumberToString(v, DtoaMode.Precision, requested_digits, out point, buffer);
                     break;
                     break;
                 default:
                 default:
-                    ExceptionHelper.ThrowArgumentOutOfRangeException<string>();
+                    ExceptionHelper.ThrowArgumentOutOfRangeException();
                     return;
                     return;
             }
             }
 
 

+ 4 - 4
Jint/Native/Number/Dtoa/FastDtoa.cs

@@ -706,7 +706,7 @@ namespace Jint.Native.Number.Dtoa
 
 
             var mk = powerResult.decimalExponent;
             var mk = powerResult.decimalExponent;
             var ten_mk = powerResult.cMk;
             var ten_mk = powerResult.cMk;
-            
+
             Debug.Assert((MinimalTargetExponent <= w.E + ten_mk.E + DiyFp.KSignificandSize) && (MaximalTargetExponent >= w.E + ten_mk.E + DiyFp.KSignificandSize));
             Debug.Assert((MinimalTargetExponent <= w.E + ten_mk.E + DiyFp.KSignificandSize) && (MaximalTargetExponent >= w.E + ten_mk.E + DiyFp.KSignificandSize));
             // Note that ten_mk is only an approximation of 10^-k. A DiyFp only contains a
             // Note that ten_mk is only an approximation of 10^-k. A DiyFp only contains a
             // 64 bit significand and ten_mk is thus only precise up to 64 bits.
             // 64 bit significand and ten_mk is thus only precise up to 64 bits.
@@ -740,8 +740,8 @@ namespace Jint.Native.Number.Dtoa
             Debug.Assert(!double.IsNaN(v));
             Debug.Assert(!double.IsNaN(v));
             Debug.Assert(!double.IsInfinity(v));
             Debug.Assert(!double.IsInfinity(v));
 
 
-            bool result;
-            int decimal_exponent = 0;
+            var result = false;
+            var decimal_exponent = 0;
             switch (mode)
             switch (mode)
             {
             {
                 case DtoaMode.Shortest:
                 case DtoaMode.Shortest:
@@ -751,7 +751,7 @@ namespace Jint.Native.Number.Dtoa
                     result = Grisu3Counted(v, requested_digits, buffer, out decimal_exponent);
                     result = Grisu3Counted(v, requested_digits, buffer, out decimal_exponent);
                     break;
                     break;
                 default:
                 default:
-                    result = ExceptionHelper.ThrowArgumentOutOfRangeException<bool>();
+                    ExceptionHelper.ThrowArgumentOutOfRangeException();
                     break;
                     break;
             }
             }
 
 

+ 15 - 23
Jint/Native/Number/NumberConstructor.cs

@@ -15,28 +15,17 @@ namespace Jint.Native.Number
         private const long MinSafeInteger = -9007199254740991;
         private const long MinSafeInteger = -9007199254740991;
         internal const long MaxSafeInteger = 9007199254740991;
         internal const long MaxSafeInteger = 9007199254740991;
 
 
-        public NumberConstructor(Engine engine)
-            : base(engine, _functionName)
+        public NumberConstructor(
+            Engine engine,
+            Realm realm,
+            FunctionPrototype functionPrototype,
+            ObjectPrototype objectPrototype)
+            : base(engine, realm, _functionName)
         {
         {
-
-        }
-
-        public static NumberConstructor CreateNumberConstructor(Engine engine)
-        {
-            var obj = new NumberConstructor(engine)
-            {
-                _prototype = engine.Function.PrototypeObject
-            };
-
-            // The value of the [[Prototype]] internal property of the Number constructor is the Function prototype object
-            obj.PrototypeObject = NumberPrototype.CreatePrototypeObject(engine, obj);
-
-            obj._length = new PropertyDescriptor(JsNumber.One, PropertyFlag.Configurable);
-
-            // The initial value of Number.prototype is the Number prototype object
-            obj._prototypeDescriptor = new PropertyDescriptor(obj.PrototypeObject, PropertyFlag.AllForbidden);
-
-            return obj;
+            _prototype = functionPrototype;
+            PrototypeObject = new NumberPrototype(engine, realm, this, objectPrototype);
+            _length = new PropertyDescriptor(JsNumber.One, PropertyFlag.Configurable);
+            _prototypeDescriptor = new PropertyDescriptor(PrototypeObject, PropertyFlag.AllForbidden);
         }
         }
 
 
         protected override void Initialize()
         protected override void Initialize()
@@ -135,7 +124,7 @@ namespace Jint.Native.Number
         /// </summary>
         /// </summary>
         public ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
         public ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
         {
         {
-            var value = arguments.Length > 0 
+            var value = arguments.Length > 0
                 ? JsNumber.Create(TypeConverter.ToNumber(arguments[0]))
                 ? JsNumber.Create(TypeConverter.ToNumber(arguments[0]))
                 : JsNumber.PositiveZero;
                 : JsNumber.PositiveZero;
 
 
@@ -144,7 +133,10 @@ namespace Jint.Native.Number
                 return Construct(value);
                 return Construct(value);
             }
             }
 
 
-            var o = OrdinaryCreateFromConstructor(newTarget, PrototypeObject, static (engine, state) => new NumberInstance(engine, (JsNumber) state), value);
+            var o = OrdinaryCreateFromConstructor(
+                newTarget,
+                static intrinsics => intrinsics.Number.PrototypeObject,
+                static (engine, realm, state) => new NumberInstance(engine, (JsNumber) state), value);
             return o;
             return o;
         }
         }
 
 

+ 25 - 27
Jint/Native/Number/NumberPrototype.cs

@@ -3,6 +3,7 @@ using System.Globalization;
 using System.Text;
 using System.Text;
 using Jint.Collections;
 using Jint.Collections;
 using Jint.Native.Number.Dtoa;
 using Jint.Native.Number.Dtoa;
+using Jint.Native.Object;
 using Jint.Pooling;
 using Jint.Pooling;
 using Jint.Runtime;
 using Jint.Runtime;
 using Jint.Runtime.Descriptors;
 using Jint.Runtime.Descriptors;
@@ -15,31 +16,27 @@ namespace Jint.Native.Number
     /// </summary>
     /// </summary>
     public sealed class NumberPrototype : NumberInstance
     public sealed class NumberPrototype : NumberInstance
     {
     {
-        private NumberConstructor _numberConstructor;
-
-        private NumberPrototype(Engine engine)
+        private readonly Realm _realm;
+        private readonly NumberConstructor _constructor;
+
+        internal NumberPrototype(
+            Engine engine,
+            Realm realm,
+            NumberConstructor constructor,
+            ObjectPrototype objectPrototype)
             : base(engine)
             : base(engine)
         {
         {
-        }
-
-        public static NumberPrototype CreatePrototypeObject(Engine engine, NumberConstructor numberConstructor)
-        {
-            var obj = new NumberPrototype(engine)
-            {
-                _prototype = engine.Object.PrototypeObject,
-                NumberData = JsNumber.Create(0),
-                _numberConstructor = numberConstructor
-            };
-
-
-            return obj;
+            _prototype = objectPrototype;
+            NumberData = JsNumber.Create(0);
+            _realm = realm;
+            _constructor = constructor;
         }
         }
 
 
         protected override void Initialize()
         protected override void Initialize()
         {
         {
             var properties = new PropertyDictionary(8, checkExistingKeys: false)
             var properties = new PropertyDictionary(8, checkExistingKeys: false)
             {
             {
-                ["constructor"] = new PropertyDescriptor(_numberConstructor, true, false, true),
+                ["constructor"] = new PropertyDescriptor(_constructor, true, false, true),
                 ["toString"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "toString", ToNumberString, 1, PropertyFlag.Configurable), 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),
                 ["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),
                 ["valueOf"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "valueOf", ValueOf, 0, PropertyFlag.Configurable), true, false, true),
@@ -54,7 +51,7 @@ namespace Jint.Native.Number
         {
         {
             if (!thisObject.IsNumber() && ReferenceEquals(thisObject.TryCast<NumberInstance>(), null))
             if (!thisObject.IsNumber() && ReferenceEquals(thisObject.TryCast<NumberInstance>(), null))
             {
             {
-                ExceptionHelper.ThrowTypeError(Engine);
+                ExceptionHelper.ThrowTypeError(_realm);
             }
             }
 
 
             var m = TypeConverter.ToNumber(thisObject);
             var m = TypeConverter.ToNumber(thisObject);
@@ -99,7 +96,8 @@ namespace Jint.Native.Number
                 return thisObj;
                 return thisObj;
             }
             }
 
 
-            return ExceptionHelper.ThrowTypeError<JsValue>(Engine);
+            ExceptionHelper.ThrowTypeError(_realm);
+            return null;
         }
         }
 
 
         private const double Ten21 = 1e21;
         private const double Ten21 = 1e21;
@@ -109,13 +107,13 @@ namespace Jint.Native.Number
             var f = (int) TypeConverter.ToInteger(arguments.At(0, 0));
             var f = (int) TypeConverter.ToInteger(arguments.At(0, 0));
             if (f < 0 || f > 100)
             if (f < 0 || f > 100)
             {
             {
-                ExceptionHelper.ThrowRangeError(_engine, "fractionDigits argument must be between 0 and 100");
+                ExceptionHelper.ThrowRangeError(_realm, "fractionDigits argument must be between 0 and 100");
             }
             }
 
 
             // limitation with .NET, max is 99
             // limitation with .NET, max is 99
             if (f == 100)
             if (f == 100)
             {
             {
-                ExceptionHelper.ThrowRangeError(_engine, "100 fraction digits is not supported due to .NET format specifier limitation");
+                ExceptionHelper.ThrowRangeError(_realm, "100 fraction digits is not supported due to .NET format specifier limitation");
             }
             }
 
 
             var x = TypeConverter.ToNumber(thisObj);
             var x = TypeConverter.ToNumber(thisObj);
@@ -146,7 +144,7 @@ namespace Jint.Native.Number
         {
         {
             if (!thisObj.IsNumber() && ReferenceEquals(thisObj.TryCast<NumberInstance>(), null))
             if (!thisObj.IsNumber() && ReferenceEquals(thisObj.TryCast<NumberInstance>(), null))
             {
             {
-                ExceptionHelper.ThrowTypeError(Engine);
+                ExceptionHelper.ThrowTypeError(_realm);
             }
             }
 
 
             var x = TypeConverter.ToNumber(thisObj);
             var x = TypeConverter.ToNumber(thisObj);
@@ -170,7 +168,7 @@ namespace Jint.Native.Number
 
 
             if (f < 0 || f > 100)
             if (f < 0 || f > 100)
             {
             {
-                ExceptionHelper.ThrowRangeError(_engine, "fractionDigits argument must be between 0 and 100");
+                ExceptionHelper.ThrowRangeError(_realm, "fractionDigits argument must be between 0 and 100");
             }
             }
 
 
             if (arguments.At(0).IsUndefined())
             if (arguments.At(0).IsUndefined())
@@ -223,7 +221,7 @@ namespace Jint.Native.Number
         {
         {
             if (!thisObj.IsNumber() && ReferenceEquals(thisObj.TryCast<NumberInstance>(), null))
             if (!thisObj.IsNumber() && ReferenceEquals(thisObj.TryCast<NumberInstance>(), null))
             {
             {
-                ExceptionHelper.ThrowTypeError(Engine);
+                ExceptionHelper.ThrowTypeError(_realm);
             }
             }
 
 
             var x = TypeConverter.ToNumber(thisObj);
             var x = TypeConverter.ToNumber(thisObj);
@@ -248,7 +246,7 @@ namespace Jint.Native.Number
 
 
             if (p < 1 || p > 100)
             if (p < 1 || p > 100)
             {
             {
-                ExceptionHelper.ThrowRangeError(_engine, "precision must be between 1 and 100");
+                ExceptionHelper.ThrowRangeError(_realm, "precision must be between 1 and 100");
             }
             }
 
 
             var dtoaBuilder = new DtoaBuilder(101);
             var dtoaBuilder = new DtoaBuilder(101);
@@ -345,7 +343,7 @@ namespace Jint.Native.Number
         {
         {
             if (!thisObject.IsNumber() && (ReferenceEquals(thisObject.TryCast<NumberInstance>(), null)))
             if (!thisObject.IsNumber() && (ReferenceEquals(thisObject.TryCast<NumberInstance>(), null)))
             {
             {
-                ExceptionHelper.ThrowTypeError(_engine);
+                ExceptionHelper.ThrowTypeError(_realm);
             }
             }
 
 
             var radix = arguments.At(0).IsUndefined()
             var radix = arguments.At(0).IsUndefined()
@@ -354,7 +352,7 @@ namespace Jint.Native.Number
 
 
             if (radix < 2 || radix > 36)
             if (radix < 2 || radix > 36)
             {
             {
-                ExceptionHelper.ThrowRangeError(_engine, "radix must be between 2 and 36");
+                ExceptionHelper.ThrowRangeError(_realm, "radix must be between 2 and 36");
             }
             }
 
 
             var x = TypeConverter.ToNumber(thisObject);
             var x = TypeConverter.ToNumber(thisObject);

+ 46 - 47
Jint/Native/Object/ObjectConstructor.cs

@@ -12,26 +12,19 @@ namespace Jint.Native.Object
     {
     {
         private static readonly JsString _name = new JsString("delegate");
         private static readonly JsString _name = new JsString("delegate");
 
 
-        private ObjectConstructor(Engine engine)
-            : base(engine, _name)
+        internal ObjectConstructor(
+            Engine engine,
+            Realm realm)
+            : base(engine, realm, _name)
         {
         {
-        }
-
-        public static ObjectConstructor CreateObjectConstructor(Engine engine)
-        {
-            var obj = new ObjectConstructor(engine);
-
-            obj.PrototypeObject = ObjectPrototype.CreatePrototypeObject(engine, obj);
-
-            obj._length = PropertyDescriptor.AllForbiddenDescriptor.NumberOne;
-            obj._prototypeDescriptor = new PropertyDescriptor(obj.PrototypeObject, PropertyFlag.AllForbidden);
-
-            return obj;
+            PrototypeObject = new ObjectPrototype(engine, realm, this);
+            _length = PropertyDescriptor.AllForbiddenDescriptor.NumberOne;
+            _prototypeDescriptor = new PropertyDescriptor(PrototypeObject, PropertyFlag.AllForbidden);
         }
         }
 
 
         protected override void Initialize()
         protected override void Initialize()
         {
         {
-            _prototype = Engine.Function.PrototypeObject;
+            _prototype = _realm.Intrinsics.Function.PrototypeObject;
 
 
             const PropertyFlag propertyFlags = PropertyFlag.Configurable | PropertyFlag.Writable;
             const PropertyFlag propertyFlags = PropertyFlag.Configurable | PropertyFlag.Writable;
             const PropertyFlag lengthFlags = PropertyFlag.Configurable;
             const PropertyFlag lengthFlags = PropertyFlag.Configurable;
@@ -64,7 +57,7 @@ namespace Jint.Native.Object
 
 
         private JsValue Assign(JsValue thisObject, JsValue[] arguments)
         private JsValue Assign(JsValue thisObject, JsValue[] arguments)
         {
         {
-            var to = TypeConverter.ToObject(_engine, arguments.At(0));
+            var to = TypeConverter.ToObject(_realm, arguments.At(0));
             if (arguments.Length < 2)
             if (arguments.Length < 2)
             {
             {
                 return to;
                 return to;
@@ -78,7 +71,7 @@ namespace Jint.Native.Object
                     continue;
                     continue;
                 }
                 }
 
 
-                var from = TypeConverter.ToObject(_engine, nextSource);
+                var from = TypeConverter.ToObject(_realm, nextSource);
                 var keys = from.GetOwnPropertyKeys();
                 var keys = from.GetOwnPropertyKeys();
                 foreach (var nextKey in keys)
                 foreach (var nextKey in keys)
                 {
                 {
@@ -95,7 +88,7 @@ namespace Jint.Native.Object
 
 
         private JsValue Entries(JsValue thisObject, JsValue[] arguments)
         private JsValue Entries(JsValue thisObject, JsValue[] arguments)
         {
         {
-            var obj = TypeConverter.ToObject(_engine, arguments.At(0));
+            var obj = TypeConverter.ToObject(_realm, arguments.At(0));
             var nameList = obj.EnumerableOwnPropertyNames(EnumerableOwnPropertyNamesKind.KeyValue);
             var nameList = obj.EnumerableOwnPropertyNames(EnumerableOwnPropertyNamesKind.KeyValue);
             return nameList;
             return nameList;
         }
         }
@@ -105,10 +98,10 @@ namespace Jint.Native.Object
             var iterable = arguments.At(0);
             var iterable = arguments.At(0);
             TypeConverter.CheckObjectCoercible(_engine, iterable);
             TypeConverter.CheckObjectCoercible(_engine, iterable);
 
 
-            var obj = _engine.Object.Construct(0);
+            var obj = _realm.Intrinsics.Object.Construct(0);
 
 
             var adder = CreateDataPropertyOnObject.Instance;
             var adder = CreateDataPropertyOnObject.Instance;
-            var iterator = arguments.At(0).GetIterator(_engine);
+            var iterator = arguments.At(0).GetIterator(_realm);
 
 
             IteratorProtocol.AddEntriesFromIterable(obj, iterator, adder);
             IteratorProtocol.AddEntriesFromIterable(obj, iterator, adder);
 
 
@@ -140,7 +133,7 @@ namespace Jint.Native.Object
                 return Construct(arguments);
                 return Construct(arguments);
             }
             }
 
 
-            return TypeConverter.ToObject(_engine, arguments[0]);
+            return TypeConverter.ToObject(_realm, arguments[0]);
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -155,9 +148,12 @@ namespace Jint.Native.Object
         {
         {
             if (!ReferenceEquals(this, newTarget) && !newTarget.IsUndefined())
             if (!ReferenceEquals(this, newTarget) && !newTarget.IsUndefined())
             {
             {
-                return OrdinaryCreateFromConstructor(newTarget, _engine.Object.PrototypeObject, (engine, state) => new ObjectInstance(engine));
+                return OrdinaryCreateFromConstructor(
+                    newTarget,
+                    static intrinsics => intrinsics.Object.PrototypeObject,
+                    (engine, realm, state) => new ObjectInstance(engine));
             }
             }
-            
+
             if (arguments.Length > 0)
             if (arguments.Length > 0)
             {
             {
                 var value = arguments[0];
                 var value = arguments[0];
@@ -169,13 +165,14 @@ namespace Jint.Native.Object
                 var type = value.Type;
                 var type = value.Type;
                 if (type == Types.String || type == Types.Number || type == Types.Boolean)
                 if (type == Types.String || type == Types.Number || type == Types.Boolean)
                 {
                 {
-                    return TypeConverter.ToObject(_engine, value);
+                    return TypeConverter.ToObject(_realm, value);
                 }
                 }
             }
             }
 
 
+
             var obj = new ObjectInstance(_engine)
             var obj = new ObjectInstance(_engine)
             {
             {
-                _prototype = Engine.Object.PrototypeObject
+                _prototype = _engine.ExecutionContext.Realm.Intrinsics.Object.PrototypeObject
             };
             };
 
 
             return obj;
             return obj;
@@ -185,7 +182,7 @@ namespace Jint.Native.Object
         {
         {
             var obj = new ObjectInstance(_engine)
             var obj = new ObjectInstance(_engine)
             {
             {
-                _prototype = Engine.Object.PrototypeObject,
+                _prototype = Engine.Realm.Intrinsics.Object.PrototypeObject,
             };
             };
 
 
             obj.SetProperties(propertyCount > 0  ? new PropertyDictionary(propertyCount, checkExistingKeys: true) : null);
             obj.SetProperties(propertyCount > 0  ? new PropertyDictionary(propertyCount, checkExistingKeys: true) : null);
@@ -195,7 +192,7 @@ namespace Jint.Native.Object
 
 
         public JsValue GetPrototypeOf(JsValue thisObject, JsValue[] arguments)
         public JsValue GetPrototypeOf(JsValue thisObject, JsValue[] arguments)
         {
         {
-            var obj = TypeConverter.ToObject(_engine, arguments.At(0));
+            var obj = TypeConverter.ToObject(_realm, arguments.At(0));
             return obj.Prototype ?? Null;
             return obj.Prototype ?? Null;
         }
         }
 
 
@@ -207,7 +204,7 @@ namespace Jint.Native.Object
             var prototype = arguments.At(1);
             var prototype = arguments.At(1);
             if (!prototype.IsObject() && !prototype.IsNull())
             if (!prototype.IsObject() && !prototype.IsNull())
             {
             {
-                ExceptionHelper.ThrowTypeError(_engine, $"Object prototype may only be an Object or null: {prototype}");
+                ExceptionHelper.ThrowTypeError(_realm, $"Object prototype may only be an Object or null: {prototype}");
             }
             }
 
 
             if (!(oArg is ObjectInstance o))
             if (!(oArg is ObjectInstance o))
@@ -217,14 +214,14 @@ namespace Jint.Native.Object
 
 
             if (!o.SetPrototypeOf(prototype))
             if (!o.SetPrototypeOf(prototype))
             {
             {
-                ExceptionHelper.ThrowTypeError(_engine);
+                ExceptionHelper.ThrowTypeError(_realm);
             }
             }
             return o;
             return o;
         }
         }
 
 
         internal JsValue GetOwnPropertyDescriptor(JsValue thisObject, JsValue[] arguments)
         internal JsValue GetOwnPropertyDescriptor(JsValue thisObject, JsValue[] arguments)
         {
         {
-            var o = TypeConverter.ToObject(_engine, arguments.At(0));
+            var o = TypeConverter.ToObject(_realm, arguments.At(0));
 
 
             var p = arguments.At(1);
             var p = arguments.At(1);
             var name = TypeConverter.ToPropertyKey(p);
             var name = TypeConverter.ToPropertyKey(p);
@@ -235,9 +232,9 @@ namespace Jint.Native.Object
 
 
         private JsValue GetOwnPropertyDescriptors(JsValue thisObject, JsValue[] arguments)
         private JsValue GetOwnPropertyDescriptors(JsValue thisObject, JsValue[] arguments)
         {
         {
-            var o = TypeConverter.ToObject(_engine, arguments.At(0));
+            var o = TypeConverter.ToObject(_realm, arguments.At(0));
             var ownKeys = o.GetOwnPropertyKeys();
             var ownKeys = o.GetOwnPropertyKeys();
-            var descriptors = _engine.Object.Construct(0);
+            var descriptors = _realm.Intrinsics.Object.Construct(0);
             foreach (var key in ownKeys)
             foreach (var key in ownKeys)
             {
             {
                 var desc = o.GetOwnProperty(key);
                 var desc = o.GetOwnProperty(key);
@@ -252,16 +249,16 @@ namespace Jint.Native.Object
 
 
         public JsValue GetOwnPropertyNames(JsValue thisObject, JsValue[] arguments)
         public JsValue GetOwnPropertyNames(JsValue thisObject, JsValue[] arguments)
         {
         {
-            var o = TypeConverter.ToObject(_engine, arguments.At(0));
+            var o = TypeConverter.ToObject(_realm, arguments.At(0));
             var names = o.GetOwnPropertyKeys(Types.String);
             var names = o.GetOwnPropertyKeys(Types.String);
-            return _engine.Array.ConstructFast(names);
+            return _realm.Intrinsics.Array.ConstructFast(names);
         }
         }
 
 
         private JsValue GetOwnPropertySymbols(JsValue thisObject, JsValue[] arguments)
         private JsValue GetOwnPropertySymbols(JsValue thisObject, JsValue[] arguments)
         {
         {
-            var o = TypeConverter.ToObject(_engine, arguments.At(0));
+            var o = TypeConverter.ToObject(_realm, arguments.At(0));
             var keys = o.GetOwnPropertyKeys(Types.Symbol);
             var keys = o.GetOwnPropertyKeys(Types.Symbol);
-            return _engine.Array.ConstructFast(keys);
+            return _realm.Intrinsics.Array.ConstructFast(keys);
         }
         }
 
 
         private JsValue Create(JsValue thisObject, JsValue[] arguments)
         private JsValue Create(JsValue thisObject, JsValue[] arguments)
@@ -269,10 +266,10 @@ namespace Jint.Native.Object
             var prototype = arguments.At(0);
             var prototype = arguments.At(0);
             if (!prototype.IsObject() && !prototype.IsNull())
             if (!prototype.IsObject() && !prototype.IsNull())
             {
             {
-                ExceptionHelper.ThrowTypeError(_engine, "Object prototype may only be an Object or null: " + prototype);
+                ExceptionHelper.ThrowTypeError(_realm, "Object prototype may only be an Object or null: " + prototype);
             }
             }
 
 
-            var obj = Engine.Object.Construct(Arguments.Empty);
+            var obj = Engine.Realm.Intrinsics.Object.Construct(Arguments.Empty);
             obj._prototype = prototype.IsNull() ? null : prototype.AsObject();
             obj._prototype = prototype.IsNull() ? null : prototype.AsObject();
 
 
             var properties = arguments.At(1);
             var properties = arguments.At(1);
@@ -290,16 +287,17 @@ namespace Jint.Native.Object
 
 
         private JsValue DefineProperty(JsValue thisObject, JsValue[] arguments)
         private JsValue DefineProperty(JsValue thisObject, JsValue[] arguments)
         {
         {
-            if (!(arguments.At(0) is ObjectInstance o))
+            var o = arguments.At(0) as ObjectInstance;
+            if (o is null)
             {
             {
-                return ExceptionHelper.ThrowTypeError<JsValue>(_engine, "Object.defineProperty called on non-object");
+                ExceptionHelper.ThrowTypeError(_realm, "Object.defineProperty called on non-object");
             }
             }
 
 
             var p = arguments.At(1);
             var p = arguments.At(1);
             var name = TypeConverter.ToPropertyKey(p);
             var name = TypeConverter.ToPropertyKey(p);
 
 
             var attributes = arguments.At(2);
             var attributes = arguments.At(2);
-            var desc = PropertyDescriptor.ToPropertyDescriptor(Engine, attributes);
+            var desc = PropertyDescriptor.ToPropertyDescriptor(_realm, attributes);
             o.DefinePropertyOrThrow(name, desc);
             o.DefinePropertyOrThrow(name, desc);
 
 
             return arguments.At(0);
             return arguments.At(0);
@@ -307,13 +305,14 @@ namespace Jint.Native.Object
 
 
         private JsValue DefineProperties(JsValue thisObject, JsValue[] arguments)
         private JsValue DefineProperties(JsValue thisObject, JsValue[] arguments)
         {
         {
-            if (!(arguments.At(0) is ObjectInstance o))
+            var o = arguments.At(0) as ObjectInstance;
+            if (o is null)
             {
             {
-                return ExceptionHelper.ThrowTypeError<JsValue>(_engine, "Object.defineProperty called on non-object");
+                ExceptionHelper.ThrowTypeError(_realm, "Object.defineProperty called on non-object");
             }
             }
 
 
             var properties = arguments.At(1);
             var properties = arguments.At(1);
-            var props = TypeConverter.ToObject(Engine, properties);
+            var props = TypeConverter.ToObject(_realm, properties);
             var descriptors = new List<KeyValuePair<JsValue, PropertyDescriptor>>();
             var descriptors = new List<KeyValuePair<JsValue, PropertyDescriptor>>();
             foreach (var p in props.GetOwnProperties())
             foreach (var p in props.GetOwnProperties())
             {
             {
@@ -323,7 +322,7 @@ namespace Jint.Native.Object
                 }
                 }
 
 
                 var descObj = props.Get(p.Key, props);
                 var descObj = props.Get(p.Key, props);
-                var desc = PropertyDescriptor.ToPropertyDescriptor(Engine, descObj);
+                var desc = PropertyDescriptor.ToPropertyDescriptor(_realm, descObj);
                 descriptors.Add(new KeyValuePair<JsValue, PropertyDescriptor>(p.Key, desc));
                 descriptors.Add(new KeyValuePair<JsValue, PropertyDescriptor>(p.Key, desc));
             }
             }
             foreach (var pair in descriptors)
             foreach (var pair in descriptors)
@@ -469,13 +468,13 @@ namespace Jint.Native.Object
 
 
         private JsValue Keys(JsValue thisObject, JsValue[] arguments)
         private JsValue Keys(JsValue thisObject, JsValue[] arguments)
         {
         {
-            var o = TypeConverter.ToObject(_engine, arguments.At(0));
+            var o = TypeConverter.ToObject(_realm, arguments.At(0));
             return o.EnumerableOwnPropertyNames(EnumerableOwnPropertyNamesKind.Key);
             return o.EnumerableOwnPropertyNames(EnumerableOwnPropertyNamesKind.Key);
         }
         }
 
 
         private JsValue Values(JsValue thisObject, JsValue[] arguments)
         private JsValue Values(JsValue thisObject, JsValue[] arguments)
         {
         {
-            var o = TypeConverter.ToObject(_engine, arguments.At(0));
+            var o = TypeConverter.ToObject(_realm, arguments.At(0));
             return o.EnumerableOwnPropertyNames(EnumerableOwnPropertyNamesKind.Value);
             return o.EnumerableOwnPropertyNames(EnumerableOwnPropertyNamesKind.Value);
         }
         }
 
 

+ 35 - 23
Jint/Native/Object/ObjectInstance.cs

@@ -65,7 +65,7 @@ namespace Jint.Native.Object
 
 
         internal PropertyDictionary Properties
         internal PropertyDictionary Properties
         {
         {
-            [DebuggerStepThrough]            
+            [DebuggerStepThrough]
             [MethodImpl(MethodImplOptions.AggressiveInlining)]
             [MethodImpl(MethodImplOptions.AggressiveInlining)]
             get => _properties;
             get => _properties;
         }
         }
@@ -101,9 +101,10 @@ namespace Jint.Native.Object
                 return defaultConstructor;
                 return defaultConstructor;
             }
             }
 
 
-            if (!(c is ObjectInstance oi))
+            var oi = c as ObjectInstance;
+            if (oi is null)
             {
             {
-                return ExceptionHelper.ThrowTypeError<IConstructor>(o._engine);
+                ExceptionHelper.ThrowTypeError(o._engine.Realm);
             }
             }
 
 
             var s = oi.Get(GlobalSymbolRegistry.Species);
             var s = oi.Get(GlobalSymbolRegistry.Species);
@@ -116,10 +117,10 @@ namespace Jint.Native.Object
             {
             {
                 return (IConstructor) s;
                 return (IConstructor) s;
             }
             }
-            
-            return ExceptionHelper.ThrowTypeError<IConstructor>(o._engine);
-        }
 
 
+            ExceptionHelper.ThrowTypeError(o._engine.Realm);
+            return null;
+        }
 
 
         internal void SetProperties(PropertyDictionary properties)
         internal void SetProperties(PropertyDictionary properties)
         {
         {
@@ -435,7 +436,7 @@ namespace Jint.Native.Object
         {
         {
             if (!Set(p, v, this) && throwOnError)
             if (!Set(p, v, this) && throwOnError)
             {
             {
-                ExceptionHelper.ThrowTypeError(_engine);
+                ExceptionHelper.ThrowTypeError(_engine.Realm);
             }
             }
 
 
             return true;
             return true;
@@ -505,7 +506,7 @@ namespace Jint.Native.Object
 
 
             return true;
             return true;
         }
         }
-        
+
         /// <summary>
         /// <summary>
         /// Returns a Boolean value indicating whether a
         /// Returns a Boolean value indicating whether a
         /// [[Put]] operation with PropertyName can be
         /// [[Put]] operation with PropertyName can be
@@ -590,7 +591,7 @@ namespace Jint.Native.Object
         {
         {
             if (!Delete(property))
             if (!Delete(property))
             {
             {
-                ExceptionHelper.ThrowTypeError(Engine);
+                ExceptionHelper.ThrowTypeError(_engine.Realm);
             }
             }
             return true;
             return true;
         }
         }
@@ -622,7 +623,7 @@ namespace Jint.Native.Object
         {
         {
             if (!DefineOwnProperty(property, desc))
             if (!DefineOwnProperty(property, desc))
             {
             {
-                ExceptionHelper.ThrowTypeError(_engine, "Cannot redefine property: " + property);
+                ExceptionHelper.ThrowTypeError(_engine.Realm, "Cannot redefine property: " + property);
             }
             }
 
 
             return true;
             return true;
@@ -680,7 +681,7 @@ namespace Jint.Native.Object
                             };
                             };
                         }
                         }
 
 
-                        propertyDescriptor._flags |= desc._flags & PropertyFlag.MutableBinding; 
+                        propertyDescriptor._flags |= desc._flags & PropertyFlag.MutableBinding;
                         o.SetOwnProperty(property, propertyDescriptor);
                         o.SetOwnProperty(property, propertyDescriptor);
                     }
                     }
                     else
                     else
@@ -1017,7 +1018,7 @@ namespace Jint.Native.Object
                 }
                 }
 
 
                 return (long) System.Math.Max(
                 return (long) System.Math.Max(
-                    0, 
+                    0,
                     System.Math.Min(len, ArrayOperations.MaxArrayLikeLength));
                     System.Math.Min(len, ArrayOperations.MaxArrayLikeLength));
             }
             }
 
 
@@ -1035,7 +1036,7 @@ namespace Jint.Native.Object
                 value = Undefined;
                 value = Undefined;
                 return false;
                 return false;
             }
             }
-            
+
             var callbackfn = arguments.At(0);
             var callbackfn = arguments.At(0);
             var thisArg = arguments.At(1);
             var thisArg = arguments.At(1);
             var callable = GetCallable(callbackfn);
             var callable = GetCallable(callbackfn);
@@ -1073,7 +1074,8 @@ namespace Jint.Native.Object
                 return callable;
                 return callable;
             }
             }
 
 
-            return ExceptionHelper.ThrowTypeError<ICallable>(_engine, "Argument must be callable");
+            ExceptionHelper.ThrowTypeError(_engine.Realm, "Argument must be callable");
+            return null;
         }
         }
 
 
         internal bool IsConcatSpreadable
         internal bool IsConcatSpreadable
@@ -1169,7 +1171,7 @@ namespace Jint.Native.Object
             var newDesc = new PropertyDescriptor(v, PropertyFlag.NonEnumerable);
             var newDesc = new PropertyDescriptor(v, PropertyFlag.NonEnumerable);
             return DefineOwnProperty(p, newDesc);
             return DefineOwnProperty(p, newDesc);
         }
         }
-        
+
         /// <summary>
         /// <summary>
         /// https://tc39.es/ecma262/#sec-createdatapropertyorthrow
         /// https://tc39.es/ecma262/#sec-createdatapropertyorthrow
         /// </summary>
         /// </summary>
@@ -1186,7 +1188,7 @@ namespace Jint.Native.Object
         {
         {
             if (!CreateDataProperty(p, v))
             if (!CreateDataProperty(p, v))
             {
             {
-                ExceptionHelper.ThrowTypeError(_engine);
+                ExceptionHelper.ThrowTypeError(_engine.Realm);
             }
             }
 
 
             return true;
             return true;
@@ -1206,7 +1208,12 @@ namespace Jint.Native.Object
                 return null;
                 return null;
             }
             }
 
 
-            return jsValue as ICallable ?? ExceptionHelper.ThrowTypeError<ICallable>(engine, "Value returned for property '" + p + "' of object is not a function");
+            var callable = jsValue as ICallable;
+            if (callable is null)
+            {
+                ExceptionHelper.ThrowTypeError(engine.Realm, "Value returned for property '" + p + "' of object is not a function");
+            }
+            return callable;
         }
         }
 
 
         internal void CopyDataProperties(
         internal void CopyDataProperties(
@@ -1232,7 +1239,7 @@ namespace Jint.Native.Object
         {
         {
             var ownKeys = GetOwnPropertyKeys(Types.String);
             var ownKeys = GetOwnPropertyKeys(Types.String);
 
 
-            var array = Engine.Array.ConstructFast((uint) ownKeys.Count);
+            var array = Engine.Realm.Intrinsics.Array.ConstructFast((uint) ownKeys.Count);
             uint index = 0;
             uint index = 0;
 
 
             for (var i = 0; i < ownKeys.Count; i++)
             for (var i = 0; i < ownKeys.Count; i++)
@@ -1243,7 +1250,7 @@ namespace Jint.Native.Object
                 {
                 {
                     continue;
                     continue;
                 }
                 }
-                
+
                 var desc = GetOwnProperty(property);
                 var desc = GetOwnProperty(property);
                 if (desc != PropertyDescriptor.Undefined && desc.Enumerable)
                 if (desc != PropertyDescriptor.Undefined && desc.Enumerable)
                 {
                 {
@@ -1260,7 +1267,7 @@ namespace Jint.Native.Object
                         }
                         }
                         else
                         else
                         {
                         {
-                            var objectInstance = _engine.Array.ConstructFast(2);
+                            var objectInstance = _engine.Realm.Intrinsics.Array.ConstructFast(2);
                             objectInstance.SetIndexValue(0,  property, updateLength: false);
                             objectInstance.SetIndexValue(0,  property, updateLength: false);
                             objectInstance.SetIndexValue(1, value, updateLength: false);
                             objectInstance.SetIndexValue(1, value, updateLength: false);
                             array.SetIndexValue(index, objectInstance, updateLength: false);
                             array.SetIndexValue(index, objectInstance, updateLength: false);
@@ -1284,13 +1291,18 @@ namespace Jint.Native.Object
 
 
         internal ObjectInstance AssertThisIsObjectInstance(JsValue value, string methodName)
         internal ObjectInstance AssertThisIsObjectInstance(JsValue value, string methodName)
         {
         {
-            return value as ObjectInstance ?? ThrowIncompatibleReceiver<ObjectInstance>(value, methodName);
+            var instance = value as ObjectInstance;
+            if (instance is null)
+            {
+                ThrowIncompatibleReceiver(value, methodName);
+            }
+            return instance;
         }
         }
 
 
         [MethodImpl(MethodImplOptions.NoInlining)]
         [MethodImpl(MethodImplOptions.NoInlining)]
-        private T ThrowIncompatibleReceiver<T>(JsValue value, string methodName)
+        private void ThrowIncompatibleReceiver(JsValue value, string methodName)
         {
         {
-            return ExceptionHelper.ThrowTypeError<T>(_engine, $"Method {methodName} called on incompatible receiver {value}");
+            ExceptionHelper.ThrowTypeError(_engine.Realm, $"Method {methodName} called on incompatible receiver {value}");
         }
         }
 
 
         public override bool Equals(JsValue obj)
         public override bool Equals(JsValue obj)

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

@@ -8,20 +8,16 @@ namespace Jint.Native.Object
 {
 {
     public sealed class ObjectPrototype : ObjectInstance
     public sealed class ObjectPrototype : ObjectInstance
     {
     {
-        private ObjectConstructor _objectConstructor;
+        private readonly Realm _realm;
+        private readonly ObjectConstructor _constructor;
 
 
-        private ObjectPrototype(Engine engine) : base(engine)
+        internal ObjectPrototype(
+            Engine engine,
+            Realm realm,
+            ObjectConstructor constructor) : base(engine)
         {
         {
-        }
-
-        public static ObjectPrototype CreatePrototypeObject(Engine engine, ObjectConstructor objectConstructor)
-        {
-            var obj = new ObjectPrototype(engine)
-            {
-                _objectConstructor = objectConstructor
-            };
-
-            return obj;
+            _realm = realm;
+            _constructor = constructor;
         }
         }
 
 
         protected override void Initialize()
         protected override void Initialize()
@@ -30,7 +26,7 @@ namespace Jint.Native.Object
             const PropertyFlag lengthFlags = PropertyFlag.Configurable;
             const PropertyFlag lengthFlags = PropertyFlag.Configurable;
             var properties = new PropertyDictionary(8, checkExistingKeys: false)
             var properties = new PropertyDictionary(8, checkExistingKeys: false)
             {
             {
-                ["constructor"] = new PropertyDescriptor(_objectConstructor, propertyFlags),
+                ["constructor"] = new PropertyDescriptor(_constructor, propertyFlags),
                 ["toString"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "toString", ToObjectString, 0, lengthFlags), propertyFlags),
                 ["toString"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "toString", ToObjectString, 0, lengthFlags), propertyFlags),
                 ["toLocaleString"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "toLocaleString", ToLocaleString, 0, lengthFlags), propertyFlags),
                 ["toLocaleString"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "toLocaleString", ToLocaleString, 0, lengthFlags), propertyFlags),
                 ["valueOf"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "valueOf", ValueOf, 0, lengthFlags), propertyFlags),
                 ["valueOf"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "valueOf", ValueOf, 0, lengthFlags), propertyFlags),
@@ -44,18 +40,18 @@ namespace Jint.Native.Object
         private JsValue PropertyIsEnumerable(JsValue thisObject, JsValue[] arguments)
         private JsValue PropertyIsEnumerable(JsValue thisObject, JsValue[] arguments)
         {
         {
             var p = TypeConverter.ToPropertyKey(arguments[0]);
             var p = TypeConverter.ToPropertyKey(arguments[0]);
-            var o = TypeConverter.ToObject(Engine, thisObject);
+            var o = TypeConverter.ToObject(_realm, thisObject);
             var desc = o.GetOwnProperty(p);
             var desc = o.GetOwnProperty(p);
             if (desc == PropertyDescriptor.Undefined)
             if (desc == PropertyDescriptor.Undefined)
             {
             {
-                return false;
+                return JsBoolean.False;
             }
             }
             return desc.Enumerable;
             return desc.Enumerable;
         }
         }
 
 
         private JsValue ValueOf(JsValue thisObject, JsValue[] arguments)
         private JsValue ValueOf(JsValue thisObject, JsValue[] arguments)
         {
         {
-            var o = TypeConverter.ToObject(Engine, thisObject);
+            var o = TypeConverter.ToObject(_realm, thisObject);
             return o;
             return o;
         }
         }
 
 
@@ -64,35 +60,38 @@ namespace Jint.Native.Object
             var arg = arguments[0];
             var arg = arguments[0];
             if (!arg.IsObject())
             if (!arg.IsObject())
             {
             {
-                return false;
+                return JsBoolean.False;
             }
             }
 
 
             var v = arg.AsObject();
             var v = arg.AsObject();
 
 
-            var o = TypeConverter.ToObject(Engine, thisObject);
+            var o = TypeConverter.ToObject(_realm, thisObject);
             while (true)
             while (true)
             {
             {
                 v = v.Prototype;
                 v = v.Prototype;
 
 
                 if (ReferenceEquals(v, null))
                 if (ReferenceEquals(v, null))
                 {
                 {
-                    return false;
+                    return JsBoolean.False;
                 }
                 }
 
 
                 if (ReferenceEquals(o, v))
                 if (ReferenceEquals(o, v))
                 {
                 {
-                    return true;
+                    return JsBoolean.True;
                 }
                 }
-
             }
             }
         }
         }
 
 
         private JsValue ToLocaleString(JsValue thisObject, JsValue[] arguments)
         private JsValue ToLocaleString(JsValue thisObject, JsValue[] arguments)
         {
         {
-            var o = TypeConverter.ToObject(Engine, thisObject);
+            var o = TypeConverter.ToObject(_realm, thisObject);
             var func = o.Get("toString");
             var func = o.Get("toString");
-            var callable = func as ICallable ?? ExceptionHelper.ThrowTypeErrorNoEngine<ICallable>("Can only invoke functions");
-            return TypeConverter.ToString(callable.Call(thisObject, arguments));
+            var callable = func as ICallable;
+            if (callable is null)
+            {
+                ExceptionHelper.ThrowTypeError(_realm, "Can only invoke functions");
+            }
+            return TypeConverter.ToJsString(callable.Call(thisObject, arguments));
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -110,7 +109,7 @@ namespace Jint.Native.Object
                 return "[object Null]";
                 return "[object Null]";
             }
             }
 
 
-            var o = TypeConverter.ToObject(Engine, thisObject);
+            var o = TypeConverter.ToObject(_realm, thisObject);
 
 
             var tag = o.Get(GlobalSymbolRegistry.ToStringTag);
             var tag = o.Get(GlobalSymbolRegistry.ToStringTag);
             if (!tag.IsString())
             if (!tag.IsString())
@@ -127,7 +126,7 @@ namespace Jint.Native.Object
         public JsValue HasOwnProperty(JsValue thisObject, JsValue[] arguments)
         public JsValue HasOwnProperty(JsValue thisObject, JsValue[] arguments)
         {
         {
             var p = TypeConverter.ToPropertyKey(arguments[0]);
             var p = TypeConverter.ToPropertyKey(arguments[0]);
-            var o = TypeConverter.ToObject(Engine, thisObject);
+            var o = TypeConverter.ToObject(_realm, thisObject);
             var desc = o.GetOwnProperty(p);
             var desc = o.GetOwnProperty(p);
             return desc != PropertyDescriptor.Undefined;
             return desc != PropertyDescriptor.Undefined;
         }
         }

+ 39 - 42
Jint/Native/Promise/PromiseConstructor.cs

@@ -23,22 +23,17 @@ namespace Jint.Native.Promise
 
 
         internal PromisePrototype PrototypeObject { get; private set; }
         internal PromisePrototype PrototypeObject { get; private set; }
 
 
-        private PromiseConstructor(Engine engine)
-            : base(engine, _functionName)
+        internal PromiseConstructor(
+            Engine engine,
+            Realm realm,
+            FunctionPrototype functionPrototype,
+            ObjectPrototype objectPrototype)
+            : base(engine, realm, _functionName)
         {
         {
-        }
-
-        internal static PromiseConstructor CreatePromiseConstructor(Engine engine)
-        {
-            var obj = new PromiseConstructor(engine)
-            {
-                _prototype = engine.Function.PrototypeObject
-            };
-
-            obj.PrototypeObject = PromisePrototype.CreatePrototypeObject(engine, obj);
-            obj._length = new PropertyDescriptor(1, PropertyFlag.Configurable);
-            obj._prototypeDescriptor = new PropertyDescriptor(obj.PrototypeObject, PropertyFlag.AllForbidden);
-            return obj;
+            _prototype = functionPrototype;
+            PrototypeObject = new PromisePrototype(engine, realm, this, objectPrototype);
+            _length = new PropertyDescriptor(1, PropertyFlag.Configurable);
+            _prototypeDescriptor = new PropertyDescriptor(PrototypeObject, PropertyFlag.AllForbidden);
         }
         }
 
 
         protected override void Initialize()
         protected override void Initialize()
@@ -71,26 +66,28 @@ namespace Jint.Native.Promise
         }
         }
 
 
         public override JsValue Call(JsValue thisObject, JsValue[] arguments)
         public override JsValue Call(JsValue thisObject, JsValue[] arguments)
-        { 
-            return ExceptionHelper.ThrowTypeError<JsValue>(_engine, "Constructor Promise requires 'new'");
+        {
+            ExceptionHelper.ThrowTypeError(_realm, "Constructor Promise requires 'new'");
+            return null;
         }
         }
 
 
         public ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
         public ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
         {
         {
             if (newTarget.IsUndefined())
             if (newTarget.IsUndefined())
             {
             {
-                ExceptionHelper.ThrowTypeError(_engine, "Constructor Promise requires 'new'");
+                ExceptionHelper.ThrowTypeError(_realm, "Constructor Promise requires 'new'");
             }
             }
-            
-            if (arguments.At(0) is not ICallable promiseExecutor)
+
+            var promiseExecutor = arguments.At(0) as ICallable;
+            if (promiseExecutor is null)
             {
             {
-                return ExceptionHelper.ThrowTypeError<ObjectInstance>(
-                    _engine,
-                    $"Promise executor {(arguments.At(0))} is not a function");
+                ExceptionHelper.ThrowTypeError(_realm, $"Promise executor {(arguments.At(0))} is not a function");
             }
             }
 
 
-            var instance = OrdinaryCreateFromConstructor(newTarget, PrototypeObject,
-                static(engine, _) => new PromiseInstance(engine));
+            var instance = OrdinaryCreateFromConstructor(
+                newTarget,
+                static intrinsics => intrinsics.Promise.PrototypeObject,
+                static(engine, realm, _) => new PromiseInstance(engine));
 
 
             var (resolve, reject) = instance.CreateResolvingFunctions();
             var (resolve, reject) = instance.CreateResolvingFunctions();
             promiseExecutor.Call(Undefined, new JsValue[] {resolve, reject});
             promiseExecutor.Call(Undefined, new JsValue[] {resolve, reject});
@@ -112,12 +109,12 @@ namespace Jint.Native.Promise
         {
         {
             if (!thisObj.IsObject())
             if (!thisObj.IsObject())
             {
             {
-                ExceptionHelper.ThrowTypeError(_engine, "PromiseResolve called on non-object");
+                ExceptionHelper.ThrowTypeError(_realm, "PromiseResolve called on non-object");
             }
             }
 
 
             if (thisObj is not IConstructor)
             if (thisObj is not IConstructor)
             {
             {
-                ExceptionHelper.ThrowTypeError(_engine, "Promise.resolve invoked on a non-constructor value");
+                ExceptionHelper.ThrowTypeError(_realm, "Promise.resolve invoked on a non-constructor value");
             }
             }
 
 
             JsValue x = arguments.At(0);
             JsValue x = arguments.At(0);
@@ -141,12 +138,12 @@ namespace Jint.Native.Promise
         {
         {
             if (!thisObj.IsObject())
             if (!thisObj.IsObject())
             {
             {
-                ExceptionHelper.ThrowTypeError(_engine, "Promise.reject called on non-object");
+                ExceptionHelper.ThrowTypeError(_realm, "Promise.reject called on non-object");
             }
             }
 
 
             if (thisObj is not IConstructor)
             if (thisObj is not IConstructor)
             {
             {
-                ExceptionHelper.ThrowTypeError(_engine, "Promise.reject invoked on a non-constructor value");
+                ExceptionHelper.ThrowTypeError(_realm, "Promise.reject invoked on a non-constructor value");
             }
             }
 
 
             var r = arguments.At(0);
             var r = arguments.At(0);
@@ -177,7 +174,7 @@ namespace Jint.Native.Promise
         {
         {
             if (!thisObj.IsObject())
             if (!thisObj.IsObject())
             {
             {
-                ExceptionHelper.ThrowTypeError(_engine, "Promise.all called on non-object");
+                ExceptionHelper.ThrowTypeError(_realm, "Promise.all called on non-object");
             }
             }
 
 
             //2. Let promiseCapability be ? NewPromiseCapability(C).
             //2. Let promiseCapability be ? NewPromiseCapability(C).
@@ -205,12 +202,12 @@ namespace Jint.Native.Promise
             {
             {
                 if (arguments.Length == 0)
                 if (arguments.Length == 0)
                 {
                 {
-                    ExceptionHelper.ThrowTypeError(_engine, "no arguments were passed to Promise.all");
+                    ExceptionHelper.ThrowTypeError(_realm, "no arguments were passed to Promise.all");
                 }
                 }
 
 
                 var iterable = arguments.At(0);
                 var iterable = arguments.At(0);
 
 
-                iterator = iterable.GetIterator(_engine);
+                iterator = iterable.GetIterator(_realm);
             }
             }
             catch (JavaScriptException e)
             catch (JavaScriptException e)
             {
             {
@@ -229,7 +226,7 @@ namespace Jint.Native.Promise
                 // if "then" method is sync then it will be resolved BEFORE the next iteration cycle
                 // if "then" method is sync then it will be resolved BEFORE the next iteration cycle
                 if (results.TrueForAll(static x => x != null) && doneIterating)
                 if (results.TrueForAll(static x => x != null) && doneIterating)
                 {
                 {
-                    var array = _engine.Array.ConstructFast(results);
+                    var array = _realm.Intrinsics.Array.ConstructFast(results);
                     resolve.Call(Undefined, new JsValue[] { array });
                     resolve.Call(Undefined, new JsValue[] { array });
                 }
                 }
             }
             }
@@ -290,7 +287,7 @@ namespace Jint.Native.Promise
                     }
                     }
                     else
                     else
                     {
                     {
-                        ExceptionHelper.ThrowTypeError(_engine, "Passed non Promise-like value");
+                        ExceptionHelper.ThrowTypeError(_realm, "Passed non Promise-like value");
                     }
                     }
 
 
                     index += 1;
                     index += 1;
@@ -308,7 +305,7 @@ namespace Jint.Native.Promise
             // resolve the promise sync
             // resolve the promise sync
             if (results.Count == 0)
             if (results.Count == 0)
             {
             {
-                resolve.Call(Undefined, new JsValue[] {Engine.Array.ConstructFast(0)});
+                resolve.Call(Undefined, new JsValue[] {_realm.Intrinsics.Array.ConstructFast(0)});
             }
             }
 
 
             return resultingPromise;
             return resultingPromise;
@@ -319,7 +316,7 @@ namespace Jint.Native.Promise
         {
         {
             if (!thisObj.IsObject())
             if (!thisObj.IsObject())
             {
             {
-                ExceptionHelper.ThrowTypeError(_engine, "Promise.all called on non-object");
+                ExceptionHelper.ThrowTypeError(_realm, "Promise.all called on non-object");
             }
             }
 
 
             // 2. Let promiseCapability be ? NewPromiseCapability(C).
             // 2. Let promiseCapability be ? NewPromiseCapability(C).
@@ -347,12 +344,12 @@ namespace Jint.Native.Promise
             {
             {
                 if (arguments.Length == 0)
                 if (arguments.Length == 0)
                 {
                 {
-                    ExceptionHelper.ThrowTypeError(_engine, "no arguments were passed to Promise.all");
+                    ExceptionHelper.ThrowTypeError(_realm, "no arguments were passed to Promise.all");
                 }
                 }
 
 
                 var iterable = arguments.At(0);
                 var iterable = arguments.At(0);
 
 
-                iterator = iterable.GetIterator(_engine);
+                iterator = iterable.GetIterator(_realm);
             }
             }
             catch (JavaScriptException e)
             catch (JavaScriptException e)
             {
             {
@@ -424,7 +421,7 @@ namespace Jint.Native.Promise
                 return resolve;
                 return resolve;
             }
             }
 
 
-            ExceptionHelper.ThrowTypeError(_engine, "resolve is not a function");
+            ExceptionHelper.ThrowTypeError(_realm, "resolve is not a function");
             // Note: throws right before return
             // Note: throws right before return
             return null;
             return null;
         }
         }
@@ -465,7 +462,7 @@ namespace Jint.Native.Promise
                 if (resolveArg != null && resolveArg != Undefined ||
                 if (resolveArg != null && resolveArg != Undefined ||
                     rejectArg != null && rejectArg != Undefined)
                     rejectArg != null && rejectArg != Undefined)
                 {
                 {
-                    ExceptionHelper.ThrowTypeError(engine, "executor was already called with not undefined args");
+                    ExceptionHelper.ThrowTypeError(engine.Realm, "executor was already called with not undefined args");
                 }
                 }
 
 
                 resolveArg = arguments.At(0);
                 resolveArg = arguments.At(0);
@@ -487,7 +484,7 @@ namespace Jint.Native.Promise
             }
             }
             else
             else
             {
             {
-                ExceptionHelper.ThrowTypeError(engine, "resolve is not a function");
+                ExceptionHelper.ThrowTypeError(engine.Realm, "resolve is not a function");
             }
             }
 
 
             if (rejectArg is ICallable rejFunc)
             if (rejectArg is ICallable rejFunc)
@@ -496,7 +493,7 @@ namespace Jint.Native.Promise
             }
             }
             else
             else
             {
             {
-                ExceptionHelper.ThrowTypeError(engine, "reject is not a function");
+                ExceptionHelper.ThrowTypeError(engine.Realm, "reject is not a function");
             }
             }
 
 
             return new PromiseCapability(instance, resolve, reject, rejectArg);
             return new PromiseCapability(instance, resolve, reject, rejectArg);

+ 2 - 3
Jint/Native/Promise/PromiseInstance.cs

@@ -45,7 +45,7 @@ namespace Jint.Native.Promise
     {
     {
         internal PromiseState State { get; private set; }
         internal PromiseState State { get; private set; }
 
 
-        // valid only in settled state (Fulfilled or Rejected) 
+        // valid only in settled state (Fulfilled or Rejected)
         internal JsValue Value { get; private set; }
         internal JsValue Value { get; private set; }
 
 
         internal List<PromiseReaction> PromiseRejectReactions = new();
         internal List<PromiseReaction> PromiseRejectReactions = new();
@@ -95,8 +95,7 @@ namespace Jint.Native.Promise
 
 
             if (result == this)
             if (result == this)
             {
             {
-                ExceptionHelper.ThrowTypeError(_engine,
-                    "Cannot resolve Promise with itself");
+                ExceptionHelper.ThrowTypeError(_engine.Realm, "Cannot resolve Promise with itself");
                 return Undefined;
                 return Undefined;
             }
             }
 
 

+ 25 - 24
Jint/Native/Promise/PromisePrototype.cs

@@ -7,23 +7,18 @@ using Jint.Runtime.Interop;
 
 
 namespace Jint.Native.Promise
 namespace Jint.Native.Promise
 {
 {
-    internal sealed class PromisePrototype : ObjectInstance
+    internal sealed class PromisePrototype : Prototype
     {
     {
-        private PromiseConstructor _promiseConstructor;
+        private readonly PromiseConstructor _constructor;
 
 
-        private PromisePrototype(Engine engine) : base(engine)
+        internal PromisePrototype(
+            Engine engine,
+            Realm realm,
+            PromiseConstructor constructor,
+            ObjectPrototype objectPrototype) : base(engine, realm)
         {
         {
-        }
-
-        public static PromisePrototype CreatePrototypeObject(Engine engine, PromiseConstructor promiseConstructor)
-        {
-            var obj = new PromisePrototype(engine)
-            {
-                _prototype = engine.Object.PrototypeObject,
-                _promiseConstructor = promiseConstructor
-            };
-
-            return obj;
+            _prototype = objectPrototype;
+            _constructor = constructor;
         }
         }
 
 
         protected override void Initialize()
         protected override void Initialize()
@@ -32,7 +27,7 @@ namespace Jint.Native.Promise
             const PropertyFlag propertyFlags = PropertyFlag.Configurable | PropertyFlag.Writable;
             const PropertyFlag propertyFlags = PropertyFlag.Configurable | PropertyFlag.Writable;
             var properties = new PropertyDictionary(5, checkExistingKeys: false)
             var properties = new PropertyDictionary(5, checkExistingKeys: false)
             {
             {
-                ["constructor"] = new(_promiseConstructor, PropertyFlag.NonEnumerable),
+                ["constructor"] = new(_constructor, PropertyFlag.NonEnumerable),
                 ["then"] = new(new ClrFunctionInstance(Engine, "then", Then, 2, lengthFlags), propertyFlags),
                 ["then"] = new(new ClrFunctionInstance(Engine, "then", Then, 2, lengthFlags), propertyFlags),
                 ["catch"] = new(new ClrFunctionInstance(Engine, "catch", Catch, 1, lengthFlags), propertyFlags),
                 ["catch"] = new(new ClrFunctionInstance(Engine, "catch", Catch, 1, lengthFlags), propertyFlags),
                 ["finally"] = new(new ClrFunctionInstance(Engine, "finally", Finally, 1, lengthFlags), propertyFlags)
                 ["finally"] = new(new ClrFunctionInstance(Engine, "finally", Finally, 1, lengthFlags), propertyFlags)
@@ -59,11 +54,14 @@ namespace Jint.Native.Promise
         {
         {
             // 1. Let promise be the this value.
             // 1. Let promise be the this value.
             // 2. If IsPromise(promise) is false, throw a TypeError exception.
             // 2. If IsPromise(promise) is false, throw a TypeError exception.
-            var promise = thisValue as PromiseInstance ?? ExceptionHelper.ThrowTypeError<PromiseInstance>(_engine,
-                "Method Promise.prototype.then called on incompatible receiver");
+            var promise = thisValue as PromiseInstance;
+            if (promise is null)
+            {
+                ExceptionHelper.ThrowTypeError(_realm, "Method Promise.prototype.then called on incompatible receiver");
+            }
 
 
             // 3. Let C be ? SpeciesConstructor(promise, %Promise%).
             // 3. Let C be ? SpeciesConstructor(promise, %Promise%).
-            var ctor = SpeciesConstructor(promise, _engine.Promise);
+            var ctor = SpeciesConstructor(promise, _realm.Intrinsics.Promise);
 
 
             // 4. Let resultCapability be ? NewPromiseCapability(C).
             // 4. Let resultCapability be ? NewPromiseCapability(C).
             var capability = PromiseConstructor.NewPromiseCapability(_engine, ctor as JsValue);
             var capability = PromiseConstructor.NewPromiseCapability(_engine, ctor as JsValue);
@@ -73,7 +71,7 @@ namespace Jint.Native.Promise
         }
         }
 
 
         // https://tc39.es/ecma262/#sec-promise.prototype.catch
         // https://tc39.es/ecma262/#sec-promise.prototype.catch
-        // 
+        //
         // When the catch method is called with argument onRejected,
         // When the catch method is called with argument onRejected,
         // the following steps are taken:
         // the following steps are taken:
         //
         //
@@ -87,12 +85,15 @@ namespace Jint.Native.Promise
         {
         {
             // 1. Let promise be the this value.
             // 1. Let promise be the this value.
             // 2. If Type(promise) is not Object, throw a TypeError exception.
             // 2. If Type(promise) is not Object, throw a TypeError exception.
-            var promise = thisValue as ObjectInstance ?? ExceptionHelper.ThrowTypeError<ObjectInstance>(_engine,
-                "this passed to Promise.prototype.finally is not an object");
+            var promise = thisValue as ObjectInstance;
+            if (promise is null)
+            {
+                ExceptionHelper.ThrowTypeError(_realm, "this passed to Promise.prototype.finally is not an object");
+            }
 
 
             // 3. Let C be ? SpeciesConstructor(promise, %Promise%).
             // 3. Let C be ? SpeciesConstructor(promise, %Promise%).
             // 4. Assert: IsConstructor(C) is true.
             // 4. Assert: IsConstructor(C) is true.
-            var ctor = SpeciesConstructor(promise, _engine.Promise);
+            var ctor = SpeciesConstructor(promise, _realm.Intrinsics.Promise);
 
 
             JsValue thenFinally;
             JsValue thenFinally;
             JsValue catchFinally;
             JsValue catchFinally;
@@ -126,7 +127,7 @@ namespace Jint.Native.Promise
                 var result = onFinally.Call(Undefined, Arguments.Empty);
                 var result = onFinally.Call(Undefined, Arguments.Empty);
 
 
                 // 7. Let promise be ? PromiseResolve(C, result).
                 // 7. Let promise be ? PromiseResolve(C, result).
-                var promise = _engine.Promise.Resolve(ctor as JsValue, new[] {result});
+                var promise = _realm.Intrinsics.Promise.Resolve(ctor as JsValue, new[] {result});
 
 
                 // 8. Let valueThunk be equivalent to a function that returns value.
                 // 8. Let valueThunk be equivalent to a function that returns value.
                 var valueThunk = new ClrFunctionInstance(_engine, "", (_, _) => value);
                 var valueThunk = new ClrFunctionInstance(_engine, "", (_, _) => value);
@@ -145,7 +146,7 @@ namespace Jint.Native.Promise
                 var result = onFinally.Call(Undefined, Arguments.Empty);
                 var result = onFinally.Call(Undefined, Arguments.Empty);
 
 
                 // 7. Let promise be ? PromiseResolve(C, result).
                 // 7. Let promise be ? PromiseResolve(C, result).
-                var promise = _engine.Promise.Resolve(ctor as JsValue, new[] {result});
+                var promise = _realm.Intrinsics.Promise.Resolve(ctor as JsValue, new[] {result});
 
 
                 // 8. Let thrower be equivalent to a function that throws reason.
                 // 8. Let thrower be equivalent to a function that throws reason.
                 var thrower = new ClrFunctionInstance(_engine, "", (_, _) => throw new JavaScriptException(reason));
                 var thrower = new ClrFunctionInstance(_engine, "", (_, _) => throw new JavaScriptException(reason));

+ 15 - 0
Jint/Native/Prototype.cs

@@ -0,0 +1,15 @@
+using Jint.Native.Object;
+using Jint.Runtime;
+
+namespace Jint.Native
+{
+    public abstract class Prototype : ObjectInstance
+    {
+        internal readonly Realm _realm;
+
+        protected Prototype(Engine engine, Realm realm) : base(engine)
+        {
+            _realm = realm;
+        }
+    }
+}

+ 12 - 15
Jint/Native/Proxy/ProxyConstructor.cs

@@ -13,21 +13,18 @@ namespace Jint.Native.Proxy
         private static readonly JsString PropertyProxy = new JsString("proxy");
         private static readonly JsString PropertyProxy = new JsString("proxy");
         private static readonly JsString PropertyRevoke = new JsString("revoke");
         private static readonly JsString PropertyRevoke = new JsString("revoke");
 
 
-        private ProxyConstructor(Engine engine)
-            : base(engine, _name)
+        internal ProxyConstructor(
+            Engine engine,
+            Realm realm)
+            : base(engine, realm, _name)
         {
         {
-        }
-
-        public static ProxyConstructor CreateProxyConstructor(Engine engine)
-        {
-            var obj = new ProxyConstructor(engine);
-            obj._length = new PropertyDescriptor(2, PropertyFlag.Configurable);
-            return obj;
+            _length = new PropertyDescriptor(2, PropertyFlag.Configurable);
         }
         }
 
 
         public override JsValue Call(JsValue thisObject, JsValue[] arguments)
         public override JsValue Call(JsValue thisObject, JsValue[] arguments)
         {
         {
-            return ExceptionHelper.ThrowTypeError<JsValue>(_engine, "Constructor Proxy requires 'new'");
+            ExceptionHelper.ThrowTypeError(_realm, "Constructor Proxy requires 'new'");
+            return null;
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -40,7 +37,7 @@ namespace Jint.Native.Proxy
 
 
             if (!target.IsObject() || !handler.IsObject())
             if (!target.IsObject() || !handler.IsObject())
             {
             {
-                return ExceptionHelper.ThrowTypeError<ObjectInstance>(_engine, "Cannot create proxy with a non-object as target or handler");
+                ExceptionHelper.ThrowTypeError(_realm, "Cannot create proxy with a non-object as target or handler");
             }
             }
             return Construct(target.AsObject(), handler.AsObject());
             return Construct(target.AsObject(), handler.AsObject());
         }
         }
@@ -56,18 +53,18 @@ namespace Jint.Native.Proxy
 
 
         protected internal override ObjectInstance GetPrototypeOf()
         protected internal override ObjectInstance GetPrototypeOf()
         {
         {
-            return _engine.Function.Prototype;
+            return _realm.Intrinsics.Function.Prototype;
         }
         }
 
 
         public ProxyInstance Construct(ObjectInstance target, ObjectInstance handler)
         public ProxyInstance Construct(ObjectInstance target, ObjectInstance handler)
         {
         {
             if (target is ProxyInstance targetProxy && targetProxy._handler is null)
             if (target is ProxyInstance targetProxy && targetProxy._handler is null)
             {
             {
-                ExceptionHelper.ThrowTypeError(_engine);
+                ExceptionHelper.ThrowTypeError(_realm);
             }
             }
             if (handler is ProxyInstance handlerProxy && handlerProxy._handler is null)
             if (handler is ProxyInstance handlerProxy && handlerProxy._handler is null)
             {
             {
-                ExceptionHelper.ThrowTypeError(_engine);
+                ExceptionHelper.ThrowTypeError(_realm);
             }
             }
             var instance = new ProxyInstance(Engine, target, handler);
             var instance = new ProxyInstance(Engine, target, handler);
             return instance;
             return instance;
@@ -85,7 +82,7 @@ namespace Jint.Native.Proxy
                 return Undefined;
                 return Undefined;
             };
             };
 
 
-            var result = _engine.Object.Construct(System.Array.Empty<JsValue>());
+            var result = _realm.Intrinsics.Object.Construct(System.Array.Empty<JsValue>());
             result.DefineOwnProperty(PropertyRevoke, new PropertyDescriptor(new ClrFunctionInstance(_engine, name: null, revoke, 0, PropertyFlag.Configurable), PropertyFlag.ConfigurableEnumerableWritable));
             result.DefineOwnProperty(PropertyRevoke, new PropertyDescriptor(new ClrFunctionInstance(_engine, name: null, revoke, 0, PropertyFlag.Configurable), PropertyFlag.ConfigurableEnumerableWritable));
             result.DefineOwnProperty(PropertyProxy, new PropertyDescriptor(p, PropertyFlag.ConfigurableEnumerableWritable));
             result.DefineOwnProperty(PropertyProxy, new PropertyDescriptor(p, PropertyFlag.ConfigurableEnumerableWritable));
             return result;
             return result;

+ 50 - 45
Jint/Native/Proxy/ProxyInstance.cs

@@ -40,15 +40,16 @@ namespace Jint.Native.Proxy
 
 
         public JsValue Call(JsValue thisObject, JsValue[] arguments)
         public JsValue Call(JsValue thisObject, JsValue[] arguments)
         {
         {
-            var jsValues = new[] { _target, thisObject, _engine.Array.ConstructFast(arguments) };
+            var jsValues = new[] { _target, thisObject, _engine.Realm.Intrinsics.Array.ConstructFast(arguments) };
             if (TryCallHandler(TrapApply, jsValues, out var result))
             if (TryCallHandler(TrapApply, jsValues, out var result))
             {
             {
                 return result;
                 return result;
             }
             }
 
 
-            if (!(_target is ICallable callable))
+            var callable = _target as ICallable;
+            if (callable is null)
             {
             {
-                return ExceptionHelper.ThrowTypeError<JsValue>(_engine, _target + " is not a function");
+                ExceptionHelper.ThrowTypeError(_engine.Realm, _target + " is not a function");
             }
             }
 
 
             return callable.Call(thisObject, arguments);
             return callable.Call(thisObject, arguments);
@@ -56,22 +57,24 @@ namespace Jint.Native.Proxy
 
 
         public ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
         public ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
         {
         {
-            var argArray = _engine.Array.Construct(arguments, _engine.Array);
+            var argArray = _engine.Realm.Intrinsics.Array.Construct(arguments, _engine.Realm.Intrinsics.Array);
 
 
             if (!TryCallHandler(TrapConstruct, new[] { _target, argArray, newTarget }, out var result))
             if (!TryCallHandler(TrapConstruct, new[] { _target, argArray, newTarget }, out var result))
             {
             {
-                if (!(_target is IConstructor constructor))
+                var constructor = _target as IConstructor;
+                if (constructor is null)
                 {
                 {
-                    return ExceptionHelper.ThrowTypeError<ObjectInstance>(_engine);
+                    ExceptionHelper.ThrowTypeError(_engine.Realm);
                 }
                 }
                 return constructor.Construct(arguments, newTarget);
                 return constructor.Construct(arguments, newTarget);
             }
             }
 
 
-            if (!(result is ObjectInstance oi))
+            var oi = result as ObjectInstance;
+            if (oi is null)
             {
             {
-                return ExceptionHelper.ThrowTypeError<ObjectInstance>(_engine);
+                ExceptionHelper.ThrowTypeError(_engine.Realm);
             }
             }
-           
+
             return oi;
             return oi;
         }
         }
 
 
@@ -81,10 +84,11 @@ namespace Jint.Native.Proxy
             return _target.IsArray();
             return _target.IsArray();
         }
         }
 
 
-        internal override bool IsConstructor => 
-            _handler is not null
-            && _handler.TryGetValue(TrapConstruct, out var handlerFunction) 
-            && handlerFunction is IConstructor;
+        internal override bool IsConstructor =>
+            _target is not null && _target.IsConstructor
+            || _handler is not null
+                && _handler.TryGetValue(TrapConstruct, out var handlerFunction)
+                && handlerFunction is IConstructor;
 
 
         public override JsValue Get(JsValue property, JsValue receiver)
         public override JsValue Get(JsValue property, JsValue receiver)
         {
         {
@@ -100,11 +104,11 @@ namespace Jint.Native.Proxy
             {
             {
                 if (targetDesc.IsDataDescriptor() && !targetDesc.Configurable && !targetDesc.Writable && !ReferenceEquals(result, targetDesc._value))
                 if (targetDesc.IsDataDescriptor() && !targetDesc.Configurable && !targetDesc.Writable && !ReferenceEquals(result, targetDesc._value))
                 {
                 {
-                   ExceptionHelper.ThrowTypeError(_engine);
+                   ExceptionHelper.ThrowTypeError(_engine.Realm);
                 }
                 }
                 if (targetDesc.IsAccessorDescriptor() && !targetDesc.Configurable && targetDesc.Get.IsUndefined() && !result.IsUndefined())
                 if (targetDesc.IsAccessorDescriptor() && !targetDesc.Configurable && targetDesc.Get.IsUndefined() && !result.IsUndefined())
                 {
                 {
-                   ExceptionHelper.ThrowTypeError(_engine, $"'get' on proxy: property '{property}' is a non-configurable accessor property on the proxy target and does not have a getter function, but the trap did not return 'undefined' (got '{result}')");
+                   ExceptionHelper.ThrowTypeError(_engine.Realm, $"'get' on proxy: property '{property}' is a non-configurable accessor property on the proxy target and does not have a getter function, but the trap did not return 'undefined' (got '{result}')");
                 }
                 }
             }
             }
 
 
@@ -118,11 +122,11 @@ namespace Jint.Native.Proxy
                 return _target.GetOwnPropertyKeys(types);
                 return _target.GetOwnPropertyKeys(types);
             }
             }
 
 
-            var trapResult = new List<JsValue>(_engine.Function.PrototypeObject.CreateListFromArrayLike(result, Types.String | Types.Symbol));
+            var trapResult = new List<JsValue>(_engine.Realm.Intrinsics.Function.PrototypeObject.CreateListFromArrayLike(result, Types.String | Types.Symbol));
 
 
             if (trapResult.Count != new HashSet<JsValue>(trapResult).Count)
             if (trapResult.Count != new HashSet<JsValue>(trapResult).Count)
             {
             {
-                ExceptionHelper.ThrowTypeError(_engine);
+                ExceptionHelper.ThrowTypeError(_engine.Realm);
             }
             }
 
 
             var extensibleTarget = _target.Extensible;
             var extensibleTarget = _target.Extensible;
@@ -141,7 +145,7 @@ namespace Jint.Native.Proxy
                 {
                 {
                     targetConfigurableKeys.Add(property);
                     targetConfigurableKeys.Add(property);
                 }
                 }
-                
+
             }
             }
 
 
             var uncheckedResultKeys = new HashSet<JsValue>(trapResult);
             var uncheckedResultKeys = new HashSet<JsValue>(trapResult);
@@ -150,7 +154,7 @@ namespace Jint.Native.Proxy
                 var key = targetNonconfigurableKeys[i];
                 var key = targetNonconfigurableKeys[i];
                 if (!uncheckedResultKeys.Remove(key))
                 if (!uncheckedResultKeys.Remove(key))
                 {
                 {
-                    ExceptionHelper.ThrowTypeError(_engine);
+                    ExceptionHelper.ThrowTypeError(_engine.Realm);
                 }
                 }
             }
             }
 
 
@@ -164,13 +168,13 @@ namespace Jint.Native.Proxy
                 var key = targetConfigurableKeys[i];
                 var key = targetConfigurableKeys[i];
                 if (!uncheckedResultKeys.Remove(key))
                 if (!uncheckedResultKeys.Remove(key))
                 {
                 {
-                    ExceptionHelper.ThrowTypeError(_engine);
+                    ExceptionHelper.ThrowTypeError(_engine.Realm);
                 }
                 }
             }
             }
 
 
             if (uncheckedResultKeys.Count > 0)
             if (uncheckedResultKeys.Count > 0)
             {
             {
-                ExceptionHelper.ThrowTypeError(_engine);
+                ExceptionHelper.ThrowTypeError(_engine.Realm);
             }
             }
 
 
             return trapResult;
             return trapResult;
@@ -185,7 +189,7 @@ namespace Jint.Native.Proxy
 
 
             if (!result.IsObject() && !result.IsUndefined())
             if (!result.IsObject() && !result.IsUndefined())
             {
             {
-                ExceptionHelper.ThrowTypeError(_engine);
+                ExceptionHelper.ThrowTypeError(_engine.Realm);
             }
             }
 
 
             var targetDesc = _target.GetOwnProperty(property);
             var targetDesc = _target.GetOwnProperty(property);
@@ -199,24 +203,24 @@ namespace Jint.Native.Proxy
 
 
                 if (!targetDesc.Configurable || !_target.Extensible)
                 if (!targetDesc.Configurable || !_target.Extensible)
                 {
                 {
-                    ExceptionHelper.ThrowTypeError(_engine);
+                    ExceptionHelper.ThrowTypeError(_engine.Realm);
                 }
                 }
 
 
                 return PropertyDescriptor.Undefined;
                 return PropertyDescriptor.Undefined;
             }
             }
 
 
             var extensibleTarget = _target.Extensible;
             var extensibleTarget = _target.Extensible;
-            var resultDesc = PropertyDescriptor.ToPropertyDescriptor(_engine, result);
+            var resultDesc = PropertyDescriptor.ToPropertyDescriptor(_engine.Realm, result);
 
 
             var valid = IsCompatiblePropertyDescriptor(extensibleTarget, resultDesc, targetDesc);
             var valid = IsCompatiblePropertyDescriptor(extensibleTarget, resultDesc, targetDesc);
             if (!valid)
             if (!valid)
             {
             {
-                ExceptionHelper.ThrowTypeError(_engine);
+                ExceptionHelper.ThrowTypeError(_engine.Realm);
             }
             }
 
 
             if (!resultDesc.Configurable && (targetDesc == PropertyDescriptor.Undefined || targetDesc.Configurable))
             if (!resultDesc.Configurable && (targetDesc == PropertyDescriptor.Undefined || targetDesc.Configurable))
             {
             {
-                ExceptionHelper.ThrowTypeError(_engine);
+                ExceptionHelper.ThrowTypeError(_engine.Realm);
             }
             }
 
 
             return resultDesc;
             return resultDesc;
@@ -242,7 +246,7 @@ namespace Jint.Native.Proxy
                 {
                 {
                     if (targetDesc.Value != value)
                     if (targetDesc.Value != value)
                     {
                     {
-                        ExceptionHelper.ThrowTypeError(_engine);
+                        ExceptionHelper.ThrowTypeError(_engine.Realm);
                     }
                     }
                 }
                 }
 
 
@@ -250,11 +254,11 @@ namespace Jint.Native.Proxy
                 {
                 {
                     if (targetDesc.Set.IsUndefined())
                     if (targetDesc.Set.IsUndefined())
                     {
                     {
-                        ExceptionHelper.ThrowTypeError(_engine);
+                        ExceptionHelper.ThrowTypeError(_engine.Realm);
                     }
                     }
                 }
                 }
             }
             }
-            
+
             return true;
             return true;
         }
         }
 
 
@@ -280,18 +284,18 @@ namespace Jint.Native.Proxy
             {
             {
                 if (!extensibleTarget || settingConfigFalse)
                 if (!extensibleTarget || settingConfigFalse)
                 {
                 {
-                    ExceptionHelper.ThrowTypeError(_engine);
+                    ExceptionHelper.ThrowTypeError(_engine.Realm);
                 }
                 }
             }
             }
             else
             else
             {
             {
                 if (!IsCompatiblePropertyDescriptor(extensibleTarget, desc, targetDesc))
                 if (!IsCompatiblePropertyDescriptor(extensibleTarget, desc, targetDesc))
                 {
                 {
-                    ExceptionHelper.ThrowTypeError(_engine);
+                    ExceptionHelper.ThrowTypeError(_engine.Realm);
                 }
                 }
                 if (targetDesc.Configurable && settingConfigFalse)
                 if (targetDesc.Configurable && settingConfigFalse)
                 {
                 {
-                    ExceptionHelper.ThrowTypeError(_engine);
+                    ExceptionHelper.ThrowTypeError(_engine.Realm);
                 }
                 }
             }
             }
 
 
@@ -319,12 +323,12 @@ namespace Jint.Native.Proxy
                 {
                 {
                     if (!targetDesc.Configurable)
                     if (!targetDesc.Configurable)
                     {
                     {
-                        ExceptionHelper.ThrowTypeError(_engine);
+                        ExceptionHelper.ThrowTypeError(_engine.Realm);
                     }
                     }
 
 
                     if (!_target.Extensible)
                     if (!_target.Extensible)
                     {
                     {
-                        ExceptionHelper.ThrowTypeError(_engine);
+                        ExceptionHelper.ThrowTypeError(_engine.Realm);
                     }
                     }
                 }
                 }
             }
             }
@@ -346,7 +350,7 @@ namespace Jint.Native.Proxy
                 var targetDesc = _target.GetOwnProperty(property);
                 var targetDesc = _target.GetOwnProperty(property);
                 if (targetDesc != PropertyDescriptor.Undefined && !targetDesc.Configurable)
                 if (targetDesc != PropertyDescriptor.Undefined && !targetDesc.Configurable)
                 {
                 {
-                    ExceptionHelper.ThrowTypeError(_engine, $"'deleteProperty' on proxy: trap returned truish for property '{property}' which is non-configurable in the proxy target");
+                    ExceptionHelper.ThrowTypeError(_engine.Realm, $"'deleteProperty' on proxy: trap returned truish for property '{property}' which is non-configurable in the proxy target");
                 }
                 }
             }
             }
 
 
@@ -364,7 +368,7 @@ namespace Jint.Native.Proxy
 
 
             if (success && _target.Extensible)
             if (success && _target.Extensible)
             {
             {
-                ExceptionHelper.ThrowTypeError(_engine);
+                ExceptionHelper.ThrowTypeError(_engine.Realm);
             }
             }
 
 
             return success ? JsBoolean.True : JsBoolean.False;
             return success ? JsBoolean.True : JsBoolean.False;
@@ -383,7 +387,7 @@ namespace Jint.Native.Proxy
                 var targetResult = _target.Extensible;
                 var targetResult = _target.Extensible;
                 if (booleanTrapResult != targetResult)
                 if (booleanTrapResult != targetResult)
                 {
                 {
-                    ExceptionHelper.ThrowTypeError(_engine);
+                    ExceptionHelper.ThrowTypeError(_engine.Realm);
                 }
                 }
                 return booleanTrapResult;
                 return booleanTrapResult;
             }
             }
@@ -398,7 +402,7 @@ namespace Jint.Native.Proxy
 
 
             if (!handlerProto.IsObject() && !handlerProto.IsNull())
             if (!handlerProto.IsObject() && !handlerProto.IsNull())
             {
             {
-                ExceptionHelper.ThrowTypeError(_engine, "'getPrototypeOf' on proxy: trap returned neither object nor null");
+                ExceptionHelper.ThrowTypeError(_engine.Realm, "'getPrototypeOf' on proxy: trap returned neither object nor null");
             }
             }
 
 
             if (_target.Extensible)
             if (_target.Extensible)
@@ -408,7 +412,7 @@ namespace Jint.Native.Proxy
 
 
             if (!ReferenceEquals(handlerProto, _target.Prototype))
             if (!ReferenceEquals(handlerProto, _target.Prototype))
             {
             {
-                ExceptionHelper.ThrowTypeError(_engine);
+                ExceptionHelper.ThrowTypeError(_engine.Realm);
             }
             }
 
 
             return (ObjectInstance) handlerProto;
             return (ObjectInstance) handlerProto;
@@ -435,7 +439,7 @@ namespace Jint.Native.Proxy
 
 
             if (!ReferenceEquals(value, _target.Prototype))
             if (!ReferenceEquals(value, _target.Prototype))
             {
             {
-                ExceptionHelper.ThrowTypeError(_engine);
+                ExceptionHelper.ThrowTypeError(_engine.Realm);
             }
             }
 
 
             return true;
             return true;
@@ -451,9 +455,10 @@ namespace Jint.Native.Proxy
             var handlerFunction = _handler.Get(propertyName);
             var handlerFunction = _handler.Get(propertyName);
             if (!handlerFunction.IsNullOrUndefined())
             if (!handlerFunction.IsNullOrUndefined())
             {
             {
-                if (!(handlerFunction is ICallable callable))
+                var callable = handlerFunction as ICallable;
+                if (callable is null)
                 {
                 {
-                    return ExceptionHelper.ThrowTypeError<bool>(_engine, $"{_handler} returned for property '{propertyName}' of object '{_target}' is not a function");
+                    ExceptionHelper.ThrowTypeError(_engine.Realm, $"{_handler} returned for property '{propertyName}' of object '{_target}' is not a function");
                 }
                 }
 
 
                 result = callable.Call(_handler, arguments);
                 result = callable.Call(_handler, arguments);
@@ -467,7 +472,7 @@ namespace Jint.Native.Proxy
         {
         {
             if (_handler is null)
             if (_handler is null)
             {
             {
-                ExceptionHelper.ThrowTypeError(_engine, $"Cannot perform '{key}' on a proxy that has been revoked");
+                ExceptionHelper.ThrowTypeError(_engine.Realm, $"Cannot perform '{key}' on a proxy that has been revoked");
             }
             }
         }
         }
 
 
@@ -475,10 +480,10 @@ namespace Jint.Native.Proxy
         {
         {
             if (_target is null)
             if (_target is null)
             {
             {
-                ExceptionHelper.ThrowTypeError(_engine, $"Cannot perform '{key}' on a proxy that has been revoked");
+                ExceptionHelper.ThrowTypeError(_engine.Realm, $"Cannot perform '{key}' on a proxy that has been revoked");
             }
             }
         }
         }
-        
+
         public override string ToString() => "function () { [native code] }";
         public override string ToString() => "function () { [native code] }";
     }
     }
 }
 }

+ 43 - 42
Jint/Native/Reflect/ReflectInstance.cs

@@ -11,18 +11,15 @@ namespace Jint.Native.Reflect
     /// </summary>
     /// </summary>
     public sealed class ReflectInstance : ObjectInstance
     public sealed class ReflectInstance : ObjectInstance
     {
     {
-        private ReflectInstance(Engine engine) : base(engine, ObjectClass.Reflect)
-        {
-        }
+        private readonly Realm _realm;
 
 
-        public static ReflectInstance CreateReflectObject(Engine engine)
+        internal ReflectInstance(
+            Engine engine,
+            Realm realm,
+            ObjectPrototype objectPrototype) : base(engine, ObjectClass.Reflect)
         {
         {
-            var math = new ReflectInstance(engine)
-            {
-                _prototype = engine.Object.PrototypeObject
-            };
-
-            return math;
+            _realm = realm;
+            _prototype = objectPrototype;
         }
         }
 
 
         protected override void Initialize()
         protected override void Initialize()
@@ -48,7 +45,7 @@ namespace Jint.Native.Reflect
 
 
         private JsValue Apply(JsValue thisObject, JsValue[] arguments)
         private JsValue Apply(JsValue thisObject, JsValue[] arguments)
         {
         {
-            return _engine.Function.PrototypeObject.Apply(arguments.At(0), new[]
+            return _realm.Intrinsics.Function.PrototypeObject.Apply(arguments.At(0), new[]
             {
             {
                 arguments.At(1),
                 arguments.At(1),
                 arguments.At(2)
                 arguments.At(2)
@@ -63,33 +60,34 @@ namespace Jint.Native.Reflect
             var newTargetArgument = arguments.At(2, arguments[0]);
             var newTargetArgument = arguments.At(2, arguments[0]);
             AssertConstructor(_engine, newTargetArgument);
             AssertConstructor(_engine, newTargetArgument);
 
 
-            var args = _engine.Function.PrototypeObject.CreateListFromArrayLike(arguments.At(1));
+            var args = _realm.Intrinsics.Function.PrototypeObject.CreateListFromArrayLike(arguments.At(1));
 
 
             return target.Construct(args, newTargetArgument);
             return target.Construct(args, newTargetArgument);
         }
         }
 
 
         private JsValue DefineProperty(JsValue thisObject, JsValue[] arguments)
         private JsValue DefineProperty(JsValue thisObject, JsValue[] arguments)
         {
         {
-            if (!(arguments.At(0) is ObjectInstance o))
+            var o = arguments.At(0) as ObjectInstance;
+            if (o is null)
             {
             {
-                return ExceptionHelper.ThrowTypeError<JsValue>(_engine, "Reflect.defineProperty called on non-object");
+                ExceptionHelper.ThrowTypeError(_realm, "Reflect.defineProperty called on non-object");
             }
             }
 
 
             var p = arguments.At(1);
             var p = arguments.At(1);
             var name = TypeConverter.ToPropertyKey(p);
             var name = TypeConverter.ToPropertyKey(p);
 
 
             var attributes = arguments.At(2);
             var attributes = arguments.At(2);
-            var desc = PropertyDescriptor.ToPropertyDescriptor(Engine, attributes);
+            var desc = PropertyDescriptor.ToPropertyDescriptor(_realm, attributes);
 
 
             return o.DefineOwnProperty(name, desc);
             return o.DefineOwnProperty(name, desc);
         }
         }
 
 
         private JsValue DeleteProperty(JsValue thisObject, JsValue[] arguments)
         private JsValue DeleteProperty(JsValue thisObject, JsValue[] arguments)
         {
         {
-            var target = arguments.At(0);
-            if (!(target is ObjectInstance o))
+            var o = arguments.At(0) as ObjectInstance;
+            if (o is null)
             {
             {
-                return ExceptionHelper.ThrowTypeError<JsValue>(_engine, "Reflect.deleteProperty called on non-object");
+                ExceptionHelper.ThrowTypeError(_realm, "Reflect.deleteProperty called on non-object");
             }
             }
 
 
             var property = TypeConverter.ToPropertyKey(arguments.At(1));
             var property = TypeConverter.ToPropertyKey(arguments.At(1));
@@ -98,10 +96,10 @@ namespace Jint.Native.Reflect
 
 
         private JsValue Has(JsValue thisObject, JsValue[] arguments)
         private JsValue Has(JsValue thisObject, JsValue[] arguments)
         {
         {
-            var target = arguments.At(0);
-            if (!(target is ObjectInstance o))
+            var o = arguments.At(0) as ObjectInstance;
+            if (o is null)
             {
             {
-                return ExceptionHelper.ThrowTypeError<JsValue>(_engine, "Reflect.has called on non-object");
+                ExceptionHelper.ThrowTypeError(_realm, "Reflect.has called on non-object");
             }
             }
 
 
             var property = TypeConverter.ToPropertyKey(arguments.At(1));
             var property = TypeConverter.ToPropertyKey(arguments.At(1));
@@ -115,9 +113,10 @@ namespace Jint.Native.Reflect
             var value = arguments.At(2);
             var value = arguments.At(2);
             var receiver = arguments.At(3, target);
             var receiver = arguments.At(3, target);
 
 
-            if (!(target is ObjectInstance o))
+            var o = target as ObjectInstance;
+            if (o is null)
             {
             {
-                return ExceptionHelper.ThrowTypeError<JsValue>(_engine, "Reflect.set called on non-object");
+                ExceptionHelper.ThrowTypeError(_realm, "Reflect.set called on non-object");
             }
             }
 
 
             return o.Set(property, value, receiver);
             return o.Set(property, value, receiver);
@@ -126,9 +125,10 @@ namespace Jint.Native.Reflect
         private JsValue Get(JsValue thisObject, JsValue[] arguments)
         private JsValue Get(JsValue thisObject, JsValue[] arguments)
         {
         {
             var target = arguments.At(0);
             var target = arguments.At(0);
-            if (!(target is ObjectInstance o))
+            var o = target as ObjectInstance;
+            if (o is null)
             {
             {
-                return ExceptionHelper.ThrowTypeError<JsValue>(_engine, "Reflect.get called on non-object");
+                ExceptionHelper.ThrowTypeError(_realm, "Reflect.get called on non-object");
             }
             }
 
 
             var receiver = arguments.At(2, target);
             var receiver = arguments.At(2, target);
@@ -140,29 +140,29 @@ namespace Jint.Native.Reflect
         {
         {
             if (!arguments.At(0).IsObject())
             if (!arguments.At(0).IsObject())
             {
             {
-                ExceptionHelper.ThrowTypeError(_engine, "Reflect.getOwnPropertyDescriptor called on non-object");
+                ExceptionHelper.ThrowTypeError(_realm, "Reflect.getOwnPropertyDescriptor called on non-object");
             }
             }
-            return _engine.Object.GetOwnPropertyDescriptor(Undefined, arguments);
+            return _realm.Intrinsics.Object.GetOwnPropertyDescriptor(Undefined, arguments);
         }
         }
 
 
         private JsValue OwnKeys(JsValue thisObject, JsValue[] arguments)
         private JsValue OwnKeys(JsValue thisObject, JsValue[] arguments)
         {
         {
-            var target = arguments.At(0);
-            if (!(target is ObjectInstance o))
+            var o = arguments.At(0) as ObjectInstance;
+            if (o is null)
             {
             {
-                return ExceptionHelper.ThrowTypeError<JsValue>(_engine, "Reflect.get called on non-object");
+                ExceptionHelper.ThrowTypeError(_realm, "Reflect.get called on non-object");
             }
             }
 
 
             var keys = o.GetOwnPropertyKeys();
             var keys = o.GetOwnPropertyKeys();
-            return _engine.Array.CreateArrayFromList(keys);
+            return _realm.Intrinsics.Array.CreateArrayFromList(keys);
         }
         }
 
 
         private JsValue IsExtensible(JsValue thisObject, JsValue[] arguments)
         private JsValue IsExtensible(JsValue thisObject, JsValue[] arguments)
         {
         {
-            var target = arguments.At(0);
-            if (!(target is ObjectInstance o))
+            var o = arguments.At(0) as ObjectInstance;
+            if (o is null)
             {
             {
-                return ExceptionHelper.ThrowTypeError<JsValue>(_engine, "Reflect.isExtensible called on non-object");
+                ExceptionHelper.ThrowTypeError(_realm, "Reflect.isExtensible called on non-object");
             }
             }
 
 
             return o.Extensible;
             return o.Extensible;
@@ -170,10 +170,10 @@ namespace Jint.Native.Reflect
 
 
         private JsValue PreventExtensions(JsValue thisObject, JsValue[] arguments)
         private JsValue PreventExtensions(JsValue thisObject, JsValue[] arguments)
         {
         {
-            var target = arguments.At(0);
-            if (!(target is ObjectInstance o))
+            var o = arguments.At(0) as ObjectInstance;
+            if (o is null)
             {
             {
-                return ExceptionHelper.ThrowTypeError<JsValue>(_engine, "Reflect.preventExtensions called on non-object");
+                ExceptionHelper.ThrowTypeError(_realm, "Reflect.preventExtensions called on non-object");
             }
             }
 
 
             return o.PreventExtensions();
             return o.PreventExtensions();
@@ -185,25 +185,26 @@ namespace Jint.Native.Reflect
 
 
             if (!target.IsObject())
             if (!target.IsObject())
             {
             {
-                return ExceptionHelper.ThrowTypeError<JsValue>(_engine, "Reflect.getPrototypeOf called on non-object");
+                ExceptionHelper.ThrowTypeError(_realm, "Reflect.getPrototypeOf called on non-object");
             }
             }
 
 
-            return _engine.Object.GetPrototypeOf(Undefined, arguments);
+            return _realm.Intrinsics.Object.GetPrototypeOf(Undefined, arguments);
         }
         }
 
 
         private JsValue SetPrototypeOf(JsValue thisObject, JsValue[] arguments)
         private JsValue SetPrototypeOf(JsValue thisObject, JsValue[] arguments)
         {
         {
             var target = arguments.At(0);
             var target = arguments.At(0);
 
 
-            if (!(target is ObjectInstance o))
+            var o = target as ObjectInstance;
+            if (o is null)
             {
             {
-                return ExceptionHelper.ThrowTypeError<JsValue>(_engine, "Reflect.setPrototypeOf called on non-object");
+                ExceptionHelper.ThrowTypeError(_realm, "Reflect.setPrototypeOf called on non-object");
             }
             }
 
 
             var prototype = arguments.At(1);
             var prototype = arguments.At(1);
             if (!prototype.IsObject() && !prototype.IsNull())
             if (!prototype.IsObject() && !prototype.IsNull())
             {
             {
-                ExceptionHelper.ThrowTypeError(_engine, $"Object prototype may only be an Object or null: {prototype}");
+                ExceptionHelper.ThrowTypeError(_realm, $"Object prototype may only be an Object or null: {prototype}");
             }
             }
 
 
             return o.SetPrototypeOf(prototype);
             return o.SetPrototypeOf(prototype);

+ 19 - 26
Jint/Native/RegExp/RegExpConstructor.cs

@@ -15,27 +15,17 @@ namespace Jint.Native.RegExp
     {
     {
         private static readonly JsString _functionName = new JsString("RegExp");
         private static readonly JsString _functionName = new JsString("RegExp");
 
 
-        public RegExpConstructor(Engine engine)
-            : base(engine, _functionName, FunctionThisMode.Global)
+        internal RegExpConstructor(
+            Engine engine,
+            Realm realm,
+            FunctionPrototype functionPrototype,
+            ObjectPrototype objectPrototype)
+            : base(engine, realm, _functionName, FunctionThisMode.Global)
         {
         {
-        }
-
-        public static RegExpConstructor CreateRegExpConstructor(Engine engine)
-        {
-            var obj = new RegExpConstructor(engine)
-            {
-                _prototype = engine.Function.PrototypeObject
-            };
-
-            // The value of the [[Prototype]] internal property of the RegExp constructor is the Function prototype object
-            obj.PrototypeObject = RegExpPrototype.CreatePrototypeObject(engine, obj);
-
-            obj._length = new PropertyDescriptor(2, PropertyFlag.AllForbidden);
-
-            // The initial value of RegExp.prototype is the RegExp prototype object
-            obj._prototypeDescriptor= new PropertyDescriptor(obj.PrototypeObject, PropertyFlag.AllForbidden);
-
-            return obj;
+            _prototype = functionPrototype;
+            PrototypeObject = new RegExpPrototype(engine, realm, this, objectPrototype);
+            _length = new PropertyDescriptor(2, PropertyFlag.AllForbidden);
+            _prototypeDescriptor= new PropertyDescriptor(PrototypeObject, PropertyFlag.AllForbidden);
         }
         }
 
 
         protected override void Initialize()
         protected override void Initialize()
@@ -114,7 +104,7 @@ namespace Jint.Native.RegExp
             try
             try
             {
             {
                 var scanner = new Scanner("/" + p + "/" + flags , new ParserOptions { AdaptRegexp = true });
                 var scanner = new Scanner("/" + p + "/" + flags , new ParserOptions { AdaptRegexp = true });
-               
+
                 // seems valid
                 // seems valid
                 r.Value = scanner.TestRegExp(p, f);
                 r.Value = scanner.TestRegExp(p, f);
 
 
@@ -126,12 +116,12 @@ namespace Jint.Native.RegExp
             }
             }
             catch (Exception ex)
             catch (Exception ex)
             {
             {
-                ExceptionHelper.ThrowSyntaxError(_engine, ex.Message);
+                ExceptionHelper.ThrowSyntaxError(_realm, ex.Message);
             }
             }
 
 
             r.Flags = f;
             r.Flags = f;
             r.Source = p;
             r.Source = p;
-            
+
             RegExpInitialize(r);
             RegExpInitialize(r);
 
 
             return r;
             return r;
@@ -139,7 +129,10 @@ namespace Jint.Native.RegExp
 
 
         private RegExpInstance RegExpAlloc(JsValue newTarget)
         private RegExpInstance RegExpAlloc(JsValue newTarget)
         {
         {
-            var r = OrdinaryCreateFromConstructor(newTarget, PrototypeObject, static(engine, value) => new RegExpInstance(engine));
+            var r = OrdinaryCreateFromConstructor(
+                newTarget,
+                static intrinsics => intrinsics.RegExp.PrototypeObject,
+                static(engine, realm, _) => new RegExpInstance(engine));
             return r;
             return r;
         }
         }
 
 
@@ -165,12 +158,12 @@ namespace Jint.Native.RegExp
 
 
             return r;
             return r;
         }
         }
-        
+
         private static void RegExpInitialize(RegExpInstance r)
         private static void RegExpInitialize(RegExpInstance r)
         {
         {
             r.SetOwnProperty(RegExpInstance.PropertyLastIndex, new PropertyDescriptor(0, PropertyFlag.OnlyWritable));
             r.SetOwnProperty(RegExpInstance.PropertyLastIndex, new PropertyDescriptor(0, PropertyFlag.OnlyWritable));
         }
         }
-        
+
         public RegExpPrototype PrototypeObject { get; private set; }
         public RegExpPrototype PrototypeObject { get; private set; }
     }
     }
 }
 }

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

@@ -15,7 +15,7 @@ using Jint.Runtime.Interop;
 
 
 namespace Jint.Native.RegExp
 namespace Jint.Native.RegExp
 {
 {
-    public sealed class RegExpPrototype : ObjectInstance
+    public sealed class RegExpPrototype : Prototype
     {
     {
         private static readonly JsString PropertyExec = new JsString("exec");
         private static readonly JsString PropertyExec = new JsString("exec");
         private static readonly JsString PropertyIndex = new JsString("index");
         private static readonly JsString PropertyIndex = new JsString("index");
@@ -26,22 +26,18 @@ namespace Jint.Native.RegExp
         private static readonly JsValue DefaultSource = new JsString("(?:)");
         private static readonly JsValue DefaultSource = new JsString("(?:)");
         internal static readonly JsString PropertyFlags = new JsString("flags");
         internal static readonly JsString PropertyFlags = new JsString("flags");
 
 
-        private RegExpConstructor _regExpConstructor;
+        private readonly RegExpConstructor _constructor;
         private readonly Func<JsValue, JsValue[], JsValue> _defaultExec;
         private readonly Func<JsValue, JsValue[], JsValue> _defaultExec;
 
 
-        private RegExpPrototype(Engine engine) : base(engine)
+        internal RegExpPrototype(
+            Engine engine,
+            Realm realm,
+            RegExpConstructor constructor,
+            ObjectPrototype objectPrototype) : base(engine, realm)
         {
         {
             _defaultExec = Exec;
             _defaultExec = Exec;
-        }
-
-        public static RegExpPrototype CreatePrototypeObject(Engine engine, RegExpConstructor regExpConstructor)
-        {
-            var obj = new RegExpPrototype(engine)
-            {
-                _prototype = engine.Object.PrototypeObject, _regExpConstructor = regExpConstructor
-            };
-
-            return obj;
+            _constructor = constructor;
+            _prototype = objectPrototype;
         }
         }
 
 
         protected override void Initialize()
         protected override void Initialize()
@@ -58,9 +54,10 @@ namespace Jint.Native.RegExp
                             return protoValue ?? Undefined;
                             return protoValue ?? Undefined;
                         }
                         }
 
 
-                        if (!(thisObj is RegExpInstance r))
+                        var r = thisObj as RegExpInstance;
+                        if (r is null)
                         {
                         {
-                            return ExceptionHelper.ThrowTypeError<JsValue>(_engine);
+                            ExceptionHelper.ThrowTypeError(_realm);
                         }
                         }
 
 
                         return valueExtractor(r);
                         return valueExtractor(r);
@@ -72,7 +69,7 @@ namespace Jint.Native.RegExp
             const PropertyFlag propertyFlags = PropertyFlag.Configurable | PropertyFlag.Writable;
             const PropertyFlag propertyFlags = PropertyFlag.Configurable | PropertyFlag.Writable;
             var properties = new PropertyDictionary(12, checkExistingKeys: false)
             var properties = new PropertyDictionary(12, checkExistingKeys: false)
             {
             {
-                ["constructor"] = new PropertyDescriptor(_regExpConstructor, propertyFlags),
+                ["constructor"] = new PropertyDescriptor(_constructor, propertyFlags),
                 ["toString"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "toString", ToRegExpString, 0, lengthFlags), propertyFlags),
                 ["toString"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "toString", ToRegExpString, 0, lengthFlags), propertyFlags),
                 ["exec"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "exec", _defaultExec, 1, lengthFlags), propertyFlags),
                 ["exec"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "exec", _defaultExec, 1, lengthFlags), propertyFlags),
                 ["test"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "test", Test, 1, lengthFlags), propertyFlags),
                 ["test"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "test", Test, 1, lengthFlags), propertyFlags),
@@ -105,9 +102,10 @@ namespace Jint.Native.RegExp
                 return DefaultSource;
                 return DefaultSource;
             }
             }
 
 
-            if (!(thisObj is RegExpInstance r))
+            var r = thisObj as RegExpInstance;
+            if (r is null)
             {
             {
-                return ExceptionHelper.ThrowTypeError<JsValue>(_engine);
+                ExceptionHelper.ThrowTypeError(_realm);
             }
             }
 
 
             return r.Source.Replace("/", "\\/");
             return r.Source.Replace("/", "\\/");
@@ -253,7 +251,7 @@ namespace Jint.Native.RegExp
                 {
                 {
                     if (!namedCaptures.IsUndefined())
                     if (!namedCaptures.IsUndefined())
                     {
                     {
-                        namedCaptures = TypeConverter.ToObject(_engine, namedCaptures);
+                        namedCaptures = TypeConverter.ToObject(_realm, namedCaptures);
                     }
                     }
 
 
                     replacement = GetSubstitution(matched, s, position, captures.ToArray(), namedCaptures, TypeConverter.ToString(replaceValue));
                     replacement = GetSubstitution(matched, s, position, captures.ToArray(), namedCaptures, TypeConverter.ToString(replaceValue));
@@ -386,7 +384,7 @@ namespace Jint.Native.RegExp
             var rx = AssertThisIsObjectInstance(thisObj, "RegExp.prototype.split");
             var rx = AssertThisIsObjectInstance(thisObj, "RegExp.prototype.split");
             var s = TypeConverter.ToString(arguments.At(0));
             var s = TypeConverter.ToString(arguments.At(0));
             var limit = arguments.At(1);
             var limit = arguments.At(1);
-            var c = SpeciesConstructor(rx, _engine.RegExp);
+            var c = SpeciesConstructor(rx, _realm.Intrinsics.RegExp);
             var flags = TypeConverter.ToJsString(rx.Get(PropertyFlags));
             var flags = TypeConverter.ToJsString(rx.Get(PropertyFlags));
             var unicodeMatching = flags.IndexOf('u') > -1;
             var unicodeMatching = flags.IndexOf('u') > -1;
             var newFlags = flags.IndexOf('y') > -1 ? flags : new JsString(flags.ToString() + 'y');
             var newFlags = flags.IndexOf('y') > -1 ? flags : new JsString(flags.ToString() + 'y');
@@ -400,12 +398,12 @@ namespace Jint.Native.RegExp
 
 
             if (lim == 0)
             if (lim == 0)
             {
             {
-                return _engine.Array.ConstructFast(0);
+                return _realm.Intrinsics.Array.ConstructFast(0);
             }
             }
 
 
             if (s.Length == 0)
             if (s.Length == 0)
             {
             {
-                var a = _engine.Array.ConstructFast(0);
+                var a = _realm.Intrinsics.Array.ConstructFast(0);
                 var z = RegExpExec(splitter, s);
                 var z = RegExpExec(splitter, s);
                 if (!z.IsNull())
                 if (!z.IsNull())
                 {
                 {
@@ -423,10 +421,10 @@ namespace Jint.Native.RegExp
                 if (R.Source == RegExpInstance.regExpForMatchingAllCharacters)
                 if (R.Source == RegExpInstance.regExpForMatchingAllCharacters)
                 {
                 {
                     // if empty string, just a string split
                     // if empty string, just a string split
-                    return StringPrototype.SplitWithStringSeparator(_engine, "", s, (uint) s.Length);                    
+                    return StringPrototype.SplitWithStringSeparator(_realm, "", s, (uint) s.Length);
                 }
                 }
-                
-                var a = (ArrayInstance) Engine.Array.Construct(Arguments.Empty);
+
+                var a = (ArrayInstance) _realm.Intrinsics.Array.Construct(Arguments.Empty);
                 var match = R.Value.Match(s, 0);
                 var match = R.Value.Match(s, 0);
 
 
                 if (!match.Success) // No match at all return the string in an array
                 if (!match.Success) // No match at all return the string in an array
@@ -486,7 +484,7 @@ namespace Jint.Native.RegExp
 
 
         private JsValue SplitSlow(string s, ObjectInstance splitter, bool unicodeMatching, uint lengthA, long lim)
         private JsValue SplitSlow(string s, ObjectInstance splitter, bool unicodeMatching, uint lengthA, long lim)
         {
         {
-            var a = _engine.Array.ConstructFast(0);
+            var a = _realm.Intrinsics.Array.ConstructFast(0);
             var previousStringIndex = 0;
             var previousStringIndex = 0;
             var currentIndex = 0;
             var currentIndex = 0;
             while (currentIndex < s.Length)
             while (currentIndex < s.Length)
@@ -577,7 +575,7 @@ namespace Jint.Native.RegExp
             {
             {
                 if (!R.Sticky && !R.Global)
                 if (!R.Sticky && !R.Global)
                 {
                 {
-                    R.Set(RegExpInstance.PropertyLastIndex, 0, throwOnError: true); 
+                    R.Set(RegExpInstance.PropertyLastIndex, 0, throwOnError: true);
                     return R.Value.IsMatch(s);
                     return R.Value.IsMatch(s);
                 }
                 }
 
 
@@ -590,13 +588,13 @@ namespace Jint.Native.RegExp
                 var m = R.Value.Match(s, lastIndex);
                 var m = R.Value.Match(s, lastIndex);
                 if (!m.Success || (R.Sticky && m.Index != lastIndex))
                 if (!m.Success || (R.Sticky && m.Index != lastIndex))
                 {
                 {
-                    R.Set(RegExpInstance.PropertyLastIndex, 0, throwOnError: true); 
+                    R.Set(RegExpInstance.PropertyLastIndex, 0, throwOnError: true);
                     return JsBoolean.False;
                     return JsBoolean.False;
                 }
                 }
                 R.Set(RegExpInstance.PropertyLastIndex, m.Index + m.Length, throwOnError: true);
                 R.Set(RegExpInstance.PropertyLastIndex, m.Index + m.Length, throwOnError: true);
                 return JsBoolean.True;
                 return JsBoolean.True;
             }
             }
-            
+
             var match = RegExpExec(r, s);
             var match = RegExpExec(r, s);
             return !match.IsNull();
             return !match.IsNull();
         }
         }
@@ -646,7 +644,7 @@ namespace Jint.Native.RegExp
                 && rei.TryGetDefaultRegExpExec(out _))
                 && rei.TryGetDefaultRegExpExec(out _))
             {
             {
                 // fast path
                 // fast path
-                var a = Engine.Array.ConstructFast(0);
+                var a = _realm.Intrinsics.Array.ConstructFast(0);
 
 
                 if (rei.Sticky)
                 if (rei.Sticky)
                 {
                 {
@@ -691,7 +689,7 @@ namespace Jint.Native.RegExp
 
 
         private JsValue MatchSlow(ObjectInstance rx, string s, bool fullUnicode)
         private JsValue MatchSlow(ObjectInstance rx, string s, bool fullUnicode)
         {
         {
-            var a = Engine.Array.ConstructFast(0);
+            var a = _realm.Intrinsics.Array.ConstructFast(0);
             uint n = 0;
             uint n = 0;
             while (true)
             while (true)
             {
             {
@@ -723,7 +721,7 @@ namespace Jint.Native.RegExp
             var r = AssertThisIsObjectInstance(thisObj, "RegExp.prototype.matchAll");
             var r = AssertThisIsObjectInstance(thisObj, "RegExp.prototype.matchAll");
 
 
             var s = TypeConverter.ToString(arguments.At(0));
             var s = TypeConverter.ToString(arguments.At(0));
-            var c = SpeciesConstructor(r, _engine.RegExp);
+            var c = SpeciesConstructor(r, _realm.Intrinsics.RegExp);
 
 
             var flags = TypeConverter.ToJsString(r.Get(PropertyFlags));
             var flags = TypeConverter.ToJsString(r.Get(PropertyFlags));
             var matcher = Construct(c, new JsValue[]
             var matcher = Construct(c, new JsValue[]
@@ -738,7 +736,7 @@ namespace Jint.Native.RegExp
             var global = flags.IndexOf('g') != -1;
             var global = flags.IndexOf('g') != -1;
             var fullUnicode = flags.IndexOf('u') != -1;
             var fullUnicode = flags.IndexOf('u') != -1;
 
 
-            return _engine.Iterator.CreateRegExpStringIterator(matcher, s, global, fullUnicode);
+            return _realm.Intrinsics.Iterator.CreateRegExpStringIterator(matcher, s, global, fullUnicode);
         }
         }
 
 
         private static int AdvanceStringIndex(string s, int index, bool unicode)
         private static int AdvanceStringIndex(string s, int index, bool unicode)
@@ -771,15 +769,16 @@ namespace Jint.Native.RegExp
                 var result = callable.Call(r, new JsValue[]  { s });
                 var result = callable.Call(r, new JsValue[]  { s });
                 if (!result.IsNull() && !result.IsObject())
                 if (!result.IsNull() && !result.IsObject())
                 {
                 {
-                    return ExceptionHelper.ThrowTypeError<ObjectInstance>(r.Engine);
+                    ExceptionHelper.ThrowTypeError(r.Engine.Realm);
                 }
                 }
 
 
                 return result;
                 return result;
             }
             }
 
 
-            if (!(r is RegExpInstance ri))
+            var ri = r as RegExpInstance;
+            if (ri is null)
             {
             {
-                return ExceptionHelper.ThrowTypeError<ObjectInstance>(r.Engine);
+                ExceptionHelper.ThrowTypeError(r.Engine.Realm);
             }
             }
 
 
             return RegExpBuiltinExec(ri, s);
             return RegExpBuiltinExec(ri, s);
@@ -817,7 +816,7 @@ namespace Jint.Native.RegExp
                 }
                 }
 
 
                 // "aaa".match() => [ '', index: 0, input: 'aaa' ]
                 // "aaa".match() => [ '', index: 0, input: 'aaa' ]
-                var array = R.Engine.Array.ConstructFast(1);
+                var array = R.Engine.Realm.Intrinsics.Array.ConstructFast(1);
                 array.FastAddProperty(PropertyIndex, lastIndex, true, true, true);
                 array.FastAddProperty(PropertyIndex, lastIndex, true, true, true);
                 array.FastAddProperty(PropertyInput, s, true, true, true);
                 array.FastAddProperty(PropertyInput, s, true, true, true);
                 array.SetIndexValue(0, JsString.Empty, updateLength: false);
                 array.SetIndexValue(0, JsString.Empty, updateLength: false);
@@ -889,7 +888,7 @@ namespace Jint.Native.RegExp
 
 
         private static ArrayInstance CreateReturnValueArray(Engine engine, Match match, string inputValue, bool fullUnicode)
         private static ArrayInstance CreateReturnValueArray(Engine engine, Match match, string inputValue, bool fullUnicode)
         {
         {
-            var array = engine.Array.ConstructFast((ulong) match.Groups.Count);
+            var array = engine.Realm.Intrinsics.Array.ConstructFast((ulong) match.Groups.Count);
             array.CreateDataProperty(PropertyIndex, match.Index);
             array.CreateDataProperty(PropertyIndex, match.Index);
             array.CreateDataProperty(PropertyInput, inputValue);
             array.CreateDataProperty(PropertyInput, inputValue);
 
 
@@ -918,9 +917,10 @@ namespace Jint.Native.RegExp
 
 
         private JsValue Exec(JsValue thisObj, JsValue[] arguments)
         private JsValue Exec(JsValue thisObj, JsValue[] arguments)
         {
         {
-            if (!(thisObj is RegExpInstance r))
+            var r = thisObj as RegExpInstance;
+            if (r is null)
             {
             {
-                return ExceptionHelper.ThrowTypeError<JsValue>(_engine);
+                ExceptionHelper.ThrowTypeError(_engine.Realm);
             }
             }
 
 
             var s = TypeConverter.ToString(arguments.At(0));
             var s = TypeConverter.ToString(arguments.At(0));

+ 20 - 26
Jint/Native/Set/SetConstructor.cs

@@ -12,31 +12,21 @@ namespace Jint.Native.Set
     {
     {
         private static readonly JsString _functionName = new JsString("Set");
         private static readonly JsString _functionName = new JsString("Set");
 
 
-        private SetConstructor(Engine engine)
-            : base(engine, _functionName, FunctionThisMode.Global)
+        internal SetConstructor(
+            Engine engine,
+            Realm realm,
+            FunctionPrototype functionPrototype,
+            ObjectPrototype objectPrototype)
+            : base(engine, realm, _functionName, FunctionThisMode.Global)
         {
         {
+            _prototype = functionPrototype;
+            PrototypeObject = new SetPrototype(engine, realm, this, objectPrototype);
+            _length = new PropertyDescriptor(0, PropertyFlag.Configurable);
+            _prototypeDescriptor = new PropertyDescriptor(PrototypeObject, PropertyFlag.AllForbidden);
         }
         }
 
 
         public SetPrototype PrototypeObject { get; private set; }
         public SetPrototype PrototypeObject { get; private set; }
 
 
-        public static SetConstructor CreateSetConstructor(Engine engine)
-        {
-            var obj = new SetConstructor(engine)
-            {
-                _prototype = engine.Function.PrototypeObject
-            };
-
-            // The value of the [[Prototype]] internal property of the Set constructor is the Function prototype object
-            obj.PrototypeObject = SetPrototype.CreatePrototypeObject(engine, obj);
-
-            obj._length = new PropertyDescriptor(0, PropertyFlag.Configurable);
-
-            // The initial value of Set.prototype is the Set prototype object
-            obj._prototypeDescriptor = new PropertyDescriptor(obj.PrototypeObject, PropertyFlag.AllForbidden);
-
-            return obj;
-        }
-
         protected override void Initialize()
         protected override void Initialize()
         {
         {
             var symbols = new SymbolDictionary(1)
             var symbols = new SymbolDictionary(1)
@@ -54,7 +44,7 @@ namespace Jint.Native.Set
 
 
         public override JsValue Call(JsValue thisObject, JsValue[] arguments)
         public override JsValue Call(JsValue thisObject, JsValue[] arguments)
         {
         {
-            ExceptionHelper.ThrowTypeError(_engine, "Constructor Set requires 'new'");
+            ExceptionHelper.ThrowTypeError(_engine.Realm, "Constructor Set requires 'new'");
             return null;
             return null;
         }
         }
 
 
@@ -65,19 +55,23 @@ namespace Jint.Native.Set
         {
         {
             if (newTarget.IsUndefined())
             if (newTarget.IsUndefined())
             {
             {
-                ExceptionHelper.ThrowTypeError(_engine);
+                ExceptionHelper.ThrowTypeError(_engine.Realm);
             }
             }
 
 
-            var set = OrdinaryCreateFromConstructor(newTarget, PrototypeObject, static (engine, _) => new SetInstance(engine));
+            var set = OrdinaryCreateFromConstructor(
+                newTarget,
+                static intrinsics => intrinsics.Set.PrototypeObject,
+                static (engine, realm, _) => new SetInstance(engine));
             if (arguments.Length > 0 && !arguments[0].IsNullOrUndefined())
             if (arguments.Length > 0 && !arguments[0].IsNullOrUndefined())
             {
             {
                 var adderValue = set.Get("add");
                 var adderValue = set.Get("add");
-                if (!(adderValue is ICallable adder))
+                var adder = adderValue as ICallable;
+                if (adder is null)
                 {
                 {
-                    return ExceptionHelper.ThrowTypeError<ObjectInstance>(_engine, "add must be callable");
+                    ExceptionHelper.ThrowTypeError(_engine.Realm, "add must be callable");
                 }
                 }
 
 
-                var iterable = arguments.At(0).GetIterator(_engine);
+                var iterable = arguments.At(0).GetIterator(_realm);
 
 
                 try
                 try
                 {
                 {

+ 2 - 2
Jint/Native/Set/SetInstance.cs

@@ -73,12 +73,12 @@ namespace Jint.Native.Set
 
 
         internal ObjectInstance Entries()
         internal ObjectInstance Entries()
         {
         {
-            return _engine.Iterator.ConstructEntryIterator(this);
+            return _engine.Realm.Intrinsics.Iterator.ConstructEntryIterator(this);
         }
         }
 
 
         internal ObjectInstance Values()
         internal ObjectInstance Values()
         {
         {
-            return _engine.Iterator.Construct(_set._list);
+            return _engine.Realm.Intrinsics.Iterator.Construct(_set._list);
         }
         }
     }
     }
 }
 }

+ 16 - 20
Jint/Native/Set/SetPrototype.cs

@@ -10,23 +10,18 @@ namespace Jint.Native.Set
     /// <summary>
     /// <summary>
     /// https://www.ecma-international.org/ecma-262/6.0/#sec-set-objects
     /// https://www.ecma-international.org/ecma-262/6.0/#sec-set-objects
     /// </summary>
     /// </summary>
-    public sealed class SetPrototype : ObjectInstance
+    public sealed class SetPrototype : Prototype
     {
     {
-        private SetConstructor _mapConstructor;
+        private readonly SetConstructor _constructor;
 
 
-        private SetPrototype(Engine engine) : base(engine)
+        internal SetPrototype(
+            Engine engine,
+            Realm realm,
+            SetConstructor setConstructor,
+            ObjectPrototype objectPrototype) : base(engine, realm)
         {
         {
-        }
-
-        public static SetPrototype CreatePrototypeObject(Engine engine, SetConstructor mapConstructor)
-        {
-            var obj = new SetPrototype(engine)
-            {
-                _prototype = engine.Object.PrototypeObject,
-                _mapConstructor = mapConstructor
-            };
-
-            return obj;
+            _prototype = objectPrototype;
+            _constructor = setConstructor;
         }
         }
 
 
         protected override void Initialize()
         protected override void Initialize()
@@ -34,7 +29,7 @@ namespace Jint.Native.Set
             var properties = new PropertyDictionary(12, checkExistingKeys: false)
             var properties = new PropertyDictionary(12, checkExistingKeys: false)
             {
             {
                 ["length"] = new PropertyDescriptor(0, PropertyFlag.Configurable),
                 ["length"] = new PropertyDescriptor(0, PropertyFlag.Configurable),
-                ["constructor"] = new PropertyDescriptor(_mapConstructor, PropertyFlag.NonEnumerable),
+                ["constructor"] = new PropertyDescriptor(_constructor, PropertyFlag.NonEnumerable),
                 ["add"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "add", Add, 1, PropertyFlag.Configurable), true, 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),
                 ["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),
                 ["delete"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "delete", Delete, 1, PropertyFlag.Configurable), true, false, true),
@@ -54,7 +49,7 @@ namespace Jint.Native.Set
             };
             };
             SetSymbols(symbols);
             SetSymbols(symbols);
         }
         }
-        
+
         private JsValue Size(JsValue thisObj, JsValue[] arguments)
         private JsValue Size(JsValue thisObj, JsValue[] arguments)
         {
         {
             AssertSetInstance(thisObj);
             AssertSetInstance(thisObj);
@@ -115,15 +110,16 @@ namespace Jint.Native.Set
             var set = AssertSetInstance(thisObj);
             var set = AssertSetInstance(thisObj);
             return set.Values();
             return set.Values();
         }
         }
-        
+
         private SetInstance AssertSetInstance(JsValue thisObj)
         private SetInstance AssertSetInstance(JsValue thisObj)
         {
         {
-            if (!(thisObj is SetInstance map))
+            var set = thisObj as SetInstance;
+            if (set is null)
             {
             {
-                return ExceptionHelper.ThrowTypeError<SetInstance>(_engine, "object must be a Set");
+                ExceptionHelper.ThrowTypeError(_realm, "object must be a Set");
             }
             }
 
 
-            return map;
+            return set;
         }
         }
     }
     }
 }
 }

+ 15 - 25
Jint/Native/String/StringConstructor.cs

@@ -16,30 +16,20 @@ namespace Jint.Native.String
     {
     {
         private static readonly JsString _functionName = new JsString("String");
         private static readonly JsString _functionName = new JsString("String");
 
 
-        public StringConstructor(Engine engine)
-            : base(engine, _functionName, FunctionThisMode.Global)
+        public StringConstructor(
+            Engine engine,
+            Realm realm,
+            FunctionPrototype functionPrototype,
+            ObjectPrototype objectPrototype)
+            : base(engine, realm, _functionName, FunctionThisMode.Global)
         {
         {
+            _prototype = functionPrototype;
+            PrototypeObject = new StringPrototype(engine, realm, this, objectPrototype);
+            _length = new PropertyDescriptor(JsNumber.One, PropertyFlag.Configurable);
+            _prototypeDescriptor = new PropertyDescriptor(PrototypeObject, PropertyFlag.AllForbidden);
         }
         }
 
 
-        public StringPrototype PrototypeObject { get; private set; }
-
-        public static StringConstructor CreateStringConstructor(Engine engine)
-        {
-            var obj = new StringConstructor(engine)
-            {
-                _prototype = engine.Function.PrototypeObject
-            };
-
-            // The value of the [[Prototype]] internal property of the String constructor is the Function prototype object
-            obj.PrototypeObject = StringPrototype.CreatePrototypeObject(engine, obj);
-
-            obj._length = new PropertyDescriptor(JsNumber.One, PropertyFlag.Configurable);
-
-            // The initial value of String.prototype is the String prototype object
-            obj._prototypeDescriptor = new PropertyDescriptor(obj.PrototypeObject, PropertyFlag.AllForbidden);
-
-            return obj;
-        }
+        public StringPrototype PrototypeObject { get; }
 
 
         protected override void Initialize()
         protected override void Initialize()
         {
         {
@@ -76,7 +66,7 @@ namespace Jint.Native.String
                     || double.IsNaN(codePoint)
                     || double.IsNaN(codePoint)
                     || TypeConverter.ToInt32(codePoint) != codePoint)
                     || TypeConverter.ToInt32(codePoint) != codePoint)
                 {
                 {
-                    return ExceptionHelper.ThrowRangeError<JsValue>(_engine, "Invalid code point " + codePoint);
+                    ExceptionHelper.ThrowRangeError(_realm, "Invalid code point " + codePoint);
                 }
                 }
 
 
                 var point = (uint) codePoint;
                 var point = (uint) codePoint;
@@ -108,8 +98,8 @@ namespace Jint.Native.String
         /// </summary>
         /// </summary>
         private JsValue Raw(JsValue thisObj, JsValue[] arguments)
         private JsValue Raw(JsValue thisObj, JsValue[] arguments)
         {
         {
-            var cooked = TypeConverter.ToObject(_engine, arguments.At(0));
-            var raw = TypeConverter.ToObject(_engine, cooked.Get(JintTaggedTemplateExpression.PropertyRaw, cooked));
+            var cooked = TypeConverter.ToObject(_realm, arguments.At(0));
+            var raw = TypeConverter.ToObject(_realm, cooked.Get(JintTaggedTemplateExpression.PropertyRaw, cooked));
 
 
             var operations = ArrayOperations.For(raw);
             var operations = ArrayOperations.For(raw);
             var length = operations.GetLength();
             var length = operations.GetLength();
@@ -176,7 +166,7 @@ namespace Jint.Native.String
                 return StringCreate(s, PrototypeObject);
                 return StringCreate(s, PrototypeObject);
             }
             }
 
 
-            return StringCreate(s, GetPrototypeFromConstructor(newTarget, PrototypeObject));
+            return StringCreate(s, GetPrototypeFromConstructor(newTarget, static intrinsics => intrinsics.String.PrototypeObject));
         }
         }
 
 
         public StringInstance Construct(string value)
         public StringInstance Construct(string value)

+ 38 - 35
Jint/Native/String/StringPrototype.cs

@@ -18,24 +18,21 @@ namespace Jint.Native.String
     /// </summary>
     /// </summary>
     public sealed class StringPrototype : StringInstance
     public sealed class StringPrototype : StringInstance
     {
     {
-        private StringConstructor _stringConstructor;
-
-        private StringPrototype(Engine engine)
+        private readonly Realm _realm;
+        private readonly StringConstructor _constructor;
+
+        internal StringPrototype(
+            Engine engine,
+            Realm realm,
+            StringConstructor constructor,
+            ObjectPrototype objectPrototype)
             : base(engine)
             : base(engine)
         {
         {
-        }
-
-        public static StringPrototype CreatePrototypeObject(Engine engine, StringConstructor stringConstructor)
-        {
-            var obj = new StringPrototype(engine)
-            {
-                _prototype = engine.Object.PrototypeObject,
-                PrimitiveValue = JsString.Empty,
-                _length = PropertyDescriptor.AllForbiddenDescriptor.NumberZero,
-                _stringConstructor = stringConstructor,
-            };
-
-            return obj;
+            _prototype = objectPrototype;
+            PrimitiveValue = JsString.Empty;
+            _length = PropertyDescriptor.AllForbiddenDescriptor.NumberZero;
+            _realm = realm;
+            _constructor = constructor;
         }
         }
 
 
         protected override void Initialize()
         protected override void Initialize()
@@ -44,7 +41,7 @@ namespace Jint.Native.String
             const PropertyFlag propertyFlags = lengthFlags | PropertyFlag.Writable;
             const PropertyFlag propertyFlags = lengthFlags | PropertyFlag.Writable;
             var properties = new PropertyDictionary(35, checkExistingKeys: false)
             var properties = new PropertyDictionary(35, checkExistingKeys: false)
             {
             {
-                ["constructor"] = new PropertyDescriptor(_stringConstructor, PropertyFlag.NonEnumerable),
+                ["constructor"] = new PropertyDescriptor(_constructor, PropertyFlag.NonEnumerable),
                 ["toString"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "toString", ToStringString, 0, lengthFlags), propertyFlags),
                 ["toString"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "toString", ToStringString, 0, lengthFlags), propertyFlags),
                 ["valueOf"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "valueOf", ValueOf, 0, lengthFlags), propertyFlags),
                 ["valueOf"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "valueOf", ValueOf, 0, lengthFlags), propertyFlags),
                 ["charAt"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "charAt", CharAt, 1, lengthFlags), propertyFlags),
                 ["charAt"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "charAt", CharAt, 1, lengthFlags), propertyFlags),
@@ -90,15 +87,20 @@ namespace Jint.Native.String
         {
         {
             TypeConverter.CheckObjectCoercible(_engine, thisObj);
             TypeConverter.CheckObjectCoercible(_engine, thisObj);
             var str = TypeConverter.ToString(thisObj);
             var str = TypeConverter.ToString(thisObj);
-            return _engine.Iterator.Construct(str);
+            return _realm.Intrinsics.Iterator.Construct(str);
         }
         }
 
 
         private JsValue ToStringString(JsValue thisObj, JsValue[] arguments)
         private JsValue ToStringString(JsValue thisObj, JsValue[] arguments)
         {
         {
-            var s = TypeConverter.ToObject(Engine, thisObj) as StringInstance;
+            if (thisObj.IsString())
+            {
+                return thisObj;
+            }
+
+            var s = TypeConverter.ToObject(_realm, thisObj) as StringInstance;
             if (ReferenceEquals(s, null))
             if (ReferenceEquals(s, null))
             {
             {
-                ExceptionHelper.ThrowTypeError(Engine);
+                ExceptionHelper.ThrowTypeError(_realm);
             }
             }
 
 
             return s.PrimitiveValue;
             return s.PrimitiveValue;
@@ -337,7 +339,7 @@ namespace Jint.Native.String
 
 
             if (lim == 0)
             if (lim == 0)
             {
             {
-                return Engine.Array.Construct(Arguments.Empty);
+                return _realm.Intrinsics.Array.Construct(Arguments.Empty);
             }
             }
 
 
             if (separator.IsNull())
             if (separator.IsNull())
@@ -346,7 +348,7 @@ namespace Jint.Native.String
             }
             }
             else if (separator.IsUndefined())
             else if (separator.IsUndefined())
             {
             {
-                var arrayInstance = Engine.Array.ConstructFast(1);
+                var arrayInstance = _realm.Intrinsics.Array.ConstructFast(1);
                 arrayInstance.SetIndexValue(0, s, updateLength: false);
                 arrayInstance.SetIndexValue(0, s, updateLength: false);
                 return arrayInstance;
                 return arrayInstance;
             }
             }
@@ -358,10 +360,10 @@ namespace Jint.Native.String
                 }
                 }
             }
             }
 
 
-            return SplitWithStringSeparator(_engine, separator, s, lim);
+            return SplitWithStringSeparator(_realm, separator, s, lim);
         }
         }
 
 
-        internal static JsValue SplitWithStringSeparator(Engine engine, JsValue separator, string s, uint lim)
+        internal static JsValue SplitWithStringSeparator(Realm realm, JsValue separator, string s, uint lim)
         {
         {
             var segments = StringExecutionContext.Current.SplitSegmentList;
             var segments = StringExecutionContext.Current.SplitSegmentList;
             segments.Clear();
             segments.Clear();
@@ -387,7 +389,7 @@ namespace Jint.Native.String
             }
             }
 
 
             var length = (uint) System.Math.Min(segments.Count, lim);
             var length = (uint) System.Math.Min(segments.Count, lim);
-            var a = engine.Array.ConstructFast(length);
+            var a = realm.Intrinsics.Array.ConstructFast(length);
             for (int i = 0; i < length; i++)
             for (int i = 0; i < length; i++)
             {
             {
                 a.SetIndexValue((uint) i, segments[i], updateLength: false);
                 a.SetIndexValue((uint) i, segments[i], updateLength: false);
@@ -452,7 +454,7 @@ namespace Jint.Native.String
                 }
                 }
             }
             }
 
 
-            var rx = (RegExpInstance) Engine.RegExp.Construct(new[] {regex});
+            var rx = (RegExpInstance) _realm.Intrinsics.RegExp.Construct(new[] {regex});
             var s = TypeConverter.ToString(thisObj);
             var s = TypeConverter.ToString(thisObj);
             return _engine.Invoke(rx, GlobalSymbolRegistry.Search, new JsValue[] { s });
             return _engine.Invoke(rx, GlobalSymbolRegistry.Search, new JsValue[] { s });
         }
         }
@@ -521,7 +523,7 @@ namespace Jint.Native.String
                 }
                 }
             }
             }
 
 
-            var rx = (RegExpInstance) Engine.RegExp.Construct(new[] {regex});
+            var rx = (RegExpInstance) _realm.Intrinsics.RegExp.Construct(new[] {regex});
 
 
             var s = TypeConverter.ToString(thisObj);
             var s = TypeConverter.ToString(thisObj);
             return _engine.Invoke(rx, GlobalSymbolRegistry.Match, new JsValue[] { s });
             return _engine.Invoke(rx, GlobalSymbolRegistry.Match, new JsValue[] { s });
@@ -540,7 +542,7 @@ namespace Jint.Native.String
                     TypeConverter.CheckObjectCoercible(_engine, flags);
                     TypeConverter.CheckObjectCoercible(_engine, flags);
                     if (TypeConverter.ToString(flags).IndexOf('g') < 0)
                     if (TypeConverter.ToString(flags).IndexOf('g') < 0)
                     {
                     {
-                        ExceptionHelper.ThrowTypeError(_engine);
+                        ExceptionHelper.ThrowTypeError(_realm);
                     }
                     }
                 }
                 }
                 var matcher = GetMethod(_engine, (ObjectInstance) regex, GlobalSymbolRegistry.MatchAll);
                 var matcher = GetMethod(_engine, (ObjectInstance) regex, GlobalSymbolRegistry.MatchAll);
@@ -551,7 +553,7 @@ namespace Jint.Native.String
             }
             }
 
 
             var s = TypeConverter.ToString(thisObj);
             var s = TypeConverter.ToString(thisObj);
-            var rx = (RegExpInstance) Engine.RegExp.Construct(new[] { regex, "g" });
+            var rx = (RegExpInstance) _realm.Intrinsics.RegExp.Construct(new[] { regex, "g" });
 
 
             return _engine.Invoke(rx, GlobalSymbolRegistry.MatchAll, new JsValue[] { s });
             return _engine.Invoke(rx, GlobalSymbolRegistry.MatchAll, new JsValue[] { s });
         }
         }
@@ -734,7 +736,8 @@ namespace Jint.Native.String
                 return thisObj;
                 return thisObj;
             }
             }
 
 
-            return ExceptionHelper.ThrowTypeError<JsValue>(Engine);
+            ExceptionHelper.ThrowTypeError(_realm);
+            return Undefined;
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -810,7 +813,7 @@ namespace Jint.Native.String
             {
             {
                 if (searchString.IsRegExp())
                 if (searchString.IsRegExp())
                 {
                 {
-                    ExceptionHelper.ThrowTypeError(Engine);
+                    ExceptionHelper.ThrowTypeError(_realm);
                 }
                 }
             }
             }
 
 
@@ -855,7 +858,7 @@ namespace Jint.Native.String
             {
             {
                 if (searchString.IsRegExp())
                 if (searchString.IsRegExp())
                 {
                 {
-                    ExceptionHelper.ThrowTypeError(Engine);
+                    ExceptionHelper.ThrowTypeError(_realm);
                 }
                 }
             }
             }
 
 
@@ -892,7 +895,7 @@ namespace Jint.Native.String
 
 
             if (searchString.IsRegExp())
             if (searchString.IsRegExp())
             {
             {
-                return ExceptionHelper.ThrowTypeError<JsValue>(_engine, "First argument to String.prototype.includes must not be a regular expression");
+                ExceptionHelper.ThrowTypeError(_realm, "First argument to String.prototype.includes must not be a regular expression");
             }
             }
 
 
             var searchStr = TypeConverter.ToString(searchString);
             var searchStr = TypeConverter.ToString(searchString);
@@ -950,7 +953,7 @@ namespace Jint.Native.String
                     break;
                     break;
                 default:
                 default:
                     ExceptionHelper.ThrowRangeError(
                     ExceptionHelper.ThrowRangeError(
-                        _engine,
+                        _realm,
                         "The normalization form should be one of NFC, NFD, NFKC, NFKD.");
                         "The normalization form should be one of NFC, NFD, NFKC, NFKD.");
                     break;
                     break;
             }
             }
@@ -966,7 +969,7 @@ namespace Jint.Native.String
 
 
             if (n < 0)
             if (n < 0)
             {
             {
-                return ExceptionHelper.ThrowRangeError<JsValue>(_engine, "Invalid count value");
+                ExceptionHelper.ThrowRangeError(_realm, "Invalid count value");
             }
             }
 
 
             if (n == 0 || str.Length == 0)
             if (n == 0 || str.Length == 0)

+ 16 - 24
Jint/Native/Symbol/SymbolConstructor.cs

@@ -15,27 +15,17 @@ namespace Jint.Native.Symbol
     {
     {
         private static readonly JsString _functionName = new JsString("Symbol");
         private static readonly JsString _functionName = new JsString("Symbol");
 
 
-        public SymbolConstructor(Engine engine)
-            : base(engine, _functionName, FunctionThisMode.Global)
+        internal SymbolConstructor(
+            Engine engine,
+            Realm realm,
+            FunctionPrototype functionPrototype,
+            ObjectPrototype objectPrototype)
+            : base(engine, realm, _functionName, FunctionThisMode.Global)
         {
         {
-        }
-
-        public static SymbolConstructor CreateSymbolConstructor(Engine engine)
-        {
-            var obj = new SymbolConstructor(engine)
-            {
-                _prototype = engine.Function.PrototypeObject
-            };
-
-            // The value of the [[Prototype]] internal property of the Symbol constructor is the Function prototype object
-            obj.PrototypeObject = SymbolPrototype.CreatePrototypeObject(engine, obj);
-
-            obj._length = new PropertyDescriptor(JsNumber.PositiveZero, PropertyFlag.Configurable);
-
-            // The initial value of String.prototype is the String prototype object
-            obj._prototypeDescriptor = new PropertyDescriptor(obj.PrototypeObject, PropertyFlag.AllForbidden);
-
-            return obj;
+            _prototype = functionPrototype;
+            PrototypeObject = new SymbolPrototype(engine, realm, this, objectPrototype);
+            _length = new PropertyDescriptor(JsNumber.PositiveZero, PropertyFlag.Configurable);
+            _prototypeDescriptor = new PropertyDescriptor(PrototypeObject, PropertyFlag.AllForbidden);
         }
         }
 
 
         protected override void Initialize()
         protected override void Initialize()
@@ -95,12 +85,13 @@ namespace Jint.Native.Symbol
 
 
         public JsValue KeyFor(JsValue thisObj, JsValue[] arguments)
         public JsValue KeyFor(JsValue thisObj, JsValue[] arguments)
         {
         {
-            if (!(arguments.At(0) is JsSymbol sym))
+            var symbol = arguments.At(0) as JsSymbol;
+            if (symbol is null)
             {
             {
-                return ExceptionHelper.ThrowTypeError<JsValue>(Engine);
+                ExceptionHelper.ThrowTypeError(_realm);
             }
             }
 
 
-            if (_engine.GlobalSymbolRegistry.TryGetSymbol(sym._value, out var e))
+            if (_engine.GlobalSymbolRegistry.TryGetSymbol(symbol._value, out var e))
             {
             {
                 return e._value;
                 return e._value;
             }
             }
@@ -110,7 +101,8 @@ namespace Jint.Native.Symbol
 
 
         public ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
         public ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
         {
         {
-            return ExceptionHelper.ThrowTypeError<ObjectInstance>(Engine);
+            ExceptionHelper.ThrowTypeError(_realm);
+            return null;
         }
         }
 
 
         public SymbolInstance Construct(JsSymbol symbol)
         public SymbolInstance Construct(JsSymbol symbol)

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

@@ -9,24 +9,19 @@ namespace Jint.Native.Symbol
     /// <summary>
     /// <summary>
     /// http://www.ecma-international.org/ecma-262/5.1/#sec-15.5.4
     /// http://www.ecma-international.org/ecma-262/5.1/#sec-15.5.4
     /// </summary>
     /// </summary>
-    public sealed class SymbolPrototype : ObjectInstance
+    public sealed class SymbolPrototype : Prototype
     {
     {
-        private SymbolConstructor _symbolConstructor;
+        private readonly SymbolConstructor _constructor;
 
 
-        private SymbolPrototype(Engine engine)
-            : base(engine)
+        internal SymbolPrototype(
+            Engine engine,
+            Realm realm,
+            SymbolConstructor symbolConstructor,
+            ObjectPrototype objectPrototype)
+            : base(engine, realm)
         {
         {
-        }
-
-        public static SymbolPrototype CreatePrototypeObject(Engine engine, SymbolConstructor symbolConstructor)
-        {
-            var obj = new SymbolPrototype(engine)
-            {
-                _prototype = engine.Object.PrototypeObject,
-                _symbolConstructor = symbolConstructor
-            };
-
-            return obj;
+            _prototype = objectPrototype;
+            _constructor = symbolConstructor;
         }
         }
 
 
         protected override void Initialize()
         protected override void Initialize()
@@ -36,7 +31,7 @@ namespace Jint.Native.Symbol
             SetProperties(new PropertyDictionary(5, checkExistingKeys: false)
             SetProperties(new PropertyDictionary(5, checkExistingKeys: false)
             {
             {
                 ["length"] = new PropertyDescriptor(JsNumber.PositiveZero, propertyFlags),
                 ["length"] = new PropertyDescriptor(JsNumber.PositiveZero, propertyFlags),
-                ["constructor"] = new PropertyDescriptor(_symbolConstructor, PropertyFlag.Configurable | PropertyFlag.Writable),
+                ["constructor"] = new PropertyDescriptor(_constructor, PropertyFlag.Configurable | PropertyFlag.Writable),
                 ["description"] = new GetSetPropertyDescriptor(new ClrFunctionInstance(Engine, "description", Description, 0, lengthFlags), Undefined, propertyFlags),
                 ["description"] = new GetSetPropertyDescriptor(new ClrFunctionInstance(Engine, "description", Description, 0, lengthFlags), Undefined, propertyFlags),
                 ["toString"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "toString", ToSymbolString, 0, lengthFlags), PropertyFlag.Configurable | PropertyFlag.Writable),
                 ["toString"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "toString", ToSymbolString, 0, lengthFlags), PropertyFlag.Configurable | PropertyFlag.Writable),
                 ["valueOf"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "valueOf", ValueOf, 0, lengthFlags), PropertyFlag.Configurable | PropertyFlag.Writable)
                 ["valueOf"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "valueOf", ValueOf, 0, lengthFlags), PropertyFlag.Configurable | PropertyFlag.Writable)
@@ -85,7 +80,8 @@ namespace Jint.Native.Symbol
                 return instance.SymbolData;
                 return instance.SymbolData;
             }
             }
 
 
-            return ExceptionHelper.ThrowTypeError<JsSymbol>(_engine);
+            ExceptionHelper.ThrowTypeError(_realm);
+            return null;
         }
         }
     }
     }
 }
 }

+ 18 - 25
Jint/Native/WeakMap/WeakMapConstructor.cs

@@ -10,34 +10,24 @@ namespace Jint.Native.WeakMap
     {
     {
         private static readonly JsString _functionName = new JsString("WeakMap");
         private static readonly JsString _functionName = new JsString("WeakMap");
 
 
-        private WeakMapConstructor(Engine engine)
-            : base(engine, _functionName)
+        internal WeakMapConstructor(
+            Engine engine,
+            Realm realm,
+            FunctionPrototype prototype,
+            ObjectPrototype objectPrototype)
+            : base(engine, realm, _functionName)
         {
         {
+            _prototype = prototype;
+            PrototypeObject = new WeakMapPrototype(engine, realm, this, objectPrototype);
+            _length = new PropertyDescriptor(0, PropertyFlag.Configurable);
+            _prototypeDescriptor = new PropertyDescriptor(PrototypeObject, PropertyFlag.AllForbidden);
         }
         }
 
 
-        public WeakMapPrototype PrototypeObject { get; private set; }
-
-        public static WeakMapConstructor CreateWeakMapConstructor(Engine engine)
-        {
-            var obj = new WeakMapConstructor(engine)
-            {
-                _prototype = engine.Function.PrototypeObject
-            };
-
-            // The value of the [[Prototype]] internal property of the WeakMap constructor is the WeakMap prototype object
-            obj.PrototypeObject = WeakMapPrototype.CreatePrototypeObject(engine, obj);
-
-            obj._length = new PropertyDescriptor(0, PropertyFlag.Configurable);
-
-            // The initial value of WeakMap.prototype is the WeakMap prototype object
-            obj._prototypeDescriptor = new PropertyDescriptor(obj.PrototypeObject, PropertyFlag.AllForbidden);
-
-            return obj;
-        }
+        public WeakMapPrototype PrototypeObject { get; }
 
 
         public override JsValue Call(JsValue thisObject, JsValue[] arguments)
         public override JsValue Call(JsValue thisObject, JsValue[] arguments)
         {
         {
-            ExceptionHelper.ThrowTypeError(_engine, "Constructor WeakMap requires 'new'");
+            ExceptionHelper.ThrowTypeError(_realm, "Constructor WeakMap requires 'new'");
             return null;
             return null;
         }
         }
 
 
@@ -45,14 +35,17 @@ namespace Jint.Native.WeakMap
         {
         {
             if (newTarget.IsUndefined())
             if (newTarget.IsUndefined())
             {
             {
-                ExceptionHelper.ThrowTypeError(_engine);
+                ExceptionHelper.ThrowTypeError(_realm);
             }
             }
 
 
-            var map = OrdinaryCreateFromConstructor(newTarget, PrototypeObject, static (engine, _) => new WeakMapInstance(engine));
+            var map = OrdinaryCreateFromConstructor(
+                newTarget,
+                static intrinsics =>  intrinsics.WeakMap.PrototypeObject,
+                static (engine, realm, _) => new WeakMapInstance(engine));
             if (arguments.Length > 0 && !arguments[0].IsNullOrUndefined())
             if (arguments.Length > 0 && !arguments[0].IsNullOrUndefined())
             {
             {
                 var adder = map.Get("set");
                 var adder = map.Get("set");
-                var iterator = arguments.At(0).GetIterator(_engine);
+                var iterator = arguments.At(0).GetIterator(_realm);
 
 
                 IteratorProtocol.AddEntriesFromIterable(map, iterator, adder);
                 IteratorProtocol.AddEntriesFromIterable(map, iterator, adder);
             }
             }

+ 1 - 1
Jint/Native/WeakMap/WeakMapInstance.cs

@@ -28,7 +28,7 @@ namespace Jint.Native.WeakMap
         {
         {
             if (key.IsPrimitive())
             if (key.IsPrimitive())
             {
             {
-                ExceptionHelper.ThrowTypeError(_engine, "WeakMap key must be an object, got " + key.ToString());
+                ExceptionHelper.ThrowTypeError(_engine.Realm, "WeakMap key must be an object, got " + key.ToString());
             }
             }
 
 
 #if NETSTANDARD2_1
 #if NETSTANDARD2_1

+ 14 - 18
Jint/Native/WeakMap/WeakMapPrototype.cs

@@ -10,23 +10,18 @@ namespace Jint.Native.WeakMap
     /// <summary>
     /// <summary>
     /// https://tc39.es/ecma262/#sec-weakmap-objects
     /// https://tc39.es/ecma262/#sec-weakmap-objects
     /// </summary>
     /// </summary>
-    public sealed class WeakMapPrototype : ObjectInstance
+    public sealed class WeakMapPrototype : Prototype
     {
     {
-        private WeakMapConstructor _weakMapConstructor;
+        private readonly WeakMapConstructor _constructor;
 
 
-        private WeakMapPrototype(Engine engine) : base(engine)
+        internal WeakMapPrototype(
+            Engine engine,
+            Realm realm,
+            WeakMapConstructor constructor,
+            ObjectPrototype prototype) : base(engine, realm)
         {
         {
-        }
-
-        public static WeakMapPrototype CreatePrototypeObject(Engine engine, WeakMapConstructor weakMapConstructor)
-        {
-            var obj = new WeakMapPrototype(engine)
-            {
-                _prototype = engine.Object.PrototypeObject,
-                _weakMapConstructor = weakMapConstructor
-            };
-
-            return obj;
+            _prototype = prototype;
+            _constructor = constructor;
         }
         }
 
 
         protected override void Initialize()
         protected override void Initialize()
@@ -35,7 +30,7 @@ namespace Jint.Native.WeakMap
             var properties = new PropertyDictionary(6, checkExistingKeys: false)
             var properties = new PropertyDictionary(6, checkExistingKeys: false)
             {
             {
                 ["length"] = new PropertyDescriptor(0, PropertyFlag.Configurable),
                 ["length"] = new PropertyDescriptor(0, PropertyFlag.Configurable),
-                ["constructor"] = new PropertyDescriptor(_weakMapConstructor, PropertyFlag.NonEnumerable),
+                ["constructor"] = new PropertyDescriptor(_constructor, PropertyFlag.NonEnumerable),
                 ["delete"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "delete", Delete, 1, PropertyFlag.Configurable), propertyFlags),
                 ["delete"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "delete", Delete, 1, PropertyFlag.Configurable), propertyFlags),
                 ["get"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "get", Get, 1, PropertyFlag.Configurable), propertyFlags),
                 ["get"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "get", Get, 1, PropertyFlag.Configurable), propertyFlags),
                 ["has"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "has", Has, 1, PropertyFlag.Configurable), propertyFlags),
                 ["has"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "has", Has, 1, PropertyFlag.Configurable), propertyFlags),
@@ -74,12 +69,13 @@ namespace Jint.Native.WeakMap
             var map = AssertWeakMapInstance(thisObj);
             var map = AssertWeakMapInstance(thisObj);
             return map.WeakMapHas(arguments.At(0)) ? JsBoolean.True : JsBoolean.False;
             return map.WeakMapHas(arguments.At(0)) ? JsBoolean.True : JsBoolean.False;
         }
         }
-        
+
         private WeakMapInstance AssertWeakMapInstance(JsValue thisObj)
         private WeakMapInstance AssertWeakMapInstance(JsValue thisObj)
         {
         {
-            if (!(thisObj is WeakMapInstance map))
+            var map = thisObj as WeakMapInstance;
+            if (map is null)
             {
             {
-                return ExceptionHelper.ThrowTypeError<WeakMapInstance>(_engine, "object must be a WeakMap");
+                ExceptionHelper.ThrowTypeError(_realm, "object must be a WeakMap");
             }
             }
 
 
             return map;
             return map;

+ 21 - 28
Jint/Native/WeakSet/WeakSetConstructor.cs

@@ -9,34 +9,24 @@ namespace Jint.Native.WeakSet
     {
     {
         private static readonly JsString _functionName = new JsString("WeakSet");
         private static readonly JsString _functionName = new JsString("WeakSet");
 
 
-        private WeakSetConstructor(Engine engine)
-            : base(engine, _functionName)
+        internal WeakSetConstructor(
+            Engine engine,
+            Realm realm,
+            FunctionPrototype functionPrototype,
+            ObjectPrototype objectPrototype)
+            : base(engine, realm, _functionName)
         {
         {
+            _prototype = functionPrototype;
+            PrototypeObject = new WeakSetPrototype(engine, realm, this, objectPrototype);
+            _length = new PropertyDescriptor(0, PropertyFlag.Configurable);
+            _prototypeDescriptor = new PropertyDescriptor(PrototypeObject, PropertyFlag.AllForbidden);
         }
         }
 
 
-        public WeakSetPrototype PrototypeObject { get; private set; }
-
-        public static WeakSetConstructor CreateWeakSetConstructor(Engine engine)
-        {
-            var obj = new WeakSetConstructor(engine)
-            {
-                _prototype = engine.Function.PrototypeObject
-            };
-
-            // The value of the [[Prototype]] internal property of the WeakSet constructor is the Function prototype object
-            obj.PrototypeObject = WeakSetPrototype.CreatePrototypeObject(engine, obj);
-
-            obj._length = new PropertyDescriptor(0, PropertyFlag.Configurable);
-
-            // The initial value of WeakSet.prototype is the WeakSet prototype object
-            obj._prototypeDescriptor = new PropertyDescriptor(obj.PrototypeObject, PropertyFlag.AllForbidden);
-
-            return obj;
-        }
+        public WeakSetPrototype PrototypeObject { get; }
 
 
         public override JsValue Call(JsValue thisObject, JsValue[] arguments)
         public override JsValue Call(JsValue thisObject, JsValue[] arguments)
         {
         {
-            ExceptionHelper.ThrowTypeError(_engine, "Constructor WeakSet requires 'new'");
+            ExceptionHelper.ThrowTypeError(_realm, "Constructor WeakSet requires 'new'");
             return null;
             return null;
         }
         }
 
 
@@ -44,19 +34,22 @@ namespace Jint.Native.WeakSet
         {
         {
             if (newTarget.IsUndefined())
             if (newTarget.IsUndefined())
             {
             {
-                ExceptionHelper.ThrowTypeError(_engine);
+                ExceptionHelper.ThrowTypeError(_realm);
             }
             }
 
 
-            var set = OrdinaryCreateFromConstructor(newTarget, PrototypeObject, static (engine, _) => new WeakSetInstance(engine));
+            var set = OrdinaryCreateFromConstructor(
+                newTarget,
+                static intrinsics => intrinsics.WeakSet.PrototypeObject,
+                static (engine, realm, _) => new WeakSetInstance(engine));
             if (arguments.Length > 0 && !arguments[0].IsNullOrUndefined())
             if (arguments.Length > 0 && !arguments[0].IsNullOrUndefined())
             {
             {
-                var adderValue = set.Get("add");
-                if (!(adderValue is ICallable adder))
+                var adder = set.Get("add") as ICallable;
+                if (adder is null)
                 {
                 {
-                    return ExceptionHelper.ThrowTypeError<ObjectInstance>(_engine, "add must be callable");
+                    ExceptionHelper.ThrowTypeError(_realm, "add must be callable");
                 }
                 }
 
 
-                var iterable = arguments.At(0).GetIterator(_engine);
+                var iterable = arguments.At(0).GetIterator(_realm);
 
 
                 try
                 try
                 {
                 {

+ 1 - 1
Jint/Native/WeakSet/WeakSetInstance.cs

@@ -30,7 +30,7 @@ namespace Jint.Native.WeakSet
         {
         {
             if (value.IsPrimitive())
             if (value.IsPrimitive())
             {
             {
-                ExceptionHelper.ThrowTypeError(_engine, "WeakSet value must be an object, got " + value.ToString());
+                ExceptionHelper.ThrowTypeError(_engine.Realm, "WeakSet value must be an object, got " + value.ToString());
             }
             }
 
 
 #if NETSTANDARD2_1
 #if NETSTANDARD2_1

+ 14 - 18
Jint/Native/WeakSet/WeakSetPrototype.cs

@@ -10,23 +10,18 @@ namespace Jint.Native.WeakSet
     /// <summary>
     /// <summary>
     /// https://tc39.es/ecma262/#sec-weakset-objects
     /// https://tc39.es/ecma262/#sec-weakset-objects
     /// </summary>
     /// </summary>
-    public sealed class WeakSetPrototype : ObjectInstance
+    public sealed class WeakSetPrototype : Prototype
     {
     {
-        private WeakSetConstructor _weakSetConstructor;
+        private readonly WeakSetConstructor _constructor;
 
 
-        private WeakSetPrototype(Engine engine) : base(engine)
+        internal WeakSetPrototype(
+            Engine engine,
+            Realm realm,
+            WeakSetConstructor constructor,
+            ObjectPrototype prototype) : base(engine, realm)
         {
         {
-        }
-
-        public static WeakSetPrototype CreatePrototypeObject(Engine engine, WeakSetConstructor weakSetConstructor)
-        {
-            var obj = new WeakSetPrototype(engine)
-            {
-                _prototype = engine.Object.PrototypeObject,
-                _weakSetConstructor = weakSetConstructor
-            };
-
-            return obj;
+            _prototype = prototype;
+            _constructor = constructor;
         }
         }
 
 
         protected override void Initialize()
         protected override void Initialize()
@@ -35,7 +30,7 @@ namespace Jint.Native.WeakSet
             var properties = new PropertyDictionary(5, checkExistingKeys: false)
             var properties = new PropertyDictionary(5, checkExistingKeys: false)
             {
             {
                 ["length"] = new PropertyDescriptor(0, PropertyFlag.Configurable),
                 ["length"] = new PropertyDescriptor(0, PropertyFlag.Configurable),
-                ["constructor"] = new PropertyDescriptor(_weakSetConstructor, PropertyFlag.NonEnumerable),
+                ["constructor"] = new PropertyDescriptor(_constructor, PropertyFlag.NonEnumerable),
                 ["delete"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "delete", Delete, 1, PropertyFlag.Configurable), propertyFlags),
                 ["delete"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "delete", Delete, 1, PropertyFlag.Configurable), propertyFlags),
                 ["add"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "add", Add, 1, PropertyFlag.Configurable), propertyFlags),
                 ["add"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "add", Add, 1, PropertyFlag.Configurable), propertyFlags),
                 ["has"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "has", Has, 1, PropertyFlag.Configurable), propertyFlags),
                 ["has"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "has", Has, 1, PropertyFlag.Configurable), propertyFlags),
@@ -67,12 +62,13 @@ namespace Jint.Native.WeakSet
             var set = AssertWeakSetInstance(thisObj);
             var set = AssertWeakSetInstance(thisObj);
             return set.WeakSetHas(arguments.At(0)) ? JsBoolean.True : JsBoolean.False;
             return set.WeakSetHas(arguments.At(0)) ? JsBoolean.True : JsBoolean.False;
         }
         }
-        
+
         private WeakSetInstance AssertWeakSetInstance(JsValue thisObj)
         private WeakSetInstance AssertWeakSetInstance(JsValue thisObj)
         {
         {
-            if (!(thisObj is WeakSetInstance set))
+            var set = thisObj as WeakSetInstance;
+            if (set is null)
             {
             {
-                return ExceptionHelper.ThrowTypeError<WeakSetInstance>(_engine, "object must be a WeakSet");
+                ExceptionHelper.ThrowTypeError(_realm, "object must be a WeakSet");
             }
             }
 
 
             return set;
             return set;

+ 24 - 12
Jint/Options.cs

@@ -39,6 +39,7 @@ namespace Jint
 
 
         private readonly List<Type> _extensionMethodClassTypes = new();
         private readonly List<Type> _extensionMethodClassTypes = new();
         internal ExtensionMethodCache _extensionMethods = ExtensionMethodCache.Empty;
         internal ExtensionMethodCache _extensionMethods = ExtensionMethodCache.Empty;
+        internal Func<Engine, Host> _hostFactory = _ => new Host();
 
 
         /// <summary>
         /// <summary>
         /// Run the script in strict mode.
         /// Run the script in strict mode.
@@ -97,13 +98,13 @@ namespace Jint
 
 
         private void AttachExtensionMethodsToPrototypes(Engine engine)
         private void AttachExtensionMethodsToPrototypes(Engine engine)
         {
         {
-            AttachExtensionMethodsToPrototype(engine, engine.Array.PrototypeObject, typeof(Array));
-            AttachExtensionMethodsToPrototype(engine, engine.Boolean.PrototypeObject, typeof(bool));
-            AttachExtensionMethodsToPrototype(engine, engine.Date.PrototypeObject, typeof(DateTime));
-            AttachExtensionMethodsToPrototype(engine, engine.Number.PrototypeObject, typeof(double));
-            AttachExtensionMethodsToPrototype(engine, engine.Object.PrototypeObject, typeof(ExpandoObject));
-            AttachExtensionMethodsToPrototype(engine, engine.RegExp.PrototypeObject, typeof(System.Text.RegularExpressions.Regex));
-            AttachExtensionMethodsToPrototype(engine, engine.String.PrototypeObject, typeof(string));
+            AttachExtensionMethodsToPrototype(engine, engine.Realm.Intrinsics.Array.PrototypeObject, typeof(Array));
+            AttachExtensionMethodsToPrototype(engine, engine.Realm.Intrinsics.Boolean.PrototypeObject, typeof(bool));
+            AttachExtensionMethodsToPrototype(engine, engine.Realm.Intrinsics.Date.PrototypeObject, typeof(DateTime));
+            AttachExtensionMethodsToPrototype(engine, engine.Realm.Intrinsics.Number.PrototypeObject, typeof(double));
+            AttachExtensionMethodsToPrototype(engine, engine.Realm.Intrinsics.Object.PrototypeObject, typeof(ExpandoObject));
+            AttachExtensionMethodsToPrototype(engine, engine.Realm.Intrinsics.RegExp.PrototypeObject, typeof(System.Text.RegularExpressions.Regex));
+            AttachExtensionMethodsToPrototype(engine, engine.Realm.Intrinsics.String.PrototypeObject, typeof(string));
         }
         }
 
 
         private void AttachExtensionMethodsToPrototype(Engine engine, ObjectInstance prototype, Type objectType)
         private void AttachExtensionMethodsToPrototype(Engine engine, ObjectInstance prototype, Type objectType)
@@ -181,11 +182,11 @@ namespace Jint
 
 
         /// <summary>
         /// <summary>
         /// Registers a delegate that is called when CLR members are invoked. This allows
         /// Registers a delegate that is called when CLR members are invoked. This allows
-        /// to change what values are returned for specific CLR objects, or if any value 
+        /// to change what values are returned for specific CLR objects, or if any value
         /// is returned at all.
         /// is returned at all.
         /// </summary>
         /// </summary>
         /// <param name="accessor">
         /// <param name="accessor">
-        /// The delegate to invoke for each CLR member. If the delegate 
+        /// The delegate to invoke for each CLR member. If the delegate
         /// returns <c>null</c>, the standard evaluation is performed.
         /// returns <c>null</c>, the standard evaluation is performed.
         /// </param>
         /// </param>
         public Options SetMemberAccessor(MemberAccessorDelegate accessor)
         public Options SetMemberAccessor(MemberAccessorDelegate accessor)
@@ -304,6 +305,17 @@ namespace Jint
             return this;
             return this;
         }
         }
 
 
+        /// <summary>
+        /// Allows to configure how the host is constructed.
+        /// </summary>
+        /// <remarks>
+        /// Passed Engine instance is still in construction and should not be used during call stage.
+        /// </remarks>
+        public void UseHostFactory<T>(Func<Engine, T> factory) where T : Host
+        {
+            _hostFactory = factory;
+        }
+
         /// <summary>
         /// <summary>
         /// Called by the <see cref="Engine"/> instance that loads this <see cref="Options" />
         /// Called by the <see cref="Engine"/> instance that loads this <see cref="Options" />
         /// once it is loaded.
         /// once it is loaded.
@@ -318,8 +330,8 @@ namespace Jint
             // add missing bits if needed
             // add missing bits if needed
             if (_allowClr)
             if (_allowClr)
             {
             {
-                engine.Global.SetProperty("System", new PropertyDescriptor(new NamespaceReference(engine, "System"), PropertyFlag.AllForbidden));
-                engine.Global.SetProperty("importNamespace", new PropertyDescriptor(new ClrFunctionInstance(
+                engine.Realm.GlobalObject.SetProperty("System", new PropertyDescriptor(new NamespaceReference(engine, "System"), PropertyFlag.AllForbidden));
+                engine.Realm.GlobalObject.SetProperty("importNamespace", new PropertyDescriptor(new ClrFunctionInstance(
                     engine,
                     engine,
                     "importNamespace",
                     "importNamespace",
                     func: (thisObj, arguments) => new NamespaceReference(engine, TypeConverter.ToString(arguments.At(0)))), PropertyFlag.AllForbidden));
                     func: (thisObj, arguments) => new NamespaceReference(engine, TypeConverter.ToString(arguments.At(0)))), PropertyFlag.AllForbidden));
@@ -367,7 +379,7 @@ namespace Jint
 
 
         private sealed class DefaultReferenceResolver : IReferenceResolver
         private sealed class DefaultReferenceResolver : IReferenceResolver
         {
         {
-            public static readonly DefaultReferenceResolver Instance = new DefaultReferenceResolver();
+            public static readonly DefaultReferenceResolver Instance = new();
 
 
             private DefaultReferenceResolver()
             private DefaultReferenceResolver()
             {
             {

+ 1 - 1
Jint/Pooling/ArgumentsInstancePool.cs

@@ -25,7 +25,7 @@ namespace Jint.Pooling
         {
         {
             return new ArgumentsInstance(_engine)
             return new ArgumentsInstance(_engine)
             {
             {
-                _prototype = _engine.Object.PrototypeObject
+                _prototype = _engine.Realm.Intrinsics.Object.PrototypeObject
             };
             };
         }
         }
 
 

+ 4 - 4
Jint/Runtime/Descriptors/GetSetPropertyDescriptor.cs

@@ -35,7 +35,7 @@ namespace Jint.Runtime.Descriptors
         {
         {
             _get = getter;
             _get = getter;
         }
         }
-        
+
         internal void SetSet(JsValue setter)
         internal void SetSet(JsValue setter)
         {
         {
             _set = setter;
             _set = setter;
@@ -46,7 +46,7 @@ namespace Jint.Runtime.Descriptors
             private readonly Engine _engine;
             private readonly Engine _engine;
             private readonly string _message;
             private readonly string _message;
             private JsValue _thrower;
             private JsValue _thrower;
-            
+
             public ThrowerPropertyDescriptor(Engine engine, PropertyFlag flags, string message)
             public ThrowerPropertyDescriptor(Engine engine, PropertyFlag flags, string message)
                 : base(flags)
                 : base(flags)
             {
             {
@@ -54,8 +54,8 @@ namespace Jint.Runtime.Descriptors
                 _message = message;
                 _message = message;
             }
             }
 
 
-            public override JsValue Get => _thrower ??= new ThrowTypeError(_engine, _message) { _prototype = _engine.Function.PrototypeObject};
-            public override JsValue Set => _thrower ??= new ThrowTypeError(_engine, _message) { _prototype = _engine.Function.PrototypeObject};
+            public override JsValue Get => _thrower ??= new ThrowTypeError(_engine, _engine.Realm, _message) { _prototype = _engine.Realm.Intrinsics.Function.PrototypeObject};
+            public override JsValue Set => _thrower ??= new ThrowTypeError(_engine, _engine.Realm, _message) { _prototype = _engine.Realm.Intrinsics.Function.PrototypeObject};
 
 
             protected internal override JsValue CustomValue
             protected internal override JsValue CustomValue
             {
             {

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

@@ -218,12 +218,12 @@ namespace Jint.Runtime.Descriptors
             get { return _flags; }
             get { return _flags; }
         }
         }
 
 
-        public static PropertyDescriptor ToPropertyDescriptor(Engine engine, JsValue o)
+        public static PropertyDescriptor ToPropertyDescriptor(Realm realm, JsValue o)
         {
         {
             var obj = o.TryCast<ObjectInstance>();
             var obj = o.TryCast<ObjectInstance>();
             if (ReferenceEquals(obj, null))
             if (ReferenceEquals(obj, null))
             {
             {
-                ExceptionHelper.ThrowTypeError(engine);
+                ExceptionHelper.ThrowTypeError(realm);
             }
             }
 
 
             var getProperty = obj.GetProperty(CommonProperties.Get);
             var getProperty = obj.GetProperty(CommonProperties.Get);
@@ -234,7 +234,7 @@ namespace Jint.Runtime.Descriptors
             if ((obj.HasProperty(CommonProperties.Value) || obj.HasProperty(CommonProperties.Writable)) &&
             if ((obj.HasProperty(CommonProperties.Value) || obj.HasProperty(CommonProperties.Writable)) &&
                 (hasGetProperty || hasSetProperty))
                 (hasGetProperty || hasSetProperty))
             {
             {
-                ExceptionHelper.ThrowTypeError(engine);
+                ExceptionHelper.ThrowTypeError(realm);
             }
             }
 
 
             var desc = hasGetProperty || hasSetProperty
             var desc = hasGetProperty || hasSetProperty
@@ -273,7 +273,7 @@ namespace Jint.Runtime.Descriptors
                 var getter = obj.UnwrapJsValue(getProperty);
                 var getter = obj.UnwrapJsValue(getProperty);
                 if (!getter.IsUndefined() && getter.TryCast<ICallable>() == null)
                 if (!getter.IsUndefined() && getter.TryCast<ICallable>() == null)
                 {
                 {
-                    ExceptionHelper.ThrowTypeError(engine);
+                    ExceptionHelper.ThrowTypeError(realm);
                 }
                 }
 
 
                 ((GetSetPropertyDescriptor) desc).SetGet(getter);
                 ((GetSetPropertyDescriptor) desc).SetGet(getter);
@@ -284,7 +284,7 @@ namespace Jint.Runtime.Descriptors
                 var setter = obj.UnwrapJsValue(setProperty);
                 var setter = obj.UnwrapJsValue(setProperty);
                 if (!setter.IsUndefined() && setter.TryCast<ICallable>() == null)
                 if (!setter.IsUndefined() && setter.TryCast<ICallable>() == null)
                 {
                 {
-                    ExceptionHelper.ThrowTypeError(engine);
+                    ExceptionHelper.ThrowTypeError(realm);
                 }
                 }
 
 
                 ((GetSetPropertyDescriptor) desc).SetSet(setter);
                 ((GetSetPropertyDescriptor) desc).SetSet(setter);
@@ -294,7 +294,7 @@ namespace Jint.Runtime.Descriptors
             {
             {
                 if (!ReferenceEquals(desc.Value, null) || desc.WritableSet)
                 if (!ReferenceEquals(desc.Value, null) || desc.WritableSet)
                 {
                 {
-                    ExceptionHelper.ThrowTypeError(engine);
+                    ExceptionHelper.ThrowTypeError(realm);
                 }
                 }
             }
             }
 
 
@@ -308,7 +308,7 @@ namespace Jint.Runtime.Descriptors
                 return Native.Undefined.Instance;
                 return Native.Undefined.Instance;
             }
             }
 
 
-            var obj = engine.Object.Construct(Arguments.Empty);
+            var obj = engine.Realm.Intrinsics.Object.Construct(Arguments.Empty);
             var properties = new PropertyDictionary(4, checkExistingKeys: false);
             var properties = new PropertyDictionary(4, checkExistingKeys: false);
 
 
             if (desc.IsDataDescriptor())
             if (desc.IsDataDescriptor())

+ 5 - 3
Jint/Runtime/Descriptors/Specialized/LazyPropertyDescriptor.cs

@@ -5,17 +5,19 @@ namespace Jint.Runtime.Descriptors.Specialized
 {
 {
     internal sealed class LazyPropertyDescriptor : PropertyDescriptor
     internal sealed class LazyPropertyDescriptor : PropertyDescriptor
     {
     {
-        private readonly Func<JsValue> _resolver;
+        private readonly object _state;
+        private readonly Func<object, JsValue> _resolver;
 
 
-        internal LazyPropertyDescriptor(Func<JsValue> resolver, PropertyFlag flags)
+        internal LazyPropertyDescriptor(object state, Func<object, JsValue> resolver, PropertyFlag flags)
             : base(null, flags | PropertyFlag.CustomJsValue)
             : base(null, flags | PropertyFlag.CustomJsValue)
         {
         {
+            _state = state;
             _resolver = resolver;
             _resolver = resolver;
         }
         }
 
 
         protected internal override JsValue CustomValue
         protected internal override JsValue CustomValue
         {
         {
-            get => _value ??= _resolver();
+            get => _value ??= _resolver(_state);
             set => _value = value;
             set => _value = value;
         }
         }
     }
     }

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

@@ -6,7 +6,7 @@ namespace Jint.Runtime.Environments
 {
 {
     /// <summary>
     /// <summary>
     /// Represents a declarative environment record
     /// Represents a declarative environment record
-    /// http://www.ecma-international.org/ecma-262/5.1/#sec-10.2.1.1
+    /// https://tc39.es/ecma262/#sec-declarative-environment-records
     /// </summary>
     /// </summary>
     internal class DeclarativeEnvironmentRecord : EnvironmentRecord
     internal class DeclarativeEnvironmentRecord : EnvironmentRecord
     {
     {
@@ -53,7 +53,7 @@ namespace Jint.Runtime.Environments
             _hasBindings = true;
             _hasBindings = true;
             _dictionary[name] = new Binding(null, canBeDeleted, mutable: true, strict: false);
             _dictionary[name] = new Binding(null, canBeDeleted, mutable: true, strict: false);
         }
         }
-        
+
         public sealed override void CreateImmutableBinding(string name, bool strict = true)
         public sealed override void CreateImmutableBinding(string name, bool strict = true)
         {
         {
             _hasBindings = true;
             _hasBindings = true;
@@ -79,7 +79,7 @@ namespace Jint.Runtime.Environments
             {
             {
                 if (strict)
                 if (strict)
                 {
                 {
-                    ExceptionHelper.ThrowReferenceError(_engine, key);
+                    ExceptionHelper.ThrowReferenceError(_engine.Realm, key);
                 }
                 }
                 CreateMutableBindingAndInitialize(key, canBeDeleted: true, value);
                 CreateMutableBindingAndInitialize(key, canBeDeleted: true, value);
                 return;
                 return;
@@ -93,9 +93,9 @@ namespace Jint.Runtime.Environments
             // Is it an uninitialized binding?
             // Is it an uninitialized binding?
             if (!binding.IsInitialized())
             if (!binding.IsInitialized())
             {
             {
-                ExceptionHelper.ThrowReferenceError<object>(_engine, message: "Cannot access '" +  key + "' before initialization");
+                ExceptionHelper.ThrowReferenceError(_engine.Realm, "Cannot access '" +  key + "' before initialization");
             }
             }
-            
+
             if (binding.Mutable)
             if (binding.Mutable)
             {
             {
                 _hasBindings = true;
                 _hasBindings = true;
@@ -105,7 +105,7 @@ namespace Jint.Runtime.Environments
             {
             {
                 if (strict)
                 if (strict)
                 {
                 {
-                    ExceptionHelper.ThrowTypeError(_engine, "Assignment to constant variable.");
+                    ExceptionHelper.ThrowTypeError(_engine.Realm, "Assignment to constant variable.");
                 }
                 }
             }
             }
         }
         }
@@ -134,7 +134,7 @@ namespace Jint.Runtime.Environments
 
 
         private void ThrowUninitializedBindingException()
         private void ThrowUninitializedBindingException()
         {
         {
-            throw new JavaScriptException(_engine.ReferenceError, "Can't access an uninitialized immutable binding.");
+            throw new JavaScriptException(_engine.Realm.Intrinsics.ReferenceError, "Can't access an uninitialized immutable binding.");
         }
         }
 
 
         public sealed override bool DeleteBinding(string name)
         public sealed override bool DeleteBinding(string name)
@@ -154,7 +154,7 @@ namespace Jint.Runtime.Environments
 
 
             return true;
             return true;
         }
         }
-        
+
         public override bool HasThisBinding() => false;
         public override bool HasThisBinding() => false;
 
 
         public override bool HasSuperBinding() => false;
         public override bool HasSuperBinding() => false;

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

@@ -6,7 +6,7 @@ namespace Jint.Runtime.Environments
 {
 {
     /// <summary>
     /// <summary>
     /// Base implementation of an Environment Record
     /// Base implementation of an Environment Record
-    /// http://www.ecma-international.org/ecma-262/5.1/#sec-10.2.1
+    /// https://tc39.es/ecma262/#sec-environment-records
     /// </summary>
     /// </summary>
     public abstract class EnvironmentRecord : JsValue
     public abstract class EnvironmentRecord : JsValue
     {
     {
@@ -91,12 +91,14 @@ namespace Jint.Runtime.Environments
 
 
         public override object ToObject()
         public override object ToObject()
         {
         {
-            return ExceptionHelper.ThrowNotSupportedException<object>();
+            ExceptionHelper.ThrowNotSupportedException();
+            return null;
         }
         }
 
 
         public override bool Equals(JsValue other)
         public override bool Equals(JsValue other)
         {
         {
-            return ExceptionHelper.ThrowNotSupportedException<bool>();
+            ExceptionHelper.ThrowNotSupportedException();
+            return false;
         }
         }
 
 
         public abstract JsValue GetThisBinding();
         public abstract JsValue GetThisBinding();

+ 17 - 5
Jint/Runtime/Environments/ExecutionContext.cs

@@ -1,28 +1,40 @@
-#nullable enable
+using Jint.Native.Function;
+
+#nullable enable
 
 
 namespace Jint.Runtime.Environments
 namespace Jint.Runtime.Environments
 {
 {
-    public readonly struct ExecutionContext
+    internal readonly struct ExecutionContext
     {
     {
         internal ExecutionContext(
         internal ExecutionContext(
             EnvironmentRecord lexicalEnvironment,
             EnvironmentRecord lexicalEnvironment,
-            EnvironmentRecord variableEnvironment)
+            EnvironmentRecord variableEnvironment,
+            PrivateEnvironmentRecord? privateEnvironment,
+            Realm realm,
+            FunctionInstance? function = null)
         {
         {
             LexicalEnvironment = lexicalEnvironment;
             LexicalEnvironment = lexicalEnvironment;
             VariableEnvironment = variableEnvironment;
             VariableEnvironment = variableEnvironment;
+            PrivateEnvironment = privateEnvironment;
+            Realm = realm;
+            Function = function;
         }
         }
 
 
         public readonly EnvironmentRecord LexicalEnvironment;
         public readonly EnvironmentRecord LexicalEnvironment;
+
         public readonly EnvironmentRecord VariableEnvironment;
         public readonly EnvironmentRecord VariableEnvironment;
+        public readonly PrivateEnvironmentRecord? PrivateEnvironment;
+        public readonly Realm Realm;
+        public readonly FunctionInstance? Function;
 
 
         public ExecutionContext UpdateLexicalEnvironment(EnvironmentRecord lexicalEnvironment)
         public ExecutionContext UpdateLexicalEnvironment(EnvironmentRecord lexicalEnvironment)
         {
         {
-            return new ExecutionContext(lexicalEnvironment, VariableEnvironment);
+            return new ExecutionContext(lexicalEnvironment, VariableEnvironment, PrivateEnvironment, Realm, Function);
         }
         }
 
 
         public ExecutionContext UpdateVariableEnvironment(EnvironmentRecord variableEnvironment)
         public ExecutionContext UpdateVariableEnvironment(EnvironmentRecord variableEnvironment)
         {
         {
-            return new ExecutionContext(LexicalEnvironment, variableEnvironment);
+            return new ExecutionContext(LexicalEnvironment, variableEnvironment, PrivateEnvironment, Realm, Function);
         }
         }
 
 
         /// <summary>
         /// <summary>

+ 30 - 25
Jint/Runtime/Environments/FunctionEnvironmentRecord.cs

@@ -27,7 +27,7 @@ namespace Jint.Runtime.Environments
         internal readonly FunctionInstance _functionObject;
         internal readonly FunctionInstance _functionObject;
 
 
         public FunctionEnvironmentRecord(
         public FunctionEnvironmentRecord(
-            Engine engine, 
+            Engine engine,
             FunctionInstance functionObject,
             FunctionInstance functionObject,
             JsValue newTarget) : base(engine)
             JsValue newTarget) : base(engine)
         {
         {
@@ -46,14 +46,14 @@ namespace Jint.Runtime.Environments
 
 
         public override bool HasThisBinding() => _thisBindingStatus != ThisBindingStatus.Lexical;
         public override bool HasThisBinding() => _thisBindingStatus != ThisBindingStatus.Lexical;
 
 
-        public override bool HasSuperBinding() => 
+        public override bool HasSuperBinding() =>
             _thisBindingStatus != ThisBindingStatus.Lexical && !_functionObject._homeObject.IsUndefined();
             _thisBindingStatus != ThisBindingStatus.Lexical && !_functionObject._homeObject.IsUndefined();
 
 
         public JsValue BindThisValue(JsValue value)
         public JsValue BindThisValue(JsValue value)
         {
         {
             if (_thisBindingStatus == ThisBindingStatus.Initialized)
             if (_thisBindingStatus == ThisBindingStatus.Initialized)
             {
             {
-                ExceptionHelper.ThrowReferenceError<JsValue>(_engine);
+                ExceptionHelper.ThrowReferenceError(_functionObject._realm, (string) null);
             }
             }
             _thisValue = value;
             _thisValue = value;
             _thisBindingStatus = ThisBindingStatus.Initialized;
             _thisBindingStatus = ThisBindingStatus.Initialized;
@@ -62,15 +62,19 @@ namespace Jint.Runtime.Environments
 
 
         public override JsValue GetThisBinding()
         public override JsValue GetThisBinding()
         {
         {
-            return _thisBindingStatus == ThisBindingStatus.Uninitialized 
-                ? ExceptionHelper.ThrowReferenceError<JsValue>(_engine)
-                : _thisValue;
+            if (_thisBindingStatus != ThisBindingStatus.Uninitialized)
+            {
+                return _thisValue;
+            }
+
+            ExceptionHelper.ThrowReferenceError(_engine.ExecutionContext.Realm, (string) null);
+            return null;
         }
         }
 
 
         public JsValue GetSuperBase()
         public JsValue GetSuperBase()
         {
         {
             var home = _functionObject._homeObject;
             var home = _functionObject._homeObject;
-            return home.IsUndefined() 
+            return home.IsUndefined()
                 ? Undefined
                 ? Undefined
                 : ((ObjectInstance) home).GetPrototypeOf();
                 : ((ObjectInstance) home).GetPrototypeOf();
         }
         }
@@ -79,7 +83,7 @@ namespace Jint.Runtime.Environments
 
 
         internal void InitializeParameters(
         internal void InitializeParameters(
             Key[] parameterNames,
             Key[] parameterNames,
-            bool hasDuplicates, 
+            bool hasDuplicates,
             JsValue[] arguments)
             JsValue[] arguments)
         {
         {
             var value = hasDuplicates ? Undefined : null;
             var value = hasDuplicates ? Undefined : null;
@@ -99,7 +103,7 @@ namespace Jint.Runtime.Environments
                 }
                 }
             }
             }
         }
         }
-        
+
         internal void AddFunctionParameters(IFunction functionDeclaration, JsValue[] arguments)
         internal void AddFunctionParameters(IFunction functionDeclaration, JsValue[] arguments)
         {
         {
             bool empty = _dictionary.Count == 0;
             bool empty = _dictionary.Count == 0;
@@ -110,7 +114,7 @@ namespace Jint.Runtime.Environments
                 SetFunctionParameter(parameters[i], arguments, i, empty);
                 SetFunctionParameter(parameters[i], arguments, i, empty);
             }
             }
         }
         }
-        
+
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         private void SetFunctionParameter(
         private void SetFunctionParameter(
             Node parameter,
             Node parameter,
@@ -163,7 +167,7 @@ namespace Jint.Runtime.Environments
         {
         {
             if (argument.IsNullOrUndefined())
             if (argument.IsNullOrUndefined())
             {
             {
-                ExceptionHelper.ThrowTypeError(_engine, "Destructed parameter is null or undefined");
+                ExceptionHelper.ThrowTypeError(_functionObject._realm, "Destructed parameter is null or undefined");
             }
             }
 
 
             if (!argument.IsObject())
             if (!argument.IsObject())
@@ -183,13 +187,14 @@ namespace Jint.Runtime.Environments
             {
             {
                 var oldEnv = _engine.ExecutionContext.LexicalEnvironment;
                 var oldEnv = _engine.ExecutionContext.LexicalEnvironment;
                 var paramVarEnv = JintEnvironment.NewDeclarativeEnvironment(_engine, oldEnv);
                 var paramVarEnv = JintEnvironment.NewDeclarativeEnvironment(_engine, oldEnv);
-                _engine.EnterExecutionContext(paramVarEnv, paramVarEnv);
+                PrivateEnvironmentRecord privateEnvironment = null; // TODO PRIVATE check when implemented
+                _engine.EnterExecutionContext(paramVarEnv, paramVarEnv, _engine.ExecutionContext.Realm, privateEnvironment);
 
 
                 try
                 try
                 {
                 {
                     if (property is Property p)
                     if (property is Property p)
                     {
                     {
-                        JsString propertyName;
+                        JsString propertyName = JsString.Empty;
                         if (p.Key is Identifier propertyIdentifier)
                         if (p.Key is Identifier propertyIdentifier)
                         {
                         {
                             propertyName = JsString.Create(propertyIdentifier.Name);
                             propertyName = JsString.Create(propertyIdentifier.Name);
@@ -206,7 +211,7 @@ namespace Jint.Runtime.Environments
                         }
                         }
                         else
                         else
                         {
                         {
-                            propertyName = ExceptionHelper.ThrowArgumentOutOfRangeException<JsString>("property", "unknown object pattern property type");
+                            ExceptionHelper.ThrowArgumentOutOfRangeException("property", "unknown object pattern property type");
                         }
                         }
 
 
                         processedProperties?.Add(propertyName.ToString());
                         processedProperties?.Add(propertyName.ToString());
@@ -217,13 +222,13 @@ namespace Jint.Runtime.Environments
                     {
                     {
                         if (((RestElement) property).Argument is Identifier restIdentifier)
                         if (((RestElement) property).Argument is Identifier restIdentifier)
                         {
                         {
-                            var rest = _engine.Object.Construct(argumentObject.Properties.Count - processedProperties.Count);
+                            var rest = _engine.Realm.Intrinsics.Object.Construct(argumentObject.Properties.Count - processedProperties.Count);
                             argumentObject.CopyDataProperties(rest, processedProperties);
                             argumentObject.CopyDataProperties(rest, processedProperties);
                             SetItemSafely(restIdentifier.Name, rest, initiallyEmpty);
                             SetItemSafely(restIdentifier.Name, rest, initiallyEmpty);
                         }
                         }
                         else
                         else
                         {
                         {
-                            ExceptionHelper.ThrowSyntaxError(_engine, "Object rest parameter can only be objects");
+                            ExceptionHelper.ThrowSyntaxError(_functionObject._realm, "Object rest parameter can only be objects");
                         }
                         }
                     }
                     }
                 }
                 }
@@ -240,7 +245,7 @@ namespace Jint.Runtime.Environments
         {
         {
             if (argument.IsNull())
             if (argument.IsNull())
             {
             {
-                ExceptionHelper.ThrowTypeError(_engine, "Destructed parameter is null");
+                ExceptionHelper.ThrowTypeError(_functionObject._realm, "Destructed parameter is null");
             }
             }
 
 
             ArrayInstance array = null;
             ArrayInstance array = null;
@@ -249,9 +254,9 @@ namespace Jint.Runtime.Environments
             {
             {
                 array = argument.AsArray();
                 array = argument.AsArray();
             }
             }
-            else if (argument.IsObject() && argument.TryGetIterator(_engine, out var iterator))
+            else if (argument.IsObject() && argument.TryGetIterator(_functionObject._realm, out var iterator))
             {
             {
-                array = _engine.Array.ConstructFast(0);
+                array = _engine.Realm.Intrinsics.Array.ConstructFast(0);
                 var protocol = new ArrayPatternProtocol(_engine, array, iterator, arrayPattern.Elements.Count);
                 var protocol = new ArrayPatternProtocol(_engine, array, iterator, arrayPattern.Elements.Count);
                 protocol.Execute();
                 protocol.Execute();
             }
             }
@@ -282,7 +287,7 @@ namespace Jint.Runtime.Environments
             int restCount = arguments.Length - (index + 1) + 1;
             int restCount = arguments.Length - (index + 1) + 1;
             uint count = restCount > 0 ? (uint) restCount : 0;
             uint count = restCount > 0 ? (uint) restCount : 0;
 
 
-            var rest = _engine.Array.ConstructFast(count);
+            var rest = _engine.Realm.Intrinsics.Array.ConstructFast(count);
 
 
             uint targetIndex = 0;
             uint targetIndex = 0;
             for (var argIndex = index; argIndex < arguments.Length; ++argIndex)
             for (var argIndex = index; argIndex < arguments.Length; ++argIndex)
@@ -303,7 +308,7 @@ namespace Jint.Runtime.Environments
             }
             }
             else
             else
             {
             {
-                ExceptionHelper.ThrowSyntaxError(_engine, "Rest parameters can only be identifiers or arrays");
+                ExceptionHelper.ThrowSyntaxError(_functionObject._realm, "Rest parameters can only be identifiers or arrays");
             }
             }
         }
         }
 
 
@@ -318,7 +323,7 @@ namespace Jint.Runtime.Environments
                 && right is Identifier idRight
                 && right is Identifier idRight
                 && idLeft.Name == idRight.Name)
                 && idLeft.Name == idRight.Name)
             {
             {
-                ExceptionHelper.ThrowReferenceError(_engine, idRight.Name);
+                ExceptionHelper.ThrowReferenceError(_functionObject._realm, idRight.Name);
             }
             }
 
 
             if (argument.IsUndefined())
             if (argument.IsUndefined())
@@ -329,7 +334,7 @@ namespace Jint.Runtime.Environments
                 var oldEnv = _engine.ExecutionContext.LexicalEnvironment;
                 var oldEnv = _engine.ExecutionContext.LexicalEnvironment;
                 var paramVarEnv = JintEnvironment.NewDeclarativeEnvironment(_engine, oldEnv);
                 var paramVarEnv = JintEnvironment.NewDeclarativeEnvironment(_engine, oldEnv);
 
 
-                _engine.EnterExecutionContext(paramVarEnv, paramVarEnv);
+                _engine.EnterExecutionContext(new ExecutionContext(paramVarEnv, paramVarEnv, null, _engine.Realm, null));
                 try
                 try
                 {
                 {
                     argument = jintExpression.GetValue();
                     argument = jintExpression.GetValue();
@@ -363,7 +368,7 @@ namespace Jint.Runtime.Environments
                 SetItemCheckExisting(name, argument);
                 SetItemCheckExisting(name, argument);
             }
             }
         }
         }
-        
+
         private void SetItemCheckExisting(Key name, JsValue argument)
         private void SetItemCheckExisting(Key name, JsValue argument)
         {
         {
             if (!_dictionary.TryGetValue(name, out var existing))
             if (!_dictionary.TryGetValue(name, out var existing))
@@ -378,7 +383,7 @@ namespace Jint.Runtime.Environments
                 }
                 }
                 else
                 else
                 {
                 {
-                    ExceptionHelper.ThrowTypeError(_engine, "Can't update the value of an immutable binding.");
+                    ExceptionHelper.ThrowTypeError(_functionObject._realm, "Can't update the value of an immutable binding.");
                 }
                 }
             }
             }
         }
         }

+ 21 - 15
Jint/Runtime/Environments/GlobalEnvironmentRecord.cs

@@ -9,16 +9,16 @@ using Jint.Runtime.Descriptors;
 namespace Jint.Runtime.Environments
 namespace Jint.Runtime.Environments
 {
 {
     /// <summary>
     /// <summary>
-    ///     http://www.ecma-international.org/ecma-262/6.0/#sec-global-environment-records
+    /// https://tc39.es/ecma262/#sec-global-environment-records
     /// </summary>
     /// </summary>
-    internal sealed class GlobalEnvironmentRecord : EnvironmentRecord
+    public sealed class GlobalEnvironmentRecord : EnvironmentRecord
     {
     {
-        private readonly GlobalObject _global;
+        private readonly ObjectInstance _global;
         private readonly DeclarativeEnvironmentRecord _declarativeRecord;
         private readonly DeclarativeEnvironmentRecord _declarativeRecord;
         private readonly ObjectEnvironmentRecord _objectRecord;
         private readonly ObjectEnvironmentRecord _objectRecord;
         private readonly HashSet<string> _varNames = new HashSet<string>();
         private readonly HashSet<string> _varNames = new HashSet<string>();
 
 
-        public GlobalEnvironmentRecord(Engine engine, GlobalObject global) : base(engine)
+        public GlobalEnvironmentRecord(Engine engine, ObjectInstance global) : base(engine)
         {
         {
             _global = global;
             _global = global;
             _objectRecord = new ObjectEnvironmentRecord(engine, global, provideThis: false, withEnvironment: false);
             _objectRecord = new ObjectEnvironmentRecord(engine, global, provideThis: false, withEnvironment: false);
@@ -58,7 +58,7 @@ namespace Jint.Runtime.Environments
 
 
             return TryGetBindingForGlobalParent(name, out value, property);
             return TryGetBindingForGlobalParent(name, out value, property);
         }
         }
-        
+
         [MethodImpl(MethodImplOptions.NoInlining)]
         [MethodImpl(MethodImplOptions.NoInlining)]
         private bool TryGetBindingForGlobalParent(
         private bool TryGetBindingForGlobalParent(
             in BindingName name,
             in BindingName name,
@@ -89,7 +89,7 @@ namespace Jint.Runtime.Environments
         {
         {
             if (_declarativeRecord._hasBindings && _declarativeRecord.HasBinding(name))
             if (_declarativeRecord._hasBindings && _declarativeRecord.HasBinding(name))
             {
             {
-                ExceptionHelper.ThrowTypeError(_engine, name + " has already been declared");
+                ExceptionHelper.ThrowTypeError(_engine.Realm, name + " has already been declared");
             }
             }
 
 
             _declarativeRecord.CreateMutableBinding(name, canBeDeleted);
             _declarativeRecord.CreateMutableBinding(name, canBeDeleted);
@@ -99,7 +99,7 @@ namespace Jint.Runtime.Environments
         {
         {
             if (_declarativeRecord._hasBindings && _declarativeRecord.HasBinding(name))
             if (_declarativeRecord._hasBindings && _declarativeRecord.HasBinding(name))
             {
             {
-                ExceptionHelper.ThrowTypeError(_engine, name + " has already been declared");
+                ExceptionHelper.ThrowTypeError(_engine.Realm, name + " has already been declared");
             }
             }
 
 
             _declarativeRecord.CreateImmutableBinding(name, strict);
             _declarativeRecord.CreateImmutableBinding(name, strict);
@@ -115,7 +115,7 @@ namespace Jint.Runtime.Environments
             {
             {
                 if (!_global.Set(name, value))
                 if (!_global.Set(name, value))
                 {
                 {
-                    ExceptionHelper.ThrowTypeError(_engine);
+                    ExceptionHelper.ThrowTypeError(_engine.Realm);
                 }
                 }
             }
             }
         }
         }
@@ -129,10 +129,10 @@ namespace Jint.Runtime.Environments
             else
             else
             {
             {
                 // fast inlined path as we know we target global, otherwise would be
                 // fast inlined path as we know we target global, otherwise would be
-                // _objectRecord.SetMutableBinding(name, value, strict); 
+                // _objectRecord.SetMutableBinding(name, value, strict);
                 if (!_global.Set(name, value) && strict)
                 if (!_global.Set(name, value) && strict)
                 {
                 {
-                    ExceptionHelper.ThrowTypeError(_engine);
+                    ExceptionHelper.ThrowTypeError(_engine.Realm);
                 }
                 }
             }
             }
         }
         }
@@ -145,11 +145,17 @@ namespace Jint.Runtime.Environments
             }
             }
             else
             else
             {
             {
-                // fast inlined path as we know we target global, otherwise would be
-                // _objectRecord.SetMutableBinding(name, value, strict); 
-                if (!_global.Set(name.Key, value) && strict)
+                if (_global is GlobalObject globalObject)
+                {
+                    // fast inlined path as we know we target global
+                    if (!globalObject.Set(name.Key, value) && strict)
+                    {
+                        ExceptionHelper.ThrowTypeError(_engine.Realm);
+                    }
+                }
+                else
                 {
                 {
-                    ExceptionHelper.ThrowTypeError(_engine);
+                    _objectRecord.SetMutableBinding(name, value ,strict);
                 }
                 }
             }
             }
         }
         }
@@ -235,7 +241,7 @@ namespace Jint.Runtime.Environments
 
 
         public bool CanDeclareGlobalFunction(string name)
         public bool CanDeclareGlobalFunction(string name)
         {
         {
-            if (!_global._properties.TryGetValue(name, out var existingProp) 
+            if (!_global._properties.TryGetValue(name, out var existingProp)
                 || existingProp == PropertyDescriptor.Undefined)
                 || existingProp == PropertyDescriptor.Undefined)
             {
             {
                 return _global.Extensible;
                 return _global.Extensible;

+ 10 - 3
Jint/Runtime/Environments/JintEnvironment.cs

@@ -2,7 +2,6 @@
 
 
 using Jint.Native;
 using Jint.Native;
 using Jint.Native.Function;
 using Jint.Native.Function;
-using Jint.Native.Global;
 using Jint.Native.Object;
 using Jint.Native.Object;
 
 
 namespace Jint.Runtime.Environments
 namespace Jint.Runtime.Environments
@@ -20,7 +19,7 @@ namespace Jint.Runtime.Environments
             record = default;
             record = default;
             value = default;
             value = default;
 
 
-            if (ReferenceEquals(lex, engine.GlobalEnvironment)
+            if (ReferenceEquals(lex, engine.Realm.GlobalEnv)
                 && lex.TryGetBinding(name, strict, out _, out value))
                 && lex.TryGetBinding(name, strict, out _, out value))
             {
             {
                 record = lex;
                 record = lex;
@@ -70,7 +69,7 @@ namespace Jint.Runtime.Environments
         /// <summary>
         /// <summary>
         /// https://tc39.es/ecma262/#sec-newglobalenvironment
         /// https://tc39.es/ecma262/#sec-newglobalenvironment
         /// </summary>
         /// </summary>
-        internal static GlobalEnvironmentRecord NewGlobalEnvironment(Engine engine, GlobalObject objectInstance, JsValue thisValue)
+        internal static GlobalEnvironmentRecord NewGlobalEnvironment(Engine engine, ObjectInstance objectInstance, JsValue thisValue)
         {
         {
             return new GlobalEnvironmentRecord(engine, objectInstance)
             return new GlobalEnvironmentRecord(engine, objectInstance)
             {
             {
@@ -88,5 +87,13 @@ namespace Jint.Runtime.Environments
                 _outerEnv = outer
                 _outerEnv = outer
             };
             };
         } 
         } 
+
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-newprivateenvironment
+        /// </summary>
+        internal static PrivateEnvironmentRecord NewPrivateEnvironment(Engine engine, PrivateEnvironmentRecord outerPriv)
+        {
+            return new PrivateEnvironmentRecord(outerPriv);
+        } 
     }
     }
 }
 }

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

@@ -8,7 +8,7 @@ namespace Jint.Runtime.Environments
 {
 {
     /// <summary>
     /// <summary>
     /// Represents an object environment record
     /// Represents an object environment record
-    /// http://www.ecma-international.org/ecma-262/5.1/#sec-10.2.1.2
+    /// https://tc39.es/ecma262/#sec-object-environment-records
     /// </summary>
     /// </summary>
     internal sealed class ObjectEnvironmentRecord : EnvironmentRecord
     internal sealed class ObjectEnvironmentRecord : EnvironmentRecord
     {
     {
@@ -18,8 +18,8 @@ namespace Jint.Runtime.Environments
 
 
         public ObjectEnvironmentRecord(
         public ObjectEnvironmentRecord(
             Engine engine,
             Engine engine,
-            ObjectInstance bindingObject, 
-            bool provideThis, 
+            ObjectInstance bindingObject,
+            bool provideThis,
             bool withEnvironment) : base(engine)
             bool withEnvironment) : base(engine)
         {
         {
             _bindingObject = bindingObject;
             _bindingObject = bindingObject;
@@ -41,7 +41,7 @@ namespace Jint.Runtime.Environments
             {
             {
                 return true;
                 return true;
             }
             }
-            
+
             return !IsBlocked(name);
             return !IsBlocked(name);
         }
         }
 
 
@@ -101,8 +101,8 @@ namespace Jint.Runtime.Environments
                 : new PropertyDescriptor(Undefined, PropertyFlag.NonConfigurable | PropertyFlag.MutableBinding);
                 : new PropertyDescriptor(Undefined, PropertyFlag.NonConfigurable | PropertyFlag.MutableBinding);
 
 
             _bindingObject.DefinePropertyOrThrow(name, propertyDescriptor);
             _bindingObject.DefinePropertyOrThrow(name, propertyDescriptor);
-        }  
-        
+        }
+
         /// <summary>
         /// <summary>
         /// http://www.ecma-international.org/ecma-262/6.0/#sec-object-environment-records-createmutablebinding-n-d
         /// http://www.ecma-international.org/ecma-262/6.0/#sec-object-environment-records-createmutablebinding-n-d
         /// </summary>
         /// </summary>
@@ -114,7 +114,7 @@ namespace Jint.Runtime.Environments
 
 
             _bindingObject.DefinePropertyOrThrow(name, propertyDescriptor);
             _bindingObject.DefinePropertyOrThrow(name, propertyDescriptor);
         }
         }
-        
+
         /// <summary>
         /// <summary>
         ///  http://www.ecma-international.org/ecma-262/6.0/#sec-object-environment-records-createimmutablebinding-n-s
         ///  http://www.ecma-international.org/ecma-262/6.0/#sec-object-environment-records-createimmutablebinding-n-s
         /// </summary>
         /// </summary>
@@ -140,7 +140,7 @@ namespace Jint.Runtime.Environments
         {
         {
             if (!_bindingObject.Set(name.StringValue, value) && strict)
             if (!_bindingObject.Set(name.StringValue, value) && strict)
             {
             {
-                ExceptionHelper.ThrowTypeError(_engine);
+                ExceptionHelper.ThrowTypeError(_engine.Realm);
             }
             }
         }
         }
 
 
@@ -149,7 +149,7 @@ namespace Jint.Runtime.Environments
             var desc = _bindingObject.GetProperty(name);
             var desc = _bindingObject.GetProperty(name);
             if (strict && desc == PropertyDescriptor.Undefined)
             if (strict && desc == PropertyDescriptor.Undefined)
             {
             {
-                ExceptionHelper.ThrowReferenceError(_engine, name.ToString());
+                ExceptionHelper.ThrowReferenceError(_engine.Realm, name.ToString());
             }
             }
 
 
             return ObjectInstance.UnwrapJsValue(desc, this);
             return ObjectInstance.UnwrapJsValue(desc, this);

+ 47 - 0
Jint/Runtime/Environments/PrivateEnvironmentRecord.cs

@@ -0,0 +1,47 @@
+using System.Collections.Generic;
+
+namespace Jint.Runtime.Environments
+{
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-privateenvironment-records
+    /// </summary>
+    internal sealed class PrivateEnvironmentRecord
+    {
+        private readonly PrivateEnvironmentRecord _outerPrivateEnvironment;
+        private List<PrivateName> _names = new List<PrivateName>();
+
+        private readonly struct PrivateName
+        {
+            public PrivateName(string name, string description)
+            {
+                Name = name;
+                Description = description;
+            }
+
+            public readonly string Name;
+            public readonly string Description;
+        }
+
+        public PrivateEnvironmentRecord(PrivateEnvironmentRecord outerPrivEnv)
+        {
+            _outerPrivateEnvironment = outerPrivEnv;
+        }
+
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-resolve-private-identifier
+        /// </summary>
+        public string ResolvePrivateIdentifier(string identifier)
+        {
+            var names = _names;
+            foreach (var privateName in names)
+            {
+                if (privateName.Description == identifier)
+                {
+                    return privateName.Name;
+                }
+            }
+
+            return _outerPrivateEnvironment.ResolvePrivateIdentifier(identifier);
+        }
+    }
+}

+ 23 - 76
Jint/Runtime/ExceptionHelper.cs

@@ -9,22 +9,10 @@ namespace Jint.Runtime
 {
 {
     internal static class ExceptionHelper
     internal static class ExceptionHelper
     {
     {
-        public static T ThrowSyntaxError<T>(Engine engine, string message = null)
-        {
-            ThrowSyntaxError(engine, message);
-            return default;
-        }
-
         [DoesNotReturn]
         [DoesNotReturn]
-        public static void ThrowSyntaxError(Engine engine, string message = null)
-        {
-            throw new JavaScriptException(engine.SyntaxError, message);
-        }
-
-        public static T ThrowArgumentException<T>(string message = null)
+        public static void ThrowSyntaxError(Realm realm, string message = null)
         {
         {
-            ThrowArgumentException(message);
-            return default;
+            throw new JavaScriptException(realm.Intrinsics.SyntaxError, message);
         }
         }
 
 
         [DoesNotReturn]
         [DoesNotReturn]
@@ -40,55 +28,40 @@ namespace Jint.Runtime
         }
         }
 
 
         [DoesNotReturn]
         [DoesNotReturn]
-        public static void ThrowReferenceError(Engine engine, Reference reference)
+        public static void ThrowReferenceError(Realm realm, Reference reference)
         {
         {
-            ThrowReferenceError(engine, reference?.GetReferencedName()?.ToString());
+            ThrowReferenceError(realm, reference?.GetReferencedName()?.ToString());
         }
         }
 
 
         [DoesNotReturn]
         [DoesNotReturn]
-        public static void ThrowReferenceError(Engine engine, string name)
+        public static void ThrowReferenceError(Realm realm, string name)
         {
         {
             var message = name != null ? name + " is not defined" : null;
             var message = name != null ? name + " is not defined" : null;
-            throw new JavaScriptException(engine.ReferenceError, message);
+            throw new JavaScriptException(realm.Intrinsics.ReferenceError, message);
         }
         }
 
 
-        public static T ThrowTypeErrorNoEngine<T>(string message = null, Exception exception = null)
+        [DoesNotReturn]
+        public static void ThrowTypeErrorNoEngine(string message = null, Exception exception = null)
         {
         {
             throw new TypeErrorException(message);
             throw new TypeErrorException(message);
         }
         }
 
 
-        public static T ThrowReferenceError<T>(Engine engine, string message = null)
-        {
-            throw new JavaScriptException(engine.ReferenceError, message);
-        }
-
-        public static T ThrowTypeError<T>(Engine engine, string message = null, Exception exception = null)
-        {
-            ThrowTypeError(engine, message, exception);
-            return default;
-        }
-
         [DoesNotReturn]
         [DoesNotReturn]
-        public static void ThrowTypeError(Engine engine, string message = null, Exception exception = null)
-        {
-            throw new JavaScriptException(engine.TypeError, message, exception);
-        }
-
-        public static T ThrowRangeError<T>(Engine engine, string message = null)
+        public static void ThrowTypeError(Realm realm, string message = null, Exception exception = null)
         {
         {
-            throw new JavaScriptException(engine.RangeError, message);
+            throw new JavaScriptException(realm.Intrinsics.TypeError, message, exception);
         }
         }
 
 
         [DoesNotReturn]
         [DoesNotReturn]
-        public static void ThrowRangeError(Engine engine, string message = null)
+        public static void ThrowRangeError(Realm realm, string message = null)
         {
         {
-            throw new JavaScriptException(engine.RangeError, message);
+            throw new JavaScriptException(realm.Intrinsics.RangeError, message);
         }
         }
 
 
         [DoesNotReturn]
         [DoesNotReturn]
-        public static void ThrowUriError(Engine engine)
+        public static void ThrowUriError(Realm realm)
         {
         {
-            throw new JavaScriptException(engine.UriError);
+            throw new JavaScriptException(realm.Intrinsics.UriError);
         }
         }
 
 
         [DoesNotReturn]
         [DoesNotReturn]
@@ -97,21 +70,6 @@ namespace Jint.Runtime
             throw new NotImplementedException(message);
             throw new NotImplementedException(message);
         }
         }
 
 
-        public static T ThrowNotImplementedException<T>()
-        {
-            throw new NotImplementedException();
-        }
-
-        public static T ThrowArgumentOutOfRangeException<T>()
-        {
-            throw new ArgumentOutOfRangeException();
-        }
-
-        public static T ThrowArgumentOutOfRangeException<T>(string paramName, string message)
-        {
-            throw new ArgumentOutOfRangeException(paramName, message);
-        }
-
         [DoesNotReturn]
         [DoesNotReturn]
         public static void ThrowArgumentOutOfRangeException(string paramName, string message)
         public static void ThrowArgumentOutOfRangeException(string paramName, string message)
         {
         {
@@ -136,11 +94,6 @@ namespace Jint.Runtime
             throw new ArgumentOutOfRangeException();
             throw new ArgumentOutOfRangeException();
         }
         }
 
 
-        public static T ThrowNotSupportedException<T>(string message = null)
-        {
-            throw new NotSupportedException(message);
-        }
-
         [DoesNotReturn]
         [DoesNotReturn]
         public static void ThrowNotSupportedException(string message = null)
         public static void ThrowNotSupportedException(string message = null)
         {
         {
@@ -152,13 +105,9 @@ namespace Jint.Runtime
         {
         {
             throw new InvalidOperationException(message);
             throw new InvalidOperationException(message);
         }
         }
-        
-        public static T ThrowInvalidOperationException<T>(string message = null)
-        {
-            throw new InvalidOperationException(message);
-        }
-        
-        public static T ThrowPromiseRejectedException<T>(JsValue error)
+
+        [DoesNotReturn]
+        public static void ThrowPromiseRejectedException(JsValue error)
         {
         {
             throw new PromiseRejectedException(error);
             throw new PromiseRejectedException(error);
         }
         }
@@ -170,7 +119,8 @@ namespace Jint.Runtime
         }
         }
 
 
         [DoesNotReturn]
         [DoesNotReturn]
-        public static void ThrowRecursionDepthOverflowException(JintCallStack currentStack, string currentExpressionReference)
+        public static void ThrowRecursionDepthOverflowException(JintCallStack currentStack,
+            string currentExpressionReference)
         {
         {
             throw new RecursionDepthOverflowException(currentStack, currentExpressionReference);
             throw new RecursionDepthOverflowException(currentStack, currentExpressionReference);
         }
         }
@@ -181,11 +131,6 @@ namespace Jint.Runtime
             throw new ArgumentNullException(paramName);
             throw new ArgumentNullException(paramName);
         }
         }
 
 
-        public static T ThrowArgumentNullException<T>(string paramName)
-        {
-            throw new ArgumentNullException(paramName);
-        }
-
         [DoesNotReturn]
         [DoesNotReturn]
         public static void ThrowMeaningfulException(Engine engine, TargetInvocationException exception)
         public static void ThrowMeaningfulException(Engine engine, TargetInvocationException exception)
         {
         {
@@ -193,15 +138,17 @@ namespace Jint.Runtime
 
 
             var handler = engine.Options._ClrExceptionsHandler;
             var handler = engine.Options._ClrExceptionsHandler;
             if (handler != null && handler(meaningfulException))
             if (handler != null && handler(meaningfulException))
+            {
                 ThrowError(engine, meaningfulException.Message);
                 ThrowError(engine, meaningfulException.Message);
+            }
 
 
             throw meaningfulException;
             throw meaningfulException;
         }
         }
 
 
         [DoesNotReturn]
         [DoesNotReturn]
-        public static void ThrowError(Engine engine, string message)
+        private static void ThrowError(Engine engine, string message)
         {
         {
-            throw new JavaScriptException(engine.Error, message);
+            throw new JavaScriptException(engine.Realm.Intrinsics.Error, message);
         }
         }
 
 
         [DoesNotReturn]
         [DoesNotReturn]

+ 96 - 0
Jint/Runtime/Host.cs

@@ -0,0 +1,96 @@
+using Jint.Native.Global;
+using Jint.Native.Object;
+using Jint.Runtime.Environments;
+
+namespace Jint.Runtime
+{
+    public class Host
+    {
+        protected Engine Engine { get; private set; }
+
+        /// <summary>
+        /// Initializes the host.
+        /// </summary>
+        public void Initialize(Engine engine)
+        {
+            Engine = engine;
+            InitializeHostDefinedRealm();
+            PostInitialize();
+        }
+
+        protected virtual void PostInitialize()
+        {
+        }
+
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-initializehostdefinedrealm
+        /// </summary>
+        protected virtual void InitializeHostDefinedRealm()
+        {
+            var realm = CreateRealm();
+
+            var newContext = new ExecutionContext(
+                lexicalEnvironment: realm.GlobalEnv,
+                variableEnvironment: realm.GlobalEnv,
+                privateEnvironment: null,
+                realm: realm,
+                function: null);
+
+            Engine.EnterExecutionContext(newContext);
+        }
+
+        protected virtual GlobalEnvironmentRecord CreateGlobalEnvironment(ObjectInstance globalObject)
+        {
+            return JintEnvironment.NewGlobalEnvironment(Engine, globalObject, globalObject);
+        }
+
+        protected virtual ObjectInstance CreateGlobalObject(Realm realm)
+        {
+            var globalObject = new GlobalObject(Engine, realm);
+            // Because the properties might need some of the built-in object
+            // their configuration is delayed to a later step
+            // trigger initialization
+            globalObject.EnsureInitialized();
+            return globalObject;
+        }
+
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-createrealm
+        /// </summary>
+        protected internal virtual Realm CreateRealm()
+        {
+            var realmRec = new Realm();
+            Engine._realmInConstruction = realmRec;
+
+            CreateIntrinsics(realmRec);
+
+            var globalObject = CreateGlobalObject(realmRec);
+
+            var globalEnv = CreateGlobalEnvironment(globalObject);
+            realmRec.GlobalEnv = globalEnv;
+            realmRec.GlobalObject = globalObject;
+
+            Engine._realmInConstruction = null;
+
+            return realmRec;
+        }
+
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-createintrinsics
+        /// </summary>
+        protected virtual void CreateIntrinsics(Realm realmRec)
+        {
+            var intrinsics = new Intrinsics(Engine, realmRec);
+            realmRec.Intrinsics = intrinsics;
+        }
+
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-hostensurecancompilestrings
+        /// </summary>
+        /// <param name="callerRealm"></param>
+        /// <param name="evalRealm"></param>
+        public virtual void EnsureCanCompileStrings(Realm callerRealm, Realm evalRealm)
+        {
+        }
+    }
+}

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

@@ -19,12 +19,12 @@ namespace Jint.Runtime.Interop
             Func<JsValue, JsValue[], JsValue> func,
             Func<JsValue, JsValue[], JsValue> func,
             int length = 0,
             int length = 0,
             PropertyFlag lengthFlags = PropertyFlag.AllForbidden)
             PropertyFlag lengthFlags = PropertyFlag.AllForbidden)
-            : base(engine, name != null ? new JsString(name) : null)
+            : base(engine, engine.Realm, name != null ? new JsString(name) : null)
         {
         {
             _name = name;
             _name = name;
             _func = func;
             _func = func;
 
 
-            _prototype = engine.Function.PrototypeObject;
+            _prototype = engine._originalIntrinsics.Function.PrototypeObject;
 
 
             _length = lengthFlags == PropertyFlag.AllForbidden
             _length = lengthFlags == PropertyFlag.AllForbidden
                 ? PropertyDescriptor.AllForbiddenDescriptor.ForNumber(length)
                 ? PropertyDescriptor.AllForbiddenDescriptor.ForNumber(length)
@@ -64,7 +64,7 @@ namespace Jint.Runtime.Interop
             {
             {
                 return true;
                 return true;
             }
             }
-            
+
             return false;
             return false;
         }
         }
 
 

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

@@ -16,11 +16,12 @@ namespace Jint.Runtime.Interop
         private readonly Delegate _d;
         private readonly Delegate _d;
         private readonly bool _delegateContainsParamsArgument;
         private readonly bool _delegateContainsParamsArgument;
 
 
-        public DelegateWrapper(Engine engine, Delegate d)
-            : base(engine, _name, FunctionThisMode.Global)
+        public DelegateWrapper(
+            Engine engine, Delegate d)
+            : base(engine, engine.Realm, _name, FunctionThisMode.Global)
         {
         {
             _d = d;
             _d = d;
-            _prototype = engine.Function.PrototypeObject;
+            _prototype = engine.Realm.Intrinsics.Function.PrototypeObject;
 
 
             var parameterInfos = _d.Method.GetParameters();
             var parameterInfos = _d.Method.GetParameters();
 
 

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

@@ -13,7 +13,7 @@ namespace Jint.Runtime.Interop
         private readonly Func<JsValue, JsValue> _getter;
         private readonly Func<JsValue, JsValue> _getter;
 
 
         public GetterFunctionInstance(Engine engine, Func<JsValue, JsValue> getter)
         public GetterFunctionInstance(Engine engine, Func<JsValue, JsValue> getter)
-            : base(engine, _name, FunctionThisMode.Global)
+            : base(engine, engine.Realm, _name, FunctionThisMode.Global)
         {
         {
             _getter = getter;
             _getter = getter;
         }
         }

Some files were not shown because too many files changed in this diff