为 Duktape 添加 JavaScript 模块化加载能力

简介:

Duktape 是一个体积小巧、可移植性高、适合嵌入到各种环境中的 JavaScript 引擎。

最近需要将 protobuf.js 移植到 Duktape 里边运行起来,所以需要解决 JavaScript 模块化加载问题,也就是要支持 require, module.exports 语法。我们通过 modSearch 函数来实现模块化加载:

实现 modSearch 函数

Implementing a native modSearch() function这篇 guide 里边有说通过在 native 实现 modSearch 函数就可以在 JavaScript 里通过require的时候加载到别的模块。

我在 c 层实现 modSearch 函数如下:

//
//  main.c
//  duktape
//
//  Created by faywong on 16/3/18.
//  Copyright © 2016年 faywong. All rights reserved.
//

#include <stdio.h>
#include "duktape.h"
#include "fileio.h"

duk_ret_t my_mod_search(duk_context *ctx) {
    /*
     *   index 0: id (string)
     *   index 1: require (object)
     *   index 2: exports (object)
     *   index 3: module (object)
     */
    printf("fun: %s in, id: %s\n", __FUNCTION__, duk_require_string(ctx, 0));

    const char *id = duk_require_string(ctx, 0);
    duk_pop_n(ctx, duk_get_top(ctx));

    const int FILE_PATH_LEN = 1024;
    char file[FILE_PATH_LEN];
    memset(file, 0, FILE_PATH_LEN);
    snprintf(file, FILE_PATH_LEN, "/Users/faywong/%s.js", id);

    duk_push_string_file(ctx, file);
    return 1;
}

/*
 * Register Duktape.modSearch
 */
void register_mod_search(duk_context *ctx) {
    duk_eval_string(ctx, "(function (fun) { Duktape.modSearch = fun; })");
    duk_push_c_function(ctx, my_mod_search, 4 /*nargs*/);
    duk_call(ctx, 1);
    duk_pop(ctx);
}

int main(int argc, const char * argv[]) {

    duk_context *ctx = duk_create_heap_default();

    if (ctx) {

        register_mod_search(ctx);

        register_fileio(ctx);

        duk_eval_file(ctx, "/Users/faywong/test.js");
        printf("result is: %s\n", duk_safe_to_string(ctx, -1));
        duk_pop(ctx);
    }

    return 0;
}

test.js 用以验证实现的模块化加载功能是否正常,内容如下:

var ByteBuffer = require('bytebuffer');
var test = new ByteBuffer(10);
print('step 1, ByteBuffer ok: ' + test.toString());
var ProtoBuf = require('protobuf');
print('step 2, ProtoBuf ok: ' + (typeof ProtoBuf));
print('step 3, typeof ProtoBuf.loadProtoFile: ' + (typeof ProtoBuf.loadProtoFile));
var builder = ProtoBuf.loadProtoFile('/Users/faywong/complex.proto');
print('step 4, typeof builder: ' + (typeof builder));

Game = builder.build("Game"),
Car = Game.Cars.Car;

// OR: Construct with values from an object, implicit message creation (address) and enum values as strings:
var car = new Car({
    "model": "Rustywq",
    "vendor": {
        "name": "Iron Inc.",
        "address": {
            "country": "US"
        }
    },
    "speed": "SUPERFAST" // also equivalent to "speed": 2
});

// OR: It's also possible to mix all of this!

// Afterwards, just encode your message:
var buffer = car.encode();

print('step 5, typeof buffer: ' + (typeof buffer) + ' toString(): ' + buffer.toString());
 

其中:

  • register_mod_search 函数用于向 Duktape 注册一个用于加载 JavaScript 模块的函数 my_mod_search,该函数有四个入参,分别为模块 id、发起 require 的模块、本模块的 exports 对象、本模块的 module 对象,该函数加载 /Users/faywong 目录下以 id 为主文件名(比如在 test.js 中 require 到的 bytebuffer, protobuf)的 JavaScript 文件并将文件内容返回给 Duktape
  • 为了方便,test.js 中 require 的其他 JavaScript 模块被笔者放在了自己的家目录下:
    /Users/faywong/bytebuffer.js
    /Users/faywong/protobuf.js
    /Users/faywong/test.js
目录
相关文章
|
1月前
|
JavaScript 前端开发 测试技术
如何编写JavaScript模块化代码
如何编写JavaScript模块化代码
12 0
|
2月前
|
JavaScript 前端开发 开发者
js模块化的好处
js模块化的好处
14 0
|
3月前
|
JavaScript 前端开发 程序员
程序员必备技能之JS模块化,改变你的JavaScript开发方式!(一)
程序员必备技能之JS模块化,改变你的JavaScript开发方式!
|
3月前
|
JavaScript 前端开发 Java
面试官:你的项目有什么亮点?我:解决了JS脚本加载失败的问题!
面试官:你的项目有什么亮点?我:解决了JS脚本加载失败的问题!
|
5月前
|
缓存 JavaScript 应用服务中间件
Nginx+Tomcat代理环境下JS无法完全加载问题
Nginx+Tomcat代理环境下JS无法完全加载问题
|
11天前
|
JavaScript 前端开发
EasyUi js 加载数据表格DataGrid
EasyUi js 加载数据表格DataGrid
|
16天前
|
JavaScript
理解DOM树的加载过程(js的问题)
理解DOM树的加载过程(js的问题)
|
27天前
|
JavaScript 前端开发
js开发:请解释什么是模块化(modularization),并说明如何在JavaScript中实现模块化。
模块化将复杂系统拆分为松散耦合的模块,提高代码可读性、可维护性、可复用性和可扩展性。JavaScript模块化历经CommonJS(Node.js中常见,使用`require()`和`module.exports`)、AMD(RequireJS,异步加载,`define()`和`require()`)和ES6 Modules(官方标准,`import`和`export`)三个阶段。打包工具如Webpack、Rollup处理兼容性问题,使模块化代码能在各种环境中运行。
|
5月前
|
JavaScript 前端开发 UED
JavaScript模块化:提高代码可维护性和可重用性的利器
JavaScript模块化:提高代码可维护性和可重用性的利器
60 0
|
1月前
|
JavaScript
js判断图片是否加载完成
js判断图片是否加载完成
24 0