Revert of Reland: Make the CPDFXFA_App non-global (patchset #2 id:20001 of https://codereview.chromium.org/2418653003/ )

Reason for revert:
https://build.chromium.org/p/client.pdfium/builders/linux_xfa_asan_lsan/builds/117/steps/corpus%20tests/logs/stdio

Original issue's description:
> Reland: Make the CPDFXFA_App non-global
>
> This reverts commit b685e6471075bebd26711bc183de3128f54932e3.
>
> This CL changes CPDFXFA_App from a global object to a child of the CPDFXFA_Document objects.
>
> BUG=pdfium:623
>
> Committed: https://pdfium.googlesource.com/pdfium/+/f3736bca5f874b0889c5906ffbd74a405089f671

TBR=tsepez@chromium.org
# Skipping CQ checks because original CL landed less than 1 days ago.
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
BUG=pdfium:623

Review-Url: https://codereview.chromium.org/2414883006
diff --git a/BUILD.gn b/BUILD.gn
index 1cf07ae..f87201c 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -1063,7 +1063,6 @@
     ]
     deps = [
       ":fxcrt",
-      ":fxjs",
       ":xfa",
     ]
     configs += [ ":pdfium_core_config" ]
diff --git a/fpdfsdk/DEPS b/fpdfsdk/DEPS
index ce037d9..5b1f3c4 100644
--- a/fpdfsdk/DEPS
+++ b/fpdfsdk/DEPS
@@ -3,7 +3,6 @@
   '+public',
   '+v8',
   '+xfa/fwl/core',
-  '+xfa/fxbarcode',
   '+xfa/fxfa',
   '+xfa/fxgraphics',
-  ]
+]
diff --git a/fpdfsdk/cpdfsdk_formfillenvironment.cpp b/fpdfsdk/cpdfsdk_formfillenvironment.cpp
index 9ad7c9f..71b83b2 100644
--- a/fpdfsdk/cpdfsdk_formfillenvironment.cpp
+++ b/fpdfsdk/cpdfsdk_formfillenvironment.cpp
@@ -58,6 +58,11 @@
   // Those widgets may call things like KillTimer() as they are shutdown.
   m_pFormFiller.reset();
 
+#ifdef PDF_ENABLE_XFA
+  CPDFXFA_App* pProvider = CPDFXFA_App::GetInstance();
+  if (pProvider->m_pFormFillEnvList.GetSize() == 0)
+    pProvider->SetJavaScriptInitialized(FALSE);
+#endif  // PDF_ENABLE_XFA
   if (m_pInfo && m_pInfo->Release)
     m_pInfo->Release(m_pInfo);
 }
