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

Second large refactor for WebIDL bindings #1594

Merged
merged 1 commit into from
Jun 25, 2019

Conversation

alexcrichton
Copy link
Contributor

This commit is the second, and hopefully last massive, refactor for
using WebIDL bindings internally in wasm-bindgen. This commit actually
fully executes on the task at hand, moving wasm-bindgen to internally
using WebIDL bindings throughout its code generation, anyref passes,
etc. This actually fixes a number of issues that have existed in the
anyref pass for some time now!

The main changes here are to basically remove the usage of Descriptor
from generating JS bindings. Instead two new types are introduced:
NonstandardIncoming and NonstandardOutgoing which are bindings lists
used for incoming/outgoing bindings. These mirror the standard
terminology and literally have variants which are the standard values.
All Descriptor types are now mapped into lists of incoming/outgoing
bindings and used for process in wasm-bindgen. All JS generation has
been refactored and updated to now process these lists of bindings
instead of the previous Descriptor.

In other words this commit takes js2rust.rs and rust2js.rs and first
splits them in two. Interpretation of Descriptor and what to do for
conversions is in the binding selection modules. The actual generation
of JS from the binding selection is now performed by incoming.rs and
outgoing.rs. To boot this also deduplicates all the code between the
argument handling of js2rust.rs and return value handling of
rust2js.rs. This means that to implement a new binding you only need
to implement it one place and it's implemented for free in the other!

This commit is not the end of the story though. I would like to add a
mdoe to wasm-bindgen that literally emits a WebIDL bindings section.
That's left for a third (and hopefully final) refactoring which is also
intended to optimize generated JS for bindings.

This commit currently loses the optimization where an imported is hooked
up by value directly whenever a shim isn't needed. It's planned that
the next refactoring to emit a webidl binding section that can be added
back in. It shouldn't be too too hard hopefully since all the
scaffolding is in place now.

cc #1524

@alexcrichton
Copy link
Contributor Author

I'll apologize in advance for the size of this as well. I didn't really find a great place to split up the changes here, it was sort of an all-or-nothing change to have anything working to a respectable degree of fidelity. @fitzgen please take your time of course in looking this over, there's no rush!

Copy link
Contributor

@Hywan Hywan left a comment

Choose a reason for hiding this comment

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

Thanks for commenting such a massive PR, that's very helpful!


// Afterwards look through the argument list (specified with various
// bindings) to find any borrowed anyref values and update our
// transformation metadata accordingly. if we find one then the binding no
Copy link
Contributor

Choose a reason for hiding this comment

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

- if
+ If

// Afterwards look through the argument list (specified with various
// bindings) to find any borrowed anyref values and update our
// transformation metadata accordingly. if we find one then the binding no
// longer needs to remember its borrowed but rather it's just a simple cast
Copy link
Contributor

Choose a reason for hiding this comment

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

- its borrowed
+ it's borrowed

}

// First up we handle all the arguments. Depending on whether incoming
// or outgoing ar the arguments this is pretty different.
Copy link
Contributor

Choose a reason for hiding this comment

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

- ar
+ are

This commit is the second, and hopefully last massive, refactor for
using WebIDL bindings internally in `wasm-bindgen`. This commit actually
fully executes on the task at hand, moving `wasm-bindgen` to internally
using WebIDL bindings throughout its code generation, anyref passes,
etc. This actually fixes a number of issues that have existed in the
anyref pass for some time now!

The main changes here are to basically remove the usage of `Descriptor`
from generating JS bindings. Instead two new types are introduced:
`NonstandardIncoming` and `NonstandardOutgoing` which are bindings lists
used for incoming/outgoing bindings. These mirror the standard
terminology and literally have variants which are the standard values.
All `Descriptor` types are now mapped into lists of incoming/outgoing
bindings and used for process in wasm-bindgen. All JS generation has
been refactored and updated to now process these lists of bindings
instead of the previous `Descriptor`.

