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