- scriptc mengompilasi TypeScript biasa menjadi biner native kecil yang berjalan tanpa Node, V8, atau mesin JavaScript, sambil mempertahankan pemeriksaan tipe dari kompiler TypeScript asli dan kompatibilitas perilaku Node
- Berdasarkan struktur kode, tool ini menentukan apakah kompilasi statis dimungkinkan lalu secara default menghasilkan kode native; hanya saat memilih
--dynamicia menjalankan JavaScript dari paket npm dan kode bertipeanydengan quickjs-ng - Mendukung kelas, generic,
async/await, exception, regex, API server Node,fetch, hingga dependensi npm; sintaks yang tidak didukung akan ditolak dengan kode error, code frame, dan petunjuk perbaikan - Menjalankan lebih dari 800 program di Node dan biner native lalu membandingkan output serta exit code, dan memeriksa error memori dengan AddressSanitizer serta audit reference count
- Pada pengukuran Apple M series, waktu start sekitar 2.4ms, biner statis 170~200KB, RSS umum 1~4MB, dan biner menjadi sekitar 3MB jika menyertakan mode dinamis serta dependensi tertanam
Model kompilasi statis
- Menggunakan TypeScript yang sudah ada tanpa dialek atau anotasi terpisah, dan menerapkan tingkat keketatan pemeriksaan
tsconfig.jsonserta libraryes2025asli dari TypeScript- Jika proyek memiliki
@types/node, itu juga ikut diperiksa tipenya - Kode yang terjangkau tanpa lowering menghasilkan diagnosis yang akurat dan kompilasi dihentikan
- Jika proyek memiliki
scriptc coveragemenampilkan jumlah statement yang dianalisis, persentase yang dikompilasi secara statis, serta faktor penghambat dan kode error- Pada contoh, 99% atau 4.451 dari 4.481 statement dikompilasi secara statis
- Cara eksekusi dibedakan secara eksplisit menjadi tiga tahap
- Kompilasi statis: mode default dan mengubahnya menjadi kode native tanpa mesin JavaScript
- Eksekusi dinamis: jika
--dynamicditentukan, tool ini menyertakan sekitar 620KB quickjs-ng untuk menjalankan JavaScript dari paket npm dan kode bertipeany- Semua nilai yang masuk dari kode statis divalidasi saat runtime
- Jika tipe deklarasi dan nilainya berbeda, ia melempar
TypeErroryang bisa ditangkap tanpa merusak memori
- Penolakan: kode yang tidak bisa ditangani diberi kode error, code frame, dan biasanya petunjuk perbaikan, alih-alih salah dikompilasi secara diam-diam
TypeScript dan library standar yang didukung
- Fitur bahasa yang didukung mencakup kelas dengan single inheritance dan dynamic dispatch, closure, monomorfisasi generic, discriminated union, destructuring, spread, template literal, getter/setter, dan iterator
- Jika keamanannya dapat dibuktikan, dynamic dispatch didevirtualisasi
- Discriminated union ditangani dengan nilai tag yang memanfaatkan narrowing TypeScript
async/awaitdiimplementasikan dengan fiber stackful dan scheduling yang disesuaikan dengan JavaScript- Mendukung exception dan
finally, serta parameter opsional, default, dan rest
- Regex memakai interpreter bytecode kompatibel ECMAScript yang sama seperti yang digunakan QuickJS, dan hanya ditautkan ke biner yang memakai regex
- Library standar mencakup string dengan semantik UTF-16, array,
Map, danSetdengan aturan urutan dan identitas yang sama seperti JavaScript- Konversi tipe pada
JSONmelalui validasi runtime - Juga menyediakan
Math, typed array,Buffer, dan hierarkiErroryang mendukungcatchbertipe
- Konversi tipe pada
Node dan Web API
- API Node mendukung
fs,path,process,child_process,os,crypto,url/URL,zlib, timer, dan signal handlerfsmenyediakan API sinkron dan Promisechild_processmendukung pipe stream- Event loop tidak memiliki dependensi eksternal
- Stack server mencakup
net,http,https,tls,dgram,dns,fs.watch,readline, dan bisa mengompilasi server proxy nyata- TLS menggunakan mbedTLS yang disertakan
- Sebagian Web API WHATWG seperti
fetch, streams,Headers, danAbortSignaldiimplementasikan di atas stack jaringan native dan TLS yang sama- Mendukung redirect, gzip,
AbortSignal.timeout, dan penyebab error bergaya Node - Tidak memakai dependensi HTTP sistem atau libcurl
- Mendukung redirect, gzip,
Dependensi npm dan eksekusi dinamis
- Dalam
--dynamic, tool ini memakai metode resolusi modul Node dan melakukan pemeriksaan tipe berdasarkan.d.tsyang disediakan paket - JavaScript dari paket npm disertakan ke dalam biner saat build, sehingga saat eksekusi tidak membaca
node_modules scriptc coverage --dynamicmenunjukkan apakah setiap statement dijalankan di area statis atau dinamis, serta faktor penghambat yang tersisa- Mesin JavaScript hanya disertakan saat mode dinamis dipilih secara eksplisit, sehingga ukuran biner tidak bertambah diam-diam
Akurasi dan keamanan memori
- Differential testing menjalankan lebih dari 800 program masing-masing di Node dan biner native, lalu membandingkan stdout, stderr, dan exit code per byte
- Output angka mengikuti representasi round-trip terpendek, dan 1 juta
doublediverifikasi dengan fuzzing terhadap Node - Untuk server, driver klien nyata dihubungkan ke kedua implementasi untuk pengujian
- Output angka mengikuti representasi round-trip terpendek, dan 1 juta
- Seluruh kumpulan pengujian dijalankan ulang di bawah AddressSanitizer dan audit reference count; jika ada leak atau use-after-free, build gagal
- Perilaku yang sengaja berbeda dari Node hanya beberapa lusin dan terutama terkait implementasi internal timing serta properti objek error
- Setiap perbedaan didokumentasikan dan diberi nomor, dan tidak ada perbedaan tersembunyi yang diizinkan
Karakteristik performa
- Diukur pada Apple M series dengan tugas yang sama dan output yang sama per byte terhadap Node, Go, Rust, dan Zig
- Waktu start sekitar 2.4ms, lebih cepat daripada Node sekitar 47ms, mirip Zig, dan unggul dari Go serta Rust
- Ukuran biner statis 170~200KB, dan sekitar 3MB jika menyertakan
--dynamicserta dependensi tertanam- Sebagai perbandingan, biner Go yang ditampilkan sekitar 2MB, dan Node SEA 60~100MB
- Penggunaan memori umum adalah RSS 1~4MB, sedangkan Node 67~116MB
- Runtime tetap mempertahankan semantik
f64yang sesuai JavaScript sambil bersaing dengan bahasa sistem di sebagian besar tugas- Inferensi integer dan analisis ownership masuk dalam roadmap
Jalur keluar yang eksplisit
comptime(() => ...)menjalankan TypeScript pada waktu build di VM terisolasi di dalam kompiler dan memasukkan hasilnya sebagai literal ke dalam biner--ffimenghubungkan deklarasi TypeScript yang hanya berisi signature langsung ke pemanggilan C ABI, dan menautkan archive, object, serta library sistem yang dideklarasikan di manifest- Batasnya eksplisit dan menyertakan informasi panjang
- Detail caranya bisa dilihat di Native FFI guide
- Type assertion tervalidasi seperti
JSON.parse(...) as Configmenyisipkan kode validasi runtime- Jika validasi gagal, ia melempar exception yang memuat jalur yang salah serta tipe yang diharapkan dan aktual, seperti
expected number at $.port, got string
- Jika validasi gagal, ia melempar exception yang memuat jalur yang salah serta tipe yang diharapkan dan aktual, seperti
Struktur kompiler
- Alur pemrosesan adalah
TypeScript → parsing dan type checking tsc → lowering → typed IR → C → clang → executable native packages/compilermencakup frontend berbasis API tsc, verifikasi dan serialisasi IR, serta backend LLVM dan C- Hanya IR yang dipakai sebagai antarmuka antara frontend dan backend
- LLVM adalah code generator default, dan program di luar cakupan dukungan memakai jalur fallback transparan
- C dipertahankan sebagai backend referensi permanen, dan
--backend cmenghasilkan output yang bisa dibaca dengan informasi baris sumber
packages/runtimemengimplementasikan value berbasis reference count dan cyclic collector, fiber stackful, event loopkqueue, stack server, dan output angka yang kompatibel dengan JavaScript- Menggunakan metode linking per fitur sehingga hanya fitur yang benar-benar dipakai yang masuk ke biner
packages/climenyediakan perintahscriptc build,scriptc run, danscriptc coverage
Instalasi dan pengembangan
- Dipasang dengan
npm install -g scriptcdan memerlukan clang - Platform utama adalah macOS arm64, sedangkan biner Linux dan Windows dikompilasi silang
- Setiap platform divalidasi melalui jalur differential testing terpisah
- Pengembangan dimulai dengan
pnpm install && pnpm buildpnpm testmenjalankan kumpulan differential testing dan snapshot diagnosisSCRIPTC_SAN=1 pnpm testmenjalankan pengujian yang sama di bawah ASan dan audit reference countpnpm scriptc build x.ts --emit-irmempertahankan C yang dihasilkan danx.ir.json
- Semua fitur ditambahkan bersama differential testing, dan penggabungan hanya bisa dilakukan jika pengujian umum serta pengujian keamanan memori sama-sama lulus
1 komentar
Komentar Hacker News
Vercel tampaknya merilis proyek sensasional kira-kira sebulan sekali untuk menjaga reliabilitas dan eksistensinya. Rasanya tidak mungkin perusahaan atau proyek yang serius akan memakai scriptc
Saya tetap menghormati para kontributornya, tetapi kodenya sangat terasa seperti dibuat dengan Claude, dan Claude tidak dicantumkan sebagai kontributor, jadi makin mencurigakan
proyek / postingan HN terkait
Porffor sudah lama mengejar tujuan yang sama. Pengembangnya, CanadaHonk, sangat hebat, tetapi proyek ini masih hanya lulus sekitar 68% Test262
Kecuali saya salah memahami cakupan proyeknya, cara Vercel bisa melaju secepat ini terasa sangat meragukan
Ini proyek khas Vercel. Baru dirilis 5 hari, semuanya vibe coding, entah kenapa dapat 1.500 bintang, tidak menyelesaikan masalah siapa pun, dan kemungkinan paling lama dalam beberapa bulan sudah tidak dirawat lagi
Daripada hanya mengkritik, saya sudah mencoba menerapkannya langsung ke beberapa proyek lokal, tetapi semuanya menghasilkan ratusan error saat analisis cakupan kode, jadi praktis tidak bisa dipakai
Kalau menulis semuanya dari nol tanpa library eksternal, mungkin memang bisa dikompilasi jadi biner, tetapi kalau begitu tidak ada alasan untuk tidak memakai bahasa seperti Rust, Go, Zig, D, C, V, Ada, C++, Nim, Swift, Kotlin Native, atau Haskell yang sejak awal memang dirancang untuk kompilasi yang benar
Kelebihan TypeScript bukan hanya ekspresivitasnya, tetapi juga kompatibilitas dengan ekosistem npm yang sangat besar. Sebagian besar paket hanya mendefinisikan antarmuka lewat deklarasi tipe dan mendistribusikan kode nyatanya sebagai JavaScript, jadi untuk memakai paket-paket itu pada praktiknya tetap butuh mesin JavaScript
Kalau memang mau mulai benar-benar dari nol dan sama sekali tidak berencana memakai paket npm, lebih baik pakai AssemblyScript. Node secara eksplisit menyarankan agar tidak mendistribusikan paket dalam TypeScript, karena TypeScript tidak kompatibel mundur bahkan antar minor version, dan pengaturan compilernya juga tidak portabel antar paket
Satu proyek seperti ini saja bisa terus tampil di halaman depan layanan seperti HN. Ini adalah strategi pertumbuhan: menginvestasikan token untuk membuat proyek yang tampak meyakinkan namun tidak diinginkan siapa pun, memperluas jangkauan lewat publikasi, lalu mengulanginya
Dalam 12 bulan, 90% proyek open source bisa saja menjadi hasil vibe coding yang hanya terlihat menarik tanpa pengguna nyata. Sekarang bahkan compiler penuh pun bisa dibuat dengan mudah, tetapi yang penting adalah pemeliharaan jangka panjang dan komunitas; pengguna tidak akan bertahan hanya karena judul yang mencolok
Kalau Vercel serius, mereka seharusnya menanggung biaya dan risikonya secara nyata dengan mengadopsinya untuk runtime eksperimental mereka sendiri
Ini area masalah yang sangat bagus. Saya menerapkan pekerjaan serupa untuk membuat compiler yang mengoptimalkan kode runtime dengan AI ke Zod: zod-compiler
Ia mengompilasi skema Zod pada waktu build menjadi rantai operasi boolean sederhana sehingga menjadi 2 hingga 74 kali lebih cepat tanpa perubahan kode, dan pluginnya mengganti pemanggilan Zod dengan parsing yang sudah dikompilasi. Sebagian besar optimisasi ditulis oleh Claude lewat lebih dari 100 iterasi
Sama seperti scriptc, kita tidak perlu menilai kebenaran secara subjektif karena hasilnya bisa dibandingkan dengan implementasi Zod yang asli. Ini bisa diterapkan ke compiler, alat serialisasi, formatter, query planner, dan sebagainya yang punya implementasi acuan dan benchmark
Saya menjalankan benchmark scriptc dan Node dengan Claude. Bahkan pada hasil array byte yang paling menguntungkan, setelah optimisasi khusus pun scriptc masih sekitar 7,5 kali lebih lambat daripada Node 24
Sebagai gantinya, startup executable 12 kali lebih cepat (1.5ms vs 18.6ms), memakai memori 72 kali lebih sedikit (2.5MiB vs 181MiB), dan menjadi executable tunggal 370KB tanpa dependensi runtime
Bagus bahwa mereka mengakui perlunya executable native yang kecil dan cepat, tetapi melihat perjalanan Java selama puluhan tahun, saya ragu soal kepraktisannya. GCJ pada 1990-an secara teknis lumayan, tetapi tidak punya dukungan ekosistem
Setelah itu GraalVM Native menangani masalahnya dengan lebih menyeluruh dan library serta framework besar mulai berupaya memastikan kompatibilitas, tetapi sampai sekarang pun sangat sulit menjalankan bahkan aplikasi lama yang sederhana secara native dengan sempurna. Upaya seperti scriptc memang disambut baik, tetapi jalan menuju penggunaan praktis tampaknya masih panjang dan berat
Salah satu alasan Excelsior menghilang mungkin karena GraalVM dan OpenJ9 tersedia gratis. PTC dan Aicas masih berjalan baik berkat pelanggan embedded dan real-time yang kurang mendapat perhatian
Jika pengembangannya berlanjut, ini punya potensi menjadi pencapaian besar setara .NET AOT. Karena baru beberapa hari sejak dirilis, saat ini saya cuma mencobanya secara ringan, tetapi jika tidak ditinggalkan dan terus berkembang, ini bisa sangat membantu ekosistem
Kode yang dibuat AI, seperti kode buatan manusia, punya rentang kualitas yang lebar. Untuk software penting, ia harus dihasilkan dengan standar yang sama seperti saat menulis langsung, dan semua kodenya harus direview; bila dipakai seperti itu, ini pendekatan yang sangat baik. Proyek yang minim review cenderung punya kualitas lebih rendah dan rasa tanggung jawab pengembang yang lebih lemah, sehingga lebih sulit diadopsi
Diskusi online sering terjebak di dua kutub: “semuanya dibuat AI” versus “sama sekali tidak memakai AI”, tetapi dalam praktiknya jalan tengah yang mempercepat penilaian yang matang adalah yang paling masuk akal. Software yang tidak seperti itu cenderung dihindari karena risiko kualitas rendah atau ditelantarkan