Skip to content

Instantly share code, notes, and snippets.

@PhoenixIllusion
Created January 22, 2026 17:00
Show Gist options
  • Select an option

  • Save PhoenixIllusion/147f9247bb9cfde1f09d88d1aeee9905 to your computer and use it in GitHub Desktop.

Select an option

Save PhoenixIllusion/147f9247bb9cfde1f09d88d1aeee9905 to your computer and use it in GitHub Desktop.
export function ensureTableExported(wasm) {
// --- minimal ULEB128 reader ---
function readULEB(buf, o) {
let v = 0, s = 0, p = o;
while (true) {
const b = buf[p++];
v |= (b & 0x7f) << s;
if (!(b & 0x80))
break;
s += 7;
}
return { v, n: p - o };
}
// --- minimal ULEB128 writer ---
function writeULEB(v) {
const out = [];
do {
let b = v & 0x7f;
v >>>= 7;
if (v)
b |= 0x80;
out.push(b);
} while (v);
return Uint8Array.from(out);
}
let pos = 8; // skip wasm header
let tableExists = false;
let tableExported = false;
let exportSecStart = -1;
let exportPayloadStart = -1;
let exportPayloadEnd = -1;
let exportCount = 0;
let exportCountLen = 0;
// --- scan sections ---
while (pos < wasm.length) {
const id = wasm[pos];
const sizeInfo = readULEB(wasm, pos + 1);
const size = sizeInfo.v;
const payload = pos + 1 + sizeInfo.n;
const end = payload + size;
if (id === 4) {
// table section
const c = readULEB(wasm, payload).v;
tableExists = c > 0;
}
if (id === 7) {
// export section
exportSecStart = pos;
exportPayloadStart = payload;
exportPayloadEnd = end;
const cnt = readULEB(wasm, payload);
exportCount = cnt.v;
exportCountLen = cnt.n;
let p = payload + cnt.n;
for (let i = 0; i < exportCount; i++) {
const nameLen = readULEB(wasm, p);
p += nameLen.n + nameLen.v;
const kind = wasm[p++];
const idx = readULEB(wasm, p);
p += idx.n;
if (kind === 1)
tableExported = true;
}
}
pos = end;
}
// nothing to do
if (!tableExists || tableExported)
return [wasm];
// --- build new export entry ---
const name = "table";
const nameBytes = Uint8Array.from(name, c => c.charCodeAt(0));
const entry = [
writeULEB(nameBytes.length),
nameBytes,
Uint8Array.of(1), // kind = table
writeULEB(0) // table index
];
// no export section → append one
if (exportSecStart < 0) {
const payload = [writeULEB(1), ...entry];
const plen = payload.reduce((a, b) => a + b.length, 0);
return [
wasm,
Uint8Array.of(7),
writeULEB(plen),
...payload
];
}
// --- patch existing export section ---
const before = wasm.subarray(0, exportSecStart);
const after = wasm.subarray(exportPayloadEnd);
const newCount = writeULEB(exportCount + 1);
const oldPayload = wasm.subarray(exportPayloadStart, exportPayloadEnd);
const rest = oldPayload.subarray(exportCountLen);
const newPayloadParts = [newCount, rest, ...entry];
const newPayloadLen = newPayloadParts.reduce((a, b) => a + b.length, 0);
return [
before,
Uint8Array.of(7),
writeULEB(newPayloadLen),
...newPayloadParts,
after
];
}
export function ensureTableExported(wasm: Uint8Array<ArrayBuffer>): Uint8Array<ArrayBuffer>[] {
// --- minimal ULEB128 reader ---
function readULEB(buf: Uint8Array, o: number) {
let v = 0, s = 0, p = o;
while (true) {
const b = buf[p++];
v |= (b & 0x7f) << s;
if (!(b & 0x80)) break;
s += 7;
}
return { v, n: p - o };
}
// --- minimal ULEB128 writer ---
function writeULEB(v: number) {
const out: number[] = [];
do {
let b = v & 0x7f;
v >>>= 7;
if (v) b |= 0x80;
out.push(b);
} while (v);
return Uint8Array.from(out);
}
let pos = 8; // skip wasm header
let tableExists = false;
let tableExported = false;
let exportSecStart = -1;
let exportPayloadStart = -1;
let exportPayloadEnd = -1;
let exportCount = 0;
let exportCountLen = 0;
// --- scan sections ---
while (pos < wasm.length) {
const id = wasm[pos];
const sizeInfo = readULEB(wasm, pos + 1);
const size = sizeInfo.v;
const payload = pos + 1 + sizeInfo.n;
const end = payload + size;
if (id === 4) {
// table section
const c = readULEB(wasm, payload).v;
tableExists = c > 0;
}
if (id === 7) {
// export section
exportSecStart = pos;
exportPayloadStart = payload;
exportPayloadEnd = end;
const cnt = readULEB(wasm, payload);
exportCount = cnt.v;
exportCountLen = cnt.n;
let p = payload + cnt.n;
for (let i = 0; i < exportCount; i++) {
const nameLen = readULEB(wasm, p);
p += nameLen.n + nameLen.v;
const kind = wasm[p++];
const idx = readULEB(wasm, p);
p += idx.n;
if (kind === 1) tableExported = true;
}
}
pos = end;
}
// nothing to do
if (!tableExists || tableExported) return [wasm];
// --- build new export entry ---
const name = "table";
const nameBytes = Uint8Array.from(name, c => c.charCodeAt(0));
const entry = [
writeULEB(nameBytes.length),
nameBytes,
Uint8Array.of(1), // kind = table
writeULEB(0) // table index
];
// no export section → append one
if (exportSecStart < 0) {
const payload = [writeULEB(1), ...entry];
const plen = payload.reduce((a, b) => a + b.length, 0);
return [
wasm,
Uint8Array.of(7),
writeULEB(plen),
...payload
];
}
// --- patch existing export section ---
const before = wasm.subarray(0, exportSecStart);
const after = wasm.subarray(exportPayloadEnd);
const newCount = writeULEB(exportCount + 1);
const oldPayload = wasm.subarray(exportPayloadStart, exportPayloadEnd);
const rest = oldPayload.subarray(exportCountLen);
const newPayloadParts = [newCount, rest, ...entry];
const newPayloadLen = newPayloadParts.reduce((a, b) => a + b.length, 0);
return [
before,
Uint8Array.of(7),
writeULEB(newPayloadLen),
...newPayloadParts,
after
];
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment