Skip to content

Conversation

@BrownNPC
Copy link
Owner

@BrownNPC BrownNPC commented Jan 28, 2026

These are a rewrite of the bindings using go:wasmimport and custom javascript helpers that are injected into the Go runtime.

This would give us the flexibility to implement all the raylib functions properly and efficiently. The current ones do a lot of unnecessary copying. (Go -> JS -> Raylib).

In the V2 bindings we control the Go runtime, so we can create helpers that directly copy Go memory into raylib and vice-versa (Go <-> Raylib)

Summary by CodeRabbit

Release Notes

  • New Features

    • Streamlined application initialization.
  • Bug Fixes

    • Removed loading screen overlay for improved startup experience.
  • Refactor

    • Updated memory management and interoperability layer.
    • Camera control functions removed.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Jan 28, 2026

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

  • 🔍 Trigger a full review
📝 Walkthrough

Walkthrough

This PR refactors WebAssembly interoperability by removing the wasm-ffi-go dependency and introducing custom FFI helpers in Go (wasm.go) and JavaScript (Runtime class). It restructures the web frontend initialization (removes loading overlay UI), updates Raylib Go structs with HostLayout fields and cptr pointer abstraction, and removes old WASM-specific public APIs from raylib_wasm.go and rcamera.go.

Changes

Cohort / File(s) Summary
Frontend Initialization
.gitignore, index/.gitignore, index/index.html, index/rl/raylib.js
Gitignore entries reorganized; removed loading overlay UI (51 lines); added default export for Module object
JavaScript Runtime Bridge
index/index.js, index/runtime.js
Replaced overlay loading with explicit canvas right-click disable; introduced Go WASM runtime bootstrap with Raylib integration (33 net lines); new Runtime class with memory accessors, slice/struct handling, string interop, and copy utilities (132 lines)
Raylib Go Struct Modernization
raylib/raylib.go
Added HostLayout field to 40+ exported structs; replaced wasm.Pointer with cptr in Wave, Music, Font, Image types; updated constructors to explicitly initialize all fields (180 net lines)
Raylib FFI & Dependency Updates
raylib/go.mod, raylib/wasm.go
Removed github.com/BrownNPC/wasm-ffi-go dependency; introduced new wasm.go with malloc/free, copy utilities, string interop, and generic memory operations for Go-C interop (105 lines)
Removed APIs
raylib/raylib_wasm.go, raylib/rcamera.go
Deleted entire raylib_wasm.go (122 lines) with 10 WASM-specific public functions (SetMain, AddFileSystem, WindowShouldClose, etc.); commented out all rcamera.go function implementations (14 functions), removing executable camera control logic

Sequence Diagram(s)

