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

Replace TryFrom with custom TryFromJsValue trait #3709

Merged
merged 8 commits into from
Nov 27, 2023

Conversation

biryukovmaxim
Copy link
Contributor

This commit replaces the usage of the standard library's TryFrom trait with a custom TryFromJsValue trait added for handling the conversion from JavaScript values in WASM. This trait has been implemented for different types across multiple modules to ensure consistent error handling on failed conversions.

fixes #3685

@biryukovmaxim biryukovmaxim force-pushed the internal-try-from-js-value branch from 0afb3ed to a3aad01 Compare November 15, 2023 18:49
@biryukovmaxim biryukovmaxim marked this pull request as draft November 15, 2023 19:02
@biryukovmaxim biryukovmaxim force-pushed the internal-try-from-js-value branch from a3aad01 to 50f52e3 Compare November 15, 2023 19:08
@biryukovmaxim biryukovmaxim marked this pull request as ready for review November 15, 2023 19:11
Copy link
Collaborator

@daxpedda daxpedda left a comment

Choose a reason for hiding this comment

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

Could you add an entry to the changelog as well?
LGTM otherwise.

@daxpedda
Copy link
Collaborator

daxpedda commented Nov 15, 2023

@hamza1311 and @Liamolucko, the idea here is to yank the current version and release a new one with this change.
Myself I'm not entirely fond of the whole idea, but I believe if somebody is affected and willing to provide a fix as well, we should take that as something that needs to be addressed. So I would vote in favor.

Let me know what you think.

@daxpedda daxpedda mentioned this pull request Nov 15, 2023
@Liamolucko
Copy link
Collaborator

Myself I'm not entirely fond of the whole idea, but I believe if somebody is affected and willing to provide a fix as well, we should take that as something that needs to be addressed. So I would vote in favor.

I feel the same way.

This does un-fix #2231 though, since wasm_bindgen::convert is an internal module and so TryFromJsValue is effectively private.

The easy solution is just to move it to wasm_bindgen::TryFromJsValue, but it's a bit weird to make people use a custom trait rather than the standard TryFrom<JsValue>. Alternatively we could make a TryFromJsValue derive macro, but that's a lot more work.

@biryukovmaxim
Copy link
Contributor Author

biryukovmaxim commented Nov 16, 2023

This does un-fix #2231 though, since wasm_bindgen::convert is an internal module and so TryFromJsValue is effectively private.

convert module is public, it already exports From/IntoWasmAbi, and others. But these two look like custom From and Into which include additional constraints.

@Liamolucko
Copy link
Collaborator

Liamolucko commented Nov 16, 2023

convert module is public, it already exports From/IntoWasmAbi, and others. But these two looks like custom From and Into that include additional constraints.

Yes, it's technically public, but see its documentation:

This is mostly an internal module, no stability guarantees are provided. Use at your own risk.

It's only really public so that macros can access it, nobody should be using anything from in there directly.

@biryukovmaxim
Copy link
Contributor Author

This is mostly an internal module, no stability guarantees are provided. Use at your own risk.

It's only really public so that macros can access it, nobody should be using anything from in there directly.

Oh. I see. Your suggestion is to move the trait to wasm_bindgen - root module?

@biryukovmaxim
Copy link
Contributor Author

Could you add an entry to the changelog as well? LGTM otherwise.

done

@biryukovmaxim biryukovmaxim force-pushed the internal-try-from-js-value branch from 26b469c to 135407a Compare November 16, 2023 06:13
@daxpedda
Copy link
Collaborator

Alternatively we could make a TryFromJsValue derive macro, but that's a lot more work.

Even if we want to do that one day, it would still require TryFromJsValue trait to be public.
I agree though this is weird, but I can't come up with a better solution.

src/lib.rs Outdated Show resolved Hide resolved
CHANGELOG.md Outdated Show resolved Hide resolved
@daxpedda
Copy link
Collaborator

I'm on the fence about moving TryFromJsValue just back to convert and just figure out what to do here another time.
Any input would be appreciated.

biryukovmaxim and others added 5 commits November 16, 2023 13:04
This commit replaces the usage of the standard library's TryFrom trait with a custom TryFromJsValue trait added for handling the conversion from JavaScript values in WASM. This trait has been implemented for different types across multiple modules to ensure consistent error handling on failed conversions.

