
إعادة هندسة ملفات bytenode .jsc (ذاكرة تخزين مؤقت لشيفرة V8) إلى JavaScript — بشكل ساكن، بلغة Rust خالصة، دون تعديل V8/Node. Node 8→26 / V8 5.8–14.6؛ تم اختبار 25 ألف ملف .jsc، دون أي فشل.
عكس ملفات .jsc المُجمَّعة بواسطة bytenode إلى JavaScript.
تحليل ساكن فقط: ملف تنفيذي واحد بلغة Rust خالصة — بدون V8 مُعدَّل، بدون بيئة تشغيل Node، بدون شبكة.
يدعم Node 8.0.0 → 26.10.0 (510 إصدارًا / 36 إصدارًا فرعيًا من V8)؛ حوالي 25 ألف ملف .jsc تجتاز
الاختبارات دون أي فشل (31 سطر Node × 41 حالة اختبار، مُجمَّعة بعلامات bytenode 1.7.0)؛ طبقتا
تحسين (طي السجلات → انتشار النسخ في swc) تجعلان المصدر المُفكَّك قابلاً للقراءة.
English · 中文
المحتويات: أبرز الميزات · البدء السريع · التثبيت · الاستخدام · مرجع سطر الأوامر · الإصدارات المدعومة · كيفية العمل · التحقق · تخطيط المستودع · القيود · المساهمة
--runtime عناصر __runtime البديلة بحيث تعمل النتيجة تحت node؛
ويمررها --verify عبر node --check.JSCD_NO_OPT=1 الشكل الخام.ReferenceError.$ cat hello.js
function greet(name) {
return "hello " + name;
}
console.log(greet("world"));
$ npm i -g bytenode && bytenode -c hello.js # Node 20.20.2 in this transcript
$ xxd -l 48 hello.jsc
00000000: cc05 dec0 0bc2 e400 9200 0000 e521 2eaa .............!..
00000010: f002 0000 0000 0000 011c 5401 2006 a860 ..........T. ..`
00000020: 0000 0000 0600 0000 010c 4c60 0000 0000 ..........L`....
$ jscd hello.jsc
console.log(greet("world"));
function greet(a0) {
return "hello " + a0;
}
$ jscd hello.jsc --runtime > hello.out.js && node hello.out.js
hello world
البايتات الأولى هي سحر ذاكرة التخزين المؤقت للشيفرة بصيغة little-endian (cc 05 de c0 = 0xc0de05cc)؛
يقوم jscd info hello.jsc بفك ترميز الترويسة بالكامل (نموذج في الاستخدام).
المخرجات أعلاه هي ما ينتج بعد طبقتي التحسين. يُظهر JSCD_NO_OPT=1 jscd hello.jsc
الترجمة الخام بدلاً من ذلك — إعادة ترتيب السجلات في V8، تعليمة واحدة في كل مرة.
على Node 22+ (V8 12.4+) تعيش بعض أسماء الخصائص المدمجة في الكومة للقراءة فقط. بالنسبة للإصدارات الفرعية الـ 29 من V8
التي تغطيها مصفوفة السلوك، يشحن jscd جدول أسماء (tables/ro_map_*) ويحلّها
تلقائيًا — على macOS، حيث استُخرجت تلك الجداول: فهارس الكومة للقراءة فقط خاصة بالمنصة، لذا على الأنظمة الأخرى ابنِ جدولك الخاص باستخدام jscd ro-map ومرّر --ro-map
(JSCD_NO_RO_MAP=1 يوقف الجدول المضمّن). بدون جدول تظهر هذه الأسماء كعناصر نائبة <ro0_…>
— وليس أبدًا كاسم خاطئ.
macOS / Linux — Homebrew
brew install ejfkdev/tap/jscd
Windows — Scoop
scoop bucket add ejfkdev https://github.com/ejfkdev/scoop-bucket
scoop install jscd
مباشرة من عنوان URL للبيان، دون إضافة الحاوية أولاً:
scoop install https://raw.githubusercontent.com/ejfkdev/scoop-bucket/main/bucket/jscd.json
scoop install ejfkdev/scoop-bucket/jscdلا يعمل: يقوم Scoop بحلbucket/appمقابل الحزم التي أضفتها بالفعل، وليس مقابل مسارowner/repo.
ملفات ثنائية جاهزة — كل إصدار موسوم يأتي مع ملفات تنفيذية جاهزة للتشغيل مباشرة (Linux / macOS / Windows × x64 / arm64؛ Linux amd64 هو بناء musl ثابت، وLinux وWindows مضغوطان بـ UPX):
احصل على واحد مباشرة من صفحة الإصدار (لا أرشيف، لا مثبّت — الملف هو الملف التنفيذي):
curl -fLO https://github.com/ejfkdev/jscd/releases/download/v0.1.0/jscd-v0.1.0-linux-amd64
chmod +x jscd-v0.1.0-linux-amd64
./jscd-v0.1.0-linux-amd64 --version
cargo (أي منصة مع Rust 1.96+)
cargo install jscd # build from crates.io
cargo binstall jscd # or fetch the release binary instead of compiling (cargo-binstall)
من المصدر
cargo install --git https://github.com/ejfkdev/jscd # latest main
git clone https://github.com/ejfkdev/jscd && cd jscd
cargo build --release # -> target/release/jscd
cargo install --path . # ...or install that build into ~/.cargo/bin
يتطلب Rust 1.96+ (swc، مُحسِّن JS، يحتاج إلى rustc حديث). لا توجد تبعيات نظام.
يقوم scripts/release.sh vX.Y.Z بتشغيل بوابات الإصدار (cargo test --release،
clippy --all-targets -- -D warnings، واختبار الدخان الشامل scripts/ci_smoke.sh — حيث تُجمَّع
الـ fixtures إلى ملفات .jsc حقيقية، ثم تُفكَّك، وتُفحَص نحويًا وتُقارَن عند التشغيل)، ثم يدفع
وسمًا مُعلَّقًا تصبح رسالته وصف إصدار GitHub. يُشغِّل الوسم
.github/workflows/release.yml، الذي يعيد بناء الملفات التنفيذية الستة المجرّدة المذكورة أعلاه. ثم
cargo publish إلى crates.io (يحافظ release.sh على تزامن الوسم مع إصدار Cargo.toml)، و
python3 scripts/update_readme_help.py لتحديث مساعدة CLI أدناه؛
Homebrew tap و
Scoop bucket يلتقطان الإصدار الجديد في تشغيلهما اليومي
للتحديث التلقائي.
jscd app.jsc # decompile one file to stdout
jscd app.jsc app.js # ...to a file
jscd dist/ # every .jsc under dist/ → dist-out/ (tree mirrored)
jscd dist/ out/ # ...into out/ instead
jscd info app.jsc # header fields, detected Node/V8 version
jscd disasm --filter main app.jsc
jscd ro-map probe.jsc > m.json # build a read-only-heap name table
jscd --help # bilingual help (-h, `help`, `help <SUBCOMMAND>`)
.jsc واحد، أو مجلد يُفحص بشكل تكراري بحثًا عن *.jsc؛ المخرج افتراضيًا
إلى stdout لملف وإلى <INPUT>-out/ (مع محاكاة الشجرة) لمجلد — -o / وسيطة OUTPUT
تكتب في مكان آخر، و- تعني stdout..jsc من إصدار V8 غير مدعوم مع ذكر الإصدار المكتشف والنطاق المدعوم
في الرسالة (jscd info يطبع supported: yes|no) — وليس ملفًا صامتًا يعمل في وقت التشغيل فقط.jscd ro-map ومرّر --ro-map
(JSCD_NO_RO_MAP=1 يعطّل الجدول المضمّن). يتم تجاهل جدول غير مطابق: تحصل على
عناصر نائبة <ro0_…>، وليس اسمًا خاطئًا أبدًا.JSCD_LANG (ثم LC_ALL / LC_MESSAGES / LANGUAGE / LANG /
LC_CTYPE): zh* هي الصينية، وأي شيء آخر الإنجليزية؛ JSCD_LANG=zh|en تفرض واحدة.