Cleanup duplicate RunScript code

This CL consolidates the duplicate RunScript code in
CPDFSDK_ActionHandler.

Change-Id: I08beb7644b6cbaa7906e5bb302372fd8a670f32a
Reviewed-on: https://pdfium-review.googlesource.com/24630
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Commit-Queue: dsinclair <dsinclair@chromium.org>
diff --git a/fpdfsdk/cpdfsdk_interform.cpp b/fpdfsdk/cpdfsdk_interform.cpp
index 21a6d41..03a782b 100644
--- a/fpdfsdk/cpdfsdk_interform.cpp
+++ b/fpdfsdk/cpdfsdk_interform.cpp
@@ -383,7 +383,7 @@
   fa.bShift = false;
   fa.sValue = csValue;
   pActionHandler->DoAction_FieldJavaScript(
-      action, CPDF_AAction::KeyStroke, m_pFormFillEnv.Get(), pFormField, fa);
+      action, CPDF_AAction::KeyStroke, m_pFormFillEnv.Get(), pFormField, &fa);
   return fa.bRC;
 }
 
@@ -403,7 +403,7 @@
   fa.bShift = false;
   fa.sValue = csValue;
   pActionHandler->DoAction_FieldJavaScript(
-      action, CPDF_AAction::Validate, m_pFormFillEnv.Get(), pFormField, fa);
+      action, CPDF_AAction::Validate, m_pFormFillEnv.Get(), pFormField, &fa);
   return fa.bRC;
 }
 
diff --git a/fpdfsdk/cpdfsdk_widget.cpp b/fpdfsdk/cpdfsdk_widget.cpp
index fc67059..d0eaa7a 100644
--- a/fpdfsdk/cpdfsdk_widget.cpp
+++ b/fpdfsdk/cpdfsdk_widget.cpp
@@ -221,7 +221,7 @@
 }
 
 bool CPDFSDK_Widget::OnXFAAAction(PDFSDK_XFAAActionType eXFAAAT,
-                                  PDFSDK_FieldAction& data,
+                                  PDFSDK_FieldAction* data,
                                   CPDFSDK_PageView* pPageView) {
   CPDFXFA_Context* pContext = m_pPageView->GetFormFillEnv()->GetXFAContext();
 
@@ -239,22 +239,22 @@
 
   CXFA_EventParam param;
   param.m_eType = eEventType;
-  param.m_wsChange = data.sChange;
-  param.m_iCommitKey = data.nCommitKey;
-  param.m_bShift = data.bShift;
-  param.m_iSelStart = data.nSelStart;
-  param.m_iSelEnd = data.nSelEnd;
-  param.m_wsFullText = data.sValue;
-  param.m_bKeyDown = data.bKeyDown;
-  param.m_bModifier = data.bModifier;
-  param.m_wsNewText = data.sValue;
-  if (data.nSelEnd > data.nSelStart)
-    param.m_wsNewText.Delete(data.nSelStart, data.nSelEnd - data.nSelStart);
+  param.m_wsChange = data->sChange;
+  param.m_iCommitKey = data->nCommitKey;
+  param.m_bShift = data->bShift;
+  param.m_iSelStart = data->nSelStart;
+  param.m_iSelEnd = data->nSelEnd;
+  param.m_wsFullText = data->sValue;
+  param.m_bKeyDown = data->bKeyDown;
+  param.m_bModifier = data->bModifier;
+  param.m_wsNewText = data->sValue;
+  if (data->nSelEnd > data->nSelStart)
+    param.m_wsNewText.Delete(data->nSelStart, data->nSelEnd - data->nSelStart);
 
-  for (const auto& c : data.sChange)
-    param.m_wsNewText.Insert(data.nSelStart, c);
+  for (const auto& c : data->sChange)
+    param.m_wsNewText.Insert(data->nSelStart, c);
 
-  param.m_wsPrevText = data.sValue;
+  param.m_wsPrevText = data->sValue;
   if ((eEventType == XFA_EVENT_Click || eEventType == XFA_EVENT_Change) &&
       GetFieldType() == FormFieldType::kRadioButton) {
     if (CXFA_FFWidget* hGroupWidget = GetGroupMixXFAWidget()) {
@@ -831,34 +831,34 @@
 }
 
 bool CPDFSDK_Widget::OnAAction(CPDF_AAction::AActionType type,
-                               PDFSDK_FieldAction& data,
+                               PDFSDK_FieldAction* data,
                                CPDFSDK_PageView* pPageView) {
   CPDFSDK_FormFillEnvironment* pFormFillEnv = pPageView->GetFormFillEnv();
 
 #ifdef PDF_ENABLE_XFA
   CPDFXFA_Context* pContext = pFormFillEnv->GetXFAContext();
   if (CXFA_FFWidget* hWidget = GetMixXFAWidget()) {
-    XFA_EVENTTYPE eEventType = GetXFAEventType(type, data.bWillCommit);
+    XFA_EVENTTYPE eEventType = GetXFAEventType(type, data->bWillCommit);
 
     if (eEventType != XFA_EVENT_Unknown) {
       if (CXFA_FFWidgetHandler* pXFAWidgetHandler = GetXFAWidgetHandler()) {
         CXFA_EventParam param;
         param.m_eType = eEventType;
-        param.m_wsChange = data.sChange;
-        param.m_iCommitKey = data.nCommitKey;
-        param.m_bShift = data.bShift;
-        param.m_iSelStart = data.nSelStart;
-        param.m_iSelEnd = data.nSelEnd;
-        param.m_wsFullText = data.sValue;
-        param.m_bKeyDown = data.bKeyDown;
-        param.m_bModifier = data.bModifier;
-        param.m_wsNewText = data.sValue;
-        if (data.nSelEnd > data.nSelStart)
-          param.m_wsNewText.Delete(data.nSelStart,
-                                   data.nSelEnd - data.nSelStart);
-        for (int i = data.sChange.GetLength() - 1; i >= 0; i--)
-          param.m_wsNewText.Insert(data.nSelStart, data.sChange[i]);
-        param.m_wsPrevText = data.sValue;
+        param.m_wsChange = data->sChange;
+        param.m_iCommitKey = data->nCommitKey;
+        param.m_bShift = data->bShift;
+        param.m_iSelStart = data->nSelStart;
+        param.m_iSelEnd = data->nSelEnd;
+        param.m_wsFullText = data->sValue;
+        param.m_bKeyDown = data->bKeyDown;
+        param.m_bModifier = data->bModifier;
+        param.m_wsNewText = data->sValue;
+        if (data->nSelEnd > data->nSelStart)
+          param.m_wsNewText.Delete(data->nSelStart,
+                                   data->nSelEnd - data->nSelStart);
+        for (int i = data->sChange.GetLength() - 1; i >= 0; i--)
+          param.m_wsNewText.Insert(data->nSelStart, data->sChange[i]);
+        param.m_wsPrevText = data->sValue;
 
         int32_t nRet = XFA_EVENTERROR_NotExist;
         CXFA_Node* node = hWidget->GetNode();
diff --git a/fpdfsdk/cpdfsdk_widget.h b/fpdfsdk/cpdfsdk_widget.h
index 22d0e36..c325732 100644
--- a/fpdfsdk/cpdfsdk_widget.h
+++ b/fpdfsdk/cpdfsdk_widget.h
@@ -42,7 +42,7 @@
 
   bool HasXFAAAction(PDFSDK_XFAAActionType eXFAAAT);
   bool OnXFAAAction(PDFSDK_XFAAActionType eXFAAAT,
-                    PDFSDK_FieldAction& data,
+                    PDFSDK_FieldAction* data,
                     CPDFSDK_PageView* pPageView);
 
   void Synchronize(bool bSynchronizeElse);
@@ -100,7 +100,7 @@
   WideString OnFormat(bool& bFormatted);
 
   bool OnAAction(CPDF_AAction::AActionType type,
-                 PDFSDK_FieldAction& data,
+                 PDFSDK_FieldAction* data,
                  CPDFSDK_PageView* pPageView);
 
   CPDFSDK_InterForm* GetInterForm() const { return m_pInterForm.Get(); }
diff --git a/fpdfsdk/formfiller/cffl_interactiveformfiller.cpp b/fpdfsdk/formfiller/cffl_interactiveformfiller.cpp
index e74f902..f33bde6 100644
--- a/fpdfsdk/formfiller/cffl_interactiveformfiller.cpp
+++ b/fpdfsdk/formfiller/cffl_interactiveformfiller.cpp
@@ -129,7 +129,7 @@
       PDFSDK_FieldAction fa;
       fa.bModifier = CPDFSDK_FormFillEnvironment::IsCTRLKeyDown(nFlag);
       fa.bShift = CPDFSDK_FormFillEnvironment::IsSHIFTKeyDown(nFlag);
-      pWidget->OnAAction(CPDF_AAction::CursorEnter, fa, pPageView);
+      pWidget->OnAAction(CPDF_AAction::CursorEnter, &fa, pPageView);
       m_bNotifying = false;
       if (!(*pAnnot))
         return;
@@ -162,7 +162,7 @@
       PDFSDK_FieldAction fa;
       fa.bModifier = CPDFSDK_FormFillEnvironment::IsCTRLKeyDown(nFlag);
       fa.bShift = CPDFSDK_FormFillEnvironment::IsSHIFTKeyDown(nFlag);
-      pWidget->OnAAction(CPDF_AAction::CursorExit, fa, pPageView);
+      pWidget->OnAAction(CPDF_AAction::CursorExit, &fa, pPageView);
       m_bNotifying = false;
       if (!(*pAnnot))
         return;
@@ -198,7 +198,7 @@
       PDFSDK_FieldAction fa;
       fa.bModifier = CPDFSDK_FormFillEnvironment::IsCTRLKeyDown(nFlags);
       fa.bShift = CPDFSDK_FormFillEnvironment::IsSHIFTKeyDown(nFlags);
-      pWidget->OnAAction(CPDF_AAction::ButtonDown, fa, pPageView);
+      pWidget->OnAAction(CPDF_AAction::ButtonDown, &fa, pPageView);
       m_bNotifying = false;
       if (!(*pAnnot))
         return true;
@@ -276,7 +276,7 @@
   PDFSDK_FieldAction fa;
   fa.bModifier = CPDFSDK_FormFillEnvironment::IsCTRLKeyDown(nFlag);
   fa.bShift = CPDFSDK_FormFillEnvironment::IsSHIFTKeyDown(nFlag);
-  pWidget->OnAAction(CPDF_AAction::ButtonUp, fa, pPageView);
+  pWidget->OnAAction(CPDF_AAction::ButtonUp, &fa, pPageView);
   m_bNotifying = false;
   if (!(*pAnnot) || !IsValidAnnot(pPageView, pWidget))
     return true;
@@ -389,7 +389,7 @@
       fa.bModifier = CPDFSDK_FormFillEnvironment::IsCTRLKeyDown(nFlag);
       fa.bShift = CPDFSDK_FormFillEnvironment::IsSHIFTKeyDown(nFlag);
       pFormFiller->GetActionData(pPageView, CPDF_AAction::GetFocus, fa);
-      pWidget->OnAAction(CPDF_AAction::GetFocus, fa, pPageView);
+      pWidget->OnAAction(CPDF_AAction::GetFocus, &fa, pPageView);
       m_bNotifying = false;
       if (!(*pAnnot))
         return false;
@@ -440,7 +440,7 @@
   fa.bModifier = CPDFSDK_FormFillEnvironment::IsCTRLKeyDown(nFlag);
   fa.bShift = CPDFSDK_FormFillEnvironment::IsSHIFTKeyDown(nFlag);
   pFormFiller->GetActionData(pPageView, CPDF_AAction::LoseFocus, fa);
-  pWidget->OnAAction(CPDF_AAction::LoseFocus, fa, pPageView);
+  pWidget->OnAAction(CPDF_AAction::LoseFocus, &fa, pPageView);
   m_bNotifying = false;
   return !!(*pAnnot);
 }
@@ -621,7 +621,7 @@
   CFFL_FormFiller* pFormFiller = GetFormFiller(pWidget, false);
   pFormFiller->GetActionData(pPageView, CPDF_AAction::KeyStroke, fa);
   pFormFiller->SaveState(pPageView);
-  pWidget->OnAAction(CPDF_AAction::KeyStroke, fa, pPageView);
+  pWidget->OnAAction(CPDF_AAction::KeyStroke, &fa, pPageView);
   if (!(*pAnnot))
     return true;
 
@@ -652,7 +652,7 @@
   CFFL_FormFiller* pFormFiller = GetFormFiller(pWidget, false);
   pFormFiller->GetActionData(pPageView, CPDF_AAction::Validate, fa);
   pFormFiller->SaveState(pPageView);
-  pWidget->OnAAction(CPDF_AAction::Validate, fa, pPageView);
+  pWidget->OnAAction(CPDF_AAction::Validate, &fa, pPageView);
   if (!(*pAnnot))
     return true;
 
@@ -716,7 +716,7 @@
   fa.bModifier = CPDFSDK_FormFillEnvironment::IsCTRLKeyDown(nFlag);
   fa.bShift = CPDFSDK_FormFillEnvironment::IsSHIFTKeyDown(nFlag);
 
-  pWidget->OnXFAAAction(PDFSDK_XFA_Click, fa, pPageView);
+  pWidget->OnXFAAAction(PDFSDK_XFA_Click, &fa, pPageView);
   m_bNotifying = false;
   if (!(*pAnnot) || !IsValidAnnot(pPageView, pWidget))
     return true;
@@ -746,7 +746,7 @@
   fa.bModifier = CPDFSDK_FormFillEnvironment::IsCTRLKeyDown(nFlag);
   fa.bShift = CPDFSDK_FormFillEnvironment::IsSHIFTKeyDown(nFlag);
 
-  pWidget->OnXFAAAction(PDFSDK_XFA_Full, fa, pPageView);
+  pWidget->OnXFAAAction(PDFSDK_XFA_Full, &fa, pPageView);
   m_bNotifying = false;
   if (!(*pAnnot) || !IsValidAnnot(pPageView, pWidget))
     return true;
@@ -799,7 +799,7 @@
   fa.bModifier = CPDFSDK_FormFillEnvironment::IsCTRLKeyDown(nFlag);
   fa.bShift = CPDFSDK_FormFillEnvironment::IsSHIFTKeyDown(nFlag);
 
-  pWidget->OnXFAAAction(PDFSDK_XFA_PreOpen, fa, pPageView);
+  pWidget->OnXFAAAction(PDFSDK_XFA_PreOpen, &fa, pPageView);
   m_bNotifying = false;
   if (!(*pAnnot) || !IsValidAnnot(pPageView, pWidget))
     return true;
@@ -830,7 +830,7 @@
   fa.bModifier = CPDFSDK_FormFillEnvironment::IsCTRLKeyDown(nFlag);
   fa.bShift = CPDFSDK_FormFillEnvironment::IsSHIFTKeyDown(nFlag);
 
-  pWidget->OnXFAAAction(PDFSDK_XFA_PostOpen, fa, pPageView);
+  pWidget->OnXFAAAction(PDFSDK_XFA_PostOpen, &fa, pPageView);
   m_bNotifying = false;
   if (!(*pAnnot) || !IsValidAnnot(pPageView, pWidget))
     return true;
@@ -900,7 +900,7 @@
 
   CPDFSDK_Annot::ObservedPtr pObserved(privateData.pWidget);
   bool action_status = privateData.pWidget->OnAAction(
-      CPDF_AAction::KeyStroke, fa, privateData.pPageView);
+      CPDF_AAction::KeyStroke, &fa, privateData.pPageView);
 
   if (!pObserved || !IsValidAnnot(privateData.pPageView, privateData.pWidget))
     return {true, true};
diff --git a/fpdfsdk/fsdk_actionhandler.cpp b/fpdfsdk/fsdk_actionhandler.cpp
index b0bc3f6..6fcf9d4 100644
--- a/fpdfsdk/fsdk_actionhandler.cpp
+++ b/fpdfsdk/fsdk_actionhandler.cpp
@@ -47,7 +47,7 @@
     CPDF_AAction::AActionType type,
     CPDFSDK_FormFillEnvironment* pFormFillEnv,
     CPDF_FormField* pFormField,
-    PDFSDK_FieldAction& data) {
+    PDFSDK_FieldAction* data) {
   ASSERT(pFormFillEnv);
   if (pFormFillEnv->IsJSInitiated() &&
       JsAction.GetType() == CPDF_Action::JavaScript) {
@@ -106,7 +106,7 @@
     CPDF_AAction::AActionType type,
     CPDFSDK_FormFillEnvironment* pFormFillEnv,
     CPDF_FormField* pFormField,
-    PDFSDK_FieldAction& data) {
+    PDFSDK_FieldAction* data) {
   std::set<CPDF_Dictionary*> visited;
   return ExecuteFieldAction(action, type, pFormFillEnv, pFormField, data,
                             &visited);
@@ -154,19 +154,10 @@
 
   ASSERT(pFormFillEnv);
   if (action.GetType() == CPDF_Action::JavaScript) {
-    if (pFormFillEnv->IsJSInitiated()) {
-      WideString swJS = action.GetJavaScript();
-      if (!swJS.IsEmpty()) {
-        IJS_Runtime* pRuntime = pFormFillEnv->GetJSRuntime();
-        IJS_EventContext* pContext = pRuntime->NewEventContext();
-        pContext->OnLink_MouseUp(pFormFillEnv);
-
-        WideString csInfo;
-        pContext->RunScript(swJS, &csInfo);
-        pRuntime->ReleaseEventContext(pContext);
-        // TODO(dsinclair): Return error if RunScript returns false.
-      }
-    }
+    RunScriptForAction(action, pFormFillEnv,
+                       [pFormFillEnv](IJS_EventContext* context) {
+                         context->OnLink_MouseUp(pFormFillEnv);
+                       });
   } else {
     DoAction_NoJs(action, pFormFillEnv);
   }
@@ -228,7 +219,7 @@
     CPDF_AAction::AActionType type,
     CPDFSDK_FormFillEnvironment* pFormFillEnv,
     CPDF_FormField* pFormField,
-    PDFSDK_FieldAction& data,
+    PDFSDK_FieldAction* data,
     std::set<CPDF_Dictionary*>* visited) {
   CPDF_Dictionary* pDict = action.GetDict();
   if (pdfium::ContainsKey(*visited, pDict))
@@ -273,21 +264,10 @@
   visited->insert(pDict);
 
   ASSERT(pFormFillEnv);
-  if (action.GetType() == CPDF_Action::JavaScript) {
-    if (pFormFillEnv->IsJSInitiated()) {
-      WideString swJS = action.GetJavaScript();
-      if (!swJS.IsEmpty()) {
-        IJS_Runtime* pRuntime = pFormFillEnv->GetJSRuntime();
-        IJS_EventContext* pContext = pRuntime->NewEventContext();
-        WideString csInfo;
-        pContext->RunScript(swJS, &csInfo);
-        pRuntime->ReleaseEventContext(pContext);
-        // TODO(dsinclair): Return error if RunScript returns false.
-      }
-    }
-  } else {
+  if (action.GetType() == CPDF_Action::JavaScript)
+    RunScriptForAction(action, pFormFillEnv, [](IJS_EventContext*) {});
+  else
     DoAction_NoJs(action, pFormFillEnv);
-  }
 
   for (int32_t i = 0, sz = action.GetSubActionsCount(); i < sz; i++) {
     CPDF_Action subaction = action.GetSubAction(i);
@@ -311,19 +291,10 @@
 
   ASSERT(pFormFillEnv);
   if (action.GetType() == CPDF_Action::JavaScript) {
-    if (pFormFillEnv->IsJSInitiated()) {
-      WideString swJS = action.GetJavaScript();
-      if (!swJS.IsEmpty()) {
-        IJS_Runtime* pRuntime = pFormFillEnv->GetJSRuntime();
-        IJS_EventContext* pContext = pRuntime->NewEventContext();
-        pContext->OnBookmark_MouseUp(pBookmark);
-
-        WideString csInfo;
-        pContext->RunScript(swJS, &csInfo);
-        pRuntime->ReleaseEventContext(pContext);
-        // TODO(dsinclair): Return error if RunScript returns false.
-      }
-    }
+    RunScriptForAction(action, pFormFillEnv,
+                       [pFormFillEnv, pBookmark](IJS_EventContext* context) {
+                         context->OnBookmark_MouseUp(pBookmark);
+                       });
   } else {
     DoAction_NoJs(action, pFormFillEnv);
   }
@@ -425,113 +396,105 @@
     CPDFSDK_FormFillEnvironment* pFormFillEnv,
     CPDF_FormField* pFormField,
     CPDF_AAction::AActionType type,
-    PDFSDK_FieldAction& data,
+    PDFSDK_FieldAction* data,
     const WideString& script) {
   ASSERT(type != CPDF_AAction::Calculate);
   ASSERT(type != CPDF_AAction::Format);
 
-  IJS_Runtime* pRuntime = pFormFillEnv->GetJSRuntime();
-  IJS_EventContext* pContext = pRuntime->NewEventContext();
-  switch (type) {
-    case CPDF_AAction::CursorEnter:
-      pContext->OnField_MouseEnter(data.bModifier, data.bShift, pFormField);
-      break;
-    case CPDF_AAction::CursorExit:
-      pContext->OnField_MouseExit(data.bModifier, data.bShift, pFormField);
-      break;
-    case CPDF_AAction::ButtonDown:
-      pContext->OnField_MouseDown(data.bModifier, data.bShift, pFormField);
-      break;
-    case CPDF_AAction::ButtonUp:
-      pContext->OnField_MouseUp(data.bModifier, data.bShift, pFormField);
-      break;
-    case CPDF_AAction::GetFocus:
-      pContext->OnField_Focus(data.bModifier, data.bShift, pFormField,
-                              data.sValue);
-      break;
-    case CPDF_AAction::LoseFocus:
-      pContext->OnField_Blur(data.bModifier, data.bShift, pFormField,
-                             data.sValue);
-      break;
-    case CPDF_AAction::KeyStroke:
-      pContext->OnField_Keystroke(data.sChange, data.sChangeEx, data.bKeyDown,
-                                  data.bModifier, data.nSelEnd, data.nSelStart,
-                                  data.bShift, pFormField, data.sValue,
-                                  data.bWillCommit, data.bFieldFull, data.bRC);
-      break;
-    case CPDF_AAction::Validate:
-      pContext->OnField_Validate(data.sChange, data.sChangeEx, data.bKeyDown,
-                                 data.bModifier, data.bShift, pFormField,
-                                 data.sValue, data.bRC);
-      break;
-    default:
-      NOTREACHED();
-      break;
-  }
-
-  WideString csInfo;
-  pContext->RunScript(script, &csInfo);
-  pRuntime->ReleaseEventContext(pContext);
-  // TODO(dsinclair): Return error if RunScript returns false.
+  RunScript(
+      pFormFillEnv, script,
+      [type, data, pFormField](IJS_EventContext* context) {
+        switch (type) {
+          case CPDF_AAction::CursorEnter:
+            context->OnField_MouseEnter(data->bModifier, data->bShift,
+                                        pFormField);
+            break;
+          case CPDF_AAction::CursorExit:
+            context->OnField_MouseExit(data->bModifier, data->bShift,
+                                       pFormField);
+            break;
+          case CPDF_AAction::ButtonDown:
+            context->OnField_MouseDown(data->bModifier, data->bShift,
+                                       pFormField);
+            break;
+          case CPDF_AAction::ButtonUp:
+            context->OnField_MouseUp(data->bModifier, data->bShift, pFormField);
+            break;
+          case CPDF_AAction::GetFocus:
+            context->OnField_Focus(data->bModifier, data->bShift, pFormField,
+                                   data->sValue);
+            break;
+          case CPDF_AAction::LoseFocus:
+            context->OnField_Blur(data->bModifier, data->bShift, pFormField,
+                                  data->sValue);
+            break;
+          case CPDF_AAction::KeyStroke:
+            context->OnField_Keystroke(
+                data->sChange, data->sChangeEx, data->bKeyDown, data->bModifier,
+                data->nSelEnd, data->nSelStart, data->bShift, pFormField,
+                data->sValue, data->bWillCommit, data->bFieldFull, data->bRC);
+            break;
+          case CPDF_AAction::Validate:
+            context->OnField_Validate(
+                data->sChange, data->sChangeEx, data->bKeyDown, data->bModifier,
+                data->bShift, pFormField, data->sValue, data->bRC);
+            break;
+          default:
+            NOTREACHED();
+            break;
+        }
+      });
 }
 
 void CPDFSDK_ActionHandler::RunDocumentOpenJavaScript(
     CPDFSDK_FormFillEnvironment* pFormFillEnv,
     const WideString& sScriptName,
     const WideString& script) {
-  IJS_Runtime* pRuntime = pFormFillEnv->GetJSRuntime();
-  IJS_EventContext* pContext = pRuntime->NewEventContext();
-  pContext->OnDoc_Open(pFormFillEnv, sScriptName);
-
-  WideString csInfo;
-  pContext->RunScript(script, &csInfo);
-  pRuntime->ReleaseEventContext(pContext);
-  // TODO(dsinclair): Return error if RunScript returns false.
+  RunScript(pFormFillEnv, script,
+            [pFormFillEnv, sScriptName](IJS_EventContext* context) {
+              context->OnDoc_Open(pFormFillEnv, sScriptName);
+            });
 }
 
 void CPDFSDK_ActionHandler::RunDocumentPageJavaScript(
     CPDFSDK_FormFillEnvironment* pFormFillEnv,
     CPDF_AAction::AActionType type,
     const WideString& script) {
-  IJS_Runtime* pRuntime = pFormFillEnv->GetJSRuntime();
-  IJS_EventContext* pContext = pRuntime->NewEventContext();
-  switch (type) {
-    case CPDF_AAction::OpenPage:
-      pContext->OnPage_Open(pFormFillEnv);
-      break;
-    case CPDF_AAction::ClosePage:
-      pContext->OnPage_Close(pFormFillEnv);
-      break;
-    case CPDF_AAction::CloseDocument:
-      pContext->OnDoc_WillClose(pFormFillEnv);
-      break;
-    case CPDF_AAction::SaveDocument:
-      pContext->OnDoc_WillSave(pFormFillEnv);
-      break;
-    case CPDF_AAction::DocumentSaved:
-      pContext->OnDoc_DidSave(pFormFillEnv);
-      break;
-    case CPDF_AAction::PrintDocument:
-      pContext->OnDoc_WillPrint(pFormFillEnv);
-      break;
-    case CPDF_AAction::DocumentPrinted:
-      pContext->OnDoc_DidPrint(pFormFillEnv);
-      break;
-    case CPDF_AAction::PageVisible:
-      pContext->OnPage_InView(pFormFillEnv);
-      break;
-    case CPDF_AAction::PageInvisible:
-      pContext->OnPage_OutView(pFormFillEnv);
-      break;
-    default:
-      NOTREACHED();
-      break;
-  }
-
-  WideString csInfo;
-  pContext->RunScript(script, &csInfo);
-  pRuntime->ReleaseEventContext(pContext);
-  // TODO(dsinclair): Return error if RunScript returns false.
+  RunScript(pFormFillEnv, script,
+            [type, pFormFillEnv](IJS_EventContext* context) {
+              switch (type) {
+                case CPDF_AAction::OpenPage:
+                  context->OnPage_Open(pFormFillEnv);
+                  break;
+                case CPDF_AAction::ClosePage:
+                  context->OnPage_Close(pFormFillEnv);
+                  break;
+                case CPDF_AAction::CloseDocument:
+                  context->OnDoc_WillClose(pFormFillEnv);
+                  break;
+                case CPDF_AAction::SaveDocument:
+                  context->OnDoc_WillSave(pFormFillEnv);
+                  break;
+                case CPDF_AAction::DocumentSaved:
+                  context->OnDoc_DidSave(pFormFillEnv);
+                  break;
+                case CPDF_AAction::PrintDocument:
+                  context->OnDoc_WillPrint(pFormFillEnv);
+                  break;
+                case CPDF_AAction::DocumentPrinted:
+                  context->OnDoc_DidPrint(pFormFillEnv);
+                  break;
+                case CPDF_AAction::PageVisible:
+                  context->OnPage_InView(pFormFillEnv);
+                  break;
+                case CPDF_AAction::PageInvisible:
+                  context->OnPage_OutView(pFormFillEnv);
+                  break;
+                default:
+                  NOTREACHED();
+                  break;
+              }
+            });
 }
 
 bool CPDFSDK_ActionHandler::DoAction_Hide(
@@ -559,3 +522,31 @@
   return pInterForm->DoAction_ResetForm(action);
 }
 
+void CPDFSDK_ActionHandler::RunScriptForAction(
+    const CPDF_Action& action,
+    CPDFSDK_FormFillEnvironment* pFormFillEnv,
+    std::function<void(IJS_EventContext* context)> cb) {
+  if (!pFormFillEnv->IsJSInitiated())
+    return;
+
+  WideString swJS = action.GetJavaScript();
+  if (swJS.IsEmpty())
+    return;
+
+  RunScript(pFormFillEnv, swJS, cb);
+}
+
+void CPDFSDK_ActionHandler::RunScript(
+    CPDFSDK_FormFillEnvironment* pFormFillEnv,
+    const WideString& script,
+    std::function<void(IJS_EventContext* context)> cb) {
+  IJS_Runtime* pRuntime = pFormFillEnv->GetJSRuntime();
+  IJS_EventContext* pContext = pRuntime->NewEventContext();
+
+  cb(pContext);
+
+  WideString csInfo;
+  pContext->RunScript(script, &csInfo);
+  pRuntime->ReleaseEventContext(pContext);
+  // TODO(dsinclair): Return error if RunScript returns false.
+}
diff --git a/fpdfsdk/fsdk_actionhandler.h b/fpdfsdk/fsdk_actionhandler.h
index 006aff3..a77ee77 100644
--- a/fpdfsdk/fsdk_actionhandler.h
+++ b/fpdfsdk/fsdk_actionhandler.h
@@ -20,6 +20,7 @@
 class CPDF_Bookmark;
 class CPDF_Dictionary;
 class CPDF_FormField;
+class IJS_EventContext;
 
 class CPDFSDK_ActionHandler {
  public:
@@ -48,14 +49,21 @@
                       CPDF_AAction::AActionType type,
                       CPDFSDK_FormFillEnvironment* pFormFillEnv,
                       CPDF_FormField* pFormField,
-                      PDFSDK_FieldAction& data);
+                      PDFSDK_FieldAction* data);
   bool DoAction_FieldJavaScript(const CPDF_Action& JsAction,
                                 CPDF_AAction::AActionType type,
                                 CPDFSDK_FormFillEnvironment* pFormFillEnv,
                                 CPDF_FormField* pFormField,
-                                PDFSDK_FieldAction& data);
+                                PDFSDK_FieldAction* data);
 
  private:
+  void RunScriptForAction(const CPDF_Action& action,
+                          CPDFSDK_FormFillEnvironment* pFormFillEnv,
+                          std::function<void(IJS_EventContext* context)> cb);
+  void RunScript(CPDFSDK_FormFillEnvironment* pFormFillEnv,
+                 const WideString& script,
+                 std::function<void(IJS_EventContext* context)> cb);
+
   bool ExecuteDocumentOpenAction(const CPDF_Action& action,
                                  CPDFSDK_FormFillEnvironment* pFormFillEnv,
                                  std::set<CPDF_Dictionary*>* visited);
@@ -67,7 +75,7 @@
                           CPDF_AAction::AActionType type,
                           CPDFSDK_FormFillEnvironment* pFormFillEnv,
                           CPDF_FormField* pFormField,
-                          PDFSDK_FieldAction& data,
+                          PDFSDK_FieldAction* data,
                           std::set<CPDF_Dictionary*>* visited);
   bool ExecuteScreenAction(const CPDF_Action& action,
                            CPDF_AAction::AActionType type,
@@ -93,7 +101,7 @@
   void RunFieldJavaScript(CPDFSDK_FormFillEnvironment* pFormFillEnv,
                           CPDF_FormField* pFormField,
                           CPDF_AAction::AActionType type,
-                          PDFSDK_FieldAction& data,
+                          PDFSDK_FieldAction* data,
                           const WideString& script);
 
   bool IsValidField(CPDFSDK_FormFillEnvironment* pFormFillEnv,