Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion document/js-api/index.bs
Original file line number Diff line number Diff line change
Expand Up @@ -795,6 +795,7 @@ The <dfn method for="Memory">type()</dfn> method steps are:
enum TableKind {
"externref",
"anyfunc",
"funcref",
// Note: More values may be added in future iterations,
// e.g., typed function references, typed GC references
};
Expand Down Expand Up @@ -950,6 +951,7 @@ enum ValueType {
"f32",
"f64",
"externref",
"funcref",
"anyfunc",
};
</pre>
Expand Down Expand Up @@ -1002,6 +1004,7 @@ which can be simultaneously referenced by multiple {{Instance}} objects. Each
1. If |s| equals "i64", return [=i64=].
1. If |s| equals "f32", return [=f32=].
1. If |s| equals "f64", return [=f64=].
1. If |s| equals "funcref", return [=funcref=].
1. If |s| equals "anyfunc", return [=funcref=].
1. If |s| equals "externref", return [=externref=].
1. Assert: This step is not reached.
Expand All @@ -1015,7 +1018,7 @@ The algorithm <dfn abstract-op>FromValueType</dfn>(|s|) performs the following s
1. If |s| equals [=i64=], return "{{ValueType/i64}}".
1. If |s| equals [=f32=], return "{{ValueType/f32}}".
1. If |s| equals [=f64=], return "{{ValueType/f64}}".
1. If |s| equals [=funcref=], return "{{ValueType/anyfunc}}".
1. If |s| equals [=funcref=], return "{{ValueType/funcref}}".
1. If |s| equals [=externref=], return "{{ValueType/externref}}".
1. Assert: This step is not reached.

Expand Down
4 changes: 2 additions & 2 deletions proposals/js-types/Overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ All Wasm types can be defined by a simple grammar. This grammar could be mapped

