Skip to content

[js-api] Treat an explicit undefined as a missing value in table.set/grow tests - #2307

Merged
Ms2ger merged 1 commit into
WebAssembly:mainfrom
kaist-plrg:fix/js-api-test-table-explicit-undefined
Oct 28, 2026
Merged

Ms2ger merged 1 commit into
WebAssembly:mainfrom
kaist-plrg:fix/js-api-test-table-explicit-undefined

Conversation

@f52985

@f52985 f52985 commented Oct 28, 2026

Copy link
Copy Markdown
Collaborator

Related to #1660.

The test "Setting non-function" in test/js-api/table/get-set.any.js expects table.set(0, undefined) to throw a TypeError on an anyfunc table.
As far as I can tell, the specification says that this call is identical with table.set(0), and should instead succeed and store a null reference.

What the specification says

As discussed in #2259, Web IDL's overload resolution turns an explicit undefined passed for an optional argument without a default into the special value "missing", exactly as if the argument had been omitted.

Table.set's second parameter is such an argument:
undefined set(AddressValue index, optional any value);

and its algorithm checks for it:

1. If |value| is missing,
    1. Let |ref| be DefaultValue(|elementtype|).
    1. If |ref| is error, throw a TypeError exception.
1. Otherwise,
    1. Let |ref| be ? ToWebAssemblyValue(|value|, |elementtype|).

So table.set(0, undefined) is the same call as table.set(0): it takes the first branch, and DefaultValue(funcref) is ref.null func, so the table entry becomes null without any exception.
The TypeError would only come from ToWebAssemblyValue(undefined, funcref) in the second branch, which this call never reaches.

Change

  • Remove undefined from the list of invalid values in "Setting non-function".
  • In "Arguments for anyfunc table set", check that table.set(0, undefined) indeed sets the the entry to null without throwing error.
  • Adds new test case for Table.grow: it has the same signature: AddressValue grow(AddressValue delta, optional any value), and the same If |value| is missing step, but grow.any.js never passes an explicit undefined as the value. (The omitted case is already covered by "Basic i32")

Why the test may have been written this way

My guess is that "missing" was read in its ordinary English sense, as "not given".
Under that reading an explicit undefined is a "given" value, goes through ToWebAssemblyValue, and is rejected because it is not a function or null.

A concern

I am not sure this is the right direction though, because current engines already follow the test rather than the specification.
The latest versions of V8, SpiderMonkey, and JavaScriptCore all throw a TypeError for both table.set(0, undefined) and table.grow(2, undefined).

If want the current engines' behavior as the intended one, the alternative is to somehow change the specification instead, for example by bypassing the overload resolution algorithm and checking for undefined explicitly.

@f52985

f52985 commented Oct 28, 2026 •

Copy link
Copy Markdown
Collaborator Author

For reference: There already exists a test suite that treats an explicit undefined as a missing value.

Global constructor has the same optional any signature and the same "If |v| is missing" step as Table.set and Table.grow,
and global/constructor.any.js expects new WebAssembly.Global({value: "i64"}, undefined) to yield 0n ("Explicit value ${name} for type i64"),
which only holds if undefined becomes "missing" and takes DefaultValue(i64);
converting it with ToWebAssemblyValue would throw a TypeError from ToBigInt64.

@Ms2ger Ms2ger left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks

@Ms2ger
Ms2ger merged commit 77c5743 into WebAssembly:main Oct 28, 2026
2 checks passed
@f52985
f52985 deleted the fix/js-api-test-table-explicit-undefined branch October 29, 2026 03:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants