πŸŸͺ 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

Perfect For

Β© 2026 GoloScript Project | Built with Gu10berg

Subscribe: πŸ“‘ RSS | βš›οΈ Atom