db4b1c360d61965096b74d054157c6a3097714b4
[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, JSFXObject obj,  \
194                             JSFXObject global);                 \
195   static void JSDestructor(JSFXObject obj);                     \
196   static int Init(IJS_Runtime* pRuntime, 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, JSFXObject obj,         \
205                                     JSFXObject global) {                       \
206     CJS_Object* pObj = new js_class_name(obj);                                 \
207     pObj->SetEmbedObject(new class_alternate(pObj));                           \
208     JS_SetPrivate(NULL, obj, (void*)pObj);                                     \
209     pObj->InitInstance(cc);                                                    \
210   }                                                                            \
211                                                                                \
212   void js_class_name::JSDestructor(JSFXObject obj) {                           \
213     js_class_name* pObj = (js_class_name*)JS_GetPrivate(NULL, obj);            \
214     ASSERT(pObj != NULL);                                                      \
215     pObj->ExitInstance();                                                      \
216     delete pObj;                                                               \
217   }                                                                            \
218                                                                                \
219   int js_class_name::Init(IJS_Runtime* pRuntime, FXJSOBJTYPE eObjType) {       \
220     int nObjDefnID = JS_DefineObj(pRuntime, js_class_name::m_pClassName,       \
221                                   eObjType, JSConstructor, JSDestructor);      \
222     if (nObjDefnID >= 0) {                                                     \
223       for (int j = 0,                                                          \
224                szj = sizeof(JS_Class_Properties) / sizeof(JSPropertySpec) - 1; \
225            j < szj; j++) {                                                     \
226         if (JS_DefineObjProperty(pRuntime, nObjDefnID,                         \
227                                  JS_Class_Properties[j].pName,                 \
228                                  JS_Class_Properties[j].pPropGet,              \
229                                  JS_Class_Properties[j].pPropPut) < 0)         \
230           return -1;                                                           \
231       }                                                                        \
232       for (int k = 0,                                                          \
233                szk = sizeof(JS_Class_Methods) / sizeof(JSMethodSpec) - 1;      \
234            k < szk; k++) {                                                     \
235         if (JS_DefineObjMethod(pRuntime, nObjDefnID,                           \
236                                JS_Class_Methods[k].pName,                      \
237                                JS_Class_Methods[k].pMethodCall) < 0)           \
238           return -1;                                                           \
239       }                                                                        \
240       return nObjDefnID;                                                       \
241     }                                                                          \
242     return -1;                                                                 \
243   }
244
245 #define IMPLEMENT_JS_CLASS(js_class_name, class_name) \
246   IMPLEMENT_JS_CLASS_RICH(js_class_name, class_name, class_name)
247
248 /* ======================================== CONST CLASS
249  * ============================================ */
250
251 #define DECLARE_JS_CLASS_CONST()                                \
252   static int Init(IJS_Runtime* pRuntime, FXJSOBJTYPE eObjType); \
253   static JSConstSpec JS_Class_Consts[];                         \
254   static const wchar_t* m_pClassName
255
256 #define IMPLEMENT_JS_CLASS_CONST(js_class_name, class_name)                   \
257   const wchar_t* js_class_name::m_pClassName = JS_WIDESTRING(class_name);     \
258   int js_class_name::Init(IJS_Runtime* pRuntime, FXJSOBJTYPE eObjType) {      \
259     int nObjDefnID = JS_DefineObj(pRuntime, js_class_name::m_pClassName,      \
260                                   eObjType, NULL, NULL);                      \
261     if (nObjDefnID >= 0) {                                                    \
262       for (int i = 0, sz = sizeof(JS_Class_Consts) / sizeof(JSConstSpec) - 1; \
263            i < sz; i++) {                                                     \
264         if (JS_Class_Consts[i].t == 0) {                                      \
265           if (JS_DefineObjConst(                                              \
266                   pRuntime, nObjDefnID, JS_Class_Consts[i].pName,             \
267                   JS_NewNumber(pRuntime, JS_Class_Consts[i].number)) < 0)     \
268             return -1;                                                        \
269         } else {                                                              \
270           if (JS_DefineObjConst(                                              \
271                   pRuntime, nObjDefnID, JS_Class_Consts[i].pName,             \
272                   JS_NewString(pRuntime, JS_Class_Consts[i].string)) < 0)     \
273             return -1;                                                        \
274         }                                                                     \
275       }                                                                       \
276       return nObjDefnID;                                                      \
277     }                                                                         \
278     return -1;                                                                \
279   }
280
281 /* ===================================== SPECIAL JS CLASS
282  * =============================================== */
283
284 template <class Alt>
285 void JSSpecialPropQuery(const char*,
286                         v8::Local<v8::String> property,
287                         const v8::PropertyCallbackInfo<v8::Integer>& info) {
288   v8::Isolate* isolate = info.GetIsolate();
289   v8::String::Utf8Value utf8_value(property);
290   CFX_WideString propname =
291       CFX_WideString::FromUTF8(*utf8_value, utf8_value.length());
292   CJS_Object* pJSObj =
293       reinterpret_cast<CJS_Object*>(JS_GetPrivate(isolate, info.Holder()));
294   Alt* pObj = reinterpret_cast<Alt*>(pJSObj->GetEmbedObject());
295   FX_BOOL bRet = pObj->QueryProperty(propname.c_str());
296   info.GetReturnValue().Set(bRet ? 4 : 0);
297 }
298
299 template <class Alt>
300 void JSSpecialPropGet(const char* class_name,
301                       v8::Local<v8::String> property,
302                       const v8::PropertyCallbackInfo<v8::Value>& info) {
303   v8::Isolate* isolate = info.GetIsolate();
304   v8::Local<v8::Context> context = isolate->GetCurrentContext();
305   v8::Local<v8::Value> v = context->GetEmbedderData(1);
306   v8::Local<v8::External> field = v8::Local<v8::External>::Cast(v);
307   IFXJS_Runtime* pRuntime = (IFXJS_Runtime*)field->Value();
308   IFXJS_Context* pRuntimeContext = pRuntime->GetCurrentContext();
309   CJS_Object* pJSObj =
310       reinterpret_cast<CJS_Object*>(JS_GetPrivate(isolate, info.Holder()));
311   Alt* pObj = reinterpret_cast<Alt*>(pJSObj->GetEmbedObject());
312   v8::String::Utf8Value utf8_value(property);
313   CFX_WideString propname =
314       CFX_WideString::FromUTF8(*utf8_value, utf8_value.length());
315   CFX_WideString sError;
316   CJS_PropValue value(isolate);
317   value.StartGetting();
318   if (!pObj->DoProperty(pRuntimeContext, propname.c_str(), value, sError)) {
319     JS_Error(isolate, JSFormatErrorString(class_name, "GetProperty", sError));
320     return;
321   }
322   info.GetReturnValue().Set((v8::Local<v8::Value>)value);
323 }
324
325 template <class Alt>
326 void JSSpecialPropPut(const char* class_name,
327                       v8::Local<v8::String> property,
328                       v8::Local<v8::Value> value,
329                       const v8::PropertyCallbackInfo<v8::Value>& info) {
330   v8::Isolate* isolate = info.GetIsolate();
331   v8::Local<v8::Context> context = isolate->GetCurrentContext();
332   v8::Local<v8::Value> v = context->GetEmbedderData(1);
333   v8::Local<v8::External> field = v8::Local<v8::External>::Cast(v);
334   IFXJS_Runtime* pRuntime = (IFXJS_Runtime*)field->Value();
335   IFXJS_Context* pRuntimeContext = pRuntime->GetCurrentContext();
336   CJS_Object* pJSObj =
337       reinterpret_cast<CJS_Object*>(JS_GetPrivate(isolate, info.Holder()));
338   Alt* pObj = reinterpret_cast<Alt*>(pJSObj->GetEmbedObject());
339   v8::String::Utf8Value utf8_value(property);
340   CFX_WideString propname =
341       CFX_WideString::FromUTF8(*utf8_value, utf8_value.length());
342   CFX_WideString sError;
343   CJS_PropValue PropValue(CJS_Value(isolate, value, VT_unknown));
344   PropValue.StartSetting();
345   if (!pObj->DoProperty(pRuntimeContext, propname.c_str(), PropValue, sError)) {
346     JS_Error(isolate, JSFormatErrorString(class_name, "PutProperty", sError));
347   }
348 }
349
350 template <class Alt>
351 void JSSpecialPropDel(const char* class_name,
352                       v8::Local<v8::String> property,
353                       const v8::PropertyCallbackInfo<v8::Boolean>& info) {
354   v8::Isolate* isolate = info.GetIsolate();
355   v8::Local<v8::Context> context = isolate->GetCurrentContext();
356   v8::Local<v8::Value> v = context->GetEmbedderData(1);
357   v8::Local<v8::External> field = v8::Local<v8::External>::Cast(v);
358   IFXJS_Runtime* pRuntime = (IFXJS_Runtime*)field->Value();
359   IFXJS_Context* pRuntimeContext = pRuntime->GetCurrentContext();
360   CJS_Object* pJSObj =
361       reinterpret_cast<CJS_Object*>(JS_GetPrivate(isolate, info.Holder()));
362   Alt* pObj = reinterpret_cast<Alt*>(pJSObj->GetEmbedObject());
363   v8::String::Utf8Value utf8_value(property);
364   CFX_WideString propname =
365       CFX_WideString::FromUTF8(*utf8_value, utf8_value.length());
366   CFX_WideString sError;
367   if (!pObj->DelProperty(pRuntimeContext, propname.c_str(), sError)) {
368     CFX_ByteString cbName;
369     cbName.Format("%s.%s", class_name, "DelProperty");
370     // Probably a missing call to JS_Error().
371   }
372 }
373
374 #define DECLARE_SPECIAL_JS_CLASS(js_class_name)                   \
375   static void JSConstructor(IFXJS_Context* cc, JSFXObject obj,    \
376                             JSFXObject global);                   \
377   static void JSDestructor(JSFXObject obj);                       \
378   static JSConstSpec JS_Class_Consts[];                           \
379   static JSPropertySpec JS_Class_Properties[];                    \
380   static JSMethodSpec JS_Class_Methods[];                         \
381   static int Init(IJS_Runtime* pRuntime, FXJSOBJTYPE eObjType);   \
382   static const wchar_t* m_pClassName;                             \
383   static void queryprop_##js_class_name##_static(                 \
384       v8::Local<v8::String> property,                             \
385       const v8::PropertyCallbackInfo<v8::Integer>& info);         \
386   static void getprop_##js_class_name##_static(                   \
387       v8::Local<v8::String> property,                             \
388       const v8::PropertyCallbackInfo<v8::Value>& info);           \
389   static void putprop_##js_class_name##_static(                   \
390       v8::Local<v8::String> property, v8::Local<v8::Value> value, \
391       const v8::PropertyCallbackInfo<v8::Value>& info);           \
392   static void delprop_##js_class_name##_static(                   \
393       v8::Local<v8::String> property,                             \
394       const v8::PropertyCallbackInfo<v8::Boolean>& info)
395
396 #define IMPLEMENT_SPECIAL_JS_CLASS(js_class_name, class_alternate, class_name) \
397   const wchar_t* js_class_name::m_pClassName = JS_WIDESTRING(class_name);      \
398   void js_class_name::queryprop_##js_class_name##_static(                      \
399       v8::Local<v8::String> property,                                          \
400       const v8::PropertyCallbackInfo<v8::Integer>& info) {                     \
401     JSSpecialPropQuery<class_alternate>(#class_name, property, info);          \
402   }                                                                            \
403   void js_class_name::getprop_##js_class_name##_static(                        \
404       v8::Local<v8::String> property,                                          \
405       const v8::PropertyCallbackInfo<v8::Value>& info) {                       \
406     JSSpecialPropGet<class_alternate>(#class_name, property, info);            \
407   }                                                                            \
408   void js_class_name::putprop_##js_class_name##_static(                        \
409       v8::Local<v8::String> property, v8::Local<v8::Value> value,              \
410       const v8::PropertyCallbackInfo<v8::Value>& info) {                       \
411     JSSpecialPropPut<class_alternate>(#class_name, property, value, info);     \
412   }                                                                            \
413   void js_class_name::delprop_##js_class_name##_static(                        \
414       v8::Local<v8::String> property,                                          \
415       const v8::PropertyCallbackInfo<v8::Boolean>& info) {                     \
416     JSSpecialPropDel<class_alternate>(#class_name, property, info);            \
417   }                                                                            \
418   void js_class_name::JSConstructor(IFXJS_Context* cc, JSFXObject obj,         \
419                                     JSFXObject global) {                       \
420     CJS_Object* pObj = new js_class_name(obj);                                 \
421     pObj->SetEmbedObject(new class_alternate(pObj));                           \
422     JS_SetPrivate(NULL, obj, (void*)pObj);                                     \
423     pObj->InitInstance(cc);                                                    \
424   }                                                                            \
425                                                                                \
426   void js_class_name::JSDestructor(JSFXObject obj) {                           \
427     js_class_name* pObj = (js_class_name*)JS_GetPrivate(NULL, obj);            \
428     ASSERT(pObj != NULL);                                                      \
429     pObj->ExitInstance();                                                      \
430     delete pObj;                                                               \
431   }                                                                            \
432                                                                                \
433   int js_class_name::Init(IJS_Runtime* pRuntime, FXJSOBJTYPE eObjType) {       \
434     int nObjDefnID = JS_DefineObj(pRuntime, js_class_name::m_pClassName,       \
435                                   eObjType, JSConstructor, JSDestructor);      \
436                                                                                \
437     if (nObjDefnID >= 0) {                                                     \
438       for (int j = 0,                                                          \
439                szj = sizeof(JS_Class_Properties) / sizeof(JSPropertySpec) - 1; \
440            j < szj; j++) {                                                     \
441         if (JS_DefineObjProperty(pRuntime, nObjDefnID,                         \
442                                  JS_Class_Properties[j].pName,                 \
443                                  JS_Class_Properties[j].pPropGet,              \
444                                  JS_Class_Properties[j].pPropPut) < 0)         \
445           return -1;                                                           \
446       }                                                                        \
447                                                                                \
448       for (int k = 0,                                                          \
449                szk = sizeof(JS_Class_Methods) / sizeof(JSMethodSpec) - 1;      \
450            k < szk; k++) {                                                     \
451         if (JS_DefineObjMethod(pRuntime, nObjDefnID,                           \
452                                JS_Class_Methods[k].pName,                      \
453                                JS_Class_Methods[k].pMethodCall) < 0)           \
454           return -1;                                                           \
455       }                                                                        \
456       if (JS_DefineObjAllProperties(                                           \
457               pRuntime, nObjDefnID,                                            \
458               js_class_name::queryprop_##js_class_name##_static,               \
459               js_class_name::getprop_##js_class_name##_static,                 \
460               js_class_name::putprop_##js_class_name##_static,                 \
461               js_class_name::delprop_##js_class_name##_static) < 0)            \
462         return -1;                                                             \
463                                                                                \
464       return nObjDefnID;                                                       \
465     }                                                                          \
466                                                                                \
467     return -1;                                                                 \
468   }
469
470 /* ======================================== GLOBAL METHODS
471  * ============================================ */
472
473 template <FX_BOOL (*F)(IFXJS_Context* cc,
474                        const CJS_Parameters& params,
475                        CJS_Value& vRet,
476                        CFX_WideString& sError)>
477 void JSGlobalFunc(const char* func_name_string,
478                   const v8::FunctionCallbackInfo<v8::Value>& info) {
479   v8::Isolate* isolate = info.GetIsolate();
480   v8::Local<v8::Context> context = isolate->GetCurrentContext();
481   v8::Local<v8::Value> v = context->GetEmbedderData(1);
482   v8::Local<v8::External> field = v8::Local<v8::External>::Cast(v);
483   IFXJS_Runtime* pRuntime = (IFXJS_Runtime*)field->Value();
484   IFXJS_Context* cc = pRuntime->GetCurrentContext();
485   CJS_Parameters parameters;
486   for (unsigned int i = 0; i < (unsigned int)info.Length(); i++) {
487     parameters.push_back(CJS_Value(isolate, info[i], VT_unknown));
488   }
489   CJS_Value valueRes(isolate);
490   CFX_WideString sError;
491   if (!(*F)(cc, parameters, valueRes, sError)) {
492     JS_Error(isolate, JSFormatErrorString(func_name_string, nullptr, sError));
493     return;
494   }
495   info.GetReturnValue().Set(valueRes.ToV8Value());
496 }
497
498 #define JS_STATIC_GLOBAL_FUN(fun_name)                   \
499   static void fun_name##_static(                         \
500       const v8::FunctionCallbackInfo<v8::Value>& info) { \
501     JSGlobalFunc<fun_name>(#fun_name, info);             \
502   }
503
504 #define JS_STATIC_DECLARE_GLOBAL_FUN()  \
505   static JSMethodSpec global_methods[]; \
506   static int Init(IJS_Runtime* pRuntime)
507
508 #define BEGIN_JS_STATIC_GLOBAL_FUN(js_class_name) \
509   JSMethodSpec js_class_name::global_methods[] = {
510 #define JS_STATIC_GLOBAL_FUN_ENTRY(method_name) \
511   JS_STATIC_METHOD_ENTRY(method_name)
512
513 #define END_JS_STATIC_GLOBAL_FUN() END_JS_STATIC_METHOD()
514
515 #define IMPLEMENT_JS_STATIC_GLOBAL_FUN(js_class_name)            \
516   int js_class_name::Init(IJS_Runtime* pRuntime) {               \
517     for (int i = 0, sz = sizeof(js_class_name::global_methods) / \
518                              sizeof(JSMethodSpec) -              \
519                          1;                                      \
520          i < sz; i++) {                                          \
521       if (JS_DefineGlobalMethod(                                 \
522               pRuntime, js_class_name::global_methods[i].pName,  \
523               js_class_name::global_methods[i].pMethodCall) < 0) \
524         return -1;                                               \
525     }                                                            \
526     return 0;                                                    \
527   }
528
529 /* ======================================== GLOBAL CONSTS
530  * ============================================ */
531 #define DEFINE_GLOBAL_CONST(pRuntime, const_name, const_value) \
532   if (JS_DefineGlobalConst(                                    \
533           pRuntime, JS_WIDESTRING(const_name),                 \
534           JS_NewString(pRuntime, JS_WIDESTRING(const_value)))) \
535   return -1
536
537 /* ======================================== GLOBAL ARRAYS
538  * ============================================ */
539
540 #define DEFINE_GLOBAL_ARRAY(pRuntime)                           \
541   int size = FX_ArraySize(ArrayContent);                        \
542                                                                 \
543   CJS_Array array(pRuntime);                                    \
544   for (int i = 0; i < size; i++)                                \
545     array.SetElement(i, CJS_Value(pRuntime, ArrayContent[i]));  \
546                                                                 \
547   CJS_PropValue prop(pRuntime);                                 \
548   prop << array;                                                \
549   if (JS_DefineGlobalConst(pRuntime, (const wchar_t*)ArrayName, \
550                            prop.ToV8Value()) < 0)               \
551   return -1
552
553 /* ============================================================ */
554
555 #define VALUE_NAME_STRING L"string"
556 #define VALUE_NAME_NUMBER L"number"
557 #define VALUE_NAME_BOOLEAN L"boolean"
558 #define VALUE_NAME_DATE L"date"
559 #define VALUE_NAME_OBJECT L"object"
560 #define VALUE_NAME_FXOBJ L"fxobj"
561 #define VALUE_NAME_NULL L"null"
562 #define VALUE_NAME_UNDEFINED L"undefined"
563
564 FXJSVALUETYPE GET_VALUE_TYPE(v8::Local<v8::Value> p);
565
566 #endif  // FPDFSDK_INCLUDE_JAVASCRIPT_JS_DEFINE_H_