spiderfire icon indicating copy to clipboard operation
spiderfire copied to clipboard

Opt<T> does not respect passing undefined explicitly

Open Arshia001 opened this issue 1 year ago • 4 comments

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)
			}
		}
	}
}

Arshia001 avatar Feb 15 '24 14:02 Arshia001

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.

Redfire75369 avatar Feb 15 '24 15:02 Redfire75369

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.

Arshia001 avatar Feb 15 '24 15:02 Arshia001

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

sagudev avatar Feb 15 '24 16:02 sagudev

This seems to be mostly related to the discussion here: https://www.w3.org/Bugs/Public/show_bug.cgi?id=23532

Arshia001 avatar Feb 15 '24 18:02 Arshia001