-
-
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
Function Attributes #4394
base: main
Are you sure you want to change the base?
Function Attributes #4394
Conversation
Please refrain from pinging maintainers like this unless there is a more specific reason then just reviewing a PR. |
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 believe we should not add support for optional
without a good use-case. While JsValue
is a good use case, we should instead discuss support for Option<JsValue>
in a separate issue.
WDYT of wrapping param_type
and return_type
with unsafe(...)
, to make sure users are aware that we can't check the type here?
Thank you for doing this, great work!
guide/src/reference/attributes/on-rust-exports/function-attributes.md
Outdated
Show resolved
Hide resolved
guide/src/reference/attributes/on-rust-exports/function-attributes.md
Outdated
Show resolved
Hide resolved
Makes sense, I'll remove that.
Yea I understand the concerns here, I personally am in the camp of the responsibility of using these attrs are upon the user/dev, as these are not something everyone needs everytime, but are something you might need at times, so using them comes with the responsibility of making sure you know what you are doing, that said, I totally understand the concerns and am totally ok to impl this or any other syntax/format you see fit for this. I can think of this format as well: @daxpedda Lastly, thanks for identifying and correcting the typos and mistakes I had in documentation, and also I replied to other review comments/suggestion as well, some of which need your final call so I can go ahead to impl, so please let me know how should we go about them. |
This might be more appropriate actually. Let go with that, we can do more bikeshedding after we are done. |
Motivation
resolves #4223
resolves #1847
resolves #4385
resolves #4377
At the moment, by default, exported Rust functions/methods generate function signature from equivalent rust types identifiers and without any documentations, unless completely handcoded using
skip-jsdoc
and/ortypescript-custom-section
, but this has some limitations as disscussed in details in issues mentioned above which have been requested to be addressed for long time, some examples of which are:skip-jsdoc
and/ortypescript-custom-section
.Vec<(Foo, Bar)>
) as return type of async functions (and in some cases non async functions) without wrapping them in new struct and actually implementingwasm_bindgen
for it.any
in typescript) where arguments and return types are only typescript interfaces and not a js class, asJsValue
in rust side where they are just serialized/deserialized using serde.snake_case
, but js/ts naming convention iscamelCase
, atm there is no way to convert function argument names tocamelCase
or optionally rename them.Proposed Solution
By introcusing function attributes these limitations and requested features can be addressed, these attributes will make it possible to override function arguments and return types and to write specific documentation for each of them individually as desired with relatively very minimal changes:
#[wasm_bindgen(unchecked_return_type)]
and#[wasm_bindgen(return_description)]
used to override function's return type and to specify description for generated js/ts bindings.#[wasm_bindgen(js_name)]
,#[wasm_bindgen(unchecked_param_type)]
and#[wasm_bindgen(param_description)]
applied to a rust function argument to override that argument's name and type and to specify description for generated js/ts bindings.These attributes will provide a great level of control and customization over functions/methods generated bindings that are essential for creating well defined and structured bindings.
Let's look at some examples for more details:
This will generate the following js bindings:
And will generate the following ts bindings:
Same thing applies to rust struct's (and enums) impl methods and their equivalent js/ts class methods:
This will generate the following js bindings:
And will generate the following ts bindings:
High Level Implementation Details
These attributes can be implemented with very minimal changes, for function arguments attributes, we need to parse and extract them before passing it token stream, and for return type attributes they will be added to
attrgen!
macro incrates/macro-support/src/parser.rs
, this guarantees that if they were used elsewhere other than a function or a method, it'll produce error or unused code warnings.Once they are parsed and extracted, they can be stored in the
ast
as follows:and then will be passed around during encode/decode process of a
ast::Function
toshared_api!
generatedFunction
struct which now has a new property that holds those attrs with similar format.These new structs can be easily extended when/if more features need to be supported.
Next it'll passed as new properties of
AuxExport
converted fromdecode::Export
, which makes those attrs available for consumption atcrates/cli-support/js/bindings.rs
where the bindings get generated.PS: validating
js_name
for an arg, or validating the provided type or description dont contain any illegal chars also takes place inside added logic ofcrates/macro-support/parser.rs
.