Skip to content

Make anyfunc an alias of funcref #34

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Nov 18, 2021
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