精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

跨端輕量JavaScript引擎的實現(xiàn)與探索

開發(fā) 前端
libuv 是一個使用C語言編寫的多平臺支持庫,專注于異步 I/O。 它主要是為 Node.js 使用而開發(fā)的,但 Luvit、Julia、uvloop 等也使用它。

一、JavaScript

1.JavaScript語言

JavaScript是ECMAScript的實現(xiàn),由ECMA 39(歐洲計算機制造商協(xié)會39號技術(shù)委員會)負責(zé)制定ECMAScript標準。

ECMAScript發(fā)展史:

時間

版本

說明

1997年7月

ES1.0 發(fā)布

當(dāng)年7月,ECMA262 標準出臺

1998年6月

ES2.0 發(fā)布

該版本修改完全符合ISO/IEC 16262國際標準。

1999年12月

ES3.0 發(fā)布

成為 JavaScript 的通行標準,得到了廣泛支持

2007年10月

ES4.0草案發(fā)布

各大廠商意見分歧,該方案未通過

2008年7月

發(fā)布ES3.1,并改名為ECMAScript 5

廢除ECMAScript 4.0,所以4.0版本不存在

2009年12月

ESt 5.0 正式發(fā)布


2011年6月

ES5.1 發(fā)布

該版本成為了 ISO 國際標準(ISO/IEC 16262:2011)

2013年12月

ES6 草案發(fā)布


2015年6月

ES6 正式發(fā)布,并且更名為“ECMAScript 2015”

TC39委員會決定每年發(fā)布一個ECMAScript 的版本

2.JavaScript引擎

JavaScript引擎是指用于處理以及執(zhí)行JavaScript腳本的虛擬機。

常見的JavaScript引擎:

引擎

所屬機構(gòu)/個人

瀏覽器

說明

SpiderMonkey

Mozilla

Firefox

第一款JavaScript引擎,早期用于 Netscape Navigator,現(xiàn)時用于 Mozilla Firefox。是用C語言實現(xiàn)的,還有一個Java版本叫Rhino;Rhino引擎由Mozilla基金會管理,開放源代碼,完全以Java編寫,用于 HTMLUnit;而后TraceMonkey引擎是基于實時編譯的引擎,用于Mozilla Firefox 3.5~3.6版本;JaegerMonkey:結(jié)合追蹤和組合碼技術(shù)大幅提高性能,用于Mozilla Firefox 4.0以上版本

JavaScriptCore

Apple

Safari

簡稱JSC,開源,用于webkit內(nèi)核瀏覽器,如 Safari ,2008 年實現(xiàn)了編譯器和字節(jié)碼解釋器,升級為了SquirrelFish。蘋果內(nèi)部代號為Nitro的 JavaScript 引擎也是基于 JSC引擎的。至于具體時間,JSC是WebKit默認內(nèi)嵌的JS引擎,而WebKit誕生于1998年,Nitro是為Safari 4編寫,Safari 4是2009年6月發(fā)布。

V8

Google

Chrome

2008年9月,Google的V8引擎第一個版本隨著Chrome的第一個版本發(fā)布。V8引擎用 C++編寫,由 Google 丹麥開發(fā),開源。除了Chrome,還被運用于Node.js以及運用于Android操作系統(tǒng)等

Chakra

Microsoft

Edge、IE

譯名查克拉,用于IE9、10、11和Microsoft Edge,IE9發(fā)布時間2011年3月

JerryScript

三星


三星推出的適用于嵌入式設(shè)備的小型 JavaScript 引擎,2015年開源

Nashorn

Oracale


從 JDK 1.8 開始,Nashorn取代Rhino(JDK 1.6, JDK1.7) 成為 Java 的嵌入式 JavaScript 引擎,JDK1.8發(fā)布于2014年

QuickJS

Fabrice Bellard


QuickJS 是一個小型的嵌入式 Javascript 引擎。 它支持 ES2023 規(guī)范,包括模塊、異步生成器、代理和 BigInt。 它可以選擇支持數(shù)學(xué)擴展,例如大十進制浮點數(shù) (BigDecimal)、大二進制浮點數(shù) (BigFloat) 和運算符重載。

Hermes

Facebook


引擎,F(xiàn)acebook在Chain React 2019 大會上發(fā)布的一個嶄新JavaScript引擎,用于移動端React Native應(yīng)用的集成,開源

3.JavaScript引擎工作原理

a.V8引擎工作原理

b.Turbofan技術(shù)實例說明

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

這里a和b可以是任意類型數(shù)據(jù),當(dāng)執(zhí)行sum函數(shù)時,Ignition解釋器會檢查a和b的數(shù)據(jù)類型,并相應(yīng)地執(zhí)行加法或者連接字符串的操作。

如果 sum函數(shù)被調(diào)用多次,每次執(zhí)行時都要檢查參數(shù)的數(shù)據(jù)類型是很浪費時間的。此時TurboFan就出場了。它會分析函數(shù)的執(zhí)行信息,如果以前每次調(diào)用sum函數(shù)時傳遞的參數(shù)類型都是數(shù)字,那么TurboFan就預(yù)設(shè)sum的參數(shù)類型是數(shù)字類型,然后將其編譯為機器碼。

但是如果某一次的調(diào)用傳入的參數(shù)不再是數(shù)字時,表示TurboFan的假設(shè)是錯誤的,此時優(yōu)化編譯生成的機器代碼就不能再使用了,于是就需要進行回退到字節(jié)碼的操作。

三、QuickJS

1.QuickJS作者簡介

法布里斯·貝拉 (Fabrice Bellard)

2.QuickJS簡介

QuickJS 是一個小型的嵌入式 Javascript 引擎。 它支持 ES2023 規(guī)范,包括模塊、異步生成器、代理和 BigInt。

它可以選擇支持數(shù)學(xué)擴展,例如大十進制浮點數(shù) (BigDecimal)、大二進制浮點數(shù) (BigFloat) 和運算符重載。

?小且易于嵌入:只需幾個 C 文件,無外部依賴項,一個簡單的 hello world 程序的 210 KiB x86 代碼。

?啟動時間極短的快速解釋器:在臺式 PC 的單核上運行 ECMAScript 測試套件的 76000 次測試只需不到 2 分鐘。 運行時實例的完整生命周期在不到 300 微秒的時間內(nèi)完成。

?幾乎完整的 ES2023 支持,包括模塊、異步生成器和完整的附錄 B 支持(舊版 Web 兼容性)。

?通過了近 100% 的 ECMAScript 測試套件測試: Test262 Report(https://test262.fyi/#)。

?可以將 Javascript 源代碼編譯為可執(zhí)行文件,無需外部依賴。

?使用引用計數(shù)(以減少內(nèi)存使用并具有確定性行為)和循環(huán)刪除的垃圾收集。

?數(shù)學(xué)擴展:BigDecimal、BigFloat、運算符重載、bigint 模式、數(shù)學(xué)模式。

?用 Javascript 實現(xiàn)的帶有上下文著色的命令行解釋器。

?帶有 C 庫包裝器的小型內(nèi)置標準庫。

3.QuickJS工程簡介

5.94MB quickjs
├── 17.6kB      cutils.c                /// 輔助函數(shù)
├── 7.58kB      cutils.h                /// 輔助函數(shù)
├── 241kB       libbf.c                 /// BigFloat相關(guān)
├── 17.9kB      libbf.h                 /// BigFloat相關(guān)
├── 2.25kB      libregexp-opcode.h      /// 正則表達式操作符
├── 82.3kB      libregexp.c             /// 正則表達式相關(guān)
├── 3.26kB      libregexp.h             /// 正則表達式相關(guān)
├── 3.09kB      list.h                  /// 鏈表實現(xiàn)
├── 16.7kB      qjs.c                   /// QuickJS stand alone interpreter
├── 22kB        qjsc.c                  /// QuickJS command line compiler
├── 73.1kB      qjscalc.js              /// 數(shù)學(xué)計算器
├── 7.97kB      quickjs-atom.h          /// 定義了javascript中的關(guān)鍵字
├── 114kB       quickjs-libc.c
├── 2.57kB      quickjs-libc.h          /// C API
├── 15.9kB      quickjs-opcode.h        /// 字節(jié)碼操作符定義
├── 1.81MB      quickjs.c               
├── 41.9kB      quickjs.h               /// QuickJS Engine
├── 49.8kB      repl.js                 /// REPL
├── 218kB       libunicode-table.h      /// unicode相關(guān)
├── 53kB        libunicode.c            /// unicode相關(guān)
├── 3.86kB      libunicode.h            /// unicode相關(guān)
├── 86.4kB      unicode_gen.c           /// unicode相關(guān)
└── 6.99kB      unicode_gen_def.h       /// unicode相關(guān)

4.QuickJS工作原理

QuickJS的解釋器是基于棧的。

QuickJS的對byte-code會優(yōu)化兩次,通過一個簡單例子看看QuickJS的字節(jié)碼與優(yōu)化器的輸出,以及執(zhí)行過程。

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

?第一階段(未經(jīng)過優(yōu)化的字節(jié)碼)

;; 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

;; }

