Move CFXJSE_Engine pointer directly into CFXJSE_ResolveProcessor itself.

Currently, this is being passed anew in each call via the
CFXJSE_ResolveProcessor::NodeData.

These are 1:1, and never change, so no need to pass it in via
NodeData on each call. In turn, make one anonymous function
into a method so it can access the engine member.

Next, get CFXJSE_Engine out of the business of creating resolve
processors, so callers can, in theory, pass in a fake one or
something.

Change-Id: I35feab1a69cee89ed9268375c2caef3fa0d9774a
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/94295
Commit-Queue: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
diff --git a/fxjs/xfa/cfxjse_engine.cpp b/fxjs/xfa/cfxjse_engine.cpp
index 7a4e436..c33c658 100644
--- a/fxjs/xfa/cfxjse_engine.cpp
+++ b/fxjs/xfa/cfxjse_engine.cpp
@@ -119,8 +119,10 @@
   return pJSObject ? pJSObject->GetXFAObject() : nullptr;
 }
 
-CFXJSE_Engine::CFXJSE_Engine(CXFA_Document* pDocument,
-                             CJS_Runtime* fxjs_runtime)
+CFXJSE_Engine::CFXJSE_Engine(
+    CXFA_Document* pDocument,
+    CJS_Runtime* fxjs_runtime,
+    std::unique_ptr<CFXJSE_ResolveProcessor> pProcessor)
     : CFX_V8(fxjs_runtime->GetIsolate()),
       m_pSubordinateRuntime(fxjs_runtime),
       m_pDocument(pDocument),
@@ -128,7 +130,8 @@
                                          &kGlobalClassDescriptor,
                                          pDocument->GetRoot()->JSObject(),
                                          nullptr)),
