• 前端:QuickJS到底能干什么


    640?wx_fmt=png


    QuickJS 是一个轻量且可嵌入的 JavaScript 引擎,它支持 ES2019 规范,包括 ES module、异步生成器以及 proxies。除此之外,还支持可选的数学扩展,例如大整数(BigInt)、大浮点数(BigFloat)和运算符重载。


    主要特点:

    • 轻量而且易于嵌入:只需几个C文件,没有外部依赖,一个x86下的简单的“hello world”程序只要180 KiB。

    • 具有极低启动时间的快速解释器:在一台单核的台式PC上,大约在100秒内运行ECMAScript 测试套件1 56000次。运行时实例的完整生命周期在不到300微秒的时间内完成。

    • 几乎完整实现ES2019支持,包括:模块,异步生成器和和完整Annex B支持 (传统的Web兼容性)。

    • 通过100%的ECMAScript Test Suite测试。

    • 可以将Javascript源编译为没有外部依赖的可执行文件。

    • 使用引用计数(以减少内存使用并具有确定性行为)的垃圾收集与循环删除。

    • 数学扩展:BigInt, BigFloat, 运算符重载, bigint模式, math模式.

    • 在Javascript中实现的具有上下文着色和完成的命令行解释器。

    • 采用C包装库构建的内置标准库。

    用途:后端服务、嵌入式应用、命令工具等等。

    示例:

    QuickJS/bjson.c:一个可读取可写入JSON文件的插件

    #include "quickjs-libc.h"
    #include "cutils.h"

    static JSValue js_bjson_read(JSContext *ctx, JSValueConst this_val,
    int argc, JSValueConst *argv)
    {
    uint8_t *buf;
    uint64_t pos, len;
    JSValue obj;
    size_t size;

    if (JS_ToIndex(ctx, &pos, argv[1]))
    return JS_EXCEPTION;
    if (JS_ToIndex(ctx, &len, argv[2]))
    return JS_EXCEPTION;
    buf = JS_GetArrayBuffer(ctx, &size, argv[0]);
    if (!buf)
    return JS_EXCEPTION;
    if (pos + len > size)
    return JS_ThrowRangeError(ctx, "array buffer overflow");
    obj = JS_ReadObject(ctx, buf + pos, len, 0);
    return obj;
    }

    static JSValue js_bjson_write(JSContext *ctx, JSValueConst this_val,
    int argc, JSValueConst *argv)
    {
    size_t len;
    uint8_t *buf;
    JSValue array;

    buf = JS_WriteObject(ctx, &len, argv[0], 0);
    if (!buf)
    return JS_EXCEPTION;
    array = JS_NewArrayBufferCopy(ctx, buf, len);
    js_free(ctx, buf);
    return array;
    }

    static const JSCFunctionListEntry js_bjson_funcs[] = {
    JS_CFUNC_DEF("read", 3, js_bjson_read ),
    JS_CFUNC_DEF("write", 1, js_bjson_write ),
    };

    static int js_bjson_init(JSContext *ctx, JSModuleDef *m)
    {
    return JS_SetModuleExportList(ctx, m, js_bjson_funcs,
    countof(js_bjson_funcs));
    }

    #ifdef JS_SHARED_LIBRARY
    #define JS_INIT_MODULE js_init_module
    #else
    #define JS_INIT_MODULE js_init_module_bjson
    #endif

    JSModuleDef *JS_INIT_MODULE(JSContext *ctx, const char *module_name)
    {
    JSModuleDef *m;
    m = JS_NewCModule(ctx, module_name, js_bjson_init);
    if (!m)
    return NULL;
    JS_AddModuleExportList(ctx, m, js_bjson_funcs, countof(js_bjson_funcs));
    return m;
    }


    QuickJS/tests/test_bjson.js:测试代码

    import * as bjson from "../bjson.so";

    function assert(b, str)
    {
    if (b) {
    return;
    } else {
    throw Error("assertion failed: " + str);
    }
    }

    function toHex(a)
    {
    var i, s = "", tab, v;
    tab = new Uint8Array(a);
    for(i = 0; i < tab.length; i++) {
    v = tab[i].toString(16);
    if (v.length < 2)
    v = "0" + v;
    if (i !== 0)
    s += " ";
    s += v;
    }
    return s;
    }

    function toStr(a)
    {
    var s, i, props, prop;

    switch(typeof(a)) {
    case "object":
    if (a === null)
    return "null";
    if (Array.isArray(a)) {
    s = "[";
    for(i = 0; i < a.length; i++) {
    if (i != 0)
    s += ",";
    s += toStr(a[i]);
    }
    s += "]";
    } else {
    props = Object.keys(a);
    s = "{";
    for(i = 0; i < props.length; i++) {
    if (i != 0)
    s += ",";
    prop = props[i];
    s += prop + ":" + toStr(a[prop]);
    }
    s += "}";
    }
    return s;
    case "undefined":
    return "undefined";
    case "string":
    return a.__quote();
    case "number":
    case "bigfloat":
    if (a == 0 && 1 / a < 0)
    return "-0";
    else
    return a.toString();
    break;
    default:
    return a.toString();
    }
    }

    function bjson_test(a)
    {
    var buf, r, a_str, r_str;
    a_str = toStr(a);
    buf = bjson.write(a);
    if (0) {
    print(a_str, "->", toHex(buf));
    }
    r = bjson.read(buf, 0, buf.byteLength);
    r_str = toStr(r);
    if (a_str != r_str) {
    print(a_str);
    print(r_str);
    assert(false);
    }
    }

    function bjson_test_all()
    {
    var obj;

    bjson_test({x:1, y:2, if:3});
    bjson_test([1, 2, 3]);
    bjson_test([1.0, "aa", true, false, undefined, null, NaN, -Infinity, -0.0]);
    if (typeof BigInt !== "undefined") {
    bjson_test([BigInt("1"), -BigInt("0x123456789"),
    BigInt("0x123456789abcdef123456789abcdef")]);
    }
    if (typeof BigFloat !== "undefined") {
    BigFloatEnv.setPrec(function () {
    bjson_test([BigFloat("0.1"), BigFloat("-1e30"), BigFloat("0"),
    BigFloat("-0"), BigFloat("Infinity"), BigFloat("-Infinity"),
    0.0 / BigFloat("0"), BigFloat.MAX_VALUE,
    BigFloat.MIN_VALUE]);
    }, 113, 15);
    }

    /* tested with a circular reference */
    obj = {};
    obj.x = obj;
    try {
    bjson.write(obj);
    assert(false);
    } catch(e) {
    assert(e instanceof TypeError);
    }
    }

    bjson_test_all();


  • 相关阅读:
    美国贷款买饭的房屋保险
    ArrayList和数组间的相互转换
    JList动态添加元素
    美国交往礼仪
    刘元普双生贵子(但行好事,莫问前程)
    CountDownLatch与CyclicBarrier
    彻底理解Java的feature模式
    Java中的Future模式原理自定义实现
    浅谈Java Future接口
    Future接口和Callable接口以及FeatureTask详解
  • 原文地址:https://www.cnblogs.com/hgmyz/p/12350957.html
Copyright © 2020-2023  润新知