当前位置:首页 > 科技  > 软件

跨端轻量JavaScript引擎的实现与探索

来源: 责编: 时间:2024-03-18 09:42:06 102观看
导读一、JavaScript1.JavaScript语言JavaScript是ECMAScript的实现,由ECMA 39(欧洲计算机制造商协会39号技术委员会)负责制定ECMAScript标准。ECMAScript发展史:时间版本说明1997年7月ES1.0 发布当年7月,ECMA262 标准出台1

一、JavaScript

1.JavaScript语言

JavaScript是ECMAScript的实现,由ECMA 39(欧洲计算机制造商协会39号技术委员会)负责制定ECMAScript标准。kJu28资讯网——每日最新资讯28at.com

ECMAScript发展史:kJu28资讯网——每日最新资讯28at.com

时间kJu28资讯网——每日最新资讯28at.com

版本kJu28资讯网——每日最新资讯28at.com

说明kJu28资讯网——每日最新资讯28at.com

1997年7月kJu28资讯网——每日最新资讯28at.com

ES1.0 发布kJu28资讯网——每日最新资讯28at.com

当年7月,ECMA262 标准出台kJu28资讯网——每日最新资讯28at.com

1998年6月kJu28资讯网——每日最新资讯28at.com

ES2.0 发布kJu28资讯网——每日最新资讯28at.com

该版本修改完全符合ISO/IEC 16262国际标准。kJu28资讯网——每日最新资讯28at.com

1999年12月kJu28资讯网——每日最新资讯28at.com

ES3.0 发布kJu28资讯网——每日最新资讯28at.com

成为 JavaScript 的通行标准,得到了广泛支持kJu28资讯网——每日最新资讯28at.com

2007年10月kJu28资讯网——每日最新资讯28at.com

ES4.0草案发布kJu28资讯网——每日最新资讯28at.com

各大厂商意见分歧,该方案未通过kJu28资讯网——每日最新资讯28at.com

2008年7月kJu28资讯网——每日最新资讯28at.com

发布ES3.1,并改名为ECMAScript 5kJu28资讯网——每日最新资讯28at.com

废除ECMAScript 4.0,所以4.0版本不存在kJu28资讯网——每日最新资讯28at.com

2009年12月kJu28资讯网——每日最新资讯28at.com

ESt 5.0 正式发布kJu28资讯网——每日最新资讯28at.com


kJu28资讯网——每日最新资讯28at.com

2011年6月kJu28资讯网——每日最新资讯28at.com

ES5.1 发布kJu28资讯网——每日最新资讯28at.com

该版本成为了 ISO 国际标准(ISO/IEC 16262:2011)kJu28资讯网——每日最新资讯28at.com

2013年12月kJu28资讯网——每日最新资讯28at.com

ES6 草案发布kJu28资讯网——每日最新资讯28at.com


kJu28资讯网——每日最新资讯28at.com

2015年6月kJu28资讯网——每日最新资讯28at.com

ES6 正式发布,并且更名为“ECMAScript 2015”kJu28资讯网——每日最新资讯28at.com

TC39委员会决定每年发布一个ECMAScript 的版本kJu28资讯网——每日最新资讯28at.com

2.JavaScript引擎

JavaScript引擎是指用于处理以及执行JavaScript脚本的虚拟机。kJu28资讯网——每日最新资讯28at.com

常见的JavaScript引擎:kJu28资讯网——每日最新资讯28at.com

kJu28资讯网——每日最新资讯28at.com

引擎kJu28资讯网——每日最新资讯28at.com

所属机构/个人kJu28资讯网——每日最新资讯28at.com

浏览器kJu28资讯网——每日最新资讯28at.com

说明kJu28资讯网——每日最新资讯28at.com

SpiderMonkeykJu28资讯网——每日最新资讯28at.com

MozillakJu28资讯网——每日最新资讯28at.com

FirefoxkJu28资讯网——每日最新资讯28at.com

第一款JavaScript引擎,早期用于 Netscape Navigator,现时用于 Mozilla Firefox。是用C语言实现的,还有一个Java版本叫Rhino;Rhino引擎由Mozilla基金会管理,开放源代码,完全以Java编写,用于 HTMLUnit;而后TraceMonkey引擎是基于实时编译的引擎,用于Mozilla Firefox 3.5~3.6版本;JaegerMonkey:结合追踪和组合码技术大幅提高性能,用于Mozilla Firefox 4.0以上版本kJu28资讯网——每日最新资讯28at.com