-      m_ResolveProcessor(std::make_unique<CFXJSE_ResolveProcessor>()) {
+      m_ResolveProcessor(std::move(pProcessor)) {
+  m_ResolveProcessor->SetEngine(this);
   RemoveBuiltInObjs(m_JsContext.get());
   m_JsContext->EnableCompatibleMode();
 
@@ -702,7 +705,7 @@
   pNodeHelper->m_pCreateParent = nullptr;
   pNodeHelper->m_iCurAllStart = -1;
 
-  CFXJSE_ResolveProcessor::NodeData rndFind(this);
+  CFXJSE_ResolveProcessor::NodeData rndFind;
   int32_t nStart = 0;
   int32_t nLevel = 0;
 
@@ -755,7 +758,7 @@
       if (((dwStyles & XFA_ResolveFlag::kBind) ||
            (dwStyles & XFA_ResolveFlag::kCreateNode)) &&
           nNodes > 1) {
-        CFXJSE_ResolveProcessor::NodeData rndBind(nullptr);
+        CFXJSE_ResolveProcessor::NodeData rndBind;
         m_ResolveProcessor->GetFilter(wsExpression, nStart, rndBind);
         i = m_ResolveProcessor->IndexForDataBind(rndBind.m_wsCondition, nNodes);
         bDataBind = true;
diff --git a/fxjs/xfa/cfxjse_engine.h b/fxjs/xfa/cfxjse_engine.h
index ce8108e..8fbc599 100644
--- a/fxjs/xfa/cfxjse_engine.h
+++ b/fxjs/xfa/cfxjse_engine.h
@@ -106,7 +106,9 @@
                                                   ByteStringView szPropName,
                                                   bool bQueryIn);
 
-  CFXJSE_Engine(CXFA_Document* pDocument, CJS_Runtime* fxjs_runtime);
+  CFXJSE_Engine(CXFA_Document* pDocument,
+                CJS_Runtime* fxjs_runtime,
+                std::unique_ptr<CFXJSE_ResolveProcessor> pProcessor);
   ~CFXJSE_Engine() override;
 
   void SetEventParam(CXFA_EventParam* param) { m_eventParam = param; }
diff --git a/fxjs/xfa/cfxjse_resolveprocessor.cpp b/fxjs/xfa/cfxjse_resolveprocessor.cpp
index 7f0017e..a945b97 100644
--- a/fxjs/xfa/cfxjse_resolveprocessor.cpp
+++ b/fxjs/xfa/cfxjse_resolveprocessor.cpp
@@ -25,40 +25,16 @@
 #include "xfa/fxfa/parser/cxfa_occur.h"
 #include "xfa/fxfa/parser/xfa_utils.h"
 
-namespace {
-
-void DoPredicateFilter(v8::Isolate* pIsolate,
-                       WideString wsCondition,
-                       size_t iFoundCount,
-                       CFXJSE_ResolveProcessor::NodeData* pRnd) {
-  DCHECK_EQ(iFoundCount, pRnd->m_Result.objects.size());
-  WideString wsExpression;
-  CXFA_Script::Type eLangType = CXFA_Script::Type::Unknown;
-  if (wsCondition.First(2).EqualsASCII(".[") && wsCondition.Back() == L']')
-    eLangType = CXFA_Script::Type::Formcalc;
-  else if (wsCondition.First(2).EqualsASCII(".(") && wsCondition.Back() == L')')
-    eLangType = CXFA_Script::Type::Javascript;
-  else
-    return;
-
-  wsExpression = wsCondition.Substr(2, wsCondition.GetLength() - 3);
-  for (size_t i = iFoundCount; i > 0; --i) {
-    auto pRetValue = std::make_unique<CFXJSE_Value>();
-    bool bRet = pRnd->m_pSC->RunScript(eLangType, wsExpression.AsStringView(),
-                                       pRetValue.get(),
-                                       pRnd->m_Result.objects[i - 1].Get());
-    if (!bRet || !pRetValue->ToBoolean(pIsolate))
-      pRnd->m_Result.objects.erase(pRnd->m_Result.objects.begin() + i - 1);
-  }
-}
-
-}  // namespace
-
 CFXJSE_ResolveProcessor::CFXJSE_ResolveProcessor()
     : m_pNodeHelper(std::make_unique<CFXJSE_NodeHelper>()) {}
 
 CFXJSE_ResolveProcessor::~CFXJSE_ResolveProcessor() = default;
 
+void CFXJSE_ResolveProcessor::SetEngine(CFXJSE_Engine* pEngine) {
+  DCHECK(!m_pEngine);
+  m_pEngine = pEngine;
+}
+
 bool CFXJSE_ResolveProcessor::Resolve(v8::Isolate* pIsolate, NodeData& rnd) {
   if (!rnd.m_CurObject)
     return false;
@@ -92,12 +68,12 @@
     }
   }
   if (rnd.m_uHashName == XFA_HASHCODE_This && rnd.m_nLevel == 0) {
-    rnd.m_Result.objects.emplace_back(rnd.m_pSC->GetThisObject());
+    rnd.m_Result.objects.emplace_back(m_pEngine->GetThisObject());
     return true;
   }
   if (rnd.m_CurObject->GetElementType() == XFA_Element::Xfa) {
     CXFA_Object* pObjNode =
-        rnd.m_pSC->GetDocument()->GetXFAObject(rnd.m_uHashName);
+        m_pEngine->GetDocument()->GetXFAObject(rnd.m_uHashName);
     if (pObjNode) {
       rnd.m_Result.objects.emplace_back(pObjNode);
     } else if (rnd.m_uHashName == XFA_HASHCODE_Xfa) {
@@ -113,7 +89,7 @@
     return !rnd.m_Result.objects.empty();
   }
   if (!ResolveNormal(pIsolate, rnd) && rnd.m_uHashName == XFA_HASHCODE_Xfa)
-    rnd.m_Result.objects.emplace_back(rnd.m_pSC->GetDocument()->GetRoot());
+    rnd.m_Result.objects.emplace_back(m_pEngine->GetDocument()->GetRoot());
 
   return !rnd.m_Result.objects.empty();
 }
@@ -163,12 +139,13 @@
   if (rnd.m_nLevel > 0)
     return false;
 
+  CXFA_Document* pDocument = m_pEngine->GetDocument();
   XFA_HashCode dwNameHash = static_cast<XFA_HashCode>(
       FX_HashCode_GetW(wsName.AsStringView().Last(nNameLen - 1)));
   if (dwNameHash == XFA_HASHCODE_Xfa) {
-    rnd.m_Result.objects.emplace_back(rnd.m_pSC->GetDocument()->GetRoot());
+    rnd.m_Result.objects.emplace_back(pDocument->GetRoot());
   } else {
-    CXFA_Object* pObjNode = rnd.m_pSC->GetDocument()->GetXFAObject(dwNameHash);
+    CXFA_Object* pObjNode = pDocument->GetXFAObject(dwNameHash);
     if (pObjNode)
       rnd.m_Result.objects.emplace_back(pObjNode);
   }
@@ -183,11 +160,11 @@
     return false;
 
   CXFA_Node* datasets =
-      ToNode(rnd.m_pSC->GetDocument()->GetXFAObject(XFA_HASHCODE_Datasets));
+      ToNode(m_pEngine->GetDocument()->GetXFAObject(XFA_HASHCODE_Datasets));
   if (!datasets)
     return false;
 
-  NodeData rndFind(rnd.m_pSC.Get());
+  NodeData rndFind;
   rndFind.m_CurObject = datasets;
   rndFind.m_wsName = rnd.m_wsName.Last(rnd.m_wsName.GetLength() - 1);
   rndFind.m_uHashName = static_cast<XFA_HashCode>(
@@ -211,7 +188,7 @@
   if (ResolveForAttributeRs(curNode, &rnd.m_Result, wsName.AsStringView()))
     return true;
 
-  NodeData rndFind(rnd.m_pSC.Get());
+  NodeData rndFind;
   rndFind.m_nLevel = rnd.m_nLevel + 1;
   rndFind.m_dwStyles = rnd.m_dwStyles;
   rndFind.m_dwStyles |= XFA_ResolveFlag::kTagName;
@@ -263,7 +240,7 @@
   XFA_HashCode uNameHash = rnd.m_uHashName;
   WideString& wsCondition = rnd.m_wsCondition;
 
-  NodeData rndFind(rnd.m_pSC.Get());
+  NodeData rndFind;
   rndFind.m_wsName = rnd.m_wsName;
   rndFind.m_wsCondition = rnd.m_wsCondition;
   rndFind.m_nLevel = rnd.m_nLevel + 1;
@@ -504,9 +481,9 @@
     if (dwStyles & XFA_ResolveFlag::kALL)
       dwSubStyles |= XFA_ResolveFlag::kALL;
 
+    m_pEngine->AddObjectToUpArray(parentNode);
     rndFind.m_dwStyles = dwSubStyles;
     rndFind.m_CurObject = parentNode;
-    rnd.m_pSC->AddObjectToUpArray(parentNode);
     ResolveNormal(pIsolate, rndFind);
     rnd.m_Result.objects.insert(rnd.m_Result.objects.end(),
                                 rndFind.m_Result.objects.begin(),
@@ -667,7 +644,7 @@
                                               WideString wsCondition,
                                               NodeData* pRnd) {
   size_t iCurIndex = 0;
-  CXFA_Node* pNode = pRnd->m_pSC->LastObjectFromUpArray();
+  CXFA_Node* pNode = m_pEngine->LastObjectFromUpArray();
   if (pNode) {
     const bool bIsProperty = pNode->IsProperty();
     const bool bIsClassIndex =
@@ -736,6 +713,30 @@
   return iCount - 1;
 }
 
-CFXJSE_ResolveProcessor::NodeData::NodeData(CFXJSE_Engine* pSC) : m_pSC(pSC) {}
+void CFXJSE_ResolveProcessor::DoPredicateFilter(v8::Isolate* pIsolate,
+                                                WideString wsCondition,
+                                                size_t iFoundCount,
+                                                NodeData* pRnd) {
+  DCHECK_EQ(iFoundCount, pRnd->m_Result.objects.size());
+  CXFA_Script::Type eLangType = CXFA_Script::Type::Unknown;
+  if (wsCondition.First(2).EqualsASCII(".[") && wsCondition.Back() == L']')
+    eLangType = CXFA_Script::Type::Formcalc;
+  else if (wsCondition.First(2).EqualsASCII(".(") && wsCondition.Back() == L')')
+    eLangType = CXFA_Script::Type::Javascript;
+  else
+    return;
+
+  WideString wsExpression = wsCondition.Substr(2, wsCondition.GetLength() - 3);
+  for (size_t i = iFoundCount; i > 0; --i) {
+    auto pRetValue = std::make_unique<CFXJSE_Value>();
+    bool bRet = m_pEngine->RunScript(eLangType, wsExpression.AsStringView(),
+                                     pRetValue.get(),
+                                     pRnd->m_Result.objects[i - 1].Get());
+    if (!bRet || !pRetValue->ToBoolean(pIsolate))
+      pRnd->m_Result.objects.erase(pRnd->m_Result.objects.begin() + i - 1);
+  }
+}
+
+CFXJSE_ResolveProcessor::NodeData::NodeData() = default;
 
 CFXJSE_ResolveProcessor::NodeData::~NodeData() = default;
diff --git a/fxjs/xfa/cfxjse_resolveprocessor.h b/fxjs/xfa/cfxjse_resolveprocessor.h
index c0ee9de..d8b076b 100644
--- a/fxjs/xfa/cfxjse_resolveprocessor.h
+++ b/fxjs/xfa/cfxjse_resolveprocessor.h
@@ -24,10 +24,9 @@
     CPPGC_STACK_ALLOCATED();  // Allows Raw/Unowned pointers.
 
    public:
-    explicit NodeData(CFXJSE_Engine* pSC);
+    NodeData();
     ~NodeData();
 
-    UnownedPtr<CFXJSE_Engine> const m_pSC;
     UnownedPtr<CXFA_Object> m_CurObject;  // Ok, stack-only.
     WideString m_wsName;
     WideString m_wsCondition;
@@ -40,6 +39,7 @@
   CFXJSE_ResolveProcessor();
   ~CFXJSE_ResolveProcessor();
 
+  void SetEngine(CFXJSE_Engine* pEngine);
   bool Resolve(v8::Isolate* pIsolate, NodeData& rnd);
   int32_t GetFilter(WideStringView wsExpression, int32_t nStart, NodeData& rnd);
   int32_t IndexForDataBind(const WideString& wsNextCondition, int32_t iCount);
@@ -66,8 +66,13 @@
   void FilterCondition(v8::Isolate* pIsolate,
                        WideString wsCondition,
                        NodeData* pRnd);
+  void DoPredicateFilter(v8::Isolate* pIsolate,
+                         WideString wsCondition,
+                         size_t iFoundCount,
+                         NodeData* pRnd);
 
   int32_t m_iCurStart = 0;
+  UnownedPtr<CFXJSE_Engine> m_pEngine;
   std::unique_ptr<CFXJSE_NodeHelper> const m_pNodeHelper;
 };
 
diff --git a/xfa/fxfa/parser/cxfa_document.cpp b/xfa/fxfa/parser/cxfa_document.cpp
index 5f8fe20..f4485fe 100644
--- a/xfa/fxfa/parser/cxfa_document.cpp
+++ b/xfa/fxfa/parser/cxfa_document.cpp
@@ -15,6 +15,7 @@
 #include "core/fxcrt/xml/cfx_xmlelement.h"
 #include "fxjs/gc/container_trace.h"
 #include "fxjs/xfa/cfxjse_engine.h"
+#include "fxjs/xfa/cfxjse_resolveprocessor.h"
 #include "fxjs/xfa/cjx_object.h"
 #include "third_party/base/check.h"
 #include "third_party/base/check_op.h"
@@ -1455,7 +1456,8 @@
 
 CFXJSE_Engine* CXFA_Document::InitScriptContext(CJS_Runtime* fxjs_runtime) {
   DCHECK(!m_pScriptContext);
-  m_pScriptContext = std::make_unique<CFXJSE_Engine>(this, fxjs_runtime);
+  m_pScriptContext = std::make_unique<CFXJSE_Engine>(
+      this, fxjs_runtime, std::make_unique<CFXJSE_ResolveProcessor>());
   return m_pScriptContext.get();
 }