Merge to XFA: Store object definition ID in each js_class.

Manual edits in JS_Define.h.

(cherry picked from commit f0a5b2803c09f3605dcd606e764ef604f0d2a8ea)
Original Review URL: https://codereview.chromium.org/1382263002 .

R=thestig@chromium.org

Review URL: https://codereview.chromium.org/1382683008 .
diff --git a/fpdfsdk/src/javascript/JS_Define.h b/fpdfsdk/src/javascript/JS_Define.h
index 8c00ba5..cb0986d 100644
--- a/fpdfsdk/src/javascript/JS_Define.h
+++ b/fpdfsdk/src/javascript/JS_Define.h
@@ -30,18 +30,17 @@
   v8::FunctionCallback pMethodCall;
 };
 
-/* ====================================== PUBLIC DEFINE SPEC
- * ============================================== */
 #define JS_WIDESTRING(widestring) L## #widestring
-
 #define BEGIN_JS_STATIC_CONST(js_class_name) \
   JSConstSpec js_class_name::JS_Class_Consts[] = {
 #define JS_STATIC_CONST_ENTRY_NUMBER(const_name, pValue) \
   { const_name, pValue, L"", 0 }                         \
   ,
+
 #define JS_STATIC_CONST_ENTRY_STRING(const_name, pValue) \
   { const_name, 0, pValue, 1 }                           \
   ,
+
 #define END_JS_STATIC_CONST() \
   { 0, 0, 0, 0 }              \
   }                           \
@@ -55,6 +54,7 @@
         set_##prop_name##_static                        \
   }                                                     \
   ,
+
 #define END_JS_STATIC_PROP() \
   { 0, 0, 0 }                \
   }                          \
@@ -65,14 +65,12 @@
 #define JS_STATIC_METHOD_ENTRY(method_name)            \
   { JS_WIDESTRING(method_name), method_name##_static } \
   ,
+
 #define END_JS_STATIC_METHOD() \
   { 0, 0 }                     \
   }                            \
   ;
 
-/* ======================================== PROP CALLBACK
- * ============================================ */
-
 template <class C,
           FX_BOOL (C::*M)(IFXJS_Context*, CJS_PropValue&, CFX_WideString&)>
 void JSPropGetter(const char* prop_name_string,
@@ -134,9 +132,6 @@
                                                      property, value, info);  \
   }
 
-/* ========================================= METHOD CALLBACK
- * =========================================== */
-
 template <class C,
           FX_BOOL (C::*M)(IFXJS_Context*,
                           const CJS_Parameters&,
@@ -180,79 +175,175 @@
         #method_name, #class_name, info);                                  \
   }
 
-/* ===================================== JS CLASS
- * =============================================== */
+// All JS classes have a name, an object defintion ID, and the ability to
+// register themselves with FXJS_V8. We never make a BASE class on its own
+// because it can't really do anything.
+#define DECLARE_JS_CLASS_BASE_PART()  \
+  static const wchar_t* g_pClassName; \
+  static int g_nObjDefnID;            \
+  static void DefineJSObjects(v8::Isolate* pIsolate, FXJSOBJTYPE eObjType);
 
-#define DECLARE_JS_CLASS(js_class_name)                                     \
-  static void JSConstructor(IFXJS_Context* cc, v8::Local<v8::Object> obj,   \
-                            v8::Local<v8::Object> global);                  \
-  static void JSDestructor(v8::Local<v8::Object> obj);                      \
-  static void DefineJSObjects(v8::Isolate* pIsolate, FXJSOBJTYPE eObjType); \
-  static JSConstSpec JS_Class_Consts[];                                     \
-  static JSPropertySpec JS_Class_Properties[];                              \
-  static JSMethodSpec JS_Class_Methods[];                                   \
-  static const wchar_t* m_pClassName
+#define IMPLEMENT_JS_CLASS_BASE_PART(js_class_name, class_name)           \
+  const wchar_t* js_class_name::g_pClassName = JS_WIDESTRING(class_name); \
+  int js_class_name::g_nObjDefnID = -1;
 
