国产av一二三区|日本不卡动作网站|黄色天天久久影片|99草成人免费在线视频|AV三级片成人电影在线|成年人aV不卡免费播放|日韩无码成人一级片视频|人人看人人玩开心色AV|人妻系列在线观看|亚洲av无码一区二区三区在线播放

網(wǎng)易首頁 > 網(wǎng)易號 > 正文 申請入駐

QuickJS作者花3天造了個Node.js

0
分享至


QuickJS作者Fabrice Bellard在2024年3月發(fā)布了一個實驗項目:用C語言手寫JavaScript運行時,完整支持定時器、文件I/O和事件循環(huán),總代碼量不到2000行。

對比Node.js依賴的V8引擎——僅核心代碼就超過100萬行——這個數(shù)字像是程序員界的"降維打擊"。但Bellard沒打算替代誰,他只是證明了一件事:JavaScript運行時可以很小,小到能塞進你的咖啡杯。

引擎和運行時,差了一個宇宙

很多開發(fā)者搞混這兩個概念。JavaScript引擎(如V8、JavaScriptCore)只干一件事:執(zhí)行JS代碼。它不知道文件是什么,沒聽說過HTTP,對定時器一臉茫然。

運行時(如Node.js、Deno、Bun)才是完整環(huán)境。它把引擎包進來,再塞入文件系統(tǒng)、網(wǎng)絡棧、事件循環(huán)——就像給裸機裝上操作系統(tǒng)。Bellard這次造的"andjs",屬于后者。

他的目標很明確:console.log、process.uptime()、setTimeout/clearTimeout、fs.readFileSync/fs.readFile,外加事件循環(huán)和I/O線程池。沒有npm,沒有模塊系統(tǒng),沒有HTTP服務器。夠用就行。

從空文件到能跑JS:200行C代碼

Bellard沒碰QuickJS自帶的qjs.c運行時,選擇從零開始。最小可運行版本只需要三樣東西:JSRuntime實例(引擎本體)、JSContext(執(zhí)行環(huán)境)、以及一個讀取-執(zhí)行-報錯的循環(huán)。

核心代碼精簡到讓人懷疑人生:創(chuàng)建運行時、創(chuàng)建上下文、運行文件、清理資源。

run_file函數(shù)更直白:讀文件、調(diào)用JS_Eval執(zhí)行、檢查異常、釋放內(nèi)存。沒有黑魔法。當代碼拋出錯誤時,它會原樣打印堆?!蚇ode.js報錯格式幾乎一致。


第一個能跑的版本已經(jīng)可以執(zhí)行throw new Error("test exception"),并在終端吐出完整的錯誤位置。但問題是:沒有console.log,成功的程序鴉雀無聲。

console.log:第一個"系統(tǒng)調(diào)用"

給JS環(huán)境添加全局函數(shù),本質(zhì)上是C函數(shù)和JS的橋接。Bellard定義了一個js_print函數(shù),接收JSContext和參數(shù)列表,把值轉(zhuǎn)成字符串,輸出到stdout。

注冊過程用到了QuickJS的C API:先創(chuàng)建JSValueCFunction,再用JS_SetPropertyStr綁定到globalThis.console對象。JS_CFUNC_DEF宏隱藏了類型轉(zhuǎn)換的臟活,讓C函數(shù)看起來像是原生的JS方法。

這里有個細節(jié):console.log在JS里是變長參數(shù),但C函數(shù)需要顯式處理argc/argv。Bellard的實現(xiàn)遍歷所有參數(shù),用JS_ToCString轉(zhuǎn)字符串,空格分隔,最后換行。和瀏覽器行為一致,但代碼只有20行。

定時器:事件循環(huán)的入門考試

setTimeout是運行時的分水嶺。它強制你回答:回調(diào)存在哪?什么時候執(zhí)行?誰負責調(diào)度?

Bellard的方案很務實。定時器用鏈表存儲,每個節(jié)點記錄回調(diào)函數(shù)、延遲時間、是否重復(setInterval)。主循環(huán)檢查當前時間與觸發(fā)時間,到點就執(zhí)行。

但JS_Eval是同步的,執(zhí)行完就返回。定時器的回調(diào)怎么辦?Bellard在main函數(shù)末尾加了一個事件循環(huán):while (has_pending_jobs) { execute_pending_jobs(); }。QuickJS內(nèi)部維護了微任務隊列,但宏任務(定時器)需要運行時自己實現(xiàn)。

更棘手的是異步I/O。readFileSync會阻塞線程,這在2000行的玩具里可以接受。但真正的運行時不能讓文件讀取卡住整個事件循環(huán)——Bellard引入了worker pool。


