WACS.WASI.Preview1
0.13.0
dotnet add package WACS.WASI.Preview1 --version 0.13.0
NuGet\Install-Package WACS.WASI.Preview1 -Version 0.13.0
<PackageReference Include="WACS.WASI.Preview1" Version="0.13.0" />
<PackageVersion Include="WACS.WASI.Preview1" Version="0.13.0" />
<PackageReference Include="WACS.WASI.Preview1" />
paket add WACS.WASI.Preview1 --version 0.13.0
#r "nuget: WACS.WASI.Preview1, 0.13.0"
#:package WACS.WASI.Preview1@0.13.0
#addin nuget:?package=WACS.WASI.Preview1&version=0.13.0
#tool nuget:?package=WACS.WASI.Preview1&version=0.13.0
WACS.WASI.Preview1
A C# implementation of WASI Preview 1 for the WACS WebAssembly
Interpreter. Supersedes the deprecated WACS.WASIp1 package — see
docs/MIGRATION_WASIp1_to_WASI.md
for a one-shot sed migration.
Installation
Add the package from NuGet:
dotnet add package WACS.WASI.Preview1
Usage example
Bind WASI Preview 1 to a WasmRuntime:
using System;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Wacs.Core;
using Wacs.Core.Runtime;
using Wacs.Core.WASIp1; // IBindable, ErrNo, SystemExitException, SignalException
using Wacs.WASI.Preview1; // Wasi, WasiConfiguration
using Wacs.WASI.Preview1.Types; // FdFlags, etc.
var runtime = new WasmRuntime();
var wasiConfig = new WasiConfiguration
{
StandardInput = Console.OpenStandardInput(),
StandardOutput = Console.OpenStandardOutput(),
StandardError = Console.OpenStandardError(),
Arguments = Environment.GetCommandLineArgs()
.Skip(1)
.ToList(),
EnvironmentVariables = Environment.GetEnvironmentVariables()
.Cast<DictionaryEntry>()
.ToDictionary(de => de.Key.ToString()!, de => de.Value?.ToString() ?? ""),
HostRootDirectory = Directory.GetCurrentDirectory(),
};
var wasi = new Wasi(wasiConfig);
wasi.BindToRuntime(runtime);
using var fileStream = new FileStream("module.wasm", FileMode.Open);
var module = BinaryModuleParser.ParseWasm(fileStream);
var modInst = runtime.InstantiateModule(module);
runtime.RegisterModule("mymodule", modInst);
if (runtime.TryGetExportedFunction(("mymodule", "main"), out var mainAddr))
{
try
{
var mainInvoker = runtime.CreateInvoker<Func<Value>>(mainAddr);
int result = mainInvoker();
Console.Error.WriteLine($"mymodule.main() => {result}");
}
catch (TrapException exc)
{
Console.Error.WriteLine(exc);
return 1;
}
catch (SignalException exc)
{
Console.Error.WriteLine(exc.HumanReadable);
return exc.Signal;
}
}
The split between Wacs.Core.WASIp1 (interpreter wiring — IBindable,
ErrNo, exceptions) and Wacs.WASI.Preview1 (host implementation —
Wasi, WasiConfiguration) is intentional. Migrating from
WACS.WASIp1 only changes the second using; the Wacs.Core.WASIp1
namespace stays.
Capability flags
WasiConfiguration exposes a few opt-in capability gates beyond the
filesystem preopens:
| Flag | Default | What it enables |
|---|---|---|
AllowFileCreation |
false |
path_open(O_CREAT) and path_create_directory |
AllowFileDeletion |
false |
path_unlink_file and path_remove_directory |
AllowSymbolicLinks |
false |
path_symlink (creates real host symlinks via File.CreateSymbolicLink) |
AllowHardLinks |
false |
path_link (P/Invoke link(2) on Unix, CreateHardLinkW on Windows) |
AllowTimeAccess |
true |
clock_time_get and clock_res_get |
AllowNetworkSockets |
false |
Preopened sockets (see below) |
PreopenHostRootDirectory |
true |
Auto-binds HostRootDirectory as a preopen at fd 3 (legacy Wacs.Console behavior; flip false to follow the wasmtime convention where fd 3 is the first explicit preopen) |
Network sockets
WASI Preview 1's socket surface is intentionally narrow: there is no
sock_open / sock_bind / sock_listen. Listening sockets are
handed in by the embedder as preopens (the same model wasmtime serve
uses for HTTP), and sock_accept mints connection fds from them.
using System.Net;
using System.Net.Sockets;
using Wacs.WASI.Preview1;
using Wacs.WASI.Preview1.Types;
var listener = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
listener.Bind(new IPEndPoint(IPAddress.Loopback, 0));
listener.Listen(8);
var wasiConfig = new WasiConfiguration
{
HostRootDirectory = Directory.GetCurrentDirectory(),
AllowNetworkSockets = true,
PreopenedSockets = { (listener, FdFlags.NonBlock) },
};
The guest's accept(3) on fd 3 (after stdio at 0/1/2) will produce a
working TCP connection. Two layers of explicit consent before any
network egress: the flag must be on AND the embedder must have
already constructed and bound the Socket.
Conformance
Tested continuously against the official
WebAssembly/wasi-testsuite
fixtures via Wacs.WASI.Preview1.Test. The harness reads each test's
*.json manifest, runs the wasm under WACS with the prescribed
preopens / args / env, and asserts on exit code + stdout + stderr. The
test project's skip.json documents which conformance fixtures are
deliberately not yet asserting (each entry carries a reason).
License
WACS is distributed under the Apache 2.0 License, allowing usage in both open-source and commercial projects.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.1 is compatible. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.1
- WACS (>= 0.13.7)
- WACS.HostBindings.Abstractions (>= 0.3.0)
-
net8.0
- WACS (>= 0.13.7)
- WACS.HostBindings.Abstractions (>= 0.3.0)
NuGet packages (2)
Showing the top 2 NuGet packages that depend on WACS.WASI.Preview1:
| Package | Downloads |
|---|---|
|
WACS.WASIp1
DEPRECATED. This package has been renamed to WACS.WASI.Preview1 (consolidating with WACS.WASI.Preview2 under one namespace prefix). It is now a metapackage that pulls in WACS.WASI.Preview1 transitively. Existing <PackageReference Include="WACS.WASIp1" /> entries still resolve, but consumer code must update its `using Wacs.WASIp1;` lines to `using Wacs.WASI.Preview1;`. |
|
|
WACS.Transpiler.Lib
Library API for WACS.Transpiler — programmatic ahead-of-time WebAssembly-to-.NET IL transpilation, plus seamless loading of saved transpiled assemblies. v0.7.2 fixes a re-instantiation bug where Module classes with active data segments would come up zeroed on the second `Activator.CreateInstance` because spec §4.5.4 segment-drop emptied the process-wide ModuleInit registry. Module ctors now restore from `ModuleInitData.SavedDataSegments` before each CopyDataSegment so every fresh instance sees its memory initialized. v0.7 retires Lokad.ILPack for PersistedAssemblyBuilder (.NET 9), moves WASM data segments + the codec blob to RVA-mapped initialized data (62.5% smaller than the prior base64-in-#US path, true zero-copy from PE pages to ModuleInitData via UnmanagedMemoryStream), and introduces EmissionTarget.Auto as the new default — promotes to AotLinked when the module fits a conservative envelope (compute / memory / globals / tables + active+passive segments / multi-memory / local tags / imported functions), falling back to Standard otherwise. ~50% first-trial cold-start cut on promoted modules. ImportDispatcher now throws on missing handlers by default (lenient: true opts out). v0.6 consumed the Branch Hinting proposal's metadata.code.branch_hint custom section. v0.5 added the AotLinked emission target, stable AssemblyName, and the [WacsTranspiledImports] / [WacsImportNames] emission used by WACS.HostBindings.SourceGen. |
GitHub repositories
This package is not used by any popular GitHub repositories.