sequenceDiagram
    participant Browser
    participant IndexJS as index.js
    participant RaylibModule as Raylib Module
    participant GoRuntime as Go Runtime
    participant RaylibWASM as Raylib WASM
    participant Runtime as Runtime.js

    Browser->>IndexJS: Page loads
    IndexJS->>RaylibModule: Import Module from raylib.js
    RaylibModule-->>IndexJS: Module object (with canvas, wasmBinary)
    IndexJS->>GoRuntime: Create Go instance
    IndexJS->>Runtime: Import Runtime helpers
    Runtime-->>IndexJS: Runtime class
    IndexJS->>GoRuntime: Inject raylib into go.importObject.raylib
    IndexJS->>GoRuntime: Bind Runtime methods to go.importObject
    IndexJS->>GoRuntime: go.Run(wasmInstance)
    GoRuntime->>RaylibWASM: Call FFI helpers (malloc, copyToC, cStringFromGoString, etc.)
    RaylibWASM-->>GoRuntime: Memory operations/pointers
    GoRuntime->>Runtime: Call Runtime bridge methods for memory access
    Runtime->>RaylibWASM: Read/write Go and C memory regions
    RaylibWASM-->>Runtime: Memory views
    Runtime-->>GoRuntime: Slice/struct/string data
    GoRuntime-->>Browser: Raylib instance ready
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 A WASM refactor, clean and bright,
Custom FFI helpers take flight,
Raylib structs now HostLayout dressed,
Gone are old APIs—a modernized best,
No loading screen, just pure delight! ✨

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'V2: go:wasmimport + custom runtime JS helpers based bindings' clearly summarizes the main change: a rewrite of bindings using Go's wasmimport mechanism and custom JavaScript runtime helpers, which aligns with the substantial refactoring across Go and JavaScript files in this changeset.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🤖 Fix all issues with AI agents
In `@index/runtime.js`:
- Around line 35-38: The function loadSlice is calling a global getInt64 which
is undefined; update the calls to use the instance method (e.g., this.getInt64)
so loadSlice uses the object's getInt64 implementation and then calls
this.getmem(array, len); specifically change getInt64(addr + 0) and
getInt64(addr + 8) to this.getInt64(addr + 0) and this.getInt64(addr + 8) inside
loadSlice to avoid a ReferenceError and ensure proper method resolution.
- Around line 117-124: In CopyToGo, the third argument (srcCptr) is being read
from the wrong stack slot (currently from sp + 8 * 2 + 4); update it to read
from the correct third 8-byte slot (same pattern as CopyToC) i.e. sp + 8 * 3 so
srcCptr is pulled from the proper stack location; adjust the getInt32 call in
the CopyToGo function accordingly to match the Go wasm ABI.
- Around line 23-27: The setInt64 implementation zeroes the high 32 bits which
truncates 64-bit values and breaks pointer/size handling; in setInt64 (and
related places that pair with getInt64/CopyToGo/CopyToC) restore the high-word
calculation instead of writing 0: compute the high 32-bit word from v (e.g.
Math.floor(v / 4294967296) or equivalent unsigned-shift/divide) and set that via
this.mem.setUint32(addr + 4, high, true) so full 64-bit values are preserved.

In `@raylib/raylib.go`:
- Around line 571-590: The NewMatrix and NewMat2 constructors assign many Matrix
fields to the wrong parameters (e.g., M13, M10, M14, M11, M15 are incorrectly
set to m1), producing invalid matrices; update both NewMatrix and NewMat2 so
each Matrix field M0..M15 is assigned the corresponding parameter m0..m15
respectively (ensure M0=m0, M1=m1, M2=m2 ... M15=m15) and keep the HostLayout
initialization unchanged—locate the assignments in the NewMatrix and NewMat2
functions and correct the mapping between the mN parameters and the Matrix.MN
fields.
- Around line 32-42: NewWave currently drops the provided audio buffer by
setting Wave.Data to 0; instead allocate the Go byte slice into C memory and
store its pointer in Wave.Data. In the NewWave function use allocSliceInC(data)
(or the appropriate allocator helper) to obtain a C pointer for the provided
data slice and assign that to the Data field of the returned Wave struct,
keeping FrameCount, SampleRate, SampleSize, Channels and __
(structs.HostLayout{}) as-is; ensure you reference NewWave and allocSliceInC so
the allocation replaces the current Data: 0 assignment.

In `@raylib/wasm.go`:
- Around line 76-83: allocSliceInC and copyArrayToGo currently index s[0] which
panics for empty slices; add a length guard at the start of each function that
returns a nil/zero cptr (or otherwise no-op) when len(s) == 0, and only compute
element size and call unsafe.SliceData/copyToC when len > 0; update
allocSliceInC to return cptr(0) for empty slices instead of indexing s[0], and
update copyArrayToGo to skip reads/writes if len == 0 so neither function ever
accesses s[0] on empty slices.
🧹 Nitpick comments (1)
index/index.js (1)

36-42: Add a MIME-type fallback for instantiateStreaming.

Some hosts serve main.wasm with a non‑wasm MIME type; a fallback avoids hard failures.

🔧 Proposed fix
-WebAssembly.instantiateStreaming(fetch("main.wasm"), go.importObject).then(
-  (result) => {
-    const instance = result.instance;
-    globalThis.goInstance = instance;
-    go.run(instance);
-  },
-);
+const goResp = await fetch("main.wasm");
+const goRespClone = goResp.clone();
+const { instance } = await WebAssembly.instantiateStreaming(goResp, go.importObject).catch(
+  async () => WebAssembly.instantiate(await goRespClone.arrayBuffer(), go.importObject),
+);
+globalThis.goInstance = instance;
+go.run(instance);

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