Cocos2d-x   发布时间:2022-05-03  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了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.log
    JS_DefineFunction(cx,"log",ScripTingCore::log,JSPROP_READONLY | JSPROP_PERMANENT);
  
}
3、
//这个函数是我们的重点
bool ScripTingCore::executeScript(JSContext *cx,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,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,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);
        }
#else
        ok = JS::Compile(cx,fullPath.c_str(),&script);
#endif
        if (ok) {
            filename_script[fullPath] = script;
        }
    }
    else {
        filename_script[byteCodePath] = script;
    }
}






大佬总结

以上是大佬教程为你收集整理的Cocos2dx 3.X jsb加载JavaScript源码文件分析全部内容,希望文章能够帮你解决Cocos2dx 3.X jsb加载JavaScript源码文件分析所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。