aboutsummaryrefslogtreecommitdiffstats
path: root/components
diff options
context:
space:
mode:
Diffstat (limited to 'components')
-rw-r--r--components/compositing/compositor.rs7
-rw-r--r--components/compositing/compositor_thread.rs3
-rw-r--r--components/compositing/lib.rs45
-rw-r--r--components/constellation/constellation.rs12
-rw-r--r--components/constellation/pipeline.rs10
-rw-r--r--components/gfx/font_context.rs55
-rw-r--r--components/layout/fragment.rs5
-rw-r--r--components/layout/text.rs13
-rw-r--r--components/net/filemanager_thread.rs1
-rw-r--r--components/net_traits/filemanager_thread.rs5
-rw-r--r--components/script/dom/characterdata.rs116
-rw-r--r--components/script/dom/cssstyledeclaration.rs5
-rw-r--r--components/script/dom/element.rs4
-rw-r--r--components/script/dom/file.rs2
-rw-r--r--components/script/dom/htmlinputelement.rs49
-rw-r--r--components/script/dom/htmllinkelement.rs4
-rw-r--r--components/script/dom/htmlstyleelement.rs4
-rw-r--r--components/script_traits/lib.rs53
-rw-r--r--components/servo/Cargo.lock2
-rw-r--r--components/servo/lib.rs2
-rw-r--r--components/style/Cargo.toml3
-rw-r--r--components/style/attr.rs21
-rw-r--r--components/style/lib.rs2
-rw-r--r--components/style/parser.rs38
-rw-r--r--components/style/properties/helpers.mako.rs2
-rw-r--r--components/style/properties/longhand/box.mako.rs75
-rw-r--r--components/style/properties/properties.mako.rs27
-rw-r--r--components/style/selector_matching.rs10
-rw-r--r--components/style/stylesheets.rs19
-rw-r--r--components/style/values.rs10
-rw-r--r--components/util/str.rs4
-rw-r--r--components/webdriver_server/Cargo.toml2
-rw-r--r--components/webdriver_server/lib.rs4
33 files changed, 420 insertions, 194 deletions
diff --git a/components/compositing/compositor.rs b/components/compositing/compositor.rs
index 5d29140e356..5d7b72b0910 100644
--- a/components/compositing/compositor.rs
+++ b/components/compositing/compositor.rs
@@ -2,9 +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 AnimationTickType;
use CompositionPipeline;
-use CompositorMsg as ConstellationMsg;
use SendableFrameTree;
use app_units::Au;
use compositor_layer::{CompositorData, CompositorLayer, RcCompositorLayer, WantsScrollEventsFlag};
@@ -37,8 +35,9 @@ use msg::constellation_msg::{WindowSizeData, WindowSizeType};
use profile_traits::mem::{self, ReportKind, Reporter, ReporterRequest};
use profile_traits::time::{self, ProfilerCategory, profile};
use script_traits::CompositorEvent::{MouseMoveEvent, MouseButtonEvent, TouchEvent};
-use script_traits::{AnimationState, ConstellationControlMsg, LayoutControlMsg};
-use script_traits::{MouseButton, MouseEventType, TouchpadPressurePhase, TouchEventType, TouchId};
+use script_traits::{AnimationState, AnimationTickType, ConstellationControlMsg};
+use script_traits::{ConstellationMsg, LayoutControlMsg, MouseButton};
+use script_traits::{MouseEventType, TouchpadPressurePhase, TouchEventType, TouchId};
use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::collections::{HashMap, HashSet};
use std::fs::File;
diff --git a/components/compositing/compositor_thread.rs b/components/compositing/compositor_thread.rs
index 79beb580daf..69c60cd2e0b 100644
--- a/components/compositing/compositor_thread.rs
+++ b/components/compositing/compositor_thread.rs
@@ -4,7 +4,6 @@
//! Communication with the compositor thread.
-use CompositorMsg as ConstellationMsg;
use SendableFrameTree;
use compositor::{self, CompositingReason};
use euclid::point::Point2D;
@@ -16,7 +15,7 @@ use layers::platform::surface::{NativeDisplay, NativeSurface};
use msg::constellation_msg::{Image, Key, KeyModifiers, KeyState, PipelineId};
use profile_traits::mem;
use profile_traits::time;
-use script_traits::{AnimationState, EventResult, ScriptToCompositorMsg};
+use script_traits::{AnimationState, ConstellationMsg, EventResult, ScriptToCompositorMsg};
use std::fmt::{Debug, Error, Formatter};
use std::rc::Rc;
use std::sync::mpsc::{Receiver, Sender, channel};
diff --git a/components/compositing/lib.rs b/components/compositing/lib.rs
index e1e3305dca8..472c7bbd71f 100644
--- a/components/compositing/lib.rs
+++ b/components/compositing/lib.rs
@@ -29,7 +29,6 @@ extern crate net_traits;
#[macro_use]
extern crate profile_traits;
extern crate script_traits;
-extern crate serde;
extern crate style_traits;
extern crate time;
extern crate url;
@@ -39,18 +38,13 @@ extern crate webrender;
extern crate webrender_traits;
pub use compositor_thread::{CompositorEventListener, CompositorProxy, CompositorThread};
-use euclid::size::{Size2D, TypedSize2D};
+use euclid::size::TypedSize2D;
use gfx::paint_thread::ChromeToPaintMsg;
-use gfx_traits::Epoch;
use ipc_channel::ipc::{IpcSender};
use layout_traits::LayoutControlChan;
-use msg::constellation_msg::{FrameId, Key, KeyState, KeyModifiers, LoadData};
-use msg::constellation_msg::{NavigationDirection, PipelineId, SubpageId};
-use msg::constellation_msg::{WebDriverCommandMsg, WindowSizeData, WindowSizeType};
+use msg::constellation_msg::PipelineId;
use script_traits::ConstellationControlMsg;
-use std::collections::HashMap;
use std::sync::mpsc::Sender;
-use url::Url;
use util::geometry::PagePx;
mod compositor;
@@ -61,41 +55,6 @@ mod surface_map;
mod touch;
pub mod windowing;
-/// Specifies whether the script or layout thread needs to be ticked for animation.
-#[derive(Deserialize, Serialize)]
-pub enum AnimationTickType {
- Script,
- Layout,
-}
-
-/// Messages from the compositor to the constellation.
-#[derive(Deserialize, Serialize)]
-pub enum CompositorMsg {
- Exit,
- FrameSize(PipelineId, Size2D<f32>),
- /// Request that the constellation send the FrameId corresponding to the document
- /// with the provided pipeline id
- GetFrame(PipelineId, IpcSender<Option<FrameId>>),
- /// Request that the constellation send the current pipeline id for the provided frame
- /// id, or for the root frame if this is None, over a provided channel.
- /// Also returns a boolean saying whether the document has finished loading or not.
- GetPipeline(Option<FrameId>, IpcSender<Option<(PipelineId, bool)>>),
- /// Requests that the constellation inform the compositor of the title of the pipeline
- /// immediately.
- GetPipelineTitle(PipelineId),
- InitLoadUrl(Url),
- /// Query the constellation to see if the current compositor output is stable
- IsReadyToSaveImage(HashMap<PipelineId, Epoch>),
- KeyEvent(Key, KeyState, KeyModifiers),
- LoadUrl(PipelineId, LoadData),
- Navigate(Option<(PipelineId, SubpageId)>, NavigationDirection),
- WindowSize(WindowSizeData, WindowSizeType),
- /// Requests that the constellation instruct layout to begin a new tick of the animation.
- TickAnimation(PipelineId, AnimationTickType),
- /// Dispatch a webdriver command
- WebDriverCommand(WebDriverCommandMsg),
-}
-
pub struct SendableFrameTree {
pub pipeline: CompositionPipeline,
pub size: Option<TypedSize2D<PagePx, f32>>,
diff --git a/components/constellation/constellation.rs b/components/constellation/constellation.rs
index d0cd2973001..bbe25acc401 100644
--- a/components/constellation/constellation.rs
+++ b/components/constellation/constellation.rs
@@ -13,10 +13,9 @@ use canvas::canvas_paint_thread::CanvasPaintThread;
use canvas::webgl_paint_thread::WebGLPaintThread;
use canvas_traits::CanvasMsg;
use clipboard::ClipboardContext;
-use compositing::CompositorMsg as FromCompositorMsg;
+use compositing::SendableFrameTree;
use compositing::compositor_thread::CompositorProxy;
use compositing::compositor_thread::Msg as ToCompositorMsg;
-use compositing::{AnimationTickType, SendableFrameTree};
use devtools_traits::{ChromeToDevtoolsControlMsg, DevtoolsControlMsg};
use euclid::scale_factor::ScaleFactor;
use euclid::size::{Size2D, TypedSize2D};
@@ -39,6 +38,7 @@ use msg::constellation_msg::{SubpageId, WindowSizeData, WindowSizeType};
use msg::constellation_msg::{self, PanicMsg};
use msg::webdriver_msg;
use net_traits::bluetooth_thread::BluetoothMethodMsg;
+use net_traits::filemanager_thread::FileManagerThreadMsg;
use net_traits::image_cache_thread::ImageCacheThread;
use net_traits::storage_thread::StorageThreadMsg;
use net_traits::{self, ResourceThreads, IpcSend};
@@ -49,7 +49,8 @@ use profile_traits::time;
use rand::{random, Rng, SeedableRng, StdRng};
#[cfg(not(target_os = "windows"))]
use sandboxing::content_process_sandbox_profile;
-use script_traits::{AnimationState, CompositorEvent, ConstellationControlMsg};
+use script_traits::{AnimationState, AnimationTickType, CompositorEvent};
+use script_traits::{ConstellationControlMsg, ConstellationMsg as FromCompositorMsg};
use script_traits::{DocumentState, LayoutControlMsg};
use script_traits::{IFrameLoadInfo, IFrameSandboxState, TimerEventRequest};
use script_traits::{LayoutMsg as FromLayoutMsg, ScriptMsg as FromScriptMsg, ScriptThreadFactory};
@@ -850,6 +851,11 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF>
if let Err(e) = self.resource_threads.send(StorageThreadMsg::Exit) {
warn!("Exit storage thread failed ({})", e);
}
+
+ if let Err(e) = self.resource_threads.send(FileManagerThreadMsg::Exit) {
+ warn!("Exit storage thread failed ({})", e);
+ }
+
if let Err(e) = self.bluetooth_thread.send(BluetoothMethodMsg::Exit) {
warn!("Exit bluetooth thread failed ({})", e);
}
diff --git a/components/constellation/pipeline.rs b/components/constellation/pipeline.rs
index 8f9252bd263..dcab55b3656 100644
--- a/components/constellation/pipeline.rs
+++ b/components/constellation/pipeline.rs
@@ -130,7 +130,6 @@ impl Pipeline {
.expect("Pipeline main chan");;
let (script_to_compositor_chan, script_to_compositor_port) = ipc::channel()
.expect("Pipeline script to compositor chan");
- let mut pipeline_port = Some(pipeline_port);
let window_size = state.window_size.map(|size| {
WindowSizeData {
@@ -159,7 +158,7 @@ impl Pipeline {
let (layout_content_process_shutdown_chan, layout_content_process_shutdown_port) =
ipc::channel().expect("Pipeline layout content shutdown chan");
- let (script_chan, script_port) = match state.script_chan {
+ let (script_chan, script_port, pipeline_port) = match state.script_chan {
Some(script_chan) => {
let (containing_pipeline_id, subpage_id) =
state.parent_info.expect("script_pipeline != None but subpage_id == None");
@@ -170,8 +169,7 @@ impl Pipeline {
load_data: state.load_data.clone(),
paint_chan: layout_to_paint_chan.clone().to_opaque(),
panic_chan: state.panic_chan.clone(),
- pipeline_port: mem::replace(&mut pipeline_port, None)
- .expect("script_pipeline != None but pipeline_port == None"),
+ pipeline_port: pipeline_port,
layout_shutdown_chan: layout_shutdown_chan.clone(),
content_process_shutdown_chan: layout_content_process_shutdown_chan.clone(),
};
@@ -179,11 +177,11 @@ impl Pipeline {
if let Err(e) = script_chan.send(ConstellationControlMsg::AttachLayout(new_layout_info)) {
warn!("Sending to script during pipeline creation failed ({})", e);
}
- (script_chan, None)
+ (script_chan, None, None)
}
None => {
let (script_chan, script_port) = ipc::channel().expect("Pipeline script chan");
- (script_chan, Some(script_port))
+ (script_chan, Some(script_port), Some(pipeline_port))
}
};
diff --git a/components/gfx/font_context.rs b/components/gfx/font_context.rs
index 42415d9b833..d6c26083bf0 100644
--- a/components/gfx/font_context.rs
+++ b/components/gfx/font_context.rs
@@ -223,38 +223,35 @@ impl FontContext {
}
}
- // If unable to create any of the specified fonts, create one from the
- // list of last resort fonts for this platform.
- if fonts.is_empty() {
- let mut cache_hit = false;
- for cached_font_entry in &self.fallback_font_cache {
- let cached_font = cached_font_entry.font.borrow();
- if cached_font.descriptor == desc &&
- cached_font.requested_pt_size == style.font_size &&
- cached_font.variant == style.font_variant {
- fonts.push(cached_font_entry.font.clone());
- cache_hit = true;
- break;
- }
+ // Add a last resort font as a fallback option.
+ let mut cache_hit = false;
+ for cached_font_entry in &self.fallback_font_cache {
+ let cached_font = cached_font_entry.font.borrow();
+ if cached_font.descriptor == desc &&
+ cached_font.requested_pt_size == style.font_size &&
+ cached_font.variant == style.font_variant {
+ fonts.push(cached_font_entry.font.clone());
+ cache_hit = true;
+ break;
}
+ }
- if !cache_hit {
- let template_info = self.font_cache_thread.last_resort_font_template(desc.clone());
- let layout_font = self.create_layout_font(template_info.font_template,
- desc.clone(),
- style.font_size,
- style.font_variant,
- template_info.font_key);
- match layout_font {
- Ok(layout_font) => {
- let layout_font = Rc::new(RefCell::new(layout_font));
- self.fallback_font_cache.push(FallbackFontCacheEntry {
- font: layout_font.clone(),
- });
- fonts.push(layout_font);
- }
- Err(_) => debug!("Failed to create fallback layout font!")
+ if !cache_hit {
+ let template_info = self.font_cache_thread.last_resort_font_template(desc.clone());
+ let layout_font = self.create_layout_font(template_info.font_template,
+ desc.clone(),
+ style.font_size,
+ style.font_variant,
+ template_info.font_key);
+ match layout_font {
+ Ok(layout_font) => {
+ let layout_font = Rc::new(RefCell::new(layout_font));
+ self.fallback_font_cache.push(FallbackFontCacheEntry {
+ font: layout_font.clone(),
+ });
+ fonts.push(layout_font);
}
+ Err(_) => debug!("Failed to create fallback layout font!")
}
}
diff --git a/components/layout/fragment.rs b/components/layout/fragment.rs
index 520e4c5ab66..f2da09b734c 100644
--- a/components/layout/fragment.rs
+++ b/components/layout/fragment.rs
@@ -1971,6 +1971,11 @@ impl Fragment {
}
}
SpecificFragmentInfo::ScannedText(ref text_fragment) => {
+ // Fragments with no glyphs don't contribute any inline metrics.
+ // TODO: Filter out these fragments during flow construction?
+ if text_fragment.content_size.inline == Au(0) {
+ return InlineMetrics::new(Au(0), Au(0), Au(0));
+ }
// See CSS 2.1 § 10.8.1.
let line_height = self.calculate_line_height(layout_context);
let font_derived_metrics =
diff --git a/components/layout/text.rs b/components/layout/text.rs
index 1848a9b8741..3ba9be9f949 100644
--- a/components/layout/text.rs
+++ b/components/layout/text.rs
@@ -197,17 +197,12 @@ impl TextRunScanner {
for (byte_index, character) in text.char_indices() {
// Search for the first font in this font group that contains a glyph for this
// character.
- let mut font_index = 0;
+ let font_index = fontgroup.fonts.iter().position(|font| {
+ font.borrow().glyph_index(character).is_some()
+ }).unwrap_or(0);
+
// The following code panics one way or another if this condition isn't met.
assert!(fontgroup.fonts.len() > 0);
- while font_index < fontgroup.fonts.len() - 1 {
- if fontgroup.fonts.get(font_index).unwrap().borrow()
- .glyph_index(character)
- .is_some() {
- break
- }
- font_index += 1;
- }
let bidi_level = match bidi_levels {
Some(levels) => levels[*paragraph_bytes_processed],
diff --git a/components/net/filemanager_thread.rs b/components/net/filemanager_thread.rs
index f2cdc658b37..bf546c80636 100644
--- a/components/net/filemanager_thread.rs
+++ b/components/net/filemanager_thread.rs
@@ -53,6 +53,7 @@ impl FileManager {
FileManagerThreadMsg::SelectFiles(sender) => self.select_files(sender),
FileManagerThreadMsg::ReadFile(sender, id) => self.read_file(sender, id),
FileManagerThreadMsg::DeleteFileID(id) => self.delete_fileid(id),
+ FileManagerThreadMsg::Exit => break,
}
}
}
diff --git a/components/net_traits/filemanager_thread.rs b/components/net_traits/filemanager_thread.rs
index ee4fdb291cf..2ced0701eff 100644
--- a/components/net_traits/filemanager_thread.rs
+++ b/components/net_traits/filemanager_thread.rs
@@ -6,7 +6,7 @@ use ipc_channel::ipc::IpcSender;
use std::path::PathBuf;
use uuid::Uuid;
-#[derive(Deserialize, Serialize)]
+#[derive(Debug, Deserialize, Serialize)]
pub struct SelectedFile {
pub id: Uuid,
pub filename: PathBuf,
@@ -28,6 +28,9 @@ pub enum FileManagerThreadMsg {
/// Delete the FileID entry
DeleteFileID(Uuid),
+
+ /// Shut down this thread
+ Exit,
}
pub type FileManagerResult<T> = Result<T, FileManagerThreadError>;
diff --git a/components/script/dom/characterdata.rs b/components/script/dom/characterdata.rs
index 74fd0db94c9..01f11e3ac50 100644
--- a/components/script/dom/characterdata.rs
+++ b/components/script/dom/characterdata.rs
@@ -20,6 +20,7 @@ use dom::node::{Node, NodeDamage};
use dom::processinginstruction::ProcessingInstruction;
use dom::text::Text;
use std::cell::Ref;
+use util::opts;
// https://dom.spec.whatwg.org/#characterdata
#[dom_struct]
@@ -94,16 +95,34 @@ impl CharacterDataMethods for CharacterData {
fn SubstringData(&self, offset: u32, count: u32) -> Fallible<DOMString> {
let data = self.data.borrow();
// Step 1.
- let data_from_offset = match find_utf16_code_unit_offset(&data, offset) {
- Some(offset_bytes) => &data[offset_bytes..],
+ let mut substring = String::new();
+ let remaining;
+ match split_at_utf16_code_unit_offset(&data, offset) {
+ Ok((_, astral, s)) => {
+ // As if we had split the UTF-16 surrogate pair in half
+ // and then transcoded that to UTF-8 lossily,
+ // since our DOMString is currently strict UTF-8.
+ if astral.is_some() {
+ substring = substring + "\u{FFFD}";
+ }
+ remaining = s;
+ }
// Step 2.
- None => return Err(Error::IndexSize),
- };
- let substring = match find_utf16_code_unit_offset(data_from_offset, count) {
+ Err(()) => return Err(Error::IndexSize),
+ }
+ match split_at_utf16_code_unit_offset(remaining, count) {
// Steps 3.
- None => data_from_offset,
+ Err(()) => substring = substring + remaining,
// Steps 4.
- Some(count_bytes) => &data_from_offset[..count_bytes],
+ Ok((s, astral, _)) => {
+ substring = substring + s;
+ // As if we had split the UTF-16 surrogate pair in half
+ // and then transcoded that to UTF-8 lossily,
+ // since our DOMString is currently strict UTF-8.
+ if astral.is_some() {
+ substring = substring + "\u{FFFD}";
+ }
+ }
};
Ok(DOMString::from(substring))
}
@@ -126,26 +145,54 @@ impl CharacterDataMethods for CharacterData {
// https://dom.spec.whatwg.org/#dom-characterdata-replacedata
fn ReplaceData(&self, offset: u32, count: u32, arg: DOMString) -> ErrorResult {
- let new_data = {
+ let mut new_data;
+ {
let data = self.data.borrow();
- let (prefix, data_from_offset) = match find_utf16_code_unit_offset(&data, offset) {
- Some(offset_bytes) => data.split_at(offset_bytes),
+ let prefix;
+ let replacement_before;
+ let remaining;
+ match split_at_utf16_code_unit_offset(&data, offset) {
+ Ok((p, astral, r)) => {
+ prefix = p;
+ // As if we had split the UTF-16 surrogate pair in half
+ // and then transcoded that to UTF-8 lossily,
+ // since our DOMString is currently strict UTF-8.
+ replacement_before = if astral.is_some() { "\u{FFFD}" } else { "" };
+ remaining = r;
+ }
// Step 2.
- None => return Err(Error::IndexSize),
+ Err(()) => return Err(Error::IndexSize),
};
- let suffix = match find_utf16_code_unit_offset(data_from_offset, count) {
+ let replacement_after;
+ let suffix;
+ match split_at_utf16_code_unit_offset(remaining, count) {
// Steps 3.
- None => "",
- Some(count_bytes) => &data_from_offset[count_bytes..],
+ Err(()) => {
+ replacement_after = "";
+ suffix = "";
+ }
+ Ok((_, astral, s)) => {
+ // As if we had split the UTF-16 surrogate pair in half
+ // and then transcoded that to UTF-8 lossily,
+ // since our DOMString is currently strict UTF-8.
+ replacement_after = if astral.is_some() { "\u{FFFD}" } else { "" };
+ suffix = s;
+ }
};
// Step 4: Mutation observers.
// Step 5 to 7.
- let mut new_data = String::with_capacity(prefix.len() + arg.len() + suffix.len());
+ new_data = String::with_capacity(
+ prefix.len() +
+ replacement_before.len() +
+ arg.len() +
+ replacement_after.len() +
+ suffix.len());
new_data.push_str(prefix);
+ new_data.push_str(replacement_before);
new_data.push_str(&arg);
+ new_data.push_str(replacement_after);
new_data.push_str(suffix);
- new_data
- };
+ }
*self.data.borrow_mut() = DOMString::from(new_data);
self.content_changed();
// Steps 8-11.
@@ -200,19 +247,40 @@ impl LayoutCharacterDataHelpers for LayoutJS<CharacterData> {
}
}
-/// Given a number of UTF-16 code units from the start of the given string,
-/// return the corresponding number of UTF-8 bytes.
+/// Split the given string at the given position measured in UTF-16 code units from the start.
+///
+/// * `Err(())` indicates that `offset` if after the end of the string
+/// * `Ok((before, None, after))` indicates that `offset` is between Unicode code points.
+/// The two string slices are such that:
+/// `before == s.to_utf16()[..offset].to_utf8()` and
+/// `after == s.to_utf16()[offset..].to_utf8()`
+/// * `Ok((before, Some(ch), after))` indicates that `offset` is "in the middle"
+/// of a single Unicode code point that would be represented in UTF-16 by a surrogate pair
+/// of two 16-bit code units.
+/// `ch` is that code point.
+/// The two string slices are such that:
+/// `before == s.to_utf16()[..offset - 1].to_utf8()` and
+/// `after == s.to_utf16()[offset + 1..].to_utf8()`
+///
+/// # Panics
///
-/// s[find_utf16_code_unit_offset(s, o).unwrap()..] == s.to_utf16()[o..].to_utf8()
-fn find_utf16_code_unit_offset(s: &str, offset: u32) -> Option<usize> {
+/// Note that the third variant is only ever returned when the `-Z replace-surrogates`
+/// command-line option is specified.
+/// When it *would* be returned but the option is *not* specified, this function panics.
+fn split_at_utf16_code_unit_offset(s: &str, offset: u32) -> Result<(&str, Option<char>, &str), ()> {
let mut code_units = 0;
for (i, c) in s.char_indices() {
if code_units == offset {
- return Some(i);
+ let (a, b) = s.split_at(i);
+ return Ok((a, None, b));
}
code_units += 1;
if c > '\u{FFFF}' {
if code_units == offset {
+ if opts::get().replace_surrogates {
+ debug_assert!(c.len_utf8() == 4);
+ return Ok((&s[..i], Some(c), &s[i + c.len_utf8()..]))
+ }
panic!("\n\n\
Would split a surrogate pair in CharacterData API.\n\
If you see this in real content, please comment with the URL\n\
@@ -223,8 +291,8 @@ fn find_utf16_code_unit_offset(s: &str, offset: u32) -> Option<usize> {
}
}
if code_units == offset {
- Some(s.len())
+ Ok((s, None, ""))
} else {
- None
+ Err(())
}
}
diff --git a/components/script/dom/cssstyledeclaration.rs b/components/script/dom/cssstyledeclaration.rs
index 6d537c40ea5..df9251f3888 100644
--- a/components/script/dom/cssstyledeclaration.rs
+++ b/components/script/dom/cssstyledeclaration.rs
@@ -16,6 +16,7 @@ use std::ascii::AsciiExt;
use std::borrow::ToOwned;
use std::cell::Ref;
use string_cache::Atom;
+use style::parser::ParserContextExtraData;
use style::properties::{PropertyDeclaration, Shorthand};
use style::properties::{is_supported_property, parse_one_declaration};
use style::selector_impl::PseudoElement;
@@ -240,7 +241,9 @@ impl CSSStyleDeclarationMethods for CSSStyleDeclaration {
// Step 6
let window = window_from_node(&*self.owner);
- let declarations = parse_one_declaration(&property, &value, &window.get_url(), window.css_error_reporter());
+ let declarations =
+ parse_one_declaration(&property, &value, &window.get_url(), window.css_error_reporter(),
+ ParserContextExtraData::default());
// Step 7
let declarations = if let Ok(declarations) = declarations {
diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs
index ec33deb1608..f5832089202 100644
--- a/components/script/dom/element.rs
+++ b/components/script/dom/element.rs
@@ -86,6 +86,7 @@ use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};
use string_cache::{Atom, BorrowedAtom, BorrowedNamespace, Namespace, QualName};
use style::element_state::*;
+use style::parser::ParserContextExtraData;
use style::properties::DeclaredValue;
use style::properties::longhands::{self, background_image, border_spacing, font_family, overflow_x, font_size};
use style::properties::{PropertyDeclaration, PropertyDeclarationBlock, parse_style_attribute};
@@ -1977,7 +1978,8 @@ impl VirtualMethods for Element {
*self.style_attribute.borrow_mut() =
mutation.new_value(attr).map(|value| {
let win = window_from_node(self);
- parse_style_attribute(&value, &doc.base_url(), win.css_error_reporter())
+ parse_style_attribute(&value, &doc.base_url(), win.css_error_reporter(),
+ ParserContextExtraData::default())
});
if node.is_in_doc() {
node.dirty(NodeDamage::NodeStyleDamaged);
diff --git a/components/script/dom/file.rs b/components/script/dom/file.rs
index 62e1b0a95bd..f566b4426b4 100644
--- a/components/script/dom/file.rs
+++ b/components/script/dom/file.rs
@@ -51,8 +51,6 @@ impl File {
pub fn new_from_selected(window: &Window, selected: SelectedFile) -> Root<File> {
let name = DOMString::from(selected.filename.to_str().expect("File name encoding error"));
- // FIXME: fix this after PR #11221 is landed
- let id = selected.id;
let slice = DataSlice::empty();
let global = GlobalRef::Window(window);
diff --git a/components/script/dom/htmlinputelement.rs b/components/script/dom/htmlinputelement.rs
index dbc0d4f8f1f..8977d45048e 100644
--- a/components/script/dom/htmlinputelement.rs
+++ b/components/script/dom/htmlinputelement.rs
@@ -271,22 +271,22 @@ impl LayoutHTMLInputElementHelpers for LayoutJS<HTMLInputElement> {
impl HTMLInputElementMethods for HTMLInputElement {
- // https://html.spec.whatwg.org/multipage/#attr-input-accept
+ // https://html.spec.whatwg.org/multipage/#dom-input-accept
make_getter!(Accept, "accept");
- // https://html.spec.whatwg.org/multipage/#attr-input-accept
+ // https://html.spec.whatwg.org/multipage/#dom-input-accept
make_setter!(SetAccept, "accept");
- // https://html.spec.whatwg.org/multipage/#attr-input-alt
+ // https://html.spec.whatwg.org/multipage/#dom-input-alt
make_getter!(Alt, "alt");
- // https://html.spec.whatwg.org/multipage/#attr-input-alt
+ // https://html.spec.whatwg.org/multipage/#dom-input-alt
make_setter!(SetAlt, "alt");
- // https://html.spec.whatwg.org/multipage/#attr-input-dirName
+ // https://html.spec.whatwg.org/multipage/#dom-input-dirName
make_getter!(DirName, "dirname");
- // https://html.spec.whatwg.org/multipage/#attr-input-dirName
+ // https://html.spec.whatwg.org/multipage/#dom-input-dirName
make_setter!(SetDirName, "dirname");
// https://html.spec.whatwg.org/multipage/#dom-fe-disabled
@@ -415,10 +415,10 @@ impl HTMLInputElementMethods for HTMLInputElement {
// https://html.spec.whatwg.org/multipage/#attr-fe-name
make_atomic_setter!(SetName, "name");
- // https://html.spec.whatwg.org/multipage/#attr-input-placeholder
+ // https://html.spec.whatwg.org/multipage/#dom-input-placeholder
make_getter!(Placeholder, "placeholder");
- // https://html.spec.whatwg.org/multipage/#attr-input-placeholder
+ // https://html.spec.whatwg.org/multipage/#dom-input-placeholder
make_setter!(SetPlaceholder, "placeholder");
// https://html.spec.whatwg.org/multipage/#dom-input-formaction
@@ -454,10 +454,10 @@ impl HTMLInputElementMethods for HTMLInputElement {
// https://html.spec.whatwg.org/multipage/#attr-fs-formnovalidate
make_bool_setter!(SetFormNoValidate, "formnovalidate");
- // https://html.spec.whatwg.org/multipage/#attr-input-max
+ // https://html.spec.whatwg.org/multipage/#dom-input-max
make_getter!(Max, "max");
- // https://html.spec.whatwg.org/multipage/#attr-input-max
+ // https://html.spec.whatwg.org/multipage/#dom-input-max
make_setter!(SetMax, "max");
// https://html.spec.whatwg.org/multipage/#dom-input-maxlength
@@ -466,40 +466,40 @@ impl HTMLInputElementMethods for HTMLInputElement {
// https://html.spec.whatwg.org/multipage/#dom-input-maxlength
make_limited_int_setter!(SetMaxLength, "maxlength", DEFAULT_MAX_LENGTH);
- // https://html.spec.whatwg.org/multipage/#attr-input-min
+ // https://html.spec.whatwg.org/multipage/#dom-input-min
make_getter!(Min, "min");
- // https://html.spec.whatwg.org/multipage/#attr-input-min
+ // https://html.spec.whatwg.org/multipage/#dom-input-min
make_setter!(SetMin, "min");
- // https://html.spec.whatwg.org/multipage/#attr-input-multiple
+ // https://html.spec.whatwg.org/multipage/#dom-input-multiple
make_bool_getter!(Multiple, "multiple");
- // https://html.spec.whatwg.org/multipage/#attr-input-multiple
+ // https://html.spec.whatwg.org/multipage/#dom-input-multiple
make_bool_setter!(SetMultiple, "multiple");
- // https://html.spec.whatwg.org/multipage/#attr-input-pattern
+ // https://html.spec.whatwg.org/multipage/#dom-input-pattern
make_getter!(Pattern, "pattern");
- // https://html.spec.whatwg.org/multipage/#attr-input-pattern
+ // https://html.spec.whatwg.org/multipage/#dom-input-pattern
make_setter!(SetPattern, "pattern");
- // https://html.spec.whatwg.org/multipage/#attr-input-required
+ // https://html.spec.whatwg.org/multipage/#dom-input-required
make_bool_getter!(Required, "required");
- // https://html.spec.whatwg.org/multipage/#attr-input-required
+ // https://html.spec.whatwg.org/multipage/#dom-input-required
make_bool_setter!(SetRequired, "required");
- // https://html.spec.whatwg.org/multipage/#attr-input-src
- make_getter!(Src, "src");
+ // https://html.spec.whatwg.org/multipage/#dom-input-src
+ make_url_getter!(Src, "src");
- // https://html.spec.whatwg.org/multipage/#attr-input-src
- make_setter!(SetSrc, "src");
+ // https://html.spec.whatwg.org/multipage/#dom-input-src
+ make_url_setter!(SetSrc, "src");
- // https://html.spec.whatwg.org/multipage/#attr-input-step
+ // https://html.spec.whatwg.org/multipage/#dom-input-step
make_getter!(Step, "step");
- // https://html.spec.whatwg.org/multipage/#attr-input-step
+ // https://html.spec.whatwg.org/multipage/#dom-input-step
make_setter!(SetStep, "step");
// https://html.spec.whatwg.org/multipage/#dom-input-indeterminate
@@ -881,6 +881,7 @@ impl VirtualMethods for HTMLInputElement {
fn parse_plain_attribute(&self, name: &Atom, value: DOMString) -> AttrValue {
match name {
+ &atom!("accept") => AttrValue::from_comma_separated_tokenlist(value.into()),
&atom!("name") => AttrValue::from_atomic(value.into()),
&atom!("size") => AttrValue::from_limited_u32(value.into(), DEFAULT_INPUT_SIZE),
&atom!("type") => AttrValue::from_atomic(value.into()),
diff --git a/components/script/dom/htmllinkelement.rs b/components/script/dom/htmllinkelement.rs
index 18ff43c000b..88de9756267 100644
--- a/components/script/dom/htmllinkelement.rs
+++ b/components/script/dom/htmllinkelement.rs
@@ -38,6 +38,7 @@ use std::mem;
use std::sync::{Arc, Mutex};
use string_cache::Atom;
use style::media_queries::{MediaQueryList, parse_media_query_list};
+use style::parser::ParserContextExtraData;
use style::servo::Stylesheet;
use style::stylesheets::Origin;
use url::Url;
@@ -307,7 +308,8 @@ impl AsyncResponseListener for StylesheetContext {
let mut sheet = Stylesheet::from_bytes(&data, final_url, protocol_encoding_label,
Some(environment_encoding), Origin::Author,
- win.css_error_reporter());
+ win.css_error_reporter(),
+ ParserContextExtraData::default());
let media = self.media.take().unwrap();
sheet.set_media(Some(media));
let sheet = Arc::new(sheet);
diff --git a/components/script/dom/htmlstyleelement.rs b/components/script/dom/htmlstyleelement.rs
index 8d4a05eb9b7..62395b682d1 100644
--- a/components/script/dom/htmlstyleelement.rs
+++ b/components/script/dom/htmlstyleelement.rs
@@ -18,6 +18,7 @@ use layout_interface::{LayoutChan, Msg};
use std::sync::Arc;
use string_cache::Atom;
use style::media_queries::parse_media_query_list;
+use style::parser::ParserContextExtraData;
use style::servo::Stylesheet;
use style::stylesheets::Origin;
@@ -60,7 +61,8 @@ impl HTMLStyleElement {
};
let data = node.GetTextContent().expect("Element.textContent must be a string");
- let mut sheet = Stylesheet::from_str(&data, url, Origin::Author, win.css_error_reporter());
+ let mut sheet = Stylesheet::from_str(&data, url, Origin::Author, win.css_error_reporter(),
+ ParserContextExtraData::default());
let mut css_parser = CssParser::new(&mq_str);
let media = parse_media_query_list(&mut css_parser);
sheet.set_media(Some(media));
diff --git a/components/script_traits/lib.rs b/components/script_traits/lib.rs
index 2dee02fec59..8d39895ed46 100644
--- a/components/script_traits/lib.rs
+++ b/components/script_traits/lib.rs
@@ -41,9 +41,10 @@ use gfx_traits::Epoch;
use gfx_traits::LayerId;
use ipc_channel::ipc::{IpcReceiver, IpcSender};
use libc::c_void;
-use msg::constellation_msg::{Key, KeyModifiers, KeyState, LoadData};
-use msg::constellation_msg::{PanicMsg, PipelineId, PipelineNamespaceId};
-use msg::constellation_msg::{SubpageId, WindowSizeData, WindowSizeType};
+use msg::constellation_msg::{FrameId, Key, KeyModifiers, KeyState, LoadData};
+use msg::constellation_msg::{NavigationDirection, PanicMsg, PipelineId};
+use msg::constellation_msg::{PipelineNamespaceId, SubpageId, WindowSizeData};
+use msg::constellation_msg::{WebDriverCommandMsg, WindowSizeType};
use msg::webdriver_msg::WebDriverScriptCommand;
use net_traits::ResourceThreads;
use net_traits::bluetooth_thread::BluetoothMethodMsg;
@@ -51,6 +52,8 @@ use net_traits::image_cache_thread::ImageCacheThread;
use net_traits::response::HttpsState;
use profile_traits::mem;
use std::any::Any;
+use std::collections::HashMap;
+use url::Url;
use util::ipc::OptionalOpaqueIpcSender;
pub use script_msg::{LayoutMsg, ScriptMsg};
@@ -491,3 +494,47 @@ impl MozBrowserErrorType {
}
}
}
+
+/// Specifies whether the script or layout thread needs to be ticked for animation.
+#[derive(Deserialize, Serialize)]
+pub enum AnimationTickType {
+ /// The script thread.
+ Script,
+ /// The layout thread.
+ Layout,
+}
+
+/// Messages to the constellation.
+#[derive(Deserialize, Serialize)]
+pub enum ConstellationMsg {
+ /// Exit the constellation.
+ Exit,
+ /// Inform the constellation of the size of the viewport.
+ FrameSize(PipelineId, Size2D<f32>),
+ /// Request that the constellation send the FrameId corresponding to the document
+ /// with the provided pipeline id
+ GetFrame(PipelineId, IpcSender<Option<FrameId>>),
+ /// Request that the constellation send the current pipeline id for the provided frame
+ /// id, or for the root frame if this is None, over a provided channel.
+ /// Also returns a boolean saying whether the document has finished loading or not.
+ GetPipeline(Option<FrameId>, IpcSender<Option<(PipelineId, bool)>>),
+ /// Requests that the constellation inform the compositor of the title of the pipeline
+ /// immediately.
+ GetPipelineTitle(PipelineId),
+ /// Request to load the initial page.
+ InitLoadUrl(Url),
+ /// Query the constellation to see if the current compositor output is stable
+ IsReadyToSaveImage(HashMap<PipelineId, Epoch>),
+ /// Inform the constellation of a key event.
+ KeyEvent(Key, KeyState, KeyModifiers),
+ /// Request to load a page.
+ LoadUrl(PipelineId, LoadData),
+ /// Request to navigate a frame.
+ Navigate(Option<(PipelineId, SubpageId)>, NavigationDirection),
+ /// Inform the constellation of a window being resized.
+ WindowSize(WindowSizeData, WindowSizeType),
+ /// Requests that the constellation instruct layout to begin a new tick of the animation.
+ TickAnimation(PipelineId, AnimationTickType),
+ /// Dispatch a webdriver command
+ WebDriverCommand(WebDriverCommandMsg),
+}
diff --git a/components/servo/Cargo.lock b/components/servo/Cargo.lock
index 8e69e676201..335c040e61c 100644
--- a/components/servo/Cargo.lock
+++ b/components/servo/Cargo.lock
@@ -2480,7 +2480,6 @@ dependencies = [
name = "webdriver_server"
version = "0.0.1"
dependencies = [
- "compositing 0.0.1",
"euclid 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
"hyper 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)",
"image 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2490,6 +2489,7 @@ dependencies = [
"plugins 0.0.1",
"regex 0.1.71 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
+ "script_traits 0.0.1",
"url 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"util 0.0.1",
"uuid 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
diff --git a/components/servo/lib.rs b/components/servo/lib.rs
index 16403134a1b..e208a4e89f1 100644
--- a/components/servo/lib.rs
+++ b/components/servo/lib.rs
@@ -58,7 +58,6 @@ fn webdriver(port: u16, constellation: Sender<ConstellationMsg>) {
fn webdriver(_port: u16, _constellation: Sender<ConstellationMsg>) { }
use compositing::CompositorEventListener;
-use compositing::CompositorMsg as ConstellationMsg;
use compositing::compositor_thread::InitialCompositorState;
use compositing::windowing::WindowEvent;
use compositing::windowing::WindowMethods;
@@ -79,6 +78,7 @@ use profile::mem as profile_mem;
use profile::time as profile_time;
use profile_traits::mem;
use profile_traits::time;
+use script_traits::ConstellationMsg;
use std::rc::Rc;
use std::sync::mpsc::Sender;
use util::resource_files::resources_dir_path;
diff --git a/components/style/Cargo.toml b/components/style/Cargo.toml
index 5198dc05b14..566506e987e 100644
--- a/components/style/Cargo.toml
+++ b/components/style/Cargo.toml
@@ -11,7 +11,7 @@ name = "style"
path = "lib.rs"
[features]
-gecko = []
+gecko = ["gecko_bindings"]
[dependencies]
app_units = {version = "0.2.3", features = ["plugins"]}
@@ -20,6 +20,7 @@ cssparser = {version = "0.5.5", features = ["heap_size", "serde-serialization"]}
encoding = "0.2"
euclid = {version = "0.6.4", features = ["plugins"]}
fnv = "1.0"
+gecko_bindings = {path = "../../ports/geckolib/gecko_bindings", optional = true}
heapsize = "0.3.0"
heapsize_plugin = "0.1.2"
lazy_static = "0.2"
diff --git a/components/style/attr.rs b/components/style/attr.rs
index 8bb307040ea..0ba247e101f 100644
--- a/components/style/attr.rs
+++ b/components/style/attr.rs
@@ -11,7 +11,7 @@ use std::str::FromStr;
use string_cache::{Atom, Namespace};
use url::Url;
use util::str::{LengthOrPercentageOrAuto, HTML_SPACE_CHARACTERS};
-use util::str::{read_exponent, read_fraction, read_numbers, split_html_space_chars};
+use util::str::{read_exponent, read_fraction, read_numbers, split_commas, split_html_space_chars};
use values::specified::{Length};
// Duplicated from script::dom::values.
@@ -124,6 +124,15 @@ impl AttrValue {
AttrValue::TokenList(tokens, atoms)
}
+ pub fn from_comma_separated_tokenlist(tokens: String) -> AttrValue {
+ let atoms = split_commas(&tokens).map(Atom::from)
+ .fold(vec![], |mut acc, atom| {
+ if !acc.contains(&atom) { acc.push(atom) }
+ acc
+ });
+ AttrValue::TokenList(tokens, atoms)
+ }
+
#[cfg(not(feature = "gecko"))] // Gecko can't borrow atoms as UTF-8.
pub fn from_atomic_tokens(atoms: Vec<Atom>) -> AttrValue {
use util::str::str_join;
@@ -151,12 +160,12 @@ impl AttrValue {
// https://html.spec.whatwg.org/multipage/#reflecting-content-attributes-in-idl-attributes:idl-double
pub fn from_double(string: String, default: f64) -> AttrValue {
let result = parse_double(&string).unwrap_or(default);
- let result = if result.is_infinite() {
- default
+
+ if result.is_normal() {
+ AttrValue::Double(string, result)
} else {
- result
- };
- AttrValue::Double(string, result)
+ AttrValue::Double(string, default)
+ }
}
// https://html.spec.whatwg.org/multipage/#limited-to-only-non-negative-numbers
diff --git a/components/style/lib.rs b/components/style/lib.rs
index 00d5d079066..4ec45e45e04 100644
--- a/components/style/lib.rs
+++ b/components/style/lib.rs
@@ -28,6 +28,8 @@ extern crate cssparser;
extern crate encoding;
extern crate euclid;
extern crate fnv;
+#[cfg(feature = "gecko")]
+extern crate gecko_bindings;
extern crate heapsize;
#[allow(unused_extern_crates)]
#[macro_use]
diff --git a/components/style/parser.rs b/components/style/parser.rs
index b044367e8dd..eadb778db55 100644
--- a/components/style/parser.rs
+++ b/components/style/parser.rs
@@ -5,20 +5,47 @@
use cssparser::{Parser, SourcePosition};
use error_reporting::ParseErrorReporter;
+#[cfg(feature = "gecko")]
+use gecko_bindings::ptr::{GeckoArcPrincipal, GeckoArcURI};
use selectors::parser::ParserContext as SelectorParserContext;
use stylesheets::Origin;
use url::Url;
+#[cfg(not(feature = "gecko"))]
+pub struct ParserContextExtraData;
+
+#[cfg(feature = "gecko")]
+pub struct ParserContextExtraData {
+ pub base: Option<GeckoArcURI>,
+ pub referrer: Option<GeckoArcURI>,
+ pub principal: Option<GeckoArcPrincipal>,
+}
+
+impl ParserContextExtraData {
+ #[cfg(not(feature = "gecko"))]
+ pub fn default() -> ParserContextExtraData {
+ ParserContextExtraData
+ }
+
+ #[cfg(feature = "gecko")]
+ pub fn default() -> ParserContextExtraData {
+ ParserContextExtraData { base: None, referrer: None, principal: None }
+ }
+}
+
pub struct ParserContext<'a> {
pub stylesheet_origin: Origin,
pub base_url: &'a Url,
pub selector_context: SelectorParserContext,
pub error_reporter: Box<ParseErrorReporter + Send>,
+ pub extra_data: ParserContextExtraData,
}
impl<'a> ParserContext<'a> {
- pub fn new(stylesheet_origin: Origin, base_url: &'a Url, error_reporter: Box<ParseErrorReporter + Send>)
- -> ParserContext<'a> {
+ pub fn new_with_extra_data(stylesheet_origin: Origin, base_url: &'a Url,
+ error_reporter: Box<ParseErrorReporter + Send>,
+ extra_data: ParserContextExtraData)
+ -> ParserContext<'a> {
let mut selector_context = SelectorParserContext::new();
selector_context.in_user_agent_stylesheet = stylesheet_origin == Origin::UserAgent;
ParserContext {
@@ -26,8 +53,15 @@ impl<'a> ParserContext<'a> {
base_url: base_url,
selector_context: selector_context,
error_reporter: error_reporter,
+ extra_data: extra_data,
}
}
+
+ pub fn new(stylesheet_origin: Origin, base_url: &'a Url, error_reporter: Box<ParseErrorReporter + Send>)
+ -> ParserContext<'a> {
+ let extra_data = ParserContextExtraData::default();
+ ParserContext::new_with_extra_data(stylesheet_origin, base_url, error_reporter, extra_data)
+ }
}
diff --git a/components/style/properties/helpers.mako.rs b/components/style/properties/helpers.mako.rs
index af052179d2c..86961c89192 100644
--- a/components/style/properties/helpers.mako.rs
+++ b/components/style/properties/helpers.mako.rs
@@ -43,7 +43,7 @@
#![allow(unused_imports)]
% if not property.derived_from:
use cssparser::Parser;
- use parser::ParserContext;
+ use parser::{ParserContext, ParserContextExtraData};
use properties::{CSSWideKeyword, DeclaredValue, Shorthand};
% endif
use error_reporting::ParseErrorReporter;
diff --git a/components/style/properties/longhand/box.mako.rs b/components/style/properties/longhand/box.mako.rs
index 6fd36b71a4d..f80a42c88d2 100644
--- a/components/style/properties/longhand/box.mako.rs
+++ b/components/style/properties/longhand/box.mako.rs
@@ -851,3 +851,78 @@ ${helpers.single_keyword("-moz-appearance",
gecko_ffi_name="mAppearance",
gecko_constant_prefix="NS_THEME",
products="gecko")}
+
+// Non-standard: https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-binding
+<%helpers:longhand name="-moz-binding" products="gecko">
+ use cssparser::{CssStringWriter, ToCss};
+ use gecko_bindings::ptr::{GeckoArcPrincipal, GeckoArcURI};
+ use std::fmt::{self, Write};
+ use url::Url;
+ use values::computed::ComputedValueAsSpecified;
+
+ #[derive(PartialEq, Clone, Debug, HeapSizeOf)]
+ pub struct UrlExtraData {
+ pub base: GeckoArcURI,
+ pub referrer: GeckoArcURI,
+ pub principal: GeckoArcPrincipal,
+ }
+
+ #[derive(PartialEq, Clone, Debug, HeapSizeOf)]
+ pub enum SpecifiedValue {
+ Url(Url, UrlExtraData),
+ None,
+ }
+
+ impl ComputedValueAsSpecified for SpecifiedValue {}
+
+ impl ToCss for SpecifiedValue {
+ fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
+ use values::LocalToCss;
+ match *self {
+ SpecifiedValue::Url(ref url, _) => {
+ url.to_css(dest)
+ }
+ SpecifiedValue::None => {
+ try!(dest.write_str("none"));
+ Ok(())
+ }
+ }
+ }
+ }
+
+ pub mod computed_value {
+ pub type T = super::SpecifiedValue;
+ }
+
+ #[inline] pub fn get_initial_value() -> SpecifiedValue {
+ SpecifiedValue::None
+ }
+
+ pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
+ if input.try(|input| input.expect_ident_matching("none")).is_ok() {
+ return Ok(SpecifiedValue::None);
+ }
+
+ let url = context.parse_url(&*try!(input.expect_url()));
+ match context.extra_data {
+ ParserContextExtraData {
+ base: Some(ref base),
+ referrer: Some(ref referrer),
+ principal: Some(ref principal),
+ } => {
+ let extra_data = UrlExtraData {
+ base: base.clone(),
+ referrer: referrer.clone(),
+ principal: principal.clone(),
+ };
+ Ok(SpecifiedValue::Url(url, extra_data))
+ },
+ _ => {
+ // FIXME(heycam) should ensure we always have a principal, etc., when parsing
+ // style attributes and re-parsing due to CSS Variables.
+ println!("stylo: skipping -moz-binding declaration without ParserContextExtraData");
+ Err(())
+ },
+ }
+ }
+</%helpers:longhand>
diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs
index dc15f7339d0..ec6fe6562e0 100644
--- a/components/style/properties/properties.mako.rs
+++ b/components/style/properties/properties.mako.rs
@@ -29,7 +29,7 @@ use euclid::size::Size2D;
use string_cache::Atom;
use computed_values;
use logical_geometry::{LogicalMargin, PhysicalSide, WritingMode};
-use parser::{ParserContext, log_css_error};
+use parser::{ParserContext, ParserContextExtraData, log_css_error};
use selectors::matching::DeclarationBlock;
use stylesheets::Origin;
use values::AuExtensionMethods;
@@ -185,13 +185,18 @@ mod property_bit_field {
if let DeclaredValue::WithVariables {
ref css, first_token_type, ref base_url, from_shorthand
} = *value {
+ // FIXME(heycam): A ParserContextExtraData should be built from data
+ // stored in the WithVariables, in case variable expansion results in
+ // a url() value.
+ let extra_data = ParserContextExtraData::default();
substitute_variables_${property.ident}_slow(css,
first_token_type,
base_url,
from_shorthand,
custom_properties,
f,
- error_reporter);
+ error_reporter,
+ extra_data);
} else {
f(value);
}
@@ -206,7 +211,8 @@ mod property_bit_field {
from_shorthand: Option<Shorthand>,
custom_properties: &Option<Arc<::custom_properties::ComputedValuesMap>>,
f: F,
- error_reporter: &mut StdBox<ParseErrorReporter + Send>)
+ error_reporter: &mut StdBox<ParseErrorReporter + Send>,
+ extra_data: ParserContextExtraData)
where F: FnOnce(&DeclaredValue<longhands::${property.ident}::SpecifiedValue>) {
f(&
::custom_properties::substitute(css, first_token_type, custom_properties)
@@ -215,8 +221,9 @@ mod property_bit_field {
//
// FIXME(pcwalton): Cloning the error reporter is slow! But so are custom
// properties, so whatever...
- let context = ParserContext::new(
- ::stylesheets::Origin::Author, base_url, (*error_reporter).clone());
+ let context = ParserContext::new_with_extra_data(
+ ::stylesheets::Origin::Author, base_url, (*error_reporter).clone(),
+ extra_data);
Parser::new(&css).parse_entirely(|input| {
match from_shorthand {
None => {
@@ -256,15 +263,17 @@ pub struct PropertyDeclarationBlock {
pub normal: Arc<Vec<PropertyDeclaration>>,
}
-pub fn parse_style_attribute(input: &str, base_url: &Url, error_reporter: StdBox<ParseErrorReporter + Send>)
+pub fn parse_style_attribute(input: &str, base_url: &Url, error_reporter: StdBox<ParseErrorReporter + Send>,
+ extra_data: ParserContextExtraData)
-> PropertyDeclarationBlock {
- let context = ParserContext::new(Origin::Author, base_url, error_reporter);
+ let context = ParserContext::new_with_extra_data(Origin::Author, base_url, error_reporter, extra_data);
parse_property_declaration_list(&context, &mut Parser::new(input))
}
-pub fn parse_one_declaration(name: &str, input: &str, base_url: &Url, error_reporter: StdBox<ParseErrorReporter + Send>)
+pub fn parse_one_declaration(name: &str, input: &str, base_url: &Url, error_reporter: StdBox<ParseErrorReporter + Send>,
+ extra_data: ParserContextExtraData)
-> Result<Vec<PropertyDeclaration>, ()> {
- let context = ParserContext::new(Origin::Author, base_url, error_reporter);
+ let context = ParserContext::new_with_extra_data(Origin::Author, base_url, error_reporter, extra_data);
let mut results = vec![];
match PropertyDeclaration::parse(name, &context, &mut Parser::new(input), &mut results) {
PropertyDeclarationParseResult::ValidOrIgnoredDeclaration => Ok(results),
diff --git a/components/style/selector_matching.rs b/components/style/selector_matching.rs
index c1989348f50..017a7443624 100644
--- a/components/style/selector_matching.rs
+++ b/components/style/selector_matching.rs
@@ -9,6 +9,7 @@ use dom::PresentationalHintsSynthetizer;
use element_state::*;
use error_reporting::StdoutErrorReporter;
use media_queries::{Device, MediaType};
+use parser::ParserContextExtraData;
use properties::{self, PropertyDeclaration, PropertyDeclarationBlock};
use restyle_hints::{ElementSnapshot, RestyleHint, DependencySet};
use selector_impl::{SelectorImplExt, ServoSelectorImpl};
@@ -46,7 +47,8 @@ lazy_static! {
None,
None,
Origin::UserAgent,
- box StdoutErrorReporter);
+ box StdoutErrorReporter,
+ ParserContextExtraData::default());
stylesheets.push(ua_stylesheet);
}
Err(..) => {
@@ -57,7 +59,8 @@ lazy_static! {
}
for &(ref contents, ref url) in &opts::get().user_stylesheets {
stylesheets.push(Stylesheet::from_bytes(
- &contents, url.clone(), None, None, Origin::User, box StdoutErrorReporter));
+ &contents, url.clone(), None, None, Origin::User, box StdoutErrorReporter,
+ ParserContextExtraData::default()));
}
stylesheets
};
@@ -73,7 +76,8 @@ lazy_static! {
None,
None,
Origin::UserAgent,
- box StdoutErrorReporter)
+ box StdoutErrorReporter,
+ ParserContextExtraData::default())
},
Err(..) => {
error!("Stylist failed to load 'quirks-mode.css'!");
diff --git a/components/style/stylesheets.rs b/components/style/stylesheets.rs
index 7a978263b2b..4de57e81d40 100644
--- a/components/style/stylesheets.rs
+++ b/components/style/stylesheets.rs
@@ -8,7 +8,7 @@ use encoding::EncodingRef;
use error_reporting::ParseErrorReporter;
use font_face::{FontFaceRule, parse_font_face_block};
use media_queries::{Device, MediaQueryList, parse_media_query_list};
-use parser::{ParserContext, log_css_error};
+use parser::{ParserContext, ParserContextExtraData, log_css_error};
use properties::{PropertyDeclarationBlock, parse_property_declaration_list};
use selectors::parser::{Selector, SelectorImpl, parse_selector_list};
use smallvec::SmallVec;
@@ -83,32 +83,37 @@ impl<Impl: SelectorImpl> Stylesheet<Impl> {
pub fn from_bytes_iter<I: Iterator<Item=Vec<u8>>>(
input: I, base_url: Url, protocol_encoding_label: Option<&str>,
environment_encoding: Option<EncodingRef>, origin: Origin,
- error_reporter: Box<ParseErrorReporter + Send>) -> Stylesheet<Impl> {
+ error_reporter: Box<ParseErrorReporter + Send>,
+ extra_data: ParserContextExtraData) -> Stylesheet<Impl> {
let mut bytes = vec![];
// TODO: incremental decoding and tokenization/parsing
for chunk in input {
bytes.extend_from_slice(&chunk)
}
Stylesheet::from_bytes(&bytes, base_url, protocol_encoding_label,
- environment_encoding, origin, error_reporter)
+ environment_encoding, origin, error_reporter,
+ extra_data)
}
pub fn from_bytes(bytes: &[u8],
base_url: Url,
protocol_encoding_label: Option<&str>,
environment_encoding: Option<EncodingRef>,
- origin: Origin, error_reporter: Box<ParseErrorReporter + Send>)
+ origin: Origin, error_reporter: Box<ParseErrorReporter + Send>,
+ extra_data: ParserContextExtraData)
-> Stylesheet<Impl> {
// TODO: bytes.as_slice could be bytes.container_as_bytes()
let (string, _) = decode_stylesheet_bytes(
bytes, protocol_encoding_label, environment_encoding);
- Stylesheet::from_str(&string, base_url, origin, error_reporter)
+ Stylesheet::from_str(&string, base_url, origin, error_reporter, extra_data)
}
pub fn from_str(css: &str, base_url: Url, origin: Origin,
- error_reporter: Box<ParseErrorReporter + Send>) -> Stylesheet<Impl> {
+ error_reporter: Box<ParseErrorReporter + Send>,
+ extra_data: ParserContextExtraData) -> Stylesheet<Impl> {
let rule_parser = TopLevelRuleParser {
- context: ParserContext::new(origin, &base_url, error_reporter.clone()),
+ context: ParserContext::new_with_extra_data(origin, &base_url, error_reporter.clone(),
+ extra_data),
state: Cell::new(State::Start),
_impl: PhantomData,
};
diff --git a/components/style/values.rs b/components/style/values.rs
index 2f295bd8775..9492a028cfc 100644
--- a/components/style/values.rs
+++ b/components/style/values.rs
@@ -90,13 +90,13 @@ pub const FONT_MEDIUM_PX: i32 = 16;
pub mod specified {
use app_units::Au;
- use cssparser::{self, CssStringWriter, Parser, ToCss, Token};
+ use cssparser::{self, Parser, ToCss, Token};
use euclid::size::Size2D;
use parser::ParserContext;
use std::ascii::AsciiExt;
use std::cmp;
use std::f32::consts::PI;
- use std::fmt::{self, Write};
+ use std::fmt;
use std::ops::Mul;
use style_traits::values::specified::AllowedNumericType;
use super::AuExtensionMethods;
@@ -1224,12 +1224,10 @@ pub mod specified {
impl ToCss for Image {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
+ use values::LocalToCss;
match *self {
Image::Url(ref url) => {
- try!(dest.write_str("url(\""));
- try!(write!(&mut CssStringWriter::new(dest), "{}", url));
- try!(dest.write_str("\")"));
- Ok(())
+ url.to_css(dest)
}
Image::LinearGradient(ref gradient) => gradient.to_css(dest)
}
diff --git a/components/util/str.rs b/components/util/str.rs
index fe23c1b5ff6..7af63f4c7f3 100644
--- a/components/util/str.rs
+++ b/components/util/str.rs
@@ -41,6 +41,10 @@ pub fn split_html_space_chars<'a>(s: &'a str) ->
s.split(HTML_SPACE_CHARACTERS).filter(not_empty as fn(&&str) -> bool)
}
+pub fn split_commas<'a>(s: &'a str) -> Filter<Split<'a, char>, fn(&&str) -> bool> {
+ fn not_empty(&split: &&str) -> bool { !split.is_empty() }
+ s.split(',').filter(not_empty as fn(&&str) -> bool)
+}
fn is_ascii_digit(c: &char) -> bool {
match *c {
diff --git a/components/webdriver_server/Cargo.toml b/components/webdriver_server/Cargo.toml
index de365ebdae3..d2e22b98b1a 100644
--- a/components/webdriver_server/Cargo.toml
+++ b/components/webdriver_server/Cargo.toml
@@ -9,7 +9,6 @@ name = "webdriver_server"
path = "lib.rs"
[dependencies]
-compositing = {path = "../compositing"}
msg = {path = "../msg"}
plugins = {path = "../plugins"}
util = {path = "../util"}
@@ -20,6 +19,7 @@ log = "0.3.5"
hyper = "0.9"
rustc-serialize = "0.3.4"
regex = "0.1.55"
+script_traits = {path = "../script_traits"}
url = {version = "1.0.0", features = ["heap_size"]}
uuid = { version = "0.2", features = ["v4"] }
webdriver = "0.9"
diff --git a/components/webdriver_server/lib.rs b/components/webdriver_server/lib.rs
index 92c339fb7d5..83771a1b070 100644
--- a/components/webdriver_server/lib.rs
+++ b/components/webdriver_server/lib.rs
@@ -10,7 +10,6 @@
#![deny(unsafe_code)]
-extern crate compositing;
extern crate euclid;
extern crate hyper;
extern crate image;
@@ -18,6 +17,7 @@ extern crate ipc_channel;
extern crate msg;
extern crate regex;
extern crate rustc_serialize;
+extern crate script_traits;
extern crate url;
extern crate util;
extern crate uuid;
@@ -25,7 +25,6 @@ extern crate webdriver;
mod keys;
-use compositing::CompositorMsg as ConstellationMsg;
use euclid::Size2D;
use hyper::method::Method::{self, Post};
use image::{DynamicImage, ImageFormat, RgbImage};
@@ -37,6 +36,7 @@ use msg::webdriver_msg::{LoadStatus, WebDriverFrameId, WebDriverJSError, WebDriv
use regex::Captures;
use rustc_serialize::base64::{CharacterSet, Config, Newline, ToBase64};
use rustc_serialize::json::{Json, ToJson};
+use script_traits::ConstellationMsg;
use std::borrow::ToOwned;
use std::collections::BTreeMap;
use std::net::{SocketAddr, SocketAddrV4};