Merge to XFA: Pass IJS_Runtime, not IJS_Context, to native object constructors.

Original Review URL: https://codereview.chromium.org/1389163007 .
(cherry picked from commit 848a13b6777cbff8cc4aea3ab3d69eaa0b82ae6c)

Merge conflics in:
fpdfsdk/src/javascript/JS_Runtime.cpp
fpdfsdk/src/javascript/JS_Runtime_Stub.cpp
fpdfsdk/src/jsapi/fxjs_v8.cpp

R=thestig@chromium.org

Review URL: https://codereview.chromium.org/1394993006 .
diff --git a/fpdfsdk/include/javascript/IJavaScript.h b/fpdfsdk/include/javascript/IJavaScript.h
index f78ee52..c8962bd 100644
--- a/fpdfsdk/include/javascript/IJavaScript.h
+++ b/fpdfsdk/include/javascript/IJavaScript.h
@@ -17,10 +17,11 @@
 class CPDF_Bookmark;
 class CPDF_FormField;
 
+// Records the details of an event and triggers JS execution for it.
 class IJS_Context {
  public:
   virtual FX_BOOL RunScript(const CFX_WideString& script,
-                            CFX_WideString& info) = 0;
+                            CFX_WideString* info) = 0;
 
   virtual void OnApp_Init() = 0;
 
@@ -132,6 +133,7 @@
   virtual ~IJS_Context() {}
 };
 
+// Owns the FJXS objects needed to actually execute JS.
 class IJS_Runtime {
  public:
   static void Initialize(unsigned int slot, void* isolate);
@@ -144,6 +146,9 @@
   virtual void SetReaderDocument(CPDFSDK_Document* pReaderDoc) = 0;
 
   virtual CPDFSDK_Document* GetReaderDocument() = 0;
+  virtual int Execute(IJS_Context* cc,
+                      const wchar_t* script,
+                      CFX_WideString* info) = 0;
 
   virtual FX_BOOL GetHValueByName(const CFX_ByteStringC& utf8Name,
                                   FXJSE_HVALUE hValue) = 0;
diff --git a/fpdfsdk/include/jsapi/fxjs_v8.h b/fpdfsdk/include/jsapi/fxjs_v8.h
index d3cd4eb..7c6f497 100644
--- a/fpdfsdk/include/jsapi/fxjs_v8.h
+++ b/fpdfsdk/include/jsapi/fxjs_v8.h
@@ -17,10 +17,10 @@
 #include <v8.h>
 #include "../../../core/include/fxcrt/fx_basic.h"
 
-// FXJS_V8 places no interpretation on these two classes; it merely
-// passes them on to the caller-provided FXJS_CONSTRUCTORs.
-class IJS_Context;
-class IJS_Runtime;
+// FXJS_V8 places no restrictions on these two classes; it merely passes them
+// on to caller-provided methods.
+class IJS_Context;  // A description of the event that caused JS execution.
+class IJS_Runtime;  // A native runtime, typically owns the v8::Context.
 
 // FXJS_V8 places no interpreation on this calass; it merely passes it
 // along to XFA.
@@ -66,7 +66,7 @@
   void Free(void* data, size_t length) override;
 };
 
-using FXJS_CONSTRUCTOR = void (*)(IJS_Context* cc, v8::Local<v8::Object> obj);
+using FXJS_CONSTRUCTOR = void (*)(IJS_Runtime* cc, v8::Local<v8::Object> obj);
 using FXJS_DESTRUCTOR = void (*)(v8::Local<v8::Object> obj);
 
 // Call before making FXJS_PrepareIsolate call.
@@ -124,8 +124,7 @@
 
 // Called after FXJS_Define* calls made.
 void FXJS_InitializeRuntime(v8::Isolate* pIsolate,
-                            IJS_Runtime* pFXRuntime,
-                            IJS_Context* context,
+                            IJS_Runtime* pIRuntime,
                             v8::Global<v8::Context>& v8PersistentContext);
 void FXJS_ReleaseRuntime(v8::Isolate* pIsolate,
                          v8::Global<v8::Context>& v8PersistentContext);
@@ -135,11 +134,10 @@
 int FXJS_Execute(v8::Isolate* pIsolate,
                  IJS_Context* pJSContext,
                  const wchar_t* script,
-                 long length,
                  FXJSErr* perror);
 
 v8::Local<v8::Object> FXJS_NewFxDynamicObj(v8::Isolate* pIsolate,
-                                           IJS_Context* pJSContext,
+                                           IJS_Runtime* pJSContext,
                                            int nObjDefnID);
 v8::Local<v8::Object> FXJS_GetThisObj(v8::Isolate* pIsolate);
 int FXJS_GetObjDefnID(v8::Local<v8::Object> pObj);
