spiderfire
spiderfire copied to clipboard
Opt<T> does not respect passing undefined explicitly
Since Opt<T>
only checks for the absence of an argument, it does not respect passing undefined
explicitly. This is probably the correct implementation:
impl<'cx, T: FromValue<'cx>> FromArgument<'_, 'cx> for Opt<T> {
type Config = T::Config;
fn from_argument(accessor: &mut Accessor<'_, 'cx>, config: Self::Config) -> Result<Opt<T>> {
if accessor.is_empty() {
Ok(Opt(None))
} else {
let val = accessor.value();
if val.handle().is_undefined() {
Ok(Opt(None))
} else {
T::from_value(accessor.cx(), &val, false, config).map(Some).map(Opt)
}
}
}
}
That is intentional, it's meant to distinguish between "empty" arguments and undefined
.
In theory, you could make a function that takes in undefined
as a sentinel value (although that's a terrible idea).
There should probably be an Undefinable<T>
, but I haven't got to that yet.
To the best of my knowledge, there's little difference in JS between passing undefined
and not passing an argument.
Also, there are WPT tests that check for passing undefined
instead of leaving a parameter out completely and that it works. That's how I discovered this in the first place. No idea if it'd be desirable everywhere though.
null, undefined and empty argument are very complex in js. I collected some relevant links here: https://github.com/servo/servo/issues/30287#issue-1879004375, the most interesting one is https://sites.google.com/a/chromium.org/dev/blink/webidl#TOC-undefined-and-null
This seems to be mostly related to the discussion here: https://www.w3.org/Bugs/Public/show_bug.cgi?id=23532