What's inside a .wasm file
Every module starts with the magic number \0asm and version 1, then a sequence of sections: an id byte, a LEB128 size, and the contents. Types, functions, exports and code each live in their own section — so tools can skip what they don't need.
Walking the sections
const SECTION_NAMES = { 0: "custom", 1: "type", 2: "import", 3: "function", 4: "table", 5: "memory", 6: "global", 7: "export", 8: "start", 9: "element", 10: "code", 11: "data" };
function sections(bytes) {
const magic = [0x00, 0x61, 0x73, 0x6d];
if (bytes.length < 8 || magic.some((b, i) => bytes[i] !== b)) throw new Error("Not a WebAssembly module");
const out = [];
let at = 8; // skip magic and version
while (at < bytes.length) {
const id = bytes[at];
const { value: size, next } = decodeULEB128(bytes, at + 1);
out.push({ id, name: SECTION_NAMES[id] ?? "unknown", size });
at = next + size; // jump over the section's contents
}
return out;
}