Skip to content

Instantly share code, notes, and snippets.

@anonhostpi
Last active September 14, 2025 08:42
Show Gist options
  • Select an option

  • Save anonhostpi/e33c2fb4e3282ff75962cf12a2a9af6a to your computer and use it in GitHub Desktop.

Select an option

Save anonhostpi/e33c2fb4e3282ff75962cf12a2a9af6a to your computer and use it in GitHub Desktop.
How to do wasm in powershell
# iex (iwr 'https://gist.github.com/anonhostpi/e33c2fb4e3282ff75962cf12a2a9af6a/raw/wasm.ps1').content
& {
# Install-Module "Wasmtime"
$package = Get-Package -Name "Wasmtime"
$directory = $package.Source | Split-Path
$runtime = "win-x64" # "win/linux/osx-arm64/x64"
$native = "$directory\runtimes\$runtime\native" | Resolve-Path
$env:PATH += ";$native"
Add-Type -Path "$directory\lib\netstandard2.1\Wasmtime.Dotnet.dll"
}
function New-WasmEngine {
[CmdletBinding()]
param(
[Parameter(ValueFromPipeline=$true)]
[Wasmtime.Config] $config = $null
)
If ($null -eq $config) {
return [Wasmtime.Engine]::new()
} else {
return [Wasmtime.Engine]::new($config)
}
}
function ConvertTo-Wasm {
[CmdletBinding()]
param(
[Parameter(Mandatory=$true, ValueFromPipeline=$true)]
[string] $Text
)
return [Wasmtime.Module]::ConvertText($Text)
}
function New-WasmModule {
[CmdletBinding(DefaultParameterSetName='InputObject')]
param (
[Parameter(Mandatory=$true)]
[Wasmtime.Engine] $Engine,
[Parameter(ParameterSetName='InputObject', Mandatory=$true)]
[string] $Name,
[Parameter(ParameterSetName='InputObject', Mandatory=$true, ValueFromPipeline=$true)]
$Input,
[Parameter(ParameterSetName='InputObject')]
[switch] $Binary, # Default is .wat (text)
[Parameter(ParameterSetName='InputObject')]
[switch] $Stream,
[Parameter(ParameterSetName='File', Mandatory=$true, ValueFromPipeline=$true)]
[string] $Path,
[Parameter(ParameterSetName='File')]
[switch] $Text # Default is .wasm (binary)
)
switch ($PSCmdlet.ParameterSetName) {
'InputObject' {
If($Binary) {
If($Stream) {
return [Wasmtime.Module]::FromStream($Engine, $Name, $Input)
}
return [Wasmtime.Module]::FromBytes($Engine, $Name, $Input)
} Else {
If($Stream) {
return [Wasmtime.Module]::FromTextStream($Engine, $Name, $Input)
}
return [Wasmtime.Module]::FromText($Engine, $Name, $Input)
}
}
'File' {
If($Text) {
return [Wasmtime.Module]::FromFileText($Engine, $Path)
} Else {
return [Wasmtime.Module]::FromFile($Engine, $Path)
}
}
}
}
function New-WasmLinker {
[CmdletBinding()]
param(
[Parameter(Mandatory=$true, ValueFromPipeline=$true)]
[Wasmtime.Engine] $Engine
)
return [Wasmtime.Linker]::new($Engine)
}
function New-WasmStore {
[CmdletBinding()]
param(
[Parameter(Mandatory=$true, ValueFromPipeline=$true)]
[Wasmtime.Engine] $Engine,
[System.Object] $Context = $Null
)
If($null -eq $Context){
return [Wasmtime.Store]::new($Engine)
} else {
return [Wasmtime.Store]::new($Engine, $Context)
}
}
# NOTE: does not support return values. To return values, declare the function explicitly!
function New-WasmFunction {
[CmdletBinding()]
param(
[Parameter(Mandatory=$true)]
[Wasmtime.Store] $Store,
[Parameter(Mandatory=$true, ValueFromPipeline=$true)]
[scriptblock] $Callback,
[Type[]] $Parameters = (&{
$callback.Ast.ParamBlock.Parameters.StaticType
})
)
$cb = If($Parameters.Count -gt 0) {
"[System.Action[$(($Parameters | ForEach-Object { $_.FullName }) -join ',')]] `$Callback"
} Else {
"[System.Action] `$Callback"
}
return [Wasmtime.Function]::FromCallback($Store, (Invoke-Expression $cb))
}
$engine = New-WasmEngine
$linker = New-WasmLinker -Engine $engine
$store = New-WasmStore -Engine $engine # -Context @{}
$import = @{
"say" = @{
"hello" = {
Write-Host "Hello, world!"
}
}
}
$signatures = @()
$import.GetEnumerator() | ForEach-Object {
$from = $_.Key
$_.Value.GetEnumerator() | ForEach-Object {
$name = $_.Key
$function = New-WasmFunction -Store $store -Callback $_.Value
$linker.Define($from, $name, $function)
$signatures += "$from.$name"
}
}
$module = & {
$labels = @()
$functions = $signatures | ForEach-Object {
$from, $name = $_ -split '\.'
$label = '$' + (@($from, $name) -join '_')
$labels += $label
return "(func $label (import `"$from`" `"$name`"))"
}
$calls = & {
$result = @()
$labels | ForEach-Object {
$result += "(call $_)"
}
return $result -join " "
}
$run = "(func (export `"run`") $calls)"
$functions = @($functions, $run)
return "(module $($functions -join " "))"
}
$module = $module | New-WasmModule -Engine $engine -Name "Main"
$module_instance = $linker.Instantiate($store, $module)
$module_instance.GetFunction("run").Invoke()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment