WebAssembly 2.0.0

dotnet add package WebAssembly --version 2.0.0
                    
NuGet\Install-Package WebAssembly -Version 2.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="WebAssembly" Version="2.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="WebAssembly" Version="2.0.0" />
                    
Directory.Packages.props
<PackageReference Include="WebAssembly" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add WebAssembly --version 2.0.0
                    
#r "nuget: WebAssembly, 2.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package WebAssembly@2.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=WebAssembly&version=2.0.0
                    
Install as a Cake Addin
#tool nuget:?package=WebAssembly&version=2.0.0
                    
Install as a Cake Tool

WebAssembly for .NET

NuGet

WebAssembly 2.0 is supported. WASM files that target a higher version may encounter errors.

A library able to create, read, modify, write, execute WebAssembly (WASM) files from .NET-based applications. It can also convert WASM files to .NET DLLs. Execution does not use an interpreter or a 3rd party library: WASM instructions are mapped to their .NET equivalents and converted to native machine language by the .NET JIT compiler.

Available on NuGet at https://www.nuget.org/packages/WebAssembly .

Getting Started

  • Use the WebAssembly.Module class to create, read, modify, and write WebAssembly (WASM) binary files.
    • Module.ReadFromBinary reads a stream into an instance, which can then be inspected and modified through its properties.
      • Files using ratified WebAssembly 2.0 features load fine; those using newer proposals may experience errors.
    • WriteToBinary on a module instance writes binary WASM to the provided stream.
  • Use the WebAssembly.Runtime.Compile class to execute WebAssembly (WASM) binary files using the .NET JIT compiler or convert it to a .NET DLL.
    • Most WASM files have many imports and exports--you'll need to cover these yourself.
    • This works for most WebAssembly 1.0 and 2.0 files, but spec compliance is not perfect.
    • Proposals newer than the ratified 2.0 standard aren't supported yet.
    • Saving to a DLL requires .NET 9 or higher and has several additional steps.

If you hit a problem, write a bug report with the repro steps and links to any files needed.

Sample: Create and execute a WebAssembly file in memory

using System;
using WebAssembly; // Acquire from https://www.nuget.org/packages/WebAssembly
using WebAssembly.Instructions;
using WebAssembly.Runtime;

// Module can be used to create, read, modify, and write WebAssembly files.
var module = new Module(); // In this case, we're creating a new one.

// Types are function signatures: the list of parameters and returns.
module.Types.Add(new WebAssemblyType // The first added type gets index 0.
{
    Parameters =
    [
        WebAssemblyValueType.Int32, // This sample takes a single Int32 as input.
        // Complex types can be passed by sending them in pieces.
    ],
    Returns =
    [
        // WebAssembly 2.0 multi-value allows more than one return; this library supports it.
        // This sample returns a single Int32.
        WebAssemblyValueType.Int32,
    ],
});
// Types can be re-used for multiple functions to reduce WASM size.

// The function list associates a function index to a type index.
module.Functions.Add(new Function // The first added function gets index 0.
{
    Type = 0, // The index for the "type" value added above.
});

// Code must be passed in the exact same order as the Functions above.
module.Codes.Add(new FunctionBody
{
    Code =
    [
        new LocalGet(0), // The parameters are the first locals, in order.
        // We defined the first parameter as Int32, so now an Int32 is at the top of the stack.
        new Int32CountOneBits(), // Returns the count of binary bits set to 1.
        // It takes the Int32 from the top of the stack, and pushes the return value.
        // So, in the end, there is still a single Int32 on the stack.
        new End(), // All functions must end with "End".
        // The final "End" also delivers the returned value.
    ],
});

// Exports enable features to be accessed by external code.
// Typically this means JavaScript, but this library adds .NET execution capability, too.
module.Exports.Add(new Export
{
    Kind = ExternalKind.Function,
    Index = 0, // This should match the function index from above.
    Name = "Demo", // Anything legal in Unicode is legal in an export name.
});

// We now have enough for a usable WASM file, which we could save with module.WriteToBinary().
// Below, we show how the Compile feature can be used for .NET-based execution.
// For stream-based compilation, WebAssembly.Compile should be used.
var instanceCreator = module.Compile<Sample>(); // Sample is defined later.

// Instances should be wrapped in a "using" block for automatic disposal.
// This sample doesn't import anything, so we pass an empty import dictionary.
using (var instance = instanceCreator(new ImportDictionary()))
{
    // FYI, instanceCreator can be used multiple times to create independent instances.
    Console.WriteLine(instance.Exports.Demo(0)); // Binary 0, result 0
    Console.WriteLine(instance.Exports.Demo(1)); // Binary 1, result 1,
    Console.WriteLine(instance.Exports.Demo(42));  // Binary 101010, result 3
} // Automatically release the WebAssembly instance here.