diff --git a/fpdfsdk/src/fsdk_actionhandler.cpp b/fpdfsdk/src/fsdk_actionhandler.cpp
index 6cb37b9..feb9a85 100644
--- a/fpdfsdk/src/fsdk_actionhandler.cpp
+++ b/fpdfsdk/src/fsdk_actionhandler.cpp
@@ -149,18 +149,14 @@
     if (pEnv->IsJSInitiated()) {
       CFX_WideString swJS = action.GetJavaScript();
       if (!swJS.IsEmpty()) {
-        IJS_Runtime* pRuntime = pDocument->GetJsRuntime();  //????
-        ASSERT(pRuntime != NULL);
-
+        IJS_Runtime* pRuntime = pDocument->GetJsRuntime();
         pRuntime->SetReaderDocument(pDocument);
 
         IJS_Context* pContext = pRuntime->NewContext();
-        ASSERT(pContext != NULL);
-
         pContext->OnLink_MouseUp(pDocument);
 
         CFX_WideString csInfo;
-        FX_BOOL bRet = pContext->RunScript(swJS, csInfo);
+        FX_BOOL bRet = pContext->RunScript(swJS, &csInfo);
         if (!bRet) {
           // FIXME: return error.
         }
@@ -293,65 +289,13 @@
       CFX_WideString swJS = action.GetJavaScript();
       if (!swJS.IsEmpty()) {
         IJS_Runtime* pRuntime = pDocument->GetJsRuntime();
-        ASSERT(pRuntime != NULL);
-
         pRuntime->SetReaderDocument(pDocument);
 
         IJS_Context* pContext = pRuntime->NewContext();
-        ASSERT(pContext != NULL);
-
-        // 			switch (type)
-        // 			{
-        // 			case CPDF_AAction::CursorEnter:
-        // 				pContext->OnScreen_MouseEnter(IsCTRLpressed(),
-        // IsSHIFTpressed(), pScreen);
-        // 				break;
-        // 			case CPDF_AAction::CursorExit:
-        // 				pContext->OnScreen_MouseExit(IsCTRLpressed(),
-        // IsSHIFTpressed(), pScreen);
-        // 				break;
-        // 			case CPDF_AAction::ButtonDown:
-        // 				pContext->OnScreen_MouseDown(IsCTRLpressed(),
-        // IsSHIFTpressed(), pScreen);
-        // 				break;
-        // 			case CPDF_AAction::ButtonUp:
-        // 				pContext->OnScreen_MouseUp(IsCTRLpressed(),
-        // IsSHIFTpressed(), pScreen);
-        // 				break;
-        // 			case CPDF_AAction::GetFocus:
-        // 				pContext->OnScreen_Focus(IsCTRLpressed(),
-        // IsSHIFTpressed(), pScreen);
-        // 				break;
-        // 			case CPDF_AAction::LoseFocus:
-        // 				pContext->OnScreen_Blur(IsCTRLpressed(),
-        // IsSHIFTpressed(), pScreen);
-        // 				break;
-        // 			case CPDF_AAction::PageOpen:
-        // 				pContext->OnScreen_Open(IsCTRLpressed(),
-        // IsSHIFTpressed(), pScreen);
-        // 				break;
-        // 			case CPDF_AAction::PageClose:
-        // 				pContext->OnScreen_Close(IsCTRLpressed(),
-        // IsSHIFTpressed(), pScreen);
-        // 				break;
-        // 			case CPDF_AAction::PageVisible:
-        // 				pContext->OnScreen_InView(IsCTRLpressed(),
-        // IsSHIFTpressed(), pScreen);
-        // 				break;
-        // 			case CPDF_AAction::PageInvisible:
-        // 				pContext->OnScreen_OutView(IsCTRLpressed(),
-        // IsSHIFTpressed(), pScreen);
-        // 				break;
-        // 			default:
-        // 				ASSERT(FALSE);
-        // 				break;
-        // 			}
-
         CFX_WideString csInfo;
-        FX_BOOL bRet = pContext->RunScript(swJS, csInfo);
+        FX_BOOL bRet = pContext->RunScript(swJS, &csInfo);
         if (!bRet) {
-          // CBCL_FormNotify::MsgBoxJSError(pPageView->GetPageViewWnd(),
-          // csInfo);
+          // FIXME: return error.
         }
 
         pRuntime->ReleaseContext(pContext);
@@ -389,20 +333,15 @@
       CFX_WideString swJS = action.GetJavaScript();
       if (!swJS.IsEmpty()) {
         IJS_Runtime* pRuntime = pDocument->GetJsRuntime();
-        ASSERT(pRuntime != NULL);
-
         pRuntime->SetReaderDocument(pDocument);
 
         IJS_Context* pContext = pRuntime->NewContext();
-        ASSERT(pContext != NULL);
-
         pContext->OnBookmark_MouseUp(pBookmark);
 
         CFX_WideString csInfo;
-        FX_BOOL bRet = pContext->RunScript(swJS, csInfo);
+        FX_BOOL bRet = pContext->RunScript(swJS, &csInfo);
         if (!bRet) {
-          // CBCL_FormNotify::MsgBoxJSError(pPageView->GetPageViewWnd(),
-          // csInfo);
+          // FIXME: return error.
         }
 
         pRuntime->ReleaseContext(pContext);
@@ -602,9 +541,9 @@
   }
 
   CFX_WideString csInfo;
-  FX_BOOL bRet = pContext->RunScript(script, csInfo);
+  FX_BOOL bRet = pContext->RunScript(script, &csInfo);
   if (!bRet) {
-    // CBCL_FormNotify::MsgBoxJSError(pPageView->GetPageViewWnd(), csInfo);
+    // FIXME: return error.
   }
 
   pRuntime->ReleaseContext(pContext);
@@ -627,9 +566,9 @@
   pContext->OnDoc_Open(pDocument, sScriptName);
 
   CFX_WideString csInfo;
-  FX_BOOL bRet = pContext->RunScript(script, csInfo);
+  FX_BOOL bRet = pContext->RunScript(script, &csInfo);
   if (!bRet) {
-    // CBCL_FormNotify::MsgBoxJSError(pPageView->GetPageViewWnd(), csInfo);
+    // FIXME: return error.
   }
 
   pRuntime->ReleaseContext(pContext);
@@ -683,9 +622,9 @@
   }
 
   CFX_WideString csInfo;
-  FX_BOOL bRet = pContext->RunScript(script, csInfo);
+  FX_BOOL bRet = pContext->RunScript(script, &csInfo);
   if (!bRet) {
-    // CBCL_FormNotify::MsgBoxJSError(pPageView->GetPageViewWnd(), csInfo);
+    // FIXME: return error.
   }
 
   pRuntime->ReleaseContext(pContext);
diff --git a/fpdfsdk/src/fsdk_baseform.cpp b/fpdfsdk/src/fsdk_baseform.cpp
index 4a6b987..fb79227 100644
--- a/fpdfsdk/src/fsdk_baseform.cpp
+++ b/fpdfsdk/src/fsdk_baseform.cpp
@@ -1996,8 +1996,7 @@
                                           CPDF_Stream* pImage) {
   ASSERT(pImage != NULL);
 
-  CPDF_Document* pDoc =
-      m_pPageView->GetPDFDocument();  // pDocument->GetDocument();
+  CPDF_Document* pDoc = m_pPageView->GetPDFDocument();
   ASSERT(pDoc != NULL);
 
   CPDF_Dictionary* pAPDict = m_pAnnot->GetAnnotDict()->GetDict("AP");
@@ -2453,7 +2452,6 @@
     for (int i = 0; i < nSize; i++) {
       if (CPDF_FormField* pField =
               m_pInterForm->GetFieldInCalculationOrder(i)) {
-        //          ASSERT(pField != NULL);
         int nType = pField->GetFieldType();
         if (nType == FIELDTYPE_COMBOBOX || nType == FIELDTYPE_TEXTFIELD) {
           CPDF_AAction aAction = pField->GetAdditionalAction();
@@ -2471,7 +2469,7 @@
                 pContext->OnField_Calculate(pFormField, pField, sValue, bRC);
 
                 CFX_WideString sInfo;
-                FX_BOOL bRet = pContext->RunScript(csJS, sInfo);
+                FX_BOOL bRet = pContext->RunScript(csJS, &sInfo);
                 pRuntime->ReleaseContext(pContext);
 
                 if (bRet) {
@@ -2533,7 +2531,7 @@
         pContext->OnField_Format(pFormField, Value, TRUE);
 
         CFX_WideString sInfo;
-        FX_BOOL bRet = pContext->RunScript(script, sInfo);
+        FX_BOOL bRet = pContext->RunScript(script, &sInfo);
         pRuntime->ReleaseContext(pContext);
 
         if (bRet) {
@@ -2831,7 +2829,7 @@
       m_pDocument->GetPath(), (CFX_PtrArray&)fields, bIncludeOrExclude);
   if (!pFDF)
     return FALSE;
-  FX_BOOL bRet = pFDF->WriteBuf(textBuf);  // = FALSE;//
+  FX_BOOL bRet = pFDF->WriteBuf(textBuf);
   delete pFDF;
 
   return bRet;
diff --git a/fpdfsdk/src/javascript/Document.cpp b/fpdfsdk/src/javascript/Document.cpp
index c1bd029..bcf8af6 100644
--- a/fpdfsdk/src/javascript/Document.cpp
+++ b/fpdfsdk/src/javascript/Document.cpp
@@ -140,17 +140,12 @@
 
 IMPLEMENT_JS_CLASS(CJS_Document, Document)
 
-FX_BOOL CJS_Document::InitInstance(IJS_Context* cc) {
-  CJS_Context* pContext = (CJS_Context*)cc;
-  ASSERT(pContext != NULL);
-
-  Document* pDoc = (Document*)GetEmbedObject();
-  ASSERT(pDoc != NULL);
-
-  pDoc->AttachDoc(pContext->GetReaderDocument());
-  pDoc->SetIsolate(pContext->GetJSRuntime()->GetIsolate());
-  return TRUE;
-};
+void CJS_Document::InitInstance(IJS_Runtime* pIRuntime) {
+  CJS_Runtime* pRuntime = static_cast<CJS_Runtime*>(pIRuntime);
+  Document* pDoc = static_cast<Document*>(GetEmbedObject());
+  pDoc->AttachDoc(pRuntime->GetReaderDocument());
+  pDoc->SetIsolate(pRuntime->GetIsolate());
+}
 
 /* --------------------------------- Document ---------------------------------
  */
@@ -326,7 +321,7 @@
 
   CJS_Runtime* pRuntime = pContext->GetJSRuntime();
   v8::Local<v8::Object> pFieldObj = FXJS_NewFxDynamicObj(
-      pRuntime->GetIsolate(), pContext, CJS_Field::g_nObjDefnID);
+      pRuntime->GetIsolate(), pRuntime, CJS_Field::g_nObjDefnID);
 
   v8::Isolate* isolate = GetIsolate(cc);
   CJS_Field* pJSField = (CJS_Field*)FXJS_GetPrivate(isolate, pFieldObj);
@@ -837,7 +832,7 @@
     CJS_Context* pContext = (CJS_Context*)cc;
     CJS_Runtime* pRuntime = pContext->GetJSRuntime();
     v8::Local<v8::Object> pObj =
-        FXJS_NewFxDynamicObj(pRuntime->GetIsolate(), pContext, -1);
+        FXJS_NewFxDynamicObj(pRuntime->GetIsolate(), pRuntime, -1);
     FXJS_PutObjectString(isolate, pObj, L"Author", cwAuthor.c_str());
     FXJS_PutObjectString(isolate, pObj, L"Title", cwTitle.c_str());
     FXJS_PutObjectString(isolate, pObj, L"Subject", cwSubject.c_str());
@@ -1433,7 +1428,6 @@
     return TRUE;
   }
 
-  CJS_Context* pContext = static_cast<CJS_Context*>(cc);
   CJS_Runtime* pRuntime = CJS_Runtime::FromContext(cc);
   CJS_Array Icons(pRuntime);
   IconElement* pIconElement = NULL;
@@ -1442,7 +1436,7 @@
     pIconElement = (*m_pIconTree)[i];
 
     v8::Local<v8::Object> pObj = FXJS_NewFxDynamicObj(
-        pRuntime->GetIsolate(), pContext, CJS_Icon::g_nObjDefnID);
+        pRuntime->GetIsolate(), pRuntime, CJS_Icon::g_nObjDefnID);
     if (pObj.IsEmpty())
       return FALSE;
 
@@ -1485,7 +1479,7 @@
       Icon* pRetIcon = (*m_pIconTree)[i]->IconStream;
 
       v8::Local<v8::Object> pObj = FXJS_NewFxDynamicObj(
-          pRuntime->GetIsolate(), pContext, CJS_Icon::g_nObjDefnID);
+          pRuntime->GetIsolate(), pRuntime, CJS_Icon::g_nObjDefnID);
       if (pObj.IsEmpty())
         return FALSE;
 
@@ -1686,7 +1680,7 @@
   CJS_Context* pContext = (CJS_Context*)cc;
   CJS_Runtime* pRuntime = pContext->GetJSRuntime();
   v8::Local<v8::Object> pRetObj = FXJS_NewFxDynamicObj(
-      pRuntime->GetIsolate(), pContext, CJS_PrintParamsObj::g_nObjDefnID);
+      pRuntime->GetIsolate(), pRuntime, CJS_PrintParamsObj::g_nObjDefnID);
 
   // Not implemented yet.
 
diff --git a/fpdfsdk/src/javascript/Document.h b/fpdfsdk/src/javascript/Document.h
index 516045e..149102d 100644
--- a/fpdfsdk/src/javascript/Document.h
+++ b/fpdfsdk/src/javascript/Document.h
@@ -310,7 +310,7 @@
   ~CJS_Document() override {}
 
   // CJS_Object
-  FX_BOOL InitInstance(IJS_Context* cc) override;
+  void InitInstance(IJS_Runtime* pIRuntime) override;
 
   DECLARE_JS_CLASS();
 
diff --git a/fpdfsdk/src/javascript/Field.cpp b/fpdfsdk/src/javascript/Field.cpp
index f04c379..f3d12b4 100644
--- a/fpdfsdk/src/javascript/Field.cpp
+++ b/fpdfsdk/src/javascript/Field.cpp
@@ -110,16 +110,10 @@
 
 IMPLEMENT_JS_CLASS(CJS_Field, Field)
 
-FX_BOOL CJS_Field::InitInstance(IJS_Context* cc) {
-  CJS_Context* pContext = (CJS_Context*)cc;
-  ASSERT(pContext != NULL);
-
-  Field* pField = (Field*)GetEmbedObject();
-  ASSERT(pField != NULL);
-
-  pField->SetIsolate(pContext->GetJSRuntime()->GetIsolate());
-
-  return TRUE;
+void CJS_Field::InitInstance(IJS_Runtime* pIRuntime) {
+  CJS_Runtime* pRuntime = static_cast<CJS_Runtime*>(pIRuntime);
+  Field* pField = static_cast<Field*>(GetEmbedObject());
+  pField->SetIsolate(pRuntime->GetIsolate());
 };
 
 Field::Field(CJS_Object* pJSObject)
@@ -3279,7 +3273,7 @@
   CJS_Context* pContext = (CJS_Context*)cc;
   CJS_Runtime* pRuntime = pContext->GetJSRuntime();
   v8::Local<v8::Object> pObj = FXJS_NewFxDynamicObj(
-      pRuntime->GetIsolate(), pContext, CJS_Icon::g_nObjDefnID);
+      pRuntime->GetIsolate(), pRuntime, CJS_Icon::g_nObjDefnID);
   ASSERT(pObj.IsEmpty() == FALSE);
 
   CJS_Icon* pJS_Icon = (CJS_Icon*)FXJS_GetPrivate(pRuntime->GetIsolate(), pObj);
@@ -3488,7 +3482,7 @@
   for (int j = 0, jsz = swSort.GetSize(); j < jsz; j++) {
     nonstd::unique_ptr<CFX_WideString> pStr(swSort.GetAt(j));
     v8::Local<v8::Object> pObj = FXJS_NewFxDynamicObj(
-        pRuntime->GetIsolate(), pContext, CJS_Field::g_nObjDefnID);
+        pRuntime->GetIsolate(), pRuntime, CJS_Field::g_nObjDefnID);
     ASSERT(!pObj.IsEmpty());
 
     CJS_Field* pJSField =
diff --git a/fpdfsdk/src/javascript/Field.h b/fpdfsdk/src/javascript/Field.h
index b263241..21ae04c 100644
--- a/fpdfsdk/src/javascript/Field.h
+++ b/fpdfsdk/src/javascript/Field.h
@@ -501,7 +501,7 @@
   CJS_Field(v8::Local<v8::Object> pObject) : CJS_Object(pObject) {}
   ~CJS_Field(void) override {}
 
-  FX_BOOL InitInstance(IJS_Context* cc) override;
+  void InitInstance(IJS_Runtime* pIRuntime) override;
 
   DECLARE_JS_CLASS();
   JS_STATIC_PROP(alignment, Field);
diff --git a/fpdfsdk/src/javascript/JS_Context.cpp b/fpdfsdk/src/javascript/JS_Context.cpp
index 4769dac..a53e745 100644
--- a/fpdfsdk/src/javascript/JS_Context.cpp
+++ b/fpdfsdk/src/javascript/JS_Context.cpp
@@ -33,7 +33,7 @@
 }
 
 FX_BOOL CJS_Context::RunScript(const CFX_WideString& script,
-                               CFX_WideString& info) {
+                               CFX_WideString* info) {
   v8::Isolate::Scope isolate_scope(m_pRuntime->GetIsolate());
   v8::Locker locker(m_pRuntime->GetIsolate());
   v8::HandleScope handle_scope(m_pRuntime->GetIsolate());
@@ -41,7 +41,7 @@
   v8::Context::Scope context_scope(context);
 
   if (m_bBusy) {
-    info = JSGetStringFromID(this, IDS_STRING_JSBUSY);
+    *info = JSGetStringFromID(this, IDS_STRING_JSBUSY);
     return FALSE;
   }
   m_bBusy = TRUE;
@@ -50,24 +50,20 @@
   CJS_Runtime::FieldEvent event(m_pEventHandler->TargetName(),
                                 m_pEventHandler->EventType());
   if (!m_pRuntime->AddEventToSet(event)) {
-    info = JSGetStringFromID(this, IDS_STRING_JSEVENT);
+    *info = JSGetStringFromID(this, IDS_STRING_JSEVENT);
     return FALSE;
   }
 
-  FXJSErr error = {NULL, NULL, 0};
+  CFX_WideString sErrorMessage;
   int nRet = 0;
   if (script.GetLength() > 0) {
-    nRet = FXJS_Execute(m_pRuntime->GetIsolate(), this, script.c_str(),
-                        script.GetLength(), &error);
+    nRet = m_pRuntime->Execute(this, script.c_str(), &sErrorMessage);
   }
 
   if (nRet < 0) {
-    CFX_WideString sLine;
-    sLine.Format(L"[ Line: %05d { %s } ] : %s", error.linnum - 1, error.srcline,
-                 error.message);
-    info += sLine;
+    *info += sErrorMessage;
   } else {
-    info = JSGetStringFromID(this, IDS_STRING_RUN);
+    *info = JSGetStringFromID(this, IDS_STRING_RUN);
   }
 
   m_pRuntime->RemoveEventFromSet(event);
diff --git a/fpdfsdk/src/javascript/JS_Context.h b/fpdfsdk/src/javascript/JS_Context.h
index 7fbcbec..dc5d833 100644
--- a/fpdfsdk/src/javascript/JS_Context.h
+++ b/fpdfsdk/src/javascript/JS_Context.h
@@ -21,7 +21,7 @@
 
   // IJS_Context
   FX_BOOL RunScript(const CFX_WideString& script,
-                    CFX_WideString& info) override;
+                    CFX_WideString* info) override;
   void OnApp_Init() override;
   void OnDoc_Open(CPDFSDK_Document* pDoc,
                   const CFX_WideString& strTargetName) override;
diff --git a/fpdfsdk/src/javascript/JS_Define.h b/fpdfsdk/src/javascript/JS_Define.h
index 178e28f..252c50f 100644
--- a/fpdfsdk/src/javascript/JS_Define.h
+++ b/fpdfsdk/src/javascript/JS_Define.h
@@ -245,22 +245,22 @@
     DefineMethods(pIsolate);                                                \
   }
 
-#define DECLARE_JS_CLASS_RICH_PART()                                     \
-  static void JSConstructor(IJS_Context* cc, v8::Local<v8::Object> obj); \
-  static void JSDestructor(v8::Local<v8::Object> obj);                   \
-  static void DefineProps(v8::Isolate* pIsoalte);                        \
-  static void DefineMethods(v8::Isolate* pIsoalte);                      \
-  static JSPropertySpec JS_Class_Properties[];                           \
+#define DECLARE_JS_CLASS_RICH_PART()                                           \
+  static void JSConstructor(IJS_Runtime* pRuntime, v8::Local<v8::Object> obj); \
+  static void JSDestructor(v8::Local<v8::Object> obj);                         \
+  static void DefineProps(v8::Isolate* pIsoalte);                              \
+  static void DefineMethods(v8::Isolate* pIsoalte);                            \
+  static JSPropertySpec JS_Class_Properties[];                                 \
   static JSMethodSpec JS_Class_Methods[];
 
 #define IMPLEMENT_JS_CLASS_RICH_PART(js_class_name, class_alternate,          \
                                      class_name)                              \
