0.2.0 - Mid migration

This commit is contained in:
Daniel Mason 2022-04-25 14:47:15 +12:00
parent 139e6a915e
commit 7e38fdbd7d
42393 changed files with 5358157 additions and 62 deletions

View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2018 Sven Sauleau <sven@sauleau.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -0,0 +1,378 @@
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
// TODO(sven): add flow in here
import { isSignature, isNumberLiteral } from "@webassemblyjs/ast";
export function moduleContextFromModuleAST(m) {
var moduleContext = new ModuleContext();
if (!(m.type === "Module")) {
throw new Error('m.type === "Module"' + " error: " + (undefined || "unknown"));
}
m.fields.forEach(function (field) {
switch (field.type) {
case "Start":
{
moduleContext.setStart(field.index);
break;
}
case "TypeInstruction":
{
moduleContext.addType(field);
break;
}
case "Func":
{
moduleContext.addFunction(field);
break;
}
case "Global":
{
moduleContext.defineGlobal(field);
break;
}
case "ModuleImport":
{
switch (field.descr.type) {
case "GlobalType":
{
moduleContext.importGlobal(field.descr.valtype, field.descr.mutability);
break;
}
case "Memory":
{
moduleContext.addMemory(field.descr.limits.min, field.descr.limits.max);
break;
}
case "FuncImportDescr":
{
moduleContext.importFunction(field.descr);
break;
}
case "Table":
{
// FIXME(sven): not implemented yet
break;
}
default:
throw new Error("Unsupported ModuleImport of type " + JSON.stringify(field.descr.type));
}
break;
}
case "Memory":
{
moduleContext.addMemory(field.limits.min, field.limits.max);
break;
}
}
});
return moduleContext;
}
/**
* Module context for type checking
*/
export var ModuleContext =
/*#__PURE__*/
function () {
function ModuleContext() {
_classCallCheck(this, ModuleContext);
this.funcs = [];
this.funcsOffsetByIdentifier = [];
this.types = [];
this.globals = [];
this.globalsOffsetByIdentifier = [];
this.mems = []; // Current stack frame
this.locals = [];
this.labels = [];
this.return = [];
this.debugName = "unknown";
this.start = null;
}
/**
* Set start segment
*/
_createClass(ModuleContext, [{
key: "setStart",
value: function setStart(index) {
this.start = index.value;
}
/**
* Get start function
*/
}, {
key: "getStart",
value: function getStart() {
return this.start;
}
/**
* Reset the active stack frame
*/
}, {
key: "newContext",
value: function newContext(debugName, expectedResult) {
this.locals = [];
this.labels = [expectedResult];
this.return = expectedResult;
this.debugName = debugName;
}
/**
* Functions
*/
}, {
key: "addFunction",
value: function addFunction(func
/*: Func*/
) {
// eslint-disable-next-line prefer-const
var _ref = func.signature || {},
_ref$params = _ref.params,
args = _ref$params === void 0 ? [] : _ref$params,
_ref$results = _ref.results,
result = _ref$results === void 0 ? [] : _ref$results;
args = args.map(function (arg) {
return arg.valtype;
});
this.funcs.push({
args: args,
result: result
});
if (typeof func.name !== "undefined") {
this.funcsOffsetByIdentifier[func.name.value] = this.funcs.length - 1;
}
}
}, {
key: "importFunction",
value: function importFunction(funcimport) {
if (isSignature(funcimport.signature)) {
// eslint-disable-next-line prefer-const
var _funcimport$signature = funcimport.signature,
args = _funcimport$signature.params,
result = _funcimport$signature.results;
args = args.map(function (arg) {
return arg.valtype;
});
this.funcs.push({
args: args,
result: result
});
} else {
if (!isNumberLiteral(funcimport.signature)) {
throw new Error('isNumberLiteral(funcimport.signature)' + " error: " + (undefined || "unknown"));
}
var typeId = funcimport.signature.value;
if (!this.hasType(typeId)) {
throw new Error('this.hasType(typeId)' + " error: " + (undefined || "unknown"));
}
var signature = this.getType(typeId);
this.funcs.push({
args: signature.params.map(function (arg) {
return arg.valtype;
}),
result: signature.results
});
}
if (typeof funcimport.id !== "undefined") {
// imports are first, we can assume their index in the array
this.funcsOffsetByIdentifier[funcimport.id.value] = this.funcs.length - 1;
}
}
}, {
key: "hasFunction",
value: function hasFunction(index) {
return typeof this.getFunction(index) !== "undefined";
}
}, {
key: "getFunction",
value: function getFunction(index) {
if (typeof index !== "number") {
throw new Error("getFunction only supported for number index");
}
return this.funcs[index];
}
}, {
key: "getFunctionOffsetByIdentifier",
value: function getFunctionOffsetByIdentifier(name) {
if (!(typeof name === "string")) {
throw new Error('typeof name === "string"' + " error: " + (undefined || "unknown"));
}
return this.funcsOffsetByIdentifier[name];
}
/**
* Labels
*/
}, {
key: "addLabel",
value: function addLabel(result) {
this.labels.unshift(result);
}
}, {
key: "hasLabel",
value: function hasLabel(index) {
return this.labels.length > index && index >= 0;
}
}, {
key: "getLabel",
value: function getLabel(index) {
return this.labels[index];
}
}, {
key: "popLabel",
value: function popLabel() {
this.labels.shift();
}
/**
* Locals
*/
}, {
key: "hasLocal",
value: function hasLocal(index) {
return typeof this.getLocal(index) !== "undefined";
}
}, {
key: "getLocal",
value: function getLocal(index) {
return this.locals[index];
}
}, {
key: "addLocal",
value: function addLocal(type) {
this.locals.push(type);
}
/**
* Types
*/
}, {
key: "addType",
value: function addType(type) {
if (!(type.functype.type === "Signature")) {
throw new Error('type.functype.type === "Signature"' + " error: " + (undefined || "unknown"));
}
this.types.push(type.functype);
}
}, {
key: "hasType",
value: function hasType(index) {
return this.types[index] !== undefined;
}
}, {
key: "getType",
value: function getType(index) {
return this.types[index];
}
/**
* Globals
*/
}, {
key: "hasGlobal",
value: function hasGlobal(index) {
return this.globals.length > index && index >= 0;
}
}, {
key: "getGlobal",
value: function getGlobal(index) {
return this.globals[index].type;
}
}, {
key: "getGlobalOffsetByIdentifier",
value: function getGlobalOffsetByIdentifier(name) {
if (!(typeof name === "string")) {
throw new Error('typeof name === "string"' + " error: " + (undefined || "unknown"));
}
return this.globalsOffsetByIdentifier[name];
}
}, {
key: "defineGlobal",
value: function defineGlobal(global
/*: Global*/
) {
var type = global.globalType.valtype;
var mutability = global.globalType.mutability;
this.globals.push({
type: type,
mutability: mutability
});
if (typeof global.name !== "undefined") {
this.globalsOffsetByIdentifier[global.name.value] = this.globals.length - 1;
}
}
}, {
key: "importGlobal",
value: function importGlobal(type, mutability) {
this.globals.push({
type: type,
mutability: mutability
});
}
}, {
key: "isMutableGlobal",
value: function isMutableGlobal(index) {
return this.globals[index].mutability === "var";
}
}, {
key: "isImmutableGlobal",
value: function isImmutableGlobal(index) {
return this.globals[index].mutability === "const";
}
/**
* Memories
*/
}, {
key: "hasMemory",
value: function hasMemory(index) {
return this.mems.length > index && index >= 0;
}
}, {
key: "addMemory",
value: function addMemory(min, max) {
this.mems.push({
min: min,
max: max
});
}
}, {
key: "getMemory",
value: function getMemory(index) {
return this.mems[index];
}
}]);
return ModuleContext;
}();

