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