763 lines
17 KiB
JavaScript
763 lines
17 KiB
JavaScript
const instanceTestFactory = [
|
|
[
|
|
"Empty module without imports argument",
|
|
function() {
|
|
return {
|
|
buffer: emptyModuleBinary,
|
|
args: [],
|
|
exports: {},
|
|
verify: () => {},
|
|
};
|
|
}
|
|
],
|
|
|
|
[
|
|
"Empty module with undefined imports argument",
|
|
function() {
|
|
return {
|
|
buffer: emptyModuleBinary,
|
|
args: [undefined],
|
|
exports: {},
|
|
verify: () => {},
|
|
};
|
|
}
|
|
],
|
|
|
|
[
|
|
"Empty module with empty imports argument",
|
|
function() {
|
|
return {
|
|
buffer: emptyModuleBinary,
|
|
args: [{}],
|
|
exports: {},
|
|
verify: () => {},
|
|
};
|
|
}
|
|
],
|
|
|
|
[
|
|
"getter order for imports object",
|
|
function() {
|
|
const builder = new WasmModuleBuilder();
|
|
builder.addImportedGlobal("module", "global1", kWasmI32);
|
|
builder.addImportedGlobal("module2", "global3", kWasmI32);
|
|
builder.addImportedMemory("module", "memory", 0, 128);
|
|
builder.addImportedGlobal("module", "global2", kWasmI32);
|
|
const buffer = builder.toBuffer();
|
|
const order = [];
|
|
|
|
const imports = {
|
|
get module() {
|
|
order.push("module getter");
|
|
return {
|
|
get global1() {
|
|
order.push("global1 getter");
|
|
return 0;
|
|
},
|
|
get global2() {
|
|
order.push("global2 getter");
|
|
return 0;
|
|
},
|
|
get memory() {
|
|
order.push("memory getter");
|
|
return new WebAssembly.Memory({ "initial": 64, maximum: 128 });
|
|
},
|
|
}
|
|
},
|
|
get module2() {
|
|
order.push("module2 getter");
|
|
return {
|
|
get global3() {
|
|
order.push("global3 getter");
|
|
return 0;
|
|
},
|
|
}
|
|
},
|
|
};
|
|
|
|
const expected = [
|
|
"module getter",
|
|
"global1 getter",
|
|
"module2 getter",
|
|
"global3 getter",
|
|
"module getter",
|
|
"memory getter",
|
|
"module getter",
|
|
"global2 getter",
|
|
];
|
|
return {
|
|
buffer,
|
|
args: [imports],
|
|
exports: {},
|
|
verify: () => assert_array_equals(order, expected),
|
|
};
|
|
}
|
|
],
|
|
|
|
[
|
|
"imports",
|
|
function() {
|
|
const builder = new WasmModuleBuilder();
|
|
|
|
builder.addImport("module", "fn", kSig_v_v);
|
|
builder.addImportedGlobal("module", "global", kWasmI32);
|
|
builder.addImportedMemory("module", "memory", 0, 128);
|
|
builder.addImportedTable("module", "table", 0, 128);
|
|
|
|
const buffer = builder.toBuffer();
|
|
const imports = {
|
|
"module": {
|
|
"fn": function() {},
|
|
"global": 0,
|
|
"memory": new WebAssembly.Memory({ "initial": 64, maximum: 128 }),
|
|
"table": new WebAssembly.Table({ "element": "anyfunc", "initial": 64, maximum: 128 }),
|
|
},
|
|
get "module2"() {
|
|
assert_unreached("Should not get modules that are not imported");
|
|
},
|
|
};
|
|
|
|
return {
|
|
buffer,
|
|
args: [imports],
|
|
exports: {},
|
|
verify: () => {},
|
|
};
|
|
}
|
|
],
|
|
|
|
[
|
|
"imports with empty module names",
|
|
function() {
|
|
const builder = new WasmModuleBuilder();
|
|
|
|
builder.addImport("", "fn", kSig_v_v);
|
|
builder.addImportedGlobal("", "global", kWasmI32);
|
|
builder.addImportedMemory("", "memory", 0, 128);
|
|
builder.addImportedTable("", "table", 0, 128);
|
|
|
|
const buffer = builder.toBuffer();
|
|
const imports = {
|
|
"": {
|
|
"fn": function() {},
|
|
"global": 0,
|
|
"memory": new WebAssembly.Memory({ "initial": 64, maximum: 128 }),
|
|
"table": new WebAssembly.Table({ "element": "anyfunc", "initial": 64, maximum: 128 }),
|
|
},
|
|
};
|
|
|
|
return {
|
|
buffer,
|
|
args: [imports],
|
|
exports: {},
|
|
verify: () => {},
|
|
};
|
|
}
|
|
],
|
|
|
|
[
|
|
"imports with empty names",
|
|
function() {
|
|
const builder = new WasmModuleBuilder();
|
|
|
|
builder.addImport("a", "", kSig_v_v);
|
|
builder.addImportedGlobal("b", "", kWasmI32);
|
|
builder.addImportedMemory("c", "", 0, 128);
|
|
builder.addImportedTable("d", "", 0, 128);
|
|
|
|
const buffer = builder.toBuffer();
|
|
const imports = {
|
|
"a": { "": function() {} },
|
|
"b": { "": 0 },
|
|
"c": { "": new WebAssembly.Memory({ "initial": 64, maximum: 128 }) },
|
|
"d": { "": new WebAssembly.Table({ "element": "anyfunc", "initial": 64, maximum: 128 }) },
|
|
};
|
|
|
|
return {
|
|
buffer,
|
|
args: [imports],
|
|
exports: {},
|
|
verify: () => {},
|
|
};
|
|
}
|
|
],
|
|
|
|
[
|
|
"exports with empty name: function",
|
|
function() {
|
|
const builder = new WasmModuleBuilder();
|
|
|
|
builder
|
|
.addFunction("", kSig_v_d)
|
|
.addBody([])
|
|
.exportFunc();
|
|
|
|
const buffer = builder.toBuffer();
|
|
|
|
const exports = {
|
|
"": { "kind": "function", "name": "0", "length": 1 },
|
|
};
|
|
|
|
return {
|
|
buffer,
|
|
args: [],
|
|
exports,
|
|
verify: () => {},
|
|
};
|
|
}
|
|
],
|
|
|
|
[
|
|
"exports with empty name: table",
|
|
function() {
|
|
const builder = new WasmModuleBuilder();
|
|
|
|
builder.setTableBounds(1);
|
|
builder.addExportOfKind("", kExternalTable, 0);
|
|
|
|
const buffer = builder.toBuffer();
|
|
|
|
const exports = {
|
|
"": { "kind": "table", "length": 1 },
|
|
};
|
|
|
|
return {
|
|
buffer,
|
|
args: [],
|
|
exports,
|
|
verify: () => {},
|
|
};
|
|
}
|
|
],
|
|
|
|
[
|
|
"exports with empty name: global",
|
|
function() {
|
|
const builder = new WasmModuleBuilder();
|
|
|
|
builder.addGlobal(kWasmI32, true)
|
|
.exportAs("")
|
|
.init = wasmI32Const(7);
|
|
|
|
const buffer = builder.toBuffer();
|
|
|
|
const exports = {
|
|
"": { "kind": "global", "value": 7 },
|
|
};
|
|
|
|
return {
|
|
buffer,
|
|
args: [],
|
|
exports,
|
|
verify: () => {},
|
|
};
|
|
}
|
|
],
|
|
|
|
[
|
|
"No imports",
|
|
function() {
|
|
const builder = new WasmModuleBuilder();
|
|
|
|
builder
|
|
.addFunction("fn", kSig_v_d)
|
|
.addBody([])
|
|
.exportFunc();
|
|
builder
|
|
.addFunction("fn2", kSig_v_v)
|
|
.addBody([])
|
|
.exportFunc();
|
|
|
|
builder.setTableBounds(1);
|
|
builder.addExportOfKind("table", kExternalTable, 0);
|
|
|
|
builder.addGlobal(kWasmI32, true)
|
|
.exportAs("global")
|
|
.init = wasmI32Const(7);
|
|
builder.addGlobal(kWasmF64, true)
|
|
.exportAs("global2")
|
|
.init = wasmF64Const(1.2);
|
|
|
|
builder.addMemory(4, 8, true);
|
|
|
|
const buffer = builder.toBuffer();
|
|
|
|
const exports = {
|
|
"fn": { "kind": "function", "name": "0", "length": 1 },
|
|
"fn2": { "kind": "function", "name": "1", "length": 0 },
|
|
"table": { "kind": "table", "length": 1 },
|
|
"global": { "kind": "global", "value": 7 },
|
|
"global2": { "kind": "global", "value": 1.2 },
|
|
"memory": { "kind": "memory", "size": 4 },
|
|
};
|
|
|
|
return {
|
|
buffer,
|
|
args: [],
|
|
exports,
|
|
verify: () => {},
|
|
};
|
|
}
|
|
],
|
|
|
|
[
|
|
"exports and imports",
|
|
function() {
|
|
const value = 102;
|
|
|
|
const builder = new WasmModuleBuilder();
|
|
|
|
const index = builder.addImportedGlobal("module", "global", kWasmI32);
|
|
builder
|
|
.addFunction("fn", kSig_i_v)
|
|
.addBody([
|
|
kExprGlobalGet,
|
|
index,
|
|
kExprReturn,
|
|
])
|
|
.exportFunc();
|
|
|
|
const buffer = builder.toBuffer();
|
|
|
|
const imports = {
|
|
"module": {
|
|
"global": value,
|
|
},
|
|
};
|
|
|
|
const exports = {
|
|
"fn": { "kind": "function", "name": "0", "length": 0 },
|
|
};
|
|
|
|
return {
|
|
buffer,
|
|
args: [imports],
|
|
exports,
|
|
verify: instance => assert_equals(instance.exports.fn(), value)
|
|
};
|
|
}
|
|
],
|
|
|
|
[
|
|
"i64 exports and imports",
|
|
function() {
|
|
const value = 102n;
|
|
|
|
const builder = new WasmModuleBuilder();
|
|
|
|
const index = builder.addImportedGlobal("module", "global", kWasmI64);
|
|
builder
|
|
.addFunction("fn", kSig_l_v)
|
|
.addBody([
|
|
kExprGlobalGet,
|
|
index,
|
|
kExprReturn,
|
|
])
|
|
.exportFunc();
|
|
|
|
const index2 = builder.addImportedGlobal("module", "global2", kWasmI64);
|
|
builder.addExportOfKind("global", kExternalGlobal, index2);
|
|
|
|
const buffer = builder.toBuffer();
|
|
|
|
const imports = {
|
|
"module": {
|
|
"global": value,
|
|
"global2": 2n ** 63n,
|
|
},
|
|
};
|
|
|
|
const exports = {
|
|
"fn": { "kind": "function", "name": "0", "length": 0 },
|
|
"global": { "kind": "global", "value": -(2n ** 63n) },
|
|
};
|
|
|
|
return {
|
|
buffer,
|
|
args: [imports],
|
|
exports,
|
|
verify: instance => assert_equals(instance.exports.fn(), value)
|
|
};
|
|
}
|
|
],
|
|
|
|
[
|
|
"import with i32-returning function",
|
|
function() {
|
|
const builder = new WasmModuleBuilder();
|
|
|
|
const fnIndex = builder.addImport("module", "fn", kSig_i_v);
|
|
const fn2 = builder
|
|
.addFunction("fn2", kSig_v_v)
|
|
.addBody([
|
|
kExprCallFunction,
|
|
fnIndex,
|
|
kExprReturn,
|
|
])
|
|
.exportFunc();
|
|
|
|
const buffer = builder.toBuffer();
|
|
|
|
let called = false;
|
|
const imports = {
|
|
"module": {
|
|
"fn": function() {
|
|
called = true;
|
|
return 6n;
|
|
},
|
|
},
|
|
};
|
|
|
|
return {
|
|
buffer,
|
|
args: [imports],
|
|
exports: {
|
|
"fn2": { "kind": "function", "name": String(fn2.index), "length": 0 },
|
|
},
|
|
verify: instance => {
|
|
assert_throws_js(TypeError, () => instance.exports.fn2());
|
|
assert_true(called, "Should have called into JS");
|
|
}
|
|
};
|
|
}
|
|
],
|
|
|
|
[
|
|
"import with function that takes and returns i32",
|
|
function() {
|
|
const builder = new WasmModuleBuilder();
|
|
|
|
const fnIndex = builder.addImport("module", "fn", kSig_i_i);
|
|
const fn2 = builder
|
|
.addFunction("fn2", kSig_i_v)
|
|
.addBody([
|
|
kExprI32Const, 0x66,
|
|
kExprCallFunction,
|
|
fnIndex,
|
|
kExprReturn,
|
|
])
|
|
.exportFunc();
|
|
|
|
const buffer = builder.toBuffer();
|
|
|
|
let called = false;
|
|
const imports = {
|
|
"module": {
|
|
"fn": function(n) {
|
|
called = true;
|
|
assert_equals(n, -26);
|
|
return { valueOf() { return 6; } };
|
|
},
|
|
},
|
|
};
|
|
|
|
return {
|
|
buffer,
|
|
args: [imports],
|
|
exports: {
|
|
"fn2": { "kind": "function", "name": String(fn2.index), "length": 0 },
|
|
},
|
|
verify: instance => {
|
|
assert_equals(instance.exports.fn2(), 6);
|
|
assert_true(called, "Should have called into JS");
|
|
}
|
|
};
|
|
}
|
|
],
|
|
|
|
[
|
|
"import with i64-returning function",
|
|
function() {
|
|
const builder = new WasmModuleBuilder();
|
|
|
|
const fnIndex = builder.addImport("module", "fn", kSig_l_v);
|
|
const fn2 = builder
|
|
.addFunction("fn2", kSig_v_v)
|
|
.addBody([
|
|
kExprCallFunction,
|
|
fnIndex,
|
|
kExprReturn,
|
|
])
|
|
.exportFunc();
|
|
|
|
const buffer = builder.toBuffer();
|
|
|
|
let called = false;
|
|
const imports = {
|
|
"module": {
|
|
"fn": function() {
|
|
called = true;
|
|
return 6;
|
|
},
|
|
},
|
|
};
|
|
|
|
return {
|
|
buffer,
|
|
args: [imports],
|
|
exports: {
|
|
"fn2": { "kind": "function", "name": String(fn2.index), "length": 0 },
|
|
},
|
|
verify: instance => {
|
|
assert_throws_js(TypeError, () => instance.exports.fn2());
|
|
assert_true(called, "Should have called into JS");
|
|
}
|
|
};
|
|
}
|
|
],
|
|
|
|
[
|
|
"import with function that takes and returns i64",
|
|
function() {
|
|
const builder = new WasmModuleBuilder();
|
|
|
|
const fnIndex = builder.addImport("module", "fn", kSig_l_l);
|
|
const fn2 = builder
|
|
.addFunction("fn2", kSig_l_v)
|
|
.addBody([
|
|
kExprI64Const, 0x66,
|
|
kExprCallFunction,
|
|
fnIndex,
|
|
kExprReturn,
|
|
])
|
|
.exportFunc();
|
|
|
|
const buffer = builder.toBuffer();
|
|
|
|
let called = false;
|
|
const imports = {
|
|
"module": {
|
|
"fn": function(n) {
|
|
called = true;
|
|
assert_equals(n, -26n);
|
|
return { valueOf() { return 6n; } };
|
|
},
|
|
},
|
|
};
|
|
|
|
return {
|
|
buffer,
|
|
args: [imports],
|
|
exports: {
|
|
"fn2": { "kind": "function", "name": String(fn2.index), "length": 0 },
|
|
},
|
|
verify: instance => {
|
|
assert_equals(instance.exports.fn2(), 6n);
|
|
assert_true(called, "Should have called into JS");
|
|
}
|
|
};
|
|
}
|
|
],
|
|
|
|
[
|
|
"import with i32-taking function",
|
|
function() {
|
|
const builder = new WasmModuleBuilder();
|
|
|
|
const fn = builder
|
|
.addFunction("fn", kSig_v_i)
|
|
.addBody([
|
|
kExprReturn,
|
|
])
|
|
.exportFunc();
|
|
|
|
const buffer = builder.toBuffer();
|
|
|
|
return {
|
|
buffer,
|
|
args: [],
|
|
exports: {
|
|
"fn": { "kind": "function", "name": String(fn.index), "length": 1 },
|
|
},
|
|
verify: instance => assert_throws_js(TypeError, () => instance.exports.fn(6n))
|
|
};
|
|
}
|
|
],
|
|
|
|
[
|
|
"import with i64-taking function",
|
|
function() {
|
|
const builder = new WasmModuleBuilder();
|
|
|
|
const fn = builder
|
|
.addFunction("fn", kSig_v_l)
|
|
.addBody([
|
|
kExprReturn,
|
|
])
|
|
.exportFunc();
|
|
|
|
const buffer = builder.toBuffer();
|
|
|
|
return {
|
|
buffer,
|
|
args: [],
|
|
exports: {
|
|
"fn": { "kind": "function", "name": String(fn.index), "length": 1 },
|
|
},
|
|
verify: instance => assert_throws_js(TypeError, () => instance.exports.fn(6))
|
|
};
|
|
}
|
|
],
|
|
|
|
[
|
|
"export i64-returning function",
|
|
function() {
|
|
const builder = new WasmModuleBuilder();
|
|
|
|
const fn = builder
|
|
.addFunction("fn", kSig_l_v)
|
|
.addBody([
|
|
kExprI64Const, 0x66,
|
|
kExprReturn,
|
|
])
|
|
.exportFunc();
|
|
|
|
const buffer = builder.toBuffer();
|
|
|
|
return {
|
|
buffer,
|
|
args: [],
|
|
exports: {
|
|
"fn": { "kind": "function", "name": String(fn.index), "length": 0 },
|
|
},
|
|
verify: instance => assert_equals(instance.exports.fn(), -26n)
|
|
};
|
|
}
|
|
],
|
|
|
|
[
|
|
"i32 mutable WebAssembly.Global import",
|
|
function() {
|
|
const initial = 102;
|
|
const value = new WebAssembly.Global({ "value": "i32", "mutable": true }, initial);
|
|
|
|
const builder = new WasmModuleBuilder();
|
|
|
|
const index = builder.addImportedGlobal("module", "global", kWasmI32, true);
|
|
const fn = builder
|
|
.addFunction("fn", kSig_i_v)
|
|
.addBody([
|
|
kExprGlobalGet,
|
|
index,
|
|
kExprReturn,
|
|
])
|
|
.exportFunc();
|
|
|
|
const buffer = builder.toBuffer();
|
|
|
|
const imports = {
|
|
"module": {
|
|
"global": value,
|
|
},
|
|
};
|
|
|
|
const exports = {
|
|
"fn": { "kind": "function", "name": String(fn.index), "length": 0 },
|
|
};
|
|
|
|
return {
|
|
buffer,
|
|
args: [imports],
|
|
exports,
|
|
verify: instance => {
|
|
assert_equals(instance.exports.fn(), initial);
|
|
const after = 201;
|
|
value.value = after;
|
|
assert_equals(instance.exports.fn(), after);
|
|
}
|
|
};
|
|
}
|
|
],
|
|
|
|
[
|
|
"i64 mutable WebAssembly.Global import",
|
|
function() {
|
|
const initial = 102n;
|
|
const value = new WebAssembly.Global({ "value": "i64", "mutable": true }, initial);
|
|
|
|
const builder = new WasmModuleBuilder();
|
|
|
|
const index = builder.addImportedGlobal("module", "global", kWasmI64, true);
|
|
const fn = builder
|
|
.addFunction("fn", kSig_l_v)
|
|
.addBody([
|
|
kExprGlobalGet,
|
|
index,
|
|
kExprReturn,
|
|
])
|
|
.exportFunc();
|
|
|
|
const buffer = builder.toBuffer();
|
|
|
|
const imports = {
|
|
"module": {
|
|
"global": value,
|
|
},
|
|
};
|
|
|
|
const exports = {
|
|
"fn": { "kind": "function", "name": String(fn.index), "length": 0 },
|
|
};
|
|
|
|
return {
|
|
buffer,
|
|
args: [imports],
|
|
exports,
|
|
verify: instance => {
|
|
assert_equals(instance.exports.fn(), initial);
|
|
const after = 201n;
|
|
value.value = after;
|
|
assert_equals(instance.exports.fn(), after);
|
|
}
|
|
};
|
|
}
|
|
],
|
|
|
|
[
|
|
"Multiple i64 arguments",
|
|
function() {
|
|
const builder = new WasmModuleBuilder();
|
|
|
|
const fn = builder
|
|
.addFunction("fn", kSig_l_ll)
|
|
.addBody([
|
|
kExprLocalGet, 1,
|
|
])
|
|
.exportFunc();
|
|
|
|
const buffer = builder.toBuffer();
|
|
|
|
const exports = {
|
|
"fn": { "kind": "function", "name": String(fn.index), "length": 2 },
|
|
};
|
|
|
|
return {
|
|
buffer,
|
|
args: [],
|
|
exports,
|
|
verify: instance => {
|
|
const fn = instance.exports.fn;
|
|
assert_equals(fn(1n, 0n), 0n);
|
|
assert_equals(fn(1n, 123n), 123n);
|
|
assert_equals(fn(1n, -123n), -123n);
|
|
assert_equals(fn(1n, "5"), 5n);
|
|
assert_throws_js(TypeError, () => fn(1n, 5));
|
|
}
|
|
};
|
|
}
|
|
],
|
|
|
|
[
|
|
"stray argument",
|
|
function() {
|
|
return {
|
|
buffer: emptyModuleBinary,
|
|
args: [{}, {}],
|
|
exports: {},
|
|
verify: () => {}
|
|
};
|
|
}
|
|
],
|
|
];
|
|
|
|
globalThis.instanceTestFactory = instanceTestFactory;
|