diff --git a/fpdfsdk/fpdfdoc_unittest.cpp b/fpdfsdk/fpdfdoc_unittest.cpp
index 45beacf..fc85404 100644
--- a/fpdfsdk/fpdfdoc_unittest.cpp
+++ b/fpdfsdk/fpdfdoc_unittest.cpp
@@ -35,7 +35,8 @@
 class CPDF_TestXFADocument : public CPDFXFA_Document {
  public:
   CPDF_TestXFADocument()
-      : CPDFXFA_Document(pdfium::MakeUnique<CPDF_TestDocument>()) {}
+      : CPDFXFA_Document(pdfium::MakeUnique<CPDF_TestDocument>(),
+                         CPDFXFA_App::GetInstance()) {}
 
   void SetRoot(CPDF_Dictionary* root) {
     reinterpret_cast<CPDF_TestDocument*>(GetPDFDoc())->SetRoot(root);
diff --git a/fpdfsdk/fpdfformfill.cpp b/fpdfsdk/fpdfformfill.cpp
index 0f44b1d..34e206d 100644
--- a/fpdfsdk/fpdfformfill.cpp
+++ b/fpdfsdk/fpdfformfill.cpp
@@ -258,6 +258,7 @@
 
 #ifdef PDF_ENABLE_XFA
   pDocument->SetFormFillEnv(pFormFillEnv);
+  CPDFXFA_App::GetInstance()->AddFormFillEnv(pFormFillEnv);
 #endif  // PDF_ENABLE_XFA
 
   return pFormFillEnv;
@@ -272,6 +273,8 @@
       HandleToCPDFSDKEnvironment(hHandle);
 
 #ifdef PDF_ENABLE_XFA
+  CPDFXFA_App::GetInstance()->RemoveFormFillEnv(pFormFillEnv);
+
   // Reset the focused annotations and remove the SDK document from the
   // XFA document.
   pFormFillEnv->ClearAllFocusedAnnots();
diff --git a/fpdfsdk/fpdfsave.cpp b/fpdfsdk/fpdfsave.cpp
index 4dfe120..364f4d2 100644
--- a/fpdfsdk/fpdfsave.cpp
+++ b/fpdfsdk/fpdfsave.cpp
@@ -85,6 +85,9 @@
       pDocument->GetDocType() != DOCTYPE_STATIC_XFA)
     return true;
 
+  if (!CPDFXFA_App::GetInstance()->GetXFAApp())
+    return true;
+
   CXFA_FFDocView* pXFADocView = pDocument->GetXFADocView();
   if (!pXFADocView)
     return true;
diff --git a/fpdfsdk/fpdfview.cpp b/fpdfsdk/fpdfview.cpp
index cb0cf59..3ab81fe 100644
--- a/fpdfsdk/fpdfview.cpp
+++ b/fpdfsdk/fpdfview.cpp
@@ -42,7 +42,6 @@
 #include "fpdfsdk/fpdfxfa/cpdfxfa_page.h"
 #include "fpdfsdk/fpdfxfa/cxfa_fwladaptertimermgr.h"
 #include "public/fpdf_formfill.h"
-#include "xfa/fxbarcode/BC_Library.h"
 #endif  // PDF_ENABLE_XFA
 
 #if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
@@ -71,8 +70,8 @@
 
 FPDF_DOCUMENT FPDFDocumentFromCPDFDocument(CPDF_Document* doc) {
 #ifdef PDF_ENABLE_XFA
-  return doc ? FPDFDocumentFromUnderlying(
-                   new CPDFXFA_Document(pdfium::WrapUnique(doc)))
+  return doc ? FPDFDocumentFromUnderlying(new CPDFXFA_Document(
+                   pdfium::WrapUnique(doc), CPDFXFA_App::GetInstance()))
              : nullptr;
 #else   // PDF_ENABLE_XFA
   return FPDFDocumentFromUnderlying(doc);
@@ -286,19 +285,19 @@
   pModuleMgr->LoadEmbeddedKorea1CMaps();
 
 #ifdef PDF_ENABLE_XFA
-  FXJSE_Initialize();
-  BC_Library_Init();
+  CPDFXFA_App::GetInstance()->Initialize(
+      (cfg && cfg->version >= 2) ? static_cast<v8::Isolate*>(cfg->m_pIsolate)
+                                 : nullptr);
 #endif  // PDF_ENABLE_XFA
+
   if (cfg && cfg->version >= 2)
     IJS_Runtime::Initialize(cfg->m_v8EmbedderSlot, cfg->m_pIsolate);
 }
 
 DLLEXPORT void STDCALL FPDF_DestroyLibrary() {
 #ifdef PDF_ENABLE_XFA
-  BC_Library_Destory();
-  FXJSE_Finalize();
+  CPDFXFA_App::ReleaseInstance();
 #endif  // PDF_ENABLE_XFA
-
   CPDF_ModuleMgr::Destroy();
   CFX_GEModule::Destroy();
 
@@ -378,7 +377,11 @@
     ProcessParseError(error);
     return nullptr;
   }
-  return FPDFDocumentFromCPDFDocument(pDocument.release());
+#ifdef PDF_ENABLE_XFA
+  return new CPDFXFA_Document(std::move(pDocument), CPDFXFA_App::GetInstance());
+#else   // PDF_ENABLE_XFA
+  return pDocument.release();
+#endif  // PDF_ENABLE_XFA
 }
 
 #ifdef PDF_ENABLE_XFA
diff --git a/fpdfsdk/fpdfxfa/DEPS b/fpdfsdk/fpdfxfa/DEPS
index 1687e30..d4de6f1 100644
--- a/fpdfsdk/fpdfxfa/DEPS
+++ b/fpdfsdk/fpdfxfa/DEPS
@@ -1,4 +1,3 @@
 include_rules = [
-  '+fxjs',
   '+xfa/fxbarcode',
 ]