```TypeScript
type ValueType = "i32" | "i64" | "f32" | "f64"
type ElemType = "anyfunc"
type ElemType = "funcref"
type GlobalType = {value: ValueType, mutable: boolean}
type MemoryType = {limits: Limits}
type TableType = {limits: Limits, element: ElemType}
Expand Down Expand Up @@ -200,7 +200,7 @@ function print(...args) {
for (let x of args) console.log(x + "\n")
}

let table = new Table({element: "anyfunc", minimum: 10});
let table = new Table({element: "funcref", minimum: 10});

let print_i32 = new WebAssembly.Function({parameters: ["i32"], results: []}, print);
table.set(0, print_i32);
Expand Down
12 changes: 12 additions & 0 deletions test/js-api/global/constructor.any.js
Original file line number Diff line number Diff line change
Expand Up @@ -164,3 +164,15 @@ test(() => {
const global = new WebAssembly.Global(argument, 0, {});
assert_Global(global, 0);
}, "Stray argument");

test(() => {
const argument = { "value": "anyfunc" };
const global = new WebAssembly.Global(argument);
assert_Global(global, null);
}, "funcref with default");

test(() => {
const argument = { "value": "funcref" };
const global = new WebAssembly.Global(argument);
assert_Global(global, null);
}, "funcref with default");
83 changes: 83 additions & 0 deletions test/js-api/global/type.any.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
// META: global=window,dedicatedworker,jsshell
// META: script=/wasm/jsapi/assertions.js

function assert_type(argument) {
const myglobal = new WebAssembly.Global(argument);
const globaltype = myglobal.type();

assert_equals(globaltype.value, argument.value);
assert_equals(globaltype.mutable, argument.mutable);
}

test(() => {
assert_type({ "value": "i32", "mutable": true});
}, "i32, mutable");

test(() => {
assert_type({ "value": "i32", "mutable": false});
}, "i32, immutable");

test(() => {
assert_type({ "value": "i64", "mutable": true});
}, "i64, mutable");

test(() => {
assert_type({ "value": "i64", "mutable": false});
}, "i64, immutable");

test(() => {
assert_type({ "value": "f32", "mutable": true});
}, "f32, mutable");

test(() => {
assert_type({ "value": "f32", "mutable": false});
}, "f32, immutable");

test(() => {
assert_type({ "value": "f64", "mutable": true});
}, "f64, mutable");

test(() => {
assert_type({ "value": "f64", "mutable": false});
}, "f64, immutable");

test(() => {
assert_type({"value": "externref", "mutable": true})
}, "externref, mutable")

test(() => {
assert_type({"value": "externref", "mutable": false})
}, "externref, immutable")

test(() => {
const argument = {"value": "anyfunc", "mutable": true};
const myglobal = new WebAssembly.Global(argument);
const globaltype = myglobal.type();

assert_equals(globaltype.value, "funcref");
assert_equals(globaltype.mutable, argument.mutable);
}, "anyfunc, mutable")

test(() => {
const argument = {"value": "anyfunc", "mutable": false};
const myglobal = new WebAssembly.Global(argument);
const globaltype = myglobal.type();

assert_equals(globaltype.value, "funcref");
assert_equals(globaltype.mutable, argument.mutable);
}, "anyfunc, immutable")

test(() => {
assert_type({"value": "funcref", "mutable": true})
}, "funcref, mutable")

test(() => {
assert_type({"value": "funcref", "mutable": false})
}, "funcref, immutable")

test(() => {
const myglobal = new WebAssembly.Global({"value": "i32", "mutable": true});
const propertyNames = Object.getOwnPropertyNames(myglobal.type());
assert_equals(propertyNames[0], "mutable");
assert_equals(propertyNames[1], "value");
}, "key ordering");
144 changes: 137 additions & 7 deletions test/js-api/module/exports.any.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,35 @@ function assert_ModuleExportDescriptor(export_, expected) {
assert_true(kind.enumerable, "kind: enumerable");
assert_true(kind.configurable, "kind: configurable");
assert_equals(kind.value, expected.kind);

if (expected.type) {
const type = Object.getOwnPropertyDescriptor(export_, 'type');
assert_true(type.writable, 'type: writable');
assert_true(type.enumerable, 'type: enumerable');
assert_true(type.configurable, 'type: configurable');

if (expected.type.parameters) {
assert_array_equals(type.value.parameters, expected.type.parameters);
}
if (expected.type.results) {
assert_array_equals(type.value.results, expected.type.results);
}
if (expected.type.value) {
assert_equals(type.value.value, expected.type.value);
}
if (expected.type.mutable !== undefined) {
assert_equals(type.value.mutable, expected.type.mutable);
}
if (expected.type.mimimum) {
assert_equals(type.value.mimimum, expected.type.mimimum);
}
if (expected.type.maximum) {
assert_equals(type.value.maximum, expected.type.maximum);
}
if (expected.type.element) {
assert_equals(type.value.element, expected.type.element);
}
}
}

function assert_exports(exports, expected) {
Expand Down Expand Up @@ -75,6 +104,12 @@ test(() => {
}
}, "Branding");

test(() => {
const module = new WebAssembly.Module(emptyModuleBinary);
const exports = WebAssembly.Module.exports(module);
assert_true(Array.isArray(exports));
}, "Return type");

test(() => {
const module = new WebAssembly.Module(emptyModuleBinary);
const exports = WebAssembly.Module.exports(module);
Expand All @@ -83,7 +118,8 @@ test(() => {

test(() => {
const module = new WebAssembly.Module(emptyModuleBinary);
assert_not_equals(WebAssembly.Module.exports(module), WebAssembly.Module.exports(module));
assert_not_equals(
WebAssembly.Module.exports(module), WebAssembly.Module.exports(module));
}, "Empty module: array caching");

test(() => {
Expand Down Expand Up @@ -114,18 +150,112 @@ test(() => {
const module = new WebAssembly.Module(buffer);
const exports = WebAssembly.Module.exports(module);
const expected = [
{ "kind": "function", "name": "fn" },
{ "kind": "function", "name": "fn2" },
{ "kind": "table", "name": "table" },
{ "kind": "global", "name": "global" },
{ "kind": "global", "name": "global2" },
{ "kind": "memory", "name": "memory" },
{
'kind': 'function',
'name': 'fn',
'type': {'parameters': [], 'results': []}
},
{
'kind': 'function',
'name': 'fn2',
'type': {'parameters': [], 'results': []}
},
{'kind': 'table', 'name': 'table'},
{'kind': 'global', 'name': 'global'},
{'kind': 'global', 'name': 'global2'},
{'kind': 'memory', 'name': 'memory'},
];
assert_exports(exports, expected);
}, "exports");

test(() => {
const builder = new WasmModuleBuilder();

builder
.addFunction("", kSig_v_v)
.addBody([])
.exportFunc();

const buffer = builder.toBuffer()
const module = new WebAssembly.Module(buffer);
const exports = WebAssembly.Module.exports(module);
const expected = [
{'kind': 'function', 'name': '', 'type': {'parameters': [], 'results': []}},
];
assert_exports(exports, expected);
}, "exports with empty name: function");

test(() => {
const builder = new WasmModuleBuilder();

builder.setTableBounds(1);
builder.addExportOfKind("", kExternalTable, 0);

const buffer = builder.toBuffer()
const module = new WebAssembly.Module(buffer);
const exports = WebAssembly.Module.exports(module);
const expected = [
{ "kind": "table", "name": "" },
];
assert_exports(exports, expected);
}, "exports with empty name: table");

test(() => {
const builder = new WasmModuleBuilder();

builder.addGlobal(kWasmI32, true)
.exportAs("")
.init = 7;

const buffer = builder.toBuffer()
const module = new WebAssembly.Module(buffer);
const exports = WebAssembly.Module.exports(module);
const expected = [
{ "kind": "global", "name": "" },
];
assert_exports(exports, expected);
}, "exports with empty name: global");

test(() => {
const module = new WebAssembly.Module(emptyModuleBinary);
const exports = WebAssembly.Module.exports(module, {});
assert_exports(exports, []);
}, "Stray argument");

test(() => {
const builder = new WasmModuleBuilder();

builder
.addFunction("fn", kSig_a_a)
.addBody([kExprLocalGet, 0])
.exportFunc();

builder.addTable(kWasmAnyFunc, 10, 100);
builder.addExportOfKind("table", kExternalTable, 0);

builder.addGlobal(kWasmAnyFunc, true)
.exportAs("global").function_index = 0;

const buffer = builder.toBuffer();
const module = new WebAssembly.Module(buffer);
const exports = WebAssembly.Module.exports(module);
const expected = [
{
'kind': 'function',
'name': 'fn',
'type': {'parameters': ['funcref'], 'results': ['funcref']}
},
{
'kind': 'table',
'name': 'table',
'type': {'minimum': 10, 'maximum': 100, 'element': 'funcref'}
},
{
'kind': 'global',
'name': 'global',
'type': {'value': 'funcref', 'mutable': true}
},
];
assert_exports(exports, expected);
}, "exports with type funcref");

Loading