diff options
81 files changed, 1255 insertions, 1191 deletions
diff --git a/.travis.yml b/.travis.yml index 2572ae3ddfd..81f6dc4aba8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,6 +15,8 @@ matrix: directories: - .cargo - .servo + - $HOME/.ccache + env: CCACHE=/usr/bin/ccache addons: apt: packages: @@ -24,6 +26,7 @@ matrix: - libosmesa6-dev - python-virtualenv - xorg-dev + - ccache branches: only: diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f5768fee4c4..a2dae5456fc 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -12,7 +12,8 @@ pull requests. Each pull request will be reviewed by a core contributor given feedback for changes that would be required. All contributions should follow this format, even those from core contributors. -If you're looking for easy bugs, have a look at the [E-Easy issue tag](https://github.com/servo/servo/labels/E-easy) on GitHub. +Head over to [Servo Starters](http://servo.github.io/servo-starters/) to find +good tasks to start with. See [`HACKING_QUICKSTART.md`](HACKING_QUICKSTART.md) for more information on how to start working on Servo. @@ -23,6 +24,9 @@ on how to start working on Servo. branch before submitting your pull request. If it doesn't merge cleanly with master you may be asked to rebase your changes. +- Commits should be as small as possible, while ensuring that each commit is + correct independently (i.e., each commit should compile and pass tests). + - Don't put submodule updates in your pull request unless they are to landed commits. diff --git a/HACKING_QUICKSTART.md b/HACKING_QUICKSTART.md index 53e2e346eef..84c206650f1 100644 --- a/HACKING_QUICKSTART.md +++ b/HACKING_QUICKSTART.md @@ -36,7 +36,7 @@ If you build with `-d`, run with `-d`. If you build with `-r`, run with `-r`. ## ./mach -`mach` is a python utility that does plenty of things to make our life easier (build, run, run tests, udpate dependencies… see `./mach --help`). Beside editing files and git commands, everything else is done via `mach`. +`mach` is a python utility that does plenty of things to make our life easier (build, run, run tests, update dependencies… see `./mach --help`). Beside editing files and git commands, everything else is done via `mach`. ``` shell ./mach run -d [mach options] -- [servo options] @@ -178,7 +178,7 @@ usually just works. If it doesn't, maybe foobar's properties implement the right To run the debugger: ``` shell -./mach -d --debug -- -y 1 -t 1 /tmp/a.html +./mach run -d --debug -- -y 1 -t 1 /tmp/a.html ``` This will start `lldb` on Mac, and `gdb` on Linux. @@ -241,7 +241,7 @@ To run a test: In some cases extensive tests for the feature you're working on may already exist under tests/wpt: - Make a release build -- run `./mach -r test-wpt --log-raw=/path/to/some/logfile` +- run `./mach test-wpt --release --log-raw=/path/to/some/logfile` - run [`update-wpt` on it](https://github.com/servo/servo/blob/master/tests/wpt/README.md#updating-test-expectations) This may create a new commit with changes to expectation ini files. If there are lots of changes, diff --git a/components/canvas/Cargo.toml b/components/canvas/Cargo.toml index 37276b5baf0..e3300568270 100644 --- a/components/canvas/Cargo.toml +++ b/components/canvas/Cargo.toml @@ -34,11 +34,8 @@ features = ["texture_surface"] [dependencies.ipc-channel] git = "https://github.com/pcwalton/ipc-channel" -[dependencies.cssparser] -version = "0.3" -features = [ "serde-serialization" ] - [dependencies] +cssparser = { version = "0.4", features = [ "serde-serialization" ] } log = "0.3" num = "0.1.24" gleam = "0.1" diff --git a/components/canvas_traits/Cargo.toml b/components/canvas_traits/Cargo.toml index cd854a761b9..ec49ede4d32 100644 --- a/components/canvas_traits/Cargo.toml +++ b/components/canvas_traits/Cargo.toml @@ -28,10 +28,6 @@ git = "https://github.com/pcwalton/ipc-channel" version = "0.6" features = [ "nightly" ] -[dependencies.cssparser] -version = "0.3" -features = [ "serde-serialization" ] - [dependencies.plugins] path = "../plugins" @@ -39,6 +35,7 @@ path = "../plugins" path = "../util" [dependencies] +cssparser = { version = "0.4", features = [ "serde-serialization" ] } euclid = {version = "0.3", features = ["plugins"]} serde_macros = "0.6" diff --git a/components/compositing/compositor.rs b/components/compositing/compositor.rs index 83e18d51562..58efffe6d6c 100644 --- a/components/compositing/compositor.rs +++ b/components/compositing/compositor.rs @@ -2011,13 +2011,11 @@ impl<Window: WindowMethods> IOCompositor<Window> { } } - pub fn cache_unused_buffers(&mut self, buffers: Vec<Box<LayerBuffer>>) { - if !buffers.is_empty() { - let surfaces = buffers.into_iter().map(|buffer| { - buffer.native_surface - }).collect(); - self.surface_map.insert_surfaces(&self.native_display, surfaces); - } + pub fn cache_unused_buffers<B>(&mut self, buffers: B) + where B: IntoIterator<Item=Box<LayerBuffer>> + { + let surfaces = buffers.into_iter().map(|buffer| buffer.native_surface); + self.surface_map.insert_surfaces(&self.native_display, surfaces); } #[allow(dead_code)] @@ -2107,14 +2105,9 @@ fn find_layer_with_pipeline_and_layer_id_for_layer(layer: Rc<Layer<CompositorDat impl<Window> CompositorEventListener for IOCompositor<Window> where Window: WindowMethods { fn handle_events(&mut self, messages: Vec<WindowEvent>) -> bool { // Check for new messages coming from the other tasks in the system. - loop { - match self.port.try_recv_compositor_msg() { - None => break, - Some(msg) => { - if !self.handle_browser_message(msg) { - break - } - } + while let Some(msg) = self.port.try_recv_compositor_msg() { + if !self.handle_browser_message(msg) { + break } } diff --git a/components/compositing/compositor_task.rs b/components/compositing/compositor_task.rs index b9d73c6b25d..fe8d82e26aa 100644 --- a/components/compositing/compositor_task.rs +++ b/components/compositing/compositor_task.rs @@ -48,10 +48,7 @@ pub trait CompositorReceiver : 'static { /// A convenience implementation of `CompositorReceiver` for a plain old Rust `Receiver`. impl CompositorReceiver for Receiver<Msg> { fn try_recv_compositor_msg(&mut self) -> Option<Msg> { - match self.try_recv() { - Ok(msg) => Some(msg), - Err(_) => None, - } + self.try_recv().ok() } fn recv_compositor_msg(&mut self) -> Msg { self.recv().unwrap() diff --git a/components/compositing/constellation.rs b/components/compositing/constellation.rs index adfb9fb5b21..c4b1c9bd5d4 100644 --- a/components/compositing/constellation.rs +++ b/components/compositing/constellation.rs @@ -25,7 +25,7 @@ use msg::compositor_msg::Epoch; use msg::constellation_msg::AnimationState; use msg::constellation_msg::Msg as ConstellationMsg; use msg::constellation_msg::WebDriverCommandMsg; -use msg::constellation_msg::{FrameId, PipelineExitType, PipelineId}; +use msg::constellation_msg::{FrameId, PipelineId}; use msg::constellation_msg::{IframeLoadInfo, IFrameSandboxState, MozBrowserEvent, NavigationDirection}; use msg::constellation_msg::{Key, KeyModifiers, KeyState, LoadData}; use msg::constellation_msg::{PipelineNamespace, PipelineNamespaceId}; @@ -565,7 +565,7 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> { fn handle_exit(&mut self) { for (_id, ref pipeline) in &self.pipelines { - pipeline.exit(PipelineExitType::Complete); + pipeline.exit(); } self.image_cache_task.exit(); self.resource_task.send(net_traits::ControlMsg::Exit).unwrap(); @@ -1356,7 +1356,7 @@ impl<LTF: LayoutTaskFactory, STF: ScriptTaskFactory> Constellation<LTF, STF> { // Inform script, compositor that this pipeline has exited. match exit_mode { - ExitPipelineMode::Normal => pipeline.exit(PipelineExitType::PipelineOnly), + ExitPipelineMode::Normal => pipeline.exit(), ExitPipelineMode::Force => pipeline.force_exit(), } } diff --git a/components/compositing/pipeline.rs b/components/compositing/pipeline.rs index ad425224d26..4cc8b87f14a 100644 --- a/components/compositing/pipeline.rs +++ b/components/compositing/pipeline.rs @@ -15,7 +15,7 @@ use ipc_channel::router::ROUTER; use layers::geometry::DevicePixel; use layout_traits::{LayoutControlChan, LayoutTaskFactory}; use msg::constellation_msg::{ConstellationChan, Failure, FrameId, PipelineId, SubpageId}; -use msg::constellation_msg::{LoadData, MozBrowserEvent, PipelineExitType, WindowSizeData}; +use msg::constellation_msg::{LoadData, MozBrowserEvent, WindowSizeData}; use msg::constellation_msg::{PipelineNamespaceId}; use net_traits::ResourceTask; use net_traits::image_cache_task::ImageCacheTask; @@ -248,13 +248,13 @@ impl Pipeline { let _ = self.chrome_to_paint_chan.send(ChromeToPaintMsg::PaintPermissionRevoked); } - pub fn exit(&self, exit_type: PipelineExitType) { + pub fn exit(&self) { debug!("pipeline {:?} exiting", self.id); // Script task handles shutting down layout, and layout handles shutting down the painter. // For now, if the script task has failed, we give up on clean shutdown. if self.script_chan - .send(ConstellationControlMsg::ExitPipeline(self.id, exit_type)) + .send(ConstellationControlMsg::ExitPipeline(self.id)) .is_ok() { // Wait until all slave tasks have terminated and run destructors // NOTE: We don't wait for script task as we don't always own it @@ -275,15 +275,10 @@ impl Pipeline { } pub fn force_exit(&self) { - let _ = self.script_chan.send( - ConstellationControlMsg::ExitPipeline(self.id, - PipelineExitType::PipelineOnly)).unwrap(); - let _ = self.chrome_to_paint_chan.send(ChromeToPaintMsg::Exit( - None, - PipelineExitType::PipelineOnly)); + let _ = self.script_chan.send(ConstellationControlMsg::ExitPipeline(self.id)).unwrap(); + let _ = self.chrome_to_paint_chan.send(ChromeToPaintMsg::Exit); let LayoutControlChan(ref layout_channel) = self.layout_chan; - let _ = layout_channel.send( - LayoutControlMsg::ExitNow(PipelineExitType::PipelineOnly)).unwrap(); + let _ = layout_channel.send(LayoutControlMsg::ExitNow).unwrap(); } pub fn to_sendable(&self) -> CompositionPipeline { diff --git a/components/compositing/scrolling.rs b/components/compositing/scrolling.rs index df266f1741e..c4f4be7804c 100644 --- a/components/compositing/scrolling.rs +++ b/components/compositing/scrolling.rs @@ -54,16 +54,11 @@ impl ScrollingTimerProxy { impl ScrollingTimer { pub fn run(&mut self) { - loop { - match self.receiver.recv() { - Ok(ToScrollingTimerMsg::ScrollEventProcessedMsg(timestamp)) => { - let target = timestamp as i64 + TIMEOUT; - let delta_ns = target - (time::precise_time_ns() as i64); - sleep_ms((delta_ns / 1000000) as u32); - self.compositor_proxy.send(Msg::ScrollTimeout(timestamp)); - } - Ok(ToScrollingTimerMsg::ExitMsg) | Err(_) => break, - } + while let Ok(ToScrollingTimerMsg::ScrollEventProcessedMsg(timestamp)) = self.receiver.recv() { + let target = timestamp as i64 + TIMEOUT; + let delta_ns = target - (time::precise_time_ns() as i64); + sleep_ms((delta_ns / 1000000) as u32); + self.compositor_proxy.send(Msg::ScrollTimeout(timestamp)); } } } diff --git a/components/compositing/surface_map.rs b/components/compositing/surface_map.rs index b773cd86e97..09a3b733dd9 100644 --- a/components/compositing/surface_map.rs +++ b/components/compositing/surface_map.rs @@ -68,7 +68,9 @@ impl SurfaceMap { } } - pub fn insert_surfaces(&mut self, display: &NativeDisplay, surfaces: Vec<NativeSurface>) { + pub fn insert_surfaces<I>(&mut self, display: &NativeDisplay, surfaces: I) + where I: IntoIterator<Item=NativeSurface> + { for surface in surfaces { self.insert(display, surface); } diff --git a/components/gfx/paint_task.rs b/components/gfx/paint_task.rs index cd996c5b8f2..926aa2fe123 100644 --- a/components/gfx/paint_task.rs +++ b/components/gfx/paint_task.rs @@ -22,7 +22,7 @@ use layers::platform::surface::{NativeDisplay, NativeSurface}; use msg::compositor_msg::{Epoch, FrameTreeId, LayerId, LayerKind, LayerProperties}; use msg::compositor_msg::{PaintListener, ScrollPolicy}; use msg::constellation_msg::Msg as ConstellationMsg; -use msg::constellation_msg::{ConstellationChan, Failure, PipelineExitType, PipelineId}; +use msg::constellation_msg::{ConstellationChan, Failure, PipelineId}; use paint_context::PaintContext; use profile_traits::mem::{self, ReportsChan}; use profile_traits::time::{self, profile}; @@ -197,7 +197,7 @@ pub enum Msg { pub enum LayoutToPaintMsg { PaintInit(Epoch, PaintLayer), CanvasLayer(LayerId, IpcSender<CanvasMsg>), - Exit(Option<IpcSender<()>>, PipelineExitType), + Exit(IpcSender<()>), } pub enum ChromeToPaintMsg { @@ -205,7 +205,7 @@ pub enum ChromeToPaintMsg { PaintPermissionGranted, PaintPermissionRevoked, CollectReports(ReportsChan), - Exit(Option<IpcSender<()>>, PipelineExitType), + Exit, } pub struct PaintTask<C> { @@ -382,14 +382,21 @@ impl<C> PaintTask<C> where C: PaintListener + Send + 'static { // FIXME(njn): should eventually measure the paint task. channel.send(Vec::new()) } - Msg::FromLayout(LayoutToPaintMsg::Exit(ref response_channel, _)) | - Msg::FromChrome(ChromeToPaintMsg::Exit(ref response_channel, _)) => { + Msg::FromLayout(LayoutToPaintMsg::Exit(ref response_channel)) => { + // Ask the compositor to remove any layers it is holding for this paint task. + // FIXME(mrobinson): This can probably move back to the constellation now. + self.compositor.notify_paint_task_exiting(self.id); + + debug!("PaintTask: Exiting."); + let _ = response_channel.send(()); + break; + } + Msg::FromChrome(ChromeToPaintMsg::Exit) => { // Ask the compositor to remove any layers it is holding for this paint task. // FIXME(mrobinson): This can probably move back to the constellation now. self.compositor.notify_paint_task_exiting(self.id); debug!("PaintTask: Exiting."); - response_channel.as_ref().map(|channel| channel.send(())); break; } } diff --git a/components/layout/Cargo.toml b/components/layout/Cargo.toml index 10af4f1566d..8697897c7b5 100644 --- a/components/layout/Cargo.toml +++ b/components/layout/Cargo.toml @@ -50,16 +50,9 @@ path = "../profile_traits" [dependencies.util] path = "../util" -[dependencies.selectors] -git = "https://github.com/servo/rust-selectors" - [dependencies.clock_ticks] git = "https://github.com/tomaka/clock_ticks" -[dependencies.cssparser] -version = "0.3" -features = [ "serde-serialization" ] - [dependencies.ipc-channel] git = "https://github.com/pcwalton/ipc-channel" @@ -69,12 +62,14 @@ features = [ "serde_serialization" ] [dependencies] app_units = {version = "0.1", features = ["plugins"]} +cssparser = { version = "0.4", features = [ "serde-serialization" ] } log = "0.3" encoding = "0.2" fnv = "1.0" bitflags = "0.3" rustc-serialize = "0.3" libc = "0.1" +selectors = "0.2" smallvec = "0.1" string_cache = "0.1" string_cache_plugin = "0.1" diff --git a/components/layout/animation.rs b/components/layout/animation.rs index 27bf118bfda..7b58e435681 100644 --- a/components/layout/animation.rs +++ b/components/layout/animation.rs @@ -14,14 +14,14 @@ use script::layout_interface::Animation; use script_traits::ConstellationControlMsg; use std::collections::HashMap; use std::collections::hash_map::Entry; -use std::sync::Arc; use std::sync::mpsc::Sender; +use std::sync::{Arc, Mutex}; use style::animation::{GetMod, PropertyAnimation}; use style::properties::ComputedValues; /// Inserts transitions into the queue of running animations as applicable for the given style /// difference. This is called from the layout worker threads. -pub fn start_transitions_if_applicable(new_animations_sender: &Sender<Animation>, +pub fn start_transitions_if_applicable(new_animations_sender: &Mutex<Sender<Animation>>, node: OpaqueNode, old_style: &ComputedValues, new_style: &mut ComputedValues) { @@ -37,7 +37,7 @@ pub fn start_transitions_if_applicable(new_animations_sender: &Sender<Animation> let animation_style = new_style.get_animation(); let start_time = now + (animation_style.transition_delay.0.get_mod(i).seconds() as f64); - new_animations_sender.send(Animation { + new_animations_sender.lock().unwrap().send(Animation { node: node.id(), property_animation: property_animation, start_time: start_time, diff --git a/components/layout/context.rs b/components/layout/context.rs index f3db3d80a01..f6058eaaf44 100644 --- a/components/layout/context.rs +++ b/components/layout/context.rs @@ -16,17 +16,16 @@ use gfx::font_cache_task::FontCacheTask; use gfx::font_context::FontContext; use ipc_channel::ipc::{self, IpcSender}; use msg::compositor_msg::LayerId; -use msg::constellation_msg::ConstellationChan; use net_traits::image::base::Image; use net_traits::image_cache_task::{ImageCacheChan, ImageCacheTask, ImageResponse, ImageState}; use net_traits::image_cache_task::{UsePlaceholder}; -use script::layout_interface::{Animation, LayoutChan, ReflowGoal}; +use script::layout_interface::{Animation, ReflowGoal}; use std::cell::{RefCell, RefMut}; use std::collections::HashMap; use std::collections::hash_state::DefaultState; use std::rc::Rc; -use std::sync::Arc; use std::sync::mpsc::{Sender, channel}; +use std::sync::{Arc, Mutex}; use style::selector_matching::Stylist; use url::Url; use util::mem::HeapSizeOf; @@ -63,8 +62,9 @@ fn create_or_get_local_context(shared_layout_context: &SharedLayoutContext) } context } else { + let font_cache_task = shared_layout_context.font_cache_task.lock().unwrap().clone(); let context = Rc::new(LocalLayoutContext { - font_context: RefCell::new(FontContext::new(shared_layout_context.font_cache_task.clone())), + font_context: RefCell::new(FontContext::new(font_cache_task)), applicable_declarations_cache: RefCell::new(ApplicableDeclarationsCache::new()), style_sharing_candidate_cache: RefCell::new(StyleSharingCandidateCache::new()), }); @@ -74,13 +74,19 @@ fn create_or_get_local_context(shared_layout_context: &SharedLayoutContext) }) } +pub struct StylistWrapper(pub *const Stylist); + +// FIXME(#6569) This implementation is unsound. +#[allow(unsafe_code)] +unsafe impl Sync for StylistWrapper {} + /// Layout information shared among all workers. This must be thread-safe. pub struct SharedLayoutContext { /// The shared image cache task. pub image_cache_task: ImageCacheTask, /// A channel for the image cache to send responses to. - pub image_cache_sender: ImageCacheChan, + pub image_cache_sender: Mutex<ImageCacheChan>, /// The current viewport size. pub viewport_size: Size2D<Au>, @@ -88,19 +94,13 @@ pub struct SharedLayoutContext { /// Screen sized changed? pub screen_size_changed: bool, - /// A channel up to the constellation. - pub constellation_chan: ConstellationChan, - - /// A channel up to the layout task. - pub layout_chan: LayoutChan, - /// Interface to the font cache task. - pub font_cache_task: FontCacheTask, + pub font_cache_task: Mutex<FontCacheTask>, /// The CSS selector stylist. /// /// FIXME(#2604): Make this no longer an unsafe pointer once we have fast `RWArc`s. - pub stylist: *const Stylist, + pub stylist: StylistWrapper, /// The URL. pub url: Url, @@ -111,10 +111,10 @@ pub struct SharedLayoutContext { /// A channel on which new animations that have been triggered by style recalculation can be /// sent. - pub new_animations_sender: Sender<Animation>, + pub new_animations_sender: Mutex<Sender<Animation>>, /// A channel to send canvas renderers to paint task, in order to correctly paint the layers - pub canvas_layers_sender: Sender<(LayerId, IpcSender<CanvasMsg>)>, + pub canvas_layers_sender: Mutex<Sender<(LayerId, IpcSender<CanvasMsg>)>>, /// The visible rects for each layer, as reported to us by the compositor. pub visible_rects: Arc<HashMap<LayerId, Rect<Au>, DefaultState<FnvHasher>>>, @@ -126,18 +126,6 @@ pub struct SharedLayoutContext { pub goal: ReflowGoal, } -// FIXME(#6569) This implementations is unsound: -// XXX UNSOUND!!! for image_cache_task -// XXX UNSOUND!!! for image_cache_sender -// XXX UNSOUND!!! for constellation_chan -// XXX UNSOUND!!! for layout_chan -// XXX UNSOUND!!! for font_cache_task -// XXX UNSOUND!!! for stylist -// XXX UNSOUND!!! for new_animations_sender -// XXX UNSOUND!!! for canvas_layers_sender -#[allow(unsafe_code)] -unsafe impl Sync for SharedLayoutContext {} - pub struct LayoutContext<'a> { pub shared: &'a SharedLayoutContext, cached_local_layout_context: Rc<LocalLayoutContext>, @@ -200,8 +188,8 @@ impl<'a> LayoutContext<'a> { } // Not yet requested, async mode - request image from the cache (ImageState::NotRequested, false) => { - self.shared.image_cache_task - .request_image(url, self.shared.image_cache_sender.clone(), None); + let sender = self.shared.image_cache_sender.lock().unwrap().clone(); + self.shared.image_cache_task.request_image(url, sender, None); None } // Image has been requested, is still pending. Return no image diff --git a/components/layout/css/matching.rs b/components/layout/css/matching.rs index 456f8cbe88f..d0260fa5c98 100644 --- a/components/layout/css/matching.rs +++ b/components/layout/css/matching.rs @@ -21,8 +21,8 @@ use smallvec::SmallVec; use std::borrow::ToOwned; use std::hash::{Hash, Hasher}; use std::slice::Iter; -use std::sync::Arc; use std::sync::mpsc::Sender; +use std::sync::{Arc, Mutex}; use string_cache::{Atom, Namespace}; use style::node::TElementAttributes; use style::properties::{ComputedValues, PropertyDeclaration, cascade}; @@ -406,7 +406,7 @@ pub trait MatchMethods { parent: Option<LayoutNode>, applicable_declarations: &ApplicableDeclarations, applicable_declarations_cache: &mut ApplicableDeclarationsCache, - new_animations_sender: &Sender<Animation>); + new_animations_sender: &Mutex<Sender<Animation>>); } trait PrivateMatchMethods { @@ -417,7 +417,7 @@ trait PrivateMatchMethods { style: &mut Option<Arc<ComputedValues>>, applicable_declarations_cache: &mut ApplicableDeclarationsCache, - new_animations_sender: &Sender<Animation>, + new_animations_sender: &Mutex<Sender<Animation>>, shareable: bool, animate_properties: bool) -> RestyleDamage; @@ -438,7 +438,7 @@ impl<'ln> PrivateMatchMethods for LayoutNode<'ln> { style: &mut Option<Arc<ComputedValues>>, applicable_declarations_cache: &mut ApplicableDeclarationsCache, - new_animations_sender: &Sender<Animation>, + new_animations_sender: &Mutex<Sender<Animation>>, shareable: bool, animate_properties: bool) -> RestyleDamage { @@ -655,7 +655,7 @@ impl<'ln> MatchMethods for LayoutNode<'ln> { parent: Option<LayoutNode>, applicable_declarations: &ApplicableDeclarations, applicable_declarations_cache: &mut ApplicableDeclarationsCache, - new_animations_sender: &Sender<Animation>) { + new_animations_sender: &Mutex<Sender<Animation>>) { // Get our parent's style. This must be unsafe so that we don't touch the parent's // borrow flags. // diff --git a/components/layout/display_list_builder.rs b/components/layout/display_list_builder.rs index 907bb5b129d..52c481f504e 100644 --- a/components/layout/display_list_builder.rs +++ b/components/layout/display_list_builder.rs @@ -1150,7 +1150,7 @@ impl FragmentDisplayListBuilding for Fragment { let data = receiver.recv().unwrap(); // Propagate the layer and the renderer to the paint task. - layout_context.shared.canvas_layers_sender.send( + layout_context.shared.canvas_layers_sender.lock().unwrap().send( (layer_id, (*ipc_renderer).clone())).unwrap(); data diff --git a/components/layout/flow.rs b/components/layout/flow.rs index 0396737822a..6902341edae 100644 --- a/components/layout/flow.rs +++ b/components/layout/flow.rs @@ -38,7 +38,6 @@ use incremental::{self, RECONSTRUCT_FLOW, REFLOW, REFLOW_OUT_OF_FLOW, RestyleDam use inline::InlineFlow; use model::{CollapsibleMargins, IntrinsicISizes, MarginCollapseInfo}; use msg::compositor_msg::{LayerId, LayerType}; -use msg::constellation_msg::ConstellationChan; use multicol::MulticolFlow; use parallel::FlowParallelInfo; use rustc_serialize::{Encodable, Encoder}; @@ -363,9 +362,6 @@ 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<ComputedValues>); - - /// Remove any compositor layers associated with this flow - fn remove_compositor_layers(&self, _: ConstellationChan) {} } // Base access diff --git a/components/layout/layout_task.rs b/components/layout/layout_task.rs index d4931848f05..6347509ad90 100644 --- a/components/layout/layout_task.rs +++ b/components/layout/layout_task.rs @@ -12,12 +12,10 @@ use app_units::Au; use azure::azure::AzColor; use canvas_traits::CanvasMsg; use construct::ConstructionResult; -use context::{SharedLayoutContext, heap_size_of_local_context}; +use context::{SharedLayoutContext, StylistWrapper, heap_size_of_local_context}; use cssparser::ToCss; use data::LayoutDataWrapper; use display_list_builder::ToGfxColor; -use encoding::EncodingRef; -use encoding::all::UTF_8; use euclid::Matrix4; use euclid::point::Point2D; use euclid::rect::Rect; @@ -40,9 +38,8 @@ use layout_traits::LayoutTaskFactory; use log; use msg::compositor_msg::{Epoch, LayerId, ScrollPolicy}; use msg::constellation_msg::Msg as ConstellationMsg; -use msg::constellation_msg::{ConstellationChan, Failure, PipelineExitType, PipelineId}; +use msg::constellation_msg::{ConstellationChan, Failure, PipelineId}; use net_traits::image_cache_task::{ImageCacheChan, ImageCacheResult, ImageCacheTask}; -use net_traits::{PendingAsyncLoad, load_bytes_iter}; use opaque_node::OpaqueNodeMethods; use parallel::{self, WorkQueueData}; use profile_traits::mem::{self, Report, ReportKind, ReportsChan}; @@ -56,7 +53,6 @@ use script::layout_interface::Animation; use script::layout_interface::{LayoutChan, LayoutRPC, OffsetParentResponse}; use script::layout_interface::{Msg, NewLayoutTaskInfo, Reflow, ReflowGoal, ReflowQueryType}; use script::layout_interface::{ScriptLayoutChan, ScriptReflow, TrustedNodeAddress}; -use script_traits::StylesheetLoadResponder; use script_traits::{ConstellationControlMsg, LayoutControlMsg, OpaqueScriptLayoutChannel}; use selectors::parser::PseudoElement; use sequential; @@ -72,13 +68,12 @@ use std::sync::mpsc::{channel, Sender, Receiver}; use std::sync::{Arc, Mutex, MutexGuard}; use string_cache::Atom; use style::computed_values::{self, filter, mix_blend_mode}; -use style::media_queries::{Device, MediaQueryList, MediaType}; +use style::media_queries::{Device, MediaType}; use style::properties::longhands::{display, position}; use style::properties::style_structs; -use style::selector_matching::Stylist; -use style::stylesheets::{CSSRule, CSSRuleIteratorExt, Origin, Stylesheet}; +use style::selector_matching::{Stylist, USER_OR_USER_AGENT_STYLESHEETS}; +use style::stylesheets::{CSSRuleIteratorExt, Stylesheet}; use style::values::AuExtensionMethods; -use style::viewport::ViewportRule; use url::Url; use util::geometry::{MAX_RECT, ZERO_POINT}; use util::ipc::OptionalIpcSender; @@ -109,9 +104,6 @@ pub struct LayoutTaskData { /// The channel on which messages can be sent to the constellation. pub constellation_chan: ConstellationChan, - /// The size of the screen. - pub screen_size: Size2D<Au>, - /// The size of the viewport. This may be different from the size of the screen due to viewport /// constraints. pub viewport_size: Size2D<Au>, @@ -326,10 +318,18 @@ fn add_font_face_rules(stylesheet: &Stylesheet, outstanding_web_fonts_counter: &Arc<AtomicUsize>) { for font_face in stylesheet.effective_rules(&device).font_face() { for source in &font_face.sources { - outstanding_web_fonts_counter.fetch_add(1, Ordering::SeqCst); - font_cache_task.add_web_font(font_face.family.clone(), - (*source).clone(), - (*font_cache_sender).clone()); + if opts::get().load_webfonts_synchronously { + let (sender, receiver) = channel(); + font_cache_task.add_web_font(font_face.family.clone(), + (*source).clone(), + sender); + receiver.recv().unwrap(); + } else { + outstanding_web_fonts_counter.fetch_add(1, Ordering::SeqCst); + font_cache_task.add_web_font(font_face.family.clone(), + (*source).clone(), + (*font_cache_sender).clone()); + } } } } @@ -350,7 +350,6 @@ impl LayoutTask { time_profiler_chan: time::ProfilerChan, mem_profiler_chan: mem::ProfilerChan) -> LayoutTask { - let screen_size = Size2D::new(Au(0), Au(0)); let device = Device::new( MediaType::Screen, opts::get().initial_window_size.as_f32() * ScaleFactor::new(1.0)); @@ -377,8 +376,8 @@ impl LayoutTask { let stylist = box Stylist::new(device); let outstanding_web_fonts_counter = Arc::new(AtomicUsize::new(0)); - for user_or_user_agent_stylesheet in stylist.stylesheets() { - add_font_face_rules(user_or_user_agent_stylesheet, + for stylesheet in &*USER_OR_USER_AGENT_STYLESHEETS { + add_font_face_rules(stylesheet, &stylist.device, &font_cache_task, &font_cache_sender, @@ -411,8 +410,7 @@ impl LayoutTask { root_flow: None, image_cache_task: image_cache_task, constellation_chan: constellation_chan, - screen_size: screen_size, - viewport_size: screen_size, + viewport_size: Size2D::new(Au(0), Au(0)), stacking_context: None, stylist: stylist, parallel_traversal: parallel_traversal, @@ -449,18 +447,16 @@ impl LayoutTask { -> SharedLayoutContext { SharedLayoutContext { image_cache_task: rw_data.image_cache_task.clone(), - image_cache_sender: self.image_cache_sender.clone(), + image_cache_sender: Mutex::new(self.image_cache_sender.clone()), viewport_size: rw_data.viewport_size.clone(), screen_size_changed: screen_size_changed, - constellation_chan: rw_data.constellation_chan.clone(), - layout_chan: self.chan.clone(), - font_cache_task: self.font_cache_task.clone(), - canvas_layers_sender: self.canvas_layers_sender.clone(), - stylist: &*rw_data.stylist, + font_cache_task: Mutex::new(self.font_cache_task.clone()), + canvas_layers_sender: Mutex::new(self.canvas_layers_sender.clone()), + stylist: StylistWrapper(&*rw_data.stylist), url: (*url).clone(), visible_rects: rw_data.visible_rects.clone(), generation: rw_data.generation, - new_animations_sender: rw_data.new_animations_sender.clone(), + new_animations_sender: Mutex::new(rw_data.new_animations_sender.clone()), goal: goal, running_animations: rw_data.running_animations.clone(), } @@ -492,8 +488,8 @@ impl LayoutTask { self.handle_request_helper(Msg::GetWebFontLoadState(sender), possibly_locked_rw_data) } - LayoutControlMsg::ExitNow(exit_type) => { - self.handle_request_helper(Msg::ExitNow(exit_type), + LayoutControlMsg::ExitNow => { + self.handle_request_helper(Msg::ExitNow, possibly_locked_rw_data) } } @@ -576,20 +572,10 @@ impl LayoutTask { LayoutTaskData>>) -> bool { match request { - Msg::AddStylesheet(sheet, mq) => { - self.handle_add_stylesheet(sheet, mq, possibly_locked_rw_data) - } - Msg::LoadStylesheet(url, mq, pending, link_element) => { - self.handle_load_stylesheet(url, - mq, - pending, - link_element, - possibly_locked_rw_data) + Msg::AddStylesheet(style_info) => { + self.handle_add_stylesheet(style_info, possibly_locked_rw_data) } Msg::SetQuirksMode => self.handle_set_quirks_mode(possibly_locked_rw_data), - Msg::AddMetaViewport(translated_rule) => { - self.handle_add_meta_viewport(translated_rule, possibly_locked_rw_data) - } Msg::GetRPC(response_chan) => { response_chan.send(box LayoutRPCImpl(self.rw_data.clone()) as Box<LayoutRPC + Send>).unwrap(); @@ -631,9 +617,9 @@ impl LayoutTask { self.prepare_to_exit(response_chan, possibly_locked_rw_data); return false }, - Msg::ExitNow(exit_type) => { + Msg::ExitNow => { debug!("layout: ExitNow received"); - self.exit_now(possibly_locked_rw_data, exit_type); + self.exit_now(possibly_locked_rw_data); return false } } @@ -711,9 +697,9 @@ impl LayoutTask { self.handle_reap_layout_data(dead_layout_data) } } - Msg::ExitNow(exit_type) => { + Msg::ExitNow => { debug!("layout task is exiting..."); - self.exit_now(possibly_locked_rw_data, exit_type); + self.exit_now(possibly_locked_rw_data); break } Msg::CollectReports(_) => { @@ -729,10 +715,7 @@ impl LayoutTask { /// Shuts down the layout task now. If there are any DOM nodes left, layout will now (safely) /// crash. fn exit_now<'a>(&'a self, - possibly_locked_rw_data: &mut Option<MutexGuard<'a, LayoutTaskData>>, - exit_type: PipelineExitType) { - let (response_chan, response_port) = ipc::channel().unwrap(); - + possibly_locked_rw_data: &mut Option<MutexGuard<'a, LayoutTaskData>>) { { let mut rw_data = self.lock_rw_data(possibly_locked_rw_data); if let Some(ref mut traversal) = (&mut *rw_data).parallel_traversal { @@ -741,79 +724,36 @@ impl LayoutTask { LayoutTask::return_rw_data(possibly_locked_rw_data, rw_data); } - self.paint_chan.send(LayoutToPaintMsg::Exit(Some(response_chan), exit_type)).unwrap(); + let (response_chan, response_port) = ipc::channel().unwrap(); + self.paint_chan.send(LayoutToPaintMsg::Exit(response_chan)).unwrap(); response_port.recv().unwrap() } - fn handle_load_stylesheet<'a>(&'a self, - url: Url, - mq: MediaQueryList, - pending: PendingAsyncLoad, - responder: Box<StylesheetLoadResponder + Send>, - possibly_locked_rw_data: - &mut Option<MutexGuard<'a, LayoutTaskData>>) { - // TODO: Get the actual value. http://dev.w3.org/csswg/css-syntax/#environment-encoding - let environment_encoding = UTF_8 as EncodingRef; - - // TODO we don't really even need to load this if mq does not match - let (metadata, iter) = load_bytes_iter(pending); - let protocol_encoding_label = metadata.charset.as_ref().map(|s| &**s); - let final_url = metadata.final_url; - - let sheet = Stylesheet::from_bytes_iter(iter, - final_url, - protocol_encoding_label, - Some(environment_encoding), - Origin::Author); - - //TODO: mark critical subresources as blocking load as well (#5974) - self.script_chan.send(ConstellationControlMsg::StylesheetLoadComplete(self.id, - url, - responder)).unwrap(); - - self.handle_add_stylesheet(sheet, mq, possibly_locked_rw_data); - } - fn handle_add_stylesheet<'a>(&'a self, - sheet: Stylesheet, - mq: MediaQueryList, + stylesheet: Arc<Stylesheet>, possibly_locked_rw_data: &mut Option<MutexGuard<'a, LayoutTaskData>>) { // Find all font-face rules and notify the font cache of them. - // GWTODO: Need to handle unloading web fonts (when we handle unloading stylesheets!) + // GWTODO: Need to handle unloading web fonts. - let mut rw_data = self.lock_rw_data(possibly_locked_rw_data); - if mq.evaluate(&rw_data.stylist.device) { - add_font_face_rules(&sheet, + let rw_data = self.lock_rw_data(possibly_locked_rw_data); + if stylesheet.is_effective_for_device(&rw_data.stylist.device) { + add_font_face_rules(&*stylesheet, &rw_data.stylist.device, &self.font_cache_task, &self.font_cache_sender, &rw_data.outstanding_web_fonts); - rw_data.stylist.add_stylesheet(sheet); } LayoutTask::return_rw_data(possibly_locked_rw_data, rw_data); } - fn handle_add_meta_viewport<'a>(&'a self, - translated_rule: ViewportRule, - possibly_locked_rw_data: - &mut Option<MutexGuard<'a, LayoutTaskData>>) - { - let mut rw_data = self.lock_rw_data(possibly_locked_rw_data); - rw_data.stylist.add_stylesheet(Stylesheet { - rules: vec![CSSRule::Viewport(translated_rule)], - origin: Origin::Author - }); - LayoutTask::return_rw_data(possibly_locked_rw_data, rw_data); - } - - /// Sets quirks mode for the document, causing the quirks mode stylesheet to be loaded. + /// Sets quirks mode for the document, causing the quirks mode stylesheet to be used. fn handle_set_quirks_mode<'a>(&'a self, possibly_locked_rw_data: &mut Option<MutexGuard<'a, LayoutTaskData>>) { let mut rw_data = self.lock_rw_data(possibly_locked_rw_data); - rw_data.stylist.add_quirks_mode_stylesheet(); + rw_data.stylist.set_quirks_mode(true); LayoutTask::return_rw_data(possibly_locked_rw_data, rw_data); } @@ -1077,7 +1017,7 @@ impl LayoutTask { flow_ref::deref_mut(layout_root)); let root_size = { let root_flow = flow::base(&**layout_root); - if rw_data.stylist.constrain_viewport().is_some() { + if rw_data.stylist.viewport_constraints().is_some() { root_flow.position.size.to_physical(root_flow.writing_mode) } else { root_flow.overflow.size @@ -1153,18 +1093,20 @@ impl LayoutTask { } let mut rw_data = self.lock_rw_data(possibly_locked_rw_data); + let stylesheets: Vec<&Stylesheet> = data.document_stylesheets.iter().map(|entry| &**entry) + .collect(); + let stylesheets_changed = data.stylesheets_changed; let initial_viewport = data.window_size.initial_viewport; let old_viewport_size = rw_data.viewport_size; let current_screen_size = Size2D::new(Au::from_f32_px(initial_viewport.width.get()), Au::from_f32_px(initial_viewport.height.get())); - rw_data.screen_size = current_screen_size; // Calculate the actual viewport as per DEVICE-ADAPT § 6 let device = Device::new(MediaType::Screen, initial_viewport); - rw_data.stylist.set_device(device); + rw_data.stylist.set_device(device, &stylesheets); - let constraints = rw_data.stylist.constrain_viewport(); + let constraints = rw_data.stylist.viewport_constraints().clone(); rw_data.viewport_size = match constraints { Some(ref constraints) => { debug!("Viewport constraints: {:?}", constraints); @@ -1180,9 +1122,6 @@ impl LayoutTask { let viewport_size_changed = rw_data.viewport_size != old_viewport_size; if viewport_size_changed { if let Some(constraints) = constraints { - let device = Device::new(MediaType::Screen, constraints.size); - rw_data.stylist.set_device(device); - // let the constellation know about the viewport constraints let ConstellationChan(ref constellation_chan) = rw_data.constellation_chan; constellation_chan.send(ConstellationMsg::ViewportConstrained( @@ -1191,7 +1130,7 @@ impl LayoutTask { } // If the entire flow tree is invalid, then it will be reflowed anyhow. - let needs_dirtying = rw_data.stylist.update(); + let needs_dirtying = rw_data.stylist.update(&stylesheets, stylesheets_changed); let needs_reflow = viewport_size_changed && !needs_dirtying; unsafe { if needs_dirtying { @@ -1204,13 +1143,12 @@ impl LayoutTask { } } - let state_changes = document.drain_element_state_changes(); + let modified_elements = document.drain_modified_elements(); if !needs_dirtying { - for &(el, state_change) in state_changes.iter() { - debug_assert!(!state_change.is_empty()); + for &(el, old_state) in modified_elements.iter() { let hint = rw_data.stylist.restyle_hint_for_state_change(&el, el.get_state(), - state_change); + old_state); el.note_restyle_hint(hint); } } @@ -1221,7 +1159,7 @@ impl LayoutTask { &self.url, data.reflow_info.goal); - if node.is_dirty() || node.has_dirty_descendants() || rw_data.stylist.is_dirty() { + if node.is_dirty() || node.has_dirty_descendants() { // Recalculate CSS styles and rebuild flows and fragments. profile(time::ProfilerCategory::LayoutStyleRecalc, self.profiler_metadata(), diff --git a/components/layout/traversal.rs b/components/layout/traversal.rs index 34427b9d8d9..3a1fcf38bc6 100644 --- a/components/layout/traversal.rs +++ b/components/layout/traversal.rs @@ -188,7 +188,7 @@ impl<'a> PreorderDomTraversal for RecalcStyleForNode<'a> { let shareable_element = match node.as_element() { Some(element) => { // Perform the CSS selector matching. - let stylist = unsafe { &*self.layout_context.shared.stylist }; + let stylist = unsafe { &*self.layout_context.shared.stylist.0 }; if element.match_element(stylist, Some(&*bf), &mut applicable_declarations) { diff --git a/components/layout/wrapper.rs b/components/layout/wrapper.rs index 04d3470fb64..ae8462426e8 100644 --- a/components/layout/wrapper.rs +++ b/components/layout/wrapper.rs @@ -375,10 +375,10 @@ impl<'le> LayoutDocument<'le> { self.as_node().children().find(LayoutNode::is_element) } - pub fn drain_element_state_changes(&self) -> Vec<(LayoutElement, ElementState)> { + pub fn drain_modified_elements(&self) -> Vec<(LayoutElement, ElementState)> { unsafe { - let changes = self.document.drain_element_state_changes(); - Vec::from_iter(changes.iter().map(|&(el, state)| + let elements = self.document.drain_modified_elements(); + Vec::from_iter(elements.iter().map(|&(el, state)| (LayoutElement { element: el, chain: PhantomData, diff --git a/components/msg/constellation_msg.rs b/components/msg/constellation_msg.rs index 98fdcc052fb..26fcb842d0e 100644 --- a/components/msg/constellation_msg.rs +++ b/components/msg/constellation_msg.rs @@ -517,11 +517,3 @@ impl fmt::Display for PipelineId { #[derive(Clone, PartialEq, Eq, Copy, Hash, Debug, Deserialize, Serialize, HeapSizeOf)] pub struct SubpageId(pub u32); - -// The type of pipeline exit. During complete shutdowns, pipelines do not have to -// release resources automatically released on process termination. -#[derive(Copy, Clone, Debug, Deserialize, Serialize)] -pub enum PipelineExitType { - PipelineOnly, - Complete, -} diff --git a/components/net_traits/lib.rs b/components/net_traits/lib.rs index 40dcdd7c15c..de59bf654d7 100644 --- a/components/net_traits/lib.rs +++ b/components/net_traits/lib.rs @@ -274,16 +274,6 @@ impl PendingAsyncLoad { } } - /// Initiate the network request associated with this pending load. - pub fn load(mut self) -> IpcReceiver<LoadResponse> { - self.guard.neuter(); - let load_data = LoadData::new(self.url, self.pipeline); - let (sender, receiver) = ipc::channel().unwrap(); - let consumer = LoadConsumer::Channel(sender); - self.resource_task.send(ControlMsg::Load(load_data, consumer)).unwrap(); - receiver - } - /// Initiate the network request associated with this pending load, using the provided target. pub fn load_async(mut self, listener: AsyncResponseTarget) { self.guard.neuter(); @@ -399,33 +389,3 @@ pub fn load_whole_resource(resource_task: &ResourceTask, url: Url, pipeline_id: } } } - -/// Load a URL asynchronously and iterate over chunks of bytes from the response. -pub fn load_bytes_iter(pending: PendingAsyncLoad) -> (Metadata, ProgressMsgPortIterator) { - let input_port = pending.load(); - let response = input_port.recv().unwrap(); - let iter = ProgressMsgPortIterator { - progress_port: response.progress_port - }; - (response.metadata, iter) -} - -/// Iterator that reads chunks of bytes from a ProgressMsg port -pub struct ProgressMsgPortIterator { - progress_port: IpcReceiver<ProgressMsg>, -} - -impl Iterator for ProgressMsgPortIterator { - type Item = Vec<u8>; - - fn next(&mut self) -> Option<Vec<u8>> { - match self.progress_port.recv().unwrap() { - ProgressMsg::Payload(data) => Some(data), - ProgressMsg::Done(Ok(())) => None, - ProgressMsg::Done(Err(e)) => { - error!("error receiving bytes: {}", e); - None - } - } - } -} diff --git a/components/script/Cargo.toml b/components/script/Cargo.toml index b2b96d04f72..34043b52a75 100644 --- a/components/script/Cargo.toml +++ b/components/script/Cargo.toml @@ -42,9 +42,6 @@ path = "../canvas" [dependencies.canvas_traits] path = "../canvas_traits" -[dependencies.selectors] -git = "https://github.com/servo/rust-selectors" - [dependencies.js] git = "https://github.com/servo/rust-mozjs" @@ -59,10 +56,6 @@ git = "https://github.com/ecoal95/rust-offscreen-rendering-context" git = "https://github.com/ecoal95/angle" branch = "servo" -[dependencies.cssparser] -version = "0.3" -features = [ "serde-serialization" ] - [dependencies.ipc-channel] git = "https://github.com/pcwalton/ipc-channel" @@ -76,6 +69,7 @@ features = ["unstable"] [dependencies] app_units = {version = "0.1", features = ["plugins"]} +cssparser = { version = "0.4", features = [ "serde-serialization" ] } log = "0.3" encoding = "0.2" fnv = "1.0" @@ -89,6 +83,7 @@ websocket = "0.12.0" uuid = "0.1.16" smallvec = "0.1" html5ever = { version = "0.2.1", features = ["unstable"] } +selectors = "0.2" string_cache = { version = "0.1.15", features = ["unstable"] } string_cache_plugin = "0.1" euclid = {version = "0.3", features = ["plugins"]} diff --git a/components/script/dom/bindings/codegen/CodegenRust.py b/components/script/dom/bindings/codegen/CodegenRust.py index 9348a198ef0..8e88b5cb2e1 100644 --- a/components/script/dom/bindings/codegen/CodegenRust.py +++ b/components/script/dom/bindings/codegen/CodegenRust.py @@ -4927,7 +4927,6 @@ class CGDictionary(CGThing): for m in self.memberInfo] return (string.Template( - "#[no_move]\n" + "pub struct ${selfName} {\n" + "${inheritance}" + "\n".join(memberDecls) + "\n" + diff --git a/components/script/dom/bindings/js.rs b/components/script/dom/bindings/js.rs index 8cae3f82618..3aceb11f113 100644 --- a/components/script/dom/bindings/js.rs +++ b/components/script/dom/bindings/js.rs @@ -454,7 +454,6 @@ impl<T: Reflectable> OptionalRootedReference<T> for Option<Option<Root<T>>> { /// /// See also [*Exact Stack Rooting - Storing a GCPointer on the CStack*] /// (https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/Internals/GC/Exact_Stack_Rooting). -#[no_move] pub struct RootCollection { roots: UnsafeCell<Vec<*const Reflector>>, } diff --git a/components/script/dom/bindings/mod.rs b/components/script/dom/bindings/mod.rs index f4b795f8c58..410f7af9dda 100644 --- a/components/script/dom/bindings/mod.rs +++ b/components/script/dom/bindings/mod.rs @@ -152,9 +152,7 @@ pub mod xmlname; /// Generated JS-Rust bindings. #[allow(missing_docs, non_snake_case)] pub mod codegen { - // FIXME(#5853) we shouldn't need to - // allow moved_no_move here - #[allow(unrooted_must_root, moved_no_move)] + #[allow(unrooted_must_root)] pub mod Bindings { include!(concat!(env!("OUT_DIR"), "/Bindings/mod.rs")); } diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs index 48f6ed39032..5d4e0a603f5 100644 --- a/components/script/dom/bindings/trace.rs +++ b/components/script/dom/bindings/trace.rs @@ -382,7 +382,7 @@ impl RootedTraceableSet { } } - fn remove<T: JSTraceable>(traceable: &T) { + unsafe fn remove<T: JSTraceable>(traceable: &T) { ROOTED_TRACEABLES.with(|ref traceables| { let mut traceables = traceables.borrow_mut(); let idx = @@ -395,7 +395,7 @@ impl RootedTraceableSet { }); } - fn add<T: JSTraceable>(traceable: &T) { + unsafe fn add<T: JSTraceable>(traceable: &T) { ROOTED_TRACEABLES.with(|ref traceables| { fn trace<T: JSTraceable>(obj: *const libc::c_void, tracer: *mut JSTracer) { let obj: &T = unsafe { &*(obj as *const T) }; @@ -432,14 +432,18 @@ pub struct RootedTraceable<'a, T: 'a + JSTraceable> { impl<'a, T: JSTraceable> RootedTraceable<'a, T> { /// Root a JSTraceable thing for the life of this RootedTraceable pub fn new(traceable: &'a T) -> RootedTraceable<'a, T> { - RootedTraceableSet::add(traceable); + unsafe { + RootedTraceableSet::add(traceable); + } RootedTraceable { ptr: traceable } } } impl<'a, T: JSTraceable> Drop for RootedTraceable<'a, T> { fn drop(&mut self) { - RootedTraceableSet::remove(self.ptr); + unsafe { + RootedTraceableSet::remove(self.ptr); + } } } @@ -461,15 +465,13 @@ impl<T: JSTraceable> RootedVec<T> { return_address() as *const libc::c_void }; - RootedVec::new_with_destination_address(addr) + unsafe { RootedVec::new_with_destination_address(addr) } } /// Create a vector of items of type T. This constructor is specific /// for RootTraceableSet. - pub fn new_with_destination_address(addr: *const libc::c_void) -> RootedVec<T> { - unsafe { - RootedTraceableSet::add::<RootedVec<T>>(&*(addr as *const _)); - } + pub unsafe fn new_with_destination_address(addr: *const libc::c_void) -> RootedVec<T> { + RootedTraceableSet::add::<RootedVec<T>>(&*(addr as *const _)); RootedVec::<T> { v: vec!() } } } @@ -477,13 +479,15 @@ impl<T: JSTraceable> RootedVec<T> { impl<T: JSTraceable + Reflectable> RootedVec<JS<T>> { /// Obtain a safe slice of references that can't outlive that RootedVec. pub fn r(&self) -> &[&T] { - unsafe { mem::transmute(&*self.v) } + unsafe { mem::transmute(&self.v[..]) } } } impl<T: JSTraceable> Drop for RootedVec<T> { fn drop(&mut self) { - RootedTraceableSet::remove(self); + unsafe { + RootedTraceableSet::remove(self); + } } } @@ -503,9 +507,9 @@ impl<T: JSTraceable> DerefMut for RootedVec<T> { impl<A: JSTraceable + Reflectable> FromIterator<Root<A>> for RootedVec<JS<A>> { #[allow(moved_no_move)] fn from_iter<T>(iterable: T) -> RootedVec<JS<A>> where T: IntoIterator<Item=Root<A>> { - let mut vec = RootedVec::new_with_destination_address(unsafe { - return_address() as *const libc::c_void - }); + let mut vec = unsafe { + RootedVec::new_with_destination_address(return_address() as *const libc::c_void) + }; vec.extend(iterable.into_iter().map(|item| JS::from_rooted(&item))); vec } diff --git a/components/script/dom/create.rs b/components/script/dom/create.rs index 4e2b07399b1..2f1d35d3b59 100644 --- a/components/script/dom/create.rs +++ b/components/script/dom/create.rs @@ -174,7 +174,7 @@ pub fn create_element(name: QualName, prefix: Option<Atom>, atom!("label") => make!(HTMLLabelElement), atom!("legend") => make!(HTMLLegendElement), atom!("li") => make!(HTMLLIElement), - atom!("link") => make!(HTMLLinkElement), + atom!("link") => make!(HTMLLinkElement, creator), // https://html.spec.whatwg.org/multipage/#other-elements,-attributes-and-apis:listing atom!("listing") => make!(HTMLPreElement), atom!("main") => make!(HTMLElement), diff --git a/components/script/dom/cssstyledeclaration.rs b/components/script/dom/cssstyledeclaration.rs index 91e2af7b0b0..aa2ce366819 100644 --- a/components/script/dom/cssstyledeclaration.rs +++ b/components/script/dom/cssstyledeclaration.rs @@ -16,8 +16,8 @@ use std::ascii::AsciiExt; use std::borrow::ToOwned; use std::cell::Ref; use string_cache::Atom; -use style::properties::PropertyDeclaration; -use style::properties::{is_supported_property, longhands_from_shorthand, parse_one_declaration}; +use style::properties::{PropertyDeclaration, Shorthand}; +use style::properties::{is_supported_property, parse_one_declaration}; use util::str::{DOMString, str_join}; // http://dev.w3.org/csswg/cssom/#the-cssstyledeclaration-interface @@ -48,9 +48,27 @@ macro_rules! css_properties( ); ); -fn serialize_list(list: &[Ref<PropertyDeclaration>]) -> DOMString { - let str_iter = list.iter().map(|d| d.value()); - DOMString(str_join(str_iter, " ")) +fn serialize_shorthand(shorthand: Shorthand, declarations: &[Ref<PropertyDeclaration>]) + -> String { + // https://drafts.csswg.org/css-variables/#variables-in-shorthands + if let Some(css) = declarations[0].with_variables_from_shorthand(shorthand) { + if declarations[1..].iter() + .all(|d| d.with_variables_from_shorthand(shorthand) == Some(css)) { + css.to_owned() + } else { + String::new() + } + } else { + if declarations.iter().any(|d| d.with_variables()) { + String::new() + } else { + let str_iter = declarations.iter().map(|d| d.value()); + // FIXME: this needs property-specific code, which probably should be in style/ + // "as appropriate according to the grammar of shorthand " + // https://drafts.csswg.org/cssom/#serialize-a-css-value + str_join(str_iter, " ") + } + } } impl CSSStyleDeclaration { @@ -130,13 +148,12 @@ impl CSSStyleDeclarationMethods for CSSStyleDeclaration { } // Step 2 - let longhand_properties = longhands_from_shorthand(&property); - if let Some(longhand_properties) = longhand_properties { + if let Some(shorthand) = Shorthand::from_name(&property) { // Step 2.1 let mut list = vec!(); // Step 2.2 - for longhand in &*longhand_properties { + for longhand in shorthand.longhands() { // Step 2.2.1 let declaration = owner.get_inline_style_declaration(&Atom::from_slice(&longhand)); @@ -148,7 +165,7 @@ impl CSSStyleDeclarationMethods for CSSStyleDeclaration { } // Step 2.3 - return serialize_list(&list); + return DOMString(serialize_shorthand(shorthand, &list)); } // Step 3 & 4 @@ -166,12 +183,11 @@ impl CSSStyleDeclarationMethods for CSSStyleDeclaration { let property = Atom::from_slice(&property); // Step 2 - let longhand_properties = longhands_from_shorthand(&property); - if let Some(longhand_properties) = longhand_properties { + if let Some(shorthand) = Shorthand::from_name(&property) { // Step 2.1 & 2.2 & 2.3 - if longhand_properties.iter() - .map(|&longhand| self.GetPropertyPriority(DOMString(longhand.to_owned()))) - .all(|priority| priority == "important") { + if shorthand.longhands().iter() + .map(|&longhand| self.GetPropertyPriority(DOMString(longhand.to_owned()))) + .all(|priority| priority == "important") { return DOMString("important".to_owned()); } @@ -261,8 +277,10 @@ impl CSSStyleDeclarationMethods for CSSStyleDeclaration { let element = self.owner.upcast::<Element>(); // Step 5 & 6 - match longhands_from_shorthand(&property) { - Some(properties) => element.set_inline_style_property_priority(properties, priority), + match Shorthand::from_name(&property) { + Some(shorthand) => { + element.set_inline_style_property_priority(shorthand.longhands(), priority) + } None => element.set_inline_style_property_priority(&[&*property], priority) } @@ -292,10 +310,10 @@ impl CSSStyleDeclarationMethods for CSSStyleDeclaration { let elem = self.owner.upcast::<Element>(); - match longhands_from_shorthand(&property) { + match Shorthand::from_name(&property) { // Step 4 - Some(longhands) => { - for longhand in &*longhands { + Some(shorthand) => { + for longhand in shorthand.longhands() { elem.remove_inline_style_property(longhand) } } diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index b39adbc53fc..dc3225bba04 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.rs @@ -48,7 +48,10 @@ use dom::htmlheadelement::HTMLHeadElement; use dom::htmlhtmlelement::HTMLHtmlElement; use dom::htmliframeelement::{self, HTMLIFrameElement}; use dom::htmlimageelement::HTMLImageElement; +use dom::htmllinkelement::HTMLLinkElement; +use dom::htmlmetaelement::HTMLMetaElement; use dom::htmlscriptelement::HTMLScriptElement; +use dom::htmlstyleelement::HTMLStyleElement; use dom::htmltitleelement::HTMLTitleElement; use dom::keyboardevent::KeyboardEvent; use dom::location::Location; @@ -96,8 +99,10 @@ use std::default::Default; use std::iter::FromIterator; use std::ptr; use std::rc::Rc; +use std::sync::Arc; use std::sync::mpsc::channel; use string_cache::{Atom, QualName}; +use style::stylesheets::Stylesheet; use time; use url::Url; use util::str::{DOMString, split_html_space_chars, str_join}; @@ -135,6 +140,10 @@ pub struct Document { scripts: MutNullableHeap<JS<HTMLCollection>>, anchors: MutNullableHeap<JS<HTMLCollection>>, applets: MutNullableHeap<JS<HTMLCollection>>, + /// List of stylesheets associated with nodes in this document. |None| if the list needs to be refreshed. + stylesheets: DOMRefCell<Option<Vec<Arc<Stylesheet>>>>, + /// Whether the list of stylesheets has changed since the last reflow was triggered. + stylesheets_changed_since_reflow: Cell<bool>, ready_state: Cell<DocumentReadyState>, /// Whether the DOMContentLoaded event has already been dispatched. domcontentloaded_dispatched: Cell<bool>, @@ -175,8 +184,8 @@ pub struct Document { /// This field is set to the document itself for inert documents. /// https://html.spec.whatwg.org/multipage/#appropriate-template-contents-owner-document appropriate_template_contents_owner_document: MutNullableHeap<JS<Document>>, - /// The collection of ElementStates that have been changed since the last restyle. - element_state_changes: DOMRefCell<HashMap<JS<Element>, ElementState>>, + /// For each element that has had a state change since the last restyle, track the original state. + modified_elements: DOMRefCell<HashMap<JS<Element>, ElementState>>, /// http://w3c.github.io/touch-events/#dfn-active-touch-point active_touch_points: DOMRefCell<Vec<JS<Touch>>>, } @@ -308,7 +317,7 @@ impl Document { pub fn needs_reflow(&self) -> bool { self.GetDocumentElement().is_some() && - (self.upcast::<Node>().get_has_dirty_descendants() || !self.element_state_changes.borrow().is_empty()) + (self.upcast::<Node>().get_has_dirty_descendants() || !self.modified_elements.borrow().is_empty()) } /// Returns the first `base` element in the DOM that has an `href` attribute. @@ -921,15 +930,14 @@ impl Document { ReflowReason::KeyEvent); } - pub fn node_from_nodes_and_strings(&self, nodes: Vec<NodeOrString>) + // https://dom.spec.whatwg.org/#converting-nodes-into-a-node + pub fn node_from_nodes_and_strings(&self, mut nodes: Vec<NodeOrString>) -> Fallible<Root<Node>> { if nodes.len() == 1 { - match nodes.into_iter().next().unwrap() { - NodeOrString::eNode(node) => Ok(node), - NodeOrString::eString(string) => { - Ok(Root::upcast(self.CreateTextNode(string))) - }, - } + Ok(match nodes.pop().unwrap() { + NodeOrString::eNode(node) => node, + NodeOrString::eString(string) => Root::upcast(self.CreateTextNode(string)), + }) } else { let fragment = Root::upcast::<Node>(self.CreateDocumentFragment()); for node in nodes { @@ -983,6 +991,21 @@ impl Document { count_cell.set(count_cell.get() - 1); } + pub fn invalidate_stylesheets(&self) { + self.stylesheets_changed_since_reflow.set(true); + *self.stylesheets.borrow_mut() = None; + // Mark the document element dirty so a reflow will be performed. + self.get_html_element().map(|root| { + root.upcast::<Node>().dirty(NodeDamage::NodeStyleDamaged); + }); + } + + pub fn get_and_reset_stylesheets_changed_since_reflow(&self) -> bool { + let changed = self.stylesheets_changed_since_reflow.get(); + self.stylesheets_changed_since_reflow.set(false); + changed + } + pub fn set_pending_parsing_blocking_script(&self, script: Option<&HTMLScriptElement>) { assert!(self.get_pending_parsing_blocking_script().is_none() || script.is_none()); self.pending_parsing_blocking_script.set(script); @@ -1100,6 +1123,13 @@ impl Document { if parser.is_suspended() { parser.resume(); } + } else if self.reflow_timeout.get().is_none() { + // If we don't have a parser, and the reflow timer has been reset, explicitly + // trigger a reflow. + if let LoadType::Stylesheet(_) = load { + self.window().reflow(ReflowGoal::ForDisplay, ReflowQueryType::NoQuery, + ReflowReason::StylesheetLoaded); + } } let loader = self.loader.borrow(); @@ -1239,7 +1269,7 @@ pub enum DocumentSource { #[allow(unsafe_code)] pub trait LayoutDocumentHelpers { unsafe fn is_html_document_for_layout(&self) -> bool; - unsafe fn drain_element_state_changes(&self) -> Vec<(LayoutJS<Element>, ElementState)>; + unsafe fn drain_modified_elements(&self) -> Vec<(LayoutJS<Element>, ElementState)>; } #[allow(unsafe_code)] @@ -1251,9 +1281,9 @@ impl LayoutDocumentHelpers for LayoutJS<Document> { #[inline] #[allow(unrooted_must_root)] - unsafe fn drain_element_state_changes(&self) -> Vec<(LayoutJS<Element>, ElementState)> { - let mut changes = (*self.unsafe_get()).element_state_changes.borrow_mut_for_layout(); - let drain = changes.drain(); + unsafe fn drain_modified_elements(&self) -> Vec<(LayoutJS<Element>, ElementState)> { + let mut elements = (*self.unsafe_get()).modified_elements.borrow_mut_for_layout(); + let drain = elements.drain(); let layout_drain = drain.map(|(k, v)| (k.to_layout(), v)); Vec::from_iter(layout_drain) } @@ -1304,6 +1334,8 @@ impl Document { scripts: Default::default(), anchors: Default::default(), applets: Default::default(), + stylesheets: DOMRefCell::new(None), + stylesheets_changed_since_reflow: Cell::new(false), ready_state: Cell::new(ready_state), domcontentloaded_dispatched: Cell::new(domcontentloaded_dispatched), possibly_focused: Default::default(), @@ -1322,7 +1354,7 @@ impl Document { reflow_timeout: Cell::new(None), base_element: Default::default(), appropriate_template_contents_owner_document: Default::default(), - element_state_changes: DOMRefCell::new(HashMap::new()), + modified_elements: DOMRefCell::new(HashMap::new()), active_touch_points: DOMRefCell::new(Vec::new()), } } @@ -1369,6 +1401,31 @@ impl Document { self.GetDocumentElement().and_then(Root::downcast) } + /// Returns the list of stylesheets associated with nodes in the document. + pub fn stylesheets(&self) -> Ref<Vec<Arc<Stylesheet>>> { + { + let mut stylesheets = self.stylesheets.borrow_mut(); + if stylesheets.is_none() { + let new_stylesheets: Vec<Arc<Stylesheet>> = self.upcast::<Node>() + .traverse_preorder() + .filter_map(|node| { + if let Some(node) = node.downcast::<HTMLStyleElement>() { + node.get_stylesheet() + } else if let Some(node) = node.downcast::<HTMLLinkElement>() { + node.get_stylesheet() + } else if let Some(node) = node.downcast::<HTMLMetaElement>() { + node.get_stylesheet() + } else { + None + } + }) + .collect(); + *stylesheets = Some(new_stylesheets); + }; + } + Ref::map(self.stylesheets.borrow(), |t| t.as_ref().unwrap()) + } + /// https://html.spec.whatwg.org/multipage/#appropriate-template-contents-owner-document pub fn appropriate_template_contents_owner_document(&self) -> Root<Document> { self.appropriate_template_contents_owner_document.or_init(|| { @@ -1389,18 +1446,9 @@ impl Document { self.idmap.borrow().get(&id).map(|ref elements| Root::from_ref(&*(*elements)[0])) } - pub fn record_element_state_change(&self, el: &Element, which: ElementState) { - let mut map = self.element_state_changes.borrow_mut(); - let empty; - { - let states = map.entry(JS::from_ref(el)) - .or_insert(ElementState::empty()); - states.toggle(which); - empty = states.is_empty(); - } - if empty { - map.remove(&JS::from_ref(el)); - } + pub fn element_state_will_change(&self, el: &Element) { + let mut map = self.modified_elements.borrow_mut(); + map.entry(JS::from_ref(el)).or_insert(el.get_state()); } } @@ -1749,8 +1797,10 @@ impl DocumentMethods for Document { let name = QualName::new(ns!(SVG), atom!("title")); let elem = Element::create(name, None, self, ElementCreator::ScriptCreated); - root.upcast::<Node>() - .AppendChild(elem.upcast()) + let parent = root.upcast::<Node>(); + let child = elem.upcast::<Node>(); + parent + .InsertBefore(child, parent.GetFirstChild().r()) .unwrap() } } diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index 7d605ecd133..d420e9b5405 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -1814,14 +1814,13 @@ impl Element { if state.contains(which) == value { return } + let node = self.upcast::<Node>(); + node.owner_doc().element_state_will_change(self); match value { true => state.insert(which), false => state.remove(which), }; self.state.set(state); - - let node = self.upcast::<Node>(); - node.owner_doc().record_element_state_change(self, which); } pub fn get_active_state(&self) -> bool { diff --git a/components/script/dom/htmlelement.rs b/components/script/dom/htmlelement.rs index 84198d29d95..ffb31eca194 100644 --- a/components/script/dom/htmlelement.rs +++ b/components/script/dom/htmlelement.rs @@ -345,7 +345,7 @@ impl HTMLElement { NodeTypeId::Element(ElementTypeId::HTMLElement(type_id)) => match type_id { HTMLElementTypeId::HTMLInputElement => - self.downcast::<HTMLInputElement>().unwrap().Type() != "hidden", + self.downcast::<HTMLInputElement>().unwrap().type_() != atom!("hidden"), HTMLElementTypeId::HTMLButtonElement | HTMLElementTypeId::HTMLMeterElement | HTMLElementTypeId::HTMLOutputElement | diff --git a/components/script/dom/htmlinputelement.rs b/components/script/dom/htmlinputelement.rs index 640df12d01c..ff4492a5520 100644 --- a/components/script/dom/htmlinputelement.rs +++ b/components/script/dom/htmlinputelement.rs @@ -127,6 +127,12 @@ impl HTMLInputElement { let element = HTMLInputElement::new_inherited(localName, prefix, document); Node::reflect_node(box element, document, HTMLInputElementBinding::Wrap) } + + pub fn type_(&self) -> Atom { + self.upcast::<Element>() + .get_attribute(&ns!(""), &atom!("type")) + .map_or_else(|| atom!(""), |a| a.value().as_atom().to_owned()) + } } pub trait LayoutHTMLInputElementHelpers { @@ -268,7 +274,7 @@ impl HTMLInputElementMethods for HTMLInputElement { ("submit") | ("image") | ("reset") | ("button")); // https://html.spec.whatwg.org/multipage/#dom-input-type - make_setter!(SetType, "type"); + make_atomic_setter!(SetType, "type"); // https://html.spec.whatwg.org/multipage/#dom-input-value fn Value(&self) -> DOMString { @@ -337,7 +343,7 @@ impl HTMLInputElementMethods for HTMLInputElement { // https://html.spec.whatwg.org/multipage/#dom-lfe-labels fn Labels(&self) -> Root<NodeList> { - if self.Type() == "hidden" { + if &*self.type_() == "hidden" { let window = window_from_node(self); NodeList::empty(&window) } else { @@ -403,7 +409,7 @@ impl HTMLInputElement { } pub fn get_form_datum(&self, submitter: Option<FormSubmitter>) -> Option<FormDatum> { - let ty = self.Type(); + let ty = self.type_(); let name = self.Name(); let is_submitter = match submitter { Some(FormSubmitter::InputElement(s)) => { @@ -434,7 +440,7 @@ impl HTMLInputElement { } } Some(FormDatum { - ty: ty, + ty: DOMString(ty.to_string()), name: name, value: value }) @@ -585,6 +591,7 @@ impl VirtualMethods for HTMLInputElement { match name { &atom!(name) => AttrValue::from_atomic(value), &atom!("size") => AttrValue::from_limited_u32(value, DEFAULT_INPUT_SIZE), + &atom!(type) => AttrValue::from_atomic(value), _ => self.super_type().unwrap().parse_plain_attribute(name, value), } } @@ -649,6 +656,7 @@ impl VirtualMethods for HTMLInputElement { } RedrawSelection => { self.force_relayout(); + event.PreventDefault(); } Nothing => (), } @@ -856,11 +864,11 @@ impl Activatable for HTMLInputElement { let inputs = node.query_selector_iter(DOMString("input".to_owned())).unwrap() .filter_map(Root::downcast::<HTMLInputElement>) .filter(|input| { - input.form_owner() == owner && match &*input.Type() { - "text" | "search" | "url" | "tel" | - "email" | "password" | "datetime" | - "date" | "month" | "week" | "time" | - "datetime-local" | "number" + input.form_owner() == owner && match input.type_() { + atom!("text") | atom!("search") | atom!("url") | atom!("tel") | + atom!("email") | atom!("password") | atom!("datetime") | + atom!("date") | atom!("month") | atom!("week") | atom!("time") | + atom!("datetime-local") | atom!("number") => true, _ => false } diff --git a/components/script/dom/htmllinkelement.rs b/components/script/dom/htmllinkelement.rs index 6fd36f60074..2860c98dd5c 100644 --- a/components/script/dom/htmllinkelement.rs +++ b/components/script/dom/htmllinkelement.rs @@ -5,55 +5,76 @@ use cssparser::Parser as CssParser; use document_loader::LoadType; use dom::attr::{Attr, AttrValue}; +use dom::bindings::cell::DOMRefCell; use dom::bindings::codegen::Bindings::HTMLLinkElementBinding; use dom::bindings::codegen::Bindings::HTMLLinkElementBinding::HTMLLinkElementMethods; use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods; -use dom::bindings::global::GlobalRef; use dom::bindings::inheritance::Castable; use dom::bindings::js::{JS, MutNullableHeap, Root}; use dom::bindings::js::{RootedReference}; use dom::bindings::refcounted::Trusted; use dom::document::Document; use dom::domtokenlist::DOMTokenList; -use dom::element::{AttributeMutation, Element}; -use dom::event::{Event, EventBubbles, EventCancelable}; -use dom::eventtarget::EventTarget; +use dom::element::{AttributeMutation, Element, ElementCreator}; use dom::htmlelement::HTMLElement; -use dom::node::{Node, window_from_node}; +use dom::node::{Node, document_from_node, window_from_node}; use dom::virtualmethods::VirtualMethods; +use encoding::EncodingRef; +use encoding::all::UTF_8; +use ipc_channel::ipc; +use ipc_channel::router::ROUTER; use layout_interface::{LayoutChan, Msg}; use msg::constellation_msg::ConstellationChan; use msg::constellation_msg::Msg as ConstellationMsg; -use script_traits::StylesheetLoadResponder; +use net_traits::{AsyncResponseListener, AsyncResponseTarget, Metadata}; +use network_listener::{NetworkListener, PreInvoke}; use std::ascii::AsciiExt; use std::borrow::ToOwned; +use std::cell::Cell; use std::default::Default; +use std::mem; +use std::sync::{Arc, Mutex}; use string_cache::Atom; -use style::media_queries::parse_media_query_list; -use url::UrlParser; +use style::media_queries::{MediaQueryList, parse_media_query_list}; +use style::stylesheets::{Origin, Stylesheet}; +use url::{Url, UrlParser}; use util::str::{DOMString, HTML_SPACE_CHARACTERS}; +no_jsmanaged_fields!(Stylesheet); + #[dom_struct] pub struct HTMLLinkElement { htmlelement: HTMLElement, rel_list: MutNullableHeap<JS<DOMTokenList>>, + stylesheet: DOMRefCell<Option<Arc<Stylesheet>>>, + + /// https://html.spec.whatwg.org/multipage/#a-style-sheet-that-is-blocking-scripts + parser_inserted: Cell<bool>, } impl HTMLLinkElement { - fn new_inherited(localName: DOMString, prefix: Option<DOMString>, document: &Document) -> HTMLLinkElement { + fn new_inherited(localName: DOMString, prefix: Option<DOMString>, document: &Document, + creator: ElementCreator) -> HTMLLinkElement { HTMLLinkElement { htmlelement: HTMLElement::new_inherited(localName, prefix, document), rel_list: Default::default(), + parser_inserted: Cell::new(creator == ElementCreator::ParserCreated), + stylesheet: DOMRefCell::new(None), } } #[allow(unrooted_must_root)] pub fn new(localName: DOMString, prefix: Option<DOMString>, - document: &Document) -> Root<HTMLLinkElement> { - let element = HTMLLinkElement::new_inherited(localName, prefix, document); + document: &Document, + creator: ElementCreator) -> Root<HTMLLinkElement> { + let element = HTMLLinkElement::new_inherited(localName, prefix, document, creator); Node::reflect_node(box element, document, HTMLLinkElementBinding::Wrap) } + + pub fn get_stylesheet(&self) -> Option<Arc<Stylesheet>> { + self.stylesheet.borrow().clone() + } } fn get_attr(element: &Element, local_name: &Atom) -> Option<String> { @@ -64,7 +85,7 @@ fn get_attr(element: &Element, local_name: &Atom) -> Option<String> { }) } -fn is_stylesheet(value: &Option<String>) -> bool { +fn string_is_stylesheet(value: &Option<String>) -> bool { match *value { Some(ref value) => { value.split(HTML_SPACE_CHARACTERS) @@ -100,14 +121,14 @@ impl VirtualMethods for HTMLLinkElement { let rel = get_attr(self.upcast(), &atom!(rel)); match attr.local_name() { &atom!(href) => { - if is_stylesheet(&rel) { + if string_is_stylesheet(&rel) { self.handle_stylesheet_url(&attr.value()); } else if is_favicon(&rel) { self.handle_favicon_url(&attr.value()); } }, &atom!(media) => { - if is_stylesheet(&rel) { + if string_is_stylesheet(&rel) { self.handle_stylesheet_url(&attr.value()); } }, @@ -134,7 +155,7 @@ impl VirtualMethods for HTMLLinkElement { let href = get_attr(element, &atom!("href")); match (rel, href) { - (ref rel, Some(ref href)) if is_stylesheet(rel) => { + (ref rel, Some(ref href)) if string_is_stylesheet(rel) => { self.handle_stylesheet_url(href); } (ref rel, Some(ref href)) if is_favicon(rel) => { @@ -164,13 +185,35 @@ impl HTMLLinkElement { let mut css_parser = CssParser::new(&mq_str); let media = parse_media_query_list(&mut css_parser); + // TODO: #8085 - Don't load external stylesheets if the node's mq doesn't match. let doc = window.Document(); - let link_element = Trusted::new(window.get_cx(), self, window.script_chan().clone()); - let load_dispatcher = StylesheetLoadDispatcher::new(link_element); + let script_chan = window.script_chan(); + let elem = Trusted::new(window.get_cx(), self, script_chan.clone()); + + let context = Arc::new(Mutex::new(StylesheetContext { + elem: elem, + media: Some(media), + data: vec!(), + metadata: None, + url: url.clone(), + })); + + let (action_sender, action_receiver) = ipc::channel().unwrap(); + let listener = NetworkListener { + context: context, + script_chan: script_chan, + }; + let response_target = AsyncResponseTarget { + sender: action_sender, + }; + ROUTER.add_route(action_receiver.to_opaque(), box move |message| { + listener.notify(message.to().unwrap()); + }); - let pending = doc.prepare_async_load(LoadType::Stylesheet(url.clone())); - let LayoutChan(ref layout_chan) = window.layout_chan(); - layout_chan.send(Msg::LoadStylesheet(url, media, pending, box load_dispatcher)).unwrap(); + if self.parser_inserted.get() { + doc.increment_script_blocking_stylesheet_count(); + } + doc.load_async(LoadType::Stylesheet(url), response_target); } Err(e) => debug!("Parsing url {} failed: {}", href, e) } @@ -190,6 +233,62 @@ impl HTMLLinkElement { } } +/// The context required for asynchronously loading an external stylesheet. +struct StylesheetContext { + /// The element that initiated the request. + elem: Trusted<HTMLLinkElement>, + media: Option<MediaQueryList>, + /// The response body received to date. + data: Vec<u8>, + /// The response metadata received to date. + metadata: Option<Metadata>, + /// The initial URL requested. + url: Url, +} + +impl PreInvoke for StylesheetContext {} + +impl AsyncResponseListener for StylesheetContext { + fn headers_available(&mut self, metadata: Metadata) { + self.metadata = Some(metadata); + } + + fn data_available(&mut self, payload: Vec<u8>) { + let mut payload = payload; + self.data.append(&mut payload); + } + + fn response_complete(&mut self, _status: Result<(), String>) { + let data = mem::replace(&mut self.data, vec!()); + let metadata = self.metadata.take().unwrap(); + // TODO: Get the actual value. http://dev.w3.org/csswg/css-syntax/#environment-encoding + let environment_encoding = UTF_8 as EncodingRef; + let protocol_encoding_label = metadata.charset.as_ref().map(|s| &**s); + let final_url = metadata.final_url; + let mut sheet = Stylesheet::from_bytes(&data, final_url, protocol_encoding_label, + Some(environment_encoding), Origin::Author); + let media = self.media.take().unwrap(); + sheet.set_media(Some(media)); + let sheet = Arc::new(sheet); + + let elem = self.elem.root(); + let elem = elem.r(); + let document = document_from_node(elem); + let document = document.r(); + + let win = window_from_node(elem); + let LayoutChan(ref layout_chan) = win.r().layout_chan(); + layout_chan.send(Msg::AddStylesheet(sheet.clone())).unwrap(); + + *elem.stylesheet.borrow_mut() = Some(sheet); + document.invalidate_stylesheets(); + if elem.parser_inserted.get() { + document.decrement_script_blocking_stylesheet_count(); + } + document.finish_load(LoadType::Stylesheet(self.url.clone())); + } +} + impl HTMLLinkElementMethods for HTMLLinkElement { // https://html.spec.whatwg.org/multipage/#dom-link-href make_url_getter!(Href); @@ -244,27 +343,3 @@ impl HTMLLinkElementMethods for HTMLLinkElement { // https://html.spec.whatwg.org/multipage/#dom-link-target make_setter!(SetTarget, "target"); } - -pub struct StylesheetLoadDispatcher { - elem: Trusted<HTMLLinkElement>, -} - -impl StylesheetLoadDispatcher { - pub fn new(elem: Trusted<HTMLLinkElement>) -> StylesheetLoadDispatcher { - StylesheetLoadDispatcher { - elem: elem, - } - } -} - -impl StylesheetLoadResponder for StylesheetLoadDispatcher { - fn respond(self: Box<StylesheetLoadDispatcher>) { - let elem = self.elem.root(); - let window = window_from_node(elem.r()); - let event = Event::new(GlobalRef::Window(window.r()), - DOMString("load".to_owned()), - EventBubbles::DoesNotBubble, - EventCancelable::NotCancelable); - event.fire(elem.upcast::<EventTarget>()); - } -} diff --git a/components/script/dom/htmlmetaelement.rs b/components/script/dom/htmlmetaelement.rs index e615a0efbf7..dd0245104cb 100644 --- a/components/script/dom/htmlmetaelement.rs +++ b/components/script/dom/htmlmetaelement.rs @@ -2,6 +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 dom::bindings::cell::DOMRefCell; use dom::bindings::codegen::Bindings::HTMLMetaElementBinding; use dom::bindings::codegen::Bindings::HTMLMetaElementBinding::HTMLMetaElementMethods; use dom::bindings::inheritance::Castable; @@ -9,16 +10,18 @@ use dom::bindings::js::{Root, RootedReference}; use dom::document::Document; use dom::element::Element; use dom::htmlelement::HTMLElement; -use dom::node::{Node, window_from_node}; +use dom::node::{Node, document_from_node}; use dom::virtualmethods::VirtualMethods; -use layout_interface::{LayoutChan, Msg}; use std::ascii::AsciiExt; +use std::sync::Arc; +use style::stylesheets::{CSSRule, Origin, Stylesheet}; use style::viewport::ViewportRule; use util::str::{DOMString, HTML_SPACE_CHARACTERS}; #[dom_struct] pub struct HTMLMetaElement { htmlelement: HTMLElement, + stylesheet: DOMRefCell<Option<Arc<Stylesheet>>>, } impl HTMLMetaElement { @@ -26,7 +29,8 @@ impl HTMLMetaElement { prefix: Option<DOMString>, document: &Document) -> HTMLMetaElement { HTMLMetaElement { - htmlelement: HTMLElement::new_inherited(localName, prefix, document) + htmlelement: HTMLElement::new_inherited(localName, prefix, document), + stylesheet: DOMRefCell::new(None), } } @@ -38,6 +42,10 @@ impl HTMLMetaElement { Node::reflect_node(box element, document, HTMLMetaElementBinding::Wrap) } + pub fn get_stylesheet(&self) -> Option<Arc<Stylesheet>> { + self.stylesheet.borrow().clone() + } + fn process_attributes(&self) { let element = self.upcast::<Element>(); if let Some(name) = element.get_attribute(&ns!(""), &atom!("name")).r() { @@ -45,22 +53,25 @@ impl HTMLMetaElement { let name = name.trim_matches(HTML_SPACE_CHARACTERS); match name { - "viewport" => self.translate_viewport(), + "viewport" => self.apply_viewport(), _ => {} } } } - fn translate_viewport(&self) { + fn apply_viewport(&self) { let element = self.upcast::<Element>(); if let Some(content) = element.get_attribute(&ns!(""), &atom!("content")).r() { let content = content.value(); if !content.is_empty() { if let Some(translated_rule) = ViewportRule::from_meta(&**content) { - let win = window_from_node(self); - let LayoutChan(ref layout_chan) = win.layout_chan(); - - layout_chan.send(Msg::AddMetaViewport(translated_rule)).unwrap(); + *self.stylesheet.borrow_mut() = Some(Arc::new(Stylesheet { + rules: vec![CSSRule::Viewport(translated_rule)], + origin: Origin::Author, + media: None, + })); + let doc = document_from_node(self); + doc.invalidate_stylesheets(); } } } diff --git a/components/script/dom/htmlstyleelement.rs b/components/script/dom/htmlstyleelement.rs index d1ac6dcc37b..e225ec33981 100644 --- a/components/script/dom/htmlstyleelement.rs +++ b/components/script/dom/htmlstyleelement.rs @@ -3,6 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use cssparser::Parser as CssParser; +use dom::bindings::cell::DOMRefCell; use dom::bindings::codegen::Bindings::HTMLStyleElementBinding; use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods; use dom::bindings::inheritance::Castable; @@ -10,9 +11,10 @@ use dom::bindings::js::Root; use dom::document::Document; use dom::element::Element; use dom::htmlelement::HTMLElement; -use dom::node::{ChildrenMutation, Node, window_from_node}; +use dom::node::{ChildrenMutation, Node, document_from_node, window_from_node}; use dom::virtualmethods::VirtualMethods; use layout_interface::{LayoutChan, Msg}; +use std::sync::Arc; use style::media_queries::parse_media_query_list; use style::stylesheets::{Origin, Stylesheet}; use util::str::DOMString; @@ -20,6 +22,7 @@ use util::str::DOMString; #[dom_struct] pub struct HTMLStyleElement { htmlelement: HTMLElement, + stylesheet: DOMRefCell<Option<Arc<Stylesheet>>>, } impl HTMLStyleElement { @@ -27,7 +30,8 @@ impl HTMLStyleElement { prefix: Option<DOMString>, document: &Document) -> HTMLStyleElement { HTMLStyleElement { - htmlelement: HTMLElement::new_inherited(localName, prefix, document) + htmlelement: HTMLElement::new_inherited(localName, prefix, document), + stylesheet: DOMRefCell::new(None), } } @@ -52,13 +56,23 @@ impl HTMLStyleElement { Some(a) => String::from(&**a.value()), None => String::new(), }; + + let data = node.GetTextContent().expect("Element.textContent must be a string"); + let mut sheet = Stylesheet::from_str(&data, url, Origin::Author); let mut css_parser = CssParser::new(&mq_str); let media = parse_media_query_list(&mut css_parser); + sheet.set_media(Some(media)); + let sheet = Arc::new(sheet); - let data = node.GetTextContent().expect("Element.textContent must be a string"); - let sheet = Stylesheet::from_str(&data, url, Origin::Author); let LayoutChan(ref layout_chan) = win.layout_chan(); - layout_chan.send(Msg::AddStylesheet(sheet, media)).unwrap(); + layout_chan.send(Msg::AddStylesheet(sheet.clone())).unwrap(); + *self.stylesheet.borrow_mut() = Some(sheet); + let doc = document_from_node(self); + doc.r().invalidate_stylesheets(); + } + + pub fn get_stylesheet(&self) -> Option<Arc<Stylesheet>> { + self.stylesheet.borrow().clone() } } diff --git a/components/script/dom/htmltextareaelement.rs b/components/script/dom/htmltextareaelement.rs index f9735e76c15..9b3f50bf91e 100644 --- a/components/script/dom/htmltextareaelement.rs +++ b/components/script/dom/htmltextareaelement.rs @@ -352,9 +352,11 @@ impl VirtualMethods for HTMLTextAreaElement { } self.force_relayout(); + event.PreventDefault(); } KeyReaction::RedrawSelection => { self.force_relayout(); + event.PreventDefault(); } KeyReaction::Nothing => (), } diff --git a/components/script/dom/webidls/ElementContentEditable.webidl b/components/script/dom/webidls/ElementContentEditable.webidl new file mode 100644 index 00000000000..4bacaf20a79 --- /dev/null +++ b/components/script/dom/webidls/ElementContentEditable.webidl @@ -0,0 +1,10 @@ +/* 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/. */ + +// https://html.spec.whatwg.org/multipage/#elementcontenteditable +[NoInterfaceObject] +interface ElementContentEditable { + // attribute DOMString contentEditable; + // readonly attribute boolean isContentEditable; +}; diff --git a/components/script/dom/webidls/HTMLElement.webidl b/components/script/dom/webidls/HTMLElement.webidl index 8581d40c46f..8b2e01ea7c6 100644 --- a/components/script/dom/webidls/HTMLElement.webidl +++ b/components/script/dom/webidls/HTMLElement.webidl @@ -31,8 +31,6 @@ interface HTMLElement : Element { //readonly attribute DOMString accessKeyLabel; // attribute boolean draggable; //[PutForwards=value] readonly attribute DOMSettableTokenList dropzone; - // attribute DOMString contentEditable; - //readonly attribute boolean isContentEditable; // attribute HTMLMenuElement? contextMenu; // attribute boolean spellcheck; //void forceSpellCheck(); @@ -57,4 +55,5 @@ partial interface HTMLElement { }; HTMLElement implements GlobalEventHandlers; +HTMLElement implements ElementContentEditable; HTMLElement implements ElementCSSInlineStyle; diff --git a/components/script/dom/websocket.rs b/components/script/dom/websocket.rs index c0ad9e3d253..ea9c0e243aa 100644 --- a/components/script/dom/websocket.rs +++ b/components/script/dom/websocket.rs @@ -295,7 +295,7 @@ impl WebSocket { } // https://html.spec.whatwg.org/multipage/#dom-websocket-send - fn Send_Impl(&self, data_byte_len: u64) -> Fallible<bool> { + fn send_impl(&self, data_byte_len: u64) -> Fallible<bool> { let return_after_buffer = match self.ready_state.get() { WebSocketRequestState::Connecting => { return Err(Error::InvalidState); @@ -380,7 +380,7 @@ impl WebSocketMethods for WebSocket { fn Send(&self, data: USVString) -> Fallible<()> { let data_byte_len = data.0.as_bytes().len() as u64; - let send_data = try!(self.Send_Impl(data_byte_len)); + let send_data = try!(self.send_impl(data_byte_len)); if send_data { let mut other_sender = self.sender.borrow_mut(); @@ -399,7 +399,7 @@ impl WebSocketMethods for WebSocket { If the buffer limit is reached in the first place, there are likely other major problems */ let data_byte_len = data.Size(); - let send_data = try!(self.Send_Impl(data_byte_len)); + let send_data = try!(self.send_impl(data_byte_len)); if send_data { let mut other_sender = self.sender.borrow_mut(); diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index e296cea77d5..e50674c222c 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -99,6 +99,7 @@ pub enum ReflowReason { WindowResize, DOMContentLoaded, DocumentLoaded, + StylesheetLoaded, ImageLoaded, RequestAnimationFrame, WebFontLoaded, @@ -915,6 +916,9 @@ impl Window { debug_reflow_events(&goal, &query_type, &reason); } + let document = self.Document(); + let stylesheets_changed = document.get_and_reset_stylesheets_changed_since_reflow(); + // Send new document and relevant styles to layout. let reflow = ScriptReflow { reflow_info: Reflow { @@ -922,6 +926,8 @@ impl Window { page_clip_rect: self.page_clip_rect.get(), }, document: self.Document().upcast::<Node>().to_trusted_node_address(), + document_stylesheets: document.stylesheets().clone(), + stylesheets_changed: stylesheets_changed, window_size: window_size, script_join_chan: join_chan, query_type: query_type, @@ -1325,6 +1331,7 @@ fn debug_reflow_events(goal: &ReflowGoal, query_type: &ReflowQueryType, reason: ReflowReason::WindowResize => "\tWindowResize", ReflowReason::DOMContentLoaded => "\tDOMContentLoaded", ReflowReason::DocumentLoaded => "\tDocumentLoaded", + ReflowReason::StylesheetLoaded => "\tStylesheetLoaded", ReflowReason::ImageLoaded => "\tImageLoaded", ReflowReason::RequestAnimationFrame => "\tRequestAnimationFrame", ReflowReason::WebFontLoaded => "\tWebFontLoaded", diff --git a/components/script/layout_interface.rs b/components/script/layout_interface.rs index afc7adedbd3..d18098bf6c1 100644 --- a/components/script/layout_interface.rs +++ b/components/script/layout_interface.rs @@ -14,34 +14,26 @@ use ipc_channel::ipc::{IpcReceiver, IpcSender}; use libc::uintptr_t; use msg::compositor_msg::Epoch; use msg::compositor_msg::LayerId; -use msg::constellation_msg::{ConstellationChan, Failure, PipelineExitType, PipelineId}; +use msg::constellation_msg::{ConstellationChan, Failure, PipelineId}; use msg::constellation_msg::{WindowSizeData}; -use net_traits::PendingAsyncLoad; use net_traits::image_cache_task::ImageCacheTask; use profile_traits::mem::ReportsChan; use script_traits::{ConstellationControlMsg, LayoutControlMsg}; -use script_traits::{OpaqueScriptLayoutChannel, StylesheetLoadResponder, UntrustedNodeAddress}; +use script_traits::{OpaqueScriptLayoutChannel, UntrustedNodeAddress}; use selectors::parser::PseudoElement; use std::any::Any; +use std::sync::Arc; use std::sync::mpsc::{Receiver, Sender, channel}; use string_cache::Atom; use style::animation::PropertyAnimation; -use style::media_queries::MediaQueryList; use style::stylesheets::Stylesheet; -use style::viewport::ViewportRule; use url::Url; pub use dom::node::TrustedNodeAddress; /// Asynchronous messages that script can send to layout. pub enum Msg { /// Adds the given stylesheet to the document. - AddStylesheet(Stylesheet, MediaQueryList), - - /// Adds the given stylesheet to the document. - LoadStylesheet(Url, MediaQueryList, PendingAsyncLoad, Box<StylesheetLoadResponder + Send>), - - /// Adds a @viewport rule (translated from a <META name="viewport"> element) to the document. - AddMetaViewport(ViewportRule), + AddStylesheet(Arc<Stylesheet>), /// Puts a document into quirks mode, causing the quirks mode stylesheet to be loaded. SetQuirksMode, @@ -78,7 +70,7 @@ pub enum Msg { /// Requests that the layout task immediately shut down. There must be no more nodes left after /// this, or layout will crash. - ExitNow(PipelineExitType), + ExitNow, /// Get the last epoch counter for this layout task. GetCurrentEpoch(IpcSender<Epoch>), @@ -175,6 +167,10 @@ pub struct ScriptReflow { pub reflow_info: Reflow, /// The document node. pub document: TrustedNodeAddress, + /// The document's list of stylesheets. + pub document_stylesheets: Vec<Arc<Stylesheet>>, + /// Whether the document's stylesheets have changed since the last script reflow. + pub stylesheets_changed: bool, /// The current window size. pub window_size: WindowSizeData, /// The channel that we send a notification to. diff --git a/components/script/script_task.rs b/components/script/script_task.rs index dda6faaa85b..28e194b2a4a 100644 --- a/components/script/script_task.rs +++ b/components/script/script_task.rs @@ -20,7 +20,7 @@ use devtools; use devtools_traits::ScriptToDevtoolsControlMsg; use devtools_traits::{DevtoolScriptControlMsg, DevtoolsPageInfo}; -use document_loader::{DocumentLoader, LoadType}; +use document_loader::DocumentLoader; use dom::bindings::cell::DOMRefCell; use dom::bindings::codegen::Bindings::DocumentBinding::{DocumentMethods, DocumentReadyState}; use dom::bindings::conversions::{FromJSValConvertible, StringificationBehavior}; @@ -64,7 +64,7 @@ use mem::heap_size_of_self_and_children; use msg::compositor_msg::{EventResult, LayerId, ScriptToCompositorMsg}; use msg::constellation_msg::Msg as ConstellationMsg; use msg::constellation_msg::{ConstellationChan, FocusType, LoadData}; -use msg::constellation_msg::{MozBrowserEvent, PipelineExitType, PipelineId}; +use msg::constellation_msg::{MozBrowserEvent, PipelineId}; use msg::constellation_msg::{PipelineNamespace}; use msg::constellation_msg::{SubpageId, WindowSizeData, WorkerId}; use msg::webdriver_msg::WebDriverScriptCommand; @@ -90,6 +90,7 @@ use std::borrow::ToOwned; use std::cell::{Cell, RefCell}; use std::collections::HashSet; use std::io::{Write, stdout}; +use std::marker::PhantomData; use std::mem as std_mem; use std::option::Option; use std::ptr; @@ -367,18 +368,18 @@ impl TimerEventChan for MainThreadTimerEventChan { } } -pub struct StackRootTLS; +pub struct StackRootTLS<'a>(PhantomData<&'a u32>); -impl StackRootTLS { - pub fn new(roots: &RootCollection) -> StackRootTLS { +impl<'a> StackRootTLS<'a> { + pub fn new(roots: &'a RootCollection) -> StackRootTLS<'a> { STACK_ROOTS.with(|ref r| { r.set(Some(RootCollectionPtr(roots as *const _))) }); - StackRootTLS + StackRootTLS(PhantomData) } } -impl Drop for StackRootTLS { +impl<'a> Drop for StackRootTLS<'a> { fn drop(&mut self) { STACK_ROOTS.with(|ref r| r.set(None)); } @@ -871,8 +872,8 @@ impl ScriptTask { let result = self.profile_event(category, move || { match msg { - MixedMessage::FromConstellation(ConstellationControlMsg::ExitPipeline(id, exit_type)) => { - if self.handle_exit_pipeline_msg(id, exit_type) { + MixedMessage::FromConstellation(ConstellationControlMsg::ExitPipeline(id)) => { + if self.handle_exit_pipeline_msg(id) { return Some(false) } }, @@ -1001,10 +1002,6 @@ impl ScriptTask { self.handle_tick_all_animations(pipeline_id), ConstellationControlMsg::WebFontLoaded(pipeline_id) => self.handle_web_font_loaded(pipeline_id), - ConstellationControlMsg::StylesheetLoadComplete(id, url, responder) => { - responder.respond(); - self.handle_resource_loaded(id, LoadType::Stylesheet(url)); - } ConstellationControlMsg::GetCurrentState(sender, pipeline_id) => { let state = self.handle_get_current_state(pipeline_id); sender.send(state).unwrap(); @@ -1153,13 +1150,6 @@ impl ScriptTask { panic!("Page rect message sent to nonexistent pipeline"); } - /// Handle a request to load a page in a new child frame of an existing page. - fn handle_resource_loaded(&self, pipeline: PipelineId, load: LoadType) { - let page = get_page(&self.root_page(), pipeline); - let doc = page.document(); - doc.finish_load(load); - } - /// Get the current state of a given pipeline. fn handle_get_current_state(&self, pipeline_id: PipelineId) -> ScriptState { // Check if the main page load is still pending @@ -1472,7 +1462,7 @@ impl ScriptTask { /// Handles a request to exit the script task and shut down layout. /// Returns true if the script task should shut down and false otherwise. - fn handle_exit_pipeline_msg(&self, id: PipelineId, exit_type: PipelineExitType) -> bool { + fn handle_exit_pipeline_msg(&self, id: PipelineId) -> bool { self.closed_pipelines.borrow_mut().insert(id); // Check if the exit message is for an in progress load. @@ -1490,7 +1480,7 @@ impl ScriptTask { if chan.send(layout_interface::Msg::PrepareToExit(response_chan)).is_ok() { debug!("shutting down layout for page {:?}", id); response_port.recv().unwrap(); - chan.send(layout_interface::Msg::ExitNow(exit_type)).ok(); + chan.send(layout_interface::Msg::ExitNow).ok(); } let has_pending_loads = self.incomplete_loads.borrow().len() > 0; @@ -1505,13 +1495,13 @@ impl ScriptTask { let window = page.window(); if window.pipeline() == id { debug!("shutting down layout for root page {:?}", id); - shut_down_layout(&page, exit_type); + shut_down_layout(&page); return true } // otherwise find just the matching page and exit all sub-pages if let Some(ref mut child_page) = page.remove(id) { - shut_down_layout(&*child_page, exit_type); + shut_down_layout(&*child_page); } false } @@ -1671,10 +1661,32 @@ impl ScriptTask { let is_javascript = incomplete.url.scheme == "javascript"; let parse_input = if is_javascript { + use url::percent_encoding::percent_decode_to; + + // Turn javascript: URL into JS code to eval, according to the steps in + // https://html.spec.whatwg.org/multipage/#javascript-protocol let _ar = JSAutoRequest::new(self.get_cx()); - let evalstr = incomplete.url.non_relative_scheme_data().unwrap(); + let mut script_source_bytes = Vec::new(); + // Start with the scheme data of the parsed URL (5.), while percent-decoding (8.) + percent_decode_to(incomplete.url.non_relative_scheme_data().unwrap().as_bytes(), + &mut script_source_bytes); + // Append question mark and query component, if any (6.), while percent-decoding (8.) + if let Some(ref query) = incomplete.url.query { + script_source_bytes.push(b'?'); + percent_decode_to(query.as_bytes(), &mut script_source_bytes); + } + // Append number sign and fragment component if any (7.), while percent-decoding (8.) + if let Some(ref fragment) = incomplete.url.fragment { + script_source_bytes.push(b'#'); + percent_decode_to(fragment.as_bytes(), &mut script_source_bytes); + } + + // UTF-8 decode (9.) + let script_source = String::from_utf8_lossy(&script_source_bytes); + + // Script source is ready to be evaluated (11.) let mut jsval = RootedValue::new(self.get_cx(), UndefinedValue()); - window.evaluate_js_on_global_with_result(evalstr, jsval.handle_mut()); + window.evaluate_js_on_global_with_result(&script_source, jsval.handle_mut()); let strval = DOMString::from_jsval(self.get_cx(), jsval.handle(), StringificationBehavior::Empty); strval.unwrap_or(DOMString::new()) @@ -2005,7 +2017,7 @@ impl Drop for ScriptTask { } /// Shuts down layout for the given page tree. -fn shut_down_layout(page_tree: &Rc<Page>, exit_type: PipelineExitType) { +fn shut_down_layout(page_tree: &Rc<Page>) { let mut channels = vec!(); for page in page_tree.iter() { @@ -2030,7 +2042,7 @@ fn shut_down_layout(page_tree: &Rc<Page>, exit_type: PipelineExitType) { // Destroy the layout task. If there were node leaks, layout will now crash safely. for chan in channels { - chan.send(layout_interface::Msg::ExitNow(exit_type)).ok(); + chan.send(layout_interface::Msg::ExitNow).ok(); } } diff --git a/components/script_traits/lib.rs b/components/script_traits/lib.rs index 827a729e236..7da6b05cf77 100644 --- a/components/script_traits/lib.rs +++ b/components/script_traits/lib.rs @@ -33,7 +33,7 @@ use libc::c_void; use msg::compositor_msg::{Epoch, LayerId, ScriptToCompositorMsg}; use msg::constellation_msg::{ConstellationChan, Failure, PipelineId, WindowSizeData}; use msg::constellation_msg::{Key, KeyModifiers, KeyState, LoadData, SubpageId}; -use msg::constellation_msg::{MozBrowserEvent, PipelineExitType, PipelineNamespaceId}; +use msg::constellation_msg::{MozBrowserEvent, PipelineNamespaceId}; use msg::webdriver_msg::WebDriverScriptCommand; use net_traits::ResourceTask; use net_traits::image_cache_task::ImageCacheTask; @@ -41,7 +41,6 @@ use net_traits::storage_task::StorageTask; use profile_traits::mem; use std::any::Any; use std::sync::mpsc::{Receiver, Sender}; -use url::Url; use util::mem::HeapSizeOf; /// The address of a node. Layout sends these back. They must be validated via @@ -55,7 +54,7 @@ unsafe impl Send for UntrustedNodeAddress {} #[derive(Deserialize, Serialize)] pub enum LayoutControlMsg { /// Requests that this layout task exit. - ExitNow(PipelineExitType), + ExitNow, /// Requests the current epoch (layout counter) from this layout. GetCurrentEpoch(IpcSender<Epoch>), /// Asks layout to run another step in its animation. @@ -90,13 +89,6 @@ pub struct NewLayoutInfo { pub layout_shutdown_chan: Sender<()>, } -/// `StylesheetLoadResponder` is used to notify a responder that a style sheet -/// has loaded. -pub trait StylesheetLoadResponder { - /// Respond to a loaded style sheet. - fn respond(self: Box<Self>); -} - /// Used to determine if a script has any pending asynchronous activity. #[derive(Copy, Clone, Debug, PartialEq)] pub enum ScriptState { @@ -115,7 +107,7 @@ pub enum ConstellationControlMsg { /// Notifies script that window has been resized but to not take immediate action. ResizeInactive(PipelineId, WindowSizeData), /// Notifies the script that a pipeline should be closed. - ExitPipeline(PipelineId, PipelineExitType), + ExitPipeline(PipelineId), /// Sends a DOM event. SendEvent(PipelineId, CompositorEvent), /// Notifies script of the viewport. @@ -141,8 +133,6 @@ pub enum ConstellationControlMsg { /// Notifies the script task that a new Web font has been loaded, and thus the page should be /// reflowed. WebFontLoaded(PipelineId), - /// Notifies script that a stylesheet has finished loading. - StylesheetLoadComplete(PipelineId, Url, Box<StylesheetLoadResponder + Send>), /// Get the current state of the script task for a given pipeline. GetCurrentState(Sender<ScriptState>, PipelineId), } diff --git a/components/servo/Cargo.lock b/components/servo/Cargo.lock index 71f72c8f7ad..701aadc6d36 100644 --- a/components/servo/Cargo.lock +++ b/components/servo/Cargo.lock @@ -151,7 +151,7 @@ version = "0.0.1" dependencies = [ "azure 0.2.0 (git+https://github.com/servo/rust-azure)", "canvas_traits 0.0.1", - "cssparser 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cssparser 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "gfx_traits 0.0.1", "gleam 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", @@ -169,7 +169,7 @@ name = "canvas_traits" version = "0.0.1" dependencies = [ "azure 0.2.0 (git+https://github.com/servo/rust-azure)", - "cssparser 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cssparser 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "gfx_traits 0.0.1", "ipc-channel 0.1.0 (git+https://github.com/pcwalton/ipc-channel)", @@ -321,7 +321,7 @@ dependencies = [ [[package]] name = "cssparser" -version = "0.3.9" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "encoding 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)", @@ -655,7 +655,7 @@ dependencies = [ "simd 0.1.0 (git+https://github.com/huonw/simd)", "skia 0.0.20130412 (git+https://github.com/servo/skia)", "smallvec 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "style 0.0.1", "time 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-script 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -853,7 +853,7 @@ dependencies = [ "phf_codegen 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)", "rc 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_plugin 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "tendril 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", @@ -935,8 +935,8 @@ dependencies = [ [[package]] name = "js" -version = "0.1.0" -source = "git+https://github.com/servo/rust-mozjs#8fabaf877224fdd7a33286c5de2a99189aae5524" +version = "0.1.1" +source = "git+https://github.com/servo/rust-mozjs#e2458c40432119693456c73ac0710ff182cfc6d2" dependencies = [ "heapsize 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -994,7 +994,7 @@ dependencies = [ "canvas 0.0.1", "canvas_traits 0.0.1", "clock_ticks 0.0.6 (git+https://github.com/tomaka/clock_ticks)", - "cssparser 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cssparser 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "encoding 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1011,12 +1011,12 @@ dependencies = [ "rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", "script 0.0.1", "script_traits 0.0.1", - "selectors 0.2.0 (git+https://github.com/servo/rust-selectors)", + "selectors 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde_macros 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_plugin 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "style 0.0.1", "unicode-bidi 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1138,7 +1138,7 @@ dependencies = [ [[package]] name = "mozjs_sys" version = "0.0.0" -source = "git+https://github.com/servo/mozjs#74e7e954f5445ca0297772d5df543c270339dec2" +source = "git+https://github.com/servo/mozjs#d5a1615370ccfaae35cc3bea0df46cbbb9e1ce1a" dependencies = [ "libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "libz-sys 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1502,7 +1502,7 @@ dependencies = [ "canvas 0.0.1", "canvas_traits 0.0.1", "caseless 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "cssparser 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cssparser 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "devtools_traits 0.0.1", "encoding 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1511,7 +1511,7 @@ dependencies = [ "hyper 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)", "image 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "ipc-channel 0.1.0 (git+https://github.com/pcwalton/ipc-channel)", - "js 0.1.0 (git+https://github.com/servo/rust-mozjs)", + "js 0.1.1 (git+https://github.com/servo/rust-mozjs)", "libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "msg 0.0.1", @@ -1523,10 +1523,10 @@ dependencies = [ "rand 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", "script_traits 0.0.1", - "selectors 0.2.0 (git+https://github.com/servo/rust-selectors)", + "selectors 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_plugin 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "style 0.0.1", "tendril 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1570,16 +1570,16 @@ dependencies = [ [[package]] name = "selectors" -version = "0.2.0" -source = "git+https://github.com/servo/rust-selectors#53f5e09a37684f6a42eb894d7a6fd0b14380a1c6" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "cssparser 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cssparser 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "matches 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "quickersort 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_plugin 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1683,13 +1683,13 @@ dependencies = [ [[package]] name = "string_cache" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_plugin 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache_shared 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache_shared 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1699,12 +1699,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "mac 0.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache_shared 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache_shared 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "string_cache_shared" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "debug_unreachable 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1718,7 +1718,7 @@ version = "0.0.1" dependencies = [ "app_units 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "cssparser 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cssparser 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "encoding 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1728,11 +1728,11 @@ dependencies = [ "num 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", "plugins 0.0.1", "rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", - "selectors 0.2.0 (git+https://github.com/servo/rust-selectors)", + "selectors 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde_macros 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_plugin 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "style_traits 0.0.1", "url 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1744,10 +1744,10 @@ name = "style_tests" version = "0.0.1" dependencies = [ "app_units 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "cssparser 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cssparser 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "selectors 0.2.0 (git+https://github.com/servo/rust-selectors)", - "string_cache 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "selectors 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_plugin 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "style 0.0.1", "style_traits 0.0.1", @@ -1759,14 +1759,14 @@ dependencies = [ name = "style_traits" version = "0.0.1" dependencies = [ - "cssparser 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cssparser 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "num 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", "plugins 0.0.1", "rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", - "selectors 0.2.0 (git+https://github.com/servo/rust-selectors)", + "selectors 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde_macros 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "url 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1895,13 +1895,13 @@ dependencies = [ "app_units 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "azure 0.2.0 (git+https://github.com/servo/rust-azure)", "bitflags 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "cssparser 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cssparser 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", "html5ever 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)", "ipc-channel 0.1.0 (git+https://github.com/pcwalton/ipc-channel)", - "js 0.1.0 (git+https://github.com/servo/rust-mozjs)", + "js 0.1.1 (git+https://github.com/servo/rust-mozjs)", "layers 0.1.0 (git+https://github.com/servo/rust-layers)", "lazy_static 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1911,11 +1911,11 @@ dependencies = [ "plugins 0.0.1", "rand 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", - "selectors 0.2.0 (git+https://github.com/servo/rust-selectors)", + "selectors 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde_macros 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "url 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2068,7 +2068,7 @@ dependencies = [ "phf_codegen 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)", "rc 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_plugin 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "tendril 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/components/style/Cargo.toml b/components/style/Cargo.toml index 9f0a2dfdcfc..d3014bf38dd 100644 --- a/components/style/Cargo.toml +++ b/components/style/Cargo.toml @@ -18,20 +18,13 @@ path = "../util" [dependencies.style_traits] path = "../style_traits" -[dependencies.selectors] -git = "https://github.com/servo/rust-selectors" -features = ["unstable"] - -[dependencies.cssparser] -version = "0.3.9" -features = [ "serde-serialization" ] - [dependencies.url] version = "0.2" features = [ "serde_serialization" ] [dependencies] app_units = {version = "0.1", features = ["plugins"]} +cssparser = { version = "0.4", features = [ "serde-serialization" ] } log = "0.3" encoding = "0.2" fnv = "1.0" @@ -40,6 +33,7 @@ matches = "0.1" bitflags = "0.3" num = "0.1.24" lazy_static = "0.1.10" +selectors = { version = "0.2", features = ["unstable"] } smallvec = "0.1" string_cache = "0.1" string_cache_plugin = "0.1" diff --git a/components/style/custom_properties.rs b/components/style/custom_properties.rs index b5f7c3f3232..fbcf4c46b0e 100644 --- a/components/style/custom_properties.rs +++ b/components/style/custom_properties.rs @@ -5,6 +5,7 @@ use cssparser::{Delimiter, Parser, SourcePosition, ToCss, Token, TokenSerializationType}; use properties::DeclaredValue; use std::ascii::AsciiExt; +use std::borrow::Cow; use std::collections::{HashMap, HashSet}; use std::fmt; use std::sync::Arc; @@ -23,7 +24,7 @@ pub fn parse_name(s: &str) -> Result<&str, ()> { } } -#[derive(Clone, PartialEq)] +#[derive(Clone, PartialEq, Debug)] pub struct SpecifiedValue { css: String, @@ -41,7 +42,7 @@ pub struct BorrowedSpecifiedValue<'a> { references: Option<&'a HashSet<Name>>, } -#[derive(Clone, HeapSizeOf)] +#[derive(Clone, HeapSizeOf, Debug)] pub struct ComputedValue { css: String, first_token_type: TokenSerializationType, @@ -73,6 +74,11 @@ impl ComputedValue { fn push(&mut self, css: &str, css_first_token_type: TokenSerializationType, css_last_token_type: TokenSerializationType) { + // This happens e.g. between to subsequent var() functions: `var(--a)var(--b)`. + // In that case, css_*_token_type is non-sensical. + if css.is_empty() { + return + } self.first_token_type.set_if_nothing(css_first_token_type); // If self.first_token_type was nothing, // self.last_token_type is also nothing and this will be false: @@ -94,44 +100,99 @@ impl ComputedValue { } pub fn parse(input: &mut Parser) -> Result<SpecifiedValue, ()> { - let start = input.position(); let mut references = Some(HashSet::new()); - let (first, last) = try!(parse_declaration_value(input, &mut references)); + let (first, css, last) = try!(parse_self_contained_declaration_value(input, &mut references)); Ok(SpecifiedValue { - css: input.slice_from(start).to_owned(), + css: css.into_owned(), first_token_type: first, last_token_type: last, references: references.unwrap(), }) } +/// Parse the value of a non-custom property that contains `var()` references. +pub fn parse_non_custom_with_var<'i, 't> + (input: &mut Parser<'i, 't>) + -> Result<(TokenSerializationType, Cow<'i, str>), ()> { + let (first_token_type, css, _) = try!(parse_self_contained_declaration_value(input, &mut None)); + Ok((first_token_type, css)) +} + +fn parse_self_contained_declaration_value<'i, 't> + (input: &mut Parser<'i, 't>, + references: &mut Option<HashSet<Name>>) + -> Result<( + TokenSerializationType, + Cow<'i, str>, + TokenSerializationType + ), ()> { + let start_position = input.position(); + let mut missing_closing_characters = String::new(); + let (first, last) = try!( + parse_declaration_value(input, references, &mut missing_closing_characters)); + let mut css: Cow<str> = input.slice_from(start_position).into(); + if !missing_closing_characters.is_empty() { + // Unescaped backslash at EOF in a quoted string is ignored. + if css.ends_with("\\") && matches!(missing_closing_characters.as_bytes()[0], b'"' | b'\'') { + css.to_mut().pop(); + } + css.to_mut().push_str(&missing_closing_characters); + } + Ok((first, css, last)) +} + /// https://drafts.csswg.org/css-syntax-3/#typedef-declaration-value -pub fn parse_declaration_value(input: &mut Parser, references: &mut Option<HashSet<Name>>) - -> Result<(TokenSerializationType, TokenSerializationType), ()> { +fn parse_declaration_value<'i, 't> + (input: &mut Parser<'i, 't>, + references: &mut Option<HashSet<Name>>, + missing_closing_characters: &mut String) + -> Result<(TokenSerializationType, TokenSerializationType), ()> { input.parse_until_before(Delimiter::Bang | Delimiter::Semicolon, |input| { // Need at least one token let start_position = input.position(); try!(input.next_including_whitespace()); input.reset(start_position); - parse_declaration_value_block(input, references) + parse_declaration_value_block(input, references, missing_closing_characters) }) } /// Like parse_declaration_value, /// but accept `!` and `;` since they are only invalid at the top level -fn parse_declaration_value_block(input: &mut Parser, references: &mut Option<HashSet<Name>>) +fn parse_declaration_value_block(input: &mut Parser, + references: &mut Option<HashSet<Name>>, + missing_closing_characters: &mut String) -> Result<(TokenSerializationType, TokenSerializationType), ()> { - let mut first_token_type = TokenSerializationType::nothing(); - let mut last_token_type = TokenSerializationType::nothing(); - while let Ok(token) = input.next_including_whitespace_and_comments() { - first_token_type.set_if_nothing(token.serialization_type()); - // This may be OpenParen when it should be Other (for the closing paren) - // but that doesn’t make a difference since OpenParen is only special - // when it comes *after* an identifier (it would turn into a function) - // but a "last" token will only be concantenated *before* another unrelated token. - last_token_type = token.serialization_type(); - match token { + let mut token_start = input.position(); + let mut token = match input.next_including_whitespace_and_comments() { + Ok(token) => token, + Err(()) => return Ok((TokenSerializationType::nothing(), TokenSerializationType::nothing())) + }; + let first_token_type = token.serialization_type(); + loop { + macro_rules! nested { + () => { + try!(input.parse_nested_block(|input| { + parse_declaration_value_block(input, references, missing_closing_characters) + })) + } + } + macro_rules! check_closed { + ($closing: expr) => { + if !input.slice_from(token_start).ends_with($closing) { + missing_closing_characters.push_str($closing) + } + } + } + let last_token_type = match token { + Token::Comment(_) => { + let token_slice = input.slice_from(token_start); + if !token_slice.ends_with("*/") { + missing_closing_characters.push_str( + if token_slice.ends_with("*") { "/" } else { "*/" }) + } + token.serialization_type() + } Token::BadUrl | Token::BadString | Token::CloseParenthesis | @@ -139,35 +200,90 @@ fn parse_declaration_value_block(input: &mut Parser, references: &mut Option<Has Token::CloseCurlyBracket => { return Err(()) } - - Token::Function(ref name) if name.eq_ignore_ascii_case("var") => { - try!(input.parse_nested_block(|input| { - parse_var_function(input, references) - })); + Token::Function(ref name) => { + if name.eq_ignore_ascii_case("var") { + let position = input.position(); + try!(input.parse_nested_block(|input| { + parse_var_function(input, references) + })); + input.reset(position); + } + nested!(); + check_closed!(")"); + Token::CloseParenthesis.serialization_type() + } + Token::ParenthesisBlock => { + nested!(); + check_closed!(")"); + Token::CloseParenthesis.serialization_type() + } + Token::CurlyBracketBlock => { + nested!(); + check_closed!("}"); + Token::CloseCurlyBracket.serialization_type() } - - Token::Function(_) | - Token::ParenthesisBlock | - Token::CurlyBracketBlock | Token::SquareBracketBlock => { - try!(input.parse_nested_block(|input| { - parse_declaration_value_block(input, references) - })); + nested!(); + check_closed!("]"); + Token::CloseSquareBracket.serialization_type() + } + Token::QuotedString(_) => { + let token_slice = input.slice_from(token_start); + let quote = &token_slice[..1]; + debug_assert!(matches!(quote, "\"" | "'")); + if !(token_slice.ends_with(quote) && token_slice.len() > 1) { + missing_closing_characters.push_str(quote) + } + token.serialization_type() + } + Token::Ident(ref value) | + Token::AtKeyword(ref value) | + Token::Hash(ref value) | + Token::IDHash(ref value) | + Token::UnquotedUrl(ref value) | + Token::Dimension(_, ref value) => { + if value.ends_with("�") && input.slice_from(token_start).ends_with("\\") { + // Unescaped backslash at EOF in these contexts is interpreted as U+FFFD + // Check the value in case the final backslash was itself escaped. + // Serialize as escaped U+FFFD, which is also interpreted as U+FFFD. + // (Unescaped U+FFFD would also work, but removing the backslash is annoying.) + missing_closing_characters.push_str("�") + } + if matches!(token, Token::UnquotedUrl(_)) { + check_closed!(")"); + } + token.serialization_type() + } + _ => { + token.serialization_type() } + }; - _ => {} + token_start = input.position(); + token = if let Ok(token) = input.next_including_whitespace_and_comments() { + token + } else { + return Ok((first_token_type, last_token_type)) } } - Ok((first_token_type, last_token_type)) } // If the var function is valid, return Ok((custom_property_name, fallback)) -fn parse_var_function<'i, 't>(input: &mut Parser<'i, 't>, references: &mut Option<HashSet<Name>>) +fn parse_var_function<'i, 't>(input: &mut Parser<'i, 't>, + references: &mut Option<HashSet<Name>>) -> Result<(), ()> { let name = try!(input.expect_ident()); let name = try!(parse_name(&name)); - if input.expect_comma().is_ok() { - try!(parse_declaration_value(input, references)); + if input.try(|input| input.expect_comma()).is_ok() { + // Exclude `!` and `;` at the top level + // https://drafts.csswg.org/css-syntax/#typedef-declaration-value + try!(input.parse_until_before(Delimiter::Bang | Delimiter::Semicolon, |input| { + // At least one non-comment token. + try!(input.next_including_whitespace()); + // Skip until the end. + while let Ok(_) = input.next_including_whitespace_and_comments() {} + Ok(()) + })); } if let Some(ref mut refs) = *references { refs.insert(Atom::from_slice(name)); diff --git a/components/style/font_face.rs b/components/style/font_face.rs index 54ffdcc7891..ff4f2993d81 100644 --- a/components/style/font_face.rs +++ b/components/style/font_face.rs @@ -3,26 +3,27 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use computed_values::font_family::FontFamily; -use cssparser::{AtRuleParser, DeclarationListParser, DeclarationParser, Parser, Token}; +use cssparser::{AtRuleParser, DeclarationListParser, DeclarationParser, Parser}; use parser::{ParserContext, log_css_error}; use properties::longhands::font_family::parse_one_family; use std::ascii::AsciiExt; use string_cache::Atom; use url::{Url, UrlParser}; +use util::mem::HeapSizeOf; -#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] +#[derive(Clone, Debug, HeapSizeOf, PartialEq, Eq, Deserialize, Serialize)] pub enum Source { Url(UrlSource), Local(Atom), } -#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] +#[derive(Clone, Debug, HeapSizeOf, PartialEq, Eq, Deserialize, Serialize)] pub struct UrlSource { pub url: Url, pub format_hints: Vec<String>, } -#[derive(Debug, PartialEq, Eq)] +#[derive(Debug, HeapSizeOf, PartialEq, Eq)] pub struct FontFaceRule { pub family: Atom, pub sources: Vec<Source>, @@ -106,23 +107,12 @@ fn parse_one_non_generic_family_name(input: &mut Parser) -> Result<Atom, ()> { fn parse_one_src(context: &ParserContext, input: &mut Parser) -> Result<Source, ()> { - let url = match input.next() { - // Parsing url() - Ok(Token::Url(url)) => { - UrlParser::new().base_url(context.base_url).parse(&url).unwrap_or_else( - |_error| Url::parse("about:invalid").unwrap()) - }, - // Parsing local() with early return - Ok(Token::Function(name)) => { - if name.eq_ignore_ascii_case("local") { - return Ok(Source::Local(try!(input.parse_nested_block(|input| { - parse_one_non_generic_family_name(input) - })))) - } - return Err(()) - }, - _ => return Err(()) - }; + if input.try(|input| input.expect_function_matching("local")).is_ok() { + return Ok(Source::Local(try!(input.parse_nested_block(parse_one_non_generic_family_name)))) + } + let url = try!(input.expect_url()); + let url = UrlParser::new().base_url(context.base_url).parse(&url).unwrap_or_else( + |_error| Url::parse("about:invalid").unwrap()); // Parsing optional format() let format_hints = if input.try(|input| input.expect_function_matching("format")).is_ok() { diff --git a/components/style/media_queries.rs b/components/style/media_queries.rs index 76516747bd1..066fc76528d 100644 --- a/components/style/media_queries.rs +++ b/components/style/media_queries.rs @@ -8,15 +8,16 @@ use euclid::size::{Size2D, TypedSize2D}; use properties::longhands; use std::ascii::AsciiExt; use util::geometry::ViewportPx; +use util::mem::HeapSizeOf; use values::specified; -#[derive(Debug, PartialEq)] +#[derive(Debug, HeapSizeOf, PartialEq)] pub struct MediaQueryList { pub media_queries: Vec<MediaQuery> } -#[derive(PartialEq, Eq, Copy, Clone, Debug)] +#[derive(PartialEq, Eq, Copy, Clone, Debug, HeapSizeOf)] pub enum Range<T> { Min(T), Max(T), @@ -59,20 +60,20 @@ impl<T: Ord> Range<T> { } /// http://dev.w3.org/csswg/mediaqueries-3/#media1 -#[derive(PartialEq, Copy, Clone, Debug)] +#[derive(PartialEq, Copy, Clone, Debug, HeapSizeOf)] pub enum Expression { /// http://dev.w3.org/csswg/mediaqueries-3/#width Width(Range<specified::Length>), } /// http://dev.w3.org/csswg/mediaqueries-3/#media0 -#[derive(PartialEq, Eq, Copy, Clone, Debug)] +#[derive(PartialEq, Eq, Copy, Clone, Debug, HeapSizeOf)] pub enum Qualifier { Only, Not, } -#[derive(Debug, PartialEq)] +#[derive(Debug, HeapSizeOf, PartialEq)] pub struct MediaQuery { pub qualifier: Option<Qualifier>, pub media_type: MediaQueryType, @@ -91,20 +92,20 @@ impl MediaQuery { } /// http://dev.w3.org/csswg/mediaqueries-3/#media0 -#[derive(PartialEq, Eq, Copy, Clone, Debug)] +#[derive(PartialEq, Eq, Copy, Clone, Debug, HeapSizeOf)] pub enum MediaQueryType { All, // Always true MediaType(MediaType), } -#[derive(PartialEq, Eq, Copy, Clone, Debug)] +#[derive(PartialEq, Eq, Copy, Clone, Debug, HeapSizeOf)] pub enum MediaType { Screen, Print, Unknown, } -#[derive(Debug)] +#[derive(Debug, HeapSizeOf)] pub struct Device { pub media_type: MediaType, pub viewport_size: TypedSize2D<ViewportPx, f32>, diff --git a/components/style/properties.mako.rs b/components/style/properties.mako.rs index a0ae4363037..847155c8de8 100644 --- a/components/style/properties.mako.rs +++ b/components/style/properties.mako.rs @@ -8,14 +8,13 @@ use std::ascii::AsciiExt; use std::collections::HashSet; use std::default::Default; use std::fmt; -use std::fmt::Debug; use std::hash::{Hash, Hasher}; use std::intrinsics; use std::mem; use std::sync::Arc; use app_units::Au; -use cssparser::{Parser, Color, RGBA, AtRuleParser, DeclarationParser, +use cssparser::{Parser, Color, RGBA, AtRuleParser, DeclarationParser, Delimiter, DeclarationListParser, parse_important, ToCss, TokenSerializationType}; use url::Url; use util::logical_geometry::{LogicalMargin, PhysicalSide, WritingMode}; @@ -211,13 +210,13 @@ pub mod longhands { let var = input.seen_var_functions(); if specified.is_err() && var { input.reset(start); - let (first_token_type, _) = try!( - ::custom_properties::parse_declaration_value(input, &mut None)); + let (first_token_type, css) = try!( + ::custom_properties::parse_non_custom_with_var(input)); return Ok(DeclaredValue::WithVariables { - css: input.slice_from(start).to_owned(), + css: css.into_owned(), first_token_type: first_token_type, base_url: context.base_url.clone(), - from_shorthand: Shorthand::None, + from_shorthand: None, }) } specified @@ -334,7 +333,7 @@ pub mod longhands { -> Result<SpecifiedValue, ()> { specified::parse_border_width(input).map(SpecifiedValue) } - #[derive(Clone, PartialEq)] + #[derive(Debug, Clone, PartialEq)] pub struct SpecifiedValue(pub specified::Length); pub mod computed_value { use app_units::Au; @@ -401,7 +400,7 @@ pub mod longhands { pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> { specified::parse_border_width(input).map(SpecifiedValue) } - #[derive(Clone, PartialEq)] + #[derive(Debug, Clone, PartialEq)] pub struct SpecifiedValue(pub specified::Length); pub mod computed_value { use app_units::Au; @@ -673,7 +672,7 @@ pub mod longhands { use values::CSSFloat; use values::computed::Context; - #[derive(Clone, PartialEq, Copy)] + #[derive(Debug, Clone, PartialEq, Copy)] pub enum SpecifiedValue { Normal, Number(CSSFloat), @@ -711,21 +710,12 @@ pub mod longhands { use app_units::Au; use std::fmt; use values::CSSFloat; - #[derive(PartialEq, Copy, Clone, HeapSizeOf)] + #[derive(PartialEq, Copy, Clone, HeapSizeOf, Debug)] pub enum T { Normal, Length(Au), Number(CSSFloat), } - impl fmt::Debug for T { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - T::Normal => write!(f, "normal"), - T::Length(length) => write!(f, "{:?}%", length), - T::Number(number) => write!(f, "{}", number), - } - } - } } impl ToCss for computed_value::T { fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { @@ -778,7 +768,7 @@ pub mod longhands { <% vertical_align_keywords = ( "baseline sub super top text-top middle bottom text-bottom".split()) %> #[allow(non_camel_case_types)] - #[derive(Clone, PartialEq, Copy)] + #[derive(Debug, Clone, PartialEq, Copy)] pub enum SpecifiedValue { % for keyword in vertical_align_keywords: ${to_rust_ident(keyword)}, @@ -821,23 +811,13 @@ pub mod longhands { use values::AuExtensionMethods; use values::{CSSFloat, computed}; #[allow(non_camel_case_types)] - #[derive(PartialEq, Copy, Clone, HeapSizeOf)] + #[derive(PartialEq, Copy, Clone, HeapSizeOf, Debug)] pub enum T { % for keyword in vertical_align_keywords: ${to_rust_ident(keyword)}, % endfor LengthOrPercentage(computed::LengthOrPercentage), } - impl fmt::Debug for T { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - % for keyword in vertical_align_keywords: - T::${to_rust_ident(keyword)} => write!(f, "${keyword}"), - % endfor - T::LengthOrPercentage(value) => write!(f, "{:?}", value), - } - } - } impl ::cssparser::ToCss for T { fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { match *self { @@ -918,7 +898,7 @@ pub mod longhands { } pub mod computed_value { - #[derive(Clone, Copy, PartialEq, HeapSizeOf)] + #[derive(Debug, Clone, Copy, PartialEq, HeapSizeOf)] pub struct T(pub super::super::overflow_x::computed_value::T); } @@ -971,7 +951,7 @@ pub mod longhands { use cssparser::{self, ToCss}; use std::fmt; - #[derive(PartialEq, Eq, Clone, HeapSizeOf)] + #[derive(Debug, PartialEq, Eq, Clone, HeapSizeOf)] pub enum ContentItem { /// Literal string content. String(String), @@ -1020,7 +1000,7 @@ pub mod longhands { } #[allow(non_camel_case_types)] - #[derive(PartialEq, Eq, Clone, HeapSizeOf)] + #[derive(Debug, PartialEq, Eq, Clone, HeapSizeOf)] pub enum T { normal, none, @@ -1138,8 +1118,9 @@ pub mod longhands { use std::fmt; use url::Url; use values::computed::Context; + use values::LocalToCss; - #[derive(Clone, PartialEq, Eq)] + #[derive(Debug, Clone, PartialEq, Eq)] pub enum SpecifiedValue { None, Url(Url), @@ -1149,9 +1130,7 @@ pub mod longhands { fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { match *self { SpecifiedValue::None => dest.write_str("none"), - SpecifiedValue::Url(ref url) => { - Token::Url(url.to_string().into()).to_css(dest) - } + SpecifiedValue::Url(ref url) => url.to_css(dest), } } } @@ -1160,15 +1139,16 @@ pub mod longhands { use cssparser::{ToCss, Token}; use std::fmt; use url::Url; + use values::LocalToCss; - #[derive(Clone, PartialEq, HeapSizeOf)] + #[derive(Debug, Clone, PartialEq, HeapSizeOf)] pub struct T(pub Option<Url>); impl ToCss for T { fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { match self.0 { None => dest.write_str("none"), - Some(ref url) => Token::Url(url.to_string().into()).to_css(dest) + Some(ref url) => url.to_css(dest), } } } @@ -1209,7 +1189,7 @@ pub mod longhands { pub use self::computed_value::T as SpecifiedValue; pub mod computed_value { - #[derive(Clone, PartialEq, HeapSizeOf)] + #[derive(Debug, Clone, PartialEq, HeapSizeOf)] pub struct T(pub Vec<(String,String)>); } @@ -1278,7 +1258,7 @@ pub mod longhands { pub use self::computed_value::T as SpecifiedValue; pub mod computed_value { - #[derive(Clone, PartialEq, HeapSizeOf)] + #[derive(Debug, Clone, PartialEq, HeapSizeOf)] pub struct T(pub Vec<(String,i32)>); } @@ -1359,10 +1339,11 @@ pub mod longhands { use std::fmt; use values::computed::Context; use values::specified::Image; + use values::LocalToCss; pub mod computed_value { use values::computed; - #[derive(Clone, PartialEq, HeapSizeOf)] + #[derive(Debug, Clone, PartialEq, HeapSizeOf)] pub struct T(pub Option<computed::Image>); } @@ -1370,15 +1351,14 @@ pub mod longhands { fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { match self.0 { None => dest.write_str("none"), - Some(computed::Image::Url(ref url)) => - ::cssparser::Token::Url(url.to_string().into()).to_css(dest), + Some(computed::Image::Url(ref url)) => url.to_css(dest), Some(computed::Image::LinearGradient(ref gradient)) => gradient.to_css(dest) } } } - #[derive(Clone, PartialEq)] + #[derive(Debug, Clone, PartialEq)] pub struct SpecifiedValue(pub Option<Image>); impl ToCss for SpecifiedValue { @@ -1431,7 +1411,7 @@ pub mod longhands { } } - #[derive(Clone, PartialEq, Copy)] + #[derive(Debug, Clone, PartialEq, Copy)] pub struct SpecifiedValue { pub horizontal: specified::LengthOrPercentage, pub vertical: specified::LengthOrPercentage, @@ -1727,7 +1707,7 @@ pub mod longhands { use std::fmt; use string_cache::Atom; - #[derive(PartialEq, Eq, Clone, Hash, HeapSizeOf)] + #[derive(Debug, PartialEq, Eq, Clone, Hash, HeapSizeOf)] pub enum FontFamily { FamilyName(Atom), // Generic @@ -1763,7 +1743,7 @@ pub mod longhands { Ok(()) } } - #[derive(Clone, PartialEq, Eq, Hash, HeapSizeOf)] + #[derive(Debug, Clone, PartialEq, Eq, Hash, HeapSizeOf)] pub struct T(pub Vec<FontFamily>); } @@ -1808,7 +1788,7 @@ pub mod longhands { use std::fmt; use values::computed::Context; - #[derive(Clone, PartialEq, Eq, Copy)] + #[derive(Debug, Clone, PartialEq, Eq, Copy)] pub enum SpecifiedValue { Bolder, Lighter, @@ -1855,21 +1835,12 @@ pub mod longhands { } pub mod computed_value { use std::fmt; - #[derive(PartialEq, Eq, Copy, Clone, Hash, Deserialize, Serialize, HeapSizeOf)] + #[derive(PartialEq, Eq, Copy, Clone, Hash, Deserialize, Serialize, HeapSizeOf, Debug)] pub enum T { % for weight in range(100, 901, 100): Weight${weight} = ${weight}, % endfor } - impl fmt::Debug for T { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - % for weight in range(100, 901, 100): - T::Weight${weight} => write!(f, "{}", ${weight}), - % endfor - } - } - } impl T { #[inline] pub fn is_bold(self) -> bool { @@ -1944,7 +1915,7 @@ pub mod longhands { } } - #[derive(Clone, PartialEq)] + #[derive(Debug, Clone, PartialEq)] pub struct SpecifiedValue(pub specified::LengthOrPercentage); pub mod computed_value { use app_units::Au; @@ -2044,7 +2015,7 @@ pub mod longhands { use values::AuExtensionMethods; use values::computed::Context; - #[derive(Clone, Copy, PartialEq)] + #[derive(Debug, Clone, Copy, PartialEq)] pub enum SpecifiedValue { Normal, Specified(specified::Length), @@ -2061,7 +2032,7 @@ pub mod longhands { pub mod computed_value { use app_units::Au; - #[derive(Clone, PartialEq, HeapSizeOf)] + #[derive(Debug, Clone, PartialEq, HeapSizeOf)] pub struct T(pub Option<Au>); } @@ -2107,7 +2078,7 @@ pub mod longhands { use values::AuExtensionMethods; use values::computed::Context; - #[derive(Clone, Copy, PartialEq)] + #[derive(Debug, Clone, Copy, PartialEq)] pub enum SpecifiedValue { Normal, Specified(specified::Length), // FIXME(SimonSapin) support percentages @@ -2124,7 +2095,7 @@ pub mod longhands { pub mod computed_value { use app_units::Au; - #[derive(Clone, PartialEq, HeapSizeOf)] + #[derive(Debug, Clone, PartialEq, HeapSizeOf)] pub struct T(pub Option<Au>); } @@ -2549,7 +2520,7 @@ pub mod longhands { use values::AuExtensionMethods; use values::computed::Context; - #[derive(Clone, Copy, PartialEq)] + #[derive(Debug, Clone, Copy, PartialEq)] pub enum SpecifiedValue { Auto, Specified(specified::Length), @@ -2566,7 +2537,7 @@ pub mod longhands { pub mod computed_value { use app_units::Au; - #[derive(Clone, PartialEq, HeapSizeOf)] + #[derive(Debug, Clone, PartialEq, HeapSizeOf)] pub struct T(pub Option<Au>); } @@ -2611,7 +2582,7 @@ pub mod longhands { use std::fmt; use values::computed::Context; - #[derive(Clone, Copy, PartialEq)] + #[derive(Debug, Clone, Copy, PartialEq)] pub enum SpecifiedValue { Auto, Specified(u32), @@ -2627,7 +2598,7 @@ pub mod longhands { } pub mod computed_value { - #[derive(Clone, PartialEq, HeapSizeOf)] + #[derive(Debug, Clone, PartialEq, HeapSizeOf)] pub struct T(pub Option<u32>); } @@ -2678,7 +2649,7 @@ pub mod longhands { use values::AuExtensionMethods; use values::computed::Context; - #[derive(Clone, Copy, PartialEq)] + #[derive(Debug, Clone, Copy, PartialEq)] pub enum SpecifiedValue { Normal, Specified(specified::Length), @@ -2695,7 +2666,7 @@ pub mod longhands { pub mod computed_value { use app_units::Au; - #[derive(Clone, PartialEq, HeapSizeOf)] + #[derive(Debug, Clone, PartialEq, HeapSizeOf)] pub struct T(pub Option<Au>); } @@ -2750,7 +2721,7 @@ pub mod longhands { } } - #[derive(Clone, PartialEq)] + #[derive(Debug, Clone, PartialEq)] pub struct SpecifiedValue(pub CSSFloat); pub mod computed_value { use values::CSSFloat; @@ -2786,10 +2757,10 @@ pub mod longhands { use values::AuExtensionMethods; use values::computed::Context; - #[derive(Clone, PartialEq)] + #[derive(Debug, Clone, PartialEq)] pub struct SpecifiedValue(Vec<SpecifiedBoxShadow>); - #[derive(Clone, PartialEq)] + #[derive(Debug, Clone, PartialEq)] pub struct SpecifiedBoxShadow { pub offset_x: specified::Length, pub offset_y: specified::Length, @@ -2842,10 +2813,10 @@ pub mod longhands { use std::fmt; use values::computed; - #[derive(Clone, PartialEq, HeapSizeOf)] + #[derive(Clone, PartialEq, HeapSizeOf, Debug)] pub struct T(pub Vec<BoxShadow>); - #[derive(Clone, PartialEq, Copy, HeapSizeOf)] + #[derive(Clone, PartialEq, Copy, HeapSizeOf, Debug)] pub struct BoxShadow { pub offset_x: Au, pub offset_y: Au, @@ -2854,17 +2825,6 @@ pub mod longhands { pub color: computed::CSSColor, pub inset: bool, } - - impl fmt::Debug for BoxShadow { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - if self.inset { - let _ = write!(f, "inset "); - } - let _ = write!(f, "{:?} {:?} {:?} {:?} {:?}", self.offset_x, self.offset_y, - self.blur_radius, self.spread_radius, self.color); - Ok(()) - } - } } impl ToCss for computed_value::T { @@ -3020,7 +2980,7 @@ pub mod longhands { pub left: Au, } - #[derive(Clone, PartialEq, HeapSizeOf)] + #[derive(Debug, Clone, PartialEq, HeapSizeOf)] pub struct T(pub Option<ClipRect>); } @@ -3161,10 +3121,10 @@ pub mod longhands { use values::AuExtensionMethods; use values::computed::Context; - #[derive(Clone, PartialEq)] + #[derive(Clone, PartialEq, Debug)] pub struct SpecifiedValue(Vec<SpecifiedTextShadow>); - #[derive(Clone, PartialEq)] + #[derive(Clone, PartialEq, Debug)] pub struct SpecifiedTextShadow { pub offset_x: specified::Length, pub offset_y: specified::Length, @@ -3172,20 +3132,6 @@ pub mod longhands { pub color: Option<specified::CSSColor>, } - impl fmt::Debug for SpecifiedTextShadow { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let _ = write!(f, - "{:?} {:?} {:?}", - self.offset_x, - self.offset_y, - self.blur_radius); - if let Some(ref color) = self.color { - let _ = write!(f, "{:?}", color); - } - Ok(()) - } - } - pub mod computed_value { use app_units::Au; use cssparser::Color; @@ -3356,7 +3302,7 @@ pub mod longhands { use values::CSSFloat; use values::specified::{Angle, Length}; - #[derive(Clone, PartialEq)] + #[derive(Debug, Clone, PartialEq)] pub struct SpecifiedValue(Vec<SpecifiedFilter>); // TODO(pcwalton): `drop-shadow` @@ -4354,7 +4300,7 @@ pub mod longhands { pub use values::computed::Time as SingleComputedValue; - #[derive(Clone, PartialEq, HeapSizeOf)] + #[derive(Debug, Clone, PartialEq, HeapSizeOf)] pub struct T(pub Vec<SingleComputedValue>); impl ToComputedValue for T { @@ -4900,7 +4846,10 @@ pub mod shorthands { -> Result<(), ()> { input.look_for_var_functions(); let start = input.position(); - let value = parse_value(context, input); + let value = input.parse_entirely(|input| parse_value(context, input)); + if value.is_err() { + while let Ok(_) = input.next() {} // Look for var() after the error. + } let var = input.seen_var_functions(); if let Ok(value) = value { % for sub_property in shorthand.sub_properties: @@ -4914,16 +4863,15 @@ pub mod shorthands { Ok(()) } else if var { input.reset(start); - let (first_token_type, _) = try!( - ::custom_properties::parse_declaration_value(input, &mut None)); - let css = input.slice_from(start); + let (first_token_type, css) = try!( + ::custom_properties::parse_non_custom_with_var(input)); % for sub_property in shorthand.sub_properties: declarations.push(PropertyDeclaration::${sub_property.camel_case}( DeclaredValue::WithVariables { - css: css.to_owned(), + css: css.clone().into_owned(), first_token_type: first_token_type, base_url: context.base_url.clone(), - from_shorthand: Shorthand::${shorthand.camel_case}, + from_shorthand: Some(Shorthand::${shorthand.camel_case}), } )); % endfor @@ -5645,12 +5593,12 @@ mod property_bit_field { ::stylesheets::Origin::Author, base_url); Parser::new(&css).parse_entirely(|input| { match from_shorthand { - Shorthand::None => { + None => { longhands::${property.ident}::parse_specified(&context, input) } % for shorthand in SHORTHANDS: % if property in shorthand.sub_properties: - Shorthand::${shorthand.camel_case} => { + Some(Shorthand::${shorthand.camel_case}) => { shorthands::${shorthand.ident}::parse_value(&context, input) .map(|result| match result.${property.ident} { Some(value) => DeclaredValue::Value(value), @@ -5718,10 +5666,12 @@ impl<'a, 'b> DeclarationParser for PropertyDeclarationParser<'a, 'b> { fn parse_value(&self, name: &str, input: &mut Parser) -> Result<(Vec<PropertyDeclaration>, bool), ()> { let mut results = vec![]; - match PropertyDeclaration::parse(name, self.context, input, &mut results) { - PropertyDeclarationParseResult::ValidOrIgnoredDeclaration => {} - _ => return Err(()) - } + try!(input.parse_until_before(Delimiter::Bang, |input| { + match PropertyDeclaration::parse(name, self.context, input, &mut results) { + PropertyDeclarationParseResult::ValidOrIgnoredDeclaration => Ok(()), + _ => Err(()) + } + })); let important = input.try(parse_important).is_ok(); Ok((results, important)) } @@ -5814,12 +5764,39 @@ impl CSSWideKeyword { #[derive(Clone, Copy, Eq, PartialEq, Debug)] pub enum Shorthand { - None, % for property in SHORTHANDS: ${property.camel_case}, % endfor } +impl Shorthand { + pub fn from_name(name: &str) -> Option<Shorthand> { + match_ignore_ascii_case! { name, + % for property in SHORTHANDS[:-1]: + "${property.name}" => Some(Shorthand::${property.camel_case}), + % endfor + % for property in SHORTHANDS[-1:]: + "${property.name}" => Some(Shorthand::${property.camel_case}) + % endfor + _ => None + } + } + + pub fn longhands(&self) -> &'static [&'static str] { + % for property in SHORTHANDS: + static ${property.ident.upper()}: &'static [&'static str] = &[ + % for sub in property.sub_properties: + "${sub.name}", + % endfor + ]; + % endfor + match *self { + % for property in SHORTHANDS: + Shorthand::${property.camel_case} => ${property.ident.upper()}, + % endfor + } + } +} #[derive(Clone, PartialEq, Eq, Debug)] pub enum DeclaredValue<T> { @@ -5828,7 +5805,7 @@ pub enum DeclaredValue<T> { css: String, first_token_type: TokenSerializationType, base_url: Url, - from_shorthand: Shorthand + from_shorthand: Option<Shorthand>, }, Initial, Inherit, @@ -5841,7 +5818,7 @@ impl<T: ToCss> ToCss for DeclaredValue<T> { fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { match *self { DeclaredValue::Value(ref inner) => inner.to_css(dest), - DeclaredValue::WithVariables { ref css, from_shorthand: Shorthand::None, .. } => { + DeclaredValue::WithVariables { ref css, from_shorthand: None, .. } => { dest.write_str(css) } // https://drafts.csswg.org/css-variables/#variables-in-shorthands @@ -5852,7 +5829,7 @@ impl<T: ToCss> ToCss for DeclaredValue<T> { } } -#[derive(PartialEq, Clone)] +#[derive(PartialEq, Clone, Debug)] pub enum PropertyDeclaration { % for property in LONGHANDS: ${property.camel_case}(DeclaredValue<longhands::${property.ident}::SpecifiedValue>), @@ -5931,6 +5908,41 @@ impl PropertyDeclaration { } } + /// If this is a pending-substitution value from the given shorthand, return that value + // Extra space here because < seems to be removed by Mako when immediately followed by &. + // ↓ + pub fn with_variables_from_shorthand(&self, shorthand: Shorthand) -> Option< &str> { + match *self { + % for property in LONGHANDS: + PropertyDeclaration::${property.camel_case}(ref value) => match *value { + DeclaredValue::WithVariables { ref css, from_shorthand: Some(s), .. } + if s == shorthand => { + Some(&**css) + } + _ => None + }, + % endfor + PropertyDeclaration::Custom(..) => None, + } + } + + /// Return whether this is a pending-substitution value. + /// https://drafts.csswg.org/css-variables/#variables-in-shorthands + pub fn with_variables(&self) -> bool { + match *self { + % for property in LONGHANDS: + PropertyDeclaration::${property.camel_case}(ref value) => match *value { + DeclaredValue::WithVariables { .. } => true, + _ => false, + }, + % endfor + PropertyDeclaration::Custom(_, ref value) => match *value { + DeclaredValue::WithVariables { .. } => true, + _ => false, + } + } + } + pub fn matches(&self, name: &str) -> bool { match *self { % for property in LONGHANDS: @@ -6033,13 +6045,6 @@ impl PropertyDeclaration { } } -impl Debug for PropertyDeclaration { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}: {}", self.name(), self.value()) - } -} - - pub mod style_structs { use super::longhands; @@ -6913,27 +6918,6 @@ macro_rules! longhand_properties_idents { } } -// Extra space here because < seems to be removed by Mako when immediately followed by &. -// ↓ -pub fn longhands_from_shorthand(shorthand: &str) -> Option< &'static [&'static str]> { - % for property in SHORTHANDS: - static ${property.ident.upper()}: &'static [&'static str] = &[ - % for sub in property.sub_properties: - "${sub.name}", - % endfor - ]; - % endfor - match_ignore_ascii_case!{ shorthand, - % for property in SHORTHANDS[:-1]: - "${property.name}" => Some(${property.ident.upper()}), - % endfor - % for property in SHORTHANDS[-1:]: - "${property.name}" => Some(${property.ident.upper()}) - % endfor - _ => None - } -} - /// Corresponds to the fields in `gfx::font_template::FontTemplateDescriptor`. fn compute_font_hash(font: &mut style_structs::Font) { let mut hasher: FnvHasher = Default::default(); diff --git a/components/style/restyle_hints.rs b/components/style/restyle_hints.rs index acb521b0f10..c180c13dcde 100644 --- a/components/style/restyle_hints.rs +++ b/components/style/restyle_hints.rs @@ -195,11 +195,10 @@ impl StateDependencySet { StateDependencySet { deps: Vec::new() } } - pub fn compute_hint<E>(&self, el: &E, current_state: ElementState, state_changes: ElementState) + pub fn compute_hint<E>(&self, el: &E, current_state: ElementState, old_state: ElementState) -> RestyleHint where E: Element, E: Clone { let mut hint = RestyleHint::empty(); - let mut old_state = current_state; - old_state.toggle(state_changes); + let state_changes = current_state ^ old_state; for dep in &self.deps { if state_changes.intersects(dep.state) { let old_el: ElementWrapper<E> = ElementWrapper::new_with_override(el.clone(), old_state); @@ -220,15 +219,16 @@ impl StateDependencySet { let mut cur = selector; let mut combinator: Option<Combinator> = None; loop { - if let Some(rightmost) = cur.simple_selectors.last() { - let state_dep = selector_to_state(rightmost); - if !state_dep.is_empty() { - self.deps.push(StateDependency { - selector: cur.clone(), - combinator: combinator, - state: state_dep, - }); - } + let mut deps = ElementState::empty(); + for s in &cur.simple_selectors { + deps.insert(selector_to_state(s)); + } + if !deps.is_empty() { + self.deps.push(StateDependency { + selector: cur.clone(), + combinator: combinator, + state: deps, + }); } cur = match cur.next { diff --git a/components/style/selector_matching.rs b/components/style/selector_matching.rs index 53f1a0d3589..85dadac97d1 100644 --- a/components/style/selector_matching.rs +++ b/components/style/selector_matching.rs @@ -3,7 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use legacy::PresentationalHintSynthesis; -use media_queries::Device; +use media_queries::{Device, MediaType}; use node::TElementAttributes; use properties::{PropertyDeclaration, PropertyDeclarationBlock}; use restyle_hints::{RestyleHint, StateDependencySet}; @@ -26,16 +26,67 @@ use viewport::{MaybeNew, ViewportRuleCascade}; pub type DeclarationBlock = GenericDeclarationBlock<Vec<PropertyDeclaration>>; -pub struct Stylist { - // List of stylesheets (including all media rules) - stylesheets: Vec<Stylesheet>, +lazy_static! { + pub static ref USER_OR_USER_AGENT_STYLESHEETS: Vec<Stylesheet> = { + let mut stylesheets = vec!(); + // FIXME: presentational-hints.css should be at author origin with zero specificity. + // (Does it make a difference?) + for &filename in &["user-agent.css", "servo.css", "presentational-hints.css"] { + match read_resource_file(&[filename]) { + Ok(res) => { + let ua_stylesheet = Stylesheet::from_bytes( + &res, + Url::parse(&format!("chrome:///{:?}", filename)).unwrap(), + None, + None, + Origin::UserAgent); + stylesheets.push(ua_stylesheet); + } + Err(..) => { + error!("Failed to load UA stylesheet {}!", filename); + process::exit(1); + } + } + } + for &(ref contents, ref url) in &opts::get().user_stylesheets { + stylesheets.push(Stylesheet::from_bytes( + &contents, url.clone(), None, None, Origin::User)); + } + stylesheets + }; +} + +lazy_static! { + pub static ref QUIRKS_MODE_STYLESHEET: Stylesheet = { + match read_resource_file(&["quirks-mode.css"]) { + Ok(res) => { + Stylesheet::from_bytes( + &res, + Url::parse("chrome:///quirks-mode.css").unwrap(), + None, + None, + Origin::UserAgent) + }, + Err(..) => { + error!("Stylist failed to load 'quirks-mode.css'!"); + process::exit(1); + } + } + }; +} +pub struct Stylist { // Device that the stylist is currently evaluating against. pub device: Device, - // If true, a stylesheet has been added or the device has - // changed, and the stylist needs to be updated. - is_dirty: bool, + // Viewport constraints based on the current device. + viewport_constraints: Option<ViewportConstraints>, + + // If true, the quirks-mode stylesheet is applied. + quirks_mode: bool, + + // If true, the device has changed, and the stylist needs to be updated. + is_device_dirty: bool, // The current selector maps, after evaluating media // rules against the current device. @@ -51,10 +102,11 @@ pub struct Stylist { impl Stylist { #[inline] pub fn new(device: Device) -> Stylist { - let mut stylist = Stylist { - stylesheets: vec!(), + let stylist = Stylist { + viewport_constraints: None, device: device, - is_dirty: true, + is_device_dirty: true, + quirks_mode: false, element_map: PerPseudoElementSelectorMap::new(), before_map: PerPseudoElementSelectorMap::new(), @@ -63,152 +115,126 @@ impl Stylist { state_deps: StateDependencySet::new(), }; // FIXME: Add iso-8859-9.css when the document’s encoding is ISO-8859-8. - // FIXME: presentational-hints.css should be at author origin with zero specificity. - // (Does it make a difference?) - for &filename in &["user-agent.css", "servo.css", "presentational-hints.css"] { - match read_resource_file(&[filename]) { - Ok(res) => { - let ua_stylesheet = Stylesheet::from_bytes( - &res, - Url::parse(&format!("chrome:///{:?}", filename)).unwrap(), - None, - None, - Origin::UserAgent); - stylist.add_stylesheet(ua_stylesheet); - } - Err(..) => { - error!("Stylist::new() failed at loading {}!", filename); - process::exit(1); - } - } - } - for &(ref contents, ref url) in &opts::get().user_stylesheets { - stylist.add_stylesheet(Stylesheet::from_bytes( - &contents, url.clone(), None, None, Origin::User)); - } stylist } - #[inline] - pub fn stylesheets(&self) -> &[Stylesheet] { - &self.stylesheets - } + pub fn update(&mut self, doc_stylesheets: &[&Stylesheet], + stylesheets_changed: bool) -> bool { + if !(self.is_device_dirty || stylesheets_changed) { + return false; + } + self.element_map = PerPseudoElementSelectorMap::new(); + self.before_map = PerPseudoElementSelectorMap::new(); + self.after_map = PerPseudoElementSelectorMap::new(); + self.rules_source_order = 0; + self.state_deps.clear(); + + for ref stylesheet in USER_OR_USER_AGENT_STYLESHEETS.iter() { + self.add_stylesheet(&stylesheet); + } - pub fn constrain_viewport(&self) -> Option<ViewportConstraints> { - let cascaded_rule = self.stylesheets.iter() - .flat_map(|s| s.effective_rules(&self.device).viewport()) - .cascade(); + if self.quirks_mode { + self.add_stylesheet(&QUIRKS_MODE_STYLESHEET); + } - ViewportConstraints::maybe_new(self.device.viewport_size, &cascaded_rule) + for ref stylesheet in doc_stylesheets.iter() { + self.add_stylesheet(stylesheet); + } + + self.is_device_dirty = false; + true } - pub fn update(&mut self) -> bool { - if self.is_dirty { - self.element_map = PerPseudoElementSelectorMap::new(); - self.before_map = PerPseudoElementSelectorMap::new(); - self.after_map = PerPseudoElementSelectorMap::new(); - self.rules_source_order = 0; - self.state_deps.clear(); - - for stylesheet in &self.stylesheets { - let (mut element_map, mut before_map, mut after_map) = match stylesheet.origin { - Origin::UserAgent => ( - &mut self.element_map.user_agent, - &mut self.before_map.user_agent, - &mut self.after_map.user_agent, - ), - Origin::Author => ( - &mut self.element_map.author, - &mut self.before_map.author, - &mut self.after_map.author, - ), - Origin::User => ( - &mut self.element_map.user, - &mut self.before_map.user, - &mut self.after_map.user, - ), - }; - let mut rules_source_order = self.rules_source_order; - - // Take apart the StyleRule into individual Rules and insert - // them into the SelectorMap of that priority. - macro_rules! append( - ($style_rule: ident, $priority: ident) => { - if $style_rule.declarations.$priority.len() > 0 { - for selector in &$style_rule.selectors { - let map = match selector.pseudo_element { - None => &mut element_map, - Some(PseudoElement::Before) => &mut before_map, - Some(PseudoElement::After) => &mut after_map, - }; - map.$priority.insert(Rule { - selector: selector.compound_selectors.clone(), - declarations: DeclarationBlock { - specificity: selector.specificity, - declarations: $style_rule.declarations.$priority.clone(), - source_order: rules_source_order, - }, - }); - } - } - }; - ); - - for style_rule in stylesheet.effective_rules(&self.device).style() { - append!(style_rule, normal); - append!(style_rule, important); - rules_source_order += 1; - for selector in &style_rule.selectors { - self.state_deps.note_selector(selector.compound_selectors.clone()); + fn add_stylesheet(&mut self, stylesheet: &Stylesheet) { + let device = &self.device; + if !stylesheet.is_effective_for_device(device) { + return; + } + let (mut element_map, mut before_map, mut after_map) = match stylesheet.origin { + Origin::UserAgent => ( + &mut self.element_map.user_agent, + &mut self.before_map.user_agent, + &mut self.after_map.user_agent, + ), + Origin::Author => ( + &mut self.element_map.author, + &mut self.before_map.author, + &mut self.after_map.author, + ), + Origin::User => ( + &mut self.element_map.user, + &mut self.before_map.user, + &mut self.after_map.user, + ), + }; + let mut rules_source_order = self.rules_source_order; + + // Take apart the StyleRule into individual Rules and insert + // them into the SelectorMap of that priority. + macro_rules! append( + ($style_rule: ident, $priority: ident) => { + if $style_rule.declarations.$priority.len() > 0 { + for selector in &$style_rule.selectors { + let map = match selector.pseudo_element { + None => &mut element_map, + Some(PseudoElement::Before) => &mut before_map, + Some(PseudoElement::After) => &mut after_map, + }; + map.$priority.insert(Rule { + selector: selector.compound_selectors.clone(), + declarations: DeclarationBlock { + specificity: selector.specificity, + declarations: $style_rule.declarations.$priority.clone(), + source_order: rules_source_order, + }, + }); } } - self.rules_source_order = rules_source_order; + }; + ); + + for style_rule in stylesheet.effective_rules(&self.device).style() { + append!(style_rule, normal); + append!(style_rule, important); + rules_source_order += 1; + for selector in &style_rule.selectors { + self.state_deps.note_selector(selector.compound_selectors.clone()); } - - self.is_dirty = false; - return true; } - - false + self.rules_source_order = rules_source_order; } pub fn restyle_hint_for_state_change<E>(&self, element: &E, current_state: ElementState, - state_change: ElementState) + old_state: ElementState) -> RestyleHint where E: Element + Clone { - self.state_deps.compute_hint(element, current_state, state_change) + self.state_deps.compute_hint(element, current_state, old_state) } - pub fn set_device(&mut self, device: Device) { - let is_dirty = self.is_dirty || self.stylesheets.iter() + pub fn set_device(&mut self, mut device: Device, stylesheets: &[&Stylesheet]) { + let cascaded_rule = stylesheets.iter() + .flat_map(|s| s.effective_rules(&self.device).viewport()) + .cascade(); + + self.viewport_constraints = ViewportConstraints::maybe_new(self.device.viewport_size, &cascaded_rule); + if let Some(ref constraints) = self.viewport_constraints { + device = Device::new(MediaType::Screen, constraints.size); + } + let is_device_dirty = self.is_device_dirty || stylesheets.iter() .flat_map(|stylesheet| stylesheet.rules().media()) .any(|media_rule| media_rule.evaluate(&self.device) != media_rule.evaluate(&device)); self.device = device; - self.is_dirty |= is_dirty; + self.is_device_dirty |= is_device_dirty; } - pub fn add_quirks_mode_stylesheet(&mut self) { - match read_resource_file(&["quirks-mode.css"]) { - Ok(res) => { - self.add_stylesheet(Stylesheet::from_bytes( - &res, - Url::parse("chrome:///quirks-mode.css").unwrap(), - None, - None, - Origin::UserAgent)); - } - Err(..) => { - error!("Stylist::add_quirks_mode_stylesheet() failed at loading 'quirks-mode.css'!"); - process::exit(1); - } - } + pub fn viewport_constraints(&self) -> &Option<ViewportConstraints> { + &self.viewport_constraints } - pub fn add_stylesheet(&mut self, stylesheet: Stylesheet) { - self.stylesheets.push(stylesheet); - self.is_dirty = true; + pub fn set_quirks_mode(&mut self, enabled: bool) { + self.quirks_mode = enabled; } /// Returns the applicable CSS declarations for the given element. This corresponds to @@ -227,7 +253,7 @@ impl Stylist { -> bool where E: Element + TElementAttributes, V: VecLike<DeclarationBlock> { - assert!(!self.is_dirty); + assert!(!self.is_device_dirty); assert!(style_attribute.is_none() || pseudo_element.is_none(), "Style attributes do not apply to pseudo-elements"); @@ -294,8 +320,8 @@ impl Stylist { shareable } - pub fn is_dirty(&self) -> bool { - self.is_dirty + pub fn is_device_dirty(&self) -> bool { + self.is_device_dirty } } diff --git a/components/style/stylesheets.rs b/components/style/stylesheets.rs index c9d5354238a..00e9def4900 100644 --- a/components/style/stylesheets.rs +++ b/components/style/stylesheets.rs @@ -17,12 +17,13 @@ use std::iter::Iterator; use std::slice; use string_cache::{Atom, Namespace}; use url::Url; +use util::mem::HeapSizeOf; use viewport::ViewportRule; /// Each style rule has an origin, which determines where it enters the cascade. /// /// http://dev.w3.org/csswg/css-cascade/#cascading-origins -#[derive(Clone, PartialEq, Eq, Copy, Debug)] +#[derive(Clone, PartialEq, Eq, Copy, Debug, HeapSizeOf)] pub enum Origin { /// http://dev.w3.org/csswg/css-cascade/#cascade-origin-ua UserAgent, @@ -35,16 +36,18 @@ pub enum Origin { } -#[derive(Debug, PartialEq)] +#[derive(Debug, HeapSizeOf, PartialEq)] pub struct Stylesheet { /// List of rules in the order they were found (important for /// cascading order) pub rules: Vec<CSSRule>, + /// List of media associated with the Stylesheet, if any. + pub media: Option<MediaQueryList>, pub origin: Origin, } -#[derive(Debug, PartialEq)] +#[derive(Debug, HeapSizeOf, PartialEq)] pub enum CSSRule { Charset(String), Namespace(Option<String>, Namespace), @@ -54,7 +57,7 @@ pub enum CSSRule { Viewport(ViewportRule), } -#[derive(Debug, PartialEq)] +#[derive(Debug, HeapSizeOf, PartialEq)] pub struct MediaRule { pub media_queries: MediaQueryList, pub rules: Vec<CSSRule>, @@ -67,7 +70,7 @@ impl MediaRule { } } -#[derive(Debug, PartialEq)] +#[derive(Debug, HeapSizeOf, PartialEq)] pub struct StyleRule { pub selectors: Vec<Selector>, pub declarations: PropertyDeclarationBlock, @@ -131,6 +134,23 @@ impl Stylesheet { Stylesheet { origin: origin, rules: rules, + media: None, + } + } + + /// Set the MediaQueryList associated with the style-sheet. + pub fn set_media(&mut self, media: Option<MediaQueryList>) { + self.media = media; + } + + /// Returns whether the style-sheet applies for the current device depending + /// on the associated MediaQueryList. + /// + /// Always true if no associated MediaQueryList exists. + pub fn is_effective_for_device(&self, device: &Device) -> bool { + match self.media { + Some(ref media) => media.evaluate(device), + None => true } } diff --git a/components/style/values.rs b/components/style/values.rs index a32b668fa9c..b6f630142b9 100644 --- a/components/style/values.rs +++ b/components/style/values.rs @@ -5,7 +5,10 @@ pub use cssparser::RGBA; use app_units::Au; -use std::fmt; +use cssparser::CssStringWriter; +use std::fmt::{self, Write}; +use url::Url; + // This is a re-implementation of the ToCss trait in cssparser. // It's done here because the app_units crate shouldn't depend @@ -64,6 +67,22 @@ macro_rules! define_numbered_css_keyword_enum { } } +/// The real ToCss trait can’t be implemented for Url +/// since neither rust-url or rust-cssparser depend on the other. +pub trait LocalToCss { + fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write; +} + +impl LocalToCss for Url { + fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + try!(dest.write_str("url(\"")); + try!(write!(CssStringWriter::new(dest), "{}", self)); + try!(dest.write_str("\")")); + Ok(()) + } +} + + pub type CSSFloat = f32; pub const FONT_MEDIUM_PX: i32 = 16; @@ -1177,20 +1196,16 @@ pub mod specified { impl Image { pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<Image, ()> { - match try!(input.next()) { - Token::Url(url) => { - Ok(Image::Url(context.parse_url(&url))) - } - Token::Function(name) => { - match_ignore_ascii_case! { name, - "linear-gradient" => { - Ok(Image::LinearGradient(try!( - input.parse_nested_block(LinearGradient::parse_function)))) - } - _ => Err(()) + if let Ok(url) = input.try(|input| input.expect_url()) { + Ok(Image::Url(context.parse_url(&url))) + } else { + match_ignore_ascii_case! { try!(input.expect_function()), + "linear-gradient" => { + Ok(Image::LinearGradient(try!( + input.parse_nested_block(LinearGradient::parse_function)))) } + _ => Err(()) } - _ => Err(()) } } } diff --git a/components/style/viewport.rs b/components/style/viewport.rs index 226edda1fd9..698015686a1 100644 --- a/components/style/viewport.rs +++ b/components/style/viewport.rs @@ -18,10 +18,11 @@ use std::str::Chars; use style_traits::viewport::{Orientation, UserZoom, ViewportConstraints, Zoom}; use stylesheets::Origin; use util::geometry::ViewportPx; +use util::mem::HeapSizeOf; use values::computed::{Context, ToComputedValue}; use values::specified::{Length, LengthOrPercentageOrAuto, ViewportPercentageLength}; -#[derive(Copy, Clone, Debug, PartialEq)] +#[derive(Copy, Clone, Debug, HeapSizeOf, PartialEq)] pub enum ViewportDescriptor { MinWidth(ViewportLength), MaxWidth(ViewportLength), @@ -133,7 +134,7 @@ struct ViewportRuleParser<'a, 'b: 'a> { context: &'a ParserContext<'b> } -#[derive(Copy, Clone, Debug, PartialEq)] +#[derive(Copy, Clone, Debug, HeapSizeOf, PartialEq)] pub struct ViewportDescriptorDeclaration { pub origin: Origin, pub descriptor: ViewportDescriptor, @@ -228,7 +229,7 @@ impl<'a, 'b> DeclarationParser for ViewportRuleParser<'a, 'b> { } } -#[derive(Debug, PartialEq)] +#[derive(Debug, HeapSizeOf, PartialEq)] pub struct ViewportRule { pub declarations: Vec<ViewportDescriptorDeclaration> } diff --git a/components/style_traits/Cargo.toml b/components/style_traits/Cargo.toml index 414bdf87ce2..7db0ab0298a 100644 --- a/components/style_traits/Cargo.toml +++ b/components/style_traits/Cargo.toml @@ -10,26 +10,20 @@ path = "lib.rs" [dependencies.util] path = "../util" -[dependencies.cssparser] -version = "0.3" -features = [ "serde-serialization" ] - [dependencies.plugins] path = "../plugins" -[dependencies.selectors] -git = "https://github.com/servo/rust-selectors" -features = ["unstable"] - [dependencies.url] version = "0.2" features = [ "serde_serialization" ] [dependencies] +cssparser = { version = "0.4", features = [ "serde-serialization" ] } euclid = {version = "0.3", features = ["plugins"]} log = "0.3" lazy_static = "0.1.10" num = "0.1.24" rustc-serialize = "0.3" +selectors = "0.2" serde = "0.6" serde_macros = "0.6" diff --git a/components/style_traits/viewport.rs b/components/style_traits/viewport.rs index e08fc3909c6..ac7c1a16be6 100644 --- a/components/style_traits/viewport.rs +++ b/components/style_traits/viewport.rs @@ -20,7 +20,7 @@ define_css_keyword_enum!(Orientation: "landscape" => Landscape); -#[derive(Debug, PartialEq, Deserialize, Serialize)] +#[derive(Clone, Debug, PartialEq, Deserialize, Serialize)] pub struct ViewportConstraints { pub size: TypedSize2D<ViewportPx, f32>, @@ -54,7 +54,7 @@ impl ToCss for ViewportConstraints { /// Zoom is a number | percentage | auto /// See http://dev.w3.org/csswg/css-device-adapt/#descdef-viewport-zoom -#[derive(Copy, Clone, Debug, PartialEq)] +#[derive(Copy, Clone, Debug, HeapSizeOf, PartialEq)] pub enum Zoom { Number(f32), Percentage(f32), diff --git a/components/util/Cargo.toml b/components/util/Cargo.toml index 7eac36662d3..480324f0578 100644 --- a/components/util/Cargo.toml +++ b/components/util/Cargo.toml @@ -29,10 +29,6 @@ git = "https://github.com/servo/rust-mozjs" git = "https://github.com/servo/rust-layers" features = ["plugins"] -[dependencies.cssparser] -version = "0.3" -features = [ "serde-serialization" ] - [dependencies.ipc-channel] git = "https://github.com/pcwalton/ipc-channel" @@ -40,11 +36,9 @@ git = "https://github.com/pcwalton/ipc-channel" version = "0.2" features = [ "serde_serialization" ] -[dependencies.selectors] -git = "https://github.com/servo/rust-selectors" - [dependencies] app_units = {version = "0.1", features = ["plugins"]} +cssparser = { version = "0.4", features = [ "serde-serialization" ] } log = "0.3" bitflags = "0.3" html5ever = { version = "0.2.1", features = ["unstable"] } @@ -55,6 +49,7 @@ smallvec = "0.1" num_cpus = "0.2.2" num = "0.1.24" euclid = {version = "0.3", features = ["plugins"]} +selectors = "0.2" serde = "0.6" serde_macros = "0.6" string_cache = "0.1" diff --git a/components/util/opts.rs b/components/util/opts.rs index 1aa7f7f574f..ce8c75cd045 100644 --- a/components/util/opts.rs +++ b/components/util/opts.rs @@ -74,6 +74,9 @@ pub struct Opts { /// Log GC passes and their durations. pub gc_profile: bool, + /// Load web fonts synchronously to avoid non-deterministic network-driven reflows. + pub load_webfonts_synchronously: bool, + pub headless: bool, pub hard_fail: bool, @@ -267,6 +270,9 @@ pub struct DebugOptions { /// Log GC passes and their durations. pub gc_profile: bool, + + /// Load web fonts synchronously to avoid non-deterministic network-driven reflows. + pub load_webfonts_synchronously: bool, } @@ -301,6 +307,7 @@ impl DebugOptions { "convert-mouse-to-touch" => debug_options.convert_mouse_to_touch = true, "replace-surrogates" => debug_options.replace_surrogates = true, "gc-profile" => debug_options.gc_profile = true, + "load-webfonts-synchronously" => debug_options.load_webfonts_synchronously = true, "" => {}, _ => return Err(option) }; @@ -345,6 +352,8 @@ pub fn print_debug_usage(app: &str) -> ! { print_option("replace-surrogates", "Replace unpaires surrogates in DOM strings with U+FFFD. \ See https://github.com/servo/servo/issues/6564"); print_option("gc-profile", "Log GC passes and their durations."); + print_option("load-webfonts-synchronously", + "Load web fonts synchronously to avoid non-deterministic network-driven reflows"); println!(""); @@ -434,6 +443,7 @@ pub fn default_opts() -> Opts { output_file: None, replace_surrogates: false, gc_profile: false, + load_webfonts_synchronously: false, headless: true, hard_fail: true, bubble_inline_sizes_separately: false, @@ -652,6 +662,7 @@ pub fn from_cmdline_args(args: &[String]) { output_file: opt_match.opt_str("o"), replace_surrogates: debug_options.replace_surrogates, gc_profile: debug_options.gc_profile, + load_webfonts_synchronously: debug_options.load_webfonts_synchronously, headless: opt_match.opt_present("z"), hard_fail: opt_match.opt_present("f"), bubble_inline_sizes_separately: bubble_inline_sizes_separately, diff --git a/ports/cef/Cargo.lock b/ports/cef/Cargo.lock index 3e4e193401b..819bc11730a 100644 --- a/ports/cef/Cargo.lock +++ b/ports/cef/Cargo.lock @@ -14,7 +14,7 @@ dependencies = [ "gfx 0.0.1", "gleam 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", "glutin_app 0.0.1", - "js 0.1.0 (git+https://github.com/servo/rust-mozjs)", + "js 0.1.1 (git+https://github.com/servo/rust-mozjs)", "layers 0.1.0 (git+https://github.com/servo/rust-layers)", "libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -144,7 +144,7 @@ version = "0.0.1" dependencies = [ "azure 0.2.0 (git+https://github.com/servo/rust-azure)", "canvas_traits 0.0.1", - "cssparser 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cssparser 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "gfx_traits 0.0.1", "gleam 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", @@ -162,7 +162,7 @@ name = "canvas_traits" version = "0.0.1" dependencies = [ "azure 0.2.0 (git+https://github.com/servo/rust-azure)", - "cssparser 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cssparser 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "gfx_traits 0.0.1", "ipc-channel 0.1.0 (git+https://github.com/pcwalton/ipc-channel)", @@ -314,7 +314,7 @@ dependencies = [ [[package]] name = "cssparser" -version = "0.3.9" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "encoding 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)", @@ -615,7 +615,7 @@ dependencies = [ "simd 0.1.0 (git+https://github.com/huonw/simd)", "skia 0.0.20130412 (git+https://github.com/servo/skia)", "smallvec 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "style 0.0.1", "time 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-script 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -806,7 +806,7 @@ dependencies = [ "phf_codegen 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)", "rc 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_plugin 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "tendril 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", @@ -888,8 +888,8 @@ dependencies = [ [[package]] name = "js" -version = "0.1.0" -source = "git+https://github.com/servo/rust-mozjs#8fabaf877224fdd7a33286c5de2a99189aae5524" +version = "0.1.1" +source = "git+https://github.com/servo/rust-mozjs#e2458c40432119693456c73ac0710ff182cfc6d2" dependencies = [ "heapsize 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -947,7 +947,7 @@ dependencies = [ "canvas 0.0.1", "canvas_traits 0.0.1", "clock_ticks 0.0.6 (git+https://github.com/tomaka/clock_ticks)", - "cssparser 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cssparser 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "encoding 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -964,12 +964,12 @@ dependencies = [ "rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", "script 0.0.1", "script_traits 0.0.1", - "selectors 0.2.0 (git+https://github.com/servo/rust-selectors)", + "selectors 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde_macros 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_plugin 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "style 0.0.1", "unicode-bidi 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1091,7 +1091,7 @@ dependencies = [ [[package]] name = "mozjs_sys" version = "0.0.0" -source = "git+https://github.com/servo/mozjs#74e7e954f5445ca0297772d5df543c270339dec2" +source = "git+https://github.com/servo/mozjs#d5a1615370ccfaae35cc3bea0df46cbbb9e1ce1a" dependencies = [ "libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "libz-sys 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1133,6 +1133,7 @@ dependencies = [ "hyper 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)", "ipc-channel 0.1.0 (git+https://github.com/pcwalton/ipc-channel)", "log 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "msg 0.0.1", "net_traits 0.0.1", "openssl 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", "plugins 0.0.1", @@ -1435,7 +1436,7 @@ dependencies = [ "canvas 0.0.1", "canvas_traits 0.0.1", "caseless 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "cssparser 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cssparser 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "devtools_traits 0.0.1", "encoding 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1444,7 +1445,7 @@ dependencies = [ "hyper 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)", "image 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "ipc-channel 0.1.0 (git+https://github.com/pcwalton/ipc-channel)", - "js 0.1.0 (git+https://github.com/servo/rust-mozjs)", + "js 0.1.1 (git+https://github.com/servo/rust-mozjs)", "libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "msg 0.0.1", @@ -1456,10 +1457,10 @@ dependencies = [ "rand 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", "script_traits 0.0.1", - "selectors 0.2.0 (git+https://github.com/servo/rust-selectors)", + "selectors 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_plugin 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "style 0.0.1", "tendril 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1494,16 +1495,16 @@ dependencies = [ [[package]] name = "selectors" -version = "0.2.0" -source = "git+https://github.com/servo/rust-selectors#53f5e09a37684f6a42eb894d7a6fd0b14380a1c6" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "cssparser 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cssparser 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "matches 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "quickersort 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_plugin 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1641,13 +1642,13 @@ dependencies = [ [[package]] name = "string_cache" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_plugin 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache_shared 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache_shared 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1657,12 +1658,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "mac 0.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache_shared 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache_shared 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "string_cache_shared" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "debug_unreachable 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1676,7 +1677,7 @@ version = "0.0.1" dependencies = [ "app_units 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "cssparser 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cssparser 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "encoding 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1686,11 +1687,11 @@ dependencies = [ "num 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", "plugins 0.0.1", "rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", - "selectors 0.2.0 (git+https://github.com/servo/rust-selectors)", + "selectors 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde_macros 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_plugin 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "style_traits 0.0.1", "url 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1701,14 +1702,14 @@ dependencies = [ name = "style_traits" version = "0.0.1" dependencies = [ - "cssparser 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cssparser 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "num 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", "plugins 0.0.1", "rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", - "selectors 0.2.0 (git+https://github.com/servo/rust-selectors)", + "selectors 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde_macros 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "url 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1837,13 +1838,13 @@ dependencies = [ "app_units 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "azure 0.2.0 (git+https://github.com/servo/rust-azure)", "bitflags 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "cssparser 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cssparser 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", "html5ever 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)", "ipc-channel 0.1.0 (git+https://github.com/pcwalton/ipc-channel)", - "js 0.1.0 (git+https://github.com/servo/rust-mozjs)", + "js 0.1.1 (git+https://github.com/servo/rust-mozjs)", "layers 0.1.0 (git+https://github.com/servo/rust-layers)", "lazy_static 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1853,11 +1854,11 @@ dependencies = [ "plugins 0.0.1", "rand 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", - "selectors 0.2.0 (git+https://github.com/servo/rust-selectors)", + "selectors 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde_macros 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "url 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2000,7 +2001,7 @@ dependencies = [ "phf_codegen 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)", "rc 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_plugin 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "tendril 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/ports/gonk/Cargo.lock b/ports/gonk/Cargo.lock index b0093519403..692d4b39388 100644 --- a/ports/gonk/Cargo.lock +++ b/ports/gonk/Cargo.lock @@ -136,7 +136,7 @@ version = "0.0.1" dependencies = [ "azure 0.2.0 (git+https://github.com/servo/rust-azure)", "canvas_traits 0.0.1", - "cssparser 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cssparser 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "gfx_traits 0.0.1", "gleam 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", @@ -154,7 +154,7 @@ name = "canvas_traits" version = "0.0.1" dependencies = [ "azure 0.2.0 (git+https://github.com/servo/rust-azure)", - "cssparser 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cssparser 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "gfx_traits 0.0.1", "ipc-channel 0.1.0 (git+https://github.com/pcwalton/ipc-channel)", @@ -306,7 +306,7 @@ dependencies = [ [[package]] name = "cssparser" -version = "0.3.9" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "encoding 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)", @@ -617,7 +617,7 @@ dependencies = [ "simd 0.1.0 (git+https://github.com/huonw/simd)", "skia 0.0.20130412 (git+https://github.com/servo/skia)", "smallvec 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "style 0.0.1", "time 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-script 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -786,7 +786,7 @@ dependencies = [ "phf_codegen 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)", "rc 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_plugin 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "tendril 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", @@ -868,8 +868,8 @@ dependencies = [ [[package]] name = "js" -version = "0.1.0" -source = "git+https://github.com/servo/rust-mozjs#8fabaf877224fdd7a33286c5de2a99189aae5524" +version = "0.1.1" +source = "git+https://github.com/servo/rust-mozjs#e2458c40432119693456c73ac0710ff182cfc6d2" dependencies = [ "heapsize 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -927,7 +927,7 @@ dependencies = [ "canvas 0.0.1", "canvas_traits 0.0.1", "clock_ticks 0.0.6 (git+https://github.com/tomaka/clock_ticks)", - "cssparser 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cssparser 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "encoding 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -944,12 +944,12 @@ dependencies = [ "rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", "script 0.0.1", "script_traits 0.0.1", - "selectors 0.2.0 (git+https://github.com/servo/rust-selectors)", + "selectors 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde_macros 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_plugin 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "style 0.0.1", "unicode-bidi 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1071,7 +1071,7 @@ dependencies = [ [[package]] name = "mozjs_sys" version = "0.0.0" -source = "git+https://github.com/servo/mozjs#74e7e954f5445ca0297772d5df543c270339dec2" +source = "git+https://github.com/servo/mozjs#d5a1615370ccfaae35cc3bea0df46cbbb9e1ce1a" dependencies = [ "libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "libz-sys 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1113,6 +1113,7 @@ dependencies = [ "hyper 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)", "ipc-channel 0.1.0 (git+https://github.com/pcwalton/ipc-channel)", "log 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "msg 0.0.1", "net_traits 0.0.1", "openssl 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", "plugins 0.0.1", @@ -1415,7 +1416,7 @@ dependencies = [ "canvas 0.0.1", "canvas_traits 0.0.1", "caseless 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "cssparser 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cssparser 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "devtools_traits 0.0.1", "encoding 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1424,7 +1425,7 @@ dependencies = [ "hyper 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)", "image 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "ipc-channel 0.1.0 (git+https://github.com/pcwalton/ipc-channel)", - "js 0.1.0 (git+https://github.com/servo/rust-mozjs)", + "js 0.1.1 (git+https://github.com/servo/rust-mozjs)", "libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "msg 0.0.1", @@ -1436,10 +1437,10 @@ dependencies = [ "rand 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", "script_traits 0.0.1", - "selectors 0.2.0 (git+https://github.com/servo/rust-selectors)", + "selectors 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_plugin 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "style 0.0.1", "tendril 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1474,16 +1475,16 @@ dependencies = [ [[package]] name = "selectors" -version = "0.2.0" -source = "git+https://github.com/servo/rust-selectors#53f5e09a37684f6a42eb894d7a6fd0b14380a1c6" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "cssparser 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cssparser 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "matches 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "quickersort 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_plugin 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1619,13 +1620,13 @@ dependencies = [ [[package]] name = "string_cache" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_plugin 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache_shared 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache_shared 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1635,12 +1636,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "mac 0.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache_shared 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache_shared 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "string_cache_shared" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "debug_unreachable 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1654,7 +1655,7 @@ version = "0.0.1" dependencies = [ "app_units 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "cssparser 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cssparser 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "encoding 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1664,11 +1665,11 @@ dependencies = [ "num 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", "plugins 0.0.1", "rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", - "selectors 0.2.0 (git+https://github.com/servo/rust-selectors)", + "selectors 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde_macros 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_plugin 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "style_traits 0.0.1", "url 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1679,14 +1680,14 @@ dependencies = [ name = "style_traits" version = "0.0.1" dependencies = [ - "cssparser 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cssparser 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "num 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", "plugins 0.0.1", "rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", - "selectors 0.2.0 (git+https://github.com/servo/rust-selectors)", + "selectors 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde_macros 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "url 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1815,13 +1816,13 @@ dependencies = [ "app_units 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "azure 0.2.0 (git+https://github.com/servo/rust-azure)", "bitflags 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "cssparser 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cssparser 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", "html5ever 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)", "ipc-channel 0.1.0 (git+https://github.com/pcwalton/ipc-channel)", - "js 0.1.0 (git+https://github.com/servo/rust-mozjs)", + "js 0.1.1 (git+https://github.com/servo/rust-mozjs)", "layers 0.1.0 (git+https://github.com/servo/rust-layers)", "lazy_static 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1831,11 +1832,11 @@ dependencies = [ "plugins 0.0.1", "rand 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", - "selectors 0.2.0 (git+https://github.com/servo/rust-selectors)", + "selectors 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde_macros 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "url 0.2.37 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1948,7 +1949,7 @@ dependencies = [ "phf_codegen 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)", "rc 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", - "string_cache 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "string_cache 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "string_cache_plugin 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "tendril 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/python/mach_bootstrap.py b/python/mach_bootstrap.py index 67d8c236100..9f1bfd5f485 100644 --- a/python/mach_bootstrap.py +++ b/python/mach_bootstrap.py @@ -9,6 +9,7 @@ import platform import subprocess import sys from distutils.spawn import find_executable +from pipes import quote SEARCH_PATHS = [ os.path.join("python", "mach"), @@ -102,7 +103,7 @@ def _activate_virtualenv(topdir): except (subprocess.CalledProcessError, OSError): sys.exit("Python virtualenv failed to execute properly.") - execfile(activate_path, dict(__file__=activate_path)) + execfile(activate_path, dict(__file__=quote(activate_path))) # TODO: Right now, we iteratively install all the requirements by invoking # `pip install` each time. If it were the case that there were conflicting diff --git a/python/servo/build_commands.py b/python/servo/build_commands.py index ad901ba0fd4..c2f7381e7ac 100644 --- a/python/servo/build_commands.py +++ b/python/servo/build_commands.py @@ -232,6 +232,9 @@ class MachCommands(CommandBase): env['OPENSSL_INCLUDE_DIR'] = path.join(openssl_dir, "include") env['OPENSSL_STATIC'] = 'TRUE' + if not (self.config["build"]["ccache"] == ""): + env['CCACHE'] = self.config["build"]["ccache"] + status = call( ["cargo", "build"] + opts, env=env, cwd=self.servo_crate(), verbose=verbose) diff --git a/python/servo/command_base.py b/python/servo/command_base.py index 14f8dff0c6f..4ceb5c629f4 100644 --- a/python/servo/command_base.py +++ b/python/servo/command_base.py @@ -107,6 +107,7 @@ class CommandBase(object): self.config["build"].setdefault("android", False) self.config["build"].setdefault("mode", "") self.config["build"].setdefault("debug-mozjs", False) + self.config["build"].setdefault("ccache", "") self.config.setdefault("android", {}) self.config["android"].setdefault("sdk", "") diff --git a/python/servo/testing_commands.py b/python/servo/testing_commands.py index 91e7fb09089..b362ee50037 100644 --- a/python/servo/testing_commands.py +++ b/python/servo/testing_commands.py @@ -598,4 +598,5 @@ testing/web-platform/mozilla/tests for Servo-only tests""" % ref_path) wpt_kwargs = vars(p.parse_args(args)) self.context.commands.dispatch("test-wpt", self.context, **wpt_kwargs) - proc.wait() + if editor: + proc.wait() diff --git a/servobuild.example b/servobuild.example index 8d57d659e9b..8157de5b88b 100644 --- a/servobuild.example +++ b/servobuild.example @@ -36,6 +36,8 @@ rustc-with-gold = true android = false # Set "debug-mozjs" or use `mach build --debug-mozjs` to build a debug spidermonkey. debug-mozjs = false +# Set to the path to your ccache binary to enable caching of compiler outputs +#ccache = "/usr/local/bin/ccache" # Android information [android] diff --git a/tests/unit/style/Cargo.toml b/tests/unit/style/Cargo.toml index b8f0cb51476..30140cecbd7 100644 --- a/tests/unit/style/Cargo.toml +++ b/tests/unit/style/Cargo.toml @@ -17,13 +17,11 @@ path = "../../../components/style_traits" [dependencies.util] path = "../../../components/util" -[dependencies.selectors] -git = "https://github.com/servo/rust-selectors" - [dependencies] app_units = {version = "0.1", features = ["plugins"]} url = "0.2" -cssparser = "0.3.1" +cssparser = "0.4" +selectors = "0.2" string_cache = "0.1" string_cache_plugin = "0.1" euclid = {version = "0.3", features = ["plugins"]} diff --git a/tests/unit/style/stylesheets.rs b/tests/unit/style/stylesheets.rs index 6eb9cde4402..d6a9c6d30ce 100644 --- a/tests/unit/style/stylesheets.rs +++ b/tests/unit/style/stylesheets.rs @@ -25,6 +25,7 @@ fn test_parse_stylesheet() { let stylesheet = Stylesheet::from_str(css, url, Origin::UserAgent); assert_eq!(stylesheet, Stylesheet { origin: Origin::UserAgent, + media: None, rules: vec![ CSSRule::Namespace(None, ns!(HTML)), CSSRule::Style(StyleRule { diff --git a/tests/wpt/harness/wptrunner/executors/executorservo.py b/tests/wpt/harness/wptrunner/executors/executorservo.py index a1e0ea97b31..b1beea9934a 100644 --- a/tests/wpt/harness/wptrunner/executors/executorservo.py +++ b/tests/wpt/harness/wptrunner/executors/executorservo.py @@ -203,7 +203,7 @@ class ServoRefTestExecutor(ProcessTestExecutor): debug_args, command = browser_command( self.binary, [render_arg(self.browser.render_backend), "--hard-fail", "--exit", - "-u", "Servo/wptrunner", "-Z", "disable-text-aa", + "-u", "Servo/wptrunner", "-Z", "disable-text-aa,load-webfonts-synchronously", "--output=%s" % output_path, full_url], self.debug_info) diff --git a/tests/wpt/metadata-css/css21_dev/html4/cascade-import-dynamic-control.htm.ini b/tests/wpt/metadata-css/css21_dev/html4/cascade-import-dynamic-control.htm.ini deleted file mode 100644 index f0a3cbaf277..00000000000 --- a/tests/wpt/metadata-css/css21_dev/html4/cascade-import-dynamic-control.htm.ini +++ /dev/null @@ -1,3 +0,0 @@ -[cascade-import-dynamic-control.htm] - type: reftest - expected: FAIL diff --git a/tests/wpt/metadata/MANIFEST.json b/tests/wpt/metadata/MANIFEST.json index f279b5f318f..22cd43f2f37 100644 --- a/tests/wpt/metadata/MANIFEST.json +++ b/tests/wpt/metadata/MANIFEST.json @@ -29809,7 +29809,16 @@ }, "local_changes": { "deleted": [], - "items": {}, + "items": { + "testharness": { + "html/browsers/browsing-the-web/navigating-across-documents/javascript-url-query-fragment-components.html": [ + { + "path": "html/browsers/browsing-the-web/navigating-across-documents/javascript-url-query-fragment-components.html", + "url": "/html/browsers/browsing-the-web/navigating-across-documents/javascript-url-query-fragment-components.html" + } + ] + } + }, "reftest_nodes": {} }, "reftest_nodes": { diff --git a/tests/wpt/metadata/XMLHttpRequest/overridemimetype-open-state-force-utf-8.htm.ini b/tests/wpt/metadata/XMLHttpRequest/overridemimetype-open-state-force-utf-8.htm.ini index 68d82dd90ec..8138e2ed72a 100644 --- a/tests/wpt/metadata/XMLHttpRequest/overridemimetype-open-state-force-utf-8.htm.ini +++ b/tests/wpt/metadata/XMLHttpRequest/overridemimetype-open-state-force-utf-8.htm.ini @@ -1,6 +1,6 @@ [overridemimetype-open-state-force-utf-8.htm] type: testharness - expected: CRASH + expected: TIMEOUT [XMLHttpRequest: overrideMimeType() in open state, enforcing UTF-8 encoding] - expected: FAIL + expected: TIMEOUT diff --git a/tests/wpt/metadata/XMLHttpRequest/overridemimetype-unsent-state-force-shiftjis.htm.ini b/tests/wpt/metadata/XMLHttpRequest/overridemimetype-unsent-state-force-shiftjis.htm.ini index be43cd7a16e..625100da359 100644 --- a/tests/wpt/metadata/XMLHttpRequest/overridemimetype-unsent-state-force-shiftjis.htm.ini +++ b/tests/wpt/metadata/XMLHttpRequest/overridemimetype-unsent-state-force-shiftjis.htm.ini @@ -1,6 +1,6 @@ [overridemimetype-unsent-state-force-shiftjis.htm] type: testharness - expected: CRASH + expected: TIMEOUT [XMLHttpRequest: overrideMimeType() in unsent state, enforcing Shift-JIS encoding] - expected: FAIL + expected: TIMEOUT diff --git a/tests/wpt/metadata/html/browsers/browsing-the-web/navigating-across-documents/javascript-url-query-fragment-components.html.ini b/tests/wpt/metadata/html/browsers/browsing-the-web/navigating-across-documents/javascript-url-query-fragment-components.html.ini new file mode 100644 index 00000000000..f95e9c54bbe --- /dev/null +++ b/tests/wpt/metadata/html/browsers/browsing-the-web/navigating-across-documents/javascript-url-query-fragment-components.html.ini @@ -0,0 +1,7 @@ +[javascript-url-query-fragment-components.html] + type: testharness + expected: OK + [iframes with javascript src] + expected: FAIL + + diff --git a/tests/wpt/metadata/html/dom/documents/dom-tree-accessors/document.title-09.html.ini b/tests/wpt/metadata/html/dom/documents/dom-tree-accessors/document.title-09.html.ini deleted file mode 100644 index 93d736c13e5..00000000000 --- a/tests/wpt/metadata/html/dom/documents/dom-tree-accessors/document.title-09.html.ini +++ /dev/null @@ -1,8 +0,0 @@ -[document.title-09.html] - type: testharness - [No title element in SVG document] - expected: FAIL - - [Title element not child of SVG root] - expected: FAIL - diff --git a/tests/wpt/mozilla/meta/css/test_variable_serialization_computed.html.ini b/tests/wpt/mozilla/meta/css/test_variable_serialization_computed.html.ini deleted file mode 100644 index 5c5d1ba2ebf..00000000000 --- a/tests/wpt/mozilla/meta/css/test_variable_serialization_computed.html.ini +++ /dev/null @@ -1,53 +0,0 @@ -[test_variable_serialization_computed.html] - type: testharness - [subtest #20 with `--a: var(--b)var(--c); --b:orange; --c:red;`] - expected: FAIL - - [subtest #21 with `--a: var(--b)var(--c,red); --b:orange;`] - expected: FAIL - - [subtest #22 with `--a: var(--b,orange)var(--c); --c:red;`] - expected: FAIL - - [subtest #24 with `--a: var(--b)var(--c); --c:[c\]; --b:('ab`] - expected: FAIL - - [subtest #25 with `--a: '`] - expected: FAIL - - [subtest #26 with `--a: '\\`] - expected: FAIL - - [subtest #27 with `--a: \\`] - expected: FAIL - - [subtest #28 with `--a: "`] - expected: FAIL - - [subtest #29 with `--a: "\\`] - expected: FAIL - - [subtest #30 with `--a: /* abc `] - expected: FAIL - - [subtest #31 with `--a: /* abc *`] - expected: FAIL - - [subtest #32 with `--a: url(http://example.org/`] - expected: FAIL - - [subtest #33 with `--a: url(http://example.org/\\`] - expected: FAIL - - [subtest #34 with `--a: url('http://example.org/`] - expected: FAIL - - [subtest #35 with `--a: url('http://example.org/\\`] - expected: FAIL - - [subtest #36 with `--a: url("http://example.org/`] - expected: FAIL - - [subtest #37 with `--a: url("http://example.org/\\`] - expected: FAIL - diff --git a/tests/wpt/mozilla/meta/css/test_variable_serialization_specified.html.ini b/tests/wpt/mozilla/meta/css/test_variable_serialization_specified.html.ini deleted file mode 100644 index b4b7a38b3f5..00000000000 --- a/tests/wpt/mozilla/meta/css/test_variable_serialization_specified.html.ini +++ /dev/null @@ -1,116 +0,0 @@ -[test_variable_serialization_specified.html] - type: testharness - [`var(--a)` is unchanged by specified value serialization] - expected: FAIL - - [`var(--a) ` is unchanged by specified value serialization] - expected: FAIL - - [`var( --a ) ` is unchanged by specified value serialization] - expected: FAIL - - [`var(--a, )` is unchanged by specified value serialization] - expected: FAIL - - [`var(--a,/**/a)` is unchanged by specified value serialization] - expected: FAIL - - [`1px var(--a)` is unchanged by specified value serialization] - expected: FAIL - - [`var(--a) 1px` is unchanged by specified value serialization] - expected: FAIL - - [`something 3px url(whereever) calc(var(--a) + 1px)` is unchanged by specified value serialization] - expected: FAIL - - [`var(--a)var(--b)` is unchanged by specified value serialization] - expected: FAIL - - [`var(--a, var(--b, var(--c, black)))` is unchanged by specified value serialization] - expected: FAIL - - [`var(--a) <!--` is unchanged by specified value serialization] - expected: FAIL - - [`--> var(--a)` is unchanged by specified value serialization] - expected: FAIL - - [`{ [ var(--a) \] }` is unchanged by specified value serialization] - expected: FAIL - - [`[;\] var(--a)` is unchanged by specified value serialization] - expected: FAIL - - [`var(--a,(;))` is unchanged by specified value serialization] - expected: FAIL - - [`VAR(--a)` is unchanged by specified value serialization] - expected: FAIL - - [`var(--0)` is unchanged by specified value serialization] - expected: FAIL - - [`var(--\\30)` is unchanged by specified value serialization] - expected: FAIL - - [`var(--\\d800)` is unchanged by specified value serialization] - expected: FAIL - - [`var(--\\ffffff)` is unchanged by specified value serialization] - expected: FAIL - - [`var(--a` becomes `var(--a)` in specified value serialization] - expected: FAIL - - [`var(--a , ` becomes `var(--a , )` in specified value serialization] - expected: FAIL - - [`var(--a, ` becomes `var(--a, )` in specified value serialization] - expected: FAIL - - [`var(--a, var(--b` becomes `var(--a, var(--b))` in specified value serialization] - expected: FAIL - - [`var(--a /* unclosed comment` becomes `var(--a /* unclosed comment*/)` in specified value serialization] - expected: FAIL - - [`var(--a /* unclosed comment *` becomes `var(--a /* unclosed comment */)` in specified value serialization] - expected: FAIL - - [`[{(((var(--a` becomes `[{(((var(--a))))}\]` in specified value serialization] - expected: FAIL - - [`var(--a, "unclosed string` becomes `var(--a, "unclosed string")` in specified value serialization] - expected: FAIL - - [`var(--a, 'unclosed string` becomes `var(--a, 'unclosed string')` in specified value serialization] - expected: FAIL - - [`var(--a) "unclosed string\\` becomes `var(--a) "unclosed string"` in specified value serialization] - expected: FAIL - - [`var(--a) 'unclosed string\\` becomes `var(--a) 'unclosed string'` in specified value serialization] - expected: FAIL - - [`var(--a) \\` becomes `var(--a) \\�` in specified value serialization] - expected: FAIL - - [`var(--a) url(unclosedurl` becomes `var(--a) url(unclosedurl)` in specified value serialization] - expected: FAIL - - [`var(--a) url('unclosedurl` becomes `var(--a) url('unclosedurl')` in specified value serialization] - expected: FAIL - - [`var(--a) url("unclosedurl` becomes `var(--a) url("unclosedurl")` in specified value serialization] - expected: FAIL - - [`var(--a) url(unclosedurl\\` becomes `var(--a) url(unclosedurl\\�)` in specified value serialization] - expected: FAIL - - [`var(--a) url('unclosedurl\\` becomes `var(--a) url('unclosedurl')` in specified value serialization] - expected: FAIL - - [`var(--a) url("unclosedurl\\` becomes `var(--a) url("unclosedurl")` in specified value serialization] - expected: FAIL - diff --git a/tests/wpt/mozilla/tests/css/restyle_hints_state.css b/tests/wpt/mozilla/tests/css/restyle_hints_state.css index 673ac25d572..6a152778e42 100644 --- a/tests/wpt/mozilla/tests/css/restyle_hints_state.css +++ b/tests/wpt/mozilla/tests/css/restyle_hints_state.css @@ -19,11 +19,15 @@ fieldset:enabled div { fieldset:enabled > div { background-color: yellow; } -fieldset:enabled ~ div { + +/* Add an unnecessary :first-child to make sure that restyle hints see + * non-rightmost pseudo-selectors. + * */ +fieldset:enabled:first-child ~ div { color: pink; background-color: purple; } -fieldset:enabled + div { +fieldset:enabled:first-child + div { color: brown; background-color: orange; } diff --git a/tests/wpt/mozilla/tests/css/test_variable_serialization_specified.html b/tests/wpt/mozilla/tests/css/test_variable_serialization_specified.html index cbb9e01e3fb..ce6219707c4 100644 --- a/tests/wpt/mozilla/tests/css/test_variable_serialization_specified.html +++ b/tests/wpt/mozilla/tests/css/test_variable_serialization_specified.html @@ -104,11 +104,6 @@ function test_specified_value_serialization(value, expected) { div1.style.removeProperty("margin"); } -/* -function test(f) { f() } -function assert_equals(a, b, m) { if (a == b) { console.log("`"+a+"`", "`"+b+"`", m) } } -*/ - values_with_unchanged_specified_value_serialization.forEach(function(value) { test(function() { test_specified_value_serialization(value, value) }, "`" + value + "` is unchanged by specified value serialization"); diff --git a/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/navigating-across-documents/javascript-url-query-fragment-components.html b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/navigating-across-documents/javascript-url-query-fragment-components.html new file mode 100644 index 00000000000..9c18f109cd5 --- /dev/null +++ b/tests/wpt/web-platform-tests/html/browsers/browsing-the-web/navigating-across-documents/javascript-url-query-fragment-components.html @@ -0,0 +1,28 @@ +<!doctype html> +<title> javascript url with query and fragment components </title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script> +var a = null; +var b = null; +var c = null; +</script> + +<iframe id="a" src='javascript:"nope" ? "yep" : "what";'></iframe> +<iframe id="b" src='javascript:"wrong"; // # %0a "ok";'></iframe> +<iframe id="c" src='javascript:"%252525 ? %252525 # %252525"'></iframe> + +<script> +var t = async_test("iframes with javascript src", {timeout:1000}); +function check(id, expected) { + assert_equals( + document.getElementById(id).contentDocument.body.textContent, + expected); +} +onload = t.step_func(function() { + check("a", "yep"); + check("b", "ok"); + check("c", "%2525 ? %2525 # %2525"); + t.done(); +}); +</script> |