Reland: Make the CPDFXFA_App non-global

This reverts commit a282c7380f3964de41ea93c9980b12c4513d3473.

This CL changes CPDFXFA_App from a global object to a child of the
CPDFXFA_Document objects.

BUG=pdfium:623

Review-Url: https://codereview.chromium.org/2421603002
diff --git a/BUILD.gn b/BUILD.gn
index a77ea4c..d35f97d 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -1067,6 +1067,7 @@
     ]
     deps = [
       ":fxcrt",
+      ":fxjs",
       ":xfa",
     ]
     configs += [ ":pdfium_core_config" ]
diff --git a/fpdfsdk/DEPS b/fpdfsdk/DEPS
index 5b1f3c4..ce037d9 100644
--- a/fpdfsdk/DEPS
+++ b/fpdfsdk/DEPS
@@ -3,6 +3,7 @@
   '+public',
   '+v8',
   '+xfa/fwl/core',
+  '+xfa/fxbarcode',
   '+xfa/fxfa',
   '+xfa/fxgraphics',
-]
+  ]
diff --git a/fpdfsdk/cpdfsdk_formfillenvironment.cpp b/fpdfsdk/cpdfsdk_formfillenvironment.cpp
index 1f39de9..2c44211 100644
--- a/fpdfsdk/cpdfsdk_formfillenvironment.cpp
+++ b/fpdfsdk/cpdfsdk_formfillenvironment.cpp
@@ -58,11 +58,6 @@
   // 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 48be723..adc135e 100644
--- a/fpdfsdk/fpdfdoc_unittest.cpp
+++ b/fpdfsdk/fpdfdoc_unittest.cpp
@@ -35,8 +35,7 @@
 class CPDF_TestXFADocument : public CPDFXFA_Document {
  public:
   CPDF_TestXFADocument()
-      : CPDFXFA_Document(pdfium::MakeUnique<CPDF_TestDocument>(),
-                         CPDFXFA_App::GetInstance()) {}
+      : CPDFXFA_Document(pdfium::MakeUnique<CPDF_TestDocument>()) {}
 
   void SetRoot(CPDF_Dictionary* root) {
     reinterpret_cast<CPDF_TestDocument*>(GetPDFDoc())->SetRoot(root);
diff --git a/fpdfsdk/fpdfformfill.cpp b/fpdfsdk/fpdfformfill.cpp
index 34e206d..0f44b1d 100644
--- a/fpdfsdk/fpdfformfill.cpp
+++ b/fpdfsdk/fpdfformfill.cpp
@@ -258,7 +258,6 @@
 
 #ifdef PDF_ENABLE_XFA
   pDocument->SetFormFillEnv(pFormFillEnv);
-  CPDFXFA_App::GetInstance()->AddFormFillEnv(pFormFillEnv);
 #endif  // PDF_ENABLE_XFA
 
   return pFormFillEnv;
@@ -273,8 +272,6 @@
       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 03a9db1..c98bb77 100644
--- a/fpdfsdk/fpdfsave.cpp
+++ b/fpdfsdk/fpdfsave.cpp
@@ -85,9 +85,6 @@
       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 03aedf6..f8e8e47 100644
--- a/fpdfsdk/fpdfview.cpp
+++ b/fpdfsdk/fpdfview.cpp
@@ -42,6 +42,7 @@
 #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_
@@ -70,8 +71,8 @@
 
 FPDF_DOCUMENT FPDFDocumentFromCPDFDocument(CPDF_Document* doc) {
 #ifdef PDF_ENABLE_XFA
-  return doc ? FPDFDocumentFromUnderlying(new CPDFXFA_Document(
-                   pdfium::WrapUnique(doc), CPDFXFA_App::GetInstance()))
+  return doc ? FPDFDocumentFromUnderlying(
+                   new CPDFXFA_Document(pdfium::WrapUnique(doc)))
              : nullptr;
 #else   // PDF_ENABLE_XFA
   return FPDFDocumentFromUnderlying(doc);
@@ -249,19 +250,19 @@
   pModuleMgr->LoadEmbeddedKorea1CMaps();
 
 #ifdef PDF_ENABLE_XFA
-  CPDFXFA_App::GetInstance()->Initialize(
-      (cfg && cfg->version >= 2) ? static_cast<v8::Isolate*>(cfg->m_pIsolate)
-                                 : nullptr);
+  FXJSE_Initialize();
+  BC_Library_Init();
 #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
-  CPDFXFA_App::ReleaseInstance();
+  BC_Library_Destory();
+  FXJSE_Finalize();
 #endif  // PDF_ENABLE_XFA
+
   CPDF_ModuleMgr::Destroy();
   CFX_GEModule::Destroy();
 
@@ -342,11 +343,7 @@
     ProcessParseError(error);
     return nullptr;
   }
-#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
+  return FPDFDocumentFromCPDFDocument(pDocument.release());
 }
 
 #ifdef PDF_ENABLE_XFA
diff --git a/fpdfsdk/fpdfxfa/DEPS b/fpdfsdk/fpdfxfa/DEPS
index d4de6f1..1687e30 100644
--- a/fpdfsdk/fpdfxfa/DEPS
+++ b/fpdfsdk/fpdfxfa/DEPS
@@ -1,3 +1,4 @@
 include_rules = [
+  '+fxjs',
   '+xfa/fxbarcode',
 ]
diff --git a/fpdfsdk/fpdfxfa/cpdfxfa_app.cpp b/fpdfsdk/fpdfxfa/cpdfxfa_app.cpp
index dc5c4be..27ca1e0 100644
--- a/fpdfsdk/fpdfxfa/cpdfxfa_app.cpp
+++ b/fpdfsdk/fpdfxfa/cpdfxfa_app.cpp
@@ -11,110 +11,58 @@
 #include "fpdfsdk/cpdfsdk_formfillenvironment.h"
 #include "fpdfsdk/fpdfxfa/cxfa_fwladaptertimermgr.h"
 #include "fpdfsdk/fsdk_define.h"
-#include "third_party/base/ptr_util.h"
-#include "xfa/fxbarcode/BC_Library.h"
+#include "fpdfsdk/javascript/cjs_runtime.h"
+#include "fxjs/fxjs_v8.h"
 #include "xfa/fxfa/xfa_ffapp.h"
 #include "xfa/fxfa/xfa_fontmgr.h"
 
-namespace {
-
-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() {
-  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;
-
+CPDFXFA_App::CPDFXFA_App() {
   m_pXFAApp = pdfium::MakeUnique<CXFA_FFApp>(this);
-  m_pXFAApp->SetDefaultFontMgr(
-      std::unique_ptr<CXFA_DefFontMgr>(new CXFA_DefFontMgr));
-
-  return TRUE;
+  m_pXFAApp->SetDefaultFontMgr(pdfium::MakeUnique<CXFA_DefFontMgr>());
 }
 
-FX_BOOL CPDFXFA_App::AddFormFillEnv(CPDFSDK_FormFillEnvironment* pFormFillEnv) {
-  if (!pFormFillEnv)
-    return FALSE;
+CPDFXFA_App::~CPDFXFA_App() {}
 
-  m_pFormFillEnvList.Add(pFormFillEnv);
-  return TRUE;
+v8::Isolate* CPDFXFA_App::GetJSERuntime() const {
+  if (!m_pFormFillEnv)
+    return nullptr;
+
+  // XFA requires V8, if we have V8 then we have a CJS_Runtime and not the stub.
+  CJS_Runtime* runtime =
+      static_cast<CJS_Runtime*>(m_pFormFillEnv->GetJSRuntime());
+  return runtime->GetIsolate();
 }
 
-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::SetFormFillEnv(CPDFSDK_FormFillEnvironment* pFormFillEnv) {
+  m_pFormFillEnv = pFormFillEnv;
 }
 
 void CPDFXFA_App::GetAppName(CFX_WideString& wsName) {
-  CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pFormFillEnvList.GetAt(0);
-  if (pFormFillEnv)
-    wsName = pFormFillEnv->FFI_GetAppName();
+  if (m_pFormFillEnv)
+    wsName = m_pFormFillEnv->FFI_GetAppName();
 }
 
 void CPDFXFA_App::GetLanguage(CFX_WideString& wsLanguage) {
-  CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pFormFillEnvList.GetAt(0);
-  if (pFormFillEnv)
-    wsLanguage = pFormFillEnv->GetLanguage();
+  if (m_pFormFillEnv)
+    wsLanguage = m_pFormFillEnv->GetLanguage();
 }
 
 void CPDFXFA_App::GetPlatform(CFX_WideString& wsPlatform) {
-  CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pFormFillEnvList.GetAt(0);
-  if (pFormFillEnv) {
-    wsPlatform = pFormFillEnv->GetPlatform();
+  if (m_pFormFillEnv) {
+    wsPlatform = m_pFormFillEnv->GetPlatform();
   }
 }
 
 void CPDFXFA_App::Beep(uint32_t dwType) {
-  CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pFormFillEnvList.GetAt(0);
-  if (pFormFillEnv)
-    pFormFillEnv->JS_appBeep(dwType);
+  if (m_pFormFillEnv)
+    m_pFormFillEnv->JS_appBeep(dwType);
 }
 
 int32_t CPDFXFA_App::MsgBox(const CFX_WideString& wsMessage,
                             const CFX_WideString& wsTitle,
                             uint32_t dwIconType,
                             uint32_t dwButtonType) {
-  CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pFormFillEnvList.GetAt(0);
-  if (!pFormFillEnv)
+  if (!m_pFormFillEnv)
     return -1;
 
   uint32_t iconType = 0;
@@ -147,8 +95,8 @@
       iButtonType |= 3;
       break;
   }
-  int32_t iRet = pFormFillEnv->JS_appAlert(wsMessage.c_str(), wsTitle.c_str(),
-                                           iButtonType, iconType);
+  int32_t iRet = m_pFormFillEnv->JS_appAlert(wsMessage.c_str(), wsTitle.c_str(),
+                                             iButtonType, iconType);
   switch (iRet) {
     case 1:
       return XFA_IDOK;
@@ -167,29 +115,29 @@
                                      const CFX_WideString& wsDefaultAnswer,
                                      FX_BOOL bMark) {
   CFX_WideString wsAnswer;
-  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(),
+  if (!m_pFormFillEnv)
+    return wsAnswer;
+
+  int nLength = 2048;
+  char* pBuff = new char[nLength];
+  nLength = m_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));
-    }
-    delete[] pBuff;
+  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;
   return wsAnswer;
 }
 
 IFX_SeekableReadStream* CPDFXFA_App::DownloadURL(const CFX_WideString& wsURL) {
-  CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pFormFillEnvList.GetAt(0);
-  return pFormFillEnv ? pFormFillEnv->DownloadFromURL(wsURL.c_str()) : nullptr;
+  return m_pFormFillEnv ? m_pFormFillEnv->DownloadFromURL(wsURL.c_str())
+                        : nullptr;
 }
 
 FX_BOOL CPDFXFA_App::PostRequestURL(const CFX_WideString& wsURL,
@@ -198,23 +146,21 @@
                                     const CFX_WideString& wsEncode,
                                     const CFX_WideString& wsHeader,
                                     CFX_WideString& wsResponse) {
-  CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pFormFillEnvList.GetAt(0);
-  if (!pFormFillEnv)
+  if (!m_pFormFillEnv)
     return FALSE;
 
-  wsResponse = pFormFillEnv->PostRequestURL(wsURL.c_str(), wsData.c_str(),
-                                            wsContentType.c_str(),
-                                            wsEncode.c_str(), wsHeader.c_str());
+  wsResponse = m_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) {
-  CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pFormFillEnvList.GetAt(0);
-  return pFormFillEnv &&
-         pFormFillEnv->PutRequestURL(wsURL.c_str(), wsData.c_str(),
-                                     wsEncode.c_str());
+  return m_pFormFillEnv &&
+         m_pFormFillEnv->PutRequestURL(wsURL.c_str(), wsData.c_str(),
+                                       wsEncode.c_str());
 }
 
 void CPDFXFA_App::LoadString(int32_t iStringID, CFX_WideString& wsString) {
@@ -316,8 +262,7 @@
 
 IFWL_AdapterTimerMgr* CPDFXFA_App::GetTimerMgr() {
   CXFA_FWLAdapterTimerMgr* pAdapter = nullptr;
-  CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pFormFillEnvList.GetAt(0);
-  if (pFormFillEnv)
-    pAdapter = new CXFA_FWLAdapterTimerMgr(pFormFillEnv);
+  if (m_pFormFillEnv)
+    pAdapter = new CXFA_FWLAdapterTimerMgr(m_pFormFillEnv);
   return pAdapter;
 }
diff --git a/fpdfsdk/fpdfxfa/cpdfxfa_app.h b/fpdfsdk/fpdfxfa/cpdfxfa_app.h
index 9ec045f..763f88d 100644
--- a/fpdfsdk/fpdfxfa/cpdfxfa_app.h
+++ b/fpdfsdk/fpdfxfa/cpdfxfa_app.h
@@ -7,31 +7,22 @@
 #ifndef FPDFSDK_FPDFXFA_CPDFXFA_APP_H_
 #define FPDFSDK_FPDFXFA_CPDFXFA_APP_H_
 
+#include "third_party/base/ptr_util.h"
 #include "xfa/fxfa/fxfa.h"
 
 class CPDFSDK_FormFillEnvironment;
-class IFXJS_Runtime;
+class CJS_Runtime;
 
 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(); }
 
-  FX_BOOL AddFormFillEnv(CPDFSDK_FormFillEnvironment* pFormFillEnv);
-  FX_BOOL RemoveFormFillEnv(CPDFSDK_FormFillEnvironment* pFormFillEnv);
+  void SetFormFillEnv(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; }
+  v8::Isolate* GetJSERuntime() const;
 
   // IFXA_AppProvider:
   void GetLanguage(CFX_WideString& wsLanguage) override;
@@ -62,12 +53,9 @@
   void LoadString(int32_t iStringID, CFX_WideString& wsString) override;
   IFWL_AdapterTimerMgr* GetTimerMgr() override;
 
-  CFX_ArrayTemplate<CPDFSDK_FormFillEnvironment*> m_pFormFillEnvList;
-
- protected:
-  FX_BOOL m_bJavaScriptInitialized;
+ private:
+  CPDFSDK_FormFillEnvironment* m_pFormFillEnv;  // Not owned.
   std::unique_ptr<CXFA_FFApp> m_pXFAApp;
-  v8::Isolate* m_pIsolate;
 };
 
 #endif  // FPDFSDK_FPDFXFA_CPDFXFA_APP_H_
diff --git a/fpdfsdk/fpdfxfa/cpdfxfa_document.cpp b/fpdfsdk/fpdfxfa/cpdfxfa_document.cpp
index df0da31..b04b950 100644
--- a/fpdfsdk/fpdfxfa/cpdfxfa_document.cpp
+++ b/fpdfsdk/fpdfxfa/cpdfxfa_document.cpp
@@ -16,6 +16,7 @@
 #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"
@@ -28,13 +29,11 @@
 extern int GetLastError();
 #endif
 
-CPDFXFA_Document::CPDFXFA_Document(std::unique_ptr<CPDF_Document> pPDFDoc,
-                                   CPDFXFA_App* pProvider)
+CPDFXFA_Document::CPDFXFA_Document(std::unique_ptr<CPDF_Document> pPDFDoc)
     : 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) {}
