Pass IJS_Runtime, not IJS_Context, to native object constructors.

This better separates the two IJS_ classes, with the IJS_Context
taking on its proper role of describing an event. There's no need
for the event details for object creation, so this gets much
cleaner.

Move some JS error reporting code from CJS_Context to CJS_Runtime.
Make InitInstance() and ExitInstance() voids, they always return
TRUE and we never check the result anyways.

R=thestig@chromium.org

Review URL: https://codereview.chromium.org/1389163007 .
diff --git a/fpdfsdk/include/javascript/IJavaScript.h b/fpdfsdk/include/javascript/IJavaScript.h
index bf90210..c4c5d0d 100644
--- a/fpdfsdk/include/javascript/IJavaScript.h
+++ b/fpdfsdk/include/javascript/IJavaScript.h
@@ -16,10 +16,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;
 
@@ -131,6 +132,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);
@@ -142,6 +144,9 @@
   virtual IJS_Context* GetCurrentContext() = 0;
   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;
 
  protected:
   IJS_Runtime() {}
diff --git a/fpdfsdk/include/jsapi/fxjs_v8.h b/fpdfsdk/include/jsapi/fxjs_v8.h
index 651414b..13fbb02 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.
 
 enum FXJSOBJTYPE {
   FXJSOBJTYPE_DYNAMIC = 0,  // Created by native method and returned to JS.
@@ -61,7 +61,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.
@@ -119,8 +119,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);
@@ -130,11 +129,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 3d1a157..874fcc7 100644
--- a/fpdfsdk/src/fsdk_actionhandler.cpp
+++ b/fpdfsdk/src/fsdk_actionhandler.cpp
@@ -148,18 +148,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.
         }
@@ -292,65 +288,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);
@@ -388,20 +332,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);
@@ -601,9 +540,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);
@@ -626,9 +565,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);
@@ -682,9 +621,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 ff71c2b..f6b6b14 100644
--- a/fpdfsdk/src/fsdk_baseform.cpp
+++ b/fpdfsdk/src/fsdk_baseform.cpp
@@ -1418,8 +1418,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");
@@ -1766,7 +1765,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();
@@ -1784,7 +1782,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) {
@@ -1846,7 +1844,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) {
@@ -2144,7 +2142,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 7c1f577..24f55b0 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);
@@ -835,7 +830,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());
@@ -1394,7 +1389,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;
@@ -1403,7 +1397,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;
 
@@ -1446,7 +1440,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;
 
@@ -1642,7 +1636,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 8f68769..4e6fdee 100644
--- a/fpdfsdk/src/javascript/Document.h
+++ b/fpdfsdk/src/javascript/Document.h
@@ -309,7 +309,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 56fc56b..021a3a6 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 b67096d..cfca043 100644
--- a/fpdfsdk/src/javascript/JS_Context.cpp
+++ b/fpdfsdk/src/javascript/JS_Context.cpp
@@ -33,14 +33,14 @@
 }
 
 FX_BOOL CJS_Context::RunScript(const CFX_WideString& script,
-                               CFX_WideString& info) {
+                               CFX_WideString* info) {
   v8::Isolate::Scope isolate_scope(m_pRuntime->GetIsolate());
   v8::HandleScope handle_scope(m_pRuntime->GetIsolate());
   v8::Local<v8::Context> context = m_pRuntime->NewJSContext();
   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;
@@ -49,24 +49,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 cb39841..3e5b797 100644
--- a/fpdfsdk/src/javascript/JS_Define.h
+++ b/fpdfsdk/src/javascript/JS_Define.h
@@ -247,22 +247,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 069edc5..4331476 100644
--- a/fpdfsdk/src/javascript/JS_Runtime.cpp
+++ b/fpdfsdk/src/javascript/JS_Runtime.cpp
@@ -64,7 +64,7 @@
     DefineJSObjects();
 
   CJS_Context* pContext = (CJS_Context*)NewContext();
-  FXJS_InitializeRuntime(GetIsolate(), this, pContext, m_context);
+  FXJS_InitializeRuntime(GetIsolate(), this, m_context);
   ReleaseContext(pContext);
 }
 
@@ -181,6 +181,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 8cbec38..d90891e 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 2c5e625..a7b081f 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;
   }
 
@@ -136,6 +136,12 @@
   }
   CPDFSDK_Document* GetReaderDocument() override { return m_pDoc; }
 
+  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 93a627c..3db1e5b 100644
--- a/fpdfsdk/src/javascript/app.cpp
+++ b/fpdfsdk/src/javascript/app.cpp
@@ -123,7 +123,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);
@@ -402,7 +402,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();
@@ -443,7 +443,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();
@@ -553,14 +553,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 c8510d2..cd0048d 100644
--- a/fpdfsdk/src/javascript/global.cpp
+++ b/fpdfsdk/src/javascript/global.cpp
@@ -87,17 +87,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 e674a3f..8a54475 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;
@@ -286,7 +285,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,12 +304,12 @@
           ->SetAlignedPointerInInternalField(0, new CFXJS_PrivateData(i));
 
       if (pObjDef->m_pConstructor)
-        pObjDef->m_pConstructor(context, v8Context->Global()
-                                             ->GetPrototype()
-                                             ->ToObject(v8Context)
-                                             .ToLocalChecked());
+        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);
     }
@@ -359,7 +358,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);
@@ -386,7 +384,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();
@@ -413,7 +411,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 187d611..b0f3f85 100644
--- a/fpdfsdk/src/jsapi/fxjs_v8_embeddertest.cpp
+++ b/fpdfsdk/src/jsapi/fxjs_v8_embeddertest.cpp
@@ -32,7 +32,7 @@
     v8::Isolate::Scope isolate_scope(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 {
@@ -61,7 +61,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());