-  void js_class_name::JSConstructor(IJS_Context* cc,                          \
+  void js_class_name::JSConstructor(IJS_Runtime* pIRuntime,                   \
                                     v8::Local<v8::Object> obj) {              \
     CJS_Object* pObj = new js_class_name(obj);                                \
     pObj->SetEmbedObject(new class_alternate(pObj));                          \
     FXJS_SetPrivate(nullptr, obj, (void*)pObj);                               \
-    pObj->InitInstance(cc);                                                   \
+    pObj->InitInstance(pIRuntime);                                            \
   }                                                                           \
   void js_class_name::JSDestructor(v8::Local<v8::Object> obj) {               \
     js_class_name* pObj = (js_class_name*)FXJS_GetPrivate(nullptr, obj);      \
diff --git a/fpdfsdk/src/javascript/JS_EventHandler.cpp b/fpdfsdk/src/javascript/JS_EventHandler.cpp
index dd5c442..cb86fde 100644
--- a/fpdfsdk/src/javascript/JS_EventHandler.cpp
+++ b/fpdfsdk/src/javascript/JS_EventHandler.cpp
@@ -613,11 +613,11 @@
 Field* CJS_EventHandler::Source() {
   CJS_Runtime* pRuntime = m_pJSContext->GetJSRuntime();
   v8::Local<v8::Object> pDocObj = FXJS_NewFxDynamicObj(
-      pRuntime->GetIsolate(), m_pJSContext, CJS_Document::g_nObjDefnID);
+      pRuntime->GetIsolate(), pRuntime, CJS_Document::g_nObjDefnID);
   ASSERT(!pDocObj.IsEmpty());
 
   v8::Local<v8::Object> pFieldObj = FXJS_NewFxDynamicObj(
-      pRuntime->GetIsolate(), m_pJSContext, CJS_Field::g_nObjDefnID);
+      pRuntime->GetIsolate(), pRuntime, CJS_Field::g_nObjDefnID);
   ASSERT(!pFieldObj.IsEmpty());
 
   CJS_Document* pJSDocument =
@@ -636,11 +636,11 @@
 Field* CJS_EventHandler::Target_Field() {
   CJS_Runtime* pRuntime = m_pJSContext->GetJSRuntime();
   v8::Local<v8::Object> pDocObj = FXJS_NewFxDynamicObj(
-      pRuntime->GetIsolate(), m_pJSContext, CJS_Document::g_nObjDefnID);
+      pRuntime->GetIsolate(), pRuntime, CJS_Document::g_nObjDefnID);
   ASSERT(!pDocObj.IsEmpty());
 
   v8::Local<v8::Object> pFieldObj = FXJS_NewFxDynamicObj(
-      pRuntime->GetIsolate(), m_pJSContext, CJS_Field::g_nObjDefnID);
+      pRuntime->GetIsolate(), pRuntime, CJS_Field::g_nObjDefnID);
   ASSERT(!pFieldObj.IsEmpty());
 
   CJS_Document* pJSDocument =
