Title: [284151] trunk
Revision
284151
Author
[email protected]
Date
2021-10-14 03:22:09 -0700 (Thu, 14 Oct 2021)

Log Message

JSTests:
Test coverage for JSC shadow realms implementation
https://bugs.webkit.org/show_bug.cgi?id=230602

Patch by Phillip Mates <[email protected]> on 2021-10-14
Reviewed by Yusuke Suzuki.

* modules/import-meta-syntax.js:
(shouldThrow):
* stress/eval-indirect.js: Added.
(shouldBe):
(shouldThrow):
* stress/import-syntax.js:
* stress/resources/shadow-realm-example-module.js: Added.
(putInGlobal):
(getFromGlobal):
(getAnObject):
(getCallCount):
* stress/shadow-realm-evaluate.js: Added.
(shouldBe):
(shouldThrow):
(assertionFn):
(shouldBe.String):
(shouldBe.globalObjectFor.doEval):
(shouldBe.globalObjectFor):
* stress/shadow-realm-import-value.js: Added.
(shouldBe):
(shouldThrow):
(async shouldThrowAsync):
(async const):
(doImport):
* stress/shadow-realm.js: Added.
(shouldBe):
(throw.new.Error):
* test262/config.yaml:

Source/_javascript_Core:
shadow realms implementation
https://bugs.webkit.org/show_bug.cgi?id=230602

Patch by Phillip Mates <[email protected]> on 2021-10-14
Reviewed by Yusuke Suzuki.

Implementation of the Shadow Realms proposal (stage 3 in TC39) [1]

Main APIs added are
 - `new ShadowRealm()`
   creates an object that has its own global object and module graph.
 - ShadowRealm.prototype.evaluate(sourceText)
   this allows for evaluating code in the context of the realm, which
   has its own module graph and global object.
 - ShadowRealm.prototype.importValue(specifier, exportName)
   this allows importing module exports in the the context of the
   realm, which has its own module graph and global object.

The main detail of the Shadow Realm implementation is that values
passed between realms must be either primitives or wrapped callables.
Wrapped callables themselves are callables that check that their
arguments and return values are also either primitives or wrapped
callables. This detail is implemented via JS builtins + a few new
intrinsics.

Can be enabled using `--useShadowRealm=true`

[1]: https://github.com/tc39/proposal-shadowrealm

* CMakeLists.txt:
* DerivedSources-input.xcfilelist:
* DerivedSources-output.xcfilelist:
* DerivedSources.make:
* _javascript_Core.xcodeproj/project.pbxproj:
* Sources.txt:
* builtins/BuiltinNames.h:
* builtins/ShadowRealmPrototype.js: Added.
(globalPrivate.wrap.wrapped):
(globalPrivate.wrap):
(evaluate):
(importValue):
* bytecode/BytecodeIntrinsicRegistry.h:
* bytecode/LinkTimeConstant.h:
* bytecompiler/BytecodeGenerator.h:
(JSC::BytecodeGenerator::emitIsShadowRealm):
* bytecompiler/NodesCodegen.cpp:
* jsc.cpp:
(JSC_DEFINE_HOST_FUNCTION):
* parser/Parser.cpp:
(JSC::Parser<LexerType>::parseMemberExpression):
* runtime/CommonIdentifiers.h:
* runtime/IndirectEvalExecutable.cpp:
(JSC::IndirectEvalExecutable::createImpl):
(JSC::IndirectEvalExecutable::create):
(JSC::IndirectEvalExecutable::tryCreate):
* runtime/IndirectEvalExecutable.h:
* runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::init):
(JSC::JSGlobalObject::visitChildrenImpl):
(JSC::JSGlobalObject::createWithCustomMethodTable):
* runtime/JSGlobalObject.h:
(JSC::JSGlobalObject::shadowRealmPrototype const):
(JSC::JSGlobalObject::shadowRealmStructure const):
* runtime/JSGlobalObjectFunctions.cpp:
(JSC::JSC_DEFINE_HOST_FUNCTION):
* runtime/JSType.cpp:
(WTF::printInternal):
* runtime/JSType.h:
* runtime/OptionsList.h:
* runtime/ShadowRealmConstructor.cpp: Added.
(JSC::ShadowRealmConstructor::ShadowRealmConstructor):
(JSC::ShadowRealmConstructor::finishCreation):
(JSC::JSC_DEFINE_HOST_FUNCTION):
* runtime/ShadowRealmConstructor.h: Added.
* runtime/ShadowRealmObject.cpp: Added.
(JSC::ShadowRealmObject::ShadowRealmObject):
(JSC::ShadowRealmObject::visitChildrenImpl):
(JSC::ShadowRealmObject::create):
(JSC::ShadowRealmObject::finishCreation):
* runtime/ShadowRealmObject.h: Added.
* runtime/ShadowRealmPrototype.cpp: Added.
(JSC::ShadowRealmPrototype::ShadowRealmPrototype):
(JSC::ShadowRealmPrototype::finishCreation):
(JSC::JSC_DEFINE_HOST_FUNCTION):
* runtime/ShadowRealmPrototype.h: Added.
* runtime/VM.cpp:
* runtime/VM.h:

Modified Paths

Added Paths

Diff

Modified: trunk/JSTests/ChangeLog (284150 => 284151)


--- trunk/JSTests/ChangeLog	2021-10-14 10:15:41 UTC (rev 284150)
+++ trunk/JSTests/ChangeLog	2021-10-14 10:22:09 UTC (rev 284151)
@@ -1,3 +1,39 @@
+2021-10-14  Phillip Mates  <[email protected]>
+
+        Test coverage for JSC shadow realms implementation
+        https://bugs.webkit.org/show_bug.cgi?id=230602
+
+        Reviewed by Yusuke Suzuki.
+
+        * modules/import-meta-syntax.js:
+        (shouldThrow):
+        * stress/eval-indirect.js: Added.
+        (shouldBe):
+        (shouldThrow):
+        * stress/import-syntax.js:
+        * stress/resources/shadow-realm-example-module.js: Added.
+        (putInGlobal):
+        (getFromGlobal):
+        (getAnObject):
+        (getCallCount):
+        * stress/shadow-realm-evaluate.js: Added.
+        (shouldBe):
+        (shouldThrow):
+        (assertionFn):
+        (shouldBe.String):
+        (shouldBe.globalObjectFor.doEval):
+        (shouldBe.globalObjectFor):
+        * stress/shadow-realm-import-value.js: Added.
+        (shouldBe):
+        (shouldThrow):
+        (async shouldThrowAsync):
+        (async const):
+        (doImport):
+        * stress/shadow-realm.js: Added.
+        (shouldBe):
+        (throw.new.Error):
+        * test262/config.yaml:
+
 2021-10-11  Saam Barati  <[email protected]>
 
         Don't branch around register allocation in DFG enumerator get by val and pass in the right LValue type to strictInt52ToJSValue

Modified: trunk/JSTests/modules/import-meta-syntax.js (284150 => 284151)


