2023-05-12 17:29:31 +08:00

1451 lines
45 KiB
C++

/****************************************************************************
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
http://www.cocos.com
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated engine source code (the "Software"), a limited,
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
to use Cocos Creator solely to develop games on your target platforms. You shall
not use Cocos Creator software for developing other software or tools that's
used for developing games. You are not granted to publish, distribute,
sublicense, and/or sell copies of Cocos Creator.
The software or tools in this License Agreement are licensed, not sold.
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
****************************************************************************/
#include "jsb_global.h"
#include "jsb_conversions.hpp"
#include "xxtea/xxtea.h"
#include "base/CCScheduler.h"
#include "base/CCThreadPool.h"
#include "network/HttpClient.h"
#include "platform/CCApplication.h"
#include "base/ccUTF8.h"
extern "C"
{
#include "rustwallet/rustwallet.h"
}
#if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID
#include "platform/android/jni/JniImp.h"
#endif // CC_PLATFORM_ANDROID
#include <regex>
#include "scrypt/native-crypto.h"
using namespace cocos2d;
se::Object* __jsbObj = nullptr;
se::Object* __glObj = nullptr;
static std::shared_ptr<ThreadPool> g_threadPool;
static std::shared_ptr<cocos2d::network::Downloader> g_localDownloader = nullptr;
static std::map<std::string, std::function<void(const std::string&, unsigned char*, int ,const std::string&)>> g_localDownloaderHandlers;
static uint64_t g_localDownloaderTaskId = 1000000;
static std::string xxteaKey = "";
void jsb_set_xxtea_key(const std::string& key)
{
xxteaKey = key;
}
static cocos2d::network::Downloader *localDownloader()
{
if(!g_localDownloader)
{
g_localDownloader = std::make_shared<cocos2d::network::Downloader>();
g_localDownloader->onDataTaskSuccess = [=](const cocos2d::network::DownloadTask& task,
std::vector<unsigned char>& data) {
if(data.empty())
{
SE_REPORT_ERROR("Getting image from (%s) failed!", task.requestURL.c_str());
return;
}
auto callback = g_localDownloaderHandlers.find(task.identifier);
if(callback == g_localDownloaderHandlers.end())
{
SE_REPORT_ERROR("Getting image from (%s), callback not found!!", task.requestURL.c_str());
return;
}
size_t imageBytes = data.size();
unsigned char* imageData = (unsigned char*)malloc(imageBytes);
memcpy(imageData, data.data(), imageBytes);
(callback->second)("", imageData, imageBytes, "");
//initImageFunc("", imageData, imageBytes);
g_localDownloaderHandlers.erase(callback);
};
g_localDownloader->onTaskError = [=](const cocos2d::network::DownloadTask& task,
int errorCode,
int errorCodeInternal,
const std::string& errorStr) {
SE_REPORT_ERROR("Getting image from (%s) failed!", task.requestURL.c_str());
auto callback = g_localDownloaderHandlers.find(task.identifier);
if(callback == g_localDownloaderHandlers.end())
{
SE_REPORT_ERROR("Getting image from (%s), callback not found!!", task.requestURL.c_str());
return;
}
(callback->second)("", nullptr, 0, errorStr);
g_localDownloaderHandlers.erase(task.identifier);
};
}
return g_localDownloader.get();
}
static const char* BYTE_CODE_FILE_EXT = ".jsc";
static std::string removeFileExt(const std::string& filePath)
{
size_t pos = filePath.rfind('.');
if (0 < pos)
{
return filePath.substr(0, pos);
}
return filePath;
}
void jsb_init_file_operation_delegate()
{
static se::ScriptEngine::FileOperationDelegate delegate;
if (!delegate.isValid())
{
delegate.onGetDataFromFile = [](const std::string& path, const std::function<void(const uint8_t*, size_t)>& readCallback) -> void{
assert(!path.empty());
Data fileData;
std::string byteCodePath = removeFileExt(path) + BYTE_CODE_FILE_EXT;
if (FileUtils::getInstance()->isFileExist(byteCodePath)) {
fileData = FileUtils::getInstance()->getDataFromFile(byteCodePath);
size_t dataLen = 0;
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);
if (data == nullptr) {
SE_REPORT_ERROR("Can't decrypt code for %s", byteCodePath.c_str());
return;
}
if (ZipUtils::isGZipBuffer(data,dataLen)) {
uint8_t* unpackedData;
ssize_t unpackedLen = ZipUtils::inflateMemory(data, dataLen,&unpackedData);
if (unpackedData == nullptr) {
SE_REPORT_ERROR("Can't decrypt code for %s", byteCodePath.c_str());
return;
}
readCallback(unpackedData, unpackedLen);
free(data);
free(unpackedData);
}
else {
readCallback(data, dataLen);
free(data);
}
return;
}
fileData = FileUtils::getInstance()->getDataFromFile(path);
readCallback(fileData.getBytes(), fileData.getSize());
};
delegate.onGetStringFromFile = [](const std::string& path) -> std::string{
assert(!path.empty());
std::string byteCodePath = removeFileExt(path) + BYTE_CODE_FILE_EXT;
if (FileUtils::getInstance()->isFileExist(byteCodePath)) {
Data fileData = FileUtils::getInstance()->getDataFromFile(byteCodePath);
uint32_t dataLen;
uint8_t* data = xxtea_decrypt((uint8_t*)fileData.getBytes(), (uint32_t)fileData.getSize(), (uint8_t*)xxteaKey.c_str(), (uint32_t)xxteaKey.size(), &dataLen);
if (data == nullptr) {
SE_REPORT_ERROR("Can't decrypt code for %s", byteCodePath.c_str());
return "";
}
if (ZipUtils::isGZipBuffer(data,dataLen)) {
uint8_t* unpackedData;
ssize_t unpackedLen = ZipUtils::inflateMemory(data, dataLen,&unpackedData);
if (unpackedData == nullptr) {
SE_REPORT_ERROR("Can't decrypt code for %s", byteCodePath.c_str());
return "";
}
std::string ret(reinterpret_cast<const char*>(unpackedData), unpackedLen);
free(unpackedData);
free(data);
return ret;
}
else {
std::string ret(reinterpret_cast<const char*>(data), dataLen);
free(data);
return ret;
}
}
if (FileUtils::getInstance()->isFileExist(path)) {
return FileUtils::getInstance()->getStringFromFile(path);
}
else {
SE_LOGE("ScriptEngine::onGetStringFromFile %s not found, possible missing file.\n", path.c_str());
}
return "";
};
delegate.onGetFullPath = [](const std::string& path) -> std::string{
assert(!path.empty());
std::string byteCodePath = removeFileExt(path) + BYTE_CODE_FILE_EXT;
if (FileUtils::getInstance()->isFileExist(byteCodePath)) {
return FileUtils::getInstance()->fullPathForFilename(byteCodePath);
}
return FileUtils::getInstance()->fullPathForFilename(path);
};
delegate.onCheckFileExist = [](const std::string& path) -> bool{
assert(!path.empty());
return FileUtils::getInstance()->isFileExist(path);
};
assert(delegate.isValid());
se::ScriptEngine::getInstance()->setFileOperationDelegate(delegate);
}
std::vector<std::string> searchPaths;
// iOS: /var/mobile/Containers/Data/Application/guid/Documents
std::string path = FileUtils::getInstance()->getWritablePath();
#if CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID
std::string extPath = FileUtils::getInstance()->getExtFileDirectory();
extPath += "luaframework/";
path += "luaframework/";
searchPaths.push_back(extPath);
#endif // CC_PLATFORM_ANDROID
searchPaths.push_back(path);
searchPaths.push_back("");
FileUtils::getInstance()->setSearchPaths(searchPaths);
}
bool jsb_enable_debugger(const std::string& debuggerServerAddr, uint32_t port, bool isWaitForConnect)
{
if (debuggerServerAddr.empty() || port == 0)
return false;
auto se = se::ScriptEngine::getInstance();
se->enableDebugger(debuggerServerAddr.c_str(), port, isWaitForConnect);
// For debugger main loop
class SimpleRunLoop
{
public:
void update(float dt)
{
se::ScriptEngine::getInstance()->mainLoopUpdate();
}
};
// static SimpleRunLoop runLoop;
//cjh IDEA: Director::getInstance()->getScheduler()->scheduleUpdate(&runLoop, 0, false);
return true;
}
bool jsb_set_extend_property(const char* ns, const char* clsName)
{
se::Object* globalObj = se::ScriptEngine::getInstance()->getGlobalObject();
se::Value nsVal;
if (globalObj->getProperty(ns, &nsVal) && nsVal.isObject())
{
se::Value ccVal;
if (globalObj->getProperty("cc", &ccVal) && ccVal.isObject())
{
se::Value ccClassVal;
if (ccVal.toObject()->getProperty("Class", &ccClassVal) && ccClassVal.isObject())
{
se::Value extendVal;
if (ccClassVal.toObject()->getProperty("extend", &extendVal) && extendVal.isObject() && extendVal.toObject()->isFunction())
{
se::Value targetClsVal;
if (nsVal.toObject()->getProperty(clsName, &targetClsVal) && targetClsVal.isObject())
{
return targetClsVal.toObject()->setProperty("extend", extendVal);
}
}
}
}
}
return false;
}
namespace {
std::unordered_map<std::string, se::Value> __moduleCache;
static bool require(se::State& s)
{
const auto& args = s.args();
int argc = (int)args.size();
assert(argc >= 1);
assert(args[0].isString());
return jsb_run_script(args[0].toString(), &s.rval());
}
SE_BIND_FUNC(require)
static bool doModuleRequire(const std::string& path, se::Value* ret, const std::string& prevScriptFileDir)
{
se::AutoHandleScope hs;
assert(!path.empty());
const auto& fileOperationDelegate = se::ScriptEngine::getInstance()->getFileOperationDelegate();
assert(fileOperationDelegate.isValid());
std::string fullPath;
std::string pathWithSuffix = path;
if (pathWithSuffix.rfind(".js") != (pathWithSuffix.length() - 3))
pathWithSuffix += ".js";
std::string scriptBuffer = fileOperationDelegate.onGetStringFromFile(pathWithSuffix);
if (scriptBuffer.empty() && !prevScriptFileDir.empty())
{
std::string secondPath = prevScriptFileDir;
if (secondPath[secondPath.length()-1] != '/')
secondPath += "/";
secondPath += path;
if (FileUtils::getInstance()->isDirectoryExist(secondPath))
{
if (secondPath[secondPath.length()-1] != '/')
secondPath += "/";
secondPath += "index.js";
}
else
{
if (path.rfind(".js") != (path.length() - 3))
secondPath += ".js";
}
fullPath = fileOperationDelegate.onGetFullPath(secondPath);
scriptBuffer = fileOperationDelegate.onGetStringFromFile(fullPath);
}
else
{
fullPath = fileOperationDelegate.onGetFullPath(pathWithSuffix);
}
if (!scriptBuffer.empty())
{
const auto& iter = __moduleCache.find(fullPath);
if (iter != __moduleCache.end())
{
*ret = iter->second;
// printf("Found cache: %s, value: %d\n", fullPath.c_str(), (int)ret->getType());
return true;
}
std::string currentScriptFileDir = FileUtils::getInstance()->getFileDir(fullPath);
// Add closure for evalutate the script
char prefix[] = "(function(currentScriptDir){ window.module = window.module || {}; var exports = window.module.exports = {}; ";
char suffix[512] = {0};
snprintf(suffix, sizeof(suffix), "\nwindow.module.exports = window.module.exports || exports;\n})('%s'); ", currentScriptFileDir.c_str());
// Add current script path to require function invocation
scriptBuffer = prefix + std::regex_replace(scriptBuffer, std::regex("([^A-Za-z0-9]|^)requireModule\\((.*?)\\)"), "$1requireModule($2, currentScriptDir)") + suffix;
// FILE* fp = fopen("/Users/james/Downloads/test.txt", "wb");
// fwrite(scriptBuffer.c_str(), scriptBuffer.length(), 1, fp);
// fclose(fp);
std::string reletivePath = fullPath;
#if CC_TARGET_PLATFORM == CC_PLATFORM_MAC || CC_TARGET_PLATFORM == CC_PLATFORM_IOS
#if CC_TARGET_PLATFORM == CC_PLATFORM_MAC
const std::string reletivePathKey = "/Contents/Resources";
#else
const std::string reletivePathKey = ".app";
#endif
size_t pos = reletivePath.find(reletivePathKey);
if (pos != std::string::npos)
{
reletivePath = reletivePath.substr(pos + reletivePathKey.length() + 1);
}
#endif
// RENDERER_LOGD("Evaluate: %s", fullPath.c_str());
auto se = se::ScriptEngine::getInstance();
bool succeed = se->evalString(scriptBuffer.c_str(), scriptBuffer.length(), nullptr, reletivePath.c_str());
se::Value moduleVal;
if (succeed && se->getGlobalObject()->getProperty("module", &moduleVal) && moduleVal.isObject())
{
se::Value exportsVal;
if (moduleVal.toObject()->getProperty("exports", &exportsVal))
{
if (ret != nullptr)
*ret = exportsVal;
__moduleCache[fullPath] = std::move(exportsVal);
}
else
{
__moduleCache[fullPath] = se::Value::Undefined;
}
// clear module.exports
moduleVal.toObject()->setProperty("exports", se::Value::Undefined);
}
else
{
__moduleCache[fullPath] = se::Value::Undefined;
}
assert(succeed);
return succeed;
}
SE_LOGE("doModuleRequire %s, buffer is empty!\n", path.c_str());
assert(false);
return false;
}
static bool moduleRequire(se::State& s)
{
const auto& args = s.args();
int argc = (int)args.size();
assert(argc >= 2);
assert(args[0].isString());
assert(args[1].isString());
return doModuleRequire(args[0].toString(), &s.rval(), args[1].toString());
}
SE_BIND_FUNC(moduleRequire)
} // namespace {
bool jsb_run_script(const std::string& filePath, se::Value* rval/* = nullptr */)
{
se::AutoHandleScope hs;
CCLOG("load js file: %s", filePath.c_str());
return se::ScriptEngine::getInstance()->runScript(filePath, rval);
}
bool jsb_run_code(const std::string& coder, se::Value* rval/* = nullptr */) {
se::AutoHandleScope hs;
return se::ScriptEngine::getInstance()->evalString(coder.c_str(), coder.size(), rval);
}
bool jsb_run_script_module(const std::string& filePath, se::Value* rval/* = nullptr */)
{
return doModuleRequire(filePath, rval, "");
}
static bool jsc_garbageCollect(se::State& s)
{
se::ScriptEngine::getInstance()->garbageCollect();
return true;
}
SE_BIND_FUNC(jsc_garbageCollect)
static bool jsc_dumpNativePtrToSeObjectMap(se::State& s)
{
cocos2d::log(">>> total: %d, Dump (native -> jsobj) map begin", (int)se::NativePtrToObjectMap::size());
struct NamePtrStruct
{
const char* name;
void* ptr;
};
std::vector<NamePtrStruct> namePtrArray;
for (const auto& e : se::NativePtrToObjectMap::instance())
{
se::Object* jsobj = e.second;
assert(jsobj->_getClass() != nullptr);
NamePtrStruct tmp;
tmp.name = jsobj->_getClass()->getName();
tmp.ptr = e.first;
namePtrArray.push_back(tmp);
}
std::sort(namePtrArray.begin(), namePtrArray.end(), [](const NamePtrStruct& a, const NamePtrStruct& b) -> bool {
std::string left = a.name;
std::string right = b.name;
for( std::string::const_iterator lit = left.begin(), rit = right.begin(); lit != left.end() && rit != right.end(); ++lit, ++rit )
if( ::tolower( *lit ) < ::tolower( *rit ) )
return true;
else if( ::tolower( *lit ) > ::tolower( *rit ) )
return false;
if( left.size() < right.size() )
return true;
return false;
});
for (const auto& e : namePtrArray)
{
cocos2d::log("%s: %p", e.name, e.ptr);
}
cocos2d::log(">>> total: %d, nonRefMap: %d, Dump (native -> jsobj) map end", (int)se::NativePtrToObjectMap::size(), (int)se::NonRefNativePtrCreatedByCtorMap::size());
return true;
}
SE_BIND_FUNC(jsc_dumpNativePtrToSeObjectMap)
static bool jsc_dumpRoot(se::State& s)
{
assert(false);
return true;
}
SE_BIND_FUNC(jsc_dumpRoot)
static bool JSBCore_platform(se::State& s)
{
Application::Platform platform = Application::getInstance()->getPlatform();
s.rval().setInt32((int32_t)platform);
return true;
}
SE_BIND_FUNC(JSBCore_platform)
static bool JSBCore_version(se::State& s)
{
//cjh char version[256];
// snprintf(version, sizeof(version)-1, "%s", cocos2dVersion());
//
// s.rval().setString(version);
return true;
}
SE_BIND_FUNC(JSBCore_version)
static bool JSBCore_os(se::State& s)
{
se::Value os;
// osx, ios, android, windows, linux, etc..
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
os.setString("iOS");
#elif (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
os.setString("Android");
#elif (CC_TARGET_PLATFORM == CC_PLATFORM_WIN32)
os.setString("Windows");
#elif (CC_TARGET_PLATFORM == CC_PLATFORM_MARMALADE)
os.setString("Marmalade");
#elif (CC_TARGET_PLATFORM == CC_PLATFORM_LINUX)
os.setString("Linux");
#elif (CC_TARGET_PLATFORM == CC_PLATFORM_BADA)
os.setString("Bada");
#elif (CC_TARGET_PLATFORM == CC_PLATFORM_BLACKBERRY)
os.setString("Blackberry");
#elif (CC_TARGET_PLATFORM == CC_PLATFORM_MAC)
os.setString("OS X");
#elif (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT)
os.setString("WINRT");
#else
os.setString("Unknown");
#endif
s.rval() = os;
return true;
}
SE_BIND_FUNC(JSBCore_os)
static bool JSBCore_getCurrentLanguage(se::State& s)
{
std::string languageStr;
Application::LanguageType language = Application::getInstance()->getCurrentLanguage();
switch (language)
{
case Application::LanguageType::ENGLISH:
languageStr = "en";
break;
case Application::LanguageType::CHINESE:
languageStr = "zh";
break;
case Application::LanguageType::FRENCH:
languageStr = "fr";
break;
case Application::LanguageType::ITALIAN:
languageStr = "it";
break;
case Application::LanguageType::GERMAN:
languageStr = "de";
break;
case Application::LanguageType::SPANISH:
languageStr = "es";
break;
case Application::LanguageType::DUTCH:
languageStr = "du";
break;
case Application::LanguageType::RUSSIAN:
languageStr = "ru";
break;
case Application::LanguageType::KOREAN:
languageStr = "ko";
break;
case Application::LanguageType::JAPANESE:
languageStr = "ja";
break;
case Application::LanguageType::HUNGARIAN:
languageStr = "hu";
break;
case Application::LanguageType::PORTUGUESE:
languageStr = "pt";
break;
case Application::LanguageType::ARABIC:
languageStr = "ar";
break;
case Application::LanguageType::NORWEGIAN:
languageStr = "no";
break;
case Application::LanguageType::POLISH:
languageStr = "pl";
break;
case Application::LanguageType::TURKISH:
languageStr = "tr";
break;
case Application::LanguageType::UKRAINIAN:
languageStr = "uk";
break;
case Application::LanguageType::ROMANIAN:
languageStr = "ro";
break;
case Application::LanguageType::BULGARIAN:
languageStr = "bg";
break;
default:
languageStr = "unknown";
break;
}
s.rval().setString(languageStr);
return true;
}
SE_BIND_FUNC(JSBCore_getCurrentLanguage)
static bool JSBCore_getCurrentLanguageCode(se::State& s)
{
std::string language = Application::getInstance()->getCurrentLanguageCode();
s.rval().setString(language);
return true;
}
SE_BIND_FUNC(JSBCore_getCurrentLanguageCode)
static bool JSB_getOSVersion(se::State& s)
{
std::string systemVersion = Application::getInstance()->getSystemVersion();
s.rval().setString(systemVersion);
return true;
}
SE_BIND_FUNC(JSB_getOSVersion)
static bool JSB_cleanScript(se::State& s)
{
assert(false); //IDEA:
return true;
}
SE_BIND_FUNC(JSB_cleanScript)
static bool JSB_core_restartVM(se::State& s)
{
//REFINE: release AudioEngine, waiting HttpClient & WebSocket threads to exit.
Application::getInstance()->restart();
return true;
}
SE_BIND_FUNC(JSB_core_restartVM)
static bool JSB_closeWindow(se::State& s)
{
Application::getInstance()->end();
return true;
}
SE_BIND_FUNC(JSB_closeWindow)
static bool JSB_isObjectValid(se::State& s)
{
const auto& args = s.args();
int argc = (int)args.size();
if (argc == 1)
{
void* nativePtr = nullptr;
seval_to_native_ptr(args[0], &nativePtr);
s.rval().setBoolean(nativePtr != nullptr);
return true;
}
SE_REPORT_ERROR("Invalid number of arguments: %d. Expecting: 1", argc);
return false;
}
SE_BIND_FUNC(JSB_isObjectValid)
static bool getOrCreatePlainObject_r(const char* name, se::Object* parent, se::Object** outObj)
{
assert(parent != nullptr);
assert(outObj != nullptr);
se::Value tmp;
if (parent->getProperty(name, &tmp) && tmp.isObject())
{
*outObj = tmp.toObject();
(*outObj)->incRef();
}
else
{
*outObj = se::Object::createPlainObject();
parent->setProperty(name, se::Value(*outObj));
}
return true;
}
static bool js_performance_now(se::State& s)
{
auto now = std::chrono::steady_clock::now();
auto micro = std::chrono::duration_cast<std::chrono::microseconds>(now - se::ScriptEngine::getInstance()->getStartTime()).count();
s.rval().setNumber((double)micro * 0.001);
return true;
}
SE_BIND_FUNC(js_performance_now)
static bool JSB_openURL(se::State& s)
{
const auto& args = s.args();
size_t argc = args.size();
CC_UNUSED bool ok = true;
if (argc > 0) {
std::string url;
ok = seval_to_std_string(args[0], &url);
SE_PRECONDITION2(ok, false, "url is invalid!");
Application::getInstance()->openURL(url);
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 1);
return false;
}
SE_BIND_FUNC(JSB_openURL)
static bool JSB_copyTextToClipboard(se::State& s)
{
const auto& args = s.args();
size_t argc = args.size();
CC_UNUSED bool ok = true;
if (argc > 0) {
std::string text;
ok = seval_to_std_string(args[0], &text);
SE_PRECONDITION2(ok, false, "text is invalid!");
Application::getInstance()->copyTextToClipboard(text);
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 1);
return false;
}
SE_BIND_FUNC(JSB_copyTextToClipboard)
static bool JSB_setPreferredFramesPerSecond(se::State& s)
{
const auto& args = s.args();
size_t argc = args.size();
CC_UNUSED bool ok = true;
if (argc > 0) {
int32_t fps;
ok = seval_to_int32(args[0], &fps);
SE_PRECONDITION2(ok, false, "fps is invalid!");
Application::getInstance()->setPreferredFramesPerSecond(fps);
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 1);
return false;
}
SE_BIND_FUNC(JSB_setPreferredFramesPerSecond)
static bool JSB_cryptoScrypt(se::State& s)
{
const auto& args = s.args();
size_t argc = args.size();
if (argc == 6)
{
bool ok = true;
std::string password;
ok = seval_to_std_string(args[0], &password);
SE_PRECONDITION2(ok, false, "Error processing arguments");
std::string salt;
ok = seval_to_std_string(args[1], &salt);
SE_PRECONDITION2(ok, false, "Error processing arguments");
int n = 0;
ok = seval_to_int32(args[2], &n);
SE_PRECONDITION2(ok, false, "Error processing arguments");
int r = 0;
ok = seval_to_int32(args[3], &r);
SE_PRECONDITION2(ok, false, "Error processing arguments");
int p = 0;
ok = seval_to_int32(args[4], &p);
SE_PRECONDITION2(ok, false, "Error processing arguments");
int size = 0;
ok = seval_to_int32(args[5], &size);
SE_PRECONDITION2(ok, false, "Error processing arguments");
std::string value;
int result = crypto_scrypt_base64(&password, &salt, n, r, p, size, &value);
if (result == 0) {
s.rval().setString(value);
}
else
s.rval().setNull(); // Should return null to make JSB behavior same as Browser since returning undefined will make JSON.parse(undefined) trigger exception.
return true;
}
SE_REPORT_ERROR("Invalid number of arguments");
return false;
}
SE_BIND_FUNC(JSB_cryptoScrypt)
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
static bool JSB_scanQRCode(se::State& s)
{
const auto& args = s.args();
size_t argc = args.size();
CC_UNUSED bool ok = true;
if (argc > 1) {
std::string funid;
ok = seval_to_std_string(args[0], &funid);
SE_PRECONDITION2(ok, false, "funid is invalid!");
std::string text;
ok = seval_to_std_string(args[1], &text);
SE_PRECONDITION2(ok, false, "title is invalid!");
// Application::getInstance()->scanQRCode(funid, text);
scanQRCodeJNI(funid, text);
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 2);
return false;
}
SE_BIND_FUNC(JSB_scanQRCode)
static bool JSB_restoreKey(se::State& s)
{
const auto& args = s.args();
size_t argc = args.size();
CC_UNUSED bool ok = true;
if (argc > 1) {
std::string funid;
ok = seval_to_std_string(args[0], &funid);
SE_PRECONDITION2(ok, false, "funid is invalid!");
std::string oid;
ok = seval_to_std_string(args[1], &oid);
SE_PRECONDITION2(ok, false, "oid is invalid!");
loadRestoreKeyJNI(funid, oid);
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 2);
return false;
}
SE_BIND_FUNC(JSB_restoreKey)
static bool JSB_signWithGoogle(se::State& s)
{
const auto& args = s.args();
size_t argc = args.size();
CC_UNUSED bool ok = true;
if (argc > 0) {
std::string funid;
ok = seval_to_std_string(args[0], &funid);
SE_PRECONDITION2(ok, false, "funid is invalid!");
signWithGoogleJNI(funid);
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 1);
return false;
}
SE_BIND_FUNC(JSB_signWithGoogle)
static bool JSB_signWithApple(se::State& s)
{
const auto& args = s.args();
size_t argc = args.size();
CC_UNUSED bool ok = true;
if (argc > 0) {
std::string funid;
ok = seval_to_std_string(args[0], &funid);
SE_PRECONDITION2(ok, false, "funid is invalid!");
signWithAppleJNI(funid);
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 1);
return false;
}
SE_BIND_FUNC(JSB_signWithApple)
//JSB_signWithTiktok
static bool JSB_signWithTiktok(se::State& s)
{
const auto& args = s.args();
size_t argc = args.size();
CC_UNUSED bool ok = true;
if (argc > 0) {
std::string funid;
ok = seval_to_std_string(args[0], &funid);
SE_PRECONDITION2(ok, false, "funid is invalid!");
signWithTiktokJNI(funid);
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 1);
return false;
}
SE_BIND_FUNC(JSB_signWithTiktok)
static bool JSB_signWithFacebook(se::State& s)
{
const auto& args = s.args();
size_t argc = args.size();
CC_UNUSED bool ok = true;
if (argc > 0) {
std::string funid;
ok = seval_to_std_string(args[0], &funid);
SE_PRECONDITION2(ok, false, "funid is invalid!");
signWithFacebookJNI(funid);
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 1);
return false;
}
SE_BIND_FUNC(JSB_signWithFacebook)
static bool JSB_signWithTwitter(se::State& s)
{
const auto& args = s.args();
size_t argc = args.size();
CC_UNUSED bool ok = true;
if (argc > 0) {
std::string funid;
ok = seval_to_std_string(args[0], &funid);
SE_PRECONDITION2(ok, false, "funid is invalid!");
signWithTwitterJNI(funid);
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 1);
return false;
}
SE_BIND_FUNC(JSB_signWithTwitter)
static bool JSB_signWithEmail(se::State& s)
{
const auto& args = s.args();
size_t argc = args.size();
CC_UNUSED bool ok = true;
if (argc > 0) {
std::string funid;
ok = seval_to_std_string(args[0], &funid);
SE_PRECONDITION2(ok, false, "funid is invalid!");
signWithEmailJNI(funid);
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 1);
return false;
}
SE_BIND_FUNC(JSB_signWithEmail)
static bool JSB_callJcVoidMethodJNI(se::State& s)
{
const auto& args = s.args();
size_t argc = args.size();
CC_UNUSED bool ok = true;
if (argc > 1) {
std::string funid;
ok = seval_to_std_string(args[0], &funid);
SE_PRECONDITION2(ok, false, "funid is invalid!");
std::string method_name;
ok = seval_to_std_string(args[1], &method_name);
callJcVoidMethodJNI(funid, method_name);
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 2);
return false;
}
SE_BIND_FUNC(JSB_callJcVoidMethodJNI)
static bool JSB_signOutGoogle(se::State& s)
{
const auto& args = s.args();
size_t argc = args.size();
CC_UNUSED bool ok = true;
if (argc > 0) {
std::string funid;
ok = seval_to_std_string(args[0], &funid);
SE_PRECONDITION2(ok, false, "funid is invalid!");
// Application::getInstance()->signOutGoogle(funid);
signOutGoogleJNI(funid);
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 1);
return false;
}
SE_BIND_FUNC(JSB_signOutGoogle)
static bool JSB_showQRCode(se::State& s)
{
const auto& args = s.args();
size_t argc = args.size();
CC_UNUSED bool ok = true;
if (argc >= 2) {
std::string funid;
ok = seval_to_std_string(args[0], &funid);
SE_PRECONDITION2(ok, false, "funid is invalid!");
std::string text;
ok = seval_to_std_string(args[1], &text);
SE_PRECONDITION2(ok, false, "content is invalid!");
showQRCodeJNI(funid, text);
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 2);
return false;
}
SE_BIND_FUNC(JSB_showQRCode)
bool jsb_showWebPage(se::State& s) {
const auto& args = s.args();
size_t argc = args.size();
if (argc >= 2) {
bool ok;
std::string funid;
ok = seval_to_std_string(args[0], &funid);
SE_PRECONDITION2(ok, false, "Error processing arguments");
std::string url;
ok = seval_to_std_string(args[1], &url);
SE_PRECONDITION2(ok, false, "Error processing arguments");
showWebPageJNI(funid, url);
return true;
}
return false;
}
SE_BIND_FUNC(jsb_showWebPage)
#endif
static bool JSB_toWallet(se::State& s)
{
const auto& args = s.args();
size_t argc = args.size();
CC_UNUSED bool ok = true;
if (argc > 0) {
std::string text;
ok = seval_to_std_string(args[0], &text);
SE_PRECONDITION2(ok, false, "url is invalid!");
Application::getInstance()->toWallet(text);
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 1);
return false;
}
SE_BIND_FUNC(JSB_toWallet)
static bool JSB_prepareWallet(se::State& s)
{
const auto& args = s.args();
size_t argc = args.size();
CC_UNUSED bool ok = true;
if (argc > 0) {
std::string id;
ok = seval_to_std_string(args[0], &id);
SE_PRECONDITION2(ok, false, "Error processing oid");
std::string openid;
ok = seval_to_std_string(args[1], &openid);
SE_PRECONDITION2(ok, false, "Error processing openid");
std::string keyMaster;
ok = seval_to_std_string(args[2], &keyMaster);
SE_PRECONDITION2(ok, false, "Error processing master key");
std::string salt;
ok = seval_to_std_string(args[3], &salt);
SE_PRECONDITION2(ok, false, "Error processing pass");
std::string pass;
ok = seval_to_std_string(args[4], &pass);
SE_PRECONDITION2(ok, false, "Error processing pass");
std::string localSKey = generate_client_key(pass.c_str(), openid.c_str(), salt.c_str());
Application::getInstance()->setKeyMaster(keyMaster.c_str());
Application::getInstance()->setKeySecond(localSKey.c_str());
std::string seed = keccak256_hash((id + openid + salt).c_str());
Application::getInstance()->setKeySeed(seed.c_str());
std::string address = get_address(
Application::getInstance()->getKeySeed(),
Application::getInstance()->getKeyMaster(),
Application::getInstance()->getKeySecond()
);
std::string result = StringUtils::format("{\"address\": \"%s\"}\n",
address.c_str()
);
s.rval().setString(result);
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 5);
return false;
}
SE_BIND_FUNC(JSB_prepareWallet)
static bool JSB_storeLocalPass(se::State& s)
{
const auto& args = s.args();
size_t argc = args.size();
CC_UNUSED bool ok = true;
if (argc > 0) {
std::string pass;
ok = seval_to_std_string(args[0], &pass);
SE_PRECONDITION2(ok, false, "Error processing pass");
std::string hashstr = local_pass_hasher(pass.c_str());
Application::getInstance()->setTmpPass(hashstr.c_str());
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 1);
return false;
}
SE_BIND_FUNC(JSB_storeLocalPass)
static bool JSB_hashSvrPass(se::State& s)
{
const auto& args = s.args();
size_t argc = args.size();
CC_UNUSED bool ok = true;
if (argc > 0) {
std::string pass;
ok = seval_to_std_string(args[0], &pass);
SE_PRECONDITION2(ok, false, "Error processing pass");
std::string hashstr = hash_pass_svr(pass.c_str());
s.rval().setString(hashstr);
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 1);
return false;
}
SE_BIND_FUNC(JSB_hashSvrPass)
static bool JSB_verifyLocalPass(se::State& s)
{
const auto& args = s.args();
size_t argc = args.size();
CC_UNUSED bool ok = true;
if (argc > 0) {
std::string msg;
ok = seval_to_std_string(args[0], &msg);
SE_PRECONDITION2(ok, false, "Error processing pass");
bool result = verify_local_pass(
msg.c_str(),
Application::getInstance()->getTmpPass()
);
s.rval().setBoolean(result);
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 1);
return false;
}
SE_BIND_FUNC(JSB_verifyLocalPass)
static bool JSB_walletSign(se::State& s)
{
const auto& args = s.args();
size_t argc = args.size();
CC_UNUSED bool ok = true;
if (argc > 0) {
std::string msg;
ok = seval_to_std_string(args[0], &msg);
SE_PRECONDITION2(ok, false, "Error processing seed");
std::string sign_str = sign(
Application::getInstance()->getKeySeed(),
Application::getInstance()->getKeyMaster(),
Application::getInstance()->getKeySecond(),
msg.c_str());
s.rval().setString(sign_str);
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 1);
return false;
}
SE_BIND_FUNC(JSB_walletSign)
static bool JSB_loadLocalStorage(se::State& s)
{
const auto& args = s.args();
size_t argc = args.size();
CC_UNUSED bool ok = true;
if (argc > 0) {
std::string key;
ok = seval_to_std_string(args[0], &key);
SE_PRECONDITION2(ok, false, "Error processing seed");
std::string val;
Application::getInstance()->loadKeyLocal(key, &val);
s.rval().setString(val);
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 1);
return false;
}
SE_BIND_FUNC(JSB_loadLocalStorage)
static bool JSB_walletSecKey(se::State& s)
{
const auto& args = s.args();
size_t argc = args.size();
CC_UNUSED bool ok = true;
if (argc > 0) {
std::string funid;
ok = seval_to_std_string(args[0], &funid);
SE_PRECONDITION2(ok, false, "funid is invalid!");
std::string key_str = generate_sec_key(
Application::getInstance()->getKeySeed(),
Application::getInstance()->getKeyMaster(),
Application::getInstance()->getKeySecond()
);
s.rval().setString(key_str);
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 1);
return false;
}
SE_BIND_FUNC(JSB_walletSecKey)
static bool JSB_walletSignTran(se::State& s)
{
const auto& args = s.args();
size_t argc = args.size();
CC_UNUSED bool ok = true;
CCLOG("JSB_walletSignTran\n");
if (argc > 0) {
std::string msg;
ok = seval_to_std_string(args[0], &msg);
SE_PRECONDITION2(ok, false, "Error processing seed");
std::string sign_str = sign_for_tran(
Application::getInstance()->getKeySeed(),
Application::getInstance()->getKeyMaster(),
Application::getInstance()->getKeySecond(),
msg.c_str());
s.rval().setString(sign_str);
// free_cwallet(wallet);
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 1);
return false;
}
SE_BIND_FUNC(JSB_walletSignTran)
static bool JSB_hexDeflate(se::State& s)
{
const auto& args = s.args();
size_t argc = args.size();
if (argc == 1)
{
bool ok = true;
std::string value;
ok = seval_to_std_string(args[0], &value);
SE_PRECONDITION2(ok, false, "Error processing arguments");
std::string result = hex_deflate(value.c_str());
s.rval().setString(result);
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 1);
return false;
}
SE_BIND_FUNC(JSB_hexDeflate)
static bool JSB_hexInflate(se::State& s)
{
const auto& args = s.args();
size_t argc = args.size();
if (argc == 1)
{
bool ok = true;
std::string value;
ok = seval_to_std_string(args[0], &value);
SE_PRECONDITION2(ok, false, "Error processing arguments");
std::string result = hex_inflate(value.c_str());
s.rval().setString(result);
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 1);
return false;
}
SE_BIND_FUNC(JSB_hexInflate)
static bool JSB_walletEncrypt(se::State& s)
{
const auto& args = s.args();
size_t argc = args.size();
CC_UNUSED bool ok = true;
if (argc > 0) {
std::string msg;
ok = seval_to_std_string(args[0], &msg);
SE_PRECONDITION2(ok, false, "Error processing msg");
std::string str_encrypt = wallet_encrypt(
Application::getInstance()->getKeySeed(),
Application::getInstance()->getKeyMaster(),
Application::getInstance()->getKeySecond(),
msg.c_str());
s.rval().setString(str_encrypt);
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 1);
return false;
}
SE_BIND_FUNC(JSB_walletEncrypt)
static bool JSB_rencrypt(se::State& s)
{
const auto& args = s.args();
size_t argc = args.size();
CC_UNUSED bool ok = true;
if (argc > 1) {
std::string pk;
ok = seval_to_std_string(args[0], &pk);
SE_PRECONDITION2(ok, false, "Error processing pk");
std::string msg;
ok = seval_to_std_string(args[1], &msg);
SE_PRECONDITION2(ok, false, "Error processing msg");
std::string str_encrypt = rencrypt(
pk.c_str(),
msg.c_str());
s.rval().setString(str_encrypt);
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 2);
return false;
}
SE_BIND_FUNC(JSB_rencrypt)
static bool JSB_walletDecrypt(se::State& s)
{
const auto& args = s.args();
size_t argc = args.size();
CC_UNUSED bool ok = true;
if (argc > 0) {
std::string msg;
ok = seval_to_std_string(args[0], &msg);
SE_PRECONDITION2(ok, false, "Error processing seed");
std::string str_encrypt = wallet_decrypt(
Application::getInstance()->getKeySeed(),
Application::getInstance()->getKeyMaster(),
Application::getInstance()->getKeySecond(),
msg.c_str());
s.rval().setString(str_encrypt);
return true;
}
SE_REPORT_ERROR("wrong number of arguments: %d, was expecting %d", (int)argc, 1);
return false;
}
SE_BIND_FUNC(JSB_walletDecrypt)
bool jsb_register_global_variables(se::Object* global)
{
g_threadPool.reset(ThreadPool::newFixedThreadPool(3));
global->defineFunction("require", _SE(require));
global->defineFunction("requireModule", _SE(moduleRequire));
getOrCreatePlainObject_r("jsb", global, &__jsbObj);
auto glContextCls = se::Class::create("WebGLRenderingContext", global, nullptr, nullptr);
glContextCls->install();
SAFE_DEC_REF(__glObj);
__glObj = se::Object::createObjectWithClass(glContextCls);
global->setProperty("__gl", se::Value(__glObj));
__jsbObj->defineFunction("garbageCollect", _SE(jsc_garbageCollect));
__jsbObj->defineFunction("jcCryptoScrypt", _SE(JSB_cryptoScrypt));
__jsbObj->defineFunction("dumpNativePtrToSeObjectMap", _SE(jsc_dumpNativePtrToSeObjectMap));
__jsbObj->defineFunction("openURL", _SE(JSB_openURL));
__jsbObj->defineFunction("copyTextToClipboard", _SE(JSB_copyTextToClipboard));
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)
__jsbObj->defineFunction("scanQRCode", _SE(JSB_scanQRCode));
__jsbObj->defineFunction("restoreKey", _SE(JSB_restoreKey));
__jsbObj->defineFunction("signWithGoogle", _SE(JSB_signWithGoogle));
__jsbObj->defineFunction("signWithApple", _SE(JSB_signWithApple));
__jsbObj->defineFunction("signWithTikTok", _SE(JSB_signWithTiktok));
__jsbObj->defineFunction("signWithFacebook", _SE(JSB_signWithFacebook));
__jsbObj->defineFunction("signWithTwitter", _SE(JSB_signWithTwitter));
__jsbObj->defineFunction("signWithEmail", _SE(JSB_signWithEmail));
__jsbObj->defineFunction("callJcVoidMethodJNI", _SE(JSB_callJcVoidMethodJNI));
__jsbObj->defineFunction("signOutGoogle", _SE(JSB_signOutGoogle));
__jsbObj->defineFunction("showQRCode", _SE(JSB_showQRCode));
__jsbObj->defineFunction("showWebPage", _SE(jsb_showWebPage));
#endif
__jsbObj->defineFunction("toWallet", _SE(JSB_toWallet));
__jsbObj->defineFunction("prepareWallet", _SE(JSB_prepareWallet));
__jsbObj->defineFunction("storeLocalPass", _SE(JSB_storeLocalPass));
__jsbObj->defineFunction("verifyLocalPass", _SE(JSB_verifyLocalPass));
__jsbObj->defineFunction("hashSvrPass", _SE(JSB_hashSvrPass));
__jsbObj->defineFunction("walletSign", _SE(JSB_walletSign));
__jsbObj->defineFunction("walletSignTran", _SE(JSB_walletSignTran));
__jsbObj->defineFunction("walletSecKey", _SE(JSB_walletSecKey));
__jsbObj->defineFunction("hexDeflate", _SE(JSB_hexDeflate));
__jsbObj->defineFunction("hexInflate", _SE(JSB_hexInflate));
__jsbObj->defineFunction("rencrypt", _SE(JSB_rencrypt));
__jsbObj->defineFunction("walletEncrypt", _SE(JSB_walletEncrypt));
__jsbObj->defineFunction("walletDecrypt", _SE(JSB_walletDecrypt));
__jsbObj->defineFunction("loadLocalStorage", _SE(JSB_loadLocalStorage));
__jsbObj->defineFunction("setPreferredFramesPerSecond", _SE(JSB_setPreferredFramesPerSecond));
global->defineFunction("__getPlatform", _SE(JSBCore_platform));
global->defineFunction("__getOS", _SE(JSBCore_os));
global->defineFunction("__getOSVersion", _SE(JSB_getOSVersion));
global->defineFunction("__getCurrentLanguage", _SE(JSBCore_getCurrentLanguage));
global->defineFunction("__getCurrentLanguageCode", _SE(JSBCore_getCurrentLanguageCode));
global->defineFunction("__getVersion", _SE(JSBCore_version));
global->defineFunction("__restartVM", _SE(JSB_core_restartVM));
global->defineFunction("__cleanScript", _SE(JSB_cleanScript));
global->defineFunction("__isObjectValid", _SE(JSB_isObjectValid));
global->defineFunction("close", _SE(JSB_closeWindow));
se::HandleObject performanceObj(se::Object::createPlainObject());
performanceObj->defineFunction("now", _SE(js_performance_now));
global->setProperty("performance", se::Value(performanceObj));
se::ScriptEngine::getInstance()->clearException();
se::ScriptEngine::getInstance()->addBeforeCleanupHook([](){
g_threadPool = nullptr;
PoolManager::getInstance()->getCurrentPool()->clear();
});
se::ScriptEngine::getInstance()->addAfterCleanupHook([](){
PoolManager::getInstance()->getCurrentPool()->clear();
__moduleCache.clear();
SAFE_DEC_REF(__jsbObj);
SAFE_DEC_REF(__glObj);
});
return true;
}