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