--- trunk/JSTests/modules/import-meta-syntax.js	2021-10-14 10:15:41 UTC (rev 284150)
+++ trunk/JSTests/modules/import-meta-syntax.js	2021-10-14 10:22:09 UTC (rev 284151)
@@ -10,7 +10,7 @@
 
 shouldThrow(() => {
     checkModuleSyntax(`(import.cocoa)`);
-}, `SyntaxError: Unexpected identifier 'cocoa'. "import." can only followed with meta.:1`);
+}, `SyntaxError: Unexpected identifier 'cocoa'. "import." can only be followed with meta.:1`);
 
 shouldThrow(() => {
     checkModuleSyntax(`(import["Cocoa"])`);
@@ -18,7 +18,7 @@
 
 shouldThrow(() => {
     checkModuleSyntax(`import.cocoa`);
-}, `SyntaxError: Unexpected identifier 'cocoa'. "import." can only followed with meta.:1`);
+}, `SyntaxError: Unexpected identifier 'cocoa'. "import." can only be followed with meta.:1`);
 
 shouldThrow(() => {
     checkModuleSyntax(`import["Cocoa"]`);

Added: trunk/JSTests/stress/eval-indirect.js (0 => 284151)


--- trunk/JSTests/stress/eval-indirect.js	                        (rev 0)
+++ trunk/JSTests/stress/eval-indirect.js	2021-10-14 10:22:09 UTC (rev 284151)
@@ -0,0 +1,34 @@
+
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error(`expected ${expected} but got ${actual}`);
+}
+
+function shouldThrow(func, errorType, assertionFn) {
+    let error;
+    try {
+        func();
+    } catch (e) {
+        error = e;
+    }
+
+    if (!(error instanceof errorType))
+        throw new Error(`Expected ${errorType.name} but got ${error.name}`);
+
+    assertionFn(error);
+}
+
+shouldBe((0, eval)("() => { return 1; }")(), 1);
+
+shouldThrow(
+  () => { (0, eval)("..") },
+  SyntaxError,
+  (err) => {
+      shouldBe(String(err), `SyntaxError: Unexpected token '.'`);
+  });
+
+// NOTE: more iterations (like 20000) will trigger a GC/OOM issue on 32-bit devices.
+for (var i = 0; i < 1000; ++i) {
+    let f = (0, eval)("() => { return 1; }");
+    shouldBe(f(), 1);
+}

Modified: trunk/JSTests/stress/import-syntax.js (284150 => 284151)


--- trunk/JSTests/stress/import-syntax.js	2021-10-14 10:15:41 UTC (rev 284150)
+++ trunk/JSTests/stress/import-syntax.js	2021-10-14 10:22:09 UTC (rev 284151)
@@ -29,7 +29,7 @@
 
 testSyntaxError(`import)`, `SyntaxError: Unexpected token ')'. import call expects exactly one argument.`);
 testSyntaxError(`new import(`, `SyntaxError: Cannot use new with import.`);
-testSyntaxError(`import.hello()`, `SyntaxError: Unexpected identifier 'hello'. "import." can only followed with meta.`);
+testSyntaxError(`import.hello()`, `SyntaxError: Unexpected identifier 'hello'. "import." can only be followed with meta.`);
 testSyntaxError(`import[`, `SyntaxError: Unexpected token '['. import call expects exactly one argument.`);
 testSyntaxError(`import<`, `SyntaxError: Unexpected token '<'. import call expects exactly one argument.`);
 

Added: trunk/JSTests/stress/resources/shadow-realm-example-module.js (0 => 284151)


--- trunk/JSTests/stress/resources/shadow-realm-example-module.js	                        (rev 0)
+++ trunk/JSTests/stress/resources/shadow-realm-example-module.js	2021-10-14 10:22:09 UTC (rev 284151)
@@ -0,0 +1,25 @@
+var callCount = 0;
+
+function putInGlobal(key, val) {
+    callCount++;
+    globalThis.key = val;
+}
+
+function getFromGlobal(key) {
+    callCount++;
+    return globalThis.key;
+}
+
+var anObject = new Object();
+
+function getAnObject() {
+    callCount++;
+    return anObject;
+}
+
+function getCallCount() {
+    return callCount;
+}
+
+var answer = 6;
+export { anObject, answer, getCallCount, getFromGlobal, getAnObject, putInGlobal };

Added: trunk/JSTests/stress/shadow-realm-evaluate.js (0 => 284151)


--- trunk/JSTests/stress/shadow-realm-evaluate.js	                        (rev 0)
+++ trunk/JSTests/stress/shadow-realm-evaluate.js	2021-10-14 10:22:09 UTC (rev 284151)
@@ -0,0 +1,153 @@
+//@ requireOptions("--useShadowRealm=1")
+
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error(`expected ${expected} but got ${actual}`);
+}
+
+function shouldThrow(func, errorType, assertionFn) {
+    let error;
+    try {
+        func();
+    } catch (e) {
+        error = e;
+    }
+
+    if (!(error instanceof errorType))
+        throw new Error(`Expected ${errorType.name} but got ${error.name}`);
+
+    assertionFn(error);
+}
+
+// basic evaluation and state setting
+{
+    let realm = new ShadowRealm();
+    let otherRealm = new ShadowRealm();
+
+    shouldBe(realm.evaluate("1"), 1);
+    var x = 2;
+    realm.evaluate("var x = 1");
+    shouldBe(realm.evaluate("x"), 1);
+    shouldBe(x, 2);
+
+    // scope isn't shared across realms
+    shouldBe(otherRealm.evaluate("globalThis.x"), undefined);
+}
+
+// accessing `globalThis` within and outside of a shadow realm
+{
+    let realm = new ShadowRealm();
+    globalThis.hi = 6;
+
+    shouldBe(realm.evaluate("globalThis.hi"), undefined);
+
+    realm.evaluate("globalThis.hi = 'fala amigo'");
+
+    shouldBe(realm.evaluate("globalThis.hi"), "fala amigo");
+    shouldBe(globalThis.hi, 6);
+}
+
+// ensure that errors thrown isn't associated with the shadow realm's global object
+{
+    let realm = new ShadowRealm();
+    shouldThrow(
+      () => { realm.evaluate(".."); },
+      SyntaxError,
+      (err) => {
+          shouldBe($.globalObjectFor(err), globalThis);
+          shouldBe(String(err), `SyntaxError: Unexpected token '.'`);
+      });
+}
+
+// ensure that errors thrown don't carry information from the shadow realm
+{
+    let realm = new ShadowRealm();
+    shouldThrow(
+      () => { realm.evaluate("throw new Error('secret')"); },
+      TypeError,
+      (err) => {
+          shouldBe($.globalObjectFor(err), globalThis);
+          shouldBe(String(err), "TypeError: Error encountered during evaluation");
+      });
+}
+
+// wrapped functions protect the shadow realm
+{
+    let realm = new ShadowRealm();
+    let wrappedInvokeAndAdd = realm.evaluate("function invokeAndAdd(xFn, yFn) { return xFn() + yFn(); }; invokeAndAdd");
+    shouldBe(wrappedInvokeAndAdd(() => { return 1 }, () => { return 2 }), 3);
+    shouldBe($.globalObjectFor(wrappedInvokeAndAdd), globalThis);
+
+    // name and length properties from wrapped function are absent
+    shouldBe(Object.getOwnPropertyDescriptor(wrappedInvokeAndAdd, "length"), undefined);
+    shouldBe(Object.getOwnPropertyDescriptor(wrappedInvokeAndAdd, "name"), undefined);
+
+    // can't pass objects into a shadow realm-wrapped function
+    let numberObj = { valueOf() { return -1 } };
+    shouldThrow(
+      () => { wrappedInvokeAndAdd(numberObj, 1); },
+      TypeError,
+      (err) => {
+          shouldBe($.globalObjectFor(err), globalThis);
+          shouldBe(String(err), "TypeError: value passing between realms must be callable or primitive");
+      });
+}
+
+{
+    let realm = new ShadowRealm();
+    // can't call `evaluate` on a non shadow realm
+    let notRealm = {};
+    shouldThrow(
+      () => { realm.evaluate.call(notRealm, '1'); },
+      TypeError,
+      (err) => { shouldBe($.globalObjectFor(err), globalThis); }
+    );
+}
+
+// trigger JIT
+{
+    function doEval(realm, s)
+    {
+        return realm.evaluate(s);
+    }
+
+    noInline(doEval);
+
+    let realm = new ShadowRealm();
+    realm.evaluate("globalThis.secret = 1;");
+    for (var i = 0; i < 10000; ++i)
+        shouldBe(doEval(realm, '42'), 42);
+
+    for (var i = 0; i < 1000; ++i) {
+        let f = doEval(realm, '(x) => { return x() + globalThis.secret; }');
+        shouldBe($.globalObjectFor(f), globalThis);
+        shouldBe(f(() => { return 41; }), 42);
+    }
+    // (potential) inlining of wrapped function uses correct global object
+    let f = doEval(realm, '(x) => { return x() + globalThis.secret; }');
+    for (var i = 0; i < 10000; ++i) {
+        shouldBe($.globalObjectFor(f), globalThis);
+        shouldBe(f(() => { return 41; }), 42);
+    }
+    // (potential) inlining inside a realm uses correct global object
+    let loopInside = doEval(realm, '(x) => { let acc = 0; for (var i = 0; i < 10000; ++i) { acc += x(); }; return acc; }');
+    globalThis.secret = -1;
+    shouldBe(loopInside(() => { return globalThis.secret; }), -10000);
+}
+
+// evaluate specs
+{
+    shouldBe(typeof ShadowRealm.prototype.evaluate, "function");
+
+    let evaluateName = Object.getOwnPropertyDescriptor(ShadowRealm.prototype.evaluate, "name");
+    shouldBe(evaluateName.value, "evaluate");
+    shouldBe(evaluateName.enumerable, false);
+    shouldBe(evaluateName.writable, false);
+    shouldBe(evaluateName.configurable, true);
+
+    let evaluateLength = Object.getOwnPropertyDescriptor(ShadowRealm.prototype.evaluate, "length");
+    shouldBe(evaluateLength.value, 1);
+    shouldBe(evaluateLength.enumerable, false);
+    shouldBe(evaluateLength.writable, false);
+    shouldBe(evaluateLength.configurable, true);
+}

Added: trunk/JSTests/stress/shadow-realm-import-value.js (0 => 284151)


--- trunk/JSTests/stress/shadow-realm-import-value.js	                        (rev 0)
+++ trunk/JSTests/stress/shadow-realm-import-value.js	2021-10-14 10:22:09 UTC (rev 284151)
@@ -0,0 +1,148 @@
+//@ requireOptions("--useShadowRealm=1")
+
+var abort = $vm.abort;
+
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error(`expected ${expected} but got ${actual}`);
+}
+
+function shouldThrow(func, errorType) {
+    let error;
+    try {
+        func();
+    } catch (e) {
+        error = e;
+    }
+
+    if (!(error instanceof errorType))
+        throw new Error(`Expected ${errorType.name}! got ${error.name}`);
+}
+
+async function shouldThrowAsync(func, errorType) {
+    let error;
+    try {
+        await func();
+    } catch (e) {
+        error = e;
+    }
+
+    if (!(error instanceof errorType))
+        throw new Error(`Expected ${errorType.name}! got ${error.name} with message ${error.message}`);
+}
+
+(async function () {
+    const importPath = "./resources/shadow-realm-example-module.js";
+    const { answer, getCallCount, putInGlobal, getFromGlobal, getAnObject } = await import(importPath);
+    const outerAnswer = answer;
+    const outerGetCallCount = getCallCount;
+    const outerPutInGlobal = putInGlobal;
+    const outerGetFromGlobal = getFromGlobal;
+    const outerGetAnObject = getAnObject;
+
+    {
+        let realm = new ShadowRealm();
+
+        // update local module state + check it
+        shouldBe(outerGetCallCount(), 0);
+        outerGetAnObject();
+        shouldBe(outerGetCallCount(), 1);
+        // update realm module state + check it
+        let innerGetCallCount = await realm.importValue(importPath, "getCallCount");
+        let innerPutInGlobal = await realm.importValue(importPath, "putInGlobal");
+        shouldBe(innerGetCallCount(), 0);
+        innerPutInGlobal("something", "random");
+        shouldBe(innerGetCallCount(), 1);
+        // re-importing the module into the realm doesn't reload the module
+        innerGetCallCount = await realm.importValue(importPath, "getCallCount");
+        shouldBe(innerGetCallCount(), 1);
+        // the (outer) local module state stays intact
+        shouldBe(outerGetCallCount(), 1);
+
+        // one can imported primitive/callable variables just fine
+        // shouldBe(innerAnswer, outerAnswer);
+        let innerAnswer = await realm.importValue(importPath, "answer");
+        shouldBe(innerAnswer, outerAnswer);
+
+        // imported variables are checked for primtive/callable-ness
+        await shouldThrowAsync(async () => { let x = await realm.importValue(importPath, "anObject"); }, TypeError);
+
+        // importing non-existent ref fails
+        await shouldThrowAsync(async () => { let x = await realm.importValue(importPath, "nothing"); }, TypeError);
+
+        // importing from non-existent file fails
+        await shouldThrowAsync(async () => { let x = await realm.importValue("random", "nothing"); }, TypeError);
+
+        // we can import functions through an inner realm for use in the outer
+        let innerGetFromGlobal = await realm.importValue(importPath, "getFromGlobal");
+        innerPutInGlobal("salutation", "sarava");
+        shouldBe(innerGetFromGlobal("salutation"), "sarava");
+
+        // inner global state is unchanged by outer global state change
+        outerPutInGlobal("salutation", "hello world!");
+        shouldBe(outerGetFromGlobal("salutation"), "hello world!");
+        shouldBe(innerGetFromGlobal("salutation"), "sarava");
+
+        // wrapped functions check arguments for primitive/callable-ness
+        shouldThrow(() => { innerPutInGlobal("treasure", new Object()); }, TypeError);
+
+        // imported functions are wrapped with correct return value checks
+        let getAnObjectFn = await realm.importValue(importPath, "getAnObject");
+        shouldThrow(() => { getAnObjectFn(); }, TypeError);
+
+        // thread a function in and out of a realm to wrap it up
+        innerPutInGlobal("outer-realm-put", outerPutInGlobal);
+        wrappedOuterPutInGlobal = innerGetFromGlobal("outer-realm-put");
+
+        // it still manipuates the correct global object state
+        wrappedOuterPutInGlobal("treasure", "shiny tin scrap");
+        shouldBe(outerGetFromGlobal("treasure"), "shiny tin scrap");
+
+        // wrapped functions check arguments for primitive/callable-ness
+        shouldThrow(() => { wrappedOuterPutInGlobal("treasure", new Object()); }, TypeError);
+        shouldThrow(() => { wrappedOuterPutInGlobal(new Object(), "shiny tin scrap"); }, TypeError);
+
+        // must be called on a ShadowRealm
+        let notRealm = {};
+        shouldThrow(
+          () => { realm.importValue.call(notRealm, importPath, "answer"); },
+          TypeError,
+          (err) => { shouldBe($.globalObjectFor(err), globalThis); }
+        );
+    }
+
+    // trigger JIT
+    {
+        function doImport(realm, s)
+        {
+            return realm.importValue(importPath, s);
+        }
+
+        noInline(doImport);
+
+        let realm = new ShadowRealm();
+        for (var i = 0; i < 10000; ++i) {
+            let result = await doImport(realm, "getCallCount");
+            shouldBe(result(), 0);
+        }
+    }
+}()).catch((error) => {
+    print(String(error));
+    abort();
+});
+
+{
+    shouldBe(typeof ShadowRealm.prototype.importValue, "function");
+
+    let importValueName = Object.getOwnPropertyDescriptor(ShadowRealm.prototype.importValue, "name");
+    shouldBe(importValueName.value, "importValue");
+    shouldBe(importValueName.enumerable, false);
+    shouldBe(importValueName.writable, false);
+    shouldBe(importValueName.configurable, true);
+
+    let importValueLength = Object.getOwnPropertyDescriptor(ShadowRealm.prototype.importValue, "length");
+    shouldBe(importValueLength.value, 2);
+    shouldBe(importValueLength.enumerable, false);
+    shouldBe(importValueLength.writable, false);
+    shouldBe(importValueLength.configurable, true);
+}

