From 9589ca286f2714b24cc092613684b71c18b04f70 Mon Sep 17 00:00:00 2001 From: Shelvacu Date: Fri, 20 Dec 2019 00:57:51 -0800 Subject: [PATCH] Fix clippy warnings --- .../static/css/todomvc-app-css/index.css | 4 +- src/ecosystem/serde.rs | 18 ++--- src/ecosystem/serde_json.rs | 2 +- src/lib.rs | 13 ++- src/webapi/array_buffer.rs | 8 +- src/webapi/blob.rs | 11 +++ src/webapi/date.rs | 2 + src/webapi/document.rs | 2 + src/webapi/element.rs | 4 +- src/webapi/event_target.rs | 2 +- src/webapi/events/drag.rs | 11 ++- src/webapi/events/mouse.rs | 2 +- src/webapi/file_list.rs | 5 ++ src/webapi/file_reader.rs | 6 ++ src/webapi/form_data.rs | 6 ++ src/webapi/global.rs | 2 +- src/webapi/history.rs | 5 ++ src/webapi/html_collection.rs | 5 ++ src/webapi/html_elements/image.rs | 6 ++ src/webapi/html_elements/slot.rs | 4 +- src/webapi/midi.rs | 10 +-- src/webapi/mutation_observer.rs | 7 +- src/webapi/node.rs | 8 +- src/webapi/node_list.rs | 5 ++ src/webapi/rendering_context.rs | 4 + src/webapi/shadow_root.rs | 4 +- src/webapi/storage.rs | 7 +- src/webapi/timer_future.rs | 9 +-- src/webapi/token_list.rs | 5 ++ src/webapi/typed_array.rs | 5 ++ src/webapi/web_socket.rs | 4 +- src/webapi/xml_http_request.rs | 6 ++ src/webcore/array.rs | 5 ++ src/webcore/executor.rs | 2 +- src/webcore/ffi/wasm_bindgen.rs | 8 +- src/webcore/global_arena.rs | 44 +++++++--- src/webcore/macros.rs | 10 +-- src/webcore/number.rs | 11 ++- src/webcore/object.rs | 31 ++++--- src/webcore/promise.rs | 7 +- src/webcore/promise_future.rs | 60 ++++++-------- src/webcore/reference_type.rs | 2 + src/webcore/serialization.rs | 81 ++++++++++--------- src/webcore/type_name.rs | 4 +- src/webcore/unsafe_typed_array.rs | 6 ++ src/webcore/value.rs | 22 +++-- 46 files changed, 309 insertions(+), 176 deletions(-) diff --git a/examples/todomvc/static/css/todomvc-app-css/index.css b/examples/todomvc/static/css/todomvc-app-css/index.css index e6e089cb..e8cc03a3 100644 --- a/examples/todomvc/static/css/todomvc-app-css/index.css +++ b/examples/todomvc/static/css/todomvc-app-css/index.css @@ -189,11 +189,11 @@ label[for='toggle-all'] { } .todo-list li .toggle:after { - content: url('data:image/svg+xml;utf8,'); + content: url('data:image/svg+xml;utf8,'); } .todo-list li .toggle:checked:after { - content: url('data:image/svg+xml;utf8,'); + content: url('data:image/svg+xml;utf8,'); } .todo-list li label { diff --git a/src/ecosystem/serde.rs b/src/ecosystem/serde.rs index b8fef8eb..3f09f839 100644 --- a/src/ecosystem/serde.rs +++ b/src/ecosystem/serde.rs @@ -168,15 +168,15 @@ impl Serialize for Value { } else if Object::instance_of( reference ) { let object: Object = reference.try_into().unwrap(); let value: BTreeMap< String, Value > = object.into(); - let mut map = try!( serializer.serialize_map( Some( value.len() ) ) ); + let mut map = serializer.serialize_map( Some( value.len() ) )?; for (key, value) in value { - try!( map.serialize_key( &key ) ); - try!( map.serialize_value( &value ) ); + map.serialize_key( &key )?; + map.serialize_value( &value )?; } map.end() } else { - let map = try!( serializer.serialize_map( None ) ); + let map = serializer.serialize_map( None )?; map.end() } } @@ -377,7 +377,7 @@ impl From< ConversionError > for value::ConversionError { } } -#[derive(Debug)] +#[derive(Default, Debug)] pub struct Serializer { } @@ -526,7 +526,7 @@ impl< 'a > ser::Serializer for &'a mut Serializer { } #[doc(hidden)] -#[cfg_attr(feature = "cargo-clippy", allow(needless_pass_by_value))] +#[allow(clippy::needless_pass_by_value)] #[inline] pub fn to_value< T: Serialize >( value: T ) -> Result< Value, ConversionError > { let mut serializer = Serializer {}; @@ -869,8 +869,8 @@ impl< 'de > de::Deserializer< 'de > for Value { }; visitor.visit_enum( EnumDeserializer { - variant: variant, - value: value, + variant, + value, }) } @@ -1254,7 +1254,7 @@ impl< T: fmt::Debug > fmt::Debug for Serde< T > { impl< T: Serialize > JsSerialize for Serde< T > { #[inline] - fn _into_js< 'a >( &'a self ) -> SerializedValue< 'a > { + fn _into_js( &self ) -> SerializedValue { let value = to_value( &self.0 ).unwrap(); global_arena::serialize_value( value ) } diff --git a/src/ecosystem/serde_json.rs b/src/ecosystem/serde_json.rs index ca713dee..b2311b25 100644 --- a/src/ecosystem/serde_json.rs +++ b/src/ecosystem/serde_json.rs @@ -35,7 +35,7 @@ impl TryFrom< JsonValue > for Value { JsonValue::Object( value ) => { let mut map: BTreeMap< String, Value > = BTreeMap::new(); for (key, value) in value.into_iter() { - map.insert( key.into(), value.try_into()? ); + map.insert( key, value.try_into()? ); } map.into() diff --git a/src/lib.rs b/src/lib.rs index fde84f75..a918fc3d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -539,6 +539,17 @@ pub mod traits { pub use super::web::midi::IMidiPort; } +#[cfg(test)] +mod tests { + #[test] + fn bla() { + // use webcore::try_from::TryInto; + // let res:bool = js!{ false }.try_into().unwrap(); + // assert!(res); + println!("hi"); + } +} + #[doc(hidden)] pub mod private { #[cfg(all(target_arch = "wasm32", target_vendor = "unknown", target_os = "unknown", not(cargo_web)))] @@ -551,7 +562,7 @@ pub mod private { pub use webcore::serialization::{ JsSerialize, JsSerializeOwned, - SerializedValue + SerializedValue, }; pub use webcore::newtype::{ diff --git a/src/webapi/array_buffer.rs b/src/webapi/array_buffer.rs index 0da70f0d..b234d0ff 100644 --- a/src/webapi/array_buffer.rs +++ b/src/webapi/array_buffer.rs @@ -26,8 +26,12 @@ impl ArrayBuffer { // https://www.ecma-international.org/ecma-262/6.0/#sec-get-arraybuffer.prototype.bytelength pub fn len( &self ) -> u64 { let reference = self.as_ref(); - let length = js!( return @{reference}.byteLength; ).try_into().unwrap(); - length + js!( return @{reference}.byteLength; ).try_into().unwrap() + } + + /// Returns `true` if the buffer contains no bytes. + pub fn is_empty( &self ) -> bool { + self.len() == 0 } } diff --git a/src/webapi/blob.rs b/src/webapi/blob.rs index 09db2728..0bf00a64 100644 --- a/src/webapi/blob.rs +++ b/src/webapi/blob.rs @@ -77,6 +77,11 @@ pub trait IBlob: ReferenceType { { slice_blob(self, range, Some(content_type)) } + + /// Returns `true` if the `Blob` contains no bytes. + fn is_empty( &self ) -> bool { + self.len() == 0 + } } /// A reference to a JavaScript object which implements the [IBlob](trait.IBlob.html) @@ -90,6 +95,12 @@ pub struct Blob( Reference ); impl IBlob for Blob {} +impl Default for Blob { + fn default() -> Self { + Self::new() + } +} + impl Blob { /// Creates a new `Blob`. /// diff --git a/src/webapi/date.rs b/src/webapi/date.rs index 49476625..349e30bc 100644 --- a/src/webapi/date.rs +++ b/src/webapi/date.rs @@ -13,6 +13,7 @@ impl Date { /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date) // https://www.ecma-international.org/ecma-262/6.0/#sec-date-constructor-date + #[allow(clippy::new_without_default)] // Because this generates a different value every time, Default is not appropriate. pub fn new() -> Self { js!( return new Date(); @@ -485,6 +486,7 @@ impl Date { /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toString) // https://www.ecma-international.org/ecma-262/6.0/#sec-date.prototype.tostring #[inline] + #[allow(clippy::inherent_to_string)] // We're matching the JS api here. pub fn to_string(&self) -> String { js!( return @{self}.toString(); diff --git a/src/webapi/document.rs b/src/webapi/document.rs index e01c8ccf..05875209 100644 --- a/src/webapi/document.rs +++ b/src/webapi/document.rs @@ -1,6 +1,8 @@ use webcore::value::{Reference, Value}; use webcore::try_from::{TryInto, TryFrom}; +#[cfg(feature = "experimental_features_which_may_break_on_minor_version_bumps")] use webcore::promise::{Promise, TypedPromise}; +#[cfg(feature = "experimental_features_which_may_break_on_minor_version_bumps")] use webapi::error::TypeError; use webapi::event_target::{IEventTarget, EventTarget}; use webapi::node::{INode, Node, CloneKind}; diff --git a/src/webapi/element.rs b/src/webapi/element.rs index 3e045150..df1110b3 100644 --- a/src/webapi/element.rs +++ b/src/webapi/element.rs @@ -1,6 +1,8 @@ use webcore::value::Reference; use webcore::try_from::{TryFrom, TryInto}; +#[cfg(feature = "experimental_features_which_may_break_on_minor_version_bumps")] use webcore::promise::{Promise, TypedPromise}; +#[cfg(feature = "experimental_features_which_may_break_on_minor_version_bumps")] use webapi::error::TypeError; use webapi::dom_exception::{InvalidCharacterError, InvalidPointerId, NoModificationAllowedError, SyntaxError}; use webapi::event_target::{IEventTarget, EventTarget}; @@ -315,8 +317,8 @@ pub enum InsertPosition { AfterEnd, } -/// Errors thrown by `Element::insert_adjacent_html`. error_enum_boilerplate! { + /// Errors thrown by `Element::insert_adjacent_html`. InsertAdjacentError, NoModificationAllowedError, SyntaxError } diff --git a/src/webapi/event_target.rs b/src/webapi/event_target.rs index 25e84d6c..7a12bca1 100644 --- a/src/webapi/event_target.rs +++ b/src/webapi/event_target.rs @@ -60,7 +60,7 @@ pub trait IEventTarget: ReferenceType { EventListenerHandle { event_type: T::EVENT_TYPE, reference: reference.clone(), - listener_reference: listener_reference + listener_reference } } diff --git a/src/webapi/events/drag.rs b/src/webapi/events/drag.rs index 1b3c7d0e..e2628254 100644 --- a/src/webapi/events/drag.rs +++ b/src/webapi/events/drag.rs @@ -486,6 +486,11 @@ impl DataTransferItemList { index: 0, } } + + /// Returns `true` if there are no drag items in the list. + pub fn is_empty( &self ) -> bool { + self.len() == 0 + } } impl IntoIterator for DataTransferItemList { @@ -598,10 +603,8 @@ impl DataTransferItem { pub fn get_as_string_future( &self ) -> oneshot::Receiver { let (sender, receiver) = oneshot::channel(); let callback = |s: String| { - match sender.send(s) { - Ok(_) => {}, - Err(_) => {}, - }; + // Ignore the Result, Ok gives () and Err only happens if the receiver is dropped before this is called, which is fine. + let _ = sender.send(s); }; js!(@(no_return) diff --git a/src/webapi/events/mouse.rs b/src/webapi/events/mouse.rs index 46261b0f..f6dca3dc 100644 --- a/src/webapi/events/mouse.rs +++ b/src/webapi/events/mouse.rs @@ -227,7 +227,7 @@ pub struct MouseButtonsState(u8); impl MouseButtonsState { /// Check if a [MouseButton](enum.MouseButton.html) is currently pressed - pub fn is_down(&self, button: MouseButton) -> bool { + pub fn is_down(self, button: MouseButton) -> bool { match button { MouseButton::Left => self.0 & 0b1 != 0, MouseButton::Right => self.0 & 0b10 != 0, diff --git a/src/webapi/file_list.rs b/src/webapi/file_list.rs index 57b51185..eb9aea2c 100644 --- a/src/webapi/file_list.rs +++ b/src/webapi/file_list.rs @@ -29,6 +29,11 @@ impl FileList { index: 0 } } + + /// Returns `true` if the list contains no Files + pub fn is_empty( &self ) -> bool { + self.len() == 0 + } } impl IntoIterator for FileList { diff --git a/src/webapi/file_reader.rs b/src/webapi/file_reader.rs index 2ee408fe..5fc18a23 100644 --- a/src/webapi/file_reader.rs +++ b/src/webapi/file_reader.rs @@ -41,6 +41,12 @@ pub enum FileReaderReadyState { Done } +impl Default for FileReader { + fn default() -> Self { + Self::new() + } +} + impl FileReader { /// Returns a newly constructed `FileReader`. /// diff --git a/src/webapi/form_data.rs b/src/webapi/form_data.rs index ebede27f..2bfdb201 100644 --- a/src/webapi/form_data.rs +++ b/src/webapi/form_data.rs @@ -63,6 +63,12 @@ impl TryFrom< Value > for Option< FormDataEntry > { } } +impl Default for FormData { + fn default() -> Self { + Self::new() + } +} + impl FormData { /// Creates a new `FormData`. /// diff --git a/src/webapi/global.rs b/src/webapi/global.rs index 4c039ac7..6e511cca 100644 --- a/src/webapi/global.rs +++ b/src/webapi/global.rs @@ -13,5 +13,5 @@ pub fn alert( message: &str ) { /// An alias for [window.confirm](struct.Window.html#method.confirm). pub fn confirm( message: &str ) -> bool { - return window().confirm( message ); + window().confirm( message ) } diff --git a/src/webapi/history.rs b/src/webapi/history.rs index c99a9eec..c0de69f3 100644 --- a/src/webapi/history.rs +++ b/src/webapi/history.rs @@ -96,4 +96,9 @@ impl History { return @{self}.length; ).try_into().unwrap() } + + /// Returns `true` if there are no history entries. + pub fn is_empty( &self ) -> bool { + self.len() == 0 + } } diff --git a/src/webapi/html_collection.rs b/src/webapi/html_collection.rs index 337265dc..3f6c253c 100644 --- a/src/webapi/html_collection.rs +++ b/src/webapi/html_collection.rs @@ -41,6 +41,11 @@ impl HtmlCollection { index: 0 } } + + /// Returns true if the collection contains no elements + pub fn is_empty( &self ) -> bool { + self.len() == 0 + } } diff --git a/src/webapi/html_elements/image.rs b/src/webapi/html_elements/image.rs index 13a4f9b6..d543b8d5 100644 --- a/src/webapi/html_elements/image.rs +++ b/src/webapi/html_elements/image.rs @@ -21,6 +21,12 @@ impl INode for ImageElement {} impl IElement for ImageElement {} impl IHtmlElement for ImageElement {} +impl Default for ImageElement { + fn default() -> Self { + Self::new() + } +} + impl ImageElement { /// Constructs a new ImageElement. /// diff --git a/src/webapi/html_elements/slot.rs b/src/webapi/html_elements/slot.rs index a269189f..a0ebb480 100644 --- a/src/webapi/html_elements/slot.rs +++ b/src/webapi/html_elements/slot.rs @@ -18,8 +18,8 @@ pub enum SlotContentKind { } impl SlotContentKind { - fn to_bool(&self) -> bool { - match *self { + fn to_bool(self) -> bool { + match self { SlotContentKind::AssignedOnly => false, SlotContentKind::WithFallback => true, } diff --git a/src/webapi/midi.rs b/src/webapi/midi.rs index 3b374740..de558146 100644 --- a/src/webapi/midi.rs +++ b/src/webapi/midi.rs @@ -86,7 +86,7 @@ impl MidiAccess { /// The MIDI input ports available to the system. // https://webaudio.github.io/web-midi-api/#dom-midiaccess-inputs pub fn inputs( &self ) -> MidiInputMap { - return js!( + js!( return @{self}.inputs; ).try_into().unwrap() } @@ -94,7 +94,7 @@ impl MidiAccess { /// The MIDI output ports available to the system. // https://webaudio.github.io/web-midi-api/#dom-midiaccess-outputs pub fn outputs( &self ) -> MidiOutputMap { - return js!( + js!( return @{self}.outputs; ).try_into().unwrap() } @@ -102,7 +102,7 @@ impl MidiAccess { /// This attribute informs the user whether system exclusive support is enabled. // https://webaudio.github.io/web-midi-api/#dom-midiaccess-sysexenabled pub fn sysex_enabled( &self ) -> bool { - return js!( + js!( return @{self}.sysexEnabled; ).try_into().unwrap() } @@ -189,13 +189,13 @@ pub trait IMidiPort: IEventTarget { /// has chosen for their application. // https://webaudio.github.io/web-midi-api/#dom-midiport-id fn id( &self ) -> String { - return js!( return @{self.as_ref()}.id; ).try_into().unwrap(); + js!( return @{self.as_ref()}.id; ).try_into().unwrap() } /// The system name of the port. // https://webaudio.github.io/web-midi-api/#dom-midiport-name fn name( &self ) -> Option< String > { - return js!( return @{self.as_ref()}.name; ).try_into().unwrap(); + js!( return @{self.as_ref()}.name; ).try_into().unwrap() } } diff --git a/src/webapi/mutation_observer.rs b/src/webapi/mutation_observer.rs index 649b5420..fd0374bf 100644 --- a/src/webapi/mutation_observer.rs +++ b/src/webapi/mutation_observer.rs @@ -63,6 +63,7 @@ impl MutationObserver { /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver#Constructor) // https://dom.spec.whatwg.org/#ref-for-dom-mutationobserver-mutationobserver + #[allow(clippy::new_ret_no_self)] pub fn new< F >( callback: F ) -> MutationObserverHandle where F: FnMut( Vec< MutationRecord >, Self ) + 'static { let callback_reference: Reference = js! ( return @{Mut(callback)}; ).try_into().unwrap(); @@ -252,19 +253,19 @@ impl TryFrom< Value > for MutationRecord { match kind.as_str() { "attributes" => Ok( MutationRecord::Attribute { - target: target, + target, name: js!( return @{r}.attributeName; ).try_into()?, namespace: js!( return @{r}.attributeNamespace; ).try_into()?, old_value: js!( return @{r}.oldValue; ).try_into()?, } ), "characterData" => Ok( MutationRecord::CharacterData { - target: target, + target, old_data: js!( return @{r}.oldValue; ).try_into()?, } ), "childList" => Ok( MutationRecord::ChildList { - target: target, + target, inserted_nodes: js!( return @{r}.addedNodes; ).try_into()?, removed_nodes: js!( return @{r}.removedNodes; ).try_into()?, previous_sibling: js!( return @{r}.previousSibling; ).try_into()?, diff --git a/src/webapi/node.rs b/src/webapi/node.rs index 1c735b08..12409f46 100644 --- a/src/webapi/node.rs +++ b/src/webapi/node.rs @@ -1,5 +1,3 @@ -use std::mem; - use webcore::value::Reference; use webcore::try_from::{TryFrom, TryInto}; use webapi::document::Document; @@ -30,7 +28,8 @@ pub trait INode: IEventTarget { fn as_node( &self ) -> &Node { let reference: &Reference = self.as_ref(); unsafe { - mem::transmute( reference ) + //TODO: Is this really always safe? Can't downstream implementors implement INode? + &*(reference as *const Reference as *const Node) } } @@ -344,8 +343,9 @@ pub trait INode: IEventTarget { } } -/// Errors thrown by `Node` insertion methods. + error_enum_boilerplate! { + /// Errors thrown by `Node` insertion methods. InsertNodeError, NotFoundError, HierarchyRequestError } diff --git a/src/webapi/node_list.rs b/src/webapi/node_list.rs index 04cfb3c8..a2e35cb9 100644 --- a/src/webapi/node_list.rs +++ b/src/webapi/node_list.rs @@ -47,6 +47,11 @@ impl NodeList { index: 0 } } + + /// Returns `true` if the list contains no Nodes. + pub fn is_empty( &self ) -> bool { + self.len() == 0 + } } impl IntoIterator for NodeList { diff --git a/src/webapi/rendering_context.rs b/src/webapi/rendering_context.rs index 4ac8d33f..ffdedaa3 100644 --- a/src/webapi/rendering_context.rs +++ b/src/webapi/rendering_context.rs @@ -1059,6 +1059,7 @@ impl CanvasRenderingContext2d { /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/drawImage) // https://html.spec.whatwg.org/#2dcontext:dom-context-2d-drawimage + #[allow(clippy::too_many_arguments)] // I would agree it's too many, but we're trying to match the standard. pub fn draw_image_s(&self, image: ImageElement, sx: f64, sy: f64, s_width: f64, s_height: f64, dx: f64, dy: f64, d_width: f64, d_height: f64 @@ -1210,6 +1211,7 @@ impl CanvasRenderingContext2d { /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/putImageData) // https://html.spec.whatwg.org/#2dcontext:dom-context-2d-putimagedata + #[allow(clippy::too_many_arguments)] // I would agree it's too many, but we're trying to match the standard. pub fn put_image_data_dirty(&self, image_data: ImageData, dx: f32, dy: f32, @@ -1306,6 +1308,7 @@ impl CanvasRenderingContext2d { /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/setTransform) // https://html.spec.whatwg.org/#2dcontext:dom-context-2d-settransform + #[allow(clippy::many_single_char_names)] pub fn set_transform(&self, a: f64, b: f64, c: f64, d: f64, e: f64, f: f64) { js! { @(no_return) @{&self.0}.setTransform(@{a}, @{b}, @{c}, @{d}, @{e}, @{f}); @@ -1359,6 +1362,7 @@ impl CanvasRenderingContext2d { /// /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/transform) // https://html.spec.whatwg.org/#2dcontext:dom-context-2d-transform + #[allow(clippy::many_single_char_names)] pub fn transform(&self, a: f64, b: f64, c: f64, d: f64, e: f64, f: f64) { js! { @(no_return) @{&self.0}.transform(@{a}, @{b}, @{c}, @{d}, @{e}, @{f}); diff --git a/src/webapi/shadow_root.rs b/src/webapi/shadow_root.rs index afb42d3c..ed6ec868 100644 --- a/src/webapi/shadow_root.rs +++ b/src/webapi/shadow_root.rs @@ -19,8 +19,8 @@ pub enum ShadowRootMode { } impl ShadowRootMode { - pub(crate) fn as_str(&self) -> &'static str { - match *self { + pub(crate) fn as_str(self) -> &'static str { + match self { ShadowRootMode::Open => "open", ShadowRootMode::Closed => "closed", } diff --git a/src/webapi/storage.rs b/src/webapi/storage.rs index c1aa748e..1585ff50 100644 --- a/src/webapi/storage.rs +++ b/src/webapi/storage.rs @@ -68,8 +68,13 @@ impl Storage { js!( return @{self}.key( @{nth} ); ).try_into().ok() } - /// Returns true if the storage contains a value for the specified key. + /// Returns `true` if the storage contains a value for the specified key. pub fn contains_key( &self, key: &str ) -> bool { js!( return !!@{self}.getItem( @{key} ); ).try_into().unwrap() } + + /// Returns `true` if the storage contains no data items. + pub fn is_empty( &self ) -> bool { + self.len() == 0 + } } diff --git a/src/webapi/timer_future.rs b/src/webapi/timer_future.rs index d1441c26..8e1d84fb 100644 --- a/src/webapi/timer_future.rs +++ b/src/webapi/timer_future.rs @@ -36,11 +36,8 @@ impl Wait { let ( sender, receiver ) = oneshot::channel(); let callback = move || { - // TODO is this correct ? - match sender.send( () ) { - Ok( _ ) => {}, - Err( _ ) => {}, - }; + // We unwrap here because an Error value indicates a significant bug in this code. + sender.send(()).unwrap(); }; let timer = js!( @@ -66,7 +63,7 @@ impl Future for Wait { #[inline] fn poll( mut self: Pin< &mut Self >, cx: &mut Context ) -> Poll< Self::Output > { - // TODO is this unwrap correct ? + // We unwrap here because an Error value indicates a significant bug in this code. self.receiver.poll_unpin( cx ).map( |x| x.unwrap() ) } } diff --git a/src/webapi/token_list.rs b/src/webapi/token_list.rs index c1eead02..04cbd736 100644 --- a/src/webapi/token_list.rs +++ b/src/webapi/token_list.rs @@ -50,4 +50,9 @@ impl TokenList { pub fn contains( &self, token: &str ) -> bool { js!( return @{self}.contains( @{token} ); ).try_into().unwrap() } + + /// Returns `true` if the list contains no tokens. + pub fn is_empty( &self ) -> bool { + self.len() == 0 + } } diff --git a/src/webapi/typed_array.rs b/src/webapi/typed_array.rs index 9b1702a7..63db1484 100644 --- a/src/webapi/typed_array.rs +++ b/src/webapi/typed_array.rs @@ -130,6 +130,11 @@ impl< T: ArrayKind > TypedArray< T > { pub fn to_vec( &self ) -> Vec< T > { T::from_typed_array( self ) } + + /// Returns `true` if the buffer contains no elements. + pub fn is_empty( &self ) -> bool { + self.len() == 0 + } } impl< 'a, T: ArrayKind > From< &'a [T] > for TypedArray< T > { diff --git a/src/webapi/web_socket.rs b/src/webapi/web_socket.rs index 28782fbd..e55e6dd4 100644 --- a/src/webapi/web_socket.rs +++ b/src/webapi/web_socket.rs @@ -277,14 +277,14 @@ impl WebSocket { } } -/// Errors thrown by `WebSocket::new`. error_enum_boilerplate! { + /// Errors thrown by `WebSocket::new`. CreationError, SecurityError, SyntaxError } -/// Errors thrown by `WebSocket::close_with_status`. error_enum_boilerplate! { + /// Errors thrown by `WebSocket::close_with_status`. CloseError, InvalidAccessError, SyntaxError } diff --git a/src/webapi/xml_http_request.rs b/src/webapi/xml_http_request.rs index e57ab0bc..abe85584 100644 --- a/src/webapi/xml_http_request.rs +++ b/src/webapi/xml_http_request.rs @@ -68,6 +68,12 @@ error_enum_boilerplate! { InvalidAccessError } +impl Default for XmlHttpRequest { + fn default() -> Self { + Self::new() + } +} + impl XmlHttpRequest { /// Creates new `XmlHttpRequest`. // https://xhr.spec.whatwg.org/#ref-for-dom-xmlhttprequest diff --git a/src/webcore/array.rs b/src/webcore/array.rs index 32461ca0..af6db162 100644 --- a/src/webcore/array.rs +++ b/src/webcore/array.rs @@ -14,6 +14,11 @@ impl Array { return @{self}.length; ).try_into().unwrap() } + + /// Returns `true` if the array has no elements. + pub fn is_empty( &self ) -> bool { + self.len() == 0 + } } impl From< Array > for Vec< Value > { diff --git a/src/webcore/executor.rs b/src/webcore/executor.rs index 77ba6c5d..94f08a85 100644 --- a/src/webcore/executor.rs +++ b/src/webcore/executor.rs @@ -254,7 +254,7 @@ impl EventLoopExecutor { let queue = Rc::new( EventLoopQueue { inner: RefCell::new( EventLoopInner { - queue: queue, + queue, past_sum: 0, past_length: 0, shrink_counter: 0, diff --git a/src/webcore/ffi/wasm_bindgen.rs b/src/webcore/ffi/wasm_bindgen.rs index c8abfd72..3b69a78d 100644 --- a/src/webcore/ffi/wasm_bindgen.rs +++ b/src/webcore/ffi/wasm_bindgen.rs @@ -64,15 +64,15 @@ pub fn initialize() { fn wasm_bindgen_initialize( memory: JsValue, table: JsValue, - alloc: &Closure< Fn( usize ) -> *mut u8 >, - free: &Closure< Fn( *mut u8, usize ) > + alloc: &Closure< dyn Fn( usize ) -> *mut u8 >, + free: &Closure< dyn Fn( *mut u8, usize ) > ) -> JsValue; } let memory = wasm_bindgen::memory(); let table = wasm_bindgen::function_table(); - let alloc = Closure::wrap( Box::new( alloc ) as Box< Fn( usize ) -> *mut u8 > ); - let free = Closure::wrap( Box::new( free ) as Box< Fn( *mut u8, usize ) > ); + let alloc = Closure::wrap( Box::new( alloc ) as Box< dyn Fn( usize ) -> *mut u8 > ); + let free = Closure::wrap( Box::new( free ) as Box< dyn Fn( *mut u8, usize ) > ); unsafe { let module = wasm_bindgen_initialize( memory, table, &alloc, &free ); MODULE = Module( Some( module ) ); diff --git a/src/webcore/global_arena.rs b/src/webcore/global_arena.rs index 79bea4b5..0ca831a5 100644 --- a/src/webcore/global_arena.rs +++ b/src/webcore/global_arena.rs @@ -4,19 +4,19 @@ use std::marker::PhantomData; use webcore::value::Value; use webcore::serialization::{JsSerialize, SerializedValue}; -struct GlobalArena { - memory: *mut u8, +struct GlobalArena { + memory: *mut T, capacity: usize, length: usize } -static mut VALUE_ARENA: GlobalArena = GlobalArena { - memory: 0 as *mut u8, +static mut VALUE_ARENA: GlobalArena = GlobalArena { + memory: 0 as *mut Value, capacity: 0, length: 0 }; -static mut ARENA: GlobalArena = GlobalArena { +static mut ARENA: GlobalArena = GlobalArena { memory: 0 as *mut u8, capacity: 0, length: 0 @@ -44,7 +44,7 @@ impl< 'a, T: 'a > RelativeSlice< 'a, T > { pub unsafe fn append( &mut self, value: T ) { debug_assert!( self.tail + mem::size_of::< T >() <= self.offset + self.length * mem::size_of::< T >() ); - let pointer = ARENA.memory.offset( self.tail as isize ) as *mut T; + let pointer = ARENA.memory.add( self.tail ) as *mut T; mem::forget( mem::replace( &mut *pointer, value ) ); self.tail += mem::size_of::< T >(); } @@ -53,10 +53,11 @@ impl< 'a, T: 'a > RelativeSlice< 'a, T > { #[doc(hidden)] pub fn serialize_value< 'a >( value: Value ) -> SerializedValue< 'a > { unsafe { + // If I understand this correctly, because Vec is doing all the allocating when the type parameter is `Value`, it will always allocate correctly `Value`-aligned pointers, even though we're casting back and forth. let mut vec = Vec::from_raw_parts( VALUE_ARENA.memory as *mut Value, VALUE_ARENA.length, VALUE_ARENA.capacity ); vec.push( value ); let pointer = vec.last().unwrap() as *const Value; - VALUE_ARENA.memory = vec.as_mut_ptr() as *mut u8; + VALUE_ARENA.memory = vec.as_mut_ptr(); VALUE_ARENA.length = vec.len(); VALUE_ARENA.capacity = vec.capacity(); mem::forget( vec ); @@ -69,7 +70,7 @@ pub fn serialize_value< 'a >( value: Value ) -> SerializedValue< 'a > { pub fn reserve< 'a, T >( length: usize ) -> RelativeSlice< 'a, T > { unsafe { let offset = reserve_impl( length * mem::size_of::< T >(), mem::align_of::< T >() ); - debug_assert_eq!( ARENA.memory.offset( offset as isize ) as usize % mem::align_of::< T >(), 0 ); + debug_assert_eq!( ARENA.memory.add( offset ) as usize % mem::align_of::< T >(), 0 ); RelativeSlice { offset, length, tail: offset, phantom: PhantomData } } @@ -108,6 +109,7 @@ pub struct ArenaRestorePoint { impl ArenaRestorePoint { #[doc(hidden)] + #[allow(clippy::new_without_default)] #[inline] pub fn new() -> Self { unsafe { @@ -128,9 +130,9 @@ impl Drop for ArenaRestorePoint { debug_assert!( VALUE_ARENA.length >= self.value_arena_length ); let count = VALUE_ARENA.length - self.value_arena_length; if count > 0 { - let mut vec = Vec::from_raw_parts( VALUE_ARENA.memory as *mut Value, VALUE_ARENA.length, VALUE_ARENA.capacity ); + let mut vec = Vec::from_raw_parts( VALUE_ARENA.memory, VALUE_ARENA.length, VALUE_ARENA.capacity ); vec.truncate( self.value_arena_length ); - VALUE_ARENA.memory = vec.as_mut_ptr() as *mut u8; + VALUE_ARENA.memory = vec.as_mut_ptr(); VALUE_ARENA.length = vec.len(); VALUE_ARENA.capacity = vec.capacity(); mem::forget( vec ); @@ -141,7 +143,7 @@ impl Drop for ArenaRestorePoint { #[cfg(test)] mod tests { - use super::{ARENA, VALUE_ARENA, GlobalArena}; + use super::{ARENA, VALUE_ARENA, GlobalArena, Value}; unsafe fn clear() { // This will leak, but in tests we don't care. @@ -152,7 +154,7 @@ mod tests { }; VALUE_ARENA = GlobalArena { - memory: 0 as *mut u8, + memory: 0 as *mut Value, capacity: 0, length: 0 }; @@ -197,4 +199,22 @@ mod tests { assert_eq!( ARENA.capacity, capacity ); } } + + // #[test] + // fn tests_are_working() { + // unsafe { + // clear(); + // use webcore::try_from::TryInto; + // let message = "Hello, 世界!"; + // println!("{}", message); + // let result = js! { + // return 2 + 2 * 2; + // }; + + // println!( "2 + 2 * 2 = {:?}", result ); + // let j = js!{return false;}; + // dbg!(j); + // assert!(false); + // } + // } } diff --git a/src/webcore/macros.rs b/src/webcore/macros.rs index 933825c4..f9b4f879 100644 --- a/src/webcore/macros.rs +++ b/src/webcore/macros.rs @@ -132,7 +132,7 @@ macro_rules! _js_impl { let restore_point = $crate::private::ArenaRestorePoint::new(); $crate::_js_impl!( @serialize [$($args)*] [$($arg_names)*] ); - #[allow(unused_unsafe, unused_parens)] + #[allow(unused_unsafe, unused_parens, clippy::too_many_arguments)] let result = unsafe { $crate::_js_impl!( @if no_return in [$($flags)*] {{ @@ -255,14 +255,14 @@ macro_rules! __js_serializable_boilerplate { (($($impl_arg:tt)*) ($($kind_arg:tt)*) ($($bounds:tt)*)) => { impl< $($impl_arg)* > $crate::private::JsSerializeOwned for $($kind_arg)* where $($bounds)* { #[inline] - fn into_js_owned< '_a >( value: &'_a mut Option< Self > ) -> $crate::private::SerializedValue< '_a > { + fn into_js_owned( value: &mut Option< Self > ) -> $crate::private::SerializedValue { $crate::private::JsSerialize::_into_js( value.as_ref().unwrap() ) } } impl< '_r, $($impl_arg)* > $crate::private::JsSerializeOwned for &'_r $($kind_arg)* where $($bounds)* { #[inline] - fn into_js_owned< '_a >( value: &'_a mut Option< Self > ) -> $crate::private::SerializedValue< '_a > { + fn into_js_owned( value: &mut Option< Self > ) -> $crate::private::SerializedValue { $crate::private::JsSerialize::_into_js( value.unwrap() ) } } @@ -485,10 +485,10 @@ macro_rules! error_enum_boilerplate { impl ::webcore::serialization::JsSerialize for $error_name { #[doc(hidden)] #[inline] - fn _into_js< 'a >( &'a self ) -> ::webcore::serialization::SerializedValue< 'a > { + fn _into_js( &self ) -> ::webcore::serialization::SerializedValue { let reference: &::webcore::value::Reference = match self { $( - &$error_name::$variant( ref variant ) => variant.as_ref(), + $error_name::$variant( ref variant ) => variant.as_ref(), )+ }; diff --git a/src/webcore/number.rs b/src/webcore/number.rs index 0216d3d1..578e6f3c 100644 --- a/src/webcore/number.rs +++ b/src/webcore/number.rs @@ -5,9 +5,10 @@ use std::error; use std::fmt; use webcore::try_from::TryFrom; -// 2^53 - 1 -const MAX_SAFE_INTEGER_F64: i64 = 9007199254740991; -const MIN_SAFE_INTEGER_F64: i64 = -9007199254740991; +#[allow(clippy::unreadable_literal)] +const MAX_SAFE_INTEGER_F64: i64 = 9007199254740991;//(2_i64.pow(53)) - 1; +#[allow(clippy::unreadable_literal)] +const MIN_SAFE_INTEGER_F64: i64 = -9007199254740991;//-((2_i64.pow(53)) - 1); #[derive(Copy, Clone, PartialEq, Debug)] pub enum Storage { @@ -242,7 +243,9 @@ macro_rules! i32_to_big_unsigned_integer { macro_rules! f64_to_integer { ($value:expr, $kind:tt) => {{ - if $value.floor() != $value { + #[allow(clippy::float_cmp)] // I find integer checking to be a perfectly reasonable reason to compare floats + let comparison = $value.floor() != $value; + if comparison { return Err( ConversionError::NotAnInteger ); } diff --git a/src/webcore/object.rs b/src/webcore/object.rs index 745fff50..b2052d6b 100644 --- a/src/webcore/object.rs +++ b/src/webcore/object.rs @@ -44,6 +44,11 @@ impl Object { pub fn to_iter( &self ) -> impl ExactSizeIterator < Item = ( String, Value ) > { deserialize_object_to_iter( self.as_ref() ) } + + /// Returns `true` if object has no elements. + pub fn is_empty( &self ) -> bool { + self.len() == 0 + } } impl From< Object > for BTreeMap< String, Value > { @@ -64,19 +69,19 @@ impl< 'a > From< &'a mut Object > for BTreeMap< String, Value > { } } -impl From< Object > for HashMap< String, Value > { +impl< S: std::hash::BuildHasher + Default > From< Object > for HashMap< String, Value, S > { fn from( object: Object ) -> Self { deserialize_object( &object.0, |iter| iter.collect() ) } } -impl< 'a > From< &'a Object > for HashMap< String, Value > { +impl< 'a, S: std::hash::BuildHasher + Default > From< &'a Object > for HashMap< String, Value, S > { fn from( object: &'a Object ) -> Self { deserialize_object( &object.0, |iter| iter.collect() ) } } -impl< 'a > From< &'a mut Object > for HashMap< String, Value > { +impl< 'a, S: std::hash::BuildHasher + Default > From< &'a mut Object > for HashMap< String, Value, S > { fn from( object: &'a mut Object ) -> Self { deserialize_object( &object.0, |iter| iter.collect() ) } @@ -112,16 +117,16 @@ impl< 'a, K, V > From< &'a mut BTreeMap< K, V > > for Object where K: AsRef< str } } -impl< K, V > From< HashMap< K, V > > for Object where K: AsRef< str > + Hash + Eq, V: JsSerialize { +impl< K, V, S: std::hash::BuildHasher > From< HashMap< K, V, S > > for Object where K: AsRef< str > + Hash + Eq, V: JsSerialize { #[inline] - fn from( value: HashMap< K, V > ) -> Self { + fn from( value: HashMap< K, V, S > ) -> Self { (&value).into() } } -impl< 'a, K, V > From< &'a HashMap< K, V > > for Object where K: AsRef< str > + Hash + Eq, V: JsSerialize { +impl< 'a, K, V, S: std::hash::BuildHasher > From< &'a HashMap< K, V, S > > for Object where K: AsRef< str > + Hash + Eq, V: JsSerialize { #[inline] - fn from( value: &'a HashMap< K, V > ) -> Self { + fn from( value: &'a HashMap< K, V, S > ) -> Self { // TODO: Do something more efficient here? let value = js! { return @{value}; @@ -134,10 +139,10 @@ impl< 'a, K, V > From< &'a HashMap< K, V > > for Object where K: AsRef< str > + } } -impl< 'a, K: Hash + Eq, V > From< &'a mut HashMap< K, V > > for Object where K: AsRef< str >, V: JsSerialize { +impl< 'a, K: Hash + Eq, V, S: std::hash::BuildHasher > From< &'a mut HashMap< K, V, S > > for Object where K: AsRef< str >, V: JsSerialize { #[inline] - fn from( value: &'a mut HashMap< K, V > ) -> Self { - let value: &HashMap< K, V > = value; + fn from( value: &'a mut HashMap< K, V, S > ) -> Self { + let value: &HashMap< K, V, S > = value; value.into() } } @@ -157,12 +162,12 @@ impl< E: Into< ConversionError >, V: TryFrom< Value, Error = E > > TryFrom< Obje } } -impl< E: Into< ConversionError >, V: TryFrom< Value, Error = E > > TryFrom< Object > for HashMap< String, V > { +impl< E: Into< ConversionError >, V: TryFrom< Value, Error = E >, S: std::hash::BuildHasher + Default > TryFrom< Object > for HashMap< String, V, S > { type Error = ConversionError; fn try_from( object: Object ) -> Result< Self, Self::Error > { - deserialize_object( object.as_ref(), |deserializer| -> Result< HashMap< String, V >, E > { - let mut output = HashMap::with_capacity( deserializer.len() ); + deserialize_object( object.as_ref(), |deserializer| -> Result< HashMap< String, V, S >, E > { + let mut output = HashMap::with_capacity_and_hasher( deserializer.len(), Default::default() ); for (key, value) in deserializer { output.insert( key, value.try_into()? ); } diff --git a/src/webcore/promise.rs b/src/webcore/promise.rs index 5e280d4d..4c20dd21 100644 --- a/src/webcore/promise.rs +++ b/src/webcore/promise.rs @@ -293,11 +293,7 @@ impl Promise { PromiseFuture { future: receiver, _done_handle: self.done( |value| { - // TODO is this correct ? - match sender.send( value ) { - Ok( _ ) => {}, - Err( _ ) => {}, - }; + let _ = sender.send( value ); } ), } } @@ -311,6 +307,7 @@ impl< T, E > TypedPromise< T, E > where T: TryFrom< Value >, E: TryFrom< Value > { + #[allow(dead_code)] #[inline] pub(crate) fn new( promise: Promise ) -> Self { TypedPromise( promise, PhantomData ) diff --git a/src/webcore/promise_future.rs b/src/webcore/promise_future.rs index d562eec9..70f6638b 100644 --- a/src/webcore/promise_future.rs +++ b/src/webcore/promise_future.rs @@ -30,11 +30,9 @@ use super::promise::{Promise, DoneHandle}; /// ```rust /// use stdweb::spawn_local; /// -/// fn main() { -/// spawn_local( -/// create_some_future() -/// ); -/// } +/// spawn_local( +/// create_some_future() +/// ); /// ``` /// /// If you want to retrieve the return value of the Future, you can use the various asynchronous @@ -46,14 +44,12 @@ use super::promise::{Promise, DoneHandle}; /// use stdweb::spawn_local; /// use futures::future::FutureExt; /// -/// fn main() { -/// spawn_local( -/// create_some_future() -/// .map(|x| { -/// println!("Future finished with value: {:#?}", x); -/// }) -/// ); -/// } +/// spawn_local( +/// create_some_future() +/// .map(|x| { +/// println!("Future finished with value: {:#?}", x); +/// }) +/// ); /// ``` /// /// 2. However, some Futures return `Result`, and in that case you will need to deal with the `Result` somehow. @@ -70,15 +66,13 @@ use super::promise::{Promise, DoneHandle}; /// use stdweb::spawn_local; /// use futures::future::TryFutureExt; /// -/// fn main() { -/// spawn_local( -/// create_some_future() -/// .map_ok(|x| { -/// println!("Future finished with value: {:#?}", x); -/// }) -/// .unwrap_or_else(|e| handle_error_somehow(e)) -/// ); -/// } +/// spawn_local( +/// create_some_future() +/// .map_ok(|x| { +/// println!("Future finished with value: {:#?}", x); +/// }) +/// .unwrap_or_else(|e| handle_error_somehow(e)) +/// ); /// ``` /// /// It is very common to want to print the errors to the console, and so as a convenience you can use the [`unwrap_future`](fn.unwrap_future.html) function: @@ -87,14 +81,12 @@ use super::promise::{Promise, DoneHandle}; /// use stdweb::{spawn_local, unwrap_future}; /// use futures::future::TryFutureExt; /// -/// fn main() { -/// spawn_local( -/// unwrap_future(create_some_future() -/// .map_ok(|x| { -/// println!("Future finished with value: {:#?}", x); -/// })) -/// ); -/// } +/// spawn_local( +/// unwrap_future(create_some_future() +/// .map_ok(|x| { +/// println!("Future finished with value: {:#?}", x); +/// })) +/// ); /// ``` /// /// If you don't need the return value from the Future, then it is even easier, since you don't need @@ -103,11 +95,9 @@ use super::promise::{Promise, DoneHandle}; /// ```rust /// use stdweb::{spawn_local, unwrap_future}; /// -/// fn main() { -/// spawn_local( -/// unwrap_future(create_some_future()) -/// ); -/// } +/// spawn_local( +/// unwrap_future(create_some_future()) +/// ); /// ``` #[inline] pub fn spawn_local< F >( future: F ) where F: Future< Output = () > + 'static { diff --git a/src/webcore/reference_type.rs b/src/webcore/reference_type.rs index f5c3a113..80803364 100644 --- a/src/webcore/reference_type.rs +++ b/src/webcore/reference_type.rs @@ -6,5 +6,7 @@ use webcore::try_from::TryFrom; pub trait ReferenceType: AsRef< Reference > + InstanceOf + TryFrom< Value > + TryFrom< Reference > { /// Converts a given reference into a concrete reference-like wrapper. /// Doesn't do any type checking; highly unsafe to use! + /// # Safety + /// This function is only safe so long as the given reference is an instance of the JS type the implementor claims to wrap. unsafe fn from_reference_unchecked( reference: Reference ) -> Self; } diff --git a/src/webcore/serialization.rs b/src/webcore/serialization.rs index 4f97d058..5fb46432 100644 --- a/src/webcore/serialization.rs +++ b/src/webcore/serialization.rs @@ -58,7 +58,7 @@ impl Default for Tag { #[doc(hidden)] pub trait JsSerializeOwned: Sized { - fn into_js_owned< 'a >( value: &'a mut Option< Self > ) -> SerializedValue< 'a >; + fn into_js_owned( value: &mut Option< Self > ) -> SerializedValue; } /// A trait for types which can be serialized through the `js!` macro. @@ -67,7 +67,7 @@ pub trait JsSerializeOwned: Sized { /// to be used inside generic code for specifying trait bounds. pub trait JsSerialize { #[doc(hidden)] - fn _into_js< 'a >( &'a self ) -> SerializedValue< 'a >; + fn _into_js( & self ) -> SerializedValue; } // This is a generic structure for serializing every JavaScript value. @@ -411,12 +411,16 @@ macro_rules! untagged_boilerplate { impl< 'a > From< $untagged_type > for SerializedValue< 'a > { #[inline] fn from( untagged: $untagged_type ) -> Self { + let mut value = SerializedValue { + data_1: 0, + data_2: 0, + tag: $tag, + phantom: PhantomData, + }; unsafe { - let mut value: SerializedValue = mem::uninitialized(); - *(&mut value as *mut SerializedValue as *mut $untagged_type) = untagged; - value.tag = $tag; - value + *(&mut value as *mut _ as *mut $untagged_type) = untagged; } + return value; } } @@ -477,7 +481,7 @@ impl< 'a > SerializedValue< 'a > { impl JsSerialize for () { #[doc(hidden)] #[inline] - fn _into_js< 'a >( &'a self ) -> SerializedValue< 'a > { + fn _into_js( & self ) -> SerializedValue { SerializedUntaggedUndefined.into() } } @@ -487,7 +491,7 @@ __js_serializable_boilerplate!( () ); impl JsSerialize for Undefined { #[doc(hidden)] #[inline] - fn _into_js< 'a >( &'a self ) -> SerializedValue< 'a > { + fn _into_js( & self ) -> SerializedValue { SerializedUntaggedUndefined.into() } } @@ -497,7 +501,7 @@ __js_serializable_boilerplate!( Undefined ); impl JsSerialize for Null { #[doc(hidden)] #[inline] - fn _into_js< 'a >( &'a self ) -> SerializedValue< 'a > { + fn _into_js( & self ) -> SerializedValue { SerializedUntaggedNull.into() } } @@ -507,7 +511,7 @@ __js_serializable_boilerplate!( Null ); impl JsSerialize for Symbol { #[doc(hidden)] #[inline] - fn _into_js< 'a >( &'a self ) -> SerializedValue< 'a > { + fn _into_js( & self ) -> SerializedValue { SerializedUntaggedSymbol { id: self.0 }.into() @@ -519,7 +523,7 @@ __js_serializable_boilerplate!( Symbol ); impl JsSerialize for Reference { #[doc(hidden)] #[inline] - fn _into_js< 'a >( &'a self ) -> SerializedValue< 'a > { + fn _into_js( & self ) -> SerializedValue { SerializedUntaggedReference { refid: self.as_raw() }.into() @@ -531,7 +535,7 @@ __js_serializable_boilerplate!( Reference ); impl JsSerialize for bool { #[doc(hidden)] #[inline] - fn _into_js< 'a >( &'a self ) -> SerializedValue< 'a > { + fn _into_js( & self ) -> SerializedValue { if *self { SerializedUntaggedTrue {}.into() } else { @@ -545,7 +549,7 @@ __js_serializable_boilerplate!( bool ); impl JsSerialize for str { #[doc(hidden)] #[inline] - fn _into_js< 'a >( &'a self ) -> SerializedValue< 'a > { + fn _into_js( & self ) -> SerializedValue { SerializedUntaggedString { pointer: self.as_ptr() as u32, length: self.len() as u32 @@ -558,7 +562,7 @@ __js_serializable_boilerplate!( impl< 'a > for &'a str ); impl JsSerialize for String { #[doc(hidden)] #[inline] - fn _into_js< 'a >( &'a self ) -> SerializedValue< 'a > { + fn _into_js( & self ) -> SerializedValue { self.as_str()._into_js() } } @@ -568,7 +572,7 @@ __js_serializable_boilerplate!( String ); impl JsSerialize for i8 { #[doc(hidden)] #[inline] - fn _into_js< 'a >( &'a self ) -> SerializedValue< 'a > { + fn _into_js( & self ) -> SerializedValue { SerializedUntaggedI32 { value: *self as i32 }.into() @@ -580,7 +584,7 @@ __js_serializable_boilerplate!( i8 ); impl JsSerialize for i16 { #[doc(hidden)] #[inline] - fn _into_js< 'a >( &'a self ) -> SerializedValue< 'a > { + fn _into_js( & self ) -> SerializedValue { SerializedUntaggedI32 { value: *self as i32 }.into() @@ -592,7 +596,7 @@ __js_serializable_boilerplate!( i16 ); impl JsSerialize for i32 { #[doc(hidden)] #[inline] - fn _into_js< 'a >( &'a self ) -> SerializedValue< 'a > { + fn _into_js( & self ) -> SerializedValue { SerializedUntaggedI32 { value: *self }.into() @@ -604,7 +608,7 @@ __js_serializable_boilerplate!( i32 ); impl JsSerialize for u8 { #[doc(hidden)] #[inline] - fn _into_js< 'a >( &'a self ) -> SerializedValue< 'a > { + fn _into_js( & self ) -> SerializedValue { SerializedUntaggedI32 { value: *self as i32 }.into() @@ -616,7 +620,7 @@ __js_serializable_boilerplate!( u8 ); impl JsSerialize for u16 { #[doc(hidden)] #[inline] - fn _into_js< 'a >( &'a self ) -> SerializedValue< 'a > { + fn _into_js( & self ) -> SerializedValue { SerializedUntaggedI32 { value: *self as i32 }.into() @@ -628,7 +632,7 @@ __js_serializable_boilerplate!( u16 ); impl JsSerialize for u32 { #[doc(hidden)] #[inline] - fn _into_js< 'a >( &'a self ) -> SerializedValue< 'a > { + fn _into_js( & self ) -> SerializedValue { SerializedUntaggedF64 { value: *self as f64 }.into() @@ -640,7 +644,7 @@ __js_serializable_boilerplate!( u32 ); impl JsSerialize for f32 { #[doc(hidden)] #[inline] - fn _into_js< 'a >( &'a self ) -> SerializedValue< 'a > { + fn _into_js( & self ) -> SerializedValue { SerializedUntaggedF64 { value: *self as f64 }.into() @@ -652,7 +656,7 @@ __js_serializable_boilerplate!( f32 ); impl JsSerialize for f64 { #[doc(hidden)] #[inline] - fn _into_js< 'a >( &'a self ) -> SerializedValue< 'a > { + fn _into_js( & self ) -> SerializedValue { SerializedUntaggedF64 { value: *self }.into() @@ -664,7 +668,7 @@ __js_serializable_boilerplate!( f64 ); impl JsSerialize for Number { #[doc(hidden)] #[inline] - fn _into_js< 'a >( &'a self ) -> SerializedValue< 'a > { + fn _into_js( & self ) -> SerializedValue { use webcore::number::{Storage, get_storage}; match *get_storage( self ) { Storage::I32( ref value ) => value._into_js(), @@ -678,7 +682,7 @@ __js_serializable_boilerplate!( Number ); impl< T: JsSerialize > JsSerialize for Option< T > { #[doc(hidden)] #[inline] - fn _into_js< 'a >( &'a self ) -> SerializedValue< 'a > { + fn _into_js( & self ) -> SerializedValue { if let Some( value ) = self.as_ref() { value._into_js() } else { @@ -692,7 +696,7 @@ __js_serializable_boilerplate!( impl< T > for Option< T > where T: JsSerialize ) impl< T: JsSerialize > JsSerialize for OptionalArg< T > { #[doc(hidden)] #[inline] - fn _into_js< 'a >( &'a self ) -> SerializedValue< 'a > { + fn _into_js( & self ) -> SerializedValue { if let OptionalArg::Some( value ) = self.as_ref() { value._into_js() } else { @@ -706,7 +710,7 @@ __js_serializable_boilerplate!( impl< T > for OptionalArg< T > where T: JsSerial impl< T: JsSerialize > JsSerialize for [T] { #[doc(hidden)] #[inline] - fn _into_js< 'a >( &'a self ) -> SerializedValue< 'a > { + fn _into_js( & self ) -> SerializedValue { let mut output = global_arena::reserve( self.len() ); for value in self { unsafe { @@ -726,7 +730,7 @@ __js_serializable_boilerplate!( impl< 'a, T > for &'a [T] where T: JsSerialize ) impl< T: JsSerialize > JsSerialize for Vec< T > { #[doc(hidden)] #[inline] - fn _into_js< 'a >( &'a self ) -> SerializedValue< 'a > { + fn _into_js( & self ) -> SerializedValue { self.as_slice()._into_js() } } @@ -753,26 +757,26 @@ fn object_into_js< 'a, K: AsRef< str >, V: 'a + JsSerialize, I: Iterator< Item = impl< K: AsRef< str >, V: JsSerialize > JsSerialize for BTreeMap< K, V > { #[doc(hidden)] #[inline] - fn _into_js< 'a >( &'a self ) -> SerializedValue< 'a > { + fn _into_js( & self ) -> SerializedValue { object_into_js( self.iter() ) } } __js_serializable_boilerplate!( impl< K, V > for BTreeMap< K, V > where K: AsRef< str >, V: JsSerialize ); -impl< K: AsRef< str > + Eq + Hash, V: JsSerialize > JsSerialize for HashMap< K, V > { +impl< K: AsRef< str > + Eq + Hash, V: JsSerialize, S: std::hash::BuildHasher > JsSerialize for HashMap< K, V, S > { #[doc(hidden)] #[inline] - fn _into_js< 'a >( &'a self ) -> SerializedValue< 'a > { + fn _into_js( &self ) -> SerializedValue { object_into_js( self.iter() ) } } -__js_serializable_boilerplate!( impl< K, V > for HashMap< K, V > where K: AsRef< str > + Eq + Hash, V: JsSerialize ); +__js_serializable_boilerplate!( impl< K, V, S > for HashMap< K, V, S > where K: AsRef< str > + Eq + Hash, V: JsSerialize, S: std::hash::BuildHasher ); impl JsSerialize for Value { #[doc(hidden)] - fn _into_js< 'a >( &'a self ) -> SerializedValue< 'a > { + fn _into_js( &self ) -> SerializedValue { match *self { Value::Undefined => SerializedUntaggedUndefined.into(), Value::Null => SerializedUntaggedNull.into(), @@ -792,7 +796,7 @@ macro_rules! impl_for_unsafe_typed_array { impl< 'r > JsSerialize for UnsafeTypedArray< 'r, $ty > { #[doc(hidden)] #[inline] - fn _into_js< 'a >( &'a self ) -> SerializedValue< 'a > { + fn _into_js( &self ) -> SerializedValue { SerializedUntaggedUnsafeTypedArray { pointer: self.0.as_ptr() as u32 / mem::size_of::< $ty >() as u32, length: self.0.len() as u32, @@ -822,7 +826,7 @@ pub struct NonFunctionTag; impl< T: JsSerialize > JsSerializeOwned for Newtype< (NonFunctionTag, ()), T > { #[inline] - fn into_js_owned< 'x >( value: &'x mut Option< Self > ) -> SerializedValue< 'x > { + fn into_js_owned( value: &mut Option< Self > ) -> SerializedValue { JsSerialize::_into_js( value.as_ref().unwrap().as_ref() ) } } @@ -864,6 +868,7 @@ macro_rules! impl_for_fn_and_modifier { let mut arguments = arguments.drain( .. ); let mut nth_argument = 0; $( + #[allow(clippy::match_wild_err_arm)] let $kind = match arguments.next().unwrap().try_into() { Ok( value ) => value, Err( _ ) => { @@ -903,7 +908,7 @@ macro_rules! impl_for_fn_and_modifier { where F: $trait< ($($kind,)*) > + 'static, F::Output: JsSerializeOwned { #[inline] - fn into_js_owned< 'a >( value: &'a mut Option< Self > ) -> SerializedValue< 'a > { + fn into_js_owned( value: &mut Option< Self > ) -> SerializedValue { let $wrapped = value.take().unwrap().unwrap_newtype(); let callback: *mut F = Box::into_raw( Box::new( $unwrap ) ); let adapter_pointer = >::funcall_adapter; @@ -920,7 +925,7 @@ macro_rules! impl_for_fn_and_modifier { where F: $trait< ($($kind,)*) > + 'static, F::Output: JsSerializeOwned { #[inline] - fn into_js_owned< 'a >( value: &'a mut Option< Self > ) -> SerializedValue< 'a > { + fn into_js_owned( value: &mut Option< Self > ) -> SerializedValue { if let Some( $wrapped ) = value.take().unwrap().unwrap_newtype() { let callback: *mut F = Box::into_raw( Box::new( $unwrap ) ); let adapter_pointer = as FuncallAdapter< F > >::funcall_adapter; @@ -976,14 +981,14 @@ loop_through_identifiers!( impl_for_fn ); impl< 'a, T: ?Sized + JsSerialize > JsSerialize for &'a T { #[doc(hidden)] #[inline] - fn _into_js< 'x >( &'x self ) -> SerializedValue< 'x > { + fn _into_js( &self ) -> SerializedValue { T::_into_js( *self ) } } impl JsSerialize for ConversionError { #[doc(hidden)] - fn _into_js< 'x >( &'x self ) -> SerializedValue< 'x > { + fn _into_js( &self ) -> SerializedValue { let type_error: TypeError = self.into(); let reference: Reference = type_error.into(); let value: Value = reference.into(); diff --git a/src/webcore/type_name.rs b/src/webcore/type_name.rs index 107061c0..02d143b0 100644 --- a/src/webcore/type_name.rs +++ b/src/webcore/type_name.rs @@ -1,9 +1,7 @@ #[cfg(rust_nightly)] pub fn type_name_opt< T >() -> Option< &'static str > { use std::intrinsics; - let name = unsafe { - intrinsics::type_name::< T >() - }; + let name = intrinsics::type_name::< T >(); Some( name ) } diff --git a/src/webcore/unsafe_typed_array.rs b/src/webcore/unsafe_typed_array.rs index 0d3bf986..ee6e352f 100644 --- a/src/webcore/unsafe_typed_array.rs +++ b/src/webcore/unsafe_typed_array.rs @@ -5,6 +5,8 @@ use std::fmt; /// /// The only thing you can do with this is to pass it to the `js!` macro. /// +/// # Safety +/// /// Using this is **highly unsafe**! After you pass it to the `js!` macro /// you **must** use it **before** triggering any Rust code whatsoever, /// either directly or indirectly. Breaking this rule will result @@ -37,6 +39,10 @@ impl< 'a, T > UnsafeTypedArray< 'a, T > { /// Even though this function is marked as `unsafe` /// the unsafely only comes into play after you /// pass it to the `js!` macro. + /// + /// # Safety + /// + /// See safety section of type documentation #[inline] pub unsafe fn new( slice: &'a [T] ) -> Self { UnsafeTypedArray( slice ) diff --git a/src/webcore/value.rs b/src/webcore/value.rs index 70da8b75..495b0179 100644 --- a/src/webcore/value.rs +++ b/src/webcore/value.rs @@ -2,7 +2,6 @@ use std::collections::{BTreeMap, HashMap}; use std::hash::Hash; use std::fmt; use std::error; -use std::mem; use std::borrow::Cow; use webcore::void::Void; use webcore::try_from::{TryFrom, TryInto}; @@ -66,10 +65,13 @@ impl PartialEq for Reference { fn eq( &self, other: &Reference ) -> bool { let result = self.0 == other.0; - debug_assert_eq!( { - let real_result: bool = js!( return @{self} === @{other}; ).try_into().unwrap(); - real_result - }, result ); + if cfg!(debug_assertions) + { + assert_eq!( { + let real_result: bool = js!( return @{self} === @{other}; ).try_into().unwrap(); + real_result + }, result ); + } result } @@ -234,7 +236,7 @@ impl Value { match *self { Value::Reference( ref reference ) if Object::instance_of( reference ) => { unsafe { - Some( mem::transmute( reference ) ) + Some( &*(reference as *const Reference as *const Object) ) } }, _ => None @@ -247,7 +249,7 @@ impl Value { match *self { Value::Reference( ref reference ) if Array::instance_of( reference ) => { unsafe { - Some( mem::transmute( reference ) ) + Some( &*(reference as *const Reference as *const Array) ) } }, _ => None @@ -285,6 +287,10 @@ impl Value { /// the given type `T`; doesn't check whenever the reference is really of type `T`. /// /// In cases where the value is not a `Reference` a `None` is returned. + /// + /// # Safety + /// + /// If the reference is not really of type `T`, behavior is undefined. #[inline] pub unsafe fn into_reference_unchecked< T: ReferenceType >( self ) -> Option< T > { let reference: Option< Reference > = self.try_into().ok(); @@ -1008,7 +1014,7 @@ impl< E: Into< ConversionError >, V: TryFrom< Value, Error = E > > TryFrom< Valu } } -impl< E: Into< ConversionError >, V: TryFrom< Value, Error = E > > TryFrom< Value > for HashMap< String, V > { +impl< E: Into< ConversionError >, V: TryFrom< Value, Error = E >, S: ::std::hash::BuildHasher + Default > TryFrom< Value > for HashMap< String, V, S > { type Error = ConversionError; #[inline]