Skip to content

feat(npm): publish gauche-rs wasm package - #7

Open
DennisOSRM wants to merge 1 commit into
mainfrom
feat/npm-wasm-package
Open

feat(npm): publish gauche-rs wasm package#7
DennisOSRM wants to merge 1 commit into
mainfrom
feat/npm-wasm-package

Conversation

@DennisOSRM

Copy link
Copy Markdown
Contributor

Turns the untracked pkg/ experiment into a publishable npm package and fixes what was wrong with it.

classifyLine could kill the wasm instance

The wrapper wrote its coordinate buffer to a hardcoded address 1024, a fallback chosen because the module exports no __heap_base. Parsing the module's layout:

Region Range
shadow stack 01048576
static data 10485762721312
live heap above ~2721312

Address 1024 sits in the shadow stack. Static data gets overwritten for large lines, but initialize_index_wasm parses the OSM string and bitmap onto the heap and never reads the static copies again, so this was invisible in normal use — a 100k-point line still classified 2343 grid points identically to a clean instance.

Past roughly 170k points the write reaches the live heap. At 400k the instance dies:

RuntimeError: memory access out of bounds
    at wasm://wasm/006a0cba:wasm-function[120]:0x6411

gauche_alloc/gauche_free are now exported from the web-wasm block and classifyLine allocates through them, freeing in a finally. init() fails with an actionable message if it is handed a .wasm older than the wrapper.

Wrong license

package.json declared ISC. The project is BSD-2-Clause. Corrected, and LICENSE plus a package README now ship in the tarball.

Verification

End-to-end against the real wrapper, with the wasm served over HTTP so fetch and instantiateStreaming take their genuine paths:

  • points, bbox, and lines for London / Berlin / Tokyo / Sydney all correct
  • 100k, 400k, and 1M point lines classify without trapping
  • 25 consecutive 50k-point calls, no leak-driven growth
  • point queries still correct afterwards
  • cargo test 16 passed; cargo fmt --check clean

npm pack: 6 files, 71.0 kB packed.

Also

allow(clippy::not_unsafe_ptr_arg_deref) on the two extern "C" fns taking raw pointers. The one on classify_line_wasm is pre-existing on main; clippy against wasm32-unknown-unknown now passes. CI only runs cargo fmt, so this was never gating.

The dist/gauche-wasm-map.html diff is the embedded wasm picking up the two new exports.

🤖 Generated with Claude Code

https://claude.ai/code/session_0152BLSwmtKX4pQmiLpd8wKN

Track the npm package that was previously an untracked local experiment in
pkg/, and fix the issues that blocked publishing it.

gauche_alloc/gauche_free are new exports on the web-wasm build. classifyLine
previously wrote its coordinate buffer to a hardcoded address 1024, chosen as
a fallback because the module exports no __heap_base. That address is in the
shadow stack region; static data starts at 1048576 and the live heap above
~2721312. Static data is only read during initialize_index_wasm, so short
lines were unaffected, but past roughly 170k points the write reached the live
heap and the instance died with "memory access out of bounds". classifyLine
now allocates through the module allocator and frees in a finally block, which
was verified up to 1M points.

The package metadata declared ISC. The project is BSD-2-Clause, so correct it
and ship LICENSE and a README in the tarball.

Also add allow(clippy::not_unsafe_ptr_arg_deref) to the two extern "C"
functions taking raw pointers. The one on classify_line_wasm is pre-existing;
cargo clippy against wasm32-unknown-unknown now passes.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0152BLSwmtKX4pQmiLpd8wKN
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.

1 participant