jsb_pluginx_basic_conversions.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497
  1. #include "jsb_pluginx_basic_conversions.h"
  2. #include <math.h>
  3. #include "jsb_pluginx_spidermonkey_specifics.h"
  4. #include "pluginxUTF8.h"
  5. #include <sstream>
  6. namespace pluginx {
  7. // just a simple utility to avoid mem leaking when using JSString
  8. class JSStringWrapper
  9. {
  10. JSString* string;
  11. const char* buffer;
  12. JSContext* cx;
  13. public:
  14. JSStringWrapper() {
  15. buffer = NULL;
  16. }
  17. JSStringWrapper(JSString* str, JSContext* cx) {
  18. set(str, cx);
  19. }
  20. JSStringWrapper(jsval val, JSContext* cx) {
  21. set(val, cx);
  22. }
  23. ~JSStringWrapper() {
  24. if (buffer) {
  25. // delete[] buffer;
  26. // buffer = NULL;
  27. JS_free(cx, (void*)buffer);
  28. }
  29. }
  30. void set(jsval val, JSContext* cx) {
  31. if (val.isString()) {
  32. this->set(val.toString(), cx);
  33. } else {
  34. buffer = NULL;
  35. }
  36. }
  37. void set(JSString* str, JSContext* cx) {
  38. this->cx = cx;
  39. string = str;
  40. // Not suppored in SpiderMonkey v19
  41. //buffer = JS_EncodeString(cx, string);
  42. buffer = JS_EncodeString(cx, str);
  43. }
  44. std::string get() {
  45. return buffer;
  46. }
  47. operator std::string() {
  48. return std::string(buffer);
  49. }
  50. operator char*() {
  51. return (char*)buffer;
  52. }
  53. };
  54. // JSFunctionWrapper
  55. JSFunctionWrapper::JSFunctionWrapper(JSContext* cx, JSObject *jsthis, jsval fval)
  56. : _cx(cx)
  57. , _jsthis(jsthis)
  58. , _fval(fval)
  59. {
  60. JS::AddNamedValueRoot(cx, &this->_fval, "JSFunctionWrapper");
  61. JS::AddNamedObjectRoot(cx, &this->_jsthis, "JSFunctionWrapper");
  62. }
  63. JSFunctionWrapper::~JSFunctionWrapper()
  64. {
  65. JS::RemoveValueRoot(this->_cx, &this->_fval);
  66. JS::RemoveObjectRoot(this->_cx, &this->_jsthis);
  67. }
  68. bool JSFunctionWrapper::invoke(unsigned int argc, jsval *argv, JS::MutableHandleValue rval)
  69. {
  70. //JSB_AUTOCOMPARTMENT_WITH_GLOBAL_OBJCET
  71. return JS_CallFunctionValue(this->_cx, JS::RootedObject(_cx, this->_jsthis), JS::RootedValue(_cx, this->_fval), JS::HandleValueArray::fromMarkedLocation(argc, argv), rval);
  72. }
  73. bool jsval_to_int32( JSContext *cx, JS::HandleValue vp, int32_t *outval )
  74. {
  75. bool ok = true;
  76. double dp;
  77. ok &= JS::ToNumber(cx, vp, &dp);
  78. if (!ok) {
  79. LOGD("jsval_to_int32: the argument is not a number");
  80. return false;
  81. }
  82. ok &= !isnan(dp);
  83. JSB_PRECONDITION2(ok, cx, false, "Error processing arguments");
  84. *outval = (int32_t)dp;
  85. return ok;
  86. }
  87. bool jsval_to_uint32( JSContext *cx, JS::HandleValue vp, uint32_t *outval )
  88. {
  89. bool ok = true;
  90. double dp;
  91. ok &= JS::ToNumber(cx, vp, &dp);
  92. if (!ok) {
  93. LOGD("jsval_to_uint32: the argument is not a number");
  94. return false;
  95. }
  96. ok &= !isnan(dp);
  97. JSB_PRECONDITION2(ok, cx, false, "Error processing arguments");
  98. *outval = (uint32_t)dp;
  99. return ok;
  100. }
  101. bool jsval_to_uint16( JSContext *cx, JS::HandleValue vp, uint16_t *outval )
  102. {
  103. bool ok = true;
  104. double dp;
  105. ok &= JS::ToNumber(cx, vp, &dp);
  106. if (!ok) {
  107. LOGD("jsval_to_uint16: the argument is not a number");
  108. return false;
  109. }
  110. ok &= !isnan(dp);
  111. JSB_PRECONDITION2(ok, cx, false, "Error processing arguments");
  112. *outval = (uint16_t)dp;
  113. return ok;
  114. }
  115. bool jsval_to_long_long(JSContext *cx, JS::HandleValue vp, long long* r) {
  116. JS::RootedObject tmp_arg(cx);
  117. bool ok = JS_ValueToObject( cx, vp, &tmp_arg );
  118. if (!ok) {
  119. LOGD("jsval_to_long_long: Error converting value to object");
  120. return false;
  121. }
  122. JSB_PRECONDITION2( tmp_arg && JS_IsTypedArrayObject( tmp_arg ), cx, false, "Not a TypedArray object");
  123. JSB_PRECONDITION2( JS_GetTypedArrayByteLength( tmp_arg ) == sizeof(long long), cx, false, "Invalid Typed Array length");
  124. uint32_t* arg_array = (uint32_t*)JS_GetArrayBufferViewData( tmp_arg );
  125. long long ret = arg_array[0];
  126. ret = ret << 32;
  127. ret |= arg_array[1];
  128. *r = ret;
  129. return true;
  130. }
  131. bool jsval_to_long(JSContext *cx, JS::HandleValue vp, long* ret)
  132. {
  133. bool ok = true;
  134. double dp;
  135. ok &= JS::ToNumber(cx, vp, &dp);
  136. if (!ok) {
  137. LOGD("jsval_to_long: the argument is not a number");
  138. return false;
  139. }
  140. ok &= !isnan(dp);
  141. JSB_PRECONDITION2(ok, cx, false, "Error processing arguments");
  142. *ret = (long)dp;
  143. return ok;
  144. }
  145. bool jsval_to_std_string(JSContext *cx, JS::HandleValue v, std::string* ret) {
  146. JSString *tmp = JS::ToString(cx, v);
  147. if (!tmp) {
  148. LOGD("jsval_to_std_string: the jsval is not a string.");
  149. return false;
  150. }
  151. JSStringWrapper str(tmp, cx);
  152. *ret = str.get();
  153. return true;
  154. }
  155. bool jsval_to_TProductInfo(JSContext *cx, JS::HandleValue v, TProductInfo* ret)
  156. {
  157. JS::RootedObject tmp(cx, v.toObjectOrNull());
  158. if (!tmp) {
  159. LOGD("jsval_to_TProductInfo: the jsval is not an object.");
  160. return false;
  161. }
  162. JS::RootedObject it(cx, JS_NewPropertyIterator(cx, tmp));
  163. while (true)
  164. {
  165. jsid idp;
  166. JS::RootedValue key(cx);
  167. if (! JS_NextProperty(cx, it, &idp) || ! JS_IdToValue(cx, idp, &key))
  168. return false; // error
  169. if (key.isNullOrUndefined())
  170. break; // end of iteration
  171. if (! key.isString())
  172. continue; // ignore integer properties
  173. JS::RootedValue value(cx);
  174. JS_GetPropertyById(cx, tmp, JS::RootedId(cx, idp), &value);
  175. if (! value.isString())
  176. continue; // ignore integer properties
  177. JSStringWrapper strWrapper(key.toString(), cx);
  178. JSStringWrapper strWrapper2(value.toString(), cx);
  179. (*ret)[strWrapper.get()] = strWrapper2.get();
  180. LOGD("iterate object: key = %s, value = %s", strWrapper.get().c_str(), strWrapper2.get().c_str());
  181. }
  182. return true;
  183. }
  184. bool jsval_to_FBInfo(JSContext *cx, JS::HandleValue v, StringMap* ret)
  185. {
  186. JS::RootedObject tmp(cx, v.toObjectOrNull());
  187. if (!tmp) {
  188. LOGD("jsval_to_TProductInfo: the jsval is not an object.");
  189. return false;
  190. }
  191. JS::RootedObject it(cx, JS_NewPropertyIterator(cx, tmp));
  192. while (true)
  193. {
  194. jsid idp;
  195. JS::RootedValue key(cx);
  196. if (! JS_NextProperty(cx, it, &idp) || ! JS_IdToValue(cx, idp, &key))
  197. return false; // error
  198. if (key.isNullOrUndefined())
  199. break; // end of iteration
  200. if (! key.isString())
  201. continue; // ignore integer properties
  202. JS::RootedValue value(cx);
  203. JS_GetPropertyById(cx, tmp, JS::RootedId(cx, idp), &value);
  204. // if (! JSVAL_IS_STRING(value))
  205. // continue; // ignore integer properties
  206. if(value.isString())
  207. {
  208. JSStringWrapper strWrapper(key.toString(), cx);
  209. JSStringWrapper strWrapper2(value.toString(), cx);
  210. ret->insert(std::map<std::string, std::string>::value_type(strWrapper.get(), strWrapper2.get()));
  211. }
  212. else if(value.isNumber())
  213. {
  214. double number = 0.0;
  215. JS::ToNumber(cx, value, &number);
  216. std::stringstream ss;
  217. ss << number;
  218. JSStringWrapper strWrapper(key.toString(), cx);
  219. //JSStringWrapper strWrapper2(JSVAL_TO_STRING(value), cx);
  220. ret->insert(std::map<std::string, std::string>::value_type(strWrapper.get(), ss.str()));
  221. }
  222. else if(value.isBoolean())
  223. {
  224. bool boolVal = JS::ToBoolean(value);
  225. JSStringWrapper strWrapper(key.toString(), cx);
  226. //JSStringWrapper strWrapper2(JSVAL_TO_STRING(value), cx);
  227. std::string boolstring = boolVal ? "true" : "false";
  228. ret->insert(std::map<std::string, std::string>::value_type(strWrapper.get(), boolstring));
  229. }
  230. }
  231. return true;
  232. }
  233. bool jsval_array_to_string(JSContext *cx, JS::HandleValue v, std::string* ret)
  234. {
  235. JS::RootedObject jsobj(cx);
  236. bool ok = v.isObject() && JS_ValueToObject( cx, JS::RootedValue(cx, v), &jsobj );
  237. JSB_PRECONDITION2( ok, cx, false, "Error converting value to object");
  238. JSB_PRECONDITION2( jsobj && JS_IsArrayObject( cx, jsobj), cx, false, "Object must be an array");
  239. uint32_t len;
  240. JS_GetArrayLength(cx, jsobj, &len);
  241. for( uint32_t i=0; i< len;i++ ) {
  242. JS::RootedValue valarg(cx);
  243. JS_GetElement(cx, jsobj, i, &valarg);
  244. std::string temp;
  245. ok = jsval_to_std_string(cx, valarg, &temp);
  246. JSB_PRECONDITION2(ok, cx, false, "Error processing arguments");
  247. if(i != len -1)
  248. ret->append(temp + ",");
  249. else
  250. ret->append(temp);
  251. }
  252. return true;
  253. }
  254. bool jsval_to_TIAPDeveloperInfo(JSContext *cx, JS::HandleValue v, TIAPDeveloperInfo* ret)
  255. {
  256. return jsval_to_TProductInfo(cx, v, ret);
  257. }
  258. bool jsval_to_TAdsDeveloperInfo(JSContext *cx, JS::HandleValue v, TAdsDeveloperInfo* ret)
  259. {
  260. return jsval_to_TProductInfo(cx, v, ret);
  261. }
  262. bool jsval_to_TAdsInfo(JSContext *cx, JS::HandleValue v, TAdsInfo* ret)
  263. {
  264. return jsval_to_TProductInfo(cx, v, ret);
  265. }
  266. bool jsval_to_TShareDeveloperInfo(JSContext *cx, JS::HandleValue v, TShareDeveloperInfo* ret)
  267. {
  268. return jsval_to_TProductInfo(cx, v, ret);
  269. }
  270. bool jsval_to_TShareInfo(JSContext *cx, JS::HandleValue v, TShareInfo* ret)
  271. {
  272. return jsval_to_TProductInfo(cx, v, ret);
  273. }
  274. bool jsval_to_TPaymentInfo(JSContext *cx, JS::HandleValue v, std::map<std::string, std::string>* ret)
  275. {
  276. return jsval_to_TProductInfo(cx, v, ret);
  277. }
  278. bool jsval_to_TSocialDeveloperInfo(JSContext *cx, JS::HandleValue v, TSocialDeveloperInfo* ret)
  279. {
  280. return jsval_to_TProductInfo(cx, v, ret);
  281. }
  282. bool jsval_to_TAchievementInfo(JSContext *cx, JS::HandleValue v, TAchievementInfo* ret)
  283. {
  284. return jsval_to_TProductInfo(cx, v, ret);
  285. }
  286. bool jsval_to_TUserDeveloperInfo(JSContext *cx, JS::HandleValue v, TUserDeveloperInfo* ret)
  287. {
  288. return jsval_to_TProductInfo(cx, v, ret);
  289. }
  290. bool jsval_to_LogEventParamMap(JSContext *cx, JS::HandleValue v, LogEventParamMap** ret)
  291. {
  292. bool jsret = false;
  293. if (v.isObject())
  294. {
  295. LogEventParamMap* tmp = new LogEventParamMap();
  296. jsret = jsval_to_TProductInfo(cx, v, tmp);
  297. if (jsret) {
  298. *ret = tmp;
  299. }
  300. }
  301. return jsret;
  302. }
  303. bool jsval_to_StringMap(JSContext *cx, JS::HandleValue v, StringMap* ret)
  304. {
  305. return jsval_to_TProductInfo(cx, v, ret);
  306. }
  307. bool jsval_to_std_map_string_string(JSContext *cx, JS::HandleValue v, std::map<std::string, std::string>* ret)
  308. {
  309. if (v.isNullOrUndefined())
  310. {
  311. return true;
  312. }
  313. JS::RootedObject tmp(cx, v.toObjectOrNull());
  314. if (!tmp) {
  315. CCLOG("%s", "jsval_to_ccvaluemap: the jsval is not an object.");
  316. return false;
  317. }
  318. JS::RootedObject it(cx, JS_NewPropertyIterator(cx, tmp));
  319. while (true)
  320. {
  321. jsid idp;
  322. JS::RootedValue key(cx);
  323. if (! JS_NextProperty(cx, it, &idp) || ! JS_IdToValue(cx, idp, &key)) {
  324. return false; // error
  325. }
  326. if (key.isNullOrUndefined()) {
  327. break; // end of iteration
  328. }
  329. if (!key.isString()) {
  330. continue; // ignore integer properties
  331. }
  332. JSStringWrapper keyWrapper(key.toString(), cx);
  333. JS::RootedValue value(cx);
  334. JS_GetPropertyById(cx, tmp, JS::RootedId(cx, idp), &value);
  335. if (value.isString())
  336. {
  337. JSStringWrapper valueWapper(value.toString(), cx);
  338. ret->insert(std::make_pair(keyWrapper.get(), valueWapper.get()));
  339. }
  340. else
  341. {
  342. CCASSERT(false, "not a string");
  343. }
  344. }
  345. return true;
  346. }
  347. // From native type to jsval
  348. jsval int32_to_jsval( JSContext *cx, int32_t number )
  349. {
  350. return INT_TO_JSVAL(number);
  351. }
  352. jsval uint32_to_jsval( JSContext *cx, uint32_t number )
  353. {
  354. return UINT_TO_JSVAL(number);
  355. }
  356. jsval long_long_to_jsval(JSContext* cx, long long v) {
  357. JSObject *tmp = JS_NewUint32Array(cx, 2);
  358. uint32_t *data = (uint32_t *)JS_GetArrayBufferViewData(tmp);
  359. data[0] = ((uint32_t *)(&v))[0];
  360. data[1] = ((uint32_t *)(&v))[1];
  361. return OBJECT_TO_JSVAL(tmp);
  362. }
  363. jsval long_to_jsval(JSContext* cx, long v)
  364. {
  365. return INT_TO_JSVAL(v);
  366. }
  367. jsval std_string_to_jsval(JSContext* cx, const std::string& v) {
  368. return c_string_to_jsval(cx, v.data());
  369. }
  370. jsval c_string_to_jsval(JSContext* cx, const char* v, size_t length /* = -1 */) {
  371. if (v == NULL) {
  372. return JSVAL_NULL;
  373. }
  374. jsval ret = JSVAL_NULL;
  375. int utf16_size = 0;
  376. jschar* strUTF16 = (jschar*)cc_utf8_to_utf16(v, length, &utf16_size);
  377. if (strUTF16 && utf16_size > 0) {
  378. JSString* str = JS_NewUCStringCopyN(cx, strUTF16, utf16_size);
  379. if (str) {
  380. ret = STRING_TO_JSVAL(str);
  381. }
  382. delete[] strUTF16;
  383. }
  384. return ret;
  385. }
  386. jsval TProductInfo_to_jsval(JSContext *cx, TProductInfo& ret)
  387. {
  388. JS::RootedObject tmp(cx, JS_NewObject(cx, nullptr, JS::NullPtr(), JS::NullPtr()));
  389. if (!tmp) return JSVAL_NULL;
  390. for (TProductInfo::iterator it = ret.begin(); it != ret.end(); ++it)
  391. {
  392. JS_DefineProperty(cx, tmp, it->first.c_str(), JS::RootedValue(cx, std_string_to_jsval(cx, it->second)), JSPROP_ENUMERATE | JSPROP_PERMANENT);
  393. }
  394. return OBJECT_TO_JSVAL(tmp);
  395. }
  396. jsval TProductList_to_jsval(JSContext *cx,TProductList list){
  397. JS::RootedObject tmp(cx, JS_NewArrayObject(cx, 0));
  398. int i = 0;
  399. for(TProductList::iterator it = list.begin();it!=list.end();++it){
  400. JS::RootedValue arrElement(cx);
  401. arrElement = TProductInfo_to_jsval(cx, *it);
  402. JS_SetElement(cx, tmp, i, arrElement);
  403. ++i;
  404. }
  405. return OBJECT_TO_JSVAL(tmp);
  406. }
  407. jsval LogEventParamMap_to_jsval(JSContext *cx, LogEventParamMap*& ret)
  408. {// TODO:
  409. return JSVAL_NULL;
  410. }
  411. }// namespace pluginx {