Move Process* methods to CXFA_Node

This CL moves the CXFA_WidgetAcc::Process* methods to CXFA_Node.

Change-Id: Ic01b62e3786a6666a698f8877a8b7b295714bf79
Reviewed-on: https://pdfium-review.googlesource.com/22472
Reviewed-by: Ryan Harrison <rharrison@chromium.org>
Commit-Queue: dsinclair <dsinclair@chromium.org>
diff --git a/fpdfsdk/fpdfxfa/cpdfxfa_docenvironment.cpp b/fpdfsdk/fpdfxfa/cpdfxfa_docenvironment.cpp
index 8cf2cf0..93f5912 100644
--- a/fpdfsdk/fpdfxfa/cpdfxfa_docenvironment.cpp
+++ b/fpdfsdk/fpdfxfa/cpdfxfa_docenvironment.cpp
@@ -637,7 +637,7 @@
   CXFA_WidgetAcc* pWidgetAcc = pWidgetAccIterator->MoveToNext();
   pWidgetAcc = pWidgetAccIterator->MoveToNext();
   while (pWidgetAcc) {
-    int fRet = pWidgetAcc->ProcessValidate(docView, -1);
+    int fRet = pWidgetAcc->GetNode()->ProcessValidate(docView, -1);
     if (fRet == XFA_EVENTERROR_Error) {
       CPDFSDK_FormFillEnvironment* pFormFillEnv = m_pContext->GetFormFillEnv();
       if (!pFormFillEnv)
diff --git a/xfa/fxfa/cxfa_ffcheckbutton.cpp b/xfa/fxfa/cxfa_ffcheckbutton.cpp
index 5e8c8e5..94fb9bd 100644
--- a/xfa/fxfa/cxfa_ffcheckbutton.cpp
+++ b/xfa/fxfa/cxfa_ffcheckbutton.cpp
@@ -313,30 +313,25 @@
           m_pNode->GetWidgetAcc()->GetValue(XFA_VALUEPICTURE_Raw);
 
       CXFA_Node* exclNode = m_pNode->GetExclGroup();
-      CXFA_WidgetAcc* pFFExclGroup =
-          exclNode ? exclNode->GetWidgetAcc() : nullptr;
       if (ProcessCommittedData()) {
-        eParam.m_pTarget = pFFExclGroup;
-        if (pFFExclGroup) {
-          m_pDocView->AddValidateWidget(pFFExclGroup);
-          m_pDocView->AddCalculateWidgetAcc(pFFExclGroup);
-          pFFExclGroup->ProcessEvent(GetDocView(), XFA_AttributeEnum::Change,
-                                     &eParam);
+        eParam.m_pTarget = exclNode ? exclNode->GetWidgetAcc() : nullptr;
+        if (exclNode) {
+          m_pDocView->AddValidateWidget(exclNode->GetWidgetAcc());
+          m_pDocView->AddCalculateWidgetAcc(exclNode->GetWidgetAcc());
+          exclNode->ProcessEvent(GetDocView(), XFA_AttributeEnum::Change,
+                                 &eParam);
         }
         eParam.m_pTarget = m_pNode->GetWidgetAcc();
-        m_pNode->GetWidgetAcc()->ProcessEvent(
-            GetDocView(), XFA_AttributeEnum::Change, &eParam);
+        m_pNode->ProcessEvent(GetDocView(), XFA_AttributeEnum::Change, &eParam);
       } else {
         SetFWLCheckState(m_pNode->GetWidgetAcc()->GetCheckState());
       }
-      if (pFFExclGroup) {
-        eParam.m_pTarget = pFFExclGroup;
-        pFFExclGroup->ProcessEvent(GetDocView(), XFA_AttributeEnum::Click,
-                                   &eParam);
+      if (exclNode) {
+        eParam.m_pTarget = exclNode->GetWidgetAcc();
+        exclNode->ProcessEvent(GetDocView(), XFA_AttributeEnum::Click, &eParam);
       }
       eParam.m_pTarget = m_pNode->GetWidgetAcc();
-      m_pNode->GetWidgetAcc()->ProcessEvent(GetDocView(),
-                                            XFA_AttributeEnum::Click, &eParam);
+      m_pNode->ProcessEvent(GetDocView(), XFA_AttributeEnum::Click, &eParam);
       break;
     }
     default:
diff --git a/xfa/fxfa/cxfa_ffcombobox.cpp b/xfa/fxfa/cxfa_ffcombobox.cpp
index 7d5a3e3..9d65a64 100644
--- a/xfa/fxfa/cxfa_ffcombobox.cpp
+++ b/xfa/fxfa/cxfa_ffcombobox.cpp
@@ -139,8 +139,7 @@
   pParam->m_eType = XFA_EVENT_Change;
   pParam->m_pTarget = m_pNode->GetWidgetAcc();
   pParam->m_wsNewText = ToComboBox(m_pNormalWidget.get())->GetEditText();
-  m_pNode->GetWidgetAcc()->ProcessEvent(GetDocView(), XFA_AttributeEnum::Change,
-                                        pParam);
+  m_pNode->ProcessEvent(GetDocView(), XFA_AttributeEnum::Change, pParam);
 }
 
 uint32_t CXFA_FFComboBox::GetAlignment() {
@@ -310,16 +309,14 @@
   CXFA_EventParam eParam;
   eParam.m_eType = XFA_EVENT_PreOpen;
   eParam.m_pTarget = m_pNode->GetWidgetAcc();
-  m_pNode->GetWidgetAcc()->ProcessEvent(GetDocView(),
-                                        XFA_AttributeEnum::PreOpen, &eParam);
+  m_pNode->ProcessEvent(GetDocView(), XFA_AttributeEnum::PreOpen, &eParam);
 }
 
 void CXFA_FFComboBox::OnPostOpen(CFWL_Widget* pWidget) {
   CXFA_EventParam eParam;
   eParam.m_eType = XFA_EVENT_PostOpen;
   eParam.m_pTarget = m_pNode->GetWidgetAcc();
-  m_pNode->GetWidgetAcc()->ProcessEvent(GetDocView(),
-                                        XFA_AttributeEnum::PostOpen, &eParam);
+  m_pNode->ProcessEvent(GetDocView(), XFA_AttributeEnum::PostOpen, &eParam);
 }
 
 void CXFA_FFComboBox::OnProcessMessage(CFWL_Message* pMessage) {
diff --git a/xfa/fxfa/cxfa_ffdatetimeedit.cpp b/xfa/fxfa/cxfa_ffdatetimeedit.cpp
index c064e0f..aab7327 100644
--- a/xfa/fxfa/cxfa_ffdatetimeedit.cpp
+++ b/xfa/fxfa/cxfa_ffdatetimeedit.cpp
@@ -202,8 +202,7 @@
   eParam.m_eType = XFA_EVENT_Change;
   eParam.m_pTarget = m_pNode->GetWidgetAcc();
   eParam.m_wsNewText = m_pNode->GetWidgetAcc()->GetValue(XFA_VALUEPICTURE_Raw);
-  m_pNode->GetWidgetAcc()->ProcessEvent(GetDocView(), XFA_AttributeEnum::Change,
-                                        &eParam);
+  m_pNode->ProcessEvent(GetDocView(), XFA_AttributeEnum::Change, &eParam);
 }
 
 void CXFA_FFDateTimeEdit::OnProcessEvent(CFWL_Event* pEvent) {
diff --git a/xfa/fxfa/cxfa_ffdocview.cpp b/xfa/fxfa/cxfa_ffdocview.cpp
index e702036..2165759 100644
--- a/xfa/fxfa/cxfa_ffdocview.cpp
+++ b/xfa/fxfa/cxfa_ffdocview.cpp
@@ -408,26 +408,27 @@
                                 CXFA_EventParam* pParam) {
   if (!pParam || pParam->m_eType == XFA_EVENT_Unknown)
     return XFA_EVENTERROR_NotExist;
-  if (!pWidgetAcc ||
-      (pWidgetAcc->GetNode() &&
-       pWidgetAcc->GetNode()->GetElementType() == XFA_Element::Draw)) {
+  if (!pWidgetAcc)
     return XFA_EVENTERROR_NotExist;
-  }
+
+  CXFA_Node* node = pWidgetAcc->GetNode();
+  if (node && node->GetElementType() == XFA_Element::Draw)
+    return XFA_EVENTERROR_NotExist;
 
   switch (pParam->m_eType) {
     case XFA_EVENT_Calculate:
-      return pWidgetAcc->ProcessCalculate(pDocView);
+      return node->ProcessCalculate(pDocView);
     case XFA_EVENT_Validate:
       if (pDocView->GetDoc()->GetDocEnvironment()->IsValidationsEnabled(
               pDocView->GetDoc())) {
-        return pWidgetAcc->ProcessValidate(pDocView, 0x01);
+        return node->ProcessValidate(pDocView, 0x01);
       }
       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(pDocView, calc->GetScript(), pParam);
@@ -436,8 +437,8 @@
       break;
   }
 
-  return pWidgetAcc->ProcessEvent(pDocView, gs_EventActivity[pParam->m_eType],
-                                  pParam);
+  return node->ProcessEvent(pDocView, gs_EventActivity[pParam->m_eType],
+                            pParam);
 }
 
 int32_t CXFA_FFDocView::ExecEventActivityByDeepFirst(CXFA_Node* pFormNode,
@@ -584,14 +585,13 @@
 
 void CXFA_FFDocView::RunSubformIndexChange() {
   for (CXFA_Node* pSubformNode : m_IndexChangedSubforms) {
-    CXFA_WidgetAcc* pWidgetAcc = pSubformNode->GetWidgetAcc();
-    if (!pWidgetAcc)
+    if (!pSubformNode->GetWidgetAcc())
       continue;
 
     CXFA_EventParam eParam;
     eParam.m_eType = XFA_EVENT_IndexChange;
-    eParam.m_pTarget = pWidgetAcc;
-    pWidgetAcc->ProcessEvent(this, XFA_AttributeEnum::IndexChange, &eParam);
+    eParam.m_pTarget = pSubformNode->GetWidgetAcc();
+    pSubformNode->ProcessEvent(this, XFA_AttributeEnum::IndexChange, &eParam);
   }
   m_IndexChangedSubforms.clear();
 }
@@ -645,15 +645,15 @@
 
 size_t CXFA_FFDocView::RunCalculateRecursive(size_t index) {
   while (index < m_CalculateAccs.size()) {
-    CXFA_WidgetAcc* pCurAcc = m_CalculateAccs[index];
-    AddCalculateNodeNotify(pCurAcc->GetNode());
-    size_t recurse =
-        pCurAcc->GetNode()->JSObject()->GetCalcRecursionCount() + 1;
-    pCurAcc->GetNode()->JSObject()->SetCalcRecursionCount(recurse);
+    CXFA_Node* node = m_CalculateAccs[index]->GetNode();
+
+    AddCalculateNodeNotify(node);
+    size_t recurse = node->JSObject()->GetCalcRecursionCount() + 1;
+    node->JSObject()->SetCalcRecursionCount(recurse);
     if (recurse > 11)
       break;
-    if (pCurAcc->ProcessCalculate(this) == XFA_EVENTERROR_Success)
-      AddValidateWidget(pCurAcc);
+    if (node->ProcessCalculate(this) == XFA_EVENTERROR_Success)
+      AddValidateWidget(node->GetWidgetAcc());
 
     index = RunCalculateRecursive(++index);
   }
@@ -704,8 +704,9 @@
     return false;
 
   for (CXFA_WidgetAcc* pAcc : m_ValidateAccs) {
-    if (!pAcc->GetNode()->HasRemovedChildren())
-      pAcc->ProcessValidate(this, 0);
+    CXFA_Node* node = pAcc->GetNode();
+    if (!node->HasRemovedChildren())
+      node->ProcessValidate(this, 0);
   }
   m_ValidateAccs.clear();
   return true;
diff --git a/xfa/fxfa/cxfa_fffield.cpp b/xfa/fxfa/cxfa_fffield.cpp
index d80fb1a..ffbaa43 100644
--- a/xfa/fxfa/cxfa_fffield.cpp
+++ b/xfa/fxfa/cxfa_fffield.cpp
@@ -741,26 +741,26 @@
         CXFA_EventParam eParam;
         eParam.m_eType = XFA_EVENT_MouseEnter;
         eParam.m_pTarget = m_pNode->GetWidgetAcc();
-        m_pNode->GetWidgetAcc()->ProcessEvent(
-            GetDocView(), XFA_AttributeEnum::MouseEnter, &eParam);
+        m_pNode->ProcessEvent(GetDocView(), XFA_AttributeEnum::MouseEnter,
+                              &eParam);
       } else if (event->m_dwCmd == FWL_MouseCommand::Leave) {
         CXFA_EventParam eParam;
         eParam.m_eType = XFA_EVENT_MouseExit;
         eParam.m_pTarget = m_pNode->GetWidgetAcc();
-        m_pNode->GetWidgetAcc()->ProcessEvent(
-            GetDocView(), XFA_AttributeEnum::MouseExit, &eParam);
+        m_pNode->ProcessEvent(GetDocView(), XFA_AttributeEnum::MouseExit,
+                              &eParam);
       } else if (event->m_dwCmd == FWL_MouseCommand::LeftButtonDown) {
         CXFA_EventParam eParam;
         eParam.m_eType = XFA_EVENT_MouseDown;
         eParam.m_pTarget = m_pNode->GetWidgetAcc();
-        m_pNode->GetWidgetAcc()->ProcessEvent(
-            GetDocView(), XFA_AttributeEnum::MouseDown, &eParam);
+        m_pNode->ProcessEvent(GetDocView(), XFA_AttributeEnum::MouseDown,
+                              &eParam);
       } else if (event->m_dwCmd == FWL_MouseCommand::LeftButtonUp) {
         CXFA_EventParam eParam;
         eParam.m_eType = XFA_EVENT_MouseUp;
         eParam.m_pTarget = m_pNode->GetWidgetAcc();
-        m_pNode->GetWidgetAcc()->ProcessEvent(
-            GetDocView(), XFA_AttributeEnum::MouseUp, &eParam);
+        m_pNode->ProcessEvent(GetDocView(), XFA_AttributeEnum::MouseUp,
+                              &eParam);
       }
       break;
     }
@@ -768,8 +768,7 @@
       CXFA_EventParam eParam;
       eParam.m_eType = XFA_EVENT_Click;
       eParam.m_pTarget = m_pNode->GetWidgetAcc();
-      m_pNode->GetWidgetAcc()->ProcessEvent(GetDocView(),
-                                            XFA_AttributeEnum::Click, &eParam);
+      m_pNode->ProcessEvent(GetDocView(), XFA_AttributeEnum::Click, &eParam);
       break;
     }
     default:
diff --git a/xfa/fxfa/cxfa_fflistbox.cpp b/xfa/fxfa/cxfa_fflistbox.cpp
index 3b01c8f..892f0a6 100644
--- a/xfa/fxfa/cxfa_fflistbox.cpp
+++ b/xfa/fxfa/cxfa_fflistbox.cpp
@@ -160,8 +160,7 @@
     CFWL_ListItem* item = pListBox->GetSelItem(0);
     eParam.m_wsNewText = item ? item->GetText() : L"";
   }
-  m_pNode->GetWidgetAcc()->ProcessEvent(GetDocView(), XFA_AttributeEnum::Change,
-                                        &eParam);
+  m_pNode->ProcessEvent(GetDocView(), XFA_AttributeEnum::Change, &eParam);
 }
 
 void CXFA_FFListBox::SetItemState(int32_t nIndex, bool bSelected) {
diff --git a/xfa/fxfa/cxfa_fftextedit.cpp b/xfa/fxfa/cxfa_fftextedit.cpp
index 4d34265..8f84b18 100644
--- a/xfa/fxfa/cxfa_fftextedit.cpp
+++ b/xfa/fxfa/cxfa_fftextedit.cpp
@@ -317,16 +317,14 @@
     if (pEdit->HasSelection())
       std::tie(eParam.m_iSelStart, eParam.m_iSelEnd) = pEdit->GetSelection();
   }
-  m_pNode->GetWidgetAcc()->ProcessEvent(GetDocView(), XFA_AttributeEnum::Change,
-                                        &eParam);
+  m_pNode->ProcessEvent(GetDocView(), XFA_AttributeEnum::Change, &eParam);
 }
 
 void CXFA_FFTextEdit::OnTextFull(CFWL_Widget* pWidget) {
   CXFA_EventParam eParam;
   eParam.m_eType = XFA_EVENT_Full;
   eParam.m_pTarget = m_pNode->GetWidgetAcc();
-  m_pNode->GetWidgetAcc()->ProcessEvent(GetDocView(), XFA_AttributeEnum::Full,
-                                        &eParam);
+  m_pNode->ProcessEvent(GetDocView(), XFA_AttributeEnum::Full, &eParam);
 }
 
 bool CXFA_FFTextEdit::CheckWord(const ByteStringView& sWord) {
diff --git a/xfa/fxfa/cxfa_ffwidget.cpp b/xfa/fxfa/cxfa_ffwidget.cpp
index 2d3b8fb..47c34b0 100644
--- a/xfa/fxfa/cxfa_ffwidget.cpp
+++ b/xfa/fxfa/cxfa_ffwidget.cpp
@@ -1084,8 +1084,7 @@
   CXFA_EventParam eParam;
   eParam.m_eType = XFA_EVENT_Enter;
   eParam.m_pTarget = m_pNode->GetWidgetAcc();
-  m_pNode->GetWidgetAcc()->ProcessEvent(GetDocView(), XFA_AttributeEnum::Enter,
-                                        &eParam);
+  m_pNode->ProcessEvent(GetDocView(), XFA_AttributeEnum::Enter, &eParam);
   return true;
 }
 
