diff --git a/components/servo/Cargo.lock b/components/servo/Cargo.lock index 0837ad5dd30..2b6ccfc0e7b 100644 --- a/components/servo/Cargo.lock +++ b/components/servo/Cargo.lock @@ -1727,7 +1727,7 @@ dependencies = [ [[package]] name = "owning_ref" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1735,7 +1735,7 @@ name = "parking_lot" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "owning_ref 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "owning_ref 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot_core 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2320,6 +2320,7 @@ dependencies = [ "num-traits 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", "ordered-float 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "owning_ref 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "plugins 0.0.1", "quickersort 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2344,6 +2345,7 @@ dependencies = [ "app_units 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "cssparser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", + "owning_ref 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", "selectors 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2960,7 +2962,7 @@ dependencies = [ "checksum osmesa-src 12.0.1 (git+https://github.com/servo/osmesa-src)" = "" "checksum osmesa-sys 0.1.2 (git+https://github.com/daggerbot/osmesa-rs)" = "" "checksum osmesa-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "88cfece6e95d2e717e0872a7f53a8684712ad13822a7979bc760b9c77ec0013b" -"checksum owning_ref 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88084505837507cbec6a9f39b5d3b985db3c84e9a741c80200b619001283293d" +"checksum owning_ref 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8d91377085359426407a287ab16884a0111ba473aa6844ff01d4ec20ce3d75e7" "checksum parking_lot 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3562f3de7bdff194212be82366abf5c6565aff8a433b71c53c63d0e7c9913878" "checksum parking_lot_core 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "06f24c980718110494e9cfb7db7438895c3f54505101bb6170329d5e43a53f64" "checksum phf 0.7.17 (registry+https://github.com/rust-lang/crates.io-index)" = "f02853ab706e88121d7ad33ed06bedce0a7cdb96136be7c20ff0dce7b4adb9ef" diff --git a/components/style/Cargo.toml b/components/style/Cargo.toml index 7a5a282620e..77eff5926ac 100644 --- a/components/style/Cargo.toml +++ b/components/style/Cargo.toml @@ -41,6 +41,7 @@ num-integer = "0.1.32" num-traits = "0.1.32" num_cpus = "0.2.2" ordered-float = "0.2.2" +owning_ref = "0.2.2" parking_lot = "0.3.3" quickersort = "2.0.0" rand = "0.3" diff --git a/components/style/lib.rs b/components/style/lib.rs index 893b88c8dff..1d9ac21be93 100644 --- a/components/style/lib.rs +++ b/components/style/lib.rs @@ -73,6 +73,7 @@ extern crate num_integer; extern crate num_traits; #[cfg(feature = "gecko")] extern crate num_cpus; extern crate ordered_float; +extern crate owning_ref; extern crate parking_lot; extern crate quickersort; extern crate rand; @@ -112,6 +113,7 @@ pub mod keyframes; pub mod logical_geometry; pub mod matching; pub mod media_queries; +pub mod owning_handle; pub mod parallel; pub mod parser; pub mod refcell; diff --git a/components/style/owning_handle.rs b/components/style/owning_handle.rs new file mode 100644 index 00000000000..f4daf750cb0 --- /dev/null +++ b/components/style/owning_handle.rs @@ -0,0 +1,81 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#![allow(unsafe_code)] + +use owning_ref::StableAddress; +use std::ops::{Deref, DerefMut}; + +/// `OwningHandle` is a complement to `OwningRef`. Where `OwningRef` allows +/// consumers to pass around an owned object and a dependent reference, +/// `OwningHandle` contains an owned object and a dependent _object_. +/// +/// `OwningHandle` can encapsulate a `RefMut` along with its associated +/// `RefCell`, or an `RwLockReadGuard` along with its associated `RwLock`. +/// However, the API is completely generic and there are no restrictions on +/// what types of owning and dependent objects may be used. +/// +/// `OwningHandle` is created by passing an owner object (which dereferences +/// to a stable address) along with a callback which receives a pointer to +/// that stable location. The callback may then dereference the pointer and +/// mint a dependent object, with the guarantee that the returned object will +/// not outlive the referent of the pointer. +/// +/// This does foist some unsafety onto the callback, which needs an `unsafe` +/// block to dereference the pointer. It would be almost good enough for +/// OwningHandle to pass a transmuted &'statc reference to the callback +/// since the lifetime is infinite as far as the minted handle is concerned. +/// However, even an `Fn` callback can still allow the reference to escape +/// via a `StaticMutex` or similar, which technically violates the safety +/// contract. Some sort of language support in the lifetime system could +/// make this API a bit nicer. +pub struct OwningHandle + where O: StableAddress, H: Deref, +{ + handle: H, + _owner: O, +} + +impl Deref for OwningHandle + where O: StableAddress, H: Deref, +{ + type Target = H::Target; + fn deref(&self) -> &H::Target { + self.handle.deref() + } +} + +unsafe impl StableAddress for OwningHandle + where O: StableAddress, H: StableAddress, +{} + +impl DerefMut for OwningHandle + where O: StableAddress, H: DerefMut, +{ + fn deref_mut(&mut self) -> &mut H::Target { + self.handle.deref_mut() + } +} + +impl OwningHandle + where O: StableAddress, H: Deref, +{ + /// Create a new OwningHandle. The provided callback will be invoked with + /// a pointer to the object owned by `o`, and the returned value is stored + /// as the object to which this `OwningHandle` will forward `Deref` and + /// `DerefMut`. + pub fn new(o: O, f: F) -> Self + where F: Fn(*const O::Target) -> H + { + let h: H; + { + h = f(o.deref() as *const O::Target); + } + + OwningHandle { + handle: h, + _owner: o, + } + } +} diff --git a/ports/cef/Cargo.lock b/ports/cef/Cargo.lock index 004c5c2f7b3..ce9c6084174 100644 --- a/ports/cef/Cargo.lock +++ b/ports/cef/Cargo.lock @@ -1598,7 +1598,7 @@ dependencies = [ [[package]] name = "owning_ref" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1606,7 +1606,7 @@ name = "parking_lot" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "owning_ref 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "owning_ref 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot_core 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2203,6 +2203,7 @@ dependencies = [ "num-traits 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", "ordered-float 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "owning_ref 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "plugins 0.0.1", "quickersort 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2813,7 +2814,7 @@ dependencies = [ "checksum osmesa-src 12.0.1 (git+https://github.com/servo/osmesa-src)" = "" "checksum osmesa-sys 0.1.2 (git+https://github.com/daggerbot/osmesa-rs)" = "" "checksum osmesa-sys 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "88cfece6e95d2e717e0872a7f53a8684712ad13822a7979bc760b9c77ec0013b" -"checksum owning_ref 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88084505837507cbec6a9f39b5d3b985db3c84e9a741c80200b619001283293d" +"checksum owning_ref 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8d91377085359426407a287ab16884a0111ba473aa6844ff01d4ec20ce3d75e7" "checksum parking_lot 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3562f3de7bdff194212be82366abf5c6565aff8a433b71c53c63d0e7c9913878" "checksum parking_lot_core 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "06f24c980718110494e9cfb7db7438895c3f54505101bb6170329d5e43a53f64" "checksum phf 0.7.17 (registry+https://github.com/rust-lang/crates.io-index)" = "f02853ab706e88121d7ad33ed06bedce0a7cdb96136be7c20ff0dce7b4adb9ef" diff --git a/ports/geckolib/Cargo.lock b/ports/geckolib/Cargo.lock index 30abc1fd3fd..3274ab5ea90 100644 --- a/ports/geckolib/Cargo.lock +++ b/ports/geckolib/Cargo.lock @@ -251,7 +251,7 @@ dependencies = [ [[package]] name = "owning_ref" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -259,7 +259,7 @@ name = "parking_lot" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "owning_ref 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "owning_ref 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot_core 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -385,6 +385,7 @@ dependencies = [ "num-traits 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", "ordered-float 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "owning_ref 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "quickersort 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", @@ -567,7 +568,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum num-traits 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "8359ea48994f253fa958b5b90b013728b06f54872e5a58bce39540fcdd0f2527" "checksum num_cpus 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "cee7e88156f3f9e19bdd598f8d6c9db7bf4078f99f8381f43a55b09648d1a6e3" "checksum ordered-float 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cc511538298611a79d5a4ddfbb75315b866d942ed26a00bdc3590795c68b7279" -"checksum owning_ref 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88084505837507cbec6a9f39b5d3b985db3c84e9a741c80200b619001283293d" +"checksum owning_ref 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8d91377085359426407a287ab16884a0111ba473aa6844ff01d4ec20ce3d75e7" "checksum parking_lot 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3562f3de7bdff194212be82366abf5c6565aff8a433b71c53c63d0e7c9913878" "checksum parking_lot_core 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "06f24c980718110494e9cfb7db7438895c3f54505101bb6170329d5e43a53f64" "checksum phf_generator 0.7.16 (registry+https://github.com/rust-lang/crates.io-index)" = "04b5ea825e28cb6efd89d9133b129b2003b45a221aeda025509b125b00ecb7c4" diff --git a/tests/unit/style/Cargo.toml b/tests/unit/style/Cargo.toml index 4dd3dd0e574..fbd9edc3bb3 100644 --- a/tests/unit/style/Cargo.toml +++ b/tests/unit/style/Cargo.toml @@ -13,6 +13,7 @@ doctest = false app_units = "0.3" cssparser = {version = "0.7", features = ["heap_size"]} euclid = "0.10.1" +owning_ref = "0.2.2" parking_lot = "0.3" rustc-serialize = "0.3" selectors = "0.13" diff --git a/tests/unit/style/lib.rs b/tests/unit/style/lib.rs index ebbd6afa05a..164ccadef10 100644 --- a/tests/unit/style/lib.rs +++ b/tests/unit/style/lib.rs @@ -9,6 +9,7 @@ extern crate app_units; extern crate cssparser; extern crate euclid; +extern crate owning_ref; extern crate parking_lot; extern crate rustc_serialize; extern crate selectors; @@ -22,6 +23,7 @@ mod attr; mod cache; mod logical_geometry; mod media_queries; +mod owning_handle; mod parsing; mod properties; mod selector_matching; diff --git a/tests/unit/style/owning_handle.rs b/tests/unit/style/owning_handle.rs new file mode 100644 index 00000000000..cf792ef9605 --- /dev/null +++ b/tests/unit/style/owning_handle.rs @@ -0,0 +1,34 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use owning_ref::RcRef; +use std::cell::RefCell; +use std::rc::Rc; +use std::sync::{Arc, RwLock}; +use style::owning_handle::OwningHandle; + +#[test] +fn owning_handle() { + use std::cell::RefCell; + let cell = Rc::new(RefCell::new(2)); + let cell_ref = RcRef::new(cell); + let mut handle = OwningHandle::new(cell_ref, |x| unsafe { x.as_ref() }.unwrap().borrow_mut()); + assert_eq!(*handle, 2); + *handle = 3; + assert_eq!(*handle, 3); +} + +#[test] +fn nested() { + let result = { + let complex = Rc::new(RefCell::new(Arc::new(RwLock::new("someString")))); + let curr = RcRef::new(complex); + let curr = OwningHandle::new(curr, |x| unsafe { x.as_ref() }.unwrap().borrow_mut()); + let mut curr = OwningHandle::new(curr, |x| unsafe { x.as_ref() }.unwrap().try_write().unwrap()); + assert_eq!(*curr, "someString"); + *curr = "someOtherString"; + curr + }; + assert_eq!(*result, "someOtherString"); +}