More Execute* methods to CXFA_Node

This Cl moves the two Execute* methods from CXFA_WidgetAcc to CXFA_Node.

Change-Id: I4e1d6cd2159028800b855558273ca80aad365570
Reviewed-on: https://pdfium-review.googlesource.com/22550
Reviewed-by: Ryan Harrison <rharrison@chromium.org>
Commit-Queue: dsinclair <dsinclair@chromium.org>
diff --git a/xfa/fxfa/cxfa_ffdocview.cpp b/xfa/fxfa/cxfa_ffdocview.cpp
index 2165759..80d40d1 100644
--- a/xfa/fxfa/cxfa_ffdocview.cpp
+++ b/xfa/fxfa/cxfa_ffdocview.cpp
@@ -431,7 +431,7 @@
       if (node->IsUserInteractive())
         return XFA_EVENTERROR_Disabled;
 
-      return pWidgetAcc->ExecuteScript(pDocView, calc->GetScript(), pParam);
+      return node->ExecuteScript(pDocView, calc->GetScript(), pParam);
     }
     default:
       break;
diff --git a/xfa/fxfa/cxfa_ffnotify.cpp b/xfa/fxfa/cxfa_ffnotify.cpp
index 5dc06f9..7fd3699 100644
--- a/xfa/fxfa/cxfa_ffnotify.cpp
+++ b/xfa/fxfa/cxfa_ffnotify.cpp
@@ -210,22 +210,17 @@
          pAcc->FindSplitPos(m_pDoc->GetDocView(), iBlockIndex, fCalcHeightPos);
 }
 
-bool CXFA_FFNotify::RunScript(CXFA_Script* pScript, CXFA_Node* pFormItem) {
+bool CXFA_FFNotify::RunScript(CXFA_Script* script, CXFA_Node* item) {
   CXFA_FFDocView* pDocView = m_pDoc->GetDocView();
   if (!pDocView)
     return false;
 
-  CXFA_WidgetAcc* pWidgetAcc = pFormItem->GetWidgetAcc();
-  if (!pWidgetAcc)
-    return false;
-
   CXFA_EventParam EventParam;
   EventParam.m_eType = XFA_EVENT_Unknown;
 
   int32_t iRet;
   bool bRet;
-  std::tie(iRet, bRet) =
-      pWidgetAcc->ExecuteBoolScript(pDocView, pScript, &EventParam);
+  std::tie(iRet, bRet) = item->ExecuteBoolScript(pDocView, script, &EventParam);
   return iRet == XFA_EVENTERROR_Success && bRet;
 }
 
diff --git a/xfa/fxfa/cxfa_ffwidgethandler.cpp b/xfa/fxfa/cxfa_ffwidgethandler.cpp
index c1e00fb..b70facd 100644
--- a/xfa/fxfa/cxfa_ffwidgethandler.cpp
+++ b/xfa/fxfa/cxfa_ffwidgethandler.cpp
@@ -229,12 +229,12 @@
       }
       return XFA_EVENTERROR_Disabled;
     case XFA_EVENT_InitCalculate: {
-      CXFA_Calculate* calc = pWidgetAcc->GetNode()->GetCalculate();
+      CXFA_Calculate* calc = node->GetCalculate();
       if (!calc)
         return XFA_EVENTERROR_NotExist;
-      if (pWidgetAcc->GetNode()->IsUserInteractive())
+      if (node->IsUserInteractive())
         return XFA_EVENTERROR_Disabled;
-      return pWidgetAcc->ExecuteScript(m_pDocView, calc->GetScript(), pParam);
+      return node->ExecuteScript(m_pDocView, calc->GetScript(), pParam);
     }
     default:
       break;
diff --git a/xfa/fxfa/cxfa_widgetacc.cpp b/xfa/fxfa/cxfa_widgetacc.cpp
index bbed5b3..870dc53 100644
--- a/xfa/fxfa/cxfa_widgetacc.cpp
+++ b/xfa/fxfa/cxfa_widgetacc.cpp
@@ -357,8 +357,7 @@
 }  // namespace
 
 CXFA_WidgetAcc::CXFA_WidgetAcc(CXFA_Node* pNode)
-    : m_nRecursionDepth(0),
-      m_bIsNull(true),
+    : m_bIsNull(true),
       m_bPreNull(true),
       m_pUiChildNode(nullptr),
       m_eUIType(XFA_Element::Unknown),
@@ -464,93 +463,6 @@
   }
 }
 
-int32_t CXFA_WidgetAcc::ExecuteScript(CXFA_FFDocView* docView,
-                                      CXFA_Script* script,
-                                      CXFA_EventParam* pEventParam) {
-  bool bRet;
-  int32_t iRet;
-  std::tie(iRet, bRet) = ExecuteBoolScript(docView, script, pEventParam);
-  return iRet;
-}
-
-std::pair<int32_t, bool> CXFA_WidgetAcc::ExecuteBoolScript(
-    CXFA_FFDocView* docView,
-    CXFA_Script* script,
-    CXFA_EventParam* pEventParam) {
-  static const uint32_t MAX_RECURSION_DEPTH = 2;
-  if (m_nRecursionDepth > MAX_RECURSION_DEPTH)
-    return {XFA_EVENTERROR_Success, false};
-
-  ASSERT(pEventParam);
-  if (!script)
-    return {XFA_EVENTERROR_NotExist, false};
-  if (script->GetRunAt() == XFA_AttributeEnum::Server)
-    return {XFA_EVENTERROR_Disabled, false};
-
-  WideString wsExpression = script->GetExpression();
-  if (wsExpression.IsEmpty())
-    return {XFA_EVENTERROR_NotExist, false};
-
-  CXFA_Script::Type eScriptType = script->GetContentType();
-  if (eScriptType == CXFA_Script::Type::Unknown)
-    return {XFA_EVENTERROR_Success, false};
-
-  CXFA_FFDoc* pDoc = docView->GetDoc();
-  CFXJSE_Engine* pContext = pDoc->GetXFADoc()->GetScriptContext();
-  pContext->SetEventParam(*pEventParam);
-  pContext->SetRunAtType(script->GetRunAt());
-
-  std::vector<CXFA_Node*> refNodes;
-  if (pEventParam->m_eType == XFA_EVENT_InitCalculate ||
-      pEventParam->m_eType == XFA_EVENT_Calculate) {
-    pContext->SetNodesOfRunScript(&refNodes);
-  }
-
-  auto pTmpRetValue = pdfium::MakeUnique<CFXJSE_Value>(pContext->GetIsolate());
-  ++m_nRecursionDepth;
-  bool bRet = pContext->RunScript(eScriptType, wsExpression.AsStringView(),
-                                  pTmpRetValue.get(), m_pNode);
-  --m_nRecursionDepth;
-  int32_t iRet = XFA_EVENTERROR_Error;
-  if (bRet) {
-    iRet = XFA_EVENTERROR_Success;
-    if (pEventParam->m_eType == XFA_EVENT_Calculate ||
-        pEventParam->m_eType == XFA_EVENT_InitCalculate) {
-      if (!pTmpRetValue->IsUndefined()) {
-        if (!pTmpRetValue->IsNull())
-          pEventParam->m_wsResult = pTmpRetValue->ToWideString();
-
-        iRet = XFA_EVENTERROR_Success;
-      } else {
-        iRet = XFA_EVENTERROR_Error;
-      }
-      if (pEventParam->m_eType == XFA_EVENT_InitCalculate) {
-        if ((iRet == XFA_EVENTERROR_Success) &&
-            (m_pNode->GetRawValue() != pEventParam->m_wsResult)) {
-          SetValue(XFA_VALUEPICTURE_Raw, pEventParam->m_wsResult);
-          docView->AddValidateWidget(this);
-        }
-      }
-      for (CXFA_Node* pRefNode : refNodes) {
-        if (pRefNode->GetWidgetAcc() == this)
-          continue;
-
-        CXFA_CalcData* pGlobalData = pRefNode->JSObject()->GetCalcData();
-        if (!pGlobalData) {
-          pRefNode->JSObject()->SetCalcData(
-              pdfium::MakeUnique<CXFA_CalcData>());
-          pGlobalData = pRefNode->JSObject()->GetCalcData();
-        }
-        if (!pdfium::ContainsValue(pGlobalData->m_Globals, GetNode()))
-          pGlobalData->m_Globals.push_back(GetNode());
-      }
-    }
-  }
-  pContext->SetNodesOfRunScript(nullptr);
-
-  return {iRet, pTmpRetValue->IsBoolean() ? pTmpRetValue->ToBoolean() : false};
-}
-
 CXFA_FFWidget* CXFA_WidgetAcc::GetNextWidget(CXFA_FFWidget* pWidget) {
   return static_cast<CXFA_FFWidget*>(pWidget->GetNext());
 }
diff --git a/xfa/fxfa/cxfa_widgetacc.h b/xfa/fxfa/cxfa_widgetacc.h
index 2a0196a..6031d9b 100644
--- a/xfa/fxfa/cxfa_widgetacc.h
+++ b/xfa/fxfa/cxfa_widgetacc.h
@@ -62,13 +62,6 @@
 
   void ResetData();
 
-  int32_t ExecuteScript(CXFA_FFDocView* docView,
-                        CXFA_Script* script,
-                        CXFA_EventParam* pEventParam);
-  std::pair<int32_t, bool> ExecuteBoolScript(CXFA_FFDocView* docView,
-                                             CXFA_Script* script,
-                                             CXFA_EventParam* pEventParam);
-
   CXFA_FFWidget* GetNextWidget(CXFA_FFWidget* pWidget);
   void StartWidgetLayout(CXFA_FFDoc* doc,
                          float& fCalcWidth,
@@ -241,7 +234,6 @@
   void GetItemLabel(const WideStringView& wsValue, WideString& wsLabel);
 
   std::unique_ptr<CXFA_WidgetLayoutData> m_pLayoutData;
-  uint32_t m_nRecursionDepth;
   bool m_bIsNull;
   bool m_bPreNull;
   CXFA_Node* m_pUiChildNode;
diff --git a/xfa/fxfa/parser/cxfa_node.cpp b/xfa/fxfa/parser/cxfa_node.cpp
index 50c4c41..8c8f0c6 100644
--- a/xfa/fxfa/parser/cxfa_node.cpp
+++ b/xfa/fxfa/parser/cxfa_node.cpp
@@ -12,6 +12,7 @@
 #include <utility>
 #include <vector>
 
+#include "core/fxcrt/autorestorer.h"
 #include "core/fxcrt/cfx_decimal.h"
 #include "core/fxcrt/cfx_memorystream.h"
 #include "core/fxcrt/fx_codepage.h"
@@ -56,6 +57,8 @@
 
 namespace {
 
+constexpr uint8_t kMaxExecuteRecursion = 2;
+
 std::vector<CXFA_Node*> NodesSortedByDocumentIdx(
     const std::set<CXFA_Node*>& rgNodeSet) {
   if (rgNodeSet.empty())
@@ -1690,8 +1693,7 @@
     case XFA_Element::Execute:
       break;
     case XFA_Element::Script:
-      return GetWidgetAcc()->ExecuteScript(docView, event->GetScript(),
-                                           pEventParam);
+      return ExecuteScript(docView, event->GetScript(), pEventParam);
     case XFA_Element::SignData:
       break;
     case XFA_Element::Submit:
@@ -1715,8 +1717,7 @@
 
   CXFA_EventParam EventParam;
   EventParam.m_eType = XFA_EVENT_Calculate;
-  int32_t iRet =
-      GetWidgetAcc()->ExecuteScript(docView, calc->GetScript(), &EventParam);
+  int32_t iRet = ExecuteScript(docView, calc->GetScript(), &EventParam);
   if (iRet != XFA_EVENTERROR_Success)
     return iRet;
 
@@ -1904,8 +1905,7 @@
     CXFA_EventParam eParam;
     eParam.m_eType = XFA_EVENT_Validate;
     eParam.m_pTarget = GetWidgetAcc();
-    std::tie(iRet, bRet) =
-        GetWidgetAcc()->ExecuteBoolScript(docView, script, &eParam);
+    std::tie(iRet, bRet) = ExecuteBoolScript(docView, script, &eParam);
   }
 
   XFA_VERSION version = docView->GetDoc()->GetXFADoc()->GetCurVersionMode();
@@ -1963,3 +1963,94 @@
       L"validations for %ls, click Ignore.",
       wsCaptionName.c_str(), wsCaptionName.c_str());
 }