線程池:用C寫Promise的底層

fs.readFile返回Promise,但C沒有Promise。Bellard的解法是把I/O扔給后臺線程,主線程繼續(xù)跑事件循環(huán),等數(shù)據(jù)準備好了再回調(diào)。

具體實現(xiàn):提交任務到隊列,worker線程取走、執(zhí)行read()、把結(jié)果塞回主線程的待處理列表。主循環(huán)每次迭代檢查這個列表,把完成的I/O包裝成Promise的resolve。

這里用到了QuickJS的JS_EnqueueJob機制,讓C層能向JS層投遞任務。整個流程和libuv(Node.js的I/O庫)原理相同,但代碼量差了三個數(shù)量級。

2000行能教給我們什么

Bellard這個項目沒有發(fā)布版本號,沒有路線圖,Git倉庫甚至沒開issue。它更像一份"參考答案":如果你被Node.js的復雜度嚇退,這里有一條最小可行路徑。

但別誤會,這不是生產(chǎn)級代碼。沒有內(nèi)存泄漏檢查,沒有安全沙箱,沒有模塊加載器。它回答的是"能不能",而非"應不應該"。

有趣的是,QuickJS本身的設(shè)計哲學在這里得到了延續(xù)。Bellard在2019年發(fā)布QuickJS時,主打的就是"小巧、可嵌入、啟動快"。這次的手寫運行時,算是把"小"字寫到了極致。

Node.js用V8是因為要兼容Chrome的JS語義,要追求極致性能。但如果你只需要跑一些腳本,處理文件和定時器,2000行C代碼真的夠用了——這個事實本身,可能比代碼更有沖擊力。

項目最后能運行的示例程序,讀起來和Node.js幾乎無異:啟動計時、延遲執(zhí)行、同步讀文件、異步讀文件、打印結(jié)果。區(qū)別只在于,你知道這背后沒有百萬行代碼的支撐,只有一個程序員三天的周末。

如果所有JavaScript運行時都能被壓縮到這種程度,我們還需要Docker鏡像里那個500MB的node:alpine嗎?

特別聲明:以上內(nèi)容(如有圖片或視頻亦包括在內(nèi))為自媒體平臺“網(wǎng)易號”用戶上傳并發(fā)布,本平臺僅提供信息存儲服務。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相關(guān)推薦
熱點推薦
金溥聰深夜發(fā)聲明“正面宣戰(zhàn)” 劍指鄭麗文 國民黨內(nèi)斗公開化

金溥聰深夜發(fā)聲明“正面宣戰(zhàn)” 劍指鄭麗文 國民黨內(nèi)斗公開化

觀星賞月
2026-03-28 12:11:40
劉曉慶自爆“家丑大瓜”:最想她死的,竟然是親外甥……

劉曉慶自爆“家丑大瓜”:最想她死的,竟然是親外甥……

桌子的生活觀
2026-03-27 12:35:54
馬英九按下暫停鍵,連戰(zhàn)或已經(jīng)出手,被踢出局的金溥聰徹底不裝了

馬英九按下暫停鍵,連戰(zhàn)或已經(jīng)出手,被踢出局的金溥聰徹底不裝了

娛樂小可愛蛙
2026-03-28 12:21:37
關(guān)于伊朗的十大虛假敘事——你是如何被網(wǎng)軍欺騙的?

關(guān)于伊朗的十大虛假敘事——你是如何被網(wǎng)軍欺騙的?

楓嶺社
2026-03-27 10:49:09
海南停車糾紛后續(xù):女子不幸離世,家屬索賠122萬,最終賠14.9萬

海南停車糾紛后續(xù):女子不幸離世,家屬索賠122萬,最終賠14.9萬

觀察鑒娛
2026-03-28 09:25:48
中東實戰(zhàn)打出真相!伊朗越猛越顯中國實力,美軍徹底慌了神

中東實戰(zhàn)打出真相!伊朗越猛越顯中國實力,美軍徹底慌了神

小舟談歷史
2026-03-28 04:42:18
廣東傳1好3壞消息!關(guān)辛談焦泊喬離隊,比輸球更可怕的麻煩出現(xiàn)了

廣東傳1好3壞消息!關(guān)辛談焦泊喬離隊,比輸球更可怕的麻煩出現(xiàn)了

后仰大風車
2026-03-28 07:10:11
央視主持人集體大哭,朱迅流淚康輝掩面痛哭,真相是什么?

央視主持人集體大哭,朱迅流淚康輝掩面痛哭,真相是什么?

落雪聽梅a
2026-03-28 09:14:37
劉曉慶親妹反擊了!揭沒養(yǎng)老金領(lǐng) 痛心姊姊晚年被「榨干骨髓」

劉曉慶親妹反擊了!揭沒養(yǎng)老金領(lǐng) 痛心姊姊晚年被「榨干骨髓」

ETtoday星光云
2026-03-27 10:38:07
張雪峰猝逝后,2萬家長搶購的17999元志愿卡誰來填?

張雪峰猝逝后,2萬家長搶購的17999元志愿卡誰來填?

薛定諤的BUG
2026-03-28 12:04:50
張雪峰追悼會定于本周六,喪事從簡不搞排場,11歲女兒成全家心病

張雪峰追悼會定于本周六,喪事從簡不搞排場,11歲女兒成全家心病

未曾青梅
2026-03-26 22:48:49
江淮做夢都想不到,自己做成中國的賓利,100萬一輛還供不應求

江淮做夢都想不到,自己做成中國的賓利,100萬一輛還供不應求

財經(jīng)老莊
2026-03-27 18:40:20
張雪峰靈堂現(xiàn)動人一幕,賓客來都是鞠躬,而他的員工給張老師磕頭

張雪峰靈堂現(xiàn)動人一幕,賓客來都是鞠躬,而他的員工給張老師磕頭

十九妹
2026-03-28 10:07:30
韓媒:日本已不再是世界五大出口國之一!

韓媒:日本已不再是世界五大出口國之一!

達文西看世界
2026-03-28 11:21:12
鄧華進餐廳吃飯,有上將漠視轉(zhuǎn)身走開,許世友:老鄧,咱們喝一杯

鄧華進餐廳吃飯,有上將漠視轉(zhuǎn)身走開,許世友:老鄧,咱們喝一杯

芳芳歷史燴
2026-03-27 17:55:19
登場20戰(zhàn)15勝!哈登29分鐘17+14早早打卡 前隊友:歷史最佳之一

登場20戰(zhàn)15勝!哈登29分鐘17+14早早打卡 前隊友:歷史最佳之一

顏小白的籃球夢
2026-03-28 09:57:45
陳松伶跑5公里馬拉松,本人曬照和路人拍的差距大,看著差出20歲

陳松伶跑5公里馬拉松,本人曬照和路人拍的差距大,看著差出20歲

八怪娛
2026-03-27 13:32:01
張雪峰二婚妻子付幸:幾個月婚姻分走數(shù)億,11歲女兒遺產(chǎn)繼承復雜

張雪峰二婚妻子付幸:幾個月婚姻分走數(shù)億,11歲女兒遺產(chǎn)繼承復雜

眼光很亮
2026-03-27 16:04:09
特朗普稱霍爾木茲為特朗普海峽

特朗普稱霍爾木茲為特朗普海峽

界面新聞
2026-03-28 09:36:19
揭開美國糧價低的真面目!他們騙人的鬼把戲終于被揭穿了!

揭開美國糧價低的真面目!他們騙人的鬼把戲終于被揭穿了!

老范談史
2026-03-25 22:45:51
2026-03-28 15:04:49
全棧遛狗員
全棧遛狗員
白天跟需求對線,晚上在小區(qū)遛狗。
375文章數(shù) 3關(guān)注度
往期回顧 全部

科技要聞

遭中國學界"拉黑"后,這家AI頂會低頭道歉

頭條要聞

牛彈琴:伊朗狠角色強硬嘲諷美國 卻被美移出獵殺名單

頭條要聞

牛彈琴:伊朗狠角色強硬嘲諷美國 卻被美移出獵殺名單

體育要聞

“我是全家最差勁的運動員”

娛樂要聞

王一博改名上熱搜!個人時代正式開啟!

財經(jīng)要聞

我在小吃培訓機構(gòu)學習“科技與狠活”

汽車要聞

置換補貼價4.28萬起 第五代宏光MINIEV正式上市

態(tài)度原創(chuàng)

時尚
房產(chǎn)
本地
藝術(shù)
軍事航空

龍蝦來了,厭蠢癥炸了

房產(chǎn)要聞

6.8萬方!天河員村再征地,金融城西區(qū)開發(fā)全面提速

本地新聞

在濰坊待了三天,沒遇到一個“濰坊人”

藝術(shù)要聞

細膩優(yōu)雅的花卉靜物畫 | Henrietta Smith

軍事要聞

伊朗:已組織超100萬人為地面戰(zhàn)斗做準備

無障礙瀏覽 進入關(guān)懷版