diff options
Diffstat (limited to 'components')
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}; |