From 6c518c89b969d1e9a96c3c5b9fe0da6cfc3637d1 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Tue, 2 May 2017 11:10:49 +0200 Subject: [PATCH 01/12] Upgrade to html5ever 0.16 --- Cargo.lock | 61 +++--- components/layout/Cargo.toml | 2 +- components/layout/lib.rs | 2 +- components/script/Cargo.toml | 5 +- components/script/dom/attr.rs | 2 +- components/script/dom/bindings/str.rs | 2 +- components/script/dom/bindings/trace.rs | 4 +- components/script/dom/bindings/xmlname.rs | 2 +- components/script/dom/create.rs | 5 +- components/script/dom/document.rs | 19 +- components/script/dom/domtokenlist.rs | 2 +- components/script/dom/element.rs | 10 +- components/script/dom/formdata.rs | 2 +- components/script/dom/htmlanchorelement.rs | 2 +- components/script/dom/htmlappletelement.rs | 2 +- components/script/dom/htmlareaelement.rs | 2 +- components/script/dom/htmlaudioelement.rs | 2 +- components/script/dom/htmlbaseelement.rs | 2 +- components/script/dom/htmlbodyelement.rs | 2 +- components/script/dom/htmlbrelement.rs | 2 +- components/script/dom/htmlbuttonelement.rs | 2 +- components/script/dom/htmlcanvaselement.rs | 2 +- components/script/dom/htmlcollection.rs | 4 +- components/script/dom/htmldataelement.rs | 2 +- components/script/dom/htmldatalistelement.rs | 2 +- components/script/dom/htmldetailselement.rs | 2 +- components/script/dom/htmldialogelement.rs | 2 +- components/script/dom/htmldirectoryelement.rs | 2 +- components/script/dom/htmldivelement.rs | 2 +- components/script/dom/htmldlistelement.rs | 2 +- components/script/dom/htmlelement.rs | 2 +- components/script/dom/htmlembedelement.rs | 2 +- components/script/dom/htmlfieldsetelement.rs | 2 +- components/script/dom/htmlfontelement.rs | 2 +- components/script/dom/htmlformelement.rs | 2 +- components/script/dom/htmlframeelement.rs | 2 +- components/script/dom/htmlframesetelement.rs | 2 +- components/script/dom/htmlheadelement.rs | 2 +- components/script/dom/htmlheadingelement.rs | 2 +- components/script/dom/htmlhrelement.rs | 2 +- components/script/dom/htmlhtmlelement.rs | 2 +- components/script/dom/htmliframeelement.rs | 2 +- components/script/dom/htmlimageelement.rs | 2 +- components/script/dom/htmlinputelement.rs | 2 +- components/script/dom/htmllabelelement.rs | 2 +- components/script/dom/htmllegendelement.rs | 2 +- components/script/dom/htmllielement.rs | 2 +- components/script/dom/htmllinkelement.rs | 2 +- components/script/dom/htmlmapelement.rs | 2 +- components/script/dom/htmlmediaelement.rs | 2 +- components/script/dom/htmlmetaelement.rs | 2 +- components/script/dom/htmlmeterelement.rs | 2 +- components/script/dom/htmlmodelement.rs | 2 +- components/script/dom/htmlobjectelement.rs | 2 +- components/script/dom/htmlolistelement.rs | 2 +- components/script/dom/htmloptgroupelement.rs | 2 +- components/script/dom/htmloptionelement.rs | 2 +- components/script/dom/htmloutputelement.rs | 2 +- components/script/dom/htmlparagraphelement.rs | 2 +- components/script/dom/htmlparamelement.rs | 2 +- components/script/dom/htmlpreelement.rs | 2 +- components/script/dom/htmlprogresselement.rs | 2 +- components/script/dom/htmlquoteelement.rs | 2 +- components/script/dom/htmlscriptelement.rs | 2 +- components/script/dom/htmlselectelement.rs | 2 +- components/script/dom/htmlsourceelement.rs | 2 +- components/script/dom/htmlspanelement.rs | 2 +- components/script/dom/htmlstyleelement.rs | 2 +- .../script/dom/htmltablecaptionelement.rs | 2 +- components/script/dom/htmltablecellelement.rs | 2 +- components/script/dom/htmltablecolelement.rs | 2 +- .../script/dom/htmltabledatacellelement.rs | 2 +- components/script/dom/htmltableelement.rs | 2 +- .../script/dom/htmltableheadercellelement.rs | 2 +- components/script/dom/htmltablerowelement.rs | 2 +- .../script/dom/htmltablesectionelement.rs | 2 +- components/script/dom/htmltemplateelement.rs | 2 +- components/script/dom/htmltextareaelement.rs | 2 +- components/script/dom/htmltimeelement.rs | 2 +- components/script/dom/htmltitleelement.rs | 2 +- components/script/dom/htmltrackelement.rs | 2 +- components/script/dom/htmlulistelement.rs | 2 +- components/script/dom/htmlunknownelement.rs | 2 +- components/script/dom/htmlvideoelement.rs | 2 +- components/script/dom/namednodemap.rs | 2 +- components/script/dom/node.rs | 4 +- components/script/dom/servoparser/html.rs | 194 ++--------------- components/script/dom/servoparser/mod.rs | 200 +++++++++++++++++- components/script/dom/servoparser/xml.rs | 133 +----------- components/script/dom/svgelement.rs | 2 +- components/script/dom/svggraphicselement.rs | 2 +- components/script/dom/svgsvgelement.rs | 2 +- components/script/dom/virtualmethods.rs | 2 +- components/script/layout_wrapper.rs | 2 +- components/script/lib.rs | 3 +- components/script_layout_interface/Cargo.toml | 2 +- components/script_layout_interface/lib.rs | 2 +- .../script_layout_interface/wrapper_traits.rs | 2 +- components/style/Cargo.toml | 4 +- components/style/lib.rs | 8 +- tests/unit/style/Cargo.toml | 2 +- tests/unit/style/lib.rs | 2 +- tests/unit/style/stylesheets.rs | 2 +- tests/unit/style/stylist.rs | 2 +- 104 files changed, 363 insertions(+), 471 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index de6a44940d0..9e00ee76e97 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1150,33 +1150,17 @@ dependencies = [ [[package]] name = "html5ever" -version = "0.15.0" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "heapsize 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "heapsize_derive 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "html5ever-atoms 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", - "phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", + "markup5ever 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", "tendril 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "html5ever-atoms" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "heapsize 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "heapsize_derive 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache_codegen 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "httparse" version = "1.2.1" @@ -1378,7 +1362,7 @@ dependencies = [ "gfx 0.0.1", "gfx_traits 0.0.1", "heapsize 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "html5ever-atoms 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "html5ever 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", "ipc-channel 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1573,6 +1557,21 @@ dependencies = [ "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "markup5ever" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "heapsize 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "heapsize_derive 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", + "phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache_codegen 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tendril 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "matches" version = "0.1.4" @@ -2279,8 +2278,7 @@ dependencies = [ "gfx_traits 0.0.1", "heapsize 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize_derive 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "html5ever 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", - "html5ever-atoms 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "html5ever 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.10.9 (registry+https://github.com/rust-lang/crates.io-index)", "hyper_serde 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "image 0.12.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2328,7 +2326,7 @@ dependencies = [ "webrender_traits 0.36.0 (git+https://github.com/servo/webrender)", "webvr 0.0.1", "webvr_traits 0.0.1", - "xml5ever 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "xml5ever 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2343,7 +2341,7 @@ dependencies = [ "gfx_traits 0.0.1", "heapsize 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize_derive 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "html5ever-atoms 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "html5ever 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", "ipc-channel 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2768,7 +2766,7 @@ dependencies = [ "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "heapsize_derive 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "html5ever-atoms 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "html5ever 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2803,7 +2801,7 @@ dependencies = [ "app_units 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "cssparser 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", - "html5ever-atoms 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "html5ever 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "rayon 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3327,15 +3325,12 @@ dependencies = [ [[package]] name = "xml5ever" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "html5ever-atoms 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", - "phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", + "markup5ever 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "tendril 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -3439,8 +3434,7 @@ dependencies = [ "checksum heapsize_derive 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "46f96d52fb1564059fc97b85ef6165728cc30198ab60073bf114c66c4c89bb5d" "checksum heartbeats-simple 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9ad003ce233955e9d95f2c69cde84e68302ba9ba4a673d351c9bff93c738aadc" "checksum heartbeats-simple-sys 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e1a408c0011427cc0e0049f7861c70377819aedfc006e8c901b1c70fd98fb1a4" -"checksum html5ever 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "89a83ad398346d1f25b21979dd79ed7b5c345796194665b34321b5551726347e" -"checksum html5ever-atoms 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8e4a291981feff7291514f8219d5cd2c740d0c042d75cff248a7c00a025f9d40" +"checksum html5ever 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)" = "83d2f9d3abeac56d8b4de9fd033473f6183b89ea91e635326b2807b6a14e98b9" "checksum httparse 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a6e7a63e511f9edffbab707141fbb8707d1a3098615fb2adbd5769cdfcc9b17d" "checksum hyper 0.10.9 (registry+https://github.com/rust-lang/crates.io-index)" = "94da93321c171e26481afeebe8288757b0501901b7c5492648163d8ec4942ec5" "checksum hyper-openssl 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "85a372eb692590b3fe014c196c30f9f52d4c42f58cd49dd94caeee1593c9cc37" @@ -3470,6 +3464,7 @@ dependencies = [ "checksum lzw 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7d947cbb889ed21c2a84be6ffbaebf5b4e0f4340638cba0444907e38b56be084" "checksum mac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" "checksum malloc_buf 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" +"checksum markup5ever 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a614f301a2d5583894d1915a8c6bd2c473e80fba69263a60cf2677dbc49936f8" "checksum matches 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "efd7622e3022e1a6eaa602c4cea8912254e5582c9c692e9167714182244801b1" "checksum memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1dbccc0e46f1ea47b9f17e6d67c5a96bd27030519c519c9c91327e31275a47b4" "checksum metadeps 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "829fffe7ea1d747e23f64be972991bc516b2f1ac2ae4a3b33d8bea150c410151" @@ -3606,4 +3601,4 @@ dependencies = [ "checksum xdg 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a66b7c2281ebde13cf4391d70d4c7e5946c3c25e72a7b859ca8f677dcd0b0c61" "checksum xi-unicode 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "12ea8eda4b1eb72f02d148402e23832d56a33f55d8c1b2d5bcdde91d79d47cb1" "checksum xml-rs 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f2b15eed12692bd59d15e98ee7f8dc8408465b992d8ddb4d1672c24865132ec7" -"checksum xml5ever 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a1aae5379a4a7ffb580300bb725696ce238bec993a7bad872ec09ea00ec1c4a5" +"checksum xml5ever 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b5bbbde15cfe438463d4e48dc0c752e427a29766d144e3304594ad0c5813cbf9" diff --git a/components/layout/Cargo.toml b/components/layout/Cargo.toml index cdeb2f09103..dee003a53b4 100644 --- a/components/layout/Cargo.toml +++ b/components/layout/Cargo.toml @@ -20,7 +20,7 @@ fnv = "1.0" gfx = {path = "../gfx"} gfx_traits = {path = "../gfx_traits"} heapsize = "0.3.0" -html5ever-atoms = "0.3" +html5ever = "0.16" ipc-channel = "0.7" libc = "0.2" log = "0.3.5" diff --git a/components/layout/lib.rs b/components/layout/lib.rs index 4c5bd766e24..7788c9a667d 100644 --- a/components/layout/lib.rs +++ b/components/layout/lib.rs @@ -22,7 +22,7 @@ extern crate fnv; extern crate gfx; extern crate gfx_traits; extern crate heapsize; -#[macro_use] extern crate html5ever_atoms; +#[macro_use] extern crate html5ever; extern crate ipc_channel; extern crate libc; #[macro_use] diff --git a/components/script/Cargo.toml b/components/script/Cargo.toml index f145e8f65b0..76facbdc2ec 100644 --- a/components/script/Cargo.toml +++ b/components/script/Cargo.toml @@ -46,8 +46,7 @@ fnv = "1.0" gfx_traits = {path = "../gfx_traits"} heapsize = "0.3.6" heapsize_derive = "0.1" -html5ever = {version = "0.15", features = ["heap_size", "unstable"]} -html5ever-atoms = {version = "0.3", features = ["heap_size"]} +html5ever = {version = "0.16", features = ["heap_size", "unstable"]} hyper = "0.10" hyper_serde = "0.6" image = "0.12" @@ -88,7 +87,7 @@ time = "0.1.12" unicode-segmentation = "1.1.0" url = {version = "1.2", features = ["heap_size", "query_encoding"]} uuid = {version = "0.4", features = ["v4"]} -xml5ever = {version = "0.5", features = ["unstable"]} +xml5ever = {version = "0.6", features = ["unstable"]} webrender_traits = {git = "https://github.com/servo/webrender", features = ["ipc"]} webvr = {path = "../webvr"} webvr_traits = {path = "../webvr_traits"} diff --git a/components/script/dom/attr.rs b/components/script/dom/attr.rs index 55f2adcfdb6..3c775ffdf57 100644 --- a/components/script/dom/attr.rs +++ b/components/script/dom/attr.rs @@ -13,7 +13,7 @@ use dom::element::{AttributeMutation, Element}; use dom::virtualmethods::vtable_for; use dom::window::Window; use dom_struct::dom_struct; -use html5ever_atoms::{Prefix, LocalName, Namespace}; +use html5ever::{Prefix, LocalName, Namespace}; use servo_atoms::Atom; use std::borrow::ToOwned; use std::cell::Ref; diff --git a/components/script/dom/bindings/str.rs b/components/script/dom/bindings/str.rs index e75958d974a..6cb17fae4e3 100644 --- a/components/script/dom/bindings/str.rs +++ b/components/script/dom/bindings/str.rs @@ -4,7 +4,7 @@ //! The `ByteString` struct. -use html5ever_atoms::{LocalName, Namespace}; +use html5ever::{LocalName, Namespace}; use servo_atoms::Atom; use std::ascii::AsciiExt; use std::borrow::{Borrow, Cow, ToOwned}; diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs index 1bc9c165fb1..11cca130e7f 100644 --- a/components/script/dom/bindings/trace.rs +++ b/components/script/dom/bindings/trace.rs @@ -47,8 +47,8 @@ use euclid::{Matrix2D, Matrix4D, Point2D}; use euclid::length::Length as EuclidLength; use euclid::rect::Rect; use euclid::size::Size2D; -use html5ever::tokenizer::buffer_queue::BufferQueue; -use html5ever_atoms::{Prefix, LocalName, Namespace, QualName}; +use html5ever::{Prefix, LocalName, Namespace, QualName}; +use html5ever::buffer_queue::BufferQueue; use hyper::header::Headers; use hyper::method::Method; use hyper::mime::Mime; diff --git a/components/script/dom/bindings/xmlname.rs b/components/script/dom/bindings/xmlname.rs index 4522c9c4ac0..e688052fba8 100644 --- a/components/script/dom/bindings/xmlname.rs +++ b/components/script/dom/bindings/xmlname.rs @@ -6,7 +6,7 @@ use dom::bindings::error::{Error, ErrorResult, Fallible}; use dom::bindings::str::DOMString; -use html5ever_atoms::{Prefix, LocalName, Namespace}; +use html5ever::{Prefix, LocalName, Namespace}; /// Validate a qualified name. See https://dom.spec.whatwg.org/#validate for details. pub fn validate_qualified_name(qualified_name: &str) -> ErrorResult { diff --git a/components/script/dom/create.rs b/components/script/dom/create.rs index 7c9a9eeea9c..ad5c4f2c763 100644 --- a/components/script/dom/create.rs +++ b/components/script/dom/create.rs @@ -77,7 +77,7 @@ use dom::htmlulistelement::HTMLUListElement; use dom::htmlunknownelement::HTMLUnknownElement; use dom::htmlvideoelement::HTMLVideoElement; use dom::svgsvgelement::SVGSVGElement; -use html5ever_atoms::{Prefix, QualName}; +use html5ever::QualName; use servo_config::prefs::PREFS; fn create_svg_element(name: QualName, @@ -274,13 +274,12 @@ fn create_html_element(name: QualName, } pub fn create_element(name: QualName, - prefix: Option, document: &Document, creator: ElementCreator) -> Root { // FIXME(ajeffrey): Convert directly from Prefix to DOMString. - let prefix = prefix.map(|p| DOMString::from(&*p)); + let prefix = name.prefix.as_ref().map(|p| DOMString::from(&**p)); match name.ns { ns!(html) => create_html_element(name, prefix, document, creator), diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index 06b8f7596cf..86fc09406ab 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.rs @@ -93,7 +93,7 @@ use dom_struct::dom_struct; use encoding::EncodingRef; use encoding::all::UTF_8; use euclid::point::Point2D; -use html5ever_atoms::{LocalName, QualName}; +use html5ever::{LocalName, QualName}; use hyper::header::{Header, SetCookie}; use hyper_serde::Serde; use ipc_channel::ipc::{self, IpcSender}; @@ -2733,7 +2733,7 @@ impl DocumentMethods for Document { -> Root { let ns = namespace_from_domstring(maybe_ns); let local = LocalName::from(tag_name); - let qname = QualName::new(ns, local); + let qname = QualName::new(None, ns, local); match self.tagns_map.borrow_mut().entry(qname.clone()) { Occupied(entry) => Root::from_ref(entry.get()), Vacant(entry) => { @@ -2782,8 +2782,8 @@ impl DocumentMethods for Document { ns!() }; - let name = QualName::new(ns, LocalName::from(local_name)); - Ok(Element::create(name, None, self, ElementCreator::ScriptCreated)) + let name = QualName::new(None, ns, LocalName::from(local_name)); + Ok(Element::create(name, self, ElementCreator::ScriptCreated)) } // https://dom.spec.whatwg.org/#dom-document-createelementns @@ -2793,8 +2793,8 @@ impl DocumentMethods for Document { -> Fallible> { let (namespace, prefix, local_name) = try!(validate_and_extract(namespace, &qualified_name)); - let name = QualName::new(namespace, local_name); - Ok(Element::create(name, prefix, self, ElementCreator::ScriptCreated)) + let name = QualName::new(prefix, namespace, local_name); + Ok(Element::create(name, self, ElementCreator::ScriptCreated)) } // https://dom.spec.whatwg.org/#dom-document-createattribute @@ -3047,8 +3047,8 @@ impl DocumentMethods for Document { match elem { Some(elem) => Root::upcast::(elem), None => { - let name = QualName::new(ns!(svg), local_name!("title")); - let elem = Element::create(name, None, self, ElementCreator::ScriptCreated); + let name = QualName::new(None, ns!(svg), local_name!("title")); + let elem = Element::create(name, self, ElementCreator::ScriptCreated); let parent = root.upcast::(); let child = elem.upcast::(); parent.InsertBefore(child, parent.GetFirstChild().r()) @@ -3064,9 +3064,8 @@ impl DocumentMethods for Document { None => { match self.GetHead() { Some(head) => { - let name = QualName::new(ns!(html), local_name!("title")); + let name = QualName::new(None, ns!(html), local_name!("title")); let elem = Element::create(name, - None, self, ElementCreator::ScriptCreated); head.upcast::() diff --git a/components/script/dom/domtokenlist.rs b/components/script/dom/domtokenlist.rs index 28266709f67..b07a4357e83 100644 --- a/components/script/dom/domtokenlist.rs +++ b/components/script/dom/domtokenlist.rs @@ -12,7 +12,7 @@ use dom::bindings::str::DOMString; use dom::element::Element; use dom::node::window_from_node; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; use servo_atoms::Atom; use style::str::HTML_SPACE_CHARACTERS; diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index d6974fb9075..517af0bcd44 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -75,11 +75,11 @@ use dom::validation::Validatable; use dom::virtualmethods::{VirtualMethods, vtable_for}; use dom::window::ReflowReason; use dom_struct::dom_struct; +use html5ever::{Prefix, LocalName, Namespace, QualName}; use html5ever::serialize; use html5ever::serialize::SerializeOpts; use html5ever::serialize::TraversalScope; use html5ever::serialize::TraversalScope::{ChildrenOnly, IncludeNode}; -use html5ever_atoms::{Prefix, LocalName, Namespace, QualName}; use js::jsapi::{HandleValue, JSAutoCompartment}; use net_traits::request::CorsSettings; use ref_filter_map::ref_filter_map; @@ -195,10 +195,10 @@ impl<'a> TryFrom<&'a str> for AdjacentPosition { // Element methods // impl Element { - pub fn create(name: QualName, prefix: Option, + pub fn create(name: QualName, document: &Document, creator: ElementCreator) -> Root { - create_element(name, prefix, document, creator) + create_element(name, document, creator) } pub fn new_inherited(local_name: LocalName, @@ -1955,8 +1955,8 @@ impl ElementMethods for Element { // Step 4. NodeTypeId::DocumentFragment => { - let body_elem = Element::create(QualName::new(ns!(html), local_name!("body")), - None, &context_document, + let body_elem = Element::create(QualName::new(None, ns!(html), local_name!("body")), + &context_document, ElementCreator::ScriptCreated); Root::upcast(body_elem) }, diff --git a/components/script/dom/formdata.rs b/components/script/dom/formdata.rs index af4c692e7d9..2d8657e3564 100644 --- a/components/script/dom/formdata.rs +++ b/components/script/dom/formdata.rs @@ -17,7 +17,7 @@ use dom::file::File; use dom::globalscope::GlobalScope; use dom::htmlformelement::{HTMLFormElement, FormDatumValue, FormDatum}; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; use std::collections::HashMap; use std::collections::hash_map::Entry::{Occupied, Vacant}; use std::iter; diff --git a/components/script/dom/htmlanchorelement.rs b/components/script/dom/htmlanchorelement.rs index a139afe0384..4468f1ed8b3 100644 --- a/components/script/dom/htmlanchorelement.rs +++ b/components/script/dom/htmlanchorelement.rs @@ -25,7 +25,7 @@ use dom::node::{Node, document_from_node}; use dom::urlhelper::UrlHelper; use dom::virtualmethods::VirtualMethods; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; use net_traits::ReferrerPolicy; use num_traits::ToPrimitive; use script_traits::MozBrowserEvent; diff --git a/components/script/dom/htmlappletelement.rs b/components/script/dom/htmlappletelement.rs index 73de3061cfe..35b1109d5b8 100644 --- a/components/script/dom/htmlappletelement.rs +++ b/components/script/dom/htmlappletelement.rs @@ -12,7 +12,7 @@ use dom::htmlelement::HTMLElement; use dom::node::Node; use dom::virtualmethods::VirtualMethods; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; use style::attr::AttrValue; #[dom_struct] diff --git a/components/script/dom/htmlareaelement.rs b/components/script/dom/htmlareaelement.rs index 724deb2bdcd..61f43c4d7e0 100644 --- a/components/script/dom/htmlareaelement.rs +++ b/components/script/dom/htmlareaelement.rs @@ -20,7 +20,7 @@ use dom::node::{Node, document_from_node}; use dom::virtualmethods::VirtualMethods; use dom_struct::dom_struct; use euclid::point::Point2D; -use html5ever_atoms::LocalName; +use html5ever::LocalName; use net_traits::ReferrerPolicy; use std::default::Default; use std::f32; diff --git a/components/script/dom/htmlaudioelement.rs b/components/script/dom/htmlaudioelement.rs index bb8b12f06d6..df832313cd4 100644 --- a/components/script/dom/htmlaudioelement.rs +++ b/components/script/dom/htmlaudioelement.rs @@ -9,7 +9,7 @@ use dom::document::Document; use dom::htmlmediaelement::HTMLMediaElement; use dom::node::Node; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; #[dom_struct] pub struct HTMLAudioElement { diff --git a/components/script/dom/htmlbaseelement.rs b/components/script/dom/htmlbaseelement.rs index fe34e6d77f0..3fa4093e737 100644 --- a/components/script/dom/htmlbaseelement.rs +++ b/components/script/dom/htmlbaseelement.rs @@ -14,7 +14,7 @@ use dom::htmlelement::HTMLElement; use dom::node::{Node, UnbindContext, document_from_node}; use dom::virtualmethods::VirtualMethods; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; use servo_url::ServoUrl; use style::attr::AttrValue; diff --git a/components/script/dom/htmlbodyelement.rs b/components/script/dom/htmlbodyelement.rs index ef2855fa512..432c15334ba 100644 --- a/components/script/dom/htmlbodyelement.rs +++ b/components/script/dom/htmlbodyelement.rs @@ -18,7 +18,7 @@ use dom::htmlelement::HTMLElement; use dom::node::{Node, document_from_node, window_from_node}; use dom::virtualmethods::VirtualMethods; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; use script_traits::ScriptMsg as ConstellationMsg; use servo_url::ServoUrl; use style::attr::AttrValue; diff --git a/components/script/dom/htmlbrelement.rs b/components/script/dom/htmlbrelement.rs index ebe6ed43706..c247cdd6123 100644 --- a/components/script/dom/htmlbrelement.rs +++ b/components/script/dom/htmlbrelement.rs @@ -9,7 +9,7 @@ use dom::document::Document; use dom::htmlelement::HTMLElement; use dom::node::Node; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; #[dom_struct] pub struct HTMLBRElement { diff --git a/components/script/dom/htmlbuttonelement.rs b/components/script/dom/htmlbuttonelement.rs index b36b276bfd7..5378fc031f5 100755 --- a/components/script/dom/htmlbuttonelement.rs +++ b/components/script/dom/htmlbuttonelement.rs @@ -24,7 +24,7 @@ use dom::validation::Validatable; use dom::validitystate::{ValidityState, ValidationFlags}; use dom::virtualmethods::VirtualMethods; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; use std::cell::Cell; use std::default::Default; use style::element_state::*; diff --git a/components/script/dom/htmlcanvaselement.rs b/components/script/dom/htmlcanvaselement.rs index 577537b421f..9d80db225d6 100644 --- a/components/script/dom/htmlcanvaselement.rs +++ b/components/script/dom/htmlcanvaselement.rs @@ -27,7 +27,7 @@ use dom::virtualmethods::VirtualMethods; use dom::webglrenderingcontext::{LayoutCanvasWebGLRenderingContextHelpers, WebGLRenderingContext}; use dom_struct::dom_struct; use euclid::size::Size2D; -use html5ever_atoms::LocalName; +use html5ever::LocalName; use image::ColorType; use image::png::PNGEncoder; use ipc_channel::ipc::{self, IpcSender}; diff --git a/components/script/dom/htmlcollection.rs b/components/script/dom/htmlcollection.rs index 4e05de86922..aff4125a29f 100644 --- a/components/script/dom/htmlcollection.rs +++ b/components/script/dom/htmlcollection.rs @@ -14,7 +14,7 @@ use dom::element::Element; use dom::node::Node; use dom::window::Window; use dom_struct::dom_struct; -use html5ever_atoms::{LocalName, QualName}; +use html5ever::{LocalName, QualName}; use servo_atoms::Atom; use std::cell::Cell; use style::str::split_html_space_chars; @@ -164,7 +164,7 @@ impl HTMLCollection { maybe_ns: Option) -> Root { let local = LocalName::from(tag); let ns = namespace_from_domstring(maybe_ns); - let qname = QualName::new(ns, local); + let qname = QualName::new(None, ns, local); HTMLCollection::by_qual_tag_name(window, root, qname) } diff --git a/components/script/dom/htmldataelement.rs b/components/script/dom/htmldataelement.rs index 8dc53d9860b..51e1fc10c71 100644 --- a/components/script/dom/htmldataelement.rs +++ b/components/script/dom/htmldataelement.rs @@ -10,7 +10,7 @@ use dom::document::Document; use dom::htmlelement::HTMLElement; use dom::node::Node; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; #[dom_struct] pub struct HTMLDataElement { diff --git a/components/script/dom/htmldatalistelement.rs b/components/script/dom/htmldatalistelement.rs index 48c39c500ed..13efb1b772c 100644 --- a/components/script/dom/htmldatalistelement.rs +++ b/components/script/dom/htmldatalistelement.rs @@ -14,7 +14,7 @@ use dom::htmlelement::HTMLElement; use dom::htmloptionelement::HTMLOptionElement; use dom::node::{Node, window_from_node}; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; #[dom_struct] pub struct HTMLDataListElement { diff --git a/components/script/dom/htmldetailselement.rs b/components/script/dom/htmldetailselement.rs index 1937c8f09b6..a48219926fd 100644 --- a/components/script/dom/htmldetailselement.rs +++ b/components/script/dom/htmldetailselement.rs @@ -16,7 +16,7 @@ use dom::htmlelement::HTMLElement; use dom::node::{Node, window_from_node}; use dom::virtualmethods::VirtualMethods; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; use script_thread::Runnable; use std::cell::Cell; use task_source::TaskSource; diff --git a/components/script/dom/htmldialogelement.rs b/components/script/dom/htmldialogelement.rs index 37b38ed82dc..00bc71147b2 100644 --- a/components/script/dom/htmldialogelement.rs +++ b/components/script/dom/htmldialogelement.rs @@ -14,7 +14,7 @@ use dom::eventtarget::EventTarget; use dom::htmlelement::HTMLElement; use dom::node::{Node, window_from_node}; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; #[dom_struct] pub struct HTMLDialogElement { diff --git a/components/script/dom/htmldirectoryelement.rs b/components/script/dom/htmldirectoryelement.rs index aa24adcfacf..a6dd2bc9cb6 100644 --- a/components/script/dom/htmldirectoryelement.rs +++ b/components/script/dom/htmldirectoryelement.rs @@ -9,7 +9,7 @@ use dom::document::Document; use dom::htmlelement::HTMLElement; use dom::node::Node; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; #[dom_struct] pub struct HTMLDirectoryElement { diff --git a/components/script/dom/htmldivelement.rs b/components/script/dom/htmldivelement.rs index e4d8bf669ef..d89e0cfa8c1 100644 --- a/components/script/dom/htmldivelement.rs +++ b/components/script/dom/htmldivelement.rs @@ -9,7 +9,7 @@ use dom::document::Document; use dom::htmlelement::HTMLElement; use dom::node::Node; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; #[dom_struct] pub struct HTMLDivElement { diff --git a/components/script/dom/htmldlistelement.rs b/components/script/dom/htmldlistelement.rs index 6da79f5d5c8..6934677ef31 100644 --- a/components/script/dom/htmldlistelement.rs +++ b/components/script/dom/htmldlistelement.rs @@ -9,7 +9,7 @@ use dom::document::Document; use dom::htmlelement::HTMLElement; use dom::node::Node; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; #[dom_struct] pub struct HTMLDListElement { diff --git a/components/script/dom/htmlelement.rs b/components/script/dom/htmlelement.rs index ade0b7307d1..578476cb574 100644 --- a/components/script/dom/htmlelement.rs +++ b/components/script/dom/htmlelement.rs @@ -30,7 +30,7 @@ use dom::node::{document_from_node, window_from_node}; use dom::nodelist::NodeList; use dom::virtualmethods::VirtualMethods; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; use std::ascii::AsciiExt; use std::borrow::ToOwned; use std::default::Default; diff --git a/components/script/dom/htmlembedelement.rs b/components/script/dom/htmlembedelement.rs index 9d88e7d7c12..64f9e19b06f 100644 --- a/components/script/dom/htmlembedelement.rs +++ b/components/script/dom/htmlembedelement.rs @@ -9,7 +9,7 @@ use dom::document::Document; use dom::htmlelement::HTMLElement; use dom::node::Node; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; #[dom_struct] pub struct HTMLEmbedElement { diff --git a/components/script/dom/htmlfieldsetelement.rs b/components/script/dom/htmlfieldsetelement.rs index 9fdc65a513c..1c30cd987ca 100644 --- a/components/script/dom/htmlfieldsetelement.rs +++ b/components/script/dom/htmlfieldsetelement.rs @@ -18,7 +18,7 @@ use dom::node::{Node, window_from_node}; use dom::validitystate::ValidityState; use dom::virtualmethods::VirtualMethods; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; use std::default::Default; use style::element_state::*; diff --git a/components/script/dom/htmlfontelement.rs b/components/script/dom/htmlfontelement.rs index 4e6b96a9c7e..3639a990be7 100644 --- a/components/script/dom/htmlfontelement.rs +++ b/components/script/dom/htmlfontelement.rs @@ -14,7 +14,7 @@ use dom::htmlelement::HTMLElement; use dom::node::Node; use dom::virtualmethods::VirtualMethods; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; use servo_atoms::Atom; use style::attr::AttrValue; use style::str::{HTML_SPACE_CHARACTERS, read_numbers}; diff --git a/components/script/dom/htmlformelement.rs b/components/script/dom/htmlformelement.rs index afcfd9c6690..268ad1a8250 100755 --- a/components/script/dom/htmlformelement.rs +++ b/components/script/dom/htmlformelement.rs @@ -45,7 +45,7 @@ use dom_struct::dom_struct; use encoding::EncodingRef; use encoding::all::UTF_8; use encoding::label::encoding_from_whatwg_label; -use html5ever_atoms::LocalName; +use html5ever::LocalName; use hyper::header::{Charset, ContentDisposition, ContentType, DispositionParam, DispositionType}; use hyper::method::Method; use msg::constellation_msg::PipelineId; diff --git a/components/script/dom/htmlframeelement.rs b/components/script/dom/htmlframeelement.rs index e36bfc95310..d41c0f67433 100644 --- a/components/script/dom/htmlframeelement.rs +++ b/components/script/dom/htmlframeelement.rs @@ -9,7 +9,7 @@ use dom::document::Document; use dom::htmlelement::HTMLElement; use dom::node::Node; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; #[dom_struct] pub struct HTMLFrameElement { diff --git a/components/script/dom/htmlframesetelement.rs b/components/script/dom/htmlframesetelement.rs index d6fba77cb08..4b92561b045 100644 --- a/components/script/dom/htmlframesetelement.rs +++ b/components/script/dom/htmlframesetelement.rs @@ -12,7 +12,7 @@ use dom::document::Document; use dom::htmlelement::HTMLElement; use dom::node::{Node, document_from_node}; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; #[dom_struct] pub struct HTMLFrameSetElement { diff --git a/components/script/dom/htmlheadelement.rs b/components/script/dom/htmlheadelement.rs index 7e05ac3d45c..4354a4545b5 100644 --- a/components/script/dom/htmlheadelement.rs +++ b/components/script/dom/htmlheadelement.rs @@ -15,7 +15,7 @@ use dom::node::{Node, document_from_node}; use dom::userscripts::load_script; use dom::virtualmethods::VirtualMethods; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; #[dom_struct] pub struct HTMLHeadElement { diff --git a/components/script/dom/htmlheadingelement.rs b/components/script/dom/htmlheadingelement.rs index f820b8ba90f..9c01dceb91f 100644 --- a/components/script/dom/htmlheadingelement.rs +++ b/components/script/dom/htmlheadingelement.rs @@ -9,7 +9,7 @@ use dom::document::Document; use dom::htmlelement::HTMLElement; use dom::node::Node; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; #[derive(JSTraceable, HeapSizeOf)] pub enum HeadingLevel { diff --git a/components/script/dom/htmlhrelement.rs b/components/script/dom/htmlhrelement.rs index f1d5774dbe9..4784957132a 100644 --- a/components/script/dom/htmlhrelement.rs +++ b/components/script/dom/htmlhrelement.rs @@ -13,7 +13,7 @@ use dom::htmlelement::HTMLElement; use dom::node::Node; use dom::virtualmethods::VirtualMethods; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; use style::attr::{AttrValue, LengthOrPercentageOrAuto}; #[dom_struct] diff --git a/components/script/dom/htmlhtmlelement.rs b/components/script/dom/htmlhtmlelement.rs index 924b55650ee..29ea62861a2 100644 --- a/components/script/dom/htmlhtmlelement.rs +++ b/components/script/dom/htmlhtmlelement.rs @@ -9,7 +9,7 @@ use dom::document::Document; use dom::htmlelement::HTMLElement; use dom::node::Node; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; #[dom_struct] pub struct HTMLHtmlElement { diff --git a/components/script/dom/htmliframeelement.rs b/components/script/dom/htmliframeelement.rs index 599f2f69c36..45f743a6424 100644 --- a/components/script/dom/htmliframeelement.rs +++ b/components/script/dom/htmliframeelement.rs @@ -36,7 +36,7 @@ use dom::node::{Node, NodeDamage, UnbindContext, document_from_node, window_from use dom::virtualmethods::VirtualMethods; use dom::window::{ReflowReason, Window}; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; use ipc_channel::ipc; use js::jsapi::{JSAutoCompartment, JSContext, MutableHandleValue}; use js::jsval::{NullValue, UndefinedValue}; diff --git a/components/script/dom/htmlimageelement.rs b/components/script/dom/htmlimageelement.rs index 389cd87b064..64f802bc2a6 100644 --- a/components/script/dom/htmlimageelement.rs +++ b/components/script/dom/htmlimageelement.rs @@ -35,7 +35,7 @@ use dom::virtualmethods::VirtualMethods; use dom::window::Window; use dom_struct::dom_struct; use euclid::point::Point2D; -use html5ever_atoms::LocalName; +use html5ever::LocalName; use ipc_channel::ipc; use ipc_channel::router::ROUTER; use net_traits::{FetchResponseListener, FetchMetadata, NetworkError, FetchResponseMsg}; diff --git a/components/script/dom/htmlinputelement.rs b/components/script/dom/htmlinputelement.rs index baff4983504..38e4156ded7 100755 --- a/components/script/dom/htmlinputelement.rs +++ b/components/script/dom/htmlinputelement.rs @@ -37,7 +37,7 @@ use dom::validation::Validatable; use dom::validitystate::ValidationFlags; use dom::virtualmethods::VirtualMethods; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; use ipc_channel::ipc::{self, IpcSender}; use mime_guess; use net_traits::{CoreResourceMsg, IpcSend}; diff --git a/components/script/dom/htmllabelelement.rs b/components/script/dom/htmllabelelement.rs index 73a62af5570..e5a5d36d9a6 100644 --- a/components/script/dom/htmllabelelement.rs +++ b/components/script/dom/htmllabelelement.rs @@ -18,7 +18,7 @@ use dom::htmlformelement::{FormControl, FormControlElementHelpers, HTMLFormEleme use dom::node::{document_from_node, Node}; use dom::virtualmethods::VirtualMethods; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; use style::attr::AttrValue; #[dom_struct] diff --git a/components/script/dom/htmllegendelement.rs b/components/script/dom/htmllegendelement.rs index 86b34c27dd0..95ad89e1137 100644 --- a/components/script/dom/htmllegendelement.rs +++ b/components/script/dom/htmllegendelement.rs @@ -16,7 +16,7 @@ use dom::htmlformelement::{HTMLFormElement, FormControl}; use dom::node::{Node, UnbindContext}; use dom::virtualmethods::VirtualMethods; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; #[dom_struct] pub struct HTMLLegendElement { diff --git a/components/script/dom/htmllielement.rs b/components/script/dom/htmllielement.rs index aef80a52311..faefea88742 100644 --- a/components/script/dom/htmllielement.rs +++ b/components/script/dom/htmllielement.rs @@ -12,7 +12,7 @@ use dom::htmlelement::HTMLElement; use dom::node::Node; use dom::virtualmethods::VirtualMethods; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; use style::attr::AttrValue; #[dom_struct] diff --git a/components/script/dom/htmllinkelement.rs b/components/script/dom/htmllinkelement.rs index bf36d28b29d..2a970e40acf 100644 --- a/components/script/dom/htmllinkelement.rs +++ b/components/script/dom/htmllinkelement.rs @@ -22,7 +22,7 @@ use dom::node::{Node, UnbindContext, document_from_node, window_from_node}; use dom::stylesheet::StyleSheet as DOMStyleSheet; use dom::virtualmethods::VirtualMethods; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; use net_traits::ReferrerPolicy; use script_layout_interface::message::Msg; use script_traits::{MozBrowserEvent, ScriptMsg as ConstellationMsg}; diff --git a/components/script/dom/htmlmapelement.rs b/components/script/dom/htmlmapelement.rs index 9a2ae807619..b0200e81645 100644 --- a/components/script/dom/htmlmapelement.rs +++ b/components/script/dom/htmlmapelement.rs @@ -11,7 +11,7 @@ use dom::htmlareaelement::HTMLAreaElement; use dom::htmlelement::HTMLElement; use dom::node::Node; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; #[dom_struct] pub struct HTMLMapElement { diff --git a/components/script/dom/htmlmediaelement.rs b/components/script/dom/htmlmediaelement.rs index fc036ee35cc..c29eb5fcf6a 100644 --- a/components/script/dom/htmlmediaelement.rs +++ b/components/script/dom/htmlmediaelement.rs @@ -28,7 +28,7 @@ use dom::mediaerror::MediaError; use dom::node::{window_from_node, document_from_node, Node, UnbindContext}; use dom::virtualmethods::VirtualMethods; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; use ipc_channel::ipc; use ipc_channel::router::ROUTER; use net_traits::{FetchResponseListener, FetchMetadata, Metadata, NetworkError}; diff --git a/components/script/dom/htmlmetaelement.rs b/components/script/dom/htmlmetaelement.rs index 62d7215e3df..4b628df363e 100644 --- a/components/script/dom/htmlmetaelement.rs +++ b/components/script/dom/htmlmetaelement.rs @@ -18,7 +18,7 @@ use dom::htmlheadelement::HTMLHeadElement; use dom::node::{Node, UnbindContext, document_from_node, window_from_node}; use dom::virtualmethods::VirtualMethods; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; use servo_config::prefs::PREFS; use std::ascii::AsciiExt; use std::sync::Arc; diff --git a/components/script/dom/htmlmeterelement.rs b/components/script/dom/htmlmeterelement.rs index b57951270a4..1ee7ef732f5 100644 --- a/components/script/dom/htmlmeterelement.rs +++ b/components/script/dom/htmlmeterelement.rs @@ -11,7 +11,7 @@ use dom::htmlelement::HTMLElement; use dom::node::Node; use dom::nodelist::NodeList; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; #[dom_struct] pub struct HTMLMeterElement { diff --git a/components/script/dom/htmlmodelement.rs b/components/script/dom/htmlmodelement.rs index 7724640642c..8a45aae5f87 100644 --- a/components/script/dom/htmlmodelement.rs +++ b/components/script/dom/htmlmodelement.rs @@ -9,7 +9,7 @@ use dom::document::Document; use dom::htmlelement::HTMLElement; use dom::node::Node; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; #[dom_struct] pub struct HTMLModElement { diff --git a/components/script/dom/htmlobjectelement.rs b/components/script/dom/htmlobjectelement.rs index c80a7838198..d61650b9412 100755 --- a/components/script/dom/htmlobjectelement.rs +++ b/components/script/dom/htmlobjectelement.rs @@ -18,7 +18,7 @@ use dom::validation::Validatable; use dom::validitystate::{ValidityState, ValidationFlags}; use dom::virtualmethods::VirtualMethods; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; use net_traits::image::base::Image; use std::default::Default; use std::sync::Arc; diff --git a/components/script/dom/htmlolistelement.rs b/components/script/dom/htmlolistelement.rs index a36e97404e4..e02e5b445cf 100644 --- a/components/script/dom/htmlolistelement.rs +++ b/components/script/dom/htmlolistelement.rs @@ -9,7 +9,7 @@ use dom::document::Document; use dom::htmlelement::HTMLElement; use dom::node::Node; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; #[dom_struct] pub struct HTMLOListElement { diff --git a/components/script/dom/htmloptgroupelement.rs b/components/script/dom/htmloptgroupelement.rs index 13a68d7ff41..fdc5de3d760 100644 --- a/components/script/dom/htmloptgroupelement.rs +++ b/components/script/dom/htmloptgroupelement.rs @@ -15,7 +15,7 @@ use dom::htmloptionelement::HTMLOptionElement; use dom::node::Node; use dom::virtualmethods::VirtualMethods; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; use style::element_state::*; #[dom_struct] diff --git a/components/script/dom/htmloptionelement.rs b/components/script/dom/htmloptionelement.rs index e54b9b563e4..d69aed022d3 100644 --- a/components/script/dom/htmloptionelement.rs +++ b/components/script/dom/htmloptionelement.rs @@ -23,7 +23,7 @@ use dom::node::{Node, UnbindContext}; use dom::text::Text; use dom::virtualmethods::VirtualMethods; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; use std::cell::Cell; use style::element_state::*; use style::str::{split_html_space_chars, str_join}; diff --git a/components/script/dom/htmloutputelement.rs b/components/script/dom/htmloutputelement.rs index 719efad95d3..e8febadef4f 100644 --- a/components/script/dom/htmloutputelement.rs +++ b/components/script/dom/htmloutputelement.rs @@ -17,7 +17,7 @@ use dom::nodelist::NodeList; use dom::validitystate::ValidityState; use dom::virtualmethods::VirtualMethods; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; #[dom_struct] pub struct HTMLOutputElement { diff --git a/components/script/dom/htmlparagraphelement.rs b/components/script/dom/htmlparagraphelement.rs index 1a7936352bc..b932e2c1b41 100644 --- a/components/script/dom/htmlparagraphelement.rs +++ b/components/script/dom/htmlparagraphelement.rs @@ -9,7 +9,7 @@ use dom::document::Document; use dom::htmlelement::HTMLElement; use dom::node::Node; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; #[dom_struct] pub struct HTMLParagraphElement { diff --git a/components/script/dom/htmlparamelement.rs b/components/script/dom/htmlparamelement.rs index 103faa0a641..eb1bb5ba3f2 100644 --- a/components/script/dom/htmlparamelement.rs +++ b/components/script/dom/htmlparamelement.rs @@ -9,7 +9,7 @@ use dom::document::Document; use dom::htmlelement::HTMLElement; use dom::node::Node; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; #[dom_struct] pub struct HTMLParamElement { diff --git a/components/script/dom/htmlpreelement.rs b/components/script/dom/htmlpreelement.rs index 7d3575d1eae..3a6f8621edf 100644 --- a/components/script/dom/htmlpreelement.rs +++ b/components/script/dom/htmlpreelement.rs @@ -9,7 +9,7 @@ use dom::document::Document; use dom::htmlelement::HTMLElement; use dom::node::Node; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; #[dom_struct] pub struct HTMLPreElement { diff --git a/components/script/dom/htmlprogresselement.rs b/components/script/dom/htmlprogresselement.rs index fe8eb2775e9..096c9dce38c 100644 --- a/components/script/dom/htmlprogresselement.rs +++ b/components/script/dom/htmlprogresselement.rs @@ -11,7 +11,7 @@ use dom::htmlelement::HTMLElement; use dom::node::Node; use dom::nodelist::NodeList; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; #[dom_struct] pub struct HTMLProgressElement { diff --git a/components/script/dom/htmlquoteelement.rs b/components/script/dom/htmlquoteelement.rs index de3e473434b..797f6913b54 100644 --- a/components/script/dom/htmlquoteelement.rs +++ b/components/script/dom/htmlquoteelement.rs @@ -9,7 +9,7 @@ use dom::document::Document; use dom::htmlelement::HTMLElement; use dom::node::Node; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; #[dom_struct] pub struct HTMLQuoteElement { diff --git a/components/script/dom/htmlscriptelement.rs b/components/script/dom/htmlscriptelement.rs index d6679c5168c..c77e7a46dfa 100644 --- a/components/script/dom/htmlscriptelement.rs +++ b/components/script/dom/htmlscriptelement.rs @@ -26,7 +26,7 @@ use dom::virtualmethods::VirtualMethods; use dom_struct::dom_struct; use encoding::label::encoding_from_whatwg_label; use encoding::types::{DecoderTrap, EncodingRef}; -use html5ever_atoms::LocalName; +use html5ever::LocalName; use ipc_channel::ipc; use ipc_channel::router::ROUTER; use js::jsval::UndefinedValue; diff --git a/components/script/dom/htmlselectelement.rs b/components/script/dom/htmlselectelement.rs index 2d4dc4758b6..f59753e60c5 100755 --- a/components/script/dom/htmlselectelement.rs +++ b/components/script/dom/htmlselectelement.rs @@ -31,7 +31,7 @@ use dom::validation::Validatable; use dom::validitystate::{ValidityState, ValidationFlags}; use dom::virtualmethods::VirtualMethods; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; use std::default::Default; use std::iter; use style::attr::AttrValue; diff --git a/components/script/dom/htmlsourceelement.rs b/components/script/dom/htmlsourceelement.rs index 2b15fabd789..0e550b6aa74 100644 --- a/components/script/dom/htmlsourceelement.rs +++ b/components/script/dom/htmlsourceelement.rs @@ -9,7 +9,7 @@ use dom::document::Document; use dom::htmlelement::HTMLElement; use dom::node::Node; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; #[dom_struct] pub struct HTMLSourceElement { diff --git a/components/script/dom/htmlspanelement.rs b/components/script/dom/htmlspanelement.rs index 1437d1dbb08..32accc8bbc1 100644 --- a/components/script/dom/htmlspanelement.rs +++ b/components/script/dom/htmlspanelement.rs @@ -9,7 +9,7 @@ use dom::document::Document; use dom::htmlelement::HTMLElement; use dom::node::Node; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; #[dom_struct] pub struct HTMLSpanElement { diff --git a/components/script/dom/htmlstyleelement.rs b/components/script/dom/htmlstyleelement.rs index 8905c3baa65..02ccc83d824 100644 --- a/components/script/dom/htmlstyleelement.rs +++ b/components/script/dom/htmlstyleelement.rs @@ -19,7 +19,7 @@ use dom::node::{ChildrenMutation, Node, UnbindContext, document_from_node, windo use dom::stylesheet::StyleSheet as DOMStyleSheet; use dom::virtualmethods::VirtualMethods; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; use net_traits::ReferrerPolicy; use script_layout_interface::message::Msg; use std::cell::Cell; diff --git a/components/script/dom/htmltablecaptionelement.rs b/components/script/dom/htmltablecaptionelement.rs index fd6c06643dd..bb78ca5fd7f 100644 --- a/components/script/dom/htmltablecaptionelement.rs +++ b/components/script/dom/htmltablecaptionelement.rs @@ -9,7 +9,7 @@ use dom::document::Document; use dom::htmlelement::HTMLElement; use dom::node::Node; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; #[dom_struct] pub struct HTMLTableCaptionElement { diff --git a/components/script/dom/htmltablecellelement.rs b/components/script/dom/htmltablecellelement.rs index ef4bffba5d7..70f39fff623 100644 --- a/components/script/dom/htmltablecellelement.rs +++ b/components/script/dom/htmltablecellelement.rs @@ -15,7 +15,7 @@ use dom::htmltablerowelement::HTMLTableRowElement; use dom::node::Node; use dom::virtualmethods::VirtualMethods; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; use style::attr::{AttrValue, LengthOrPercentageOrAuto}; const DEFAULT_COLSPAN: u32 = 1; diff --git a/components/script/dom/htmltablecolelement.rs b/components/script/dom/htmltablecolelement.rs index 00f618ed65f..3b7656f3386 100644 --- a/components/script/dom/htmltablecolelement.rs +++ b/components/script/dom/htmltablecolelement.rs @@ -9,7 +9,7 @@ use dom::document::Document; use dom::htmlelement::HTMLElement; use dom::node::Node; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; #[dom_struct] pub struct HTMLTableColElement { diff --git a/components/script/dom/htmltabledatacellelement.rs b/components/script/dom/htmltabledatacellelement.rs index 77808c77d79..fe3ab42ef73 100644 --- a/components/script/dom/htmltabledatacellelement.rs +++ b/components/script/dom/htmltabledatacellelement.rs @@ -9,7 +9,7 @@ use dom::document::Document; use dom::htmltablecellelement::HTMLTableCellElement; use dom::node::Node; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; #[dom_struct] pub struct HTMLTableDataCellElement { diff --git a/components/script/dom/htmltableelement.rs b/components/script/dom/htmltableelement.rs index 56e9876b753..d255d8a91c8 100644 --- a/components/script/dom/htmltableelement.rs +++ b/components/script/dom/htmltableelement.rs @@ -23,7 +23,7 @@ use dom::htmltablesectionelement::HTMLTableSectionElement; use dom::node::{Node, document_from_node, window_from_node}; use dom::virtualmethods::VirtualMethods; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; use std::cell::Cell; use style::attr::{AttrValue, LengthOrPercentageOrAuto, parse_unsigned_integer}; diff --git a/components/script/dom/htmltableheadercellelement.rs b/components/script/dom/htmltableheadercellelement.rs index a471faee00f..aeb293081e8 100644 --- a/components/script/dom/htmltableheadercellelement.rs +++ b/components/script/dom/htmltableheadercellelement.rs @@ -9,7 +9,7 @@ use dom::document::Document; use dom::htmltablecellelement::HTMLTableCellElement; use dom::node::Node; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; #[dom_struct] pub struct HTMLTableHeaderCellElement { diff --git a/components/script/dom/htmltablerowelement.rs b/components/script/dom/htmltablerowelement.rs index be1b636beb4..40cb25148bd 100644 --- a/components/script/dom/htmltablerowelement.rs +++ b/components/script/dom/htmltablerowelement.rs @@ -22,7 +22,7 @@ use dom::htmltablesectionelement::HTMLTableSectionElement; use dom::node::{Node, window_from_node}; use dom::virtualmethods::VirtualMethods; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; use style::attr::AttrValue; #[derive(JSTraceable)] diff --git a/components/script/dom/htmltablesectionelement.rs b/components/script/dom/htmltablesectionelement.rs index cf9be4b81b4..717705622eb 100644 --- a/components/script/dom/htmltablesectionelement.rs +++ b/components/script/dom/htmltablesectionelement.rs @@ -17,7 +17,7 @@ use dom::htmltablerowelement::HTMLTableRowElement; use dom::node::{Node, window_from_node}; use dom::virtualmethods::VirtualMethods; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; use style::attr::AttrValue; #[dom_struct] diff --git a/components/script/dom/htmltemplateelement.rs b/components/script/dom/htmltemplateelement.rs index 8e54ae63523..db45fada13d 100644 --- a/components/script/dom/htmltemplateelement.rs +++ b/components/script/dom/htmltemplateelement.rs @@ -15,7 +15,7 @@ use dom::htmlelement::HTMLElement; use dom::node::{CloneChildrenFlag, Node, document_from_node}; use dom::virtualmethods::VirtualMethods; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; #[dom_struct] pub struct HTMLTemplateElement { diff --git a/components/script/dom/htmltextareaelement.rs b/components/script/dom/htmltextareaelement.rs index 8a4e9f41cd3..a8f9d22947c 100755 --- a/components/script/dom/htmltextareaelement.rs +++ b/components/script/dom/htmltextareaelement.rs @@ -26,7 +26,7 @@ use dom::nodelist::NodeList; use dom::validation::Validatable; use dom::virtualmethods::VirtualMethods; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; use ipc_channel::ipc::IpcSender; use script_traits::ScriptMsg as ConstellationMsg; use std::cell::Cell; diff --git a/components/script/dom/htmltimeelement.rs b/components/script/dom/htmltimeelement.rs index 2c559a30cc5..907f6373ea7 100644 --- a/components/script/dom/htmltimeelement.rs +++ b/components/script/dom/htmltimeelement.rs @@ -10,7 +10,7 @@ use dom::document::Document; use dom::htmlelement::HTMLElement; use dom::node::Node; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; #[dom_struct] pub struct HTMLTimeElement { diff --git a/components/script/dom/htmltitleelement.rs b/components/script/dom/htmltitleelement.rs index 43208399fb6..8f312ef41a0 100644 --- a/components/script/dom/htmltitleelement.rs +++ b/components/script/dom/htmltitleelement.rs @@ -13,7 +13,7 @@ use dom::htmlelement::HTMLElement; use dom::node::{ChildrenMutation, Node}; use dom::virtualmethods::VirtualMethods; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; #[dom_struct] pub struct HTMLTitleElement { diff --git a/components/script/dom/htmltrackelement.rs b/components/script/dom/htmltrackelement.rs index 97811ee5a10..77868e484a7 100644 --- a/components/script/dom/htmltrackelement.rs +++ b/components/script/dom/htmltrackelement.rs @@ -9,7 +9,7 @@ use dom::document::Document; use dom::htmlelement::HTMLElement; use dom::node::Node; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; #[dom_struct] pub struct HTMLTrackElement { diff --git a/components/script/dom/htmlulistelement.rs b/components/script/dom/htmlulistelement.rs index 4153709e108..552202c3421 100644 --- a/components/script/dom/htmlulistelement.rs +++ b/components/script/dom/htmlulistelement.rs @@ -9,7 +9,7 @@ use dom::document::Document; use dom::htmlelement::HTMLElement; use dom::node::Node; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; #[dom_struct] pub struct HTMLUListElement { diff --git a/components/script/dom/htmlunknownelement.rs b/components/script/dom/htmlunknownelement.rs index d54025de852..a7f3f77b095 100644 --- a/components/script/dom/htmlunknownelement.rs +++ b/components/script/dom/htmlunknownelement.rs @@ -9,7 +9,7 @@ use dom::document::Document; use dom::htmlelement::HTMLElement; use dom::node::Node; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; #[dom_struct] pub struct HTMLUnknownElement { diff --git a/components/script/dom/htmlvideoelement.rs b/components/script/dom/htmlvideoelement.rs index 1a0d93dacf8..f3d698b3376 100644 --- a/components/script/dom/htmlvideoelement.rs +++ b/components/script/dom/htmlvideoelement.rs @@ -9,7 +9,7 @@ use dom::document::Document; use dom::htmlmediaelement::HTMLMediaElement; use dom::node::Node; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; #[dom_struct] pub struct HTMLVideoElement { diff --git a/components/script/dom/namednodemap.rs b/components/script/dom/namednodemap.rs index 273b87c8d00..9d92bf11c2d 100644 --- a/components/script/dom/namednodemap.rs +++ b/components/script/dom/namednodemap.rs @@ -14,7 +14,7 @@ use dom::bindings::xmlname::namespace_from_domstring; use dom::element::Element; use dom::window::Window; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; use std::ascii::AsciiExt; #[dom_struct] diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs index 0384c4ed19d..b511d8630dd 100644 --- a/components/script/dom/node.rs +++ b/components/script/dom/node.rs @@ -58,7 +58,7 @@ use euclid::point::Point2D; use euclid::rect::Rect; use euclid::size::Size2D; use heapsize::{HeapSizeOf, heap_size_of}; -use html5ever_atoms::{Prefix, Namespace, QualName}; +use html5ever::{Prefix, Namespace, QualName}; use js::jsapi::{JSContext, JSObject, JSRuntime}; use libc::{self, c_void, uintptr_t}; use msg::constellation_msg::PipelineId; @@ -1749,11 +1749,11 @@ impl Node { NodeTypeId::Element(..) => { let element = node.downcast::().unwrap(); let name = QualName { + prefix: element.prefix().map(|p| Prefix::from(&**p)), ns: element.namespace().clone(), local: element.local_name().clone() }; let element = Element::create(name, - element.prefix().map(|p| Prefix::from(&**p)), &document, ElementCreator::ScriptCreated); Root::upcast::(element) }, diff --git a/components/script/dom/servoparser/html.rs b/components/script/dom/servoparser/html.rs index 6142dba20f6..f25e95507e4 100644 --- a/components/script/dom/servoparser/html.rs +++ b/components/script/dom/servoparser/html.rs @@ -5,38 +5,28 @@ #![allow(unrooted_must_root)] use dom::bindings::codegen::Bindings::HTMLTemplateElementBinding::HTMLTemplateElementMethods; -use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods; use dom::bindings::inheritance::{Castable, CharacterDataTypeId, NodeTypeId}; use dom::bindings::js::{JS, Root}; -use dom::bindings::str::DOMString; use dom::bindings::trace::JSTraceable; use dom::characterdata::CharacterData; -use dom::comment::Comment; use dom::document::Document; use dom::documenttype::DocumentType; -use dom::element::{Element, ElementCreator}; -use dom::htmlformelement::{FormControlElementHelpers, HTMLFormElement}; +use dom::element::Element; use dom::htmlscriptelement::HTMLScriptElement; use dom::htmltemplateelement::HTMLTemplateElement; use dom::node::Node; use dom::processinginstruction::ProcessingInstruction; -use dom::virtualmethods::vtable_for; -use html5ever::Attribute; +use dom::servoparser::Sink; use html5ever::QualName; -use html5ever::serialize::{AttrRef, Serializable, Serializer}; +use html5ever::buffer_queue::BufferQueue; +use html5ever::serialize::{AttrRef, Serialize, Serializer}; use html5ever::serialize::TraversalScope; use html5ever::serialize::TraversalScope::{ChildrenOnly, IncludeNode}; -use html5ever::tendril::StrTendril; use html5ever::tokenizer::{Tokenizer as HtmlTokenizer, TokenizerOpts, TokenizerResult}; -use html5ever::tokenizer::buffer_queue::BufferQueue; -use html5ever::tree_builder::{NodeOrText, QuirksMode}; -use html5ever::tree_builder::{Tracer as HtmlTracer, TreeBuilder, TreeBuilderOpts, TreeSink}; +use html5ever::tree_builder::{Tracer as HtmlTracer, TreeBuilder, TreeBuilderOpts}; use js::jsapi::JSTracer; use servo_url::ServoUrl; -use std::ascii::AsciiExt; -use std::borrow::Cow; -use std::io::{self, Write}; -use style::context::QuirksMode as ServoQuirksMode; +use std::io; #[derive(HeapSizeOf, JSTraceable)] #[must_root] @@ -55,6 +45,7 @@ impl Tokenizer { base_url: url, document: JS::from_ref(document), current_line: 1, + script: Default::default(), }; let options = TreeBuilderOpts { @@ -124,179 +115,18 @@ unsafe impl JSTraceable for HtmlTokenizer, Sink>> { } } -#[derive(JSTraceable, HeapSizeOf)] -#[must_root] -struct Sink { - base_url: ServoUrl, - document: JS, - current_line: u64, -} - -impl TreeSink for Sink { - type Output = Self; - fn finish(self) -> Self { self } - - type Handle = JS; - - fn get_document(&mut self) -> JS { - JS::from_ref(self.document.upcast()) - } - - fn get_template_contents(&mut self, target: JS) -> JS { - let template = target.downcast::() - .expect("tried to get template contents of non-HTMLTemplateElement in HTML parsing"); - JS::from_ref(template.Content().upcast()) - } - - fn same_node(&self, x: JS, y: JS) -> bool { - x == y - } - - fn elem_name(&self, target: JS) -> QualName { - let elem = target.downcast::() - .expect("tried to get name of non-Element in HTML parsing"); - QualName { - ns: elem.namespace().clone(), - local: elem.local_name().clone(), - } - } - - fn same_tree(&self, x: JS, y: JS) -> bool { - let x = x.downcast::().expect("Element node expected"); - let y = y.downcast::().expect("Element node expected"); - - x.is_in_same_home_subtree(y) - } - - fn create_element(&mut self, name: QualName, attrs: Vec) - -> JS { - let elem = Element::create(name, None, &*self.document, - ElementCreator::ParserCreated(self.current_line)); - - for attr in attrs { - elem.set_attribute_from_parser(attr.name, DOMString::from(String::from(attr.value)), None); - } - - JS::from_ref(elem.upcast()) - } - - fn create_comment(&mut self, text: StrTendril) -> JS { - let comment = Comment::new(DOMString::from(String::from(text)), &*self.document); - JS::from_ref(comment.upcast()) - } - - fn has_parent_node(&self, node: JS) -> bool { - node.GetParentNode().is_some() - } - - fn associate_with_form(&mut self, target: JS, form: JS) { - let node = target; - let form = Root::downcast::(Root::from_ref(&*form)) - .expect("Owner must be a form element"); - - let elem = node.downcast::(); - let control = elem.as_ref().and_then(|e| e.as_maybe_form_control()); - - if let Some(control) = control { - control.set_form_owner_from_parser(&form); - } else { - // TODO remove this code when keygen is implemented. - assert!(node.NodeName() == "KEYGEN", "Unknown form-associatable element"); - } - } - - fn append_before_sibling(&mut self, - sibling: JS, - new_node: NodeOrText>) { - let parent = sibling.GetParentNode() - .expect("append_before_sibling called on node without parent"); - - super::insert(&parent, Some(&*sibling), new_node); - } - - fn parse_error(&mut self, msg: Cow<'static, str>) { - debug!("Parse error: {}", msg); - } - - fn set_quirks_mode(&mut self, mode: QuirksMode) { - let mode = match mode { - QuirksMode::Quirks => ServoQuirksMode::Quirks, - QuirksMode::LimitedQuirks => ServoQuirksMode::LimitedQuirks, - QuirksMode::NoQuirks => ServoQuirksMode::NoQuirks, - }; - self.document.set_quirks_mode(mode); - } - - fn append(&mut self, parent: JS, child: NodeOrText>) { - super::insert(&parent, None, child); - } - - fn append_doctype_to_document(&mut self, name: StrTendril, public_id: StrTendril, - system_id: StrTendril) { - let doc = &*self.document; - let doctype = DocumentType::new( - DOMString::from(String::from(name)), Some(DOMString::from(String::from(public_id))), - Some(DOMString::from(String::from(system_id))), doc); - doc.upcast::().AppendChild(doctype.upcast()).expect("Appending failed"); - } - - fn add_attrs_if_missing(&mut self, target: JS, attrs: Vec) { - let elem = target.downcast::() - .expect("tried to set attrs on non-Element in HTML parsing"); - for attr in attrs { - elem.set_attribute_from_parser(attr.name, DOMString::from(String::from(attr.value)), None); - } - } - - fn remove_from_parent(&mut self, target: JS) { - if let Some(ref parent) = target.GetParentNode() { - parent.RemoveChild(&*target).unwrap(); - } - } - - fn mark_script_already_started(&mut self, node: JS) { - let script = node.downcast::(); - script.map(|script| script.set_already_started(true)); - } - - fn reparent_children(&mut self, node: JS, new_parent: JS) { - while let Some(ref child) = node.GetFirstChild() { - new_parent.AppendChild(&child).unwrap(); - } - } - - /// https://html.spec.whatwg.org/multipage/#html-integration-point - /// Specifically, the cases. - fn is_mathml_annotation_xml_integration_point(&self, handle: JS) -> bool { - let elem = handle.downcast::().unwrap(); - elem.get_attribute(&ns!(), &local_name!("encoding")).map_or(false, |attr| { - attr.value().eq_ignore_ascii_case("text/html") - || attr.value().eq_ignore_ascii_case("application/xhtml+xml") - }) - } - - fn set_current_line(&mut self, line_number: u64) { - self.current_line = line_number; - } - - fn pop(&mut self, node: JS) { - let node = Root::from_ref(&*node); - vtable_for(&node).pop(); - } -} - -impl<'a> Serializable for &'a Node { - fn serialize<'wr, Wr: Write>(&self, serializer: &mut Serializer<'wr, Wr>, - traversal_scope: TraversalScope) -> io::Result<()> { +impl<'a> Serialize for &'a Node { + fn serialize(&self, serializer: &mut S, + traversal_scope: TraversalScope) -> io::Result<()> { let node = *self; match (traversal_scope, node.type_id()) { (_, NodeTypeId::Element(..)) => { let elem = node.downcast::().unwrap(); - let name = QualName::new(elem.namespace().clone(), + let name = QualName::new(None, elem.namespace().clone(), elem.local_name().clone()); if traversal_scope == IncludeNode { let attrs = elem.attrs().iter().map(|attr| { - let qname = QualName::new(attr.namespace().clone(), + let qname = QualName::new(None, attr.namespace().clone(), attr.local_name().clone()); let value = attr.value().clone(); (qname, value) diff --git a/components/script/dom/servoparser/mod.rs b/components/script/dom/servoparser/mod.rs index 3904910d3a3..39c199a34f7 100644 --- a/components/script/dom/servoparser/mod.rs +++ b/components/script/dom/servoparser/mod.rs @@ -6,27 +6,35 @@ use document_loader::{DocumentLoader, LoadType}; use dom::bindings::cell::DOMRefCell; use dom::bindings::codegen::Bindings::DocumentBinding::{DocumentMethods, DocumentReadyState}; use dom::bindings::codegen::Bindings::HTMLImageElementBinding::HTMLImageElementMethods; +use dom::bindings::codegen::Bindings::HTMLTemplateElementBinding::HTMLTemplateElementMethods; use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods; use dom::bindings::codegen::Bindings::ServoParserBinding; use dom::bindings::inheritance::Castable; -use dom::bindings::js::{JS, Root, RootedReference}; +use dom::bindings::js::{JS, MutNullableJS, Root, RootedReference}; use dom::bindings::refcounted::Trusted; use dom::bindings::reflector::{Reflector, reflect_dom_object}; use dom::bindings::str::DOMString; use dom::characterdata::CharacterData; +use dom::comment::Comment; use dom::document::{Document, DocumentSource, HasBrowsingContext, IsHTMLDocument}; -use dom::element::Element; +use dom::documenttype::DocumentType; +use dom::element::{Element, ElementCreator}; use dom::globalscope::GlobalScope; -use dom::htmlformelement::HTMLFormElement; +use dom::htmlformelement::{FormControlElementHelpers, HTMLFormElement}; use dom::htmlimageelement::HTMLImageElement; use dom::htmlscriptelement::{HTMLScriptElement, ScriptResult}; +use dom::htmltemplateelement::HTMLTemplateElement; use dom::node::{Node, NodeSiblingIterator}; +use dom::processinginstruction::ProcessingInstruction; use dom::text::Text; +use dom::virtualmethods::vtable_for; use dom_struct::dom_struct; use encoding::all::UTF_8; use encoding::types::{DecoderTrap, Encoding}; -use html5ever::tokenizer::buffer_queue::BufferQueue; -use html5ever::tree_builder::NodeOrText; +use html5ever::{Attribute, QualName, ExpandedName}; +use html5ever::buffer_queue::BufferQueue; +use html5ever::tendril::StrTendril; +use html5ever::tree_builder::{NodeOrText, TreeSink, NextParserState, QuirksMode, ElementFlags}; use hyper::header::ContentType; use hyper::mime::{Mime, SubLevel, TopLevel}; use hyper_serde::Serde; @@ -40,8 +48,10 @@ use script_traits::DocumentActivity; use servo_config::resource_files::read_resource_file; use servo_url::ServoUrl; use std::ascii::AsciiExt; +use std::borrow::Cow; use std::cell::Cell; use std::mem; +use style::context::QuirksMode as ServoQuirksMode; mod html; mod xml; @@ -671,3 +681,183 @@ fn insert(parent: &Node, reference_child: Option<&Node>, child: NodeOrText, + current_line: u64, + script: MutNullableJS, +} + +#[allow(unrooted_must_root)] // FIXME: really? +impl TreeSink for Sink { + type Output = Self; + fn finish(self) -> Self { self } + + type Handle = JS; + + fn get_document(&mut self) -> JS { + JS::from_ref(self.document.upcast()) + } + + fn get_template_contents(&mut self, target: &JS) -> JS { + let template = target.downcast::() + .expect("tried to get template contents of non-HTMLTemplateElement in HTML parsing"); + JS::from_ref(template.Content().upcast()) + } + + fn same_node(&self, x: &JS, y: &JS) -> bool { + x == y + } + + fn elem_name<'a>(&self, target: &'a JS) -> ExpandedName<'a> { + let elem = target.downcast::() + .expect("tried to get name of non-Element in HTML parsing"); + ExpandedName { + ns: elem.namespace(), + local: elem.local_name(), + } + } + + fn same_tree(&self, x: &JS, y: &JS) -> bool { + let x = x.downcast::().expect("Element node expected"); + let y = y.downcast::().expect("Element node expected"); + + x.is_in_same_home_subtree(y) + } + + fn create_element(&mut self, name: QualName, attrs: Vec, _flags: ElementFlags) + -> JS { + let elem = Element::create(name, &*self.document, + ElementCreator::ParserCreated(self.current_line)); + + for attr in attrs { + elem.set_attribute_from_parser(attr.name, DOMString::from(String::from(attr.value)), None); + } + + JS::from_ref(elem.upcast()) + } + + fn create_comment(&mut self, text: StrTendril) -> JS { + let comment = Comment::new(DOMString::from(String::from(text)), &*self.document); + JS::from_ref(comment.upcast()) + } + + fn create_pi(&mut self, target: StrTendril, data: StrTendril) -> JS { + let doc = &*self.document; + let pi = ProcessingInstruction::new( + DOMString::from(String::from(target)), DOMString::from(String::from(data)), + doc); + JS::from_ref(pi.upcast()) + } + + fn has_parent_node(&self, node: &JS) -> bool { + node.GetParentNode().is_some() + } + + fn associate_with_form(&mut self, target: &JS, form: &JS) { + let node = target; + let form = Root::downcast::(Root::from_ref(&**form)) + .expect("Owner must be a form element"); + + let elem = node.downcast::(); + let control = elem.and_then(|e| e.as_maybe_form_control()); + + if let Some(control) = control { + control.set_form_owner_from_parser(&form); + } else { + // TODO remove this code when keygen is implemented. + assert!(node.NodeName() == "KEYGEN", "Unknown form-associatable element"); + } + } + + fn append_before_sibling(&mut self, + sibling: &JS, + new_node: NodeOrText>) { + let parent = sibling.GetParentNode() + .expect("append_before_sibling called on node without parent"); + + insert(&parent, Some(&*sibling), new_node); + } + + fn parse_error(&mut self, msg: Cow<'static, str>) { + debug!("Parse error: {}", msg); + } + + fn set_quirks_mode(&mut self, mode: QuirksMode) { + let mode = match mode { + QuirksMode::Quirks => ServoQuirksMode::Quirks, + QuirksMode::LimitedQuirks => ServoQuirksMode::LimitedQuirks, + QuirksMode::NoQuirks => ServoQuirksMode::NoQuirks, + }; + self.document.set_quirks_mode(mode); + } + + fn append(&mut self, parent: &JS, child: NodeOrText>) { + insert(&parent, None, child); + } + + fn append_doctype_to_document(&mut self, name: StrTendril, public_id: StrTendril, + system_id: StrTendril) { + let doc = &*self.document; + let doctype = DocumentType::new( + DOMString::from(String::from(name)), Some(DOMString::from(String::from(public_id))), + Some(DOMString::from(String::from(system_id))), doc); + doc.upcast::().AppendChild(doctype.upcast()).expect("Appending failed"); + } + + fn add_attrs_if_missing(&mut self, target: &JS, attrs: Vec) { + let elem = target.downcast::() + .expect("tried to set attrs on non-Element in HTML parsing"); + for attr in attrs { + elem.set_attribute_from_parser(attr.name, DOMString::from(String::from(attr.value)), None); + } + } + + fn remove_from_parent(&mut self, target: &JS) { + if let Some(ref parent) = target.GetParentNode() { + parent.RemoveChild(&*target).unwrap(); + } + } + + fn mark_script_already_started(&mut self, node: &JS) { + let script = node.downcast::(); + script.map(|script| script.set_already_started(true)); + } + + fn complete_script(&mut self, node: &JS) -> NextParserState { + if let Some(script) = node.downcast() { + self.script.set(Some(script)); + NextParserState::Suspend + } else { + NextParserState::Continue + } + } + + fn reparent_children(&mut self, node: &JS, new_parent: &JS) { + while let Some(ref child) = node.GetFirstChild() { + new_parent.AppendChild(&child).unwrap(); + } + } + + /// https://html.spec.whatwg.org/multipage/#html-integration-point + /// Specifically, the cases. + fn is_mathml_annotation_xml_integration_point(&self, handle: &JS) -> bool { + let elem = handle.downcast::().unwrap(); + elem.get_attribute(&ns!(), &local_name!("encoding")).map_or(false, |attr| { + attr.value().eq_ignore_ascii_case("text/html") + || attr.value().eq_ignore_ascii_case("application/xhtml+xml") + }) + } + + fn set_current_line(&mut self, line_number: u64) { + self.current_line = line_number; + } + + fn pop(&mut self, node: &JS) { + let node = Root::from_ref(&**node); + vtable_for(&node).pop(); + } +} diff --git a/components/script/dom/servoparser/xml.rs b/components/script/dom/servoparser/xml.rs index 1ef5f882db0..da5e1987253 100644 --- a/components/script/dom/servoparser/xml.rs +++ b/components/script/dom/servoparser/xml.rs @@ -4,29 +4,17 @@ #![allow(unrooted_must_root)] -use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods; -use dom::bindings::inheritance::Castable; -use dom::bindings::js::{JS, MutNullableJS, Root}; -use dom::bindings::str::DOMString; +use dom::bindings::js::{JS, Root}; use dom::bindings::trace::JSTraceable; -use dom::comment::Comment; use dom::document::Document; -use dom::documenttype::DocumentType; -use dom::element::{Element, ElementCreator}; use dom::htmlscriptelement::HTMLScriptElement; use dom::node::Node; -use dom::processinginstruction::ProcessingInstruction; -use dom::virtualmethods::vtable_for; -use html5ever::tokenizer::buffer_queue::BufferQueue; -use html5ever::tree_builder::{NodeOrText as H5eNodeOrText}; -use html5ever_atoms::{Prefix, QualName}; +use dom::servoparser::Sink; use js::jsapi::JSTracer; use servo_url::ServoUrl; -use std::borrow::Cow; -use xml5ever::tendril::StrTendril; -use xml5ever::tokenizer::{Attribute, QName, XmlTokenizer}; -use xml5ever::tree_builder::{NextParserState, NodeOrText}; -use xml5ever::tree_builder::{Tracer as XmlTracer, TreeSink, XmlTreeBuilder}; +use xml5ever::buffer_queue::BufferQueue; +use xml5ever::tokenizer::XmlTokenizer; +use xml5ever::tree_builder::{Tracer as XmlTracer, XmlTreeBuilder}; #[derive(HeapSizeOf, JSTraceable)] #[must_root] @@ -40,6 +28,7 @@ impl Tokenizer { let sink = Sink { base_url: url, document: JS::from_ref(document), + current_line: 1, script: Default::default(), }; @@ -86,7 +75,7 @@ unsafe impl JSTraceable for XmlTokenizer, Sink>> { impl XmlTracer for Tracer { type Handle = JS; #[allow(unrooted_must_root)] - fn trace_handle(&self, node: JS) { + fn trace_handle(&self, node: &JS) { unsafe { node.trace(self.0); } } } @@ -96,111 +85,3 @@ unsafe impl JSTraceable for XmlTokenizer, Sink>> { tree_builder.sink().trace(trc); } } - -#[derive(JSTraceable, HeapSizeOf)] -#[must_root] -struct Sink { - base_url: ServoUrl, - document: JS, - script: MutNullableJS, -} - -impl TreeSink for Sink { - type Output = Self; - type Handle = JS; - - fn finish(self) -> Self { - self - } - - fn parse_error(&mut self, msg: Cow<'static, str>) { - debug!("Parse error: {}", msg); - } - - fn get_document(&mut self) -> JS { - JS::from_ref(self.document.upcast()) - } - - fn elem_name(&self, target: &JS) -> QName { - let elem = target.downcast::() - .expect("tried to get name of non-Element in XML parsing"); - QName { - prefix: elem.prefix().map_or(namespace_prefix!(""), |p| Prefix::from(&**p)), - namespace_url: elem.namespace().clone(), - local: elem.local_name().clone(), - } - } - - fn create_element(&mut self, name: QName, attrs: Vec) - -> JS { - let prefix = if name.prefix == namespace_prefix!("") { None } else { Some(name.prefix) }; - let name = QualName { - ns: name.namespace_url, - local: name.local, - }; - //TODO: Add ability to track lines to API of xml5ever - let elem = Element::create(name, prefix, &*self.document, - ElementCreator::ParserCreated(1)); - - for attr in attrs { - let name = QualName { - ns: attr.name.namespace_url, - local: attr.name.local, - }; - elem.set_attribute_from_parser(name, DOMString::from(String::from(attr.value)), None); - } - - JS::from_ref(elem.upcast()) - } - - fn create_comment(&mut self, text: StrTendril) -> JS { - let comment = Comment::new(DOMString::from(String::from(text)), &*self.document); - JS::from_ref(comment.upcast()) - } - - fn append(&mut self, parent: JS, child: NodeOrText>) { - let child = match child { - NodeOrText::AppendNode(n) => H5eNodeOrText::AppendNode(n), - NodeOrText::AppendText(s) => H5eNodeOrText::AppendText(s), - }; - super::insert(&*parent, None, child); - } - - fn append_doctype_to_document(&mut self, name: StrTendril, public_id: StrTendril, - system_id: StrTendril) { - let doc = &*self.document; - let doctype = DocumentType::new( - DOMString::from(String::from(name)), Some(DOMString::from(String::from(public_id))), - Some(DOMString::from(String::from(system_id))), doc); - doc.upcast::().AppendChild(doctype.upcast()).expect("Appending failed"); - } - - fn create_pi(&mut self, target: StrTendril, data: StrTendril) -> JS { - let doc = &*self.document; - let pi = ProcessingInstruction::new( - DOMString::from(String::from(target)), DOMString::from(String::from(data)), - doc); - JS::from_ref(pi.upcast()) - } - - fn mark_script_already_started(&mut self, node: Self::Handle) { - let script = node.downcast::(); - if let Some(script) = script { - script.set_already_started(true); - } - } - - fn complete_script(&mut self, node: Self::Handle) -> NextParserState { - if let Some(script) = node.downcast() { - self.script.set(Some(script)); - NextParserState::Suspend - } else { - NextParserState::Continue - } - } - - fn pop(&mut self, node: Self::Handle) { - let node = Root::from_ref(&*node); - vtable_for(&node).pop(); - } -} diff --git a/components/script/dom/svgelement.rs b/components/script/dom/svgelement.rs index 1a0654ed312..358cc925383 100644 --- a/components/script/dom/svgelement.rs +++ b/components/script/dom/svgelement.rs @@ -8,7 +8,7 @@ use dom::document::Document; use dom::element::Element; use dom::virtualmethods::VirtualMethods; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; use style::element_state::ElementState; #[dom_struct] diff --git a/components/script/dom/svggraphicselement.rs b/components/script/dom/svggraphicselement.rs index f41768f9815..73b3a3789f6 100644 --- a/components/script/dom/svggraphicselement.rs +++ b/components/script/dom/svggraphicselement.rs @@ -8,7 +8,7 @@ use dom::document::Document; use dom::svgelement::SVGElement; use dom::virtualmethods::VirtualMethods; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; use style::element_state::ElementState; #[dom_struct] diff --git a/components/script/dom/svgsvgelement.rs b/components/script/dom/svgsvgelement.rs index 7c7d85f17b0..c8bb6ff54ad 100644 --- a/components/script/dom/svgsvgelement.rs +++ b/components/script/dom/svgsvgelement.rs @@ -13,7 +13,7 @@ use dom::node::Node; use dom::svggraphicselement::SVGGraphicsElement; use dom::virtualmethods::VirtualMethods; use dom_struct::dom_struct; -use html5ever_atoms::LocalName; +use html5ever::LocalName; use script_layout_interface::SVGSVGData; use style::attr::AttrValue; diff --git a/components/script/dom/virtualmethods.rs b/components/script/dom/virtualmethods.rs index 8ff47f9ced5..ecb4d2ee559 100644 --- a/components/script/dom/virtualmethods.rs +++ b/components/script/dom/virtualmethods.rs @@ -51,7 +51,7 @@ use dom::htmltextareaelement::HTMLTextAreaElement; use dom::htmltitleelement::HTMLTitleElement; use dom::node::{ChildrenMutation, CloneChildrenFlag, Node, UnbindContext}; use dom::svgsvgelement::SVGSVGElement; -use html5ever_atoms::LocalName; +use html5ever::LocalName; use style::attr::AttrValue; /// Trait to allow DOM nodes to opt-in to overriding (or adding to) common diff --git a/components/script/layout_wrapper.rs b/components/script/layout_wrapper.rs index 3ddb1d2b5c9..6f7c8723c2b 100644 --- a/components/script/layout_wrapper.rs +++ b/components/script/layout_wrapper.rs @@ -42,7 +42,7 @@ use dom::node::{CAN_BE_FRAGMENTED, DIRTY_ON_VIEWPORT_SIZE_CHANGE, HAS_DIRTY_DESC use dom::node::{LayoutNodeHelpers, Node}; use dom::text::Text; use gfx_traits::ByteIndex; -use html5ever_atoms::{LocalName, Namespace}; +use html5ever::{LocalName, Namespace}; use msg::constellation_msg::PipelineId; use range::Range; use script_layout_interface::{HTMLCanvasData, LayoutNodeType, SVGSVGData, TrustedNodeAddress}; diff --git a/components/script/lib.rs b/components/script/lib.rs index 678603ee60f..c1bd886b927 100644 --- a/components/script/lib.rs +++ b/components/script/lib.rs @@ -48,8 +48,7 @@ extern crate fnv; extern crate gfx_traits; extern crate heapsize; #[macro_use] extern crate heapsize_derive; -extern crate html5ever; -#[macro_use] extern crate html5ever_atoms; +#[macro_use] extern crate html5ever; #[macro_use] extern crate hyper; extern crate hyper_serde; diff --git a/components/script_layout_interface/Cargo.toml b/components/script_layout_interface/Cargo.toml index 2df1a3f3205..03bb0df8436 100644 --- a/components/script_layout_interface/Cargo.toml +++ b/components/script_layout_interface/Cargo.toml @@ -18,7 +18,7 @@ euclid = "0.11" gfx_traits = {path = "../gfx_traits"} heapsize = "0.3.0" heapsize_derive = "0.1" -html5ever-atoms = "0.3" +html5ever = "0.16" ipc-channel = "0.7" libc = "0.2" log = "0.3.5" diff --git a/components/script_layout_interface/lib.rs b/components/script_layout_interface/lib.rs index 98375e6a05a..46d9bf2aadc 100644 --- a/components/script_layout_interface/lib.rs +++ b/components/script_layout_interface/lib.rs @@ -19,7 +19,7 @@ extern crate euclid; extern crate gfx_traits; extern crate heapsize; #[macro_use] extern crate heapsize_derive; -#[macro_use] extern crate html5ever_atoms; +#[macro_use] extern crate html5ever; extern crate ipc_channel; extern crate libc; #[macro_use] diff --git a/components/script_layout_interface/wrapper_traits.rs b/components/script_layout_interface/wrapper_traits.rs index 4abc74bcac0..237cc4f5687 100644 --- a/components/script_layout_interface/wrapper_traits.rs +++ b/components/script_layout_interface/wrapper_traits.rs @@ -10,7 +10,7 @@ use OpaqueStyleAndLayoutData; use SVGSVGData; use atomic_refcell::AtomicRefCell; use gfx_traits::{ByteIndex, FragmentType, combine_id_with_fragment_type}; -use html5ever_atoms::{Namespace, LocalName}; +use html5ever::{Namespace, LocalName}; use msg::constellation_msg::PipelineId; use range::Range; use servo_url::ServoUrl; diff --git a/components/style/Cargo.toml b/components/style/Cargo.toml index 3f1aa94f750..a7e262ec322 100644 --- a/components/style/Cargo.toml +++ b/components/style/Cargo.toml @@ -16,7 +16,7 @@ doctest = false gecko = ["nsstring_vendor", "rayon/unstable", "num_cpus"] use_bindgen = ["bindgen", "regex"] servo = ["serde/unstable", "serde", "serde_derive", "heapsize", "heapsize_derive", - "style_traits/servo", "servo_atoms", "servo_config", "html5ever-atoms", + "style_traits/servo", "servo_atoms", "servo_config", "html5ever", "cssparser/heapsize", "cssparser/serde", "encoding", "smallvec/heapsizeof", "rayon/unstable", "servo_url"] testing = [] @@ -35,7 +35,7 @@ euclid = "0.11" fnv = "1.0" heapsize = {version = "0.3.0", optional = true} heapsize_derive = {version = "0.1", optional = true} -html5ever-atoms = {version = "0.3", optional = true} +html5ever = {version = "0.16", optional = true} lazy_static = "0.2" log = "0.3" matches = "0.1" diff --git a/components/style/lib.rs b/components/style/lib.rs index 7479279418d..ab09fcdbc61 100644 --- a/components/style/lib.rs +++ b/components/style/lib.rs @@ -50,7 +50,7 @@ extern crate fnv; #[cfg(feature = "gecko")] #[macro_use] pub mod gecko_string_cache; #[cfg(feature = "servo")] extern crate heapsize; #[cfg(feature = "servo")] #[macro_use] extern crate heapsize_derive; -#[cfg(feature = "servo")] #[macro_use] extern crate html5ever_atoms; +#[cfg(feature = "servo")] #[macro_use] extern crate html5ever; #[macro_use] extern crate lazy_static; #[macro_use] @@ -140,9 +140,9 @@ use style_traits::ToCss; #[cfg(feature = "gecko")] pub use gecko_string_cache::Atom as LocalName; #[cfg(feature = "servo")] pub use servo_atoms::Atom; -#[cfg(feature = "servo")] pub use html5ever_atoms::Prefix; -#[cfg(feature = "servo")] pub use html5ever_atoms::LocalName; -#[cfg(feature = "servo")] pub use html5ever_atoms::Namespace; +#[cfg(feature = "servo")] pub use html5ever::Prefix; +#[cfg(feature = "servo")] pub use html5ever::LocalName; +#[cfg(feature = "servo")] pub use html5ever::Namespace; /// The CSS properties supported by the style system. /// Generated from the properties.mako.rs template by build.rs diff --git a/tests/unit/style/Cargo.toml b/tests/unit/style/Cargo.toml index 4450cb901b4..09e0231931b 100644 --- a/tests/unit/style/Cargo.toml +++ b/tests/unit/style/Cargo.toml @@ -16,7 +16,7 @@ testing = ["style/testing"] app_units = "0.4" cssparser = "0.13" euclid = "0.11" -html5ever-atoms = "0.3" +html5ever = "0.16" parking_lot = "0.3" rayon = "0.6" rustc-serialize = "0.3" diff --git a/tests/unit/style/lib.rs b/tests/unit/style/lib.rs index baddd4da618..4a03cf0f232 100644 --- a/tests/unit/style/lib.rs +++ b/tests/unit/style/lib.rs @@ -8,7 +8,7 @@ extern crate app_units; extern crate cssparser; extern crate euclid; -#[macro_use] extern crate html5ever_atoms; +#[macro_use] extern crate html5ever; extern crate parking_lot; extern crate rayon; extern crate rustc_serialize; diff --git a/tests/unit/style/stylesheets.rs b/tests/unit/style/stylesheets.rs index 47aa1ea9730..877cc82de31 100644 --- a/tests/unit/style/stylesheets.rs +++ b/tests/unit/style/stylesheets.rs @@ -3,7 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use cssparser::{self, Parser as CssParser, SourcePosition}; -use html5ever_atoms::{Namespace as NsAtom}; +use html5ever::{Namespace as NsAtom}; use media_queries::CSSErrorReporterTest; use parking_lot::RwLock; use selectors::parser::*; diff --git a/tests/unit/style/stylist.rs b/tests/unit/style/stylist.rs index ea89dfde06b..7b58cab58c2 100644 --- a/tests/unit/style/stylist.rs +++ b/tests/unit/style/stylist.rs @@ -2,7 +2,7 @@ * 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 html5ever_atoms::LocalName; +use html5ever::LocalName; use selectors::parser::LocalName as LocalNameSelector; use selectors::parser::Selector; use servo_atoms::Atom; From 71f3d8a3205141d32b430384af9bca7af5aa6c22 Mon Sep 17 00:00:00 2001 From: Alan Jeffrey Date: Tue, 2 May 2017 11:39:36 -0500 Subject: [PATCH 02/12] Added mozilla wpt test for adopted nodes passing same-origin-domain checks. --- tests/wpt/mozilla/meta/MANIFEST.json | 10 +++++++ ...dopted_node_is_same_origin_domain.html.ini | 4 +++ .../adopted_node_is_same_origin_domain.html | 30 +++++++++++++++++++ 3 files changed, 44 insertions(+) create mode 100644 tests/wpt/mozilla/meta/mozilla/adopted_node_is_same_origin_domain.html.ini create mode 100644 tests/wpt/mozilla/tests/mozilla/adopted_node_is_same_origin_domain.html diff --git a/tests/wpt/mozilla/meta/MANIFEST.json b/tests/wpt/mozilla/meta/MANIFEST.json index 5b451022e62..6d77e39770b 100644 --- a/tests/wpt/mozilla/meta/MANIFEST.json +++ b/tests/wpt/mozilla/meta/MANIFEST.json @@ -11369,6 +11369,12 @@ {} ] ], + "mozilla/adopted_node_is_same_origin_domain.html": [ + [ + "/_mozilla/mozilla/adopted_node_is_same_origin_domain.html", + {} + ] + ], "mozilla/binding_keyword.html": [ [ "/_mozilla/mozilla/binding_keyword.html", @@ -24492,6 +24498,10 @@ "170d51460da58c16f5cf94ecda18f18a1c18c116", "support" ], + "mozilla/adopted_node_is_same_origin_domain.html": [ + "3f2e6af92f9391aa1892e485c61c9e92c7661194", + "testharness" + ], "mozilla/binding_keyword.html": [ "c79aa6d506fbabbed0f6f31d1b8600ea6ba8ff41", "testharness" diff --git a/tests/wpt/mozilla/meta/mozilla/adopted_node_is_same_origin_domain.html.ini b/tests/wpt/mozilla/meta/mozilla/adopted_node_is_same_origin_domain.html.ini new file mode 100644 index 00000000000..3c4d9edc50f --- /dev/null +++ b/tests/wpt/mozilla/meta/mozilla/adopted_node_is_same_origin_domain.html.ini @@ -0,0 +1,4 @@ +[adopted_node_is_same_origin_domain.html] + type: testharness + [Adopting a node should make it same-origin-domain.] + expected: FAIL diff --git a/tests/wpt/mozilla/tests/mozilla/adopted_node_is_same_origin_domain.html b/tests/wpt/mozilla/tests/mozilla/adopted_node_is_same_origin_domain.html new file mode 100644 index 00000000000..81de5b389c9 --- /dev/null +++ b/tests/wpt/mozilla/tests/mozilla/adopted_node_is_same_origin_domain.html @@ -0,0 +1,30 @@ + + +Ensure that adopted nodes pass the same-origin-domain checks + + + +
+ From 2b6c494f858772dd539e4a06c18572cbd87189f5 Mon Sep 17 00:00:00 2001 From: Brad Werth Date: Thu, 27 Apr 2017 12:13:44 -0700 Subject: [PATCH 03/12] Change StyleSet to track stylesheets by unique ID. MozReview-Commit-ID: Ky3P53o4Euw --- components/style/gecko/data.rs | 7 ++- components/style/gecko_bindings/bindings.rs | 8 ++- components/style/stylesheet_set.rs | 67 ++++++++++++++------- ports/geckolib/glue.rs | 17 +++--- 4 files changed, 62 insertions(+), 37 deletions(-) diff --git a/components/style/gecko/data.rs b/components/style/gecko/data.rs index 7efad2a9fbe..942aaf4f7b5 100644 --- a/components/style/gecko/data.rs +++ b/components/style/gecko/data.rs @@ -18,7 +18,7 @@ use std::collections::HashMap; use std::sync::Arc; use std::sync::mpsc::{Receiver, Sender, channel}; use stylesheet_set::StylesheetSet; -use stylesheets::{FontFaceRule, Origin}; +use stylesheets::{FontFaceRule, Origin, Stylesheet}; use stylist::{ExtraStyleData, Stylist}; /// The container for data that a Servo-backed Gecko document needs to style @@ -106,8 +106,9 @@ impl PerDocumentStyleDataImpl { }; let author_style_disabled = self.stylesheets.author_style_disabled(); - let stylesheets = self.stylesheets.flush(); - stylist.update(stylesheets, + let mut stylesheets = Vec::>::new(); + self.stylesheets.flush(&mut stylesheets); + stylist.update(stylesheets.as_slice(), &StylesheetGuards::same(guard), /* ua_sheets = */ None, /* stylesheets_changed = */ true, diff --git a/components/style/gecko_bindings/bindings.rs b/components/style/gecko_bindings/bindings.rs index 36075707b5b..1b3560dc849 100644 --- a/components/style/gecko_bindings/bindings.rs +++ b/components/style/gecko_bindings/bindings.rs @@ -1574,16 +1574,18 @@ extern "C" { extern "C" { pub fn Servo_StyleSet_AppendStyleSheet(set: RawServoStyleSetBorrowed, sheet: RawServoStyleSheetBorrowed, + unique_id: u32, flush: bool); } extern "C" { pub fn Servo_StyleSet_PrependStyleSheet(set: RawServoStyleSetBorrowed, sheet: RawServoStyleSheetBorrowed, + unique_id: u32, flush: bool); } extern "C" { pub fn Servo_StyleSet_RemoveStyleSheet(set: RawServoStyleSetBorrowed, - sheet: RawServoStyleSheetBorrowed, + unique_id: u32, flush: bool); } extern "C" { @@ -1591,8 +1593,8 @@ extern "C" { RawServoStyleSetBorrowed, sheet: RawServoStyleSheetBorrowed, - reference: - RawServoStyleSheetBorrowed, + unique_id: u32, + before_unique_id: u32, flush: bool); } extern "C" { diff --git a/components/style/stylesheet_set.rs b/components/style/stylesheet_set.rs index e1f782bbbbf..78e0c9cd558 100644 --- a/components/style/stylesheet_set.rs +++ b/components/style/stylesheet_set.rs @@ -4,19 +4,26 @@ //! A centralized set of stylesheets for a document. -use arc_ptr_eq; use std::sync::Arc; use stylesheets::Stylesheet; +/// Entry for a StylesheetSet. We don't bother creating a constructor, because +/// there's no sensible defaults for the member variables. +pub struct StylesheetSetEntry { + unique_id: u32, + sheet: Arc, +} + /// The set of stylesheets effective for a given document. pub struct StylesheetSet { - /// The actual list of all the stylesheets that apply to the given document. + /// The actual list of all the stylesheets that apply to the given document, + /// each stylesheet associated with a unique ID. /// /// This is only a list of top-level stylesheets, and as such it doesn't /// include recursive `@import` rules. - stylesheets: Vec>, + entries: Vec, - /// Whether the stylesheets list above has changed since the last restyle. + /// Whether the entries list above has changed since the last restyle. dirty: bool, /// Has author style been disabled? @@ -27,7 +34,7 @@ impl StylesheetSet { /// Create a new empty StylesheetSet. pub fn new() -> Self { StylesheetSet { - stylesheets: vec![], + entries: vec![], dirty: false, author_style_disabled: false, } @@ -39,39 +46,51 @@ impl StylesheetSet { self.author_style_disabled } - fn remove_stylesheet_if_present(&mut self, sheet: &Arc) { - self.stylesheets.retain(|x| !arc_ptr_eq(x, sheet)); + fn remove_stylesheet_if_present(&mut self, unique_id: u32) { + self.entries.retain(|x| x.unique_id != unique_id); } /// Appends a new stylesheet to the current set. - pub fn append_stylesheet(&mut self, sheet: &Arc) { - self.remove_stylesheet_if_present(sheet); - self.stylesheets.push(sheet.clone()); + pub fn append_stylesheet(&mut self, sheet: &Arc, + unique_id: u32) { + self.remove_stylesheet_if_present(unique_id); + self.entries.push(StylesheetSetEntry { + unique_id: unique_id, + sheet: sheet.clone(), + }); self.dirty = true; } /// Prepend a new stylesheet to the current set. - pub fn prepend_stylesheet(&mut self, sheet: &Arc) { - self.remove_stylesheet_if_present(sheet); - self.stylesheets.insert(0, sheet.clone()); + pub fn prepend_stylesheet(&mut self, sheet: &Arc, + unique_id: u32) { + self.remove_stylesheet_if_present(unique_id); + self.entries.insert(0, StylesheetSetEntry { + unique_id: unique_id, + sheet: sheet.clone(), + }); self.dirty = true; } /// Insert a given stylesheet before another stylesheet in the document. pub fn insert_stylesheet_before(&mut self, sheet: &Arc, - before: &Arc) { - self.remove_stylesheet_if_present(sheet); - let index = self.stylesheets.iter().position(|x| { - arc_ptr_eq(x, before) - }).expect("`before` stylesheet not found"); - self.stylesheets.insert(index, sheet.clone()); + unique_id: u32, + before_unique_id: u32) { + self.remove_stylesheet_if_present(unique_id); + let index = self.entries.iter().position(|x| { + x.unique_id == before_unique_id + }).expect("`before_unique_id` stylesheet not found"); + self.entries.insert(index, StylesheetSetEntry { + unique_id: unique_id, + sheet: sheet.clone(), + }); self.dirty = true; } /// Remove a given stylesheet from the set. - pub fn remove_stylesheet(&mut self, sheet: &Arc) { - self.remove_stylesheet_if_present(sheet); + pub fn remove_stylesheet(&mut self, unique_id: u32) { + self.remove_stylesheet_if_present(unique_id); self.dirty = true; } @@ -90,9 +109,11 @@ impl StylesheetSet { } /// Flush the current set, unmarking it as dirty. - pub fn flush(&mut self) -> &[Arc] { + pub fn flush(&mut self, sheets: &mut Vec>) { self.dirty = false; - &self.stylesheets + for entry in &self.entries { + sheets.push(entry.sheet.clone()) + } } /// Mark the stylesheets as dirty, because something external may have diff --git a/ports/geckolib/glue.rs b/ports/geckolib/glue.rs index 25790188460..dff56ce8b0f 100644 --- a/ports/geckolib/glue.rs +++ b/ports/geckolib/glue.rs @@ -593,12 +593,13 @@ pub extern "C" fn Servo_StyleSheet_ClearAndUpdate(stylesheet: RawServoStyleSheet #[no_mangle] pub extern "C" fn Servo_StyleSet_AppendStyleSheet(raw_data: RawServoStyleSetBorrowed, raw_sheet: RawServoStyleSheetBorrowed, + unique_id: u32, flush: bool) { let global_style_data = &*GLOBAL_STYLE_DATA; let guard = global_style_data.shared_lock.read(); let mut data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut(); let sheet = HasArcFFI::as_arc(&raw_sheet); - data.stylesheets.append_stylesheet(sheet); + data.stylesheets.append_stylesheet(sheet, unique_id); if flush { data.flush_stylesheets(&guard); } @@ -607,12 +608,13 @@ pub extern "C" fn Servo_StyleSet_AppendStyleSheet(raw_data: RawServoStyleSetBorr #[no_mangle] pub extern "C" fn Servo_StyleSet_PrependStyleSheet(raw_data: RawServoStyleSetBorrowed, raw_sheet: RawServoStyleSheetBorrowed, + unique_id: u32, flush: bool) { let global_style_data = &*GLOBAL_STYLE_DATA; let guard = global_style_data.shared_lock.read(); let mut data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut(); let sheet = HasArcFFI::as_arc(&raw_sheet); - data.stylesheets.prepend_stylesheet(sheet); + data.stylesheets.prepend_stylesheet(sheet, unique_id); if flush { data.flush_stylesheets(&guard); } @@ -621,14 +623,14 @@ pub extern "C" fn Servo_StyleSet_PrependStyleSheet(raw_data: RawServoStyleSetBor #[no_mangle] pub extern "C" fn Servo_StyleSet_InsertStyleSheetBefore(raw_data: RawServoStyleSetBorrowed, raw_sheet: RawServoStyleSheetBorrowed, - raw_reference: RawServoStyleSheetBorrowed, + unique_id: u32, + before_unique_id: u32, flush: bool) { let global_style_data = &*GLOBAL_STYLE_DATA; let guard = global_style_data.shared_lock.read(); let mut data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut(); let sheet = HasArcFFI::as_arc(&raw_sheet); - let reference = HasArcFFI::as_arc(&raw_reference); - data.stylesheets.insert_stylesheet_before(sheet, reference); + data.stylesheets.insert_stylesheet_before(sheet, unique_id, before_unique_id); if flush { data.flush_stylesheets(&guard); } @@ -636,13 +638,12 @@ pub extern "C" fn Servo_StyleSet_InsertStyleSheetBefore(raw_data: RawServoStyleS #[no_mangle] pub extern "C" fn Servo_StyleSet_RemoveStyleSheet(raw_data: RawServoStyleSetBorrowed, - raw_sheet: RawServoStyleSheetBorrowed, + unique_id: u32, flush: bool) { let global_style_data = &*GLOBAL_STYLE_DATA; let guard = global_style_data.shared_lock.read(); let mut data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut(); - let sheet = HasArcFFI::as_arc(&raw_sheet); - data.stylesheets.remove_stylesheet(sheet); + data.stylesheets.remove_stylesheet(unique_id); if flush { data.flush_stylesheets(&guard); } From 46bc0525f7cef6f48a2ff3c1f4ec4baff9876816 Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Sat, 29 Apr 2017 22:03:41 -0700 Subject: [PATCH 04/12] Fork std::arc. This is a verbatim copy of the source at [1]. It won't compile on stable rust, but I'm including it here to make the changes clear. [1] https://doc.rust-lang.org/src/alloc/arc.rs.html MozReview-Commit-ID: XEbOK4fXQX --- components/style/stylearc.rs | 1468 ++++++++++++++++++++++++++++++++++ 1 file changed, 1468 insertions(+) create mode 100644 components/style/stylearc.rs diff --git a/components/style/stylearc.rs b/components/style/stylearc.rs new file mode 100644 index 00000000000..8c0dd6b3795 --- /dev/null +++ b/components/style/stylearc.rs @@ -0,0 +1,1468 @@ +// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![stable(feature = "rust1", since = "1.0.0")] + +//! Thread-safe reference-counting pointers. +//! +//! See the [`Arc`][arc] documentation for more details. +//! +//! [arc]: struct.Arc.html + +use boxed::Box; + +use core::sync::atomic; +use core::sync::atomic::Ordering::{Acquire, Relaxed, Release, SeqCst}; +use core::borrow; +use core::fmt; +use core::cmp::Ordering; +use core::mem::{align_of_val, size_of_val}; +use core::intrinsics::abort; +use core::mem; +use core::mem::uninitialized; +use core::ops::Deref; +use core::ops::CoerceUnsized; +use core::ptr::{self, Shared}; +use core::marker::Unsize; +use core::hash::{Hash, Hasher}; +use core::{isize, usize}; +use core::convert::From; +use heap::deallocate; + +/// A soft limit on the amount of references that may be made to an `Arc`. +/// +/// Going above this limit will abort your program (although not +/// necessarily) at _exactly_ `MAX_REFCOUNT + 1` references. +const MAX_REFCOUNT: usize = (isize::MAX) as usize; + +/// A thread-safe reference-counting pointer. +/// +/// The type `Arc` provides shared ownership of a value of type `T`, +/// allocated in the heap. Invoking [`clone`][clone] on `Arc` produces +/// a new pointer to the same value in the heap. When the last `Arc` +/// pointer to a given value is destroyed, the pointed-to value is +/// also destroyed. +/// +/// Shared references in Rust disallow mutation by default, and `Arc` is no +/// exception. If you need to mutate through an `Arc`, use [`Mutex`][mutex], +/// [`RwLock`][rwlock], or one of the [`Atomic`][atomic] types. +/// +/// `Arc` uses atomic operations for reference counting, so `Arc`s can be +/// sent between threads. In other words, `Arc` implements [`Send`] +/// as long as `T` implements [`Send`] and [`Sync`][sync]. The disadvantage is +/// that atomic operations are more expensive than ordinary memory accesses. +/// If you are not sharing reference-counted values between threads, consider +/// using [`rc::Rc`][`Rc`] for lower overhead. [`Rc`] is a safe default, because +/// the compiler will catch any attempt to send an [`Rc`] between threads. +/// However, a library might choose `Arc` in order to give library consumers +/// more flexibility. +/// +/// The [`downgrade`][downgrade] method can be used to create a non-owning +/// [`Weak`][weak] pointer. A [`Weak`][weak] pointer can be [`upgrade`][upgrade]d +/// to an `Arc`, but this will return [`None`] if the value has already been +/// dropped. +/// +/// A cycle between `Arc` pointers will never be deallocated. For this reason, +/// [`Weak`][weak] is used to break cycles. For example, a tree could have +/// strong `Arc` pointers from parent nodes to children, and [`Weak`][weak] +/// pointers from children back to their parents. +/// +/// `Arc` automatically dereferences to `T` (via the [`Deref`][deref] trait), +/// so you can call `T`'s methods on a value of type `Arc`. To avoid name +/// clashes with `T`'s methods, the methods of `Arc` itself are [associated +/// functions][assoc], called using function-like syntax: +/// +/// ``` +/// use std::sync::Arc; +/// let my_arc = Arc::new(()); +/// +/// Arc::downgrade(&my_arc); +/// ``` +/// +/// [`Weak`][weak] does not auto-dereference to `T`, because the value may have +/// already been destroyed. +/// +/// [arc]: struct.Arc.html +/// [weak]: struct.Weak.html +/// [`Rc`]: ../../std/rc/struct.Rc.html +/// [clone]: ../../std/clone/trait.Clone.html#tymethod.clone +/// [mutex]: ../../std/sync/struct.Mutex.html +/// [rwlock]: ../../std/sync/struct.RwLock.html +/// [atomic]: ../../std/sync/atomic/ +/// [`Send`]: ../../std/marker/trait.Send.html +/// [sync]: ../../std/marker/trait.Sync.html +/// [deref]: ../../std/ops/trait.Deref.html +/// [downgrade]: struct.Arc.html#method.downgrade +/// [upgrade]: struct.Weak.html#method.upgrade +/// [`None`]: ../../std/option/enum.Option.html#variant.None +/// [assoc]: ../../book/method-syntax.html#associated-functions +/// +/// # Examples +/// +/// Sharing some immutable data between threads: +/// +// Note that we **do not** run these tests here. The windows builders get super +// unhappy if a thread outlives the main thread and then exits at the same time +// (something deadlocks) so we just avoid this entirely by not running these +// tests. +/// ```no_run +/// use std::sync::Arc; +/// use std::thread; +/// +/// let five = Arc::new(5); +/// +/// for _ in 0..10 { +/// let five = five.clone(); +/// +/// thread::spawn(move || { +/// println!("{:?}", five); +/// }); +/// } +/// ``` +/// +/// Sharing a mutable [`AtomicUsize`]: +/// +/// [`AtomicUsize`]: ../../std/sync/atomic/struct.AtomicUsize.html +/// +/// ```no_run +/// use std::sync::Arc; +/// use std::sync::atomic::{AtomicUsize, Ordering}; +/// use std::thread; +/// +/// let val = Arc::new(AtomicUsize::new(5)); +/// +/// for _ in 0..10 { +/// let val = val.clone(); +/// +/// thread::spawn(move || { +/// let v = val.fetch_add(1, Ordering::SeqCst); +/// println!("{:?}", v); +/// }); +/// } +/// ``` +/// +/// See the [`rc` documentation][rc_examples] for more examples of reference +/// counting in general. +/// +/// [rc_examples]: ../../std/rc/#examples +#[stable(feature = "rust1", since = "1.0.0")] +pub struct Arc { + ptr: Shared>, +} + +#[stable(feature = "rust1", since = "1.0.0")] +unsafe impl Send for Arc {} +#[stable(feature = "rust1", since = "1.0.0")] +unsafe impl Sync for Arc {} + +#[unstable(feature = "coerce_unsized", issue = "27732")] +impl, U: ?Sized> CoerceUnsized> for Arc {} + +/// A weak version of [`Arc`][arc]. +/// +/// `Weak` pointers do not count towards determining if the inner value +/// should be dropped. +/// +/// The typical way to obtain a `Weak` pointer is to call +/// [`Arc::downgrade`][downgrade]. +/// +/// See the [`Arc`][arc] documentation for more details. +/// +/// [arc]: struct.Arc.html +/// [downgrade]: struct.Arc.html#method.downgrade +#[stable(feature = "arc_weak", since = "1.4.0")] +pub struct Weak { + ptr: Shared>, +} + +#[stable(feature = "arc_weak", since = "1.4.0")] +unsafe impl Send for Weak {} +#[stable(feature = "arc_weak", since = "1.4.0")] +unsafe impl Sync for Weak {} + +#[unstable(feature = "coerce_unsized", issue = "27732")] +impl, U: ?Sized> CoerceUnsized> for Weak {} + +#[stable(feature = "arc_weak", since = "1.4.0")] +impl fmt::Debug for Weak { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "(Weak)") + } +} + +struct ArcInner { + strong: atomic::AtomicUsize, + + // the value usize::MAX acts as a sentinel for temporarily "locking" the + // ability to upgrade weak pointers or downgrade strong ones; this is used + // to avoid races in `make_mut` and `get_mut`. + weak: atomic::AtomicUsize, + + data: T, +} + +unsafe impl Send for ArcInner {} +unsafe impl Sync for ArcInner {} + +impl Arc { + /// Constructs a new `Arc`. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let five = Arc::new(5); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn new(data: T) -> Arc { + // Start the weak pointer count as 1 which is the weak pointer that's + // held by all the strong pointers (kinda), see std/rc.rs for more info + let x: Box<_> = box ArcInner { + strong: atomic::AtomicUsize::new(1), + weak: atomic::AtomicUsize::new(1), + data: data, + }; + Arc { ptr: unsafe { Shared::new(Box::into_raw(x)) } } + } + + /// Returns the contained value, if the `Arc` has exactly one strong reference. + /// + /// Otherwise, an [`Err`][result] is returned with the same `Arc` that was + /// passed in. + /// + /// This will succeed even if there are outstanding weak references. + /// + /// [result]: ../../std/result/enum.Result.html + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let x = Arc::new(3); + /// assert_eq!(Arc::try_unwrap(x), Ok(3)); + /// + /// let x = Arc::new(4); + /// let _y = x.clone(); + /// assert_eq!(*Arc::try_unwrap(x).unwrap_err(), 4); + /// ``` + #[inline] + #[stable(feature = "arc_unique", since = "1.4.0")] + pub fn try_unwrap(this: Self) -> Result { + // See `drop` for why all these atomics are like this + if this.inner().strong.compare_exchange(1, 0, Release, Relaxed).is_err() { + return Err(this); + } + + atomic::fence(Acquire); + + unsafe { + let ptr = *this.ptr; + let elem = ptr::read(&(*ptr).data); + + // Make a weak pointer to clean up the implicit strong-weak reference + let _weak = Weak { ptr: this.ptr }; + mem::forget(this); + + Ok(elem) + } + } + + /// Consumes the `Arc`, returning the wrapped pointer. + /// + /// To avoid a memory leak the pointer must be converted back to an `Arc` using + /// [`Arc::from_raw`][from_raw]. + /// + /// [from_raw]: struct.Arc.html#method.from_raw + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let x = Arc::new(10); + /// let x_ptr = Arc::into_raw(x); + /// assert_eq!(unsafe { *x_ptr }, 10); + /// ``` + #[stable(feature = "rc_raw", since = "1.17.0")] + pub fn into_raw(this: Self) -> *const T { + let ptr = unsafe { &(**this.ptr).data as *const _ }; + mem::forget(this); + ptr + } + + /// Constructs an `Arc` from a raw pointer. + /// + /// The raw pointer must have been previously returned by a call to a + /// [`Arc::into_raw`][into_raw]. + /// + /// This function is unsafe because improper use may lead to memory problems. For example, a + /// double-free may occur if the function is called twice on the same raw pointer. + /// + /// [into_raw]: struct.Arc.html#method.into_raw + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let x = Arc::new(10); + /// let x_ptr = Arc::into_raw(x); + /// + /// unsafe { + /// // Convert back to an `Arc` to prevent leak. + /// let x = Arc::from_raw(x_ptr); + /// assert_eq!(*x, 10); + /// + /// // Further calls to `Arc::from_raw(x_ptr)` would be memory unsafe. + /// } + /// + /// // The memory was freed when `x` went out of scope above, so `x_ptr` is now dangling! + /// ``` + #[stable(feature = "rc_raw", since = "1.17.0")] + pub unsafe fn from_raw(ptr: *const T) -> Self { + // To find the corresponding pointer to the `ArcInner` we need to subtract the offset of the + // `data` field from the pointer. + let ptr = (ptr as *const u8).offset(-offset_of!(ArcInner, data)); + Arc { + ptr: Shared::new(ptr as *const _), + } + } +} + +impl Arc { + /// Creates a new [`Weak`][weak] pointer to this value. + /// + /// [weak]: struct.Weak.html + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let five = Arc::new(5); + /// + /// let weak_five = Arc::downgrade(&five); + /// ``` + #[stable(feature = "arc_weak", since = "1.4.0")] + pub fn downgrade(this: &Self) -> Weak { + // This Relaxed is OK because we're checking the value in the CAS + // below. + let mut cur = this.inner().weak.load(Relaxed); + + loop { + // check if the weak counter is currently "locked"; if so, spin. + if cur == usize::MAX { + cur = this.inner().weak.load(Relaxed); + continue; + } + + // NOTE: this code currently ignores the possibility of overflow + // into usize::MAX; in general both Rc and Arc need to be adjusted + // to deal with overflow. + + // Unlike with Clone(), we need this to be an Acquire read to + // synchronize with the write coming from `is_unique`, so that the + // events prior to that write happen before this read. + match this.inner().weak.compare_exchange_weak(cur, cur + 1, Acquire, Relaxed) { + Ok(_) => return Weak { ptr: this.ptr }, + Err(old) => cur = old, + } + } + } + + /// Gets the number of [`Weak`][weak] pointers to this value. + /// + /// [weak]: struct.Weak.html + /// + /// # Safety + /// + /// This method by itself is safe, but using it correctly requires extra care. + /// Another thread can change the weak count at any time, + /// including potentially between calling this method and acting on the result. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let five = Arc::new(5); + /// let _weak_five = Arc::downgrade(&five); + /// + /// // This assertion is deterministic because we haven't shared + /// // the `Arc` or `Weak` between threads. + /// assert_eq!(1, Arc::weak_count(&five)); + /// ``` + #[inline] + #[stable(feature = "arc_counts", since = "1.15.0")] + pub fn weak_count(this: &Self) -> usize { + this.inner().weak.load(SeqCst) - 1 + } + + /// Gets the number of strong (`Arc`) pointers to this value. + /// + /// # Safety + /// + /// This method by itself is safe, but using it correctly requires extra care. + /// Another thread can change the strong count at any time, + /// including potentially between calling this method and acting on the result. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let five = Arc::new(5); + /// let _also_five = five.clone(); + /// + /// // This assertion is deterministic because we haven't shared + /// // the `Arc` between threads. + /// assert_eq!(2, Arc::strong_count(&five)); + /// ``` + #[inline] + #[stable(feature = "arc_counts", since = "1.15.0")] + pub fn strong_count(this: &Self) -> usize { + this.inner().strong.load(SeqCst) + } + + #[inline] + fn inner(&self) -> &ArcInner { + // This unsafety is ok because while this arc is alive we're guaranteed + // that the inner pointer is valid. Furthermore, we know that the + // `ArcInner` structure itself is `Sync` because the inner data is + // `Sync` as well, so we're ok loaning out an immutable pointer to these + // contents. + unsafe { &**self.ptr } + } + + // Non-inlined part of `drop`. + #[inline(never)] + unsafe fn drop_slow(&mut self) { + let ptr = self.ptr.as_mut_ptr(); + + // Destroy the data at this time, even though we may not free the box + // allocation itself (there may still be weak pointers lying around). + ptr::drop_in_place(&mut (*ptr).data); + + if self.inner().weak.fetch_sub(1, Release) == 1 { + atomic::fence(Acquire); + deallocate(ptr as *mut u8, size_of_val(&*ptr), align_of_val(&*ptr)) + } + } + + #[inline] + #[stable(feature = "ptr_eq", since = "1.17.0")] + /// Returns true if the two `Arc`s point to the same value (not + /// just values that compare as equal). + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let five = Arc::new(5); + /// let same_five = five.clone(); + /// let other_five = Arc::new(5); + /// + /// assert!(Arc::ptr_eq(&five, &same_five)); + /// assert!(!Arc::ptr_eq(&five, &other_five)); + /// ``` + pub fn ptr_eq(this: &Self, other: &Self) -> bool { + let this_ptr: *const ArcInner = *this.ptr; + let other_ptr: *const ArcInner = *other.ptr; + this_ptr == other_ptr + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for Arc { + /// Makes a clone of the `Arc` pointer. + /// + /// This creates another pointer to the same inner value, increasing the + /// strong reference count. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let five = Arc::new(5); + /// + /// five.clone(); + /// ``` + #[inline] + fn clone(&self) -> Arc { + // Using a relaxed ordering is alright here, as knowledge of the + // original reference prevents other threads from erroneously deleting + // the object. + // + // As explained in the [Boost documentation][1], Increasing the + // reference counter can always be done with memory_order_relaxed: New + // references to an object can only be formed from an existing + // reference, and passing an existing reference from one thread to + // another must already provide any required synchronization. + // + // [1]: (www.boost.org/doc/libs/1_55_0/doc/html/atomic/usage_examples.html) + let old_size = self.inner().strong.fetch_add(1, Relaxed); + + // However we need to guard against massive refcounts in case someone + // is `mem::forget`ing Arcs. If we don't do this the count can overflow + // and users will use-after free. We racily saturate to `isize::MAX` on + // the assumption that there aren't ~2 billion threads incrementing + // the reference count at once. This branch will never be taken in + // any realistic program. + // + // We abort because such a program is incredibly degenerate, and we + // don't care to support it. + if old_size > MAX_REFCOUNT { + unsafe { + abort(); + } + } + + Arc { ptr: self.ptr } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Deref for Arc { + type Target = T; + + #[inline] + fn deref(&self) -> &T { + &self.inner().data + } +} + +impl Arc { + /// Makes a mutable reference into the given `Arc`. + /// + /// If there are other `Arc` or [`Weak`][weak] pointers to the same value, + /// then `make_mut` will invoke [`clone`][clone] on the inner value to + /// ensure unique ownership. This is also referred to as clone-on-write. + /// + /// See also [`get_mut`][get_mut], which will fail rather than cloning. + /// + /// [weak]: struct.Weak.html + /// [clone]: ../../std/clone/trait.Clone.html#tymethod.clone + /// [get_mut]: struct.Arc.html#method.get_mut + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let mut data = Arc::new(5); + /// + /// *Arc::make_mut(&mut data) += 1; // Won't clone anything + /// let mut other_data = data.clone(); // Won't clone inner data + /// *Arc::make_mut(&mut data) += 1; // Clones inner data + /// *Arc::make_mut(&mut data) += 1; // Won't clone anything + /// *Arc::make_mut(&mut other_data) *= 2; // Won't clone anything + /// + /// // Now `data` and `other_data` point to different values. + /// assert_eq!(*data, 8); + /// assert_eq!(*other_data, 12); + /// ``` + #[inline] + #[stable(feature = "arc_unique", since = "1.4.0")] + pub fn make_mut(this: &mut Self) -> &mut T { + // Note that we hold both a strong reference and a weak reference. + // Thus, releasing our strong reference only will not, by itself, cause + // the memory to be deallocated. + // + // Use Acquire to ensure that we see any writes to `weak` that happen + // before release writes (i.e., decrements) to `strong`. Since we hold a + // weak count, there's no chance the ArcInner itself could be + // deallocated. + if this.inner().strong.compare_exchange(1, 0, Acquire, Relaxed).is_err() { + // Another strong pointer exists; clone + *this = Arc::new((**this).clone()); + } else if this.inner().weak.load(Relaxed) != 1 { + // Relaxed suffices in the above because this is fundamentally an + // optimization: we are always racing with weak pointers being + // dropped. Worst case, we end up allocated a new Arc unnecessarily. + + // We removed the last strong ref, but there are additional weak + // refs remaining. We'll move the contents to a new Arc, and + // invalidate the other weak refs. + + // Note that it is not possible for the read of `weak` to yield + // usize::MAX (i.e., locked), since the weak count can only be + // locked by a thread with a strong reference. + + // Materialize our own implicit weak pointer, so that it can clean + // up the ArcInner as needed. + let weak = Weak { ptr: this.ptr }; + + // mark the data itself as already deallocated + unsafe { + // there is no data race in the implicit write caused by `read` + // here (due to zeroing) because data is no longer accessed by + // other threads (due to there being no more strong refs at this + // point). + let mut swap = Arc::new(ptr::read(&(**weak.ptr).data)); + mem::swap(this, &mut swap); + mem::forget(swap); + } + } else { + // We were the sole reference of either kind; bump back up the + // strong ref count. + this.inner().strong.store(1, Release); + } + + // As with `get_mut()`, the unsafety is ok because our reference was + // either unique to begin with, or became one upon cloning the contents. + unsafe { + let inner = &mut *this.ptr.as_mut_ptr(); + &mut inner.data + } + } +} + +impl Arc { + /// Returns a mutable reference to the inner value, if there are + /// no other `Arc` or [`Weak`][weak] pointers to the same value. + /// + /// Returns [`None`][option] otherwise, because it is not safe to + /// mutate a shared value. + /// + /// See also [`make_mut`][make_mut], which will [`clone`][clone] + /// the inner value when it's shared. + /// + /// [weak]: struct.Weak.html + /// [option]: ../../std/option/enum.Option.html + /// [make_mut]: struct.Arc.html#method.make_mut + /// [clone]: ../../std/clone/trait.Clone.html#tymethod.clone + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let mut x = Arc::new(3); + /// *Arc::get_mut(&mut x).unwrap() = 4; + /// assert_eq!(*x, 4); + /// + /// let _y = x.clone(); + /// assert!(Arc::get_mut(&mut x).is_none()); + /// ``` + #[inline] + #[stable(feature = "arc_unique", since = "1.4.0")] + pub fn get_mut(this: &mut Self) -> Option<&mut T> { + if this.is_unique() { + // This unsafety is ok because we're guaranteed that the pointer + // returned is the *only* pointer that will ever be returned to T. Our + // reference count is guaranteed to be 1 at this point, and we required + // the Arc itself to be `mut`, so we're returning the only possible + // reference to the inner data. + unsafe { + let inner = &mut *this.ptr.as_mut_ptr(); + Some(&mut inner.data) + } + } else { + None + } + } + + /// Determine whether this is the unique reference (including weak refs) to + /// the underlying data. + /// + /// Note that this requires locking the weak ref count. + fn is_unique(&mut self) -> bool { + // lock the weak pointer count if we appear to be the sole weak pointer + // holder. + // + // The acquire label here ensures a happens-before relationship with any + // writes to `strong` prior to decrements of the `weak` count (via drop, + // which uses Release). + if self.inner().weak.compare_exchange(1, usize::MAX, Acquire, Relaxed).is_ok() { + // Due to the previous acquire read, this will observe any writes to + // `strong` that were due to upgrading weak pointers; only strong + // clones remain, which require that the strong count is > 1 anyway. + let unique = self.inner().strong.load(Relaxed) == 1; + + // The release write here synchronizes with a read in `downgrade`, + // effectively preventing the above read of `strong` from happening + // after the write. + self.inner().weak.store(1, Release); // release the lock + unique + } else { + false + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +unsafe impl<#[may_dangle] T: ?Sized> Drop for Arc { + /// Drops the `Arc`. + /// + /// This will decrement the strong reference count. If the strong reference + /// count reaches zero then the only other references (if any) are + /// [`Weak`][weak], so we `drop` the inner value. + /// + /// [weak]: struct.Weak.html + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// struct Foo; + /// + /// impl Drop for Foo { + /// fn drop(&mut self) { + /// println!("dropped!"); + /// } + /// } + /// + /// let foo = Arc::new(Foo); + /// let foo2 = foo.clone(); + /// + /// drop(foo); // Doesn't print anything + /// drop(foo2); // Prints "dropped!" + /// ``` + #[inline] + fn drop(&mut self) { + // Because `fetch_sub` is already atomic, we do not need to synchronize + // with other threads unless we are going to delete the object. This + // same logic applies to the below `fetch_sub` to the `weak` count. + if self.inner().strong.fetch_sub(1, Release) != 1 { + return; + } + + // This fence is needed to prevent reordering of use of the data and + // deletion of the data. Because it is marked `Release`, the decreasing + // of the reference count synchronizes with this `Acquire` fence. This + // means that use of the data happens before decreasing the reference + // count, which happens before this fence, which happens before the + // deletion of the data. + // + // As explained in the [Boost documentation][1], + // + // > It is important to enforce any possible access to the object in one + // > thread (through an existing reference) to *happen before* deleting + // > the object in a different thread. This is achieved by a "release" + // > operation after dropping a reference (any access to the object + // > through this reference must obviously happened before), and an + // > "acquire" operation before deleting the object. + // + // [1]: (www.boost.org/doc/libs/1_55_0/doc/html/atomic/usage_examples.html) + atomic::fence(Acquire); + + unsafe { + self.drop_slow(); + } + } +} + +impl Weak { + /// Constructs a new `Weak`, without an accompanying instance of `T`. + /// + /// This allocates memory for `T`, but does not initialize it. Calling + /// [`upgrade`][upgrade] on the return value always gives + /// [`None`][option]. + /// + /// [upgrade]: struct.Weak.html#method.upgrade + /// [option]: ../../std/option/enum.Option.html + /// + /// # Examples + /// + /// ``` + /// use std::sync::Weak; + /// + /// let empty: Weak = Weak::new(); + /// assert!(empty.upgrade().is_none()); + /// ``` + #[stable(feature = "downgraded_weak", since = "1.10.0")] + pub fn new() -> Weak { + unsafe { + Weak { + ptr: Shared::new(Box::into_raw(box ArcInner { + strong: atomic::AtomicUsize::new(0), + weak: atomic::AtomicUsize::new(1), + data: uninitialized(), + })), + } + } + } +} + +impl Weak { + /// Upgrades the `Weak` pointer to an [`Arc`][arc], if possible. + /// + /// Returns [`None`][option] if the strong count has reached zero and the + /// inner value was destroyed. + /// + /// [arc]: struct.Arc.html + /// [option]: ../../std/option/enum.Option.html + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let five = Arc::new(5); + /// + /// let weak_five = Arc::downgrade(&five); + /// + /// let strong_five: Option> = weak_five.upgrade(); + /// assert!(strong_five.is_some()); + /// + /// // Destroy all strong pointers. + /// drop(strong_five); + /// drop(five); + /// + /// assert!(weak_five.upgrade().is_none()); + /// ``` + #[stable(feature = "arc_weak", since = "1.4.0")] + pub fn upgrade(&self) -> Option> { + // We use a CAS loop to increment the strong count instead of a + // fetch_add because once the count hits 0 it must never be above 0. + let inner = self.inner(); + + // Relaxed load because any write of 0 that we can observe + // leaves the field in a permanently zero state (so a + // "stale" read of 0 is fine), and any other value is + // confirmed via the CAS below. + let mut n = inner.strong.load(Relaxed); + + loop { + if n == 0 { + return None; + } + + // See comments in `Arc::clone` for why we do this (for `mem::forget`). + if n > MAX_REFCOUNT { + unsafe { + abort(); + } + } + + // Relaxed is valid for the same reason it is on Arc's Clone impl + match inner.strong.compare_exchange_weak(n, n + 1, Relaxed, Relaxed) { + Ok(_) => return Some(Arc { ptr: self.ptr }), + Err(old) => n = old, + } + } + } + + #[inline] + fn inner(&self) -> &ArcInner { + // See comments above for why this is "safe" + unsafe { &**self.ptr } + } +} + +#[stable(feature = "arc_weak", since = "1.4.0")] +impl Clone for Weak { + /// Makes a clone of the `Weak` pointer. + /// + /// This creates another pointer to the same inner value, increasing the + /// weak reference count. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let weak_five = Arc::downgrade(&Arc::new(5)); + /// + /// weak_five.clone(); + /// ``` + #[inline] + fn clone(&self) -> Weak { + // See comments in Arc::clone() for why this is relaxed. This can use a + // fetch_add (ignoring the lock) because the weak count is only locked + // where are *no other* weak pointers in existence. (So we can't be + // running this code in that case). + let old_size = self.inner().weak.fetch_add(1, Relaxed); + + // See comments in Arc::clone() for why we do this (for mem::forget). + if old_size > MAX_REFCOUNT { + unsafe { + abort(); + } + } + + return Weak { ptr: self.ptr }; + } +} + +#[stable(feature = "downgraded_weak", since = "1.10.0")] +impl Default for Weak { + /// Constructs a new `Weak`, without an accompanying instance of `T`. + /// + /// This allocates memory for `T`, but does not initialize it. Calling + /// [`upgrade`][upgrade] on the return value always gives + /// [`None`][option]. + /// + /// [upgrade]: struct.Weak.html#method.upgrade + /// [option]: ../../std/option/enum.Option.html + /// + /// # Examples + /// + /// ``` + /// use std::sync::Weak; + /// + /// let empty: Weak = Default::default(); + /// assert!(empty.upgrade().is_none()); + /// ``` + fn default() -> Weak { + Weak::new() + } +} + +#[stable(feature = "arc_weak", since = "1.4.0")] +impl Drop for Weak { + /// Drops the `Weak` pointer. + /// + /// This will decrement the weak reference count. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// struct Foo; + /// + /// impl Drop for Foo { + /// fn drop(&mut self) { + /// println!("dropped!"); + /// } + /// } + /// + /// let foo = Arc::new(Foo); + /// let weak_foo = Arc::downgrade(&foo); + /// let other_weak_foo = weak_foo.clone(); + /// + /// drop(weak_foo); // Doesn't print anything + /// drop(foo); // Prints "dropped!" + /// + /// assert!(other_weak_foo.upgrade().is_none()); + /// ``` + fn drop(&mut self) { + let ptr = *self.ptr; + + // If we find out that we were the last weak pointer, then its time to + // deallocate the data entirely. See the discussion in Arc::drop() about + // the memory orderings + // + // It's not necessary to check for the locked state here, because the + // weak count can only be locked if there was precisely one weak ref, + // meaning that drop could only subsequently run ON that remaining weak + // ref, which can only happen after the lock is released. + if self.inner().weak.fetch_sub(1, Release) == 1 { + atomic::fence(Acquire); + unsafe { deallocate(ptr as *mut u8, size_of_val(&*ptr), align_of_val(&*ptr)) } + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialEq for Arc { + /// Equality for two `Arc`s. + /// + /// Two `Arc`s are equal if their inner values are equal. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let five = Arc::new(5); + /// + /// assert!(five == Arc::new(5)); + /// ``` + fn eq(&self, other: &Arc) -> bool { + *(*self) == *(*other) + } + + /// Inequality for two `Arc`s. + /// + /// Two `Arc`s are unequal if their inner values are unequal. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let five = Arc::new(5); + /// + /// assert!(five != Arc::new(6)); + /// ``` + fn ne(&self, other: &Arc) -> bool { + *(*self) != *(*other) + } +} +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialOrd for Arc { + /// Partial comparison for two `Arc`s. + /// + /// The two are compared by calling `partial_cmp()` on their inner values. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// use std::cmp::Ordering; + /// + /// let five = Arc::new(5); + /// + /// assert_eq!(Some(Ordering::Less), five.partial_cmp(&Arc::new(6))); + /// ``` + fn partial_cmp(&self, other: &Arc) -> Option { + (**self).partial_cmp(&**other) + } + + /// Less-than comparison for two `Arc`s. + /// + /// The two are compared by calling `<` on their inner values. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let five = Arc::new(5); + /// + /// assert!(five < Arc::new(6)); + /// ``` + fn lt(&self, other: &Arc) -> bool { + *(*self) < *(*other) + } + + /// 'Less than or equal to' comparison for two `Arc`s. + /// + /// The two are compared by calling `<=` on their inner values. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let five = Arc::new(5); + /// + /// assert!(five <= Arc::new(5)); + /// ``` + fn le(&self, other: &Arc) -> bool { + *(*self) <= *(*other) + } + + /// Greater-than comparison for two `Arc`s. + /// + /// The two are compared by calling `>` on their inner values. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let five = Arc::new(5); + /// + /// assert!(five > Arc::new(4)); + /// ``` + fn gt(&self, other: &Arc) -> bool { + *(*self) > *(*other) + } + + /// 'Greater than or equal to' comparison for two `Arc`s. + /// + /// The two are compared by calling `>=` on their inner values. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let five = Arc::new(5); + /// + /// assert!(five >= Arc::new(5)); + /// ``` + fn ge(&self, other: &Arc) -> bool { + *(*self) >= *(*other) + } +} +#[stable(feature = "rust1", since = "1.0.0")] +impl Ord for Arc { + /// Comparison for two `Arc`s. + /// + /// The two are compared by calling `cmp()` on their inner values. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// use std::cmp::Ordering; + /// + /// let five = Arc::new(5); + /// + /// assert_eq!(Ordering::Less, five.cmp(&Arc::new(6))); + /// ``` + fn cmp(&self, other: &Arc) -> Ordering { + (**self).cmp(&**other) + } +} +#[stable(feature = "rust1", since = "1.0.0")] +impl Eq for Arc {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Display for Arc { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(&**self, f) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for Arc { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(&**self, f) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Pointer for Arc { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Pointer::fmt(&*self.ptr, f) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Default for Arc { + /// Creates a new `Arc`, with the `Default` value for `T`. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// + /// let x: Arc = Default::default(); + /// assert_eq!(*x, 0); + /// ``` + fn default() -> Arc { + Arc::new(Default::default()) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Hash for Arc { + fn hash(&self, state: &mut H) { + (**self).hash(state) + } +} + +#[stable(feature = "from_for_ptrs", since = "1.6.0")] +impl From for Arc { + fn from(t: T) -> Self { + Arc::new(t) + } +} + +#[cfg(test)] +mod tests { + use std::clone::Clone; + use std::sync::mpsc::channel; + use std::mem::drop; + use std::ops::Drop; + use std::option::Option; + use std::option::Option::{None, Some}; + use std::sync::atomic; + use std::sync::atomic::Ordering::{Acquire, SeqCst}; + use std::thread; + use std::vec::Vec; + use super::{Arc, Weak}; + use std::sync::Mutex; + use std::convert::From; + + struct Canary(*mut atomic::AtomicUsize); + + impl Drop for Canary { + fn drop(&mut self) { + unsafe { + match *self { + Canary(c) => { + (*c).fetch_add(1, SeqCst); + } + } + } + } + } + + #[test] + #[cfg_attr(target_os = "emscripten", ignore)] + fn manually_share_arc() { + let v = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + let arc_v = Arc::new(v); + + let (tx, rx) = channel(); + + let _t = thread::spawn(move || { + let arc_v: Arc> = rx.recv().unwrap(); + assert_eq!((*arc_v)[3], 4); + }); + + tx.send(arc_v.clone()).unwrap(); + + assert_eq!((*arc_v)[2], 3); + assert_eq!((*arc_v)[4], 5); + } + + #[test] + fn test_arc_get_mut() { + let mut x = Arc::new(3); + *Arc::get_mut(&mut x).unwrap() = 4; + assert_eq!(*x, 4); + let y = x.clone(); + assert!(Arc::get_mut(&mut x).is_none()); + drop(y); + assert!(Arc::get_mut(&mut x).is_some()); + let _w = Arc::downgrade(&x); + assert!(Arc::get_mut(&mut x).is_none()); + } + + #[test] + fn try_unwrap() { + let x = Arc::new(3); + assert_eq!(Arc::try_unwrap(x), Ok(3)); + let x = Arc::new(4); + let _y = x.clone(); + assert_eq!(Arc::try_unwrap(x), Err(Arc::new(4))); + let x = Arc::new(5); + let _w = Arc::downgrade(&x); + assert_eq!(Arc::try_unwrap(x), Ok(5)); + } + + #[test] + fn into_from_raw() { + let x = Arc::new(box "hello"); + let y = x.clone(); + + let x_ptr = Arc::into_raw(x); + drop(y); + unsafe { + assert_eq!(**x_ptr, "hello"); + + let x = Arc::from_raw(x_ptr); + assert_eq!(**x, "hello"); + + assert_eq!(Arc::try_unwrap(x).map(|x| *x), Ok("hello")); + } + } + + #[test] + fn test_cowarc_clone_make_mut() { + let mut cow0 = Arc::new(75); + let mut cow1 = cow0.clone(); + let mut cow2 = cow1.clone(); + + assert!(75 == *Arc::make_mut(&mut cow0)); + assert!(75 == *Arc::make_mut(&mut cow1)); + assert!(75 == *Arc::make_mut(&mut cow2)); + + *Arc::make_mut(&mut cow0) += 1; + *Arc::make_mut(&mut cow1) += 2; + *Arc::make_mut(&mut cow2) += 3; + + assert!(76 == *cow0); + assert!(77 == *cow1); + assert!(78 == *cow2); + + // none should point to the same backing memory + assert!(*cow0 != *cow1); + assert!(*cow0 != *cow2); + assert!(*cow1 != *cow2); + } + + #[test] + fn test_cowarc_clone_unique2() { + let mut cow0 = Arc::new(75); + let cow1 = cow0.clone(); + let cow2 = cow1.clone(); + + assert!(75 == *cow0); + assert!(75 == *cow1); + assert!(75 == *cow2); + + *Arc::make_mut(&mut cow0) += 1; + assert!(76 == *cow0); + assert!(75 == *cow1); + assert!(75 == *cow2); + + // cow1 and cow2 should share the same contents + // cow0 should have a unique reference + assert!(*cow0 != *cow1); + assert!(*cow0 != *cow2); + assert!(*cow1 == *cow2); + } + + #[test] + fn test_cowarc_clone_weak() { + let mut cow0 = Arc::new(75); + let cow1_weak = Arc::downgrade(&cow0); + + assert!(75 == *cow0); + assert!(75 == *cow1_weak.upgrade().unwrap()); + + *Arc::make_mut(&mut cow0) += 1; + + assert!(76 == *cow0); + assert!(cow1_weak.upgrade().is_none()); + } + + #[test] + fn test_live() { + let x = Arc::new(5); + let y = Arc::downgrade(&x); + assert!(y.upgrade().is_some()); + } + + #[test] + fn test_dead() { + let x = Arc::new(5); + let y = Arc::downgrade(&x); + drop(x); + assert!(y.upgrade().is_none()); + } + + #[test] + fn weak_self_cyclic() { + struct Cycle { + x: Mutex>>, + } + + let a = Arc::new(Cycle { x: Mutex::new(None) }); + let b = Arc::downgrade(&a.clone()); + *a.x.lock().unwrap() = Some(b); + + // hopefully we don't double-free (or leak)... + } + + #[test] + fn drop_arc() { + let mut canary = atomic::AtomicUsize::new(0); + let x = Arc::new(Canary(&mut canary as *mut atomic::AtomicUsize)); + drop(x); + assert!(canary.load(Acquire) == 1); + } + + #[test] + fn drop_arc_weak() { + let mut canary = atomic::AtomicUsize::new(0); + let arc = Arc::new(Canary(&mut canary as *mut atomic::AtomicUsize)); + let arc_weak = Arc::downgrade(&arc); + assert!(canary.load(Acquire) == 0); + drop(arc); + assert!(canary.load(Acquire) == 1); + drop(arc_weak); + } + + #[test] + fn test_strong_count() { + let a = Arc::new(0); + assert!(Arc::strong_count(&a) == 1); + let w = Arc::downgrade(&a); + assert!(Arc::strong_count(&a) == 1); + let b = w.upgrade().expect(""); + assert!(Arc::strong_count(&b) == 2); + assert!(Arc::strong_count(&a) == 2); + drop(w); + drop(a); + assert!(Arc::strong_count(&b) == 1); + let c = b.clone(); + assert!(Arc::strong_count(&b) == 2); + assert!(Arc::strong_count(&c) == 2); + } + + #[test] + fn test_weak_count() { + let a = Arc::new(0); + assert!(Arc::strong_count(&a) == 1); + assert!(Arc::weak_count(&a) == 0); + let w = Arc::downgrade(&a); + assert!(Arc::strong_count(&a) == 1); + assert!(Arc::weak_count(&a) == 1); + let x = w.clone(); + assert!(Arc::weak_count(&a) == 2); + drop(w); + drop(x); + assert!(Arc::strong_count(&a) == 1); + assert!(Arc::weak_count(&a) == 0); + let c = a.clone(); + assert!(Arc::strong_count(&a) == 2); + assert!(Arc::weak_count(&a) == 0); + let d = Arc::downgrade(&c); + assert!(Arc::weak_count(&c) == 1); + assert!(Arc::strong_count(&c) == 2); + + drop(a); + drop(c); + drop(d); + } + + #[test] + fn show_arc() { + let a = Arc::new(5); + assert_eq!(format!("{:?}", a), "5"); + } + + // Make sure deriving works with Arc + #[derive(Eq, Ord, PartialEq, PartialOrd, Clone, Debug, Default)] + struct Foo { + inner: Arc, + } + + #[test] + fn test_unsized() { + let x: Arc<[i32]> = Arc::new([1, 2, 3]); + assert_eq!(format!("{:?}", x), "[1, 2, 3]"); + let y = Arc::downgrade(&x.clone()); + drop(x); + assert!(y.upgrade().is_none()); + } + + #[test] + fn test_from_owned() { + let foo = 123; + let foo_arc = Arc::from(foo); + assert!(123 == *foo_arc); + } + + #[test] + fn test_new_weak() { + let foo: Weak = Weak::new(); + assert!(foo.upgrade().is_none()); + } + + #[test] + fn test_ptr_eq() { + let five = Arc::new(5); + let same_five = five.clone(); + let other_five = Arc::new(5); + + assert!(Arc::ptr_eq(&five, &same_five)); + assert!(!Arc::ptr_eq(&five, &other_five)); + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl borrow::Borrow for Arc { + fn borrow(&self) -> &T { + &**self + } +} + +#[stable(since = "1.5.0", feature = "smart_ptr_as_ref")] +impl AsRef for Arc { + fn as_ref(&self) -> &T { + &**self + } +} From 6d8fc600b88dc2f393d7ff3e57d140891343c988 Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Sun, 30 Apr 2017 11:39:47 -0700 Subject: [PATCH 05/12] Strip down StyleArc to what we need. We remove most of the doc comments to minimize the number of lines of forked code. MozReview-Commit-ID: LehEisKxkJW --- components/style/lib.rs | 2 + components/style/stylearc.rs | 1366 ++++------------------------------ 2 files changed, 141 insertions(+), 1227 deletions(-) diff --git a/components/style/lib.rs b/components/style/lib.rs index 7479279418d..99ded2b9fe8 100644 --- a/components/style/lib.rs +++ b/components/style/lib.rs @@ -70,6 +70,7 @@ extern crate pdqsort; #[cfg(feature = "gecko")] extern crate precomputed_hash; extern crate rayon; extern crate selectors; +#[cfg(feature = "servo")] extern crate serde; #[cfg(feature = "servo")] #[macro_use] extern crate serde_derive; #[cfg(feature = "servo")] #[macro_use] extern crate servo_atoms; #[cfg(feature = "servo")] extern crate servo_config; @@ -118,6 +119,7 @@ pub mod sequential; pub mod sink; pub mod str; pub mod style_adjuster; +pub mod stylearc; pub mod stylesheet_set; pub mod stylesheets; pub mod supports; diff --git a/components/style/stylearc.rs b/components/style/stylearc.rs index 8c0dd6b3795..01885dc481b 100644 --- a/components/style/stylearc.rs +++ b/components/style/stylearc.rs @@ -8,33 +8,51 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![stable(feature = "rust1", since = "1.0.0")] - -//! Thread-safe reference-counting pointers. +//! Fork of Arc for the style system. This has the following advantages over std::Arc: +//! * We don't waste storage on the weak reference count. +//! * We don't do extra RMU operations to handle the possibility of weak references. +//! * We can experiment with arena allocation (todo). +//! * We can add methods to support our custom use cases [1]. //! -//! See the [`Arc`][arc] documentation for more details. -//! -//! [arc]: struct.Arc.html +//! [1] https://bugzilla.mozilla.org/show_bug.cgi?id=1360883 -use boxed::Box; +// The semantics of Arc are alread documented in the Rust docs, so we don't +// duplicate those here. +#![allow(missing_docs)] -use core::sync::atomic; -use core::sync::atomic::Ordering::{Acquire, Relaxed, Release, SeqCst}; -use core::borrow; -use core::fmt; -use core::cmp::Ordering; -use core::mem::{align_of_val, size_of_val}; -use core::intrinsics::abort; -use core::mem; -use core::mem::uninitialized; -use core::ops::Deref; -use core::ops::CoerceUnsized; -use core::ptr::{self, Shared}; -use core::marker::Unsize; -use core::hash::{Hash, Hasher}; -use core::{isize, usize}; -use core::convert::From; -use heap::deallocate; +#[cfg(feature = "servo")] +use heapsize::HeapSizeOf; +#[cfg(feature = "servo")] +use serde::{Deserialize, Serialize}; +use std::{isize, usize}; +use std::borrow; +use std::cmp::Ordering; +use std::convert::From; +use std::fmt; +use std::hash::{Hash, Hasher}; +use std::mem; +use std::ops::Deref; +use std::sync::atomic; +use std::sync::atomic::Ordering::{Acquire, Relaxed, Release}; + +// Private macro to get the offset of a struct field in bytes from the address of the struct. +macro_rules! offset_of { + ($container:path, $field:ident) => {{ + // Make sure the field actually exists. This line ensures that a compile-time error is + // generated if $field is accessed through a Deref impl. + let $container { $field: _, .. }; + + // Create an (invalid) instance of the container and calculate the offset to its + // field. Using a null pointer might be UB if `&(*(0 as *const T)).field` is interpreted to + // be nullptr deref. + let invalid: $container = ::std::mem::uninitialized(); + let offset = &invalid.$field as *const _ as usize - &invalid as *const _ as usize; + + // Do not run destructors on the made up invalid instance. + ::std::mem::forget(invalid); + offset as isize + }}; +} /// A soft limit on the amount of references that may be made to an `Arc`. /// @@ -42,169 +60,22 @@ use heap::deallocate; /// necessarily) at _exactly_ `MAX_REFCOUNT + 1` references. const MAX_REFCOUNT: usize = (isize::MAX) as usize; -/// A thread-safe reference-counting pointer. -/// -/// The type `Arc` provides shared ownership of a value of type `T`, -/// allocated in the heap. Invoking [`clone`][clone] on `Arc` produces -/// a new pointer to the same value in the heap. When the last `Arc` -/// pointer to a given value is destroyed, the pointed-to value is -/// also destroyed. -/// -/// Shared references in Rust disallow mutation by default, and `Arc` is no -/// exception. If you need to mutate through an `Arc`, use [`Mutex`][mutex], -/// [`RwLock`][rwlock], or one of the [`Atomic`][atomic] types. -/// -/// `Arc` uses atomic operations for reference counting, so `Arc`s can be -/// sent between threads. In other words, `Arc` implements [`Send`] -/// as long as `T` implements [`Send`] and [`Sync`][sync]. The disadvantage is -/// that atomic operations are more expensive than ordinary memory accesses. -/// If you are not sharing reference-counted values between threads, consider -/// using [`rc::Rc`][`Rc`] for lower overhead. [`Rc`] is a safe default, because -/// the compiler will catch any attempt to send an [`Rc`] between threads. -/// However, a library might choose `Arc` in order to give library consumers -/// more flexibility. -/// -/// The [`downgrade`][downgrade] method can be used to create a non-owning -/// [`Weak`][weak] pointer. A [`Weak`][weak] pointer can be [`upgrade`][upgrade]d -/// to an `Arc`, but this will return [`None`] if the value has already been -/// dropped. -/// -/// A cycle between `Arc` pointers will never be deallocated. For this reason, -/// [`Weak`][weak] is used to break cycles. For example, a tree could have -/// strong `Arc` pointers from parent nodes to children, and [`Weak`][weak] -/// pointers from children back to their parents. -/// -/// `Arc` automatically dereferences to `T` (via the [`Deref`][deref] trait), -/// so you can call `T`'s methods on a value of type `Arc`. To avoid name -/// clashes with `T`'s methods, the methods of `Arc` itself are [associated -/// functions][assoc], called using function-like syntax: -/// -/// ``` -/// use std::sync::Arc; -/// let my_arc = Arc::new(()); -/// -/// Arc::downgrade(&my_arc); -/// ``` -/// -/// [`Weak`][weak] does not auto-dereference to `T`, because the value may have -/// already been destroyed. -/// -/// [arc]: struct.Arc.html -/// [weak]: struct.Weak.html -/// [`Rc`]: ../../std/rc/struct.Rc.html -/// [clone]: ../../std/clone/trait.Clone.html#tymethod.clone -/// [mutex]: ../../std/sync/struct.Mutex.html -/// [rwlock]: ../../std/sync/struct.RwLock.html -/// [atomic]: ../../std/sync/atomic/ -/// [`Send`]: ../../std/marker/trait.Send.html -/// [sync]: ../../std/marker/trait.Sync.html -/// [deref]: ../../std/ops/trait.Deref.html -/// [downgrade]: struct.Arc.html#method.downgrade -/// [upgrade]: struct.Weak.html#method.upgrade -/// [`None`]: ../../std/option/enum.Option.html#variant.None -/// [assoc]: ../../book/method-syntax.html#associated-functions -/// -/// # Examples -/// -/// Sharing some immutable data between threads: -/// -// Note that we **do not** run these tests here. The windows builders get super -// unhappy if a thread outlives the main thread and then exits at the same time -// (something deadlocks) so we just avoid this entirely by not running these -// tests. -/// ```no_run -/// use std::sync::Arc; -/// use std::thread; -/// -/// let five = Arc::new(5); -/// -/// for _ in 0..10 { -/// let five = five.clone(); -/// -/// thread::spawn(move || { -/// println!("{:?}", five); -/// }); -/// } -/// ``` -/// -/// Sharing a mutable [`AtomicUsize`]: -/// -/// [`AtomicUsize`]: ../../std/sync/atomic/struct.AtomicUsize.html -/// -/// ```no_run -/// use std::sync::Arc; -/// use std::sync::atomic::{AtomicUsize, Ordering}; -/// use std::thread; -/// -/// let val = Arc::new(AtomicUsize::new(5)); -/// -/// for _ in 0..10 { -/// let val = val.clone(); -/// -/// thread::spawn(move || { -/// let v = val.fetch_add(1, Ordering::SeqCst); -/// println!("{:?}", v); -/// }); -/// } -/// ``` -/// -/// See the [`rc` documentation][rc_examples] for more examples of reference -/// counting in general. -/// -/// [rc_examples]: ../../std/rc/#examples -#[stable(feature = "rust1", since = "1.0.0")] pub struct Arc { - ptr: Shared>, + // FIXME(bholley): When NonZero/Shared/Unique are stabilized, we should use + // Shared here to get the NonZero optimization. Gankro is working on this. + // + // If we need a compact Option> beforehand, we can make a helper + // class that wraps the result of Arc::into_raw. + // + // https://github.com/rust-lang/rust/issues/27730 + ptr: *mut ArcInner, } -#[stable(feature = "rust1", since = "1.0.0")] unsafe impl Send for Arc {} -#[stable(feature = "rust1", since = "1.0.0")] unsafe impl Sync for Arc {} -#[unstable(feature = "coerce_unsized", issue = "27732")] -impl, U: ?Sized> CoerceUnsized> for Arc {} - -/// A weak version of [`Arc`][arc]. -/// -/// `Weak` pointers do not count towards determining if the inner value -/// should be dropped. -/// -/// The typical way to obtain a `Weak` pointer is to call -/// [`Arc::downgrade`][downgrade]. -/// -/// See the [`Arc`][arc] documentation for more details. -/// -/// [arc]: struct.Arc.html -/// [downgrade]: struct.Arc.html#method.downgrade -#[stable(feature = "arc_weak", since = "1.4.0")] -pub struct Weak { - ptr: Shared>, -} - -#[stable(feature = "arc_weak", since = "1.4.0")] -unsafe impl Send for Weak {} -#[stable(feature = "arc_weak", since = "1.4.0")] -unsafe impl Sync for Weak {} - -#[unstable(feature = "coerce_unsized", issue = "27732")] -impl, U: ?Sized> CoerceUnsized> for Weak {} - -#[stable(feature = "arc_weak", since = "1.4.0")] -impl fmt::Debug for Weak { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "(Weak)") - } -} - struct ArcInner { - strong: atomic::AtomicUsize, - - // the value usize::MAX acts as a sentinel for temporarily "locking" the - // ability to upgrade weak pointers or downgrade strong ones; this is used - // to avoid races in `make_mut` and `get_mut`. - weak: atomic::AtomicUsize, - + count: atomic::AtomicUsize, data: T, } @@ -212,228 +83,32 @@ unsafe impl Send for ArcInner {} unsafe impl Sync for ArcInner {} impl Arc { - /// Constructs a new `Arc`. - /// - /// # Examples - /// - /// ``` - /// use std::sync::Arc; - /// - /// let five = Arc::new(5); - /// ``` #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn new(data: T) -> Arc { - // Start the weak pointer count as 1 which is the weak pointer that's - // held by all the strong pointers (kinda), see std/rc.rs for more info - let x: Box<_> = box ArcInner { - strong: atomic::AtomicUsize::new(1), - weak: atomic::AtomicUsize::new(1), + pub fn new(data: T) -> Self { + let x = Box::new(ArcInner { + count: atomic::AtomicUsize::new(1), data: data, - }; - Arc { ptr: unsafe { Shared::new(Box::into_raw(x)) } } + }); + Arc { ptr: Box::into_raw(x) } } - /// Returns the contained value, if the `Arc` has exactly one strong reference. - /// - /// Otherwise, an [`Err`][result] is returned with the same `Arc` that was - /// passed in. - /// - /// This will succeed even if there are outstanding weak references. - /// - /// [result]: ../../std/result/enum.Result.html - /// - /// # Examples - /// - /// ``` - /// use std::sync::Arc; - /// - /// let x = Arc::new(3); - /// assert_eq!(Arc::try_unwrap(x), Ok(3)); - /// - /// let x = Arc::new(4); - /// let _y = x.clone(); - /// assert_eq!(*Arc::try_unwrap(x).unwrap_err(), 4); - /// ``` - #[inline] - #[stable(feature = "arc_unique", since = "1.4.0")] - pub fn try_unwrap(this: Self) -> Result { - // See `drop` for why all these atomics are like this - if this.inner().strong.compare_exchange(1, 0, Release, Relaxed).is_err() { - return Err(this); - } - - atomic::fence(Acquire); - - unsafe { - let ptr = *this.ptr; - let elem = ptr::read(&(*ptr).data); - - // Make a weak pointer to clean up the implicit strong-weak reference - let _weak = Weak { ptr: this.ptr }; - mem::forget(this); - - Ok(elem) - } - } - - /// Consumes the `Arc`, returning the wrapped pointer. - /// - /// To avoid a memory leak the pointer must be converted back to an `Arc` using - /// [`Arc::from_raw`][from_raw]. - /// - /// [from_raw]: struct.Arc.html#method.from_raw - /// - /// # Examples - /// - /// ``` - /// use std::sync::Arc; - /// - /// let x = Arc::new(10); - /// let x_ptr = Arc::into_raw(x); - /// assert_eq!(unsafe { *x_ptr }, 10); - /// ``` - #[stable(feature = "rc_raw", since = "1.17.0")] pub fn into_raw(this: Self) -> *const T { - let ptr = unsafe { &(**this.ptr).data as *const _ }; + let ptr = unsafe { &((*this.ptr).data) as *const _ }; mem::forget(this); ptr } - /// Constructs an `Arc` from a raw pointer. - /// - /// The raw pointer must have been previously returned by a call to a - /// [`Arc::into_raw`][into_raw]. - /// - /// This function is unsafe because improper use may lead to memory problems. For example, a - /// double-free may occur if the function is called twice on the same raw pointer. - /// - /// [into_raw]: struct.Arc.html#method.into_raw - /// - /// # Examples - /// - /// ``` - /// use std::sync::Arc; - /// - /// let x = Arc::new(10); - /// let x_ptr = Arc::into_raw(x); - /// - /// unsafe { - /// // Convert back to an `Arc` to prevent leak. - /// let x = Arc::from_raw(x_ptr); - /// assert_eq!(*x, 10); - /// - /// // Further calls to `Arc::from_raw(x_ptr)` would be memory unsafe. - /// } - /// - /// // The memory was freed when `x` went out of scope above, so `x_ptr` is now dangling! - /// ``` - #[stable(feature = "rc_raw", since = "1.17.0")] pub unsafe fn from_raw(ptr: *const T) -> Self { - // To find the corresponding pointer to the `ArcInner` we need to subtract the offset of the - // `data` field from the pointer. + // To find the corresponding pointer to the `ArcInner` we need + // to subtract the offset of the `data` field from the pointer. let ptr = (ptr as *const u8).offset(-offset_of!(ArcInner, data)); Arc { - ptr: Shared::new(ptr as *const _), + ptr: ptr as *mut ArcInner, } } } impl Arc { - /// Creates a new [`Weak`][weak] pointer to this value. - /// - /// [weak]: struct.Weak.html - /// - /// # Examples - /// - /// ``` - /// use std::sync::Arc; - /// - /// let five = Arc::new(5); - /// - /// let weak_five = Arc::downgrade(&five); - /// ``` - #[stable(feature = "arc_weak", since = "1.4.0")] - pub fn downgrade(this: &Self) -> Weak { - // This Relaxed is OK because we're checking the value in the CAS - // below. - let mut cur = this.inner().weak.load(Relaxed); - - loop { - // check if the weak counter is currently "locked"; if so, spin. - if cur == usize::MAX { - cur = this.inner().weak.load(Relaxed); - continue; - } - - // NOTE: this code currently ignores the possibility of overflow - // into usize::MAX; in general both Rc and Arc need to be adjusted - // to deal with overflow. - - // Unlike with Clone(), we need this to be an Acquire read to - // synchronize with the write coming from `is_unique`, so that the - // events prior to that write happen before this read. - match this.inner().weak.compare_exchange_weak(cur, cur + 1, Acquire, Relaxed) { - Ok(_) => return Weak { ptr: this.ptr }, - Err(old) => cur = old, - } - } - } - - /// Gets the number of [`Weak`][weak] pointers to this value. - /// - /// [weak]: struct.Weak.html - /// - /// # Safety - /// - /// This method by itself is safe, but using it correctly requires extra care. - /// Another thread can change the weak count at any time, - /// including potentially between calling this method and acting on the result. - /// - /// # Examples - /// - /// ``` - /// use std::sync::Arc; - /// - /// let five = Arc::new(5); - /// let _weak_five = Arc::downgrade(&five); - /// - /// // This assertion is deterministic because we haven't shared - /// // the `Arc` or `Weak` between threads. - /// assert_eq!(1, Arc::weak_count(&five)); - /// ``` - #[inline] - #[stable(feature = "arc_counts", since = "1.15.0")] - pub fn weak_count(this: &Self) -> usize { - this.inner().weak.load(SeqCst) - 1 - } - - /// Gets the number of strong (`Arc`) pointers to this value. - /// - /// # Safety - /// - /// This method by itself is safe, but using it correctly requires extra care. - /// Another thread can change the strong count at any time, - /// including potentially between calling this method and acting on the result. - /// - /// # Examples - /// - /// ``` - /// use std::sync::Arc; - /// - /// let five = Arc::new(5); - /// let _also_five = five.clone(); - /// - /// // This assertion is deterministic because we haven't shared - /// // the `Arc` between threads. - /// assert_eq!(2, Arc::strong_count(&five)); - /// ``` - #[inline] - #[stable(feature = "arc_counts", since = "1.15.0")] - pub fn strong_count(this: &Self) -> usize { - this.inner().strong.load(SeqCst) - } - #[inline] fn inner(&self) -> &ArcInner { // This unsafety is ok because while this arc is alive we're guaranteed @@ -441,66 +116,25 @@ impl Arc { // `ArcInner` structure itself is `Sync` because the inner data is // `Sync` as well, so we're ok loaning out an immutable pointer to these // contents. - unsafe { &**self.ptr } + unsafe { &*self.ptr } } - // Non-inlined part of `drop`. + // Non-inlined part of `drop`. Just invokes the destructor. #[inline(never)] unsafe fn drop_slow(&mut self) { - let ptr = self.ptr.as_mut_ptr(); - - // Destroy the data at this time, even though we may not free the box - // allocation itself (there may still be weak pointers lying around). - ptr::drop_in_place(&mut (*ptr).data); - - if self.inner().weak.fetch_sub(1, Release) == 1 { - atomic::fence(Acquire); - deallocate(ptr as *mut u8, size_of_val(&*ptr), align_of_val(&*ptr)) - } + let _ = Box::from_raw(self.ptr); } + #[inline] - #[stable(feature = "ptr_eq", since = "1.17.0")] - /// Returns true if the two `Arc`s point to the same value (not - /// just values that compare as equal). - /// - /// # Examples - /// - /// ``` - /// use std::sync::Arc; - /// - /// let five = Arc::new(5); - /// let same_five = five.clone(); - /// let other_five = Arc::new(5); - /// - /// assert!(Arc::ptr_eq(&five, &same_five)); - /// assert!(!Arc::ptr_eq(&five, &other_five)); - /// ``` pub fn ptr_eq(this: &Self, other: &Self) -> bool { - let this_ptr: *const ArcInner = *this.ptr; - let other_ptr: *const ArcInner = *other.ptr; - this_ptr == other_ptr + this.ptr == other.ptr } } -#[stable(feature = "rust1", since = "1.0.0")] impl Clone for Arc { - /// Makes a clone of the `Arc` pointer. - /// - /// This creates another pointer to the same inner value, increasing the - /// strong reference count. - /// - /// # Examples - /// - /// ``` - /// use std::sync::Arc; - /// - /// let five = Arc::new(5); - /// - /// five.clone(); - /// ``` #[inline] - fn clone(&self) -> Arc { + fn clone(&self) -> Self { // Using a relaxed ordering is alright here, as knowledge of the // original reference prevents other threads from erroneously deleting // the object. @@ -512,7 +146,7 @@ impl Clone for Arc { // another must already provide any required synchronization. // // [1]: (www.boost.org/doc/libs/1_55_0/doc/html/atomic/usage_examples.html) - let old_size = self.inner().strong.fetch_add(1, Relaxed); + let old_size = self.inner().count.fetch_add(1, Relaxed); // However we need to guard against massive refcounts in case someone // is `mem::forget`ing Arcs. If we don't do this the count can overflow @@ -524,16 +158,19 @@ impl Clone for Arc { // We abort because such a program is incredibly degenerate, and we // don't care to support it. if old_size > MAX_REFCOUNT { - unsafe { - abort(); - } + // Note: std::process::abort is stable in 1.17, which we don't yet + // require for Gecko. Panic is good enough in practice here (it will + // trigger an abort at least in Gecko, and this case is degenerate + // enough that Servo shouldn't have code that triggers it). + // + // We should fix this when we require 1.17. + panic!(); } Arc { ptr: self.ptr } } } -#[stable(feature = "rust1", since = "1.0.0")] impl Deref for Arc { type Target = T; @@ -544,207 +181,67 @@ impl Deref for Arc { } impl Arc { - /// Makes a mutable reference into the given `Arc`. - /// - /// If there are other `Arc` or [`Weak`][weak] pointers to the same value, - /// then `make_mut` will invoke [`clone`][clone] on the inner value to - /// ensure unique ownership. This is also referred to as clone-on-write. - /// - /// See also [`get_mut`][get_mut], which will fail rather than cloning. - /// - /// [weak]: struct.Weak.html - /// [clone]: ../../std/clone/trait.Clone.html#tymethod.clone - /// [get_mut]: struct.Arc.html#method.get_mut - /// - /// # Examples - /// - /// ``` - /// use std::sync::Arc; - /// - /// let mut data = Arc::new(5); - /// - /// *Arc::make_mut(&mut data) += 1; // Won't clone anything - /// let mut other_data = data.clone(); // Won't clone inner data - /// *Arc::make_mut(&mut data) += 1; // Clones inner data - /// *Arc::make_mut(&mut data) += 1; // Won't clone anything - /// *Arc::make_mut(&mut other_data) *= 2; // Won't clone anything - /// - /// // Now `data` and `other_data` point to different values. - /// assert_eq!(*data, 8); - /// assert_eq!(*other_data, 12); - /// ``` #[inline] - #[stable(feature = "arc_unique", since = "1.4.0")] pub fn make_mut(this: &mut Self) -> &mut T { - // Note that we hold both a strong reference and a weak reference. - // Thus, releasing our strong reference only will not, by itself, cause - // the memory to be deallocated. - // - // Use Acquire to ensure that we see any writes to `weak` that happen - // before release writes (i.e., decrements) to `strong`. Since we hold a - // weak count, there's no chance the ArcInner itself could be - // deallocated. - if this.inner().strong.compare_exchange(1, 0, Acquire, Relaxed).is_err() { - // Another strong pointer exists; clone + if !this.is_unique() { + // Another pointer exists; clone *this = Arc::new((**this).clone()); - } else if this.inner().weak.load(Relaxed) != 1 { - // Relaxed suffices in the above because this is fundamentally an - // optimization: we are always racing with weak pointers being - // dropped. Worst case, we end up allocated a new Arc unnecessarily. - - // We removed the last strong ref, but there are additional weak - // refs remaining. We'll move the contents to a new Arc, and - // invalidate the other weak refs. - - // Note that it is not possible for the read of `weak` to yield - // usize::MAX (i.e., locked), since the weak count can only be - // locked by a thread with a strong reference. - - // Materialize our own implicit weak pointer, so that it can clean - // up the ArcInner as needed. - let weak = Weak { ptr: this.ptr }; - - // mark the data itself as already deallocated - unsafe { - // there is no data race in the implicit write caused by `read` - // here (due to zeroing) because data is no longer accessed by - // other threads (due to there being no more strong refs at this - // point). - let mut swap = Arc::new(ptr::read(&(**weak.ptr).data)); - mem::swap(this, &mut swap); - mem::forget(swap); - } - } else { - // We were the sole reference of either kind; bump back up the - // strong ref count. - this.inner().strong.store(1, Release); } - // As with `get_mut()`, the unsafety is ok because our reference was - // either unique to begin with, or became one upon cloning the contents. unsafe { - let inner = &mut *this.ptr.as_mut_ptr(); - &mut inner.data - } - } -} - -impl Arc { - /// Returns a mutable reference to the inner value, if there are - /// no other `Arc` or [`Weak`][weak] pointers to the same value. - /// - /// Returns [`None`][option] otherwise, because it is not safe to - /// mutate a shared value. - /// - /// See also [`make_mut`][make_mut], which will [`clone`][clone] - /// the inner value when it's shared. - /// - /// [weak]: struct.Weak.html - /// [option]: ../../std/option/enum.Option.html - /// [make_mut]: struct.Arc.html#method.make_mut - /// [clone]: ../../std/clone/trait.Clone.html#tymethod.clone - /// - /// # Examples - /// - /// ``` - /// use std::sync::Arc; - /// - /// let mut x = Arc::new(3); - /// *Arc::get_mut(&mut x).unwrap() = 4; - /// assert_eq!(*x, 4); - /// - /// let _y = x.clone(); - /// assert!(Arc::get_mut(&mut x).is_none()); - /// ``` - #[inline] - #[stable(feature = "arc_unique", since = "1.4.0")] - pub fn get_mut(this: &mut Self) -> Option<&mut T> { - if this.is_unique() { // This unsafety is ok because we're guaranteed that the pointer // returned is the *only* pointer that will ever be returned to T. Our // reference count is guaranteed to be 1 at this point, and we required // the Arc itself to be `mut`, so we're returning the only possible // reference to the inner data. + &mut (*this.ptr).data + } + } +} + +impl Arc { + #[inline] + pub fn get_mut(this: &mut Self) -> Option<&mut T> { + if this.is_unique() { unsafe { - let inner = &mut *this.ptr.as_mut_ptr(); - Some(&mut inner.data) + // See make_mut() for documentation of the threadsafety here. + Some(&mut (*this.ptr).data) } } else { None } } - /// Determine whether this is the unique reference (including weak refs) to - /// the underlying data. - /// - /// Note that this requires locking the weak ref count. - fn is_unique(&mut self) -> bool { - // lock the weak pointer count if we appear to be the sole weak pointer - // holder. + #[inline] + fn is_unique(&self) -> bool { + // We can use Relaxed here, but the justification is a bit subtle. // - // The acquire label here ensures a happens-before relationship with any - // writes to `strong` prior to decrements of the `weak` count (via drop, - // which uses Release). - if self.inner().weak.compare_exchange(1, usize::MAX, Acquire, Relaxed).is_ok() { - // Due to the previous acquire read, this will observe any writes to - // `strong` that were due to upgrading weak pointers; only strong - // clones remain, which require that the strong count is > 1 anyway. - let unique = self.inner().strong.load(Relaxed) == 1; - - // The release write here synchronizes with a read in `downgrade`, - // effectively preventing the above read of `strong` from happening - // after the write. - self.inner().weak.store(1, Release); // release the lock - unique - } else { - false - } + // The reason to use Acquire would be to synchronize with other threads + // that are modifying the refcount with Release, i.e. to ensure that + // their writes to memory guarded by this refcount are flushed. However, + // we know that threads only modify the contents of the Arc when they + // observe the refcount to be 1, and no other thread could observe that + // because we're holding one strong reference here. + self.inner().count.load(Relaxed) == 1 } } -#[stable(feature = "rust1", since = "1.0.0")] -unsafe impl<#[may_dangle] T: ?Sized> Drop for Arc { - /// Drops the `Arc`. - /// - /// This will decrement the strong reference count. If the strong reference - /// count reaches zero then the only other references (if any) are - /// [`Weak`][weak], so we `drop` the inner value. - /// - /// [weak]: struct.Weak.html - /// - /// # Examples - /// - /// ``` - /// use std::sync::Arc; - /// - /// struct Foo; - /// - /// impl Drop for Foo { - /// fn drop(&mut self) { - /// println!("dropped!"); - /// } - /// } - /// - /// let foo = Arc::new(Foo); - /// let foo2 = foo.clone(); - /// - /// drop(foo); // Doesn't print anything - /// drop(foo2); // Prints "dropped!" - /// ``` +impl Drop for Arc { #[inline] fn drop(&mut self) { // Because `fetch_sub` is already atomic, we do not need to synchronize - // with other threads unless we are going to delete the object. This - // same logic applies to the below `fetch_sub` to the `weak` count. - if self.inner().strong.fetch_sub(1, Release) != 1 { + // with other threads unless we are going to delete the object. + if self.inner().count.fetch_sub(1, Release) != 1 { return; } - // This fence is needed to prevent reordering of use of the data and + // FIXME(bholley): Use the updated comment when [2] is merged. + // + // This load is needed to prevent reordering of use of the data and // deletion of the data. Because it is marked `Release`, the decreasing - // of the reference count synchronizes with this `Acquire` fence. This + // of the reference count synchronizes with this `Acquire` load. This // means that use of the data happens before decreasing the reference - // count, which happens before this fence, which happens before the + // count, which happens before this load, which happens before the // deletion of the data. // // As explained in the [Boost documentation][1], @@ -757,7 +254,8 @@ unsafe impl<#[may_dangle] T: ?Sized> Drop for Arc { // > "acquire" operation before deleting the object. // // [1]: (www.boost.org/doc/libs/1_55_0/doc/html/atomic/usage_examples.html) - atomic::fence(Acquire); + // [2]: https://github.com/rust-lang/rust/pull/41714 + self.inner().count.load(Acquire); unsafe { self.drop_slow(); @@ -765,704 +263,118 @@ unsafe impl<#[may_dangle] T: ?Sized> Drop for Arc { } } -impl Weak { - /// Constructs a new `Weak`, without an accompanying instance of `T`. - /// - /// This allocates memory for `T`, but does not initialize it. Calling - /// [`upgrade`][upgrade] on the return value always gives - /// [`None`][option]. - /// - /// [upgrade]: struct.Weak.html#method.upgrade - /// [option]: ../../std/option/enum.Option.html - /// - /// # Examples - /// - /// ``` - /// use std::sync::Weak; - /// - /// let empty: Weak = Weak::new(); - /// assert!(empty.upgrade().is_none()); - /// ``` - #[stable(feature = "downgraded_weak", since = "1.10.0")] - pub fn new() -> Weak { - unsafe { - Weak { - ptr: Shared::new(Box::into_raw(box ArcInner { - strong: atomic::AtomicUsize::new(0), - weak: atomic::AtomicUsize::new(1), - data: uninitialized(), - })), - } - } - } -} - -impl Weak { - /// Upgrades the `Weak` pointer to an [`Arc`][arc], if possible. - /// - /// Returns [`None`][option] if the strong count has reached zero and the - /// inner value was destroyed. - /// - /// [arc]: struct.Arc.html - /// [option]: ../../std/option/enum.Option.html - /// - /// # Examples - /// - /// ``` - /// use std::sync::Arc; - /// - /// let five = Arc::new(5); - /// - /// let weak_five = Arc::downgrade(&five); - /// - /// let strong_five: Option> = weak_five.upgrade(); - /// assert!(strong_five.is_some()); - /// - /// // Destroy all strong pointers. - /// drop(strong_five); - /// drop(five); - /// - /// assert!(weak_five.upgrade().is_none()); - /// ``` - #[stable(feature = "arc_weak", since = "1.4.0")] - pub fn upgrade(&self) -> Option> { - // We use a CAS loop to increment the strong count instead of a - // fetch_add because once the count hits 0 it must never be above 0. - let inner = self.inner(); - - // Relaxed load because any write of 0 that we can observe - // leaves the field in a permanently zero state (so a - // "stale" read of 0 is fine), and any other value is - // confirmed via the CAS below. - let mut n = inner.strong.load(Relaxed); - - loop { - if n == 0 { - return None; - } - - // See comments in `Arc::clone` for why we do this (for `mem::forget`). - if n > MAX_REFCOUNT { - unsafe { - abort(); - } - } - - // Relaxed is valid for the same reason it is on Arc's Clone impl - match inner.strong.compare_exchange_weak(n, n + 1, Relaxed, Relaxed) { - Ok(_) => return Some(Arc { ptr: self.ptr }), - Err(old) => n = old, - } - } - } - - #[inline] - fn inner(&self) -> &ArcInner { - // See comments above for why this is "safe" - unsafe { &**self.ptr } - } -} - -#[stable(feature = "arc_weak", since = "1.4.0")] -impl Clone for Weak { - /// Makes a clone of the `Weak` pointer. - /// - /// This creates another pointer to the same inner value, increasing the - /// weak reference count. - /// - /// # Examples - /// - /// ``` - /// use std::sync::Arc; - /// - /// let weak_five = Arc::downgrade(&Arc::new(5)); - /// - /// weak_five.clone(); - /// ``` - #[inline] - fn clone(&self) -> Weak { - // See comments in Arc::clone() for why this is relaxed. This can use a - // fetch_add (ignoring the lock) because the weak count is only locked - // where are *no other* weak pointers in existence. (So we can't be - // running this code in that case). - let old_size = self.inner().weak.fetch_add(1, Relaxed); - - // See comments in Arc::clone() for why we do this (for mem::forget). - if old_size > MAX_REFCOUNT { - unsafe { - abort(); - } - } - - return Weak { ptr: self.ptr }; - } -} - -#[stable(feature = "downgraded_weak", since = "1.10.0")] -impl Default for Weak { - /// Constructs a new `Weak`, without an accompanying instance of `T`. - /// - /// This allocates memory for `T`, but does not initialize it. Calling - /// [`upgrade`][upgrade] on the return value always gives - /// [`None`][option]. - /// - /// [upgrade]: struct.Weak.html#method.upgrade - /// [option]: ../../std/option/enum.Option.html - /// - /// # Examples - /// - /// ``` - /// use std::sync::Weak; - /// - /// let empty: Weak = Default::default(); - /// assert!(empty.upgrade().is_none()); - /// ``` - fn default() -> Weak { - Weak::new() - } -} - -#[stable(feature = "arc_weak", since = "1.4.0")] -impl Drop for Weak { - /// Drops the `Weak` pointer. - /// - /// This will decrement the weak reference count. - /// - /// # Examples - /// - /// ``` - /// use std::sync::Arc; - /// - /// struct Foo; - /// - /// impl Drop for Foo { - /// fn drop(&mut self) { - /// println!("dropped!"); - /// } - /// } - /// - /// let foo = Arc::new(Foo); - /// let weak_foo = Arc::downgrade(&foo); - /// let other_weak_foo = weak_foo.clone(); - /// - /// drop(weak_foo); // Doesn't print anything - /// drop(foo); // Prints "dropped!" - /// - /// assert!(other_weak_foo.upgrade().is_none()); - /// ``` - fn drop(&mut self) { - let ptr = *self.ptr; - - // If we find out that we were the last weak pointer, then its time to - // deallocate the data entirely. See the discussion in Arc::drop() about - // the memory orderings - // - // It's not necessary to check for the locked state here, because the - // weak count can only be locked if there was precisely one weak ref, - // meaning that drop could only subsequently run ON that remaining weak - // ref, which can only happen after the lock is released. - if self.inner().weak.fetch_sub(1, Release) == 1 { - atomic::fence(Acquire); - unsafe { deallocate(ptr as *mut u8, size_of_val(&*ptr), align_of_val(&*ptr)) } - } - } -} - -#[stable(feature = "rust1", since = "1.0.0")] impl PartialEq for Arc { - /// Equality for two `Arc`s. - /// - /// Two `Arc`s are equal if their inner values are equal. - /// - /// # Examples - /// - /// ``` - /// use std::sync::Arc; - /// - /// let five = Arc::new(5); - /// - /// assert!(five == Arc::new(5)); - /// ``` fn eq(&self, other: &Arc) -> bool { *(*self) == *(*other) } - /// Inequality for two `Arc`s. - /// - /// Two `Arc`s are unequal if their inner values are unequal. - /// - /// # Examples - /// - /// ``` - /// use std::sync::Arc; - /// - /// let five = Arc::new(5); - /// - /// assert!(five != Arc::new(6)); - /// ``` fn ne(&self, other: &Arc) -> bool { *(*self) != *(*other) } } -#[stable(feature = "rust1", since = "1.0.0")] impl PartialOrd for Arc { - /// Partial comparison for two `Arc`s. - /// - /// The two are compared by calling `partial_cmp()` on their inner values. - /// - /// # Examples - /// - /// ``` - /// use std::sync::Arc; - /// use std::cmp::Ordering; - /// - /// let five = Arc::new(5); - /// - /// assert_eq!(Some(Ordering::Less), five.partial_cmp(&Arc::new(6))); - /// ``` fn partial_cmp(&self, other: &Arc) -> Option { (**self).partial_cmp(&**other) } - /// Less-than comparison for two `Arc`s. - /// - /// The two are compared by calling `<` on their inner values. - /// - /// # Examples - /// - /// ``` - /// use std::sync::Arc; - /// - /// let five = Arc::new(5); - /// - /// assert!(five < Arc::new(6)); - /// ``` fn lt(&self, other: &Arc) -> bool { *(*self) < *(*other) } - /// 'Less than or equal to' comparison for two `Arc`s. - /// - /// The two are compared by calling `<=` on their inner values. - /// - /// # Examples - /// - /// ``` - /// use std::sync::Arc; - /// - /// let five = Arc::new(5); - /// - /// assert!(five <= Arc::new(5)); - /// ``` fn le(&self, other: &Arc) -> bool { *(*self) <= *(*other) } - /// Greater-than comparison for two `Arc`s. - /// - /// The two are compared by calling `>` on their inner values. - /// - /// # Examples - /// - /// ``` - /// use std::sync::Arc; - /// - /// let five = Arc::new(5); - /// - /// assert!(five > Arc::new(4)); - /// ``` fn gt(&self, other: &Arc) -> bool { *(*self) > *(*other) } - /// 'Greater than or equal to' comparison for two `Arc`s. - /// - /// The two are compared by calling `>=` on their inner values. - /// - /// # Examples - /// - /// ``` - /// use std::sync::Arc; - /// - /// let five = Arc::new(5); - /// - /// assert!(five >= Arc::new(5)); - /// ``` fn ge(&self, other: &Arc) -> bool { *(*self) >= *(*other) } } -#[stable(feature = "rust1", since = "1.0.0")] impl Ord for Arc { - /// Comparison for two `Arc`s. - /// - /// The two are compared by calling `cmp()` on their inner values. - /// - /// # Examples - /// - /// ``` - /// use std::sync::Arc; - /// use std::cmp::Ordering; - /// - /// let five = Arc::new(5); - /// - /// assert_eq!(Ordering::Less, five.cmp(&Arc::new(6))); - /// ``` fn cmp(&self, other: &Arc) -> Ordering { (**self).cmp(&**other) } } -#[stable(feature = "rust1", since = "1.0.0")] impl Eq for Arc {} -#[stable(feature = "rust1", since = "1.0.0")] impl fmt::Display for Arc { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&**self, f) } } -#[stable(feature = "rust1", since = "1.0.0")] impl fmt::Debug for Arc { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Debug::fmt(&**self, f) } } -#[stable(feature = "rust1", since = "1.0.0")] impl fmt::Pointer for Arc { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Pointer::fmt(&*self.ptr, f) + fmt::Pointer::fmt(&self.ptr, f) } } -#[stable(feature = "rust1", since = "1.0.0")] impl Default for Arc { - /// Creates a new `Arc`, with the `Default` value for `T`. - /// - /// # Examples - /// - /// ``` - /// use std::sync::Arc; - /// - /// let x: Arc = Default::default(); - /// assert_eq!(*x, 0); - /// ``` fn default() -> Arc { Arc::new(Default::default()) } } -#[stable(feature = "rust1", since = "1.0.0")] impl Hash for Arc { fn hash(&self, state: &mut H) { (**self).hash(state) } } -#[stable(feature = "from_for_ptrs", since = "1.6.0")] impl From for Arc { fn from(t: T) -> Self { Arc::new(t) } } -#[cfg(test)] -mod tests { - use std::clone::Clone; - use std::sync::mpsc::channel; - use std::mem::drop; - use std::ops::Drop; - use std::option::Option; - use std::option::Option::{None, Some}; - use std::sync::atomic; - use std::sync::atomic::Ordering::{Acquire, SeqCst}; - use std::thread; - use std::vec::Vec; - use super::{Arc, Weak}; - use std::sync::Mutex; - use std::convert::From; - - struct Canary(*mut atomic::AtomicUsize); - - impl Drop for Canary { - fn drop(&mut self) { - unsafe { - match *self { - Canary(c) => { - (*c).fetch_add(1, SeqCst); - } - } - } - } - } - - #[test] - #[cfg_attr(target_os = "emscripten", ignore)] - fn manually_share_arc() { - let v = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; - let arc_v = Arc::new(v); - - let (tx, rx) = channel(); - - let _t = thread::spawn(move || { - let arc_v: Arc> = rx.recv().unwrap(); - assert_eq!((*arc_v)[3], 4); - }); - - tx.send(arc_v.clone()).unwrap(); - - assert_eq!((*arc_v)[2], 3); - assert_eq!((*arc_v)[4], 5); - } - - #[test] - fn test_arc_get_mut() { - let mut x = Arc::new(3); - *Arc::get_mut(&mut x).unwrap() = 4; - assert_eq!(*x, 4); - let y = x.clone(); - assert!(Arc::get_mut(&mut x).is_none()); - drop(y); - assert!(Arc::get_mut(&mut x).is_some()); - let _w = Arc::downgrade(&x); - assert!(Arc::get_mut(&mut x).is_none()); - } - - #[test] - fn try_unwrap() { - let x = Arc::new(3); - assert_eq!(Arc::try_unwrap(x), Ok(3)); - let x = Arc::new(4); - let _y = x.clone(); - assert_eq!(Arc::try_unwrap(x), Err(Arc::new(4))); - let x = Arc::new(5); - let _w = Arc::downgrade(&x); - assert_eq!(Arc::try_unwrap(x), Ok(5)); - } - - #[test] - fn into_from_raw() { - let x = Arc::new(box "hello"); - let y = x.clone(); - - let x_ptr = Arc::into_raw(x); - drop(y); - unsafe { - assert_eq!(**x_ptr, "hello"); - - let x = Arc::from_raw(x_ptr); - assert_eq!(**x, "hello"); - - assert_eq!(Arc::try_unwrap(x).map(|x| *x), Ok("hello")); - } - } - - #[test] - fn test_cowarc_clone_make_mut() { - let mut cow0 = Arc::new(75); - let mut cow1 = cow0.clone(); - let mut cow2 = cow1.clone(); - - assert!(75 == *Arc::make_mut(&mut cow0)); - assert!(75 == *Arc::make_mut(&mut cow1)); - assert!(75 == *Arc::make_mut(&mut cow2)); - - *Arc::make_mut(&mut cow0) += 1; - *Arc::make_mut(&mut cow1) += 2; - *Arc::make_mut(&mut cow2) += 3; - - assert!(76 == *cow0); - assert!(77 == *cow1); - assert!(78 == *cow2); - - // none should point to the same backing memory - assert!(*cow0 != *cow1); - assert!(*cow0 != *cow2); - assert!(*cow1 != *cow2); - } - - #[test] - fn test_cowarc_clone_unique2() { - let mut cow0 = Arc::new(75); - let cow1 = cow0.clone(); - let cow2 = cow1.clone(); - - assert!(75 == *cow0); - assert!(75 == *cow1); - assert!(75 == *cow2); - - *Arc::make_mut(&mut cow0) += 1; - assert!(76 == *cow0); - assert!(75 == *cow1); - assert!(75 == *cow2); - - // cow1 and cow2 should share the same contents - // cow0 should have a unique reference - assert!(*cow0 != *cow1); - assert!(*cow0 != *cow2); - assert!(*cow1 == *cow2); - } - - #[test] - fn test_cowarc_clone_weak() { - let mut cow0 = Arc::new(75); - let cow1_weak = Arc::downgrade(&cow0); - - assert!(75 == *cow0); - assert!(75 == *cow1_weak.upgrade().unwrap()); - - *Arc::make_mut(&mut cow0) += 1; - - assert!(76 == *cow0); - assert!(cow1_weak.upgrade().is_none()); - } - - #[test] - fn test_live() { - let x = Arc::new(5); - let y = Arc::downgrade(&x); - assert!(y.upgrade().is_some()); - } - - #[test] - fn test_dead() { - let x = Arc::new(5); - let y = Arc::downgrade(&x); - drop(x); - assert!(y.upgrade().is_none()); - } - - #[test] - fn weak_self_cyclic() { - struct Cycle { - x: Mutex>>, - } - - let a = Arc::new(Cycle { x: Mutex::new(None) }); - let b = Arc::downgrade(&a.clone()); - *a.x.lock().unwrap() = Some(b); - - // hopefully we don't double-free (or leak)... - } - - #[test] - fn drop_arc() { - let mut canary = atomic::AtomicUsize::new(0); - let x = Arc::new(Canary(&mut canary as *mut atomic::AtomicUsize)); - drop(x); - assert!(canary.load(Acquire) == 1); - } - - #[test] - fn drop_arc_weak() { - let mut canary = atomic::AtomicUsize::new(0); - let arc = Arc::new(Canary(&mut canary as *mut atomic::AtomicUsize)); - let arc_weak = Arc::downgrade(&arc); - assert!(canary.load(Acquire) == 0); - drop(arc); - assert!(canary.load(Acquire) == 1); - drop(arc_weak); - } - - #[test] - fn test_strong_count() { - let a = Arc::new(0); - assert!(Arc::strong_count(&a) == 1); - let w = Arc::downgrade(&a); - assert!(Arc::strong_count(&a) == 1); - let b = w.upgrade().expect(""); - assert!(Arc::strong_count(&b) == 2); - assert!(Arc::strong_count(&a) == 2); - drop(w); - drop(a); - assert!(Arc::strong_count(&b) == 1); - let c = b.clone(); - assert!(Arc::strong_count(&b) == 2); - assert!(Arc::strong_count(&c) == 2); - } - - #[test] - fn test_weak_count() { - let a = Arc::new(0); - assert!(Arc::strong_count(&a) == 1); - assert!(Arc::weak_count(&a) == 0); - let w = Arc::downgrade(&a); - assert!(Arc::strong_count(&a) == 1); - assert!(Arc::weak_count(&a) == 1); - let x = w.clone(); - assert!(Arc::weak_count(&a) == 2); - drop(w); - drop(x); - assert!(Arc::strong_count(&a) == 1); - assert!(Arc::weak_count(&a) == 0); - let c = a.clone(); - assert!(Arc::strong_count(&a) == 2); - assert!(Arc::weak_count(&a) == 0); - let d = Arc::downgrade(&c); - assert!(Arc::weak_count(&c) == 1); - assert!(Arc::strong_count(&c) == 2); - - drop(a); - drop(c); - drop(d); - } - - #[test] - fn show_arc() { - let a = Arc::new(5); - assert_eq!(format!("{:?}", a), "5"); - } - - // Make sure deriving works with Arc - #[derive(Eq, Ord, PartialEq, PartialOrd, Clone, Debug, Default)] - struct Foo { - inner: Arc, - } - - #[test] - fn test_unsized() { - let x: Arc<[i32]> = Arc::new([1, 2, 3]); - assert_eq!(format!("{:?}", x), "[1, 2, 3]"); - let y = Arc::downgrade(&x.clone()); - drop(x); - assert!(y.upgrade().is_none()); - } - - #[test] - fn test_from_owned() { - let foo = 123; - let foo_arc = Arc::from(foo); - assert!(123 == *foo_arc); - } - - #[test] - fn test_new_weak() { - let foo: Weak = Weak::new(); - assert!(foo.upgrade().is_none()); - } - - #[test] - fn test_ptr_eq() { - let five = Arc::new(5); - let same_five = five.clone(); - let other_five = Arc::new(5); - - assert!(Arc::ptr_eq(&five, &same_five)); - assert!(!Arc::ptr_eq(&five, &other_five)); - } -} - -#[stable(feature = "rust1", since = "1.0.0")] impl borrow::Borrow for Arc { fn borrow(&self) -> &T { &**self } } -#[stable(since = "1.5.0", feature = "smart_ptr_as_ref")] impl AsRef for Arc { fn as_ref(&self) -> &T { &**self } } + +// This is what the HeapSize crate does for regular arc, but is questionably +// sound. See https://github.com/servo/heapsize/issues/37 +#[cfg(feature = "servo")] +impl HeapSizeOf for Arc { + fn heap_size_of_children(&self) -> usize { + (**self).heap_size_of_children() + } +} + +#[cfg(feature = "servo")] +impl Deserialize for Arc +{ + fn deserialize(deserializer: D) -> Result, D::Error> + where + D: ::serde::de::Deserializer, + { + T::deserialize(deserializer).map(Arc::new) + } +} + +#[cfg(feature = "servo")] +impl Serialize for Arc +{ + fn serialize(&self, serializer: S) -> Result + where + S: ::serde::ser::Serializer, + { + (**self).serialize(serializer) + } +} From d78ca4c4f9f1866204cbb420b284be1cbc137712 Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Sun, 30 Apr 2017 15:18:01 -0700 Subject: [PATCH 06/12] Use StyleArc in the style system. MozReview-Commit-ID: flF0fv9E9M --- components/style/animation.rs | 2 +- components/style/attr.rs | 2 +- components/style/context.rs | 3 ++- components/style/custom_properties.rs | 2 +- components/style/data.rs | 2 +- components/style/dom.rs | 2 +- components/style/encoding_support.rs | 2 +- components/style/gecko/data.rs | 2 +- components/style/gecko/media_queries.rs | 2 +- components/style/gecko/restyle_damage.rs | 2 +- components/style/gecko/url.rs | 2 +- components/style/gecko/wrapper.rs | 2 +- components/style/gecko_bindings/sugar/ownership.rs | 2 +- components/style/gecko_bindings/sugar/refptr.rs | 2 +- components/style/keyframes.rs | 2 +- components/style/lib.rs | 9 --------- components/style/matching.rs | 6 +++--- components/style/properties/gecko.mako.rs | 2 +- components/style/properties/helpers.mako.rs | 4 ++-- components/style/properties/longhand/svg.mako.rs | 2 +- components/style/properties/properties.mako.rs | 6 +++--- components/style/rule_tree/mod.rs | 9 ++++----- components/style/selector_parser.rs | 2 +- components/style/servo/restyle_damage.rs | 2 +- components/style/servo/url.rs | 3 +++ components/style/shared_lock.rs | 4 ++-- components/style/stylesheet_set.rs | 2 +- components/style/stylesheets.rs | 2 +- components/style/stylist.rs | 2 +- ports/geckolib/glue.rs | 3 ++- ports/geckolib/stylesheet_loader.rs | 2 +- tests/unit/style/keyframes.rs | 2 +- tests/unit/style/media_queries.rs | 2 +- tests/unit/style/rule_tree/bench.rs | 2 +- tests/unit/style/stylesheets.rs | 2 +- tests/unit/style/stylist.rs | 2 +- tests/unit/style/viewport.rs | 2 +- 37 files changed, 49 insertions(+), 54 deletions(-) diff --git a/components/style/animation.rs b/components/style/animation.rs index 941db59cc85..0a4c7cab345 100644 --- a/components/style/animation.rs +++ b/components/style/animation.rs @@ -19,8 +19,8 @@ use properties::longhands::animation_iteration_count::single_value::computed_val use properties::longhands::animation_play_state::computed_value::single_value::T as AnimationPlayState; use properties::longhands::transition_timing_function::single_value::computed_value::StartEnd; use properties::longhands::transition_timing_function::single_value::computed_value::T as TransitionTimingFunction; -use std::sync::Arc; use std::sync::mpsc::Sender; +use stylearc::Arc; use timer::Timer; use values::computed::Time; diff --git a/components/style/attr.rs b/components/style/attr.rs index 1989816329d..101810212b7 100644 --- a/components/style/attr.rs +++ b/components/style/attr.rs @@ -16,10 +16,10 @@ use servo_url::ServoUrl; use shared_lock::Locked; use std::ascii::AsciiExt; use std::str::FromStr; -use std::sync::Arc; use str::{HTML_SPACE_CHARACTERS, read_exponent, read_fraction}; use str::{read_numbers, split_commas, split_html_space_chars}; use str::str_join; +use stylearc::Arc; use values::specified::Length; // Duplicated from script::dom::values. diff --git a/components/style/context.rs b/components/style/context.rs index 581a7c12cd3..1cdd8c00636 100644 --- a/components/style/context.rs +++ b/components/style/context.rs @@ -27,8 +27,9 @@ use std::collections::HashMap; #[cfg(not(feature = "servo"))] use std::env; use std::fmt; use std::ops::Add; -use std::sync::{Arc, Mutex}; +use std::sync::Mutex; use std::sync::mpsc::Sender; +use stylearc::Arc; use stylist::Stylist; use thread_state; use time; diff --git a/components/style/custom_properties.rs b/components/style/custom_properties.rs index 95e43b46fdf..071efade790 100644 --- a/components/style/custom_properties.rs +++ b/components/style/custom_properties.rs @@ -14,8 +14,8 @@ use std::ascii::AsciiExt; use std::borrow::Cow; use std::collections::{HashMap, HashSet}; use std::fmt; -use std::sync::Arc; use style_traits::ToCss; +use stylearc::Arc; /// A custom property name is just an `Atom`. /// diff --git a/components/style/data.rs b/components/style/data.rs index 4052f0b30a3..651f003e4e9 100644 --- a/components/style/data.rs +++ b/components/style/data.rs @@ -16,7 +16,7 @@ use selector_parser::{EAGER_PSEUDO_COUNT, PseudoElement, RestyleDamage, Snapshot use std::fmt; #[cfg(feature = "servo")] use std::hash::BuildHasherDefault; use std::ops::Deref; -use std::sync::Arc; +use stylearc::Arc; use stylist::Stylist; use thread_state; use traversal::TraversalFlags; diff --git a/components/style/dom.rs b/components/style/dom.rs index ffc46b0cc94..7a4fe5d1003 100644 --- a/components/style/dom.rs +++ b/components/style/dom.rs @@ -26,7 +26,7 @@ use std::fmt; use std::fmt::Debug; use std::hash::Hash; use std::ops::Deref; -use std::sync::Arc; +use stylearc::Arc; use stylist::ApplicableDeclarationBlock; use thread_state; diff --git a/components/style/encoding_support.rs b/components/style/encoding_support.rs index 2775de54893..92620378b30 100644 --- a/components/style/encoding_support.rs +++ b/components/style/encoding_support.rs @@ -13,7 +13,7 @@ use media_queries::MediaList; use self::encoding::{EncodingRef, DecoderTrap}; use shared_lock::SharedRwLock; use std::str; -use std::sync::Arc; +use stylearc::Arc; use stylesheets::{Stylesheet, StylesheetLoader, Origin, UrlExtraData}; struct RustEncoding; diff --git a/components/style/gecko/data.rs b/components/style/gecko/data.rs index 942aaf4f7b5..2e1e17a2ebc 100644 --- a/components/style/gecko/data.rs +++ b/components/style/gecko/data.rs @@ -15,8 +15,8 @@ use parking_lot::RwLock; use properties::ComputedValues; use shared_lock::{Locked, StylesheetGuards, SharedRwLockReadGuard}; use std::collections::HashMap; -use std::sync::Arc; use std::sync::mpsc::{Receiver, Sender, channel}; +use stylearc::Arc; use stylesheet_set::StylesheetSet; use stylesheets::{FontFaceRule, Origin, Stylesheet}; use stylist::{ExtraStyleData, Stylist}; diff --git a/components/style/gecko/media_queries.rs b/components/style/gecko/media_queries.rs index a0aeaec2e5c..2444338f174 100644 --- a/components/style/gecko/media_queries.rs +++ b/components/style/gecko/media_queries.rs @@ -18,11 +18,11 @@ use media_queries::MediaType; use parser::ParserContext; use properties::{ComputedValues, StyleBuilder}; use std::fmt::{self, Write}; -use std::sync::Arc; use str::starts_with_ignore_ascii_case; use string_cache::Atom; use style_traits::ToCss; use style_traits::viewport::ViewportConstraints; +use stylearc::Arc; use values::{CSSFloat, specified}; use values::computed::{self, ToComputedValue}; diff --git a/components/style/gecko/restyle_damage.rs b/components/style/gecko/restyle_damage.rs index 4d6c1269eb8..39fdafebd5d 100644 --- a/components/style/gecko/restyle_damage.rs +++ b/components/style/gecko/restyle_damage.rs @@ -10,7 +10,7 @@ use gecko_bindings::structs::{nsChangeHint, nsStyleContext}; use gecko_bindings::sugar::ownership::FFIArcHelpers; use properties::ComputedValues; use std::ops::{BitAnd, BitOr, BitOrAssign, Not}; -use std::sync::Arc; +use stylearc::Arc; /// The representation of Gecko's restyle damage is just a wrapper over /// `nsChangeHint`. diff --git a/components/style/gecko/url.rs b/components/style/gecko/url.rs index 286094bcb0e..191ae082726 100644 --- a/components/style/gecko/url.rs +++ b/components/style/gecko/url.rs @@ -10,8 +10,8 @@ use gecko_bindings::sugar::refptr::RefPtr; use parser::ParserContext; use std::borrow::Cow; use std::fmt::{self, Write}; -use std::sync::Arc; use style_traits::ToCss; +use stylearc::Arc; /// A specified url() value for gecko. Gecko does not eagerly resolve SpecifiedUrls. #[derive(Clone, Debug, PartialEq)] diff --git a/components/style/gecko/wrapper.rs b/components/style/gecko/wrapper.rs index 100830c0e0d..f71ef0a6c9c 100644 --- a/components/style/gecko/wrapper.rs +++ b/components/style/gecko/wrapper.rs @@ -71,8 +71,8 @@ use std::collections::HashMap; use std::fmt; use std::hash::{Hash, Hasher}; use std::ptr; -use std::sync::Arc; use string_cache::{Atom, Namespace, WeakAtom, WeakNamespace}; +use stylearc::Arc; use stylesheets::UrlExtraData; use stylist::ApplicableDeclarationBlock; diff --git a/components/style/gecko_bindings/sugar/ownership.rs b/components/style/gecko_bindings/sugar/ownership.rs index abcf5c65a8a..6c4746013b3 100644 --- a/components/style/gecko_bindings/sugar/ownership.rs +++ b/components/style/gecko_bindings/sugar/ownership.rs @@ -8,7 +8,7 @@ use std::marker::PhantomData; use std::mem::{forget, transmute}; use std::ops::{Deref, DerefMut}; use std::ptr; -use std::sync::Arc; +use stylearc::Arc; /// Indicates that a given Servo type has a corresponding Gecko FFI type. pub unsafe trait HasFFI : Sized { diff --git a/components/style/gecko_bindings/sugar/refptr.rs b/components/style/gecko_bindings/sugar/refptr.rs index 3c3dec9aee3..9ca1d3dc7b6 100644 --- a/components/style/gecko_bindings/sugar/refptr.rs +++ b/components/style/gecko_bindings/sugar/refptr.rs @@ -9,7 +9,7 @@ use gecko_bindings::sugar::ownership::HasArcFFI; use std::{mem, ptr}; use std::marker::PhantomData; use std::ops::{Deref, DerefMut}; -use std::sync::Arc; +use stylearc::Arc; /// Trait for all objects that have Addref() and Release /// methods and can be placed inside RefPtr diff --git a/components/style/keyframes.rs b/components/style/keyframes.rs index 8113c06bb6c..3a80320bb52 100644 --- a/components/style/keyframes.rs +++ b/components/style/keyframes.rs @@ -17,8 +17,8 @@ use properties::animated_properties::TransitionProperty; use properties::longhands::transition_timing_function::single_value::SpecifiedValue as SpecifiedTimingFunction; use shared_lock::{SharedRwLock, SharedRwLockReadGuard, Locked, ToCssWithGuard}; use std::fmt; -use std::sync::Arc; use style_traits::ToCss; +use stylearc::Arc; use stylesheets::{CssRuleType, Stylesheet, VendorPrefix}; /// A number from 0 to 1, indicating the percentage of the animation when this diff --git a/components/style/lib.rs b/components/style/lib.rs index 99ded2b9fe8..8902ab4efc6 100644 --- a/components/style/lib.rs +++ b/components/style/lib.rs @@ -132,7 +132,6 @@ pub mod values; pub mod viewport; use std::fmt; -use std::sync::Arc; use style_traits::ToCss; #[cfg(feature = "gecko")] pub use gecko_string_cache as string_cache; @@ -177,14 +176,6 @@ macro_rules! reexport_computed_values { } longhand_properties_idents!(reexport_computed_values); -/// Returns whether the two arguments point to the same value. -/// -/// FIXME: Remove this and use Arc::ptr_eq once we require Rust 1.17 -#[inline] -pub fn arc_ptr_eq(a: &Arc, b: &Arc) -> bool { - ptr_eq::(&**a, &**b) -} - /// Pointer equality /// /// FIXME: Remove this and use std::ptr::eq once we require Rust 1.17 diff --git a/components/style/matching.rs b/components/style/matching.rs index ca2db43c4b9..8da1192d4d3 100644 --- a/components/style/matching.rs +++ b/components/style/matching.rs @@ -27,7 +27,7 @@ use selectors::bloom::BloomFilter; use selectors::matching::{ElementSelectorFlags, StyleRelations}; use selectors::matching::AFFECTED_BY_PSEUDO_ELEMENTS; use sink::ForgetfulSink; -use std::sync::Arc; +use stylearc::Arc; use stylist::ApplicableDeclarationBlock; /// The way a style should be inherited. @@ -120,8 +120,8 @@ fn same_computed_values(first: Option, second: Option) -> boo _ => return false, }; - let eq = ::arc_ptr_eq(a.borrow_data().unwrap().styles().primary.values(), - b.borrow_data().unwrap().styles().primary.values()); + let eq = Arc::ptr_eq(a.borrow_data().unwrap().styles().primary.values(), + b.borrow_data().unwrap().styles().primary.values()); eq } diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index 4643d176949..b428ec3e198 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -61,7 +61,7 @@ use properties::{PropertyDeclaration, PropertyDeclarationBlock, PropertyDeclarat use std::fmt::{self, Debug}; use std::mem::{forget, transmute, zeroed}; use std::ptr; -use std::sync::Arc; +use stylearc::Arc; use std::cmp; use values::computed::ToComputedValue; use values::{Either, Auto, KeyframesName}; diff --git a/components/style/properties/helpers.mako.rs b/components/style/properties/helpers.mako.rs index 4db19381e1f..3c3bb537320 100644 --- a/components/style/properties/helpers.mako.rs +++ b/components/style/properties/helpers.mako.rs @@ -252,7 +252,7 @@ use properties::{DeclaredValue, LonghandId, LonghandIdSet}; use properties::{CSSWideKeyword, ComputedValues, PropertyDeclaration}; use properties::style_structs; - use std::sync::Arc; + use stylearc::Arc; use values::computed::{Context, ToComputedValue}; use values::{computed, generics, specified}; use Atom; @@ -716,7 +716,7 @@ use properties::{PropertyDeclaration, ParsedDeclaration}; use properties::{ShorthandId, UnparsedValue, longhands}; use std::fmt; - use std::sync::Arc; + use stylearc::Arc; use style_traits::ToCss; pub struct Longhands { diff --git a/components/style/properties/longhand/svg.mako.rs b/components/style/properties/longhand/svg.mako.rs index 7a764fbe9f5..45cb125bf33 100644 --- a/components/style/properties/longhand/svg.mako.rs +++ b/components/style/properties/longhand/svg.mako.rs @@ -197,7 +197,7 @@ ${helpers.single_keyword("mask-composite", spec="https://drafts.fxtf.org/css-masking/#propdef-mask-image"> use std::fmt; use style_traits::ToCss; - use std::sync::Arc; + use stylearc::Arc; use values::specified::Image; use values::specified::url::SpecifiedUrl; use values::HasViewportPercentage; diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs index aba24623855..83ca3e3d4fb 100644 --- a/components/style/properties/properties.mako.rs +++ b/components/style/properties/properties.mako.rs @@ -14,7 +14,7 @@ use std::borrow::Cow; use std::collections::HashSet; use std::fmt; use std::ops::Deref; -use std::sync::Arc; +use stylearc::Arc; use app_units::Au; #[cfg(feature = "servo")] use cssparser::{Color as CSSParserColor, RGBA}; @@ -178,7 +178,7 @@ pub mod shorthands { use cssparser::Parser; use parser::ParserContext; use properties::{ParsedDeclaration, ShorthandId, UnparsedValue}; - use std::sync::Arc; + use stylearc::Arc; pub fn parse(context: &ParserContext, input: &mut Parser) -> Result { // This function is like the parse() that is generated by @@ -2246,7 +2246,7 @@ pub use self::lazy_static_module::INITIAL_SERVO_VALUES; #[allow(missing_docs)] mod lazy_static_module { use logical_geometry::WritingMode; - use std::sync::Arc; + use stylearc::Arc; use super::{ComputedValues, longhands, style_structs}; /// The initial values for all style structs as defined by the specification. diff --git a/components/style/rule_tree/mod.rs b/components/style/rule_tree/mod.rs index fa6acaa92b5..0947198e2da 100644 --- a/components/style/rule_tree/mod.rs +++ b/components/style/rule_tree/mod.rs @@ -6,15 +6,14 @@ //! The rule tree. -use arc_ptr_eq; #[cfg(feature = "servo")] use heapsize::HeapSizeOf; use properties::{Importance, PropertyDeclarationBlock}; use shared_lock::{Locked, StylesheetGuards, SharedRwLockReadGuard}; use std::io::{self, Write}; use std::ptr; -use std::sync::Arc; use std::sync::atomic::{AtomicPtr, AtomicUsize, Ordering}; +use stylearc::Arc; use stylesheets::StyleRule; use thread_state; @@ -65,8 +64,8 @@ impl StyleSource { fn ptr_equals(&self, other: &Self) -> bool { use self::StyleSource::*; match (self, other) { - (&Style(ref one), &Style(ref other)) => arc_ptr_eq(one, other), - (&Declarations(ref one), &Declarations(ref other)) => arc_ptr_eq(one, other), + (&Style(ref one), &Style(ref other)) => Arc::ptr_eq(one, other), + (&Declarations(ref one), &Declarations(ref other)) => Arc::ptr_eq(one, other), _ => false, } } @@ -203,7 +202,7 @@ impl RuleTree { // so let's skip it for now. let is_here_already = match current.get().source.as_ref() { Some(&StyleSource::Declarations(ref already_here)) => { - arc_ptr_eq(pdb, already_here) + Arc::ptr_eq(pdb, already_here) }, _ => unreachable!("Replacing non-declarations style?"), }; diff --git a/components/style/selector_parser.rs b/components/style/selector_parser.rs index 0664483cbe7..0af60279af8 100644 --- a/components/style/selector_parser.rs +++ b/components/style/selector_parser.rs @@ -37,7 +37,7 @@ pub use gecko::restyle_damage::GeckoRestyleDamage as RestyleDamage; /// A type that represents the previous computed values needed for restyle /// damage calculation. #[cfg(feature = "servo")] -pub type PreExistingComputedValues = ::std::sync::Arc<::properties::ServoComputedValues>; +pub type PreExistingComputedValues = ::stylearc::Arc<::properties::ServoComputedValues>; /// A type that represents the previous computed values needed for restyle /// damage calculation. diff --git a/components/style/servo/restyle_damage.rs b/components/style/servo/restyle_damage.rs index 0ad934278c1..1fd7b38cae2 100644 --- a/components/style/servo/restyle_damage.rs +++ b/components/style/servo/restyle_damage.rs @@ -11,7 +11,7 @@ use computed_values::display; use heapsize::HeapSizeOf; use properties::ServoComputedValues; use std::fmt; -use std::sync::Arc; +use stylearc::Arc; bitflags! { #[doc = "Individual layout actions that may be necessary after restyling."] diff --git a/components/style/servo/url.rs b/components/style/servo/url.rs index c59c6bcb0b7..467f7a45715 100644 --- a/components/style/servo/url.rs +++ b/components/style/servo/url.rs @@ -9,6 +9,9 @@ use parser::ParserContext; use servo_url::ServoUrl; use std::borrow::Cow; use std::fmt::{self, Write}; +// Note: We use std::sync::Arc rather than stylearc::Arc here because the +// nonzero optimization is important in keeping the size of SpecifiedUrl below +// the threshold. use std::sync::Arc; use style_traits::ToCss; diff --git a/components/style/shared_lock.rs b/components/style/shared_lock.rs index 2dec153f342..360118d472e 100644 --- a/components/style/shared_lock.rs +++ b/components/style/shared_lock.rs @@ -10,7 +10,7 @@ use atomic_refcell::{AtomicRefCell, AtomicRef, AtomicRefMut}; use parking_lot::RwLock; use std::cell::UnsafeCell; use std::fmt; -use std::sync::Arc; +use stylearc::Arc; /// A shared read/write lock that can protect multiple objects. /// @@ -149,7 +149,7 @@ impl fmt::Debug for Locked { impl Locked { #[cfg(feature = "servo")] fn same_lock_as(&self, lock: &SharedRwLock) -> bool { - ::arc_ptr_eq(&self.shared_lock.arc, &lock.arc) + Arc::ptr_eq(&self.shared_lock.arc, &lock.arc) } #[cfg(feature = "gecko")] diff --git a/components/style/stylesheet_set.rs b/components/style/stylesheet_set.rs index 78e0c9cd558..0cc6f4fbf51 100644 --- a/components/style/stylesheet_set.rs +++ b/components/style/stylesheet_set.rs @@ -4,7 +4,7 @@ //! A centralized set of stylesheets for a document. -use std::sync::Arc; +use stylearc::Arc; use stylesheets::Stylesheet; /// Entry for a StylesheetSet. We don't bother creating a constructor, because diff --git a/components/style/stylesheets.rs b/components/style/stylesheets.rs index 97dfce4c51f..36e5a2a936e 100644 --- a/components/style/stylesheets.rs +++ b/components/style/stylesheets.rs @@ -36,10 +36,10 @@ use servo_url::ServoUrl; use shared_lock::{SharedRwLock, Locked, ToCssWithGuard, SharedRwLockReadGuard}; use std::cell::Cell; use std::fmt; -use std::sync::Arc; use std::sync::atomic::{AtomicBool, Ordering}; use str::starts_with_ignore_ascii_case; use style_traits::ToCss; +use stylearc::Arc; use stylist::FnvHashMap; use supports::SupportsCondition; use values::{CustomIdent, KeyframesName}; diff --git a/components/style/stylist.rs b/components/style/stylist.rs index cda795d559c..5dc3e807374 100644 --- a/components/style/stylist.rs +++ b/components/style/stylist.rs @@ -39,8 +39,8 @@ use std::fmt; use std::hash::Hash; #[cfg(feature = "servo")] use std::marker::PhantomData; -use std::sync::Arc; use style_traits::viewport::ViewportConstraints; +use stylearc::Arc; use stylesheets::{CssRule, FontFaceRule, Origin, StyleRule, Stylesheet, UserAgentStylesheets}; use thread_state; use viewport::{self, MaybeNew, ViewportRule}; diff --git a/ports/geckolib/glue.rs b/ports/geckolib/glue.rs index dff56ce8b0f..f53a47f0af7 100644 --- a/ports/geckolib/glue.rs +++ b/ports/geckolib/glue.rs @@ -11,7 +11,7 @@ use std::borrow::Cow; use std::env; use std::fmt::Write; use std::ptr; -use std::sync::{Arc, Mutex}; +use std::sync::Mutex; use style::context::{QuirksMode, SharedStyleContext, StyleContext}; use style::context::{ThreadLocalStyleContext, ThreadLocalStyleContextCreationInfo}; use style::data::{ElementData, ElementStyles, RestyleData}; @@ -83,6 +83,7 @@ use style::sequential; use style::shared_lock::{SharedRwLock, SharedRwLockReadGuard, StylesheetGuards, ToCssWithGuard, Locked}; use style::string_cache::Atom; use style::style_adjuster::StyleAdjuster; +use style::stylearc::Arc; use style::stylesheets::{CssRule, CssRules, CssRuleType, CssRulesHelpers}; use style::stylesheets::{ImportRule, MediaRule, NamespaceRule, Origin}; use style::stylesheets::{PageRule, Stylesheet, StyleRule, SupportsRule}; diff --git a/ports/geckolib/stylesheet_loader.rs b/ports/geckolib/stylesheet_loader.rs index a79aa6e192f..87fdc4d39f3 100644 --- a/ports/geckolib/stylesheet_loader.rs +++ b/ports/geckolib/stylesheet_loader.rs @@ -2,12 +2,12 @@ * 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 std::sync::Arc; use style::gecko_bindings::bindings::Gecko_LoadStyleSheet; use style::gecko_bindings::structs::{Loader, ServoStyleSheet}; use style::gecko_bindings::sugar::ownership::{HasArcFFI, FFIArcHelpers}; use style::media_queries::MediaList; use style::shared_lock::Locked; +use style::stylearc::Arc; use style::stylesheets::{ImportRule, Stylesheet, StylesheetLoader as StyleStylesheetLoader}; pub struct StylesheetLoader(*mut Loader, *mut ServoStyleSheet); diff --git a/tests/unit/style/keyframes.rs b/tests/unit/style/keyframes.rs index 4f96b5f88a9..1f3947c5815 100644 --- a/tests/unit/style/keyframes.rs +++ b/tests/unit/style/keyframes.rs @@ -2,12 +2,12 @@ * 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 std::sync::Arc; use style::keyframes::{Keyframe, KeyframesAnimation, KeyframePercentage, KeyframeSelector}; use style::keyframes::{KeyframesStep, KeyframesStepValue}; use style::properties::{PropertyDeclaration, PropertyDeclarationBlock, Importance}; use style::properties::animated_properties::TransitionProperty; use style::shared_lock::SharedRwLock; +use style::stylearc::Arc; use style::values::specified::{LengthOrPercentageOrAuto, NoCalcLength}; #[test] diff --git a/tests/unit/style/media_queries.rs b/tests/unit/style/media_queries.rs index 10634a6f134..d538225d9d8 100644 --- a/tests/unit/style/media_queries.rs +++ b/tests/unit/style/media_queries.rs @@ -6,13 +6,13 @@ use cssparser::{Parser, SourcePosition}; use euclid::size::TypedSize2D; use servo_url::ServoUrl; use std::borrow::ToOwned; -use std::sync::Arc; use style::Atom; use style::context::QuirksMode; use style::error_reporting::ParseErrorReporter; use style::media_queries::*; use style::servo::media_queries::*; use style::shared_lock::{SharedRwLock, SharedRwLockReadGuard}; +use style::stylearc::Arc; use style::stylesheets::{Stylesheet, Origin, CssRule}; use style::values::specified; use style_traits::ToCss; diff --git a/tests/unit/style/rule_tree/bench.rs b/tests/unit/style/rule_tree/bench.rs index ed73bd11d6f..68d253b2965 100644 --- a/tests/unit/style/rule_tree/bench.rs +++ b/tests/unit/style/rule_tree/bench.rs @@ -5,13 +5,13 @@ use cssparser::{Parser, SourcePosition}; use rayon; use servo_url::ServoUrl; -use std::sync::Arc; use style::context::QuirksMode; use style::error_reporting::ParseErrorReporter; use style::media_queries::MediaList; use style::properties::{longhands, Importance, PropertyDeclaration, PropertyDeclarationBlock}; use style::rule_tree::{CascadeLevel, RuleTree, StrongRuleNode, StyleSource}; use style::shared_lock::SharedRwLock; +use style::stylearc::Arc; use style::stylesheets::{Origin, Stylesheet, CssRule}; use test::{self, Bencher}; diff --git a/tests/unit/style/stylesheets.rs b/tests/unit/style/stylesheets.rs index 47aa1ea9730..e599e9687ae 100644 --- a/tests/unit/style/stylesheets.rs +++ b/tests/unit/style/stylesheets.rs @@ -10,7 +10,6 @@ use selectors::parser::*; use servo_atoms::Atom; use servo_url::ServoUrl; use std::borrow::ToOwned; -use std::sync::Arc; use std::sync::Mutex; use std::sync::atomic::AtomicBool; use style::context::QuirksMode; @@ -22,6 +21,7 @@ use style::properties::{CSSWideKeyword, DeclaredValueOwned, PropertyDeclaration, use style::properties::longhands; use style::properties::longhands::animation_play_state; use style::shared_lock::SharedRwLock; +use style::stylearc::Arc; use style::stylesheets::{Origin, Namespaces}; use style::stylesheets::{Stylesheet, NamespaceRule, CssRule, CssRules, StyleRule, KeyframesRule}; use style::values::{KeyframesName, CustomIdent}; diff --git a/tests/unit/style/stylist.rs b/tests/unit/style/stylist.rs index ea89dfde06b..096af2d0006 100644 --- a/tests/unit/style/stylist.rs +++ b/tests/unit/style/stylist.rs @@ -6,12 +6,12 @@ use html5ever_atoms::LocalName; use selectors::parser::LocalName as LocalNameSelector; use selectors::parser::Selector; use servo_atoms::Atom; -use std::sync::Arc; use style::properties::{PropertyDeclarationBlock, PropertyDeclaration}; use style::properties::{longhands, Importance}; use style::rule_tree::CascadeLevel; use style::selector_parser::{SelectorImpl, SelectorParser}; use style::shared_lock::SharedRwLock; +use style::stylearc::Arc; use style::stylesheets::StyleRule; use style::stylist::{Rule, SelectorMap}; use style::stylist::needs_revalidation; diff --git a/tests/unit/style/viewport.rs b/tests/unit/style/viewport.rs index fb29e87debf..ed8b9b527ee 100644 --- a/tests/unit/style/viewport.rs +++ b/tests/unit/style/viewport.rs @@ -7,11 +7,11 @@ use euclid::size::TypedSize2D; use media_queries::CSSErrorReporterTest; use servo_config::prefs::{PREFS, PrefValue}; use servo_url::ServoUrl; -use std::sync::Arc; use style::context::QuirksMode; use style::media_queries::{Device, MediaList, MediaType}; use style::parser::{LengthParsingMode, Parse, ParserContext}; use style::shared_lock::SharedRwLock; +use style::stylearc::Arc; use style::stylesheets::{CssRuleType, Stylesheet, Origin}; use style::values::specified::LengthOrPercentageOrAuto::{self, Auto}; use style::values::specified::NoCalcLength::{self, ViewportPercentage}; From 7b0679848b177ead3a87171d0224e05ecadd8006 Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Tue, 2 May 2017 16:22:10 -0700 Subject: [PATCH 07/12] Fix up script and layout. --- components/gfx/font_context.rs | 5 +++-- components/layout/block.rs | 2 +- components/layout/construct.rs | 7 ++++--- components/layout/display_list_builder.rs | 2 +- components/layout/flex.rs | 3 +-- components/layout/flow.rs | 6 +++--- components/layout/fragment.rs | 16 ++++++++-------- components/layout/generated_content.rs | 5 ++--- components/layout/inline.rs | 10 +++++----- components/layout/lib.rs | 12 ++++++++++++ components/layout/list_item.rs | 3 +-- components/layout/multicol.rs | 5 +++-- components/layout/query.rs | 2 +- components/layout/table.rs | 3 +-- components/layout/table_caption.rs | 3 +-- components/layout/table_cell.rs | 3 +-- components/layout/table_colgroup.rs | 3 +-- components/layout/table_row.rs | 3 +-- components/layout/table_rowgroup.rs | 3 +-- components/layout/table_wrapper.rs | 3 +-- components/layout/text.rs | 2 +- components/layout_thread/lib.rs | 19 ++++++++++--------- components/script/dom/bindings/trace.rs | 7 +++++++ components/script/dom/cssconditionrule.rs | 2 +- components/script/dom/cssfontfacerule.rs | 2 +- components/script/dom/cssgroupingrule.rs | 2 +- components/script/dom/cssimportrule.rs | 2 +- components/script/dom/csskeyframerule.rs | 2 +- components/script/dom/csskeyframesrule.rs | 2 +- components/script/dom/cssmediarule.rs | 2 +- components/script/dom/cssnamespacerule.rs | 2 +- components/script/dom/cssrulelist.rs | 2 +- components/script/dom/cssstyledeclaration.rs | 2 +- components/script/dom/cssstylerule.rs | 2 +- components/script/dom/cssstylesheet.rs | 2 +- components/script/dom/csssupportsrule.rs | 2 +- components/script/dom/cssviewportrule.rs | 2 +- components/script/dom/document.rs | 2 +- components/script/dom/element.rs | 2 +- components/script/dom/htmllinkelement.rs | 2 +- components/script/dom/htmlmetaelement.rs | 2 +- components/script/dom/htmlobjectelement.rs | 2 +- components/script/dom/htmlstyleelement.rs | 2 +- components/script/dom/medialist.rs | 2 +- components/script/dom/node.rs | 2 +- components/script/layout_wrapper.rs | 2 +- components/script/stylesheet_loader.rs | 5 +++-- components/script_layout_interface/message.rs | 4 ++-- .../script_layout_interface/wrapper_traits.rs | 2 +- 49 files changed, 99 insertions(+), 85 deletions(-) diff --git a/components/gfx/font_context.rs b/components/gfx/font_context.rs index b1b9bbc6838..2e91e549611 100644 --- a/components/gfx/font_context.rs +++ b/components/gfx/font_context.rs @@ -21,6 +21,7 @@ use std::sync::Arc; use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT}; use style::computed_values::{font_style, font_variant_caps}; use style::properties::style_structs; +use style::stylearc::Arc as StyleArc; use webrender_traits; static SMALL_CAPS_SCALE_FACTOR: f32 = 0.8; // Matches FireFox (see gfxFont.h) @@ -109,7 +110,7 @@ impl FontContext { /// Create a group of fonts for use in layout calculations. May return /// a cached font if this font instance has already been used by /// this context. - pub fn layout_font_group_for_style(&mut self, style: Arc) + pub fn layout_font_group_for_style(&mut self, style: StyleArc) -> Rc { self.expire_font_caches_if_necessary(); @@ -239,7 +240,7 @@ impl HeapSizeOf for FontContext { #[derive(Debug)] struct LayoutFontGroupCacheKey { - pointer: Arc, + pointer: StyleArc, size: Au, } diff --git a/components/layout/block.rs b/components/layout/block.rs index 297bfcdc689..5e30c6f08ee 100644 --- a/components/layout/block.rs +++ b/components/layout/block.rs @@ -2134,7 +2134,7 @@ impl Flow for BlockFlow { self.build_display_list_for_block(state, BorderPaintingMode::Separate); } - fn repair_style(&mut self, new_style: &Arc) { + fn repair_style(&mut self, new_style: &::StyleArc) { self.fragment.repair_style(new_style) } diff --git a/components/layout/construct.rs b/components/layout/construct.rs index 089209551ac..2f24629b5e4 100644 --- a/components/layout/construct.rs +++ b/components/layout/construct.rs @@ -13,6 +13,7 @@ #![deny(unsafe_code)] +use StyleArc; use app_units::Au; use block::BlockFlow; use context::{LayoutContext, with_thread_local_font_context}; @@ -107,7 +108,7 @@ pub enum ConstructionItem { /// Inline fragments and associated {ib} splits that have not yet found flows. InlineFragments(InlineFragmentsConstructionResult), /// Potentially ignorable whitespace. - Whitespace(OpaqueNode, PseudoElementType<()>, Arc, RestyleDamage), + Whitespace(OpaqueNode, PseudoElementType<()>, StyleArc, RestyleDamage), /// TableColumn Fragment TableColumnFragment(Fragment), } @@ -675,7 +676,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode> fn create_fragments_for_node_text_content(&self, fragments: &mut IntermediateInlineFragments, node: &ConcreteThreadSafeLayoutNode, - style: &Arc) { + style: &StyleArc) { // Fast path: If there is no text content, return immediately. let text_content = node.text_content(); if text_content.is_empty() { @@ -1804,7 +1805,7 @@ pub fn strip_ignorable_whitespace_from_end(this: &mut LinkedList) { /// If the 'unicode-bidi' property has a value other than 'normal', return the bidi control codes /// to inject before and after the text content of the element. -fn bidi_control_chars(style: &Arc) -> Option<(&'static str, &'static str)> { +fn bidi_control_chars(style: &StyleArc) -> Option<(&'static str, &'static str)> { use style::computed_values::direction::T::*; use style::computed_values::unicode_bidi::T::*; diff --git a/components/layout/display_list_builder.rs b/components/layout/display_list_builder.rs index a2453067e1f..878b1220336 100644 --- a/components/layout/display_list_builder.rs +++ b/components/layout/display_list_builder.rs @@ -577,7 +577,7 @@ fn build_border_radius(abs_bounds: &Rect, /// Get the border radius for the rectangle inside of a rounded border. This is useful /// for building the clip for the content inside the border. fn build_border_radius_for_inner_rect(outer_rect: &Rect, - style: Arc) + style: ::StyleArc) -> BorderRadii { let mut radii = build_border_radius(&outer_rect, style.get_border()); if radii.is_square() { diff --git a/components/layout/flex.rs b/components/layout/flex.rs index cf77455afa8..dd990c61510 100644 --- a/components/layout/flex.rs +++ b/components/layout/flex.rs @@ -21,7 +21,6 @@ use model::{IntrinsicISizes, MaybeAuto, SizeConstraint}; use model::{specified, specified_or_none}; use std::cmp::{max, min}; use std::ops::Range; -use std::sync::Arc; use style::computed_values::{align_content, align_self, flex_direction, flex_wrap, justify_content}; use style::computed_values::border_collapse; use style::logical_geometry::{Direction, LogicalSize}; @@ -970,7 +969,7 @@ impl Flow for FlexFlow { self.block_flow.collect_stacking_contexts(state); } - fn repair_style(&mut self, new_style: &Arc) { + fn repair_style(&mut self, new_style: &::StyleArc) { self.block_flow.repair_style(new_style) } diff --git a/components/layout/flow.rs b/components/layout/flow.rs index 27b5c291cc8..1944f0decbd 100644 --- a/components/layout/flow.rs +++ b/components/layout/flow.rs @@ -424,7 +424,7 @@ pub trait Flow: fmt::Debug + Sync + Send + 'static { /// Attempts to perform incremental fixup of this flow by replacing its fragment's style with /// the new style. This can only succeed if the flow has exactly one fragment. - fn repair_style(&mut self, new_style: &Arc); + fn repair_style(&mut self, new_style: &::StyleArc); /// Print any extra children (such as fragments) contained in this Flow /// for debugging purposes. Any items inserted into the tree will become @@ -561,7 +561,7 @@ pub trait MutableFlowUtils { /// Calls `repair_style` and `bubble_inline_sizes`. You should use this method instead of /// calling them individually, since there is no reason not to perform both operations. - fn repair_style_and_bubble_inline_sizes(self, style: &Arc); + fn repair_style_and_bubble_inline_sizes(self, style: &::StyleArc); } pub trait MutableOwnedFlowUtils { @@ -1361,7 +1361,7 @@ impl<'a> MutableFlowUtils for &'a mut Flow { /// Calls `repair_style` and `bubble_inline_sizes`. You should use this method instead of /// calling them individually, since there is no reason not to perform both operations. - fn repair_style_and_bubble_inline_sizes(self, style: &Arc) { + fn repair_style_and_bubble_inline_sizes(self, style: &::StyleArc) { self.repair_style(style); self.bubble_inline_sizes(); } diff --git a/components/layout/fragment.rs b/components/layout/fragment.rs index 5c311ec3311..9f98ff318ec 100644 --- a/components/layout/fragment.rs +++ b/components/layout/fragment.rs @@ -6,6 +6,7 @@ #![deny(unsafe_code)] +use StyleArc; use app_units::Au; use canvas_traits::CanvasMsg; use context::{LayoutContext, with_thread_local_font_context}; @@ -39,7 +40,6 @@ use std::borrow::ToOwned; use std::cmp::{Ordering, max, min}; use std::collections::LinkedList; use std::sync::{Arc, Mutex}; -use style::arc_ptr_eq; use style::computed_values::{border_collapse, box_sizing, clear, color, display, mix_blend_mode}; use style::computed_values::{overflow_wrap, overflow_x, position, text_decoration_line, transform}; use style::computed_values::{transform_style, vertical_align, white_space, word_break}; @@ -95,10 +95,10 @@ pub struct Fragment { pub node: OpaqueNode, /// The CSS style of this fragment. - pub style: Arc, + pub style: StyleArc, /// The CSS style of this fragment when it's selected - pub selected_style: Arc, + pub selected_style: StyleArc, /// The position of this fragment relative to its owning flow. The size includes padding and /// border, but not margin. @@ -672,8 +672,8 @@ impl Fragment { /// Constructs a new `Fragment` instance from an opaque node. pub fn from_opaque_node_and_style(node: OpaqueNode, pseudo: PseudoElementType<()>, - style: Arc, - selected_style: Arc, + style: StyleArc, + selected_style: StyleArc, mut restyle_damage: RestyleDamage, specific: SpecificFragmentInfo) -> Fragment { @@ -702,7 +702,7 @@ impl Fragment { /// type. For the new anonymous fragment, layout-related values (border box, etc.) are reset to /// initial values. pub fn create_similar_anonymous_fragment(&self, - style: Arc, + style: StyleArc, specific: SpecificFragmentInfo) -> Fragment { let writing_mode = style.writing_mode; @@ -1846,7 +1846,7 @@ impl Fragment { match (&mut self.specific, &next_fragment.specific) { (&mut SpecificFragmentInfo::ScannedText(ref mut this_info), &SpecificFragmentInfo::ScannedText(ref other_info)) => { - debug_assert!(arc_ptr_eq(&this_info.run, &other_info.run)); + debug_assert!(::arc_ptr_eq(&this_info.run, &other_info.run)); this_info.range_end_including_stripped_whitespace = other_info.range_end_including_stripped_whitespace; if other_info.requires_line_break_afterward_if_wrapping_on_newlines() { @@ -2398,7 +2398,7 @@ impl Fragment { } } - pub fn repair_style(&mut self, new_style: &Arc) { + pub fn repair_style(&mut self, new_style: &StyleArc) { self.style = (*new_style).clone() } diff --git a/components/layout/generated_content.rs b/components/layout/generated_content.rs index a23fd165ecf..5f6f9b1e706 100644 --- a/components/layout/generated_content.rs +++ b/components/layout/generated_content.rs @@ -16,7 +16,6 @@ use gfx::display_list::OpaqueNode; use script_layout_interface::wrapper_traits::PseudoElementType; use smallvec::SmallVec; use std::collections::{HashMap, LinkedList}; -use std::sync::Arc; use style::computed_values::{display, list_style_type}; use style::computed_values::content::ContentItem; use style::properties::ServoComputedValues; @@ -369,7 +368,7 @@ impl Counter { layout_context: &LayoutContext, node: OpaqueNode, pseudo: PseudoElementType<()>, - style: Arc, + style: ::StyleArc, list_style_type: list_style_type::T, mode: RenderingMode) -> Option { @@ -432,7 +431,7 @@ struct CounterValue { fn render_text(layout_context: &LayoutContext, node: OpaqueNode, pseudo: PseudoElementType<()>, - style: Arc, + style: ::StyleArc, string: String) -> Option { let mut fragments = LinkedList::new(); diff --git a/components/layout/inline.rs b/components/layout/inline.rs index f28e583460f..d8cd4003ab3 100644 --- a/components/layout/inline.rs +++ b/components/layout/inline.rs @@ -4,6 +4,7 @@ #![deny(unsafe_code)] +use StyleArc; use app_units::Au; use block::AbsoluteAssignBSizesTraversal; use context::LayoutContext; @@ -29,7 +30,6 @@ use std::{fmt, i32, isize, mem}; use std::cmp::max; use std::collections::VecDeque; use std::sync::Arc; -use style::arc_ptr_eq; use style::computed_values::{display, overflow_x, position, text_align, text_justify}; use style::computed_values::{vertical_align, white_space}; use style::logical_geometry::{LogicalRect, LogicalSize, WritingMode}; @@ -398,7 +398,7 @@ impl LineBreaker { result.border_padding.inline_end == Au(0) && candidate.border_padding.inline_start == Au(0) && result_info.selected() == candidate_info.selected() && - arc_ptr_eq(&result_info.run, &candidate_info.run) && + ::arc_ptr_eq(&result_info.run, &candidate_info.run) && inline_contexts_are_equal(&result.inline_context, &candidate.inline_context) } @@ -1657,7 +1657,7 @@ impl Flow for InlineFlow { self.build_display_list_for_inline(state); } - fn repair_style(&mut self, _: &Arc) {} + fn repair_style(&mut self, _: &StyleArc) {} fn compute_overflow(&self) -> Overflow { let mut overflow = Overflow::new(); @@ -1746,8 +1746,8 @@ impl fmt::Debug for InlineFlow { #[derive(Clone)] pub struct InlineFragmentNodeInfo { pub address: OpaqueNode, - pub style: Arc, - pub selected_style: Arc, + pub style: StyleArc, + pub selected_style: StyleArc, pub pseudo: PseudoElementType<()>, pub flags: InlineFragmentNodeFlags, } diff --git a/components/layout/lib.rs b/components/layout/lib.rs index 4c5bd766e24..dd86ba46cde 100644 --- a/components/layout/lib.rs +++ b/components/layout/lib.rs @@ -93,3 +93,15 @@ pub mod wrapper; // For unit tests: pub use fragment::Fragment; pub use fragment::SpecificFragmentInfo; + +/// Returns whether the two arguments point to the same value. +/// +/// FIXME: Remove this and use Arc::ptr_eq once we require Rust 1.17 +#[inline] +pub fn arc_ptr_eq(a: &::std::sync::Arc, b: &::std::sync::Arc) -> bool { + ::style::ptr_eq::(&**a, &**b) +} + +// We can't use stylearc for everything in layout, because the Flow stuff uses +// weak references. +use style::stylearc::Arc as StyleArc; diff --git a/components/layout/list_item.rs b/components/layout/list_item.rs index cb260480cb9..8a79aaa40b7 100644 --- a/components/layout/list_item.rs +++ b/components/layout/list_item.rs @@ -18,7 +18,6 @@ use fragment::{CoordinateSystem, Fragment, FragmentBorderBoxIterator, GeneratedC use fragment::Overflow; use generated_content; use inline::InlineFlow; -use std::sync::Arc; use style::computed_values::{list_style_type, position}; use style::logical_geometry::LogicalSize; use style::properties::ServoComputedValues; @@ -148,7 +147,7 @@ impl Flow for ListItemFlow { self.block_flow.collect_stacking_contexts(state); } - fn repair_style(&mut self, new_style: &Arc) { + fn repair_style(&mut self, new_style: &::StyleArc) { self.block_flow.repair_style(new_style) } diff --git a/components/layout/multicol.rs b/components/layout/multicol.rs index 18cfe6409cb..b43a6eb17ff 100644 --- a/components/layout/multicol.rs +++ b/components/layout/multicol.rs @@ -6,6 +6,7 @@ #![deny(unsafe_code)] +use StyleArc; use app_units::Au; use block::BlockFlow; use context::LayoutContext; @@ -193,7 +194,7 @@ impl Flow for MulticolFlow { self.block_flow.collect_stacking_contexts(state); } - fn repair_style(&mut self, new_style: &Arc) { + fn repair_style(&mut self, new_style: &StyleArc) { self.block_flow.repair_style(new_style) } @@ -275,7 +276,7 @@ impl Flow for MulticolColumnFlow { self.block_flow.collect_stacking_contexts(state); } - fn repair_style(&mut self, new_style: &Arc) { + fn repair_style(&mut self, new_style: &StyleArc) { self.block_flow.repair_style(new_style) } diff --git a/components/layout/query.rs b/components/layout/query.rs index 92c3a1525dd..6b594066963 100644 --- a/components/layout/query.rs +++ b/components/layout/query.rs @@ -55,7 +55,7 @@ pub struct LayoutThreadData { pub display_list: Option>, /// Performs CSS selector matching and style resolution. - pub stylist: Arc, + pub stylist: ::StyleArc, /// A queued response for the union of the content boxes of a node. pub content_box_response: Option>, diff --git a/components/layout/table.rs b/components/layout/table.rs index b130b62bd04..c3ba52a305b 100644 --- a/components/layout/table.rs +++ b/components/layout/table.rs @@ -21,7 +21,6 @@ use layout_debug; use model::{IntrinsicISizes, IntrinsicISizesContribution, MaybeAuto}; use std::cmp; use std::fmt; -use std::sync::Arc; use style::computed_values::{border_collapse, border_spacing, table_layout}; use style::context::SharedStyleContext; use style::logical_geometry::LogicalSize; @@ -507,7 +506,7 @@ impl Flow for TableFlow { self.block_flow.collect_stacking_contexts(state); } - fn repair_style(&mut self, new_style: &Arc) { + fn repair_style(&mut self, new_style: &::StyleArc) { self.block_flow.repair_style(new_style) } diff --git a/components/layout/table_caption.rs b/components/layout/table_caption.rs index fe3eb5bf692..99d95fd9587 100644 --- a/components/layout/table_caption.rs +++ b/components/layout/table_caption.rs @@ -15,7 +15,6 @@ use flow::{Flow, FlowClass, OpaqueFlow}; use fragment::{Fragment, FragmentBorderBoxIterator, Overflow}; use gfx_traits::print_tree::PrintTree; use std::fmt; -use std::sync::Arc; use style::logical_geometry::LogicalSize; use style::properties::ServoComputedValues; @@ -84,7 +83,7 @@ impl Flow for TableCaptionFlow { self.block_flow.collect_stacking_contexts(state); } - fn repair_style(&mut self, new_style: &Arc) { + fn repair_style(&mut self, new_style: &::StyleArc) { self.block_flow.repair_style(new_style) } diff --git a/components/layout/table_cell.rs b/components/layout/table_cell.rs index b40d25e936c..8c54297d4b5 100644 --- a/components/layout/table_cell.rs +++ b/components/layout/table_cell.rs @@ -19,7 +19,6 @@ use layout_debug; use model::MaybeAuto; use script_layout_interface::wrapper_traits::ThreadSafeLayoutNode; use std::fmt; -use std::sync::Arc; use style::computed_values::{border_collapse, border_top_style, vertical_align}; use style::logical_geometry::{LogicalMargin, LogicalRect, LogicalSize, WritingMode}; use style::properties::ServoComputedValues; @@ -264,7 +263,7 @@ impl Flow for TableCellFlow { self.block_flow.collect_stacking_contexts(state); } - fn repair_style(&mut self, new_style: &Arc) { + fn repair_style(&mut self, new_style: &::StyleArc) { self.block_flow.repair_style(new_style) } diff --git a/components/layout/table_colgroup.rs b/components/layout/table_colgroup.rs index 5603a02e3c9..85d5207646e 100644 --- a/components/layout/table_colgroup.rs +++ b/components/layout/table_colgroup.rs @@ -15,7 +15,6 @@ use fragment::{Fragment, FragmentBorderBoxIterator, Overflow, SpecificFragmentIn use layout_debug; use std::cmp::max; use std::fmt; -use std::sync::Arc; use style::logical_geometry::LogicalSize; use style::properties::ServoComputedValues; use style::values::computed::LengthOrPercentageOrAuto; @@ -95,7 +94,7 @@ impl Flow for TableColGroupFlow { fn collect_stacking_contexts(&mut self, _: &mut DisplayListBuildState) {} - fn repair_style(&mut self, _: &Arc) {} + fn repair_style(&mut self, _: &::StyleArc) {} fn compute_overflow(&self) -> Overflow { Overflow::new() diff --git a/components/layout/table_row.rs b/components/layout/table_row.rs index d1c7146d247..8d074f59c52 100644 --- a/components/layout/table_row.rs +++ b/components/layout/table_row.rs @@ -22,7 +22,6 @@ use serde::{Serialize, Serializer}; use std::cmp::max; use std::fmt; use std::iter::{Enumerate, IntoIterator, Peekable}; -use std::sync::Arc; use style::computed_values::{border_collapse, border_spacing, border_top_style}; use style::logical_geometry::{LogicalSize, PhysicalSide, WritingMode}; use style::properties::ServoComputedValues; @@ -483,7 +482,7 @@ impl Flow for TableRowFlow { self.block_flow.collect_stacking_contexts(state); } - fn repair_style(&mut self, new_style: &Arc) { + fn repair_style(&mut self, new_style: &::StyleArc) { self.block_flow.repair_style(new_style) } diff --git a/components/layout/table_rowgroup.rs b/components/layout/table_rowgroup.rs index e4c4291bce4..7664796b082 100644 --- a/components/layout/table_rowgroup.rs +++ b/components/layout/table_rowgroup.rs @@ -18,7 +18,6 @@ use layout_debug; use serde::{Serialize, Serializer}; use std::fmt; use std::iter::{IntoIterator, Iterator, Peekable}; -use std::sync::Arc; use style::computed_values::{border_collapse, border_spacing}; use style::logical_geometry::LogicalSize; use style::properties::ServoComputedValues; @@ -186,7 +185,7 @@ impl Flow for TableRowGroupFlow { self.block_flow.collect_stacking_contexts(state); } - fn repair_style(&mut self, new_style: &Arc) { + fn repair_style(&mut self, new_style: &::StyleArc) { self.block_flow.repair_style(new_style) } diff --git a/components/layout/table_wrapper.rs b/components/layout/table_wrapper.rs index 64799a37e42..015f32a9762 100644 --- a/components/layout/table_wrapper.rs +++ b/components/layout/table_wrapper.rs @@ -27,7 +27,6 @@ use model::MaybeAuto; use std::cmp::{max, min}; use std::fmt; use std::ops::Add; -use std::sync::Arc; use style::computed_values::{border_collapse, position, table_layout}; use style::context::SharedStyleContext; use style::logical_geometry::{LogicalRect, LogicalSize}; @@ -467,7 +466,7 @@ impl Flow for TableWrapperFlow { self.block_flow.collect_stacking_contexts(state); } - fn repair_style(&mut self, new_style: &Arc) { + fn repair_style(&mut self, new_style: &::StyleArc) { self.block_flow.repair_style(new_style) } diff --git a/components/layout/text.rs b/components/layout/text.rs index 5c9b93edee1..43b2fd086e7 100644 --- a/components/layout/text.rs +++ b/components/layout/text.rs @@ -435,7 +435,7 @@ fn bounding_box_for_run_metrics(metrics: &RunMetrics, writing_mode: WritingMode) /// /// `#[inline]` because often the caller only needs a few fields from the font metrics. #[inline] -pub fn font_metrics_for_style(font_context: &mut FontContext, font_style: Arc) +pub fn font_metrics_for_style(font_context: &mut FontContext, font_style: ::StyleArc) -> FontMetrics { let fontgroup = font_context.layout_font_group_for_style(font_style); // FIXME(https://github.com/rust-lang/rust/issues/23338) diff --git a/components/layout_thread/lib.rs b/components/layout_thread/lib.rs index 30d59180a3c..054d82397d5 100644 --- a/components/layout_thread/lib.rs +++ b/components/layout_thread/lib.rs @@ -115,6 +115,7 @@ use style::logical_geometry::LogicalPoint; use style::media_queries::{Device, MediaList, MediaType}; use style::servo::restyle_damage::{REFLOW, REFLOW_OUT_OF_FLOW, REPAINT, REPOSITION, STORE_OVERFLOW}; use style::shared_lock::{SharedRwLock, SharedRwLockReadGuard, StylesheetGuards}; +use style::stylearc::Arc as StyleArc; use style::stylesheets::{Origin, Stylesheet, UserAgentStylesheets}; use style::stylist::{ExtraStyleData, Stylist}; use style::thread_state; @@ -192,10 +193,10 @@ pub struct LayoutThread { document_shared_lock: Option, /// The list of currently-running animations. - running_animations: Arc>>>, + running_animations: StyleArc>>>, /// The list of animations that have expired since the last style recalculation. - expired_animations: Arc>>>, + expired_animations: StyleArc>>>, /// A counter for epoch messages epoch: Epoch, @@ -412,7 +413,7 @@ impl LayoutThread { let font_cache_receiver = ROUTER.route_ipc_receiver_to_new_mpsc_receiver(ipc_font_cache_receiver); - let stylist = Arc::new(Stylist::new(device)); + let stylist = StyleArc::new(Stylist::new(device)); let outstanding_web_fonts_counter = Arc::new(AtomicUsize::new(0)); let ua_stylesheets = &*UA_STYLESHEETS; let guard = ua_stylesheets.shared_lock.read(); @@ -448,8 +449,8 @@ impl LayoutThread { outstanding_web_fonts: outstanding_web_fonts_counter, root_flow: None, document_shared_lock: None, - running_animations: Arc::new(RwLock::new(HashMap::new())), - expired_animations: Arc::new(RwLock::new(HashMap::new())), + running_animations: StyleArc::new(RwLock::new(HashMap::new())), + expired_animations: StyleArc::new(RwLock::new(HashMap::new())), epoch: Epoch(0), viewport_size: Size2D::new(Au(0), Au(0)), webrender_api: webrender_api_sender.create_api(), @@ -741,7 +742,7 @@ impl LayoutThread { } fn handle_add_stylesheet<'a, 'b>(&self, - stylesheet: Arc, + stylesheet: StyleArc, possibly_locked_rw_data: &mut RwData<'a, 'b>) { // Find all font-face rules and notify the font cache of them. // GWTODO: Need to handle unloading web fonts. @@ -776,7 +777,7 @@ impl LayoutThread { possibly_locked_rw_data: &mut RwData<'a, 'b>, quirks_mode: QuirksMode) { let mut rw_data = possibly_locked_rw_data.lock(); - Arc::get_mut(&mut rw_data.stylist).unwrap().set_quirks_mode(quirks_mode); + StyleArc::get_mut(&mut rw_data.stylist).unwrap().set_quirks_mode(quirks_mode); possibly_locked_rw_data.block(rw_data); } @@ -1034,7 +1035,7 @@ impl LayoutThread { self.document_shared_lock = Some(document_shared_lock.clone()); let author_guard = document_shared_lock.read(); let device = Device::new(MediaType::Screen, initial_viewport); - Arc::get_mut(&mut rw_data.stylist).unwrap() + StyleArc::get_mut(&mut rw_data.stylist).unwrap() .set_device(device, &author_guard, &data.document_stylesheets); self.viewport_size = @@ -1088,7 +1089,7 @@ impl LayoutThread { let mut extra_data = ExtraStyleData { marker: PhantomData, }; - let needs_dirtying = Arc::get_mut(&mut rw_data.stylist).unwrap().update( + let needs_dirtying = StyleArc::get_mut(&mut rw_data.stylist).unwrap().update( &data.document_stylesheets, &guards, Some(ua_stylesheets), diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs index 1bc9c165fb1..2ecae0d9d73 100644 --- a/components/script/dom/bindings/trace.rs +++ b/components/script/dom/bindings/trace.rs @@ -99,6 +99,7 @@ use style::media_queries::MediaList; use style::properties::PropertyDeclarationBlock; use style::selector_parser::{PseudoElement, Snapshot}; use style::shared_lock::{SharedRwLock as StyleSharedRwLock, Locked as StyleLocked}; +use style::stylearc::Arc as StyleArc; use style::stylesheets::{CssRules, FontFaceRule, KeyframesRule, MediaRule}; use style::stylesheets::{NamespaceRule, StyleRule, ImportRule, SupportsRule}; use style::values::specified::Length; @@ -166,6 +167,12 @@ unsafe impl JSTraceable for Arc { } } +unsafe impl JSTraceable for StyleArc { + unsafe fn trace(&self, trc: *mut JSTracer) { + (**self).trace(trc) + } +} + unsafe impl JSTraceable for Box { unsafe fn trace(&self, trc: *mut JSTracer) { (**self).trace(trc) diff --git a/components/script/dom/cssconditionrule.rs b/components/script/dom/cssconditionrule.rs index 8bf5dad6c93..1944c28c379 100644 --- a/components/script/dom/cssconditionrule.rs +++ b/components/script/dom/cssconditionrule.rs @@ -10,8 +10,8 @@ use dom::cssmediarule::CSSMediaRule; use dom::cssstylesheet::CSSStyleSheet; use dom::csssupportsrule::CSSSupportsRule; use dom_struct::dom_struct; -use std::sync::Arc; use style::shared_lock::{SharedRwLock, Locked}; +use style::stylearc::Arc; use style::stylesheets::CssRules as StyleCssRules; #[dom_struct] diff --git a/components/script/dom/cssfontfacerule.rs b/components/script/dom/cssfontfacerule.rs index 1f247c25fdc..560722d2452 100644 --- a/components/script/dom/cssfontfacerule.rs +++ b/components/script/dom/cssfontfacerule.rs @@ -10,8 +10,8 @@ use dom::cssrule::{CSSRule, SpecificCSSRule}; use dom::cssstylesheet::CSSStyleSheet; use dom::window::Window; use dom_struct::dom_struct; -use std::sync::Arc; use style::shared_lock::{Locked, ToCssWithGuard}; +use style::stylearc::Arc; use style::stylesheets::FontFaceRule; #[dom_struct] diff --git a/components/script/dom/cssgroupingrule.rs b/components/script/dom/cssgroupingrule.rs index 249aaccd42e..4fd77b46a7c 100644 --- a/components/script/dom/cssgroupingrule.rs +++ b/components/script/dom/cssgroupingrule.rs @@ -12,8 +12,8 @@ use dom::cssrule::CSSRule; use dom::cssrulelist::{CSSRuleList, RulesSource}; use dom::cssstylesheet::CSSStyleSheet; use dom_struct::dom_struct; -use std::sync::Arc; use style::shared_lock::{SharedRwLock, Locked}; +use style::stylearc::Arc; use style::stylesheets::CssRules as StyleCssRules; #[dom_struct] diff --git a/components/script/dom/cssimportrule.rs b/components/script/dom/cssimportrule.rs index 3c0eb7eb4aa..d9d867cbc19 100644 --- a/components/script/dom/cssimportrule.rs +++ b/components/script/dom/cssimportrule.rs @@ -10,8 +10,8 @@ use dom::cssrule::{CSSRule, SpecificCSSRule}; use dom::cssstylesheet::CSSStyleSheet; use dom::window::Window; use dom_struct::dom_struct; -use std::sync::Arc; use style::shared_lock::{Locked, ToCssWithGuard}; +use style::stylearc::Arc; use style::stylesheets::ImportRule; #[dom_struct] diff --git a/components/script/dom/csskeyframerule.rs b/components/script/dom/csskeyframerule.rs index d36e8988e04..46dac811d9f 100644 --- a/components/script/dom/csskeyframerule.rs +++ b/components/script/dom/csskeyframerule.rs @@ -12,9 +12,9 @@ use dom::cssstyledeclaration::{CSSModificationAccess, CSSStyleDeclaration, CSSSt use dom::cssstylesheet::CSSStyleSheet; use dom::window::Window; use dom_struct::dom_struct; -use std::sync::Arc; use style::keyframes::Keyframe; use style::shared_lock::{Locked, ToCssWithGuard}; +use style::stylearc::Arc; #[dom_struct] pub struct CSSKeyframeRule { diff --git a/components/script/dom/csskeyframesrule.rs b/components/script/dom/csskeyframesrule.rs index a3715e914ed..f48abe60751 100644 --- a/components/script/dom/csskeyframesrule.rs +++ b/components/script/dom/csskeyframesrule.rs @@ -16,9 +16,9 @@ use dom::cssrulelist::{CSSRuleList, RulesSource}; use dom::cssstylesheet::CSSStyleSheet; use dom::window::Window; use dom_struct::dom_struct; -use std::sync::Arc; use style::keyframes::{Keyframe, KeyframeSelector}; use style::shared_lock::{Locked, ToCssWithGuard}; +use style::stylearc::Arc; use style::stylesheets::KeyframesRule; use style::values::KeyframesName; diff --git a/components/script/dom/cssmediarule.rs b/components/script/dom/cssmediarule.rs index 45bf65b1adf..afc41d31be0 100644 --- a/components/script/dom/cssmediarule.rs +++ b/components/script/dom/cssmediarule.rs @@ -15,10 +15,10 @@ use dom::cssstylesheet::CSSStyleSheet; use dom::medialist::MediaList; use dom::window::Window; use dom_struct::dom_struct; -use std::sync::Arc; use style::media_queries::parse_media_query_list; use style::parser::{LengthParsingMode, ParserContext}; use style::shared_lock::{Locked, ToCssWithGuard}; +use style::stylearc::Arc; use style::stylesheets::{CssRuleType, MediaRule}; use style_traits::ToCss; diff --git a/components/script/dom/cssnamespacerule.rs b/components/script/dom/cssnamespacerule.rs index 744a8020667..eafabf8a4a6 100644 --- a/components/script/dom/cssnamespacerule.rs +++ b/components/script/dom/cssnamespacerule.rs @@ -11,8 +11,8 @@ use dom::cssrule::{CSSRule, SpecificCSSRule}; use dom::cssstylesheet::CSSStyleSheet; use dom::window::Window; use dom_struct::dom_struct; -use std::sync::Arc; use style::shared_lock::{Locked, ToCssWithGuard}; +use style::stylearc::Arc; use style::stylesheets::NamespaceRule; #[dom_struct] diff --git a/components/script/dom/cssrulelist.rs b/components/script/dom/cssrulelist.rs index 67eac2beda2..d0dfe120410 100644 --- a/components/script/dom/cssrulelist.rs +++ b/components/script/dom/cssrulelist.rs @@ -13,8 +13,8 @@ use dom::cssrule::CSSRule; use dom::cssstylesheet::CSSStyleSheet; use dom::window::Window; use dom_struct::dom_struct; -use std::sync::Arc; use style::shared_lock::Locked; +use style::stylearc::Arc; use style::stylesheets::{CssRules, CssRulesHelpers, KeyframesRule, RulesMutateError}; #[allow(unsafe_code)] diff --git a/components/script/dom/cssstyledeclaration.rs b/components/script/dom/cssstyledeclaration.rs index d0996f04567..8b81201de77 100644 --- a/components/script/dom/cssstyledeclaration.rs +++ b/components/script/dom/cssstyledeclaration.rs @@ -16,13 +16,13 @@ use dom::window::Window; use dom_struct::dom_struct; use servo_url::ServoUrl; use std::ascii::AsciiExt; -use std::sync::Arc; use style::attr::AttrValue; use style::parser::LengthParsingMode; use style::properties::{Importance, PropertyDeclarationBlock, PropertyId, LonghandId, ShorthandId}; use style::properties::{parse_one_declaration, parse_style_attribute}; use style::selector_parser::PseudoElement; use style::shared_lock::Locked; +use style::stylearc::Arc; use style_traits::ToCss; // http://dev.w3.org/csswg/cssom/#the-cssstyledeclaration-interface diff --git a/components/script/dom/cssstylerule.rs b/components/script/dom/cssstylerule.rs index fed2b947f90..607f2cfb816 100644 --- a/components/script/dom/cssstylerule.rs +++ b/components/script/dom/cssstylerule.rs @@ -12,8 +12,8 @@ use dom::cssstyledeclaration::{CSSModificationAccess, CSSStyleDeclaration, CSSSt use dom::cssstylesheet::CSSStyleSheet; use dom::window::Window; use dom_struct::dom_struct; -use std::sync::Arc; use style::shared_lock::{Locked, ToCssWithGuard}; +use style::stylearc::Arc; use style::stylesheets::StyleRule; #[dom_struct] diff --git a/components/script/dom/cssstylesheet.rs b/components/script/dom/cssstylesheet.rs index ee097313c2e..cb378b2261a 100644 --- a/components/script/dom/cssstylesheet.rs +++ b/components/script/dom/cssstylesheet.rs @@ -15,8 +15,8 @@ use dom::stylesheet::StyleSheet; use dom::window::Window; use dom_struct::dom_struct; use std::cell::Cell; -use std::sync::Arc; use style::shared_lock::SharedRwLock; +use style::stylearc::Arc; use style::stylesheets::Stylesheet as StyleStyleSheet; #[dom_struct] diff --git a/components/script/dom/csssupportsrule.rs b/components/script/dom/csssupportsrule.rs index 86aedf10864..9a0743856d6 100644 --- a/components/script/dom/csssupportsrule.rs +++ b/components/script/dom/csssupportsrule.rs @@ -13,9 +13,9 @@ use dom::cssrule::SpecificCSSRule; use dom::cssstylesheet::CSSStyleSheet; use dom::window::Window; use dom_struct::dom_struct; -use std::sync::Arc; use style::parser::{LengthParsingMode, ParserContext}; use style::shared_lock::{Locked, ToCssWithGuard}; +use style::stylearc::Arc; use style::stylesheets::{CssRuleType, SupportsRule}; use style::supports::SupportsCondition; use style_traits::ToCss; diff --git a/components/script/dom/cssviewportrule.rs b/components/script/dom/cssviewportrule.rs index 38abf909ff0..4438aabb53e 100644 --- a/components/script/dom/cssviewportrule.rs +++ b/components/script/dom/cssviewportrule.rs @@ -10,8 +10,8 @@ use dom::cssrule::{CSSRule, SpecificCSSRule}; use dom::cssstylesheet::CSSStyleSheet; use dom::window::Window; use dom_struct::dom_struct; -use std::sync::Arc; use style::shared_lock::{Locked, ToCssWithGuard}; +use style::stylearc::Arc; use style::viewport::ViewportRule; #[dom_struct] diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index 06b8f7596cf..024c201a85c 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.rs @@ -128,7 +128,6 @@ use std::default::Default; use std::iter::once; use std::mem; use std::rc::Rc; -use std::sync::Arc; use std::time::{Duration, Instant}; use style::attr::AttrValue; use style::context::{QuirksMode, ReflowGoal}; @@ -136,6 +135,7 @@ use style::restyle_hints::{RestyleHint, RESTYLE_SELF, RESTYLE_STYLE_ATTRIBUTE}; use style::selector_parser::{RestyleDamage, Snapshot}; use style::shared_lock::SharedRwLock as StyleSharedRwLock; use style::str::{HTML_SPACE_CHARACTERS, split_html_space_chars, str_join}; +use style::stylearc::Arc; use style::stylesheets::Stylesheet; use task_source::TaskSource; use time; diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index d6974fb9075..a7d2d96fe73 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -96,7 +96,6 @@ use std::convert::TryFrom; use std::default::Default; use std::fmt; use std::rc::Rc; -use std::sync::Arc; use style::attr::{AttrValue, LengthOrPercentageOrAuto}; use style::context::{QuirksMode, ReflowGoal}; use style::element_state::*; @@ -107,6 +106,7 @@ use style::rule_tree::CascadeLevel; use style::selector_parser::{NonTSPseudoClass, RestyleDamage, SelectorImpl, SelectorParser}; use style::shared_lock::{SharedRwLock, Locked}; use style::sink::Push; +use style::stylearc::Arc; use style::stylist::ApplicableDeclarationBlock; use style::thread_state; use style::values::CSSFloat; diff --git a/components/script/dom/htmllinkelement.rs b/components/script/dom/htmllinkelement.rs index bf36d28b29d..f3c12a30699 100644 --- a/components/script/dom/htmllinkelement.rs +++ b/components/script/dom/htmllinkelement.rs @@ -30,11 +30,11 @@ use std::ascii::AsciiExt; use std::borrow::ToOwned; use std::cell::Cell; use std::default::Default; -use std::sync::Arc; use style::attr::AttrValue; use style::media_queries::parse_media_query_list; use style::parser::{LengthParsingMode, ParserContext as CssParserContext}; use style::str::HTML_SPACE_CHARACTERS; +use style::stylearc::Arc; use style::stylesheets::{CssRuleType, Stylesheet}; use stylesheet_loader::{StylesheetLoader, StylesheetContextSource, StylesheetOwner}; diff --git a/components/script/dom/htmlmetaelement.rs b/components/script/dom/htmlmetaelement.rs index 62d7215e3df..0c1ac5a0229 100644 --- a/components/script/dom/htmlmetaelement.rs +++ b/components/script/dom/htmlmetaelement.rs @@ -21,11 +21,11 @@ use dom_struct::dom_struct; use html5ever_atoms::LocalName; use servo_config::prefs::PREFS; use std::ascii::AsciiExt; -use std::sync::Arc; use std::sync::atomic::AtomicBool; use style::attr::AttrValue; use style::media_queries::MediaList; use style::str::HTML_SPACE_CHARACTERS; +use style::stylearc::Arc; use style::stylesheets::{Stylesheet, CssRule, CssRules, Origin}; use style::viewport::ViewportRule; diff --git a/components/script/dom/htmlobjectelement.rs b/components/script/dom/htmlobjectelement.rs index c80a7838198..ee847610791 100755 --- a/components/script/dom/htmlobjectelement.rs +++ b/components/script/dom/htmlobjectelement.rs @@ -21,7 +21,7 @@ use dom_struct::dom_struct; use html5ever_atoms::LocalName; use net_traits::image::base::Image; use std::default::Default; -use std::sync::Arc; +use style::stylearc::Arc; #[dom_struct] pub struct HTMLObjectElement { diff --git a/components/script/dom/htmlstyleelement.rs b/components/script/dom/htmlstyleelement.rs index 8905c3baa65..8b9a2c74fcb 100644 --- a/components/script/dom/htmlstyleelement.rs +++ b/components/script/dom/htmlstyleelement.rs @@ -23,9 +23,9 @@ use html5ever_atoms::LocalName; use net_traits::ReferrerPolicy; use script_layout_interface::message::Msg; use std::cell::Cell; -use std::sync::Arc; use style::media_queries::parse_media_query_list; use style::parser::{LengthParsingMode, ParserContext as CssParserContext}; +use style::stylearc::Arc; use style::stylesheets::{CssRuleType, Stylesheet, Origin}; use stylesheet_loader::{StylesheetLoader, StylesheetOwner}; diff --git a/components/script/dom/medialist.rs b/components/script/dom/medialist.rs index f2a2299d169..514bccecc4a 100644 --- a/components/script/dom/medialist.rs +++ b/components/script/dom/medialist.rs @@ -12,11 +12,11 @@ use dom::bindings::str::DOMString; use dom::cssstylesheet::CSSStyleSheet; use dom::window::Window; use dom_struct::dom_struct; -use std::sync::Arc; use style::media_queries::{MediaQuery, parse_media_query_list}; use style::media_queries::MediaList as StyleMediaList; use style::parser::{LengthParsingMode, ParserContext}; use style::shared_lock::{SharedRwLock, Locked}; +use style::stylearc::Arc; use style::stylesheets::CssRuleType; use style_traits::ToCss; diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs index 0384c4ed19d..aa0fcc9a2a1 100644 --- a/components/script/dom/node.rs +++ b/components/script/dom/node.rs @@ -78,10 +78,10 @@ use std::default::Default; use std::iter; use std::mem; use std::ops::Range; -use std::sync::Arc; use style::context::QuirksMode; use style::dom::OpaqueNode; use style::selector_parser::{SelectorImpl, SelectorParser}; +use style::stylearc::Arc; use style::stylesheets::Stylesheet; use style::thread_state; use uuid::Uuid; diff --git a/components/script/layout_wrapper.rs b/components/script/layout_wrapper.rs index 3ddb1d2b5c9..5fe45595388 100644 --- a/components/script/layout_wrapper.rs +++ b/components/script/layout_wrapper.rs @@ -58,7 +58,6 @@ use std::fmt::Debug; use std::hash::{Hash, Hasher}; use std::marker::PhantomData; use std::mem::transmute; -use std::sync::Arc; use std::sync::atomic::Ordering; use style; use style::attr::AttrValue; @@ -74,6 +73,7 @@ use style::selector_parser::{NonTSPseudoClass, PseudoElement, SelectorImpl}; use style::shared_lock::{SharedRwLock as StyleSharedRwLock, Locked as StyleLocked}; use style::sink::Push; use style::str::is_whitespace; +use style::stylearc::Arc; use style::stylist::ApplicableDeclarationBlock; #[derive(Copy, Clone)] diff --git a/components/script/stylesheet_loader.rs b/components/script/stylesheet_loader.rs index 14b8c385e39..3143d8b34ad 100644 --- a/components/script/stylesheet_loader.rs +++ b/components/script/stylesheet_loader.rs @@ -24,9 +24,10 @@ use net_traits::request::{CorsSettings, CredentialsMode, Destination, RequestIni use network_listener::{NetworkListener, PreInvoke}; use servo_url::ServoUrl; use std::mem; -use std::sync::{Arc, Mutex}; +use std::sync::Mutex; use style::media_queries::MediaList; use style::shared_lock::Locked as StyleLocked; +use style::stylearc::Arc; use style::stylesheets::{ImportRule, Stylesheet, Origin}; use style::stylesheets::StylesheetLoader as StyleStylesheetLoader; @@ -207,7 +208,7 @@ impl<'a> StylesheetLoader<'a> { let document = document_from_node(self.elem); let gen = self.elem.downcast::() .map(HTMLLinkElement::get_request_generation_id); - let context = Arc::new(Mutex::new(StylesheetContext { + let context = ::std::sync::Arc::new(Mutex::new(StylesheetContext { elem: Trusted::new(&*self.elem), source: source, url: url.clone(), diff --git a/components/script_layout_interface/message.rs b/components/script_layout_interface/message.rs index b94b6cd8d14..8b04a131404 100644 --- a/components/script_layout_interface/message.rs +++ b/components/script_layout_interface/message.rs @@ -25,7 +25,7 @@ use style::stylesheets::Stylesheet; /// Asynchronous messages that script can send to layout. pub enum Msg { /// Adds the given stylesheet to the document. - AddStylesheet(Arc), + AddStylesheet(::style::stylearc::Arc), /// Change the quirks mode. SetQuirksMode(QuirksMode), @@ -116,7 +116,7 @@ pub struct ScriptReflow { /// The document node. pub document: TrustedNodeAddress, /// The document's list of stylesheets. - pub document_stylesheets: Vec>, + pub document_stylesheets: Vec<::style::stylearc::Arc>, /// Whether the document's stylesheets have changed since the last script reflow. pub stylesheets_changed: bool, /// The current window size. diff --git a/components/script_layout_interface/wrapper_traits.rs b/components/script_layout_interface/wrapper_traits.rs index 4abc74bcac0..bb7d1e373cf 100644 --- a/components/script_layout_interface/wrapper_traits.rs +++ b/components/script_layout_interface/wrapper_traits.rs @@ -15,7 +15,6 @@ use msg::constellation_msg::PipelineId; use range::Range; use servo_url::ServoUrl; use std::fmt::Debug; -use std::sync::Arc; use style::computed_values::display; use style::context::SharedStyleContext; use style::data::ElementData; @@ -24,6 +23,7 @@ use style::dom::OpaqueNode; use style::font_metrics::ServoMetricsProvider; use style::properties::{CascadeFlags, ServoComputedValues}; use style::selector_parser::{PseudoElement, PseudoElementCascadeType, SelectorImpl}; +use style::stylearc::Arc; use webrender_traits::ClipId; #[derive(Copy, PartialEq, Clone, Debug)] From 7dba36ed73de4ea00a8bd2e7690312f3e51440a9 Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Tue, 2 May 2017 11:08:31 -0700 Subject: [PATCH 08/12] Make StyleBuilder more efficient using stylearc. MozReview-Commit-ID: 8wSsYPEmYE4 --- components/style/properties/properties.mako.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs index 83ca3e3d4fb..ff2361fb792 100644 --- a/components/style/properties/properties.mako.rs +++ b/components/style/properties/properties.mako.rs @@ -2056,7 +2056,7 @@ pub enum StyleStructRef<'a, T: 'a> { /// A borrowed struct from the parent, for example, for inheriting style. Borrowed(&'a Arc), /// An owned struct, that we've already mutated. - Owned(T), + Owned(Arc), } impl<'a, T: 'a> StyleStructRef<'a, T> @@ -2066,11 +2066,11 @@ impl<'a, T: 'a> StyleStructRef<'a, T> /// borrowed value, or returning the owned one. pub fn mutate(&mut self) -> &mut T { if let StyleStructRef::Borrowed(v) = *self { - *self = StyleStructRef::Owned((**v).clone()); + *self = StyleStructRef::Owned(Arc::new((**v).clone())); } match *self { - StyleStructRef::Owned(ref mut v) => v, + StyleStructRef::Owned(ref mut v) => Arc::get_mut(v).unwrap(), StyleStructRef::Borrowed(..) => unreachable!(), } } @@ -2079,7 +2079,7 @@ impl<'a, T: 'a> StyleStructRef<'a, T> /// hasn't been mutated. pub fn get_if_mutated(&mut self) -> Option<<&mut T> { match *self { - StyleStructRef::Owned(ref mut v) => Some(v), + StyleStructRef::Owned(ref mut v) => Some(Arc::get_mut(v).unwrap()), StyleStructRef::Borrowed(..) => None, } } @@ -2088,7 +2088,7 @@ impl<'a, T: 'a> StyleStructRef<'a, T> /// appropriate. pub fn build(self) -> Arc { match self { - StyleStructRef::Owned(v) => Arc::new(v), + StyleStructRef::Owned(v) => v, StyleStructRef::Borrowed(v) => v.clone(), } } @@ -2099,7 +2099,7 @@ impl<'a, T: 'a> Deref for StyleStructRef<'a, T> { fn deref(&self) -> &T { match *self { - StyleStructRef::Owned(ref v) => v, + StyleStructRef::Owned(ref v) => &**v, StyleStructRef::Borrowed(v) => &**v, } } From fd1c814e7812e68e1207165c9387ddcfd8a6379b Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Tue, 2 May 2017 17:59:53 -0700 Subject: [PATCH 09/12] Bump the DOM element sizes. This will go back down soonish when NonZero stablizes and we can use it in StyleArc, which I expect will be long before the memory overhead here matters. --- tests/unit/script/size_of.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/unit/script/size_of.rs b/tests/unit/script/size_of.rs index a328bcbf6f5..c319c0b77c5 100644 --- a/tests/unit/script/size_of.rs +++ b/tests/unit/script/size_of.rs @@ -31,10 +31,10 @@ macro_rules! sizeof_checker ( // Update the sizes here sizeof_checker!(size_event_target, EventTarget, 40); sizeof_checker!(size_node, Node, 152); -sizeof_checker!(size_element, Element, 320); -sizeof_checker!(size_htmlelement, HTMLElement, 336); -sizeof_checker!(size_div, HTMLDivElement, 336); -sizeof_checker!(size_span, HTMLSpanElement, 336); +sizeof_checker!(size_element, Element, 328); +sizeof_checker!(size_htmlelement, HTMLElement, 344); +sizeof_checker!(size_div, HTMLDivElement, 344); +sizeof_checker!(size_span, HTMLSpanElement, 344); sizeof_checker!(size_text, Text, 184); sizeof_checker!(size_characterdata, CharacterData, 184); sizeof_checker!(size_servothreadsafelayoutnode, ServoThreadSafeLayoutNode, 16); From b298a2bb8e667befdd93eb5ace2f5178e043fec3 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Tue, 2 May 2017 09:57:34 -0700 Subject: [PATCH 10/12] Do not inherit kw font size if it was not used due to MathML --- components/style/properties/gecko.mako.rs | 7 ++++++- components/style/properties/longhand/font.mako.rs | 10 +++++++--- components/style/properties/properties.mako.rs | 3 ++- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index 5d09b9472e8..15a77838e31 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -1490,8 +1490,10 @@ fn static_assert() { /// This function will also handle scriptminsize and scriptlevel /// so should not be called when you just want the font sizes to be copied. /// Hence the different name. + /// + /// Returns true if the inherited keyword size was actually used pub fn inherit_font_size_from(&mut self, parent: &Self, - kw_inherited_size: Option) { + kw_inherited_size: Option) -> bool { let (adjusted_size, adjusted_unconstrained_size) = self.calculate_script_level_size(parent); if adjusted_size.0 != parent.gecko.mSize || @@ -1513,18 +1515,21 @@ fn static_assert() { self.gecko.mFont.size = adjusted_size.0; self.gecko.mSize = adjusted_size.0; self.gecko.mScriptUnconstrainedSize = adjusted_unconstrained_size.0; + false } else if let Some(size) = kw_inherited_size { // Parent element was a keyword-derived size. self.gecko.mFont.size = size.0; self.gecko.mSize = size.0; // MathML constraints didn't apply here, so we can ignore this. self.gecko.mScriptUnconstrainedSize = size.0; + true } else { // MathML isn't affecting us, and our parent element does not // have a keyword-derived size. Set things normally. self.gecko.mFont.size = parent.gecko.mFont.size; self.gecko.mSize = parent.gecko.mSize; self.gecko.mScriptUnconstrainedSize = parent.gecko.mScriptUnconstrainedSize; + false } } diff --git a/components/style/properties/longhand/font.mako.rs b/components/style/properties/longhand/font.mako.rs index e99b15dd9cf..842b3279d90 100644 --- a/components/style/properties/longhand/font.mako.rs +++ b/components/style/properties/longhand/font.mako.rs @@ -927,10 +927,14 @@ ${helpers.single_keyword_system("font-variant-caps", let kw_inherited_size = context.style().font_size_keyword.map(|(kw, ratio)| { SpecifiedValue::Keyword(kw, ratio).to_computed_value(context) }); - context.mutate_style().mutate_font() + let used_kw = context.mutate_style().mutate_font() .inherit_font_size_from(parent, kw_inherited_size); - context.mutate_style().font_size_keyword = - context.inherited_style.font_size_keyword; + if used_kw { + context.mutate_style().font_size_keyword = + context.inherited_style.font_size_keyword; + } else { + context.mutate_style().font_size_keyword = None; + } } pub fn cascade_initial_font_size(context: &mut Context) { diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs index be94b96b5f0..5d3d648d306 100644 --- a/components/style/properties/properties.mako.rs +++ b/components/style/properties/properties.mako.rs @@ -1538,8 +1538,9 @@ pub mod style_structs { /// (Servo does not handle MathML, so this just calls copy_font_size_from) pub fn inherit_font_size_from(&mut self, parent: &Self, - _: Option) { + _: Option) -> bool { self.copy_font_size_from(parent); + false } /// (Servo does not handle MathML, so this just calls set_font_size) pub fn apply_font_size(&mut self, From a46960dbfa7e70e32b9bfc9a824fd64409a54c06 Mon Sep 17 00:00:00 2001 From: Boris Chiou Date: Wed, 3 May 2017 11:19:23 +0800 Subject: [PATCH 11/12] Bug 1346052 - Add Servo_AnimationValue_Compute for AnimationValue::FromString. We need this FFI to compute the AnimationValue from a property id and a string. --- components/style/gecko_bindings/bindings.rs | 18 +++++++--- ports/geckolib/glue.rs | 39 +++++++++++++++++++++ 2 files changed, 53 insertions(+), 4 deletions(-) diff --git a/components/style/gecko_bindings/bindings.rs b/components/style/gecko_bindings/bindings.rs index 1b3560dc849..4099761c6c3 100644 --- a/components/style/gecko_bindings/bindings.rs +++ b/components/style/gecko_bindings/bindings.rs @@ -1074,10 +1074,6 @@ extern "C" { pub fn Gecko_CSSValue_GetAbsoluteLength(css_value: nsCSSValueBorrowed) -> nscoord; } -extern "C" { - pub fn Gecko_GetAppUnitsPerPhysicalInch(pres_context: RawGeckoPresContextBorrowed) - -> i32; -} extern "C" { pub fn Gecko_CSSValue_GetKeyword(aCSSValue: nsCSSValueBorrowed) -> nsCSSKeyword; @@ -1172,6 +1168,11 @@ extern "C" { font_size: nscoord, use_user_font_set: bool) -> GeckoFontMetrics; } +extern "C" { + pub fn Gecko_GetAppUnitsPerPhysicalInch(pres_context: + RawGeckoPresContextBorrowed) + -> i32; +} extern "C" { pub fn Gecko_GetMediaFeatures() -> *const nsMediaFeature; } @@ -1855,6 +1856,15 @@ extern "C" { RawServoAnimationValueBorrowed) -> RawServoDeclarationBlockStrong; } +extern "C" { + pub fn Servo_AnimationValue_Compute(declarations: + RawServoDeclarationBlockBorrowed, + style: ServoComputedValuesBorrowed, + parent_style: + ServoComputedValuesBorrowedOrNull, + raw_data: RawServoStyleSetBorrowed) + -> RawServoAnimationValueStrong; +} extern "C" { pub fn Servo_ParseStyleAttribute(data: *const nsACString, extra_data: *mut RawGeckoURLExtraData) diff --git a/ports/geckolib/glue.rs b/ports/geckolib/glue.rs index f53a47f0af7..c0d41d03ca3 100644 --- a/ports/geckolib/glue.rs +++ b/ports/geckolib/glue.rs @@ -2066,6 +2066,45 @@ pub extern "C" fn Servo_GetComputedKeyframeValues(keyframes: RawGeckoKeyframeLis } } +#[no_mangle] +pub extern "C" fn Servo_AnimationValue_Compute(declarations: RawServoDeclarationBlockBorrowed, + style: ServoComputedValuesBorrowed, + parent_style: ServoComputedValuesBorrowedOrNull, + raw_data: RawServoStyleSetBorrowed) + -> RawServoAnimationValueStrong { + use style::values::computed::Context; + + let data = PerDocumentStyleData::from_ffi(raw_data).borrow(); + let style = ComputedValues::as_arc(&style); + let parent_style = parent_style.as_ref().map(|r| &**ComputedValues::as_arc(&r)); + let default_values = data.default_computed_values(); + let metrics = get_metrics_provider_for_product(); + let mut context = Context { + is_root_element: false, + device: &data.stylist.device, + inherited_style: parent_style.unwrap_or(default_values), + layout_parent_style: parent_style.unwrap_or(default_values), + style: StyleBuilder::for_derived_style(&style), + font_metrics_provider: &metrics, + cached_system_font: None, + in_media_query: false, + quirks_mode: QuirksMode::NoQuirks, + }; + + let global_style_data = &*GLOBAL_STYLE_DATA; + let guard = global_style_data.shared_lock.read(); + let declarations = Locked::::as_arc(&declarations); + // We only compute the first element in declarations. + match declarations.read_with(&guard).declarations().first() { + Some(&(ref decl, imp)) if imp == Importance::Normal => { + let animation = AnimationValue::from_declaration(decl, &mut context, default_values); + animation.map_or(RawServoAnimationValueStrong::null(), |value| { + Arc::new(value).into_strong() + }) + }, + _ => RawServoAnimationValueStrong::null() + } +} #[no_mangle] pub extern "C" fn Servo_AssertTreeIsClean(root: RawGeckoElementBorrowed) { From f3f9e28e88f92a08a042006d985cda56ce823af1 Mon Sep 17 00:00:00 2001 From: Josh Matthews Date: Sat, 29 Apr 2017 10:03:02 -0400 Subject: [PATCH 12/12] Make unit tests pass on TravisCI. --- .travis.yml | 2 +- components/selectors/Cargo.toml | 2 ++ components/style/restyle_hints.rs | 41 +++++++++++-------------------- python/servo/testing_commands.py | 4 +++ tests/unit/style/lib.rs | 1 + tests/unit/style/restyle_hints.rs | 31 +++++++++++++++++++++++ 6 files changed, 53 insertions(+), 28 deletions(-) create mode 100644 tests/unit/style/restyle_hints.rs diff --git a/.travis.yml b/.travis.yml index d6dc6cc89b4..534ecf3f1af 100644 --- a/.travis.yml +++ b/.travis.yml @@ -22,7 +22,7 @@ matrix: - bash etc/ci/lockfile_changed.sh - bash etc/ci/manifest_changed.sh - ./mach cargo test -p selectors - - ./mach cargo test -p style + - ./mach test-unit -p style cache: directories: - .cargo diff --git a/components/selectors/Cargo.toml b/components/selectors/Cargo.toml index 9e5e9df6f35..22ee4e526c2 100644 --- a/components/selectors/Cargo.toml +++ b/components/selectors/Cargo.toml @@ -14,6 +14,8 @@ license = "MPL-2.0" [lib] name = "selectors" path = "lib.rs" +# https://github.com/servo/servo/issues/16710 +doctest = false [dependencies] bitflags = "0.7" diff --git a/components/style/restyle_hints.rs b/components/style/restyle_hints.rs index 193b7e82a9d..0e7dcd19adc 100644 --- a/components/style/restyle_hints.rs +++ b/components/style/restyle_hints.rs @@ -431,8 +431,11 @@ fn combinator_to_restyle_hint(combinator: Option) -> RestyleHint { #[derive(Debug)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] -struct Sensitivities { +/// The aspects of an selector which are sensitive. +pub struct Sensitivities { + /// The states which are sensitive. pub states: ElementState, + /// Whether attributes are sensitive. pub attrs: bool, } @@ -469,11 +472,13 @@ impl Sensitivities { /// change may have on the style of elements in the document. #[derive(Debug)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] -struct Dependency { +pub struct Dependency { #[cfg_attr(feature = "servo", ignore_heap_size_of = "Arc")] selector: SelectorInner, - hint: RestyleHint, - sensitivities: Sensitivities, + /// The hint associated with this dependency. + pub hint: RestyleHint, + /// The sensitivities associated with this dependency. + pub sensitivities: Sensitivities, } @@ -681,27 +686,9 @@ impl DependencySet { } } } -} - -#[test] -#[cfg(all(test, feature = "servo"))] -fn smoke_restyle_hints() { - use cssparser::Parser; - use selector_parser::SelectorParser; - use stylesheets::{Origin, Namespaces}; - let namespaces = Namespaces::default(); - let parser = SelectorParser { - stylesheet_origin: Origin::Author, - namespaces: &namespaces, - }; - - let mut dependencies = DependencySet::new(); - - let mut p = Parser::new(":not(:active) ~ label"); - let selector = ComplexSelector::parse(&parser, &mut p).unwrap(); - dependencies.note_selector(&selector); - assert_eq!(dependencies.len(), 1); - assert_eq!(dependencies.state_deps.len(), 1); - assert!(!dependencies.state_deps[0].sensitivities.states.is_empty()); - assert!(dependencies.state_deps[0].hint.contains(RESTYLE_LATER_SIBLINGS)); + + /// Get the dependencies affected by state. + pub fn get_state_deps(&self) -> &[Dependency] { + &self.state_deps + } } diff --git a/python/servo/testing_commands.py b/python/servo/testing_commands.py index 70c90eab136..64d79e38501 100644 --- a/python/servo/testing_commands.py +++ b/python/servo/testing_commands.py @@ -231,8 +231,10 @@ class MachCommands(CommandBase): else: test_patterns.append(test) + in_crate_packages = [] if not packages: packages = set(os.listdir(path.join(self.context.topdir, "tests", "unit"))) - set(['.DS_Store']) + in_crate_packages += ["selectors"] packages.discard('stylo') @@ -255,6 +257,8 @@ class MachCommands(CommandBase): args = ["cargo", "bench" if bench else "test"] for crate in packages: args += ["-p", "%s_tests" % crate] + for crate in in_crate_packages: + args += ["-p", crate] args += test_patterns if features: diff --git a/tests/unit/style/lib.rs b/tests/unit/style/lib.rs index baddd4da618..1b0b6f2d853 100644 --- a/tests/unit/style/lib.rs +++ b/tests/unit/style/lib.rs @@ -27,6 +27,7 @@ mod logical_geometry; mod media_queries; mod parsing; mod properties; +mod restyle_hints; mod rule_tree; mod size_of; mod str; diff --git a/tests/unit/style/restyle_hints.rs b/tests/unit/style/restyle_hints.rs new file mode 100644 index 00000000000..9a050e05fb5 --- /dev/null +++ b/tests/unit/style/restyle_hints.rs @@ -0,0 +1,31 @@ +/* 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/. */ + +#[test] +fn smoke_restyle_hints() { + use cssparser::Parser; + use selectors::parser::SelectorList; + use style::restyle_hints::{DependencySet, RESTYLE_LATER_SIBLINGS}; + use style::selector_parser::SelectorParser; + use style::stylesheets::{Origin, Namespaces}; + let namespaces = Namespaces::default(); + let parser = SelectorParser { + stylesheet_origin: Origin::Author, + namespaces: &namespaces, + }; + + let mut dependencies = DependencySet::new(); + + let mut p = Parser::new(":not(:active) ~ label"); + let selectors = SelectorList::parse(&parser, &mut p).unwrap(); + assert_eq!((selectors.0).len(), 1); + + let selector = (selectors.0).first().unwrap(); + dependencies.note_selector(selector); + assert_eq!(dependencies.len(), 1); + let state_deps = dependencies.get_state_deps(); + assert_eq!(state_deps.len(), 1); + assert!(!state_deps[0].sensitivities.states.is_empty()); + assert!(state_deps[0].hint.contains(RESTYLE_LATER_SIBLINGS)); +}