7 puan yazan GN⁺ 2025-12-24 | 2 yorum | WhatsApp'ta paylaş
  • MicroQuickJS(MQuickJS), gömülü sistemler için tasarlanmış ultra hafif bir JavaScript motoru olup yalnızca yaklaşık 10kB RAM ve 100kB ROM ile çalışabiliyor
  • QuickJS'e benzer hızı korurken bellek kullanımını azaltmak için tracing garbage collector ve UTF-8 string depolama biçimi kullanıyor
  • Desteklenen dil, ES5'e yakın sınırlı bir JavaScript alt kümesi ve yalnızca hata olasılığı yüksek sözdizimlerini yasaklayan strict mode destekleniyor
  • REPL aracı mqjs ile script çalıştırma, bytecode kaydetme ve bellek sınırı ayarlama yapılabiliyor; üretilen bytecode doğrudan ROM'dan çalıştırılabiliyor
  • Tüm motor ve standart kütüphane ROM'da bulunduğundan hızlı başlatma ve düşük bellek tüketimi sağlanıyor; bu da gömülü ortamlarda JavaScript çalıştırma verimliliğini artırıyor

Giriş

  • MicroQuickJS(MQuickJS), gömülü sistemleri hedefleyen bir JavaScript motoru olup 10kB RAM ve 100kB ROM'da (ARM Thumb-2 kodu dahil) çalışır
    • Hızı QuickJS'e benzerdir
  • Yalnızca ES5'e yakın bir alt kümeyi destekler ve verimsiz ya da hata olasılığı yüksek sözdizimlerini yasaklayan strict mode ile çalışır
  • QuickJS ile kodun bir kısmını paylaşsa da iç yapısı bellekten tasarruf etmek için tamamen farklı tasarlanmıştır
    • Tracing garbage collector, CPU stack kullanmama, UTF-8 string depolama yaklaşımı kullanılır

REPL

  • REPL komutu mqjs olup script çalıştırma, değerlendirme, interaktif mod, bellek sınırı ayarlama ve bytecode kaydetmeyi destekler
    • Örnek: ./mqjs --memory-limit 10k tests/mandelbrot.js
  • -o seçeneği ile derlenmiş bytecode bir dosyaya kaydedilebilir
    • Kaydedilen bytecode ./mqjs mandelbrot.bin ile çalıştırılabilir
  • Bytecode, CPU'nun endianness ve word length (32/64-bit) değerlerine göre farklıdır; -m32 seçeneği ile 32 bit için bytecode üretilebilir
  • --no-column seçeneği ile debug bilgisindeki sütun numaraları kaldırılabilir

Strict mode

  • Yalnızca strict mode desteklenir; with anahtar sözcüğü kullanılamaz ve global değişkenler mutlaka var ile tanımlanmalıdır
  • Array hole kullanımına izin verilmez
    • Örnek: a[10] = 2 bir TypeError üretir
    • Delikli array gerekiyorsa normal object kullanılmalıdır
  • Yalnızca global eval desteklenir, local değişkenlere erişim yoktur
  • Value boxing desteklenmez (new Number(1) vb.)

JavaScript alt kümesi

  • Strict mode temellidir ve ES5 uyumluluğuna odaklanır
  • Array object'lerinde hole yoktur; aralık dışı indeks erişimi hatadır
  • for in, object'in yalnızca kendi özellikleri üzerinde dolaşır; for of yalnızca array'leri destekler
  • Global object vardır ancak getter/setter desteklenmez; doğrudan oluşturulan özellikler global değişken olarak açığa çıkmaz
  • Regexp yalnızca ASCII için büyük/küçük harf ayrımını işler; /./ UTF-16 yerine Unicode code point bazında eşleşir
  • String fonksiyonları yalnızca ASCII işler (toLowerCase, toUpperCase)
  • Date için yalnızca Date.now() desteklenir
  • Ek desteklenen özellikler:
    • for of, Typed arrays, \u{hex} string literal
    • Math fonksiyonları: imul, clz32, fround, trunc, log2, log10
    • Üs alma operatörü, regexp flag'leri (s, y, u), string fonksiyonları(replaceAll, trimStart, trimEnd), globalThis

C API

  • C kütüphanesi bağımlılığı minimumdur, malloc, free, printf kullanılmaz
  • Bellek buffer'ı doğrudan sağlanmalıdır ve motor yalnızca bu buffer içinde bellek tahsisi yapar
    • Örnek: ctx = JS_NewContext(mem_buf, sizeof(mem_buf), &js_stdlib)
  • Garbage collection yaklaşımı nedeniyle JS_FreeValue() çağrısı gerekmez
  • Object adresleri her tahsiste taşınabilir olduğundan JSValue pointer kullanımı önerilir
    • JS_PushGCRef() / JS_PopGCRef() ile güvenli referans yönetimi yapılır
  • Standart kütüphane, ROM'da saklanabilen C yapıları olarak derlenir; böylece hızlı başlatma ve düşük RAM kullanımı sağlanır
  • Bytecode çalıştırma ROM'dan mümkündür; JS_RelocateBytecode() ile yeniden yerleştirildikten sonra JS_LoadBytecode() ve JS_Run() ile çalıştırılır
  • Matematik kütüphanesi (libm.c) ve floating-point emulator dahildir

İç yapı ve QuickJS karşılaştırması

  • Garbage collection: reference counting yerine tracing ve compacting GC kullanılır
    • Bellek parçalanmasını önler, object boyutunu küçültür
  • Değer gösterimi: CPU word boyutuna (32/64-bit) göre tasarlanmıştır
    • 31 bit integer, Unicode code point, floating-point ve memory block pointer saklayabilir
  • String'ler UTF-8 olarak saklanır, bu da QuickJS'in 8/16-bit array yaklaşımından daha verimlidir
  • C fonksiyonları tek bir değer olarak saklanabilir, özellik eklenemez
  • Standart kütüphane ROM'da yer alır ve minimum RAM object ile hızlı motor başlatma sağlar
  • Bytecode stack tabanlıdır ve dolaylı referans tablosu üzerinden salt okunur şekilde işlenir
    • Golomb code ile satır ve sütun numaraları sıkıştırılır
  • Derleyici QuickJS'e benzer, ancak C stack kullanımını sınırlamak için özyinelemesiz parser kullanır
    • Parse tree olmadan tek geçişte bytecode üretimi yapar

Test ve benchmark

  • Temel testler: make test
  • QuickJS micro benchmark: make microbench
  • Octane benchmark için (strict mode'a uyarlanmış sürüm) ayrı indirme yapılabilir
    • Çalıştırma: make octane

Lisans

  • MIT lisansı ile dağıtılır
  • Kaynak kod telif hakkı Fabrice Bellard ve Charlie Gordon'a aittir

2 yorum

 
xguru 2025-12-24

Fabrice Bellard hakkında bir tanıtım için daha önce yorum olarak yazdıklarıma bakabilirsiniz. Gerçekten hem istikrarlı hem de şaşırtıcı derecede olağanüstü biri..
https://news.hada.io/comment?id=51

 
GN⁺ 2025-12-24
Hacker News görüşleri
  • Eğer 2010'da böyle bir şey olsaydı, Redis'in betik dili muhtemelen Lua değil JavaScript olurdu
    Lua, dilsel nedenlerle değil, uygulama tarafındaki kısıtlar yüzünden seçildi (küçük, hızlı ve ANSI-C tabanlı)
    Lua'nın bazı fikirleri güzel, ama kişisel olarak Algol ailesi sözdiziminden uzaklaşmasını gereksiz buluyordum
    SmallTalk ya da FORTH'ta olduğu gibi yeni soyut kavramlar öğrenmenin getirdiği kafa karışıklığına değiyorsa tamam, ama Lua'daki değişim bana o kadar gerekçeli gelmiyordu

    • Lua'nın sözdizimini sevdiğimi söyleyemem, ama geliştiricilerin onu seçme nedenleri bana gayet makul geliyor
      Lua, tail call optimization (TCO) destekleyen tek hafif dil ve bu sayede döngü kullanmadan yalnızca özyineleme ile program yazabiliyorsunuz
      JavaScript'te bu optimizasyon yok, dolayısıyla aynı yaklaşım mümkün değil
      Lua ayrıca derleyici yazımı için özellikle uygun. Çünkü özyinelemeli yapı çok fazla
      Redis scripting için JS daha uygun olabilir, ama Lua'yı küçümsemek üzücü
    • Lua'nın ilk kez 1993'te çıktığını düşünürsek, o dönem için oldukça geleneksel bir sözdizimi vardı
      Brezilya'da C'den çok Pascal ve Ada daha yaygındı, dolayısıyla etkisi oradan geliyor
      Ruby ve Perl de benzer dönemde çıktı ama çok daha radikal sözdizimi değişiklikleri denediler
    • İlk başta Lua'yı 13 yaşımdayken kolayca öğrendiğimi yazacaktım, sonra yorumu yazanın bizzat antirez olduğunu fark edip şaşırdım
    • Sözdizimi sorununu çözmez belki ama "language skins" fikri ilginç
      Parser ve lexer'ı ayırıp {} yerine then/end gibi token'ları değiştirilebilir yapmak pek denenmiş bir şey değil
      İlgili tartışmalar: HN başlığı, Reddit tartışması
    • Redis betik dili olarak Tcl hiç değerlendirildi mi diye merak ediyorum. Sonuçta özgün gömülü dillerden biri
  • Bu motor, eskiden JSC üzerinde çalışırken benim istediğim şekilde JS'i kısıtlıyor
    Web'de uyumluluk yüzünden böyle sınırlamalar mümkün değil, ama gömülü ortamlarda bu tür kısıtlar aksine keyif veren bir tasarım olabilir

    • Zaten bu tür kısıtları olmayan bir JS motorumuz var
    • JSC'de yapılan çok iş parçacıklı çalışma ne oldu diye merak ediyorum. Apple'dan ayrıldıktan sonra durdu mu, kod hâlâ duruyor mu bilmek isterdim
  • Tarayıcıda doğrudan MicroQuickJS çalıştırabileceğiniz bir playground yaptım
    MicroQuickJS WebAssembly sürümü
    Referans için özgün QuickJS sürümü de var
    QuickJS 2.28MB, MicroQuickJS ise 303KB; yani çok daha hafif

    • Görünüşe göre build'e ad bilgileri vb. dahil olduğu için boyut büyümüş
      emcc -O3 seçeneği ya da --closure 1 eklenirse daha da küçülebilir
      QuickJS zaten optimize edilmiş, iyileştirme alanı daha çok MicroQuickJS tarafında var
  • Jeff Atwood'un meşhur sözüyle, "JavaScript ile yazılabilecek her uygulama eninde sonunda JavaScript ile yazılır"
    Görünüşe göre artık bu söz gömülü sistemler için de geçerli
    Jeff Atwood vikisi

  • Commit geçmişi olmadan yüklenmiş olması biraz hayal kırıklığı
    Bu seviyedeki bir geliştiricinin projeyi ne kadar hızlı bitirdiğini görmek isterdim
    Zaten QuickJS tabanlı olduğu için karşılaştırmanın çok da anlamlı olmayacağını düşünüyorum

    • "public repository of..." ifadesine bakınca, gerçek çalışma geçmişinin özel bir depoda olma ihtimali var
    • Belki de gerçekten tek seferde bitirmiştir
  • Bunun yt-dlp'nin YouTube JS challenge sorununu çözmenin en hafif yolu olup olamayacağını merak ediyorum
    Bkz. yt-dlp EJS belgeleri
    QuickJS zaten destekleniyor

    • Pek olası görünmüyor. Çünkü yalnızca ES5 düzeyinde kısmi bir uygulama destekleniyor
      YouTube'un JS bulmacaları o kadar karmaşık ki, Python ile yazılmış bir JS emülatörü bile vazgeçmek zorunda kalmıştı
    • Yalnızca ES5 uygulandığı için pratikte zor görünüyor
  • Gömülü sistemleri pek bilmiyorum ama böyle bir motorun ESP32 veya Arduino'yu JavaScript ile programlamayı mümkün kılıp kılamayacağını merak ediyorum
    MicroPython gibi yani

    • Benzer projeler zaten var
    • Moddable/Kinoma'nın XS motoru ES6 ve üstünü destekliyor
      MicroQuickJS yalnızca ES5'in bir kısmını uyguluyor ve ortam binding'leri de sunmuyor
    • Eskiden Tessel adında JS programlama kartı vardı
      JS kodunu Lua VM bytecode'una çevirip çalıştırıyordu; oldukça zekice bir yaklaşımdı
      Yakın zamanda o eski Node 0.8 CLI'ını Rust ile yeniden yazmayı denedim ama cihaz sonunda yine çekmeceye döndü
    • Asıl kilit nokta, malloc() içermeyen bir yapı olması. O da yeni olasılıkların önünü açıyor
  • Zamanlama gerçekten çok önemli. Dün gece paylaşıldığında hiç ilgi görmemişti

    • Muhtemelen sadece şans meselesi
    • Başka biri de denemiş ama ilgi gelmemiş
      ABD sabah saatlerinde yeniden paylaşmak ya da düzenli aralıklarla tekrar göndermek gibi taktikler var
  • Fabrice Bellard, bugün yaşayan en üretken ve çok yönlü programcılardan biri
    Başlıca işleri: FFmpeg, QEMU, JSLinux, TCC, QuickJS
    Efsanevi bir isim

    • Bu kadar takdir edilmesine rağmen, insanların onun geliştirme tarzına daha az ilgi göstermesi ilginç
      En az bağımlılık ve araçla eksiksiz programlar üretme yaklaşımı gerçekten etkileyici
    • Artık onun tek bir kişi değil, deneyimli hacker'lardan oluşan bir grubun kod adı olabileceğini düşünmeye başladım
      Gerçekten tek kişiyse uyuması da gerekiyor sonuçta
    • Kendisi bir LLM çıkarım motoru da geliştirdi ve bunu GPT-2 döneminden beri sürdürüyor
      ts_server, TextSynth
    • İlginç olan şu ki, yaptığı programların çoğu GUI ağırlıklı kullanıcı arayüzleriyle ilgili değil
      Kullanıcının parametreleri verip programın kendi başına tamamlanacak şekilde çalıştığı yapıları tercih ediyor gibi görünüyor
    • Uluslararası Obfuscated C Kod Yarışması (IOCCC)'nda 3 kez kazanmışlığı da var
      IOCCC kazananları listesi
  • "10kB RAM'de bile JS derleyip çalıştırabiliyor" olması etkileyici
    RAM'in pahalandığı bu dönemde zamanlaması da manidar
    Acaba bunu Chromium veya Electron'a koymak mümkün olur mu diye merak ediyorum

    • Web uyumluluğu yüzünden zor olur, ama zaten Chromium tarafında bellek tasarrufu etkisi çok büyük olmayabilir