Added: trunk/JSTests/stress/shadow-realm.js (0 => 284151)


--- trunk/JSTests/stress/shadow-realm.js	                        (rev 0)
+++ trunk/JSTests/stress/shadow-realm.js	2021-10-14 10:22:09 UTC (rev 284151)
@@ -0,0 +1,36 @@
+//@ requireOptions("--useShadowRealm=1")
+
+function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error(`expected ${expected} but got ${actual}`);
+}
+
+// shadow realm specs
+{
+    let shadowRealmProp = Object.getOwnPropertyDescriptor(this, "ShadowRealm");
+    shouldBe(shadowRealmProp.enumerable, false);
+    shouldBe(shadowRealmProp.writable, true);
+    shouldBe(shadowRealmProp.configurable, true);
+
+    let shadowRealmEvaluate = Object.getOwnPropertyDescriptor(ShadowRealm.prototype, "evaluate");
+    shouldBe(shadowRealmEvaluate.enumerable, false);
+    shouldBe(shadowRealmEvaluate.writable, true);
+    shouldBe(shadowRealmEvaluate.configurable, true);
+
+    let shadowRealmImportValue = Object.getOwnPropertyDescriptor(ShadowRealm.prototype, "importValue");
+    shouldBe(shadowRealmImportValue.enumerable, false);
+    shouldBe(shadowRealmImportValue.writable, true);
+    shouldBe(shadowRealmImportValue.configurable, true);
+
+    let shadowRealmName = Object.getOwnPropertyDescriptor(ShadowRealm, "name");
+    shouldBe(shadowRealmName.value, "ShadowRealm");
+    shouldBe(shadowRealmName.enumerable, false);
+    shouldBe(shadowRealmName.writable, false);
+    shouldBe(shadowRealmName.configurable, true);
+
+    let shadowRealmLength = Object.getOwnPropertyDescriptor(ShadowRealm, "length");
+    shouldBe(shadowRealmLength.value, 0);
+    shouldBe(shadowRealmLength.enumerable, false);
+    shouldBe(shadowRealmLength.writable, false);
+    shouldBe(shadowRealmLength.configurable, true);
+}

Modified: trunk/JSTests/test262/config.yaml (284150 => 284151)


--- trunk/JSTests/test262/config.yaml	2021-10-14 10:15:41 UTC (rev 284150)
+++ trunk/JSTests/test262/config.yaml	2021-10-14 10:22:09 UTC (rev 284151)
@@ -9,6 +9,7 @@
   Temporal: useTemporal
   array-find-from-last: useArrayFindLastMethod
   Object.hasOwn: useHasOwn
+  ShadowRealm: useShadowRealm
 skip:
   features:
     - Atomics.waitAsync
@@ -20,7 +21,6 @@
     - json-modules
     - class-static-block
     - callable-boundary-realms
-    - ShadowRealm
   paths:
     - test/built-ins/Temporal/Calendar
     - test/built-ins/Temporal/Instant

Modified: trunk/Source/_javascript_Core/CMakeLists.txt (284150 => 284151)


--- trunk/Source/_javascript_Core/CMakeLists.txt	2021-10-14 10:15:41 UTC (rev 284150)
+++ trunk/Source/_javascript_Core/CMakeLists.txt	2021-10-14 10:22:09 UTC (rev 284151)
@@ -103,6 +103,8 @@
     runtime/RegExpPrototype.cpp
     runtime/RegExpStringIteratorPrototype.cpp
     runtime/SetPrototype.cpp
+    runtime/ShadowRealmObject.cpp
+    runtime/ShadowRealmPrototype.cpp
     runtime/StringConstructor.cpp
     runtime/StringPrototype.cpp
     runtime/SymbolConstructor.cpp
@@ -373,6 +375,7 @@
     ${_javascript_CORE_DIR}/builtins/RegExpStringIteratorPrototype.js
     ${_javascript_CORE_DIR}/builtins/SetIteratorPrototype.js
     ${_javascript_CORE_DIR}/builtins/SetPrototype.js
+    ${_javascript_CORE_DIR}/builtins/ShadowRealmPrototype.js
     ${_javascript_CORE_DIR}/builtins/StringConstructor.js
     ${_javascript_CORE_DIR}/builtins/StringIteratorPrototype.js
     ${_javascript_CORE_DIR}/builtins/StringPrototype.js
@@ -1157,6 +1160,7 @@
     runtime/ScriptExecutable.h
     runtime/ScriptFetchParameters.h
     runtime/ScriptFetcher.h
+    runtime/ShadowRealmObject.h
     runtime/SlowPathFunction.h
     runtime/SlowPathReturnType.h
     runtime/SmallStrings.h

Modified: trunk/Source/_javascript_Core/ChangeLog (284150 => 284151)


--- trunk/Source/_javascript_Core/ChangeLog	2021-10-14 10:15:41 UTC (rev 284150)
+++ trunk/Source/_javascript_Core/ChangeLog	2021-10-14 10:22:09 UTC (rev 284151)
@@ -1,3 +1,92 @@
+2021-10-14  Phillip Mates  <[email protected]>
+
+        shadow realms implementation
+        https://bugs.webkit.org/show_bug.cgi?id=230602
+
+        Reviewed by Yusuke Suzuki.
+
+        Implementation of the Shadow Realms proposal (stage 3 in TC39) [1]
+
+        Main APIs added are
+         - `new ShadowRealm()`
+           creates an object that has its own global object and module graph.
+         - ShadowRealm.prototype.evaluate(sourceText)
+           this allows for evaluating code in the context of the realm, which
+           has its own module graph and global object.
+         - ShadowRealm.prototype.importValue(specifier, exportName)
+           this allows importing module exports in the the context of the
+           realm, which has its own module graph and global object.
+
+        The main detail of the Shadow Realm implementation is that values
+        passed between realms must be either primitives or wrapped callables.
+        Wrapped callables themselves are callables that check that their
+        arguments and return values are also either primitives or wrapped
+        callables. This detail is implemented via JS builtins + a few new
+        intrinsics.
+
+        Can be enabled using `--useShadowRealm=true`
+
+        [1]: https://github.com/tc39/proposal-shadowrealm
+
+        * CMakeLists.txt:
+        * DerivedSources-input.xcfilelist:
+        * DerivedSources-output.xcfilelist:
+        * DerivedSources.make:
+        * _javascript_Core.xcodeproj/project.pbxproj:
+        * Sources.txt:
+        * builtins/BuiltinNames.h:
+        * builtins/ShadowRealmPrototype.js: Added.
+        (globalPrivate.wrap.wrapped):
+        (globalPrivate.wrap):
+        (evaluate):
+        (importValue):
+        * bytecode/BytecodeIntrinsicRegistry.h:
+        * bytecode/LinkTimeConstant.h:
+        * bytecompiler/BytecodeGenerator.h:
+        (JSC::BytecodeGenerator::emitIsShadowRealm):
+        * bytecompiler/NodesCodegen.cpp:
+        * jsc.cpp:
+        (JSC_DEFINE_HOST_FUNCTION):
+        * parser/Parser.cpp:
+        (JSC::Parser<LexerType>::parseMemberExpression):
+        * runtime/CommonIdentifiers.h:
+        * runtime/IndirectEvalExecutable.cpp:
+        (JSC::IndirectEvalExecutable::createImpl):
+        (JSC::IndirectEvalExecutable::create):
+        (JSC::IndirectEvalExecutable::tryCreate):
+        * runtime/IndirectEvalExecutable.h:
+        * runtime/JSGlobalObject.cpp:
+        (JSC::JSGlobalObject::init):
+        (JSC::JSGlobalObject::visitChildrenImpl):
+        (JSC::JSGlobalObject::createWithCustomMethodTable):
+        * runtime/JSGlobalObject.h:
+        (JSC::JSGlobalObject::shadowRealmPrototype const):
+        (JSC::JSGlobalObject::shadowRealmStructure const):
+        * runtime/JSGlobalObjectFunctions.cpp:
+        (JSC::JSC_DEFINE_HOST_FUNCTION):
+        * runtime/JSType.cpp:
+        (WTF::printInternal):
+        * runtime/JSType.h:
+        * runtime/OptionsList.h:
+        * runtime/ShadowRealmConstructor.cpp: Added.
+        (JSC::ShadowRealmConstructor::ShadowRealmConstructor):
+        (JSC::ShadowRealmConstructor::finishCreation):
+        (JSC::JSC_DEFINE_HOST_FUNCTION):
+        * runtime/ShadowRealmConstructor.h: Added.
+        * runtime/ShadowRealmObject.cpp: Added.
+        (JSC::ShadowRealmObject::ShadowRealmObject):
+        (JSC::ShadowRealmObject::visitChildrenImpl):
+        (JSC::ShadowRealmObject::create):
+        (JSC::ShadowRealmObject::finishCreation):
+        * runtime/ShadowRealmObject.h: Added.
+        * runtime/ShadowRealmPrototype.cpp: Added.
+        (JSC::ShadowRealmPrototype::ShadowRealmPrototype):
+        (JSC::ShadowRealmPrototype::finishCreation):
+        (JSC::JSC_DEFINE_HOST_FUNCTION):
+        * runtime/ShadowRealmPrototype.h: Added.
+        * runtime/VM.cpp:
+        * runtime/VM.h:
+
 2021-10-13  Yusuke Suzuki  <[email protected]>
 
         Unreviewed, speculative build fix with new clang

Modified: trunk/Source/_javascript_Core/DerivedSources-input.xcfilelist (284150 => 284151)


--- trunk/Source/_javascript_Core/DerivedSources-input.xcfilelist	2021-10-14 10:15:41 UTC (rev 284150)
+++ trunk/Source/_javascript_Core/DerivedSources-input.xcfilelist	2021-10-14 10:22:09 UTC (rev 284151)
@@ -50,6 +50,7 @@
 $(PROJECT_DIR)/builtins/RegExpStringIteratorPrototype.js
 $(PROJECT_DIR)/builtins/SetIteratorPrototype.js
 $(PROJECT_DIR)/builtins/SetPrototype.js
+$(PROJECT_DIR)/builtins/ShadowRealmPrototype.js
 $(PROJECT_DIR)/builtins/StringConstructor.js
 $(PROJECT_DIR)/builtins/StringIteratorPrototype.js
 $(PROJECT_DIR)/builtins/StringPrototype.js

Modified: trunk/Source/_javascript_Core/DerivedSources-output.xcfilelist (284150 => 284151)


