Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F92262117
decoder.js
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Mon, Nov 18, 21:38
Size
51 KB
Mime Type
text/x-java
Expires
Wed, Nov 20, 21:38 (1 d, 22 h)
Engine
blob
Format
Raw Data
Handle
22407836
Attached To
rOACCT Open Access Compliance Check Tool (OACCT)
decoder.js
View Options
function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }
import { CompileError } from "@webassemblyjs/helper-api-error";
import * as ieee754 from "@webassemblyjs/ieee754";
import * as utf8 from "@webassemblyjs/utf8";
import * as t from "@webassemblyjs/ast";
import { decodeInt32, decodeUInt32, MAX_NUMBER_OF_BYTE_U32, decodeInt64, decodeUInt64, MAX_NUMBER_OF_BYTE_U64 } from "@webassemblyjs/leb128";
import constants from "@webassemblyjs/helper-wasm-bytecode";
function toHex(n) {
return "0x" + Number(n).toString(16);
}
function byteArrayEq(l, r) {
if (l.length !== r.length) {
return false;
}
for (var i = 0; i < l.length; i++) {
if (l[i] !== r[i]) {
return false;
}
}
return true;
}
export function decode(ab, opts) {
var buf = new Uint8Array(ab);
var getUniqueName = t.getUniqueNameGenerator();
var offset = 0;
function getPosition() {
return {
line: -1,
column: offset
};
}
function dump(b, msg) {
if (opts.dump === false) return;
var pad = "\t\t\t\t\t\t\t\t\t\t";
var str = "";
if (b.length < 5) {
str = b.map(toHex).join(" ");
} else {
str = "...";
}
console.log(toHex(offset) + ":\t", str, pad, ";", msg);
}
function dumpSep(msg) {
if (opts.dump === false) return;
console.log(";", msg);
}
/**
* TODO(sven): we can atually use a same structure
* we are adding incrementally new features
*/
var state = {
elementsInFuncSection: [],
elementsInExportSection: [],
elementsInCodeSection: [],
/**
* Decode memory from:
* - Memory section
*/
memoriesInModule: [],
/**
* Decoded types from:
* - Type section
*/
typesInModule: [],
/**
* Decoded functions from:
* - Function section
* - Import section
*/
functionsInModule: [],
/**
* Decoded tables from:
* - Table section
*/
tablesInModule: [],
/**
* Decoded globals from:
* - Global section
*/
globalsInModule: []
};
function isEOF() {
return offset >= buf.length;
}
function eatBytes(n) {
offset = offset + n;
}
function readBytesAtOffset(_offset, numberOfBytes) {
var arr = [];
for (var i = 0; i < numberOfBytes; i++) {
arr.push(buf[_offset + i]);
}
return arr;
}
function readBytes(numberOfBytes) {
return readBytesAtOffset(offset, numberOfBytes);
}
function readF64() {
var bytes = readBytes(ieee754.NUMBER_OF_BYTE_F64);
var value = ieee754.decodeF64(bytes);
if (Math.sign(value) * value === Infinity) {
return {
value: Math.sign(value),
inf: true,
nextIndex: ieee754.NUMBER_OF_BYTE_F64
};
}
if (isNaN(value)) {
var sign = bytes[bytes.length - 1] >> 7 ? -1 : 1;
var mantissa = 0;
for (var i = 0; i < bytes.length - 2; ++i) {
mantissa += bytes[i] * Math.pow(256, i);
}
mantissa += bytes[bytes.length - 2] % 16 * Math.pow(256, bytes.length - 2);
return {
value: sign * mantissa,
nan: true,
nextIndex: ieee754.NUMBER_OF_BYTE_F64
};
}
return {
value: value,
nextIndex: ieee754.NUMBER_OF_BYTE_F64
};
}
function readF32() {
var bytes = readBytes(ieee754.NUMBER_OF_BYTE_F32);
var value = ieee754.decodeF32(bytes);
if (Math.sign(value) * value === Infinity) {
return {
value: Math.sign(value),
inf: true,
nextIndex: ieee754.NUMBER_OF_BYTE_F32
};
}
if (isNaN(value)) {
var sign = bytes[bytes.length - 1] >> 7 ? -1 : 1;
var mantissa = 0;
for (var i = 0; i < bytes.length - 2; ++i) {
mantissa += bytes[i] * Math.pow(256, i);
}
mantissa += bytes[bytes.length - 2] % 128 * Math.pow(256, bytes.length - 2);
return {
value: sign * mantissa,
nan: true,
nextIndex: ieee754.NUMBER_OF_BYTE_F32
};
}
return {
value: value,
nextIndex: ieee754.NUMBER_OF_BYTE_F32
};
}
function readUTF8String() {
var lenu32 = readU32(); // Don't eat any bytes. Instead, peek ahead of the current offset using
// readBytesAtOffset below. This keeps readUTF8String neutral with respect
// to the current offset, just like the other readX functions.
var strlen = lenu32.value;
dump([strlen], "string length");
var bytes = readBytesAtOffset(offset + lenu32.nextIndex, strlen);
var value = utf8.decode(bytes);
return {
value: value,
nextIndex: strlen + lenu32.nextIndex
};
}
/**
* Decode an unsigned 32bits integer
*
* The length will be handled by the leb librairy, we pass the max number of
* byte.
*/
function readU32() {
var bytes = readBytes(MAX_NUMBER_OF_BYTE_U32);
var buffer = Buffer.from(bytes);
return decodeUInt32(buffer);
}
function readVaruint32() {
// where 32 bits = max 4 bytes
var bytes = readBytes(4);
var buffer = Buffer.from(bytes);
return decodeUInt32(buffer);
}
function readVaruint7() {
// where 7 bits = max 1 bytes
var bytes = readBytes(1);
var buffer = Buffer.from(bytes);
return decodeUInt32(buffer);
}
/**
* Decode a signed 32bits interger
*/
function read32() {
var bytes = readBytes(MAX_NUMBER_OF_BYTE_U32);
var buffer = Buffer.from(bytes);
return decodeInt32(buffer);
}
/**
* Decode a signed 64bits integer
*/
function read64() {
var bytes = readBytes(MAX_NUMBER_OF_BYTE_U64);
var buffer = Buffer.from(bytes);
return decodeInt64(buffer);
}
function readU64() {
var bytes = readBytes(MAX_NUMBER_OF_BYTE_U64);
var buffer = Buffer.from(bytes);
return decodeUInt64(buffer);
}
function readByte() {
return readBytes(1)[0];
}
function parseModuleHeader() {
if (isEOF() === true || offset + 4 > buf.length) {
throw new Error("unexpected end");
}
var header = readBytes(4);
if (byteArrayEq(constants.magicModuleHeader, header) === false) {
throw new CompileError("magic header not detected");
}
dump(header, "wasm magic header");
eatBytes(4);
}
function parseVersion() {
if (isEOF() === true || offset + 4 > buf.length) {
throw new Error("unexpected end");
}
var version = readBytes(4);
if (byteArrayEq(constants.moduleVersion, version) === false) {
throw new CompileError("unknown binary version");
}
dump(version, "wasm version");
eatBytes(4);
}
function parseVec(cast) {
var u32 = readU32();
var length = u32.value;
eatBytes(u32.nextIndex);
dump([length], "number");
if (length === 0) {
return [];
}
var elements = [];
for (var i = 0; i < length; i++) {
var byte = readByte();
eatBytes(1);
var value = cast(byte);
dump([byte], value);
if (typeof value === "undefined") {
throw new CompileError("Internal failure: parseVec could not cast the value");
}
elements.push(value);
}
return elements;
} // Type section
// https://webassembly.github.io/spec/binary/modules.html#binary-typesec
function parseTypeSection(numberOfTypes) {
var typeInstructionNodes = [];
dump([numberOfTypes], "num types");
for (var i = 0; i < numberOfTypes; i++) {
var _startLoc = getPosition();
dumpSep("type " + i);
var type = readByte();
eatBytes(1);
if (type == constants.types.func) {
dump([type], "func");
var paramValtypes = parseVec(function (b) {
return constants.valtypes[b];
});
var params = paramValtypes.map(function (v) {
return t.funcParam(
/*valtype*/
v);
});
var result = parseVec(function (b) {
return constants.valtypes[b];
});
typeInstructionNodes.push(function () {
var endLoc = getPosition();
return t.withLoc(t.typeInstruction(undefined, t.signature(params, result)), endLoc, _startLoc);
}());
state.typesInModule.push({
params: params,
result: result
});
} else {
throw new Error("Unsupported type: " + toHex(type));
}
}
return typeInstructionNodes;
} // Import section
// https://webassembly.github.io/spec/binary/modules.html#binary-importsec
function parseImportSection(numberOfImports) {
var imports = [];
for (var i = 0; i < numberOfImports; i++) {
dumpSep("import header " + i);
var _startLoc2 = getPosition();
/**
* Module name
*/
var moduleName = readUTF8String();
eatBytes(moduleName.nextIndex);
dump([], "module name (".concat(moduleName.value, ")"));
/**
* Name
*/
var name = readUTF8String();
eatBytes(name.nextIndex);
dump([], "name (".concat(name.value, ")"));
/**
* Import descr
*/
var descrTypeByte = readByte();
eatBytes(1);
var descrType = constants.importTypes[descrTypeByte];
dump([descrTypeByte], "import kind");
if (typeof descrType === "undefined") {
throw new CompileError("Unknown import description type: " + toHex(descrTypeByte));
}
var importDescr = void 0;
if (descrType === "func") {
var indexU32 = readU32();
var typeindex = indexU32.value;
eatBytes(indexU32.nextIndex);
dump([typeindex], "type index");
var signature = state.typesInModule[typeindex];
if (typeof signature === "undefined") {
throw new CompileError("function signature not found (".concat(typeindex, ")"));
}
var id = getUniqueName("func");
importDescr = t.funcImportDescr(id, t.signature(signature.params, signature.result));
state.functionsInModule.push({
id: t.identifier(name.value),
signature: signature,
isExternal: true
});
} else if (descrType === "global") {
importDescr = parseGlobalType();
var globalNode = t.global(importDescr, []);
state.globalsInModule.push(globalNode);
} else if (descrType === "table") {
importDescr = parseTableType(i);
} else if (descrType === "mem") {
var memoryNode = parseMemoryType(0);
state.memoriesInModule.push(memoryNode);
importDescr = memoryNode;
} else {
throw new CompileError("Unsupported import of type: " + descrType);
}
imports.push(function () {
var endLoc = getPosition();
return t.withLoc(t.moduleImport(moduleName.value, name.value, importDescr), endLoc, _startLoc2);
}());
}
return imports;
} // Function section
// https://webassembly.github.io/spec/binary/modules.html#function-section
function parseFuncSection(numberOfFunctions) {
dump([numberOfFunctions], "num funcs");
for (var i = 0; i < numberOfFunctions; i++) {
var indexU32 = readU32();
var typeindex = indexU32.value;
eatBytes(indexU32.nextIndex);
dump([typeindex], "type index");
var signature = state.typesInModule[typeindex];
if (typeof signature === "undefined") {
throw new CompileError("function signature not found (".concat(typeindex, ")"));
} // preserve anonymous, a name might be resolved later
var id = t.withRaw(t.identifier(getUniqueName("func")), "");
state.functionsInModule.push({
id: id,
signature: signature,
isExternal: false
});
}
} // Export section
// https://webassembly.github.io/spec/binary/modules.html#export-section
function parseExportSection(numberOfExport) {
dump([numberOfExport], "num exports"); // Parse vector of exports
for (var i = 0; i < numberOfExport; i++) {
var _startLoc3 = getPosition();
/**
* Name
*/
var name = readUTF8String();
eatBytes(name.nextIndex);
dump([], "export name (".concat(name.value, ")"));
/**
* exportdescr
*/
var typeIndex = readByte();
eatBytes(1);
dump([typeIndex], "export kind");
var indexu32 = readU32();
var index = indexu32.value;
eatBytes(indexu32.nextIndex);
dump([index], "export index");
var id = void 0,
signature = void 0;
if (constants.exportTypes[typeIndex] === "Func") {
var func = state.functionsInModule[index];
if (typeof func === "undefined") {
throw new CompileError("unknown function (".concat(index, ")"));
}
id = t.numberLiteralFromRaw(index, String(index));
signature = func.signature;
} else if (constants.exportTypes[typeIndex] === "Table") {
var table = state.tablesInModule[index];
if (typeof table === "undefined") {
throw new CompileError("unknown table ".concat(index));
}
id = t.numberLiteralFromRaw(index, String(index));
signature = null;
} else if (constants.exportTypes[typeIndex] === "Mem") {
var memNode = state.memoriesInModule[index];
if (typeof memNode === "undefined") {
throw new CompileError("unknown memory ".concat(index));
}
id = t.numberLiteralFromRaw(index, String(index));
signature = null;
} else if (constants.exportTypes[typeIndex] === "Global") {
var global = state.globalsInModule[index];
if (typeof global === "undefined") {
throw new CompileError("unknown global ".concat(index));
}
id = t.numberLiteralFromRaw(index, String(index));
signature = null;
} else {
console.warn("Unsupported export type: " + toHex(typeIndex));
return;
}
var endLoc = getPosition();
state.elementsInExportSection.push({
name: name.value,
type: constants.exportTypes[typeIndex],
signature: signature,
id: id,
index: index,
endLoc: endLoc,
startLoc: _startLoc3
});
}
} // Code section
// https://webassembly.github.io/spec/binary/modules.html#code-section
function parseCodeSection(numberOfFuncs) {
dump([numberOfFuncs], "number functions"); // Parse vector of function
for (var i = 0; i < numberOfFuncs; i++) {
var _startLoc4 = getPosition();
dumpSep("function body " + i); // the u32 size of the function code in bytes
// Ignore it for now
var bodySizeU32 = readU32();
eatBytes(bodySizeU32.nextIndex);
dump([bodySizeU32.value], "function body size");
var code = [];
/**
* Parse locals
*/
var funcLocalNumU32 = readU32();
var funcLocalNum = funcLocalNumU32.value;
eatBytes(funcLocalNumU32.nextIndex);
dump([funcLocalNum], "num locals");
var locals = [];
for (var _i = 0; _i < funcLocalNum; _i++) {
var _startLoc5 = getPosition();
var localCountU32 = readU32();
var localCount = localCountU32.value;
eatBytes(localCountU32.nextIndex);
dump([localCount], "num local");
var valtypeByte = readByte();
eatBytes(1);
var type = constants.valtypes[valtypeByte];
var args = [];
for (var _i2 = 0; _i2 < localCount; _i2++) {
args.push(t.valtypeLiteral(type));
}
var localNode = function () {
var endLoc = getPosition();
return t.withLoc(t.instruction("local", args), endLoc, _startLoc5);
}();
locals.push(localNode);
dump([valtypeByte], type);
if (typeof type === "undefined") {
throw new CompileError("Unexpected valtype: " + toHex(valtypeByte));
}
}
code.push.apply(code, locals); // Decode instructions until the end
parseInstructionBlock(code);
var endLoc = getPosition();
state.elementsInCodeSection.push({
code: code,
locals: locals,
endLoc: endLoc,
startLoc: _startLoc4,
bodySize: bodySizeU32.value
});
}
}
function parseInstructionBlock(code) {
while (true) {
var _startLoc6 = getPosition();
var instructionAlreadyCreated = false;
var instructionByte = readByte();
eatBytes(1);
if (instructionByte === 0xfe) {
throw new CompileError("Atomic instructions are not implemented");
}
var instruction = constants.symbolsByByte[instructionByte];
if (typeof instruction === "undefined") {
throw new CompileError("Unexpected instruction: " + toHex(instructionByte));
}
if (typeof instruction.object === "string") {
dump([instructionByte], "".concat(instruction.object, ".").concat(instruction.name));
} else {
dump([instructionByte], instruction.name);
}
/**
* End of the function
*/
if (instruction.name === "end") {
var node = function () {
var endLoc = getPosition();
return t.withLoc(t.instruction(instruction.name), endLoc, _startLoc6);
}();
code.push(node);
break;
}
var args = [];
if (instruction.name === "loop") {
var _startLoc7 = getPosition();
var blocktypeByte = readByte();
eatBytes(1);
var blocktype = constants.blockTypes[blocktypeByte];
dump([blocktypeByte], "blocktype");
if (typeof blocktype === "undefined") {
throw new CompileError("Unexpected blocktype: " + toHex(blocktypeByte));
}
var instr = [];
parseInstructionBlock(instr); // preserve anonymous
var label = t.withRaw(t.identifier(getUniqueName("loop")), "");
var loopNode = function () {
var endLoc = getPosition();
return t.withLoc(t.loopInstruction(label, blocktype, instr), endLoc, _startLoc7);
}();
code.push(loopNode);
instructionAlreadyCreated = true;
} else if (instruction.name === "if") {
var _startLoc8 = getPosition();
var _blocktypeByte = readByte();
eatBytes(1);
var _blocktype = constants.blockTypes[_blocktypeByte];
dump([_blocktypeByte], "blocktype");
if (typeof _blocktype === "undefined") {
throw new CompileError("Unexpected blocktype: " + toHex(_blocktypeByte));
}
var testIndex = t.withRaw(t.identifier(getUniqueName("if")), "");
var ifBody = [];
parseInstructionBlock(ifBody); // Defaults to no alternate
var elseIndex = 0;
for (elseIndex = 0; elseIndex < ifBody.length; ++elseIndex) {
var _instr = ifBody[elseIndex];
if (_instr.type === "Instr" && _instr.id === "else") {
break;
}
}
var consequentInstr = ifBody.slice(0, elseIndex);
var alternate = ifBody.slice(elseIndex + 1); // wast sugar
var testInstrs = [];
var ifNode = function () {
var endLoc = getPosition();
return t.withLoc(t.ifInstruction(testIndex, testInstrs, _blocktype, consequentInstr, alternate), endLoc, _startLoc8);
}();
code.push(ifNode);
instructionAlreadyCreated = true;
} else if (instruction.name === "block") {
var _startLoc9 = getPosition();
var _blocktypeByte2 = readByte();
eatBytes(1);
var _blocktype2 = constants.blockTypes[_blocktypeByte2];
dump([_blocktypeByte2], "blocktype");
if (typeof _blocktype2 === "undefined") {
throw new CompileError("Unexpected blocktype: " + toHex(_blocktypeByte2));
}
var _instr2 = [];
parseInstructionBlock(_instr2); // preserve anonymous
var _label = t.withRaw(t.identifier(getUniqueName("block")), "");
var blockNode = function () {
var endLoc = getPosition();
return t.withLoc(t.blockInstruction(_label, _instr2, _blocktype2), endLoc, _startLoc9);
}();
code.push(blockNode);
instructionAlreadyCreated = true;
} else if (instruction.name === "call") {
var indexu32 = readU32();
var index = indexu32.value;
eatBytes(indexu32.nextIndex);
dump([index], "index");
var callNode = function () {
var endLoc = getPosition();
return t.withLoc(t.callInstruction(t.indexLiteral(index)), endLoc, _startLoc6);
}();
code.push(callNode);
instructionAlreadyCreated = true;
} else if (instruction.name === "call_indirect") {
var _startLoc10 = getPosition();
var indexU32 = readU32();
var typeindex = indexU32.value;
eatBytes(indexU32.nextIndex);
dump([typeindex], "type index");
var signature = state.typesInModule[typeindex];
if (typeof signature === "undefined") {
throw new CompileError("call_indirect signature not found (".concat(typeindex, ")"));
}
var _callNode = t.callIndirectInstruction(t.signature(signature.params, signature.result), []);
var flagU32 = readU32();
var flag = flagU32.value; // 0x00 - reserved byte
eatBytes(flagU32.nextIndex);
if (flag !== 0) {
throw new CompileError("zero flag expected");
}
code.push(function () {
var endLoc = getPosition();
return t.withLoc(_callNode, endLoc, _startLoc10);
}());
instructionAlreadyCreated = true;
} else if (instruction.name === "br_table") {
var indicesu32 = readU32();
var indices = indicesu32.value;
eatBytes(indicesu32.nextIndex);
dump([indices], "num indices");
for (var i = 0; i <= indices; i++) {
var _indexu = readU32();
var _index = _indexu.value;
eatBytes(_indexu.nextIndex);
dump([_index], "index");
args.push(t.numberLiteralFromRaw(_indexu.value.toString(), "u32"));
}
} else if (instructionByte >= 0x28 && instructionByte <= 0x40) {
/**
* Memory instructions
*/
if (instruction.name === "grow_memory" || instruction.name === "current_memory") {
var _indexU = readU32();
var _index2 = _indexU.value;
eatBytes(_indexU.nextIndex);
if (_index2 !== 0) {
throw new Error("zero flag expected");
}
dump([_index2], "index");
} else {
var aligun32 = readU32();
var align = aligun32.value;
eatBytes(aligun32.nextIndex);
dump([align], "align");
var offsetu32 = readU32();
var _offset2 = offsetu32.value;
eatBytes(offsetu32.nextIndex);
dump([_offset2], "offset");
}
} else if (instructionByte >= 0x41 && instructionByte <= 0x44) {
/**
* Numeric instructions
*/
if (instruction.object === "i32") {
var value32 = read32();
var value = value32.value;
eatBytes(value32.nextIndex);
dump([value], "i32 value");
args.push(t.numberLiteralFromRaw(value));
}
if (instruction.object === "u32") {
var valueu32 = readU32();
var _value = valueu32.value;
eatBytes(valueu32.nextIndex);
dump([_value], "u32 value");
args.push(t.numberLiteralFromRaw(_value));
}
if (instruction.object === "i64") {
var value64 = read64();
var _value2 = value64.value;
eatBytes(value64.nextIndex);
dump([Number(_value2.toString())], "i64 value");
var high = _value2.high,
low = _value2.low;
var _node = {
type: "LongNumberLiteral",
value: {
high: high,
low: low
}
};
args.push(_node);
}
if (instruction.object === "u64") {
var valueu64 = readU64();
var _value3 = valueu64.value;
eatBytes(valueu64.nextIndex);
dump([Number(_value3.toString())], "u64 value");
var _high = _value3.high,
_low = _value3.low;
var _node2 = {
type: "LongNumberLiteral",
value: {
high: _high,
low: _low
}
};
args.push(_node2);
}
if (instruction.object === "f32") {
var valuef32 = readF32();
var _value4 = valuef32.value;
eatBytes(valuef32.nextIndex);
dump([_value4], "f32 value");
args.push( // $FlowIgnore
t.floatLiteral(_value4, valuef32.nan, valuef32.inf, String(_value4)));
}
if (instruction.object === "f64") {
var valuef64 = readF64();
var _value5 = valuef64.value;
eatBytes(valuef64.nextIndex);
dump([_value5], "f64 value");
args.push( // $FlowIgnore
t.floatLiteral(_value5, valuef64.nan, valuef64.inf, String(_value5)));
}
} else {
for (var _i3 = 0; _i3 < instruction.numberOfArgs; _i3++) {
var u32 = readU32();
eatBytes(u32.nextIndex);
dump([u32.value], "argument " + _i3);
args.push(t.numberLiteralFromRaw(u32.value));
}
}
if (instructionAlreadyCreated === false) {
if (typeof instruction.object === "string") {
var _node3 = function () {
var endLoc = getPosition();
return t.withLoc(t.objectInstruction(instruction.name, instruction.object, args), endLoc, _startLoc6);
}();
code.push(_node3);
} else {
var _node4 = function () {
var endLoc = getPosition();
return t.withLoc(t.instruction(instruction.name, args), endLoc, _startLoc6);
}();
code.push(_node4);
}
}
}
} // https://webassembly.github.io/spec/core/binary/types.html#limits
function parseLimits() {
var limitType = readByte();
eatBytes(1);
dump([limitType], "limit type");
var min, max;
if (limitType === 0x01 || limitType === 0x03 // shared limits
) {
var u32min = readU32();
min = parseInt(u32min.value);
eatBytes(u32min.nextIndex);
dump([min], "min");
var u32max = readU32();
max = parseInt(u32max.value);
eatBytes(u32max.nextIndex);
dump([max], "max");
}
if (limitType === 0x00) {
var _u32min = readU32();
min = parseInt(_u32min.value);
eatBytes(_u32min.nextIndex);
dump([min], "min");
}
return t.limit(min, max);
} // https://webassembly.github.io/spec/core/binary/types.html#binary-tabletype
function parseTableType(index) {
var name = t.withRaw(t.identifier(getUniqueName("table")), String(index));
var elementTypeByte = readByte();
eatBytes(1);
dump([elementTypeByte], "element type");
var elementType = constants.tableTypes[elementTypeByte];
if (typeof elementType === "undefined") {
throw new CompileError("Unknown element type in table: " + toHex(elementType));
}
var limits = parseLimits();
return t.table(elementType, limits, name);
} // https://webassembly.github.io/spec/binary/types.html#global-types
function parseGlobalType() {
var valtypeByte = readByte();
eatBytes(1);
var type = constants.valtypes[valtypeByte];
dump([valtypeByte], type);
if (typeof type === "undefined") {
throw new CompileError("Unknown valtype: " + toHex(valtypeByte));
}
var globalTypeByte = readByte();
eatBytes(1);
var globalType = constants.globalTypes[globalTypeByte];
dump([globalTypeByte], "global type (".concat(globalType, ")"));
if (typeof globalType === "undefined") {
throw new CompileError("Invalid mutability: " + toHex(globalTypeByte));
}
return t.globalType(type, globalType);
} // function parseNameModule() {
// const lenu32 = readVaruint32();
// eatBytes(lenu32.nextIndex);
// console.log("len", lenu32);
// const strlen = lenu32.value;
// dump([strlen], "string length");
// const bytes = readBytes(strlen);
// eatBytes(strlen);
// const value = utf8.decode(bytes);
// return [t.moduleNameMetadata(value)];
// }
// this section contains an array of function names and indices
function parseNameSectionFunctions() {
var functionNames = [];
var numberOfFunctionsu32 = readU32();
var numbeOfFunctions = numberOfFunctionsu32.value;
eatBytes(numberOfFunctionsu32.nextIndex);
for (var i = 0; i < numbeOfFunctions; i++) {
var indexu32 = readU32();
var index = indexu32.value;
eatBytes(indexu32.nextIndex);
var name = readUTF8String();
eatBytes(name.nextIndex);
functionNames.push(t.functionNameMetadata(name.value, index));
}
return functionNames;
}
function parseNameSectionLocals() {
var localNames = [];
var numbeOfFunctionsu32 = readU32();
var numbeOfFunctions = numbeOfFunctionsu32.value;
eatBytes(numbeOfFunctionsu32.nextIndex);
for (var i = 0; i < numbeOfFunctions; i++) {
var functionIndexu32 = readU32();
var functionIndex = functionIndexu32.value;
eatBytes(functionIndexu32.nextIndex);
var numLocalsu32 = readU32();
var numLocals = numLocalsu32.value;
eatBytes(numLocalsu32.nextIndex);
for (var _i4 = 0; _i4 < numLocals; _i4++) {
var localIndexu32 = readU32();
var localIndex = localIndexu32.value;
eatBytes(localIndexu32.nextIndex);
var name = readUTF8String();
eatBytes(name.nextIndex);
localNames.push(t.localNameMetadata(name.value, localIndex, functionIndex));
}
}
return localNames;
} // this is a custom section used for name resolution
// https://github.com/WebAssembly/design/blob/master/BinaryEncoding.md#name-section
function parseNameSection(remainingBytes) {
var nameMetadata = [];
var initialOffset = offset;
while (offset - initialOffset < remainingBytes) {
// name_type
var sectionTypeByte = readVaruint7();
eatBytes(sectionTypeByte.nextIndex); // name_payload_len
var subSectionSizeInBytesu32 = readVaruint32();
eatBytes(subSectionSizeInBytesu32.nextIndex);
switch (sectionTypeByte.value) {
// case 0: {
// TODO(sven): re-enable that
// Current status: it seems that when we decode the module's name
// no name_payload_len is used.
//
// See https://github.com/WebAssembly/design/blob/master/BinaryEncoding.md#name-section
//
// nameMetadata.push(...parseNameModule());
// break;
// }
case 1:
{
nameMetadata.push.apply(nameMetadata, _toConsumableArray(parseNameSectionFunctions()));
break;
}
case 2:
{
nameMetadata.push.apply(nameMetadata, _toConsumableArray(parseNameSectionLocals()));
break;
}
default:
{
// skip unknown subsection
eatBytes(subSectionSizeInBytesu32.value);
}
}
}
return nameMetadata;
} // this is a custom section used for information about the producers
// https://github.com/WebAssembly/tool-conventions/blob/master/ProducersSection.md
function parseProducersSection() {
var metadata = t.producersSectionMetadata([]); // field_count
var sectionTypeByte = readVaruint32();
eatBytes(sectionTypeByte.nextIndex);
dump([sectionTypeByte.value], "num of producers");
var fields = {
language: [],
"processed-by": [],
sdk: []
}; // fields
for (var fieldI = 0; fieldI < sectionTypeByte.value; fieldI++) {
// field_name
var fieldName = readUTF8String();
eatBytes(fieldName.nextIndex); // field_value_count
var valueCount = readVaruint32();
eatBytes(valueCount.nextIndex); // field_values
for (var producerI = 0; producerI < valueCount.value; producerI++) {
var producerName = readUTF8String();
eatBytes(producerName.nextIndex);
var producerVersion = readUTF8String();
eatBytes(producerVersion.nextIndex);
fields[fieldName.value].push(t.producerMetadataVersionedName(producerName.value, producerVersion.value));
}
metadata.producers.push(fields[fieldName.value]);
}
return metadata;
}
function parseGlobalSection(numberOfGlobals) {
var globals = [];
dump([numberOfGlobals], "num globals");
for (var i = 0; i < numberOfGlobals; i++) {
var _startLoc11 = getPosition();
var globalType = parseGlobalType();
/**
* Global expressions
*/
var init = [];
parseInstructionBlock(init);
var node = function () {
var endLoc = getPosition();
return t.withLoc(t.global(globalType, init), endLoc, _startLoc11);
}();
globals.push(node);
state.globalsInModule.push(node);
}
return globals;
}
function parseElemSection(numberOfElements) {
var elems = [];
dump([numberOfElements], "num elements");
for (var i = 0; i < numberOfElements; i++) {
var _startLoc12 = getPosition();
var tableindexu32 = readU32();
var tableindex = tableindexu32.value;
eatBytes(tableindexu32.nextIndex);
dump([tableindex], "table index");
/**
* Parse instructions
*/
var instr = [];
parseInstructionBlock(instr);
/**
* Parse ( vector function index ) *
*/
var indicesu32 = readU32();
var indices = indicesu32.value;
eatBytes(indicesu32.nextIndex);
dump([indices], "num indices");
var indexValues = [];
for (var _i5 = 0; _i5 < indices; _i5++) {
var indexu32 = readU32();
var index = indexu32.value;
eatBytes(indexu32.nextIndex);
dump([index], "index");
indexValues.push(t.indexLiteral(index));
}
var elemNode = function () {
var endLoc = getPosition();
return t.withLoc(t.elem(t.indexLiteral(tableindex), instr, indexValues), endLoc, _startLoc12);
}();
elems.push(elemNode);
}
return elems;
} // https://webassembly.github.io/spec/core/binary/types.html#memory-types
function parseMemoryType(i) {
var limits = parseLimits();
return t.memory(limits, t.indexLiteral(i));
} // https://webassembly.github.io/spec/binary/modules.html#table-section
function parseTableSection(numberOfElements) {
var tables = [];
dump([numberOfElements], "num elements");
for (var i = 0; i < numberOfElements; i++) {
var tablesNode = parseTableType(i);
state.tablesInModule.push(tablesNode);
tables.push(tablesNode);
}
return tables;
} // https://webassembly.github.io/spec/binary/modules.html#memory-section
function parseMemorySection(numberOfElements) {
var memories = [];
dump([numberOfElements], "num elements");
for (var i = 0; i < numberOfElements; i++) {
var memoryNode = parseMemoryType(i);
state.memoriesInModule.push(memoryNode);
memories.push(memoryNode);
}
return memories;
} // https://webassembly.github.io/spec/binary/modules.html#binary-startsec
function parseStartSection() {
var startLoc = getPosition();
var u32 = readU32();
var startFuncIndex = u32.value;
eatBytes(u32.nextIndex);
dump([startFuncIndex], "index");
return function () {
var endLoc = getPosition();
return t.withLoc(t.start(t.indexLiteral(startFuncIndex)), endLoc, startLoc);
}();
} // https://webassembly.github.io/spec/binary/modules.html#data-section
function parseDataSection(numberOfElements) {
var dataEntries = [];
dump([numberOfElements], "num elements");
for (var i = 0; i < numberOfElements; i++) {
var memoryIndexu32 = readU32();
var memoryIndex = memoryIndexu32.value;
eatBytes(memoryIndexu32.nextIndex);
dump([memoryIndex], "memory index");
var instrs = [];
parseInstructionBlock(instrs);
var hasExtraInstrs = instrs.filter(function (i) {
return i.id !== "end";
}).length !== 1;
if (hasExtraInstrs) {
throw new CompileError("data section offset must be a single instruction");
}
var bytes = parseVec(function (b) {
return b;
});
dump([], "init");
dataEntries.push(t.data(t.memIndexLiteral(memoryIndex), instrs[0], t.byteArray(bytes)));
}
return dataEntries;
} // https://webassembly.github.io/spec/binary/modules.html#binary-section
function parseSection(sectionIndex) {
var sectionId = readByte();
eatBytes(1);
if (sectionId >= sectionIndex || sectionIndex === constants.sections.custom) {
sectionIndex = sectionId + 1;
} else {
if (sectionId !== constants.sections.custom) throw new CompileError("Unexpected section: " + toHex(sectionId));
}
var nextSectionIndex = sectionIndex;
var startOffset = offset;
var startLoc = getPosition();
var u32 = readU32();
var sectionSizeInBytes = u32.value;
eatBytes(u32.nextIndex);
var sectionSizeInBytesNode = function () {
var endLoc = getPosition();
return t.withLoc(t.numberLiteralFromRaw(sectionSizeInBytes), endLoc, startLoc);
}();
switch (sectionId) {
case constants.sections.type:
{
dumpSep("section Type");
dump([sectionId], "section code");
dump([sectionSizeInBytes], "section size");
var _startLoc13 = getPosition();
var _u = readU32();
var numberOfTypes = _u.value;
eatBytes(_u.nextIndex);
var _metadata = t.sectionMetadata("type", startOffset, sectionSizeInBytesNode, function () {
var endLoc = getPosition();
return t.withLoc(t.numberLiteralFromRaw(numberOfTypes), endLoc, _startLoc13);
}());
var _nodes = parseTypeSection(numberOfTypes);
return {
nodes: _nodes,
metadata: _metadata,
nextSectionIndex: nextSectionIndex
};
}
case constants.sections.table:
{
dumpSep("section Table");
dump([sectionId], "section code");
dump([sectionSizeInBytes], "section size");
var _startLoc14 = getPosition();
var _u2 = readU32();
var numberOfTable = _u2.value;
eatBytes(_u2.nextIndex);
dump([numberOfTable], "num tables");
var _metadata2 = t.sectionMetadata("table", startOffset, sectionSizeInBytesNode, function () {
var endLoc = getPosition();
return t.withLoc(t.numberLiteralFromRaw(numberOfTable), endLoc, _startLoc14);
}());
var _nodes2 = parseTableSection(numberOfTable);
return {
nodes: _nodes2,
metadata: _metadata2,
nextSectionIndex: nextSectionIndex
};
}
case constants.sections.import:
{
dumpSep("section Import");
dump([sectionId], "section code");
dump([sectionSizeInBytes], "section size");
var _startLoc15 = getPosition();
var numberOfImportsu32 = readU32();
var numberOfImports = numberOfImportsu32.value;
eatBytes(numberOfImportsu32.nextIndex);
dump([numberOfImports], "number of imports");
var _metadata3 = t.sectionMetadata("import", startOffset, sectionSizeInBytesNode, function () {
var endLoc = getPosition();
return t.withLoc(t.numberLiteralFromRaw(numberOfImports), endLoc, _startLoc15);
}());
var _nodes3 = parseImportSection(numberOfImports);
return {
nodes: _nodes3,
metadata: _metadata3,
nextSectionIndex: nextSectionIndex
};
}
case constants.sections.func:
{
dumpSep("section Function");
dump([sectionId], "section code");
dump([sectionSizeInBytes], "section size");
var _startLoc16 = getPosition();
var numberOfFunctionsu32 = readU32();
var numberOfFunctions = numberOfFunctionsu32.value;
eatBytes(numberOfFunctionsu32.nextIndex);
var _metadata4 = t.sectionMetadata("func", startOffset, sectionSizeInBytesNode, function () {
var endLoc = getPosition();
return t.withLoc(t.numberLiteralFromRaw(numberOfFunctions), endLoc, _startLoc16);
}());
parseFuncSection(numberOfFunctions);
var _nodes4 = [];
return {
nodes: _nodes4,
metadata: _metadata4,
nextSectionIndex: nextSectionIndex
};
}
case constants.sections.export:
{
dumpSep("section Export");
dump([sectionId], "section code");
dump([sectionSizeInBytes], "section size");
var _startLoc17 = getPosition();
var _u3 = readU32();
var numberOfExport = _u3.value;
eatBytes(_u3.nextIndex);
var _metadata5 = t.sectionMetadata("export", startOffset, sectionSizeInBytesNode, function () {
var endLoc = getPosition();
return t.withLoc(t.numberLiteralFromRaw(numberOfExport), endLoc, _startLoc17);
}());
parseExportSection(numberOfExport);
var _nodes5 = [];
return {
nodes: _nodes5,
metadata: _metadata5,
nextSectionIndex: nextSectionIndex
};
}
case constants.sections.code:
{
dumpSep("section Code");
dump([sectionId], "section code");
dump([sectionSizeInBytes], "section size");
var _startLoc18 = getPosition();
var _u4 = readU32();
var numberOfFuncs = _u4.value;
eatBytes(_u4.nextIndex);
var _metadata6 = t.sectionMetadata("code", startOffset, sectionSizeInBytesNode, function () {
var endLoc = getPosition();
return t.withLoc(t.numberLiteralFromRaw(numberOfFuncs), endLoc, _startLoc18);
}());
if (opts.ignoreCodeSection === true) {
var remainingBytes = sectionSizeInBytes - _u4.nextIndex;
eatBytes(remainingBytes); // eat the entire section
} else {
parseCodeSection(numberOfFuncs);
}
var _nodes6 = [];
return {
nodes: _nodes6,
metadata: _metadata6,
nextSectionIndex: nextSectionIndex
};
}
case constants.sections.start:
{
dumpSep("section Start");
dump([sectionId], "section code");
dump([sectionSizeInBytes], "section size");
var _metadata7 = t.sectionMetadata("start", startOffset, sectionSizeInBytesNode);
var _nodes7 = [parseStartSection()];
return {
nodes: _nodes7,
metadata: _metadata7,
nextSectionIndex: nextSectionIndex
};
}
case constants.sections.element:
{
dumpSep("section Element");
dump([sectionId], "section code");
dump([sectionSizeInBytes], "section size");
var _startLoc19 = getPosition();
var numberOfElementsu32 = readU32();
var numberOfElements = numberOfElementsu32.value;
eatBytes(numberOfElementsu32.nextIndex);
var _metadata8 = t.sectionMetadata("element", startOffset, sectionSizeInBytesNode, function () {
var endLoc = getPosition();
return t.withLoc(t.numberLiteralFromRaw(numberOfElements), endLoc, _startLoc19);
}());
var _nodes8 = parseElemSection(numberOfElements);
return {
nodes: _nodes8,
metadata: _metadata8,
nextSectionIndex: nextSectionIndex
};
}
case constants.sections.global:
{
dumpSep("section Global");
dump([sectionId], "section code");
dump([sectionSizeInBytes], "section size");
var _startLoc20 = getPosition();
var numberOfGlobalsu32 = readU32();
var numberOfGlobals = numberOfGlobalsu32.value;
eatBytes(numberOfGlobalsu32.nextIndex);
var _metadata9 = t.sectionMetadata("global", startOffset, sectionSizeInBytesNode, function () {
var endLoc = getPosition();
return t.withLoc(t.numberLiteralFromRaw(numberOfGlobals), endLoc, _startLoc20);
}());
var _nodes9 = parseGlobalSection(numberOfGlobals);
return {
nodes: _nodes9,
metadata: _metadata9,
nextSectionIndex: nextSectionIndex
};
}
case constants.sections.memory:
{
dumpSep("section Memory");
dump([sectionId], "section code");
dump([sectionSizeInBytes], "section size");
var _startLoc21 = getPosition();
var _numberOfElementsu = readU32();
var _numberOfElements = _numberOfElementsu.value;
eatBytes(_numberOfElementsu.nextIndex);
var _metadata10 = t.sectionMetadata("memory", startOffset, sectionSizeInBytesNode, function () {
var endLoc = getPosition();
return t.withLoc(t.numberLiteralFromRaw(_numberOfElements), endLoc, _startLoc21);
}());
var _nodes10 = parseMemorySection(_numberOfElements);
return {
nodes: _nodes10,
metadata: _metadata10,
nextSectionIndex: nextSectionIndex
};
}
case constants.sections.data:
{
dumpSep("section Data");
dump([sectionId], "section code");
dump([sectionSizeInBytes], "section size");
var _metadata11 = t.sectionMetadata("data", startOffset, sectionSizeInBytesNode);
var _startLoc22 = getPosition();
var _numberOfElementsu2 = readU32();
var _numberOfElements2 = _numberOfElementsu2.value;
eatBytes(_numberOfElementsu2.nextIndex);
_metadata11.vectorOfSize = function () {
var endLoc = getPosition();
return t.withLoc(t.numberLiteralFromRaw(_numberOfElements2), endLoc, _startLoc22);
}();
if (opts.ignoreDataSection === true) {
var _remainingBytes = sectionSizeInBytes - _numberOfElementsu2.nextIndex;
eatBytes(_remainingBytes); // eat the entire section
dumpSep("ignore data (" + sectionSizeInBytes + " bytes)");
return {
nodes: [],
metadata: _metadata11,
nextSectionIndex: nextSectionIndex
};
} else {
var _nodes11 = parseDataSection(_numberOfElements2);
return {
nodes: _nodes11,
metadata: _metadata11,
nextSectionIndex: nextSectionIndex
};
}
}
case constants.sections.custom:
{
dumpSep("section Custom");
dump([sectionId], "section code");
dump([sectionSizeInBytes], "section size");
var _metadata12 = [t.sectionMetadata("custom", startOffset, sectionSizeInBytesNode)];
var sectionName = readUTF8String();
eatBytes(sectionName.nextIndex);
dump([], "section name (".concat(sectionName.value, ")"));
var _remainingBytes2 = sectionSizeInBytes - sectionName.nextIndex;
if (sectionName.value === "name") {
var initialOffset = offset;
try {
_metadata12.push.apply(_metadata12, _toConsumableArray(parseNameSection(_remainingBytes2)));
} catch (e) {
console.warn("Failed to decode custom \"name\" section @".concat(offset, "; ignoring (").concat(e.message, ")."));
eatBytes(offset - (initialOffset + _remainingBytes2));
}
} else if (sectionName.value === "producers") {
var _initialOffset = offset;
try {
_metadata12.push(parseProducersSection());
} catch (e) {
console.warn("Failed to decode custom \"producers\" section @".concat(offset, "; ignoring (").concat(e.message, ")."));
eatBytes(offset - (_initialOffset + _remainingBytes2));
}
} else {
// We don't parse the custom section
eatBytes(_remainingBytes2);
dumpSep("ignore custom " + JSON.stringify(sectionName.value) + " section (" + _remainingBytes2 + " bytes)");
}
return {
nodes: [],
metadata: _metadata12,
nextSectionIndex: nextSectionIndex
};
}
}
throw new CompileError("Unexpected section: " + toHex(sectionId));
}
parseModuleHeader();
parseVersion();
var moduleFields = [];
var sectionIndex = 0;
var moduleMetadata = {
sections: [],
functionNames: [],
localNames: [],
producers: []
};
/**
* All the generate declaration are going to be stored in our state
*/
while (offset < buf.length) {
var _parseSection = parseSection(sectionIndex),
_nodes12 = _parseSection.nodes,
_metadata13 = _parseSection.metadata,
nextSectionIndex = _parseSection.nextSectionIndex;
moduleFields.push.apply(moduleFields, _toConsumableArray(_nodes12));
var metadataArray = Array.isArray(_metadata13) ? _metadata13 : [_metadata13];
metadataArray.forEach(function (metadataItem) {
if (metadataItem.type === "FunctionNameMetadata") {
moduleMetadata.functionNames.push(metadataItem);
} else if (metadataItem.type === "LocalNameMetadata") {
moduleMetadata.localNames.push(metadataItem);
} else if (metadataItem.type === "ProducersSectionMetadata") {
moduleMetadata.producers.push(metadataItem);
} else {
moduleMetadata.sections.push(metadataItem);
}
}); // Ignore custom section
if (nextSectionIndex) {
sectionIndex = nextSectionIndex;
}
}
/**
* Transform the state into AST nodes
*/
var funcIndex = 0;
state.functionsInModule.forEach(function (func) {
var params = func.signature.params;
var result = func.signature.result;
var body = []; // External functions doesn't provide any code, can skip it here
if (func.isExternal === true) {
return;
}
var decodedElementInCodeSection = state.elementsInCodeSection[funcIndex];
if (opts.ignoreCodeSection === false) {
if (typeof decodedElementInCodeSection === "undefined") {
throw new CompileError("func " + toHex(funcIndex) + " code not found");
}
body = decodedElementInCodeSection.code;
}
funcIndex++;
var funcNode = t.func(func.id, t.signature(params, result), body);
if (func.isExternal === true) {
funcNode.isExternal = func.isExternal;
} // Add function position in the binary if possible
if (opts.ignoreCodeSection === false) {
var _startLoc23 = decodedElementInCodeSection.startLoc,
endLoc = decodedElementInCodeSection.endLoc,
bodySize = decodedElementInCodeSection.bodySize;
funcNode = t.withLoc(funcNode, endLoc, _startLoc23);
funcNode.metadata = {
bodySize: bodySize
};
}
moduleFields.push(funcNode);
});
state.elementsInExportSection.forEach(function (moduleExport) {
/**
* If the export has no id, we won't be able to call it from the outside
* so we can omit it
*/
if (moduleExport.id != null) {
moduleFields.push(t.withLoc(t.moduleExport(moduleExport.name, t.moduleExportDescr(moduleExport.type, moduleExport.id)), moduleExport.endLoc, moduleExport.startLoc));
}
});
dumpSep("end of program");
var module = t.module(null, moduleFields, t.moduleMetadata(moduleMetadata.sections, moduleMetadata.functionNames, moduleMetadata.localNames, moduleMetadata.producers));
return t.program([module]);
}
Event Timeline
Log In to Comment