JavaScriptCorekJu28资讯网——每日最新资讯28at.com

ApplekJu28资讯网——每日最新资讯28at.com

SafarikJu28资讯网——每日最新资讯28at.com

简称JSC,开源,用于webkit内核浏览器,如 Safari ,2008 年实现了编译器和字节码解释器,升级为了SquirrelFish。苹果内部代号为Nitro的 JavaScript 引擎也是基于 JSC引擎的。至于具体时间,JSC是WebKit默认内嵌的JS引擎,而WebKit诞生于1998年,Nitro是为Safari 4编写,Safari 4是2009年6月发布。kJu28资讯网——每日最新资讯28at.com

V8kJu28资讯网——每日最新资讯28at.com

GooglekJu28资讯网——每日最新资讯28at.com

ChromekJu28资讯网——每日最新资讯28at.com

2008年9月,Google的V8引擎第一个版本随着Chrome的第一个版本发布。V8引擎用 C++编写,由 Google 丹麦开发,开源。除了Chrome,还被运用于Node.js以及运用于Android操作系统等kJu28资讯网——每日最新资讯28at.com

ChakrakJu28资讯网——每日最新资讯28at.com

MicrosoftkJu28资讯网——每日最新资讯28at.com

Edge、IEkJu28资讯网——每日最新资讯28at.com

译名查克拉,用于IE9、10、11和Microsoft Edge,IE9发布时间2011年3月kJu28资讯网——每日最新资讯28at.com

JerryScriptkJu28资讯网——每日最新资讯28at.com

三星kJu28资讯网——每日最新资讯28at.com


kJu28资讯网——每日最新资讯28at.com

三星推出的适用于嵌入式设备的小型 JavaScript 引擎,2015年开源kJu28资讯网——每日最新资讯28at.com

NashornkJu28资讯网——每日最新资讯28at.com

OracalekJu28资讯网——每日最新资讯28at.com


kJu28资讯网——每日最新资讯28at.com

从 JDK 1.8 开始,Nashorn取代Rhino(JDK 1.6, JDK1.7) 成为 Java 的嵌入式 JavaScript 引擎,JDK1.8发布于2014年kJu28资讯网——每日最新资讯28at.com

QuickJSkJu28资讯网——每日最新资讯28at.com

Fabrice BellardkJu28资讯网——每日最新资讯28at.com


kJu28资讯网——每日最新资讯28at.com

QuickJS 是一个小型的嵌入式 Javascript 引擎。 它支持 ES2023 规范,包括模块、异步生成器、代理和 BigInt。 它可以选择支持数学扩展,例如大十进制浮点数 (BigDecimal)、大二进制浮点数 (BigFloat) 和运算符重载。kJu28资讯网——每日最新资讯28at.com

HermeskJu28资讯网——每日最新资讯28at.com

FacebookkJu28资讯网——每日最新资讯28at.com


kJu28资讯网——每日最新资讯28at.com

引擎,Facebook在Chain React 2019 大会上发布的一个崭新JavaScript引擎,用于移动端React Native应用的集成,开源kJu28资讯网——每日最新资讯28at.com

3.JavaScript引擎工作原理

a.V8引擎工作原理

kJu28资讯网——每日最新资讯28at.com

b.Turbofan技术实例说明

function sum(a, b) {    return a + b;}

这里a和b可以是任意类型数据,当执行sum函数时,Ignition解释器会检查a和b的数据类型,并相应地执行加法或者连接字符串的操作。kJu28资讯网——每日最新资讯28at.com

如果 sum函数被调用多次,每次执行时都要检查参数的数据类型是很浪费时间的。此时TurboFan就出场了。它会分析函数的执行信息,如果以前每次调用sum函数时传递的参数类型都是数字,那么TurboFan就预设sum的参数类型是数字类型,然后将其编译为机器码。kJu28资讯网——每日最新资讯28at.com

但是如果某一次的调用传入的参数不再是数字时,表示TurboFan的假设是错误的,此时优化编译生成的机器代码就不能再使用了,于是就需要进行回退到字节码的操作。kJu28资讯网——每日最新资讯28at.com

三、QuickJS

1.QuickJS作者简介

法布里斯·貝拉 (Fabrice Bellard)kJu28资讯网——每日最新资讯28at.com

kJu28资讯网——每日最新资讯28at.com

kJu28资讯网——每日最新资讯28at.com

2.QuickJS简介

QuickJS 是一个小型的嵌入式 Javascript 引擎。 它支持 ES2023 规范,包括模块、异步生成器、代理和 BigInt。kJu28资讯网——每日最新资讯28at.com

