Remove pointless CPDFSDK_PageView usage in CJS_Object / CJS_EmbedObj.
[pdfium.git] / fpdfsdk / include / javascript / JS_Define.h
1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7 #ifndef FPDFSDK_INCLUDE_JAVASCRIPT_JS_DEFINE_H_
8 #define FPDFSDK_INCLUDE_JAVASCRIPT_JS_DEFINE_H_
9
10 #include "../jsapi/fxjs_v8.h"
11 #include "resource.h"
12 #include "JS_Object.h"
13 #include "JS_Value.h"
14
15 struct JSConstSpec {
16   const wchar_t* pName;
17   double number;
18   const wchar_t* string;
19   uint8_t t;  // 0:double 1:str
20 };
21
22 struct JSPropertySpec {
23   const wchar_t* pName;
24   v8::AccessorGetterCallback pPropGet;
25   v8::AccessorSetterCallback pPropPut;
26 };
27
28 struct JSMethodSpec {
29   const wchar_t* pName;
30   v8::FunctionCallback pMethodCall;
31 };
32
33 /* ====================================== PUBLIC DEFINE SPEC
34  * ============================================== */
35 #define JS_WIDESTRING(widestring) L## #widestring
36
37 #define BEGIN_JS_STATIC_CONST(js_class_name) \
38   JSConstSpec js_class_name::JS_Class_Consts[] = {
39 #define JS_STATIC_CONST_ENTRY_NUMBER(const_name, pValue) \
40   { const_name, pValue, L"", 0 }                         \
41   ,
42 #define JS_STATIC_CONST_ENTRY_STRING(const_name, pValue) \
43   { const_name, 0, pValue, 1 }                           \
44   ,
45 #define END_JS_STATIC_CONST() \
46   { 0, 0, 0, 0 }              \
47   }                           \
48   ;
49
50 #define BEGIN_JS_STATIC_PROP(js_class_name) \
51   JSPropertySpec js_class_name::JS_Class_Properties[] = {
52 #define JS_STATIC_PROP_ENTRY(prop_name)                                          \
53   {                                                                              \
54     JS_WIDESTRING(prop_name), get_##prop_name##_static, set_##prop_name##_static \
55   }                                                                              \
56   ,
57 #define END_JS_STATIC_PROP() \
58   { 0, 0, 0 }                \
59   }                          \
60   ;
61
62 #define BEGIN_JS_STATIC_METHOD(js_class_name) \
63   JSMethodSpec js_class_name::JS_Class_Methods[] = {
64 #define JS_STATIC_METHOD_ENTRY(method_name)            \
65   { JS_WIDESTRING(method_name), method_name##_static } \
66   ,
67 #define END_JS_STATIC_METHOD() \
68   { 0, 0 }                     \
69   }                            \
70   ;
71
72 /* ======================================== PROP CALLBACK
73  * ============================================ */
74
75 template <class C,
76           FX_BOOL (C::*M)(IFXJS_Context* cc,
77                           CJS_PropValue& vp,
78                           CFX_WideString& sError)>
79 void JSPropGetter(const char* prop_name_string,
80                   const char* class_name_string,
81                   v8::Local<v8::String> property,
82                   const v8::PropertyCallbackInfo<v8::Value>& info) {
83   v8::Isolate* isolate = info.GetIsolate();
84   IFXJS_Runtime* pRuntime = FXJS_GetRuntimeFromIsolate(isolate);
85   if (!pRuntime)
86     return;
87   IFXJS_Context* pContext = pRuntime->GetCurrentContext();
88   CJS_Object* pJSObj = (CJS_Object*)FXJS_GetPrivate(isolate, info.Holder());
89   C* pObj = reinterpret_cast<C*>(pJSObj->GetEmbedObject());
90   CFX_WideString sError;
91   CJS_PropValue value(isolate);
92   value.StartGetting();
93   if (!(pObj->*M)(pContext, value, sError)) {
94     FXJS_Error(isolate, JSFormatErrorString(class_name_string, prop_name_string,
95                                             sError));
96     return;
97   }
98   info.GetReturnValue().Set((v8::Local<v8::Value>)value);
99 }
100
101 template <class C,
102           FX_BOOL (C::*M)(IFXJS_Context* cc,
103                           CJS_PropValue& vp,
104                           CFX_WideString& sError)>
105 void JSPropSetter(const char* prop_name_string,
106                   const char* class_name_string,
107                   v8::Local<v8::String> property,
108                   v8::Local<v8::Value> value,
109                   const v8::PropertyCallbackInfo<void>& info) {
110   v8::Isolate* isolate = info.GetIsolate();
111   IFXJS_Runtime* pRuntime = FXJS_GetRuntimeFromIsolate(isolate);
112   if (!pRuntime)
113     return;
114   IFXJS_Context* pContext = pRuntime->GetCurrentContext();
115   CJS_Object* pJSObj = (CJS_Object*)FXJS_GetPrivate(isolate, info.Holder());
116   C* pObj = reinterpret_cast<C*>(pJSObj->GetEmbedObject());
117   CFX_WideString sError;
118   CJS_PropValue propValue(CJS_Value(isolate, value, CJS_Value::VT_unknown));
119   propValue.StartSetting();
120   if (!(pObj->*M)(pContext, propValue, sError)) {
121     FXJS_Error(isolate, JSFormatErrorString(class_name_string, prop_name_string,
122                                             sError));
123   }
124 }
125
126 #define JS_STATIC_PROP(prop_name, class_name)                                 \
127   static void get_##prop_name##_static(                                       \
128       v8::Local<v8::String> property,                                         \
129       const v8::PropertyCallbackInfo<v8::Value>& info) {                      \
130     JSPropGetter<class_name, &class_name::prop_name>(#prop_name, #class_name, \
131                                                      property, info);         \
132   }                                                                           \
133   static void set_##prop_name##_static(                                       \
134       v8::Local<v8::String> property, v8::Local<v8::Value> value,             \
135       const v8::PropertyCallbackInfo<void>& info) {                           \
136     JSPropSetter<class_name, &class_name::prop_name>(#prop_name, #class_name, \
137                                                      property, value, info);  \
138   }
139
140 /* ========================================= METHOD CALLBACK
141  * =========================================== */
142
143 template <class C,
144           FX_BOOL (C::*M)(IFXJS_Context* cc,
145                           const CJS_Parameters& params,
146                           CJS_Value& vRet,
147                           CFX_WideString& sError)>
148 void JSMethod(const char* method_name_string,
149               const char* class_name_string,
150               const v8::FunctionCallbackInfo<v8::Value>& info) {
151   v8::Isolate* isolate = info.GetIsolate();
152   IFXJS_Runtime* pRuntime = FXJS_GetRuntimeFromIsolate(isolate);
153   if (!pRuntime)
154     return;
155   IFXJS_Context* cc = pRuntime->GetCurrentContext();
156   CJS_Parameters parameters;
157   for (unsigned int i = 0; i < (unsigned int)info.Length(); i++) {
158     parameters.push_back(CJS_Value(isolate, info[i], CJS_Value::VT_unknown));
159   }
160   CJS_Value valueRes(isolate);
161   CJS_Object* pJSObj = (CJS_Object*)FXJS_GetPrivate(isolate, info.Holder());
162   C* pObj = reinterpret_cast<C*>(pJSObj->GetEmbedObject());
163   CFX_WideString sError;
164   if (!(pObj->*M)(cc, parameters, valueRes, sError)) {
165     FXJS_Error(isolate, JSFormatErrorString(class_name_string,
166                                             method_name_string, sError));
167     return;
168   }
169   info.GetReturnValue().Set(valueRes.ToV8Value());
170 }
171
172 #define JS_STATIC_METHOD(method_name, class_name)                             \
173   static void method_name##_static(                                           \
174       const v8::FunctionCallbackInfo<v8::Value>& info) {                      \
175     JSMethod<class_name, &class_name::method_name>(#method_name, #class_name, \
176                                                    info);                     \
177   }
178
179 #define JS_SPECIAL_STATIC_METHOD(method_name, class_alternate, class_name) \
180   static void method_name##_static(                                        \
181       const v8::FunctionCallbackInfo<v8::Value>& info) {                   \
182     JSMethod<class_alternate, &class_alternate::method_name>(              \
183         #method_name, #class_name, info);                                  \
184   }
185
186 /* ===================================== JS CLASS
187  * =============================================== */
188
189 #define DECLARE_JS_CLASS(js_class_name)                                     \
190   static void JSConstructor(IFXJS_Context* cc, v8::Local<v8::Object> obj,   \
191                             v8::Local<v8::Object> global);                  \
192   static void JSDestructor(v8::Local<v8::Object> obj);                      \
193   static void DefineJSObjects(v8::Isolate* pIsolate, FXJSOBJTYPE eObjType); \
194   static JSConstSpec JS_Class_Consts[];                                     \
195   static JSPropertySpec JS_Class_Properties[];                              \
196   static JSMethodSpec JS_Class_Methods[];                                   \
197   static const wchar_t* m_pClassName
198
199 #define IMPLEMENT_JS_CLASS_RICH(js_class_name, class_alternate, class_name)  \
200   const wchar_t* js_class_name::m_pClassName = JS_WIDESTRING(class_name);    \
201   void js_class_name::JSConstructor(IFXJS_Context* cc,                       \
202                                     v8::Local<v8::Object> obj,               \
203                                     v8::Local<v8::Object> global) {          \
204     CJS_Object* pObj = new js_class_name(obj);                               \
205     pObj->SetEmbedObject(new class_alternate(pObj));                         \
206     FXJS_SetPrivate(NULL, obj, (void*)pObj);                                 \
207     pObj->InitInstance(cc);                                                  \
208   }                                                                          \
209                                                                              \
210   void js_class_name::JSDestructor(v8::Local<v8::Object> obj) {              \
211     js_class_name* pObj = (js_class_name*)FXJS_GetPrivate(NULL, obj);        \
212     pObj->ExitInstance();                                                    \
213     delete pObj;                                                             \
214   }                                                                          \
215                                                                              \
216   void js_class_name::DefineJSObjects(v8::Isolate* pIsolate,                 \
217                                       FXJSOBJTYPE eObjType) {                \
218     int nObjDefnID = FXJS_DefineObj(pIsolate, js_class_name::m_pClassName,   \
219                                     eObjType, JSConstructor, JSDestructor);  \
220     for (int i = 0; i < FX_ArraySize(JS_Class_Properties) - 1; ++i) {        \
221       FXJS_DefineObjProperty(                                                \
222           pIsolate, nObjDefnID, JS_Class_Properties[i].pName,                \
223           JS_Class_Properties[i].pPropGet, JS_Class_Properties[i].pPropPut); \
224     }                                                                        \
225     for (int i = 0; i < FX_ArraySize(JS_Class_Methods) - 1; ++i) {           \
226       FXJS_DefineObjMethod(pIsolate, nObjDefnID, JS_Class_Methods[i].pName,  \
227                            JS_Class_Methods[i].pMethodCall);                 \
228     }                                                                        \
229   }
230
231 #define IMPLEMENT_JS_CLASS(js_class_name, class_name) \
232   IMPLEMENT_JS_CLASS_RICH(js_class_name, class_name, class_name)
233
234 /* ======================================== CONST CLASS
235  * ============================================ */
236
237 #define DECLARE_JS_CLASS_CONST()                                            \
238   static void DefineJSObjects(v8::Isolate* pIsolate, FXJSOBJTYPE eObjType); \
239   static JSConstSpec JS_Class_Consts[];                                     \
240   static const wchar_t* m_pClassName
241
242 #define IMPLEMENT_JS_CLASS_CONST(js_class_name, class_name)                \
243   const wchar_t* js_class_name::m_pClassName = JS_WIDESTRING(class_name);  \
244   void js_class_name::DefineJSObjects(v8::Isolate* pIsolate,               \
245                                       FXJSOBJTYPE eObjType) {              \
246     int nObjDefnID = FXJS_DefineObj(pIsolate, js_class_name::m_pClassName, \
247                                     eObjType, NULL, NULL);                 \
248     for (int i = 0; i < FX_ArraySize(JS_Class_Consts) - 1; ++i) {          \
249       FXJS_DefineObjConst(                                                 \
250           pIsolate, nObjDefnID, JS_Class_Consts[i].pName,                  \
251           JS_Class_Consts[i].t == 0                                        \
252               ? FXJS_NewNumber(pIsolate, JS_Class_Consts[i].number)        \
253               : FXJS_NewString(pIsolate, JS_Class_Consts[i].string));      \
254     }                                                                      \
255   }
256
257 /* ===================================== SPECIAL JS CLASS
258  * =============================================== */
259
260 template <class Alt>
261 void JSSpecialPropQuery(const char*,
262                         v8::Local<v8::String> property,
263                         const v8::PropertyCallbackInfo<v8::Integer>& info) {
264   v8::Isolate* isolate = info.GetIsolate();
265   v8::String::Utf8Value utf8_value(property);
266   CFX_WideString propname =
267       CFX_WideString::FromUTF8(*utf8_value, utf8_value.length());
268   CJS_Object* pJSObj =
269       reinterpret_cast<CJS_Object*>(FXJS_GetPrivate(isolate, info.Holder()));
270   Alt* pObj = reinterpret_cast<Alt*>(pJSObj->GetEmbedObject());
271   FX_BOOL bRet = pObj->QueryProperty(propname.c_str());
272   info.GetReturnValue().Set(bRet ? 4 : 0);
273 }
274
275 template <class Alt>
276 void JSSpecialPropGet(const char* class_name,
277                       v8::Local<v8::String> property,
278                       const v8::PropertyCallbackInfo<v8::Value>& info) {
279   v8::Isolate* isolate = info.GetIsolate();
280   IFXJS_Runtime* pRuntime = FXJS_GetRuntimeFromIsolate(isolate);
281   if (!pRuntime)
282     return;
283   IFXJS_Context* pRuntimeContext = pRuntime->GetCurrentContext();
284   CJS_Object* pJSObj =
285       reinterpret_cast<CJS_Object*>(FXJS_GetPrivate(isolate, info.Holder()));
286   Alt* pObj = reinterpret_cast<Alt*>(pJSObj->GetEmbedObject());
287   v8::String::Utf8Value utf8_value(property);
288   CFX_WideString propname =
289       CFX_WideString::FromUTF8(*utf8_value, utf8_value.length());
290   CFX_WideString sError;
291   CJS_PropValue value(isolate);
292   value.StartGetting();
293   if (!pObj->DoProperty(pRuntimeContext, propname.c_str(), value, sError)) {
294     FXJS_Error(isolate, JSFormatErrorString(class_name, "GetProperty", sError));
295     return;
296   }
297   info.GetReturnValue().Set((v8::Local<v8::Value>)value);
298 }
299
300 template <class Alt>
301 void JSSpecialPropPut(const char* class_name,
302                       v8::Local<v8::String> property,
303                       v8::Local<v8::Value> value,
304                       const v8::PropertyCallbackInfo<v8::Value>& info) {
305   v8::Isolate* isolate = info.GetIsolate();
306   IFXJS_Runtime* pRuntime = FXJS_GetRuntimeFromIsolate(isolate);
307   if (!pRuntime)
308     return;
309   IFXJS_Context* pRuntimeContext = pRuntime->GetCurrentContext();
310   CJS_Object* pJSObj =
311       reinterpret_cast<CJS_Object*>(FXJS_GetPrivate(isolate, info.Holder()));
312   Alt* pObj = reinterpret_cast<Alt*>(pJSObj->GetEmbedObject());
313   v8::String::Utf8Value utf8_value(property);
314   CFX_WideString propname =
315       CFX_WideString::FromUTF8(*utf8_value, utf8_value.length());
316   CFX_WideString sError;
317   CJS_PropValue PropValue(CJS_Value(isolate, value, CJS_Value::VT_unknown));
318   PropValue.StartSetting();
319   if (!pObj->DoProperty(pRuntimeContext, propname.c_str(), PropValue, sError)) {
320     FXJS_Error(isolate, JSFormatErrorString(class_name, "PutProperty", sError));
321   }
322 }
323
324 template <class Alt>
325 void JSSpecialPropDel(const char* class_name,
326                       v8::Local<v8::String> property,
327                       const v8::PropertyCallbackInfo<v8::Boolean>& info) {
328   v8::Isolate* isolate = info.GetIsolate();
329   IFXJS_Runtime* pRuntime = FXJS_GetRuntimeFromIsolate(isolate);
330   if (!pRuntime)
331     return;
332   IFXJS_Context* pRuntimeContext = pRuntime->GetCurrentContext();
333   CJS_Object* pJSObj =
334       reinterpret_cast<CJS_Object*>(FXJS_GetPrivate(isolate, info.Holder()));
335   Alt* pObj = reinterpret_cast<Alt*>(pJSObj->GetEmbedObject());
336   v8::String::Utf8Value utf8_value(property);
337   CFX_WideString propname =
338       CFX_WideString::FromUTF8(*utf8_value, utf8_value.length());
339   CFX_WideString sError;
340   if (!pObj->DelProperty(pRuntimeContext, propname.c_str(), sError)) {
341     CFX_ByteString cbName;
342     cbName.Format("%s.%s", class_name, "DelProperty");
343     // Probably a missing call to JSFX_Error().
344   }
345 }
346
347 #define DECLARE_SPECIAL_JS_CLASS(js_class_name)                             \
348   static void JSConstructor(IFXJS_Context* cc, v8::Local<v8::Object> obj,   \
349                             v8::Local<v8::Object> global);                  \
350   static void JSDestructor(v8::Local<v8::Object> obj);                      \
351   static JSConstSpec JS_Class_Consts[];                                     \
352   static JSPropertySpec JS_Class_Properties[];                              \
353   static JSMethodSpec JS_Class_Methods[];                                   \
354   static void DefineJSObjects(v8::Isolate* pIsolate, FXJSOBJTYPE eObjType); \
355   static const wchar_t* m_pClassName;                                       \
356   static void queryprop_##js_class_name##_static(                           \
357       v8::Local<v8::String> property,                                       \
358       const v8::PropertyCallbackInfo<v8::Integer>& info);                   \
359   static void getprop_##js_class_name##_static(                             \
360       v8::Local<v8::String> property,                                       \
361       const v8::PropertyCallbackInfo<v8::Value>& info);                     \
362   static void putprop_##js_class_name##_static(                             \
363       v8::Local<v8::String> property, v8::Local<v8::Value> value,           \
364       const v8::PropertyCallbackInfo<v8::Value>& info);                     \
365   static void delprop_##js_class_name##_static(                             \
366       v8::Local<v8::String> property,                                       \
367       const v8::PropertyCallbackInfo<v8::Boolean>& info)
368
369 #define IMPLEMENT_SPECIAL_JS_CLASS(js_class_name, class_alternate, class_name) \
370   const wchar_t* js_class_name::m_pClassName = JS_WIDESTRING(class_name);      \
371   void js_class_name::queryprop_##js_class_name##_static(                      \
372       v8::Local<v8::String> property,                                          \
373       const v8::PropertyCallbackInfo<v8::Integer>& info) {                     \
374     JSSpecialPropQuery<class_alternate>(#class_name, property, info);          \
375   }                                                                            \
376   void js_class_name::getprop_##js_class_name##_static(                        \
377       v8::Local<v8::String> property,                                          \
378       const v8::PropertyCallbackInfo<v8::Value>& info) {                       \
379     JSSpecialPropGet<class_alternate>(#class_name, property, info);            \
380   }                                                                            \
381   void js_class_name::putprop_##js_class_name##_static(                        \
382       v8::Local<v8::String> property, v8::Local<v8::Value> value,              \
383       const v8::PropertyCallbackInfo<v8::Value>& info) {                       \
384     JSSpecialPropPut<class_alternate>(#class_name, property, value, info);     \
385   }                                                                            \
386   void js_class_name::delprop_##js_class_name##_static(                        \
387       v8::Local<v8::String> property,                                          \
388       const v8::PropertyCallbackInfo<v8::Boolean>& info) {                     \
389     JSSpecialPropDel<class_alternate>(#class_name, property, info);            \
390   }                                                                            \
391   void js_class_name::JSConstructor(IFXJS_Context* cc,                         \
392                                     v8::Local<v8::Object> obj,                 \
393                                     v8::Local<v8::Object> global) {            \
394     CJS_Object* pObj = new js_class_name(obj);                                 \
395     pObj->SetEmbedObject(new class_alternate(pObj));                           \
396     FXJS_SetPrivate(NULL, obj, (void*)pObj);                                   \
397     pObj->InitInstance(cc);                                                    \
398   }                                                                            \
399                                                                                \
400   void js_class_name::JSDestructor(v8::Local<v8::Object> obj) {                \
401     js_class_name* pObj = (js_class_name*)FXJS_GetPrivate(NULL, obj);          \
402     ASSERT(pObj != NULL);                                                      \
403     pObj->ExitInstance();                                                      \
404     delete pObj;                                                               \
405   }                                                                            \
406                                                                                \
407   void js_class_name::DefineJSObjects(v8::Isolate* pIsolate,                   \
408                                       FXJSOBJTYPE eObjType) {                  \
409     int nObjDefnID = FXJS_DefineObj(pIsolate, js_class_name::m_pClassName,     \
410                                     eObjType, JSConstructor, JSDestructor);    \
411     for (int i = 0; i < FX_ArraySize(JS_Class_Properties) - 1; ++i) {          \
412       FXJS_DefineObjProperty(                                                  \
413           pIsolate, nObjDefnID, JS_Class_Properties[i].pName,                  \
414           JS_Class_Properties[i].pPropGet, JS_Class_Properties[i].pPropPut);   \
415     }                                                                          \
416                                                                                \
417     for (int i = 0; i < FX_ArraySize(JS_Class_Methods) - 1; ++i) {             \
418       FXJS_DefineObjMethod(pIsolate, nObjDefnID, JS_Class_Methods[i].pName,    \
419                            JS_Class_Methods[i].pMethodCall);                   \
420     }                                                                          \
421     FXJS_DefineObjAllProperties(                                               \
422         pIsolate, nObjDefnID,                                                  \
423         js_class_name::queryprop_##js_class_name##_static,                     \
424         js_class_name::getprop_##js_class_name##_static,                       \
425         js_class_name::putprop_##js_class_name##_static,                       \
426         js_class_name::delprop_##js_class_name##_static);                      \
427   }
428
429 /* ======================================== GLOBAL METHODS
430  * ============================================ */
431
432 template <FX_BOOL (*F)(IFXJS_Context* cc,
433                        const CJS_Parameters& params,
434                        CJS_Value& vRet,
435                        CFX_WideString& sError)>
436 void JSGlobalFunc(const char* func_name_string,
437                   const v8::FunctionCallbackInfo<v8::Value>& info) {
438   v8::Isolate* isolate = info.GetIsolate();
439   IFXJS_Runtime* pRuntime = FXJS_GetRuntimeFromIsolate(isolate);
440   if (!pRuntime)
441     return;
442   IFXJS_Context* cc = pRuntime->GetCurrentContext();
443   CJS_Parameters parameters;
444   for (unsigned int i = 0; i < (unsigned int)info.Length(); i++) {
445     parameters.push_back(CJS_Value(isolate, info[i], CJS_Value::VT_unknown));
446   }
447   CJS_Value valueRes(isolate);
448   CFX_WideString sError;
449   if (!(*F)(cc, parameters, valueRes, sError)) {
450     FXJS_Error(isolate, JSFormatErrorString(func_name_string, nullptr, sError));
451     return;
452   }
453   info.GetReturnValue().Set(valueRes.ToV8Value());
454 }
455
456 #define JS_STATIC_GLOBAL_FUN(fun_name)                   \
457   static void fun_name##_static(                         \
458       const v8::FunctionCallbackInfo<v8::Value>& info) { \
459     JSGlobalFunc<fun_name>(#fun_name, info);             \
460   }
461
462 #define JS_STATIC_DECLARE_GLOBAL_FUN()  \
463   static JSMethodSpec global_methods[]; \
464   static void DefineJSObjects(v8::Isolate* pIsolate)
465
466 #define BEGIN_JS_STATIC_GLOBAL_FUN(js_class_name) \
467   JSMethodSpec js_class_name::global_methods[] = {
468 #define JS_STATIC_GLOBAL_FUN_ENTRY(method_name) \
469   JS_STATIC_METHOD_ENTRY(method_name)
470
471 #define END_JS_STATIC_GLOBAL_FUN() END_JS_STATIC_METHOD()
472
473 #define IMPLEMENT_JS_STATIC_GLOBAL_FUN(js_class_name)                        \
474   void js_class_name::DefineJSObjects(v8::Isolate* pIsolate) {               \
475     for (int i = 0; i < FX_ArraySize(global_methods) - 1; ++i) {             \
476       FXJS_DefineGlobalMethod(pIsolate,                                      \
477                               js_class_name::global_methods[i].pName,        \
478                               js_class_name::global_methods[i].pMethodCall); \
479     }                                                                        \
480   }
481
482 CJS_Value::Type GET_VALUE_TYPE(v8::Local<v8::Value> p);
483
484 #endif  // FPDFSDK_INCLUDE_JAVASCRIPT_JS_DEFINE_H_