-#define IMPLEMENT_JS_CLASS_RICH(js_class_name, class_alternate, class_name)  \
-  const wchar_t* js_class_name::m_pClassName = JS_WIDESTRING(class_name);    \
-  void js_class_name::JSConstructor(IFXJS_Context* cc,                       \
-                                    v8::Local<v8::Object> obj,               \
-                                    v8::Local<v8::Object> global) {          \
-    CJS_Object* pObj = new js_class_name(obj);                               \
-    pObj->SetEmbedObject(new class_alternate(pObj));                         \
-    FXJS_SetPrivate(NULL, obj, (void*)pObj);                                 \
-    pObj->InitInstance(cc);                                                  \
-  }                                                                          \
-                                                                             \
-  void js_class_name::JSDestructor(v8::Local<v8::Object> obj) {              \
-    js_class_name* pObj = (js_class_name*)FXJS_GetPrivate(NULL, obj);        \
-    pObj->ExitInstance();                                                    \
-    delete pObj;                                                             \
-  }                                                                          \
-                                                                             \
-  void js_class_name::DefineJSObjects(v8::Isolate* pIsolate,                 \
-                                      FXJSOBJTYPE eObjType) {                \
-    int nObjDefnID = FXJS_DefineObj(pIsolate, js_class_name::m_pClassName,   \
-                                    eObjType, JSConstructor, JSDestructor);  \
-    for (int i = 0; i < FX_ArraySize(JS_Class_Properties) - 1; ++i) {        \
-      FXJS_DefineObjProperty(                                                \
-          pIsolate, nObjDefnID, JS_Class_Properties[i].pName,                \
-          JS_Class_Properties[i].pPropGet, JS_Class_Properties[i].pPropPut); \
-    }                                                                        \
-    for (int i = 0; i < FX_ArraySize(JS_Class_Methods) - 1; ++i) {           \
-      FXJS_DefineObjMethod(pIsolate, nObjDefnID, JS_Class_Methods[i].pName,  \
-                           JS_Class_Methods[i].pMethodCall);                 \
-    }                                                                        \
+// CONST classes provide constants, but not constructors, methods, or props.
+#define DECLARE_JS_CLASS_CONST() \
+  DECLARE_JS_CLASS_BASE_PART()   \
+  DECLARE_JS_CLASS_CONST_PART()
+
+#define IMPLEMENT_JS_CLASS_CONST(js_class_name, class_name)              \
+  IMPLEMENT_JS_CLASS_BASE_PART(js_class_name, class_name)                \
+  IMPLEMENT_JS_CLASS_CONST_PART(js_class_name, class_name)               \
+  void js_class_name::DefineJSObjects(v8::Isolate* pIsolate,             \
+                                      FXJSOBJTYPE eObjType) {            \
+    g_nObjDefnID = FXJS_DefineObj(pIsolate, js_class_name::g_pClassName, \
+                                  eObjType, nullptr, nullptr);           \
+    DefineConsts(pIsolate);                                              \
   }
 
+#define DECLARE_JS_CLASS_CONST_PART()   \
+  static JSConstSpec JS_Class_Consts[]; \
+  static void DefineConsts(v8::Isolate* pIsolate);
+
+#define IMPLEMENT_JS_CLASS_CONST_PART(js_class_name, class_name)      \
+  void js_class_name::DefineConsts(v8::Isolate* pIsolate) {           \
+    for (size_t i = 0; i < FX_ArraySize(JS_Class_Consts) - 1; ++i) {  \
+      FXJS_DefineObjConst(                                            \
+          pIsolate, g_nObjDefnID, JS_Class_Consts[i].pName,           \
+          JS_Class_Consts[i].t == 0                                   \
+              ? FXJS_NewNumber(pIsolate, JS_Class_Consts[i].number)   \
+              : FXJS_NewString(pIsolate, JS_Class_Consts[i].string)); \
+    }                                                                 \
+  }
+
+// Convenience macros for declaring classes without an alternate.
+#define DECLARE_JS_CLASS() DECLARE_JS_CLASS_RICH()
 #define IMPLEMENT_JS_CLASS(js_class_name, class_name) \
   IMPLEMENT_JS_CLASS_RICH(js_class_name, class_name, class_name)
 
-/* ======================================== CONST CLASS
- * ============================================ */
+// Rich JS classes provide constants, methods, properties, and the ability
+// to construct native object state.
+#define DECLARE_JS_CLASS_RICH() \
+  DECLARE_JS_CLASS_BASE_PART()  \
+  DECLARE_JS_CLASS_CONST_PART() \
+  DECLARE_JS_CLASS_RICH_PART()
 
-#define DECLARE_JS_CLASS_CONST()                                            \
-  static void DefineJSObjects(v8::Isolate* pIsolate, FXJSOBJTYPE eObjType); \
-  static JSConstSpec JS_Class_Consts[];                                     \
-  static const wchar_t* m_pClassName
-
-#define IMPLEMENT_JS_CLASS_CONST(js_class_name, class_name)                \
-  const wchar_t* js_class_name::m_pClassName = JS_WIDESTRING(class_name);  \
-  void js_class_name::DefineJSObjects(v8::Isolate* pIsolate,               \
-                                      FXJSOBJTYPE eObjType) {              \
-    int nObjDefnID = FXJS_DefineObj(pIsolate, js_class_name::m_pClassName, \
-                                    eObjType, NULL, NULL);                 \
-    for (int i = 0; i < FX_ArraySize(JS_Class_Consts) - 1; ++i) {          \
-      FXJS_DefineObjConst(                                                 \
-          pIsolate, nObjDefnID, JS_Class_Consts[i].pName,                  \
-          JS_Class_Consts[i].t == 0                                        \
-              ? FXJS_NewNumber(pIsolate, JS_Class_Consts[i].number)        \
-              : FXJS_NewString(pIsolate, JS_Class_Consts[i].string));      \
-    }                                                                      \
+#define IMPLEMENT_JS_CLASS_RICH(js_class_name, class_alternate, class_name) \
+  IMPLEMENT_JS_CLASS_BASE_PART(js_class_name, class_name)                   \
+  IMPLEMENT_JS_CLASS_CONST_PART(js_class_name, class_name)                  \
+  IMPLEMENT_JS_CLASS_RICH_PART(js_class_name, class_alternate, class_name)  \
+  void js_class_name::DefineJSObjects(v8::Isolate* pIsolate,                \
+                                      FXJSOBJTYPE eObjType) {               \
+    g_nObjDefnID = FXJS_DefineObj(pIsolate, js_class_name::g_pClassName,    \
+                                  eObjType, JSConstructor, JSDestructor);   \
+    DefineConsts(pIsolate);                                                 \
+    DefineProps(pIsolate);                                                  \
+    DefineMethods(pIsolate);                                                \
   }
 
-/* ===================================== SPECIAL JS CLASS
- * =============================================== */
+#define DECLARE_JS_CLASS_RICH_PART()                                      \
+  static void JSConstructor(IFXJS_Context* cc, v8::Local<v8::Object> obj, \
+                            v8::Local<v8::Object> global);                \
+  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(IFXJS_Context* cc,                        \
+                                    v8::Local<v8::Object> obj,                \
+                                    v8::Local<v8::Object> global) {           \
+    CJS_Object* pObj = new js_class_name(obj);                                \
+    pObj->SetEmbedObject(new class_alternate(pObj));                          \
+    FXJS_SetPrivate(nullptr, obj, (void*)pObj);                               \
+    pObj->InitInstance(cc);                                                   \
+  }                                                                           \
+  void js_class_name::JSDestructor(v8::Local<v8::Object> obj) {               \
+    js_class_name* pObj = (js_class_name*)FXJS_GetPrivate(nullptr, obj);      \
+    pObj->ExitInstance();                                                     \
+    delete pObj;                                                              \
+  }                                                                           \
+  void js_class_name::DefineProps(v8::Isolate* pIsolate) {                    \
+    for (size_t i = 0; i < FX_ArraySize(JS_Class_Properties) - 1; ++i) {      \
+      FXJS_DefineObjProperty(                                                 \
+          pIsolate, g_nObjDefnID, JS_Class_Properties[i].pName,               \
+          JS_Class_Properties[i].pPropGet, JS_Class_Properties[i].pPropPut);  \
+    }                                                                         \
+  }                                                                           \
+  void js_class_name::DefineMethods(v8::Isolate* pIsolate) {                  \
+    for (size_t i = 0; i < FX_ArraySize(JS_Class_Methods) - 1; ++i) {         \
+      FXJS_DefineObjMethod(pIsolate, g_nObjDefnID, JS_Class_Methods[i].pName, \
+                           JS_Class_Methods[i].pMethodCall);                  \
+    }                                                                         \
+  }
+
+// Special JS classes implement methods, props, and queries, but not consts.
+#define DECLARE_SPECIAL_JS_CLASS() \
+  DECLARE_JS_CLASS_BASE_PART()     \
+  DECLARE_JS_CLASS_CONST_PART()    \
+  DECLARE_JS_CLASS_RICH_PART()     \
+  DECLARE_SPECIAL_JS_CLASS_PART()
+
+#define IMPLEMENT_SPECIAL_JS_CLASS(js_class_name, class_alternate, class_name) \
+  IMPLEMENT_JS_CLASS_BASE_PART(js_class_name, class_name)                      \
+  IMPLEMENT_JS_CLASS_CONST_PART(js_class_name, class_name)                     \
+  IMPLEMENT_JS_CLASS_RICH_PART(js_class_name, class_alternate, class_name)     \
+  IMPLEMENT_SPECIAL_JS_CLASS_PART(js_class_name, class_alternate, class_name)  \
+  void js_class_name::DefineJSObjects(v8::Isolate* pIsolate,                   \
+                                      FXJSOBJTYPE eObjType) {                  \
+    g_nObjDefnID = FXJS_DefineObj(pIsolate, js_class_name::g_pClassName,       \
+                                  eObjType, JSConstructor, JSDestructor);      \
+    DefineConsts(pIsolate);                                                    \
+    DefineProps(pIsolate);                                                     \
+    DefineMethods(pIsolate);                                                   \
+    DefineAllProperties(pIsolate);                                             \
+  }
+
+#define DECLARE_SPECIAL_JS_CLASS_PART()                                        \
+  static void queryprop_static(                                                \
+      v8::Local<v8::String> property,                                          \
+      const v8::PropertyCallbackInfo<v8::Integer>& info);                      \
+  static void getprop_static(v8::Local<v8::String> property,                   \
+                             const v8::PropertyCallbackInfo<v8::Value>& info); \
+  static void putprop_static(v8::Local<v8::String> property,                   \
+                             v8::Local<v8::Value> value,                       \
+                             const v8::PropertyCallbackInfo<v8::Value>& info); \
+  static void delprop_static(                                                  \
+      v8::Local<v8::String> property,                                          \
+      const v8::PropertyCallbackInfo<v8::Boolean>& info);                      \
+  static void DefineAllProperties(v8::Isolate* pIsolate);
+
+#define IMPLEMENT_SPECIAL_JS_CLASS_PART(js_class_name, class_alternate,    \
+                                        class_name)                        \
+  void js_class_name::queryprop_static(                                    \
+      v8::Local<v8::String> property,                                      \
+      const v8::PropertyCallbackInfo<v8::Integer>& info) {                 \
+    JSSpecialPropQuery<class_alternate>(#class_name, property, info);      \
+  }                                                                        \
+  void js_class_name::getprop_static(                                      \
+      v8::Local<v8::String> property,                                      \
+      const v8::PropertyCallbackInfo<v8::Value>& info) {                   \
+    JSSpecialPropGet<class_alternate>(#class_name, property, info);        \
+  }                                                                        \
+  void js_class_name::putprop_static(                                      \
+      v8::Local<v8::String> property, v8::Local<v8::Value> value,          \
+      const v8::PropertyCallbackInfo<v8::Value>& info) {                   \
+    JSSpecialPropPut<class_alternate>(#class_name, property, value, info); \
+  }                                                                        \
+  void js_class_name::delprop_static(                                      \
+      v8::Local<v8::String> property,                                      \
+      const v8::PropertyCallbackInfo<v8::Boolean>& info) {                 \
+    JSSpecialPropDel<class_alternate>(#class_name, property, info);        \
+  }                                                                        \
+  void js_class_name::DefineAllProperties(v8::Isolate* pIsolate) {         \
+    FXJS_DefineObjAllProperties(                                           \
+        pIsolate, g_nObjDefnID, js_class_name::queryprop_static,           \
+        js_class_name::getprop_static, js_class_name::putprop_static,      \
+        js_class_name::delprop_static);                                    \
+  }
 
 template <class Alt>
 void JSSpecialPropQuery(const char*,
@@ -341,93 +432,10 @@
   }
 }
 
-#define DECLARE_SPECIAL_JS_CLASS(js_class_name)                             \
-  static void JSConstructor(IFXJS_Context* cc, v8::Local<v8::Object> obj,   \
-                            v8::Local<v8::Object> global);                  \
-  static void JSDestructor(v8::Local<v8::Object> obj);                      \
-  static JSConstSpec JS_Class_Consts[];                                     \
-  static JSPropertySpec JS_Class_Properties[];                              \
-  static JSMethodSpec JS_Class_Methods[];                                   \
-  static void DefineJSObjects(v8::Isolate* pIsolate, FXJSOBJTYPE eObjType); \
-  static const wchar_t* m_pClassName;                                       \
-  static void queryprop_##js_class_name##_static(                           \
-      v8::Local<v8::String> property,                                       \
-      const v8::PropertyCallbackInfo<v8::Integer>& info);                   \
-  static void getprop_##js_class_name##_static(                             \
-      v8::Local<v8::String> property,                                       \
-      const v8::PropertyCallbackInfo<v8::Value>& info);                     \
-  static void putprop_##js_class_name##_static(                             \
-      v8::Local<v8::String> property, v8::Local<v8::Value> value,           \
-      const v8::PropertyCallbackInfo<v8::Value>& info);                     \
-  static void delprop_##js_class_name##_static(                             \
-      v8::Local<v8::String> property,                                       \
-      const v8::PropertyCallbackInfo<v8::Boolean>& info)
-
-#define IMPLEMENT_SPECIAL_JS_CLASS(js_class_name, class_alternate, class_name) \
-  const wchar_t* js_class_name::m_pClassName = JS_WIDESTRING(class_name);      \
-  void js_class_name::queryprop_##js_class_name##_static(                      \
-      v8::Local<v8::String> property,                                          \
-      const v8::PropertyCallbackInfo<v8::Integer>& info) {                     \
-    JSSpecialPropQuery<class_alternate>(#class_name, property, info);          \
-  }                                                                            \
-  void js_class_name::getprop_##js_class_name##_static(                        \
-      v8::Local<v8::String> property,                                          \
-      const v8::PropertyCallbackInfo<v8::Value>& info) {                       \
-    JSSpecialPropGet<class_alternate>(#class_name, property, info);            \
-  }                                                                            \
-  void js_class_name::putprop_##js_class_name##_static(                        \
-      v8::Local<v8::String> property, v8::Local<v8::Value> value,              \
-      const v8::PropertyCallbackInfo<v8::Value>& info) {                       \
-    JSSpecialPropPut<class_alternate>(#class_name, property, value, info);     \
-  }                                                                            \
-  void js_class_name::delprop_##js_class_name##_static(                        \
-      v8::Local<v8::String> property,                                          \
-      const v8::PropertyCallbackInfo<v8::Boolean>& info) {                     \
-    JSSpecialPropDel<class_alternate>(#class_name, property, info);            \
-  }                                                                            \
-  void js_class_name::JSConstructor(IFXJS_Context* cc,                         \
-                                    v8::Local<v8::Object> obj,                 \
-                                    v8::Local<v8::Object> global) {            \
-    CJS_Object* pObj = new js_class_name(obj);                                 \
-    pObj->SetEmbedObject(new class_alternate(pObj));                           \
-    FXJS_SetPrivate(NULL, obj, (void*)pObj);                                   \
-    pObj->InitInstance(cc);                                                    \
-  }                                                                            \
-                                                                               \
-  void js_class_name::JSDestructor(v8::Local<v8::Object> obj) {                \
-    js_class_name* pObj = (js_class_name*)FXJS_GetPrivate(NULL, obj);          \
-    ASSERT(pObj != NULL);                                                      \
-    pObj->ExitInstance();                                                      \
-    delete pObj;                                                               \
-  }                                                                            \
-                                                                               \
-  void js_class_name::DefineJSObjects(v8::Isolate* pIsolate,                   \
-                                      FXJSOBJTYPE eObjType) {                  \
-    int nObjDefnID = FXJS_DefineObj(pIsolate, js_class_name::m_pClassName,     \
-                                    eObjType, JSConstructor, JSDestructor);    \
-    for (int i = 0; i < FX_ArraySize(JS_Class_Properties) - 1; ++i) {          \
-      FXJS_DefineObjProperty(                                                  \
-          pIsolate, nObjDefnID, JS_Class_Properties[i].pName,                  \
-          JS_Class_Properties[i].pPropGet, JS_Class_Properties[i].pPropPut);   \
-    }                                                                          \
-                                                                               \
-    for (int i = 0; i < FX_ArraySize(JS_Class_Methods) - 1; ++i) {             \
-      FXJS_DefineObjMethod(pIsolate, nObjDefnID, JS_Class_Methods[i].pName,    \
-                           JS_Class_Methods[i].pMethodCall);                   \
-    }                                                                          \
-    FXJS_DefineObjAllProperties(                                               \
-        pIsolate, nObjDefnID,                                                  \
-        js_class_name::queryprop_##js_class_name##_static,                     \
-        js_class_name::getprop_##js_class_name##_static,                       \
-        js_class_name::putprop_##js_class_name##_static,                       \
-        js_class_name::delprop_##js_class_name##_static);                      \
-  }
-
-/* ======================================== GLOBAL METHODS
- * ============================================ */
-
-template <FX_BOOL (
-    *F)(IFXJS_Context*, const CJS_Parameters&, CJS_Value&, CFX_WideString&)>
+template <FX_BOOL (*F)(IFXJS_Context* cc,
+                       const CJS_Parameters& params,
+                       CJS_Value& vRet,
+                       CFX_WideString& sError)>
 void JSGlobalFunc(const char* func_name_string,
                   const v8::FunctionCallbackInfo<v8::Value>& info) {
   v8::Isolate* isolate = info.GetIsolate();
@@ -467,7 +475,7 @@
 
 #define IMPLEMENT_JS_STATIC_GLOBAL_FUN(js_class_name)                        \
   void js_class_name::DefineJSObjects(v8::Isolate* pIsolate) {               \
-    for (int i = 0; i < FX_ArraySize(global_methods) - 1; ++i) {             \
+    for (size_t i = 0; i < FX_ArraySize(global_methods) - 1; ++i) {          \
       FXJS_DefineGlobalMethod(pIsolate,                                      \
                               js_class_name::global_methods[i].pName,        \
                               js_class_name::global_methods[i].pMethodCall); \