Auto-Update, Inspector Live, dan Compiler yang Memotong Dirinya Sendiri
Postingan terakhir berakhir di v0.5.306 dengan kisah gen-GC + JSON + benchmark. Empat hari kemudian, Perry sudah di v0.5.359 — yaitu 53 patch release — dan ceritanya berbeda lagi. Tidak ada satu pun release itu yang menjadi headline angka benchmark. Hampir semuanya adalah issue dari tracker yang ditutup.
perry/updaterhadir — auto-update bergaya Sparkle/Tauri untuk aplikasi desktop (Ed25519 atas digest SHA-256, sentinel-rollback, relaunch terdetach). PR komunitas dari TheHypnoo (#224).- Geisterhand Fase D — inspector live di
http://localhost:7676dengan pohon widget, detail per widget, dispatch klik, dan editing style live viaPOST /style/:h. - Refactor compiler. Sepanjang v0.5.329 → v0.5.343 empat file paling banyak disinggung dipotong:
lower::lower_expr6.687 → 624 LOC (−91%),compile.rs9.391 → 3.783 LOC (−60%),lower.rs13.591 → 7.554 LOC (−44%),lower_call.rs7.000+ → 4.681 LOC (−33%).walker.rsbaru mengubah kelas bug catch-all_ =>jadi error compile. - UI styling Fase C tutup — props inline
style: { ... }di setiap widget di Apple, Android, GTK4, Windows, dan Web. Windows mendapat 4 dari 5 stub tersambung (decoration / opacity / borders); tinggalwidget.shadow(follow-up DirectComposition). - Bucket Scoop untuk Windows:
scoop install perry-ts/perry. Sidecar SHA-256 di workflow release. - Gelombang fix issue komunitas — sekitar 30 issue ditutup di runtime, codegen, fetch, GTK4, linker Windows, async, dan stdlib.
1. perry/updater — auto-update untuk aplikasi desktop
Sebelum fix, Perry tidak punya jalur update. Aplikasi rilis, rilis lagi, dan sudah. TheHypnoo membuka #224 dengan ceritanya lengkap:
import { initUpdater, checkForUpdate, markHealthy } from "@perry/updater";
initUpdater(); // sentinel-rollback jika launch sebelumnya crash
const update = await checkForUpdate({
manifestUrl: "https://example.com/updates/manifest.json",
publicKey: "<ed25519 raw 32-byte hex>",
currentVersion: "1.4.0",
});
if (update) {
await update.download((pct) => console.log(`${pct}%`));
await update.installAndRelaunch();
}
markHealthy(); // panggil setelah build baru sukses jalanModel trust: Ed25519 atas digest SHA-256 file (bukan atas byte file — verifikasi tetap murah pada binary besar). Manifest berbentuk JSON, ber-versi schema, satu entri per triple <os>-<arch>. Instalasi atomik dengan backup <exe>.prev, relaunch terdetach (setsid di Unix, DETACHED_PROCESS di Windows). Mobile dikecualikan secara desain — App Store / Play Store memiliki pipeline instalasi di level OS.
Dua keanehan runtime Perry mencuat saat menulis smoke test, dan diperbaiki sekalian:
response.arrayBuffer()mengembalikan stub metadata saja. Diperbaiki di #232 (juga TheHypnoo) —js_response_array_bufferkini meng-allocateBufferHeaderasli danmemcpyresp.bodyke dalamnya.fs.appendFileSyncmenulis 0 byte. Diperbaiki di #226 — jalur lowering namespace-import (import * as fs from "fs") tidak punya cabang untukappendFileSync, dan codegen LLVM juga tidak punya cabang untuk varian HIR-nya. Keduanya kini tersambung.
Dokumentasi ada di docs/src/updater/overview.md.
2. Geisterhand: inspector live di localhost:7676
Geisterhand selama ini adalah harness uji UI in-process Perry — HTTP API di port 7676 untuk snapshot state widget dan dispatch klik. Fase D mengubahnya menjadi inspector ala devtools yang bisa dibuka dari browser apa pun.
- Langkah 1 (v0.5.349) —
GET /menyajikan UI vanilla-JS satu halaman dengan pohon widget, detail per widget (frame, value, raw JSON), auto-refresh 1,5 detik dengan pause/resume, dan tombol «trigger onClick». Codegen mem-pinINSPECTOR_HTMLterhadap lazy-load-dead_stripmacOS supaya selamat di release build. - Langkah 2 (v0.5.350) —
POST /style/:hmenerima sekantong props JSON dan menerapkannya live. 9 props (backgroundColor,color,borderColor,borderWidth,borderRadius,opacity,padding,hidden,enabled) mengalir dari thread HTTP → thread utama via pump-queue yang sudah ada. JSON salah → 400; handle salah → 400; props tak dikenal disaring di server dan response mendaftar mana yang lolos.
perry compile main.ts -o app --enable-geisterhand
./app &
open http://localhost:7676
curl -X POST localhost:7676/style/3 \
-H 'content-type: application/json' \
-d '{"backgroundColor":"#1a1a1e","opacity":0.8}'
# => {"ok":true,"applied":["backgroundColor","opacity"]}Dispatcher macOS sudah tersambung; Linux / Windows / iOS / tvOS / visionOS / Android mengikuti bentuk yang sama dan jadi yang berikut.
3. Refactor compiler — memotong empat file terbesar
Lima issue di tracker (#167, #169, #212, #214, plus ekor panjang) berbentuk sama: varian Expr baru ditambahkan ke ir.rs, tetapi salah satu dari empat walker ad-hoc di lower.rs punya catch-all _ => dan diam-diam salah meng-compile varian baru itu. Menangkap ini di runtime mahal — kadang tak terlihat, kadang SIGSEGV di bawah SSO.
v0.5.329 memperkenalkan crates/perry-hir/src/walker.rs dengan walk_expr_children / walk_expr_children_mut — match exhaustive atas seluruh 178 varian Expr, tanpa catch-all. Menambah varian baru tanpa mendaftarkannya di sini sekarang adalah error compile. Empat consumer (substitute_locals, find_max_local_id::check_expr, collect_local_refs_expr, remap_local_ids_in_expr) jadi ringkas:
| Fungsi | Sebelum | Sesudah | Δ |
|---|---|---|---|
find_max_local_id::check_expr | 225 | 57 | −75% |
substitute_locals | 553 | 80 | −86% |
collect_local_refs_expr | 720 | 70 | −90% |
remap_local_ids_in_expr | 542 | 85 | −84% |
Total: −1.830 baris descent yang duplikatif, digantikan +1.840 baris satu walker tersentralisasi — netto datar, tetapi kelas bug-nya hilang.
Itu membuka jalan untuk sisanya. v0.5.331 → v0.5.343 memotong empat monolit dalam 14 commit. Angka headline-nya:
| File | Sebelum | Sesudah | Δ |
|---|---|---|---|
lower::lower_expr | 6.687 | 624 | −91% |
compile.rs | 9.391 | 3.783 | −60% |
lower.rs | 13.591 | 7.554 | −44% |
lower_call.rs | 7.000+ | 4.681 | −33% |
Pemecahannya mendarat sebagai 19 sub-modul terfokus: compile/{parse_cache, strip_dedup, library_search, object_cache, resolve, collect_modules, optimized_libs, targets, link}.rs, lower/{expr_misc, expr_function, expr_object, expr_call, expr_member, expr_assign, expr_new}.rs, lower_call/{ui_styling, builtin, native}.rs, ditambah crate baru crates/perry-dispatch yang menjadi sumber tunggal kebenaran untuk tabel metode UI / system / i18n (fan-out _ => "perry_ui_unknown" yang dulu memicu kejutan «compile di macOS, jebol di web» pada issue #191 sekarang cuma satu lookup).
Win perf Tier 4 ikut serta (v0.5.335–v0.5.336):
- Menggabung dua pass di
inline_functionsdan tiga pass rayon dicompile.rs— menghemat 5 scan modul + 3 round-trip scheduler per compile. - Membatasi parse cache
perry devdi 500 entri, eviction FIFO. Sebelum fix, sesi yang menyusurinode_modulesbisa menahan 100+ MB AST SWC. - Memparalelkan loop tulis
.llpasca-codegen — wall-time 2–4× lebih cepat di SSD dengan 50+ modul. Arc<I18nTable>alih-alih meng-clone tabel locale per worker.
Tes workspace tetap di 434 passed / 0 failed / 5 ignored di tiap commit; gap test di baseline 25/28; doc-test di baseline 80/82.
4. UI styling Fase C, selesai
Fase C adalah rollout style: { ... } inline. Langkah 1–7 ditutup di jendela ini:
- v0.5.305 → v0.5.306 — surface tipe
StyleProps+style:inline di Button. - v0.5.307 → v0.5.309 — destructure inline color/padding/shadow di setiap widget tabel, lalu VStack / HStack.
- v0.5.310 → v0.5.311 — string hex + gradien +
parseColorruntime untuk nilai dinamis. - v0.5.312 — dokumentasi styling + issue tracking Windows.
Lalu sapuan lintas-platform:
- GTK4 (#202, #206) — 4 FFI styling tersambung, plus 7 FFI hilang yang menutup gerbang doc-test Linux (v0.5.322).
- macOS (v0.5.324) — pipa shadow
CALayeruntukwidget.shadow+ infrastruktur visual_test; class-probeset_coloruntuk widget non-NSTextField. - iOS / tvOS / visionOS (v0.5.346) — Button dengan
color: ...sebelumnya memanggilsetTextColor:diUIButton, yang tidak mengimplementasi selektor itu; panicobjc2melintasi batasextern "C"dan proses abort. Diperbaiki dengan pola class-probe yang sama seperti macOS — UIButton sekarang melaluisetTitleColor:forState:UIControlStateNormal. - Windows (v0.5.347) — 4 dari 5 stub styling tersambung (
text.decorationvia round-tripLOGFONT,widget.opacityviaWS_EX_LAYERED+SetLayeredWindowAttributes, borders viaSetWindowSubclass+WM_PAINT). Hanyawidget.shadowyang tersisa (perlu DirectComposition).
Matriks styling di docs/src/ui/styling-matrix.md menutup jendela dengan Web di 43/43 Wired, Windows di 42/43 Wired, sisanya cakupan penuh.
5. Pass kebenaran runtime — issue demi issue
Tema periode ini: setiap miscompile yang masuk via tracker berakhir sebagai fix atau error compile-time. Sorotannya:
- #212 (v0.5.323) — metode kelas di dalam
fntidak bisa menangkap local fn pembungkusnya. Repro multi-modul kini cocok byte-per-byte dengan Node. - #214 (v0.5.321 + v0.5.330) — unbox string-handle yang aman SSO di 7 site operand string:
arr.join,arr.toString,obj[stringKey]get/set/delete,string.match(re),process.env[dynKey], input digest crypto. Sebelum fix, masing-masing diam-diam mengembalikan sampah atau SIGSEGV pada operand string inline. - #221 (v0.5.351) — array
constkosong di level modul kehilangan tulisanarr[i]=dari dalam fungsi. Muncul saatdiscoverLevels()Bloom-Engine/jump mengisiLEVEL_FILESdi level modul lewat index-assign dan layar pemilihan level keluar kosong. - #233 (v0.5.357) —
Array.pushdari dalam fungsi async diam-diam terbatas di 16 elemen ketika array masuk sebagai parameter. Fungsi async tidak diinline; realokasi mengembalikan pointer baru yang tidak dilihat caller. Fix: pasang pointer forwarding di posisi lama setiap kali tumbuh, memakai mekanismeGC_FLAG_FORWARDEDyang sudah ada di GC. - #235 (v0.5.358) — dispatch parameter default metode mengoper sampah ketika caller melewatkan arg di belakang. Dua bagian penyumbang: declare metode cross-module hardcode 6 double, bukan
arity + 1, danlower_class_methodsama sekali tidak memanggilbuild_default_param_stmts. Muncul difindOne(filter, options = {})mongodb yang hang diam-diam; fix-nya seragam di dispatch lokal dan cross-module. - #236 (v0.5.355) — tiga bug independen fetch + promise dari satu repro: api.github.com merespons 403 anonim (User-Agent default kini diset),
.then(console.log)hang selamanya (callback null tidak mendorong entri ke TASK_QUEUE), setiap rejection fetch mencetakUncaught exception: [object Object](NaN-box*StringHeadertelanjang alih-alihErrorHeadersungguhan). - #234 (v0.5.359) —
Blobsungguhan dengan metode instancearrayBuffer/text/bytes/slice. Sebelum fix,await response.blob()mengembalikan stub metadata{size, type}. Fix tiga bagian mendarat di runtime + HIR + codegen.
Plus penyusulan kecil:
- #181 — strip-dedup kelebihan memangkas monomorfisasi generik di Linux + silent-fallback link GTK4. Fix: ganti penyaringan pola nama dengan perbandingan himpunan simbol via
llvm-nm. Anggota dengan satu saja simbol unik tetap dipertahankan.libperry_ui_macos.adipangkas 196 → 35 objek tanpa error link. - #220 —
secur32.libditambahkan ke baris link Windows. - #198 — i18n
FormatNumberround-trip FP via Ryū. - #188 — codegen dispatch tersambung untuk wrapper format
perry/i18n. - #189 / #203 — codegen dispatch
perry/plugin. - #190 — widget Canvas via codegen LLVM.
- #191 — CameraView via codegen.
- #192 — widget Table via codegen.
- #193 (parsial) — 11 cabang dispatch helper stdlib.
- #98 — penerimaan notifikasi di background di iOS + Android (warm-path).
- #106 — fallback lemah untuk hook FFI game-loop di watchOS.
- #154 — hook dispose
using/await using. - #167 — alloca arg
js_native_call_methoddihoist ke blok entry. - #169 — cabang Uint8Array di
substitute_locals. - #226 —
fs.appendFileSynctersambung end-to-end (PR komunitas).
6. Windows + Scoop
Cerita toolchain Windows terus jadi lebih sederhana. v0.5.353 memaku clang -target di build host — clang non-MSVC di PATH (MinGW / MSYS2 / Anaconda / bundle GNU Rust) diam-diam menulis ulang IR x86_64-pc-windows-msvc Perry menjadi windows-gnu, dan lld-link tidak bisa menyelesaikan referensi __main yang disisipkan emitter mingw32 LLVM. probe_clang_default_triple baru menjalankan clang --version sekali per proses dan mencetak satu baris catatan informatif jika default host adalah GNU sementara kita menarget MSVC. Suppress dengan PERRY_NO_CLANG_PROBE=1.
v0.5.345 menyelaraskan ABI perry-ui Win64 dengan perry-dispatch — tiga signature extern runtime sudah melenceng (perry_ui_navstack_create, perry_ui_menu_add_item_with_shortcut, perry_ui_app_set_timer). Pada ABI Win64, arg posisional integer dan float berbagi indeks slot, jadi mismatch akan membaca sampah dari register tak terinisialisasi. SysV (macOS / Linux) memakai pool register int/float terpisah dan kebetulan bit valid-nya jatuh tepat — crash khusus Windows, diperbaiki di seluruh 8 crate platform perry-ui-*.
Lalu: scoop install perry-ts/perry. Manifest dipaku di v0.5.345 (dengan depends: main/llvm untuk otomatis menarik LLVM resmi default-MSVC). Workflow release sekarang menerbitkan sidecar <artifact>.sha256 di sebelah setiap arsip, dengan format kompatibel sha256sum untuk bumper package manager downstream apa pun.
# Host Windows
scoop bucket add perry-ts https://github.com/PerryTS/perry
scoop install perry-ts/perry
perry compile src\main.ts --target windows -o myapp.exe7. Penutup
Pola periode ini adalah keterlibatan komunitas plus higiene internal. TheHypnoo mengirimkan tiga PR signifikan (#224 perry/updater, #231 menyambung fs.appendFileSync, #232 byte body response.arrayBuffer). Tracker terkuras sekitar 30 issue. Compiler menyusut 60% pada file terbesarnya dan menumbuhkan walker exhaustive yang mengubah «lupa memperbarui salah satu dari empat walker ad-hoc» dari miscompile runtime menjadi error cargo build. UI styling mencapai paritas di setiap platform desktop kecuali bayangan di Windows. Geisterhand memperoleh permukaan devtools berbasis browser. Jalur instalasi Windows berkurang satu perintah.
Coba:
# npm (platform mana pun)
npm install @perryts/perry
npx perry compile src/main.ts -o myapp && ./myapp
# Homebrew (macOS)
brew install PerryTS/perry/perry
# Scoop (Windows)
scoop bucket add perry-ts https://github.com/PerryTS/perry
scoop install perry-ts/perry
# Auto-update aplikasi desktop
npm install @perry/updater
# Inspector live
perry compile main.ts -o app --enable-geisterhand
./app & # lalu buka http://localhost:7676Source: github.com/PerryTS/perry — Issues: github.com/PerryTS/perry/issues — Changelog: CHANGELOG.md
— Ralph