djs: موتور جاوااسکریپت کوچیک با Rust برای اسکریپتهای مدلها
خلاصهٔ کاملتر
djs یه موتور JavaScript و TypeScript هست که با no_std Rust (یعنی Rust بدون کتابخونهی استاندارد سیستمعامل) نوشته شده. هدف اصلیش wasm32 هست و قراره جای QuickJS رو توی codemode پروژهی pi بگیره. codemode یعنی مدل هوش مصنوعی یه اسکریپت مینویسه که ابزارها رو صدا میزنه، نتیجهشون رو پردازش میکنه و داده برمیگردونه. مرجع رفتاری و تستش هم dquickts هست که یه fork از QuickJS هست.
طراحیش از همین کاربرد میاد. کل وضعیت VM، یعنی آبجکتها، رشتهها، bytecode، فریمها و صف jobها، توی یه arena بایتی با آدرسهای u32 هست. پس snapshot گرفتن از VM فقط کپی کردن بایتهاست. مفسر هم برای فراخوانیهای JS از stack خود Rust بهصورت بازگشتی (recursion) استفاده نمیکنه. یعنی میتونه بین هر دو دستور متوقف بشه و بعداً ادامه بده، حتی وسط getterها، generatorها و توابع async.
چند تصمیم دیگه هم تو README اومده: کامپایلر بدون AST و تکمرحلهای مستقیم bytecode میسازه و typeهای TypeScript رو موقع parse پاک میکنه. builtinها با یه زیرمجموعهی سختگیر از TypeScript نوشته شدن. موتور هم deterministic هست، یعنی ساعت و عدد تصادفی از میزبان میاد و ورودی یکسان دقیقاً همون heap رو میسازه. از سمت JS با پکیج @djs/host اینطوری کار میکنی:
const sb = await Sandbox.create({
asyncFunctions: { search: (q) => mySearch(q as string) },
memoryLimit: 64 << 20,
});
const result = await sb.runAsync("const hits = await search(q); return hits.length;", { q: "djs" });
const image = sb.bytes();از نظر سازگاری، djs از ۳۸۱۰۹ تست فعال test262 تعداد ۳۸۰۶۹ تا رو پاس میکنه (۹۹.۹ درصد). چیزهایی مثل Intl، Temporal، SharedArrayBuffer، sloppy mode، eval مستقیم و modules عمداً کنار گذاشته شدن و موتور همیشه strict هست. از ۲۲۶ تست codemode پروژهی pi هم ۲۲۱ تا پاس میشه.
سرعتش توی wasm نسبت به quickjs-wasi قاطیه. توی حلقههای ساده، دسترسی به property و رشتهها حدود نصف دستورات ماشین رو مصرف میکنه، ولی توی کدهای پر از callback مثل map و filter و reduce تقریباً ۲.۹ برابر کندتره. تو بنچمارک خود pi با ۶۱ فراخوانی ابزار، ۴.۲ میلیثانیه در برابر ۵.۳ طول میکشه و شروع اسکریپت ۱.۰ در برابر ۳.۹ میلیثانیهست.
نکات کلیدی:
- فایل djs_wasm.wasm حدود ۱۴۷۱ کیلوبایت، و با brotli حدود ۴۲۳ کیلوبایت
- ساختن یه VM جدید با کپی snapshot پایه حدود ۴۰ میکروثانیه طول میکشه
- ۳۸۰۶۹ از ۳۸۱۰۹ تست فعال test262 پاس میشه
- کدهای پر از callback مثل map و filter هنوز نقطهضعف اصلی سرعتشه
- نیاز به Rust stable با edition 2024 و node نسخهی ۲۲.۶ به بالا