fixes rustwasm#3685
In this commit, the TryFromJsValue trait has been relocated from the convert::traits module to the root module. Subsequently, all the references to TryFromJsValue have been updated across various modules. This reorganization helps in improving the coherence and organization of the codebase relative to JavaScript-to-WASM conversions.
The updated CHANGELOG reflects the recent bug fix in wasm-bindgen. It used to force auto-derivation of the TryFrom trait for any struct, but now it will respect the use of custom TryFrom<JsValue> implementations by adopting the new TryFromJsValue trait instead.
Co-authored-by: daxpedda <[email protected]>
@biryukovmaxim biryukovmaxim force-pushed the internal-try-from-js-value branch from 1007bb1 to ba58bf4 Compare November 16, 2023 09:05
This refactor brings the TryFromJsValue trait into the convert sub-module, from the core library.
Copy link
Collaborator

@daxpedda daxpedda left a comment

Choose a reason for hiding this comment

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

LGTM, just some nits about docs.

As mentioned before, this unfixes #2231, but we can figure out exactly what to do here at some later point.

@biryukovmaxim you should probably hold off on any major changes for now, we are still discussing how exactly to proceed, there's no need to move TryFromJsValue back and forth upon every whimsical comment I make! (don't move it back now 😄)

src/convert/traits.rs Outdated Show resolved Hide resolved
Copy link
Collaborator

@daxpedda daxpedda left a comment

Choose a reason for hiding this comment

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

I'm happy to move forward with this, we can figure out how to fix #2231 again in the future.

@daxpedda daxpedda requested a review from Liamolucko November 20, 2023 10:55
@daxpedda daxpedda requested a review from ranile November 20, 2023 10:55
@dani-garcia
Copy link

I've hit a problem with the TryFrom changes that is unrelated to #3685, but that would probably also occur with this PR, related to the ambiguity of using Self::Error when #[wasm_bindgen] is applied to an enum containing an Error variant.

#[wasm_bindgen]
pub enum LogLevel {
    Trace,
    Debug,
    Info,
    Warn,
    Error,
}

The way to solve that would be to use the fully qualified syntax for Self:

fn try_from_js_value(value: #wasm_bindgen::JsValue)
-                   -> #wasm_bindgen::__rt::std::result::Result<Self, Self::Error> {
+                   -> #wasm_bindgen::__rt::std::result::Result<Self, <Self as TryFromJsValue>::Error> {

I can open a PR myself after this one is merged if you prefer to merge this one as-is though.

@daxpedda
Copy link
Collaborator

daxpedda commented Nov 20, 2023

Could you open a PR targeting main? We can merge that right now and let this PR rebase.
Thank you for bringing this up!

@Liamolucko
Copy link
Collaborator

I've hit a problem with the TryFrom changes that is unrelated to #3685, but that would probably also occur with this PR, related to the ambiguity of using Self::Error when #[wasm_bindgen] is applied to an enum containing an Error variant.

#[wasm_bindgen]
pub enum LogLevel {
    Trace,
    Debug,
    Info,
    Warn,
    Error,
}

The way to solve that would be to use the fully qualified syntax for Self:

fn try_from_js_value(value: #wasm_bindgen::JsValue)
-                   -> #wasm_bindgen::__rt::std::result::Result<Self, Self::Error> {
+                   -> #wasm_bindgen::__rt::std::result::Result<Self, <Self as TryFromJsValue>::Error> {

I can open a PR myself after this one is merged if you prefer to merge this one as-is though.

I think this was already fixed in #3678, can you check if it still happens using a git version of the wasm-bindgen macro?

@dani-garcia
Copy link

My bad, seems this was fixed on master a bit ago, and I was looking at the struct changes of this PR instead of the enum changes. I just tested both master and this PR and they both work as expected, sorry for the confusion!

Copy link
Collaborator

@Liamolucko Liamolucko left a comment

Choose a reason for hiding this comment

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

I don't like regressing on #2231, but I guess the breaking changes are a higher priority.

@Liamolucko
Copy link
Collaborator

Alternatively we could make a TryFromJsValue derive macro, but that's a lot more work.

Even if we want to do that one day, it would still require TryFromJsValue trait to be public. I agree though this is weird, but I can't come up with a better solution.

By the way, what I meant by a TryFromJsValue derive macro was a derive macro named TryFromJsValue that implements TryFrom<JsValue>. I guess that is a bit confusing when there's also an internal trait with the same name, but the internal one could be renamed to TryFromJsValueInternal or something to avoid that (not that that needs to happen in this PR).

@daxpedda
Copy link
Collaborator

I'm gonna go ahead and merge this now and get the new release going.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
4 participants