Merge to XFA: Tidy up JS_Defines.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 _JS_DEFINE_H_
8 #define _JS_DEFINE_H_
9
10 typedef v8::Value                       JSValue;
11 typedef v8::Handle<v8::Object>  JSObject;
12 typedef v8::Handle<v8::Object>  JSFXObject;
13 typedef unsigned                JSBool;
14
15 struct JSConstSpec
16 {
17         const wchar_t* pName;
18         double number;
19         const wchar_t* string;
20         FX_BYTE t; //0:double 1:str
21 };
22
23 struct JSPropertySpec
24 {
25         const wchar_t* pName;
26         v8::AccessorGetterCallback pPropGet;
27         v8::AccessorSetterCallback pPropPut;
28 };
29
30 struct JSMethodSpec
31 {
32         const wchar_t* pName;
33         v8::FunctionCallback pMethodCall;
34         unsigned nParamNum;
35 };
36
37 typedef CFX_WideString  JS_ErrorString;
38
39 #define JS_TRUE                 (unsigned)1
40 #define JS_FALSE                (unsigned)0
41
42
43 #define CJS_PointsArray         CFX_ArrayTemplate<float>
44 #define CJS_IntArray            CFX_ArrayTemplate<int>
45
46 /* ====================================== PUBLIC DEFINE SPEC ============================================== */
47 #define JS_WIDESTRING(widestring) L###widestring
48
49 #define BEGIN_JS_STATIC_CONST(js_class_name) JSConstSpec js_class_name::JS_Class_Consts[] = {
50 #define JS_STATIC_CONST_ENTRY_NUMBER(const_name, pValue) {JS_WIDESTRING(const_name), pValue, L"", 0},
51 #define JS_STATIC_CONST_ENTRY_STRING(const_name, pValue) {JS_WIDESTRING(const_name), 0, JS_WIDESTRING(pValue), 1},
52 #define END_JS_STATIC_CONST() {0, 0, 0, 0}};
53
54 #define BEGIN_JS_STATIC_PROP(js_class_name) JSPropertySpec js_class_name::JS_Class_Properties[] = {
55 #define JS_STATIC_PROP_ENTRY(prop_name) {JS_WIDESTRING(prop_name), get_##prop_name##_static, set_##prop_name##_static},
56 #define END_JS_STATIC_PROP() {0, 0, 0}};
57
58 #define BEGIN_JS_STATIC_METHOD(js_class_name) JSMethodSpec js_class_name::JS_Class_Methods[] = {
59 #define JS_STATIC_METHOD_ENTRY(method_name, nargs) {JS_WIDESTRING(method_name), method_name##_static, nargs},
60 #define END_JS_STATIC_METHOD() {0, 0, 0}};
61 #define MEMLEAKCHECK_1() ((void)0)
62 #define MEMLEAKCHECK_2(main_name, sub_name) ((void)0)
63
64
65 /*
66 #ifdef _DEBUG
67 #define MEMLEAKCHECK_1() \
68         _CrtMemState state1;\
69         _CrtMemCheckpoint(&state1);
70
71 #define MEMLEAKCHECK_2(main_name,sub_name) \
72         _CrtMemState state2;\
73         _CrtMemCheckpoint(&state2);\
74         _CrtMemState diff;\
75         _CrtMemDifference(&diff,&state1,&state2);\
76         if (diff.lSizes[_NORMAL_BLOCK] > 0)\
77         {\
78                 TRACE("Detected normal block memory leaks in JS Module! [%s.%s]\n",#main_name,#sub_name);\
79                 _CrtMemDumpStatistics(&diff);\
80         }
81 #else
82         #define MEMLEAKCHECK_1() ((void)0)
83         #define MEMLEAKCHECK_2(main_name,sub_name) ((void)0)
84 #endif
85 */
86
87 /* ======================================== PROP CALLBACK ============================================ */
88
89 #define JS_STATIC_PROP_GET(prop_name, class_name)\
90   static void get_##prop_name##_static(v8::Local<v8::String> property, \
91                                        const v8::PropertyCallbackInfo<v8::Value>& info) \
92 {\
93         v8::Isolate* isolate = info.GetIsolate();\
94         v8::Local<v8::Context> context = isolate->GetCurrentContext();\
95         IFXJS_Runtime* pRuntime = (IFXJS_Runtime*)isolate->GetData(2);\
96         if (pRuntime == NULL) return;\
97         IFXJS_Context* cc = pRuntime->GetCurrentContext();\
98         CJS_PropValue value(isolate);\
99         value.StartGetting();\
100         CJS_Object* pJSObj = (CJS_Object*)JS_GetPrivate(isolate,info.Holder());\
101         ASSERT(pJSObj != NULL);\
102         class_name* pObj = (class_name*)pJSObj->GetEmbedObject();\
103         ASSERT(pObj != NULL);\
104         JS_ErrorString sError;\
105         FX_BOOL bRet = FALSE;\
106         MEMLEAKCHECK_1();\
107         bRet = pObj->prop_name(cc, value, sError);\
108         MEMLEAKCHECK_2(class_name, prop_name);\
109         if (bRet)\
110         {\
111                 info.GetReturnValue().Set((v8::Handle<v8::Value>)value);\
112                 return ;\
113         }\
114         else\
115         {\
116         CFX_ByteString cbName;\
117                 cbName.Format("%s.%s", #class_name, #prop_name);\
118                 JS_Error(NULL,CFX_WideString::FromLocal(cbName), sError);\
119                 return ;\
120         }\
121 }
122
123 #define JS_STATIC_PROP_SET(prop_name, class_name)\
124   static void set_##prop_name##_static(v8::Local<v8::String> property, \
125                                        v8::Local<v8::Value> value, \
126                                        const v8::PropertyCallbackInfo<void>& info) \
127 {\
128         v8::Isolate* isolate = info.GetIsolate();\
129         v8::Local<v8::Context> context = isolate->GetCurrentContext();\
130         IFXJS_Runtime* pRuntime = (IFXJS_Runtime*)isolate->GetData(2);\
131         if (pRuntime == NULL) return;\
132         IFXJS_Context* cc = pRuntime->GetCurrentContext();\
133         CJS_PropValue propValue(CJS_Value(isolate,value,VT_unknown));\
134         propValue.StartSetting();\
135         CJS_Object* pJSObj = (CJS_Object*)JS_GetPrivate(isolate,info.Holder());\
136         ASSERT(pJSObj != NULL);\
137         class_name* pObj = (class_name*)pJSObj->GetEmbedObject();\
138         ASSERT(pObj != NULL);\
139         JS_ErrorString sError;\
140         FX_BOOL bRet = FALSE;\
141         MEMLEAKCHECK_1();\
142         bRet = pObj->prop_name(cc, propValue, sError);\
143         MEMLEAKCHECK_2(class_name, prop_name);\
144         if (bRet)\
145         {\
146                 return ;\
147         }\
148         else\
149         {\
150                 CFX_ByteString cbName;\
151                 cbName.Format("%s.%s", #class_name, #prop_name);\
152                 JS_Error(NULL,CFX_WideString::FromLocal(cbName), sError);\
153                 return ;\
154         }\
155 }
156
157 #define JS_STATIC_PROP(prop_name, class_name)\
158 JS_STATIC_PROP_GET(prop_name, class_name);\
159 JS_STATIC_PROP_SET(prop_name, class_name)
160
161 /* ========================================= METHOD CALLBACK =========================================== */
162
163 #define JS_STATIC_METHOD(method_name, class_name)\
164   static void method_name##_static(const v8::FunctionCallbackInfo<v8::Value>& info) \
165 {\
166         v8::Isolate* isolate = info.GetIsolate();\
167         v8::Local<v8::Context> context = isolate->GetCurrentContext();\
168         IFXJS_Runtime* pRuntime = (IFXJS_Runtime*)isolate->GetData(2);\
169         if (pRuntime == NULL) return;\
170         IFXJS_Context* cc = pRuntime->GetCurrentContext();\
171         CJS_Parameters parameters;\
172         for (unsigned int i = 0; i<(unsigned int)info.Length(); i++)\
173     {\
174                 parameters.push_back(CJS_Value(isolate, info[i], VT_unknown));\
175         }\
176         CJS_Value valueRes(isolate);\
177         CJS_Object* pJSObj = (CJS_Object *)JS_GetPrivate(isolate,info.Holder());\
178         ASSERT(pJSObj != NULL);\
179         class_name* pObj = (class_name*)pJSObj->GetEmbedObject();\
180         ASSERT(pObj != NULL);\
181         JS_ErrorString sError;\
182         FX_BOOL bRet = FALSE;\
183         MEMLEAKCHECK_1();\
184         bRet = pObj->method_name(cc, parameters, valueRes, sError);\
185         MEMLEAKCHECK_2(class_name, method_name);\
186         if (bRet)\
187         {\
188                 info.GetReturnValue().Set(valueRes.ToJSValue());\
189                 return ;\
190         }\
191         else\
192         {\
193                 CFX_ByteString cbName;\
194                 cbName.Format("%s.%s", #class_name, #method_name);\
195                 JS_Error(NULL, CFX_WideString::FromLocal(cbName), sError);\
196                 return ;\
197         }\
198 }
199
200 /* ===================================== JS CLASS =============================================== */
201
202 #define DECLARE_JS_CLASS(js_class_name) \
203         static JSBool JSConstructor(IFXJS_Context* cc, JSFXObject obj,JSFXObject global);\
204         static JSBool JSDestructor(JSFXObject obj);\
205         static int Init(IJS_Runtime* pRuntime, FXJSOBJTYPE eObjType);\
206         static void GetConsts(JSConstSpec*& pConsts, int& nSize);\
207         static void GetProperties(JSPropertySpec*& pProperties, int& nSize);\
208         static void GetMethods(JSMethodSpec*& pMethods, int& nSize);\
209         static JSConstSpec JS_Class_Consts[];\
210         static JSPropertySpec JS_Class_Properties[];\
211         static JSMethodSpec     JS_Class_Methods[];\
212         static const wchar_t* m_pClassName
213
214 #define IMPLEMENT_JS_CLASS_RICH(js_class_name, class_alternate, class_name) \
215 const wchar_t* js_class_name::m_pClassName = JS_WIDESTRING(class_name);\
216 JSBool js_class_name::JSConstructor(IFXJS_Context* cc, JSFXObject obj, JSFXObject global)\
217 {\
218         CJS_Object* pObj = FX_NEW js_class_name(obj);\
219         pObj->SetEmbedObject(FX_NEW class_alternate(pObj));\
220         JS_SetPrivate(NULL,obj,(void*)pObj); \
221         pObj->InitInstance(cc);\
222         return JS_TRUE;\
223 }\
224 \
225 JSBool js_class_name::JSDestructor(JSFXObject obj) \
226 {\
227         js_class_name* pObj = (js_class_name*)JS_GetPrivate(NULL,obj);\
228         ASSERT(pObj != NULL);\
229         pObj->ExitInstance();\
230         delete pObj;\
231         return JS_TRUE;\
232 }\
233 \
234 int js_class_name::Init(IJS_Runtime* pRuntime, FXJSOBJTYPE eObjType)\
235 {\
236         int nObjDefnID = JS_DefineObj(pRuntime, js_class_name::m_pClassName, eObjType, JSConstructor, JSDestructor, 0);\
237         if (nObjDefnID >= 0)\
238         {\
239                 for (int j=0, szj=sizeof(JS_Class_Properties)/sizeof(JSPropertySpec)-1; j<szj; j++)\
240                 {\
241                         if (JS_DefineObjProperty(pRuntime, nObjDefnID, JS_Class_Properties[j].pName, JS_Class_Properties[j].pPropGet, JS_Class_Properties[j].pPropPut) < 0) return -1;\
242                 }\
243                 for (int k=0, szk=sizeof(JS_Class_Methods)/sizeof(JSMethodSpec)-1; k<szk; k++)\
244                 {\
245                         if (JS_DefineObjMethod(pRuntime, nObjDefnID,JS_Class_Methods[k].pName, JS_Class_Methods[k].pMethodCall, JS_Class_Methods[k].nParamNum) < 0) return -1;\
246                 }\
247                 return nObjDefnID;\
248         }\
249         return -1;\
250 }\
251 void js_class_name::GetConsts(JSConstSpec*& pConsts, int& nSize)\
252 {\
253         pConsts = JS_Class_Consts;\
254         nSize = sizeof(JS_Class_Consts) / sizeof(JSConstSpec) - 1;\
255 }\
256 void js_class_name::GetProperties(JSPropertySpec*& pProperties, int& nSize)\
257 {\
258         pProperties = JS_Class_Properties;\
259         nSize = sizeof(JS_Class_Properties) / sizeof(JSPropertySpec) - 1;\
260 }\
261 void js_class_name::GetMethods(JSMethodSpec*& pMethods, int& nSize)\
262 {\
263         pMethods = JS_Class_Methods;\
264         nSize = sizeof(JS_Class_Methods) / sizeof(JSMethodSpec) - 1;\
265 }
266
267 #define IMPLEMENT_JS_CLASS(js_class_name, class_name) IMPLEMENT_JS_CLASS_RICH(js_class_name, class_name, class_name)
268
269 /* ======================================== CONST CLASS ============================================ */
270
271 #define DECLARE_JS_CLASS_CONST() \
272         static int Init(IJS_Runtime* pRuntime, FXJSOBJTYPE eObjType);\
273         static void GetConsts(JSConstSpec*& pConsts, int& nSize);\
274         static JSConstSpec JS_Class_Consts[];\
275         static const wchar_t* m_pClassName
276
277 #define IMPLEMENT_JS_CLASS_CONST(js_class_name, class_name) \
278 const wchar_t* js_class_name::m_pClassName = JS_WIDESTRING(class_name);\
279 int js_class_name::Init(IJS_Runtime* pRuntime, FXJSOBJTYPE eObjType)\
280 {\
281         int nObjDefnID = JS_DefineObj(pRuntime, js_class_name::m_pClassName, eObjType, NULL, NULL, 0);\
282         if (nObjDefnID >=0)\
283         {\
284                 for (int i=0, sz=sizeof(JS_Class_Consts)/sizeof(JSConstSpec)-1; i<sz; i++)\
285                 {\
286                         if (JS_Class_Consts[i].t == 0)\
287                         {\
288                                 if (JS_DefineObjConst(pRuntime, nObjDefnID, JS_Class_Consts[i].pName, JS_NewNumber(pRuntime,JS_Class_Consts[i].number)) < 0) return -1;\
289                         }\
290                         else\
291                         {\
292                         if (JS_DefineObjConst(pRuntime, nObjDefnID, JS_Class_Consts[i].pName, JS_NewString(pRuntime,JS_Class_Consts[i].string)) < 0) return -1;\
293                         }\
294                 }\
295                 return nObjDefnID;\
296         }\
297         return -1;\
298 }\
299 void js_class_name::GetConsts(JSConstSpec*& pConsts, int& nSize)\
300 {\
301         pConsts = JS_Class_Consts;\
302         nSize = sizeof(JS_Class_Consts)/sizeof(JSConstSpec)-1;\
303 }
304
305 /* ===================================== SPECIAL JS CLASS =============================================== */
306
307 #define DECLARE_SPECIAL_JS_CLASS(js_class_name) \
308         static JSBool JSConstructor(IFXJS_Context* cc, JSFXObject obj, JSFXObject global);\
309         static JSBool JSDestructor(JSFXObject obj);\
310         static void GetConsts(JSConstSpec*& pConsts, int& nSize);\
311         static void GetProperties(JSPropertySpec*& pProperties, int& nSize);\
312         static void GetMethods(JSMethodSpec*& pMethods, int& nSize);\
313         static JSConstSpec JS_Class_Consts[];\
314         static JSPropertySpec JS_Class_Properties[];\
315         static JSMethodSpec     JS_Class_Methods[];\
316         static int Init(IJS_Runtime* pRuntime, FXJSOBJTYPE eObjType);\
317         static const wchar_t* m_pClassName;\
318         static void queryprop_##js_class_name##_static(JS_PROPQUERY_ARGS);\
319         static void getprop_##js_class_name##_static(JS_NAMED_PROPGET_ARGS);\
320         static void putprop_##js_class_name##_static(JS_NAMED_PROPPUT_ARGS);\
321         static void delprop_##js_class_name##_static(JS_PROPDEL_ARGS)
322
323 #define IMPLEMENT_SPECIAL_JS_CLASS(js_class_name, class_alternate, class_name) \
324 const wchar_t * js_class_name::m_pClassName = JS_WIDESTRING(class_name);\
325         void js_class_name::queryprop_##js_class_name##_static(JS_PROPQUERY_ARGS)\
326 {\
327         v8::Isolate* isolate = info.GetIsolate();\
328         v8::String::Utf8Value utf8_value(property);\
329         CFX_WideString propname = CFX_WideString::FromUTF8(*utf8_value, utf8_value.length());\
330         CJS_Object* pJSObj = (CJS_Object*)JS_GetPrivate(isolate,info.Holder());\
331         ASSERT(pJSObj != NULL);\
332         class_alternate* pObj = (class_alternate*)pJSObj->GetEmbedObject();\
333         ASSERT(pObj != NULL);\
334         FX_BOOL bRet = FALSE;\
335         MEMLEAKCHECK_1();\
336         bRet = pObj->QueryProperty(propname.c_str());\
337         MEMLEAKCHECK_2(class_name, prop_name.c_str());\
338         if (bRet)\
339         {\
340                 info.GetReturnValue().Set(0x004);\
341                 return ;\
342         }\
343         else\
344         {\
345                 info.GetReturnValue().Set(0);\
346                 return ;\
347         }\
348         return ;\
349 }\
350         void js_class_name::getprop_##js_class_name##_static(JS_NAMED_PROPGET_ARGS)\
351 {\
352         v8::Isolate* isolate = info.GetIsolate();\
353         v8::Local<v8::Context> context = isolate->GetCurrentContext();\
354         IFXJS_Runtime* pRuntime = (IFXJS_Runtime*)isolate->GetData(2);\
355         if (pRuntime == NULL) return;\
356         IFXJS_Context* cc = pRuntime->GetCurrentContext();\
357         v8::String::Utf8Value utf8_value(property);\
358         CFX_WideString propname = CFX_WideString::FromUTF8(*utf8_value, utf8_value.length());\
359         CJS_PropValue value(isolate);\
360         value.StartGetting();\
361         CJS_Object* pJSObj = (CJS_Object*)JS_GetPrivate(isolate,info.Holder());\
362         ASSERT(pJSObj != NULL);\
363         class_alternate* pObj = (class_alternate*)pJSObj->GetEmbedObject();\
364         ASSERT(pObj != NULL);\
365         JS_ErrorString sError;\
366         FX_BOOL bRet = FALSE;\
367         MEMLEAKCHECK_1();\
368         bRet = pObj->DoProperty(cc, propname.c_str(), value, sError);\
369         MEMLEAKCHECK_2(class_name, L"GetProperty");\
370         if (bRet)\
371         {\
372                 info.GetReturnValue().Set((v8::Handle<v8::Value>)value);\
373                 return ;\
374         }\
375         else\
376         {\
377                 CFX_ByteString cbName;\
378                 cbName.Format("%s.%s", #class_name, L"GetProperty");\
379                 JS_Error(NULL,CFX_WideString::FromLocal(cbName), sError);\
380                 return ;\
381         }\
382         JS_Error(NULL,L"GetProperty", L"Embeded object not found!");\
383         return ;\
384 }\
385         void js_class_name::putprop_##js_class_name##_static(JS_NAMED_PROPPUT_ARGS)\
386 {\
387         v8::Isolate* isolate = info.GetIsolate();\
388         v8::Local<v8::Context> context = isolate->GetCurrentContext();\
389         IFXJS_Runtime* pRuntime = (IFXJS_Runtime*)isolate->GetData(2);\
390         if (pRuntime == NULL) return;\
391         IFXJS_Context* cc = pRuntime->GetCurrentContext();\
392         v8::String::Utf8Value utf8_value(property);\
393         CFX_WideString propname = CFX_WideString::FromUTF8(*utf8_value, utf8_value.length());\
394         CJS_PropValue PropValue(CJS_Value(isolate,value,VT_unknown));\
395         PropValue.StartSetting();\
396         CJS_Object* pJSObj = (CJS_Object*)JS_GetPrivate(isolate,info.Holder());\
397         if(!pJSObj) return;\
398         class_alternate* pObj = (class_alternate*)pJSObj->GetEmbedObject();\
399         ASSERT(pObj != NULL);\
400         JS_ErrorString sError;\
401         FX_BOOL bRet = FALSE;\
402         MEMLEAKCHECK_1();\
403         bRet = pObj->DoProperty(cc, propname.c_str(), PropValue, sError);\
404         MEMLEAKCHECK_2(class_name,L"PutProperty");\
405         if (bRet)\
406         {\
407                 return ;\
408         }\
409         else\
410         {\
411                 CFX_ByteString cbName;\
412                 cbName.Format("%s.%s", #class_name, "PutProperty");\
413                 JS_Error(NULL,CFX_WideString::FromLocal(cbName), sError);\
414                 return ;\
415         }\
416         JS_Error(NULL,L"PutProperty", L"Embeded object not found!");\
417         return ;\
418 }\
419         void js_class_name::delprop_##js_class_name##_static(JS_PROPDEL_ARGS)\
420 {\
421         v8::Isolate* isolate = info.GetIsolate();\
422         v8::Local<v8::Context> context = isolate->GetCurrentContext();\
423         IFXJS_Runtime* pRuntime = (IFXJS_Runtime*)isolate->GetData(2);\
424         if (pRuntime == NULL) return;\
425         IFXJS_Context* cc = pRuntime->GetCurrentContext();\
426         v8::String::Utf8Value utf8_value(property);\
427         CFX_WideString propname = CFX_WideString::FromUTF8(*utf8_value, utf8_value.length());\
428         CJS_Object* pJSObj = (CJS_Object*)JS_GetPrivate(isolate,info.Holder());\
429         ASSERT(pJSObj != NULL);\
430         class_alternate* pObj = (class_alternate*)pJSObj->GetEmbedObject();\
431         ASSERT(pObj != NULL);\
432         JS_ErrorString sError;\
433         FX_BOOL bRet = FALSE;\
434         MEMLEAKCHECK_1();\
435         bRet = pObj->DelProperty(cc, propname.c_str(), sError);\
436         MEMLEAKCHECK_2(class_name,L"DelProperty");\
437         if (bRet)\
438         {\
439                 return ;\
440         }\
441         else\
442         {\
443                 CFX_ByteString cbName;\
444                 cbName.Format("%s.%s", #class_name, "DelProperty");\
445                 return ;\
446         }\
447         return ;\
448 }\
449 JSBool js_class_name::JSConstructor(IFXJS_Context* cc, JSFXObject  obj,JSFXObject  global)\
450 {\
451         CJS_Object* pObj = FX_NEW js_class_name(obj);\
452         pObj->SetEmbedObject(FX_NEW class_alternate(pObj));\
453         JS_SetPrivate(NULL,obj, (void*)pObj); \
454         pObj->InitInstance(cc);\
455         return JS_TRUE;\
456 }\
457 \
458 JSBool js_class_name::JSDestructor(JSFXObject obj) \
459 {\
460         js_class_name* pObj = (js_class_name*)JS_GetPrivate(NULL,obj);\
461         ASSERT(pObj != NULL);\
462         pObj->ExitInstance();\
463         delete pObj;\
464         return JS_TRUE;\
465 }\
466 \
467 int js_class_name::Init(IJS_Runtime* pRuntime, FXJSOBJTYPE eObjType)\
468 {\
469 \
470         int nObjDefnID = JS_DefineObj(pRuntime, js_class_name::m_pClassName, eObjType, JSConstructor, JSDestructor, 0);\
471 \
472         if (nObjDefnID >= 0)\
473         {\
474                 for (int j=0, szj=sizeof(JS_Class_Properties)/sizeof(JSPropertySpec)-1; j<szj; j++)\
475                 {\
476                         if (JS_DefineObjProperty(pRuntime, nObjDefnID, JS_Class_Properties[j].pName, JS_Class_Properties[j].pPropGet,JS_Class_Properties[j].pPropPut)<0)return -1;\
477                 }\
478 \
479                 for (int k=0, szk=sizeof(JS_Class_Methods)/sizeof(JSMethodSpec)-1; k<szk; k++)\
480                 {\
481                         if (JS_DefineObjMethod(pRuntime, nObjDefnID,JS_Class_Methods[k].pName,JS_Class_Methods[k].pMethodCall,JS_Class_Methods[k].nParamNum)<0)return -1;\
482                 }\
483                 if (JS_DefineObjAllProperties(pRuntime, nObjDefnID, js_class_name::queryprop_##js_class_name##_static, js_class_name::getprop_##js_class_name##_static,js_class_name::putprop_##js_class_name##_static,js_class_name::delprop_##js_class_name##_static)<0) return -1;\
484 \
485                 return nObjDefnID;\
486         }\
487 \
488         return -1;\
489 }\
490 void js_class_name::GetConsts(JSConstSpec*& pConsts, int& nSize)\
491 {\
492         pConsts = JS_Class_Consts;\
493         nSize = sizeof(JS_Class_Consts)/sizeof(JSConstSpec)-1;\
494 }\
495 void js_class_name::GetProperties(JSPropertySpec*& pProperties, int& nSize)\
496 {\
497         pProperties = JS_Class_Properties;\
498         nSize = sizeof(JS_Class_Properties)/sizeof(JSPropertySpec)-1;\
499 }\
500 void js_class_name::GetMethods(JSMethodSpec*& pMethods, int& nSize)\
501 {\
502         pMethods = JS_Class_Methods;\
503         nSize = sizeof(JS_Class_Methods)/sizeof(JSMethodSpec)-1;\
504 }
505
506 #define JS_SPECIAL_STATIC_METHOD(method_name, class_alternate, class_name)\
507         static void method_name##_static(const v8::FunctionCallbackInfo<v8::Value>& info)\
508 {\
509         v8::Isolate* isolate = info.GetIsolate();\
510         v8::Local<v8::Context> context = isolate->GetCurrentContext();\
511         IFXJS_Runtime* pRuntime = (IFXJS_Runtime*)isolate->GetData(2);\
512         if (pRuntime == NULL) return;\
513         IFXJS_Context* cc = pRuntime->GetCurrentContext();\
514         CJS_Parameters parameters;\
515         for (unsigned int i = 0; i<(unsigned int)info.Length(); i++)\
516         {\
517         parameters.push_back(CJS_Value(isolate, info[i], VT_unknown));\
518         }\
519         CJS_Value valueRes(isolate);\
520         CJS_Object* pJSObj = (CJS_Object *)JS_GetPrivate(isolate, info.Holder());\
521         ASSERT(pJSObj != NULL);\
522         class_alternate* pObj = (class_alternate*)pJSObj->GetEmbedObject();\
523         ASSERT(pObj != NULL);\
524         JS_ErrorString sError;\
525         FX_BOOL bRet = FALSE;\
526         MEMLEAKCHECK_1();\
527         bRet = pObj->method_name(cc, parameters, valueRes, sError);\
528         MEMLEAKCHECK_2(class_name, method_name);\
529         if (bRet)\
530         {\
531                 info.GetReturnValue().Set(valueRes.ToJSValue());\
532                 return ;\
533         }\
534         else\
535         {\
536                 CFX_ByteString cbName;\
537                 cbName.Format("%s.%s", #class_name, #method_name);\
538                 JS_Error(NULL, CFX_WideString::FromLocal(cbName), sError);\
539                 return ;\
540         }\
541         JS_Error(NULL,  JS_WIDESTRING(method_name), L"Embeded object not found!");\
542     return ;\
543 }
544
545 /* ======================================== GLOBAL METHODS ============================================ */
546 #define JS_STATIC_GLOBAL_FUN(fun_name) \
547 static void fun_name##_static(const v8::FunctionCallbackInfo<v8::Value>& info)\
548 {\
549         v8::Isolate* isolate = info.GetIsolate();\
550         v8::Local<v8::Context> context = isolate->GetCurrentContext();\
551         IFXJS_Runtime* pRuntime = (IFXJS_Runtime*)isolate->GetData(2);\
552         if (pRuntime == NULL) return;\
553         IFXJS_Context* cc = pRuntime->GetCurrentContext();\
554         CJS_Parameters parameters;\
555         for (unsigned int i = 0; i<(unsigned int)info.Length(); i++)\
556         {\
557         parameters.push_back(CJS_Value(isolate, info[i], VT_unknown));\
558         }\
559         CJS_Value valueRes(isolate);\
560         JS_ErrorString sError;\
561         if (!fun_name(cc, parameters, valueRes, sError))\
562         {\
563                 JS_Error(NULL, JS_WIDESTRING(fun_name), sError);\
564                 return ;\
565         }\
566         info.GetReturnValue().Set(valueRes.ToJSValue());\
567         return ;\
568 }
569
570 #define JS_STATIC_DECLARE_GLOBAL_FUN() \
571 static JSMethodSpec     global_methods[]; \
572 static int Init(IJS_Runtime* pRuntime)
573
574 #define BEGIN_JS_STATIC_GLOBAL_FUN(js_class_name) \
575 JSMethodSpec js_class_name::global_methods[] = {
576
577 #define JS_STATIC_GLOBAL_FUN_ENTRY(method_name,nargs) JS_STATIC_METHOD_ENTRY(method_name,nargs)
578
579 #define END_JS_STATIC_GLOBAL_FUN() END_JS_STATIC_METHOD()
580
581 #define IMPLEMENT_JS_STATIC_GLOBAL_FUN(js_class_name) \
582 int js_class_name::Init(IJS_Runtime* pRuntime)\
583 {\
584         for (int i=0, sz=sizeof(js_class_name::global_methods)/sizeof(JSMethodSpec)-1; i<sz; i++)\
585         {\
586                 if (JS_DefineGlobalMethod(pRuntime,\
587                                 js_class_name::global_methods[i].pName,\
588                                 js_class_name::global_methods[i].pMethodCall,\
589                                 js_class_name::global_methods[i].nParamNum\
590                                 ) < 0\
591                         )return -1;\
592         }\
593         return 0;\
594 }
595
596 /* ======================================== GLOBAL CONSTS ============================================ */
597 #define DEFINE_GLOBAL_CONST(pRuntime, const_name , const_value)\
598 if (JS_DefineGlobalConst(pRuntime,JS_WIDESTRING(const_name),JS_NewString(pRuntime,JS_WIDESTRING(const_value)))) return -1
599
600 /* ======================================== GLOBAL ARRAYS ============================================ */
601
602 #define DEFINE_GLOBAL_ARRAY(pRuntime)\
603 int size = FX_ArraySize(ArrayContent);\
604 \
605 CJS_Array array(pRuntime);\
606 for (int i=0; i<size; i++) array.SetElement(i,CJS_Value(pRuntime,ArrayContent[i]));\
607 \
608 CJS_PropValue prop(pRuntime);\
609 prop << array;\
610 if (JS_DefineGlobalConst(pRuntime, (const wchar_t*)ArrayName, prop.ToJSValue()) < 0)\
611         return -1
612
613 /* ============================================================ */
614
615 #define VALUE_NAME_STRING               L"string"
616 #define VALUE_NAME_NUMBER               L"number"
617 #define VALUE_NAME_BOOLEAN              L"boolean"
618 #define VALUE_NAME_DATE                 L"date"
619 #define VALUE_NAME_OBJECT               L"object"
620 #define VALUE_NAME_FXOBJ                L"fxobj"
621 #define VALUE_NAME_NULL                 L"null"
622 #define VALUE_NAME_UNDEFINED    L"undefined"
623
624 #define CLASSNAME_ARRAY                 L"Array"
625 #define CLASSNAME_DATE                  L"Date"
626 #define CLASSNAME_STRING                L"v8::String"
627
628 FXJSVALUETYPE GET_VALUE_TYPE(v8::Handle<v8::Value> p);
629
630 #endif //_JS_DEFINE_H_