summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Groh <mail@linusgroh.de>2021-10-14 12:04:10 +0100
committerLinus Groh <mail@linusgroh.de>2021-10-14 23:02:19 +0100
commitcbbf4abb0dbb70c527e2638c6801f5d1b585b4db (patch)
treea3db5e67da7be26180d2498a48f92ed0fb5e4a45
parent2447b27d973deb7f5b66f853afe176a3ff8d5da3 (diff)
downloadserenity-cbbf4abb0dbb70c527e2638c6801f5d1b585b4db.zip
LibJS: Add a way to get from a GlobalObject to its associated Realm
This is just another workaround, but it should be much more reliable than Interpreter::realm(), especially when allocating NativeFunctions and ECMAScriptFunctionObjects: we're guaranteed to have a GlobalObject at that point, and it likely was set as the GlobalObject of a Realm and can lead us back to it. We're however not guaranteed that the VM can give us an Interpreter, which is why functions in LibWeb can be a bit crashy at the moment. We use a WeakPtr<Realm> to properly handle the unlikely case where the Realm goes away after associating a GlobalObject to it. We'll always need _something_ of this sort if we want to support OrdinaryFunctionCreate and CreateBuiltinFunction without the explicit realm argument while no JS is running, because they want to use the current Realm Record (always in the first and as fallback in the second case).
-rw-r--r--Userland/Libraries/LibJS/Runtime/GlobalObject.cpp11
-rw-r--r--Userland/Libraries/LibJS/Runtime/GlobalObject.h5
-rw-r--r--Userland/Libraries/LibJS/Runtime/Realm.cpp3
-rw-r--r--Userland/Libraries/LibJS/Runtime/Realm.h5
4 files changed, 23 insertions, 1 deletions
diff --git a/Userland/Libraries/LibJS/Runtime/GlobalObject.cpp b/Userland/Libraries/LibJS/Runtime/GlobalObject.cpp
index 48ed9b3c8d..a133fac961 100644
--- a/Userland/Libraries/LibJS/Runtime/GlobalObject.cpp
+++ b/Userland/Libraries/LibJS/Runtime/GlobalObject.cpp
@@ -65,6 +65,7 @@
#include <LibJS/Runtime/PromiseConstructor.h>
#include <LibJS/Runtime/PromisePrototype.h>
#include <LibJS/Runtime/ProxyConstructor.h>
+#include <LibJS/Runtime/Realm.h>
#include <LibJS/Runtime/ReflectObject.h>
#include <LibJS/Runtime/RegExpConstructor.h>
#include <LibJS/Runtime/RegExpPrototype.h>
@@ -318,6 +319,16 @@ void GlobalObject::visit_edges(Visitor& visitor)
#undef __JS_ENUMERATE
}
+Realm* GlobalObject::associated_realm()
+{
+ return m_associated_realm;
+}
+
+void GlobalObject::set_associated_realm(Badge<Realm>, Realm& realm)
+{
+ m_associated_realm = &realm;
+}
+
JS_DEFINE_NATIVE_FUNCTION(GlobalObject::gc)
{
#ifdef __serenity__
diff --git a/Userland/Libraries/LibJS/Runtime/GlobalObject.h b/Userland/Libraries/LibJS/Runtime/GlobalObject.h
index 321fd3aeed..32387a0eef 100644
--- a/Userland/Libraries/LibJS/Runtime/GlobalObject.h
+++ b/Userland/Libraries/LibJS/Runtime/GlobalObject.h
@@ -23,6 +23,9 @@ public:
Console& console() { return *m_console; }
+ Realm* associated_realm();
+ void set_associated_realm(Badge<Realm>, Realm&);
+
Shape* empty_object_shape() { return m_empty_object_shape; }
Shape* new_object_shape() { return m_new_object_shape; }
@@ -88,6 +91,8 @@ private:
NonnullOwnPtr<Console> m_console;
+ WeakPtr<Realm> m_associated_realm;
+
Shape* m_empty_object_shape { nullptr };
Shape* m_new_object_shape { nullptr };
Shape* m_new_ordinary_function_prototype_object_shape { nullptr };
diff --git a/Userland/Libraries/LibJS/Runtime/Realm.cpp b/Userland/Libraries/LibJS/Runtime/Realm.cpp
index 1082f0804f..eb324077be 100644
--- a/Userland/Libraries/LibJS/Runtime/Realm.cpp
+++ b/Userland/Libraries/LibJS/Runtime/Realm.cpp
@@ -14,6 +14,9 @@ void Realm::set_global_object(GlobalObject& global_object, Object* this_value)
// NOTE: Step 1 is not supported, the global object must be allocated elsewhere.
// 2. Assert: Type(globalObj) is Object.
+ // Non-standard
+ global_object.set_associated_realm({}, *this);
+
// 3. If thisValue is undefined, set thisValue to globalObj.
if (!this_value)
this_value = &global_object;
diff --git a/Userland/Libraries/LibJS/Runtime/Realm.h b/Userland/Libraries/LibJS/Runtime/Realm.h
index bd4d25d5e2..3c3820433a 100644
--- a/Userland/Libraries/LibJS/Runtime/Realm.h
+++ b/Userland/Libraries/LibJS/Runtime/Realm.h
@@ -6,6 +6,7 @@
#pragma once
+#include <AK/Weakable.h>
#include <LibJS/Heap/Cell.h>
#include <LibJS/Runtime/GlobalEnvironment.h>
#include <LibJS/Runtime/GlobalObject.h>
@@ -13,7 +14,9 @@
namespace JS {
// 9.3 Realms, https://tc39.es/ecma262/#realm-record
-class Realm final : public Cell {
+class Realm final
+ : public Cell
+ , public Weakable<Realm> {
public:
Realm() = default;