From 436e551de735997b761284d6e4b9f5b472601ed3 Mon Sep 17 00:00:00 2001
From: Hakkin Lain <hakkin@github>
Date: Sat, 25 Jan 2025 09:22:39 -0800
Subject: [PATCH] Add Runtime.SetGlobalObject() method.

---
 runtime.go      |  6 +++++
 runtime_test.go | 66 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 72 insertions(+)

diff --git a/runtime.go b/runtime.go
index fe889944..047855c7 100644
--- a/runtime.go
+++ b/runtime.go
@@ -2377,6 +2377,12 @@ func (r *Runtime) GlobalObject() *Object {
 	return r.globalObject
 }
 
+// SetGlobalObject sets the global object to the given object.
+// Note, any existing references to the previous global object will continue to reference that object.
+func (r *Runtime) SetGlobalObject(object *Object) {
+	r.globalObject = object
+}
+
 // Set the specified variable in the global context.
 // Equivalent to running "name = value" in non-strict mode.
 // The value is first converted using ToValue().
diff --git a/runtime_test.go b/runtime_test.go
index 00b5523f..31e64ac2 100644
--- a/runtime_test.go
+++ b/runtime_test.go
@@ -1087,6 +1087,72 @@ func TestRuntime_ExportToObject(t *testing.T) {
 	}
 }
 
+func TestRuntime_SetGlobalObject(t *testing.T) {
+	vm := New()
+
+	_, err := vm.RunString(`var myVar = 123;`)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	oldGlobalObject := vm.GlobalObject()
+
+	newGlobalObject, err := vm.RunString(`({oldGlobalReference:globalThis});`)
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	vm.SetGlobalObject(newGlobalObject.(*Object))
+
+	if vm.GlobalObject() != newGlobalObject {
+		t.Fatal("Expected global object to be new object")
+	}
+
+	if vm.GlobalObject().Get("myVar") != nil {
+		t.Fatal("Expected myVar to be undefined")
+	}
+
+	oldGlobalReference := vm.GlobalObject().Get("oldGlobalReference")
+	if oldGlobalReference == nil {
+		t.Fatal("Expected oldGlobalReference to be defined")
+	}
+
+	if oldGlobalReference != oldGlobalObject {
+		t.Fatal("Expected reference to be to old global object")
+	}
+}
+
+func TestRuntime_SetGlobalObject_Proxy(t *testing.T) {
+	vm := New()
+
+	globalObject := vm.GlobalObject()
+
+	globalObjectProxy := vm.NewProxy(globalObject, &ProxyTrapConfig{
+		Get: func(target *Object, property string, receiver Value) (value Value) {
+			if target != globalObject {
+				t.Fatal("Expected target to be global object")
+			}
+
+			if property != "testing" {
+				t.Fatal("Expected property to be 'testing'")
+			}
+
+			return valueTrue
+		},
+	})
+
+	vm.SetGlobalObject(vm.ToValue(globalObjectProxy).(*Object))
+
+	ret, err := vm.RunString("testing")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	if ret != valueTrue {
+		t.Fatal("Expected return value to equal true")
+	}
+}
+
 func ExampleAssertFunction() {
 	vm := New()
 	_, err := vm.RunString(`