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