Diff
Modified: trunk/JSTests/ChangeLog (292894 => 292895)
--- trunk/JSTests/ChangeLog 2022-04-14 23:36:49 UTC (rev 292894)
+++ trunk/JSTests/ChangeLog 2022-04-14 23:39:06 UTC (rev 292895)
@@ -1,3 +1,12 @@
+2022-04-14 Caitlin Potter <ca...@igalia.com>
+
+ [JSC] ShadowRealm global object has a mutable prototype
+ https://bugs.webkit.org/show_bug.cgi?id=239332
+
+ Reviewed by Yusuke Suzuki.
+
+ * stress/shadow-realm-globalThis-mutable-prototype.js: Added.
+
2022-04-14 Alexey Shvayka <ashva...@apple.com>
InternalFunction::createSubclassStructure() should use base object's global object
Added: trunk/JSTests/stress/shadow-realm-globalThis-mutable-prototype.js (0 => 292895)
--- trunk/JSTests/stress/shadow-realm-globalThis-mutable-prototype.js (rev 0)
+++ trunk/JSTests/stress/shadow-realm-globalThis-mutable-prototype.js 2022-04-14 23:39:06 UTC (rev 292895)
@@ -0,0 +1,39 @@
+//@ requireOptions("--useShadowRealm=1")
+
+let sr = new ShadowRealm;
+
+let install = sr.evaluate(`
+(function(name, fn) {
+ globalThis[name] = fn;
+})
+`);
+
+let log = function(...args) {
+ let string = args.join(" ");
+ print(string);
+ return string;
+};
+install("log", log);
+
+// Test that the GlobalObject prototype is not immutable,
+let MAX_ITER = 10000;
+sr.evaluate(`
+ var i = 1;
+ function test() {
+ globalThis.__proto__ = { x: i++ };
+ }
+ for (let i = 0; i < ${MAX_ITER}; ++i) {
+ try {
+ test();
+ if (globalThis.x !== i + 1)
+ throw new Error(\`Prototype not written successfully (Expected globalThis.x === \${i + 1}, but found \${globalThis.x})\`);
+ } catch (e) {
+ log(\`\${e}\`);
+ throw e;
+ }
+ }
+`);
+
+if (sr.evaluate(`globalThis.x`) !== MAX_ITER)
+ throw new Error("Prototype invalid in separate eval");
+
Modified: trunk/LayoutTests/ChangeLog (292894 => 292895)
--- trunk/LayoutTests/ChangeLog 2022-04-14 23:36:49 UTC (rev 292894)
+++ trunk/LayoutTests/ChangeLog 2022-04-14 23:39:06 UTC (rev 292895)
@@ -1,3 +1,16 @@
+2022-04-14 Caitlin Potter <ca...@igalia.com>
+
+ [JSC] ShadowRealm global object has a mutable prototype
+ https://bugs.webkit.org/show_bug.cgi?id=239332
+
+ Reviewed by Yusuke Suzuki.
+
+ Add a new layout test to verify changes to verify that ShadowRealmGlobalObject has a properly
+ mutable prototype.
+
+ * js/ShadowRealm-globalThis-expected.txt: Added.
+ * js/ShadowRealm-globalThis.html: Added.
+
2022-04-14 Nikolaos Mouchtaris <nmouchta...@apple.com>
calc(): Serialize top level min/max/hypot as calc()
Added: trunk/LayoutTests/js/ShadowRealm-globalThis-expected.txt (0 => 292895)
--- trunk/LayoutTests/js/ShadowRealm-globalThis-expected.txt (rev 0)
+++ trunk/LayoutTests/js/ShadowRealm-globalThis-expected.txt 2022-04-14 23:39:06 UTC (rev 292895)
@@ -0,0 +1,12 @@
+Test to ensure correct behaviour of ShadowRealm global scope
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+Object.getPrototypeOf(globalThis) === Object.prototype
+globalThis.__proto__ = { alpha: "omega" };
+Object.setPrototypeOf(globalThis, { chuckle: "buckle" });
+Reflect.setPrototypeOf(globalThis, { zoo: "moo" });
+
+PASS ShadowRealm global scope is an ordinary object
+
Added: trunk/LayoutTests/js/ShadowRealm-globalThis.html (0 => 292895)
--- trunk/LayoutTests/js/ShadowRealm-globalThis.html (rev 0)
+++ trunk/LayoutTests/js/ShadowRealm-globalThis.html 2022-04-14 23:39:06 UTC (rev 292895)
@@ -0,0 +1,58 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"><!-- webkit-test-runner [ jscOptions=--useShadowRealm=true ] -->
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script src =""
+<script src =""
+<script>
+ description("Test to ensure correct behaviour of ShadowRealm global scope");
+
+ promise_test(async t => {
+ const bootstrap = function() {
+ const shadowRealm = new ShadowRealm;
+ const install = shadowRealm.evaluate(`(function(name, fn) {
+ globalThis[name] = fn;
+ return;
+ })`);
+ install("debug", (...args) => { debug(...args); });
+ return shadowRealm;
+ }
+
+ debug(`Object.getPrototypeOf(globalThis) === Object.prototype`);
+ let shadowRealm = bootstrap();
+ assert_equals(shadowRealm.evaluate("Object.getPrototypeOf(globalThis) === Object.prototype"), true);
+
+ debug(`globalThis.__proto__ = { alpha: "omega" };`);
+ shadowRealm.evaluate(`try {
+ globalThis.__proto__ = { alpha: "omega" };
+ "ok";
+ } catch (e) {
+ debug("Failed to set globalThis.__proto__");
+ }`);
+ assert_equals(shadowRealm.evaluate("globalThis.alpha"), "omega");
+
+ debug(`Object.setPrototypeOf(globalThis, { chuckle: "buckle" });`);
+ shadowRealm = bootstrap();
+ shadowRealm.evaluate(`try {
+ Object.setPrototypeOf(globalThis, { chuckle: "buckle" });
+ "ok";
+ } catch (e) {
+ debug("Failure in Object.setPrototypeOf(globalThis)");
+ }`);
+ assert_equals(shadowRealm.evaluate("globalThis.chuckle"), "buckle");
+
+ debug(`Reflect.setPrototypeOf(globalThis, { zoo: "moo" });`);
+ shadowRealm = bootstrap();
+ shadowRealm.evaluate(`try {
+ Reflect.setPrototypeOf(globalThis, { zoo: "moo" });
+ "ok";
+ } catch (e) {
+ debug("Failure in Reflect.setPrototypeOf(globalThis)");
+ }`);
+ assert_equals(shadowRealm.evaluate("globalThis.zoo"), "moo");
+ }, "ShadowRealm global scope is an ordinary object");
+</script>
+</body>
+</html>
Modified: trunk/Source/_javascript_Core/ChangeLog (292894 => 292895)
--- trunk/Source/_javascript_Core/ChangeLog 2022-04-14 23:36:49 UTC (rev 292894)
+++ trunk/Source/_javascript_Core/ChangeLog 2022-04-14 23:39:06 UTC (rev 292895)
@@ -1,3 +1,23 @@
+2022-04-14 Caitlin Potter <ca...@igalia.com>
+
+ [JSC] ShadowRealm global object has a mutable prototype
+ https://bugs.webkit.org/show_bug.cgi?id=239332
+
+ Reviewed by Yusuke Suzuki.
+
+ This patch circumvents the `ASSERT(toThis() == this)` in JSObject::setPrototypeWithCycleCheck()
+ when `this` is a GlobalObject. Ordinarily, GlobalObjects have the IsImmutablePrototypeExoticObject
+ bit set and miss this pathway, however this is not the case for ShadowRealm Global Objects.
+
+ In addition, the JSC internal version is also modified to have a mutable prototype in the same way
+ as in WebCore.
+
+ * runtime/JSGlobalObject.h:
+ (JSC::JSGlobalObject::deriveShadowRealmGlobalObject):
+ (JSC::JSGlobalObject::createStructureForShadowRealm):
+ * runtime/JSObject.cpp:
+ (JSC::JSObject::setPrototypeWithCycleCheck):
+
2022-04-14 Yusuke Suzuki <ysuz...@apple.com>
[JSC] Reduce use of CallFrame::deprecatedVM
Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObject.h (292894 => 292895)
--- trunk/Source/_javascript_Core/runtime/JSGlobalObject.h 2022-04-14 23:36:49 UTC (rev 292894)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObject.h 2022-04-14 23:39:06 UTC (rev 292895)
@@ -1099,7 +1099,8 @@
static JSGlobalObject* deriveShadowRealmGlobalObject(JSGlobalObject* globalObject)
{
auto& vm = globalObject->vm();
- return JSGlobalObject::createWithCustomMethodTable(vm, JSGlobalObject::createStructure(vm, jsNull()), globalObject->globalObjectMethodTable());
+ JSGlobalObject* result = JSGlobalObject::createWithCustomMethodTable(vm, JSGlobalObject::createStructureForShadowRealm(vm, jsNull()), globalObject->globalObjectMethodTable());
+ return result;
}
static bool shouldInterruptScript(const JSGlobalObject*) { return true; }
@@ -1143,6 +1144,12 @@
result->setTransitionWatchpointIsLikelyToBeFired(true);
return result;
}
+ static Structure* createStructureForShadowRealm(VM& vm, JSValue prototype)
+ {
+ Structure* result = Structure::create(vm, nullptr, prototype, TypeInfo(GlobalObjectType, StructureFlags & ~IsImmutablePrototypeExoticObject), info());
+ result->setTransitionWatchpointIsLikelyToBeFired(true);
+ return result;
+ }
void registerWeakMap(OpaqueJSWeakObjectMap* map)
{
Modified: trunk/Source/_javascript_Core/runtime/JSObject.cpp (292894 => 292895)
--- trunk/Source/_javascript_Core/runtime/JSObject.cpp 2022-04-14 23:36:49 UTC (rev 292894)
+++ trunk/Source/_javascript_Core/runtime/JSObject.cpp 2022-04-14 23:39:06 UTC (rev 292895)
@@ -1915,7 +1915,9 @@
return typeError(globalObject, scope, shouldThrowIfCantSet, "Cannot set prototype of immutable prototype object"_s);
}
- ASSERT(methodTable(vm)->toThis(this, globalObject, ECMAMode::sloppy()) == this);
+ // Default realm global objects should have mutable prototypes despite having
+ // a Proxy globalThis.
+ ASSERT(this->isGlobalObject() || methodTable(vm)->toThis(this, globalObject, ECMAMode::sloppy()) == this);
if (this->getPrototypeDirect(vm) == prototype)
return true;
Modified: trunk/Source/WebCore/ChangeLog (292894 => 292895)
--- trunk/Source/WebCore/ChangeLog 2022-04-14 23:36:49 UTC (rev 292894)
+++ trunk/Source/WebCore/ChangeLog 2022-04-14 23:39:06 UTC (rev 292895)
@@ -1,3 +1,22 @@
+2022-04-14 Caitlin Potter <ca...@igalia.com>
+
+ [JSC] ShadowRealm global object has a mutable prototype
+ https://bugs.webkit.org/show_bug.cgi?id=239332
+
+ Reviewed by Yusuke Suzuki.
+
+ Hack: The IDL code generator now special cases ShadowRealmGlobalObject to remove the
+ ImmutablePrototypeExoticObject bit from the inherited JSGlobalObject structure flags.
+
+ As a result, this enables the assignment of a ShadowRealm's globalThis.__proto__, or
+ overwriting the prototype with [Object / Reflect].setPrototypeOf().
+
+ Test: js/ShadowRealm-globalThis.html
+
+ * bindings/scripts/CodeGeneratorJS.pm:
+ (GenerateHeader):
+ * bindings/scripts/test/JS/JSShadowRealmGlobalScope.h:
+
2022-04-14 Nikolaos Mouchtaris <nmouchta...@apple.com>
calc(): Serialize top level min/max/hypot as calc()
Modified: trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm (292894 => 292895)
--- trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm 2022-04-14 23:36:49 UTC (rev 292894)
+++ trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm 2022-04-14 23:39:06 UTC (rev 292895)
@@ -3205,7 +3205,12 @@
# structure flags
if (%structureFlags) {
push(@headerContent, "public:\n");
- push(@headerContent, " static constexpr unsigned StructureFlags = Base::StructureFlags");
+ if ($interfaceName eq "ShadowRealmGlobalScope") {
+ # Hack to make ShadowRealmGlobalScope a default realm global object (not an ImmutablePrototypeExoticObject)
+ push(@headerContent, " static constexpr unsigned StructureFlags = (Base::StructureFlags & ~JSC::IsImmutablePrototypeExoticObject)");
+ } else {
+ push(@headerContent, " static constexpr unsigned StructureFlags = Base::StructureFlags");
+ }
foreach my $structureFlag (sort (keys %structureFlags)) {
push(@headerContent, " | " . $structureFlag);
}
Modified: trunk/Source/WebCore/bindings/scripts/test/JS/JSShadowRealmGlobalScope.h (292894 => 292895)
--- trunk/Source/WebCore/bindings/scripts/test/JS/JSShadowRealmGlobalScope.h 2022-04-14 23:36:49 UTC (rev 292894)
+++ trunk/Source/WebCore/bindings/scripts/test/JS/JSShadowRealmGlobalScope.h 2022-04-14 23:39:06 UTC (rev 292895)
@@ -57,7 +57,7 @@
static JSC::GCClient::IsoSubspace* subspaceForImpl(JSC::VM& vm);
static void analyzeHeap(JSCell*, JSC::HeapAnalyzer&);
public:
- static constexpr unsigned StructureFlags = Base::StructureFlags | JSC::HasStaticPropertyTable;
+ static constexpr unsigned StructureFlags = (Base::StructureFlags & ~JSC::IsImmutablePrototypeExoticObject) | JSC::HasStaticPropertyTable;
protected:
JSShadowRealmGlobalScope(JSC::VM&, JSC::Structure*, Ref<ShadowRealmGlobalScope>&&);
void finishCreation(JSC::VM&, JSC::JSProxy*);