WebAssembly Modules
WebAssembly modules are the fundamental unit of code in WebAssembly. This guide covers module creation, validation, introspection, and management.
Module Basics
Creating Modules
From Bytes
# Read WebAssembly binary
wasm_bytes = read("module.wasm")
module_obj = WasmModule(engine, wasm_bytes)
From WebAssembly Text (WAT) (✅ Working Feature)
# WAT to WASM conversion is implemented and working
wat_content = """
(module
(func $add (param $x i32) (param $y i32) (result i32)
local.get $x
local.get $y
i32.add)
(export "add" (func $add)))
"""
# Convert WAT to WASM bytes
wasm_bytes = wat2wasm(wat_content)
module_obj = WasmModule(engine, wasm_bytes)
From File Path (File Reading)
# Read file and create module
wasm_bytes = read("path/to/module.wasm")
module_obj = WasmModule(engine, wasm_bytes)
Module Properties
module_obj = WasmModule(engine, wasm_bytes)
# Check validity
isvalid(module_obj) # Returns true if module is valid
# Access underlying engine
module_obj.engine === engine # true
Module Validation
Validating WebAssembly Bytes
Before creating a module, validate the WebAssembly bytes:
engine = WasmEngine()
wasm_bytes = read("module.wasm")
# Validate before creating module
if validate(engine, wasm_bytes)
module_obj = WasmModule(engine, wasm_bytes)
println("Module is valid!")
else
println("Invalid WebAssembly bytes")
end
Validation Behavior
# Valid empty module
empty_wasm = UInt8[0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00]
validate(engine, empty_wasm) # true
# Invalid bytes
invalid_wasm = UInt8[0x00, 0x00, 0x00, 0x00]
validate(engine, invalid_wasm) # false
# Empty bytes
validate(engine, UInt8[]) # false
Module Introspection
Exports (🚧 Partial Implementation)
Query what the module exports:
module_obj = WasmModule(engine, wasm_bytes)
module_exports = exports(module_obj)
# Currently returns Dict{String, Any}() - placeholder data
# Full export introspection planned for future release
Imports (🚧 Partial Implementation)
Query what the module requires as imports:
module_imports = imports(module_obj)
# Currently returns Dict{String, Any}() - placeholder data
# Full import introspection planned for future release
Module Structure (🚧 Limited)
# Basic module information (returns placeholder data)
println("Module exports: ", length(exports(module_obj))) # Currently 0
println("Module imports: ", length(imports(module_obj))) # Currently 0
Module Lifecycle
Creation and Memory Management
Modules are automatically memory-managed:
function create_module()
engine = WasmEngine()
wasm_bytes = read("module.wasm")
return WasmModule(engine, wasm_bytes)
end
module_obj = create_module()
# Module and engine are cleaned up when GC'd
Module Reuse
Modules can be instantiated multiple times:
engine = WasmEngine()
module_obj = WasmModule(engine, wasm_bytes)
# Create multiple instances
store1 = WasmStore(engine)
store2 = WasmStore(engine)
instance1 = Instance(store1, module_obj)
instance2 = Instance(store2, module_obj)
# Each instance has separate state
Sharing Across Engines
Modules are tied to their engine:
engine1 = Engine()
engine2 = Engine()
module_obj = WasmModule(engine1, wasm_bytes)
# This works - same engine
store1 = Store(engine1)
instance1 = Instance(store1, module_obj)
# This would fail - different engine
store2 = Store(engine2)
# instance2 = Instance(store2, module_obj) # Error!
Error Handling
Module Creation Errors
try
# Invalid WebAssembly bytes
invalid_bytes = UInt8[0x00, 0x00, 0x00, 0x00]
module_obj = WasmModule(engine, invalid_bytes)
catch e::WasmtimeError
println("Failed to create module: $(e.message)")
end
File System Errors
try
# Non-existent file
module_obj = WasmModule(engine, "nonexistent.wasm")
catch e::SystemError
println("File not found: $(e.msg)")
end
try
# File with invalid content
module_obj = WasmModule(engine, "invalid_file.txt")
catch e::WasmtimeError
println("Invalid WebAssembly content: $(e.message)")
end
Validation Errors
# Safe module creation with validation
function safe_create_module(engine, bytes_or_path)
try
if isa(bytes_or_path, String)
# File path
bytes = read(bytes_or_path)
else
# Byte array
bytes = bytes_or_path
end
if !validate(engine, bytes)
throw(WasmtimeError("Invalid WebAssembly module"))
end
return WasmModule(engine, bytes)
catch e
rethrow(e)
end
end
Advanced Module Operations
Module Compilation Performance
# For better performance, reuse engines
engine = Engine(Config(optimization_level = SpeedAndSize))
# Compile multiple modules with the same engine
modules = []
for wasm_file in ["module1.wasm", "module2.wasm", "module3.wasm"]
push!(modules, WasmModule(engine, wasm_file))
end
Module Caching Pattern
# Simple module cache
module_cache = Dict{String, WasmModule}()
function get_module(engine, file_path)
if haskey(module_cache, file_path)
return module_cache[file_path]
else
module_obj = WasmModule(engine, file_path)
module_cache[file_path] = module_obj
return module_obj
end
end
Batch Module Processing
function process_modules(engine, wasm_files)
results = []
for file in wasm_files
try
# Validate first
bytes = read(file)
if validate(engine, bytes)
module_obj = WasmModule(engine, bytes)
push!(results, (file, module_obj, :success))
else
push!(results, (file, nothing, :invalid))
end
catch e
push!(results, (file, nothing, :error))
end
end
return results
end
WAT to WASM Conversion (Future)
The wat_to_wasm
function is planned but not yet implemented:
# Placeholder implementation
function convert_wat_when_available()
wat_content = """
(module
(func $hello (result i32)
i32.const 42)
(export "hello" (func $hello)))
"""
try
wasm_bytes = wat_to_wasm(wat_content)
return WasmModule(engine, wasm_bytes)
catch e::WasmtimeError
if occursin("not yet implemented", e.message)
println("WAT conversion not available yet")
return nothing
else
rethrow(e)
end
end
end
Best Practices
Module Creation
- Validate before creating: Always validate WebAssembly bytes
- Reuse engines: Share engines across multiple modules
- Handle errors gracefully: Wrap module creation in try-catch
- Cache compiled modules: Avoid recompiling the same module
Performance
- Use appropriate optimization: Configure engine optimization level
- Minimize module recreation: Reuse modules when possible
- Batch operations: Process multiple modules efficiently
Error Recovery
function robust_module_creation(engine, source)
# Try different creation methods
if isa(source, String) && isfile(source)
try
return WasmModule(engine, source)
catch e
@warn "Failed to load from file: $source" exception=e
end
end
if isa(source, Vector{UInt8})
if validate(engine, source)
try
return WasmModule(engine, source)
catch e
@warn "Failed to create from bytes" exception=e
end
else
@warn "Invalid WebAssembly bytes"
end
end
return nothing
end
Debugging Modules
Module Inspection
function inspect_module(module_obj)
println("Module validity: ", isvalid(module_obj))
println("Module pointer: ", module_obj.ptr)
println("Engine pointer: ", module_obj.engine.ptr)
# Introspection (when implemented)
exports_info = exports(module_obj)
imports_info = imports(module_obj)
println("Exports count: ", length(exports_info))
println("Imports count: ", length(imports_info))
end
Common Issues
- Module creation fails: Check WebAssembly bytes validity
- Engine mismatch: Ensure module and store use same engine
- File not found: Verify file paths and permissions
- Memory issues: Monitor module lifecycle and cleanup
The module system provides a robust foundation for WebAssembly execution while maintaining Julia's ease of use and safety guarantees.