为了账号安全,请及时绑定邮箱和手机立即绑定

如何将多个js文件与Duktape一起使用?

如何将多个js文件与Duktape一起使用?

慕斯709654 2022-09-02 21:03:05
我在嵌入式MCU中使用Duktape。对于测试用例,我有:主.js文件:(function(){    test();})();测试.js文件:(function test(){    print("func");})编译为全局默认代码和主.js都使用duk_call(ctx, 0)执行;问题是它在调用 test() 函数时会引发错误。我也尝试过使用function test() {   print("test");}在 test.js代码,但它也不起作用。我的理解是,这两个文件都有单独的执行上下文。这就是为什么功能无法访问的原因。但是,将Duktape的代码拆分为多个文件的正确方法是什么?附言:我的目标是避免使用全局上下文,因为在文档中,据说以这种方式访问变量很慢,这就是为什么main.js看起来那样的原因。附言我确信test()函数是无法访问的,但我不知道如何编写js代码以便一切正常。P.P.P.S print() 是一个 C 函数,输出到 esp32 的串行端口,它可以工作。甚至 main.js 在没有 test() 函数调用的情况下工作。
查看完整描述

1 回答

?
德玛西亚99

TA贡献1770条经验 获得超3个赞

基本上,您想要的是文件导入功能。您可以通过两种方式实现它:

  1. 在后端提供一个函数并将其导出到 JS,以允许在运行时动态加载文件。

  2. 实现像Node.js这样的模块处理(本质上也归结为导入函数)。

第二个想法是最常用的方法,并实现了一种定义良好的方法,以在JS应用程序中包含其他文件。Duktape附带了一个额外的文件来实现该命令,就像在Node.js中一样。您只需要提供自己的函数来解析模块并从磁盘加载它(因为 duktape 没有文件 I/O 支持)。require

我在MySQL Workbench的MGA工具中实现了这种方法。用于实现节点模块处理的 duktape 文件在这里。解析模块的函数(包括处理嵌套文件夹等)在 ScriptingContext 类中实现。它的相关部分是这样的:node_modules

/**

 * Part of the module loading machinery. JS interfacing is done by the duk_module_node code.

 * But we have to do the file work here. On the stack we get the value passed to `require()` as a "module ID" and

 * the ID of the calling script (which is empty for the main script).

 */

duk_ret_t ScriptingContext::resolveModule(duk_context *ctx) {

  // stack: [ requested_id parent_id ]

  std::string requestedID = duk_get_string(ctx, 0);

  std::string callingID = duk_get_string(ctx, 1);

  std::string parentPath = FS::isDir(callingID) ? callingID : Path::dirname(callingID);


  // Module resolution strategy in Node.js style: https://nodejs.org/api/modules.html#modules_all_together

  auto modules = getInternalModules();

  if (modules.find(requestedID) != modules.end()) {

    duk_push_string(ctx, requestedID.c_str());

    return 1;

  }


  ScriptingContext *context = ScriptingContext::fromDuktapeContext(ctx);

  std::string resolvedID;

  std::string cwd = Process::cwd();


  try {

    if (Path::isAbsolute(requestedID) || Utilities::hasPrefix(requestedID, ".")) {

      std::string temp;

      if (Path::isAbsolute(requestedID)) {

        temp = Path::relative(cwd, requestedID);

      } else

        temp = Path::join({ parentPath, requestedID });


      resolvedID = resolveFile(temp);

      if (resolvedID.empty())

        resolvedID = resolveFolder(context, temp);

    }

  } catch (std::runtime_error &e) {

    // Triggered for parse errors in package.json.

    context->throwScriptingError(ScriptingError::Syntax, e.what());

    return 0;

  }


  // No files found so far. Check node modules.

  if (resolvedID.empty()) {

    for (auto &folder : moduleFolders(parentPath)) {

      std::string path = Path::join({ folder, requestedID });

      std::string temp = resolveFile(path);

      if (!temp.empty()) {

        resolvedID = temp;

        break;

      }


      temp = resolveFolder(context, path);

      if (!temp.empty()) {

        resolvedID = temp;

        break;

      }

    }

  }


  if (resolvedID.empty()) {

    context->throwScriptingError(ScriptingError::Error, Utilities::format("Cannot resolve module %s", requestedID.c_str()));

    return 0;

  }


  duk_push_string(ctx, resolvedID.c_str());

  return 1;  // Use result on stack.

}


查看完整回答
反对 回复 2022-09-02
  • 1 回答
  • 0 关注
  • 202 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号