View file

@ -0,0 +1,389 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.moduleContextFromModuleAST = moduleContextFromModuleAST;
exports.ModuleContext = void 0;
var _ast = require("@webassemblyjs/ast");
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
function moduleContextFromModuleAST(m) {
var moduleContext = new ModuleContext();
if (!(m.type === "Module")) {
throw new Error('m.type === "Module"' + " error: " + (undefined || "unknown"));
}
m.fields.forEach(function (field) {
switch (field.type) {
case "Start":
{
moduleContext.setStart(field.index);
break;
}
case "TypeInstruction":
{
moduleContext.addType(field);
break;
}
case "Func":
{
moduleContext.addFunction(field);
break;
}
case "Global":
{
moduleContext.defineGlobal(field);
break;
}
case "ModuleImport":
{
switch (field.descr.type) {
case "GlobalType":
{
moduleContext.importGlobal(field.descr.valtype, field.descr.mutability);
break;
}
case "Memory":
{
moduleContext.addMemory(field.descr.limits.min, field.descr.limits.max);
break;
}
case "FuncImportDescr":
{
moduleContext.importFunction(field.descr);
break;
}
case "Table":
{
// FIXME(sven): not implemented yet
break;
}
default:
throw new Error("Unsupported ModuleImport of type " + JSON.stringify(field.descr.type));
}
break;
}
case "Memory":
{
moduleContext.addMemory(field.limits.min, field.limits.max);
break;
}
}
});
return moduleContext;
}
/**
* Module context for type checking
*/
var ModuleContext =
/*#__PURE__*/
function () {
function ModuleContext() {
_classCallCheck(this, ModuleContext);
this.funcs = [];
this.funcsOffsetByIdentifier = [];
this.types = [];
this.globals = [];
this.globalsOffsetByIdentifier = [];
this.mems = []; // Current stack frame
this.locals = [];
this.labels = [];
this.return = [];
this.debugName = "unknown";
this.start = null;
}
/**
* Set start segment
*/
_createClass(ModuleContext, [{
key: "setStart",
value: function setStart(index) {
this.start = index.value;
}
/**
* Get start function
*/
}, {
key: "getStart",
value: function getStart() {
return this.start;
}
/**
* Reset the active stack frame
*/
}, {
key: "newContext",
value: function newContext(debugName, expectedResult) {
this.locals = [];
this.labels = [expectedResult];
this.return = expectedResult;
this.debugName = debugName;
}
/**
* Functions
*/
}, {
key: "addFunction",
value: function addFunction(func
/*: Func*/
) {
// eslint-disable-next-line prefer-const
var _ref = func.signature || {},
_ref$params = _ref.params,
args = _ref$params === void 0 ? [] : _ref$params,
_ref$results = _ref.results,
result = _ref$results === void 0 ? [] : _ref$results;
args = args.map(function (arg) {
return arg.valtype;
});
this.funcs.push({
args: args,
result: result
});
if (typeof func.name !== "undefined") {
this.funcsOffsetByIdentifier[func.name.value] = this.funcs.length - 1;
}
}
}, {
key: "importFunction",
value: function importFunction(funcimport) {
if ((0, _ast.isSignature)(funcimport.signature)) {
// eslint-disable-next-line prefer-const
var _funcimport$signature = funcimport.signature,
args = _funcimport$signature.params,
result = _funcimport$signature.results;
args = args.map(function (arg) {
return arg.valtype;
});
this.funcs.push({
args: args,
result: result
});
} else {
if (!(0, _ast.isNumberLiteral)(funcimport.signature)) {
throw new Error('isNumberLiteral(funcimport.signature)' + " error: " + (undefined || "unknown"));
}
var typeId = funcimport.signature.value;
if (!this.hasType(typeId)) {
throw new Error('this.hasType(typeId)' + " error: " + (undefined || "unknown"));
}
var signature = this.getType(typeId);
this.funcs.push({
args: signature.params.map(function (arg) {
return arg.valtype;
}),
result: signature.results
});
}
if (typeof funcimport.id !== "undefined") {
// imports are first, we can assume their index in the array
this.funcsOffsetByIdentifier[funcimport.id.value] = this.funcs.length - 1;
}
}
}, {
key: "hasFunction",
value: function hasFunction(index) {
return typeof this.getFunction(index) !== "undefined";
}
}, {
key: "getFunction",
value: function getFunction(index) {
if (typeof index !== "number") {
throw new Error("getFunction only supported for number index");
}
return this.funcs[index];
}
}, {
key: "getFunctionOffsetByIdentifier",
value: function getFunctionOffsetByIdentifier(name) {
if (!(typeof name === "string")) {
throw new Error('typeof name === "string"' + " error: " + (undefined || "unknown"));
}
return this.funcsOffsetByIdentifier[name];
}
/**
* Labels
*/
}, {
key: "addLabel",
value: function addLabel(result) {
this.labels.unshift(result);
}
}, {
key: "hasLabel",
value: function hasLabel(index) {
return this.labels.length > index && index >= 0;
}
}, {
key: "getLabel",
value: function getLabel(index) {
return this.labels[index];
}
}, {
key: "popLabel",
value: function popLabel() {
this.labels.shift();
}
/**
* Locals
*/
}, {
key: "hasLocal",
value: function hasLocal(index) {
return typeof this.getLocal(index) !== "undefined";
}
}, {
key: "getLocal",
value: function getLocal(index) {
return this.locals[index];
}
}, {
key: "addLocal",
value: function addLocal(type) {
this.locals.push(type);
}
/**
* Types
*/
}, {
key: "addType",
value: function addType(type) {
if (!(type.functype.type === "Signature")) {
throw new Error('type.functype.type === "Signature"' + " error: " + (undefined || "unknown"));
}
this.types.push(type.functype);
}
}, {
key: "hasType",
value: function hasType(index) {
return this.types[index] !== undefined;
}
}, {
key: "getType",
value: function getType(index) {
return this.types[index];
}
/**
* Globals
*/
}, {
key: "hasGlobal",
value: function hasGlobal(index) {
return this.globals.length > index && index >= 0;
}
}, {
key: "getGlobal",
value: function getGlobal(index) {
return this.globals[index].type;
}
}, {
key: "getGlobalOffsetByIdentifier",
value: function getGlobalOffsetByIdentifier(name) {
if (!(typeof name === "string")) {
throw new Error('typeof name === "string"' + " error: " + (undefined || "unknown"));
}
return this.globalsOffsetByIdentifier[name];
}
}, {
key: "defineGlobal",
value: function defineGlobal(global
/*: Global*/
) {
var type = global.globalType.valtype;
var mutability = global.globalType.mutability;
this.globals.push({
type: type,
mutability: mutability
});
if (typeof global.name !== "undefined") {
this.globalsOffsetByIdentifier[global.name.value] = this.globals.length - 1;
}
}
}, {
key: "importGlobal",
value: function importGlobal(type, mutability) {
this.globals.push({
type: type,
mutability: mutability
});
}
}, {
key: "isMutableGlobal",
value: function isMutableGlobal(index) {
return this.globals[index].mutability === "var";
}
}, {
key: "isImmutableGlobal",
value: function isImmutableGlobal(index) {
return this.globals[index].mutability === "const";
}
/**
* Memories
*/
}, {
key: "hasMemory",
value: function hasMemory(index) {
return this.mems.length > index && index >= 0;
}
}, {
key: "addMemory",
value: function addMemory(min, max) {
this.mems.push({
min: min,
max: max
});
}
}, {
key: "getMemory",
value: function getMemory(index) {
return this.mems[index];
}
}]);
return ModuleContext;
}();
exports.ModuleContext = ModuleContext;

