GoWM Navigation

GoWM - Enterprise Manager

v1.2.0 - 206/206 tests ✅

Cache Active

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

View on npm
bash
npm install gowm
bash
yarn add gowm
bash
pnpm add gowm

Quick Start

Basic usage examples with real function calls

javascript
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

javascript
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

javascript
// 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. 1. Specified path/filename
  2. 2. Module-specific paths
  3. 3. Root directory files
  4. 4. Common build folders
  5. 5. GitHub releases
  6. 6. Recursive search

Common Patterns

  • {name}/main.wasm
  • main.wasm, index.wasm
  • wasm/, dist/, build/
  • {repo-name}.wasm
  • • Release assets

Repository Format Support

javascript
// 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

javascript
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:

javascript
// 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:

javascript
// 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:

javascript
// 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:

javascript
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:

javascript
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:

javascript
// 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:

javascript
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:

javascript
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.

javascript
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.

javascript
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.

javascript
const module = get('my-module');
if (module) {
  const result = module.call('function', arg1, arg2);
}

unload(name)

Unloads a module and cleans up its resources.

javascript
const success = await unload('my-module');
console.log('Module unloaded:', success);

WasmBridge Methods

call(funcName, ...args)

Calls a WASM function synchronously.

javascript
const result = wasm.call('add', 5, 3);
const data = wasm.call('processData', buffer.ptr, buffer.size);

callAsync(funcName, ...args)

Calls a WASM function asynchronously.

javascript
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.

javascript
const buffer = wasm.createBuffer(new Float64Array([1, 2, 3]));
console.log('Buffer:', buffer.size, 'bytes');
buffer.free(); // Always release memory

call("getAvailableFunctions")string[]

Returns a list of all available functions via WASM call method.

javascript
const functions = wasm.call(&apos;getAvailableFunctions&apos;);
console.log(&apos;Available functions:&apos;, functions);
// Example: [&apos;add&apos;, &apos;multiply&apos;, &apos;setSilentMode&apos;, &apos;getAvailableFunctions&apos;]

call("getAvailableFunctions") → Check Functions

Check if a function exists by listing available functions.

javascript
const functions = wasm.call(&apos;getAvailableFunctions&apos;);
if (functions.includes(&apos;optionalFeature&apos;)) {
  const result = wasm.call(&apos;optionalFeature&apos;, data);
}

getStats()ModuleStats

Returns detailed statistics about the module. In v1.4.0, includes metadata information.

javascript
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.

javascript
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).

javascript
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.

javascript
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).

javascript
wasm.registerCallback('logMessage', (message) => {
  console.log('From WASM:', message);
});

// WASM can now call logMessage(&apos;Hello from Go!&apos;)

cleanup()void

Manually cleans up module resources.

javascript
// Called automatically, but can be called manually
wasm.cleanup();

Management Functions

isLoaded(name)boolean | Promise<boolean>

Checks if a module is currently loaded.

javascript
// 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.

javascript
const modules = await listModules();
console.log('Loaded modules:', modules);

getStats()Promise<Record<string, ModuleStats>>

Returns statistics for all loaded modules.

javascript
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.

javascript
const totalMemory = await getTotalMemoryUsage();
console.log(`Total WASM memory: ${totalMemory} bytes`);

unloadAll()Promise<void>

Unloads all modules and cleans up resources.

javascript
await unloadAll(); // Clean slate

Core API Methods

loadFromGitHub(repo, options)Promise<WasmBridge>

Load a WASM module from GitHub repository with automatic file discovery.

javascript
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.

javascript
// 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');            // File

Framework 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 (false or { 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

javascript
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

javascript
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

javascript
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
//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

go
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:

bash
# 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-wasm

Manual Build Commands

bash
# 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.wasm

Advanced Features

go
// 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

javascript
// 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() and setSilentMode()
  • • Set __gowm_ready = true when 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
javascript
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:

javascript
// 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:

javascript
// 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