@@ -42,6 +41,12 @@
 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
@@ -50,19 +55,35 @@
     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();
+}
+
+void CPDFXFA_Document::SetFormFillEnv(
+    CPDFSDK_FormFillEnvironment* pFormFillEnv) {
+  // The layout data can have pointers back into the script context. That
+  // context will be different if the form fill environment closes, so, force
+  // the layout data to clear.
+  if (m_pXFADoc && m_pXFADoc->GetXFADoc())
+    m_pXFADoc->GetXFADoc()->ClearLayoutData();
+
+  GetApp()->SetFormFillEnv(pFormFillEnv);
+  m_pFormFillEnv = pFormFillEnv;
+}
+
 FX_BOOL CPDFXFA_Document::LoadXFADoc() {
   m_nLoadStatus = FXFA_LOADSTATUS_LOADING;
 
@@ -71,7 +92,7 @@
 
   m_XFAPageList.RemoveAll();
 
-  CXFA_FFApp* pApp = m_pApp->GetXFAApp();
+  CXFA_FFApp* pApp = GetApp()->GetXFAApp();
   if (!pApp)
     return FALSE;
 
@@ -95,7 +116,7 @@
     return FALSE;
   }
   m_pXFADoc->StopLoad();
-  m_pXFADoc->GetXFADoc()->InitScriptContext(m_pApp->GetJSERuntime());
+  m_pXFADoc->GetXFADoc()->InitScriptContext(GetApp()->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 de997c1..00a9f25 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,8 +29,7 @@
 
 class CPDFXFA_Document {
  public:
-  CPDFXFA_Document(std::unique_ptr<CPDF_Document> pPDFDoc,
-                   CPDFXFA_App* pProvider);
+  CPDFXFA_Document(std::unique_ptr<CPDF_Document> pPDFDoc);
   ~CPDFXFA_Document();
 
   FX_BOOL LoadXFADoc();
@@ -38,11 +37,10 @@
   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) {
-    m_pFormFillEnv = pFormFillEnv;
-  }
+  void SetFormFillEnv(CPDFSDK_FormFillEnvironment* pFormFillEnv);
 
   void DeletePage(int page_index);
   int GetPageCount() const;
@@ -68,13 +66,7 @@
   CFX_ArrayTemplate<CPDFXFA_Page*>* GetXFAPageList() { return &m_XFAPageList; }
 
  private:
-  void CloseXFADoc(CXFA_FFDocHandler* pDoc) {
-    if (pDoc) {
-      m_pXFADoc->CloseDoc();
-      m_pXFADoc.reset();
-      m_pXFADocView = nullptr;
-    }
-  }
+  void CloseXFADoc(CXFA_FFDocHandler* pDoc);
 
   int m_iDocType;
 
@@ -82,7 +74,7 @@
   std::unique_ptr<CXFA_FFDoc> m_pXFADoc;
   CPDFSDK_FormFillEnvironment* m_pFormFillEnv;  // not owned.
   CXFA_FFDocView* m_pXFADocView;  // not owned.
-  CPDFXFA_App* const m_pApp;
+  std::unique_ptr<CPDFXFA_App> 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 d41726b..637fa0a 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,44 +81,15 @@
   }
   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);
