You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
chore(version): v0.5.327 — close#191 wire CameraView through codegen
Wires the CameraView widget through every codegen path (LLVM, JS, WASM)
so user code calling CameraView() / cameraStart / cameraStop /
cameraFreeze / cameraUnfreeze / cameraSampleColor / cameraSetOnTap
resolves on every target. Pre-fix the runtime FFI was implemented in
perry-ui-ios (AVCaptureSession) and perry-ui-android (Camera2) but no
codegen had a dispatch row; calls fell through the receiver-less
early-out and silently returned 0.0.
Adds:
- 7 rows to PERRY_UI_TABLE in crates/perry-codegen/src/lower_call.rs
- 7 arms each in JS + WASM emit map_ui_method
- 7 browser stubs in wasm_runtime.js + dispatch table registration
- macOS / GTK4 / Windows no-op stubs (tvOS / visionOS / watchOS
already had them from prior audit work)
- TS declarations under a new "Camera" section in
types/perry/ui/index.d.ts
- docs/examples/ui/camera/snippets.ts (compile-only with `run: false`)
- docs/src/ui/camera.md drops the not-yet-wired callout, replaces it
with the platform-support matrix, converts all 10 ,no-test fences to
{{#include}} extracts
Verified: cargo build clean, ./perry compile --no-link emits all 7
camera FFI calls as undefined references in the .o, full link produces
a 0.9 MB macOS executable that exits 0 in PERRY_UI_TEST_MODE=1,
./target/release/doc-tests --filter camera passes 1/1 (1080 ms), full
sweep is 79/81 same as v0.5.325 baseline.
Version slot bumped above origin's v0.5.326 (slider FFI calling-convention
fix, parallel-track on origin) per the merge precedent for collisions.
Copy file name to clipboardExpand all lines: CLAUDE.md
+2-1Lines changed: 2 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -8,7 +8,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
8
8
9
9
Perry is a native TypeScript compiler written in Rust that compiles TypeScript source code directly to native executables. It uses SWC for TypeScript parsing and LLVM for code generation.
10
10
11
-
**Current Version:** 0.5.326
11
+
**Current Version:** 0.5.327
12
12
13
13
## TypeScript Parity Status
14
14
@@ -149,6 +149,7 @@ First-resolved directory cached in `compile_package_dirs`; subsequent imports re
149
149
150
150
Keep entries to 1-2 lines max. Full details in CHANGELOG.md.
151
151
152
+
- **v0.5.327** — Closes #191: wires the `CameraView` widget through every codegen path (LLVM, JS, WASM) so user code calling `CameraView()` / `cameraStart` / `cameraStop` / `cameraFreeze` / `cameraUnfreeze` / `cameraSampleColor` / `cameraSetOnTap` resolves on every target instead of failing with "unknown function" at compile time. Pre-fix the runtime FFI was implemented in `crates/perry-ui-ios/src/lib.rs` (AVCaptureSession) and `crates/perry-ui-android/src/lib.rs` (Camera2) but no codegen had a dispatch row; calls reached the receiver-less early-out and silently returned 0.0. Five-part landing: (1) **LLVM codegen** — 7 new rows in `PERRY_UI_TABLE` (`crates/perry-codegen/src/lower_call.rs`): `CameraView` → `perry_ui_camera_create` (no args, returns Widget), `cameraStart`/`cameraStop`/`cameraFreeze`/`cameraUnfreeze` → matching `perry_ui_camera_*` setters (Widget arg, Void return), `cameraSampleColor` → `perry_ui_camera_sample_color` (F64×2 args, F64 return — packed RGB or -1), `cameraSetOnTap` → `perry_ui_camera_set_on_tap` (Widget + Closure). (2) **JS codegen** (`crates/perry-codegen-js/src/emit.rs`) + **WASM codegen** (`crates/perry-codegen-wasm/src/emit.rs::map_ui_method`) — 7 new arms in each routing the TS names to the canonical `perry_ui_camera_*` symbols. (3) **WASM runtime stubs** (`crates/perry-codegen-wasm/src/wasm_runtime.js`) — `perry_ui_camera_create` allocates a placeholder `<div>` so layout slots reserve the same space they would for a real preview, `perry_ui_camera_sample_color` returns -1 (matching the documented "no frame available" sentinel), the rest are no-ops. All 7 registered in `__perryUiDispatch`. (4) **Desktop no-op stubs** added to `perry-ui-macos/src/lib.rs`, `perry-ui-gtk4/src/lib.rs`, `perry-ui-windows/src/lib.rs` — `perry_ui_camera_create` returns 0, `perry_ui_camera_sample_color` returns -1.0, the rest are no-ops. tvOS / visionOS / watchOS already had stubs from earlier audit work. (5) **TS surface** — `types/perry/ui/index.d.ts` adds the 7 declarations under a new "Camera (issue #191)" section with platform-support documentation; `docs/examples/ui/camera/snippets.ts` (compile-only with `run: false` banner since the camera needs hardware permissions) pins every name down so a future rename / drop trips a link error in CI; `docs/src/ui/camera.md` drops the "Status: not yet wired into any codegen path" callout, replaces it with the platform-support matrix (iOS+Android real, others no-op stubs), and converts all 10 `,no-test` fences to `{{#include}}` extracts using anchor markers. Verified end-to-end: `cargo build --release -p perry-runtime -p perry-stdlib -p perry-ui-macos -p perry` clean; `./perry compile --no-link` on the example produces an .o with all 7 `_perry_ui_camera_*` symbols as undefined references (codegen wired); full link produces a 0.9 MB macOS executable that exits 0 in `PERRY_UI_TEST_MODE=1`; `./target/release/doc-tests --filter camera` passes (1/1, 1080 ms compile-only); full doc-tests sweep `./target/release/doc-tests --skip-xcompile` is 79/81 — same baseline as v0.5.325 (the lone fail remains the pre-existing `ui/gallery.ts` retina screenshot drift, the lone skip remains `platforms/wasm_snippets.ts` which opts out of the macOS host run phase). Real-camera wiring on macOS / Linux / Windows / Web (AVFoundation, GStreamer/V4L2, Media Foundation, `getUserMedia`) tracked as separate follow-ups — the codegen surface is now stable and contributors can light up each backend incrementally without touching the dispatcher. Version slot: bumped above origin's v0.5.326 (slider FFI calling-convention fix, parallel-track on origin) per the merge precedent for collisions.
152
153
- **v0.5.326** — Fix latent calling-convention mismatch on `perry_ui_slider_create` across all 7 backends. Surfaced as `GLib-GObject-CRITICAL: value "nan" of type 'gdouble' is invalid or out of range for property 'value'` on Linux GTK4 when running `docs/examples/ui/styling/visual_test.ts` (section 10). Root cause: codegen at `crates/perry-codegen/src/lower_call.rs:5094` declares Slider with 3 args (`UiArgKind::F64, F64, Closure`) per the TS surface `Slider(min, max, onChange)` in `types/perry/ui/index.d.ts:224`, but every native backend's FFI shim declared 4 (`min, max, initial, on_change`) and called `widgets::slider::create(min, max, initial, on_change)`. Verified by `PERRY_NO_CACHE=1 PERRY_SAVE_LL=...` dump: emitted IR is `declare i64 @perry_ui_slider_create(double, double, double)` + `call i64 @perry_ui_slider_create(double 0.0, double 100.0, double %r480_callback)`. The 4th `initial` parameter at the FFI boundary therefore reads whatever the SysV ABI's xmm3 holds at the call site (uninitialized → frequently NaN). On macOS / iOS / Android / Windows that NaN flowed into `slider.setDoubleValue(NaN)` → silently clamped to min by AppKit/UIKit/Material/Win32 — no symptom. On GTK4 it flowed into `Adjustment::new(value=NaN, lower=0, upper=100, ...)` → GTK validated the range and emitted the loud warning. Fix: 5 native FFI shims (`crates/perry-ui-{gtk4,macos,ios,android,windows}/src/lib.rs`) drop the `initial` parameter and pass `min` to the internal `widgets::slider::create(min, max, min, on_change)`. Internal `widgets/slider.rs::create` keeps its 4-arg form for any future caller that wants explicit-initial semantics. Web (`crates/perry-codegen-js/src/web_runtime.js:275`) and wasm (`crates/perry-codegen-wasm/src/wasm_runtime.js:2579`) `perry_ui_slider_create` JS functions also drop their `initial` param — pre-fix Web set `el.value = undefined` (browser silently coerced to empty string then probably to min), wasm set `el.value = initial || 0` (worked coincidentally for `[0..N]` ranges, broke silently for `[10..100]`). Default-to-`min` matches the most common pattern (slider starts at the low end of its range) and the cross-backend behavior the existing native impls were already implicitly providing. Verified end-to-end on the visual_test repro: pre-fix `PERRY_UI_TEST_MODE=1 ./visual_test` printed the GLib-GObject-CRITICAL once before exit-0; post-fix the binary exits silent. Full Linux ui/ doc-tests: 44/45 pass / 0 fail / 1 skip (the lone skip is the pre-existing `image_symbol.ts` Linux banner exclusion). No regressions on the 12 other styling examples. Cross-backend FFI signatures now agree with codegen — closes the latent UB across all 7 platforms in one change. Version slot: bumped above origin's v0.5.325 (#219 doc-tests banner fix, parallel-track on origin) per the merge precedent for collisions.
153
154
- **v0.5.325** — Closes #219: `docs/examples/platforms/wasm_snippets.ts` was failing every host doc-tests gate (macOS, GTK4, Windows) because its `// platforms: macos, linux, windows` banner enabled the host run phase, but the file's `declare function bloom_init_window/bloom_draw_rect` FFIs only resolve as WASM imports under `--target wasm` / `--target web` — on a native compile the host linker can't find them and bombs with `undefined reference to bloom_init_window`. Two-part fix: (1) `crates/perry-doc-tests/src/main.rs::read_banner` now tracks a `platforms_seen` flag — an explicit empty `// platforms:` directive (no values) suppresses the default-fill of `[macos, linux, windows]`, letting an example opt out of the host run phase entirely. Pre-fix the parser couldn't distinguish "directive absent" from "directive present but empty". (2) `docs/examples/platforms/wasm_snippets.ts` banner switched from `// platforms: macos, linux, windows` to `// platforms:` + `// targets: wasm, web` — the cross-compile phase still drives both targets (catching API drift in `declare function`, `fetch()`'s options shape, and `parallelMap`), but the host phase skips. Verified end-to-end: `./target/release/doc-tests --filter wasm_snippets --verbose` now reports `SKIP platform 'macos' not listed in banner` + `XCOMPILE_PASS target='wasm'` (504 ms) + `XCOMPILE_PASS target='web'` (101 ms); `strings target/perry-doc-tests/platforms_wasm_snippets__wasm.wasm` confirms `bloom_init_window` and `bloom_draw_rect` are present as WASM imports (per the issue's spot-check criterion). Full sweep `./target/release/doc-tests --skip-xcompile` now 78/80 pass with the lone fail being the pre-existing `ui/gallery.ts` retina screenshot baseline mismatch — unchanged from prior baselines, no regression from the parser change.
154
155
- **v0.5.324** — Issue #185 follow-up: `box-shadow` on macOS (sections 4 of `docs/examples/ui/styling/visual_test.ts`) was invisible despite the FFI args being correct in the IR dump. Root cause: `crates/perry-ui-macos/src/widgets/mod.rs::set_shadow` set `shadowColor` / `shadowOpacity` / `shadowRadius` / `shadowOffset` on the view's CALayer but never set `setMasksToBounds: false` — and CALayer shadows are clipped by `masksToBounds`. The iOS / tvOS / visionOS mirror impls all set this; the macOS one was missing it. One-line fix: `let _: () = objc2::msg_send![layer, setMasksToBounds: false];` after the four shadow setters. Also adds (1) `docs/examples/ui/styling/visual_test.ts` — single-window comprehensive 13-section visual styling test exercising every styling prop family (colors hex/named/object/alpha/runtime, borders, padding, **shadow** (the case that surfaced the bug), gradient, opacity, typography, buttons, inputs, controls, image symbols, hidden/opacity-0 states, runtime-resolved colors via Phase C step 7); (2) `docs/examples/ui/styling/visual_test.spec.md` — LLM-debuggable per-cell expected-values manifest with 13 numbered sections matching the .ts and a "Visible signature" string per cell so a screenshot can be compared cell-by-cell against the spec; (3) `scripts/run_visual_test_check.sh` — drift check that asserts the .ts's `labeled("N. ...", ...)` calls and the spec's `### N.` headers stay 1:1 in lockstep, fails CI when either file adds/removes a row without updating the other; (4) wired into `.github/workflows/test.yml` after the existing UI styling matrix step. Verified end-to-end via 3 rounds of `shadow_repro.ts` (high-contrast yellow shadow against gray cells) — round 1 was inconclusive low-contrast, round 2 confirmed shadows missing, round 3 (post-fix) confirmed shadows render correctly. Cross-platform compile sanity check: web/wasm + iOS-simulator both produce valid binaries from the same `visual_test.ts` source; tvOS/watchOS sim builds need nightly Rust + `-Zbuild-std` (tier-3 targets), deferred. iOS simulator launch crash observed by user — investigation deferred so Windows/Linux validation can run; the macOS fix here is independently shippable and only touches the macOS UI crate.
0 commit comments