+
+int32_t CXFA_Node::ExecuteScript(CXFA_FFDocView* docView,
+                                 CXFA_Script* script,
+                                 CXFA_EventParam* pEventParam) {
+  bool bRet;
+  int32_t iRet;
+  std::tie(iRet, bRet) = ExecuteBoolScript(docView, script, pEventParam);
+  return iRet;
+}
+
+std::pair<int32_t, bool> CXFA_Node::ExecuteBoolScript(
+    CXFA_FFDocView* docView,
+    CXFA_Script* script,
+    CXFA_EventParam* pEventParam) {
+  if (m_ExecuteRecursionDepth > kMaxExecuteRecursion)
+    return {XFA_EVENTERROR_Success, false};
+
+  ASSERT(pEventParam);
+  if (!script)
+    return {XFA_EVENTERROR_NotExist, false};
+  if (script->GetRunAt() == XFA_AttributeEnum::Server)
+    return {XFA_EVENTERROR_Disabled, false};
+
+  WideString wsExpression = script->GetExpression();
+  if (wsExpression.IsEmpty())
+    return {XFA_EVENTERROR_NotExist, false};
+
+  CXFA_Script::Type eScriptType = script->GetContentType();
+  if (eScriptType == CXFA_Script::Type::Unknown)
+    return {XFA_EVENTERROR_Success, false};
+
+  CXFA_FFDoc* pDoc = docView->GetDoc();
+  CFXJSE_Engine* pContext = pDoc->GetXFADoc()->GetScriptContext();
+  pContext->SetEventParam(*pEventParam);
+  pContext->SetRunAtType(script->GetRunAt());
+
+  std::vector<CXFA_Node*> refNodes;
+  if (pEventParam->m_eType == XFA_EVENT_InitCalculate ||
+      pEventParam->m_eType == XFA_EVENT_Calculate) {
+    pContext->SetNodesOfRunScript(&refNodes);
+  }
+
+  auto pTmpRetValue = pdfium::MakeUnique<CFXJSE_Value>(pContext->GetIsolate());
+  bool bRet = false;
+  {
+    AutoRestorer<uint8_t> restorer(&m_ExecuteRecursionDepth);
+    ++m_ExecuteRecursionDepth;
+    bRet = pContext->RunScript(eScriptType, wsExpression.AsStringView(),
+                               pTmpRetValue.get(), this);
+  }
+
+  int32_t iRet = XFA_EVENTERROR_Error;
+  if (bRet) {
+    iRet = XFA_EVENTERROR_Success;
+    if (pEventParam->m_eType == XFA_EVENT_Calculate ||
+        pEventParam->m_eType == XFA_EVENT_InitCalculate) {
+      if (!pTmpRetValue->IsUndefined()) {
+        if (!pTmpRetValue->IsNull())
+          pEventParam->m_wsResult = pTmpRetValue->ToWideString();
+
+        iRet = XFA_EVENTERROR_Success;
+      } else {
+        iRet = XFA_EVENTERROR_Error;
+      }
+      if (pEventParam->m_eType == XFA_EVENT_InitCalculate) {
+        if ((iRet == XFA_EVENTERROR_Success) &&
+            (GetRawValue() != pEventParam->m_wsResult)) {
+          GetWidgetAcc()->SetValue(XFA_VALUEPICTURE_Raw,
+                                   pEventParam->m_wsResult);
+          docView->AddValidateWidget(GetWidgetAcc());
+        }
+      }
+      for (CXFA_Node* pRefNode : refNodes) {
+        if (pRefNode == this)
+          continue;
+
+        CXFA_CalcData* pGlobalData = pRefNode->JSObject()->GetCalcData();
+        if (!pGlobalData) {
+          pRefNode->JSObject()->SetCalcData(
+              pdfium::MakeUnique<CXFA_CalcData>());
+          pGlobalData = pRefNode->JSObject()->GetCalcData();
+        }
+        if (!pdfium::ContainsValue(pGlobalData->m_Globals, this))
+          pGlobalData->m_Globals.push_back(this);
+      }
+    }
+  }
+  pContext->SetNodesOfRunScript(nullptr);
+
+  return {iRet, pTmpRetValue->IsBoolean() ? pTmpRetValue->ToBoolean() : false};
+}
diff --git a/xfa/fxfa/parser/cxfa_node.h b/xfa/fxfa/parser/cxfa_node.h
index ed948cf..7bf0654 100644
--- a/xfa/fxfa/parser/cxfa_node.h
+++ b/xfa/fxfa/parser/cxfa_node.h
@@ -31,6 +31,7 @@
 class CXFA_Margin;
 class CXFA_Occur;
 class CXFA_Para;
+class CXFA_Script;
 class CXFA_Validate;
 class CXFA_Value;
 class CXFA_WidgetAcc;
@@ -271,6 +272,13 @@
   int32_t ProcessCalculate(CXFA_FFDocView* docView);
   int32_t ProcessValidate(CXFA_FFDocView* docView, int32_t iFlags);
 
+  int32_t ExecuteScript(CXFA_FFDocView* docView,
+                        CXFA_Script* script,
+                        CXFA_EventParam* pEventParam);
+  std::pair<int32_t, bool> ExecuteBoolScript(CXFA_FFDocView* docView,
+                                             CXFA_Script* script,
+                                             CXFA_EventParam* pEventParam);
+
  protected:
   CXFA_Node(CXFA_Document* pDoc,
             XFA_PacketType ePacket,
@@ -329,6 +337,7 @@
   CXFA_Node* m_pParent;
   CFX_XMLNode* m_pXMLNode;
   const XFA_PacketType m_ePacket;
+  uint8_t m_ExecuteRecursionDepth = 0;
   uint16_t m_uNodeFlags;
   uint32_t m_dwNameHash;
   CXFA_Node* m_pAuxNode;