jsb_global.cpp 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305
  1. /****************************************************************************
  2. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
  3. http://www.cocos.com
  4. Permission is hereby granted, free of charge, to any person obtaining a copy
  5. of this software and associated engine source code (the "Software"), a limited,
  6. worldwide, royalty-free, non-assignable, revocable and non-exclusive license
  7. to use Cocos Creator solely to develop games on your target platforms. You shall
  8. not use Cocos Creator software for developing other software or tools that's
  9. used for developing games. You are not granted to publish, distribute,
  10. sublicense, and/or sell copies of Cocos Creator.
  11. The software or tools in this License Agreement are licensed, not sold.
  12. Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
  13. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  18. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  19. THE SOFTWARE.
  20. ****************************************************************************/
  21. #include "jsb_global.h"
  22. #include "jsb_conversions.hpp"
  23. #include "xxtea/xxtea.h"
  24. #include "base/CCScheduler.h"
  25. #include "base/CCThreadPool.h"
  26. #include "network/HttpClient.h"
  27. #include "platform/CCApplication.h"
  28. #include "ui/edit-box/EditBox.h"
  29. #if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID
  30. #include "platform/android/jni/JniImp.h"
  31. #endif
  32. #include <regex>
  33. using namespace cocos2d;
  34. se::Object* __jsbObj = nullptr;
  35. se::Object* __glObj = nullptr;
  36. static std::shared_ptr<ThreadPool> g_threadPool;
  37. static std::shared_ptr<cocos2d::network::Downloader> g_localDownloader = nullptr;
  38. static std::map<std::string, std::function<void(const std::string&, unsigned char*, int ,const std::string&)>> g_localDownloaderHandlers;
  39. static uint64_t g_localDownloaderTaskId = 1000000;
  40. static std::string xxteaKey = "";
  41. void jsb_set_xxtea_key(const std::string& key)
  42. {
  43. xxteaKey = key;
  44. }
  45. static cocos2d::network::Downloader *localDownloader()
  46. {
  47. if(!g_localDownloader)
  48. {
  49. g_localDownloader = std::make_shared<cocos2d::network::Downloader>();
  50. g_localDownloader->onDataTaskSuccess = [=](const cocos2d::network::DownloadTask& task,
  51. std::vector<unsigned char>& data) {
  52. if(data.empty())
  53. {
  54. SE_REPORT_ERROR("Getting image from (%s) failed!", task.requestURL.c_str());
  55. return;
  56. }
  57. auto callback = g_localDownloaderHandlers.find(task.identifier);
  58. if(callback == g_localDownloaderHandlers.end())
  59. {
  60. SE_REPORT_ERROR("Getting image from (%s), callback not found!!", task.requestURL.c_str());
  61. return;
  62. }
  63. size_t imageBytes = data.size();
  64. unsigned char* imageData = (unsigned char*)malloc(imageBytes);
  65. memcpy(imageData, data.data(), imageBytes);
  66. (callback->second)("", imageData, imageBytes, "");
  67. //initImageFunc("", imageData, imageBytes);
  68. g_localDownloaderHandlers.erase(callback);
  69. };
  70. g_localDownloader->onTaskError = [=](const cocos2d::network::DownloadTask& task,
  71. int errorCode,
  72. int errorCodeInternal,
  73. const std::string& errorStr) {
  74. SE_REPORT_ERROR("Getting image from (%s) failed!", task.requestURL.c_str());
  75. auto callback = g_localDownloaderHandlers.find(task.identifier);
  76. if(callback == g_localDownloaderHandlers.end())
  77. {
  78. SE_REPORT_ERROR("Getting image from (%s), callback not found!!", task.requestURL.c_str());
  79. return;
  80. }
  81. (callback->second)("", nullptr, 0, errorStr);
  82. g_localDownloaderHandlers.erase(task.identifier);
  83. };
  84. }
  85. return g_localDownloader.get();
  86. }
  87. static void localDownloaderCreateTask(const std::string &url, std::function<void(const std::string&, unsigned char*, int, const std::string&)> callback)
  88. {
  89. std::stringstream ss;
  90. ss << "jsb_loadimage_" << (g_localDownloaderTaskId++);
  91. std::string key = ss.str();
  92. auto task = localDownloader()->createDownloadDataTask(url, key);
  93. g_localDownloaderHandlers.emplace(std::make_pair(task->identifier, callback));
  94. }
  95. static const char* BYTE_CODE_FILE_EXT = ".jsc";
  96. static std::string removeFileExt(const std::string& filePath)
  97. {
  98. size_t pos = filePath.rfind('.');
  99. if (0 < pos)
  100. {
  101. return filePath.substr(0, pos);
  102. }
  103. return filePath;
  104. }
  105. void jsb_init_file_operation_delegate()
  106. {
  107. static se::ScriptEngine::FileOperationDelegate delegate;
  108. if (!delegate.isValid())
  109. {
  110. delegate.onGetDataFromFile = [](const std::string& path, const std::function<void(const uint8_t*, size_t)>& readCallback) -> void{
  111. assert(!path.empty());
  112. Data fileData;
  113. std::string byteCodePath = removeFileExt(path) + BYTE_CODE_FILE_EXT;
  114. if (FileUtils::getInstance()->isFileExist(byteCodePath)) {
  115. fileData = FileUtils::getInstance()->getDataFromFile(byteCodePath);
  116. size_t dataLen = 0;
  117. uint8_t* data = xxtea_decrypt((unsigned char*)fileData.getBytes(), (uint32_t)fileData.getSize(), (unsigned char*)xxteaKey.c_str(), (uint32_t)xxteaKey.size(), (uint32_t*)&dataLen);
  118. if (data == nullptr) {
  119. SE_REPORT_ERROR("Can't decrypt code for %s", byteCodePath.c_str());
  120. return;
  121. }
  122. if (ZipUtils::isGZipBuffer(data,dataLen)) {
  123. uint8_t* unpackedData;
  124. ssize_t unpackedLen = ZipUtils::inflateMemory(data, dataLen,&unpackedData);
  125. if (unpackedData == nullptr) {
  126. SE_REPORT_ERROR("Can't decrypt code for %s", byteCodePath.c_str());
  127. return;
  128. }
  129. readCallback(unpackedData, unpackedLen);
  130. free(data);
  131. free(unpackedData);
  132. }
  133. else {
  134. readCallback(data, dataLen);
  135. free(data);
  136. }
  137. return;
  138. }
  139. fileData = FileUtils::getInstance()->getDataFromFile(path);
  140. readCallback(fileData.getBytes(), fileData.getSize());
  141. };
  142. delegate.onGetStringFromFile = [](const std::string& path) -> std::string{
  143. assert(!path.empty());
  144. std::string byteCodePath = removeFileExt(path) + BYTE_CODE_FILE_EXT;
  145. if (FileUtils::getInstance()->isFileExist(byteCodePath)) {
  146. Data fileData = FileUtils::getInstance()->getDataFromFile(byteCodePath);
  147. uint32_t dataLen;
  148. uint8_t* data = xxtea_decrypt((uint8_t*)fileData.getBytes(), (uint32_t)fileData.getSize(), (uint8_t*)xxteaKey.c_str(), (uint32_t)xxteaKey.size(), &dataLen);
  149. if (data == nullptr) {
  150. SE_REPORT_ERROR("Can't decrypt code for %s", byteCodePath.c_str());
  151. return "";
  152. }
  153. if (ZipUtils::isGZipBuffer(data,dataLen)) {
  154. uint8_t* unpackedData;
  155. ssize_t unpackedLen = ZipUtils::inflateMemory(data, dataLen,&unpackedData);
  156. if (unpackedData == nullptr) {
  157. SE_REPORT_ERROR("Can't decrypt code for %s", byteCodePath.c_str());
  158. return "";
  159. }
  160. std::string ret(reinterpret_cast<const char*>(unpackedData), unpackedLen);
  161. free(unpackedData);
  162. free(data);
  163. return ret;
  164. }
  165. else {
  166. std::string ret(reinterpret_cast<const char*>(data), dataLen);
  167. free(data);
  168. return ret;
  169. }
  170. }
  171. if (FileUtils::getInstance()->isFileExist(path)) {
  172. return FileUtils::getInstance()->getStringFromFile(path);
  173. }
  174. else {
  175. SE_LOGE("ScriptEngine::onGetStringFromFile %s not found, possible missing file.\n", path.c_str());
  176. }
  177. return "";
  178. };
  179. delegate.onGetFullPath = [](const std::string& path) -> std::string{
  180. assert(!path.empty());
  181. std::string byteCodePath = removeFileExt(path) + BYTE_CODE_FILE_EXT;
  182. if (FileUtils::getInstance()->isFileExist(byteCodePath)) {
  183. return FileUtils::getInstance()->fullPathForFilename(byteCodePath);
  184. }
  185. return FileUtils::getInstance()->fullPathForFilename(path);
  186. };
  187. delegate.onCheckFileExist = [](const std::string& path) -> bool{
  188. assert(!path.empty());
  189. return FileUtils::getInstance()->isFileExist(path);
  190. };
  191. assert(delegate.isValid());
  192. se::ScriptEngine::getInstance()->setFileOperationDelegate(delegate);
  193. }
  194. }
  195. bool jsb_enable_debugger(const std::string& debuggerServerAddr, uint32_t port, bool isWaitForConnect)
  196. {
  197. if (debuggerServerAddr.empty() || port == 0)
  198. return false;
  199. auto se = se::ScriptEngine::getInstance();
  200. se->enableDebugger(debuggerServerAddr.c_str(), port, isWaitForConnect);
  201. // For debugger main loop
  202. class SimpleRunLoop
  203. {
  204. public:
  205. void update(float dt)
  206. {
  207. se::ScriptEngine::getInstance()->mainLoopUpdate();
  208. }
  209. };
  210. // static SimpleRunLoop runLoop;
  211. //cjh IDEA: Director::getInstance()->getScheduler()->scheduleUpdate(&runLoop, 0, false);
  212. return true;
  213. }
  214. bool jsb_set_extend_property(const char* ns, const char* clsName)
  215. {
  216. se::Object* globalObj = se::ScriptEngine::getInstance()->getGlobalObject();
  217. se::Value nsVal;
  218. if (globalObj->getProperty(ns, &nsVal) && nsVal.isObject())
  219. {
  220. se::Value ccVal;
  221. if (globalObj->getProperty("cc", &ccVal) && ccVal.isObject())
  222. {
  223. se::Value ccClassVal;
  224. if (ccVal.toObject()->getProperty("Class", &ccClassVal) && ccClassVal.isObject())
  225. {
  226. se::Value extendVal;
  227. if (ccClassVal.toObject()->getProperty("extend", &extendVal) && extendVal.isObject() && extendVal.toObject()->isFunction())
  228. {
  229. se::Value targetClsVal;
  230. if (nsVal.toObject()->getProperty(clsName, &targetClsVal) && targetClsVal.isObject())
  231. {
  232. return targetClsVal.toObject()->setProperty("extend", extendVal);
  233. }
  234. }
  235. }
  236. }
  237. }
  238. return false;
  239. }
  240. namespace {
  241. std::unordered_map<std::string, se::Value> __moduleCache;
  242. static bool require(se::State& s)
  243. {
  244. const auto& args = s.args();
  245. int argc = (int)args.size();
  246. assert(argc >= 1);
  247. assert(args[0].isString());
  248. return jsb_run_script(args[0].toString(), &s.rval());
  249. }
  250. SE_BIND_FUNC(require)
  251. static bool doModuleRequire(const std::string& path, se::Value* ret, const std::string& prevScriptFileDir)
  252. {
  253. se::AutoHandleScope hs;
  254. assert(!path.empty());
  255. const auto& fileOperationDelegate = se::ScriptEngine::getInstance()->getFileOperationDelegate();
  256. assert(fileOperationDelegate.isValid());
  257. std::string fullPath;
  258. std::string pathWithSuffix = path;
  259. if (pathWithSuffix.rfind(".js") != (pathWithSuffix.length() - 3))
  260. pathWithSuffix += ".js";
  261. std::string scriptBuffer = fileOperationDelegate.onGetStringFromFile(pathWithSuffix);
  262. if (scriptBuffer.empty() && !prevScriptFileDir.empty())
  263. {
  264. std::string secondPath = prevScriptFileDir;
  265. if (secondPath[secondPath.length()-1] != '/')
  266. secondPath += "/";
  267. secondPath += path;
  268. if (FileUtils::getInstance()->isDirectoryExist(secondPath))
  269. {
  270. if (secondPath[secondPath.length()-1] != '/')
  271. secondPath += "/";
  272. secondPath += "index.js";
  273. }
  274. else
  275. {
  276. if (path.rfind(".js") != (path.length() - 3))
  277. secondPath += ".js";
  278. }
  279. fullPath = fileOperationDelegate.onGetFullPath(secondPath);
  280. scriptBuffer = fileOperationDelegate.onGetStringFromFile(fullPath);
  281. }
  282. else
  283. {
  284. fullPath = fileOperationDelegate.onGetFullPath(pathWithSuffix);
  285. }
  286. if (!scriptBuffer.empty())
  287. {
  288. const auto& iter = __moduleCache.find(fullPath);
  289. if (iter != __moduleCache.end())
  290. {
  291. *ret = iter->second;
  292. // printf("Found cache: %s, value: %d\n", fullPath.c_str(), (int)ret->getType());
  293. return true;
  294. }
  295. std::string currentScriptFileDir = FileUtils::getInstance()->getFileDir(fullPath);
  296. // Add closure for evalutate the script
  297. char prefix[] = "(function(currentScriptDir){ window.module = window.module || {}; var exports = window.module.exports = {}; ";
  298. char suffix[512] = {0};
  299. snprintf(suffix, sizeof(suffix), "\nwindow.module.exports = window.module.exports || exports;\n})('%s'); ", currentScriptFileDir.c_str());
  300. // Add current script path to require function invocation
  301. scriptBuffer = prefix + std::regex_replace(scriptBuffer, std::regex("([^A-Za-z0-9]|^)requireModule\\((.*?)\\)"), "$1requireModule($2, currentScriptDir)") + suffix;
  302. // FILE* fp = fopen("/Users/james/Downloads/test.txt", "wb");
  303. // fwrite(scriptBuffer.c_str(), scriptBuffer.length(), 1, fp);
  304. // fclose(fp);
  305. std::string reletivePath = fullPath;
  306. #if CC_TARGET_PLATFORM == CC_PLATFORM_MAC || CC_TARGET_PLATFORM == CC_PLATFORM_IOS
  307. #if CC_TARGET_PLATFORM == CC_PLATFORM_MAC
  308. const std::string reletivePathKey = "/Contents/Resources";
  309. #else
  310. const std::string reletivePathKey = ".app";
  311. #endif
  312. size_t pos = reletivePath.find(reletivePathKey);
  313. if (pos != std::string::npos)
  314. {
  315. reletivePath = reletivePath.substr(pos + reletivePathKey.length() + 1);
  316. }
  317. #endif
  318. // RENDERER_LOGD("Evaluate: %s", fullPath.c_str());
  319. auto se = se::ScriptEngine::getInstance();
  320. bool succeed = se->evalString(scriptBuffer.c_str(), scriptBuffer.length(), nullptr, reletivePath.c_str());
  321. se::Value moduleVal;
  322. if (succeed && se->getGlobalObject()->getProperty("module", &moduleVal) && moduleVal.isObject())
  323. {
  324. se::Value exportsVal;
  325. if (moduleVal.toObject()->getProperty("exports", &exportsVal))
  326. {
  327. if (ret != nullptr)
  328. *ret = exportsVal;
  329. __moduleCache[fullPath] = std::move(exportsVal);
  330. }
  331. else
  332. {
  333. __moduleCache[fullPath] = se::Value::Undefined;
  334. }
  335. // clear module.exports
  336. moduleVal.toObject()->setProperty("exports", se::Value::Undefined);
  337. }
  338. else
  339. {
  340. __moduleCache[fullPath] = se::Value::Undefined;
  341. }
  342. assert(succeed);
  343. return succeed;
  344. }
  345. SE_LOGE("doModuleRequire %s, buffer is empty!\n", path.c_str());
  346. assert(false);
  347. return false;
  348. }
  349. static bool moduleRequire(se::State& s)
  350. {
  351. const auto& args = s.args();
  352. int argc = (int)args.size();
  353. assert(argc >= 2);
  354. assert(args[0].isString());
  355. assert(args[1].isString());
  356. return doModuleRequire(args[0].toString(), &s.rval(), args[1].toString());
  357. }
  358. SE_BIND_FUNC(moduleRequire)
  359. } // namespace {
  360. bool jsb_run_script(const std::string& filePath, se::Value* rval/* = nullptr */)
  361. {
  362. se::AutoHandleScope hs;
  363. return se::ScriptEngine::getInstance()->runScript(filePath, rval);
  364. }
  365. bool jsb_run_script_module(const std::string& filePath, se::Value* rval/* = nullptr */)
  366. {
  367. return doModuleRequire(filePath, rval, "");
  368. }
  369. static bool jsc_garbageCollect(se::State& s)
  370. {
  371. se::ScriptEngine::getInstance()->garbageCollect();
  372. return true;
  373. }
  374. SE_BIND_FUNC(jsc_garbageCollect)
  375. static bool jsc_dumpNativePtrToSeObjectMap(se::State& s)
  376. {
  377. cocos2d::log(">>> total: %d, Dump (native -> jsobj) map begin", (int)se::NativePtrToObjectMap::size());
  378. struct NamePtrStruct
  379. {
  380. const char* name;
  381. void* ptr;
  382. };
  383. std::vector<NamePtrStruct> namePtrArray;
  384. for (const auto& e : se::NativePtrToObjectMap::instance())
  385. {
  386. se::Object* jsobj = e.second;
  387. assert(jsobj->_getClass() != nullptr);
  388. NamePtrStruct tmp;
  389. tmp.name = jsobj->_getClass()->getName();
  390. tmp.ptr = e.first;
  391. namePtrArray.push_back(tmp);
  392. }
  393. std::sort(namePtrArray.begin(), namePtrArray.end(), [](const NamePtrStruct& a, const NamePtrStruct& b) -> bool {
  394. std::string left = a.name;
  395. std::string right = b.name;
  396. for( std::string::const_iterator lit = left.begin(), rit = right.begin(); lit != left.end() && rit != right.end(); ++lit, ++rit )
  397. if( ::tolower( *lit ) < ::tolower( *rit ) )
  398. return true;
  399. else if( ::tolower( *lit ) > ::tolower( *rit ) )
  400. return false;
  401. if( left.size() < right.size() )
  402. return true;
  403. return false;
  404. });
  405. for (const auto& e : namePtrArray)
  406. {
  407. cocos2d::log("%s: %p", e.name, e.ptr);
  408. }
  409. cocos2d::log(">>> total: %d, nonRefMap: %d, Dump (native -> jsobj) map end", (int)se::NativePtrToObjectMap::size(), (int)se::NonRefNativePtrCreatedByCtorMap::size());
  410. return true;
  411. }
  412. SE_BIND_FUNC(jsc_dumpNativePtrToSeObjectMap)
  413. static bool jsc_dumpRoot(se::State& s)
  414. {
  415. assert(false);
  416. return true;
  417. }
  418. SE_BIND_FUNC(jsc_dumpRoot)
  419. static bool JSBCore_platform(se::State& s)
  420. {
  421. Application::Platform platform = Application::getInstance()->getPlatform();
  422. s.rval().setInt32((int32_t)platform);
  423. return true;
  424. }
  425. SE_BIND_FUNC(JSBCore_platform)
  426. static bool JSBCore_version(se::State& s)
  427. {
  428. //cjh char version[256];
  429. // snprintf(version, sizeof(version)-1, "%s", cocos2dVersion());
  430. //
  431. // s.rval().setString(version);
  432. return true;
  433. }
  434. SE_BIND_FUNC(JSBCore_version)
  435. static bool JSBCore_os(se::State& s)
  436. {
  437. se::Value os;
  438. // osx, ios, android, windows, linux, etc..
  439. #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
  440. os.setString("iOS");
  441. #elif (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
  442. os.setString("Android");
  443. #elif (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
  444. os.setString("Windows");
  445. #elif (CC_TARGET_PLATFORM == CC_PLATFORM_MARMALADE)
  446. os.setString("Marmalade");
  447. #elif (CC_TARGET_PLATFORM == CC_PLATFORM_LINUX)
  448. os.setString("Linux");
  449. #elif (CC_TARGET_PLATFORM == CC_PLATFORM_BADA)
  450. os.setString("Bada");
  451. #elif (CC_TARGET_PLATFORM == CC_PLATFORM_BLACKBERRY)
  452. os.setString("Blackberry");
  453. #elif (CC_TARGET_PLATFORM == CC_PLATFORM_MAC)
  454. os.setString("OS X");
  455. #elif (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
  456. os.setString("WINRT");
  457. #else
  458. os.setString("Unknown");
  459. #endif
  460. s.rval() = os;
  461. return true;
  462. }
  463. SE_BIND_FUNC(JSBCore_os)
  464. static bool JSBCore_getCurrentLanguage(se::State& s)
  465. {
  466. std::string languageStr;
  467. Application::LanguageType language = Application::getInstance()->getCurrentLanguage();
  468. switch (language)
  469. {
  470. case Application::LanguageType::ENGLISH:
  471. languageStr = "en";
  472. break;
  473. case Application::LanguageType::CHINESE:
  474. languageStr = "zh";
  475. break;
  476. case Application::LanguageType::FRENCH:
  477. languageStr = "fr";
  478. break;
  479. case Application::LanguageType::ITALIAN:
  480. languageStr = "it";
  481. break;
  482. case Application::LanguageType::GERMAN:
  483. languageStr = "de";
  484. break;
  485. case Application::LanguageType::SPANISH:
  486. languageStr = "es";
  487. break;
  488. case Application::LanguageType::DUTCH:
  489. languageStr = "du";
  490. break;
  491. case Application::LanguageType::RUSSIAN:
  492. languageStr = "ru";
  493. break;
  494. case Application::LanguageType::KOREAN:
  495. languageStr = "ko";
  496. break;
  497. case Application::LanguageType::JAPANESE:
  498. languageStr = "ja";
  499. break;
  500. case Application::LanguageType::HUNGARIAN:
  501. languageStr = "hu";
  502. break;
  503. case Application::LanguageType::PORTUGUESE:
  504. languageStr = "pt";
  505. break;
  506. case Application::LanguageType::ARABIC:
  507. languageStr = "ar";
  508. break;
  509. case Application::LanguageType::NORWEGIAN:
  510. languageStr = "no";
  511. break;
  512. case Application::LanguageType::POLISH:
  513. languageStr = "pl";
  514. break;
  515. case Application::LanguageType::TURKISH:
  516. languageStr = "tr";
  517. break;
  518. case Application::LanguageType::UKRAINIAN:
  519. languageStr = "uk";
  520. break;
  521. case Application::LanguageType::ROMANIAN:
  522. languageStr = "ro";
  523. break;
  524. case Application::LanguageType::BULGARIAN:
  525. languageStr = "bg";
  526. break;
  527. default:
  528. languageStr = "unknown";
  529. break;
  530. }
  531. s.rval().setString(languageStr);
  532. return true;
  533. }
  534. SE_BIND_FUNC(JSBCore_getCurrentLanguage)
  535. static bool JSBCore_getCurrentLanguageCode(se::State& s)
  536. {
  537. std::string language = Application::getInstance()->getCurrentLanguageCode();
  538. s.rval().setString(language);
  539. return true;
  540. }
  541. SE_BIND_FUNC(JSBCore_getCurrentLanguageCode)
  542. static bool JSB_getOSVersion(se::State& s)
  543. {
  544. std::string systemVersion = Application::getInstance()->getSystemVersion();
  545. s.rval().setString(systemVersion);
  546. return true;
  547. }
  548. SE_BIND_FUNC(JSB_getOSVersion)
  549. static bool JSB_cleanScript(se::State& s)
  550. {
  551. assert(false); //IDEA:
  552. return true;
  553. }
  554. SE_BIND_FUNC(JSB_cleanScript)
  555. static bool JSB_core_restartVM(se::State& s)
  556. {
  557. //REFINE: release AudioEngine, waiting HttpClient & WebSocket threads to exit.
  558. Application::getInstance()->restart();
  559. return true;
  560. }
  561. SE_BIND_FUNC(JSB_core_restartVM)
  562. static bool JSB_closeWindow(se::State& s)
  563. {
  564. Application::getInstance()->end();
  565. return true;
  566. }
  567. SE_BIND_FUNC(JSB_closeWindow)
  568. static bool JSB_isObjectValid(se::State& s)
  569. {
  570. const auto& args = s.args();
  571. int argc = (int)args.size();
  572. if (argc == 1)
  573. {
  574. void* nativePtr = nullptr;
  575. seval_to_native_ptr(args[0], &nativePtr);
  576. s.rval().setBoolean(nativePtr != nullptr);
  577. return true;
  578. }
  579. SE_REPORT_ERROR("Invalid number of arguments: %d. Expecting: 1", argc);
  580. return false;
  581. }
  582. SE_BIND_FUNC(JSB_isObjectValid)
  583. static bool getOrCreatePlainObject_r(const char* name, se::Object* parent, se::Object** outObj)
  584. {
  585. assert(parent != nullptr);
  586. assert(outObj != nullptr);
  587. se::Value tmp;
  588. if (parent->getProperty(name, &tmp) && tmp.isObject())
  589. {
  590. *outObj = tmp.toObject();
  591. (*outObj)->incRef();
  592. }
  593. else
  594. {
  595. *outObj = se::Object::createPlainObject();
  596. parent->setProperty(name, se::Value(*outObj));
  597. }
  598. return true;
  599. }
  600. static bool js_performance_now(se::State& s)
  601. {
  602. auto now = std::chrono::steady_clock::now();
  603. auto micro = std::chrono::duration_cast<std::chrono::microseconds>(now - se::ScriptEngine::getInstance()->getStartTime()).count();
  604. s.rval().setNumber((double)micro * 0.001);
  605. return true;
  606. }
  607. SE_BIND_FUNC(js_performance_now)
  608. namespace
  609. {
  610. struct ImageInfo
  611. {
  612. ~ImageInfo()
  613. {
  614. if (freeData)
  615. delete [] data;
  616. }
  617. uint32_t length = 0;
  618. uint32_t width = 0;
  619. uint32_t height = 0;
  620. uint8_t* data = nullptr;
  621. GLenum glFormat = GL_RGBA;
  622. GLenum glInternalFormat = GL_RGBA;
  623. GLenum type = GL_UNSIGNED_BYTE;
  624. uint8_t bpp = 0;
  625. uint8_t numberOfMipmaps = 0;
  626. bool hasAlpha = false;
  627. bool hasPremultipliedAlpha = false;
  628. bool compressed = false;
  629. bool freeData = false;
  630. };
  631. uint8_t* convertRGB2RGBA (uint32_t length, uint8_t* src) {
  632. uint8_t* dst = new uint8_t[length];
  633. for (uint32_t i = 0; i < length; i += 4) {
  634. dst[i] = *src++;
  635. dst[i + 1] = *src++;
  636. dst[i + 2] = *src++;
  637. dst[i + 3] = 255;
  638. }
  639. return dst;
  640. }
  641. uint8_t* convertIA2RGBA (uint32_t length, uint8_t* src) {
  642. uint8_t* dst = new uint8_t[length];
  643. for (uint32_t i = 0; i < length; i += 4) {
  644. dst[i] = *src;
  645. dst[i + 1] = *src;
  646. dst[i + 2] = *src++;
  647. dst[i + 3] = *src++;
  648. }
  649. return dst;
  650. }
  651. uint8_t* convertI2RGBA (uint32_t length, uint8_t* src) {
  652. uint8_t* dst = new uint8_t[length];
  653. for (uint32_t i = 0; i < length; i += 4) {
  654. dst[i] = *src;
  655. dst[i + 1] = *src;
  656. dst[i + 2] = *src++;
  657. dst[i + 3] = 255;
  658. }
  659. return dst;
  660. }
  661. struct ImageInfo* createImageInfo(const Image* img)
  662. {
  663. struct ImageInfo* imgInfo = new struct ImageInfo();
  664. imgInfo->length = (uint32_t)img->getDataLen();
  665. imgInfo->width = img->getWidth();
  666. imgInfo->height = img->getHeight();
  667. imgInfo->data = img->getData();
  668. const auto& pixelFormatInfo = img->getPixelFormatInfo();
  669. imgInfo->glFormat = pixelFormatInfo.format;
  670. imgInfo->glInternalFormat = pixelFormatInfo.internalFormat;
  671. imgInfo->type = pixelFormatInfo.type;
  672. imgInfo->bpp = img->getBitPerPixel();
  673. imgInfo->numberOfMipmaps = img->getNumberOfMipmaps();
  674. imgInfo->hasAlpha = img->hasAlpha();
  675. imgInfo->hasPremultipliedAlpha = img->hasPremultipliedAlpha();
  676. imgInfo->compressed = img->isCompressed();
  677. // Convert to RGBA888 because standard web api will return only RGBA888.
  678. // If not, then it may have issue in glTexSubImage. For example, engine
  679. // will create a big texture, and update its content with small pictures.
  680. // The big texture is RGBA888, then the small picture should be the same
  681. // format, or it will cause 0x502 error on OpenGL ES 2.
  682. if (!imgInfo->compressed && imgInfo->glFormat != GL_RGBA) {
  683. imgInfo->length = img->getWidth() * img->getHeight() * 4;
  684. uint8_t* dst = nullptr;
  685. uint32_t length = imgInfo->length;
  686. uint8_t* src = imgInfo->data;
  687. switch(imgInfo->glFormat) {
  688. case GL_LUMINANCE_ALPHA:
  689. dst = convertIA2RGBA(length, src);
  690. break;
  691. case GL_ALPHA:
  692. case GL_LUMINANCE:
  693. dst = convertI2RGBA(length, src);
  694. break;
  695. case GL_RGB:
  696. dst = convertRGB2RGBA(length, src);
  697. break;
  698. default:
  699. SE_LOGE("unknown image format");
  700. break;
  701. }
  702. imgInfo->data = dst;
  703. imgInfo->hasAlpha = true;
  704. imgInfo->bpp = 32;
  705. imgInfo->glFormat = GL_RGBA;
  706. imgInfo->glInternalFormat = GL_RGBA;
  707. imgInfo->freeData = true;
  708. }
  709. return imgInfo;
  710. }
  711. }
  712. bool jsb_global_load_image(const std::string& path, const se::Value& callbackVal) {
  713. if (path.empty())
  714. {
  715. se::ValueArray seArgs;
  716. callbackVal.toObject()->call(seArgs, nullptr);
  717. return true;
  718. }
  719. std::shared_ptr<se::Value> callbackPtr = std::make_shared<se::Value>(callbackVal);
  720. auto initImageFunc = [path, callbackPtr](const std::string& fullPath, unsigned char* imageData, int imageBytes, const std::string& errorMsg){
  721. std::shared_ptr<uint8_t> imageDataGuard(imageData, free);
  722. auto pool = g_threadPool;
  723. if (!pool)
  724. return;
  725. pool->pushTask([=](int tid) mutable {
  726. // NOTE: FileUtils::getInstance()->fullPathForFilename isn't a threadsafe method,
  727. // Image::initWithImageFile will call fullPathForFilename internally which may
  728. // cause thread race issues. Therefore, we get the full path of file before
  729. // going into task callback.
  730. // Be careful of invoking any Cocos2d-x interface in a sub-thread.
  731. bool loadSucceed = false;
  732. std::shared_ptr<Image> img(new Image(), [](Image *image) {
  733. image->release();
  734. });
  735. if (!errorMsg.empty()) {
  736. loadSucceed = false;
  737. }
  738. else if (fullPath.empty())
  739. {
  740. loadSucceed = img->initWithImageData(imageDataGuard.get(), imageBytes);
  741. imageDataGuard = nullptr;
  742. }
  743. else
  744. {
  745. loadSucceed = img->initWithImageFile(fullPath);
  746. }
  747. std::shared_ptr<ImageInfo> imgInfo;
  748. if(loadSucceed)
  749. {
  750. imgInfo.reset(createImageInfo(img.get()));
  751. }
  752. Application::getInstance()->getScheduler()->performFunctionInCocosThread([=]() mutable {
  753. se::AutoHandleScope hs;
  754. se::ValueArray seArgs;
  755. se::Value dataVal;
  756. if (loadSucceed)
  757. {
  758. se::HandleObject retObj(se::Object::createPlainObject());
  759. Data data;
  760. data.fastSet(imgInfo->data, imgInfo->length);
  761. Data_to_seval(data, &dataVal);
  762. data.takeBuffer();
  763. retObj->setProperty("data", dataVal);
  764. retObj->setProperty("width", se::Value(imgInfo->width));
  765. retObj->setProperty("height", se::Value(imgInfo->height));
  766. retObj->setProperty("premultiplyAlpha", se::Value(imgInfo->hasPremultipliedAlpha));
  767. retObj->setProperty("bpp", se::Value(imgInfo->bpp));
  768. retObj->setProperty("hasAlpha", se::Value(imgInfo->hasAlpha));
  769. retObj->setProperty("compressed", se::Value(imgInfo->compressed));
  770. retObj->setProperty("numberOfMipmaps", se::Value(imgInfo->numberOfMipmaps));
  771. if (imgInfo->numberOfMipmaps > 0)
  772. {
  773. se::HandleObject mipmapArray(se::Object::createArrayObject(imgInfo->numberOfMipmaps));
  774. retObj->setProperty("mipmaps", se::Value(mipmapArray));
  775. auto mipmapInfo = img->getMipmaps();
  776. for (int i = 0; i < imgInfo->numberOfMipmaps; ++i)
  777. {
  778. se::HandleObject info(se::Object::createPlainObject());
  779. info->setProperty("offset", se::Value(mipmapInfo[i].offset));
  780. info->setProperty("length", se::Value(mipmapInfo[i].len));
  781. mipmapArray->setArrayElement(i, se::Value(info));
  782. }
  783. }
  784. retObj->setProperty("glFormat", se::Value(imgInfo->glFormat));
  785. retObj->setProperty("glInternalFormat", se::Value(imgInfo->glInternalFormat));
  786. retObj->setProperty("glType", se::Value(imgInfo->type));
  787. seArgs.push_back(se::Value(retObj));
  788. imgInfo = nullptr;
  789. }
  790. else
  791. {
  792. SE_REPORT_ERROR("initWithImageFile: %s failed!", path.c_str());
  793. }
  794. if (!errorMsg.empty()) {
  795. se::HandleObject retObj(se::Object::createPlainObject());
  796. retObj->setProperty("errorMsg", se::Value(errorMsg));
  797. seArgs.push_back(se::Value(retObj));
  798. }
  799. callbackPtr->toObject()->call(seArgs, nullptr);
  800. img = nullptr;
  801. });
  802. });
  803. };
  804. size_t pos = std::string::npos;
  805. if (path.find("http://") == 0 || path.find("https://") == 0)
  806. {
  807. localDownloaderCreateTask(path, initImageFunc);
  808. }
  809. else if (path.find("data:") == 0 && (pos = path.find("base64,")) != std::string::npos)
  810. {
  811. int imageBytes = 0;
  812. unsigned char* imageData = nullptr;
  813. size_t dataStartPos = pos + strlen("base64,");
  814. const char* base64Data = path.data() + dataStartPos;
  815. size_t dataLen = path.length() - dataStartPos;
  816. imageBytes = base64Decode((const unsigned char *)base64Data, (unsigned int)dataLen, &imageData);
  817. if (imageBytes <= 0 || imageData == nullptr)
  818. {
  819. SE_REPORT_ERROR("Decode base64 image data failed!");
  820. return false;
  821. }
  822. initImageFunc("", imageData, imageBytes, "");
  823. }
  824. else
  825. {
  826. std::string fullPath(FileUtils::getInstance()->fullPathForFilename(path));
  827. if (0 == path.find("file://"))
  828. fullPath = FileUtils::getInstance()->fullPathForFilename(path.substr(strlen("file://")));
  829. if (fullPath.empty())
  830. {
  831. SE_REPORT_ERROR("File (%s) doesn't exist!", path.c_str());
  832. return false;
  833. }
  834. initImageFunc(fullPath, nullptr, 0, "");
  835. }
  836. return true;
  837. }
  838. static bool js_loadImage(se::State& s)
  839. {
  840. const auto& args = s.args();
  841. size_t argc = args.size();
  842. CC_UNUSED bool ok = true;
  843. if (argc == 2) {
  844. std::string path;
  845. ok &= seval_to_std_string(args[0], &path);
  846. SE_PRECONDITION2(ok, false, "js_loadImage : Error processing arguments");
  847. se::Value callbackVal = args[1];
  848. assert(callbackVal.isObject());
  849. assert(callbackVal.toObject()->isFunction());
  850. return jsb_global_load_image(path, callbackVal);
  851. }
  852. SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 2);
  853. return false;
  854. }
  855. SE_BIND_FUNC(js_loadImage)
  856. //pixels(RGBA), width, height, fullFilePath(*.png/*.jpg)
  857. static bool js_saveImageData(se::State& s)
  858. {
  859. const auto& args = s.args();
  860. size_t argc = args.size();
  861. CC_UNUSED bool ok = true;
  862. if (argc == 4) {
  863. cocos2d::Data data;
  864. ok &= seval_to_Data(args[0], &data);
  865. uint32_t width, height;
  866. ok &= seval_to_uint32(args[1], &width);
  867. ok &= seval_to_uint32(args[2], &height);
  868. std::string filePath;
  869. ok &= seval_to_std_string(args[3], &filePath);
  870. SE_PRECONDITION2(ok, false, "js_saveImageData : Error processing arguments");
  871. Image* img = new Image();
  872. img->initWithRawData(data.getBytes(), data.getSize(), width, height, 8);
  873. // isToRGB = false, to keep alpha channel
  874. bool ret = img->saveToFile(filePath, false);
  875. s.rval().setBoolean(ret);
  876. img->release();
  877. return ret;
  878. }
  879. SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 2);
  880. return false;
  881. }
  882. SE_BIND_FUNC(js_saveImageData)
  883. static bool js_setDebugViewText(se::State& s)
  884. {
  885. const auto& args = s.args();
  886. size_t argc = args.size();
  887. CC_UNUSED bool ok = true;
  888. if (argc == 2) {
  889. int32_t index;
  890. ok = seval_to_int32(args[0], &index);
  891. SE_PRECONDITION2(ok, false, "Convert arg0 index failed!");
  892. std::string text;
  893. ok = seval_to_std_string(args[1], &text);
  894. SE_PRECONDITION2(ok, false, "Convert arg1 text failed!");
  895. #if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID
  896. setGameInfoDebugViewTextJNI(index, text);
  897. #endif
  898. return true;
  899. }
  900. SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 2);
  901. return false;
  902. }
  903. SE_BIND_FUNC(js_setDebugViewText)
  904. static bool js_openDebugView(se::State& s)
  905. {
  906. #if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID
  907. openDebugViewJNI();
  908. #endif
  909. return true;
  910. }
  911. SE_BIND_FUNC(js_openDebugView)
  912. static bool js_disableBatchGLCommandsToNative(se::State& s)
  913. {
  914. #if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID
  915. disableBatchGLCommandsToNativeJNI();
  916. #endif
  917. return true;
  918. }
  919. SE_BIND_FUNC(js_disableBatchGLCommandsToNative)
  920. static bool JSB_openURL(se::State& s)
  921. {
  922. const auto& args = s.args();
  923. size_t argc = args.size();
  924. CC_UNUSED bool ok = true;
  925. if (argc > 0) {
  926. std::string url;
  927. ok = seval_to_std_string(args[0], &url);
  928. SE_PRECONDITION2(ok, false, "url is invalid!");
  929. Application::getInstance()->openURL(url);
  930. return true;
  931. }
  932. SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 1);
  933. return false;
  934. }
  935. SE_BIND_FUNC(JSB_openURL)
  936. static bool JSB_copyTextToClipboard(se::State& s)
  937. {
  938. const auto& args = s.args();
  939. size_t argc = args.size();
  940. CC_UNUSED bool ok = true;
  941. if (argc > 0) {
  942. std::string text;
  943. ok = seval_to_std_string(args[0], &text);
  944. SE_PRECONDITION2(ok, false, "text is invalid!");
  945. Application::getInstance()->copyTextToClipboard(text);
  946. return true;
  947. }
  948. SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 1);
  949. return false;
  950. }
  951. SE_BIND_FUNC(JSB_copyTextToClipboard)
  952. static bool JSB_setPreferredFramesPerSecond(se::State& s)
  953. {
  954. const auto& args = s.args();
  955. size_t argc = args.size();
  956. CC_UNUSED bool ok = true;
  957. if (argc > 0) {
  958. int32_t fps;
  959. ok = seval_to_int32(args[0], &fps);
  960. SE_PRECONDITION2(ok, false, "fps is invalid!");
  961. Application::getInstance()->setPreferredFramesPerSecond(fps);
  962. return true;
  963. }
  964. SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 1);
  965. return false;
  966. }
  967. SE_BIND_FUNC(JSB_setPreferredFramesPerSecond)
  968. static bool JSB_showInputBox(se::State& s)
  969. {
  970. const auto& args = s.args();
  971. size_t argc = args.size();
  972. CC_UNUSED bool ok = true;
  973. if (argc == 1)
  974. {
  975. bool ok;
  976. se::Value tmp;
  977. const auto& obj = args[0].toObject();
  978. cocos2d::EditBox::ShowInfo showInfo;
  979. ok = obj->getProperty("defaultValue", &tmp);
  980. SE_PRECONDITION2(ok && tmp.isString(), false, "defaultValue is invalid!");
  981. showInfo.defaultValue = tmp.toString();
  982. ok = obj->getProperty("maxLength", &tmp);
  983. SE_PRECONDITION2(ok && tmp.isNumber(), false, "maxLength is invalid!");
  984. showInfo.maxLength = tmp.toInt32();
  985. ok = obj->getProperty("multiple", &tmp);
  986. SE_PRECONDITION2(ok && tmp.isBoolean(), false, "multiple is invalid!");
  987. showInfo.isMultiline = tmp.toBoolean();
  988. if (obj->getProperty("confirmHold", &tmp))
  989. {
  990. SE_PRECONDITION2(tmp.isBoolean(), false, "confirmHold is invalid!");
  991. if (! tmp.isUndefined())
  992. showInfo.confirmHold = tmp.toBoolean();
  993. }
  994. if (obj->getProperty("confirmType", &tmp))
  995. {
  996. SE_PRECONDITION2(tmp.isString(), false, "confirmType is invalid!");
  997. if (!tmp.isUndefined())
  998. showInfo.confirmType = tmp.toString();
  999. }
  1000. if (obj->getProperty("inputType", &tmp))
  1001. {
  1002. SE_PRECONDITION2(tmp.isString(), false, "inputType is invalid!");
  1003. if (! tmp.isUndefined())
  1004. showInfo.inputType = tmp.toString();
  1005. }
  1006. if (obj->getProperty("originX", &tmp))
  1007. {
  1008. SE_PRECONDITION2(tmp.isNumber(), false, "originX is invalid!");
  1009. if (! tmp.isUndefined())
  1010. showInfo.x = tmp.toInt32();
  1011. }
  1012. if (obj->getProperty("originY", &tmp))
  1013. {
  1014. SE_PRECONDITION2(tmp.isNumber(), false, "originY is invalid!");
  1015. if (! tmp.isUndefined())
  1016. showInfo.y = tmp.toInt32();
  1017. }
  1018. if (obj->getProperty("width", &tmp))
  1019. {
  1020. SE_PRECONDITION2(tmp.isNumber(), false, "width is invalid!");
  1021. if (! tmp.isUndefined())
  1022. showInfo.width = tmp.toInt32();
  1023. }
  1024. if (obj->getProperty("height", &tmp))
  1025. {
  1026. SE_PRECONDITION2(tmp.isNumber(), false, "height is invalid!");
  1027. if (! tmp.isUndefined())
  1028. showInfo.height = tmp.toInt32();
  1029. }
  1030. EditBox::show(showInfo);
  1031. return true;
  1032. }
  1033. SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 1);
  1034. return false;
  1035. }
  1036. SE_BIND_FUNC(JSB_showInputBox);
  1037. static bool JSB_updateInputBoxRect(se::State& s)
  1038. {
  1039. const auto& args = s.args();
  1040. size_t argc = args.size();
  1041. if (argc == 4)
  1042. {
  1043. SE_PRECONDITION2(args[0].isNumber(), false, "x is invalid!");
  1044. const auto& x = args[0].toInt32();
  1045. SE_PRECONDITION2(args[1].isNumber(), false, "y is invalid!");
  1046. const auto& y = args[1].toInt32();
  1047. SE_PRECONDITION2(args[2].isNumber(), false, "width is invalid!");
  1048. const auto& width = args[2].toInt32();
  1049. SE_PRECONDITION2(args[3].isNumber(), false, "height is invalid!");
  1050. const auto& height = args[3].toInt32();
  1051. EditBox::updateRect(x, y, width, height);
  1052. return true;
  1053. }
  1054. SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 4);
  1055. return false;
  1056. }
  1057. SE_BIND_FUNC(JSB_updateInputBoxRect);
  1058. static bool JSB_hideInputBox(se::State& s)
  1059. {
  1060. EditBox::hide();
  1061. return true;
  1062. }
  1063. SE_BIND_FUNC(JSB_hideInputBox)
  1064. bool jsb_register_global_variables(se::Object* global)
  1065. {
  1066. g_threadPool.reset(ThreadPool::newFixedThreadPool(3));
  1067. global->defineFunction("require", _SE(require));
  1068. global->defineFunction("requireModule", _SE(moduleRequire));
  1069. getOrCreatePlainObject_r("jsb", global, &__jsbObj);
  1070. auto glContextCls = se::Class::create("WebGLRenderingContext", global, nullptr, nullptr);
  1071. glContextCls->install();
  1072. SAFE_DEC_REF(__glObj);
  1073. __glObj = se::Object::createObjectWithClass(glContextCls);
  1074. global->setProperty("__gl", se::Value(__glObj));
  1075. __jsbObj->defineFunction("garbageCollect", _SE(jsc_garbageCollect));
  1076. __jsbObj->defineFunction("dumpNativePtrToSeObjectMap", _SE(jsc_dumpNativePtrToSeObjectMap));
  1077. __jsbObj->defineFunction("loadImage", _SE(js_loadImage));
  1078. __jsbObj->defineFunction("saveImageData", _SE(js_saveImageData));
  1079. __jsbObj->defineFunction("setDebugViewText", _SE(js_setDebugViewText));
  1080. __jsbObj->defineFunction("openDebugView", _SE(js_openDebugView));
  1081. __jsbObj->defineFunction("disableBatchGLCommandsToNative", _SE(js_disableBatchGLCommandsToNative));
  1082. __jsbObj->defineFunction("openURL", _SE(JSB_openURL));
  1083. __jsbObj->defineFunction("copyTextToClipboard", _SE(JSB_copyTextToClipboard));
  1084. __jsbObj->defineFunction("setPreferredFramesPerSecond", _SE(JSB_setPreferredFramesPerSecond));
  1085. __jsbObj->defineFunction("showInputBox", _SE(JSB_showInputBox));
  1086. __jsbObj->defineFunction("hideInputBox", _SE(JSB_hideInputBox));
  1087. __jsbObj->defineFunction("updateInputBoxRect", _SE(JSB_updateInputBoxRect));
  1088. global->defineFunction("__getPlatform", _SE(JSBCore_platform));
  1089. global->defineFunction("__getOS", _SE(JSBCore_os));
  1090. global->defineFunction("__getOSVersion", _SE(JSB_getOSVersion));
  1091. global->defineFunction("__getCurrentLanguage", _SE(JSBCore_getCurrentLanguage));
  1092. global->defineFunction("__getCurrentLanguageCode", _SE(JSBCore_getCurrentLanguageCode));
  1093. global->defineFunction("__getVersion", _SE(JSBCore_version));
  1094. global->defineFunction("__restartVM", _SE(JSB_core_restartVM));
  1095. global->defineFunction("__cleanScript", _SE(JSB_cleanScript));
  1096. global->defineFunction("__isObjectValid", _SE(JSB_isObjectValid));
  1097. global->defineFunction("close", _SE(JSB_closeWindow));
  1098. se::HandleObject performanceObj(se::Object::createPlainObject());
  1099. performanceObj->defineFunction("now", _SE(js_performance_now));
  1100. global->setProperty("performance", se::Value(performanceObj));
  1101. se::ScriptEngine::getInstance()->clearException();
  1102. se::ScriptEngine::getInstance()->addBeforeCleanupHook([](){
  1103. g_threadPool = nullptr;
  1104. PoolManager::getInstance()->getCurrentPool()->clear();
  1105. });
  1106. se::ScriptEngine::getInstance()->addAfterCleanupHook([](){
  1107. PoolManager::getInstance()->getCurrentPool()->clear();
  1108. __moduleCache.clear();
  1109. SAFE_DEC_REF(__jsbObj);
  1110. SAFE_DEC_REF(__glObj);
  1111. });
  1112. return true;
  1113. }