GoWM Documentation
JavaScript library for Go WebAssembly modules
GoWM ... (Go Wasm Manager) is a JavaScript library that simplifies loading and executing Go WASM modules in both Node.js and browser environments, with GitHub repository support, event system, React hooks, Vue composables, CLI, type generation, and advanced memory management.
Main Features
- Universal Loading - Load WASM from local files, URLs, or GitHub repositories
- Cross-Platform - Works in Node.js and browser with automatic environment detection
- TypeScript Support - Complete type definitions with IntelliSense support
- GitHub Support - Direct loading from repositories with branch/tag support
- Memory Management - Advanced buffer creation and cleanup for WASM interactions
- Simple API - Clean interface for calling WASM functions and managing modules
Framework Integration - Available in v1.1.2
React hooks and Vue 3 composables are now available! Import from gowm/react or gowm/vue. Also includes event system (on/off/once), CLI (npx gowm), TypeScript type generator from module.json, ESM exports map, and 274 unit tests.
Installation
Add GoWM to your project
npm install gowmyarn add gowmpnpm add gowmQuick Start
Basic usage examples with real function calls
import { GoWM } from 'gowm';
// Create a GoWM instance with configurable logging
const gowm = new GoWM({ logLevel: 'info' });
// Load from GitHub repository (branch auto-detected)
// Cached, retries on failure, tries compressed variants
const mathModule = await gowm.loadFromGitHub('benoitpetit/wasm-modules-repository', {
name: 'math',
path: 'math-wasm',
filename: 'main.wasm',
retries: 3, // retry on network failure
cache: { ttl: 3600000 } // cache for 1 hour
});
// Load from local file or URL
const localWasm = await load('./math.wasm', { name: 'local-math' });
// Function calls (synchronous)
const result = mathModule.call('add', 5, 3);
console.log('5 + 3 =', result); // 8
const multiply = mathModule.call('multiply', 6, 7);
console.log('6 × 7 =', multiply); // 42
// Clear cache when needed
await gowm.clearCache();
// Module statistics
const stats = mathModule.getStats();
console.log('Module info:', {
name: stats.name,
ready: stats.ready,
functions: stats.functions.length,
memoryUsage: stats.memoryUsage
});
// Global GoWM statistics
const globalStats = await getStats();
console.log('Total modules:', globalStats.modules?.length || 0);GitHub Loading
Load WASM modules directly from repositories with intelligent file discovery
Basic GitHub Loading
import { GoWM } from 'gowm';
const gowm = new GoWM();
// Basic loading — branch auto-detected via GitHub API
const math = await gowm.loadFromGitHub('benoitpetit/wasm-modules-repository', {
path: 'math-wasm',
filename: 'main.wasm',
name: 'math-basic'
});
// Enable silent mode and test functions
math.call('setSilentMode', true);
console.log('5 + 3 =', math.call('add', 5, 3));
console.log('Available functions:', math.call('getAvailableFunctions'));Advanced GitHub Options
// Load with advanced options (v1.4.0)
const crypto = await gowm.loadFromGitHub('benoitpetit/wasm-modules-repository', {
path: 'crypto-wasm',
filename: 'main.wasm',
name: 'crypto-advanced',
// branch is auto-detected via GitHub API
cache: { ttl: 3600000 }, // 1 hour cache TTL
retries: 3, // retry on network failure
// v1.4.0 options:
// metadata: true, // fetch module.json (default: true)
// integrity: true, // verify SHA256 hash (default: true)
// validateCalls: true, // validate function parameters (default: true)
});
// v1.4.0: Describe a function from module.json metadata
const desc = crypto.describe('hashSHA256');
console.log(desc.name, desc.description, desc.parameters);
// v1.4.0: Get all functions with metadata
const functions = crypto.getDetailedFunctions();
functions.forEach(fn => console.log(fn.name, fn.description));
// v1.4.0: Get function categories
const categories = crypto.getFunctionCategories();
// v1.4.0: Module metadata at GoWM level
const metadata = gowm.getModuleMetadata('crypto-advanced');
console.log(metadata.name, metadata.version);
// Load from specific tag or commit
const stable = await gowm.loadFromGitHub('owner/repo', {
tag: 'v1.2.3', // Use specific version (overrides branch)
path: 'dist',
filename: 'module.wasm',
name: 'stable-version'
});Automatic File Discovery
GoWM automatically searches for WASM files using intelligent patterns:
Search Priority
- 1. Specified path/filename
- 2. Module-specific paths
- 3. Root directory files
- 4. Common build folders
- 5. GitHub releases
- 6. Recursive search
Common Patterns
- •
{name}/main.wasm - •
main.wasm,index.wasm - •
wasm/,dist/,build/ - •
{repo-name}.wasm - • Release assets
Repository Format Support
// Supported repository formats:
// 1. Simple owner/repo
await loadFromGitHub('owner/repo');
// 2. With branch specification
await loadFromGitHub('owner/repo@main');
// 3. With path in repository
await loadFromGitHub('owner/repo/path/to/wasm');
// 4. With branch and path
await loadFromGitHub('owner/repo@branch/path/to/wasm');
// 5. Full GitHub URL
await loadFromGitHub('https://github.com/owner/repo');
// 6. Options override format parsing
await loadFromGitHub('owner/repo', {
branch: 'develop', // Overrides @branch in URL
path: 'custom/path', // Overrides path in URL
tag: 'v2.0.0' // Takes precedence over branch
});Loading Multiple Modules
import { GoWM } from 'gowm';
const gowm = new GoWM({ logLevel: 'info' });
// Load multiple modules in parallel (each gets its own namespace)
const [math, crypto] = await Promise.all([
gowm.loadFromGitHub('benoitpetit/wasm-modules-repository', {
path: 'math-wasm', name: 'math'
}),
gowm.loadFromGitHub('benoitpetit/wasm-modules-repository', {
path: 'crypto-wasm', name: 'crypto'
})
]);
// Modules are isolated — no function name conflicts
console.log('Math functions:', math.getAvailableFunctions());
console.log('Crypto functions:', crypto.getAvailableFunctions());
// List all loaded modules
console.log('Loaded:', gowm.listModules());Memory Management
Advanced buffer creation and cleanup for WASM interactions
Buffer Creation
Create buffers for efficient data transfer between JavaScript and WASM:
// Create buffer from typed array
const floatBuffer = wasm.createBuffer(new Float64Array([1.5, 2.7, 3.14]));
console.log('Float buffer:', floatBuffer.size, 'bytes');
// Create buffer from string
const textBuffer = wasm.createBuffer('Hello WASM World!');
console.log('Text buffer:', textBuffer.size, 'bytes');
// Create buffer from regular array
const intBuffer = wasm.createBuffer(new Uint8Array([1, 2, 3, 4, 5]));
console.log('Integer buffer:', intBuffer.size, 'bytes');Buffer Usage in WASM Functions
Pass buffer pointers to WASM functions for processing:
// Process array data in WASM
const data = new Float64Array([1, 2, 3, 4, 5]);
const buffer = wasm.createBuffer(data);
// Pass buffer pointer and size to WASM function
const result = wasm.call('processArray', buffer.ptr, buffer.size);
console.log('Processing result:', result);
// Always clean up when done
buffer.free();Memory Management Best Practices
Proper memory management prevents leaks and ensures optimal performance:
// Always use try-finally for cleanup
let buffer = null;
try {
buffer = wasm.createBuffer(largeDataArray);
const result = wasm.call('processLargeData', buffer.ptr, buffer.size);
return result;
} finally {
if (buffer) {
buffer.free(); // Ensures cleanup even if errors occur
}
}
// Check memory usage
const stats = wasm.getStats();
console.log('Allocated buffers:', stats.allocatedBuffers);
console.log('Memory usage:', stats.memoryUsage, 'bytes');Memory Management Tips
- • Always call
buffer.free()when done with buffers - • Use try-finally blocks for guaranteed cleanup
- • Monitor memory usage with
wasm.getStats() - • Prefer smaller, frequent operations over large buffers
Web Workers & Performance
Non-blocking execution and zero-copy memory transfers (v1.3.0)
🆕 Phase 2: Performance & Concurrency
GoWM v1.3.0 introduces Web Workers support for non-blocking execution and SharedArrayBuffer for zero-copy memory transfers. Perfect for heavy computations like cryptography, image processing, and machine learning inference.
Web Workers: Non-Blocking Execution
Load WASM modules in dedicated worker threads to prevent UI freezing during heavy computations:
import { GoWM } from 'gowm';
// Enable worker support
const gowm = new GoWM({ enableWorkers: true });
// Load module in a worker thread
const workerModule = await gowm.loadInWorker('benoitpetit/wasm-modules-repository', {
name: 'crypto',
path: 'crypto-wasm',
maxWorkers: 4 // Pool size (default: 4)
});
// Call functions in worker (non-blocking, returns Promise)
const encrypted = await workerModule.call('encrypt', largeData, key);
console.log('Encrypted (UI never froze!):', encrypted);
// Check worker status
const status = workerModule.getStatus();
console.log('Worker ready:', status.ready);
// Cleanup when done
workerModule.terminate();React Hook: useWasmWorker
Use the useWasmWorker hook for seamless integration in React applications:
import { useWasmWorker } from 'gowm/react';
function ImageProcessor() {
const { worker, loading, error, call, terminate } = useWasmWorker(
'benoitpetit/wasm-modules-repository',
{ path: 'image-wasm' }
);
const processImage = async (imageData) => {
if (!worker) return;
// Heavy image processing in worker - UI stays responsive
const processed = await call('processImage', imageData);
return processed;
};
if (loading) return <p>Loading worker...</p>;
if (error) return <p>Error: {error.message}</p>;
return (
<button onClick={() => processImage(largeImageData)}>
Process Image (Non-Blocking)
</button>
);
}SharedArrayBuffer: Zero-Copy Transfers
Share memory directly between main thread and workers without copying - up to 10x faster for large datasets:
// Check browser support first
if (bridge.isSharedArrayBufferSupported()) {
// Create 1MB shared buffer
const sharedBuffer = bridge.createSharedBuffer(1024 * 1024);
// Write large data without copying
const largeData = new Uint8Array(1024 * 1024);
sharedBuffer.write(largeData, 0);
// Map to WASM memory for direct access
const mapped = bridge.mapSharedBuffer(sharedBuffer.buffer, 0, largeData.length);
// WASM can now read/write directly
const result = bridge.call('processSharedData', mapped.ptr, mapped.size);
// Sync changes back
mapped.sync();
// Read results
const processed = sharedBuffer.read(1024, 0);
// Cleanup
mapped.free();
} else {
console.warn('SharedArrayBuffer not supported - falling back to regular buffers');
}React Hook: useSharedBuffer
Manage SharedArrayBuffer with React hooks for optimal performance:
import { useSharedBuffer } from 'gowm/react';
function VideoProcessor() {
const { buffer, view, supported, writeData, readData, clear } =
useSharedBuffer(1024 * 1024 * 10); // 10MB buffer
if (!supported) {
return <p>SharedArrayBuffer not supported in this browser</p>;
}
const processVideo = async (videoFrameData) => {
// Write frame data without copying
writeData(videoFrameData, 0);
// Process with WASM (using the shared buffer)
// ...
// Read processed data
const processed = readData(videoFrameData.length, 0);
return processed;
};
return <div>Video processor ready (zero-copy mode)</div>;
}Combined: Worker + SharedMemory
Maximum performance by combining workers with shared memory:
import { useWasmWorkerWithSharedMemory } from 'gowm/react';
function MLInference() {
const {
worker,
sharedBuffer,
callWithSharedMemory,
loading,
ready
} = useWasmWorkerWithSharedMemory('owner/ml-model-wasm', {
sharedBufferSize: 1024 * 1024 * 50 // 50MB for ML model
});
const runInference = async (inputTensor) => {
if (!ready) return;
// Zero-copy + non-blocking: best of both worlds
const result = await callWithSharedMemory(
'inferModel',
inputTensor,
'modelConfig'
);
return result;
};
return ready ? <button onClick={() => runInference(data)}>Run ML Inference</button> : null;
}Browser Requirements
- Web Workers: Supported in all modern browsers (automatically disabled in Node.js)
- SharedArrayBuffer: Requires HTTPS (or localhost) + CORS headers:
- •
Cross-Origin-Opener-Policy: same-origin - •
Cross-Origin-Embedder-Policy: require-corp
- •
- Browser support: Chrome 92+, Firefox 79+, Safari 15.2+
Performance Impact
- • UI Responsiveness: Heavy computations never freeze the interface
- • Zero-Copy: Up to 10x faster for large data transfers (>1MB)
- • Parallel Processing: Multiple workers enable concurrent computation
- • Memory Efficiency: SharedArrayBuffer eliminates redundant copies
Perfect Use Cases
- • Image/Video Processing: Real-time filters, compression, format conversion
- • Cryptography: Encryption, decryption, hashing operations
- • Data Processing: Large dataset transformations and analytics
- • Machine Learning: WASM ML models with zero-copy inference
- • Real-time Applications: Continuous computation without UI lag
API Reference
Complete GoWM API documentation
Loading Functions
load(source, options)
Loads a WASM module from a local file or URL.
const module = await load('./math.wasm', {
name: 'math-module',
goRuntimePath: './custom_wasm_exec.js'
});loadFromGitHub(repo, options)
Loads a WASM module from a GitHub repository with automatic file discovery.
const module = await loadFromGitHub('user/repo', {
name: 'github-module',
// branch auto-detected via GitHub API
path: 'wasm',
filename: 'module.wasm'
});get(name)
Retrieves an already loaded module by name.
const module = get('my-module');
if (module) {
const result = module.call('function', arg1, arg2);
}unload(name)
Unloads a module and cleans up its resources.
const success = await unload('my-module');
console.log('Module unloaded:', success);WasmBridge Methods
call(funcName, ...args)
Calls a WASM function synchronously.
const result = wasm.call('add', 5, 3);
const data = wasm.call('processData', buffer.ptr, buffer.size);callAsync(funcName, ...args)
Calls a WASM function asynchronously.
const result = await wasm.callAsync('complexCalculation', data);
const processed = await wasm.callAsync('asyncOperation', input);createBuffer(data)
Creates a buffer in WASM memory for data transfer.
const buffer = wasm.createBuffer(new Float64Array([1, 2, 3]));
console.log('Buffer:', buffer.size, 'bytes');
buffer.free(); // Always release memorycall("getAvailableFunctions") → string[]
Returns a list of all available functions via WASM call method.
const functions = wasm.call('getAvailableFunctions');
console.log('Available functions:', functions);
// Example: ['add', 'multiply', 'setSilentMode', 'getAvailableFunctions']call("getAvailableFunctions") → Check Functions
Check if a function exists by listing available functions.
const functions = wasm.call('getAvailableFunctions');
if (functions.includes('optionalFeature')) {
const result = wasm.call('optionalFeature', data);
}getStats() → ModuleStats
Returns detailed statistics about the module. In v1.4.0, includes metadata information.
const stats = wasm.getStats();
console.log('Module Statistics:', {
name: stats.name,
ready: stats.ready,
functions: stats.functions,
memoryUsage: stats.memoryUsage,
allocatedBuffers: stats.allocatedBuffers,
// v1.4.0
hasMetadata: stats.hasMetadata,
metadata: stats.metadata // { name, version, functionsCount, categories }
});describe(funcName) → FunctionDescription | null (v1.4.0)
Returns inline documentation for a function from module.json metadata.
const desc = wasm.describe('add');
// { name: 'add', description: '...', category: 'Basic Arithmetic',
// parameters: [{ name: 'a', type: 'number' }, { name: 'b', type: 'number' }],
// returnType: 'number', example: 'add(5, 3) → 8' }getDetailedFunctions() → DetailedFunction[] (v1.4.0)
Returns all functions with full metadata (parameters, types, descriptions).
const functions = wasm.getDetailedFunctions();
functions.forEach(fn => {
console.log(fn.name + ': ' + fn.description);
fn.parameters?.forEach(p => console.log(' ' + p.name + ': ' + p.type));
});getFunctionCategories() → object | null (v1.4.0)
Returns function categories from metadata.
const categories = wasm.getFunctionCategories();
// { 'Basic Arithmetic': ['add', 'subtract'], 'Advanced': ['factorial'] }
Object.entries(categories).forEach(([cat, funcs]) => {
console.log(cat + ': ' + funcs.join(', '));
});registerCallback(name, callback) → void
Register a JavaScript callback that can be called from WASM (if supported).
wasm.registerCallback('logMessage', (message) => {
console.log('From WASM:', message);
});
// WASM can now call logMessage('Hello from Go!')cleanup() → void
Manually cleans up module resources.
// Called automatically, but can be called manually
wasm.cleanup();Management Functions
isLoaded(name) → boolean | Promise<boolean>
Checks if a module is currently loaded.
// Synchronous check (browser)
if (isLoaded('my-module')) {
console.log('Module is ready to use');
}
// Async check (Node.js)
if (await isLoaded('my-module')) {
console.log('Module is ready to use');
}listModules() → Promise<string[]>
Returns array of loaded module names.
const modules = await listModules();
console.log('Loaded modules:', modules);getStats() → Promise<Record<string, ModuleStats>>
Returns statistics for all loaded modules.
const stats = await getStats();
Object.entries(stats).forEach(([name, stat]) => {
console.log(`${name}: ${stat.memoryUsage} bytes`);
});getTotalMemoryUsage() → Promise<number>
Returns total memory usage of all loaded modules.
const totalMemory = await getTotalMemoryUsage();
console.log(`Total WASM memory: ${totalMemory} bytes`);unloadAll() → Promise<void>
Unloads all modules and cleans up resources.
await unloadAll(); // Clean slateCore API Methods
loadFromGitHub(repo, options) → Promise<WasmBridge>
Load a WASM module from GitHub repository with automatic file discovery.
const module = await loadFromGitHub('owner/repo', {
// branch auto-detected via GitHub API
path: 'wasm-dir', // Directory path
filename: 'main.wasm', // Specific filename
name: 'my-module', // Module identifier
retries: 3, // Retry on failure
cache: { ttl: 3600000 } // 1h cache
});load(source, options) → Promise<WasmBridge>
Universal loader with auto-detection for files, URLs, and GitHub repos.
// Auto-detection examples
const wasm1 = await load('owner/repo'); // GitHub
const wasm2 = await load('https://domain.com/mod.wasm'); // URL
const wasm3 = await load('./local.wasm'); // FileFramework Integration - Available in v1.1.2
React hooks and Vue 3 composables are now available. Import from gowm/react or gowm/vue.
Load Options Reference
Basic Load Options
- •
name- Module identifier (string) - •
goRuntimePath- Custom Go runtime path - •
preInit- Pre-initialize module (boolean, default: true)
GitHub Load Options
- •
branch- Git branch (default: auto-detected) - •
tag- Git tag (overrides branch) - •
path- Path within repository - •
filename- Specific filename - •
cache- Cache config (falseor{ ttl }) - •
retries- Retry attempts (default: 3) - •
metadata- Fetch module.json (default: true) v1.4.0 - •
integrity- Verify SHA256 hash (default: true) v1.4.0 - •
validateCalls- Validate params (default: true) v1.4.0
Examples
Practical usage examples
Basic Node.js Example
import { GoWM } from 'gowm';
async function example() {
const gowm = new GoWM({ logLevel: 'info' });
try {
// Load from GitHub (branch auto-detected, metadata & integrity auto-fetched)
const math = await gowm.loadFromGitHub('benoitpetit/wasm-modules-repository', {
name: 'math',
path: 'math-wasm'
});
// Function calls (v1.4.0: parameters validated against metadata)
const result = math.call('add', 5, 3);
console.log('5 + 3 =', result); // 8
const asyncResult = await math.callAsync('multiply', 4, 7);
console.log('4 * 7 =', asyncResult); // 28
// v1.4.0: Describe a function from module.json
const desc = math.describe('add');
console.log(desc.name, desc.description, desc.parameters);
// v1.4.0: Get all functions with metadata
const functions = math.getDetailedFunctions();
functions.forEach(fn => console.log(fn.name + ': ' + fn.description));
// v1.4.0: Module metadata
const metadata = gowm.getModuleMetadata('math');
console.log(metadata.name + ' v' + metadata.version);
// Statistics (v1.4.0: includes hasMetadata)
const stats = math.getStats();
console.log('Module info:', {
name: stats.name,
ready: stats.ready,
hasMetadata: stats.hasMetadata
});
} catch (error) {
console.error('Error:', error.message);
}
}
example();Advanced Memory Management
import { GoWM } from 'gowm';
async function memoryExample() {
const gowm = new GoWM();
const module = await gowm.loadFromGitHub('benoitpetit/wasm-modules-repository', {
name: 'image-processor',
path: 'image-wasm'
});
// Create different types of buffers
const floatBuffer = module.createBuffer(new Float64Array([1, 2, 3, 4, 5]));
const byteBuffer = module.createBuffer(new Uint8Array([65, 66, 67]));
const stringBuffer = module.createBuffer('Hello, WASM!');
try {
// Use buffers in WASM calls
const result = module.call('processArray', floatBuffer.ptr, floatBuffer.size);
const processed = await module.callAsync('processBytes', byteBuffer.ptr, byteBuffer.size);
// Monitor memory usage
const stats = module.getStats();
console.log('Memory usage:', stats.memoryUsage, 'bytes');
console.log('Allocated buffers:', stats.allocatedBuffers);
} finally {
// Always clean up buffers
floatBuffer.free();
byteBuffer.free();
stringBuffer.free();
}
}GoWM Instance & Logging
import { GoWM } from 'gowm';
// Initialize with configurable logging
const gowm = new GoWM({
logLevel: 'debug', // 'silent' | 'error' | 'warn' | 'info' | 'debug'
// logger: customLoggerFn // Optional custom logger
});
// Load module (metadata & integrity auto-fetched in v1.4.0)
const module = await gowm.loadFromGitHub('owner/repo', {
name: 'my-module',
path: 'wasm-dir'
});
// v1.4.0: Describe a function from module.json
const desc = gowm.describeFunction('my-module', 'add');
console.log(desc); // { name, description, parameters, returnType, example }
// v1.4.0: Get module metadata
const metadata = gowm.getModuleMetadata('my-module');
console.log(metadata.name, metadata.version);
// Get version info
console.log('GoWM version:', gowm.getVersion());
// Get statistics for all loaded modules
const stats = gowm.getStats();
Object.entries(stats).forEach(([name, stat]) => {
console.log(`${name}: ${stat.functions.length} functions, metadata: ${stat.hasMetadata}`);
});
// Unload all modules when done
gowm.unloadAll();Creating GoWM-Compatible WASM Modules
Build Go WASM modules that work seamlessly with GoWM
Basic Module Structure
A GoWM-compatible WASM module must follow specific patterns for function registration and initialization:
//go:build js && wasm
package main
import (
"fmt"
"syscall/js"
)
var silentMode = false
// setSilentMode enables/disables console output
func setSilentMode(this js.Value, args []js.Value) interface{} {
if len(args) == 1 {
silentMode = args[0].Bool()
}
return js.ValueOf(silentMode)
}
// Example function: add two numbers
func add(this js.Value, args []js.Value) interface{} {
if len(args) != 2 {
return js.ValueOf("Error: two arguments required for add")
}
a := args[0].Float()
b := args[1].Float()
result := a + b
if !silentMode {
fmt.Printf("Go WASM: %f + %f = %f\n", a, b, result)
}
return js.ValueOf(result)
}
// getAvailableFunctions returns list of available functions
func getAvailableFunctions(this js.Value, args []js.Value) interface{} {
functions := []interface{}{
"add", "setSilentMode", "getAvailableFunctions",
}
return js.ValueOf(functions)
}
func main() {
fmt.Println("Go WASM Module initializing...")
// Register functions on global scope
js.Global().Set("add", js.FuncOf(add))
js.Global().Set("setSilentMode", js.FuncOf(setSilentMode))
js.Global().Set("getAvailableFunctions", js.FuncOf(getAvailableFunctions))
// Signal readiness for GoWM (important!)
js.Global().Set("__gowm_ready", js.ValueOf(true))
fmt.Println("Go WASM Module ready!")
// Keep the program alive
select {}
}Required Functions & Patterns
Essential Functions
- •
getAvailableFunctions()- Returns array of function names - •
setSilentMode(bool)- Controls console output - •
__gowm_ready- Global flag indicating module is ready
Function Signature Pattern
func myFunction(this js.Value, args []js.Value) interface{} {
// 1. Validate arguments
if len(args) != expectedCount {
return js.ValueOf("Error: description")
}
// 2. Extract and convert arguments
param1 := args[0].Float()
param2 := args[1].String()
// 3. Perform operation
result := doSomething(param1, param2)
// 4. Optional logging (respect silentMode)
if !silentMode {
fmt.Printf("Operation result: %v\n", result)
}
// 5. Return js.Value
return js.ValueOf(result)
}Building Your Module
Using the Integrated WASM Manager (Recommended)
The wasm-modules-repository includes a high-performance Go-based build system with parallel processing:
# Clone the wasm-modules-repository
git clone https://github.com/benoitpetit/wasm-modules-repository.git
cd wasm-modules-repository
# Setup the build manager
make setup
# Build all modules with parallel processing
./wasm-manager build
# Build specific module
./wasm-manager build math-wasm
# Build with custom worker count
./wasm-manager build --workers 8
# Build with optimizations (default)
./wasm-manager build --optimize
# Build without compression
./wasm-manager build --compress=false
# Validate module structure
./wasm-manager validate math-wasm
# Test module functionality
./wasm-manager test math-wasmManual Build Commands
# Basic build command
GOOS=js GOARCH=wasm go build -o main.wasm main.go
# Optimized build (recommended)
GOOS=js GOARCH=wasm go build -ldflags="-s -w" -o main.wasm main.go
# Using TinyGo for smaller binaries
tinygo build -o main.wasm -target wasm -no-debug main.go
# Build with wasm-opt optimization (if available)
wasm-opt -Oz main.wasm -o main.wasmAdvanced Features
// Error handling with structured responses
func processData(this js.Value, args []js.Value) interface{} {
if len(args) != 1 {
return js.ValueOf(map[string]interface{}{
"error": "Invalid arguments",
"code": "INVALID_ARGS",
})
}
data := args[0].String()
result, err := complexOperation(data)
if err != nil {
return js.ValueOf(map[string]interface{}{
"error": err.Error(),
"code": "PROCESSING_ERROR",
})
}
return js.ValueOf(map[string]interface{}{
"success": true,
"data": result,
"size": len(result),
})
}
// Memory management helpers
func allocateBuffer(this js.Value, args []js.Value) interface{} {
size := int(args[0].Float())
// Allocate and return pointer for GoWM memory management
return js.ValueOf(size) // Simplified example
}
// Callback registration for async operations
func registerCallback(this js.Value, args []js.Value) interface{} {
callback := args[0]
// Store callback for later use
storedCallbacks = append(storedCallbacks, callback)
return js.ValueOf("callback registered")
}Testing Your Module
// test-module.js
import { load } from 'gowm';
async function testModule() {
try {
// Load your module
const module = await load('./main.wasm', { name: 'my-module' });
// Test basic functionality
console.log('Available functions:', module.call('getAvailableFunctions'));
// Test silent mode
module.call('setSilentMode', true);
// Test your functions
const result = module.call('add', 5, 3);
console.assert(result === 8, 'Add function should return 8');
// Test error handling
const error = module.call('add', 5); // Missing argument
console.assert(typeof error === 'string' && error.includes('Error'), 'Should return error message');
console.log('✅ All tests passed!');
} catch (error) {
console.error('❌ Test failed:', error);
}
}
testModule();WASM Manager Features
Parallel Processing
- • Configurable worker pools
- • Auto-detects CPU cores
- • 5-10x faster builds
- • Error isolation per module
Advanced Optimizations
- • WASM-opt integration
- • Gzip/Brotli compression
- • Integrity hash generation
- • Size analysis reporting
Validation & Testing
- • Module structure validation
- • Function compliance checks
- • Metadata verification
- • Automated testing
Build Management
- • Module auto-discovery
- • Clean build support
- • Build artifact management
- • Comprehensive reporting
Best Practices
- • Use the integrated wasm-manager for production builds
- • Always validate function arguments and return descriptive errors
- • Implement
getAvailableFunctions()andsetSilentMode() - • Set
__gowm_ready = truewhen module is initialized - • Use structured error responses with error codes
- • Keep the main goroutine alive with
select - • Test your module with GoWM before deployment
- • Validate module structure with
./wasm-manager validate
Troubleshooting
Common issues and solutions
GitHub Repository Not Found
If loading from GitHub fails, check:
- • Repository name and owner are correct
- • Branch or tag exists
- • Path to WASM file is correct
- • Repository is public or you have permissions
try {
const wasm = await loadFromGitHub('invalid/repo');
} catch (error) {
if (error.code === 'REPO_NOT_FOUND') {
console.log('Repository not found');
} else if (error.code === 'WASM_FILE_NOT_FOUND') {
console.log('WASM file not found in repository');
}
}WASM Memory Errors
For memory errors, try:
// Always free buffers manually
const buffer = wasm.createBuffer(data);
// ... use buffer
buffer.free(); // Important!
// Monitor memory usage
const stats = wasm.getStats();
console.log('Memory used:', stats.memoryUsage, 'bytes');
// Get total memory usage across all modules
const totalMemory = getTotalMemoryUsage();
console.log(`Total WASM memory: ${totalMemory} bytes`);Function Not Found
Check that the function exists in the module:
// List available functions
const functions = wasm.getAvailableFunctions();
console.log('Available functions:', functions);
// Check if function exists
if (wasm.hasFunction('myFunction')) {
const result = wasm.call('myFunction', args);
} else {
console.error('Function myFunction not found');
}Performance Issues
Best practices for optimal performance:
- • Use module sharing across components
- • Enable debug mode during development
- • Configure cache TTL and priority based on usage
- • Use async functions for heavy computations
- • Monitor memory usage regularly