-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Add null
to argument types of optional parameters
#4188
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
Missing a changelog entry.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Small nit left, otherwise this LGTM.
dst.push_str(" | undefined"); | ||
adapter2ts(ty, position, dst, refs); | ||
dst.push_str(match position { | ||
TypePosition::Argument => " | undefined | null", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TypePosition::Argument => " | undefined | null", | |
TypePosition::Argument => unreachable!(), |
We always handle this case manually, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't for variadic arguments (bindings.rs
line 419). Though I'm not sure how relevant that is, since varargs probably don't allow Option<T>
.
But I also don't like the idea of adapter2ts
knowing with what types it is called. This feels like a bit of global reasoning to me.
WDYT?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, aren't we handling all Option<T>
manually before they ever arrive in adapter2ts()
?
I'm just concerned because this code is actually incorrect, this function can't handle this case correctly.
Ideally we move Option<T>
handling entirely into this function, but this could be done in a separate PR.
So unless I'm missing something, I think the whole AdapterType::Option(ty) => { ... }
statement should yield unreachable!()
imo.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, aren't we handling all
Option<T>
manually before they ever arrive inadapter2ts()
?
As I said, not for varargs AFAICT.
wasm-bindgen/crates/cli-support/src/js/binding.rs
Lines 417 to 420 in 90f1efb
if let (Some(name), Some(ty)) = (variadic_arg, arg_tys.last()) { | |
ret.push_str("@param {..."); | |
adapter2ts(ty, TypePosition::Argument, &mut ret, None); | |
ret.push_str("} "); |
But I also don't know if varargs even allow Option<T>
since Vec<Option<T>>
is not ABI compatible rn. But that's very much global reasoning.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm just concerned because this code is actually incorrect, this function can't handle this case correctly.
Lets say varargs do support Option<T>
, would the output be correct?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, the output would be correct for documenting varargs in JSDoc AFAICT. E.g. Option<u32>
would produce:
@param {...number | null | undefined} name
I just realized that return and argument types not being the same is a problem for generated getter-setter pairs. |
All functions with
Option<T>
arguments take bothundefined
andnull
and generally treat them as equivalent (seeisLikeNone
). Despite bothundefined
andnull
being accepted, the generated type definitions only allowedundefined
. Example:This is unnecessarily restrictive, as
echo(null)
would also work (seeisLikeNone
) and returnundefined
just likeecho(undefined)
. This also results in worse ergonomics as many DOM APIs returnvalue | null
(e.g.textContent
), which currently requires dev to unnecessarily mapnull
toundefined
(e.g.echo(element.textContent ?? undefined)
).To bring the generated type definitions in line with the actual runtime behavior of the JS glue code, I changed the type of optional parameters from
T | undefined
toT | undefined | null
. E.g. the function signature ofecho
is the following with this PR:This accurately represent the runtime behavior of the function and results in better ergonomics.
Note: This PR only affects function arguments. The return type is still
T | undefined
, as it should be.Tests
To test that this (and other features I have planned) are implemented correctly, I added a single large test file:
echo.rs
. This test file just contains echo/identity functions for various types to check the glue code of various input/output types.