@@ -261,19 +232,9 @@
 
   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 d74d355..5ce8c47 100644
--- a/fxjs/fxjs_v8.cpp
+++ b/fxjs/fxjs_v8.cpp
@@ -233,14 +233,6 @@
           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 5f65898..ba72962 100644
--- a/fxjs/fxjs_v8.h
+++ b/fxjs/fxjs_v8.h
@@ -139,13 +139,6 @@
   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.
diff --git a/xfa/fxfa/parser/cxfa_scriptcontext.cpp b/xfa/fxfa/parser/cxfa_scriptcontext.cpp
index e7d45e3..af2f99a 100644
--- a/xfa/fxfa/parser/cxfa_scriptcontext.cpp
+++ b/xfa/fxfa/parser/cxfa_scriptcontext.cpp
@@ -135,6 +135,7 @@
 
   m_upObjectArray.RemoveAll();
 }
+
 void CXFA_ScriptContext::Initialize(v8::Isolate* pIsolate) {
   m_pIsolate = pIsolate;
   DefineJsContext();
diff --git a/xfa/fxfa/xfa_ffdoc.h b/xfa/fxfa/xfa_ffdoc.h
index f1ecd90..3976f1d 100644
--- a/xfa/fxfa/xfa_ffdoc.h
+++ b/xfa/fxfa/xfa_ffdoc.h
@@ -29,16 +29,21 @@
  public:
   CXFA_FFDoc(CXFA_FFApp* pApp, IXFA_DocEnvironment* pDocEnvironment);
   ~CXFA_FFDoc();
+
   IXFA_DocEnvironment* GetDocEnvironment() const { return m_pDocEnvironment; }
   uint32_t GetDocType();
+  void SetDocType(uint32_t dwType);
+
   int32_t StartLoad();
   int32_t DoLoad(IFX_Pause* pPause = nullptr);
   void StopLoad();
+
   CXFA_FFDocView* CreateDocView(uint32_t dwView = 0);
+
   FX_BOOL OpenDoc(IFX_SeekableReadStream* pStream, FX_BOOL bTakeOverFile);
   FX_BOOL OpenDoc(CPDF_Document* pPDFDoc);
   FX_BOOL CloseDoc();
-  void SetDocType(uint32_t dwType);
+
   CXFA_Document* GetXFADoc() { return m_pDocumentParser->GetDocument(); }
   CXFA_FFApp* GetApp() { return m_pApp; }
   CXFA_FFDocView* GetDocView(CXFA_LayoutProcessor* pLayout);