public abstract class Sample
{
    // Sometimes you can use C# dynamic instead of building an abstract class like this.
    public abstract int Demo(int value);
}

Sample: Convert a WASM file to a .NET DLL

This feature is experimental.

The saving process uses the PersistedAssemblyBuilder feature introduced in .NET 9. Aided by MetadataLoadContext, this example produces a DLL for .NET 8.

var resolver = new PathAssemblyResolver([
    // A core DLL containing System.String and other basic features (add sibling ref assemblies from this folder if resolution fails):
    "C:\\Program Files\\dotnet\\packs\\Microsoft.NETCore.App.Ref\\8.0.0\\ref\\net8.0\\System.Runtime.dll",
    // One way or another you'll need a reference to the matching WebAssembly.dll built against the core DLL.
    "C:\\dotnet-webassembly\\WebAssembly\\bin\\Release\\net8.0\\WebAssembly.dll"
    ]);
using var context = new MetadataLoadContext(resolver);

const string name = "HelloWorld"; // Name components should match.

var assembly = Compile.CreatePersistedAssembly(
    File.OpenRead("HelloWorld.wasm"), // This is part of the "RunExisting" sample.
    new(
        context.CoreAssembly,
        resolver.Resolve(context, new("WebAssembly")),
        new(name),
        $"{name}.dll"
        )
    {
        // The type name includes the namespace.
        // If not set, defaults to WebAssembly.CompiledFromWasm.
        TypeName = "Converted.HelloWorld"
    }
    );

assembly.Save($"{name}.dll");

To use the new DLL, you directly reference it in your .csproj.

<ItemGroup>
  <Reference Include="HelloWorld">
    <HintPath>bin\HelloWorld.dll</HintPath> 
  </Reference>
</ItemGroup>

Once the DLL reference is in place, you can access it just like any other .NET library.

var helloWorld = new Converted.HelloWorld((module, field) =>
{
    // Imports are defined by the original WASM and must be supplied by you.
    if (module == "env" && field == "sayc")
        return new FunctionImport(new Action<int>(raw => Console.Write((char)raw)));

    throw new Exception($"Unknown import: {module} {field}");
});

// You can directly access anything exported by the WASM.
var result = helloWorld.main();

Other Information

Product Compatible and additional computed target framework versions.
.NET 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 is compatible.  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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net8.0

    • No dependencies.
  • net9.0

    • No dependencies.

NuGet packages (4)

Showing the top 4 NuGet packages that depend on WebAssembly:

Package Downloads
ConcordiumNetSdk

A .NET integration library written in C# which adds support for constructing and sending various transactions, as well as querying various aspects of the Concordium blockchain and its nodes. This SDK uses version 2 of the Concordium Node gRPC API to interact with Concordium nodes and in turn the Concordium blockchain.

Backlang.Backends.Wasm

A backend for backlang for the bs2k emulation system

WebAssembly.FSharp

Provides an idiomatic F# WebAssembly module generation toolkit around the base WebAssembly package.

Microsoft.CST.OSSGadget.Shared.CLI

OSS Gadget - Shared CLI Functionality

GitHub repositories (1)

Showing the top 1 popular GitHub repositories that depend on WebAssembly:

Repository Stars
microsoft/OSSGadget
Collection of tools for analyzing open source packages.
Version Downloads Last Updated
2.0.0 35 6/21/2026
1.3.0 1,145 4/20/2025
1.2.1 30,056 8/14/2022
1.2.0 8,889 5/24/2021
1.1.0 635 5/16/2021
1.0.0 599 4/24/2021
0.11.0 1,112 2/15/2021
0.10.2-preview 430 1/31/2021
0.10.1-preview 542 12/26/2020
0.10.0-preview 520 10/3/2020
0.9.0-preview 1,306 6/13/2020
0.8.0-preview 1,965 12/8/2019
0.7.1-preview 848 8/4/2019
0.7.0-preview 590 7/27/2019
0.6.0-preview 615 7/4/2019
0.5.0-preview 633 7/1/2019
0.4.0-preview 627 6/24/2019
0.3.8-preview 676 5/26/2019
0.3.7-preview 757 2/10/2019
0.3.6-preview 748 2/3/2019
Loading failed

Full support for creation, modification, execution, and conversion of WASM 2.0 files.