@@ -1335,8 +1334,7 @@
   CXFA_EventParam eParam;
   eParam.m_eType = XFA_EVENT_Exit;
   eParam.m_pTarget = m_pNode->GetWidgetAcc();
-  m_pNode->GetWidgetAcc()->ProcessEvent(GetDocView(), XFA_AttributeEnum::Exit,
-                                        &eParam);
+  m_pNode->ProcessEvent(GetDocView(), XFA_AttributeEnum::Exit, &eParam);
 }
 
 bool CXFA_FFWidget::IsButtonDown() {
diff --git a/xfa/fxfa/cxfa_ffwidgethandler.cpp b/xfa/fxfa/cxfa_ffwidgethandler.cpp
index 454627d..c1e00fb 100644
--- a/xfa/fxfa/cxfa_ffwidgethandler.cpp
+++ b/xfa/fxfa/cxfa_ffwidgethandler.cpp
@@ -185,20 +185,20 @@
                                     XFA_EVENTTYPE eEventType) {
   if (eEventType == XFA_EVENT_Unknown)
     return false;
-
-  if (!pWidgetAcc ||
-      (pWidgetAcc->GetNode() &&
-       pWidgetAcc->GetNode()->GetElementType() == XFA_Element::Draw)) {
+  if (!pWidgetAcc)
     return false;
-  }
+
+  CXFA_Node* node = pWidgetAcc->GetNode();
+  if (!node || node->GetElementType() == XFA_Element::Draw)
+    return false;
 
   switch (eEventType) {
     case XFA_EVENT_Calculate: {
-      CXFA_Calculate* calc = pWidgetAcc->GetNode()->GetCalculate();
+      CXFA_Calculate* calc = node->GetCalculate();
       return calc && calc->GetScript();
     }
     case XFA_EVENT_Validate: {
-      CXFA_Validate* validate = pWidgetAcc->GetNode()->GetValidate(false);
+      CXFA_Validate* validate = node->GetValidate(false);
       return validate && validate->GetScript();
     }
     default:
@@ -212,19 +212,20 @@
                                            CXFA_EventParam* pParam) {
   if (!pParam || pParam->m_eType == XFA_EVENT_Unknown)
     return XFA_EVENTERROR_NotExist;
-  if (!pWidgetAcc ||
-      (pWidgetAcc->GetNode() &&
-       pWidgetAcc->GetNode()->GetElementType() == XFA_Element::Draw)) {
+  if (!pWidgetAcc)
     return XFA_EVENTERROR_NotExist;
-  }
+
+  CXFA_Node* node = pWidgetAcc->GetNode();
+  if (!node || node->GetElementType() == XFA_Element::Draw)
+    return XFA_EVENTERROR_NotExist;
 
   switch (pParam->m_eType) {
     case XFA_EVENT_Calculate:
-      return pWidgetAcc->ProcessCalculate(m_pDocView);
+      return node->ProcessCalculate(m_pDocView);
     case XFA_EVENT_Validate:
       if (m_pDocView->GetDoc()->GetDocEnvironment()->IsValidationsEnabled(
               m_pDocView->GetDoc())) {
-        return pWidgetAcc->ProcessValidate(m_pDocView, 0);
+        return node->ProcessValidate(m_pDocView, 0);
       }
       return XFA_EVENTERROR_Disabled;
     case XFA_EVENT_InitCalculate: {
@@ -238,8 +239,8 @@
     default:
       break;
   }
-  int32_t iRet = pWidgetAcc->ProcessEvent(
-      m_pDocView, gs_EventActivity[pParam->m_eType], pParam);
+  int32_t iRet =
+      node->ProcessEvent(m_pDocView, gs_EventActivity[pParam->m_eType], pParam);
   return iRet;
 }
 
diff --git a/xfa/fxfa/cxfa_widgetacc.cpp b/xfa/fxfa/cxfa_widgetacc.cpp
index da552e1..bbed5b3 100644
--- a/xfa/fxfa/cxfa_widgetacc.cpp
+++ b/xfa/fxfa/cxfa_widgetacc.cpp
@@ -464,308 +464,6 @@
   }
 }
 
-int32_t CXFA_WidgetAcc::ProcessEvent(CXFA_FFDocView* docView,
-                                     XFA_AttributeEnum iActivity,
-                                     CXFA_EventParam* pEventParam) {
-  if (m_pNode && m_pNode->GetElementType() == XFA_Element::Draw)
-    return XFA_EVENTERROR_NotExist;
-
-  std::vector<CXFA_Event*> eventArray =
-      GetEventByActivity(iActivity, pEventParam->m_bIsFormReady);
-  bool first = true;
-  int32_t iRet = XFA_EVENTERROR_NotExist;
-  for (CXFA_Event* event : eventArray) {
-    int32_t result = ProcessEvent(docView, event, pEventParam);
-    if (first || result == XFA_EVENTERROR_Success)
-      iRet = result;
-    first = false;
-  }
-  return iRet;
-}
-
-int32_t CXFA_WidgetAcc::ProcessEvent(CXFA_FFDocView* docView,
-                                     CXFA_Event* event,
-                                     CXFA_EventParam* pEventParam) {
-  if (!event)
-    return XFA_EVENTERROR_NotExist;
-
-  switch (event->GetEventType()) {
-    case XFA_Element::Execute:
-      break;
-    case XFA_Element::Script:
-      return ExecuteScript(docView, event->GetScript(), pEventParam);
-    case XFA_Element::SignData:
-      break;
-    case XFA_Element::Submit:
-      return docView->GetDoc()->GetDocEnvironment()->Submit(docView->GetDoc(),
-                                                            event->GetSubmit());
-    default:
-      break;
-  }
-  return XFA_EVENTERROR_NotExist;
-}
-
-int32_t CXFA_WidgetAcc::ProcessCalculate(CXFA_FFDocView* docView) {
-  if (m_pNode && m_pNode->GetElementType() == XFA_Element::Draw)
-    return XFA_EVENTERROR_NotExist;
-
-  CXFA_Calculate* calc = m_pNode->GetCalculate();
-  if (!calc)
-    return XFA_EVENTERROR_NotExist;
-  if (GetNode()->IsUserInteractive())
-    return XFA_EVENTERROR_Disabled;
-
-  CXFA_EventParam EventParam;
-  EventParam.m_eType = XFA_EVENT_Calculate;
-  int32_t iRet = ExecuteScript(docView, calc->GetScript(), &EventParam);
-  if (iRet != XFA_EVENTERROR_Success)
-    return iRet;
-
-  if (m_pNode->GetRawValue() != EventParam.m_wsResult) {
-    SetValue(XFA_VALUEPICTURE_Raw, EventParam.m_wsResult);
-    UpdateUIDisplay(docView, nullptr);
-  }
-  return XFA_EVENTERROR_Success;
-}
-
-void CXFA_WidgetAcc::ProcessScriptTestValidate(CXFA_FFDocView* docView,
-                                               CXFA_Validate* validate,
-                                               int32_t iRet,
-                                               bool bRetValue,
-                                               bool bVersionFlag) {
-  if (iRet != XFA_EVENTERROR_Success)
-    return;
-  if (bRetValue)
-    return;
-
-  IXFA_AppProvider* pAppProvider =
-      docView->GetDoc()->GetApp()->GetAppProvider();
-  if (!pAppProvider)
-    return;
-
-  WideString wsTitle = pAppProvider->GetAppTitle();
-  WideString wsScriptMsg = validate->GetScriptMessageText();
-  if (validate->GetScriptTest() == XFA_AttributeEnum::Warning) {
-    if (GetNode()->IsUserInteractive())
-      return;
-    if (wsScriptMsg.IsEmpty())
-      wsScriptMsg = GetValidateMessage(false, bVersionFlag);
-
-    if (bVersionFlag) {
-      pAppProvider->MsgBox(wsScriptMsg, wsTitle, XFA_MBICON_Warning, XFA_MB_OK);
-      return;
-    }
-    if (pAppProvider->MsgBox(wsScriptMsg, wsTitle, XFA_MBICON_Warning,
-                             XFA_MB_YesNo) == XFA_IDYes) {
-      GetNode()->SetFlag(XFA_NodeFlag_UserInteractive, false);
-    }
-    return;
-  }
-
-  if (wsScriptMsg.IsEmpty())
-    wsScriptMsg = GetValidateMessage(true, bVersionFlag);
-  pAppProvider->MsgBox(wsScriptMsg, wsTitle, XFA_MBICON_Error, XFA_MB_OK);
-}
-
-int32_t CXFA_WidgetAcc::ProcessFormatTestValidate(CXFA_FFDocView* docView,
-                                                  CXFA_Validate* validate,
-                                                  bool bVersionFlag) {
-  WideString wsRawValue = m_pNode->GetRawValue();
-  if (!wsRawValue.IsEmpty()) {
-    WideString wsPicture = validate->GetPicture();
-    if (wsPicture.IsEmpty())
-      return XFA_EVENTERROR_NotExist;
-
-    IFX_Locale* pLocale = GetLocale();
-    if (!pLocale)
-      return XFA_EVENTERROR_NotExist;
-
-    CXFA_LocaleValue lcValue = XFA_GetLocaleValue(GetNode());
-    if (!lcValue.ValidateValue(lcValue.GetValue(), wsPicture, pLocale,
-                               nullptr)) {
-      IXFA_AppProvider* pAppProvider =
-          docView->GetDoc()->GetApp()->GetAppProvider();
-      if (!pAppProvider)
-        return XFA_EVENTERROR_NotExist;
-
-      WideString wsFormatMsg = validate->GetFormatMessageText();
-      WideString wsTitle = pAppProvider->GetAppTitle();
-      if (validate->GetFormatTest() == XFA_AttributeEnum::Error) {
-        if (wsFormatMsg.IsEmpty())
-          wsFormatMsg = GetValidateMessage(true, bVersionFlag);
-        pAppProvider->MsgBox(wsFormatMsg, wsTitle, XFA_MBICON_Error, XFA_MB_OK);
-        return XFA_EVENTERROR_Success;
-      }
-      if (GetNode()->IsUserInteractive())
-        return XFA_EVENTERROR_NotExist;
-      if (wsFormatMsg.IsEmpty())
-        wsFormatMsg = GetValidateMessage(false, bVersionFlag);
-
-      if (bVersionFlag) {
-        pAppProvider->MsgBox(wsFormatMsg, wsTitle, XFA_MBICON_Warning,
-                             XFA_MB_OK);
-        return XFA_EVENTERROR_Success;
-      }
-      if (pAppProvider->MsgBox(wsFormatMsg, wsTitle, XFA_MBICON_Warning,
-                               XFA_MB_YesNo) == XFA_IDYes) {
-        GetNode()->SetFlag(XFA_NodeFlag_UserInteractive, false);
-      }
-      return XFA_EVENTERROR_Success;
-    }
-  }
-  return XFA_EVENTERROR_NotExist;
-}
-
-int32_t CXFA_WidgetAcc::ProcessNullTestValidate(CXFA_FFDocView* docView,
-                                                CXFA_Validate* validate,
-                                                int32_t iFlags,
-                                                bool bVersionFlag) {
-  if (!GetValue(XFA_VALUEPICTURE_Raw).IsEmpty())
-    return XFA_EVENTERROR_Success;
-  if (IsNull() && IsPreNull())
-    return XFA_EVENTERROR_Success;
-
-  XFA_AttributeEnum eNullTest = validate->GetNullTest();
-  WideString wsNullMsg = validate->GetNullMessageText();
-  if (iFlags & 0x01) {
-    int32_t iRet = XFA_EVENTERROR_Success;
-    if (eNullTest != XFA_AttributeEnum::Disabled)
-      iRet = XFA_EVENTERROR_Error;
-
-    if (!wsNullMsg.IsEmpty()) {
-      if (eNullTest != XFA_AttributeEnum::Disabled) {
-        docView->m_arrNullTestMsg.push_back(wsNullMsg);
-        return XFA_EVENTERROR_Error;
-      }
-      return XFA_EVENTERROR_Success;
-    }
-    return iRet;
-  }
-  if (wsNullMsg.IsEmpty() && bVersionFlag &&
-      eNullTest != XFA_AttributeEnum::Disabled) {
-    return XFA_EVENTERROR_Error;
-  }
-  IXFA_AppProvider* pAppProvider =
-      docView->GetDoc()->GetApp()->GetAppProvider();
-  if (!pAppProvider)
-    return XFA_EVENTERROR_NotExist;
-
-  WideString wsCaptionName;
-  WideString wsTitle = pAppProvider->GetAppTitle();
-  switch (eNullTest) {
-    case XFA_AttributeEnum::Error: {
-      if (wsNullMsg.IsEmpty()) {
-        wsCaptionName = GetValidateCaptionName(bVersionFlag);
-        wsNullMsg =
-            WideString::Format(L"%ls cannot be blank.", wsCaptionName.c_str());
-      }
-      pAppProvider->MsgBox(wsNullMsg, wsTitle, XFA_MBICON_Status, XFA_MB_OK);
-      return XFA_EVENTERROR_Error;
-    }
-    case XFA_AttributeEnum::Warning: {
-      if (GetNode()->IsUserInteractive())
-        return true;
-
-      if (wsNullMsg.IsEmpty()) {
-        wsCaptionName = GetValidateCaptionName(bVersionFlag);
-        wsNullMsg = WideString::Format(
-            L"%ls cannot be blank. To ignore validations for %ls, click "
-            L"Ignore.",
-            wsCaptionName.c_str(), wsCaptionName.c_str());
-      }
-      if (pAppProvider->MsgBox(wsNullMsg, wsTitle, XFA_MBICON_Warning,
-                               XFA_MB_YesNo) == XFA_IDYes) {
-        GetNode()->SetFlag(XFA_NodeFlag_UserInteractive, false);
-      }
-      return XFA_EVENTERROR_Error;
-    }
-    case XFA_AttributeEnum::Disabled:
-    default:
-      break;
-  }
-  return XFA_EVENTERROR_Success;
-}
-
-WideString CXFA_WidgetAcc::GetValidateCaptionName(bool bVersionFlag) {
-  WideString wsCaptionName;
-
-  if (!bVersionFlag) {
-    CXFA_Caption* caption = m_pNode->GetCaption();
-    if (caption) {
-      CXFA_Value* capValue = caption->GetValue();
-      if (capValue) {
-        CXFA_Text* captionText = capValue->GetText();
-        if (captionText)
-          wsCaptionName = captionText->GetContent();
-      }
-    }
-  }
-  if (!wsCaptionName.IsEmpty())
-    return wsCaptionName;
-  return m_pNode->JSObject()->GetCData(XFA_Attribute::Name);
-}
-
-WideString CXFA_WidgetAcc::GetValidateMessage(bool bError, bool bVersionFlag) {
-  WideString wsCaptionName = GetValidateCaptionName(bVersionFlag);
-  if (bVersionFlag)
-    return WideString::Format(L"%ls validation failed", wsCaptionName.c_str());
-  if (bError) {
-    return WideString::Format(L"The value you entered for %ls is invalid.",
-                              wsCaptionName.c_str());
-  }
-  return WideString::Format(
-      L"The value you entered for %ls is invalid. To ignore "
-      L"validations for %ls, click Ignore.",
-      wsCaptionName.c_str(), wsCaptionName.c_str());
-}
-
-int32_t CXFA_WidgetAcc::ProcessValidate(CXFA_FFDocView* docView,
-                                        int32_t iFlags) {
-  if (m_pNode && m_pNode->GetElementType() == XFA_Element::Draw)
-    return XFA_EVENTERROR_NotExist;
-
-  CXFA_Validate* validate = m_pNode->GetValidate(false);
-  if (!validate)
-    return XFA_EVENTERROR_NotExist;
-
-  bool bInitDoc = validate->NeedsInitApp();
-  bool bStatus = docView->GetLayoutStatus() < XFA_DOCVIEW_LAYOUTSTATUS_End;
-  int32_t iFormat = 0;
-  int32_t iRet = XFA_EVENTERROR_NotExist;
-  CXFA_Script* script = validate->GetScript();
-  bool bRet = false;
-  bool hasBoolResult =
-      (bInitDoc || bStatus) && m_pNode->GetRawValue().IsEmpty();
-  if (script) {
-    CXFA_EventParam eParam;
-    eParam.m_eType = XFA_EVENT_Validate;
-    eParam.m_pTarget = this;
-    std::tie(iRet, bRet) = ExecuteBoolScript(docView, script, &eParam);
-  }
-
-  XFA_VERSION version = docView->GetDoc()->GetXFADoc()->GetCurVersionMode();
-  bool bVersionFlag = false;
-  if (version < XFA_VERSION_208)
-    bVersionFlag = true;
-
-  if (bInitDoc) {
-    validate->ClearFlag(XFA_NodeFlag_NeedsInitApp);
-  } else {
-    iFormat = ProcessFormatTestValidate(docView, validate, bVersionFlag);
-    if (!bVersionFlag) {
-      bVersionFlag =
-          docView->GetDoc()->GetXFADoc()->HasFlag(XFA_DOCFLAG_Scripting);
-    }
-
-    iRet |= ProcessNullTestValidate(docView, validate, iFlags, bVersionFlag);
-  }
-
-  if (iFormat != XFA_EVENTERROR_Success && hasBoolResult)
-    ProcessScriptTestValidate(docView, validate, iRet, bRet, bVersionFlag);
-
-  return iRet | iFormat;
-}
-
 int32_t CXFA_WidgetAcc::ExecuteScript(CXFA_FFDocView* docView,
                                       CXFA_Script* script,
                                       CXFA_EventParam* pEventParam) {
diff --git a/xfa/fxfa/cxfa_widgetacc.h b/xfa/fxfa/cxfa_widgetacc.h
index 44d2d28..2a0196a 100644
--- a/xfa/fxfa/cxfa_widgetacc.h
+++ b/xfa/fxfa/cxfa_widgetacc.h
@@ -62,14 +62,6 @@
 
   void ResetData();
 
-  int32_t ProcessEvent(CXFA_FFDocView* docView,
-                       XFA_AttributeEnum iActivity,
-                       CXFA_EventParam* pEventParam);
-  int32_t ProcessEvent(CXFA_FFDocView* docView,
-                       CXFA_Event* event,
-                       CXFA_EventParam* pEventParam);
-  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);
@@ -218,20 +210,6 @@
   void SetIsNull(bool val) { m_bIsNull = val; }
 
  private:
-  void ProcessScriptTestValidate(CXFA_FFDocView* docView,
-                                 CXFA_Validate* validate,
-                                 int32_t iRet,
-                                 bool pRetValue,
-                                 bool bVersionFlag);
-  int32_t ProcessFormatTestValidate(CXFA_FFDocView* docView,
-                                    CXFA_Validate* validate,
-                                    bool bVersionFlag);
-  int32_t ProcessNullTestValidate(CXFA_FFDocView* docView,
-                                  CXFA_Validate* validate,
-                                  int32_t iFlags,
-                                  bool bVersionFlag);
-  WideString GetValidateCaptionName(bool bVersionFlag);
-  WideString GetValidateMessage(bool bError, bool bVersionFlag);
   void CalcCaptionSize(CXFA_FFDoc* doc, CFX_SizeF& szCap);
   bool CalculateFieldAutoSize(CXFA_FFDoc* doc, CFX_SizeF& size);
   bool CalculateWidgetAutoSize(CFX_SizeF& size);
diff --git a/xfa/fxfa/parser/cxfa_node.cpp b/xfa/fxfa/parser/cxfa_node.cpp
index 6021ec3..50c4c41 100644
--- a/xfa/fxfa/parser/cxfa_node.cpp
+++ b/xfa/fxfa/parser/cxfa_node.cpp
@@ -25,6 +25,8 @@
 #include "third_party/base/ptr_util.h"
 #include "third_party/base/stl_util.h"
 #include "xfa/fxfa/cxfa_eventparam.h"