diff --git a/fpdfsdk/src/javascript/JS_Object.h b/fpdfsdk/src/javascript/JS_Object.h
index 563a316..5075152 100644
--- a/fpdfsdk/src/javascript/JS_Object.h
+++ b/fpdfsdk/src/javascript/JS_Object.h
@@ -49,8 +49,8 @@
   virtual FX_BOOL IsType(const FX_CHAR* sClassName) { return TRUE; }
   virtual CFX_ByteString GetClassName() { return ""; }
 
-  virtual FX_BOOL InitInstance(IJS_Context* cc) { return TRUE; }
-  virtual FX_BOOL ExitInstance() { return TRUE; }
+  virtual void InitInstance(IJS_Runtime* pIRuntime) {}
+  virtual void ExitInstance() {}
 
   v8::Local<v8::Object> ToV8Object() { return m_pV8Object.Get(m_pIsolate); }
 
diff --git a/fpdfsdk/src/javascript/JS_Runtime.cpp b/fpdfsdk/src/javascript/JS_Runtime.cpp
index 1d2fa84..8b0475b 100644
--- a/fpdfsdk/src/javascript/JS_Runtime.cpp
+++ b/fpdfsdk/src/javascript/JS_Runtime.cpp
@@ -77,7 +77,7 @@
   v8::HandleScope handle_scope(isolate);
   if (CPDFXFA_App::GetInstance()->IsJavaScriptInitialized()) {
     CJS_Context* pContext = (CJS_Context*)NewContext();
-    FXJS_InitializeRuntime(GetIsolate(), this, pContext, m_context);
+    FXJS_InitializeRuntime(GetIsolate(), this, m_context);
     ReleaseContext(pContext);
     return;
   }