--- trunk/Source/_javascript_Core/DerivedSources-output.xcfilelist	2021-10-14 10:15:41 UTC (rev 284150)
+++ trunk/Source/_javascript_Core/DerivedSources-output.xcfilelist	2021-10-14 10:22:09 UTC (rev 284151)
@@ -62,6 +62,8 @@
 $(BUILT_PRODUCTS_DIR)/DerivedSources/_javascript_Core/RegExpConstructor.lut.h
 $(BUILT_PRODUCTS_DIR)/DerivedSources/_javascript_Core/RegExpJitTables.h
 $(BUILT_PRODUCTS_DIR)/DerivedSources/_javascript_Core/SetPrototype.lut.h
+$(BUILT_PRODUCTS_DIR)/DerivedSources/_javascript_Core/ShadowRealmObject.lut.h
+$(BUILT_PRODUCTS_DIR)/DerivedSources/_javascript_Core/ShadowRealmPrototype.lut.h
 $(BUILT_PRODUCTS_DIR)/DerivedSources/_javascript_Core/StringConstructor.lut.h
 $(BUILT_PRODUCTS_DIR)/DerivedSources/_javascript_Core/StringPrototype.lut.h
 $(BUILT_PRODUCTS_DIR)/DerivedSources/_javascript_Core/SymbolConstructor.lut.h

Modified: trunk/Source/_javascript_Core/DerivedSources.make (284150 => 284151)


--- trunk/Source/_javascript_Core/DerivedSources.make	2021-10-14 10:15:41 UTC (rev 284150)
+++ trunk/Source/_javascript_Core/DerivedSources.make	2021-10-14 10:22:09 UTC (rev 284151)
@@ -122,6 +122,7 @@
     ${_javascript_Core}/builtins/RegExpStringIteratorPrototype.js \
     $(_javascript_Core)/builtins/SetIteratorPrototype.js \
     $(_javascript_Core)/builtins/SetPrototype.js \
+    $(_javascript_Core)/builtins/ShadowRealmPrototype.js \
     $(_javascript_Core)/builtins/StringConstructor.js \
     $(_javascript_Core)/builtins/StringIteratorPrototype.js \
     $(_javascript_Core)/builtins/StringPrototype.js \
@@ -187,6 +188,7 @@
     ReflectObject.lut.h \
     RegExpConstructor.lut.h \
     SetPrototype.lut.h \
+    ShadowRealmPrototype.lut.h \
     StringConstructor.lut.h \
     StringPrototype.lut.h \
     SymbolConstructor.lut.h \

Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (284150 => 284151)


