aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.travis.yml3
-rw-r--r--CONTRIBUTING.md6
-rw-r--r--HACKING_QUICKSTART.md6
-rw-r--r--components/canvas/Cargo.toml5
-rw-r--r--components/canvas_traits/Cargo.toml5
-rw-r--r--components/compositing/compositor.rs23
-rw-r--r--components/compositing/compositor_task.rs5
-rw-r--r--components/compositing/constellation.rs6
-rw-r--r--components/compositing/pipeline.rs17
-rw-r--r--components/compositing/scrolling.rs15
-rw-r--r--components/compositing/surface_map.rs4
-rw-r--r--components/gfx/paint_task.rs19
-rw-r--r--components/layout/Cargo.toml9
-rw-r--r--components/layout/animation.rs6
-rw-r--r--components/layout/context.rs46
-rw-r--r--components/layout/css/matching.rs10
-rw-r--r--components/layout/display_list_builder.rs2
-rw-r--r--components/layout/flow.rs4
-rw-r--r--components/layout/layout_task.rs170
-rw-r--r--components/layout/traversal.rs2
-rw-r--r--components/layout/wrapper.rs6
-rw-r--r--components/msg/constellation_msg.rs8
-rw-r--r--components/net_traits/lib.rs40
-rw-r--r--components/script/Cargo.toml9
-rw-r--r--components/script/dom/bindings/codegen/CodegenRust.py1
-rw-r--r--components/script/dom/bindings/js.rs1
-rw-r--r--components/script/dom/bindings/mod.rs4
-rw-r--r--components/script/dom/bindings/trace.rs32
-rw-r--r--components/script/dom/create.rs2
-rw-r--r--components/script/dom/cssstyledeclaration.rs56
-rw-r--r--components/script/dom/document.rs108
-rw-r--r--components/script/dom/element.rs5
-rw-r--r--components/script/dom/htmlelement.rs2
-rw-r--r--components/script/dom/htmlinputelement.rs26
-rw-r--r--components/script/dom/htmllinkelement.rs163
-rw-r--r--components/script/dom/htmlmetaelement.rs29
-rw-r--r--components/script/dom/htmlstyleelement.rs24
-rw-r--r--components/script/dom/htmltextareaelement.rs2
-rw-r--r--components/script/dom/webidls/ElementContentEditable.webidl10
-rw-r--r--components/script/dom/webidls/HTMLElement.webidl3
-rw-r--r--components/script/dom/websocket.rs6
-rw-r--r--components/script/dom/window.rs7
-rw-r--r--components/script/layout_interface.rs22
-rw-r--r--components/script/script_task.rs68
-rw-r--r--components/script_traits/lib.rs16
-rw-r--r--components/servo/Cargo.lock72
-rw-r--r--components/style/Cargo.toml10
-rw-r--r--components/style/custom_properties.rs188
-rw-r--r--components/style/font_face.rs32
-rw-r--r--components/style/media_queries.rs17
-rw-r--r--components/style/properties.mako.rs284
-rw-r--r--components/style/restyle_hints.rs24
-rw-r--r--components/style/selector_matching.rs290
-rw-r--r--components/style/stylesheets.rs30
-rw-r--r--components/style/values.rs41
-rw-r--r--components/style/viewport.rs7
-rw-r--r--components/style_traits/Cargo.toml10
-rw-r--r--components/style_traits/viewport.rs4
-rw-r--r--components/util/Cargo.toml9
-rw-r--r--components/util/opts.rs11
-rw-r--r--ports/cef/Cargo.lock69
-rw-r--r--ports/gonk/Cargo.lock67
-rw-r--r--python/mach_bootstrap.py3
-rw-r--r--python/servo/build_commands.py3
-rw-r--r--python/servo/command_base.py1
-rw-r--r--python/servo/testing_commands.py3
-rw-r--r--servobuild.example2
-rw-r--r--tests/unit/style/Cargo.toml6
-rw-r--r--tests/unit/style/stylesheets.rs1
-rw-r--r--tests/wpt/harness/wptrunner/executors/executorservo.py2
-rw-r--r--tests/wpt/metadata-css/css21_dev/html4/cascade-import-dynamic-control.htm.ini3
-rw-r--r--tests/wpt/metadata/MANIFEST.json11
-rw-r--r--tests/wpt/metadata/XMLHttpRequest/overridemimetype-open-state-force-utf-8.htm.ini4
-rw-r--r--tests/wpt/metadata/XMLHttpRequest/overridemimetype-unsent-state-force-shiftjis.htm.ini4
-rw-r--r--tests/wpt/metadata/html/browsers/browsing-the-web/navigating-across-documents/javascript-url-query-fragment-components.html.ini7
-rw-r--r--tests/wpt/metadata/html/dom/documents/dom-tree-accessors/document.title-09.html.ini8
-rw-r--r--tests/wpt/mozilla/meta/css/test_variable_serialization_computed.html.ini53
-rw-r--r--tests/wpt/mozilla/meta/css/test_variable_serialization_specified.html.ini116
-rw-r--r--tests/wpt/mozilla/tests/css/restyle_hints_state.css8
-rw-r--r--tests/wpt/mozilla/tests/css/test_variable_serialization_specified.html5
-rw-r--r--tests/wpt/web-platform-tests/html/browsers/browsing-the-web/navigating-across-documents/javascript-url-query-fragment-components.html28
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>