Replace PDF_ENABLE_XFA with an interface in CFXJS_Engine.

Then remove some JS calls from fpdfsdk when fxjs/xfa wants to interact
with fxjs/non-xfa, merely returning the reference itself. In turn,
we are now passing V8 locals, so the lifetime of the handle scope
must increase in the callers.

Also remove an ifdef from messages just to get more similarity
between xfa/non-xfa at the cost of a few bytes of string.

The result is no more PDF_ENABLE_XFA in fjxs.

-- Remove unused ChangeObjName().
-- Set result to undefined at method start so early returns are safer.
-- Always set up handle/isolate scopes prior to defining objects, even
   though it may not be strictly required for non-xfa.

Change-Id: Ie69077cca17d132122050073f15743ffdd1a4e07
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/59257
Commit-Queue: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
diff --git a/fpdfsdk/fpdfxfa/cpdfxfa_docenvironment.cpp b/fpdfsdk/fpdfxfa/cpdfxfa_docenvironment.cpp
index 16fd3e1..662af58 100644
--- a/fpdfsdk/fpdfxfa/cpdfxfa_docenvironment.cpp
+++ b/fpdfsdk/fpdfxfa/cpdfxfa_docenvironment.cpp
@@ -21,7 +21,6 @@
 #include "fpdfsdk/cpdfsdk_pageview.h"
 #include "fpdfsdk/fpdfxfa/cpdfxfa_context.h"
 #include "fpdfsdk/fpdfxfa/cpdfxfa_page.h"
-#include "fxjs/ijs_runtime.h"
 #include "xfa/fxfa/cxfa_ffdocview.h"
 #include "xfa/fxfa/cxfa_ffwidget.h"
 #include "xfa/fxfa/cxfa_ffwidgethandler.h"
@@ -233,7 +232,6 @@
   }
 
   pPopupRect->height = popup_height;
-
   return true;
 }
 
@@ -600,97 +598,14 @@
                                 pForm->GetHighlightColor(FormFieldType::kXFA));
 }
 
-#ifdef PDF_XFA_ELEMENT_SUBMIT_ENABLED
-bool CPDFXFA_DocEnvironment::NotifySubmit(bool bPrevOrPost) {
-  if (bPrevOrPost)
-    return OnBeforeNotifySubmit();
+IJS_Runtime* CPDFXFA_DocEnvironment::GetIJSRuntime(CXFA_FFDoc* hDoc) const {
+  if (hDoc != m_pContext->GetXFADoc())
+    return nullptr;
 
-  OnAfterNotifySubmit();
-  return true;
+  CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pContext->GetFormFillEnv();
+  return pFormFillEnv ? pFormFillEnv->GetIJSRuntime() : nullptr;
 }
 
-bool CPDFXFA_DocEnvironment::OnBeforeNotifySubmit() {
-  if (!m_pContext->ContainsXFAForm())
-    return true;
-
-  CXFA_FFDocView* docView = m_pContext->GetXFADocView();
-  if (!docView)
-    return true;
-
-  CXFA_FFWidgetHandler* pWidgetHandler = docView->GetWidgetHandler();
-  if (!pWidgetHandler)
-    return true;
-
-  auto it = docView->CreateReadyNodeIterator();
-  if (it) {
-    CXFA_EventParam Param;
-    Param.m_eType = XFA_EVENT_PreSubmit;
-    while (CXFA_Node* pNode = it->MoveToNext())
-      pWidgetHandler->ProcessEvent(pNode, &Param);
-  }
-
-  it = docView->CreateReadyNodeIterator();
-  if (!it)
-    return true;
-
-  (void)it->MoveToNext();
-  CXFA_Node* pNode = it->MoveToNext();
-
-  while (pNode) {
-    if (pNode->ProcessValidate(docView, -1) == XFA_EventError::kError) {
-      CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pContext->GetFormFillEnv();
-      if (!pFormFillEnv)
-        return false;
-
-      pFormFillEnv->JS_appAlert(WideString::FromDefANSI(IDS_XFA_Validate_Input),
-                                WideString(), JSPLATFORM_ALERT_BUTTON_OK,
-                                JSPLATFORM_ALERT_ICON_WARNING);
-      return false;
-    }
-    pNode = it->MoveToNext();
-  }
-
-  docView->UpdateDocView();
-  return true;
-}
-
-void CPDFXFA_DocEnvironment::OnAfterNotifySubmit() {
-  if (!m_pContext->ContainsXFAForm())
-    return;
-
-  if (!m_pContext->GetXFADocView())
-    return;
-
-  CXFA_FFWidgetHandler* pWidgetHandler =
-      m_pContext->GetXFADocView()->GetWidgetHandler();
-  if (!pWidgetHandler)
-    return;
-
-  auto it = m_pContext->GetXFADocView()->CreateReadyNodeIterator();
-  if (!it)
-    return;
-
-  CXFA_EventParam Param;
-  Param.m_eType = XFA_EVENT_PostSubmit;
-  CXFA_Node* pNode = it->MoveToNext();
-  while (pNode) {
-    pWidgetHandler->ProcessEvent(pNode, &Param);
-    pNode = it->MoveToNext();
-  }
-  m_pContext->GetXFADocView()->UpdateDocView();
-}
-
-bool CPDFXFA_DocEnvironment::Submit(CXFA_FFDoc* hDoc, CXFA_Submit* submit) {
-  if (!NotifySubmit(true) || !m_pContext->GetXFADocView())
-    return false;
-
-  m_pContext->GetXFADocView()->UpdateDocView();
-  bool ret = SubmitInternal(hDoc, submit);
-  NotifySubmit(false);
-  return ret;
-}
-#endif  // PDF_XFA_ELEMENT_SUBMIT_ENABLED
-
 RetainPtr<IFX_SeekableReadStream> CPDFXFA_DocEnvironment::OpenLinkedFile(
     CXFA_FFDoc* hDoc,
     const WideString& wsLink) {
@@ -707,6 +622,83 @@
   return MakeSeekableStream(pFileHandler);
 }
 
+#ifdef PDF_XFA_ELEMENT_SUBMIT_ENABLED
+bool CPDFXFA_DocEnvironment::Submit(CXFA_FFDoc* hDoc, CXFA_Submit* submit) {
+  if (!NotifySubmit(true) || !m_pContext->GetXFADocView())
+    return false;
+
+  m_pContext->GetXFADocView()->UpdateDocView();
+  bool ret = SubmitInternal(hDoc, submit);
+  NotifySubmit(false);
+  return ret;
+}
+#endif  // PDF_XFA_ELEMENT_SUBMIT_ENABLED
+
+bool CPDFXFA_DocEnvironment::MailToInfo(WideString& csURL,
+                                        WideString& csToAddress,
+                                        WideString& csCCAddress,
+                                        WideString& csBCCAddress,
+                                        WideString& csSubject,
+                                        WideString& csMsg) {
+  WideString srcURL = csURL;
+  srcURL.TrimLeft();
+  if (srcURL.Left(7).CompareNoCase(L"mailto:") != 0)
+    return false;
+
+  auto pos = srcURL.Find(L'?');
+
+  {
+    WideString tmp;
+    if (!pos.has_value()) {
+      pos = srcURL.Find(L'@');
+      if (!pos.has_value())
+        return false;
+
+      tmp = srcURL.Right(csURL.GetLength() - 7);
+    } else {
+      tmp = srcURL.Left(pos.value());
+      tmp = tmp.Right(tmp.GetLength() - 7);
+    }
+    tmp.Trim();
+    csToAddress = std::move(tmp);
+  }
+
+  srcURL = srcURL.Right(srcURL.GetLength() - (pos.value() + 1));
+  while (!srcURL.IsEmpty()) {
+    srcURL.Trim();
+    pos = srcURL.Find(L'&');
+    WideString tmp = (!pos.has_value()) ? srcURL : srcURL.Left(pos.value());
+    tmp.Trim();
+    if (tmp.GetLength() >= 3 && tmp.Left(3).CompareNoCase(L"cc=") == 0) {
+      tmp = tmp.Right(tmp.GetLength() - 3);
+      if (!csCCAddress.IsEmpty())
+        csCCAddress += L';';
+      csCCAddress += tmp;
+    } else if (tmp.GetLength() >= 4 &&
+               tmp.Left(4).CompareNoCase(L"bcc=") == 0) {
+      tmp = tmp.Right(tmp.GetLength() - 4);
+      if (!csBCCAddress.IsEmpty())
+        csBCCAddress += L';';
+      csBCCAddress += tmp;
+    } else if (tmp.GetLength() >= 8 &&
+               tmp.Left(8).CompareNoCase(L"subject=") == 0) {
+      tmp = tmp.Right(tmp.GetLength() - 8);
+      csSubject += tmp;
+    } else if (tmp.GetLength() >= 5 &&
+               tmp.Left(5).CompareNoCase(L"body=") == 0) {
+      tmp = tmp.Right(tmp.GetLength() - 5);
+      csMsg += tmp;
+    }
+    srcURL = pos.has_value()
+                 ? srcURL.Right(csURL.GetLength() - (pos.value() + 1))
+                 : WideString();
+  }
+  csToAddress.Replace(L",", L";");
+  csCCAddress.Replace(L",", L";");
+  csBCCAddress.Replace(L",", L";");
+  return true;
+}
+
 bool CPDFXFA_DocEnvironment::ExportSubmitFile(FPDF_FILEHANDLER* pFileHandler,
                                               int fileType,
                                               FPDF_DWORD encodeType,
@@ -823,72 +815,86 @@
   }
 }
 
