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