--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2021-10-14 10:15:41 UTC (rev 284150)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj	2021-10-14 10:22:09 UTC (rev 284151)
@@ -1263,6 +1263,9 @@
 		860161E30F3A83C100F84710 /* AbstractMacroAssembler.h in Headers */ = {isa = PBXBuildFile; fileRef = 860161DF0F3A83C100F84710 /* AbstractMacroAssembler.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		860161E50F3A83C100F84710 /* MacroAssemblerX86_64.h in Headers */ = {isa = PBXBuildFile; fileRef = 860161E10F3A83C100F84710 /* MacroAssemblerX86_64.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		860161E60F3A83C100F84710 /* MacroAssemblerX86Common.h in Headers */ = {isa = PBXBuildFile; fileRef = 860161E20F3A83C100F84710 /* MacroAssemblerX86Common.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		8602960226FB552D0078EB62 /* ShadowRealmConstructor.h in Headers */ = {isa = PBXBuildFile; fileRef = 860295FC26FB552C0078EB62 /* ShadowRealmConstructor.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		8602960426FB552D0078EB62 /* ShadowRealmObject.h in Headers */ = {isa = PBXBuildFile; fileRef = 860295FE26FB552D0078EB62 /* ShadowRealmObject.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		8602960526FB552D0078EB62 /* ShadowRealmPrototype.h in Headers */ = {isa = PBXBuildFile; fileRef = 860295FF26FB552D0078EB62 /* ShadowRealmPrototype.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		8606DDEA18DA44AB00A383D0 /* IdentifierInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 8606DDE918DA44AB00A383D0 /* IdentifierInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		860BD801148EA6F200112B2F /* Intrinsic.h in Headers */ = {isa = PBXBuildFile; fileRef = 86BF642A148DB2B5004DE36A /* Intrinsic.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		8612E4CD152389EC00C836BE /* MatchResult.h in Headers */ = {isa = PBXBuildFile; fileRef = 8612E4CB1522918400C836BE /* MatchResult.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -4242,6 +4245,12 @@
 		860161DF0F3A83C100F84710 /* AbstractMacroAssembler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AbstractMacroAssembler.h; sourceTree = "<group>"; };
 		860161E10F3A83C100F84710 /* MacroAssemblerX86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MacroAssemblerX86_64.h; sourceTree = "<group>"; };
 		860161E20F3A83C100F84710 /* MacroAssemblerX86Common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MacroAssemblerX86Common.h; sourceTree = "<group>"; };
+		860295FA26FB552C0078EB62 /* ShadowRealmPrototype.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ShadowRealmPrototype.cpp; sourceTree = "<group>"; };
+		860295FB26FB552C0078EB62 /* ShadowRealmObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ShadowRealmObject.cpp; sourceTree = "<group>"; };
+		860295FC26FB552C0078EB62 /* ShadowRealmConstructor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ShadowRealmConstructor.h; sourceTree = "<group>"; };
+		860295FD26FB552D0078EB62 /* ShadowRealmConstructor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ShadowRealmConstructor.cpp; sourceTree = "<group>"; };
+		860295FE26FB552D0078EB62 /* ShadowRealmObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ShadowRealmObject.h; sourceTree = "<group>"; };
+		860295FF26FB552D0078EB62 /* ShadowRealmPrototype.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ShadowRealmPrototype.h; sourceTree = "<group>"; };
 		8604F4F2143A6C4400B295F5 /* ChangeLog */ = {isa = PBXFileReference; lastKnownFileType = text; lineEnding = 0; path = ChangeLog; sourceTree = "<group>"; };
 		8606DDE918DA44AB00A383D0 /* IdentifierInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IdentifierInlines.h; sourceTree = "<group>"; };
 		8612E4CB1522918400C836BE /* MatchResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MatchResult.h; sourceTree = "<group>"; };
@@ -7993,6 +8002,12 @@
 				A790DD68182F499700588807 /* SetIteratorPrototype.h */,
 				A7299D9F17D12848005F5FF9 /* SetPrototype.cpp */,
 				A7299DA017D12848005F5FF9 /* SetPrototype.h */,
+				860295FD26FB552D0078EB62 /* ShadowRealmConstructor.cpp */,
+				860295FC26FB552C0078EB62 /* ShadowRealmConstructor.h */,
+				860295FB26FB552C0078EB62 /* ShadowRealmObject.cpp */,
+				860295FE26FB552D0078EB62 /* ShadowRealmObject.h */,
+				860295FA26FB552C0078EB62 /* ShadowRealmPrototype.cpp */,
+				860295FF26FB552D0078EB62 /* ShadowRealmPrototype.h */,
 				0F2B66D617B6B5AB00A7AE3F /* SimpleTypedArrayController.cpp */,
 				0F2B66D717B6B5AB00A7AE3F /* SimpleTypedArrayController.h */,
 				FE8C0311264A6910001A44AD /* SlowPathFunction.h */,
@@ -10715,6 +10730,9 @@
 				0FEE98411A8865B700754E93 /* SetupVarargsFrame.h in Headers */,
 				DC17E8181C9C91D9008A6AB3 /* ShadowChicken.h in Headers */,
 				DC17E8191C9C91DB008A6AB3 /* ShadowChickenInlines.h in Headers */,
+				8602960226FB552D0078EB62 /* ShadowRealmConstructor.h in Headers */,
+				8602960426FB552D0078EB62 /* ShadowRealmObject.h in Headers */,
+				8602960526FB552D0078EB62 /* ShadowRealmPrototype.h in Headers */,
 				FE3022D31E3D73A500BAC493 /* SigillCrashAnalyzer.h in Headers */,
 				0F4D8C781FCA3CFA001D32AC /* SimpleMarkingConstraint.h in Headers */,
 				0F2B670517B6B5AB00A7AE3F /* SimpleTypedArrayController.h in Headers */,

Modified: trunk/Source/_javascript_Core/Sources.txt (284150 => 284151)


--- trunk/Source/_javascript_Core/Sources.txt	2021-10-14 10:15:41 UTC (rev 284150)
+++ trunk/Source/_javascript_Core/Sources.txt	2021-10-14 10:22:09 UTC (rev 284151)
@@ -970,6 +970,9 @@
 runtime/ProxyObject.cpp
 runtime/ProxyRevoke.cpp
 runtime/RandomizingFuzzerAgent.cpp
+runtime/ShadowRealmObject.cpp
+runtime/ShadowRealmConstructor.cpp
+runtime/ShadowRealmPrototype.cpp
 runtime/ReflectObject.cpp
 runtime/RegExp.cpp
 runtime/RegExpCache.cpp

Modified: trunk/Source/_javascript_Core/builtins/BuiltinNames.h (284150 => 284151)


--- trunk/Source/_javascript_Core/builtins/BuiltinNames.h	2021-10-14 10:15:41 UTC (rev 284150)
+++ trunk/Source/_javascript_Core/builtins/BuiltinNames.h	2021-10-14 10:22:09 UTC (rev 284151)
@@ -62,6 +62,7 @@
     macro(Number) \
     macro(Array) \
     macro(ArrayBuffer) \
+    macro(ShadowRealm) \
     macro(RegExp) \
     macro(min) \
     macro(trunc) \
@@ -115,6 +116,8 @@
     macro(asyncGeneratorQueueItemNext) \
     macro(dateTimeFormat) \
     macro(this) \
+    macro(importInRealm) \
+    macro(evalInRealm) \
     macro(thisTimeValue) \
     macro(newTargetLocal) \
     macro(derivedConstructor) \

Added: trunk/Source/_javascript_Core/builtins/ShadowRealmPrototype.js (0 => 284151)


--- trunk/Source/_javascript_Core/builtins/ShadowRealmPrototype.js	                        (rev 0)
+++ trunk/Source/_javascript_Core/builtins/ShadowRealmPrototype.js	2021-10-14 10:22:09 UTC (rev 284151)
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2021 Igalia S.L.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+@globalPrivate
+function wrap(target)
+{
+    "use strict";
+
+    if (@isCallable(target)) {
+        var wrapped = function(/* args... */) {
+            var length = arguments.length;
+            var wrappedArgs = @newArrayWithSize(length);
+            for (var index = 0; index < length; ++index)
+                @putByValDirect(wrappedArgs, index, @wrap(arguments[index]));
+
+            var result = target.@apply(@undefined, wrappedArgs);
+            return @wrap(result);
+        };
+        delete wrapped['name'];
+        delete wrapped['length'];
+        return wrapped;
+    } else if (@isObject(target)) {
+        @throwTypeError("value passing between realms must be callable or primitive");
+    }
+    return target;
+}
+
+function evaluate(sourceText)
+{
+    "use strict";
+
+    if (!@isShadowRealm(this))
+        @throwTypeError("`%ShadowRealm%.evaluate requires that |this| be a ShadowRealm instance");
+
+    if (typeof sourceText !== 'string')
+        @throwTypeError("`%ShadowRealm%.evaluate requires that the |sourceText| argument be a string");
+
+    var result = @evalInRealm(this, sourceText)
+    return @wrap(result);
+}
+
+function importValue(specifier, exportName)
+{
+    "use strict";
+
+    if (!@isShadowRealm(this))
+        @throwTypeError("`%ShadowRealm%.importValue requires that |this| be a ShadowRealm instance");
+
+    var exportNameString = @toString(exportName);
+    var specifierString = @toString(specifier);
+
+    var lookupBinding = (module) => {
+        var lookup = module[exportNameString]
+        if (lookup === @undefined)
+            @throwTypeError("%ShadowRealm%.importValue requires |exportName| to exist in the |specifier|");
+
+        return @wrap(lookup);
+    };
+
+    var crossRealmThrow = (error) => {
+        // re-throw because import issues raise errors using the realm's global object
+        @throwTypeError(@toString(error));
+    };
+
+    return @importInRealm(this, specifierString).@then(lookupBinding, crossRealmThrow);
+}

Modified: trunk/Source/_javascript_Core/bytecode/BytecodeIntrinsicRegistry.h (284150 => 284151)


--- trunk/Source/_javascript_Core/bytecode/BytecodeIntrinsicRegistry.h	2021-10-14 10:15:41 UTC (rev 284150)
+++ trunk/Source/_javascript_Core/bytecode/BytecodeIntrinsicRegistry.h	2021-10-14 10:22:09 UTC (rev 284151)
@@ -66,6 +66,7 @@
     macro(isRegExpObject) \
     macro(isMap) \
     macro(isSet) \
+    macro(isShadowRealm) \
     macro(isStringIterator) \
     macro(isArrayIterator) \
     macro(isMapIterator) \

Modified: trunk/Source/_javascript_Core/bytecode/LinkTimeConstant.h (284150 => 284151)


--- trunk/Source/_javascript_Core/bytecode/LinkTimeConstant.h	2021-10-14 10:15:41 UTC (rev 284150)
+++ trunk/Source/_javascript_Core/bytecode/LinkTimeConstant.h	2021-10-14 10:22:09 UTC (rev 284151)
@@ -78,6 +78,8 @@
     v(hostPromiseRejectionTracker, nullptr) \
     v(Set, nullptr) \
     v(thisTimeValue, nullptr) \
+    v(importInRealm, nullptr) \
+    v(evalInRealm, nullptr) \
     v(isConstructor, nullptr) \
     v(sameValue, nullptr) \
     v(regExpProtoFlagsGetter, nullptr) \

Modified: trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h (284150 => 284151)


--- trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h	2021-10-14 10:15:41 UTC (rev 284150)
+++ trunk/Source/_javascript_Core/bytecompiler/BytecodeGenerator.h	2021-10-14 10:22:09 UTC (rev 284151)
@@ -885,6 +885,7 @@
         RegisterID* emitIsRegExpObject(RegisterID* dst, RegisterID* src) { return emitIsCellWithType(dst, src, RegExpObjectType); }
         RegisterID* emitIsMap(RegisterID* dst, RegisterID* src) { return emitIsCellWithType(dst, src, JSMapType); }
         RegisterID* emitIsSet(RegisterID* dst, RegisterID* src) { return emitIsCellWithType(dst, src, JSSetType); }
+        RegisterID* emitIsShadowRealm(RegisterID* dst, RegisterID* src) { return emitIsCellWithType(dst, src, ShadowRealmType); }
         RegisterID* emitIsStringIterator(RegisterID* dst, RegisterID* src) { return emitIsCellWithType(dst, src, JSStringIteratorType); }
         RegisterID* emitIsArrayIterator(RegisterID* dst, RegisterID* src) { return emitIsCellWithType(dst, src, JSArrayIteratorType); }
         RegisterID* emitIsMapIterator(RegisterID* dst, RegisterID* src) { return emitIsCellWithType(dst, src, JSMapIteratorType); }

Modified: trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp (284150 => 284151)


--- trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp	2021-10-14 10:15:41 UTC (rev 284150)
+++ trunk/Source/_javascript_Core/bytecompiler/NodesCodegen.cpp	2021-10-14 10:22:09 UTC (rev 284151)
@@ -1894,6 +1894,7 @@
 CREATE_INTRINSIC_FOR_BRAND_CHECK(isRegExpObject, IsRegExpObject)
 CREATE_INTRINSIC_FOR_BRAND_CHECK(isMap, IsMap)
 CREATE_INTRINSIC_FOR_BRAND_CHECK(isSet, IsSet)
+CREATE_INTRINSIC_FOR_BRAND_CHECK(isShadowRealm, IsShadowRealm)
 CREATE_INTRINSIC_FOR_BRAND_CHECK(isStringIterator, IsStringIterator)
 CREATE_INTRINSIC_FOR_BRAND_CHECK(isArrayIterator, IsArrayIterator)
 CREATE_INTRINSIC_FOR_BRAND_CHECK(isMapIterator, IsMapIterator)

Modified: trunk/Source/_javascript_Core/jsc.cpp (284150 => 284151)


--- trunk/Source/_javascript_Core/jsc.cpp	2021-10-14 10:15:41 UTC (rev 284150)
+++ trunk/Source/_javascript_Core/jsc.cpp	2021-10-14 10:22:09 UTC (rev 284151)
@@ -364,6 +364,7 @@
 static JSC_DECLARE_HOST_FUNCTION(functionDollarEvalScript);
 static JSC_DECLARE_HOST_FUNCTION(functionDollarGC);
 static JSC_DECLARE_HOST_FUNCTION(functionDollarClearKeptObjects);
+static JSC_DECLARE_HOST_FUNCTION(functionDollarGlobalObjectFor);
 static JSC_DECLARE_HOST_FUNCTION(functionDollarAgentStart);
 static JSC_DECLARE_HOST_FUNCTION(functionDollarAgentReceiveBroadcast);
 static JSC_DECLARE_HOST_FUNCTION(functionDollarAgentReport);
@@ -646,6 +647,7 @@
         addFunction(vm, dollar, "evalScript", functionDollarEvalScript, 1, static_cast<unsigned>(PropertyAttribute::None));
         addFunction(vm, dollar, "gc", functionDollarGC, 0, static_cast<unsigned>(PropertyAttribute::None));
         addFunction(vm, dollar, "clearKeptObjects", functionDollarClearKeptObjects, 0, static_cast<unsigned>(PropertyAttribute::None));
+        addFunction(vm, dollar, "globalObjectFor", functionDollarGlobalObjectFor, 1, static_cast<unsigned>(PropertyAttribute::None));
         
         dollar->putDirect(vm, Identifier::fromString(vm, "global"), globalThis());
         dollar->putDirectCustomAccessor(vm, Identifier::fromString(vm, "IsHTMLDDA"),
@@ -2066,6 +2068,20 @@
     return JSValue::encode(jsUndefined());
 }
 
+JSC_DEFINE_HOST_FUNCTION(functionDollarGlobalObjectFor, (JSGlobalObject* globalObject, CallFrame* callFrame))
+{
+    VM& vm = globalObject->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
+    if (callFrame->argumentCount() < 1)
+        return JSValue::encode(throwException(globalObject, scope, createError(globalObject, "Not enough arguments"_s)));
+    JSValue arg = callFrame->argument(0);
+    if (arg.isCell())
+        return JSValue::encode(arg.asCell()->structure(vm)->globalObject()->globalThis());
+
+    return JSValue::encode(jsUndefined());
+}
+
 JSC_DEFINE_HOST_FUNCTION(functionDollarAgentStart, (JSGlobalObject* globalObject, CallFrame* callFrame))
 {
     VM& vm = globalObject->vm();

Modified: trunk/Source/_javascript_Core/parser/Parser.cpp (284150 => 284151)


--- trunk/Source/_javascript_Core/parser/Parser.cpp	2021-10-14 10:15:41 UTC (rev 284150)
+++ trunk/Source/_javascript_Core/parser/Parser.cpp	2021-10-14 10:22:09 UTC (rev 284151)
@@ -5096,7 +5096,7 @@
             newCount--;
             next();
         } else {
-            failIfTrue(match(IDENT), "\"new.\" can only followed with target");
+            failIfTrue(match(IDENT), "\"new.\" can only be followed with target");
             failDueToUnexpectedToken();
         }
     }
@@ -5131,7 +5131,7 @@
                 base = context.createImportMetaExpr(location, createResolveAndUseVariable(context, &m_vm.propertyNames->metaPrivateName, false, expressionStart, location));
                 next();
             } else {
-                failIfTrue(match(IDENT), "\"import.\" can only followed with meta");
+                failIfTrue(match(IDENT), "\"import.\" can only be followed with meta");
                 failDueToUnexpectedToken();
             }
         } else {

Modified: trunk/Source/_javascript_Core/runtime/CommonIdentifiers.h (284150 => 284151)


--- trunk/Source/_javascript_Core/runtime/CommonIdentifiers.h	2021-10-14 10:15:41 UTC (rev 284150)
+++ trunk/Source/_javascript_Core/runtime/CommonIdentifiers.h	2021-10-14 10:22:09 UTC (rev 284151)
@@ -52,6 +52,7 @@
     macro(Object) \
     macro(PluralRules) \
     macro(Promise) \
+    macro(ShadowRealm) \
     macro(Reflect) \
     macro(RegExp) \
     macro(RelativeTimeFormat) \

Modified: trunk/Source/_javascript_Core/runtime/IndirectEvalExecutable.cpp (284150 => 284151)


--- trunk/Source/_javascript_Core/runtime/IndirectEvalExecutable.cpp	2021-10-14 10:15:41 UTC (rev 284150)
+++ trunk/Source/_javascript_Core/runtime/IndirectEvalExecutable.cpp	2021-10-14 10:22:09 UTC (rev 284151)
@@ -34,7 +34,9 @@
 
 namespace JSC {
 
-IndirectEvalExecutable* IndirectEvalExecutable::create(JSGlobalObject* globalObject, const SourceCode& source, DerivedContextType derivedContextType, bool isArrowFunctionContext, EvalContextType evalContextType)
+
+template<typename ErrorHandlerFunctor>
+inline IndirectEvalExecutable* IndirectEvalExecutable::createImpl(JSGlobalObject* globalObject, const SourceCode& source, DerivedContextType derivedContextType, bool isArrowFunctionContext, EvalContextType evalContextType, ErrorHandlerFunctor errorHandler)
 {
     VM& vm = globalObject->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
@@ -50,7 +52,7 @@
 
     ParserError error;
     OptionSet<CodeGenerationMode> codeGenerationMode = globalObject->defaultCodeGenerationMode();
-    
+
     UnlinkedEvalCodeBlock* unlinkedEvalCode = vm.codeCache()->getUnlinkedEvalCodeBlock(
         vm, executable, executable->source(), JSParserStrictMode::NotStrict, codeGenerationMode, error, evalContextType);
 
@@ -58,7 +60,8 @@
         globalObject->debugger()->sourceParsed(globalObject, executable->source().provider(), error.line(), error.message());
 
     if (error.isValid()) {
-        throwVMError(globalObject, scope, error.toErrorObject(globalObject, executable->source()));
+        errorHandler(executable->source(), &error);
+        scope.release();
         return nullptr;
     }
 
@@ -67,6 +70,24 @@
     return executable;
 }
 
+IndirectEvalExecutable* IndirectEvalExecutable::create(JSGlobalObject* globalObject, const SourceCode& source, DerivedContextType derivedContextType, bool isArrowFunctionContext, EvalContextType evalContextType, NakedPtr<JSObject>& resultingError)
+{
+    auto handleError = [&](const SourceCode& source, ParserError* error) {
+        resultingError = error->toErrorObject(globalObject, source);
+    };
+    return createImpl(globalObject, source, derivedContextType, isArrowFunctionContext, evalContextType, handleError);
+}
+
+IndirectEvalExecutable* IndirectEvalExecutable::tryCreate(JSGlobalObject* globalObject, const SourceCode& source, DerivedContextType derivedContextType, bool isArrowFunctionContext, EvalContextType evalContextType)
+{
+    VM& vm = globalObject->vm();
+    auto handleError = [&](const SourceCode& source, ParserError* error) {
+        auto scope = DECLARE_THROW_SCOPE(vm);
+        throwVMError(globalObject, scope, error->toErrorObject(globalObject, source));
+    };
+    return createImpl(globalObject, source, derivedContextType, isArrowFunctionContext, evalContextType, handleError);
+}
+
 constexpr bool inStrictContext = false;
 constexpr bool insideOrdinaryFunction = false;
 IndirectEvalExecutable::IndirectEvalExecutable(JSGlobalObject* globalObject, const SourceCode& source, DerivedContextType derivedContextType, bool isArrowFunctionContext, EvalContextType evalContextType)

Modified: trunk/Source/_javascript_Core/runtime/IndirectEvalExecutable.h (284150 => 284151)


--- trunk/Source/_javascript_Core/runtime/IndirectEvalExecutable.h	2021-10-14 10:15:41 UTC (rev 284150)
+++ trunk/Source/_javascript_Core/runtime/IndirectEvalExecutable.h	2021-10-14 10:22:09 UTC (rev 284151)
@@ -31,8 +31,12 @@
 
 class IndirectEvalExecutable final : public EvalExecutable {
 public:
-    static IndirectEvalExecutable* create(JSGlobalObject*, const SourceCode&, DerivedContextType, bool isArrowFunctionContext, EvalContextType);
+    static IndirectEvalExecutable* tryCreate(JSGlobalObject*, const SourceCode&, DerivedContextType, bool isArrowFunctionContext, EvalContextType);
+    static IndirectEvalExecutable* create(JSGlobalObject*, const SourceCode&, DerivedContextType, bool isArrowFunctionContext, EvalContextType, NakedPtr<JSObject>&);
 private:
+    template<typename ErrorHandlerFunctor>
+    inline static IndirectEvalExecutable* createImpl(JSGlobalObject*, const SourceCode&, DerivedContextType, bool isArrowFunctionContext, EvalContextType, ErrorHandlerFunctor);
+
     IndirectEvalExecutable(JSGlobalObject*, const SourceCode&, DerivedContextType, bool isArrowFunctionContext, EvalContextType);
 };
 

Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp (284150 => 284151)


--- trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp	2021-10-14 10:15:41 UTC (rev 284150)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp	2021-10-14 10:22:09 UTC (rev 284151)
@@ -196,6 +196,9 @@
 #include "SetConstructor.h"
 #include "SetIteratorPrototype.h"
 #include "SetPrototype.h"
+#include "ShadowRealmConstructor.h"
+#include "ShadowRealmObject.h"
+#include "ShadowRealmPrototype.h"
 #include "StrictEvalActivation.h"
 #include "StringConstructor.h"
 #include "StringIteratorPrototype.h"
@@ -924,6 +927,9 @@
     for (unsigned i = 0; i < NumberOfArrayIndexingModes; ++i)
         m_arrayStructureForIndexingShapeDuringAllocation[i] = m_originalArrayStructureForIndexingShape[i];
 
+    m_shadowRealmPrototype.set(vm, this, ShadowRealmPrototype::create(vm, ShadowRealmPrototype::createStructure(vm, this, m_objectPrototype.get())));
+    m_shadowRealmObjectStructure.set(vm, this, ShadowRealmObject::createStructure(vm, this, m_shadowRealmPrototype.get()));
+
     m_regExpPrototype.set(vm, this, RegExpPrototype::create(vm, this, RegExpPrototype::createStructure(vm, this, m_objectPrototype.get())));
     m_regExpStructure.set(vm, this, RegExpObject::createStructure(vm, this, m_regExpPrototype.get()));
     m_regExpMatchesArrayStructure.set(vm, this, createRegExpMatchesArrayStructure(vm, this));
@@ -1030,7 +1036,10 @@
     ArrayConstructor* arrayConstructor = ArrayConstructor::create(vm, this, ArrayConstructor::createStructure(vm, this, m_functionPrototype.get()), m_arrayPrototype.get(), m_speciesGetterSetter.get());
     m_arrayConstructor.set(vm, this, arrayConstructor);
     m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::Array)].set(vm, this, arrayConstructor);
-    
+
+    ShadowRealmConstructor* shadowRealmConstructor = ShadowRealmConstructor::create(vm, ShadowRealmConstructor::createStructure(vm, this, m_functionPrototype.get()), m_shadowRealmPrototype.get(), m_speciesGetterSetter.get());
+    m_shadowRealmConstructor.set(vm, this, shadowRealmConstructor);
+
     RegExpConstructor* regExpConstructor = RegExpConstructor::create(vm, RegExpConstructor::createStructure(vm, this, m_functionPrototype.get()), m_regExpPrototype.get(), m_speciesGetterSetter.get());
     m_regExpConstructor.set(vm, this, regExpConstructor);
     m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::RegExp)].set(vm, this, regExpConstructor);
@@ -1110,6 +1119,7 @@
     m_functionPrototype->putDirectWithoutTransition(vm, vm.propertyNames->constructor, functionConstructor, static_cast<unsigned>(PropertyAttribute::DontEnum));
     m_arrayPrototype->putDirectWithoutTransition(vm, vm.propertyNames->constructor, arrayConstructor, static_cast<unsigned>(PropertyAttribute::DontEnum));
     m_regExpPrototype->putDirectWithoutTransition(vm, vm.propertyNames->constructor, regExpConstructor, static_cast<unsigned>(PropertyAttribute::DontEnum));
+    m_shadowRealmPrototype->putDirectWithoutTransition(vm, vm.propertyNames->constructor, shadowRealmConstructor, static_cast<unsigned>(PropertyAttribute::DontEnum));
     
     putDirectWithoutTransition(vm, vm.propertyNames->Object, objectConstructor, static_cast<unsigned>(PropertyAttribute::DontEnum));
     putDirectWithoutTransition(vm, vm.propertyNames->Function, functionConstructor, static_cast<unsigned>(PropertyAttribute::DontEnum));
@@ -1261,6 +1271,8 @@
         TemporalObject* temporal = TemporalObject::create(vm, TemporalObject::createStructure(vm, this));
         putDirectWithoutTransition(vm, vm.propertyNames->Temporal, temporal, static_cast<unsigned>(PropertyAttribute::DontEnum));
     }
+    if (Options::useShadowRealm())
+        putDirectWithoutTransition(vm, vm.propertyNames->ShadowRealm, shadowRealmConstructor, static_cast<unsigned>(PropertyAttribute::DontEnum));
 
     m_moduleLoader.initLater(
         [] (const Initializer<JSModuleLoader>& init) {
@@ -1433,6 +1445,12 @@
     m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::hostPromiseRejectionTracker)].initLater([] (const Initializer<JSCell>& init) {
             init.set(JSFunction::create(init.vm, jsCast<JSGlobalObject*>(init.owner), 2, String(), globalFuncHostPromiseRejectionTracker));
         });
+    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::importInRealm)].initLater([] (const Initializer<JSCell>& init) {
+            init.set(JSFunction::create(init.vm, jsCast<JSGlobalObject*>(init.owner), 0, String(), importInRealm));
+        });
+    m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::evalInRealm)].initLater([] (const Initializer<JSCell>& init) {
+            init.set(JSFunction::create(init.vm, jsCast<JSGlobalObject*>(init.owner), 0, String(), evalInRealm));
+        });
     m_linkTimeConstants[static_cast<unsigned>(LinkTimeConstant::thisTimeValue)].initLater([] (const Initializer<JSCell>& init) {
             init.set(JSFunction::create(init.vm, jsCast<JSGlobalObject*>(init.owner), 0, String(), dateProtoFuncGetTime, DatePrototypeGetTimeIntrinsic));
         });
