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