View file

@ -0,0 +1,27 @@
{
"name": "@webassemblyjs/helper-module-context",
"version": "1.9.0",
"description": "",
"main": "lib/index.js",
"module": "esm/index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "https://github.com/xtuc/webassemblyjs.git"
},
"dependencies": {
"@webassemblyjs/ast": "1.9.0"
},
"devDependencies": {
"@webassemblyjs/wast-parser": "1.9.0",
"mamacro": "^0.0.7"
},
"publishConfig": {
"access": "public"
},
"author": "Sven Sauleau",
"license": "MIT",
"gitHead": "0440b420888c1f7701eb9762ec657775506b87d8"
}

View file

@ -0,0 +1,287 @@
// TODO(sven): add flow in here
import { isSignature, isNumberLiteral } from "@webassemblyjs/ast";
import { assert } from "mamacro";
export function moduleContextFromModuleAST(m) {
const moduleContext = new ModuleContext();
assert(m.type === "Module");
m.fields.forEach(field => {
switch (field.type) {
case "Start": {
moduleContext.setStart(field.index);
break;
}
case "TypeInstruction": {
moduleContext.addType(field);
break;
}
case "Func": {
moduleContext.addFunction(field);
break;
}
case "Global": {
moduleContext.defineGlobal(field);
break;
}
case "ModuleImport": {
switch (field.descr.type) {
case "GlobalType": {
moduleContext.importGlobal(
field.descr.valtype,
field.descr.mutability
);
break;
}
case "Memory": {
moduleContext.addMemory(
field.descr.limits.min,
field.descr.limits.max
);
break;
}
case "FuncImportDescr": {
moduleContext.importFunction(field.descr);
break;
}
case "Table": {
// FIXME(sven): not implemented yet
break;
}
default:
throw new Error(
"Unsupported ModuleImport of type " +
JSON.stringify(field.descr.type)
);
}
break;
}
case "Memory": {
moduleContext.addMemory(field.limits.min, field.limits.max);
break;
}
}
});
return moduleContext;
}
/**
* Module context for type checking
*/
export class ModuleContext {
constructor() {
this.funcs = [];
this.funcsOffsetByIdentifier = [];
this.types = [];
this.globals = [];
this.globalsOffsetByIdentifier = [];
this.mems = [];
// Current stack frame
this.locals = [];
this.labels = [];
this.return = [];
this.debugName = "unknown";
this.start = null;
}
/**
* Set start segment
*/
setStart(index) {
this.start = index.value;
}
/**
* Get start function
*/
getStart() {
return this.start;
}
/**
* Reset the active stack frame
*/
newContext(debugName, expectedResult) {
this.locals = [];
this.labels = [expectedResult];
this.return = expectedResult;
this.debugName = debugName;
}
/**
* Functions
*/
addFunction(func /*: Func*/) {
// eslint-disable-next-line prefer-const
let { params: args = [], results: result = [] } = func.signature || {};
args = args.map(arg => arg.valtype);
this.funcs.push({ args, result });
if (typeof func.name !== "undefined") {
this.funcsOffsetByIdentifier[func.name.value] = this.funcs.length - 1;
}
}
importFunction(funcimport) {
if (isSignature(funcimport.signature)) {
// eslint-disable-next-line prefer-const
let { params: args, results: result } = funcimport.signature;
args = args.map(arg => arg.valtype);
this.funcs.push({ args, result });
} else {
assert(isNumberLiteral(funcimport.signature));
const typeId = funcimport.signature.value;
assert(this.hasType(typeId));
const signature = this.getType(typeId);
this.funcs.push({
args: signature.params.map(arg => arg.valtype),
result: signature.results
});
}
if (typeof funcimport.id !== "undefined") {
// imports are first, we can assume their index in the array
this.funcsOffsetByIdentifier[funcimport.id.value] = this.funcs.length - 1;
}
}
hasFunction(index) {
return typeof this.getFunction(index) !== "undefined";
}
getFunction(index) {
if (typeof index !== "number") {
throw new Error("getFunction only supported for number index");
}
return this.funcs[index];
}
getFunctionOffsetByIdentifier(name) {
assert(typeof name === "string");
return this.funcsOffsetByIdentifier[name];
}
/**
* Labels
*/
addLabel(result) {
this.labels.unshift(result);
}
hasLabel(index) {
return this.labels.length > index && index >= 0;
}
getLabel(index) {
return this.labels[index];
}
popLabel() {
this.labels.shift();
}
/**
* Locals
*/
hasLocal(index) {
return typeof this.getLocal(index) !== "undefined";
}
getLocal(index) {
return this.locals[index];
}
addLocal(type) {
this.locals.push(type);
}
/**
* Types
*/
addType(type) {
assert(type.functype.type === "Signature");
this.types.push(type.functype);
}
hasType(index) {
return this.types[index] !== undefined;
}
getType(index) {
return this.types[index];
}
/**
* Globals
*/
hasGlobal(index) {
return this.globals.length > index && index >= 0;
}
getGlobal(index) {
return this.globals[index].type;
}
getGlobalOffsetByIdentifier(name) {
assert(typeof name === "string");
return this.globalsOffsetByIdentifier[name];
}
defineGlobal(global /*: Global*/) {
const type = global.globalType.valtype;
const mutability = global.globalType.mutability;
this.globals.push({ type, mutability });
if (typeof global.name !== "undefined") {
this.globalsOffsetByIdentifier[global.name.value] =
this.globals.length - 1;
}
}
importGlobal(type, mutability) {
this.globals.push({ type, mutability });
}
isMutableGlobal(index) {
return this.globals[index].mutability === "var";
}
isImmutableGlobal(index) {
return this.globals[index].mutability === "const";
}
/**
* Memories
*/
hasMemory(index) {
return this.mems.length > index && index >= 0;
}
addMemory(min, max) {
this.mems.push({ min, max });
}
getMemory(index) {
return this.mems[index];
}
}