diff --git a/fpdfsdk/fpdfxfa/cpdfxfa_app.cpp b/fpdfsdk/fpdfxfa/cpdfxfa_app.cpp
index 569e314..61694d0 100644
--- a/fpdfsdk/fpdfxfa/cpdfxfa_app.cpp
+++ b/fpdfsdk/fpdfxfa/cpdfxfa_app.cpp
@@ -11,49 +11,110 @@
 #include "fpdfsdk/cpdfsdk_formfillenvironment.h"
 #include "fpdfsdk/fpdfxfa/cxfa_fwladaptertimermgr.h"
 #include "fpdfsdk/fsdk_define.h"
-#include "fxjs/fxjs_v8.h"
 #include "third_party/base/ptr_util.h"
+#include "xfa/fxbarcode/BC_Library.h"
 #include "xfa/fxfa/xfa_ffapp.h"
 #include "xfa/fxfa/xfa_fontmgr.h"
 
-CPDFXFA_App::CPDFXFA_App() : m_pIsolate(nullptr) {
-  m_bOwnsIsolate = FXJS_GetIsolate(&m_pIsolate);
+namespace {
 
-  m_pXFAApp = pdfium::MakeUnique<CXFA_FFApp>(this);
-  m_pXFAApp->SetDefaultFontMgr(pdfium::MakeUnique<CXFA_DefFontMgr>());
+CPDFXFA_App* g_pApp = nullptr;
+
+}  // namespace
+
+CPDFXFA_App* CPDFXFA_App::GetInstance() {
+  if (!g_pApp) {
+    g_pApp = new CPDFXFA_App();
+  }
+  return g_pApp;
+}
+
+void CPDFXFA_App::ReleaseInstance() {
+  delete g_pApp;
+  g_pApp = nullptr;
+}
+
+CPDFXFA_App::CPDFXFA_App()
+    : m_bJavaScriptInitialized(FALSE), m_pIsolate(nullptr) {
+  m_pFormFillEnvList.RemoveAll();
 }
 
 CPDFXFA_App::~CPDFXFA_App() {
-  if (m_bOwnsIsolate)
-    m_pIsolate->Dispose();
+  FXJSE_Runtime_Release(m_pIsolate);
+  m_pIsolate = nullptr;
+
+  FXJSE_Finalize();
+  BC_Library_Destory();
+}
+
+FX_BOOL CPDFXFA_App::Initialize(v8::Isolate* pIsolate) {
+  BC_Library_Init();
+  FXJSE_Initialize();
+
+  m_pIsolate = pIsolate ? pIsolate : FXJSE_Runtime_Create_Own();
+  if (!m_pIsolate)
+    return FALSE;
+
+  m_pXFAApp = pdfium::MakeUnique<CXFA_FFApp>(this);
+  m_pXFAApp->SetDefaultFontMgr(
+      std::unique_ptr<CXFA_DefFontMgr>(new CXFA_DefFontMgr));
+
+  return TRUE;
+}
+
+FX_BOOL CPDFXFA_App::AddFormFillEnv(CPDFSDK_FormFillEnvironment* pFormFillEnv) {
+  if (!pFormFillEnv)
+    return FALSE;
+
+  m_pFormFillEnvList.Add(pFormFillEnv);
+  return TRUE;
+}
+
+FX_BOOL CPDFXFA_App::RemoveFormFillEnv(
+    CPDFSDK_FormFillEnvironment* pFormFillEnv) {
+  if (!pFormFillEnv)
+    return FALSE;
+
+  int nFind = m_pFormFillEnvList.Find(pFormFillEnv);
+  if (nFind != -1) {
+    m_pFormFillEnvList.RemoveAt(nFind);
+    return TRUE;
+  }
+
+  return FALSE;
 }
 
 void CPDFXFA_App::GetAppName(CFX_WideString& wsName) {
-  if (m_pFormFillEnv)
-    wsName = m_pFormFillEnv->FFI_GetAppName();
+  CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pFormFillEnvList.GetAt(0);
+  if (pFormFillEnv)
+    wsName = pFormFillEnv->FFI_GetAppName();
 }
 
 void CPDFXFA_App::GetLanguage(CFX_WideString& wsLanguage) {
-  if (m_pFormFillEnv)
-    wsLanguage = m_pFormFillEnv->GetLanguage();
+  CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pFormFillEnvList.GetAt(0);
+  if (pFormFillEnv)
+    wsLanguage = pFormFillEnv->GetLanguage();
 }
 
 void CPDFXFA_App::GetPlatform(CFX_WideString& wsPlatform) {
-  if (m_pFormFillEnv) {
-    wsPlatform = m_pFormFillEnv->GetPlatform();
+  CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pFormFillEnvList.GetAt(0);
+  if (pFormFillEnv) {
+    wsPlatform = pFormFillEnv->GetPlatform();
   }
 }
 
 void CPDFXFA_App::Beep(uint32_t dwType) {
-  if (m_pFormFillEnv)
-    m_pFormFillEnv->JS_appBeep(dwType);
+  CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pFormFillEnvList.GetAt(0);
+  if (pFormFillEnv)
+    pFormFillEnv->JS_appBeep(dwType);
 }
 
 int32_t CPDFXFA_App::MsgBox(const CFX_WideString& wsMessage,
                             const CFX_WideString& wsTitle,
                             uint32_t dwIconType,
                             uint32_t dwButtonType) {
-  if (!m_pFormFillEnv)
+  CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pFormFillEnvList.GetAt(0);
+  if (!pFormFillEnv)
     return -1;
 
   uint32_t iconType = 0;
@@ -86,8 +147,8 @@
       iButtonType |= 3;
       break;
   }
-  int32_t iRet = m_pFormFillEnv->JS_appAlert(wsMessage.c_str(), wsTitle.c_str(),
-                                             iButtonType, iconType);
+  int32_t iRet = pFormFillEnv->JS_appAlert(wsMessage.c_str(), wsTitle.c_str(),
+                                           iButtonType, iconType);
   switch (iRet) {
     case 1:
       return XFA_IDOK;
@@ -106,29 +167,29 @@
                                      const CFX_WideString& wsDefaultAnswer,
                                      FX_BOOL bMark) {
   CFX_WideString wsAnswer;
-  if (!m_pFormFillEnv)
-    return wsAnswer;
-
-  int nLength = 2048;
-  char* pBuff = new char[nLength];
-  nLength = m_pFormFillEnv->JS_appResponse(wsQuestion.c_str(), wsTitle.c_str(),
+  CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pFormFillEnvList.GetAt(0);
+  if (pFormFillEnv) {
+    int nLength = 2048;
+    char* pBuff = new char[nLength];
+    nLength = pFormFillEnv->JS_appResponse(wsQuestion.c_str(), wsTitle.c_str(),
                                            wsDefaultAnswer.c_str(), nullptr,
                                            bMark, pBuff, nLength);
-  if (nLength > 0) {
-    nLength = nLength > 2046 ? 2046 : nLength;
-    pBuff[nLength] = 0;
-    pBuff[nLength + 1] = 0;
-    wsAnswer = CFX_WideString::FromUTF16LE(
-        reinterpret_cast<const unsigned short*>(pBuff),
-        nLength / sizeof(unsigned short));
+    if (nLength > 0) {
+      nLength = nLength > 2046 ? 2046 : nLength;
+      pBuff[nLength] = 0;
+      pBuff[nLength + 1] = 0;
+      wsAnswer = CFX_WideString::FromUTF16LE(
+          reinterpret_cast<const unsigned short*>(pBuff),
+          nLength / sizeof(unsigned short));
+    }
+    delete[] pBuff;
   }
-  delete[] pBuff;
   return wsAnswer;
 }
 
 IFX_FileRead* CPDFXFA_App::DownloadURL(const CFX_WideString& wsURL) {
-  return m_pFormFillEnv ? m_pFormFillEnv->DownloadFromURL(wsURL.c_str())
-                        : nullptr;
+  CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pFormFillEnvList.GetAt(0);
+  return pFormFillEnv ? pFormFillEnv->DownloadFromURL(wsURL.c_str()) : nullptr;
 }
 
 FX_BOOL CPDFXFA_App::PostRequestURL(const CFX_WideString& wsURL,
@@ -137,21 +198,23 @@
                                     const CFX_WideString& wsEncode,
                                     const CFX_WideString& wsHeader,
                                     CFX_WideString& wsResponse) {
-  if (!m_pFormFillEnv)
+  CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pFormFillEnvList.GetAt(0);
+  if (!pFormFillEnv)
     return FALSE;
 
-  wsResponse = m_pFormFillEnv->PostRequestURL(
-      wsURL.c_str(), wsData.c_str(), wsContentType.c_str(), wsEncode.c_str(),
-      wsHeader.c_str());
+  wsResponse = pFormFillEnv->PostRequestURL(wsURL.c_str(), wsData.c_str(),
+                                            wsContentType.c_str(),
+                                            wsEncode.c_str(), wsHeader.c_str());
   return TRUE;
 }
 
 FX_BOOL CPDFXFA_App::PutRequestURL(const CFX_WideString& wsURL,
                                    const CFX_WideString& wsData,
                                    const CFX_WideString& wsEncode) {
-  return m_pFormFillEnv &&
-         m_pFormFillEnv->PutRequestURL(wsURL.c_str(), wsData.c_str(),
-                                       wsEncode.c_str());
+  CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pFormFillEnvList.GetAt(0);
+  return pFormFillEnv &&
+         pFormFillEnv->PutRequestURL(wsURL.c_str(), wsData.c_str(),
+                                     wsEncode.c_str());
 }
 
 void CPDFXFA_App::LoadString(int32_t iStringID, CFX_WideString& wsString) {
@@ -253,7 +316,8 @@
 
 IFWL_AdapterTimerMgr* CPDFXFA_App::GetTimerMgr() {
   CXFA_FWLAdapterTimerMgr* pAdapter = nullptr;
-  if (m_pFormFillEnv)
-    pAdapter = new CXFA_FWLAdapterTimerMgr(m_pFormFillEnv);
+  CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pFormFillEnvList.GetAt(0);
+  if (pFormFillEnv)
+    pAdapter = new CXFA_FWLAdapterTimerMgr(pFormFillEnv);
   return pAdapter;
 }
diff --git a/fpdfsdk/fpdfxfa/cpdfxfa_app.h b/fpdfsdk/fpdfxfa/cpdfxfa_app.h
index c867df2..78184d1 100644
--- a/fpdfsdk/fpdfxfa/cpdfxfa_app.h
+++ b/fpdfsdk/fpdfxfa/cpdfxfa_app.h
@@ -14,13 +14,21 @@
 
 class CPDFXFA_App : public IXFA_AppProvider {
  public:
+  static CPDFXFA_App* GetInstance();
+  static void ReleaseInstance();
+
   CPDFXFA_App();
   ~CPDFXFA_App() override;
 
+  FX_BOOL Initialize(v8::Isolate* pIsolate);
   CXFA_FFApp* GetXFAApp() { return m_pXFAApp.get(); }
 
-  void SetFormFillEnv(CPDFSDK_FormFillEnvironment* pFormFillEnv) {
-    m_pFormFillEnv = pFormFillEnv;
+  FX_BOOL AddFormFillEnv(CPDFSDK_FormFillEnvironment* pFormFillEnv);
+  FX_BOOL RemoveFormFillEnv(CPDFSDK_FormFillEnvironment* pFormFillEnv);
+
+  FX_BOOL IsJavaScriptInitialized() const { return m_bJavaScriptInitialized; }
+  void SetJavaScriptInitialized(FX_BOOL bInitialized) {
+    m_bJavaScriptInitialized = bInitialized;
   }
 
   v8::Isolate* GetJSERuntime() const { return m_pIsolate; }
@@ -54,11 +62,12 @@
   void LoadString(int32_t iStringID, CFX_WideString& wsString) override;
   IFWL_AdapterTimerMgr* GetTimerMgr() override;
 
- private:
-  CPDFSDK_FormFillEnvironment* m_pFormFillEnv;  // Not owned.
+  CFX_ArrayTemplate<CPDFSDK_FormFillEnvironment*> m_pFormFillEnvList;
+
+ protected:
+  FX_BOOL m_bJavaScriptInitialized;
   std::unique_ptr<CXFA_FFApp> m_pXFAApp;
   v8::Isolate* m_pIsolate;
-  bool m_bOwnsIsolate;
 };
 
 #endif  // FPDFSDK_FPDFXFA_CPDFXFA_APP_H_
diff --git a/fpdfsdk/fpdfxfa/cpdfxfa_document.cpp b/fpdfsdk/fpdfxfa/cpdfxfa_document.cpp
index 79d28c0..df0da31 100644
--- a/fpdfsdk/fpdfxfa/cpdfxfa_document.cpp
+++ b/fpdfsdk/fpdfxfa/cpdfxfa_document.cpp
@@ -16,7 +16,6 @@
 #include "fpdfsdk/fsdk_define.h"
 #include "fpdfsdk/javascript/ijs_runtime.h"
 #include "public/fpdf_formfill.h"
-#include "third_party/base/ptr_util.h"
 #include "xfa/fxfa/cxfa_eventparam.h"
 #include "xfa/fxfa/xfa_ffapp.h"
 #include "xfa/fxfa/xfa_ffdoc.h"
@@ -29,11 +28,13 @@
 extern int GetLastError();
 #endif
 
-CPDFXFA_Document::CPDFXFA_Document(std::unique_ptr<CPDF_Document> pPDFDoc)
+CPDFXFA_Document::CPDFXFA_Document(std::unique_ptr<CPDF_Document> pPDFDoc,
+                                   CPDFXFA_App* pProvider)
     : m_iDocType(DOCTYPE_PDF),
       m_pPDFDoc(std::move(pPDFDoc)),
       m_pFormFillEnv(nullptr),
       m_pXFADocView(nullptr),
+      m_pApp(pProvider),
       m_nLoadStatus(FXFA_LOADSTATUS_PRELOAD),
       m_nPageCount(0),
       m_DocEnv(this) {}
@@ -41,12 +42,6 @@
 CPDFXFA_Document::~CPDFXFA_Document() {
   m_nLoadStatus = FXFA_LOADSTATUS_CLOSING;
 
-  // Must happen before we remove the form fill environment.
-  if (m_pXFADoc) {
-    if (CXFA_FFApp* pApp = GetApp()->GetXFAApp())
-      CloseXFADoc(pApp->GetDocHandler());
-  }
-
   if (m_pFormFillEnv) {
     m_pFormFillEnv->ClearAllFocusedAnnots();
     // Once we're deleted the FormFillEnvironment will point at a bad underlying
@@ -55,23 +50,19 @@
     m_pFormFillEnv = nullptr;
   }
 
+  if (m_pXFADoc) {
+    CXFA_FFApp* pApp = m_pApp->GetXFAApp();
+    if (pApp) {
+      CXFA_FFDocHandler* pDocHandler = pApp->GetDocHandler();
+      if (pDocHandler)
+        CloseXFADoc(pDocHandler);
+    }
+    m_pXFADoc.reset();
+  }
+
   m_nLoadStatus = FXFA_LOADSTATUS_CLOSED;
 }
 
-void CPDFXFA_Document::CloseXFADoc(CXFA_FFDocHandler* pDoc) {
-  if (!pDoc)
-    return;
-  m_pXFADoc->CloseDoc();
-  m_pXFADoc.reset();
-  m_pXFADocView = nullptr;
-}
-
-CPDFXFA_App* CPDFXFA_Document::GetApp() {
-  if (!m_pApp)
-    m_pApp = pdfium::MakeUnique<CPDFXFA_App>();
-  return m_pApp.get();
-}
-
 FX_BOOL CPDFXFA_Document::LoadXFADoc() {
   m_nLoadStatus = FXFA_LOADSTATUS_LOADING;
 
@@ -80,7 +71,7 @@
 
   m_XFAPageList.RemoveAll();
 
-  CXFA_FFApp* pApp = GetApp()->GetXFAApp();
+  CXFA_FFApp* pApp = m_pApp->GetXFAApp();
   if (!pApp)
     return FALSE;
 
@@ -104,7 +95,7 @@
     return FALSE;
   }
   m_pXFADoc->StopLoad();
-  m_pXFADoc->GetXFADoc()->InitScriptContext(GetApp()->GetJSERuntime());
+  m_pXFADoc->GetXFADoc()->InitScriptContext(m_pApp->GetJSERuntime());
 
   if (m_pXFADoc->GetDocType() == XFA_DOCTYPE_Dynamic)
     m_iDocType = DOCTYPE_DYNAMIC_XFA;
diff --git a/fpdfsdk/fpdfxfa/cpdfxfa_document.h b/fpdfsdk/fpdfxfa/cpdfxfa_document.h
index 88c0e60..de997c1 100644
--- a/fpdfsdk/fpdfxfa/cpdfxfa_document.h
+++ b/fpdfsdk/fpdfxfa/cpdfxfa_document.h
@@ -9,11 +9,11 @@
 
 #include <memory>
 
-#include "fpdfsdk/fpdfxfa/cpdfxfa_app.h"
 #include "fpdfsdk/fpdfxfa/cpdfxfa_docenvironment.h"
 #include "xfa/fxfa/xfa_ffdoc.h"
 
 class CPDFSDK_FormFillEnvironment;
+class CPDFXFA_App;
 class CPDFXFA_Page;
 class CXFA_FFDocHandler;
 class IJS_Runtime;
@@ -29,7 +29,8 @@
 
 class CPDFXFA_Document {
  public:
-  CPDFXFA_Document(std::unique_ptr<CPDF_Document> pPDFDoc);
+  CPDFXFA_Document(std::unique_ptr<CPDF_Document> pPDFDoc,
+                   CPDFXFA_App* pProvider);
   ~CPDFXFA_Document();
 
   FX_BOOL LoadXFADoc();
@@ -37,11 +38,9 @@
   CXFA_FFDoc* GetXFADoc() { return m_pXFADoc.get(); }
   CXFA_FFDocView* GetXFADocView() { return m_pXFADocView; }
   int GetDocType() const { return m_iDocType; }
-  CPDFXFA_App* GetApp();  // Creates if needed.
 
   CPDFSDK_FormFillEnvironment* GetFormFillEnv() const { return m_pFormFillEnv; }
   void SetFormFillEnv(CPDFSDK_FormFillEnvironment* pFormFillEnv) {
-    GetApp()->SetFormFillEnv(pFormFillEnv);
     m_pFormFillEnv = pFormFillEnv;
   }
 
@@ -69,7 +68,13 @@
   CFX_ArrayTemplate<CPDFXFA_Page*>* GetXFAPageList() { return &m_XFAPageList; }
 
  private:
-  void CloseXFADoc(CXFA_FFDocHandler* pDoc);
+  void CloseXFADoc(CXFA_FFDocHandler* pDoc) {
+    if (pDoc) {
+      m_pXFADoc->CloseDoc();
+      m_pXFADoc.reset();
+      m_pXFADocView = nullptr;
+    }
+  }
 
   int m_iDocType;
 
@@ -77,7 +82,7 @@
   std::unique_ptr<CXFA_FFDoc> m_pXFADoc;
   CPDFSDK_FormFillEnvironment* m_pFormFillEnv;  // not owned.
   CXFA_FFDocView* m_pXFADocView;  // not owned.
-  std::unique_ptr<CPDFXFA_App> m_pApp;
+  CPDFXFA_App* const m_pApp;
   CFX_ArrayTemplate<CPDFXFA_Page*> m_XFAPageList;
   LoadStatus m_nLoadStatus;
   int m_nPageCount;
diff --git a/fpdfsdk/javascript/cjs_runtime.cpp b/fpdfsdk/javascript/cjs_runtime.cpp
index 637fa0a..d41726b 100644
--- a/fpdfsdk/javascript/cjs_runtime.cpp
+++ b/fpdfsdk/javascript/cjs_runtime.cpp
@@ -68,7 +68,7 @@
       m_bBlocking(false),
       m_isolateManaged(false) {
   v8::Isolate* pIsolate = nullptr;
-
+#ifndef PDF_ENABLE_XFA
   IPDF_JSPLATFORM* pPlatform = m_pFormFillEnv->GetFormFillInfo()->m_pJsPlatform;
   if (pPlatform->version <= 2) {
     unsigned int embedderDataSlot = 0;
@@ -81,15 +81,44 @@
   }
   m_isolateManaged = FXJS_GetIsolate(&pIsolate);
   SetIsolate(pIsolate);
+#else
+  if (CPDFXFA_App::GetInstance()->GetJSERuntime()) {
+    // TODO(tsepez): CPDFXFA_App should also use the embedder provided isolate.
+    pIsolate = CPDFXFA_App::GetInstance()->GetJSERuntime();
+    SetIsolate(pIsolate);
+  } else {
+    IPDF_JSPLATFORM* pPlatform =
+        m_pFormFillEnv->GetFormFillInfo()->m_pJsPlatform;
+    if (pPlatform->version <= 2) {
+      unsigned int embedderDataSlot = 0;
+      v8::Isolate* pExternalIsolate = nullptr;
+      if (pPlatform->version == 2) {
+        pExternalIsolate = reinterpret_cast<v8::Isolate*>(pPlatform->m_isolate);
+        embedderDataSlot = pPlatform->m_v8EmbedderSlot;
+      }
+      FXJS_Initialize(embedderDataSlot, pExternalIsolate);
+    }
+    m_isolateManaged = FXJS_GetIsolate(&pIsolate);
+    SetIsolate(pIsolate);
+  }
 
-#ifdef PDF_ENABLE_XFA
   v8::Isolate::Scope isolate_scope(pIsolate);
   v8::HandleScope handle_scope(pIsolate);
+  if (CPDFXFA_App::GetInstance()->IsJavaScriptInitialized()) {
+    CJS_Context* pContext = (CJS_Context*)NewContext();
+    InitializeEngine();
+    ReleaseContext(pContext);
+    return;
+  }
 #endif
 
   if (m_isolateManaged || FXJS_GlobalIsolateRefCount() == 0)
     DefineJSObjects();
 
+#ifdef PDF_ENABLE_XFA
+  CPDFXFA_App::GetInstance()->SetJavaScriptInitialized(TRUE);
+#endif
+
   CJS_Context* pContext = (CJS_Context*)NewContext();
   InitializeEngine();
   ReleaseContext(pContext);
@@ -232,9 +261,19 @@
 
   v8::Isolate::Scope isolate_scope(GetIsolate());
   v8::HandleScope handle_scope(GetIsolate());
+  v8::Local<v8::Context> old_context = GetIsolate()->GetCurrentContext();
   v8::Local<v8::Context> context = NewLocalContext();
   v8::Context::Scope context_scope(context);
 
+  // Caution: We're about to hand to XFA an object that in order to invoke
+  // methods will require that the current v8::Context always has a pointer
+  // to a CJS_Runtime in its embedder data slot. Unfortunately, XFA creates
+  // its own v8::Context which has not initialized the embedder data slot.
+  // Do so now.
+  // TODO(tsepez): redesign PDF-side objects to not rely on v8::Context's
+  // embedder data slots, and/or to always use the right context.
+  CFXJS_Engine::SetForV8Context(old_context, this);
+
   v8::Local<v8::Value> propvalue =
       context->Global()->Get(v8::String::NewFromUtf8(
           GetIsolate(), name, v8::String::kNormalString, utf8Name.GetLength()));
diff --git a/fxjs/fxjs_v8.cpp b/fxjs/fxjs_v8.cpp
index 5ce8c47..d74d355 100644
--- a/fxjs/fxjs_v8.cpp
+++ b/fxjs/fxjs_v8.cpp
@@ -233,6 +233,14 @@
           kPerContextDataIndex));
 }
 
+#ifdef PDF_ENABLE_XFA
+// static
+void CFXJS_Engine::SetForV8Context(v8::Local<v8::Context> v8Context,
+                                   CFXJS_Engine* pEngine) {
+  v8Context->SetAlignedPointerInEmbedderData(kPerContextDataIndex, pEngine);
+}
+#endif  // PDF_ENABLE_XFA
+
 // static
 int CFXJS_Engine::GetObjDefnID(v8::Local<v8::Object> pObj) {
   if (pObj.IsEmpty() || !pObj->InternalFieldCount())
diff --git a/fxjs/fxjs_v8.h b/fxjs/fxjs_v8.h
index ba72962..5f65898 100644
--- a/fxjs/fxjs_v8.h
+++ b/fxjs/fxjs_v8.h
@@ -139,6 +139,13 @@
   static CFXJS_Engine* CurrentEngineFromIsolate(v8::Isolate* pIsolate);
   static int GetObjDefnID(v8::Local<v8::Object> pObj);
 
+#ifdef PDF_ENABLE_XFA
+  // Called as part of FXJS_InitializeEngine, exposed so PDF can make its
+  // own contexts compatible with XFA or vice versa.
+  static void SetForV8Context(v8::Local<v8::Context> v8Context,
+                              CFXJS_Engine* pEngine);
+#endif  // PDF_ENABLE_XFA
+
   v8::Isolate* GetIsolate() const { return m_isolate; }
 
   // Always returns a valid, newly-created objDefnID.