Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Motivation
resolves #4451
Currently if a function/method has a generic return or arguments type like:
where
SomeType
is just plain struct that impls wasm traits manually (not using wasm_bindgen macro on its definition, ie not js class) the generated typescript bindings wont correctly map the generic types and doesnt actually include them:Although user can use
unchecked_return_type
andunchecked_param_type
attribute to specify them, but this is not really ideal, it is fine and ok if there are a couple of functions to apply those attrs to, but if there are tons of functions and methods, it wont really end up good as they are unchecked and bug prone, however if the nested types can be processed regularly like the main type, this can simply be resolved, so on typescript we would get:Proposed Solution
Implement some logic to parse and map the types deeply, possibly recursively, until all nested types are parsed and accounted for in generated typescript.
There is a mapper currently that maps the rust return types to their equivalent js/ts types, but looks like it just checks 1 level deep, and doesnt go deeper than that, however with some tweaks, the same logic can be applied on nested types to correctly map the return type for the js/ts bindings.
We need to parse the args/return
syn::Type
s separately and map them with their nestedsyn::Type
s into their correspondingWasmDescribe
which later on can be encoded and then decoded intoDescriptor
and next intoAdapterType
so can be appended lastly to the parent TS type as generic if they happen to be generic.High-Level Implementation Details
We we would use native encoded/decoded
WasmDescribe::inform()
for return and arguments types, meaning we will encode their wasm informs in thebackend::codegen
forExport
and then decode it atcli-support::descriptor::Function
which now has 2 new more fields:inner_ret_map
andargs_ty_map
, these 2 field hold theDescriptor
which now has 1 more variant calledDescriptor::Generic
which exclusively added for this purpose and doesnt have any effect on any previous functionalities:that can hold the type map for both args and return type, now at
cli-support::wit::register_export_adapter
we convert thoseinner_ret_map
andargs_ty_map
fields intoAdapterType
using a newly added function calleddescribe_map_to_adapter
where it just maps the givenDescriptor
to itsAdapterType
by also handling of nested generic types.Lastly when building the ts signature and js doc for the binding function/method, we will convert those generic
AdapterType
s into their corresponding js/ts types and append them to the main parent type.New tests are added under
typescript-tests
crate testing complex nested generic types to be correctly mapped to their ts signature.This feature doesnt change any of the previous functionalities and logic, it simply is a new piece of logic that separately maps a
syn::Type
with any of its nestedsyn::Type
s to theirWasmDescribe
and thenDescriptor
and after that toAdapterType
completely separate to the how args and return type are resolved, and at the very last step of generating the ts signature, if the arg/return type is a generic, it will just append the generic to the actual parent type.Note
An attribute can be added to be able to turn this off for a given function/method, I have not added such attribute in this PR, but if that's desired, I can add it.