@@ -88,7 +88,7 @@
   CPDFXFA_App::GetInstance()->SetJavaScriptInitialized(TRUE);
 
   CJS_Context* pContext = (CJS_Context*)NewContext();
-  FXJS_InitializeRuntime(GetIsolate(), this, pContext, m_context);
+  FXJS_InitializeRuntime(GetIsolate(), this, m_context);
   ReleaseContext(pContext);
 }
 
@@ -208,6 +208,18 @@
   }
 }
 
+int CJS_Runtime::Execute(IJS_Context* cc,
+                         const wchar_t* script,
+                         CFX_WideString* info) {
+  FXJSErr error = {};
+  int nRet = FXJS_Execute(m_isolate, cc, script, &error);
+  if (nRet < 0) {
+    info->Format(L"[ Line: %05d { %s } ] : %s", error.linnum - 1, error.srcline,
+                 error.message);
+  }
+  return nRet;
+}
+
 bool CJS_Runtime::AddEventToSet(const FieldEvent& event) {
   return m_FieldEventSet.insert(event).second;
 }
diff --git a/fpdfsdk/src/javascript/JS_Runtime.h b/fpdfsdk/src/javascript/JS_Runtime.h
index c259a41..4772823 100644
--- a/fpdfsdk/src/javascript/JS_Runtime.h
+++ b/fpdfsdk/src/javascript/JS_Runtime.h
@@ -40,6 +40,9 @@
   IJS_Context* GetCurrentContext() override;
   void SetReaderDocument(CPDFSDK_Document* pReaderDoc) override;
   CPDFSDK_Document* GetReaderDocument() override { return m_pDocument; }
