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