?第二階段

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

        line_num 2
        get_arg 0: a        /// 獲取參數(shù)列表中的變量
        get_arg 1: b
        add
        return
;; }

?第三階段

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

        get_arg0 0: a        /// 精簡成獲取參數(shù)列表中第0個參數(shù)
        get_arg1 1: b
        add
        return

;; }
sum(1,2);

通過上述簡單的函數(shù)調(diào)用,觀察sum函數(shù)調(diào)用過程中棧幀的變化,通過計算可知sum函數(shù)最棧幀大小為兩個字節(jié)

get_arg0

get_arg1

add

return

1

2

3

將棧頂?shù)臄?shù)據(jù)3返回


1



5.內(nèi)存管理

QuickJS通過引用計算來管理內(nèi)存,在使用C API時需要根據(jù)不同API的說明手動增加或者減少引用計數(shù)器。

對于循環(huán)引用的對象,QuickJS通過臨時減引用保存到臨時數(shù)組中的方法來判斷相互引用的對象是否可以回收。

6.QuickJS簡單使用

從github上clone完最新的源碼后,通過執(zhí)行(macos 環(huán)境)以下代碼即可在本地安裝好qjs、qjsc、qjscalc幾個命令行程序

sudo make
sudo make install

?qjs: JavaScript代碼解釋器

?qjsc: JavaScript代碼編譯器

?qjscalc: 基于QuickJS的REPL計算器程序

通過使用qjs可以直接運行一個JavaScript源碼,通過qsjc的如下命令,則可以輸出一個帶有byte-code源碼的可直接運行的C源文件:

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源文件,通過如下命令即可編譯成可執(zhí)行文件:

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文件直接編譯成可執(zhí)行文件:

qjsc -o add_exec examples/add.js

7.給qjsc添加擴展

QuickJS只實現(xiàn)了最基本的JavaScript能力,同時QuickJS也可以實現(xiàn)能力的擴展,比如給QuickJS添加打開文件并讀取文件內(nèi)容的內(nèi)容,這樣在JavaScript代碼中即可通過js代碼打開并讀取到文件內(nèi)容了。

通過一個例子來看看添加擴展都需要做哪些操作:

?編寫一個C語言的擴展模塊

#include "quickjs.h"
#include "cutils.h"

/// js中對應(yīng)plus函數(shù)的C語言函數(shù)
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);
}
/// 模塊需要導(dǎo)致的列表
static const JSCFunctionListEntry js_my_module_funcs[] = {
    JS_CFUNC_DEF("plus", 2, plusNumbers),
};
/// 模塊初始化函數(shù),并將plus導(dǎo)出
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模塊的編譯

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

?在qjsc.c文件中注冊模塊

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

?編寫一個my_module.js測試文件

import * as mm from 'my_module';

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

?重新編譯

sudo make && sudo make install
qjsc -m -o my_module examples/my_module.js /// 這里需要指定my_module模塊

最終生成的my_module可執(zhí)行文件,通過執(zhí)行my_module輸出:

my_module.plus: 3

8.使用C API

在第5個步驟時,生成了add.c文件中實際上已經(jīng)給出了一個簡單的使用C API最基本的代碼。當(dāng)編寫一下如下的js源碼時,會發(fā)現(xiàn)當(dāng)前的qjsc編譯后的可執(zhí)行文件或者qjs執(zhí)行這段js代碼與我們的預(yù)期不符:

function getName() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve("張三峰");
        }, 2000);
    });
}
console.log(`開始執(zhí)行`);
getName().then(name => console.log(`promise name: ${name}`));

上面的代碼并不會按預(yù)期的效果輸出結(jié)果,因為js環(huán)境下的loop只執(zhí)行了一次,任務(wù)隊列還沒有來得急執(zhí)行程序就結(jié)束了,稍微改動一下讓程序可以正常輸出,如下:

#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;
}

這樣的操作只適合用于測試一下功能,實際生產(chǎn)中使用需要一個即可以在必要的時候調(diào)用loop又可以做到不搶占過多的CPU或者只搶占較少的CPU時間片。

四、libuv

1.libuv簡價

libuv 是一個使用C語言編寫的多平臺支持庫,專注于異步 I/O。 它主要是為 Node.js 使用而開發(fā)的,但 Luvit、Julia、uvloop 等也使用它。

功能亮點

?由 epoll、kqueue、IOCP、事件端口支持的全功能事件循環(huán)。

?異步 TCP 和 UDP 套接字

?異步 DNS 解析

?異步文件和文件系統(tǒng)操作

?文件系統(tǒng)事件

?ANSI 轉(zhuǎn)義碼控制的 TTY

?具有套接字共享的 IPC,使用 Unix 域套接字或命名管道 (Windows)

?子進程

?線程池

?信號處理

?高分辨率時鐘

?線程和同步原語

2.libuv運行原理

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(`開始執(zhí)行`);
function getName() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve("張三峰");
        }, 2000);
    });
}
getName().then(name => console.log(`promise name: ${name}`));

#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;
}
責(zé)任編輯:武曉燕 來源: 今日頭條
相關(guān)推薦

2023-10-31 18:32:26

WebRTC存儲

2021-05-27 05:22:28

前端引擎平臺

2022-08-06 08:34:04

京東App適配技術(shù)棧

2021-08-26 05:27:57

Swift 監(jiān)聽系統(tǒng)泛型

2023-12-13 13:15:13

平臺開發(fā)實踐

2009-06-09 21:59:13

語法高亮Javascript

2019-11-26 09:42:36

代碼開發(fā)API

2024-04-30 09:53:12

axios架構(gòu)適配器

2022-02-24 18:51:04

跨端框架方案

2024-05-15 18:59:01

JavaScript語言原型

2025-06-11 02:30:00

2024-09-23 19:53:27

數(shù)據(jù)飛輪數(shù)據(jù)驅(qū)動數(shù)字化轉(zhuǎn)型

2023-07-03 07:42:42

2024-01-08 08:23:08

OpenCV機器學(xué)習(xí)計算機視覺

2022-04-15 14:31:02

鴻蒙操作系統(tǒng)

2020-10-09 09:21:45

鴻蒙

2023-07-26 11:22:44

騰訊趙裕

2022-09-12 07:17:20

redis命令redissynce

2022-11-30 15:15:48

點贊
收藏

51CTO技術(shù)棧公眾號

91亚洲国产成人久久精品网站 | 亚洲成人av在线| 性一交一乱一伧国产女士spa| 成人免费公开视频| 日韩精品亚洲一区| 超薄丝袜一区二区| 国产交换配乱淫视频免费| 四虎国产精品成人免费影视| 午夜亚洲福利老司机| 色噜噜一区二区| 蜜臀av免费在线观看| 蜜桃一区二区三区四区| 久久久久久一区二区三区| 日本二区在线观看| 成人资源在线| 4438亚洲最大| 国产视频一区二区视频| 后进极品白嫩翘臀在线播放| 国产日产精品一区| 狠狠色伊人亚洲综合网站色| 国产美女免费视频| 日韩精品午夜视频| 午夜精品久久久99热福利| 少妇视频一区二区| 亚洲素人在线| 精品国产一区二区三区忘忧草| 中文久久久久久| 激情都市亚洲| 欧美日韩国产在线看| 欧美与动交zoz0z| 日本中文字幕电影在线免费观看| 99久久久精品| 国产欧美综合精品一区二区| 国产农村妇女毛片精品| 美女网站色91| 国产成人啪精品视频免费网| 天天操中文字幕| 亚洲国产激情| 久久久久久中文| 国产黄色片在线免费观看| 91精品综合久久久久久久久久久| 中文字幕在线成人| 刘亦菲国产毛片bd| 久久中文字幕av| 在线精品国产成人综合| 性欧美13一14内谢| 欧美久久香蕉| 日韩电影视频免费| 黄色性生活一级片| 欧美黑人巨大videos精品| 亚洲福利在线视频| 中文在线永久免费观看| 久久99精品国产自在现线| 亚洲精品一区二区三区99| 苍井空张开腿实干12次| 6080成人| 亚洲精品美女在线观看| 国产网站无遮挡| 要久久爱电视剧全集完整观看| 亚洲精品国产精品国自产在线 | 欧美激情videos| 久久久久久免费观看| 亚洲国产电影| 国产suv精品一区二区| 国产99免费视频| 免费观看一级特黄欧美大片| 国产欧美精品在线| 国产黄色小视频在线观看| 成人综合婷婷国产精品久久| 国产精品综合久久久久久| 天天综合网在线| 国产亚洲成av人在线观看导航| 日本在线一区| 很黄的网站在线观看| 亚洲国产三级在线| 国产真实乱子伦| 日韩美香港a一级毛片| 日韩一区二区免费在线观看| 久久久久久久久久影视| 亚洲国产网址| 日韩在线观看网址| 国产亚洲精品av| 模特精品在线| 国产精品一二三在线| 99久久国产免费| 91在线一区二区三区| 天堂精品一区二区三区| 2021国产在线| 日韩欧美国产高清91| 视频免费1区二区三区| 成人性生交大片免费看96| 亚洲欧美日韩一区二区三区在线| 日韩一卡二卡在线观看| 伊人成人在线| 国产精品一区二区三区成人| www.久久色| 国产婷婷精品av在线| 50度灰在线观看| 欧美大片高清| 精品久久久久99| 潘金莲一级淫片aaaaa| 先锋影音国产精品| 欧美激情喷水视频| 中文字幕av片| 在线日韩av观看| 国产一级片自拍| 国产一区福利| 日韩有码在线电影| 婷婷激情五月网| 国产精品综合在线视频| 人偷久久久久久久偷女厕| 在线你懂的视频| 欧美性受xxxx黑人xyx性爽| 娇妻高潮浓精白浆xxⅹ| 97精品视频| 日韩av电影免费观看高清| 亚洲va欧美va| 亚洲欧洲日韩在线| 日本新janpanese乱熟| 大桥未久女教师av一区二区| 日韩中文字在线| 午夜久久久久久久久久影院| 粉嫩一区二区三区在线看| 一区二区三区四区在线视频| 九色porny丨首页入口在线| 欧美一区二区三区色| 妖精视频在线观看免费 | av免费观看网| 超碰在线成人| 久久99精品久久久久久琪琪| 国产又黄又粗又硬| 中文无字幕一区二区三区| 国产97在线 | 亚洲| 成人动态视频| 欧美精品久久久久久久久| 精品女同一区二区三区| 亚洲视频免费看| av噜噜在线观看| **女人18毛片一区二区| 国产欧美久久久久久| 在线中文资源天堂| 欧美午夜精品久久久久久超碰| av黄色免费网站| 蜜桃av综合| 欧美一区二区三区四区在线观看地址| a级片在线免费观看| 精品成人一区二区三区四区| 九九热视频精品| 成人永久免费视频| 国产精品成人久久电影| 91精品尤物| 97涩涩爰在线观看亚洲| 亚州精品国产精品乱码不99按摩| 亚洲网友自拍偷拍| 国产精品久久久久久亚洲色 | 少妇精品久久久| 国产极品jizzhd欧美| 成人一区二区不卡免费| 欧美日韩一区二区三区四区五区| 亚洲熟女少妇一区二区| 国产精品自拍在线| 又大又硬又爽免费视频| 日本中文字幕在线一区| 情事1991在线| 免费黄网在线观看| 日韩精品一区二区三区四区视频| 免费在线视频一区二区| 99精品桃花视频在线观看| 午夜精品久久久内射近拍高清| 亚洲欧美tv| 国产伦精品一区二区三区精品视频| 美女免费久久| 亚洲成人精品av| 最近中文在线观看| 亚洲欧美日韩一区二区| 艳妇乳肉豪妇荡乳xxx| 久久九九电影| 中国黄色录像片| 日韩欧美国产大片| 国产一区二区丝袜高跟鞋图片| av片在线观看| 亚洲免费伊人电影在线观看av| 中文字幕无线码一区| 一级日本不卡的影视| 色婷婷在线影院| 国产在线不卡视频| 成人性免费视频| 久久精品国产99久久| 国产精品久久久久久久免费大片| 成人黄色免费短视频| 九色精品免费永久在线| 久蕉在线视频| 日韩欧美二区三区| 国产精品熟女视频| 亚洲一二三四在线| 免费看的黄色网| 成人av午夜电影| 色噜噜狠狠一区二区| 99av国产精品欲麻豆| 久久久国产精华液999999| 露出调教综合另类| 亚洲aⅴ男人的天堂在线观看| 午夜影视一区二区三区| 久久深夜福利免费观看| 免费福利在线视频| 欧美va亚洲va在线观看蝴蝶网| 丁香社区五月天| 亚洲成人你懂的| 欧美h片在线观看| 久久伊人蜜桃av一区二区| 波多野结衣中文字幕在线播放| 日韩在线a电影| 国产午夜福利在线播放| 欧美三级特黄| 浴室偷拍美女洗澡456在线| 日韩国产一区二区| 免费看成人午夜电影| 国产精品对白久久久久粗| 91久久夜色精品国产网站| 韩国精品主播一区二区在线观看| 2019中文在线观看| 9999精品成人免费毛片在线看| 美女视频黄免费的亚洲男人天堂| 成人免费一区二区三区视频网站| 日韩成人激情在线| 黄色一级大片在线免费看国产| 欧美高清激情brazzers| 亚洲午夜无码久久久久| 一本大道久久a久久综合婷婷 | 欧美三级三级三级| 无码人妻aⅴ一区二区三区有奶水| 亚洲成人综合视频| 久久久久97国产| 亚洲在线中文字幕| 久久黄色小视频| 夜夜嗨av一区二区三区四季av| 强制高潮抽搐sm调教高h| 中文字幕免费一区| 日本精品久久久久中文| 国产精品三级视频| 最近中文字幕免费| 国产日韩av一区二区| 国产熟女一区二区| 欧美国产日韩a欧美在线观看| 成人午夜剧场视频网站| 久久影院午夜片一区| 国产av自拍一区| 久久久久久久久99精品| 老熟妇一区二区| 国产精品国产三级国产aⅴ入口 | 色狠狠一区二区| 久久久久久在线观看| 在线视频亚洲一区| 最近中文字幕av| 欧美一区二区三区在线视频| 99久久精品无免国产免费| 日韩欧美一区二区不卡| 日本成人动漫在线观看| 精品无人国产偷自产在线| 男人天堂网在线| 色999日韩欧美国产| 国内外激情在线| 久久久久久国产三级电影| 手机在线观看av| 国产精品爱久久久久久久| 日本亚洲欧洲无免费码在线| 99re6热在线精品视频播放速度| 豆花视频一区二区| 品久久久久久久久久96高清| 日本午夜一区| av影院在线播放| 亚洲综合三区| 国产精品区在线| 成人午夜视频福利| av电影在线不卡| 亚洲黄色小视频| 人妻 日韩精品 中文字幕| 欧美精品在线一区二区三区| 亚洲精品成人电影| 国产亚洲精品综合一区91| a天堂中文在线官网在线| 91国在线精品国内播放| 国产人妖一区| 国产乱人伦精品一区二区| 欧美精品系列| 无码 制服 丝袜 国产 另类| 视频一区国产视频| 性生活在线视频| 久久久无码精品亚洲日韩按摩| 国产一区第一页| 精品成人在线视频| 国产片在线播放| 亚洲女人天堂色在线7777| 国产在线看片| 国产精品福利网站| 好吊妞国产欧美日韩免费观看网站 | 亚洲精品97久久中文字幕无码| 夜夜嗨av一区二区三区免费区| 欧美另类tv| 91在线视频成人| 国产日产精品_国产精品毛片| 欧美美女黄色网| 青青草国产精品97视觉盛宴| 一级黄色免费视频| 亚洲日本护士毛茸茸| 精品人妻一区二区三区免费看| 日韩欧美国产一区二区三区| 二区在线观看| 欧洲亚洲在线视频| 亚洲精品在线国产| 国产又粗又硬又长| 喷水一区二区三区| 久久久久国产精品区片区无码| 亚洲精品成a人| 中文字幕第三页| 亚洲另类激情图| av伦理在线| 成人av电影免费| 一区二区三区国产精华| xxx国产在线观看| 国产视频视频一区| 性无码专区无码| 亚洲国产成人av在线| 在线观看午夜av| 亚洲自拍av在线| 99精品视频精品精品视频| 激情综合网俺也去| 国产亚洲一本大道中文在线| 日韩欧美大片在线观看| 精品久久久久久久久久久久久久久 | 91久久久久国产一区二区| 一个色综合导航| 99久久久国产精品免费调教网站| 欧美精品一区二区视频| 亚洲一区成人| 亚洲午夜福利在线观看| 欧美日韩激情视频| 亚洲AV成人无码一二三区在线| 午夜精品久久久久久久99热| 精品久久对白| 高清在线观看免费| 91在线视频官网| 神马久久久久久久| 国产亚洲在线播放| 欧美色片在线观看| 一本一道久久久a久久久精品91| 日本中文一区二区三区| 日本综合在线观看| 欧美日韩国产一级片| a视频在线观看免费| 91视频在线免费观看| 国色天香一区二区| 国产伦精品一区二区三区妓女| 日本韩国欧美在线| 91美女视频在线| 亚洲综合国产精品| 黄页网站一区| 日韩aaaaa| 欧美曰成人黄网| 免费a级在线播放| 国产精品免费一区二区三区| 在线视频日韩| 精品日韩在线视频| 欧美一二区视频| 无遮挡爽大片在线观看视频| 日本精品国语自产拍在线观看| 日韩不卡一区二区三区| 亚洲人a成www在线影院| 亚洲成人va| 老司机午夜网站| 97久久精品人人澡人人爽| 日韩一级片中文字幕| 久久精品亚洲94久久精品| 大型av综合网站| 亚洲综合色在线观看| 一区二区三区**美女毛片| 性感美女视频一二三| 国产日韩专区在线| 亚洲啪啪91| 男女男精品视频网站| 亚洲国产精品va| 韩国精品主播一区二区在线观看| 日韩精品一区二区三区电影| www.在线欧美| 国产精品无码免费播放| 国内精品久久久久久影视8| 欧美亚洲国产激情| 日本wwwwwww| 精品视频一区 二区 三区| 国产在线拍揄自揄拍视频 | 全部免费毛片在线播放网站| 国产欧美 在线欧美| 一本色道久久综合一区| 少妇高潮在线观看| 国产午夜精品麻豆| 日本免费一区二区视频| 成人黄色一区二区| 午夜精品一区二区三区三上悠亚| a天堂中文在线88| 久久久com|