+#include "xfa/fxfa/cxfa_ffapp.h"
+#include "xfa/fxfa/cxfa_ffdocview.h"
 #include "xfa/fxfa/cxfa_ffnotify.h"
 #include "xfa/fxfa/cxfa_ffwidget.h"
 #include "xfa/fxfa/parser/cxfa_arraynodelist.h"
@@ -34,9 +36,11 @@
 #include "xfa/fxfa/parser/cxfa_calculate.h"
 #include "xfa/fxfa/parser/cxfa_caption.h"
 #include "xfa/fxfa/parser/cxfa_document.h"
+#include "xfa/fxfa/parser/cxfa_event.h"
 #include "xfa/fxfa/parser/cxfa_font.h"
 #include "xfa/fxfa/parser/cxfa_keep.h"
 #include "xfa/fxfa/parser/cxfa_layoutprocessor.h"
+#include "xfa/fxfa/parser/cxfa_localevalue.h"
 #include "xfa/fxfa/parser/cxfa_margin.h"
 #include "xfa/fxfa/parser/cxfa_measurement.h"
 #include "xfa/fxfa/parser/cxfa_nodeiteratortemplate.h"
@@ -1656,3 +1660,306 @@
     return nullptr;
   return pExcl;
 }
+
+int32_t CXFA_Node::ProcessEvent(CXFA_FFDocView* docView,
+                                XFA_AttributeEnum iActivity,
+                                CXFA_EventParam* pEventParam) {
+  if (GetElementType() == XFA_Element::Draw)
+    return XFA_EVENTERROR_NotExist;
+
+  std::vector<CXFA_Event*> eventArray = GetWidgetAcc()->GetEventByActivity(
+      iActivity, pEventParam->m_bIsFormReady);
+  bool first = true;
+  int32_t iRet = XFA_EVENTERROR_NotExist;
+  for (CXFA_Event* event : eventArray) {
+    int32_t result = ProcessEvent(docView, event, pEventParam);
+    if (first || result == XFA_EVENTERROR_Success)
+      iRet = result;
+    first = false;
+  }
+  return iRet;
+}
+
+int32_t CXFA_Node::ProcessEvent(CXFA_FFDocView* docView,
+                                CXFA_Event* event,
+                                CXFA_EventParam* pEventParam) {
+  if (!event)
+    return XFA_EVENTERROR_NotExist;
+
+  switch (event->GetEventType()) {
+    case XFA_Element::Execute:
+      break;
+    case XFA_Element::Script:
+      return GetWidgetAcc()->ExecuteScript(docView, event->GetScript(),
+                                           pEventParam);
+    case XFA_Element::SignData:
+      break;
+    case XFA_Element::Submit:
+      return docView->GetDoc()->GetDocEnvironment()->Submit(docView->GetDoc(),
+                                                            event->GetSubmit());
+    default:
+      break;
+  }
+  return XFA_EVENTERROR_NotExist;
+}
+
+int32_t CXFA_Node::ProcessCalculate(CXFA_FFDocView* docView) {
+  if (GetElementType() == XFA_Element::Draw)
+    return XFA_EVENTERROR_NotExist;
+
+  CXFA_Calculate* calc = GetCalculate();
+  if (!calc)
+    return XFA_EVENTERROR_NotExist;
+  if (IsUserInteractive())
+    return XFA_EVENTERROR_Disabled;
+
+  CXFA_EventParam EventParam;
+  EventParam.m_eType = XFA_EVENT_Calculate;
+  int32_t iRet =
+      GetWidgetAcc()->ExecuteScript(docView, calc->GetScript(), &EventParam);
+  if (iRet != XFA_EVENTERROR_Success)
+    return iRet;
+
+  if (GetRawValue() != EventParam.m_wsResult) {
+    GetWidgetAcc()->SetValue(XFA_VALUEPICTURE_Raw, EventParam.m_wsResult);
+    GetWidgetAcc()->UpdateUIDisplay(docView, nullptr);
+  }
+  return XFA_EVENTERROR_Success;
+}
+
+void CXFA_Node::ProcessScriptTestValidate(CXFA_FFDocView* docView,
+                                          CXFA_Validate* validate,
+                                          int32_t iRet,
+                                          bool bRetValue,
+                                          bool bVersionFlag) {
+  if (iRet != XFA_EVENTERROR_Success)
+    return;
+  if (bRetValue)
+    return;
+
+  IXFA_AppProvider* pAppProvider =
+      docView->GetDoc()->GetApp()->GetAppProvider();
+  if (!pAppProvider)
+    return;
+
+  WideString wsTitle = pAppProvider->GetAppTitle();
+  WideString wsScriptMsg = validate->GetScriptMessageText();
+  if (validate->GetScriptTest() == XFA_AttributeEnum::Warning) {
+    if (IsUserInteractive())
+      return;
+    if (wsScriptMsg.IsEmpty())
+      wsScriptMsg = GetValidateMessage(false, bVersionFlag);
+
+    if (bVersionFlag) {
+      pAppProvider->MsgBox(wsScriptMsg, wsTitle, XFA_MBICON_Warning, XFA_MB_OK);
+      return;
+    }
+    if (pAppProvider->MsgBox(wsScriptMsg, wsTitle, XFA_MBICON_Warning,
+                             XFA_MB_YesNo) == XFA_IDYes) {
+      SetFlag(XFA_NodeFlag_UserInteractive, false);
+    }
+    return;
+  }
+
+  if (wsScriptMsg.IsEmpty())
+    wsScriptMsg = GetValidateMessage(true, bVersionFlag);
+  pAppProvider->MsgBox(wsScriptMsg, wsTitle, XFA_MBICON_Error, XFA_MB_OK);
+}
+
+int32_t CXFA_Node::ProcessFormatTestValidate(CXFA_FFDocView* docView,
+                                             CXFA_Validate* validate,
+                                             bool bVersionFlag) {
+  WideString wsRawValue = GetRawValue();
+  if (!wsRawValue.IsEmpty()) {
+    WideString wsPicture = validate->GetPicture();
+    if (wsPicture.IsEmpty())
+      return XFA_EVENTERROR_NotExist;
+
+    IFX_Locale* pLocale = GetLocale();
+    if (!pLocale)
+      return XFA_EVENTERROR_NotExist;
+
+    CXFA_LocaleValue lcValue = XFA_GetLocaleValue(this);
+    if (!lcValue.ValidateValue(lcValue.GetValue(), wsPicture, pLocale,
+                               nullptr)) {
+      IXFA_AppProvider* pAppProvider =
+          docView->GetDoc()->GetApp()->GetAppProvider();
+      if (!pAppProvider)
+        return XFA_EVENTERROR_NotExist;
+
+      WideString wsFormatMsg = validate->GetFormatMessageText();
+      WideString wsTitle = pAppProvider->GetAppTitle();
+      if (validate->GetFormatTest() == XFA_AttributeEnum::Error) {
+        if (wsFormatMsg.IsEmpty())
+          wsFormatMsg = GetValidateMessage(true, bVersionFlag);
+        pAppProvider->MsgBox(wsFormatMsg, wsTitle, XFA_MBICON_Error, XFA_MB_OK);
+        return XFA_EVENTERROR_Success;
+      }
+      if (IsUserInteractive())
+        return XFA_EVENTERROR_NotExist;
+      if (wsFormatMsg.IsEmpty())
+        wsFormatMsg = GetValidateMessage(false, bVersionFlag);
+
+      if (bVersionFlag) {
+        pAppProvider->MsgBox(wsFormatMsg, wsTitle, XFA_MBICON_Warning,
+                             XFA_MB_OK);
+        return XFA_EVENTERROR_Success;
+      }
+      if (pAppProvider->MsgBox(wsFormatMsg, wsTitle, XFA_MBICON_Warning,
+                               XFA_MB_YesNo) == XFA_IDYes) {
+        SetFlag(XFA_NodeFlag_UserInteractive, false);
+      }
+      return XFA_EVENTERROR_Success;
+    }
+  }
+  return XFA_EVENTERROR_NotExist;
+}
+
+int32_t CXFA_Node::ProcessNullTestValidate(CXFA_FFDocView* docView,
+                                           CXFA_Validate* validate,
+                                           int32_t iFlags,
+                                           bool bVersionFlag) {
+  if (!GetWidgetAcc()->GetValue(XFA_VALUEPICTURE_Raw).IsEmpty())
+    return XFA_EVENTERROR_Success;
+  if (GetWidgetAcc()->IsNull() && GetWidgetAcc()->IsPreNull())
+    return XFA_EVENTERROR_Success;
+
+  XFA_AttributeEnum eNullTest = validate->GetNullTest();
+  WideString wsNullMsg = validate->GetNullMessageText();
+  if (iFlags & 0x01) {
+    int32_t iRet = XFA_EVENTERROR_Success;
+    if (eNullTest != XFA_AttributeEnum::Disabled)
+      iRet = XFA_EVENTERROR_Error;
+
+    if (!wsNullMsg.IsEmpty()) {
+      if (eNullTest != XFA_AttributeEnum::Disabled) {
+        docView->m_arrNullTestMsg.push_back(wsNullMsg);
+        return XFA_EVENTERROR_Error;
+      }
+      return XFA_EVENTERROR_Success;
+    }
+    return iRet;
+  }
+  if (wsNullMsg.IsEmpty() && bVersionFlag &&
+      eNullTest != XFA_AttributeEnum::Disabled) {
+    return XFA_EVENTERROR_Error;
+  }
+  IXFA_AppProvider* pAppProvider =
+      docView->GetDoc()->GetApp()->GetAppProvider();
+  if (!pAppProvider)
+    return XFA_EVENTERROR_NotExist;
+
+  WideString wsCaptionName;
+  WideString wsTitle = pAppProvider->GetAppTitle();
+  switch (eNullTest) {
+    case XFA_AttributeEnum::Error: {
+      if (wsNullMsg.IsEmpty()) {
+        wsCaptionName = GetValidateCaptionName(bVersionFlag);
+        wsNullMsg =
+            WideString::Format(L"%ls cannot be blank.", wsCaptionName.c_str());
+      }
+      pAppProvider->MsgBox(wsNullMsg, wsTitle, XFA_MBICON_Status, XFA_MB_OK);
+      return XFA_EVENTERROR_Error;
+    }
+    case XFA_AttributeEnum::Warning: {
+      if (IsUserInteractive())
+        return true;
+
+      if (wsNullMsg.IsEmpty()) {
+        wsCaptionName = GetValidateCaptionName(bVersionFlag);
+        wsNullMsg = WideString::Format(
+            L"%ls cannot be blank. To ignore validations for %ls, click "
+            L"Ignore.",
+            wsCaptionName.c_str(), wsCaptionName.c_str());
+      }
+      if (pAppProvider->MsgBox(wsNullMsg, wsTitle, XFA_MBICON_Warning,
+                               XFA_MB_YesNo) == XFA_IDYes) {
+        SetFlag(XFA_NodeFlag_UserInteractive, false);
+      }
+      return XFA_EVENTERROR_Error;
+    }
+    case XFA_AttributeEnum::Disabled:
+    default:
+      break;
+  }
+  return XFA_EVENTERROR_Success;
+}
+
+int32_t CXFA_Node::ProcessValidate(CXFA_FFDocView* docView, int32_t iFlags) {
+  if (GetElementType() == XFA_Element::Draw)
+    return XFA_EVENTERROR_NotExist;
+
+  CXFA_Validate* validate = GetValidate(false);
+  if (!validate)
+    return XFA_EVENTERROR_NotExist;
+
+  bool bInitDoc = validate->NeedsInitApp();
+  bool bStatus = docView->GetLayoutStatus() < XFA_DOCVIEW_LAYOUTSTATUS_End;
+  int32_t iFormat = 0;
+  int32_t iRet = XFA_EVENTERROR_NotExist;
+  CXFA_Script* script = validate->GetScript();
+  bool bRet = false;
+  bool hasBoolResult = (bInitDoc || bStatus) && GetRawValue().IsEmpty();
+  if (script) {
+    CXFA_EventParam eParam;
+    eParam.m_eType = XFA_EVENT_Validate;
+    eParam.m_pTarget = GetWidgetAcc();
+    std::tie(iRet, bRet) =
+        GetWidgetAcc()->ExecuteBoolScript(docView, script, &eParam);
+  }
+
+  XFA_VERSION version = docView->GetDoc()->GetXFADoc()->GetCurVersionMode();
+  bool bVersionFlag = false;
+  if (version < XFA_VERSION_208)
+    bVersionFlag = true;
+
+  if (bInitDoc) {
+    validate->ClearFlag(XFA_NodeFlag_NeedsInitApp);
+  } else {
+    iFormat = ProcessFormatTestValidate(docView, validate, bVersionFlag);
+    if (!bVersionFlag) {
+      bVersionFlag =
+          docView->GetDoc()->GetXFADoc()->HasFlag(XFA_DOCFLAG_Scripting);
+    }
+
+    iRet |= ProcessNullTestValidate(docView, validate, iFlags, bVersionFlag);
+  }
+
+  if (iFormat != XFA_EVENTERROR_Success && hasBoolResult)
+    ProcessScriptTestValidate(docView, validate, iRet, bRet, bVersionFlag);
+
+  return iRet | iFormat;
+}
+
+WideString CXFA_Node::GetValidateCaptionName(bool bVersionFlag) {
+  WideString wsCaptionName;
+
+  if (!bVersionFlag) {
+    CXFA_Caption* caption = GetCaption();
+    if (caption) {
+      CXFA_Value* capValue = caption->GetValue();
+      if (capValue) {
+        CXFA_Text* captionText = capValue->GetText();
+        if (captionText)
+          wsCaptionName = captionText->GetContent();
+      }
+    }
+  }
+  if (!wsCaptionName.IsEmpty())
+    return wsCaptionName;
+  return JSObject()->GetCData(XFA_Attribute::Name);
+}
+
+WideString CXFA_Node::GetValidateMessage(bool bError, bool bVersionFlag) {
+  WideString wsCaptionName = GetValidateCaptionName(bVersionFlag);
+  if (bVersionFlag)
+    return WideString::Format(L"%ls validation failed", wsCaptionName.c_str());
+  if (bError) {
+    return WideString::Format(L"The value you entered for %ls is invalid.",
+                              wsCaptionName.c_str());
+  }
+  return WideString::Format(
+      L"The value you entered for %ls is invalid. To ignore "
+      L"validations for %ls, click Ignore.",
+      wsCaptionName.c_str(), wsCaptionName.c_str());
+}
diff --git a/xfa/fxfa/parser/cxfa_node.h b/xfa/fxfa/parser/cxfa_node.h
index c2edc70..ed948cf 100644
--- a/xfa/fxfa/parser/cxfa_node.h
+++ b/xfa/fxfa/parser/cxfa_node.h
@@ -24,6 +24,9 @@
 class CXFA_Border;
 class CXFA_Calculate;
 class CXFA_Caption;
+class CXFA_Event;
+class CXFA_EventParam;
+class CXFA_FFDocView;
 class CXFA_Font;
 class CXFA_Margin;
 class CXFA_Occur;
@@ -259,6 +262,15 @@
 
   CXFA_Node* GetExclGroup();
 
+  int32_t ProcessEvent(CXFA_FFDocView* docView,
+                       XFA_AttributeEnum iActivity,
+                       CXFA_EventParam* pEventParam);
+  int32_t ProcessEvent(CXFA_FFDocView* docView,
+                       CXFA_Event* event,
+                       CXFA_EventParam* pEventParam);
+  int32_t ProcessCalculate(CXFA_FFDocView* docView);
+  int32_t ProcessValidate(CXFA_FFDocView* docView, int32_t iFlags);
+
  protected:
   CXFA_Node(CXFA_Document* pDoc,
             XFA_PacketType ePacket,
@@ -279,6 +291,21 @@
             const WideStringView& elementName);
 
  private:
+  void ProcessScriptTestValidate(CXFA_FFDocView* docView,
+                                 CXFA_Validate* validate,
+                                 int32_t iRet,
+                                 bool pRetValue,
+                                 bool bVersionFlag);
+  int32_t ProcessFormatTestValidate(CXFA_FFDocView* docView,
+                                    CXFA_Validate* validate,
+                                    bool bVersionFlag);
+  int32_t ProcessNullTestValidate(CXFA_FFDocView* docView,
+                                  CXFA_Validate* validate,
+                                  int32_t iFlags,
+                                  bool bVersionFlag);
+  WideString GetValidateCaptionName(bool bVersionFlag);
+  WideString GetValidateMessage(bool bError, bool bVersionFlag);
+
   bool HasFlag(XFA_NodeFlag dwFlag) const;
   CXFA_Node* Deprecated_GetPrevSibling();
   const PropertyData* GetPropertyData(XFA_Element property) const;