Cocos2dx 3.X jsb加载JavaScript源码文件分析

2024-04-06 03:58

本文主要是介绍Cocos2dx 3.X jsb加载JavaScript源码文件分析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Cocos2dx 3.X jsb加载JavaScript源码文件分析:
1、其实js和lua差不多,lua中通过require函数加载lua文件,js中也是通过一个函数require,加载js源码文件,而且思路差不多,那这个函数是如何执行的呢?2、require函数
在ScriptingCore.cpp文件中有个registerDefaultClasses函数,这个函数注册了一些C++ 函数供javascript调用,require就是其中之一:
void registerDefaultClasses(JSContext* cx, JS::HandleObject global) {
………不需要的东西,都去掉了。
// register some global functions
//这里就是重点,注册了一个require函数,实际调用的是/*** run a script from script :)*/static bool executeScript(JSContext *cx, uint32_t argc, jsval *vp);
函数,找到源头,我们可以去看下代码,具体如何实现得了。JS_DefineFunction(cx, global, "require", ScriptingCore::executeScript, 1, JSPROP_READONLY | JSPROP_PERMANENT);//顺便说下这个,这个log如果是jsb可以直接使用,但不能在h5上面使用,所以最好还是使用cc.logJS_DefineFunction(cx, global, "log", ScriptingCore::log, 0, JSPROP_READONLY | JSPROP_PERMANENT);}
3、
//这个函数是我们的重点
bool ScriptingCore::executeScript(JSContext *cx, uint32_t argc, jsval *vp)
{JS::CallArgs args = JS::CallArgsFromVp(argc, vp);//获取参数if (argc >= 1) {JSString* str = JS::ToString(cx, JS::RootedValue(cx, args.get(0)));JSStringWrapper path(str);bool res = false;if (argc == 2 && args.get(1).isString()) {JSString* globalName = args.get(1).toString();JSStringWrapper name(globalName);JS::RootedObject debugObj(cx, ScriptingCore::getInstance()->getDebugGlobal());if (debugObj) {res = ScriptingCore::getInstance()->runScript(path.get(), debugObj);} else {JS_ReportError(cx, "Invalid global object: %s", name.get());return false;}} else {JS::RootedObject glob(cx, JS::CurrentGlobalOrNull(cx));res = ScriptingCore::getInstance()->runScript(path.get(), glob);}return res;}args.rval().setUndefined();return true;
}------》》其实最终都是执行这个path就是我们传进来,也就是想要加载的js文件
ScriptingCore::getInstance()->runScript(path.get(), glob);
4、这个函数就是真正加载的函数:
bool ScriptingCore::runScript(const char *path, JS::HandleObject global, JSContext* cx)
{if (cx == NULL) {cx = _cx;}//进行编译compileScript(path,global,cx);JS::RootedScript script(cx, getScript(path));bool evaluatedOK = false;
if (script) {
//编译完后,就可以调用JS_ExecuteScript函数执行了。JS::RootedValue rval(cx);JSAutoCompartment ac(cx, global);evaluatedOK = JS_ExecuteScript(cx, global, script, &rval);if (false == evaluatedOK) {cocos2d::log("(evaluatedOK == JS_FALSE)");JS_ReportPendingException(cx);}}return evaluatedOK;
}
5、编译函数
void ScriptingCore::compileScript(const char *path, JSObject* global, JSContext* cx)
{if (!path) {return;}if (getScript(path)) { //如果已经编译过,则直接返回,这里有一个缓存
// name ~> JSScript map
static std::unordered_map<std::string, JSScript*> filename_script;return;}cocos2d::FileUtils *futil = cocos2d::FileUtils::getInstance();if (global == NULL) {global = _global.ref().get();}if (cx == NULL) {cx = _cx;}JSAutoCompartment ac(cx, global);JS::RootedScript script(cx);JS::RootedObject obj(cx, global);// a) check jsc file first  //先测试字节码,我们一般把js文件弄成字节码,防止被人使用std::string byteCodePath = RemoveFileExt(std::string(path)) + BYTE_CODE_FILE_EXT;// Check whether '.jsc' files exist to avoid outputing log which says 'couldn't find .jsc file'.if (futil->isFileExist(byteCodePath)){ //如果找到字节码文件,则进行JS_DecodeScript解码Data data = futil->getDataFromFile(byteCodePath);if (!data.isNull()){script = JS_DecodeScript(cx, data.getBytes(), static_cast<uint32_t>(data.getSize()), nullptr);}}// b) no jsc file, check js file, 如果没有jsc字节码文件,则找js文件if (!script){/* Clear any pending exception from previous failed decoding.  */ReportException(cx);std::string fullPath = futil->fullPathForFilename(path);JS::CompileOptions op(cx);op.setUTF8(true);op.setFileAndLine(fullPath.c_str(), 1);bool ok = false;
//这里对不同平台有个不同的处理,主要是存放文件的方式不同,然后调用
JS::Compile编译即可。
#if (CC_TARGET_PLATFORM == CC_PLATFORM_ANDROID)std::string jsFileContent = futil->getStringFromFile(fullPath);if (!jsFileContent.empty()){ok = JS::Compile(cx, obj, op, jsFileContent.c_str(), jsFileContent.size(), &script);}
#elseok = JS::Compile(cx, obj, op, fullPath.c_str(), &script);
#endifif (ok) {filename_script[fullPath] = script;}}else {filename_script[byteCodePath] = script;}
}

这篇关于Cocos2dx 3.X jsb加载JavaScript源码文件分析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/878939

相关文章

Spring Boot中的路径变量示例详解

《SpringBoot中的路径变量示例详解》SpringBoot中PathVariable通过@PathVariable注解实现URL参数与方法参数绑定,支持多参数接收、类型转换、可选参数、默认值及... 目录一. 基本用法与参数映射1.路径定义2.参数绑定&nhttp://www.chinasem.cnbs

JAVA中安装多个JDK的方法

《JAVA中安装多个JDK的方法》文章介绍了在Windows系统上安装多个JDK版本的方法,包括下载、安装路径修改、环境变量配置(JAVA_HOME和Path),并说明如何通过调整JAVA_HOME在... 首先去oracle官网下载好两个版本不同的jdk(需要登录Oracle账号,没有可以免费注册)下载完

Spring StateMachine实现状态机使用示例详解

《SpringStateMachine实现状态机使用示例详解》本文介绍SpringStateMachine实现状态机的步骤,包括依赖导入、枚举定义、状态转移规则配置、上下文管理及服务调用示例,重点解... 目录什么是状态机使用示例什么是状态机状态机是计算机科学中的​​核心建模工具​​,用于描述对象在其生命

Spring Boot 结合 WxJava 实现文章上传微信公众号草稿箱与群发

《SpringBoot结合WxJava实现文章上传微信公众号草稿箱与群发》本文将详细介绍如何使用SpringBoot框架结合WxJava开发工具包,实现文章上传到微信公众号草稿箱以及群发功能,... 目录一、项目环境准备1.1 开发环境1.2 微信公众号准备二、Spring Boot 项目搭建2.1 创建

Java中Integer128陷阱

《Java中Integer128陷阱》本文主要介绍了Java中Integer与int的区别及装箱拆箱机制,重点指出-128至127范围内的Integer值会复用缓存对象,导致==比较结果为true,下... 目录一、Integer和int的联系1.1 Integer和int的区别1.2 Integer和in

SpringSecurity整合redission序列化问题小结(最新整理)

《SpringSecurity整合redission序列化问题小结(最新整理)》文章详解SpringSecurity整合Redisson时的序列化问题,指出需排除官方Jackson依赖,通过自定义反序... 目录1. 前言2. Redission配置2.1 RedissonProperties2.2 Red

IntelliJ IDEA2025创建SpringBoot项目的实现步骤

《IntelliJIDEA2025创建SpringBoot项目的实现步骤》本文主要介绍了IntelliJIDEA2025创建SpringBoot项目的实现步骤,文中通过示例代码介绍的非常详细,对大家... 目录一、创建 Spring Boot 项目1. 新建项目2. 基础配置3. 选择依赖4. 生成项目5.

JSONArray在Java中的应用操作实例

《JSONArray在Java中的应用操作实例》JSONArray是org.json库用于处理JSON数组的类,可将Java对象(Map/List)转换为JSON格式,提供增删改查等操作,适用于前后端... 目录1. jsONArray定义与功能1.1 JSONArray概念阐释1.1.1 什么是JSONA

Java JDK1.8 安装和环境配置教程详解

《JavaJDK1.8安装和环境配置教程详解》文章简要介绍了JDK1.8的安装流程,包括官网下载对应系统版本、安装时选择非系统盘路径、配置JAVA_HOME、CLASSPATH和Path环境变量,... 目录1.下载JDK2.安装JDK3.配置环境变量4.检验JDK官网下载地址:Java Downloads

Spring boot整合dubbo+zookeeper的详细过程

《Springboot整合dubbo+zookeeper的详细过程》本文讲解SpringBoot整合Dubbo与Zookeeper实现API、Provider、Consumer模式,包含依赖配置、... 目录Spring boot整合dubbo+zookeeper1.创建父工程2.父工程引入依赖3.创建ap