πͺ WebAssembly Integration in GoloScript
- GoloScript + WASM: The power of native performance with the simplicity of scripting.
- Extend GoloScript with WebAssembly. Call Rust, Go, C++, and moreβinstantly.
Why WASM + GoloScript?
GoloScript makes WebAssembly simple. Load modules, call functions, and share data between host and guest with zero configuration.
Load and Call WASM in 3 Lines
let runner = wasmLoad("./module.wasm")
let result = wasmCallString(runner, "hello", "Alice")
wasmClose(runner)
Thatβs it. No complicated configuration. No binding generation. Just works.
Native WASM Support
String Functions
Call WASM functions that take and return strings:
module examples.wasm.StringExample
function main = |args| {
println("=== πͺ WASM String Function Example ===")
# Load the WASM module (TinyGo compiled)
let runner = wasmLoad("./guest.wasm")
println("β WASM module loaded")
# Call the hello function with different names
let names = ["Alice", "Bob", "Charlie"]
foreach name in names {
let result = wasmCallString(runner, "hello", name)
println(" β " + result)
}
wasmClose(runner)
}
Output:
=== πͺ WASM String Function Example ===
β WASM module loaded
β Hello, Alice! π
β Hello, Bob! π
β Hello, Charlie! π
Number Functions
Work with numeric data seamlessly:
let runner = wasmLoad("./calculator.wasm")
# Call with numbers, get numbers back
let sum = wasmCallNumber(runner, "add", 42, 17)
println("Result:", sum) # 59
let factorial = wasmCallNumber(runner, "factorial", 5)
println("5! =", factorial) # 120
wasmClose(runner)
Bidirectional Communication
Host Functions: Call GoloScript from WASM
Register GoloScript functions that WASM can call back:
module examples.wasm.HostFunction
function main = |args| {
println("π Testing WASM host functions...")
# Load the WASM module
let runner = wasmLoad("./guest.wasm")
# Create a handler function that WASM can call
let myHandler = |input| {
println("π΅ Host receives: " + input)
# Process the input
let result = input: toUpperCase() + " [PROCESSED BY GOLO]"
println("π’ Host returns: " + result)
return result
}
# Register the handler
wasmRegisterStringHandler(runner, myHandler)
println("β
Handler registered")
# Call WASM function that will call back to our handler
println("\nπ Calling WASM function 'processWithHost'...")
let result = wasmCallString(runner, "processWithHost", "Hello from GoloScript!")
println("\n⨠Final result: " + result)
wasmClose(runner)
}
Output:
π Testing WASM host functions...
β
WASM module loaded
β
Handler registered
π Calling WASM function 'processWithHost'...
π΅ Host receives: Hello from GoloScript!
π’ Host returns: HELLO FROM GOLOSCRIPT! [PROCESSED BY GOLO]
β¨ Final result: HELLO FROM GOLOSCRIPT! [PROCESSED BY GOLO]
The WASM Guest (TinyGo)
package main
import (
"unsafe"
)
//export processWithHost
func processWithHost(ptr, size uint32) (uint64) {
// Get input from host
input := ptrToString(ptr, size)
// Call the host function
result := callHostFunction(input)
// Return result to host
return stringToPtr(result)
}
//export callHostFunction
func callHostFunction(input string) string
func main() {}
Real-World Patterns
Pattern 1: Dynamic Plugin System
# Load plugins dynamically based on user input
function loadPlugin = |pluginName| {
let wasmPath = "./plugins/" + pluginName + ".wasm"
try {
let runner = wasmLoad(wasmPath)
println("β
Plugin loaded:", pluginName)
return Result(runner)
} catch (e) {
return Error("Failed to load plugin: " + e)
}
}
# Use the plugin
let pluginResult = loadPlugin("image-filter")
if pluginResult: isOk() {
let runner = pluginResult: value()
# Check available functions
if wasmHasFunction(runner, "grayscale") {
let output = wasmCallString(runner, "grayscale", imageData)
println("Processed image:", output)
}
wasmClose(runner)
}
Pattern 2: Multi-Language Pipeline
Combine WASM modules from different languages:
function main = |args| {
# Step 1: Use Rust for cryptography
let rustCrypto = wasmLoad("./crypto.wasm") # Compiled from Rust
let encrypted = wasmCallString(rustCrypto, "encrypt", "secret data")
# Step 2: Use Go for compression
let goCompress = wasmLoad("./compress.wasm") # Compiled from TinyGo
let compressed = wasmCallString(goCompress, "compress", encrypted)
# Step 3: Use C++ for encoding
let cppEncoder = wasmLoad("./encoder.wasm") # Compiled from C++
let encoded = wasmCallString(cppEncoder, "base64", compressed)
println("Final result:", encoded)
# Cleanup
wasmClose(rustCrypto)
wasmClose(goCompress)
wasmClose(cppEncoder)
}
Pattern 3: Error Handling
function safeWasmCall = |runner, funcName, input| {
try {
if not wasmHasFunction(runner, funcName) {
return Error("Function '" + funcName + "' not found")
}
let result = wasmCallString(runner, funcName, input)
return Result(result)
} catch (e) {
return Error("WASM call failed: " + e)
}
}
# Usage
let runner = wasmLoad("./module.wasm")
let result = safeWasmCall(runner, "process", "data")
if result: isOk() {
println("Success:", result: value())
} else {
println("Error:", result: message())
}
wasmClose(runner)
Supported WASM Languages
GoloScript works with any language that compiles to WASM:
| Language | Compiler | Status |
|---|---|---|
| Go | TinyGo | Tested |
| Rust | rustc + wasm32-unknown-unknown | Tested |
| C/C++ | Emscripten, clang | Compatible |
| AssemblyScript | asc | Compatible |
| Zig | zig build-lib | Compatible |
| Swift | SwiftWasm | Compatible |
WASM API Reference
Core Functions
# Load a WASM module
let runner = wasmLoad(path: String) -> WasmRunner
# Check if function exists
let exists = wasmHasFunction(runner: WasmRunner, funcName: String) -> Boolean
# Call with string parameters
let result = wasmCallString(runner: WasmRunner, funcName: String, input: String) -> String
# Call with number parameters
let result = wasmCallNumber(runner: WasmRunner, funcName: String, args: Number...) -> Number
# Register host function
wasmRegisterStringHandler(runner: WasmRunner, handler: Closure)
# Clean up
wasmClose(runner: WasmRunner)
Use Cases
Performance-Critical Code
Use Rust or C++ for CPU-intensive tasks:
# Heavy computation in Rust WASM
let runner = wasmLoad("./image-processor.wasm")
let processed = wasmCallString(runner, "apply_filter", imageData)
Reuse Existing Libraries
Leverage mature C/C++ libraries:
# Use OpenCV compiled to WASM
let cv = wasmLoad("./opencv.wasm")
let faces = wasmCallString(cv, "detect_faces", imageData)
Sandboxed Execution
Run untrusted code safely:
# User-provided WASM plugin (sandboxed)
let userPlugin = wasmLoad("./user_plugin.wasm")
let result = wasmCallString(userPlugin, "process", userInput)
Cross-Platform Native Code
Write once in Rust/Go, run anywhere:
# Same WASM module works on Linux, Mac, Windows
let runner = wasmLoad("./native.wasm")
let result = wasmCallString(runner, "get_system_info", "")
Key Features
- Zero Config: No build tools, no binding generation
- String & Number Support: Automatic conversion between host and guest
- Bidirectional Calls: Host can call guest, guest can call host
- Multiple Modules: Load as many WASM modules as you need
- Error Handling: Try/catch integration with WASM calls
- Function Inspection: Check if functions exist before calling
Perfect For
- Plugin systems - Load user-provided WASM modules safely
- Performance - Delegate heavy work to optimized WASM
- Polyglot development - Mix languages in one application
- Legacy code reuse - Compile C/C++ libraries to WASM
- Edge computing - Lightweight, portable, sandboxed
Β© 2026 GoloScript Project | Built with Gu10berg
Subscribe: π‘ RSS | βοΈ Atom