View file

@ -0,0 +1,100 @@
const { assert } = require("chai");
const { parse } = require("@webassemblyjs/wast-parser");
const { moduleContextFromModuleAST } = require("../lib");
const contextFromWast = wast => moduleContextFromModuleAST(parse(wast).body[0]);
describe("module context", () => {
describe("start segment", () => {
it("should return the start function offset", () => {
const context = contextFromWast(`
(module
(func)
(func)
(start 1)
)
`);
assert.isOk(context.getStart());
assert.typeOf(context.getStart(), "number");
assert.equal(context.getStart(), 1);
});
it("should return null if no start function", () => {
const context = contextFromWast(`
(module (func))
`);
assert.isNull(context.getStart());
});
it("should retrive the type of implemented functions", () => {
const context = contextFromWast(`
(module
(func (param i32) (result i64))
(func (param i64) (result i32))
(func (result i64))
(func)
)
`);
assert.deepEqual(context.getFunction(0), {
args: ["i32"],
result: ["i64"]
});
assert.deepEqual(context.getFunction(1), {
args: ["i64"],
result: ["i32"]
});
assert.deepEqual(context.getFunction(2), { args: [], result: ["i64"] });
assert.deepEqual(context.getFunction(3), { args: [], result: [] });
});
it("should retrive the type of imported functions", () => {
const context = contextFromWast(`
(module
(import "a" "a" (func (param i32) (result i32)))
(import "a" "b" (func (result i64)))
(import "a" "c" (func))
(func (result f32))
)
`);
assert.deepEqual(context.getFunction(0), {
args: ["i32"],
result: ["i32"]
});
assert.deepEqual(context.getFunction(1), {
args: [],
result: ["i64"]
});
assert.deepEqual(context.getFunction(2), { args: [], result: [] });
assert.deepEqual(context.getFunction(3), { args: [], result: ["f32"] });
});
it("should retrive the type of functions with type ref", () => {
const context = contextFromWast(`
(module
(type (func (param i32) (result i32)))
(type (func (result i64)))
(type (func))
(import "a" "a" (func (type 0)))
(import "a" "b" (func (type 1)))
(func (type 2))
)
`);
assert.deepEqual(context.getFunction(0), {
args: ["i32"],
result: ["i32"]
});
assert.deepEqual(context.getFunction(1), {
args: [],
result: ["i64"]
});
assert.deepEqual(context.getFunction(2), { args: [], result: [] });
});
});
});