Skip to content

web/wasm target: perry/ui reactive state + setText are no-ops (interactive label updates don't work) #1392

Description

@proggeramlug

Summary

On the wasm/web target (what the playground hub compiles to), perry/ui's reactive state and imperative setText don't update the DOM. Button callbacks fire fine (callWasmClosure works), and by-handle widget mutation works — but anything that updates displayed text via state/setText is a silent no-op. This made a counter example look like "buttons don't work".

Repro

import { App, VStack, Text, Button, state } from 'perry/ui';
const count = state(0);
App({ title: 'c', width: 320, height: 180, body: VStack(12, [
  Text('Counter'),
  (count as any).text(),
  Button('+', () => { (count as any).set(count.value + 1); console.log('val ' + count.value); }),
]) });

Compile --target wasm32-wasi (hub) or --target web, run in a browser:

  • The bound count.text() shows 0 and never changes after clicking +.
  • console.log('val ' + count.value) prints val undefinedcount.value reads undefined.

Imperative path is also dead:

const label = Text('Count: 0', 'count');  // 2nd-arg id
setText('count', 'Count: 1');             // no-op
  • perry_ui_text_create(text) in crates/perry-codegen-wasm/src/wasm_runtime.js ignores the 2nd id arg, and there is no perry_ui_set_text in that runtime, so setText(id, value) dispatches to nothing.

What does work on wasm/web (for contrast)

  • Button onPress callbacks fire (callWasmClosure).
  • By-handle widget mutation in callbacks: widgetSetBackgroundColor(w, …), setCornerRadius, etc. (colors are 0..1 floatsset_background does r*255).
  • showToast, alert.
  • Static layout (VStack/HStack/Text/Button) + static styling.

So an interactive demo is possible via by-handle mutation, but the documented state/setText reactive APIs need wiring on this target.

Likely area

  • crates/perry-codegen-wasm/src/wasm_runtime.js: no perry_ui_set_text; perry_ui_text_create drops the id; js_state_get/js_state_set not bound to the text-update path the way the native targets are.
  • The state_desugar HIR pass / state.text() desugar may not be emitting the bound-text wiring for the wasm backend (perry-codegen-wasm) the way perry-codegen-js does.

Found while building example programs for playground.perryts.com. Happy to test a fix.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions