From 9729efe50e2c374a59dac2a0c9dfdd8ff205d855 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 24 Aug 2018 20:45:11 -0700 Subject: [PATCH] Remove casting to `&mut T` for JS casts I discussed this with @fitzgen awhile back and this sort of casting seems especially problematic when you have code along the lines of: let mut x: HtmlElement = ...; { let y: &mut JsValue = x.as_ref(); *y = 3.into(); } x.some_html_element_method(); as that will immediately throw! We didn't have a use case for mutable casting other than consistency, so this commit removes it for now. We can possibly add it back in later if motivated, but for now it seems reasonable to try to avoid these sorts of pitfalls! --- crates/backend/src/codegen.rs | 23 ----------------- src/cast.rs | 48 +---------------------------------- src/lib.rs | 5 ---- 3 files changed, 1 insertion(+), 75 deletions(-) diff --git a/crates/backend/src/codegen.rs b/crates/backend/src/codegen.rs index 45711ba3..8bdd391c 100644 --- a/crates/backend/src/codegen.rs +++ b/crates/backend/src/codegen.rs @@ -618,9 +618,6 @@ impl ToTokens for ast::ImportType { fn as_ref(&self) -> &JsValue { &self.obj } } - impl AsMut for #rust_name { - fn as_mut(&mut self) -> &mut JsValue { &mut self.obj } - } impl From<#rust_name> for JsValue { fn from(obj: #rust_name) -> JsValue { @@ -656,12 +653,6 @@ impl ToTokens for ast::ImportType { // wrapper around `val` unsafe { &*(val as *const JsValue as *const #rust_name) } } - - fn unchecked_from_js_mut(val: &mut JsValue) -> &mut Self { - // Should be safe because `#rust_name` is a transparent - // wrapper around `val` - unsafe { &mut *(val as *mut JsValue as *mut #rust_name) } - } } () @@ -683,13 +674,6 @@ impl ToTokens for ast::ImportType { #superclass::unchecked_from_js_ref(self.as_ref()) } } - - impl AsMut<#superclass> for #rust_name { - fn as_mut(&mut self) -> &mut #superclass { - use wasm_bindgen::JsCast; - #superclass::unchecked_from_js_mut(self.as_mut()) - } - } }).to_tokens(tokens); } } @@ -1191,9 +1175,6 @@ impl ToTokens for ast::Dictionary { impl AsRef for #name { fn as_ref(&self) -> &JsValue { self.obj.as_ref() } } - impl AsMut for #name { - fn as_mut(&mut self) -> &mut JsValue { self.obj.as_mut() } - } // Boundary conversion impls impl WasmDescribe for #name { @@ -1257,10 +1238,6 @@ impl ToTokens for ast::Dictionary { fn unchecked_from_js_ref(val: &JsValue) -> &Self { unsafe { &*(val as *const JsValue as *const #name) } } - - fn unchecked_from_js_mut(val: &mut JsValue) -> &mut Self { - unsafe { &mut *(val as *mut JsValue as *mut #name) } - } } }; }).to_tokens(tokens); diff --git a/src/cast.rs b/src/cast.rs index 928283d3..f856761b 100644 --- a/src/cast.rs +++ b/src/cast.rs @@ -14,7 +14,7 @@ use JsValue; /// [rfc]: https://github.com/rustwasm/rfcs/pull/2 pub trait JsCast where - Self: AsRef + AsMut + Into, + Self: AsRef + Into, { /// Test whether this JS value is an instance of the type `T`. /// @@ -61,24 +61,6 @@ where } } - /// Performs a dynamic cast (checked at runtime) of this value into the - /// target type `T`. - /// - /// This method will return `None` is `self.is_instance_of::()` - /// returns `false`, and otherwise it will return `Some(&mut T)` - /// manufactured with an unchecked cast (verified correct via the - /// `instanceof` operation). - fn dyn_mut(&mut self) -> Option<&mut T> - where - T: JsCast, - { - if self.is_instance_of::() { - Some(self.unchecked_mut()) - } else { - None - } - } - /// Performs a zero-cost unchecked cast into the specified type. /// /// This method will convert the `self` value to the type `T`, where both @@ -111,24 +93,6 @@ where T::unchecked_from_js_ref(self.as_ref()) } - /// Performs a zero-cost unchecked cast into a mutable reference to the - /// specified type. - /// - /// This method will convert the `self` value to the type `T`, where both - /// `self` and `T` are simple wrappers around `JsValue`. This method **does - /// not check whether `self` is an instance of `T`**. If used incorrectly - /// then this method may cause runtime exceptions in both Rust and JS, this - /// should be used with caution. - /// - /// This method, unlike `unchecked_into`, does not consume ownership of - /// `self` and instead works over a utable reference. - fn unchecked_mut(&mut self) -> &mut T - where - T: JsCast, - { - T::unchecked_from_js_mut(self.as_mut()) - } - /// Performs a dynamic `instanceof` check to see whether the `JsValue` /// provided is an instance of this type. /// @@ -152,14 +116,4 @@ where /// This is intended to be an internal implementation detail, you likely /// won't need to call this. fn unchecked_from_js_ref(val: &JsValue) -> &Self; - - /// Performs a zero-cost unchecked conversion from a `&mut JsValue` into an - /// instance of `&mut Self`. - /// - /// Note the safety of this method, which basically means that `Self` must - /// be a newtype wrapper around `JsValue`. - /// - /// This is intended to be an internal implementation detail, you likely - /// won't need to call this. - fn unchecked_from_js_mut(val: &mut JsValue) -> &mut Self; } diff --git a/src/lib.rs b/src/lib.rs index 7c9ce9f9..b26c872d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -370,11 +370,6 @@ impl JsCast for JsValue { fn instanceof(_val: &JsValue) -> bool { true } fn unchecked_from_js(val: JsValue) -> Self { val } fn unchecked_from_js_ref(val: &JsValue) -> &Self { val } - fn unchecked_from_js_mut(val: &mut JsValue) -> &mut Self { val } -} - -impl AsMut for JsValue { - fn as_mut(&mut self) -> &mut JsValue { self } } impl AsRef for JsValue {