@@ -2117,6 +2135,7 @@
     thisObject->m_URIErrorStructure.visit(visitor);
     thisObject->m_aggregateErrorStructure.visit(visitor);
     visitor.append(thisObject->m_arrayConstructor);
+    visitor.append(thisObject->m_shadowRealmConstructor);
     visitor.append(thisObject->m_regExpConstructor);
     visitor.append(thisObject->m_objectConstructor);
     visitor.append(thisObject->m_functionConstructor);
@@ -2214,6 +2233,7 @@
     thisObject->m_customSetterFunctionStructure.visit(visitor);
     thisObject->m_boundFunctionStructure.visit(visitor);
     thisObject->m_nativeStdFunctionStructure.visit(visitor);
+    visitor.append(thisObject->m_shadowRealmObjectStructure);
     visitor.append(thisObject->m_regExpStructure);
     visitor.append(thisObject->m_generatorFunctionStructure);
     visitor.append(thisObject->m_asyncFunctionStructure);
@@ -2570,6 +2590,13 @@
     return globalObject;
 }
 
+JSGlobalObject* JSGlobalObject::createWithCustomMethodTable(VM& vm, Structure* structure, const GlobalObjectMethodTable* methodTable)
+{
+    JSGlobalObject* globalObject = new (NotNull, allocateCell<JSGlobalObject>(vm.heap)) JSGlobalObject(vm, structure, methodTable);
+    globalObject->finishCreation(vm);
+    return globalObject;
+}
+
 void JSGlobalObject::finishCreation(VM& vm)
 {
     DeferTermination deferTermination(vm);

Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObject.h (284150 => 284151)


--- trunk/Source/_javascript_Core/runtime/JSGlobalObject.h	2021-10-14 10:15:41 UTC (rev 284150)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObject.h	2021-10-14 10:22:09 UTC (rev 284151)
@@ -115,6 +115,8 @@
 class ObjectConstructor;
 class ProgramCodeBlock;
 class ProgramExecutable;
+class ShadowRealmConstructor;
+class ShadowRealmPrototype;
 class RegExpConstructor;
 class RegExpPrototype;
 class SetIteratorPrototype;
@@ -311,6 +313,7 @@
 
     WriteBarrier<ObjectConstructor> m_objectConstructor;
     WriteBarrier<ArrayConstructor> m_arrayConstructor;
+    WriteBarrier<ShadowRealmConstructor> m_shadowRealmConstructor;
     WriteBarrier<RegExpConstructor> m_regExpConstructor;
     WriteBarrier<FunctionConstructor> m_functionConstructor;
     WriteBarrier<JSPromiseConstructor> m_promiseConstructor;
@@ -358,6 +361,7 @@
     WriteBarrier<ObjectPrototype> m_objectPrototype;
     WriteBarrier<FunctionPrototype> m_functionPrototype;
     WriteBarrier<ArrayPrototype> m_arrayPrototype;
+    WriteBarrier<ShadowRealmPrototype> m_shadowRealmPrototype;
     WriteBarrier<RegExpPrototype> m_regExpPrototype;
     WriteBarrier<IteratorPrototype> m_iteratorPrototype;
     WriteBarrier<AsyncIteratorPrototype> m_asyncIteratorPrototype;
@@ -414,6 +418,7 @@
     LazyProperty<JSGlobalObject, Structure> m_customSetterFunctionStructure;
     LazyProperty<JSGlobalObject, Structure> m_nativeStdFunctionStructure;
     PropertyOffset m_functionNameOffset;
+    WriteBarrier<Structure> m_shadowRealmObjectStructure;
     WriteBarrier<Structure> m_regExpStructure;
     WriteBarrier<AsyncFunctionPrototype> m_asyncFunctionPrototype;
     WriteBarrier<AsyncGeneratorFunctionPrototype> m_asyncGeneratorFunctionPrototype;
@@ -616,6 +621,7 @@
     }
 
     JS_EXPORT_PRIVATE static JSGlobalObject* create(VM&, Structure*);
