feat(perry-codegen-arkts): #669 Chart + #670 TreeView on HarmonyOS (v0.5.893) - #736
Merged
Merged
Conversation
proggeramlug
added a commit
that referenced
this pull request
May 13, 2026
Pre-existing flake in `readline::tests::has_active_reflects_state`: the test pushes "x" into PENDING_LINES then asserts has_active==1, but `injected_line_drains_via_test_helper`'s `reset()` (called by the parallel runner) can clear PENDING_LINES in the window between those two lines. All readline tests share global state (PENDING_LINES / PENDING_DATA / EOF_REACHED / RAW_MODE / thread_local callback cells), which cargo test's default parallel scheduler races on. Fix: add a `TEST_LOCK: Mutex<()>` and have `reset()` acquire it + return the guard. Tests that touch shared state now hold the guard for the test's duration via `let _g = reset();`. Pure-function tests (`parse_keypress_*`) don't call `reset()` and stay parallel-safe. Unblocks PR #736 (issues #669/#670 — Chart + TreeView on HarmonyOS) which was bouncing on this pre-existing flake.
…(v0.5.892) Closes the last two widgets in the perry/ui parity matrix — ArkUI has no native chart or tree-outline primitive, so both are hand-rolled. Chart: `Chart(kind, w, h)` → `Canvas(this.__chart_<n>_ctx)` backed by per-instance `RenderingContextSettings` + `CanvasRenderingContext2D` fields on the @component. Four new `Mutation` variants (`ChartAddDataPoint`/`ChartClearData`/`ChartSetTitle`/`ChartReload`) fold the mutator stream at codegen time via `collect_mutations_in_expr`; `fold_chart_mutations` reduces it to a (points, title) pair baked into the `.onReady()` draw closure as `const data` + `const title`. Three draw branches (line/bar/pie) mirror the Android `PerryChartView.onDraw` math 1:1. TreeView: `TreeView(root, onSelect)` → `List({space: 0})` with `ForEach(this.__tree_<n>_flatten(), …)`. Reconstructs the static node graph at codegen time by chasing `rootNode` through `bindings` to its `TreeNode(id, label)` constructor + accumulated `treeNodeAddChild` mutations (`Mutation::TreeAddChild`, `build_tree_node` with 16-hop guard). Emits a `private __tree_<n>_nodes` constant + two `@State` fields (expanded Set, selectedId string) + a `__tree_<n>_flatten()` helper. Tap toggles the expanded set and dispatches `row.id` to `perryEntry.invokeCallback1(<slot>, row.id)`. Threading: bundles `chart_instances` + `tree_view_instances` into one new `&mut HarvestExtras` param so future state-emitting widgets don't each grow every recursive emit_* signature. Tests: six new perry-codegen-arkts unit tests (chart bar/line/pie/clear + treeview graph/depth-padding); all 109 unit tests pass.
Pre-existing flake in `readline::tests::has_active_reflects_state`: the test pushes "x" into PENDING_LINES then asserts has_active==1, but `injected_line_drains_via_test_helper`'s `reset()` (called by the parallel runner) can clear PENDING_LINES in the window between those two lines. All readline tests share global state (PENDING_LINES / PENDING_DATA / EOF_REACHED / RAW_MODE / thread_local callback cells), which cargo test's default parallel scheduler races on. Fix: add a `TEST_LOCK: Mutex<()>` and have `reset()` acquire it + return the guard. Tests that touch shared state now hold the guard for the test's duration via `let _g = reset();`. Pure-function tests (`parse_keypress_*`) don't call `reset()` and stay parallel-safe. Unblocks PR #736 (issues #669/#670 — Chart + TreeView on HarmonyOS) which was bouncing on this pre-existing flake.
proggeramlug
force-pushed
the
feat/669-670-arkts-chart-treeview
branch
from
May 13, 2026 04:32
338ad27 to
f8a12b6
Compare
proggeramlug
added a commit
that referenced
this pull request
May 13, 2026
…g (v0.5.895) Two-site override (resolve.rs::resolve_import + collect_modules.rs) so a package listed in `perry.compilePackages` is compiled from its node_modules source instead of routed to the built-in Rust FFI binding. Unblocks users of packages whose native binding is incomplete (e.g. `rate-limiter-flexible`, where `perry-ext-ratelimit` only wires `consume` through codegen and the codegen-declared `js_ratelimit_create(I64)` doesn't match the real two-arg `js_ratelimit_new(points, duration_secs)` impl). Default behavior unchanged: stock projects without `compilePackages` go through the exact same path. Opt-in and package-scoped. Refs #665. Renumbered from v0.5.892 → v0.5.895 (parallel PRs #734/#736/#737 landed on main). See CHANGELOG.md for full root-cause notes.
proggeramlug
added a commit
that referenced
this pull request
May 13, 2026
…g (v0.5.895) Two-site override (resolve.rs::resolve_import + collect_modules.rs) so a package listed in `perry.compilePackages` is compiled from its node_modules source instead of routed to the built-in Rust FFI binding. Unblocks users of packages whose native binding is incomplete (e.g. `rate-limiter-flexible`, where `perry-ext-ratelimit` only wires `consume` through codegen and the codegen-declared `js_ratelimit_create(I64)` doesn't match the real two-arg `js_ratelimit_new(points, duration_secs)` impl). Default behavior unchanged: stock projects without `compilePackages` go through the exact same path. Opt-in and package-scoped. Refs #665. Renumbered from v0.5.892 → v0.5.895 (parallel PRs #734/#736/#737 landed on main). See CHANGELOG.md for full root-cause notes.
proggeramlug
added a commit
that referenced
this pull request
May 13, 2026
…er-flexible work end-to-end (#735) * feat(resolve): #665 — compilePackages overrides NATIVE_MODULES routing (v0.5.895) Two-site override (resolve.rs::resolve_import + collect_modules.rs) so a package listed in `perry.compilePackages` is compiled from its node_modules source instead of routed to the built-in Rust FFI binding. Unblocks users of packages whose native binding is incomplete (e.g. `rate-limiter-flexible`, where `perry-ext-ratelimit` only wires `consume` through codegen and the codegen-declared `js_ratelimit_create(I64)` doesn't match the real two-arg `js_ratelimit_new(points, duration_secs)` impl). Default behavior unchanged: stock projects without `compilePackages` go through the exact same path. Opt-in and package-scoped. Refs #665. Renumbered from v0.5.892 → v0.5.895 (parallel PRs #734/#736/#737 landed on main). See CHANGELOG.md for full root-cause notes. * fix(codegen): #665 — default-import collision no longer mints phantom cross-class method symbols (v0.5.896) When two different classes are both default-imported in the same file, the `class_ids` / `imported_class_prefix` / `imported_class_source_name` side maps in `compile_module` overwrote each other (last-writer-wins) while `class_table` kept the first stub (first-writer-wins). The mismatch produced method symbols mangled with FIRST stub's method list + LAST writer's class name + LAST writer's source prefix — names the linker can't resolve since Phase F only declares each ic's REAL methods. Flip the three side-map `.insert()` calls to `.entry().or_insert()` so all four maps agree on first-writer-wins. Fixes the `@perry_method_..._RateLimiterRes_js__RateLimiterRes__delete` / `__get` / `__set` / `__block` undefined-value errors that surfaced in rate-limiter-flexible's 5 leaf files once v0.5.895's routing opt-in let them reach codegen. Refs #665. See CHANGELOG.md for full root-cause walkthrough. * fix(codegen,runtime): #665 — setTimeout(fn, delay, ...args) forwards trailing args (v0.5.897) Existing `"setTimeout" if args.len() == 2` arm only handled the 2-arg shape; 3+ arg call sites (e.g. `setTimeout(resolve, delay, res)` inside Promise executors per ECMA-262 §27.5.4.1) fell through to the generic ExternFuncRef fallthrough and emitted `call @settimeout(...)` against a symbol nothing in stdlib defines. Discovering call site: `RateLimiterMemory.consume()`'s Promise executor in rate-limiter-flexible. Adds: - `CallbackTimer::args: Vec<f64>` (empty for 2-arg shape — back-compat). - `js_set_timeout_callback_args(callback, delay_ms, args_ptr, n_args)` runtime entry that copies the buffer in. - `js_callback_timer_tick` dispatch via `match args.len()` to `js_closure_call0..js_closure_call9`, clamping at 9 trailing args. - Codegen `"setTimeout" if args.len() >= 3` arm: alloca a stack buffer of doubles for the trailing args, GEP for the base, call the new runtime entry. Refs #665. See CHANGELOG.md for full root-cause + scope notes. * fix(hir): #665 — compilePackages-opted-in packages skip native-instance lowering (v0.5.898) HIR's `is_native_module` only consulted the NATIVE_MODULES manifest, so `rate-limiter-flexible` was lowered as a native import regardless of the user's `compilePackages` opt-in. That cascaded: register_native_module(local, "rate-limiter-flexible", ...) → new RateLimiterMemory(...) triggers register_native_instance(limiter, "rate-limiter-flexible", "RateLimiterMemory") → limiter.consume in expr_member::lower_member emits NativeMethodCall { module, object: Some(limiter), method: "consume", args: [] } → codegen routes to js_native_call_method → no FFI entry → 0.0 So `typeof limiter.consume === "number"`. For genuine native bindings (req.method on http.IncomingMessage) this zero-arg-getter lowering is correct; for compile-package-overridden classes it's wrong because `consume` is a real method, not a getter. Fix: add a thread-local `COMPILE_PACKAGES_OVERRIDE: HashSet<String>` in perry-hir, set by the compiler driver via `set_compile_packages_override(ctx.compile_packages.clone())` before each `lower_module_full` invocation and cleared after. `is_native_module` parses the package name (supports `node:` prefix + `@scope/pkg` scoped form) and returns false when the package is in the override even if it appears in NATIVE_MODULES. Validation: rate-limiter-flexible probe now reports `typeof limiter.consume: function` (was "number"). Workspace tests green. Refs #665. See CHANGELOG.md for full root-cause walkthrough.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Chart(kind, w, h)lowers to ArkUICanvas(this.__chart_<n>_ctx)with per-instanceCanvasRenderingContext2Dfield. Four newMutationvariants foldchartAddDataPoint/chartClearData/chartSetTitle/chartReloadat codegen time; the draw closure bakes in the data + title as inline literals. Three draw branches (line/bar/pie) mirror the AndroidPerryChartView.onDrawmath 1:1.TreeView(root, onSelect)lowers toList({space: 0})+ForEach(this.__tree_<n>_flatten(), …). Static node graph reconstructed at codegen time by chasingrootNodethrough bindings +treeNodeAddChildmutations (16-hop guard). Emitsprivate __tree_<n>_nodesconstant +@Stateexpanded set + selectedId + a flatten helper. Tap toggles expansion and dispatches the row id viaperryEntry.invokeCallback1.HarvestExtras { chart_instances, tree_view_instances }bundle passed as a single&mut HarvestExtrasso future state-emitting widgets don't each grow every recursive emit_* signature.Test plan
cargo test --release -p perry-codegen-arkts— 109/109 unit tests pass (6 new), 2/2 integration passcargo test --release --workspace --exclude perry-ui-{ios,tvos,watchos,visionos,android,windows,gtk4}— exit 0cargo build --release -p perry-codegen-arkts -p perry-runtime -p perry-stdlib -p perry— clean