Bug 1325878: Pass the MediaList down to Servo, making <style media> work. r?xidorn
MozReview-Commit-ID: BUCSQJs2CNI
--- a/layout/style/MediaList.h
+++ b/layout/style/MediaList.h
@@ -64,16 +64,20 @@ public:
JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) final;
nsISupports* GetParentObject() const { return nullptr; }
virtual void GetText(nsAString& aMediaText) = 0;
virtual void SetText(const nsAString& aMediaText) = 0;
virtual bool Matches(nsPresContext& aPresContext,
nsMediaQueryResultCacheKey* = nullptr) const = 0;
+#ifdef DEBUG
+ virtual bool IsServo() const = 0;
+#endif
+
void SetStyleSheet(StyleSheet* aSheet);
NS_DECL_NSIDOMMEDIALIST
// WebIDL
// XPCOM GetMediaText and SetMediaText are fine.
virtual uint32_t Length() = 0;
virtual void IndexedGetter(uint32_t aIndex, bool& aFound,
--- a/layout/style/ServoBindingList.h
+++ b/layout/style/ServoBindingList.h
@@ -24,16 +24,17 @@ SERVO_BINDING_FUNC(Servo_Element_ClearDa
// Styleset and Stylesheet management
SERVO_BINDING_FUNC(Servo_StyleSheet_Empty, RawServoStyleSheetStrong,
mozilla::css::SheetParsingMode parsing_mode)
SERVO_BINDING_FUNC(Servo_StyleSheet_FromUTF8Bytes, RawServoStyleSheetStrong,
mozilla::css::Loader* loader,
mozilla::ServoStyleSheet* gecko_stylesheet,
const nsACString* data,
mozilla::css::SheetParsingMode parsing_mode,
+ const RawServoMediaList* media_list,
RawGeckoURLExtraData* extra_data)
SERVO_BINDING_FUNC(Servo_ImportRule_GetSheet,
RawServoStyleSheetStrong,
const RawServoImportRuleBorrowed import_rule)
SERVO_BINDING_FUNC(Servo_StyleSheet_ClearAndUpdate,
void,
RawServoStyleSheetBorrowed stylesheet,
mozilla::css::Loader* loader,
--- a/layout/style/ServoMediaList.h
+++ b/layout/style/ServoMediaList.h
@@ -28,16 +28,22 @@ public:
void SetText(const nsAString& aMediaText) final;
uint32_t Length() final;
void IndexedGetter(uint32_t aIndex, bool& aFound,
nsAString& aReturn) final;
bool Matches(nsPresContext&, nsMediaQueryResultCacheKey*) const final;
+#ifdef DEBUG
+ bool IsServo() const final { return true; }
+#endif
+
+ RawServoMediaList& RawList() { return *mRawList; }
+
protected:
nsresult Delete(const nsAString& aOldMedium) final;
nsresult Append(const nsAString& aNewMedium) final;
~ServoMediaList() {}
private:
RefPtr<RawServoMediaList> mRawList;
--- a/layout/style/ServoStyleSheet.cpp
+++ b/layout/style/ServoStyleSheet.cpp
@@ -4,19 +4,21 @@
* 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/. */
#include "mozilla/ServoStyleSheet.h"
#include "mozilla/css/Rule.h"
#include "mozilla/StyleBackendType.h"
#include "mozilla/ServoBindings.h"
+#include "mozilla/ServoMediaList.h"
#include "mozilla/ServoCSSRuleList.h"
#include "mozilla/css/GroupRule.h"
#include "mozilla/dom/CSSRuleList.h"
+#include "mozilla/dom/MediaList.h"
#include "mozAutoDocUpdate.h"
using namespace mozilla::dom;
namespace mozilla {
// -------------------------------
@@ -92,25 +94,32 @@ ServoStyleSheet::HasRules() const
nsresult
ServoStyleSheet::ParseSheet(css::Loader* aLoader,
const nsAString& aInput,
nsIURI* aSheetURI,
nsIURI* aBaseURI,
nsIPrincipal* aSheetPrincipal,
uint32_t aLineNumber)
{
+ MOZ_ASSERT_IF(mMedia, mMedia->IsServo());
RefPtr<URLExtraData> extraData =
new URLExtraData(aBaseURI, aSheetURI, aSheetPrincipal);
NS_ConvertUTF16toUTF8 input(aInput);
if (!Inner()->mSheet) {
+ auto* mediaList = static_cast<ServoMediaList*>(mMedia.get());
+ RawServoMediaList* media = mediaList ? &mediaList->RawList() : nullptr;
+
Inner()->mSheet =
- Servo_StyleSheet_FromUTF8Bytes(aLoader, this, &input,
- mParsingMode, extraData).Consume();
+ Servo_StyleSheet_FromUTF8Bytes(
+ aLoader, this, &input, mParsingMode, media, extraData).Consume();
} else {
+ // TODO(emilio): Once we have proper inner cloning (which we don't right
+ // now) we should update the mediaList here too, though it's slightly
+ // tricky.
Servo_StyleSheet_ClearAndUpdate(Inner()->mSheet, aLoader,
this, &input, extraData);
}
Inner()->mURLData = extraData.forget();
return NS_OK;
}
--- a/layout/style/nsMediaList.h
+++ b/layout/style/nsMediaList.h
@@ -255,16 +255,20 @@ public:
void GetText(nsAString& aMediaText) final;
void SetText(const nsAString& aMediaText) final;
// Does this query apply to the presentation?
// If |aKey| is non-null, add cache information to it.
bool Matches(nsPresContext& aPresContext,
nsMediaQueryResultCacheKey* aKey) const final;
+#ifdef DEBUG
+ bool IsServo() const final { return false; }
+#endif
+
void AppendQuery(nsAutoPtr<nsMediaQuery>& aQuery) {
// Takes ownership of aQuery
mArray.AppendElement(aQuery.forget());
}
already_AddRefed<mozilla::dom::MediaList> Clone() final;
nsMediaQuery* MediumAt(int32_t aIndex) { return mArray[aIndex]; }
--- a/servo/components/style/media_queries.rs
+++ b/servo/components/style/media_queries.rs
@@ -29,18 +29,19 @@ pub struct MediaList {
impl ToCss for MediaList {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result
where W: fmt::Write
{
serialize_comma_separated_list(dest, &self.media_queries)
}
}
-impl Default for MediaList {
- fn default() -> MediaList {
+impl MediaList {
+ /// Create an empty MediaList.
+ pub fn empty() -> Self {
MediaList { media_queries: vec![] }
}
}
/// https://drafts.csswg.org/mediaqueries/#mq-prefix
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub enum Qualifier {
@@ -245,17 +246,17 @@ impl MediaQuery {
/// Parse a media query list from CSS.
///
/// Always returns a media query list. If any invalid media query is found, the
/// media query list is only filled with the equivalent of "not all", see:
///
/// https://drafts.csswg.org/mediaqueries/#error-handling
pub fn parse_media_query_list(input: &mut Parser) -> MediaList {
if input.is_exhausted() {
- return Default::default()
+ return MediaList::empty()
}
let mut media_queries = vec![];
loop {
match input.parse_until_before(Delimiter::Comma, MediaQuery::parse) {
Ok(mq) => {
media_queries.push(mq);
},
--- a/servo/components/style/stylesheets.rs
+++ b/servo/components/style/stylesheets.rs
@@ -717,31 +717,31 @@ impl Stylesheet {
/// Creates an empty stylesheet and parses it with a given base url, origin
/// and media.
///
/// Effectively creates a new stylesheet and forwards the hard work to
/// `Stylesheet::update_from_str`.
pub fn from_str(css: &str,
url_data: UrlExtraData,
origin: Origin,
- media: MediaList,
+ media: Arc<Locked<MediaList>>,
shared_lock: SharedRwLock,
stylesheet_loader: Option<&StylesheetLoader>,
error_reporter: &ParseErrorReporter) -> Stylesheet {
let mut namespaces = Namespaces::default();
let (rules, dirty_on_viewport_size_change) = Stylesheet::parse_rules(
css, &url_data, origin, &mut namespaces,
&shared_lock, stylesheet_loader, error_reporter,
);
Stylesheet {
origin: origin,
url_data: url_data,
namespaces: RwLock::new(namespaces),
rules: CssRules::new(rules, &shared_lock),
- media: Arc::new(shared_lock.wrap(media)),
+ media: media,
shared_lock: shared_lock,
dirty_on_viewport_size_change: AtomicBool::new(dirty_on_viewport_size_change),
disabled: AtomicBool::new(false),
}
}
/// Whether this stylesheet can be dirty on viewport size change.
pub fn dirty_on_viewport_size_change(&self) -> bool {
--- a/servo/ports/geckolib/glue.rs
+++ b/servo/ports/geckolib/glue.rs
@@ -25,17 +25,17 @@ use style::gecko::data::{PerDocumentStyl
use style::gecko::global_style_data::GLOBAL_STYLE_DATA;
use style::gecko::restyle_damage::GeckoRestyleDamage;
use style::gecko::selector_parser::{SelectorImpl, PseudoElement};
use style::gecko::traversal::RecalcStyleOnly;
use style::gecko::wrapper::GeckoElement;
use style::gecko_bindings::bindings;
use style::gecko_bindings::bindings::{RawGeckoKeyframeListBorrowed, RawGeckoKeyframeListBorrowedMut};
use style::gecko_bindings::bindings::{RawServoDeclarationBlockBorrowed, RawServoDeclarationBlockStrong};
-use style::gecko_bindings::bindings::{RawServoMediaListBorrowed, RawServoMediaListStrong};
+use style::gecko_bindings::bindings::{RawServoMediaList, RawServoMediaListBorrowed, RawServoMediaListStrong};
use style::gecko_bindings::bindings::{RawServoMediaRule, RawServoMediaRuleBorrowed};
use style::gecko_bindings::bindings::{RawServoNamespaceRule, RawServoNamespaceRuleBorrowed};
use style::gecko_bindings::bindings::{RawServoPageRule, RawServoPageRuleBorrowed};
use style::gecko_bindings::bindings::{RawServoStyleSetBorrowed, RawServoStyleSetOwned};
use style::gecko_bindings::bindings::{RawServoStyleSheetBorrowed, ServoComputedValuesBorrowed};
use style::gecko_bindings::bindings::{RawServoStyleSheetStrong, ServoComputedValuesStrong};
use style::gecko_bindings::bindings::{ServoCssRulesBorrowed, ServoCssRulesStrong};
use style::gecko_bindings::bindings::{nsACString, nsAString};
@@ -453,25 +453,27 @@ pub extern "C" fn Servo_StyleSheet_Empty
let origin = match mode {
SheetParsingMode::eAuthorSheetFeatures => Origin::Author,
SheetParsingMode::eUserSheetFeatures => Origin::User,
SheetParsingMode::eAgentSheetFeatures => Origin::UserAgent,
};
let shared_lock = global_style_data.shared_lock.clone();
Arc::new(Stylesheet::from_str(
"", unsafe { dummy_url_data() }.clone(), origin,
- Default::default(), shared_lock, None, &StdoutErrorReporter)
+ Arc::new(shared_lock.wrap(MediaList::empty())),
+ shared_lock, None, &StdoutErrorReporter)
).into_strong()
}
#[no_mangle]
pub extern "C" fn Servo_StyleSheet_FromUTF8Bytes(loader: *mut Loader,
stylesheet: *mut ServoStyleSheet,
data: *const nsACString,
mode: SheetParsingMode,
+ media_list: *mut RawServoMediaList,
extra_data: *mut URLExtraData)
-> RawServoStyleSheetStrong {
let global_style_data = &*GLOBAL_STYLE_DATA;
let input = unsafe { data.as_ref().unwrap().as_str_unchecked() };
let origin = match mode {
SheetParsingMode::eAuthorSheetFeatures => Origin::Author,
SheetParsingMode::eUserSheetFeatures => Origin::User,
@@ -487,18 +489,24 @@ pub extern "C" fn Servo_StyleSheet_FromU
// FIXME(emilio): loader.as_ref() doesn't typecheck for some reason?
let loader: Option<&StyleStylesheetLoader> = match loader {
None => None,
Some(ref s) => Some(s),
};
let shared_lock = global_style_data.shared_lock.clone();
+ let media = if media_list.is_null() {
+ Arc::new(shared_lock.wrap(MediaList::empty()))
+ } else {
+ Locked::<MediaList>::as_arc(unsafe { &&*media_list }).clone()
+ };
+
Arc::new(Stylesheet::from_str(
- input, url_data.clone(), origin, Default::default(),
+ input, url_data.clone(), origin, media,
shared_lock, loader, &StdoutErrorReporter)
).into_strong()
}
#[no_mangle]
pub extern "C" fn Servo_StyleSheet_ClearAndUpdate(stylesheet: RawServoStyleSheetBorrowed,
loader: *mut Loader,
gecko_stylesheet: *mut ServoStyleSheet,
@@ -1159,17 +1167,17 @@ pub extern "C" fn Servo_DeclarationBlock
pub extern "C" fn Servo_DeclarationBlock_RemovePropertyById(declarations: RawServoDeclarationBlockBorrowed,
property: nsCSSPropertyID) {
remove_property(declarations, get_property_id_from_nscsspropertyid!(property, ()))
}
#[no_mangle]
pub extern "C" fn Servo_MediaList_Create() -> RawServoMediaListStrong {
let global_style_data = &*GLOBAL_STYLE_DATA;
- Arc::new(global_style_data.shared_lock.wrap(MediaList::default())).into_strong()
+ Arc::new(global_style_data.shared_lock.wrap(MediaList::empty())).into_strong()
}
#[no_mangle]
pub extern "C" fn Servo_MediaList_DeepClone(list: RawServoMediaListBorrowed) -> RawServoMediaListStrong {
let global_style_data = &*GLOBAL_STYLE_DATA;
read_locked_arc(list, |list: &MediaList| {
Arc::new(global_style_data.shared_lock.wrap(list.clone()))
.into_strong()