+  int Execute(IJS_Context* cc,
+              const wchar_t* script,
+              CFX_WideString* info) override;
 
   CPDFDoc_Environment* GetReaderApp() const { return m_pApp; }
 
diff --git a/fpdfsdk/src/javascript/JS_Runtime_Stub.cpp b/fpdfsdk/src/javascript/JS_Runtime_Stub.cpp
index ea1e6c1..7e3d788 100644
--- a/fpdfsdk/src/javascript/JS_Runtime_Stub.cpp
+++ b/fpdfsdk/src/javascript/JS_Runtime_Stub.cpp
@@ -15,7 +15,7 @@
 
   // IJS_Context:
   FX_BOOL RunScript(const CFX_WideString& script,
-                    CFX_WideString& info) override {
+                    CFX_WideString* info) override {
     return FALSE;
   }
 
@@ -146,6 +146,12 @@
     return FALSE;
   }
 
+  int Execute(IJS_Context* cc,
+              const wchar_t* script,
+              CFX_WideString* info) override {
+    return 0;
+  }
+
  protected:
   CPDFSDK_Document* m_pDoc;
   nonstd::unique_ptr<CJS_ContextStub> m_pContext;
diff --git a/fpdfsdk/src/javascript/app.cpp b/fpdfsdk/src/javascript/app.cpp
index 80edaa6..80a9b17 100644
--- a/fpdfsdk/src/javascript/app.cpp
+++ b/fpdfsdk/src/javascript/app.cpp
@@ -124,7 +124,7 @@
             (CJS_Document*)FXJS_GetPrivate(pRuntime->GetIsolate(), pObj);
     } else {
       v8::Local<v8::Object> pObj = FXJS_NewFxDynamicObj(
-          pRuntime->GetIsolate(), pContext, CJS_Document::g_nObjDefnID);
+          pRuntime->GetIsolate(), pRuntime, CJS_Document::g_nObjDefnID);
       pJSDocument =
           (CJS_Document*)FXJS_GetPrivate(pRuntime->GetIsolate(), pObj);
       ASSERT(pJSDocument != NULL);
@@ -409,7 +409,7 @@
   m_aTimer.Add(pTimer);
 
   v8::Local<v8::Object> pRetObj = FXJS_NewFxDynamicObj(
-      pRuntime->GetIsolate(), pContext, CJS_TimerObj::g_nObjDefnID);
+      pRuntime->GetIsolate(), pRuntime, CJS_TimerObj::g_nObjDefnID);
   CJS_TimerObj* pJS_TimerObj =
       (CJS_TimerObj*)FXJS_GetPrivate(pRuntime->GetIsolate(), pRetObj);
   TimerObj* pTimerObj = (TimerObj*)pJS_TimerObj->GetEmbedObject();
@@ -450,7 +450,7 @@
   m_aTimer.Add(pTimer);
 
   v8::Local<v8::Object> pRetObj = FXJS_NewFxDynamicObj(
-      pRuntime->GetIsolate(), pContext, CJS_TimerObj::g_nObjDefnID);
+      pRuntime->GetIsolate(), pRuntime, CJS_TimerObj::g_nObjDefnID);
   CJS_TimerObj* pJS_TimerObj =
       (CJS_TimerObj*)FXJS_GetPrivate(pRuntime->GetIsolate(), pRetObj);
   TimerObj* pTimerObj = (TimerObj*)pJS_TimerObj->GetEmbedObject();
@@ -560,14 +560,11 @@
 }
 
 void app::RunJsScript(CJS_Runtime* pRuntime, const CFX_WideString& wsScript) {
-  ASSERT(pRuntime != NULL);
-
   if (!pRuntime->IsBlocking()) {
     IJS_Context* pContext = pRuntime->NewContext();
-    ASSERT(pContext != NULL);
     pContext->OnExternal_Exec();
     CFX_WideString wtInfo;
-    pContext->RunScript(wsScript, wtInfo);
+    pContext->RunScript(wsScript, &wtInfo);
     pRuntime->ReleaseContext(pContext);
   }
 }
diff --git a/fpdfsdk/src/javascript/global.cpp b/fpdfsdk/src/javascript/global.cpp
index 97a74e7..403cf58 100644
--- a/fpdfsdk/src/javascript/global.cpp
+++ b/fpdfsdk/src/javascript/global.cpp
@@ -88,17 +88,12 @@
 
 IMPLEMENT_SPECIAL_JS_CLASS(CJS_Global, JSGlobalAlternate, global);
 