+    JS_EXPORT_PRIVATE static JSGlobalObject* createWithCustomMethodTable(VM&, Structure*, const GlobalObjectMethodTable*);
 
     DECLARE_EXPORT_INFO;
 
@@ -720,6 +726,7 @@
     BigIntPrototype* bigIntPrototype() const { return m_bigIntPrototype.get(); }
     JSObject* datePrototype() const { return m_dateStructure.prototype(this); }
     JSObject* symbolPrototype() const { return m_symbolObjectStructure.prototypeInitializedOnMainThread(this); }
+    ShadowRealmPrototype* shadowRealmPrototype() const { return m_shadowRealmPrototype.get(); }
     RegExpPrototype* regExpPrototype() const { return m_regExpPrototype.get(); }
     JSObject* errorPrototype() const { return m_errorStructure.prototype(this); }
     IteratorPrototype* iteratorPrototype() const { return m_iteratorPrototype.get(); }
@@ -837,6 +844,7 @@
     PropertyOffset functionNameOffset() const { return m_functionNameOffset; }
     Structure* numberObjectStructure() const { return m_numberObjectStructure.get(this); }
     Structure* regExpStructure() const { return m_regExpStructure.get(); }
+    Structure* shadowRealmStructure() const { return m_shadowRealmObjectStructure.get(); }
     Structure* generatorStructure() const { return m_generatorStructure.get(); }
     Structure* asyncGeneratorStructure() const { return m_asyncGeneratorStructure.get(); }
     Structure* generatorFunctionStructure() const { return m_generatorFunctionStructure.get(); }

Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObjectFunctions.cpp (284150 => 284151)


--- trunk/Source/_javascript_Core/runtime/JSGlobalObjectFunctions.cpp	2021-10-14 10:15:41 UTC (rev 284150)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObjectFunctions.cpp	2021-10-14 10:22:09 UTC (rev 284151)
@@ -492,7 +492,7 @@
         return JSValue::encode(parsedObject);
 
     SourceOrigin sourceOrigin = callFrame->callerSourceOrigin(vm);
-    EvalExecutable* eval = IndirectEvalExecutable::create(globalObject, makeSource(s, sourceOrigin), DerivedContextType::None, false, EvalContextType::None);
+    EvalExecutable* eval = IndirectEvalExecutable::tryCreate(globalObject, makeSource(s, sourceOrigin), DerivedContextType::None, false, EvalContextType::None);
     EXCEPTION_ASSERT(!!scope.exception() == !eval);
     if (!eval)
         return encodedJSValue();

Modified: trunk/Source/_javascript_Core/runtime/JSType.cpp (284150 => 284151)


--- trunk/Source/_javascript_Core/runtime/JSType.cpp	2021-10-14 10:15:41 UTC (rev 284150)
+++ trunk/Source/_javascript_Core/runtime/JSType.cpp	2021-10-14 10:22:09 UTC (rev 284151)
@@ -96,6 +96,7 @@
     CASE(StrictEvalActivationType)
     CASE(WithScopeType)
     CASE(ModuleNamespaceObjectType)
+    CASE(ShadowRealmType)
     CASE(RegExpObjectType)
     CASE(JSDateType)
     CASE(ProxyObjectType)

Modified: trunk/Source/_javascript_Core/runtime/JSType.h (284150 => 284151)


--- trunk/Source/_javascript_Core/runtime/JSType.h	2021-10-14 10:15:41 UTC (rev 284150)
+++ trunk/Source/_javascript_Core/runtime/JSType.h	2021-10-14 10:22:09 UTC (rev 284151)
@@ -110,6 +110,7 @@
     // End JSScope types.
 
     ModuleNamespaceObjectType,
+    ShadowRealmType,
     RegExpObjectType,
     JSDateType,
     ProxyObjectType,

Modified: trunk/Source/_javascript_Core/runtime/OptionsList.h (284150 => 284151)


--- trunk/Source/_javascript_Core/runtime/OptionsList.h	2021-10-14 10:15:41 UTC (rev 284150)
+++ trunk/Source/_javascript_Core/runtime/OptionsList.h	2021-10-14 10:22:09 UTC (rev 284151)
@@ -540,6 +540,8 @@
     v(Bool, useHasOwn, true, Normal, "Expose the Object.hasOwn method") \
     v(Bool, useIntlEnumeration, true, Normal, "Expose the Intl enumeration APIs.") \
     v(Bool, useSharedArrayBuffer, false, Normal, nullptr) \
+    /* FIXME: ShadownRealm can be enabled once WebCore's JSGlobalObject == JSDOMGlobalObject assumption is removed,  https://bugs.webkit.org/show_bug.cgi?id=231506 */\
+    v(Bool, useShadowRealm, false, Normal, "Expose the ShadowRealm object.") \
     v(Bool, useTemporal, false, Normal, "Expose the Temporal object.") \
     v(Bool, useWebAssemblyThreading, true, Normal, "Allow instructions from the wasm threading spec.") \
     v(Bool, useWebAssemblyTypedFunctionReferences, false, Normal, "Allow function types from the wasm typed function references spec.") \

Added: trunk/Source/_javascript_Core/runtime/ShadowRealmConstructor.cpp (0 => 284151)


--- trunk/Source/_javascript_Core/runtime/ShadowRealmConstructor.cpp	                        (rev 0)
+++ trunk/Source/_javascript_Core/runtime/ShadowRealmConstructor.cpp	2021-10-14 10:22:09 UTC (rev 284151)
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2021 Igalia S.L.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ShadowRealmConstructor.h"
+
+#include "JSCInlines.h"
+#include "ShadowRealmObject.h"
+
+namespace JSC {
+
+const ClassInfo ShadowRealmConstructor::s_info = { "Function", &InternalFunction::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(ShadowRealmConstructor) };
+
+STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(ShadowRealmConstructor);
+
+static JSC_DECLARE_HOST_FUNCTION(callShadowRealm);
+static JSC_DECLARE_HOST_FUNCTION(constructWithShadowRealmConstructor);
+
+ShadowRealmConstructor::ShadowRealmConstructor(VM& vm, Structure* structure)
+    : InternalFunction(vm, structure, callShadowRealm, constructWithShadowRealmConstructor)
+{
+}
+
+void ShadowRealmConstructor::finishCreation(VM& vm, ShadowRealmPrototype* shadowRealmPrototype)
+{
+    Base::finishCreation(vm, 0, vm.propertyNames->ShadowRealm.string(), PropertyAdditionMode::WithoutStructureTransition);
+    putDirectWithoutTransition(vm, vm.propertyNames->prototype, shadowRealmPrototype, PropertyAttribute::DontEnum | PropertyAttribute::DontDelete | PropertyAttribute::ReadOnly);
+}
+
+JSC_DEFINE_HOST_FUNCTION(constructWithShadowRealmConstructor, (JSGlobalObject* globalObject, CallFrame*))
+{
+    VM& vm = globalObject->vm();
+    Structure* shadowRealmStructure = ShadowRealmObject::createStructure(vm, globalObject, globalObject->shadowRealmPrototype());
+    JSObject* shadowRealmObject = ShadowRealmObject::create(vm, shadowRealmStructure, globalObject->globalObjectMethodTable());
+    return JSValue::encode(shadowRealmObject);
+}
+
+JSC_DEFINE_HOST_FUNCTION(callShadowRealm, (JSGlobalObject* globalObject, CallFrame*))
+{
+    auto scope = DECLARE_THROW_SCOPE(globalObject->vm());
+    return JSValue::encode(throwConstructorCannotBeCalledAsFunctionTypeError(globalObject, scope, "ShadowRealm"));
+}
+
+} // namespace JSC

Added: trunk/Source/_javascript_Core/runtime/ShadowRealmConstructor.h (0 => 284151)


--- trunk/Source/_javascript_Core/runtime/ShadowRealmConstructor.h	                        (rev 0)
+++ trunk/Source/_javascript_Core/runtime/ShadowRealmConstructor.h	2021-10-14 10:22:09 UTC (rev 284151)
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2021 Igalia S.L.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "InternalFunction.h"
+#include "ShadowRealmPrototype.h"
+
+namespace JSC {
+
+class GetterSetter;
+
+class ShadowRealmConstructor final : public InternalFunction {
+public:
+    typedef InternalFunction Base;
+    static constexpr unsigned StructureFlags = Base::StructureFlags;
+
+    static ShadowRealmConstructor* create(VM& vm, Structure* structure, ShadowRealmPrototype* shadowRealmPrototype, GetterSetter*)
+    {
+        ShadowRealmConstructor* constructor = new (NotNull, allocateCell<ShadowRealmConstructor>(vm.heap)) ShadowRealmConstructor(vm, structure);
+        constructor->finishCreation(vm, shadowRealmPrototype);
+        return constructor;
+    }
+
+    DECLARE_INFO;
+
+    static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
+    {
+        return Structure::create(vm, globalObject, prototype, TypeInfo(InternalFunctionType, StructureFlags), info());
+    }
+
+private:
+    ShadowRealmConstructor(VM&, Structure*);
+    void finishCreation(VM&, ShadowRealmPrototype*);
+};
+STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(ShadowRealmConstructor, InternalFunction);
+
+} // namespace JSC
+

Added: trunk/Source/_javascript_Core/runtime/ShadowRealmObject.cpp (0 => 284151)


--- trunk/Source/_javascript_Core/runtime/ShadowRealmObject.cpp	                        (rev 0)
+++ trunk/Source/_javascript_Core/runtime/ShadowRealmObject.cpp	2021-10-14 10:22:09 UTC (rev 284151)
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2021 Igalia S.L.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ShadowRealmObject.h"
+
+namespace JSC {
+
+STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(ShadowRealmObject);
+
+} // namespace JSC
+
+namespace JSC {
+
+const ClassInfo ShadowRealmObject::s_info = { "ShadowRealm", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(ShadowRealmObject) };
+
+ShadowRealmObject::ShadowRealmObject(VM& vm, Structure* structure)
+    : Base(vm, structure)
+{
+}
+
+template<typename Visitor>
+void ShadowRealmObject::visitChildrenImpl(JSCell* cell, Visitor& visitor)
+{
+    ShadowRealmObject* thisObject = jsCast<ShadowRealmObject*>(cell);
+    ASSERT_GC_OBJECT_INHERITS(thisObject, info());
+    Base::visitChildren(thisObject, visitor);
+
+    visitor.append(thisObject->m_globalObject);
+}
+
+DEFINE_VISIT_CHILDREN(ShadowRealmObject);
+
+ShadowRealmObject* ShadowRealmObject::create(VM& vm, Structure* structure, const GlobalObjectMethodTable* methodTable)
+{
+    ShadowRealmObject* object = new (NotNull, allocateCell<ShadowRealmObject>(vm.heap)) ShadowRealmObject(vm, structure);
+    object->finishCreation(vm);
+    JSGlobalObject* globalObject = JSGlobalObject::createWithCustomMethodTable(vm, JSGlobalObject::createStructure(vm, jsNull()), methodTable);
+    object->m_globalObject.set(vm, object, globalObject);
+    return object;
+}
+
+void ShadowRealmObject::finishCreation(VM& vm)
+{
+    Base::finishCreation(vm);
+    ASSERT(inherits(vm, info()));
+    JSC_TO_STRING_TAG_WITHOUT_TRANSITION();
+}
+
+} // namespace JSC

Added: trunk/Source/_javascript_Core/runtime/ShadowRealmObject.h (0 => 284151)


--- trunk/Source/_javascript_Core/runtime/ShadowRealmObject.h	                        (rev 0)
+++ trunk/Source/_javascript_Core/runtime/ShadowRealmObject.h	2021-10-14 10:22:09 UTC (rev 284151)
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2021 Igalia S.L.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "JSCJSValueInlines.h"
+#include "JSObject.h"
+
+namespace JSC {
+
+class ShadowRealmObject final : public JSNonFinalObject {
+public:
+    using Base = JSNonFinalObject;
+    static constexpr unsigned StructureFlags = Base::StructureFlags;
+
+    template<typename CellType, SubspaceAccess mode>
+    static IsoSubspace* subspaceFor(VM& vm)
+    {
+        return vm.shadowRealmSpace<mode>();
+    }
+
+    static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
+    {
+        return Structure::create(vm, globalObject, prototype, TypeInfo(ShadowRealmType, StructureFlags), info());
+    }
+
+    DECLARE_INFO;
+
+    static ShadowRealmObject* create(VM&, Structure*, const GlobalObjectMethodTable*);
+
+    JSGlobalObject* globalObject() { return m_globalObject.get(); }
+
+private:
+    ShadowRealmObject(VM&, Structure*);
+    void finishCreation(VM&);
+    DECLARE_VISIT_CHILDREN;
+
+    WriteBarrier<JSGlobalObject> m_globalObject;
+};
+
+} // namespace JSC

Added: trunk/Source/_javascript_Core/runtime/ShadowRealmPrototype.cpp (0 => 284151)


--- trunk/Source/_javascript_Core/runtime/ShadowRealmPrototype.cpp	                        (rev 0)
+++ trunk/Source/_javascript_Core/runtime/ShadowRealmPrototype.cpp	2021-10-14 10:22:09 UTC (rev 284151)
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2021 Igalia S.L.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ShadowRealmPrototype.h"
+
+#include "IndirectEvalExecutable.h"
+#include "Interpreter.h"
+#include "JSGlobalObject.h"
+#include "JSInternalPromise.h"
+#include "JSModuleLoader.h"
+#include "ShadowRealmObject.h"
+
+#include "ShadowRealmPrototype.lut.h"
+
+namespace JSC {
+
+/* Source for ShadowRealmPrototype.lut.h
+@begin shadowRealmPrototypeTable
+  evaluate    JSBuiltin     DontEnum|Function  1
+  importValue JSBuiltin     DontEnum|Function  2
+@end
+*/
+
+const ClassInfo ShadowRealmPrototype::s_info = { "ShadowRealm", &Base::s_info, &shadowRealmPrototypeTable, nullptr, CREATE_METHOD_TABLE(ShadowRealmPrototype) };
+
+ShadowRealmPrototype::ShadowRealmPrototype(VM& vm, Structure* structure)
+    : JSNonFinalObject(vm, structure)
+{
+}
+
+void ShadowRealmPrototype::finishCreation(VM& vm)
+{
+    Base::finishCreation(vm);
+    ASSERT(inherits(vm, info()));
+    JSC_TO_STRING_TAG_WITHOUT_TRANSITION();
+}
+
+JSC_DEFINE_HOST_FUNCTION(importInRealm, (JSGlobalObject* globalObject, CallFrame* callFrame))
+{
+    VM& vm = globalObject->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
+    JSValue thisValue = callFrame->uncheckedArgument(0);
+    ShadowRealmObject* thisRealm = jsDynamicCast<ShadowRealmObject*>(vm, thisValue);
+    ASSERT(thisRealm);
+
+    auto* promise = JSPromise::create(vm, globalObject->promiseStructure());
+
+    auto sourceOrigin = callFrame->callerSourceOrigin(vm);
+    auto* specifier = callFrame->uncheckedArgument(1).toString(globalObject);
+    RETURN_IF_EXCEPTION(scope, { });
+
+    JSGlobalObject* realmGlobalObject = thisRealm->globalObject();
+    auto* internalPromise = realmGlobalObject->moduleLoader()->importModule(realmGlobalObject, specifier, jsUndefined(), sourceOrigin);
+    RETURN_IF_EXCEPTION(scope, JSValue::encode(promise->rejectWithCaughtException(realmGlobalObject, scope)));
+
+    scope.release();
+    promise->resolve(globalObject, internalPromise);
+    return JSValue::encode(promise);
+}
+
+JSC_DEFINE_HOST_FUNCTION(evalInRealm, (JSGlobalObject* globalObject, CallFrame* callFrame))
+{
+    VM& vm = globalObject->vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
+    JSValue thisValue = callFrame->argument(0);
+    ShadowRealmObject* thisRealm = jsDynamicCast<ShadowRealmObject*>(vm, thisValue);
+    ASSERT(thisRealm);
+    JSGlobalObject* realmGlobalObject = thisRealm->globalObject();
+
+    JSValue evalArg = callFrame->argument(1);
+    // eval code adapted from JSGlobalObjecFunctions::globalFuncEval
+    String script = asString(evalArg)->value(globalObject);
+    RETURN_IF_EXCEPTION(scope, { });
+
+    NakedPtr<JSObject> executableError;
+    SourceCode source = makeSource(script, callFrame->callerSourceOrigin(vm));
+    EvalExecutable* eval = IndirectEvalExecutable::create(realmGlobalObject, source, DerivedContextType::None, false, EvalContextType::None, executableError);
+    if (executableError) {
+        ErrorInstance* error = jsDynamicCast<ErrorInstance*>(vm, JSValue(executableError.get()));
+        if (error != nullptr && error->errorType() == ErrorType::SyntaxError) {
+            scope.clearException();
+            const String syntaxErrorMessage = error->sanitizedMessageString(globalObject);
+            RETURN_IF_EXCEPTION(scope, { });
+            throwVMError(globalObject, scope, createSyntaxError(globalObject, syntaxErrorMessage));
+        } else
+            throwVMError(globalObject, scope, createTypeError(globalObject, "Error encountered during evaluation"_s));
+        return JSValue::encode(jsUndefined());
+    }
+    RETURN_IF_EXCEPTION(scope, { });
+
+    JSValue result = vm.interpreter->execute(eval, realmGlobalObject, realmGlobalObject->globalThis(), realmGlobalObject->globalScope());
+    if (UNLIKELY(scope.exception())) {
+        scope.clearException();
+        return throwVMError(globalObject, scope, createTypeError(globalObject, "Error encountered during evaluation"_s));
+    }
+
+    RELEASE_AND_RETURN(scope, JSValue::encode(result));
+}
+
+} // namespace JSC

Added: trunk/Source/_javascript_Core/runtime/ShadowRealmPrototype.h (0 => 284151)


--- trunk/Source/_javascript_Core/runtime/ShadowRealmPrototype.h	                        (rev 0)
+++ trunk/Source/_javascript_Core/runtime/ShadowRealmPrototype.h	2021-10-14 10:22:09 UTC (rev 284151)
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2021 Igalia S.L.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "JSObject.h"
+
+namespace JSC {
+
+class ShadowRealmPrototype final : public JSNonFinalObject {
+public:
+    using Base = JSNonFinalObject;
+    static constexpr unsigned StructureFlags = Base::StructureFlags | HasStaticPropertyTable;
+
+    template<typename CellType, SubspaceAccess>
+    static IsoSubspace* subspaceFor(VM& vm)
+    {
+        STATIC_ASSERT_ISO_SUBSPACE_SHARABLE(ShadowRealmPrototype, Base);
+        return &vm.plainObjectSpace;
+    }
+
+    static ShadowRealmPrototype* create(VM& vm, Structure* structure)
+    {
+        ShadowRealmPrototype* prototype = new (NotNull, allocateCell<ShadowRealmPrototype>(vm.heap)) ShadowRealmPrototype(vm, structure);
+        prototype->finishCreation(vm);
+        return prototype;
+    }
+
+    DECLARE_INFO;
+
+    static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
+    {
+        return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
+    }
+
+private:
+    ShadowRealmPrototype(VM&, Structure*);
+    void finishCreation(VM&);
+};
+
+JSC_DECLARE_HOST_FUNCTION(importInRealm);
+JSC_DECLARE_HOST_FUNCTION(evalInRealm);
+
+} // namespace JSC

Modified: trunk/Source/_javascript_Core/runtime/VM.cpp (284150 => 284151)


--- trunk/Source/_javascript_Core/runtime/VM.cpp	2021-10-14 10:15:41 UTC (rev 284150)
+++ trunk/Source/_javascript_Core/runtime/VM.cpp	2021-10-14 10:22:09 UTC (rev 284151)
@@ -156,6 +156,7 @@
 #include "SamplingProfiler.h"
 #include "ScopedArguments.h"
 #include "ShadowChicken.h"
+#include "ShadowRealmObject.h"
 #include "SimpleTypedArrayController.h"
 #include "SourceProviderCache.h"
 #include "StrictEvalActivation.h"
@@ -1587,6 +1588,7 @@
 DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(setBucketSpace, cellHeapCellType.get(), JSSet::BucketType)
 DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(setIteratorSpace, cellHeapCellType.get(), JSSetIterator)
 DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(setSpace, cellHeapCellType.get(), JSSet)
+DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(shadowRealmSpace, cellHeapCellType.get(), ShadowRealmObject)
 DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(strictEvalActivationSpace, cellHeapCellType.get(), StrictEvalActivation)
 DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(stringIteratorSpace, cellHeapCellType.get(), JSStringIterator)
 DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER_SLOW(sourceCodeSpace, destructibleCellHeapCellType.get(), JSSourceCode)

Modified: trunk/Source/_javascript_Core/runtime/VM.h (284150 => 284151)


--- trunk/Source/_javascript_Core/runtime/VM.h	2021-10-14 10:15:41 UTC (rev 284150)
+++ trunk/Source/_javascript_Core/runtime/VM.h	2021-10-14 10:22:09 UTC (rev 284151)
@@ -592,6 +592,7 @@
     DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER(setBucketSpace)
     DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER(setIteratorSpace)
     DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER(setSpace)
+    DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER(shadowRealmSpace);
     DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER(strictEvalActivationSpace)
     DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER(stringIteratorSpace)
     DYNAMIC_ISO_SUBSPACE_DEFINE_MEMBER(sourceCodeSpace)
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to