ted.neward@newardassociates.com | Blog: http://blogs.newardassociates.com | Github: tedneward | LinkedIn: tedneward
Code: https://github.com/tedneward/Demo-WebAssembly
Slides: http://www.newardassociates.com/presentations/BusyDevsGuide/WebAssembly.html
Understand where WASM came from
Figure out how to get started with WASM
Examine some of the tools
Explore the specification
... a bytecode-inspired/influenced for browsers to execute
faster load
faster parse
faster resolution
better checking and verification
standardized across browsers
defined in text and binary format
intended as a target for language compilers/transpilers
accessible both in-browser and VMs (e.g., NodeJS)
Browsers already have JavaScript, so....
Was JavaScript not...
... fast enough?
... flexible enough?
... verbose enough?
Is WASM intended to replace JavaScript?
Did Web developers really have not enough to worry about?
Fast, safe, and portable semantics
fast, safe, open, well-defined, hardware-, language-, and platform-independent
Efficient and portable representation
compact, modular, efficient, streamable, parallelizable, and portable
(and easy to inspect and debug)
Source: http://www.webassembly.org
https://webassembly.org/docs/use-cases/ (The official list)
Code migration/interoperability
"legacy" code (C/C++, for example) migration
polyglot scenarios (mix-and-match languages)
Embedded use within applications (e.g., plugin host)
Performance: ehh....
It's not 1:1 with native execution (yet)
Does seem to be improving steadily
Definitely easier to optimize than JS constructs
slow
non-standard
"nothing like Java"
Sun debuted the "HotJava" browser
had everybody thinking "applets-to-CORBA-to-database"
applets had extremely weak UI support
Java had to be installed in the browser
Sun's battles with Microsoft split the industry
If you couldn't do it in HTML, don't do it
Server-side rendering was the only game in town
the struggle was real
"modern" Javascript usage starts to normalize the browsers
minor UI effects (animations, etc) begin to wake up our expectations
users are really, really, really tired of server round-trips
https://www.hanselman.com/blog/JavaScriptIsAssemblyLanguageForTheWebSematicMarkupIsDeadCleanVsMachinecodedHTML.aspx
browsers are ubiquitous
Javascript will never be replaced as the language of the browser
thus, target it as the output of compilation tools and such
"Project Volta" (discontinued in 2012)-- later IL2JS: https://github.com/Reactive-Extensions/IL2JS
"asm.js is a subset of JavaScript designed to allow computer software written in languages such as C to be run as web applications while maintaining performance characteristics considerably better than standard JavaScript, which is the typical language used for such applications." (Wikipedia)
targeted by Emscripten C/C++ toolchain
browsers could optimize execution by recognizing these operations
Mozilla supported this starting with v22 of their browser
involving numerous companies and Javascript luminaries
https://medium.com/javascript-scene/why-we-need-webassembly-an-interview-with-brendan-eich-7fb2a60b0723
supported in four major browsers
Chrome, IE/Edge, Mozilla, Safari
specification(s) released
Core (https://webassembly.github.io/spec/core/_download/WebAssembly.pdf)
JavaScript embedding (https://webassembly.github.io/spec/js-api/index.html)
Web embedding (https://webassembly.github.io/spec/web-api/index.html)
WASM 2.0: 16 June 2025
WASM 3.0: 7 July 2026
in other words, you usually won't write WASM "in the raw"
though, of course, you could
C/C++ (Emscripten)
gcc/g++ front-end
WASM-generating (HTML/JS) back-end
Zig (oh, fine, Rust too)
AssemblyScript (TypeScript-ish)
COBOL
others
browser is an obvious target
wasmtime
NodeJS
GraalVM
WABT ("wabbit")
brew install wabt
binaryen
brew install binaryen
A single module, expressed in "WAT"
Assembled into "WASM"
Executed using a command-line interpreter
... or with NodeJS
adder.wat: Export an add() function
(module
(func $add (param $a i32) (param $b i32) (result i64)
(i64.add
(i64.extend_i32_s (local.get $a))
(i64.extend_i32_s (local.get $b))
)
)
(export "add" (func $add))
)
main.wat: Call the exported add() function
(module
(import "adder" "add" (func $add (param i32 i32) (result i64)))
(func $start
;; Call the imported "add" function with 2 and 4
i32.const 2
i32.const 4
call $add
drop ;; Discard the result
)
(start $start)
(export "_start" (func $start))
)
Building
$ wat2wasm app.wat -o app.wasm
Running
$ wasm-interp app.wasm
Mainstream
languages you already know
languages you don't know but should
languages that wanna become mainstream
Adapters
adapting a language to the WASM environment
Academic/"Thought experiment"
you're never gonna use this
not in prod, anyway
but they have some interesting ideas
see https://github.com/wasmlang/awesome-wasm-langs
C/C++ (Emscripten, Cheerp)
Rust
Zig
Go / TinyGo (a subset of Go targeted to embedded devices and WASM)
AssemblyScript (a superset of TypeScript)
LLVM
Pyodide (Python compiled to WASM)
Blazor (.NET CLR compiled to WASM)
Lumen - an alternative BEAM (Erlang) implementation for WASM
https://github.com/lumen/lumen
Forest - a functional programming language that compiles to WebAssembly
https://github.com/forest-lang/core
Wase - a friendly, low-level language for Wasm
https://github.com/area9innovation/wase
... and really, about a billion more
really popular "new language" compilation target
... and a bunch more get support through LLVM
Browser: Javascript engine knows how to bind/call exported WASM functions
Node.js: V8 engine uses JS APIs to bind/call WASM functions
Rust: wasm_bindgen crate and attribute; extern function declarations
Other hosts/languages: YMMV
Given: adder.wasm
(module
(func $add (param $a i32) (param $b i32) (result i64)
(i64.add
(i64.extend_i32_s (local.get $a))
(i64.extend_i32_s (local.get $b))
)
)
(export "add" (func $add))
)
WASM Module instance contains exports map of exported functions
JS will attempt to match arguments to target parameters as best it can
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly
instantiate()/instantiateStreaming(): compile and instantiate WASM
returns both Module and Instance
compile()/compileStreaming(): compiles WASM code
returns Module; does not instantiate
validate(): validate given typed array as valid WASM binary
returns true/false
Module(): another way to create a module object
Instance(): represents a module instance (state)
Memory(): linear memory for use by WASM and JS
Table(): function tables for invocation
Global(): new global for use by WASM/JS
Run in an HTML page: runwat.html
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Run WebAssembly - Check the Console</title>
</head>
<body>
<script>
async function loadWasm() {
try {
const response = await WebAssembly.instantiateStreaming(
fetch('main.wasm')
);
const { _start, add } = response.instance.exports;
const result = add(5, 10);
console.log("Result from Wasm:", result);
} catch (error) {
console.error("Error loading WebAssembly:", error);
}
}
loadWasm();
</script>
</body>
</html>
Make sure to load via HTTP: python3 -m http.server 9000
Run at the CLI: runwat.js
import fs from 'node:fs/promises';
// Use readFile to read contents of the "add.wasm" file
const wasmBuffer = await fs.readFile('main.wasm');
// Use the WebAssembly.instantiate method to instantiate the WebAssembly module
const wasmModule = await WebAssembly.instantiate(wasmBuffer);
// Exported function lives under instance.exports object
const { _start, add } = wasmModule.instance.exports;
_start();
const sum = add(55, 66);
console.log(sum, (typeof sum));
$ node runwat.js
WebAssembly System Interface - https://wasi.dev/
https://github.com/WebAssembly/WASI
"a group of standards-track API specifications for software compiled to the W3C WebAssembly standard."
Introduced w/Web Assembly 3.0 Specification
currently (July 2026) at a 0.3 release
touches a lot of new things, including a component model for WASM
https://component-model.bytecodealliance.org/
a "virtual Instruction Set Architecture"
an embeddable interpreter (the "embedder")
in this respect, very much akin to Javascript itself
many/most Javascript engines will recognize WASM
based on a stack machine
instructions manipulate values on an operand stack
instructions will pop arguments off the stack, and results onto it
decoding
validation
execution
process the distribution format
convert into an internal representation
guarantee that the module is meaningful and safe
broken into two sub-phases, each accessible as an operation in the hosting environment:
instantiation: "A module instance is the dynamic representation of a module, complete with its own state and execution stack. Instantiation executes the module body itself, given definitions for all its imports. It initializes globals, memories and tables and invokes the module’s start function if defined. It returns the instances of the module’s exports.""
invocation: "Once instantiated, further WebAssembly computations can be initiated by invoking an exported function on a module instance. Given the required arguments, that executes the respective function and returns its results."
"A WebAssembly binary takes the form of a module that contains definitions for functions, tables, and linear memories, as well as mutable or immutable global variables. Definitions can also be imported, specifying a module/name pair and a suitable type. Each definition can optionally be exported under one or more names. In addition to definitions, modules can define initialization data for their memories or tables that takes the form of segments copied to given offsets. They can also define a start function that is automatically executed."
"Code is organized into separate functions. Each function takes a sequence of values as parameters and returns a sequence of values as results. Functions can call each other, including recursively, resulting in an implicit call stack that cannot be accessed directly. Functions may also declare mutable local variables that are usable as virtual registers."
"A table is an array of opaque values of a particular reference type that is specified by the table type. It allows programs to select such values indirectly through a dynamic index operand. Thereby, a program can call functions indirectly through a dynamic index into a table. For example, this allows emulating function pointers by way of table indices."
"A linear memory is a contiguous, mutable array of raw bytes. Such a memory is created with an initial size but can be grown dynamically. A program can load and store values from/to a linear memory at any byte address (including unaligned). Integer loads and stores can specify a storage size which is smaller than the size of the respective value type. A trap occurs if an access is not within the bounds of the current memory size."
"Under some conditions, certain instructions may produce a trap, which immediately aborts execution. Traps cannot be handled by WebAssembly code, but are reported to the outside environment, where they typically can be caught."
"A WebAssembly implementation will typically be embedded into a host environment. This environment defines how loading of modules is initiated, how imports are provided (including host-side definitions), and how exports can be accessed. However, the details of any particular embedding are beyond the scope of this specification, and will instead be provided by complementary, environment-specific API definitions."
Module/structure definitions
Numeric operations
Variable instructions
Memory instructions
Control instructions
modules are made up of 0..n:
types
imports/exports, including a "start" function
tags
global variables ("globals")
linear memories ("mems")
tables
functions ("funcs")
data segments ("datas")
element segments ("elems")
... s-expressions (parenthesized values/placeholders, a la LISP)
any/all may be empty
An empty module
(module)
each of these sections are referenced by index
u32 in size
this includes locals (inside functions) and labels (inside functions)
indexes are often replaceable by names in WAT
types defines a vector of function types
function signature types
functions will declare themselves to be one of these types
future versions of WASM may add new types
start declares the start function invoked at module instantiation
exports declares all functions exported from this module
imports declares all functions needed by this module
That add function again
(module
(func $add (param $a i32) (param $b i32) (result i64)
(i64.add
(i64.extend_i32_s (local.get $a))
(i64.extend_i32_s (local.get $b))
)
)
(export "add" (func $add))
)
number types
vector types
heap types
reference types
block types
structure ("aggregate") types (a la 'structs' or 'objects')
... plus some other housekeeping-esque types
i32, i64, f32, f64: integer and floating-point, 32- and 64-bit
these are "bases" for any numeric-related operation
in a form like {base}.{operation} {operand}
e.g, i64.add 4 4 or i32.add ($a) ($b)
push operands, pop operands
{base}.const {v}: push {v} (of type {base}) onto stack
drop: throws away single operand
select: selects either {a} or {b} operand depending on {c == 0}
iclz {v}: count of leading zero bits in v
ictz {v}: count of trailing zero bits in v
ipopcnt {v}: count of non-zero bits in v
add, sub, mul, div_u, div_s, rem_u, rem_s
and, or, xor, shl, shr, shr_s, rotl, irotr
abs, neg, ceil, floor, trunc, nearest, sqrt, min, max
eqz, eq, ne, lt, gt, le, ge
full list given in WASM Specification (Text Format, Instructions)
global.set {idx}, global.get {idx}
get/set global #{idx} to/from top of stack
local.set {idx}, local.get {idx}
get/set local #{idx} to/from top of stack
local.tee {idx}
like local.set but also returns its argument
{base}.load {memarg} | {base}.store {memarg}
load or store to linear memory
{memarg} is an offset/alignment pair
memory.size
return current size of linear memory
memory.grow
expand linear memory
nop: does nothing
unreachable: unconditional trap
structured instructions
block {resulttype} {instructions} end
loop {resulttype} {instructions} end
if {resulttype} {instructions} else {instructions} end
each introduces an implicit label
br {label}: unconditional branch to label
br_if {label}: conditional branch to label
br_table {label}: table-lookup branch
call {fnidx}: call function #{fnidx} directly
call_indrect {tableidx}: call function at index {tableidx}
return: terminate local function
"WABT" ("wabbit")
Collection of binary tools manipulating/exploring WASM files
https://github.com/WebAssembly/wabt
"Binaryen"
Compiler toolchain for WASM written in C++ intended for others' use
https://github.com/WebAssembly/binaryen
WebAssembly.Studio
https://webassembly.studio/
Github: https://github.com/wasdk/WebAssemblyStudio
... which unfortunately is archived now
C, Rust, AssemblyScript, Wat project types
wat2wasm
translate from WebAssembly text format to the WebAssembly binary format
wasm2wat
the inverse of wat2wasm, translate from the binary format back to the text format (also known as a .wat)
wasm-objdump
print information about a wasm binary. Similiar to objdump.
wasm-interp
decode and run a WebAssembly binary file using a stack-based interpreter
wat-desugar
parse .wat text form as supported by the spec interpreter (s-expressions, flat syntax, or mixed) and print "canonical" flat format
wasm2c
convert a WebAssembly binary file to a C source and header
wasm-strip
remove sections of a WebAssembly binary file
wasm-validate
validate a file in the WebAssembly binary format
wast2json
convert a file in the wasm spec test format to a JSON file and associated wasm binary files
wasm-opcodecnt
count opcode usage for instructions
spectest-interp
read a Spectest JSON file, and run its tests in the interpreter
aims to make compiling to WASM easy, fast, and effective
easy: simple C API header; can be used from Javascript
fast: internal IR optimized for performance
effective: optimizer has numerous passes to improve codegen
wasm-shell
A shell that can load and interpret WebAssembly code. It can also run the spec test suite.
wasm-as
Assembles WebAssembly in text format (currently S-Expression format) into binary format (going through Binaryen IR).
wasm-dis
Un-assembles WebAssembly in binary format into text format (going through Binaryen IR).
wasm-opt
Loads WebAssembly and runs Binaryen IR passes on it.
asm2wasm
An asm.js-to-WebAssembly compiler, using Emscripten's asm optimizer infrastructure. This is used by Emscripten in Binaryen mode when it uses Emscripten's fastcomp asm.js backend.
wasm2js
A WebAssembly-to-JS compiler (still experimental).
wasm-merge
Combines wasm files into a single big wasm file (without sophisticated linking).
wasm-ctor-eval
A tool that can execute C++ global constructors ahead of time. Used by Emscripten.
wasm-emscripten-finalize
Takes a wasm binary produced by llvm+lld and performs emscripten-specific passes over it.
binaryen.js
A standalone JavaScript library that exposes Binaryen methods for creating and optimizing WASM modules. For builds, see binaryen.js on npm (or download it directly from github, rawgit, or unpkg).
Runtime-Backed (that is, Blazor):
Compiles C# into normal .NET IL (.dll files)
Wasm-compiled .NET runtime (Mono) is downloaded to the browser to execute those DLLs.
~36,000 websites usage (https://trends.builtwith.com/framework/Blazor)
Native AOT (Browser/WASI):
C# compiled directly into standard .wasm bytecode
that is, without shipping the interpreter
wasm-tools workload (dotnet workload install wasm-tools) for frontend JavaScript apps
The first is wildly more popular than the second
Cheerp
https://leaningtech.com/cheerp/
a commercial open-source C/C++ compiler for Web applications
https://github.com/leaningtech/cheerp-meta
AssemblyScript
language derived from TypeScript intended to be as close to WASM semantics as possible
uses JS port of binaryen
https://github.com/AssemblyScript/assemblyscript
... certainly holds a lot of promise
bytecode offers lots of room for performance improvement
WASM futures offer a lot of areas for general enhancement
... is as-yet-unclear as to its impact
could represent huge shift in client-side Web
could end up being a footnote that nobody cares about
not clear what will make the difference
Officlal website
http://www.webassembly.org
Official GitHub
https://github.com/WebAssembly
WABT: https://github.com/WebAssembly/wabt
Binaryen: https://github.com/WebAssembly/binaryen
Specs: https://github.com/WebAssembly/spec
Proposals: https://github.com/WebAssembly/proposals
MDN
https://developer.mozilla.org/en-US/docs/WebAssembly
"Top 5 Uses for WebAssembly"
https://thenewstack.io/top-5-uses-of-webassembly-for-web-developers/
C#: Blazor
https://learn.microsoft.com/en-us/aspnet/core/blazor/tutorials/
deeply wrapped together with ASP.NET
C/C++: Emscripten
https://emscripten.org/docs/getting_started/downloads.html
AssemblyScript
https://www.assemblyscript.org/introduction.html
Zig
https://ziglang.org/documentation/master/#WebAssembly
and, yeah, Rust, but that's so last year
https://rustwasm.github.io/book/
more complete list at
https://github.com/appcypher/awesome-wasm-langs
browser-based Javascript
https://developer.mozilla.org/en-US/docs/WebAssembly/Guides/Loading_and_running
NodeJS
https://nodejs.org/api/wasi.html
GraalVM (JVM)
https://www.graalvm.org/webassembly/
wasmtime
https://wasmtime.dev/
... which can be embedded from Rust, C/C++, Python, .NET, Go, Ruby
Architect, Engineering Manager/Leader, "force multiplier"
http://www.newardassociates.com
http://blogs.newardassociates.com
Books
Developer Relations Activity Patterns (w/Woodruff, et al; APress, 2026)
Professional F# 2.0 (w/Erickson, et al; Wrox, 2010)
Effective Enterprise Java (Addison-Wesley, 2004)
SSCLI Essentials (w/Stutz, et al; OReilly, 2003)
Server-Based Java Programming (Manning, 2000)