Skip to content

Rust: wasm-bindgen and UniFFI entrances, examples, and the lists slot - #156

Open
daniloc wants to merge 2 commits into
mainfrom
rust-wasm-entrances-and-lists
Open

daniloc wants to merge 2 commits into
mainfrom
rust-wasm-entrances-and-lists

Conversation

@daniloc

@daniloc daniloc commented Oct 25, 2026

Copy link
Copy Markdown
Collaborator

#147 filled the Rust plugin's text slots, but it still missed most of what a wasm crate exports, and it left the lists slot empty. This change ports what Holofield's ejected Rust plugin read, written to fit #147's structure.

  • Foreign exports: each pub method and constructor of a #[wasm_bindgen] impl is now detected, and named Type::method. So are #[wasm_bindgen(start)] functions, #[uniffi::export] functions, and the pub methods of an exported impl (every method, for a trait impl). These are not detected: imports in an extern block, private, pub(crate) and #[wasm_bindgen(skip)] methods, methods of a plain impl, a trait impl under #[wasm_bindgen], and anything in #[cfg(test)]. Before, a constructor was detected as a bare new, and an extern block's #[wasm_bindgen(js_namespace = …)] fn was detected as an export. These all stay under the existing foreign export rule, so no existing rule is renamed (d-bd0638ec).
  • Examples: a new example rule detects fn main in examples/x.rs and examples/x/main.rs, named example x. A helper file beside it and an examples/ folder under src/ are not detected.
  • Lists: rustListOf fills the lists slot. It reads a top-level const or static array (behind & or in vec![…]): string literals (raw strings by their contents), tuples by their first element, and paths by their last segment. Anything else is reported as unread, and comments are skipped.
  • Core: until now nothing in the core read the lists slot. mirrors.ts always used the TypeScript reader, so a Rust list named under ## mirrors was reported as gone. readLiteral now asks the language of the list's file for its lists reader, and falls back to the TypeScript reader. Literal is now exported from the plugin API.
  • Manifest: testFiles gets ^tests\.rs$. markedFolders gets pkg beside Cargo.toml (wasm-pack output). notDetected now also lists macro-generated exports, UniFFI .udl functions, wasm-bindgen's generated field accessors, and examples away from the default paths.
  • Tests: entrance-candidates.test.ts covers wasm, UniFFI and examples, with the negatives. rust-source.test.ts covers the lists reader. mirrors.test.ts has a Rust list mirrored by a TypeScript literal, broken by an edit. walks.test.ts has pkg beside a Cargo.toml.

Checked by hand on Holofield (11 Rust crates, wasm-bindgen viewer and session crates). Entrance detection found 34 entrances on main and 153 on this branch. Foreign exports went from 32 to 135: the Viewer, Simulation and MeshWorker impl methods, and main's two bare news are now Viewer::new and Simulation::new. Examples went from 0 to 16. That is the same set of (file, symbol) pairs as the ejected plugin. The lists reader reads Holofield's chart tables (KINDS, FUNCTIONS, SEQUENTIAL, ALIASES, TOP) with nothing unread.

Tests: 750 run, 737 pass, 2 skipped. 11 fail, the same 11 as on main in this environment: no pytest or tach venv, no gopls, a temp-folder cleanup in dead-triggers, and the reporter-dependent run tests, because Node 25 prints its spec reporter where testMatch expects TAP. With a node shim that adds --test-reporter=tap, 9 fail, also all present on main. The lexicon check and spec check are clean (533 bullets, 0 problems).

Spec: the entrance detection bullet now covers examples and the impl exports. A new Lifecycle bullet, "a mirror's list is read in its own language", covers the core change. Each was refuted with refute and witnessed batched and alone with run --each.

🤖 Generated with Claude Code

- Entrances: each pub method and constructor of a #[wasm_bindgen] impl,
  #[wasm_bindgen(start)], #[uniffi::export] fns and an exported impl's
  methods (a trait impl's all) are foreign exports, named Type::method; an
  extern block's imports, private, pub(crate), skipped and plain impls'
  methods are not. An example's main at Cargo's default paths is a new
  example rule.
- Lists: rustListOf fills the lists slot (a top-level const or static
  array: strings, tuples by their first, paths by their last segment), and
  mirrors.ts now reads a list through its language's lists slot, which no
  core module read before.
- Manifest: testFiles ^tests\.rs$; pkg beside Cargo.toml is wasm-pack
  output.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Comment thread src/lifecycle/mirrors.ts Fixed
CodeQL's js/unvalidated-dynamic-method-call: the reader comes from a plugin's
syntax slot, chosen by the list file's language. A slot that is not a function
now falls back to the TypeScript reader instead of throwing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants