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