From 66d9976f65c7532aacf1c0b6c77e79132b4635c1 Mon Sep 17 00:00:00 2001 From: chicoxyzzy Date: Tue, 1 Sep 2026 15:13:08 +0200 Subject: [PATCH] [js-api] Accept anyref and funcref in ValueType and TableKind Fixes #1980. Add the GC top type "anyref" and "funcref" as an alias of "anyfunc". Do not add i31ref, eqref, structref, arrayref, null bottoms, or exnref. DefaultValue for anyref is val_default (ref.null any, JS null), not the externref default (undefined). --- document/js-api/index.bs | 10 +++++++--- test/js-api/global/constructor.any.js | 24 ++++++++++++++++++++++++ test/js-api/table/constructor.any.js | 10 ++++++++++ 3 files changed, 41 insertions(+), 3 deletions(-) diff --git a/document/js-api/index.bs b/document/js-api/index.bs index a24dc3ea66..4063a827fe 100644 --- a/document/js-api/index.bs +++ b/document/js-api/index.bs @@ -198,6 +198,7 @@ urlPrefix: https://webassembly.github.io/spec/core/; spec: WebAssembly; type: df url: syntax/types.html#syntax-reftype text: reftype text: funcref + text: anyref text: exnref text: externref text: ref @@ -989,8 +990,8 @@ Immediately after a WebAssembly [=memory.grow=] |x| instruction executes, perfor enum TableKind { "externref", "anyfunc", - // Note: More values may be added in future iterations, - // e.g., typed function references, typed GC references + "funcref", + "anyref", }; dictionary TableDescriptor { @@ -1125,6 +1126,8 @@ enum ValueType { "v128", "externref", "anyfunc", + "funcref", + "anyref", }; @@ -1175,8 +1178,9 @@ which can be simultaneously referenced by multiple {{Instance}} objects. Each 1. If |s| equals "f32", return [=f32=]. 1. If |s| equals "f64", return [=f64=]. 1. If |s| equals "v128", return [=v128=]. - 1. If |s| equals "anyfunc", return [=funcref=]. + 1. If |s| equals "anyfunc" or |s| equals "funcref", return [=funcref=]. 1. If |s| equals "externref", return [=externref=]. + 1. If |s| equals "anyref", return [=anyref=]. 1. Assert: This step is not reached. diff --git a/test/js-api/global/constructor.any.js b/test/js-api/global/constructor.any.js index f11ae8af6f..a7710fed00 100644 --- a/test/js-api/global/constructor.any.js +++ b/test/js-api/global/constructor.any.js @@ -193,3 +193,27 @@ test(() => { let global = new WebAssembly.Global({value: "externref"}); assert_Global(global, undefined); }, "externref global with default value"); + +test(() => { + let global = new WebAssembly.Global({value: "funcref"}); + assert_Global(global, null); +}, "funcref global with default value"); + +test(() => { + let global = new WebAssembly.Global({value: "anyfunc"}); + assert_Global(global, null); +}, "anyfunc remains an alias of funcref"); + +test(() => { + let global = new WebAssembly.Global({value: "anyref"}); + assert_Global(global, null); +}, "anyref global with default value"); + +test(() => { + let global = new WebAssembly.Global({value: "anyref"}, null); + assert_Global(global, null); +}, "anyref global with null"); + +test(() => { + assert_throws_js(TypeError, () => new WebAssembly.Global({value: "anyref"}, {})); +}, "anyref global rejects a plain object"); diff --git a/test/js-api/table/constructor.any.js b/test/js-api/table/constructor.any.js index 46d1e0fe05..f24f698af8 100644 --- a/test/js-api/table/constructor.any.js +++ b/test/js-api/table/constructor.any.js @@ -278,3 +278,13 @@ test(() => { const argument = { "element": "i32", "initial": 3n, "maximum": 10 }; assert_throws_js(TypeError, () => new WebAssembly.Table(argument)); }, "initialize table with a wrong maximum type (i64)"); + +test(() => { + const table = new WebAssembly.Table({element: "funcref", initial: 1}); + assert_equals(table.get(0), null); +}, "funcref table with default value"); + +test(() => { + const table = new WebAssembly.Table({element: "anyref", initial: 1}); + assert_equals(table.get(0), null); +}, "anyref table with default value");