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