aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock2
-rw-r--r--components/compositing/compositor.rs3
-rw-r--r--components/constellation/constellation.rs219
-rw-r--r--components/constellation/frame.rs12
-rw-r--r--components/constellation/pipeline.rs7
-rw-r--r--components/layout/display_list_builder.rs6
-rw-r--r--components/layout/fragment.rs10
-rw-r--r--components/layout/lib.rs1
-rw-r--r--components/layout/model.rs15
-rw-r--r--components/msg/constellation_msg.rs1
-rwxr-xr-xcomponents/script/dom/htmlformelement.rs2
-rw-r--r--components/script/dom/htmliframeelement.rs134
-rw-r--r--components/script/dom/node.rs9
-rw-r--r--components/script/dom/window.rs6
-rw-r--r--components/script/layout_wrapper.rs7
-rw-r--r--components/script/script_thread.rs54
-rw-r--r--components/script_layout_interface/lib.rs5
-rw-r--r--components/script_layout_interface/wrapper_traits.rs6
-rw-r--r--components/script_traits/lib.rs24
-rw-r--r--components/script_traits/script_msg.rs8
-rw-r--r--components/style/attr.rs2
-rw-r--r--components/style/build_gecko.rs9
-rw-r--r--components/style/element_state.rs4
-rw-r--r--components/style/gecko/generated/bindings.rs21
-rw-r--r--components/style/gecko/global_style_data.rs5
-rw-r--r--components/style/gecko/non_ts_pseudo_class_list.rs6
-rw-r--r--components/style/gecko/wrapper.rs16
-rw-r--r--components/style/properties/data.py3
-rw-r--r--components/style/properties/longhand/font.mako.rs56
-rw-r--r--components/style/properties/shorthand/font.mako.rs5
-rw-r--r--components/style/restyle_hints.rs2
-rw-r--r--components/style/values/computed/length.rs10
-rw-r--r--components/style/values/specified/length.rs15
-rw-r--r--components/webdriver_server/lib.rs2
-rw-r--r--python/servo/devenv_commands.py20
-rw-r--r--tests/unit/layout/Cargo.toml2
-rw-r--r--tests/unit/layout/align_of.rs26
-rw-r--r--tests/unit/layout/lib.rs3
-rw-r--r--tests/unit/style/parsing/font.rs23
-rw-r--r--tests/unit/style/properties/serialization.rs3
-rw-r--r--tests/wpt/metadata/MANIFEST.json10
-rw-r--r--tests/wpt/mozilla/meta/css/matchMedia.html.ini1
-rw-r--r--tests/wpt/web-platform-tests/html/semantics/embedded-content/the-iframe-element/content_document_changes_only_after_load_matures.html21
43 files changed, 527 insertions, 269 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 9811dc986c6..cb09c8d5ba4 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1403,7 +1403,9 @@ dependencies = [
name = "layout_tests"
version = "0.0.1"
dependencies = [
+ "atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"layout 0.0.1",
+ "script_layout_interface 0.0.1",
]
[[package]]
diff --git a/components/compositing/compositor.rs b/components/compositing/compositor.rs
index eb2a964ac23..cbe8e31667e 100644
--- a/components/compositing/compositor.rs
+++ b/components/compositing/compositor.rs
@@ -903,7 +903,8 @@ impl<Window: WindowMethods> IOCompositor<Window> {
match ServoUrl::parse(&url_string) {
Ok(url) => {
let msg = match self.root_pipeline {
- Some(ref pipeline) => ConstellationMsg::LoadUrl(pipeline.id, LoadData::new(url, None, None)),
+ Some(ref pipeline) =>
+ ConstellationMsg::LoadUrl(pipeline.id, LoadData::new(url, Some(pipeline.id), None, None)),
None => ConstellationMsg::InitLoadUrl(url)
};
if let Err(e) = self.constellation_chan.send(msg) {
diff --git a/components/constellation/constellation.rs b/components/constellation/constellation.rs
index 731486c4e16..01a59070730 100644
--- a/components/constellation/constellation.rs
+++ b/components/constellation/constellation.rs
@@ -101,7 +101,7 @@ use script_traits::{IFrameLoadInfo, IFrameLoadInfoWithData, IFrameSandboxState,
use script_traits::{LayoutMsg as FromLayoutMsg, ScriptMsg as FromScriptMsg, ScriptThreadFactory};
use script_traits::{LogEntry, ServiceWorkerMsg, webdriver_msg};
use script_traits::{MozBrowserErrorType, MozBrowserEvent, WebDriverCommandMsg, WindowSizeData};
-use script_traits::{SWManagerMsg, ScopeThings, WindowSizeType};
+use script_traits::{SWManagerMsg, ScopeThings, UpdatePipelineIdReason, WindowSizeType};
use serde::{Deserialize, Serialize};
use servo_config::opts;
use servo_config::prefs::PREFS;
@@ -599,17 +599,31 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
let (event_loop, host) = match sandbox {
IFrameSandboxState::IFrameSandboxed => (None, None),
- IFrameSandboxState::IFrameUnsandboxed => match reg_host(&load_data.url) {
- None => (None, None),
- Some(host) => {
- let event_loop = self.event_loops.get(&top_level_frame_id)
- .and_then(|map| map.get(&host))
- .and_then(|weak| weak.upgrade());
- match event_loop {
- None => (None, Some(host)),
- Some(event_loop) => (Some(event_loop.clone()), None),
+ IFrameSandboxState::IFrameUnsandboxed => {
+ // If this is an about:blank load, it must share the creator's event loop.
+ // This must match the logic in the script thread when determining the proper origin.
+ if load_data.url.as_str() != "about:blank" {
+ match reg_host(&load_data.url) {
+ None => (None, None),
+ Some(host) => {
+ let event_loop = self.event_loops.get(&top_level_frame_id)
+ .and_then(|map| map.get(&host))
+ .and_then(|weak| weak.upgrade());
+ match event_loop {
+ None => (None, Some(host)),
+ Some(event_loop) => (Some(event_loop.clone()), None),
+ }
+ },
}
- },
+ } else if let Some(parent) = parent_info
+ .and_then(|(pipeline_id, _)| self.pipelines.get(&pipeline_id)) {
+ (Some(parent.event_loop.clone()), None)
+ } else if let Some(creator) = load_data.creator_pipeline_id
+ .and_then(|pipeline_id| self.pipelines.get(&pipeline_id)) {
+ (Some(creator.event_loop.clone()), None)
+ } else {
+ (None, None)
+ }
},
};
@@ -735,7 +749,10 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
}
/// Create a new frame and update the internal bookkeeping.
- fn new_frame(&mut self, frame_id: FrameId, pipeline_id: PipelineId, load_data: LoadData) {
+ fn new_frame(&mut self,
+ frame_id: FrameId,
+ pipeline_id: PipelineId,
+ load_data: LoadData) {
let frame = Frame::new(frame_id, pipeline_id, load_data);
self.frames.insert(frame_id, frame);
@@ -915,11 +932,11 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
load_info.info.new_pipeline_id);
self.handle_script_loaded_url_in_iframe_msg(load_info);
}
- FromScriptMsg::ScriptLoadedAboutBlankInIFrame(load_info, lc) => {
+ FromScriptMsg::ScriptNewIFrame(load_info, layout_sender) => {
debug!("constellation got loaded `about:blank` in iframe message {:?} {:?}",
load_info.parent_pipeline_id,
load_info.new_pipeline_id);
- self.handle_script_loaded_about_blank_in_iframe_msg(load_info, lc);
+ self.handle_script_new_iframe(load_info, layout_sender);
}
FromScriptMsg::ChangeRunningAnimationsState(pipeline_id, animation_state) => {
self.handle_change_running_animations_state(pipeline_id, animation_state)
@@ -1277,10 +1294,19 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
// Notify the browser chrome that the pipeline has failed
self.trigger_mozbrowsererror(top_level_frame_id, reason, backtrace);
- let pipeline_id = self.frames.get(&top_level_frame_id).map(|frame| frame.pipeline_id);
- let pipeline_url = pipeline_id.and_then(|id| self.pipelines.get(&id).map(|pipeline| pipeline.url.clone()));
- let parent_info = pipeline_id.and_then(|id| self.pipelines.get(&id).and_then(|pipeline| pipeline.parent_info));
- let window_size = pipeline_id.and_then(|id| self.pipelines.get(&id).and_then(|pipeline| pipeline.size));
+ let (window_size, pipeline_id) = {
+ let frame = self.frames.get(&top_level_frame_id);
+ let window_size = frame.and_then(|frame| frame.size);
+ let pipeline_id = frame.map(|frame| frame.pipeline_id);
+ (window_size, pipeline_id)
+ };
+
+ let (pipeline_url, parent_info) = {
+ let pipeline = pipeline_id.and_then(|id| self.pipelines.get(&id));
+ let pipeline_url = pipeline.map(|pipeline| pipeline.url.clone());
+ let parent_info = pipeline.and_then(|pipeline| pipeline.parent_info);
+ (pipeline_url, parent_info)
+ };
self.close_frame_children(top_level_frame_id, DiscardBrowsingContext::No, ExitPipelineMode::Force);
@@ -1295,7 +1321,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
warn!("creating replacement pipeline for about:failure");
let new_pipeline_id = PipelineId::new();
- let load_data = LoadData::new(failure_url, None, None);
+ let load_data = LoadData::new(failure_url, None, None, None);
let sandbox = IFrameSandboxState::IFrameSandboxed;
self.new_pipeline(new_pipeline_id, top_level_frame_id, parent_info,
window_size, load_data.clone(), sandbox, false);
@@ -1340,7 +1366,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
let window_size = self.window_size.initial_viewport;
let root_pipeline_id = PipelineId::new();
let root_frame_id = self.root_frame_id;
- let load_data = LoadData::new(url.clone(), None, None);
+ let load_data = LoadData::new(url.clone(), None, None, None);
let sandbox = IFrameSandboxState::IFrameUnsandboxed;
self.new_pipeline(root_pipeline_id, root_frame_id, None, Some(window_size), load_data.clone(), sandbox, false);
self.handle_load_start_msg(root_pipeline_id);
@@ -1353,29 +1379,14 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
}
fn handle_frame_size_msg(&mut self,
- iframe_sizes: Vec<(PipelineId, TypedSize2D<f32, CSSPixel>)>) {
- for (pipeline_id, size) in iframe_sizes {
- let result = {
- let pipeline = match self.pipelines.get_mut(&pipeline_id) {
- Some(pipeline) => pipeline,
- None => continue,
- };
-
- if pipeline.size == Some(size) {
- continue;
- }
-
- pipeline.size = Some(size);
- let msg = ConstellationControlMsg::Resize(pipeline_id, WindowSizeData {
- initial_viewport: size,
- device_pixel_ratio: self.window_size.device_pixel_ratio,
- }, WindowSizeType::Initial);
-
- pipeline.event_loop.send(msg)
+ iframe_sizes: Vec<(FrameId, TypedSize2D<f32, CSSPixel>)>) {
+ for (frame_id, size) in iframe_sizes {
+ let window_size = WindowSizeData {
+ initial_viewport: size,
+ device_pixel_ratio: self.window_size.device_pixel_ratio,
};
- if let Err(e) = result {
- self.handle_send_error(pipeline_id, e);
- }
+
+ self.resize_frame(window_size, WindowSizeType::Initial, frame_id);
}
}
@@ -1423,12 +1434,12 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
};
// TODO - loaddata here should have referrer info (not None, None)
- LoadData::new(url, None, None)
+ LoadData::new(url, Some(source_pipeline.id), None, None)
});
let is_private = load_info.info.is_private || source_pipeline.is_private;
- let window_size = old_pipeline.and_then(|old_pipeline| old_pipeline.size);
+ let window_size = self.frames.get(&load_info.info.frame_id).and_then(|frame| frame.size);
(load_data, window_size, is_private)
};
@@ -1456,9 +1467,9 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
is_private);
}
- fn handle_script_loaded_about_blank_in_iframe_msg(&mut self,
- load_info: IFrameLoadInfo,
- layout_sender: IpcSender<LayoutControlMsg>) {
+ fn handle_script_new_iframe(&mut self,
+ load_info: IFrameLoadInfo,
+ layout_sender: IpcSender<LayoutControlMsg>) {
let IFrameLoadInfo {
parent_pipeline_id,
new_pipeline_id,
@@ -1486,12 +1497,11 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
self.compositor_proxy.clone_compositor_proxy(),
is_private || parent_pipeline.is_private,
url.clone(),
- None,
parent_pipeline.visible)
};
// TODO: Referrer?
- let load_data = LoadData::new(url, None, None);
+ let load_data = LoadData::new(url, Some(parent_pipeline_id), None, None);
let replace_instant = if replace {
self.frames.get(&frame_id).map(|frame| frame.instant)
@@ -1641,7 +1651,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
// changes would be overridden by changing the subframe associated with source_id.
// Create the new pipeline
- let window_size = self.pipelines.get(&source_id).and_then(|source| source.size);
+ let window_size = self.frames.get(&root_frame_id).and_then(|frame| frame.size);
let new_pipeline_id = PipelineId::new();
let sandbox = IFrameSandboxState::IFrameUnsandboxed;
let replace_instant = if replace {
@@ -1959,7 +1969,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
},
WebDriverCommandMsg::Refresh(pipeline_id, reply) => {
let load_data = match self.pipelines.get(&pipeline_id) {
- Some(pipeline) => LoadData::new(pipeline.url.clone(), None, None),
+ Some(pipeline) => LoadData::new(pipeline.url.clone(), None, None, None),
None => return warn!("Pipeline {:?} Refresh after closure.", pipeline_id),
};
self.load_url_for_webdriver(pipeline_id, load_data, reply, true);
@@ -2019,8 +2029,8 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
let load_data = entry.load_data;
let (parent_info, window_size, is_private) = match self.frames.get(&frame_id) {
Some(frame) => match self.pipelines.get(&frame.pipeline_id) {
- Some(pipeline) => (pipeline.parent_info, pipeline.size, pipeline.is_private),
- None => (None, None, false),
+ Some(pipeline) => (pipeline.parent_info, frame.size, pipeline.is_private),
+ None => (None, frame.size, false),
},
None => return warn!("no frame to traverse"),
};
@@ -2101,7 +2111,8 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
// Update the owning iframe to point to the new pipeline id.
// This makes things like contentDocument work correctly.
if let Some((parent_pipeline_id, _)) = parent_info {
- let msg = ConstellationControlMsg::UpdatePipelineId(parent_pipeline_id, frame_id, pipeline_id);
+ let msg = ConstellationControlMsg::UpdatePipelineId(parent_pipeline_id,
+ frame_id, pipeline_id, UpdatePipelineIdReason::Traversal);
let result = match self.pipelines.get(&parent_pipeline_id) {
None => return warn!("Pipeline {:?} child traversed after closure.", parent_pipeline_id),
Some(pipeline) => pipeline.event_loop.send(msg),
@@ -2245,7 +2256,9 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
}
if new_frame {
- self.new_frame(frame_change.frame_id, frame_change.new_pipeline_id, frame_change.load_data);
+ self.new_frame(frame_change.frame_id,
+ frame_change.new_pipeline_id,
+ frame_change.load_data);
self.update_activity(frame_change.new_pipeline_id);
self.notify_history_changed(frame_change.new_pipeline_id);
};
@@ -2275,7 +2288,8 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
if let Some(pipeline) = self.pipelines.get(&pipeline_id) {
if let Some((parent_pipeline_id, _)) = pipeline.parent_info {
if let Some(parent_pipeline) = self.pipelines.get(&parent_pipeline_id) {
- let msg = ConstellationControlMsg::FramedContentChanged(parent_pipeline_id, pipeline.frame_id);
+ let msg = ConstellationControlMsg::UpdatePipelineId(parent_pipeline_id,
+ pipeline.frame_id, pipeline_id, UpdatePipelineIdReason::Navigation);
let _ = parent_pipeline.event_loop.send(msg);
}
}
@@ -2298,45 +2312,8 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
fn handle_window_size_msg(&mut self, new_size: WindowSizeData, size_type: WindowSizeType) {
debug!("handle_window_size_msg: {:?}", new_size.initial_viewport.to_untyped());
- if let Some(frame) = self.frames.get(&self.root_frame_id) {
- // Send Resize (or ResizeInactive) messages to each
- // pipeline in the frame tree.
- let pipeline_id = frame.pipeline_id;
- let pipeline = match self.pipelines.get(&pipeline_id) {
- None => return warn!("Pipeline {:?} resized after closing.", pipeline_id),
- Some(pipeline) => pipeline,
- };
- let _ = pipeline.event_loop.send(ConstellationControlMsg::Resize(
- pipeline.id,
- new_size,
- size_type
- ));
- let pipelines = frame.prev.iter().chain(frame.next.iter())
- .filter_map(|entry| entry.pipeline_id)
- .filter_map(|pipeline_id| self.pipelines.get(&pipeline_id));
- for pipeline in pipelines {
- let _ = pipeline.event_loop.send(ConstellationControlMsg::ResizeInactive(
- pipeline.id,
- new_size
- ));
- }
- }
-
- // Send resize message to any pending pipelines that aren't loaded yet.
- for pending_frame in &self.pending_frames {
- let pipeline_id = pending_frame.new_pipeline_id;
- let pipeline = match self.pipelines.get(&pipeline_id) {
- None => { warn!("Pending pipeline {:?} is closed", pipeline_id); continue; }
- Some(pipeline) => pipeline,
- };
- if pipeline.parent_info.is_none() {
- let _ = pipeline.event_loop.send(ConstellationControlMsg::Resize(
- pipeline.id,
- new_size,
- size_type
- ));
- }
- }
+ let frame_id = self.root_frame_id;
+ self.resize_frame(new_size, size_type, frame_id);
if let Some(resize_channel) = self.webdriver.resize_channel.take() {
let _ = resize_channel.send(new_size);
@@ -2422,7 +2399,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
// size for the pipeline, then its painting should be up to date. If the constellation
// *hasn't* received a size, it could be that the layer was hidden by script before the
// compositor discovered it, so we just don't check the layer.
- if let Some(size) = pipeline.size {
+ if let Some(size) = frame.size {
// If the rectangle for this pipeline is zero sized, it will
// never be painted. In this case, don't query the layout
// thread as it won't contribute to the final output image.
@@ -2509,6 +2486,54 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
self.set_activity(pipeline_id, self.get_activity(pipeline_id));
}
+ /// Handle updating the size of a frame. This notifies every pipeline in the frame of the new
+ /// size.
+ fn resize_frame(&mut self, new_size: WindowSizeData, size_type: WindowSizeType, frame_id: FrameId) {
+ if let Some(frame) = self.frames.get_mut(&frame_id) {
+ frame.size = Some(new_size.initial_viewport);
+ }
+
+ if let Some(frame) = self.frames.get(&frame_id) {
+ // Send Resize (or ResizeInactive) messages to each
+ // pipeline in the frame tree.
+ let pipeline_id = frame.pipeline_id;
+ let pipeline = match self.pipelines.get(&pipeline_id) {
+ None => return warn!("Pipeline {:?} resized after closing.", pipeline_id),
+ Some(pipeline) => pipeline,
+ };
+ let _ = pipeline.event_loop.send(ConstellationControlMsg::Resize(
+ pipeline.id,
+ new_size,
+ size_type
+ ));
+ let pipelines = frame.prev.iter().chain(frame.next.iter())
+ .filter_map(|entry| entry.pipeline_id)
+ .filter_map(|pipeline_id| self.pipelines.get(&pipeline_id));
+ for pipeline in pipelines {
+ let _ = pipeline.event_loop.send(ConstellationControlMsg::ResizeInactive(
+ pipeline.id,
+ new_size
+ ));
+ }
+ }
+
+ // Send resize message to any pending pipelines that aren't loaded yet.
+ for pending_frame in &self.pending_frames {
+ let pipeline_id = pending_frame.new_pipeline_id;
+ let pipeline = match self.pipelines.get(&pipeline_id) {
+ None => { warn!("Pending pipeline {:?} is closed", pipeline_id); continue; }
+ Some(pipeline) => pipeline,
+ };
+ if pipeline.frame_id == frame_id {
+ let _ = pipeline.event_loop.send(ConstellationControlMsg::Resize(
+ pipeline.id,
+ new_size,
+ size_type
+ ));
+ }
+ }
+ }
+
fn clear_joint_session_future(&mut self, frame_id: FrameId) {
let frame_ids: Vec<FrameId> = self.full_frame_tree_iter(frame_id)
.map(|frame| frame.id)
@@ -2652,7 +2677,7 @@ impl<Message, LTF, STF> Constellation<Message, LTF, STF>
self.pipelines.get(&frame.pipeline_id).map(|pipeline: &Pipeline| {
let mut frame_tree = SendableFrameTree {
pipeline: pipeline.to_sendable(),
- size: pipeline.size,
+ size: frame.size,
children: vec!(),
};
diff --git a/components/constellation/frame.rs b/components/constellation/frame.rs
index 74aabee2de0..ac85c14d214 100644
--- a/components/constellation/frame.rs
+++ b/components/constellation/frame.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 euclid::size::TypedSize2D;
use msg::constellation_msg::{FrameId, PipelineId};
use pipeline::Pipeline;
use script_traits::LoadData;
@@ -9,6 +10,7 @@ use std::collections::HashMap;
use std::iter::once;
use std::mem::replace;
use std::time::Instant;
+use style_traits::CSSPixel;
/// A frame in the frame tree.
/// Each frame is the constellation's view of a browsing context.
@@ -22,13 +24,16 @@ pub struct Frame {
/// The frame id.
pub id: FrameId,
- /// The timestamp for the current session history entry
+ /// The size of the frame.
+ pub size: Option<TypedSize2D<f32, CSSPixel>>,
+
+ /// The timestamp for the current session history entry.
pub instant: Instant,
- /// The pipeline for the current session history entry
+ /// The pipeline for the current session history entry.
pub pipeline_id: PipelineId,
- /// The load data for the current session history entry
+ /// The load data for the current session history entry.
pub load_data: LoadData,
/// The past session history, ordered chronologically.
@@ -44,6 +49,7 @@ impl Frame {
pub fn new(id: FrameId, pipeline_id: PipelineId, load_data: LoadData) -> Frame {
Frame {
id: id,
+ size: None,
pipeline_id: pipeline_id,
instant: Instant::now(),
load_data: load_data,
diff --git a/components/constellation/pipeline.rs b/components/constellation/pipeline.rs
index aa380a8e5c1..60401f4313c 100644
--- a/components/constellation/pipeline.rs
+++ b/components/constellation/pipeline.rs
@@ -76,10 +76,6 @@ pub struct Pipeline {
/// The title of the most recently-loaded page.
pub title: Option<String>,
- /// The size of the frame.
- /// TODO: move this field to `Frame`.
- pub size: Option<TypedSize2D<f32, CSSPixel>>,
-
/// Whether this pipeline is currently running animations. Pipelines that are running
/// animations cause composites to be continually scheduled.
pub running_animations: bool,
@@ -291,7 +287,6 @@ impl Pipeline {
state.compositor_proxy,
state.is_private,
url,
- state.window_size,
state.prev_visibility.unwrap_or(true)))
}
@@ -305,7 +300,6 @@ impl Pipeline {
compositor_proxy: Box<CompositorProxy + 'static + Send>,
is_private: bool,
url: ServoUrl,
- size: Option<TypedSize2D<f32, CSSPixel>>,
visible: bool)
-> Pipeline {
let pipeline = Pipeline {
@@ -318,7 +312,6 @@ impl Pipeline {
url: url,
title: None,
children: vec!(),
- size: size,
running_animations: false,
visible: visible,
is_private: is_private,
diff --git a/components/layout/display_list_builder.rs b/components/layout/display_list_builder.rs
index 472a34529ca..5f9a783c896 100644
--- a/components/layout/display_list_builder.rs
+++ b/components/layout/display_list_builder.rs
@@ -34,7 +34,7 @@ use inline::{FIRST_FRAGMENT_OF_ELEMENT, InlineFlow, LAST_FRAGMENT_OF_ELEMENT};
use ipc_channel::ipc;
use list_item::ListItemFlow;
use model::{self, MaybeAuto, specified};
-use msg::constellation_msg::PipelineId;
+use msg::constellation_msg::FrameId;
use net_traits::image::base::PixelFormat;
use net_traits::image_cache::UsePlaceholder;
use range::Range;
@@ -173,7 +173,7 @@ pub struct DisplayListBuildState<'a> {
/// Vector containing iframe sizes, used to inform the constellation about
/// new iframe sizes
- pub iframe_sizes: Vec<(PipelineId, TypedSize2D<f32, CSSPixel>)>,
+ pub iframe_sizes: Vec<(FrameId, TypedSize2D<f32, CSSPixel>)>,
/// A stack of clips used to cull display list entries that are outside the
/// rendered region.
@@ -1809,7 +1809,7 @@ impl FragmentDisplayListBuilding for Fragment {
let size = Size2D::new(item.bounds().size.width.to_f32_px(),
item.bounds().size.height.to_f32_px());
- state.iframe_sizes.push((fragment_info.pipeline_id, TypedSize2D::from_untyped(&size)));
+ state.iframe_sizes.push((fragment_info.frame_id, TypedSize2D::from_untyped(&size)));
state.add_display_item(item);
}
diff --git a/components/layout/fragment.rs b/components/layout/fragment.rs
index 9f98ff318ec..c4dfefcc696 100644
--- a/components/layout/fragment.rs
+++ b/components/layout/fragment.rs
@@ -26,7 +26,7 @@ use ipc_channel::ipc::IpcSender;
use layout_debug;
use model::{self, IntrinsicISizes, IntrinsicISizesContribution, MaybeAuto, SizeConstraint};
use model::{style_length, ToGfxMatrix};
-use msg::constellation_msg::PipelineId;
+use msg::constellation_msg::{FrameId, PipelineId};
use net_traits::image::base::{Image, ImageMetadata};
use net_traits::image_cache::{ImageOrMetadataAvailable, UsePlaceholder};
use range::*;
@@ -467,19 +467,23 @@ impl ImageFragmentInfo {
}
}
-/// A fragment that represents an inline frame (iframe). This stores the pipeline ID so that the
+/// A fragment that represents an inline frame (iframe). This stores the frame ID so that the
/// size of this iframe can be communicated via the constellation to the iframe's own layout thread.
#[derive(Clone)]
pub struct IframeFragmentInfo {
- /// The pipeline ID of this iframe.
+ /// The frame ID of this iframe.
+ pub frame_id: FrameId,
+ /// The pipelineID of this iframe.
pub pipeline_id: PipelineId,
}
impl IframeFragmentInfo {
/// Creates the information specific to an iframe fragment.
pub fn new<N: ThreadSafeLayoutNode>(node: &N) -> IframeFragmentInfo {
+ let frame_id = node.iframe_frame_id();
let pipeline_id = node.iframe_pipeline_id();
IframeFragmentInfo {
+ frame_id: frame_id,
pipeline_id: pipeline_id,
}
}
diff --git a/components/layout/lib.rs b/components/layout/lib.rs
index abdf6ff04c0..1df46c557f4 100644
--- a/components/layout/lib.rs
+++ b/components/layout/lib.rs
@@ -93,6 +93,7 @@ pub mod wrapper;
// For unit tests:
pub use fragment::Fragment;
pub use fragment::SpecificFragmentInfo;
+pub use self::data::PersistentLayoutData;
/// Returns whether the two arguments point to the same value.
///
diff --git a/components/layout/model.rs b/components/layout/model.rs
index 531d37038d7..aba7c3f3927 100644
--- a/components/layout/model.rs
+++ b/components/layout/model.rs
@@ -143,16 +143,19 @@ impl MarginCollapseInfo {
may_collapse_through = may_collapse_through &&
match fragment.style().content_block_size() {
LengthOrPercentageOrAuto::Auto => true,
- LengthOrPercentageOrAuto::Length(Au(0)) => true,
- LengthOrPercentageOrAuto::Percentage(0.) => true,
- LengthOrPercentageOrAuto::Percentage(_) if
- containing_block_size.is_none() => true,
- _ => false,
+ LengthOrPercentageOrAuto::Length(Au(v)) => v == 0,
+ LengthOrPercentageOrAuto::Percentage(v) => {
+ v == 0. || containing_block_size.is_none()
+ }
+ LengthOrPercentageOrAuto::Calc(_) => false,
};
if may_collapse_through {
match fragment.style().min_block_size() {
- LengthOrPercentage::Length(Au(0)) | LengthOrPercentage::Percentage(0.) => {
+ LengthOrPercentage::Length(Au(0)) => {
+ FinalMarginState::MarginsCollapseThrough
+ },
+ LengthOrPercentage::Percentage(v) if v == 0. => {
FinalMarginState::MarginsCollapseThrough
},
_ => {
diff --git a/components/msg/constellation_msg.rs b/components/msg/constellation_msg.rs
index 5b5110099f6..02d4157f20c 100644
--- a/components/msg/constellation_msg.rs
+++ b/components/msg/constellation_msg.rs
@@ -310,3 +310,4 @@ pub enum FrameType {
IFrame,
MozBrowserIFrame,
}
+
diff --git a/components/script/dom/htmlformelement.rs b/components/script/dom/htmlformelement.rs
index 4397364f68f..53867c755f8 100755
--- a/components/script/dom/htmlformelement.rs
+++ b/components/script/dom/htmlformelement.rs
@@ -345,7 +345,7 @@ impl HTMLFormElement {
let _target = submitter.target();
// TODO: Handle browsing contexts, partially loaded documents (step 16-17)
- let mut load_data = LoadData::new(action_components, doc.get_referrer_policy(), Some(doc.url()));
+ let mut load_data = LoadData::new(action_components, None, doc.get_referrer_policy(), Some(doc.url()));
// Step 18
match (&*scheme, method) {
diff --git a/components/script/dom/htmliframeelement.rs b/components/script/dom/htmliframeelement.rs
index bee9f1a50c7..1e6615ce36a 100644
--- a/components/script/dom/htmliframeelement.rs
+++ b/components/script/dom/htmliframeelement.rs
@@ -44,7 +44,7 @@ use msg::constellation_msg::{FrameType, FrameId, PipelineId, TraversalDirection}
use net_traits::response::HttpsState;
use script_layout_interface::message::ReflowQueryType;
use script_thread::{ScriptThread, Runnable};
-use script_traits::{IFrameLoadInfo, IFrameLoadInfoWithData, LoadData};
+use script_traits::{IFrameLoadInfo, IFrameLoadInfoWithData, LoadData, UpdatePipelineIdReason};
use script_traits::{MozBrowserEvent, NewLayoutInfo, ScriptMsg as ConstellationMsg};
use script_traits::IFrameSandboxState::{IFrameSandboxed, IFrameUnsandboxed};
use servo_atoms::Atom;
@@ -70,6 +70,12 @@ bitflags! {
}
#[derive(PartialEq)]
+pub enum NavigationType {
+ InitialAboutBlank,
+ Regular,
+}
+
+#[derive(PartialEq)]
enum ProcessingMode {
FirstTime,
NotFirstTime,
@@ -80,6 +86,7 @@ pub struct HTMLIFrameElement {
htmlelement: HTMLElement,
frame_id: FrameId,
pipeline_id: Cell<Option<PipelineId>>,
+ pending_pipeline_id: Cell<Option<PipelineId>>,
sandbox: MutNullableJS<DOMTokenList>,
sandbox_allowance: Cell<Option<SandboxAllowance>>,
load_blocker: DOMRefCell<Option<LoadBlocker>>,
@@ -108,12 +115,14 @@ impl HTMLIFrameElement {
pub fn generate_new_pipeline_id(&self) -> (Option<PipelineId>, PipelineId) {
let old_pipeline_id = self.pipeline_id.get();
let new_pipeline_id = PipelineId::new();
- self.pipeline_id.set(Some(new_pipeline_id));
debug!("Frame {} created pipeline {}.", self.frame_id, new_pipeline_id);
(old_pipeline_id, new_pipeline_id)
}
- pub fn navigate_or_reload_child_browsing_context(&self, load_data: Option<LoadData>, replace: bool) {
+ pub fn navigate_or_reload_child_browsing_context(&self,
+ load_data: Option<LoadData>,
+ nav_type: NavigationType,
+ replace: bool) {
let sandboxed = if self.is_sandboxed() {
IFrameSandboxed
} else {
@@ -136,6 +145,7 @@ impl HTMLIFrameElement {
let window = window_from_node(self);
let (old_pipeline_id, new_pipeline_id) = self.generate_new_pipeline_id();
+ self.pending_pipeline_id.set(Some(new_pipeline_id));
let private_iframe = self.privatebrowsing();
let frame_type = if self.Mozbrowser() { FrameType::MozBrowserIFrame } else { FrameType::IFrame };
@@ -149,37 +159,41 @@ impl HTMLIFrameElement {
replace: replace,
};
- if load_data.as_ref().map_or(false, |d| d.url.as_str() == "about:blank") {
- let (pipeline_sender, pipeline_receiver) = ipc::channel().unwrap();
-
- global_scope
- .constellation_chan()
- .send(ConstellationMsg::ScriptLoadedAboutBlankInIFrame(load_info, pipeline_sender))
- .unwrap();
-
- let new_layout_info = NewLayoutInfo {
- parent_info: Some((global_scope.pipeline_id(), frame_type)),
- new_pipeline_id: new_pipeline_id,
- frame_id: self.frame_id,
- load_data: load_data.unwrap(),
- pipeline_port: pipeline_receiver,
- content_process_shutdown_chan: None,
- window_size: None,
- layout_threads: PREFS.get("layout.threads").as_u64().expect("count") as usize,
- };
-
- ScriptThread::process_attach_layout(new_layout_info, document.origin().clone());
- } else {
- let load_info = IFrameLoadInfoWithData {
- info: load_info,
- load_data: load_data,
- old_pipeline_id: old_pipeline_id,
- sandbox: sandboxed,
- };
- global_scope
+ match nav_type {
+ NavigationType::InitialAboutBlank => {
+ let (pipeline_sender, pipeline_receiver) = ipc::channel().unwrap();
+
+ global_scope
+ .constellation_chan()
+ .send(ConstellationMsg::ScriptNewIFrame(load_info, pipeline_sender))
+ .unwrap();
+
+ let new_layout_info = NewLayoutInfo {
+ parent_info: Some((global_scope.pipeline_id(), frame_type)),
+ new_pipeline_id: new_pipeline_id,
+ frame_id: self.frame_id,
+ load_data: load_data.unwrap(),
+ pipeline_port: pipeline_receiver,
+ content_process_shutdown_chan: None,
+ window_size: None,
+ layout_threads: PREFS.get("layout.threads").as_u64().expect("count") as usize,
+ };
+
+ self.pipeline_id.set(Some(new_pipeline_id));
+ ScriptThread::process_attach_layout(new_layout_info, document.origin().clone());
+ },
+ NavigationType::Regular => {
+ let load_info = IFrameLoadInfoWithData {
+ info: load_info,
+ load_data: load_data,
+ old_pipeline_id: old_pipeline_id,
+ sandbox: sandboxed,
+ };
+ global_scope
.constellation_chan()
.send(ConstellationMsg::ScriptLoadedURLInIFrame(load_info))
.unwrap();
+ }
}
if PREFS.is_mozbrowser_enabled() {
@@ -192,9 +206,10 @@ impl HTMLIFrameElement {
fn process_the_iframe_attributes(&self, mode: ProcessingMode) {
// TODO: srcdoc
+ let window = window_from_node(self);
+
// https://github.com/whatwg/html/issues/490
if mode == ProcessingMode::FirstTime && !self.upcast::<Element>().has_attribute(&local_name!("src")) {
- let window = window_from_node(self);
let event_loop = window.dom_manipulation_task_source();
let _ = event_loop.queue(box IFrameLoadEventSteps::new(self),
window.upcast());
@@ -205,9 +220,15 @@ impl HTMLIFrameElement {
// TODO: check ancestor browsing contexts for same URL
+ let creator_pipeline_id = if url.as_str() == "about:blank" {
+ Some(window.upcast::<GlobalScope>().pipeline_id())
+ } else {
+ None
+ };
+
let document = document_from_node(self);
- self.navigate_or_reload_child_browsing_context(
- Some(LoadData::new(url, document.get_referrer_policy(), Some(document.url()))), false);
+ let load_data = LoadData::new(url, creator_pipeline_id, document.get_referrer_policy(), Some(document.url()));
+ self.navigate_or_reload_child_browsing_context(Some(load_data), NavigationType::Regular, false);
}
#[allow(unsafe_code)]
@@ -225,19 +246,30 @@ impl HTMLIFrameElement {
// Synchronously create a new context and navigate it to about:blank.
let url = ServoUrl::parse("about:blank").unwrap();
let document = document_from_node(self);
- let load_data = LoadData::new(url,
- document.get_referrer_policy(),
- Some(document.url().clone()));
- self.navigate_or_reload_child_browsing_context(Some(load_data), false);
+ let pipeline_id = Some(window_from_node(self).upcast::<GlobalScope>().pipeline_id());
+ let load_data = LoadData::new(url, pipeline_id, document.get_referrer_policy(), Some(document.url().clone()));
+ self.navigate_or_reload_child_browsing_context(Some(load_data), NavigationType::InitialAboutBlank, false);
}
- pub fn update_pipeline_id(&self, new_pipeline_id: PipelineId) {
+ pub fn update_pipeline_id(&self, new_pipeline_id: PipelineId, reason: UpdatePipelineIdReason) {
+ if self.pending_pipeline_id.get() != Some(new_pipeline_id) && reason == UpdatePipelineIdReason::Navigation {
+ return;
+ }
+
self.pipeline_id.set(Some(new_pipeline_id));
- let mut blocker = self.load_blocker.borrow_mut();
- LoadBlocker::terminate(&mut blocker);
+ // Only terminate the load blocker if the pipeline id was updated due to a traversal.
+ // The load blocker will be terminated for a navigation in iframe_load_event_steps.
+ if reason == UpdatePipelineIdReason::Traversal {
+ let mut blocker = self.load_blocker.borrow_mut();
+ LoadBlocker::terminate(&mut blocker);
+ }
self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage);
+ let window = window_from_node(self);
+ window.reflow(ReflowGoal::ForDisplay,
+ ReflowQueryType::NoQuery,
+ ReflowReason::FramedContentChanged);
}
fn new_inherited(local_name: LocalName,
@@ -247,6 +279,7 @@ impl HTMLIFrameElement {
htmlelement: HTMLElement::new_inherited(local_name, prefix, document),
frame_id: FrameId::new(),
pipeline_id: Cell::new(None),
+ pending_pipeline_id: Cell::new(None),
sandbox: Default::default(),
sandbox_allowance: Cell::new(None),
load_blocker: DOMRefCell::new(None),
@@ -296,7 +329,7 @@ impl HTMLIFrameElement {
pub fn iframe_load_event_steps(&self, loaded_pipeline: PipelineId) {
// TODO(#9592): assert that the load blocker is present at all times when we
// can guarantee that it's created for the case of iframe.reload().
- if Some(loaded_pipeline) != self.pipeline_id() { return; }
+ if Some(loaded_pipeline) != self.pending_pipeline_id.get() { return; }
// TODO A cross-origin child document would not be easily accessible
// from this script thread. It's unclear how to implement
@@ -330,7 +363,8 @@ impl HTMLIFrameElement {
}
pub trait HTMLIFrameElementLayoutMethods {
- fn pipeline_id(self) -> Option<PipelineId>;
+ fn pipeline_id(&self) -> Option<PipelineId>;
+ fn frame_id(&self) -> FrameId;
fn get_width(&self) -> LengthOrPercentageOrAuto;
fn get_height(&self) -> LengthOrPercentageOrAuto;
}
@@ -338,12 +372,21 @@ pub trait HTMLIFrameElementLayoutMethods {
impl HTMLIFrameElementLayoutMethods for LayoutJS<HTMLIFrameElement> {
#[inline]
#[allow(unsafe_code)]
- fn pipeline_id(self) -> Option<PipelineId> {
+ fn pipeline_id(&self) -> Option<PipelineId> {
unsafe {
(*self.unsafe_get()).pipeline_id.get()
}
}
+ #[inline]
+ #[allow(unsafe_code)]
+ fn frame_id(&self) -> FrameId {
+ unsafe {
+ (*self.unsafe_get()).frame_id
+ }
+ }
+
+
#[allow(unsafe_code)]
fn get_width(&self) -> LengthOrPercentageOrAuto {
unsafe {
@@ -563,7 +606,7 @@ impl HTMLIFrameElementMethods for HTMLIFrameElement {
fn Reload(&self, _hard_reload: bool) -> ErrorResult {
if self.Mozbrowser() {
if self.upcast::<Node>().is_in_doc_with_browsing_context() {
- self.navigate_or_reload_child_browsing_context(None, true);
+ self.navigate_or_reload_child_browsing_context(None, NavigationType::Regular, true);
}
Ok(())
} else {
@@ -739,6 +782,7 @@ impl VirtualMethods for HTMLIFrameElement {
// a new iframe. Without this, the constellation gets very
// confused.
self.pipeline_id.set(None);
+ self.pending_pipeline_id.set(None);
}
}
diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs
index 31e48b5b695..81a06850757 100644
--- a/components/script/dom/node.rs
+++ b/components/script/dom/node.rs
@@ -61,7 +61,7 @@ use heapsize::{HeapSizeOf, heap_size_of};
use html5ever::{Prefix, Namespace, QualName};
use js::jsapi::{JSContext, JSObject, JSRuntime};
use libc::{self, c_void, uintptr_t};
-use msg::constellation_msg::PipelineId;
+use msg::constellation_msg::{FrameId, PipelineId};
use ref_slice::ref_slice;
use script_layout_interface::{HTMLCanvasData, OpaqueStyleAndLayoutData, SVGSVGData};
use script_layout_interface::{LayoutElementType, LayoutNodeType, TrustedNodeAddress};
@@ -970,6 +970,7 @@ pub trait LayoutNodeHelpers {
fn image_url(&self) -> Option<ServoUrl>;
fn canvas_data(&self) -> Option<HTMLCanvasData>;
fn svg_data(&self) -> Option<SVGSVGData>;
+ fn iframe_frame_id(&self) -> FrameId;
fn iframe_pipeline_id(&self) -> PipelineId;
fn opaque(&self) -> OpaqueNode;
}
@@ -1120,6 +1121,12 @@ impl LayoutNodeHelpers for LayoutJS<Node> {
.map(|svg| svg.data())
}
+ fn iframe_frame_id(&self) -> FrameId {
+ let iframe_element = self.downcast::<HTMLIFrameElement>()
+ .expect("not an iframe element!");
+ iframe_element.frame_id()
+ }
+
fn iframe_pipeline_id(&self) -> PipelineId {
let iframe_element = self.downcast::<HTMLIFrameElement>()
.expect("not an iframe element!");
diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs
index 98abc5cad74..dbcbd054743 100644
--- a/components/script/dom/window.rs
+++ b/components/script/dom/window.rs
@@ -1537,10 +1537,10 @@ impl Window {
}
}
+ let pipeline_id = self.upcast::<GlobalScope>().pipeline_id();
self.main_thread_script_chan().send(
- MainThreadScriptMsg::Navigate(self.upcast::<GlobalScope>().pipeline_id(),
- LoadData::new(url, referrer_policy, Some(doc.url())),
- replace)).unwrap();
+ MainThreadScriptMsg::Navigate(pipeline_id,
+ LoadData::new(url, Some(pipeline_id), referrer_policy, Some(doc.url())), replace)).unwrap();
}
pub fn handle_fire_timer(&self, timer_id: TimerEventId) {
diff --git a/components/script/layout_wrapper.rs b/components/script/layout_wrapper.rs
index dec2123149b..3d4b90eaeab 100644
--- a/components/script/layout_wrapper.rs
+++ b/components/script/layout_wrapper.rs
@@ -44,7 +44,7 @@ use dom::node::{LayoutNodeHelpers, Node};
use dom::text::Text;
use gfx_traits::ByteIndex;
use html5ever::{LocalName, Namespace};
-use msg::constellation_msg::PipelineId;
+use msg::constellation_msg::{FrameId, PipelineId};
use range::Range;
use script_layout_interface::{HTMLCanvasData, LayoutNodeType, SVGSVGData, TrustedNodeAddress};
use script_layout_interface::{OpaqueStyleAndLayoutData, PartialPersistentLayoutData};
@@ -908,6 +908,11 @@ impl<'ln> ThreadSafeLayoutNode for ServoThreadSafeLayoutNode<'ln> {
this.svg_data()
}
+ fn iframe_frame_id(&self) -> FrameId {
+ let this = unsafe { self.get_jsmanaged() };
+ this.iframe_frame_id()
+ }
+
fn iframe_pipeline_id(&self) -> PipelineId {
let this = unsafe { self.get_jsmanaged() };
this.iframe_pipeline_id()
diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs
index 8cd6ee86222..8a861e92570 100644
--- a/components/script/script_thread.rs
+++ b/components/script/script_thread.rs
@@ -45,7 +45,7 @@ use dom::element::Element;
use dom::event::{Event, EventBubbles, EventCancelable};
use dom::globalscope::GlobalScope;
use dom::htmlanchorelement::HTMLAnchorElement;
-use dom::htmliframeelement::HTMLIFrameElement;
+use dom::htmliframeelement::{HTMLIFrameElement, NavigationType};
use dom::mutationobserver::MutationObserver;
use dom::node::{Node, NodeDamage, window_from_node};
use dom::serviceworker::TrustedServiceWorkerAddress;
@@ -87,7 +87,7 @@ use script_runtime::{ScriptPort, StackRootTLS, get_reports, new_rt_and_cx};
use script_traits::{CompositorEvent, ConstellationControlMsg};
use script_traits::{DocumentActivity, DiscardBrowsingContext, EventResult};
use script_traits::{InitialScriptState, LayoutMsg, LoadData, MouseButton, MouseEventType, MozBrowserEvent};
-use script_traits::{NewLayoutInfo, ScriptMsg as ConstellationMsg};
+use script_traits::{NewLayoutInfo, ScriptMsg as ConstellationMsg, UpdatePipelineIdReason};
use script_traits::{ScriptThreadFactory, TimerEvent, TimerSchedulerMsg, TimerSource};
use script_traits::{TouchEventType, TouchId, UntrustedNodeAddress, WindowSizeData, WindowSizeType};
use script_traits::CompositorEvent::{KeyEvent, MouseButtonEvent, MouseMoveEvent, ResizeEvent};
@@ -555,8 +555,8 @@ impl ScriptThreadFactory for ScriptThread {
let mut failsafe = ScriptMemoryFailsafe::new(&script_thread);
let origin = MutableOrigin::new(load_data.url.origin());
- let new_load = InProgressLoad::new(id, frame_id, parent_info, layout_chan, window_size,
- load_data.url.clone(), origin);
+ let new_load = InProgressLoad::new(id, frame_id, parent_info,
+ layout_chan, window_size, load_data.url.clone(), origin);
script_thread.start_page_load(new_load, load_data);
let reporter_name = format!("script-reporter-{}", id);
@@ -827,7 +827,22 @@ impl ScriptThread {
FromConstellation(ConstellationControlMsg::AttachLayout(
new_layout_info)) => {
self.profile_event(ScriptThreadEventCategory::AttachLayout, || {
- let origin = MutableOrigin::new(new_layout_info.load_data.url.origin());
+ // If this is an about:blank load, it must share the creator's origin.
+ // This must match the logic in the constellation when creating a new pipeline
+ let origin = if new_layout_info.load_data.url.as_str() != "about:blank" {
+ MutableOrigin::new(new_layout_info.load_data.url.origin())
+ } else if let Some(parent) = new_layout_info.parent_info
+ .and_then(|(pipeline_id, _)| self.documents.borrow()
+ .find_document(pipeline_id)) {
+ parent.origin().clone()
+ } else if let Some(creator) = new_layout_info.load_data.creator_pipeline_id
+ .and_then(|pipeline_id| self.documents.borrow()
+ .find_document(pipeline_id)) {
+ creator.origin().clone()
+ } else {
+ MutableOrigin::new(ImmutableOrigin::new_opaque())
+ };
+
self.handle_new_layout(new_layout_info, origin);
})
}
@@ -1043,10 +1058,12 @@ impl ScriptThread {
event),
ConstellationControlMsg::UpdatePipelineId(parent_pipeline_id,
frame_id,
- new_pipeline_id) =>
+ new_pipeline_id,
+ reason) =>
self.handle_update_pipeline_id(parent_pipeline_id,
frame_id,
- new_pipeline_id),
+ new_pipeline_id,
+ reason),
ConstellationControlMsg::FocusIFrame(parent_pipeline_id, frame_id) =>
self.handle_focus_iframe_msg(parent_pipeline_id, frame_id),
ConstellationControlMsg::WebDriverScriptCommand(pipeline_id, msg) =>
@@ -1062,8 +1079,6 @@ impl ScriptThread {
self.handle_frame_load_event(parent_id, frame_id, child_id),
ConstellationControlMsg::DispatchStorageEvent(pipeline_id, storage, url, key, old_value, new_value) =>
self.handle_storage_event(pipeline_id, storage, url, key, old_value, new_value),
- ConstellationControlMsg::FramedContentChanged(parent_pipeline_id, frame_id) =>
- self.handle_framed_content_changed(parent_pipeline_id, frame_id),
ConstellationControlMsg::ReportCSSError(pipeline_id, filename, line, column, msg) =>
self.handle_css_error_reporting(pipeline_id, filename, line, column, msg),
ConstellationControlMsg::Reload(pipeline_id) =>
@@ -1399,20 +1414,6 @@ impl ScriptThread {
}
}
- fn handle_framed_content_changed(&self,
- parent_pipeline_id: PipelineId,
- frame_id: FrameId) {
- let doc = self.documents.borrow().find_document(parent_pipeline_id).unwrap();
- let frame_element = doc.find_iframe(frame_id);
- if let Some(ref frame_element) = frame_element {
- frame_element.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage);
- let window = doc.window();
- window.reflow(ReflowGoal::ForDisplay,
- ReflowQueryType::NoQuery,
- ReflowReason::FramedContentChanged);
- }
- }
-
fn handle_post_message_msg(&self, pipeline_id: PipelineId, origin: Option<ImmutableOrigin>, data: Vec<u8>) {
match { self.documents.borrow().find_window(pipeline_id) } {
None => return warn!("postMessage after pipeline {} closed.", pipeline_id),
@@ -1443,10 +1444,11 @@ impl ScriptThread {
fn handle_update_pipeline_id(&self,
parent_pipeline_id: PipelineId,
frame_id: FrameId,
- new_pipeline_id: PipelineId) {
+ new_pipeline_id: PipelineId,
+ reason: UpdatePipelineIdReason) {
let frame_element = self.documents.borrow().find_iframe(parent_pipeline_id, frame_id);
if let Some(frame_element) = frame_element {
- frame_element.update_pipeline_id(new_pipeline_id);
+ frame_element.update_pipeline_id(new_pipeline_id, reason);
}
}
@@ -2065,7 +2067,7 @@ impl ScriptThread {
Some(frame_id) => {
let iframe = self.documents.borrow().find_iframe(parent_pipeline_id, frame_id);
if let Some(iframe) = iframe {
- iframe.navigate_or_reload_child_browsing_context(Some(load_data), replace);
+ iframe.navigate_or_reload_child_browsing_context(Some(load_data), NavigationType::Regular, replace);
}
}
None => {
diff --git a/components/script_layout_interface/lib.rs b/components/script_layout_interface/lib.rs
index 46d9bf2aadc..ddeed0d6366 100644
--- a/components/script_layout_interface/lib.rs
+++ b/components/script_layout_interface/lib.rs
@@ -50,6 +50,7 @@ use servo_url::ServoUrl;
use std::sync::atomic::AtomicIsize;
use style::data::ElementData;
+#[repr(C)]
pub struct PartialPersistentLayoutData {
/// Data that the style system associates with a node. When the
/// style system is being used standalone, this is all that hangs
@@ -59,6 +60,9 @@ pub struct PartialPersistentLayoutData {
/// Information needed during parallel traversals.
pub parallel: DomParallelInfo,
+
+ // Required alignment for safe transmutes between PersistentLayoutData and PartialPersistentLayoutData.
+ _align: [u64; 0]
}
impl PartialPersistentLayoutData {
@@ -66,6 +70,7 @@ impl PartialPersistentLayoutData {
PartialPersistentLayoutData {
style_data: ElementData::new(None),
parallel: DomParallelInfo::new(),
+ _align: [],
}
}
}
diff --git a/components/script_layout_interface/wrapper_traits.rs b/components/script_layout_interface/wrapper_traits.rs
index 52caf77805b..9683d049775 100644
--- a/components/script_layout_interface/wrapper_traits.rs
+++ b/components/script_layout_interface/wrapper_traits.rs
@@ -11,7 +11,7 @@ use SVGSVGData;
use atomic_refcell::AtomicRefCell;
use gfx_traits::{ByteIndex, FragmentType, combine_id_with_fragment_type};
use html5ever::{Namespace, LocalName};
-use msg::constellation_msg::PipelineId;
+use msg::constellation_msg::{FrameId, PipelineId};
use range::Range;
use servo_url::ServoUrl;
use std::fmt::Debug;
@@ -271,6 +271,10 @@ pub trait ThreadSafeLayoutNode: Clone + Copy + Debug + GetLayoutData + NodeInfo
fn svg_data(&self) -> Option<SVGSVGData>;
+ /// If this node is an iframe element, returns its frame ID. If this node is
+ /// not an iframe element, fails.
+ fn iframe_frame_id(&self) -> FrameId;
+
/// If this node is an iframe element, returns its pipeline ID. If this node is
/// not an iframe element, fails.
fn iframe_pipeline_id(&self) -> PipelineId;
diff --git a/components/script_traits/lib.rs b/components/script_traits/lib.rs
index 954c1386fa2..29baf8821e6 100644
--- a/components/script_traits/lib.rs
+++ b/components/script_traits/lib.rs
@@ -134,6 +134,8 @@ pub enum LayoutControlMsg {
pub struct LoadData {
/// The URL.
pub url: ServoUrl,
+ /// The creator pipeline id if this is an about:blank load.
+ pub creator_pipeline_id: Option<PipelineId>,
/// The method.
#[serde(deserialize_with = "::hyper_serde::deserialize",
serialize_with = "::hyper_serde::serialize")]
@@ -152,9 +154,14 @@ pub struct LoadData {
impl LoadData {
/// Create a new `LoadData` object.
- pub fn new(url: ServoUrl, referrer_policy: Option<ReferrerPolicy>, referrer_url: Option<ServoUrl>) -> LoadData {
+ pub fn new(url: ServoUrl,
+ creator_pipeline_id: Option<PipelineId>,
+ referrer_policy: Option<ReferrerPolicy>,
+ referrer_url: Option<ServoUrl>)
+ -> LoadData {
LoadData {
url: url,
+ creator_pipeline_id: creator_pipeline_id,
method: Method::Get,
headers: Headers::new(),
data: None,
@@ -211,6 +218,15 @@ pub enum DocumentActivity {
FullyActive,
}
+/// The reason why the pipeline id of an iframe is being updated.
+#[derive(Copy, Clone, PartialEq, Eq, Hash, HeapSizeOf, Debug, Deserialize, Serialize)]
+pub enum UpdatePipelineIdReason {
+ /// The pipeline id is being updated due to a navigation.
+ Navigation,
+ /// The pipeline id is being updated due to a history traversal.
+ Traversal,
+}
+
/// Messages sent from the constellation or layout to the script thread.
#[derive(Deserialize, Serialize)]
pub enum ConstellationControlMsg {
@@ -249,7 +265,7 @@ pub enum ConstellationControlMsg {
MozBrowserEvent(PipelineId, Option<FrameId>, MozBrowserEvent),
/// Updates the current pipeline ID of a given iframe.
/// First PipelineId is for the parent, second is the new PipelineId for the frame.
- UpdatePipelineId(PipelineId, FrameId, PipelineId),
+ UpdatePipelineId(PipelineId, FrameId, PipelineId, UpdatePipelineIdReason),
/// Set an iframe to be focused. Used when an element in an iframe gains focus.
/// PipelineId is for the parent, FrameId is for the actual frame.
FocusIFrame(PipelineId, FrameId),
@@ -274,9 +290,6 @@ pub enum ConstellationControlMsg {
/// Cause a `storage` event to be dispatched at the appropriate window.
/// The strings are key, old value and new value.
DispatchStorageEvent(PipelineId, StorageType, ServoUrl, Option<String>, Option<String>, Option<String>),
- /// Notifies a parent pipeline that one of its child frames is now active.
- /// PipelineId is for the parent, FrameId is the child frame.
- FramedContentChanged(PipelineId, FrameId),
/// Report an error from a CSS parser for the given pipeline
ReportCSSError(PipelineId, String, usize, usize, String),
/// Reload the given page.
@@ -312,7 +325,6 @@ impl fmt::Debug for ConstellationControlMsg {
WebFontLoaded(..) => "WebFontLoaded",
DispatchFrameLoadEvent { .. } => "DispatchFrameLoadEvent",
DispatchStorageEvent(..) => "DispatchStorageEvent",
- FramedContentChanged(..) => "FramedContentChanged",
ReportCSSError(..) => "ReportCSSError",
Reload(..) => "Reload",
WebVREvents(..) => "WebVREvents",
diff --git a/components/script_traits/script_msg.rs b/components/script_traits/script_msg.rs
index 47a7b103c8c..0402e3ddad6 100644
--- a/components/script_traits/script_msg.rs
+++ b/components/script_traits/script_msg.rs
@@ -34,8 +34,8 @@ use webrender_traits::ClipId;
pub enum LayoutMsg {
/// Indicates whether this pipeline is currently running animations.
ChangeRunningAnimationsState(PipelineId, AnimationState),
- /// Inform the constellation of the size of the pipeline's viewport.
- FrameSizes(Vec<(PipelineId, TypedSize2D<f32, CSSPixel>)>),
+ /// Inform the constellation of the size of the frame's viewport.
+ FrameSizes(Vec<(FrameId, TypedSize2D<f32, CSSPixel>)>),
/// Requests that the constellation inform the compositor of the a cursor change.
SetCursor(Cursor),
/// Notifies the constellation that the viewport has been constrained in some manner
@@ -120,8 +120,8 @@ pub enum ScriptMsg {
VisibilityChangeComplete(PipelineId, bool),
/// A load has been requested in an IFrame.
ScriptLoadedURLInIFrame(IFrameLoadInfoWithData),
- /// A load of `about:blank` has been completed in an IFrame.
- ScriptLoadedAboutBlankInIFrame(IFrameLoadInfo, IpcSender<LayoutControlMsg>),
+ /// A load of the initial `about:blank` has been completed in an IFrame.
+ ScriptNewIFrame(IFrameLoadInfo, IpcSender<LayoutControlMsg>),
/// Requests that the constellation set the contents of the clipboard
SetClipboardContents(String),
/// Mark a new document as active
diff --git a/components/style/attr.rs b/components/style/attr.rs
index 101810212b7..bbf8d53a430 100644
--- a/components/style/attr.rs
+++ b/components/style/attr.rs
@@ -375,7 +375,7 @@ impl ::std::ops::Deref for AttrValue {
pub fn parse_nonzero_length(value: &str) -> LengthOrPercentageOrAuto {
match parse_length(value) {
LengthOrPercentageOrAuto::Length(x) if x == Au::zero() => LengthOrPercentageOrAuto::Auto,
- LengthOrPercentageOrAuto::Percentage(0.) => LengthOrPercentageOrAuto::Auto,
+ LengthOrPercentageOrAuto::Percentage(x) if x == 0. => LengthOrPercentageOrAuto::Auto,
x => x,
}
}
diff --git a/components/style/build_gecko.rs b/components/style/build_gecko.rs
index 8376587d5ac..ad964b4b21d 100644
--- a/components/style/build_gecko.rs
+++ b/components/style/build_gecko.rs
@@ -153,6 +153,15 @@ mod bindings {
}
if cfg!(target_os = "linux") {
builder = builder.clang_arg("-DOS_LINUX=1");
+ // We may be cross-compiling with a clang that defaults to
+ // a different architecture, so we should explicitly specify
+ // the bitness being used here. Specifying --target instead
+ // leads to difficulties with LLVM search paths.
+ if cfg!(target_arch = "x86") {
+ builder = builder.clang_arg("-m32")
+ } else if cfg!(target_arch = "x86_64") {
+ builder = builder.clang_arg("-m64")
+ }
} else if cfg!(target_os = "solaris") {
builder = builder.clang_arg("-DOS_SOLARIS=1");
} else if cfg!(target_os = "dragonfly") {
diff --git a/components/style/element_state.rs b/components/style/element_state.rs
index 1c94580554b..30e67060f3f 100644
--- a/components/style/element_state.rs
+++ b/components/style/element_state.rs
@@ -115,5 +115,9 @@ bitflags! {
const IN_HANDLER_VULNERABLE_NO_UPDATE_STATE = 1 << 42,
/// https://drafts.csswg.org/selectors-4/#the-focus-within-pseudo
const IN_FOCUS_WITHIN_STATE = 1 << 43,
+ /// Non-standard & undocumented.
+ const IN_AUTOFILL_STATE = 1 << 50,
+ /// Non-standard & undocumented.
+ const IN_AUTOFILL_PREVIEW_STATE = 1 << 51,
}
}
diff --git a/components/style/gecko/generated/bindings.rs b/components/style/gecko/generated/bindings.rs
index c365ff677a1..13fe500e0c4 100644
--- a/components/style/gecko/generated/bindings.rs
+++ b/components/style/gecko/generated/bindings.rs
@@ -250,16 +250,16 @@ pub type RawServoSupportsRuleBorrowed<'a> = &'a RawServoSupportsRule;
pub type RawServoSupportsRuleBorrowedOrNull<'a> = Option<&'a RawServoSupportsRule>;
enum RawServoSupportsRuleVoid { }
pub struct RawServoSupportsRule(RawServoSupportsRuleVoid);
-pub type RawServoRuleNodeStrong = ::gecko_bindings::sugar::ownership::Strong<RawServoRuleNode>;
-pub type RawServoRuleNodeBorrowed<'a> = &'a RawServoRuleNode;
-pub type RawServoRuleNodeBorrowedOrNull<'a> = Option<&'a RawServoRuleNode>;
-enum RawServoRuleNodeVoid { }
-pub struct RawServoRuleNode(RawServoRuleNodeVoid);
pub type RawServoDocumentRuleStrong = ::gecko_bindings::sugar::ownership::Strong<RawServoDocumentRule>;
pub type RawServoDocumentRuleBorrowed<'a> = &'a RawServoDocumentRule;
pub type RawServoDocumentRuleBorrowedOrNull<'a> = Option<&'a RawServoDocumentRule>;
enum RawServoDocumentRuleVoid { }
pub struct RawServoDocumentRule(RawServoDocumentRuleVoid);
+pub type RawServoRuleNodeStrong = ::gecko_bindings::sugar::ownership::Strong<RawServoRuleNode>;
+pub type RawServoRuleNodeBorrowed<'a> = &'a RawServoRuleNode;
+pub type RawServoRuleNodeBorrowedOrNull<'a> = Option<&'a RawServoRuleNode>;
+enum RawServoRuleNodeVoid { }
+pub struct RawServoRuleNode(RawServoRuleNodeVoid);
pub type RawServoStyleSetOwned = ::gecko_bindings::sugar::ownership::Owned<RawServoStyleSet>;
pub type RawServoStyleSetOwnedOrNull = ::gecko_bindings::sugar::ownership::OwnedOrNull<RawServoStyleSet>;
pub type RawServoStyleSetBorrowed<'a> = &'a RawServoStyleSet;
@@ -422,16 +422,16 @@ extern "C" {
pub fn Servo_SupportsRule_Release(ptr: RawServoSupportsRuleBorrowed);
}
extern "C" {
- pub fn Servo_RuleNode_AddRef(ptr: RawServoRuleNodeBorrowed);
+ pub fn Servo_DocumentRule_AddRef(ptr: RawServoDocumentRuleBorrowed);
}
extern "C" {
- pub fn Servo_RuleNode_Release(ptr: RawServoRuleNodeBorrowed);
+ pub fn Servo_DocumentRule_Release(ptr: RawServoDocumentRuleBorrowed);
}
extern "C" {
- pub fn Servo_DocumentRule_AddRef(ptr: RawServoDocumentRuleBorrowed);
+ pub fn Servo_RuleNode_AddRef(ptr: RawServoRuleNodeBorrowed);
}
extern "C" {
- pub fn Servo_DocumentRule_Release(ptr: RawServoDocumentRuleBorrowed);
+ pub fn Servo_RuleNode_Release(ptr: RawServoRuleNodeBorrowed);
}
extern "C" {
pub fn Servo_StyleSet_Drop(ptr: RawServoStyleSetOwned);
@@ -1588,6 +1588,9 @@ extern "C" {
-> bool;
}
extern "C" {
+ pub fn Gecko_SetJemallocThreadLocalArena(enabled: bool);
+}
+extern "C" {
pub fn Servo_Element_ClearData(node: RawGeckoElementBorrowed);
}
extern "C" {
diff --git a/components/style/gecko/global_style_data.rs b/components/style/gecko/global_style_data.rs
index b1f62b0eac0..3cbace9b90a 100644
--- a/components/style/gecko/global_style_data.rs
+++ b/components/style/gecko/global_style_data.rs
@@ -6,6 +6,7 @@
use context::StyleSystemOptions;
use gecko_bindings::bindings::{Gecko_RegisterProfilerThread, Gecko_UnregisterProfilerThread};
+use gecko_bindings::bindings::Gecko_SetJemallocThreadLocalArena;
use num_cpus;
use rayon;
use shared_lock::SharedRwLock;
@@ -33,6 +34,9 @@ fn thread_name(index: usize) -> String {
}
fn thread_startup(index: usize) {
+ unsafe {
+ Gecko_SetJemallocThreadLocalArena(true);
+ }
let name = thread_name(index);
let name = CString::new(name).unwrap();
unsafe {
@@ -44,6 +48,7 @@ fn thread_startup(index: usize) {
fn thread_shutdown(_: usize) {
unsafe {
Gecko_UnregisterProfilerThread();
+ Gecko_SetJemallocThreadLocalArena(false);
}
}
diff --git a/components/style/gecko/non_ts_pseudo_class_list.rs b/components/style/gecko/non_ts_pseudo_class_list.rs
index 4d9b91384a1..145126656c2 100644
--- a/components/style/gecko/non_ts_pseudo_class_list.rs
+++ b/components/style/gecko/non_ts_pseudo_class_list.rs
@@ -38,7 +38,9 @@
* possible.
*
* $gecko_type can be either "_" or an ident in Gecko's CSSPseudoClassType.
- * $state can be either "_" or an expression of type ElementState.
+ * $state can be either "_" or an expression of type ElementState. If present,
+ * the semantics are that the pseudo-class matches if any of the bits in
+ * $state are set on the element.
* $flags can be either "_" or an expression of type NonTSPseudoClassFlag,
* see selector_parser.rs for more details.
*/
@@ -73,6 +75,8 @@ macro_rules! apply_non_ts_list {
("-moz-broken", MozBroken, mozBroken, IN_BROKEN_STATE, _),
("-moz-loading", MozLoading, mozLoading, IN_LOADING_STATE, _),
("-moz-suppressed", MozSuppressed, mozSuppressed, IN_SUPPRESSED_STATE, PSEUDO_CLASS_INTERNAL),
+ ("-moz-autofill", MozAutofill, mozAutofill, IN_AUTOFILL_STATE, PSEUDO_CLASS_INTERNAL),
+ ("-moz-autofill-preview", MozAutofillPreview, mozAutofillPreview, IN_AUTOFILL_PREVIEW_STATE, PSEUDO_CLASS_INTERNAL),
("-moz-handler-clicktoplay", MozHandlerClickToPlay, mozHandlerClickToPlay, IN_HANDLER_CLICK_TO_PLAY_STATE, PSEUDO_CLASS_INTERNAL),
("-moz-handler-vulnerable-updatable", MozHandlerVulnerableUpdatable, mozHandlerVulnerableUpdatable, IN_HANDLER_VULNERABLE_UPDATABLE_STATE, PSEUDO_CLASS_INTERNAL),
diff --git a/components/style/gecko/wrapper.rs b/components/style/gecko/wrapper.rs
index 5461bd7768e..a14348f4914 100644
--- a/components/style/gecko/wrapper.rs
+++ b/components/style/gecko/wrapper.rs
@@ -406,6 +406,12 @@ impl<'le> GeckoElement<'le> {
},
}
}
+
+ fn may_have_animations(&self) -> bool {
+ use gecko_bindings::structs::nsINode_BooleanFlag;
+ self.as_node().bool_flags() &
+ (1u32 << nsINode_BooleanFlag::ElementHasAnimations as u32) != 0
+ }
}
/// Converts flags from the layout used by rust-selectors to the layout used
@@ -764,15 +770,15 @@ impl<'le> TElement for GeckoElement<'le> {
}
fn has_animations(&self) -> bool {
- unsafe { Gecko_ElementHasAnimations(self.0) }
+ self.may_have_animations() && unsafe { Gecko_ElementHasAnimations(self.0) }
}
fn has_css_animations(&self) -> bool {
- unsafe { Gecko_ElementHasCSSAnimations(self.0) }
+ self.may_have_animations() && unsafe { Gecko_ElementHasCSSAnimations(self.0) }
}
fn has_css_transitions(&self) -> bool {
- unsafe { Gecko_ElementHasCSSTransitions(self.0) }
+ self.may_have_animations() && unsafe { Gecko_ElementHasCSSTransitions(self.0) }
}
fn get_css_transitions_info(&self)
@@ -1174,7 +1180,9 @@ impl<'le> ::selectors::Element for GeckoElement<'le> {
NonTSPseudoClass::MozUIInvalid |
NonTSPseudoClass::MozMeterOptimum |
NonTSPseudoClass::MozMeterSubOptimum |
- NonTSPseudoClass::MozMeterSubSubOptimum => {
+ NonTSPseudoClass::MozMeterSubSubOptimum |
+ NonTSPseudoClass::MozAutofill |
+ NonTSPseudoClass::MozAutofillPreview => {
// NB: It's important to use `intersect` instead of `contains`
// here, to handle `:any-link` correctly.
self.get_state().intersects(pseudo_class.state_flag())
diff --git a/components/style/properties/data.py b/components/style/properties/data.py
index eb1706e691e..8bb1fc86988 100644
--- a/components/style/properties/data.py
+++ b/components/style/properties/data.py
@@ -18,7 +18,8 @@ SYSTEM_FONT_LONGHANDS = """font_family font_size font_style
font_variant_position font_weight
font_size_adjust font_variant_alternates
font_variant_ligatures font_variant_east_asian
- font_variant_numeric font_language_override""".split()
+ font_variant_numeric font_language_override
+ font_feature_settings""".split()
def maybe_moz_logical_alias(product, side, prop):
diff --git a/components/style/properties/longhand/font.mako.rs b/components/style/properties/longhand/font.mako.rs
index f83757fb5e8..6691603499f 100644
--- a/components/style/properties/longhand/font.mako.rs
+++ b/components/style/properties/longhand/font.mako.rs
@@ -22,7 +22,7 @@
impl ToCss for SpecifiedValue {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
match *self {
- SpecifiedValue::Value(v) => v.to_css(dest),
+ SpecifiedValue::Value(ref v) => v.to_css(dest),
SpecifiedValue::System(_) => Ok(())
}
}
@@ -47,17 +47,17 @@
fn to_computed_value(&self, _context: &Context) -> computed_value::T {
match *self {
- SpecifiedValue::Value(v) => v,
+ SpecifiedValue::Value(ref v) => v.clone(),
SpecifiedValue::System(_) => {
<%self:nongecko_unreachable>
- _context.cached_system_font.as_ref().unwrap().${name}
+ _context.cached_system_font.as_ref().unwrap().${name}.clone()
</%self:nongecko_unreachable>
}
}
}
fn from_computed_value(other: &computed_value::T) -> Self {
- SpecifiedValue::Value(*other)
+ SpecifiedValue::Value(other.clone())
}
}
</%def>
@@ -337,14 +337,14 @@ ${helpers.single_keyword_system("font-style",
<% font_variant_caps_custom_consts= { "small-caps": "SMALLCAPS",
- "all-small": "ALLSMALL",
+ "all-small-caps": "ALLSMALL",
"petite-caps": "PETITECAPS",
- "all-petite": "ALLPETITE",
+ "all-petite-caps": "ALLPETITE",
"titling-caps": "TITLING" } %>
${helpers.single_keyword_system("font-variant-caps",
"normal small-caps",
- extra_gecko_values="all-small petite-caps unicase titling-caps",
+ extra_gecko_values="all-small-caps petite-caps all-petite-caps unicase titling-caps",
gecko_constant_prefix="NS_FONT_VARIANT_CAPS",
gecko_ffi_name="mFont.variantCaps",
spec="https://drafts.csswg.org/css-fonts/#propdef-font-variant-caps",
@@ -891,9 +891,10 @@ ${helpers.single_keyword_system("font-variant-caps",
}
}
+ #[allow(unused_mut)]
pub fn cascade_specified_font_size(context: &mut Context,
specified_value: &SpecifiedValue,
- computed: Au,
+ mut computed: Au,
parent: &Font) {
if let SpecifiedValue::Keyword(kw, fraction)
= *specified_value {
@@ -914,6 +915,22 @@ ${helpers.single_keyword_system("font-variant-caps",
context.mutate_style().font_size_keyword = None;
}
+ // we could use clone_language and clone_font_family() here but that's
+ // expensive. Do it only in gecko mode for now.
+ % if product == "gecko":
+ use gecko_bindings::structs::nsIAtom;
+ // if the language or generic changed, we need to recalculate
+ // the font size from the stored font-size origin information.
+ if context.style().get_font().gecko().mLanguage.raw::<nsIAtom>() !=
+ context.inherited_style().get_font().gecko().mLanguage.raw::<nsIAtom>() ||
+ context.style().get_font().gecko().mGenericID !=
+ context.inherited_style().get_font().gecko().mGenericID {
+ if let Some((kw, ratio)) = context.style().font_size_keyword {
+ computed = kw.to_computed_value(context).scale_by(ratio);
+ }
+ }
+ % endif
+
let parent_unconstrained = context.mutate_style()
.mutate_font()
.apply_font_size(computed,
@@ -1760,17 +1777,24 @@ ${helpers.single_keyword_system("font-variant-position",
spec="https://drafts.csswg.org/css-fonts/#propdef-font-variant-position",
animation_value_type="none")}
-<%helpers:longhand name="font-feature-settings" products="gecko" animation_value_type="none" extra_prefixes="moz"
+<%helpers:longhand name="font-feature-settings" products="gecko" animation_value_type="none"
+ extra_prefixes="moz" boxed="True"
spec="https://drafts.csswg.org/css-fonts/#propdef-font-feature-settings">
+ use properties::longhands::system_font::SystemFont;
use std::fmt;
use style_traits::ToCss;
use values::HasViewportPercentage;
use values::computed::ComputedValueAsSpecified;
- pub use self::computed_value::T as SpecifiedValue;
- impl ComputedValueAsSpecified for SpecifiedValue {}
+ #[derive(Debug, Clone, PartialEq)]
+ pub enum SpecifiedValue {
+ Value(computed_value::T),
+ System(SystemFont)
+ }
no_viewport_percentage!(SpecifiedValue);
+ <%self:simple_system_boilerplate name="font_feature_settings"></%self:simple_system_boilerplate>
+
pub mod computed_value {
use cssparser::Parser;
use parser::{Parse, ParserContext};
@@ -1874,13 +1898,18 @@ ${helpers.single_keyword_system("font-variant-position",
computed_value::T::Normal
}
+ #[inline]
+ pub fn get_initial_specified_value() -> SpecifiedValue {
+ SpecifiedValue::Value(computed_value::T::Normal)
+ }
+
/// normal | <feature-tag-value>#
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
if input.try(|input| input.expect_ident_matching("normal")).is_ok() {
- Ok(computed_value::T::Normal)
+ Ok(SpecifiedValue::Value(computed_value::T::Normal))
} else {
input.parse_comma_separated(|i| computed_value::FeatureTagValue::parse(context, i))
- .map(computed_value::T::Tag)
+ .map(computed_value::T::Tag).map(SpecifiedValue::Value)
}
}
</%helpers:longhand>
@@ -2373,6 +2402,7 @@ ${helpers.single_keyword("-moz-math-variant",
% endfor
font_language_override: longhands::font_language_override::computed_value
::T(system.languageOverride),
+ font_feature_settings: longhands::font_feature_settings::get_initial_value(),
system_font: *self,
};
unsafe { bindings::Gecko_nsFont_Destroy(&mut system); }
diff --git a/components/style/properties/shorthand/font.mako.rs b/components/style/properties/shorthand/font.mako.rs
index f82aea164cc..409e0717013 100644
--- a/components/style/properties/shorthand/font.mako.rs
+++ b/components/style/properties/shorthand/font.mako.rs
@@ -15,7 +15,8 @@
${'font-variant-ligatures' if product == 'gecko' or data.testing else ''}
${'font-variant-numeric' if product == 'gecko' or data.testing else ''}
${'font-variant-position' if product == 'gecko' or data.testing else ''}
- ${'font-language-override' if product == 'gecko' or data.testing else ''}"
+ ${'font-language-override' if product == 'gecko' or data.testing else ''}
+ ${'font-feature-settings' if product == 'gecko' or data.testing else ''}"
spec="https://drafts.csswg.org/css-fonts-3/#propdef-font">
use properties::longhands::{font_family, font_style, font_weight, font_stretch};
use properties::longhands::{font_size, line_height, font_variant_caps};
@@ -25,7 +26,7 @@
gecko_sub_properties = "kerning language_override size_adjust \
variant_alternates variant_east_asian \
variant_ligatures variant_numeric \
- variant_position".split()
+ variant_position feature_settings".split()
%>
% if product == "gecko" or data.testing:
% for prop in gecko_sub_properties:
diff --git a/components/style/restyle_hints.rs b/components/style/restyle_hints.rs
index b90dc0350fc..539ddb41561 100644
--- a/components/style/restyle_hints.rs
+++ b/components/style/restyle_hints.rs
@@ -343,7 +343,7 @@ impl<'a, E> Element for ElementWrapper<'a, E>
&mut |_, _| {})
}
match self.snapshot().and_then(|s| s.state()) {
- Some(snapshot_state) => snapshot_state.contains(flag),
+ Some(snapshot_state) => snapshot_state.intersects(flag),
None => {
self.element.match_non_ts_pseudo_class(pseudo_class,
relations,
diff --git a/components/style/values/computed/length.rs b/components/style/values/computed/length.rs
index 0312c601df9..5addd13be6d 100644
--- a/components/style/values/computed/length.rs
+++ b/components/style/values/computed/length.rs
@@ -221,8 +221,9 @@ impl LengthOrPercentage {
pub fn is_definitely_zero(&self) -> bool {
use self::LengthOrPercentage::*;
match *self {
- Length(Au(0)) | Percentage(0.0) => true,
- Length(_) | Percentage(_) | Calc(_) => false
+ Length(Au(0)) => true,
+ Percentage(p) => p == 0.0,
+ Length(_) | Calc(_) => false
}
}
@@ -312,8 +313,9 @@ impl LengthOrPercentageOrAuto {
pub fn is_definitely_zero(&self) -> bool {
use self::LengthOrPercentageOrAuto::*;
match *self {
- Length(Au(0)) | Percentage(0.0) => true,
- Length(_) | Percentage(_) | Calc(_) | Auto => false
+ Length(Au(0)) => true,
+ Percentage(p) => p == 0.0,
+ Length(_) | Calc(_) | Auto => false
}
}
}
diff --git a/components/style/values/specified/length.rs b/components/style/values/specified/length.rs
index 5c8845a5605..2062786adf8 100644
--- a/components/style/values/specified/length.rs
+++ b/components/style/values/specified/length.rs
@@ -266,14 +266,13 @@ pub enum AbsoluteLength {
impl AbsoluteLength {
fn is_zero(&self) -> bool {
match *self {
- AbsoluteLength::Px(0.)
- | AbsoluteLength::In(0.)
- | AbsoluteLength::Cm(0.)
- | AbsoluteLength::Mm(0.)
- | AbsoluteLength::Q(0.)
- | AbsoluteLength::Pt(0.)
- | AbsoluteLength::Pc(0.) => true,
- _ => false,
+ AbsoluteLength::Px(v)
+ | AbsoluteLength::In(v)
+ | AbsoluteLength::Cm(v)
+ | AbsoluteLength::Mm(v)
+ | AbsoluteLength::Q(v)
+ | AbsoluteLength::Pt(v)
+ | AbsoluteLength::Pc(v) => v == 0.,
}
}
}
diff --git a/components/webdriver_server/lib.rs b/components/webdriver_server/lib.rs
index 210c5b0f9c8..250ad21813b 100644
--- a/components/webdriver_server/lib.rs
+++ b/components/webdriver_server/lib.rs
@@ -357,7 +357,7 @@ impl Handler {
let (sender, receiver) = ipc::channel().unwrap();
- let load_data = LoadData::new(url, None, None);
+ let load_data = LoadData::new(url, Some(pipeline_id), None, None);
let cmd_msg = WebDriverCommandMsg::LoadUrl(pipeline_id, load_data, sender.clone());
self.constellation_chan.send(ConstellationMsg::WebDriverCommand(cmd_msg)).unwrap();
diff --git a/python/servo/devenv_commands.py b/python/servo/devenv_commands.py
index 314c5c2b8c1..f7df09ce754 100644
--- a/python/servo/devenv_commands.py
+++ b/python/servo/devenv_commands.py
@@ -226,11 +226,23 @@ class MachCommands(CommandBase):
env=self.build_env())
@Command('rustup',
- description='Update the Rust version to latest master',
+ description='Update the Rust version to latest Nightly',
category='devenv')
- def rustup(self):
- url = "https://api.github.com/repos/rust-lang/rust/git/refs/heads/master"
- commit = json.load(urllib2.urlopen(url))["object"]["sha"]
+ @CommandArgument('--master',
+ action='store_true',
+ help='Use the latest commit of the "master" branch')
+ def rustup(self, master=False):
+ if master:
+ url = "https://api.github.com/repos/rust-lang/rust/git/refs/heads/master"
+ commit = json.load(urllib2.urlopen(url))["object"]["sha"]
+ else:
+ import toml
+ import re
+ url = "https://static.rust-lang.org/dist/channel-rust-nightly.toml"
+ version = toml.load(urllib2.urlopen(url))["pkg"]["rustc"]["version"]
+ short_commit = re.search("\(([0-9a-f]+) ", version).group(1)
+ url = "https://api.github.com/repos/rust-lang/rust/commits/" + short_commit
+ commit = json.load(urllib2.urlopen(url))["sha"]
filename = path.join(self.context.topdir, "rust-commit-hash")
with open(filename, "w") as f:
f.write(commit + "\n")
diff --git a/tests/unit/layout/Cargo.toml b/tests/unit/layout/Cargo.toml
index 283964447d2..d0c5024a73e 100644
--- a/tests/unit/layout/Cargo.toml
+++ b/tests/unit/layout/Cargo.toml
@@ -10,4 +10,6 @@ path = "lib.rs"
doctest = false
[dependencies]
+atomic_refcell = "0.1"
layout = {path = "../../../components/layout"}
+script_layout_interface = {path = "../../../components/script_layout_interface"}
diff --git a/tests/unit/layout/align_of.rs b/tests/unit/layout/align_of.rs
new file mode 100644
index 00000000000..fe13b8fed94
--- /dev/null
+++ b/tests/unit/layout/align_of.rs
@@ -0,0 +1,26 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+use atomic_refcell::AtomicRefCell;
+use layout::PersistentLayoutData;
+use script_layout_interface::PartialPersistentLayoutData;
+use std::mem::align_of;
+
+fn check_layout_alignment(expected: usize, current: usize) {
+ if current != expected {
+ panic!("Your changes have altered the mem alignment of the PartialPersistentLayoutData \
+ struct to {}, but it must match the {}-alignment of PersistentLayoutData struct. \
+ Please fix alignment in components/script_layout_interface/lib.rs",
+ current, expected);
+ }
+}
+
+#[test]
+fn test_persistent_layout_data_alignment() {
+ check_layout_alignment(align_of::<PersistentLayoutData>(),
+ align_of::<PartialPersistentLayoutData>());
+
+ check_layout_alignment(align_of::<AtomicRefCell<PersistentLayoutData>>(),
+ align_of::<AtomicRefCell<PartialPersistentLayoutData>>());
+}
diff --git a/tests/unit/layout/lib.rs b/tests/unit/layout/lib.rs
index 59092bf4d9a..12091f920d6 100644
--- a/tests/unit/layout/lib.rs
+++ b/tests/unit/layout/lib.rs
@@ -2,6 +2,9 @@
* 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/. */
+extern crate atomic_refcell;
extern crate layout;
+extern crate script_layout_interface;
+#[cfg(test)] mod align_of;
#[cfg(all(test, target_pointer_width = "64"))] mod size_of;
diff --git a/tests/unit/style/parsing/font.rs b/tests/unit/style/parsing/font.rs
index 4513f79ce98..607f0ecb967 100644
--- a/tests/unit/style/parsing/font.rs
+++ b/tests/unit/style/parsing/font.rs
@@ -4,6 +4,7 @@
use parsing::parse;
use style::properties::longhands::{font_feature_settings, font_weight};
+use style::properties::longhands::font_feature_settings::SpecifiedValue;
use style::properties::longhands::font_feature_settings::computed_value;
use style::properties::longhands::font_feature_settings::computed_value::FeatureTagValue;
use style_traits::ToCss;
@@ -14,7 +15,7 @@ fn font_feature_settings_should_parse_properly() {
use std::io::Cursor;
let normal = parse_longhand!(font_feature_settings, "normal");
- let normal_computed = computed_value::T::Normal;
+ let normal_computed = SpecifiedValue::Value(computed_value::T::Normal);
assert_eq!(normal, normal_computed);
let mut a_d_bytes = Cursor::new(b"abcd");
@@ -24,34 +25,34 @@ fn font_feature_settings_should_parse_properly() {
let efgh = e_h_bytes.read_u32::<BigEndian>().unwrap();
let on = parse_longhand!(font_feature_settings, "\"abcd\" on");
- let on_computed = computed_value::T::Tag(vec![
+ let on_computed = SpecifiedValue::Value(computed_value::T::Tag(vec![
FeatureTagValue { tag: abcd, value: 1 }
- ]);
+ ]));
assert_eq!(on, on_computed);
let off = parse_longhand!(font_feature_settings, "\"abcd\" off");
- let off_computed = computed_value::T::Tag(vec![
+ let off_computed = SpecifiedValue::Value(computed_value::T::Tag(vec![
FeatureTagValue { tag: abcd, value: 0 }
- ]);
+ ]));
assert_eq!(off, off_computed);
let no_value = parse_longhand!(font_feature_settings, "\"abcd\"");
- let no_value_computed = computed_value::T::Tag(vec![
+ let no_value_computed = SpecifiedValue::Value(computed_value::T::Tag(vec![
FeatureTagValue { tag: abcd, value: 1 }
- ]);
+ ]));
assert_eq!(no_value, no_value_computed);
let pos_integer = parse_longhand!(font_feature_settings, "\"abcd\" 100");
- let pos_integer_computed = computed_value::T::Tag(vec![
+ let pos_integer_computed = SpecifiedValue::Value(computed_value::T::Tag(vec![
FeatureTagValue { tag: abcd, value: 100 }
- ]);
+ ]));
assert_eq!(pos_integer, pos_integer_computed);
let multiple = parse_longhand!(font_feature_settings, "\"abcd\" off, \"efgh\"");
- let multiple_computed = computed_value::T::Tag(vec![
+ let multiple_computed = SpecifiedValue::Value(computed_value::T::Tag(vec![
FeatureTagValue { tag: abcd, value: 0 },
FeatureTagValue { tag: efgh, value: 1 }
- ]);
+ ]));
assert_eq!(multiple, multiple_computed);
}
diff --git a/tests/unit/style/properties/serialization.rs b/tests/unit/style/properties/serialization.rs
index f164b656ce1..426597e56b4 100644
--- a/tests/unit/style/properties/serialization.rs
+++ b/tests/unit/style/properties/serialization.rs
@@ -653,7 +653,8 @@ mod shorthand_serialization {
font-kerning: auto; \
font-variant-caps: normal; \
font-variant-position: normal; \
- font-language-override: normal;";
+ font-language-override: normal; \
+ font-feature-settings: normal;";
let block = parse(|c, i| Ok(parse_property_declaration_list(c, i)), block_text).unwrap();
diff --git a/tests/wpt/metadata/MANIFEST.json b/tests/wpt/metadata/MANIFEST.json
index 90d74745236..24d4a7ee7da 100644
--- a/tests/wpt/metadata/MANIFEST.json
+++ b/tests/wpt/metadata/MANIFEST.json
@@ -331418,6 +331418,12 @@
{}
]
],
+ "html/semantics/embedded-content/the-iframe-element/content_document_changes_only_after_load_matures.html": [
+ [
+ "/html/semantics/embedded-content/the-iframe-element/content_document_changes_only_after_load_matures.html",
+ {}
+ ]
+ ],
"html/semantics/embedded-content/the-iframe-element/cross_origin_parentage.html": [
[
"/html/semantics/embedded-content/the-iframe-element/cross_origin_parentage.html",
@@ -570683,6 +570689,10 @@
"56df0cb79a1af927a0209c0bbbb5edb25ccaee5f",
"testharness"
],
+ "html/semantics/embedded-content/the-iframe-element/content_document_changes_only_after_load_matures.html": [
+ "46708fc218e559fba7049a36888a7c8a24c22672",
+ "testharness"
+ ],
"html/semantics/embedded-content/the-iframe-element/cross_origin_child.html": [
"a42082bb612b280eda5aa598ed750cfce3edd537",
"support"
diff --git a/tests/wpt/mozilla/meta/css/matchMedia.html.ini b/tests/wpt/mozilla/meta/css/matchMedia.html.ini
index 8c726be5a03..dded0e3276d 100644
--- a/tests/wpt/mozilla/meta/css/matchMedia.html.ini
+++ b/tests/wpt/mozilla/meta/css/matchMedia.html.ini
@@ -1,4 +1,5 @@
[matchMedia.html]
+ disabled: true
type: testharness
[window.matchMedia exists]
expected: FAIL
diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-iframe-element/content_document_changes_only_after_load_matures.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-iframe-element/content_document_changes_only_after_load_matures.html
new file mode 100644
index 00000000000..2cb85700230
--- /dev/null
+++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-iframe-element/content_document_changes_only_after_load_matures.html
@@ -0,0 +1,21 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>Iframe's contentDocument should only change after its pending load has matured.</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body></body>
+<script>
+async_test(function(t) {
+ var iframe = document.createElement("iframe");
+ document.body.appendChild(iframe);
+ iframe.onload = t.step_func(function() {
+ assert_true(iframe.contentDocument.location.toString().includes("support/blank.htm"));
+ t.done();
+ });
+
+ assert_equals(iframe.contentDocument.location.toString(), "about:blank");
+ iframe.src = "support/blank.htm?pipe=trickle(d2)";
+ // The location of the contentDocument should not change until the new document has matured.
+ assert_equals(iframe.contentDocument.location.toString(), "about:blank");
+}, "contentDocument should only change after a load matures.");
+</script>