它可以选择支持数学扩展,例如大十进制浮点数 (BigDecimal)、大二进制浮点数 (BigFloat) 和运算符重载。kJu28资讯网——每日最新资讯28at.com

•小且易于嵌入:只需几个 C 文件,无外部依赖项,一个简单的 hello world 程序的 210 KiB x86 代码。kJu28资讯网——每日最新资讯28at.com

•启动时间极短的快速解释器:在台式 PC 的单核上运行 ECMAScript 测试套件的 76000 次测试只需不到 2 分钟。 运行时实例的完整生命周期在不到 300 微秒的时间内完成。kJu28资讯网——每日最新资讯28at.com

•几乎完整的 ES2023 支持,包括模块、异步生成器和完整的附录 B 支持(旧版 Web 兼容性)。kJu28资讯网——每日最新资讯28at.com

•通过了近 100% 的 ECMAScript 测试套件测试: Test262 Report(https://test262.fyi/#)。kJu28资讯网——每日最新资讯28at.com

•可以将 Javascript 源代码编译为可执行文件,无需外部依赖。kJu28资讯网——每日最新资讯28at.com

•使用引用计数(以减少内存使用并具有确定性行为)和循环删除的垃圾收集。kJu28资讯网——每日最新资讯28at.com

•数学扩展:BigDecimal、BigFloat、运算符重载、bigint 模式、数学模式。kJu28资讯网——每日最新资讯28at.com

•用 Javascript 实现的带有上下文着色的命令行解释器。kJu28资讯网——每日最新资讯28at.com

•带有 C 库包装器的小型内置标准库。kJu28资讯网——每日最新资讯28at.com

3.QuickJS工程简介

5.94MB quickjs├── 17.6kB      cutils.c                /// 辅助函数├── 7.58kB      cutils.h                /// 辅助函数├── 241kB       libbf.c                 /// BigFloat相关├── 17.9kB      libbf.h                 /// BigFloat相关├── 2.25kB      libregexp-opcode.h      /// 正则表达式操作符├── 82.3kB      libregexp.c             /// 正则表达式相关├── 3.26kB      libregexp.h             /// 正则表达式相关├── 3.09kB      list.h                  /// 链表实现├── 16.7kB      qjs.c                   /// QuickJS stand alone interpreter├── 22kB        qjsc.c                  /// QuickJS command line compiler├── 73.1kB      qjscalc.js              /// 数学计算器├── 7.97kB      quickjs-atom.h          /// 定义了javascript中的关键字├── 114kB       quickjs-libc.c├── 2.57kB      quickjs-libc.h          /// C API├── 15.9kB      quickjs-opcode.h        /// 字节码操作符定义├── 1.81MB      quickjs.c               ├── 41.9kB      quickjs.h               /// QuickJS Engine├── 49.8kB      repl.js                 /// REPL├── 218kB       libunicode-table.h      /// unicode相关├── 53kB        libunicode.c            /// unicode相关├── 3.86kB      libunicode.h            /// unicode相关├── 86.4kB      unicode_gen.c           /// unicode相关└── 6.99kB      unicode_gen_def.h       /// unicode相关

4.QuickJS工作原理

QuickJS的解释器是基于栈的。kJu28资讯网——每日最新资讯28at.com

kJu28资讯网——每日最新资讯28at.com

QuickJS的对byte-code会优化两次,通过一个简单例子看看QuickJS的字节码与优化器的输出,以及执行过程。kJu28资讯网——每日最新资讯28at.com

function sum(a, b) {    return a + b;}

•第一阶段(未经过优化的字节码)kJu28资讯网——每日最新资讯28at.com

;; function sum(a, b) {        enter_scope 1    ;;     return a + b;        line_num 2        scope_get_var a,1    ///通用的获取变量的指令        scope_get_var b,1            add        return;; }

•第二阶段kJu28资讯网——每日最新资讯28at.com

;; function sum(a, b) {;;     return a + b;        line_num 2        get_arg 0: a        /// 获取参数列表中的变量        get_arg 1: b        add        return;; }

•第三阶段kJu28资讯网——每日最新资讯28at.com

;; function sum(a, b) {;;     return a + b;        get_arg0 0: a        /// 精简成获取参数列表中第0个参数        get_arg1 1: b        add        return;; }
sum(1,2);

通过上述简单的函数调用,观察sum函数调用过程中栈帧的变化,通过计算可知sum函数最栈帧大小为两个字节kJu28资讯网——每日最新资讯28at.com

get_arg0kJu28资讯网——每日最新资讯28at.com

get_arg1kJu28资讯网——每日最新资讯28at.com

addkJu28资讯网——每日最新资讯28at.com

returnkJu28资讯网——每日最新资讯28at.com

1kJu28资讯网——每日最新资讯28at.com

2kJu28资讯网——每日最新资讯28at.com

3kJu28资讯网——每日最新资讯28at.com

将栈顶的数据3返回kJu28资讯网——每日最新资讯28at.com


kJu28资讯网——每日最新资讯28at.com

1kJu28资讯网——每日最新资讯28at.com


kJu28资讯网——每日最新资讯28at.com


kJu28资讯网——每日最新资讯28at.com

5.内存管理

QuickJS通过引用计算来管理内存,在使用C API时需要根据不同API的说明手动增加或者减少引用计数器。kJu28资讯网——每日最新资讯28at.com

对于循环引用的对象,QuickJS通过临时减引用保存到临时数组中的方法来判断相互引用的对象是否可以回收。kJu28资讯网——每日最新资讯28at.com

6.QuickJS简单使用

从github上clone完最新的源码后,通过执行(macos 环境)以下代码即可在本地安装好qjs、qjsc、qjscalc几个命令行程序kJu28资讯网——每日最新资讯28at.com

sudo makesudo make install

•qjs: JavaScript代码解释器kJu28资讯网——每日最新资讯28at.com

•qjsc: JavaScript代码编译器kJu28资讯网——每日最新资讯28at.com

•qjscalc: 基于QuickJS的REPL计算器程序kJu28资讯网——每日最新资讯28at.com

通过使用qjs可以直接运行一个JavaScript源码,通过qsjc的如下命令,则可以输出一个带有byte-code源码的可直接运行的C源文件:kJu28资讯网——每日最新资讯28at.com

qjsc -e  -o add.c examples/add.js
#include "quickjs-libc.h"const uint32_t qjsc_add_size = 135;const uint8_t qjsc_add[135] = { 0x02, 0x06, 0x06, 0x73, 0x75, 0x6d, 0x0e, 0x63, 0x6f, 0x6e, 0x73, 0x6f, 0x6c, 0x65, 0x06, 0x6c, 0x6f, 0x67, 0x1e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x73, 0x2f, 0x61, 0x64, 0x64, 0x2e, 0x6a, 0x73, 0x02, 0x61, 0x02, 0x62, 0x0e, 0x00, 0x06, 0x00, 0xa2, 0x01, 0x00, 0x01, 0x00, 0x05, 0x00, 0x01, 0x25, 0x01, 0xa4, 0x01, 0x00, 0x00, 0x00, 0x3f, 0xe3, 0x00, 0x00, 0x00, 0x40, 0xc2, 0x00, 0x40, 0xe3, 0x00, 0x00, 0x00, 0x00, 0x38, 0xe4, 0x00, 0x00, 0x00, 0x42, 0xe5, 0x00, 0x00, 0x00, 0x38, 0xe3, 0x00, 0x00, 0x00, 0xb8, 0xb9, 0xf2, 0x24, 0x01, 0x00, 0xcf, 0x28, 0xcc, 0x03, 0x01, 0x04, 0x1f, 0x00, 0x08, 0x0a, 0x0e, 0x43, 0x06, 0x00, 0xc6, 0x03, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x04, 0x02, 0xce, 0x03, 0x00, 0x01, 0x00, 0xd0, 0x03, 0x00, 0x01, 0x00, 0xd3, 0xd4, 0x9e, 0x28, 0xcc, 0x03, 0x01, 0x01, 0x03,};static JSContext *JS_NewCustomContext(JSRuntime *rt){  JSContext *ctx = JS_NewContextRaw(rt);  if (!ctx)    return NULL;  JS_AddIntrinsicBaseObjects(ctx);  JS_AddIntrinsicDate(ctx);  JS_AddIntrinsicEval(ctx);  JS_AddIntrinsicStringNormalize(ctx);  JS_AddIntrinsicRegExp(ctx);  JS_AddIntrinsicJSON(ctx);  JS_AddIntrinsicProxy(ctx);  JS_AddIntrinsicMapSet(ctx);  JS_AddIntrinsicTypedArrays(ctx);  JS_AddIntrinsicPromise(ctx);  JS_AddIntrinsicBigInt(ctx);  return ctx;}int main(int argc, char **argv){  JSRuntime *rt;  JSContext *ctx;  rt = JS_NewRuntime();  js_std_set_worker_new_context_func(JS_NewCustomContext);  js_std_init_handlers(rt);  JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL);  ctx = JS_NewCustomContext(rt);  js_std_add_helpers(ctx, argc, argv);  js_std_eval_binary(ctx, qjsc_add, qjsc_add_size, 0);  js_std_loop(ctx);  js_std_free_handlers(rt);  JS_FreeContext(ctx);  JS_FreeRuntime(rt);  return 0;}

上面的这个C源文件,通过如下命令即可编译成可执行文件:kJu28资讯网——每日最新资讯28at.com

gcc add.c -o add_exec -I/usr/local/include quickjs-libc.c quickjs.c cutils.c libbf.c libregexp.c libunicode.c  -DCONFIG_BIGNUM

也可以直接使用如下命令,将JavaScript文件直接编译成可执行文件:kJu28资讯网——每日最新资讯28at.com

qjsc -o add_exec examples/add.js

7.给qjsc添加扩展

QuickJS只实现了最基本的JavaScript能力,同时QuickJS也可以实现能力的扩展,比如给QuickJS添加打开文件并读取文件内容的内容,这样在JavaScript代码中即可通过js代码打开并读取到文件内容了。kJu28资讯网——每日最新资讯28at.com

通过一个例子来看看添加扩展都需要做哪些操作:kJu28资讯网——每日最新资讯28at.com

•编写一个C语言的扩展模块kJu28资讯网——每日最新资讯28at.com

#include "quickjs.h"#include "cutils.h"/// js中对应plus函数的C语言函数static JSValue plusNumbers(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) {    int a, b;    if (JS_ToInt32(ctx, &a, argv[0]))        return JS_EXCEPTION;    if (JS_ToInt32(ctx, &b, argv[1]))        return JS_EXCEPTION;    return JS_NewInt32(ctx, a + b);}/// 模块需要导致的列表static const JSCFunctionListEntry js_my_module_funcs[] = {    JS_CFUNC_DEF("plus", 2, plusNumbers),};/// 模块初始化函数,并将plus导出static int js_my_module_init(JSContext *ctx, JSModuleDef *m) {    return JS_SetModuleExportList(ctx, m, js_my_module_funcs, countof(js_my_module_funcs));}JSModuleDef *js_init_module_my_module(JSContext *ctx, const char *module_name) {    JSModuleDef *m;    m = JS_NewCModule(ctx, module_name, js_my_module_init);    if (!m)        return NULL;    JS_AddModuleExportList(ctx, m, js_my_module_funcs, countof(js_my_module_funcs));    return m;}

•Makefile文件中添加my_module.c模块的编译kJu28资讯网——每日最新资讯28at.com

QJS_LIB_OBJS= ... $(OBJDIR)/my_module.o

•在qjsc.c文件中注册模块kJu28资讯网——每日最新资讯28at.com

namelist_add(&cmodule_list,“my_module”,“my_module”,0);

•编写一个my_module.js测试文件kJu28资讯网——每日最新资讯28at.com

import * as mm from 'my_module';const value = mm.plus(1, 2);console.log(`my_module.plus: ${value}`);

•重新编译kJu28资讯网——每日最新资讯28at.com

sudo make && sudo make installqjsc -m -o my_module examples/my_module.js /// 这里需要指定my_module模块

最终生成的my_module可执行文件,通过执行my_module输出:kJu28资讯网——每日最新资讯28at.com

my_module.plus: 3

8.使用C API

在第5个步骤时,生成了add.c文件中实际上已经给出了一个简单的使用C API最基本的代码。当编写一下如下的js源码时,会发现当前的qjsc编译后的可执行文件或者qjs执行这段js代码与我们的预期不符:kJu28资讯网——每日最新资讯28at.com

function getName() {    return new Promise((resolve, reject) => {        setTimeout(() => {            resolve("张三峰");        }, 2000);    });}console.log(`开始执行`);getName().then(name => console.log(`promise name: ${name}`));

kJu28资讯网——每日最新资讯28at.com

上面的代码并不会按预期的效果输出结果,因为js环境下的loop只执行了一次,任务队列还没有来得急执行程序就结束了,稍微改动一下让程序可以正常输出,如下:kJu28资讯网——每日最新资讯28at.com

#include <stdio.h>#include <pthread.h>#include <stdlib.h>#include <uv.h>/* File generated automatically by the QuickJS compiler. */#include "quickjs-libc.h"#include <string.h>static JSContext *JS_NewCustomContext(JSRuntime *rt) {  JSContext *ctx = JS_NewContextRaw(rt);  if (!ctx)    return NULL;  JS_AddIntrinsicBaseObjects(ctx);  JS_AddIntrinsicDate(ctx);  JS_AddIntrinsicEval(ctx);  JS_AddIntrinsicStringNormalize(ctx);  JS_AddIntrinsicRegExp(ctx);  JS_AddIntrinsicJSON(ctx);  JS_AddIntrinsicProxy(ctx);  JS_AddIntrinsicMapSet(ctx);  JS_AddIntrinsicTypedArrays(ctx);  JS_AddIntrinsicPromise(ctx);  JS_AddIntrinsicBigInt(ctx);  return ctx;}JSRuntime *rt = NULL;JSContext *ctx = NULL;void *run(void *args) {    const char *file_path = "/Volumes/Work/分享/quickjs/code/quickjs/examples/promise.js";    size_t pbuf_len = 0;            js_std_set_worker_new_context_func(JS_NewCustomContext);    js_std_init_handlers(rt);    JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL);    ctx = JS_NewCustomContext(rt);            js_std_add_helpers(ctx, 0, NULL);    js_init_module_os(ctx, "test");    const uint8_t *code = js_load_file(ctx, &pbuf_len, file_path);    JSValue js_ret_val = JS_Eval(ctx, (char *)code, pbuf_len, "add", JS_EVAL_TYPE_MODULE);    if(JS_IsError(ctx, js_ret_val) || JS_IsException(js_ret_val)) {        js_std_dump_error(ctx);    }    return NULL;}pthread_t quickjs_t;int main(int argc, char **argv) {    rt = JS_NewRuntime();    pthread_create(&quickjs_t, NULL, run, NULL);    while (1) {        if(ctx) js_std_loop(ctx);    }    js_std_free_handlers(rt);    JS_FreeContext(ctx);    JS_FreeRuntime(rt);    return 0;}

这样的操作只适合用于测试一下功能,实际生产中使用需要一个即可以在必要的时候调用loop又可以做到不抢占过多的CPU或者只抢占较少的CPU时间片。kJu28资讯网——每日最新资讯28at.com

四、libuv

1.libuv简价

libuv 是一个使用C语言编写的多平台支持库,专注于异步 I/O。 它主要是为 Node.js 使用而开发的,但 Luvit、Julia、uvloop 等也使用它。kJu28资讯网——每日最新资讯28at.com

功能亮点kJu28资讯网——每日最新资讯28at.com

•由 epoll、kqueue、IOCP、事件端口支持的全功能事件循环。kJu28资讯网——每日最新资讯28at.com

•异步 TCP 和 UDP 套接字kJu28资讯网——每日最新资讯28at.com

•异步 DNS 解析kJu28资讯网——每日最新资讯28at.com

•异步文件和文件系统操作kJu28资讯网——每日最新资讯28at.com

•文件系统事件kJu28资讯网——每日最新资讯28at.com

•ANSI 转义码控制的 TTYkJu28资讯网——每日最新资讯28at.com

•具有套接字共享的 IPC,使用 Unix 域套接字或命名管道 (Windows)kJu28资讯网——每日最新资讯28at.com

•子进程kJu28资讯网——每日最新资讯28at.com

•线程池kJu28资讯网——每日最新资讯28at.com

•信号处理kJu28资讯网——每日最新资讯28at.com

•高分辨率时钟kJu28资讯网——每日最新资讯28at.com

•线程和同步原语kJu28资讯网——每日最新资讯28at.com

2.libuv运行原理

kJu28资讯网——每日最新资讯28at.com

int uv_run(uv_loop_t* loop, uv_run_mode mode) {  ...  r = uv__loop_alive(loop);  if (!r)    uv__update_time(loop);  while (r != 0 && loop->stop_flag == 0) {    uv__update_time(loop);    uv__run_timers(loop);    ran_pending = uv__run_pending(loop);    uv__run_idle(loop);    uv__run_prepare(loop);    ...    uv__io_poll(loop, timeout);    uv__run_check(loop);    uv__run_closing_handles(loop);    ...  }}

3.简单使用

static void timer_cb(uv_timer_t *handler) {    printf("timer_cb exec./r/n");}int main(int argc, const char * argv[]) {   uv_loop_t *loop = uv_default_loop();   uv_timer_t *timer = (uv_timer_t*)malloc(sizeof(uv_timer_t));   uv_timer_init(loop, timer);   uv_timer_start(timer, timer_cb, 2000, 0);   uv_run(loop, UV_RUN_DEFAULT);}

五、QuickJS + libuv

console.log(`开始执行`);function getName() {    return new Promise((resolve, reject) => {        setTimeout(() => {            resolve("张三峰");        }, 2000);    });}getName().then(name => console.log(`promise name: ${name}`));

kJu28资讯网——每日最新资讯28at.com

#include <stdio.h>#include <pthread.h>#include <stdlib.h>#include <uv.h>/* File generated automatically by the QuickJS compiler. */#include "quickjs-libc.h"#include <string.h>typedef struct once_timer_data {    JSValue func;    JSValue this_val;    JSContext *ctx;} once_timer_data;void once_timer_cb(uv_timer_t *once_timer) {    once_timer_data *data = (once_timer_data *)once_timer->data;    JSContext *ctx = data->ctx;    JSValue js_ret_val = JS_Call(data->ctx, data->func, data->this_val, 0, NULL);    if(JS_IsError(ctx, js_ret_val) || JS_IsException(js_ret_val)) {        js_std_dump_error(ctx);    }    JS_FreeValue(data->ctx, js_ret_val);    JS_FreeValue(data->ctx, data->func);    JS_FreeValue(data->ctx, data->this_val);    free(data);    uv_timer_stop(once_timer);    free(once_timer);}void check_cb(uv_check_t *check) {    JSContext *ctx = (JSContext *)check->data;    js_std_loop(ctx);}void idle_cb(uv_idle_t *idle) {    }JSValue set_timeout(JSContext *ctx, JSValue this_val, int argc, JSValue *argv) {     if(argc != 2) return JS_NULL;    JSValue func_val = argv[0];    JSValue delay_val = argv[1];    int64_t delay = 0;    int ret = JS_ToInt64(ctx, &delay, delay_val);    if(ret < 0) js_std_dump_error(ctx);    uv_timer_t *once_timer = (uv_timer_t *)malloc(sizeof(uv_timer_t));    once_timer_data *data = (once_timer_data *)malloc(sizeof(once_timer_data));    data->func = JS_DupValue(ctx, func_val);    data->this_val = JS_DupValue(ctx, this_val);    data->ctx = ctx;    once_timer->data = data;    uv_timer_init(uv_default_loop(), once_timer);    uv_timer_start(once_timer, once_timer_cb, delay, 0);    JSValue js_timer = JS_NewInt64(ctx, (uint64_t)once_timer);    return js_timer;}static JSContext *JS_NewCustomContext(JSRuntime *rt) {  JSContext *ctx = JS_NewContextRaw(rt);  if (!ctx)    return NULL;  JS_AddIntrinsicBaseObjects(ctx);  JS_AddIntrinsicDate(ctx);  JS_AddIntrinsicEval(ctx);  JS_AddIntrinsicStringNormalize(ctx);  JS_AddIntrinsicRegExp(ctx);  JS_AddIntrinsicJSON(ctx);  JS_AddIntrinsicProxy(ctx);  JS_AddIntrinsicMapSet(ctx);  JS_AddIntrinsicTypedArrays(ctx);  JS_AddIntrinsicPromise(ctx);  JS_AddIntrinsicBigInt(ctx);  return ctx;}void js_job(uv_timer_t *timer) {    JSRuntime *rt = timer->data;    const char *file_path = "/Volumes/Work/分享/quickjs/code/quickjs/examples/promise.js";    size_t pbuf_len = 0;        JSContext *ctx;    js_std_set_worker_new_context_func(JS_NewCustomContext);    js_std_init_handlers(rt);    JS_SetModuleLoaderFunc(rt, NULL, js_module_loader, NULL);    ctx = JS_NewCustomContext(rt);        uv_check_t *check = (uv_check_t *)malloc(sizeof(uv_check_t));    uv_check_init(uv_default_loop(), check);    check->data = ctx;    uv_check_start(check, check_cb);        JSValue global = JS_GetGlobalObject(ctx);    JSValue func_val = JS_NewCFunction(ctx, set_timeout, "setTimeout", 1);    JS_SetPropertyStr(ctx, global, "setTimeout", func_val);    JS_FreeValue(ctx, global);            js_std_add_helpers(ctx, 0, NULL);    js_init_module_os(ctx, "test");    const uint8_t *code = js_load_file(ctx, &pbuf_len, file_path);    JSValue js_ret_val = JS_Eval(ctx, (char *)code, pbuf_len, "add", JS_EVAL_TYPE_MODULE);    if(JS_IsError(ctx, js_ret_val) || JS_IsException(js_ret_val)) {        js_std_dump_error(ctx);    }    js_std_free_handlers(rt);    JS_FreeContext(ctx);  }int main(int argc, char **argv) {    JSRuntime *rt = JS_NewRuntime();    uv_loop_t *loop = uv_default_loop();        uv_timer_t *timer = (uv_timer_t*)malloc(sizeof(uv_timer_t));    timer->data = rt;    uv_timer_init(loop, timer);    uv_timer_start(timer, js_job, 0, 0);        uv_idle_t *idle = (uv_idle_t *)malloc(sizeof(uv_idle_t));    uv_idle_init(loop, idle);    uv_idle_start(idle, idle_cb);    uv_run(loop, UV_RUN_DEFAULT);    JS_FreeRuntime(rt);    return 0;}

本文链接://www.dmpip.com//www.dmpip.com/showinfo-26-76532-0.html跨端轻量JavaScript引擎的实现与探索

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: ​2024年保护微服务的前十种技术

下一篇: .NET Core 上传文件到本地服务器技术详解

标签:
  • 热门焦点
  • Java NIO内存映射文件:提高文件读写效率的优秀实践!

    Java NIO内存映射文件:提高文件读写效率的优秀实践!

    Java的NIO库提供了内存映射文件的支持,它可以将文件映射到内存中,从而可以更快地读取和写入文件数据。本文将对Java内存映射文件进行详细的介绍和演示。内存映射文件概述内存
  • 企业采用CRM系统的11个好处

    企业采用CRM系统的11个好处

    客户关系管理(CRM)软件可以为企业提供很多的好处,从客户保留到提高生产力。  CRM软件用于企业收集客户互动,以改善客户体验和满意度。  CRM软件市场规模如今超过580
  • 三分钟白话RocketMQ系列—— 如何发送消息

    三分钟白话RocketMQ系列—— 如何发送消息

    我们知道RocketMQ主要分为消息 生产、存储(消息堆积)、消费 三大块领域。那接下来,我们白话一下,RocketMQ是如何发送消息的,揭秘消息生产全过程。注意,如果白话中不小心提到相关代
  • 一文搞定Java NIO,以及各种奇葩流

    一文搞定Java NIO,以及各种奇葩流

    大家好,我是哪吒。很多朋友问我,如何才能学好IO流,对各种流的概念,云里雾里的,不求甚解。用到的时候,现百度,功能虽然实现了,但是为什么用这个?不知道。更别说效率问题了~下次再遇到,
  • 使用AIGC工具提升安全工作效率

    使用AIGC工具提升安全工作效率

    在日常工作中,安全人员可能会涉及各种各样的安全任务,包括但不限于:开发某些安全工具的插件,满足自己特定的安全需求;自定义github搜索工具,快速查找所需的安全资料、漏洞poc、exp
  • 梁柱接棒两年,腾讯音乐闯出新路子

    梁柱接棒两年,腾讯音乐闯出新路子

    文丨田静 出品丨牛刀财经(niudaocaijing)7月5日,企鹅FM发布官方公告称由于业务调整,将于9月6日正式停止运营,这意味着腾讯音乐长音频业务走向消亡。腾讯在长音频领域还在摸索。为
  • 自律,给不了Keep自由!

    自律,给不了Keep自由!

    来源 | 互联网品牌官作者 | 李大为编排 | 又耳 审核 | 谷晓辉自律能不能给用户自由暂时不好说,但大概率不能给Keep自由。近日,全球最大的在线健身平台Keep正式登陆港交所,努力
  • 华为HarmonyOS 4升级计划公布:首批34款机型今日开启公测

    华为HarmonyOS 4升级计划公布:首批34款机型今日开启公测

    8月4日消息,今天下午华为正式发布了HarmonyOS 4系统,在更流畅的前提下,还带来了不少新功能,UI设计也有变化,会让手机焕然一新。华为宣布,首批机型将会在
  • 与兆芯合作  联想推出全新旗舰版笔记本电脑开天N7系列

    与兆芯合作 联想推出全新旗舰版笔记本电脑开天N7系列

    联想与兆芯合作推出全新联想旗舰版笔记本电脑开天 N7系列。这个系列采用兆芯KX-6640MA处理器平台,KX-6640MA 处理器是采用了陆家嘴架构,16nm 工艺,4 核 4 线
Top
Baidu
map