-FX_BOOL CJS_Global::InitInstance(IJS_Context* cc) {
-  CJS_Context* pContext = (CJS_Context*)cc;
-  ASSERT(pContext != NULL);
-
-  JSGlobalAlternate* pGlobal = (JSGlobalAlternate*)GetEmbedObject();
-  ASSERT(pGlobal != NULL);
-
-  pGlobal->Initial(pContext->GetReaderApp());
-
-  return TRUE;
-};
+void CJS_Global::InitInstance(IJS_Runtime* pIRuntime) {
+  CJS_Runtime* pRuntime = static_cast<CJS_Runtime*>(pIRuntime);
+  JSGlobalAlternate* pGlobal =
+      static_cast<JSGlobalAlternate*>(GetEmbedObject());
+  pGlobal->Initial(pRuntime->GetReaderApp());
+}
 
 JSGlobalAlternate::JSGlobalAlternate(CJS_Object* pJSObject)
     : CJS_EmbedObj(pJSObject), m_pApp(NULL) {
diff --git a/fpdfsdk/src/javascript/global.h b/fpdfsdk/src/javascript/global.h
index 30f5d07..174e63a 100644
--- a/fpdfsdk/src/javascript/global.h
+++ b/fpdfsdk/src/javascript/global.h
@@ -82,7 +82,7 @@
   ~CJS_Global() override {}
 
   // CJS_Object
-  FX_BOOL InitInstance(IJS_Context* cc) override;
+  void InitInstance(IJS_Runtime* pIRuntime) override;
 
   DECLARE_SPECIAL_JS_CLASS();
   JS_SPECIAL_STATIC_METHOD(setPersistent, JSGlobalAlternate, global);
diff --git a/fpdfsdk/src/jsapi/fxjs_v8.cpp b/fpdfsdk/src/jsapi/fxjs_v8.cpp
index f400efb..1f8c572 100644
--- a/fpdfsdk/src/jsapi/fxjs_v8.cpp
+++ b/fpdfsdk/src/jsapi/fxjs_v8.cpp
@@ -273,8 +273,7 @@
 }
 
 void FXJS_InitializeRuntime(v8::Isolate* pIsolate,
-                            IJS_Runtime* pFXRuntime,
-                            IJS_Context* context,
+                            IJS_Runtime* pIRuntime,
                             v8::Global<v8::Context>& v8PersistentContext) {
   if (pIsolate == g_isolate)
     ++g_isolate_ref_count;
@@ -287,7 +286,7 @@
   v8::Context::Scope context_scope(v8Context);
 
   FXJS_PerIsolateData::SetUp(pIsolate);
-  v8Context->SetAlignedPointerInEmbedderData(kPerContextDataIndex, pFXRuntime);
+  v8Context->SetAlignedPointerInEmbedderData(kPerContextDataIndex, pIRuntime);
 
   int maxID = CFXJS_ObjDefinition::MaxID(pIsolate);
   for (int i = 0; i < maxID; ++i) {
@@ -305,14 +304,13 @@
           .ToLocalChecked()
           ->SetAlignedPointerInInternalField(0, new CFXJS_PrivateData(i));
 
-      if (pObjDef->m_pConstructor) {
-        pObjDef->m_pConstructor(context, v8Context->Global()
-                                             ->GetPrototype()
-                                             ->ToObject(v8Context)
-                                             .ToLocalChecked());
-      }
+      if (pObjDef->m_pConstructor)
+        pObjDef->m_pConstructor(pIRuntime, v8Context->Global()
+                                               ->GetPrototype()
+                                               ->ToObject(v8Context)
+                                               .ToLocalChecked());
     } else if (pObjDef->m_ObjType == FXJSOBJTYPE_STATIC) {
-      v8::Local<v8::Object> obj = FXJS_NewFxDynamicObj(pIsolate, context, i);
+      v8::Local<v8::Object> obj = FXJS_NewFxDynamicObj(pIsolate, pIRuntime, i);
       v8Context->Global()->Set(v8Context, m_ObjName, obj).FromJust();
       pObjDef->m_StaticObj.Reset(pIsolate, obj);
     }
@@ -365,7 +363,6 @@
 int FXJS_Execute(v8::Isolate* pIsolate,
                  IJS_Context* pJSContext,
                  const wchar_t* script,
-                 long length,
                  FXJSErr* pError) {
   v8::Isolate::Scope isolate_scope(pIsolate);
   v8::TryCatch try_catch(pIsolate);
@@ -392,7 +389,7 @@
 }
 
 v8::Local<v8::Object> FXJS_NewFxDynamicObj(v8::Isolate* pIsolate,
-                                           IJS_Context* pJSContext,
+                                           IJS_Runtime* pIRuntime,
                                            int nObjDefnID) {
   v8::Isolate::Scope isolate_scope(pIsolate);
   v8::Local<v8::Context> context = pIsolate->GetCurrentContext();
@@ -419,7 +416,7 @@
 
   obj->SetAlignedPointerInInternalField(0, new CFXJS_PrivateData(nObjDefnID));
   if (pObjDef->m_pConstructor)
-    pObjDef->m_pConstructor(pJSContext, obj);
+    pObjDef->m_pConstructor(pIRuntime, obj);
 
   return obj;
 }
diff --git a/fpdfsdk/src/jsapi/fxjs_v8_embeddertest.cpp b/fpdfsdk/src/jsapi/fxjs_v8_embeddertest.cpp
index fc23247..1c10df7 100644
--- a/fpdfsdk/src/jsapi/fxjs_v8_embeddertest.cpp
+++ b/fpdfsdk/src/jsapi/fxjs_v8_embeddertest.cpp
@@ -33,7 +33,7 @@
     v8::Locker locker(m_pIsolate);
     v8::HandleScope handle_scope(m_pIsolate);
     FXJS_PerIsolateData::SetUp(m_pIsolate);
-    FXJS_InitializeRuntime(m_pIsolate, nullptr, nullptr, m_pPersistentContext);
+    FXJS_InitializeRuntime(m_pIsolate, nullptr, m_pPersistentContext);
   }
 
   void TearDown() override {
@@ -63,7 +63,7 @@
   FXJSErr error;
   CFX_WideString wsInfo;
   CFX_WideString wsScript(kScript);
-  int sts = FXJS_Execute(isolate(), nullptr, kScript, wcslen(kScript), &error);
+  int sts = FXJS_Execute(isolate(), nullptr, kScript, &error);
   EXPECT_EQ(0, sts);
 
   v8::Local<v8::Object> This = FXJS_GetThisObj(isolate());