Skip to content
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

Special-case "optionals with a default value" and fix compilation errors in Gecko JS #314

Merged
merged 2 commits into from
Oct 7, 2020

Conversation

linabutler
Copy link
Member

Optional arguments and members with a default value are a bag of special cases.

On the C++ side, optional arguments with default values are passed as const T&, and optional dictionary members are type T (for optional arguments, they're const dom::Optional<T>& and dom::Optional<T>, respectively). But the Rust side is expecting them to be serialized as Option<T>. It's basically the same problem as strings, where null and non-null strings have the same const nsAString&/nsString type—the Rust side is expecting to read 1/0 followed by the serialization of the type, but the C++ side isn't passing that 1/0.

So the first commit adds a special WebIDLType::OptionalWithDefaultValue that's emitted as T, except when we call ViaFfi, where it passes Nullable = true. It also adds a helper for serializing non-null things on the C++ side as if they were Some<T> for Rust.

The second commit fixes some errors in the generated Nimbus bindings. dom::Optional<T> can't be constructed directly, and ThrowOperationError takes a const ACString&, not a raw char*, so we have to wrap it in an nsDependentCString.

@dmose and I paired on this yesterday, and got the Nimbus SDK building with these changes. We haven't written an xpcshell test for it yet—it's crashing because it's trying to use Viaduct to make a network request from the main thread, which is forbidden—but it compiles and runs.

These types are different than optionals without a default value.
Their C++ type is just `T`, not `Optional<T>`, since the default value
is a fallback if the caller doesn't pass one. But they must be
serialized as if they were `Optional<T>`, because the Rust side of the
FFI will try to deserialize them as optionals instead of instances of
the value.
@linabutler linabutler requested review from eoger and dmose October 3, 2020 15:34
Copy link
Contributor

@eoger eoger left a comment

Choose a reason for hiding this comment

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

Ship it!
Dancing kid

Comment on lines +53 to +57
/// Optionals with a default value are a grab bag of special cases in Gecko.
/// In the generated C++ bindings, the type of an optional with a default
/// value is `T`, not `Optional<T>`. However, it must be serialized as if
/// it's an `Optional<T>`, since that's what the Rust side of the FFI
/// expects.
Copy link
Contributor

Choose a reason for hiding this comment

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

What a headache, I wonder if we shouldn't have disallowed optionals without default values in IDL files.

@dmose dmose merged commit 6ec1d44 into main Oct 7, 2020
@dmose dmose deleted the nimbus-in-firefox branch October 7, 2020 17:47
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.

3 participants