-bool CPDFXFA_DocEnvironment::MailToInfo(WideString& csURL,
-                                        WideString& csToAddress,
-                                        WideString& csCCAddress,
-                                        WideString& csBCCAddress,
-                                        WideString& csSubject,
-                                        WideString& csMsg) {
-  WideString srcURL = csURL;
-  srcURL.TrimLeft();
-  if (srcURL.Left(7).CompareNoCase(L"mailto:") != 0)
-    return false;
+#ifdef PDF_XFA_ELEMENT_SUBMIT_ENABLED
+bool CPDFXFA_DocEnvironment::OnBeforeNotifySubmit() {
+  if (!m_pContext->ContainsXFAForm())
+    return true;
 
-  auto pos = srcURL.Find(L'?');
+  CXFA_FFDocView* docView = m_pContext->GetXFADocView();
+  if (!docView)
+    return true;
 
-  {
-    WideString tmp;
-    if (!pos.has_value()) {
-      pos = srcURL.Find(L'@');
-      if (!pos.has_value())
+  CXFA_FFWidgetHandler* pWidgetHandler = docView->GetWidgetHandler();
+  if (!pWidgetHandler)
+    return true;
+
+  auto it = docView->CreateReadyNodeIterator();
+  if (it) {
+    CXFA_EventParam Param;
+    Param.m_eType = XFA_EVENT_PreSubmit;
+    while (CXFA_Node* pNode = it->MoveToNext())
+      pWidgetHandler->ProcessEvent(pNode, &Param);
+  }
+
+  it = docView->CreateReadyNodeIterator();
+  if (!it)
+    return true;
+
+  (void)it->MoveToNext();
+  CXFA_Node* pNode = it->MoveToNext();
+
+  while (pNode) {
+    if (pNode->ProcessValidate(docView, -1) == XFA_EventError::kError) {
+      CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pContext->GetFormFillEnv();
+      if (!pFormFillEnv)
         return false;
 
-      tmp = srcURL.Right(csURL.GetLength() - 7);
-    } else {
-      tmp = srcURL.Left(pos.value());
-      tmp = tmp.Right(tmp.GetLength() - 7);
+      pFormFillEnv->JS_appAlert(WideString::FromDefANSI(IDS_XFA_Validate_Input),
+                                WideString(), JSPLATFORM_ALERT_BUTTON_OK,
+                                JSPLATFORM_ALERT_ICON_WARNING);
+      return false;
     }
-    tmp.Trim();
-    csToAddress = std::move(tmp);
+    pNode = it->MoveToNext();
   }
 
-  srcURL = srcURL.Right(srcURL.GetLength() - (pos.value() + 1));
-  while (!srcURL.IsEmpty()) {
-    srcURL.Trim();
-    pos = srcURL.Find(L'&');
-    WideString tmp = (!pos.has_value()) ? srcURL : srcURL.Left(pos.value());
-    tmp.Trim();
-    if (tmp.GetLength() >= 3 && tmp.Left(3).CompareNoCase(L"cc=") == 0) {
-      tmp = tmp.Right(tmp.GetLength() - 3);
-      if (!csCCAddress.IsEmpty())
-        csCCAddress += L';';
-      csCCAddress += tmp;
-    } else if (tmp.GetLength() >= 4 &&
-               tmp.Left(4).CompareNoCase(L"bcc=") == 0) {
-      tmp = tmp.Right(tmp.GetLength() - 4);
-      if (!csBCCAddress.IsEmpty())
-        csBCCAddress += L';';
-      csBCCAddress += tmp;
-    } else if (tmp.GetLength() >= 8 &&
-               tmp.Left(8).CompareNoCase(L"subject=") == 0) {
-      tmp = tmp.Right(tmp.GetLength() - 8);
-      csSubject += tmp;
-    } else if (tmp.GetLength() >= 5 &&
-               tmp.Left(5).CompareNoCase(L"body=") == 0) {
-      tmp = tmp.Right(tmp.GetLength() - 5);
-      csMsg += tmp;
-    }
-    srcURL = pos.has_value()
-                 ? srcURL.Right(csURL.GetLength() - (pos.value() + 1))
-                 : WideString();
-  }
-  csToAddress.Replace(L",", L";");
-  csCCAddress.Replace(L",", L";");
-  csBCCAddress.Replace(L",", L";");
+  docView->UpdateDocView();
   return true;
 }
 
-#ifdef PDF_XFA_ELEMENT_SUBMIT_ENABLED
+void CPDFXFA_DocEnvironment::OnAfterNotifySubmit() {
+  if (!m_pContext->ContainsXFAForm())
+    return;
+
+  if (!m_pContext->GetXFADocView())
+    return;
+
+  CXFA_FFWidgetHandler* pWidgetHandler =
+      m_pContext->GetXFADocView()->GetWidgetHandler();
+  if (!pWidgetHandler)
+    return;
+
+  auto it = m_pContext->GetXFADocView()->CreateReadyNodeIterator();
+  if (!it)
+    return;
+
+  CXFA_EventParam Param;
+  Param.m_eType = XFA_EVENT_PostSubmit;
+  CXFA_Node* pNode = it->MoveToNext();
+  while (pNode) {
+    pWidgetHandler->ProcessEvent(pNode, &Param);
+    pNode = it->MoveToNext();
+  }
+  m_pContext->GetXFADocView()->UpdateDocView();
+}
+
+bool CPDFXFA_DocEnvironment::NotifySubmit(bool bPrevOrPost) {
+  if (bPrevOrPost)
+    return OnBeforeNotifySubmit();
+
+  OnAfterNotifySubmit();
+  return true;
+}
+
 bool CPDFXFA_DocEnvironment::SubmitInternal(CXFA_FFDoc* hDoc,
                                             CXFA_Submit* submit) {
   CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pContext->GetFormFillEnv();
@@ -967,35 +973,3 @@
   return true;
 }
 #endif  // PDF_XFA_ELEMENT_SUBMIT_ENABLED
-
-bool CPDFXFA_DocEnvironment::SetPropertyInNonXFAGlobalObject(
-    CXFA_FFDoc* hDoc,
-    ByteStringView szPropName,
-    CFXJSE_Value* pValue) {
-  if (hDoc != m_pContext->GetXFADoc())
-    return false;
-
-  CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pContext->GetFormFillEnv();
-  if (!pFormFillEnv)
-    return false;
-
-  IJS_Runtime* pIJSRuntime = pFormFillEnv->GetIJSRuntime();
-  IJS_Runtime::ScopedEventContext pContext(pIJSRuntime);
-  return pIJSRuntime->SetValueByNameInGlobalObject(szPropName, pValue);
-}
-
-bool CPDFXFA_DocEnvironment::GetPropertyFromNonXFAGlobalObject(
-    CXFA_FFDoc* hDoc,
-    ByteStringView szPropName,
-    CFXJSE_Value* pValue) {
-  if (hDoc != m_pContext->GetXFADoc())
-    return false;
-
-  CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pContext->GetFormFillEnv();
-  if (!pFormFillEnv)
-    return false;
-
-  IJS_Runtime* pIJSRuntime = pFormFillEnv->GetIJSRuntime();
-  IJS_Runtime::ScopedEventContext pContext(pIJSRuntime);
-  return pIJSRuntime->GetValueByNameFromGlobalObject(szPropName, pValue);
-}
diff --git a/fpdfsdk/fpdfxfa/cpdfxfa_docenvironment.h b/fpdfsdk/fpdfxfa/cpdfxfa_docenvironment.h
index 7c86bd81..100e664 100644
--- a/fpdfsdk/fpdfxfa/cpdfxfa_docenvironment.h
+++ b/fpdfsdk/fpdfxfa/cpdfxfa_docenvironment.h
@@ -13,34 +13,28 @@
 #include "xfa/fxfa/fxfa.h"
 
 class CPDFXFA_Context;
+class IJS_Runtime;
 
 class CPDFXFA_DocEnvironment final : public IXFA_DocEnvironment {
  public:
   explicit CPDFXFA_DocEnvironment(CPDFXFA_Context*);
   ~CPDFXFA_DocEnvironment() override;
 
-  // IXFA_DocEnvironment
+  // IXFA_DocEnvironment:
   void SetChangeMark(CXFA_FFDoc* hDoc) override;
-  // Used in dynamic xfa.
   void InvalidateRect(CXFA_FFPageView* pPageView, const CFX_RectF& rt) override;
-  // Show or hide caret.
   void DisplayCaret(CXFA_FFWidget* hWidget,
                     bool bVisible,
                     const CFX_RectF* pRtAnchor) override;
-  // dwPos: (0:bottom 1:top)
   bool GetPopupPos(CXFA_FFWidget* hWidget,
                    float fMinPopup,
                    float fMaxPopup,
                    const CFX_RectF& rtAnchor,
                    CFX_RectF* pPopupRect) override;
   bool PopupMenu(CXFA_FFWidget* hWidget, const CFX_PointF& ptPopup) override;
-
-  // dwFlags XFA_PAGEVIEWEVENT_Added, XFA_PAGEVIEWEVENT_Removing
   void PageViewEvent(CXFA_FFPageView* pPageView, uint32_t dwFlags) override;
   void WidgetPostAdd(CXFA_FFWidget* hWidget) override;
   void WidgetPreRemove(CXFA_FFWidget* hWidget) override;
-
-  // Host method
   int32_t CountPages(CXFA_FFDoc* hDoc) override;
   int32_t GetCurrentPage(CXFA_FFDoc* hDoc) override;
   void SetCurrentPage(CXFA_FFDoc* hDoc, int32_t iCurPage) override;
@@ -60,30 +54,16 @@
              int32_t nEndPage,
              uint32_t dwOptions) override;
   FX_ARGB GetHighlightColor(CXFA_FFDoc* hDoc) override;
+  IJS_Runtime* GetIJSRuntime(CXFA_FFDoc* hDoc) const override;
+  RetainPtr<IFX_SeekableReadStream> OpenLinkedFile(
+      CXFA_FFDoc* hDoc,
+      const WideString& wsLink) override;
 
 #ifdef PDF_XFA_ELEMENT_SUBMIT_ENABLED
   bool Submit(CXFA_FFDoc* hDoc, CXFA_Submit* submit) override;
 #endif  // PDF_XFA_ELEMENT_SUBMIT_ENABLED
 
-  bool GetPropertyFromNonXFAGlobalObject(CXFA_FFDoc* hDoc,
-                                         ByteStringView szPropName,
-                                         CFXJSE_Value* pValue) override;
-  bool SetPropertyInNonXFAGlobalObject(CXFA_FFDoc* hDoc,
-                                       ByteStringView szPropName,
-                                       CFXJSE_Value* pValue) override;
-
-  RetainPtr<IFX_SeekableReadStream> OpenLinkedFile(
-      CXFA_FFDoc* hDoc,
-      const WideString& wsLink) override;
-
  private:
-#ifdef PDF_XFA_ELEMENT_SUBMIT_ENABLED
-  bool OnBeforeNotifySubmit();
-  void OnAfterNotifySubmit();
-  bool NotifySubmit(bool bPrevOrPost);
-  bool SubmitInternal(CXFA_FFDoc* hDoc, CXFA_Submit* submit);
-#endif  // PDF_XFA_ELEMENT_SUBMIT_ENABLED
-
   bool MailToInfo(WideString& csURL,
                   WideString& csToAddress,
                   WideString& csCCAddress,
@@ -96,6 +76,13 @@
                         FPDF_DWORD flag);
   void ToXFAContentFlags(WideString csSrcContent, FPDF_DWORD& flag);
 
+#ifdef PDF_XFA_ELEMENT_SUBMIT_ENABLED
+  bool OnBeforeNotifySubmit();
+  void OnAfterNotifySubmit();
+  bool NotifySubmit(bool bPrevOrPost);
+  bool SubmitInternal(CXFA_FFDoc* hDoc, CXFA_Submit* submit);
+#endif  // PDF_XFA_ELEMENT_SUBMIT_ENABLED
+
   UnownedPtr<CPDFXFA_Context> const m_pContext;
 };
 
diff --git a/fxjs/cfxjs_engine.h b/fxjs/cfxjs_engine.h
index 8c6c69c..933c250 100644
--- a/fxjs/cfxjs_engine.h
+++ b/fxjs/cfxjs_engine.h
@@ -24,11 +24,6 @@
 #include "fxjs/ijs_runtime.h"
 #include "v8/include/v8.h"
 
-#ifdef PDF_ENABLE_XFA
-// CFXJS_ENGINE doesn't interpret this class, it is just passed along to XFA.
-class CFXJSE_RuntimeData;
-#endif  // PDF_ENABLE_XFA
-
 class CFXJS_ObjDefinition;
 class CJS_Object;
 class V8TemplateMap;
@@ -45,6 +40,12 @@
 
 class FXJS_PerIsolateData {
  public:
+  // Hook for XFA's data, when present.
+  class ExtensionIface {
+   public:
+    virtual ~ExtensionIface() = default;
+  };
+
   ~FXJS_PerIsolateData();
 
   static void SetUp(v8::Isolate* pIsolate);
@@ -56,9 +57,7 @@
 
   std::vector<std::unique_ptr<CFXJS_ObjDefinition>> m_ObjectDefnArray;
   std::unique_ptr<V8TemplateMap> m_pDynamicObjsMap;
-#ifdef PDF_ENABLE_XFA
-  std::unique_ptr<CFXJSE_RuntimeData> m_pFXJSERuntimeData;
-#endif  // PDF_ENABLE_XFA
+  std::unique_ptr<ExtensionIface> m_pFXJSERuntimeData;
 
  protected:
   explicit FXJS_PerIsolateData(v8::Isolate* pIsolate);
diff --git a/fxjs/cjs_runtime.cpp b/fxjs/cjs_runtime.cpp
index 4cb37dd..81148de 100644
--- a/fxjs/cjs_runtime.cpp
+++ b/fxjs/cjs_runtime.cpp
@@ -39,14 +39,9 @@
 #include "fxjs/js_define.h"
 #include "third_party/base/ptr_util.h"
 
-#ifdef PDF_ENABLE_XFA
-#include "fxjs/xfa/cfxjse_value.h"
-#endif  // PDF_ENABLE_XFA
-
 CJS_Runtime::CJS_Runtime(CPDFSDK_FormFillEnvironment* pFormFillEnv)
     : m_pFormFillEnv(pFormFillEnv) {
   v8::Isolate* pIsolate = nullptr;
-
   IPDF_JSPLATFORM* pPlatform = m_pFormFillEnv->GetFormFillInfo()->m_pJsPlatform;
   if (pPlatform->version <= 2) {
     unsigned int embedderDataSlot = 0;
@@ -60,11 +55,8 @@
   m_isolateManaged = FXJS_GetIsolate(&pIsolate);
   SetIsolate(pIsolate);
 
-#ifdef PDF_ENABLE_XFA
   v8::Isolate::Scope isolate_scope(pIsolate);
   v8::HandleScope handle_scope(pIsolate);
-#endif
-
   if (m_isolateManaged || FXJS_GlobalIsolateRefCount() == 0)
     DefineJSObjects();
 
@@ -180,21 +172,13 @@
   m_FieldEventSet.erase(event);
 }
 
-#ifdef PDF_ENABLE_XFA
-WideString ChangeObjName(const WideString& str) {
-  WideString sRet = str;
-  sRet.Replace(L"_", L".");
-  return sRet;
-}
-
 CJS_Runtime* CJS_Runtime::AsCJSRuntime() {
   return this;
 }
 
 bool CJS_Runtime::GetValueByNameFromGlobalObject(ByteStringView utf8Name,
-                                                 CFXJSE_Value* pValue) {
+                                                 v8::Local<v8::Value>* pValue) {
   v8::Isolate::Scope isolate_scope(GetIsolate());
-  v8::HandleScope handle_scope(GetIsolate());
   v8::Local<v8::Context> context = GetV8Context();
   v8::Context::Scope context_scope(context);
   v8::Local<v8::String> str =
@@ -203,39 +187,29 @@
           .ToLocalChecked();
   v8::MaybeLocal<v8::Value> maybe_propvalue =
       context->Global()->Get(context, str);
-  if (maybe_propvalue.IsEmpty()) {
-    pValue->SetUndefined();
+  if (maybe_propvalue.IsEmpty())
     return false;
-  }
-  v8::Local<v8::Value> propvalue = maybe_propvalue.ToLocalChecked();
-  if (propvalue.IsEmpty()) {
-    pValue->SetUndefined();
-    return false;
-  }
-  pValue->ForceSetValue(propvalue);
+
+  *pValue = maybe_propvalue.ToLocalChecked();
   return true;
 }
 
 bool CJS_Runtime::SetValueByNameInGlobalObject(ByteStringView utf8Name,
-                                               CFXJSE_Value* pValue) {
-  if (utf8Name.IsEmpty() || !pValue)
+                                               v8::Local<v8::Value> pValue) {
+  if (utf8Name.IsEmpty() || pValue.IsEmpty())
     return false;
 
   v8::Isolate* pIsolate = GetIsolate();
   v8::Isolate::Scope isolate_scope(pIsolate);
-  v8::HandleScope handle_scope(pIsolate);
   v8::Local<v8::Context> context = GetV8Context();
   v8::Context::Scope context_scope(context);
-  v8::Local<v8::Value> propvalue =
-      v8::Local<v8::Value>::New(pIsolate, pValue->DirectGetValue());
   v8::Local<v8::String> str =
       v8::String::NewFromUtf8(pIsolate, utf8Name.unterminated_c_str(),
                               v8::NewStringType::kNormal, utf8Name.GetLength())
           .ToLocalChecked();
-  v8::Maybe<bool> result = context->Global()->Set(context, str, propvalue);
+  v8::Maybe<bool> result = context->Global()->Set(context, str, pValue);
   return result.IsJust() && result.FromJust();
 }
-#endif  // PDF_ENABLE_XFA
 
 v8::Local<v8::Value> CJS_Runtime::MaybeCoerceToNumber(
     v8::Local<v8::Value> value) {
diff --git a/fxjs/cjs_runtime.h b/fxjs/cjs_runtime.h
index 4320c3d..b3f8ef6 100644
--- a/fxjs/cjs_runtime.h
+++ b/fxjs/cjs_runtime.h
@@ -30,7 +30,8 @@
   explicit CJS_Runtime(CPDFSDK_FormFillEnvironment* pFormFillEnv);
   ~CJS_Runtime() override;
 
-  // IJS_Runtime
+  // IJS_Runtime:
+  CJS_Runtime* AsCJSRuntime() override;
   IJS_EventContext* NewEventContext() override;
   void ReleaseEventContext(IJS_EventContext* pContext) override;
   CPDFSDK_FormFillEnvironment* GetFormFillEnv() const override;
@@ -52,13 +53,10 @@
   // value will be returned, otherwise |value| is returned.
   v8::Local<v8::Value> MaybeCoerceToNumber(v8::Local<v8::Value> value);
 
-#ifdef PDF_ENABLE_XFA
-  CJS_Runtime* AsCJSRuntime() override;
   bool GetValueByNameFromGlobalObject(ByteStringView utf8Name,
-                                      CFXJSE_Value* pValue) override;
+                                      v8::Local<v8::Value>* pValue);
   bool SetValueByNameInGlobalObject(ByteStringView utf8Name,
-                                    CFXJSE_Value* pValue) override;
-#endif  // PDF_ENABLE_XFA
+                                    v8::Local<v8::Value> pValue);
 
  private:
   void DefineJSObjects();
diff --git a/fxjs/cjs_runtimestub.cpp b/fxjs/cjs_runtimestub.cpp
index 0a774a56..6e313de 100644
--- a/fxjs/cjs_runtimestub.cpp
+++ b/fxjs/cjs_runtimestub.cpp
@@ -26,22 +26,10 @@
   return m_pFormFillEnv.Get();
 }
 
-#ifdef PDF_ENABLE_XFA
 CJS_Runtime* CJS_RuntimeStub::AsCJSRuntime() {
   return nullptr;
 }
 
-bool CJS_RuntimeStub::GetValueByNameFromGlobalObject(ByteStringView,
-                                                     CFXJSE_Value*) {
-  return false;
-}
-
-bool CJS_RuntimeStub::SetValueByNameInGlobalObject(ByteStringView,
-                                                   CFXJSE_Value*) {
-  return false;
-}
-#endif  // PDF_ENABLE_XFA
-
 Optional<IJS_Runtime::JS_Error> CJS_RuntimeStub::ExecuteScript(
     const WideString& script) {
   return pdfium::nullopt;
diff --git a/fxjs/cjs_runtimestub.h b/fxjs/cjs_runtimestub.h
index a702b77..2b5e713 100644
--- a/fxjs/cjs_runtimestub.h
+++ b/fxjs/cjs_runtimestub.h
@@ -22,16 +22,11 @@
   ~CJS_RuntimeStub() override;
 
   // IJS_Runtime:
+  CJS_Runtime* AsCJSRuntime() override;
   IJS_EventContext* NewEventContext() override;
   void ReleaseEventContext(IJS_EventContext* pContext) override;
   CPDFSDK_FormFillEnvironment* GetFormFillEnv() const override;
 
-#ifdef PDF_ENABLE_XFA
-  CJS_Runtime* AsCJSRuntime() override;
-  bool GetValueByNameFromGlobalObject(ByteStringView, CFXJSE_Value*) override;
-  bool SetValueByNameInGlobalObject(ByteStringView, CFXJSE_Value*) override;
-#endif  // PDF_ENABLE_XFA
-
   Optional<IJS_Runtime::JS_Error> ExecuteScript(
       const WideString& script) override;
 
diff --git a/fxjs/ijs_runtime.h b/fxjs/ijs_runtime.h
index 2d879f6..ca103aa 100644
--- a/fxjs/ijs_runtime.h
+++ b/fxjs/ijs_runtime.h
@@ -52,19 +52,12 @@
 
   virtual ~IJS_Runtime();
 
+  virtual CJS_Runtime* AsCJSRuntime() = 0;
   virtual IJS_EventContext* NewEventContext() = 0;
   virtual void ReleaseEventContext(IJS_EventContext* pContext) = 0;
   virtual CPDFSDK_FormFillEnvironment* GetFormFillEnv() const = 0;
   virtual Optional<JS_Error> ExecuteScript(const WideString& script) = 0;
 
-#ifdef PDF_ENABLE_XFA
-  virtual CJS_Runtime* AsCJSRuntime() = 0;
-  virtual bool GetValueByNameFromGlobalObject(ByteStringView utf8Name,
-                                              CFXJSE_Value* pValue) = 0;
-  virtual bool SetValueByNameInGlobalObject(ByteStringView utf8Name,
-                                            CFXJSE_Value* pValue) = 0;
-#endif  // PDF_ENABLE_XFA
-
  protected:
   IJS_Runtime() = default;
 };
diff --git a/fxjs/js_resources.cpp b/fxjs/js_resources.cpp
index 16df281..3bc8df3 100644
--- a/fxjs/js_resources.cpp
+++ b/fxjs/js_resources.cpp
@@ -81,7 +81,6 @@
     case JSMessage::kUserGestureRequiredError:
       msg_string = "User gesture required.";
       break;
-#ifdef PDF_ENABLE_XFA
     case JSMessage::kTooManyOccurances:
       msg_string = "Too many occurances.";
       break;
@@ -91,7 +90,6 @@
     default:
       NOTREACHED();
       break;
-#endif
   }
   return WideString::FromASCII(msg_string);
 }
diff --git a/fxjs/js_resources.h b/fxjs/js_resources.h
index a95e1b3..8a30862 100644
--- a/fxjs/js_resources.h
+++ b/fxjs/js_resources.h
@@ -33,10 +33,8 @@
   kUnknownProperty,
   kInvalidSetError,
   kUserGestureRequiredError,
-#ifdef PDF_ENABLE_XFA
   kTooManyOccurances,
   kUnknownMethod,
-#endif
 };
 
 WideString JSGetStringFromID(JSMessage msg);
diff --git a/fxjs/xfa/cfxjse_engine.cpp b/fxjs/xfa/cfxjse_engine.cpp
index 8dafcb3..7ac440d 100644
--- a/fxjs/xfa/cfxjse_engine.cpp
+++ b/fxjs/xfa/cfxjse_engine.cpp
@@ -198,19 +198,25 @@
           true)) {
     return;
   }
-  if (lpOrginalNode->IsThisProxy()) {
-    if (pValue && pValue->IsUndefined()) {
-      pObject->DeleteObjectProperty(szPropName);
-      return;
-    }
+  if (lpOrginalNode->IsThisProxy() && pValue && pValue->IsUndefined()) {
+    pObject->DeleteObjectProperty(szPropName);
+    return;
   }
   CXFA_FFNotify* pNotify = pDoc->GetNotify();
   if (!pNotify)
     return;
 
   CXFA_FFDoc* hDoc = pNotify->GetHDOC();
-  hDoc->GetDocEnvironment()->SetPropertyInNonXFAGlobalObject(hDoc, szPropName,
-                                                             pValue);
+  auto* pCJSRuntime =
+      static_cast<CJS_Runtime*>(hDoc->GetDocEnvironment()->GetIJSRuntime(hDoc));
+  if (!pCJSRuntime)
+    return;
+
+  v8::HandleScope handle_scope(lpScriptContext->GetIsolate());
+  IJS_Runtime::ScopedEventContext pContext(pCJSRuntime);
+  pCJSRuntime->SetValueByNameInGlobalObject(
+      szPropName, v8::Local<v8::Value>::New(lpScriptContext->GetIsolate(),
+                                            pValue->DirectGetValue()));
 }
 
 // static
@@ -222,6 +228,7 @@
   CFXJSE_Engine* lpScriptContext = pDoc->GetScriptContext();
   WideString wsPropName = WideString::FromUTF8(szPropName);
 
+  pValue->SetUndefined();  // Assume failure.
   if (lpScriptContext->GetType() == CXFA_Script::Type::Formcalc) {
     if (szPropName == kFormCalcRuntime) {
       lpScriptContext->m_FM2JSContext->GlobalPropertyGetter(pValue);
@@ -244,7 +251,6 @@
     pRefNode =
         ToNode(lpScriptContext->GetVariablesThis(pOriginalObject, false));
   }
-
   if (lpScriptContext->QueryNodeByFlag(
           pRefNode, wsPropName.AsStringView(), pValue,
           XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Properties |
@@ -252,7 +258,6 @@
           false)) {
     return;
   }
-
   if (lpScriptContext->QueryNodeByFlag(
           pRefNode, wsPropName.AsStringView(), pValue,
           XFA_RESOLVENODE_Parent | XFA_RESOLVENODE_Siblings, false)) {
@@ -271,8 +276,21 @@
     return;
 
   CXFA_FFDoc* hDoc = pNotify->GetHDOC();
-  hDoc->GetDocEnvironment()->GetPropertyFromNonXFAGlobalObject(hDoc, szPropName,
-                                                               pValue);
+  auto* pCJSRuntime =
+      static_cast<CJS_Runtime*>(hDoc->GetDocEnvironment()->GetIJSRuntime(hDoc));
+  if (!pCJSRuntime)
+    return;
+
+  v8::HandleScope handle_scope(lpScriptContext->GetIsolate());
+  IJS_Runtime::ScopedEventContext pContext(pCJSRuntime);
+  v8::Local<v8::Value> temp_value;
+  if (!pCJSRuntime->GetValueByNameFromGlobalObject(szPropName, &temp_value))
+    return;
+
+  if (temp_value.IsEmpty())
+    return;
+
+  pValue->ForceSetValue(temp_value);
 }
 
 int32_t CFXJSE_Engine::GlobalPropTypeGetter(CFXJSE_Value* pOriginalValue,
@@ -295,11 +313,10 @@
 void CFXJSE_Engine::NormalPropertyGetter(CFXJSE_Value* pOriginalValue,
                                          ByteStringView szPropName,
                                          CFXJSE_Value* pReturnValue) {
+  pReturnValue->SetUndefined();  // Assume failure.
   CXFA_Object* pOriginalObject = ToObject(pOriginalValue);
-  if (!pOriginalObject) {
-    pReturnValue->SetUndefined();
+  if (!pOriginalObject)
     return;
-  }
 
   WideString wsPropName = WideString::FromUTF8(szPropName);
   CFXJSE_Engine* lpScriptContext =
@@ -333,36 +350,43 @@
 
   CXFA_Object* pScriptObject =
       lpScriptContext->GetVariablesThis(pOriginalObject, true);
-  if (pScriptObject) {
-    bRet = lpScriptContext->QueryVariableValue(ToNode(pScriptObject),
-                                               szPropName, pReturnValue, true);
+  if (!pScriptObject)
+    return;
 
-    if (!bRet) {
-      Optional<XFA_SCRIPTATTRIBUTEINFO> info = XFA_GetScriptAttributeByName(
-          pObject->GetElementType(), wsPropName.AsStringView());
-      if (info.has_value()) {
-        CJX_Object* jsObject = pObject->JSObject();
-        (*info.value().callback)(jsObject, pReturnValue, false,
-                                 info.value().attribute);
-        return;
-      }
-    }
+  bRet = lpScriptContext->QueryVariableValue(ToNode(pScriptObject), szPropName,
+                                             pReturnValue, true);
+  if (bRet)
+    return;
 
-    CXFA_FFNotify* pNotify = pObject->GetDocument()->GetNotify();
-    if (!pNotify) {
-      pReturnValue->SetUndefined();
-      return;
-    }
-
-    CXFA_FFDoc* hDoc = pNotify->GetHDOC();
-    if (hDoc->GetDocEnvironment()->GetPropertyFromNonXFAGlobalObject(
-            hDoc, szPropName, pReturnValue)) {
-      return;
-    }
+  Optional<XFA_SCRIPTATTRIBUTEINFO> info = XFA_GetScriptAttributeByName(
+      pObject->GetElementType(), wsPropName.AsStringView());
+  if (info.has_value()) {
+    CJX_Object* jsObject = pObject->JSObject();
+    (*info.value().callback)(jsObject, pReturnValue, false,
+                             info.value().attribute);
+    return;
   }
 
-  if (!bRet)
-    pReturnValue->SetUndefined();
+  CXFA_FFNotify* pNotify = pObject->GetDocument()->GetNotify();
+  if (!pNotify)
+    return;
+
+  CXFA_FFDoc* hDoc = pNotify->GetHDOC();
+  auto* pCJSRuntime =
+      static_cast<CJS_Runtime*>(hDoc->GetDocEnvironment()->GetIJSRuntime(hDoc));
+  if (!pCJSRuntime)
+    return;
+
+  v8::HandleScope handle_scope(lpScriptContext->GetIsolate());
+  IJS_Runtime::ScopedEventContext pContext(pCJSRuntime);
+  v8::Local<v8::Value> temp_local;
+  if (!pCJSRuntime->GetValueByNameFromGlobalObject(szPropName, &temp_local))
+    return;
+
+  if (temp_local.IsEmpty())
+    return;
+
+  pReturnValue->ForceSetValue(temp_local);
 }
 
 // static
diff --git a/fxjs/xfa/cfxjse_runtimedata.cpp b/fxjs/xfa/cfxjse_runtimedata.cpp
index fdff67a..0478e3e 100644
--- a/fxjs/xfa/cfxjse_runtimedata.cpp
+++ b/fxjs/xfa/cfxjse_runtimedata.cpp
@@ -51,5 +51,5 @@
   FXJS_PerIsolateData* pData = FXJS_PerIsolateData::Get(pIsolate);
   if (!pData->m_pFXJSERuntimeData)
     pData->m_pFXJSERuntimeData = CFXJSE_RuntimeData::Create(pIsolate);
-  return pData->m_pFXJSERuntimeData.get();
+  return static_cast<CFXJSE_RuntimeData*>(pData->m_pFXJSERuntimeData.get());
 }
diff --git a/fxjs/xfa/cfxjse_runtimedata.h b/fxjs/xfa/cfxjse_runtimedata.h
index c0f5da3..148b01e 100644
--- a/fxjs/xfa/cfxjse_runtimedata.h
+++ b/fxjs/xfa/cfxjse_runtimedata.h
@@ -9,13 +9,12 @@
 
 #include <memory>
 
+#include "fxjs/cfxjs_engine.h"
 #include "v8/include/v8.h"
 
-class CFXJSE_RuntimeList;
-
-class CFXJSE_RuntimeData {
+class CFXJSE_RuntimeData : public FXJS_PerIsolateData::ExtensionIface {
  public:
-  ~CFXJSE_RuntimeData();
+  ~CFXJSE_RuntimeData() override;
 
   static CFXJSE_RuntimeData* Get(v8::Isolate* pIsolate);
 
diff --git a/xfa/fxfa/fxfa.h b/xfa/fxfa/fxfa.h
index 350e0e4..9193d1b 100644
--- a/xfa/fxfa/fxfa.h
+++ b/xfa/fxfa/fxfa.h
@@ -15,12 +15,12 @@
 #include "core/fxge/fx_dib.h"
 #include "xfa/fxfa/fxfa_basic.h"
 
-class CFXJSE_Value;
 class CXFA_FFDoc;
 class CXFA_FFPageView;
 class CXFA_FFWidget;
 class CXFA_Submit;
 class IFX_SeekableReadStream;
+class IJS_Runtime;
 
 // Note, values must match fpdf_formfill.h JSPLATFORM_ALERT_BUTTON_* flags.
 enum class AlertButton {
@@ -227,19 +227,23 @@
   virtual void SetChangeMark(CXFA_FFDoc* hDoc) = 0;
   virtual void InvalidateRect(CXFA_FFPageView* pPageView,
                               const CFX_RectF& rt) = 0;
+  // Show or hide caret.
   virtual void DisplayCaret(CXFA_FFWidget* hWidget,
                             bool bVisible,
                             const CFX_RectF* pRtAnchor) = 0;
+
   virtual bool GetPopupPos(CXFA_FFWidget* hWidget,
                            float fMinPopup,
                            float fMaxPopup,
                            const CFX_RectF& rtAnchor,
                            CFX_RectF* pPopupRect) = 0;
   virtual bool PopupMenu(CXFA_FFWidget* hWidget, const CFX_PointF& ptPopup) = 0;
+
+  // Specify dwFlags XFA_PAGEVIEWEVENT_Added, XFA_PAGEVIEWEVENT_Removing
   virtual void PageViewEvent(CXFA_FFPageView* pPageView, uint32_t dwFlags) = 0;
+
   virtual void WidgetPostAdd(CXFA_FFWidget* hWidget) = 0;
   virtual void WidgetPreRemove(CXFA_FFWidget* hWidget) = 0;
-
   virtual int32_t CountPages(CXFA_FFDoc* hDoc) = 0;
   virtual int32_t GetCurrentPage(CXFA_FFDoc* hDoc) = 0;
   virtual void SetCurrentPage(CXFA_FFDoc* hDoc, int32_t iCurPage) = 0;
@@ -259,20 +263,14 @@
                      int32_t nEndPage,
                      uint32_t dwOptions) = 0;
   virtual FX_ARGB GetHighlightColor(CXFA_FFDoc* hDoc) = 0;
+  virtual IJS_Runtime* GetIJSRuntime(CXFA_FFDoc* hDoc) const = 0;
+  virtual RetainPtr<IFX_SeekableReadStream> OpenLinkedFile(
+      CXFA_FFDoc* hDoc,
+      const WideString& wsLink) = 0;
 
 #ifdef PDF_XFA_ELEMENT_SUBMIT_ENABLED
   virtual bool Submit(CXFA_FFDoc* hDoc, CXFA_Submit* submit) = 0;
 #endif  // PDF_XFA_ELEMENT_SUBMIT_ENABLED
-
-  virtual bool GetPropertyFromNonXFAGlobalObject(CXFA_FFDoc* hDoc,
-                                                 ByteStringView szPropName,
-                                                 CFXJSE_Value* pValue) = 0;
-  virtual bool SetPropertyInNonXFAGlobalObject(CXFA_FFDoc* hDoc,
-                                               ByteStringView szPropName,
-                                               CFXJSE_Value* pValue) = 0;
-  virtual RetainPtr<IFX_SeekableReadStream> OpenLinkedFile(
-      CXFA_FFDoc* hDoc,
-      const WideString& wsLink) = 0;
 };
 
 class IXFA_WidgetIterator {