Store global proxy object in CJS_Document

Avoid leaking actual global object back to V8 during callbacks. This
triggered a DCHECK() in some recent V8 versions.

Bug: chromium:1418955
Change-Id: Iad6173dcd2ac8dd49fb3d6c95825fa7fe9889edb
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/104630
Reviewed-by: Nigi <nigi@chromium.org>
Commit-Queue: Tom Sepez <tsepez@chromium.org>
diff --git a/fxjs/cfxjs_engine.cpp b/fxjs/cfxjs_engine.cpp
index 294452a..2ff6301 100644
--- a/fxjs/cfxjs_engine.cpp
+++ b/fxjs/cfxjs_engine.cpp
@@ -236,9 +236,11 @@
     return scope.Escape(m_Signature.Get(GetIsolate()));
   }
 
-  void RunConstructor(CFXJS_Engine* pEngine, v8::Local<v8::Object> obj) {
+  void RunConstructor(CFXJS_Engine* pEngine,
+                      v8::Local<v8::Object> obj,
+                      v8::Local<v8::Object> proxy) {
     if (m_pConstructor)
-      m_pConstructor(pEngine, obj);
+      m_pConstructor(pEngine, obj, proxy);
   }
 
   void RunDestructor(v8::Local<v8::Object> obj) {
@@ -522,15 +524,8 @@
   for (uint32_t i = 1; i <= maxID; ++i) {
     CFXJS_ObjDefinition* pObjDef = pIsolateData->ObjDefinitionForID(i);
     if (pObjDef->GetObjType() == FXJSOBJTYPE_GLOBAL) {
-      CFXJS_PerObjectData::SetInObject(new CFXJS_PerObjectData(i),
-                                       v8Context->Global()
-                                           ->GetPrototype()
-                                           ->ToObject(v8Context)
-                                           .ToLocalChecked());
-      pObjDef->RunConstructor(this, v8Context->Global()
-                                        ->GetPrototype()
-                                        ->ToObject(v8Context)
-                                        .ToLocalChecked());
+      CFXJS_PerObjectData::SetInObject(new CFXJS_PerObjectData(i), pThis);
+      pObjDef->RunConstructor(this, pThis, pThisProxy);
     } else if (pObjDef->GetObjType() == FXJSOBJTYPE_STATIC) {
       v8::Local<v8::String> pObjName = NewString(pObjDef->GetObjName());
       v8::Local<v8::Object> obj = NewFXJSBoundObject(i, FXJSOBJTYPE_STATIC);
@@ -625,7 +620,7 @@
 
   CFXJS_PerObjectData* pObjData = new CFXJS_PerObjectData(nObjDefnID);
   CFXJS_PerObjectData::SetInObject(pObjData, obj);
-  pObjDef->RunConstructor(this, obj);
+  pObjDef->RunConstructor(this, obj, obj);
   if (type == FXJSOBJTYPE_DYNAMIC) {
     auto* pIsolateData = FXJS_PerIsolateData::Get(GetIsolate());
     V8TemplateMap* pObjsMap = pIsolateData->GetDynamicObjsMap();
diff --git a/fxjs/cfxjs_engine.h b/fxjs/cfxjs_engine.h
index 3be3662..b0011fc 100644
--- a/fxjs/cfxjs_engine.h
+++ b/fxjs/cfxjs_engine.h
@@ -85,8 +85,9 @@
   explicit CFXJS_Engine(v8::Isolate* pIsolate);
   ~CFXJS_Engine() override;
 
-  using Constructor =
-      std::function<void(CFXJS_Engine* pEngine, v8::Local<v8::Object> obj)>;
+  using Constructor = std::function<void(CFXJS_Engine* pEngine,
+                                         v8::Local<v8::Object> obj,
+                                         v8::Local<v8::Object> proxy)>;
   using Destructor = std::function<void(v8::Local<v8::Object> obj)>;
 
   static uint32_t GetObjDefnID(v8::Local<v8::Object> pObj);
diff --git a/fxjs/cfxjs_engine_unittest.cpp b/fxjs/cfxjs_engine_unittest.cpp
index c6f01ed..8d6c36b 100644
--- a/fxjs/cfxjs_engine_unittest.cpp
+++ b/fxjs/cfxjs_engine_unittest.cpp
@@ -49,9 +49,10 @@
   // Object: 1
   engine()->DefineObj(
       "perm", FXJSOBJTYPE_DYNAMIC,
-      [](CFXJS_Engine* pEngine, v8::Local<v8::Object> obj) {
+      [](CFXJS_Engine* pEngine, v8::Local<v8::Object> obj,
+         v8::Local<v8::Object> proxy) {
         pEngine->SetObjectPrivate(obj,
-                                  std::make_unique<CJS_Object>(obj, nullptr));
+                                  std::make_unique<CJS_Object>(proxy, nullptr));
         perm_created = true;
       },
       [](v8::Local<v8::Object> obj) {
@@ -62,9 +63,10 @@
   // Object: 2
   engine()->DefineObj(
       "temp", FXJSOBJTYPE_DYNAMIC,
-      [](CFXJS_Engine* pEngine, v8::Local<v8::Object> obj) {
+      [](CFXJS_Engine* pEngine, v8::Local<v8::Object> obj,
+         v8::Local<v8::Object> proxy) {
         pEngine->SetObjectPrivate(obj,
-                                  std::make_unique<CJS_Object>(obj, nullptr));
+                                  std::make_unique<CJS_Object>(proxy, nullptr));
         temp_created = true;
       },
       [](v8::Local<v8::Object> obj) {
diff --git a/fxjs/js_define.h b/fxjs/js_define.h
index 1228c10..5b6573a 100644
--- a/fxjs/js_define.h
+++ b/fxjs/js_define.h
@@ -42,9 +42,11 @@
 // to construct native object state.
 
 template <class T>
-static void JSConstructor(CFXJS_Engine* pEngine, v8::Local<v8::Object> obj) {
+static void JSConstructor(CFXJS_Engine* pEngine,
+                          v8::Local<v8::Object> obj,
+                          v8::Local<v8::Object> proxy) {
   pEngine->SetObjectPrivate(
-      obj, std::make_unique<T>(obj, static_cast<CJS_Runtime*>(pEngine)));
+      obj, std::make_unique<T>(proxy, static_cast<CJS_Runtime*>(pEngine)));
 }
 
 // CJS_Object has virtual dtor, template not required.