mirror of
https://github.com/fluencelabs/wasm-bindgen
synced 2025-07-31 03:51:56 +00:00
Implement Deref
for all imported JS types
This commit implements the first half of [RFC #5] where the `Deref` trait is implemented for all imported types. The target of `Deref` is either the first entry of the list of `extends` attribute or `JsValue`. All examples using `.as_ref()` with various `web-sys` types have been updated to the more ergonomic deref casts now. Additionally the `web-sys` generation of the `extends` array has been fixed slightly to explicitly list implementatoins in the hierarchy order to ensure the correct target for `Deref` is chosen. [RFC #5]: https://github.com/rustwasm/rfcs/blob/master/text/005-structural-and-deref.md
This commit is contained in:
@@ -535,7 +535,7 @@ impl ToTokens for ast::ImportType {
|
||||
use wasm_bindgen::convert::RefFromWasmAbi;
|
||||
use wasm_bindgen::describe::WasmDescribe;
|
||||
use wasm_bindgen::{JsValue, JsCast};
|
||||
use wasm_bindgen::__rt::core::mem::ManuallyDrop;
|
||||
use wasm_bindgen::__rt::core;
|
||||
|
||||
impl WasmDescribe for #rust_name {
|
||||
fn describe() {
|
||||
@@ -589,13 +589,13 @@ impl ToTokens for ast::ImportType {
|
||||
|
||||
impl RefFromWasmAbi for #rust_name {
|
||||
type Abi = <JsValue as RefFromWasmAbi>::Abi;
|
||||
type Anchor = ManuallyDrop<#rust_name>;
|
||||
type Anchor = core::mem::ManuallyDrop<#rust_name>;
|
||||
|
||||
#[inline]
|
||||
unsafe fn ref_from_abi(js: Self::Abi, extra: &mut Stack) -> Self::Anchor {
|
||||
let tmp = <JsValue as RefFromWasmAbi>::ref_from_abi(js, extra);
|
||||
ManuallyDrop::new(#rust_name {
|
||||
obj: ManuallyDrop::into_inner(tmp),
|
||||
core::mem::ManuallyDrop::new(#rust_name {
|
||||
obj: core::mem::ManuallyDrop::into_inner(tmp),
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -657,6 +657,20 @@ impl ToTokens for ast::ImportType {
|
||||
};
|
||||
}).to_tokens(tokens);
|
||||
|
||||
let deref_target = match self.extends.first() {
|
||||
Some(target) => quote! { #target },
|
||||
None => quote! { JsValue },
|
||||
};
|
||||
(quote! {
|
||||
impl core::ops::Deref for #rust_name {
|
||||
type Target = #deref_target;
|
||||
|
||||
#[inline]
|
||||
fn deref(&self) -> &#deref_target {
|
||||
self.as_ref()
|
||||
}
|
||||
}
|
||||
}).to_tokens(tokens);
|
||||
for superclass in self.extends.iter() {
|
||||
(quote! {
|
||||
impl From<#rust_name> for #superclass {
|
||||
|
@@ -7,7 +7,8 @@ extern crate wasm_bindgen_futures;
|
||||
extern crate wasm_bindgen_test;
|
||||
extern crate web_sys;
|
||||
|
||||
use wasm_bindgen_test::wasm_bindgen_test_configure;
|
||||
use wasm_bindgen::{JsValue, JsCast};
|
||||
use wasm_bindgen_test::*;
|
||||
|
||||
wasm_bindgen_test_configure!(run_in_browser);
|
||||
|
||||
@@ -56,3 +57,11 @@ pub mod table_element;
|
||||
pub mod title_element;
|
||||
pub mod xpath_result;
|
||||
pub mod indexeddb;
|
||||
|
||||
#[wasm_bindgen_test]
|
||||
fn deref_works() {
|
||||
let x = JsValue::from(3);
|
||||
let x = x.unchecked_into::<web_sys::XmlHttpRequestUpload>();
|
||||
let y: &web_sys::XmlHttpRequestEventTarget = &x;
|
||||
drop(y);
|
||||
}
|
||||
|
@@ -735,11 +735,17 @@ impl<'src> FirstPass<'src, ()> for weedle::CallbackInterfaceDefinition<'src> {
|
||||
impl<'a> FirstPassRecord<'a> {
|
||||
pub fn all_superclasses<'me>(&'me self, interface: &str) -> impl Iterator<Item = String> + 'me {
|
||||
let mut set = BTreeSet::new();
|
||||
self.fill_superclasses(interface, &mut set);
|
||||
set.into_iter()
|
||||
let mut list = Vec::new();
|
||||
self.fill_superclasses(interface, &mut set, &mut list);
|
||||
list.into_iter()
|
||||
}
|
||||
|
||||
fn fill_superclasses(&self, interface: &str, set: &mut BTreeSet<String>) {
|
||||
fn fill_superclasses(
|
||||
&self,
|
||||
interface: &str,
|
||||
set: &mut BTreeSet<&'a str>,
|
||||
list: &mut Vec<String>,
|
||||
) {
|
||||
let data = match self.interfaces.get(interface) {
|
||||
Some(data) => data,
|
||||
None => return,
|
||||
@@ -749,8 +755,9 @@ impl<'a> FirstPassRecord<'a> {
|
||||
None => return,
|
||||
};
|
||||
if self.interfaces.contains_key(superclass) {
|
||||
if set.insert(camel_case_ident(superclass)) {
|
||||
self.fill_superclasses(superclass, set);
|
||||
if set.insert(superclass) {
|
||||
list.push(camel_case_ident(superclass));
|
||||
self.fill_superclasses(superclass, set, list);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user