Last active
September 14, 2025 08:42
-
-
Save anonhostpi/e33c2fb4e3282ff75962cf12a2a9af6a to your computer and use it in GitHub Desktop.
How to do wasm in powershell
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # 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