In other words this commit takes `js2rust.rs` and `rust2js.rs` and first
splits them in two. Interpretation of `Descriptor` and what to do for
conversions is in the binding selection modules. The actual generation
of JS from the binding selection is now performed by `incoming.rs` and
`outgoing.rs`. To boot this also deduplicates all the code between the
argument handling of `js2rust.rs` and return value handling of
`rust2js.rs`. This means that to implement a new binding you only need
to implement it one place and it's implemented for free in the other!

This commit is not the end of the story though. I would like to add a
mdoe to `wasm-bindgen` that literally emits a WebIDL bindings section.
That's left for a third (and hopefully final) refactoring which is also
intended to optimize generated JS for bindings.

This commit currently loses the optimization where an imported is hooked
up by value directly whenever a shim isn't needed. It's planned that
the next refactoring to emit a webidl binding section that can be added
back in. It shouldn't be too too hard hopefully since all the
scaffolding is in place now.

cc rustwasm#1524
Copy link
Member

@fitzgen fitzgen left a comment

Choose a reason for hiding this comment

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

Alex and I were in the same location last week, and we talked through this PR in person. I'm excited! Next step will be actually using the wasm_webidl_bindings::WebidlBindings custom section type internally :)

@alexcrichton alexcrichton merged commit e0ef329 into rustwasm:master Jun 25, 2019
@alexcrichton
Copy link
Contributor Author

🎊

@alexcrichton alexcrichton deleted the webidl-for-realz branch June 25, 2019 06:21
snOm3ad added a commit to snOm3ad/wasm-bindgen that referenced this pull request Aug 17, 2023
After rustwasm#1594 constructors of Rust exported structs started using class
wrapping when generating JS shims. Wrapping erases prototype information
from the object instance in JS and as a result it is not possible to
override methods (via inheritance) of the generated class.

Additionally, some checks to ensure constructors always return an
instance of `Self` were lost.

This PR fixes the above two issues by embedding the kind of export into
the `CallExport` instruction and monitoring for constructor exports
calls during the export adapter creation.

Once a constructor export call is detected and validated a new
instruction `SelfFromI32` is pushed into the stack that avoids class
wrapping.

Fixes rustwasm#3213

Signed-off-by: Oliver T <geronimooliver00@gmail.com>
snOm3ad added a commit to snOm3ad/wasm-bindgen that referenced this pull request Aug 18, 2023
After rustwasm#1594 constructors of Rust exported structs started using class
wrapping when generating JS shims. Wrapping erases prototype information
from the object instance in JS and as a result it is not possible to
override methods (via inheritance) of the generated class.

Additionally, some checks to ensure constructors always return an
instance of `Self` were lost.

This PR is rebased from rustwasm#3561, it passes the constructor information
from the `Builder` into the instruction translation function which
is then used to modify the generated bindings.

The `return` statement is also removed instead the value is directly
attached to the instance.

Signed-off-by: Oliver T <geronimooliver00@gmail.com>
Liamolucko added a commit that referenced this pull request Aug 25, 2023
* Remove class wrap for constructors in Rust exports

After #1594 constructors of Rust exported structs started using class
wrapping when generating JS shims. Wrapping erases prototype information
from the object instance in JS and as a result it is not possible to
override methods (via inheritance) of the generated class.

Additionally, some checks to ensure constructors always return an
instance of `Self` were lost.

This PR is rebased from #3561, it passes the constructor information
from the `Builder` into the instruction translation function which
is then used to modify the generated bindings.

The `return` statement is also removed instead the value is directly
attached to the instance.

Signed-off-by: Oliver T <geronimooliver00@gmail.com>

* Fix typo

Co-authored-by: Liam Murphy <liampm32@gmail.com>

* Disallow returning JS primitives from constructors

Signed-off-by: Oliver T <geronimooliver00@gmail.com>

* Added missing String in match

Signed-off-by: Oliver T <geronimooliver00@gmail.com>

* Handle nested descriptors

Signed-off-by: Oliver T <geronimooliver00@gmail.com>

---------

Signed-off-by: Oliver T <geronimooliver00@gmail.com>
Co-authored-by: Liam Murphy <liampm32@gmail.com>
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