--- a/dom/xbl/nsXBLBinding.cpp
+++ b/dom/xbl/nsXBLBinding.cpp
@@ -866,16 +866,22 @@ nsXBLBinding::WalkRules(nsIStyleRuleProc
if (mNextBinding)
mNextBinding->WalkRules(aFunc, aData);
nsIStyleRuleProcessor *rules = mPrototypeBinding->GetRuleProcessor();
if (rules)
(*aFunc)(rules, aData);
}
+RawServoStyleSet*
+nsXBLBinding::GetRawServoStyleSet()
+{
+ return mPrototypeBinding->GetRawServoStyleSet();
+}
+
// Internal helper methods ////////////////////////////////////////////////////////////////
// Get or create a WeakMap object on a given XBL-hosting global.
//
// The scheme is as follows. XBL-hosting globals (either privileged content
// Windows or XBL scopes) get two lazily-defined WeakMap properties. Each
// WeakMap is keyed by the grand-proto - i.e. the original prototype of the
// content before it was bound, and the prototype of the class object that we
--- a/dom/xbl/nsXBLBinding.h
+++ b/dom/xbl/nsXBLBinding.h
@@ -2,16 +2,17 @@
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsXBLBinding_h_
#define nsXBLBinding_h_
+#include "mozilla/ServoBindings.h"
#include "nsXBLService.h"
#include "nsCOMPtr.h"
#include "nsINodeList.h"
#include "nsIStyleRuleProcessor.h"
#include "nsClassHashtable.h"
#include "nsTArray.h"
#include "nsCycleCollectionParticipant.h"
#include "nsISupportsImpl.h"
@@ -124,16 +125,18 @@ public:
void AttributeChanged(nsIAtom* aAttribute, int32_t aNameSpaceID,
bool aRemoveFlag, bool aNotify);
void ChangeDocument(nsIDocument* aOldDocument, nsIDocument* aNewDocument);
void WalkRules(nsIStyleRuleProcessor::EnumFunc aFunc, void* aData);
+ RawServoStyleSet* GetRawServoStyleSet();
+
static nsresult DoInitJSClass(JSContext *cx, JS::Handle<JSObject*> obj,
const nsAFlatString& aClassName,
nsXBLPrototypeBinding* aProtoBinding,
JS::MutableHandle<JSObject*> aClassObject,
bool* aNew);
bool AllowScripts();
--- a/dom/xbl/nsXBLPrototypeBinding.cpp
+++ b/dom/xbl/nsXBLPrototypeBinding.cpp
@@ -564,16 +564,22 @@ nsXBLPrototypeBinding::GetRuleProcessor(
{
if (mResources) {
return mResources->GetRuleProcessor();
}
return nullptr;
}
+RawServoStyleSet*
+nsXBLPrototypeBinding::GetRawServoStyleSet() const
+{
+ return mResources ? mResources->GetRawServoStyleSet() : nullptr;
+}
+
void
nsXBLPrototypeBinding::EnsureAttributeTable()
{
if (!mAttributeTable) {
mAttributeTable =
new nsClassHashtable<nsUint32HashKey, InnerAttributeTable>(2);
}
}
--- a/dom/xbl/nsXBLPrototypeBinding.h
+++ b/dom/xbl/nsXBLPrototypeBinding.h
@@ -124,16 +124,17 @@ public:
void RemoveStyleSheet(mozilla::StyleSheet* aSheet);
void InsertStyleSheetAt(size_t aIndex, mozilla::StyleSheet* aSheet);
mozilla::StyleSheet* StyleSheetAt(size_t aIndex) const;
size_t SheetCount() const;
bool HasStyleSheets() const;
void AppendStyleSheetsTo(nsTArray<mozilla::StyleSheet*>& aResult) const;
nsIStyleRuleProcessor* GetRuleProcessor();
+ RawServoStyleSet* GetRawServoStyleSet() const;
nsresult FlushSkinSheets();
nsIAtom* GetBaseTag(int32_t* aNamespaceID);
void SetBaseTag(int32_t aNamespaceID, nsIAtom* aTag);
bool ImplementsInterface(REFNSIID aIID) const;
--- a/dom/xbl/nsXBLPrototypeResources.cpp
+++ b/dom/xbl/nsXBLPrototypeResources.cpp
@@ -14,16 +14,18 @@
#include "nsIDocumentObserver.h"
#include "mozilla/css/Loader.h"
#include "nsIURI.h"
#include "nsLayoutCID.h"
#include "nsCSSRuleProcessor.h"
#include "nsStyleSet.h"
#include "mozilla/dom/URL.h"
#include "mozilla/DebugOnly.h"
+#include "mozilla/ServoBindings.h"
+#include "mozilla/ServoBindingTypes.h"
#include "mozilla/StyleSheet.h"
#include "mozilla/StyleSheetInlines.h"
using namespace mozilla;
using mozilla::dom::IsChromeURI;
nsXBLPrototypeResources::nsXBLPrototypeResources(nsXBLPrototypeBinding* aBinding)
{
@@ -157,16 +159,28 @@ nsXBLPrototypeResources::GatherRuleProce
}
mRuleProcessor = new nsCSSRuleProcessor(Move(sheets),
SheetType::Doc,
nullptr,
mRuleProcessor);
}
void
+nsXBLPrototypeResources::ComputeRawServoStyleSet(nsPresContext* aPresContext)
+{
+ static uint32_t uniqueIDCounter = 0;
+ mRawSet.reset(Servo_StyleSet_Init(aPresContext));
+ for (StyleSheet* sheet : mStyleSheetList) {
+ const RawServoStyleSheet* rawSheet = sheet->AsServo()->RawSheet();
+ Servo_StyleSet_AppendStyleSheet(mRawSet.get(), rawSheet, uniqueIDCounter++);
+ }
+ Servo_StyleSet_FlushStyleSheets(mRawSet.get());
+}
+
+void
nsXBLPrototypeResources::AppendStyleSheet(StyleSheet* aSheet)
{
mStyleSheetList.AppendElement(aSheet);
}
void
nsXBLPrototypeResources::RemoveStyleSheet(StyleSheet* aSheet)
{
--- a/dom/xbl/nsXBLPrototypeResources.h
+++ b/dom/xbl/nsXBLPrototypeResources.h
@@ -2,16 +2,17 @@
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef nsXBLPrototypeResources_h__
#define nsXBLPrototypeResources_h__
+#include "mozilla/ServoBindings.h"
#include "mozilla/StyleSheet.h"
#include "nsICSSLoaderObserver.h"
class nsCSSRuleProcessor;
class nsIAtom;
class nsIContent;
class nsXBLPrototypeBinding;
class nsXBLResourceLoader;
@@ -53,20 +54,26 @@ public:
* Recreates mRuleProcessor to represent the current list of style sheets
* stored in mStyleSheetList. (Named GatherRuleProcessor to parallel
* nsStyleSet::GatherRuleProcessors.)
*/
void GatherRuleProcessor();
nsCSSRuleProcessor* GetRuleProcessor() const { return mRuleProcessor; }
+ RawServoStyleSet* GetRawServoStyleSet() const { return mRawSet.get(); }
+
+ void ComputeRawServoStyleSet(nsPresContext* aPresContext);
+
private:
// A loader object. Exists only long enough to load resources, and then it dies.
RefPtr<nsXBLResourceLoader> mLoader;
// A list of loaded stylesheets for this binding.
nsTArray<RefPtr<mozilla::StyleSheet>> mStyleSheetList;
// The list of stylesheets converted to a rule processor.
RefPtr<nsCSSRuleProcessor> mRuleProcessor;
+
+ mozilla::UniquePtr<RawServoStyleSet> mRawSet;
};
#endif
--- a/dom/xbl/nsXBLResourceLoader.cpp
+++ b/dom/xbl/nsXBLResourceLoader.cpp
@@ -109,17 +109,17 @@ nsXBLResourceLoader::LoadResources(nsICo
if (NS_FAILED(NS_NewURI(getter_AddRefs(url), curr->mSrc,
doc->GetDocumentCharacterSet().get(), docURL)))
continue;
if (curr->mType == nsGkAtoms::image) {
// Now kick off the image load...
// Passing nullptr for pretty much everything -- cause we don't care!
- // XXX: initialDocumentURI is nullptr!
+ // XXX: initialDocumentURI is nullptr!
RefPtr<imgRequestProxy> req;
nsContentUtils::LoadImage(url, doc, doc, docPrincipal, docURL,
doc->GetReferrerPolicy(), nullptr,
nsIRequest::LOAD_BACKGROUND, EmptyString(),
getter_AddRefs(req));
}
else if (curr->mType == nsGkAtoms::stylesheet) {
// Kick off the load of the stylesheet.
@@ -135,16 +135,23 @@ nsXBLResourceLoader::LoadResources(nsICo
nsIScriptSecurityManager::ALLOW_CHROME);
if (NS_SUCCEEDED(rv)) {
RefPtr<StyleSheet> sheet;
rv = cssLoader->LoadSheetSync(url, &sheet);
NS_ASSERTION(NS_SUCCEEDED(rv), "Load failed!!!");
if (NS_SUCCEEDED(rv))
{
rv = StyleSheetLoaded(sheet, false, NS_OK);
+
+ // XXX: How about those style sheets loaded asynchronously?
+ if (boundDoc->IsStyledByServo()) {
+ mResources->ComputeRawServoStyleSet(
+ boundDoc->GetShell()->GetPresContext());
+ }
+
NS_ASSERTION(NS_SUCCEEDED(rv), "Processing the style sheet failed!!!");
}
}
}
else
{
rv = cssLoader->LoadSheet(url, false, docPrincipal, EmptyCString(), this);
if (NS_SUCCEEDED(rv))
@@ -167,47 +174,49 @@ NS_IMETHODIMP
nsXBLResourceLoader::StyleSheetLoaded(StyleSheet* aSheet,
bool aWasAlternate,
nsresult aStatus)
{
if (!mResources) {
// Our resources got destroyed -- just bail out
return NS_OK;
}
-
+
mResources->AppendStyleSheet(aSheet);
if (!mInLoadResourcesFunc)
mPendingSheets--;
-
+
if (mPendingSheets == 0) {
- // All stylesheets are loaded.
- mResources->GatherRuleProcessor();
+ // All stylesheets are loaded.
+ if (aSheet->IsGecko()) {
+ mResources->GatherRuleProcessor();
+ }
// XXX Check for mPendingScripts when scripts also come online.
if (!mInLoadResourcesFunc)
NotifyBoundElements();
}
return NS_OK;
}
-void
+void
nsXBLResourceLoader::AddResource(nsIAtom* aResourceType, const nsAString& aSrc)
{
nsXBLResource* res = new nsXBLResource(aResourceType, aSrc);
if (!mResourceList)
mResourceList = res;
else
mLastResource->mNext = res;
mLastResource = res;
}
void
-nsXBLResourceLoader::AddResourceListener(nsIContent* aBoundElement)
+nsXBLResourceLoader::AddResourceListener(nsIContent* aBoundElement)
{
if (aBoundElement) {
mBoundElements.AppendObject(aBoundElement);
}
}
void
nsXBLResourceLoader::NotifyBoundElements()
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -5781,26 +5781,34 @@ nsCSSFrameConstructor::AddFrameConstruct
return;
if (newPendingBinding->mBinding) {
pendingBinding = newPendingBinding;
// aState takes over owning newPendingBinding
aState.AddPendingBinding(newPendingBinding.forget());
}
- if (aContent->IsStyledByServo()) {
- NS_WARNING("stylo: Skipping Unsupported binding re-resolve. This needs fixing.");
- resolveStyle = false;
- }
-
if (resolveStyle) {
- styleContext =
- ResolveStyleContext(styleContext->GetParent(), aContent, &aState);
- display = styleContext->StyleDisplay();
- aStyleContext = styleContext;
+ if (aContent->IsStyledByServo()) {
+ // XXX: This is a hack. We should have a better way to restyle aContent.
+ ServoRestyleManager::ClearServoDataFromSubtree(aContent->AsElement());
+ mPresShell->StyleSet()->AsServo()->StyleNewSubtree(aContent->AsElement());
+ // should_traverse_children() in traversal.rs skips the parent with
+ // moz-binding the first time. Thus call StyleNewChildren() again.
+ mPresShell->StyleSet()->AsServo()->StyleNewChildren(aContent->AsElement());
+ styleContext =
+ ResolveStyleContext(aParentFrame, aContent, &aState);
+ display = styleContext->StyleDisplay();
+ aStyleContext = styleContext;
+ } else {
+ styleContext =
+ ResolveStyleContext(styleContext->GetParent(), aContent, &aState);
+ display = styleContext->StyleDisplay();
+ aStyleContext = styleContext;
+ }
}
aTag = mDocument->BindingManager()->ResolveTag(aContent, &aNameSpaceID);
} else if (display->mBinding.ForceGet()) {
if (aContent->IsStyledByServo()) {
// Servo's should_traverse_children skips styling descendants of
// elements with a -moz-binding value. For -moz-binding URLs that can
// be resolved, we will load the binding above, which will style the
--- a/layout/style/ServoBindingTypes.h
+++ b/layout/style/ServoBindingTypes.h
@@ -36,16 +36,17 @@ using ComputedKeyframeValues = nsTArray<
} // namespace mozilla
class nsCSSValue;
struct nsFontFaceRuleContainer;
class nsIDocument;
class nsINode;
class nsPresContext;
struct nsTimingFunction;
+class nsXBLBinding;
using mozilla::dom::StyleChildrenIterator;
using mozilla::ServoElementSnapshot;
typedef nsINode RawGeckoNode;
typedef mozilla::dom::Element RawGeckoElement;
typedef nsIDocument RawGeckoDocument;
typedef nsPresContext RawGeckoPresContext;
@@ -134,16 +135,17 @@ DECL_BORROWED_REF_TYPE_FOR(RawGeckoKeyfr
DECL_BORROWED_MUT_REF_TYPE_FOR(RawGeckoComputedKeyframeValuesList)
DECL_BORROWED_REF_TYPE_FOR(RawGeckoStyleAnimationList)
DECL_BORROWED_MUT_REF_TYPE_FOR(nsTimingFunction)
DECL_BORROWED_REF_TYPE_FOR(nsTimingFunction)
DECL_BORROWED_MUT_REF_TYPE_FOR(RawGeckoFontFaceRuleList)
DECL_BORROWED_REF_TYPE_FOR(RawGeckoAnimationPropertySegment)
DECL_BORROWED_REF_TYPE_FOR(RawGeckoComputedTiming)
DECL_BORROWED_MUT_REF_TYPE_FOR(RawGeckoServoStyleRuleList)
+DECL_BORROWED_REF_TYPE_FOR(nsXBLBinding)
#undef DECL_ARC_REF_TYPE_FOR
#undef DECL_OWNED_REF_TYPE_FOR
#undef DECL_NULLABLE_OWNED_REF_TYPE_FOR
#undef DECL_BORROWED_REF_TYPE_FOR
#undef DECL_NULLABLE_BORROWED_REF_TYPE_FOR
#undef DECL_BORROWED_MUT_REF_TYPE_FOR
#undef DECL_NULLABLE_BORROWED_MUT_REF_TYPE_FOR
--- a/layout/style/ServoBindings.cpp
+++ b/layout/style/ServoBindings.cpp
@@ -1990,16 +1990,34 @@ Gecko_GetBaseSize(nsIAtom* aLanguage)
prefs.Initialize(langGroupAtom);
FontSizePrefs sizes;
sizes.CopyFrom(prefs);
return sizes;
}
+nsXBLBinding*
+Gecko_ElementGetXBLBinding(RawGeckoElementBorrowed aElement)
+{
+ return aElement->GetXBLBinding();
+}
+
+nsXBLBinding*
+Gecko_XBLBinding_GetBaseBinding(nsXBLBinding* aXBLBinding)
+{
+ return aXBLBinding->GetBaseBinding();
+}
+
+RawServoStyleSet*
+Gecko_XBLBinding_GetRawServoStyleSet(nsXBLBinding* aXBLBinding)
+{
+ return aXBLBinding ? aXBLBinding->GetRawServoStyleSet() : nullptr;
+}
+
void
InitializeServo()
{
URLExtraData::InitDummy();
Servo_Initialize(URLExtraData::Dummy());
sServoFontMetricsLock = new Mutex("Gecko_GetFontMetrics");
}
--- a/layout/style/ServoBindings.h
+++ b/layout/style/ServoBindings.h
@@ -55,16 +55,17 @@ class nsCSSCounterStyleRule;
class nsCSSFontFaceRule;
struct nsMediaFeature;
struct nsStyleList;
struct nsStyleImage;
struct nsStyleGradientStop;
class nsStyleGradient;
class nsStyleCoord;
struct nsStyleDisplay;
+class nsXBLBinding;
#define NS_DECL_THREADSAFE_FFI_REFCOUNTING(class_, name_) \
void Gecko_AddRef##name_##ArbitraryThread(class_* aPtr); \
void Gecko_Release##name_##ArbitraryThread(class_* aPtr);
#define NS_IMPL_THREADSAFE_FFI_REFCOUNTING(class_, name_) \
static_assert(class_::HasThreadSafeRefCnt::value, \
"NS_DECL_THREADSAFE_FFI_REFCOUNTING can only be used with " \
"classes that have thread-safe refcounting"); \
@@ -494,16 +495,21 @@ NS_DECL_THREADSAFE_FFI_REFCOUNTING(nsCSS
bool Gecko_PropertyId_IsPrefEnabled(nsCSSPropertyID id);
void Gecko_nsStyleFont_SetLang(nsStyleFont* font, nsIAtom* atom);
void Gecko_nsStyleFont_CopyLangFrom(nsStyleFont* aFont, const nsStyleFont* aSource);
void Gecko_nsStyleFont_FixupNoneGeneric(nsStyleFont* font,
RawGeckoPresContextBorrowed pres_context);
FontSizePrefs Gecko_GetBaseSize(nsIAtom* lang);
+nsXBLBinding* Gecko_ElementGetXBLBinding(RawGeckoElementBorrowed aElement);
+
+nsXBLBinding* Gecko_XBLBinding_GetBaseBinding(nsXBLBinding* aXBLBinding);
+RawServoStyleSet* Gecko_XBLBinding_GetRawServoStyleSet(nsXBLBinding* aXBLBinding);
+
struct GeckoFontMetrics
{
nscoord mChSize;
nscoord mXSize;
};
GeckoFontMetrics Gecko_GetFontMetrics(RawGeckoPresContextBorrowed pres_context,
bool is_vertical,
--- a/servo/components/style/build_gecko.rs
+++ b/servo/components/style/build_gecko.rs
@@ -497,16 +497,17 @@ mod bindings {
"StyleShapeSource",
"StyleTransition",
"mozilla::UniquePtr",
"mozilla::DefaultDelete",
"mozilla::Side",
"mozilla::binding_danger::AssertAndSuppressCleanupPolicy",
"mozilla::ParsingMode",
"mozilla::InheritTarget",
+ "nsXBLBinding",
];
let opaque_types = [
"std::pair__PCCP",
"std::namespace::atomic___base", "std::atomic__My_base",
"std::atomic",
"std::atomic___base",
"mozilla::gfx::.*",
"FallibleTArray",
@@ -764,16 +765,17 @@ mod bindings {
"nsresult",
"Loader",
"ServoStyleSheet",
"EffectCompositor_CascadeLevel",
"UpdateAnimationsTasks",
"ParsingMode",
"InheritTarget",
"URLMatchingFunction",
+ "nsXBLBinding",
];
struct ArrayType {
cpp_type: &'static str,
rust_type: &'static str
}
let array_types = [
ArrayType { cpp_type: "uintptr_t", rust_type: "usize" },
];
--- a/servo/components/style/dom.rs
+++ b/servo/components/style/dom.rs
@@ -16,16 +16,17 @@ use font_metrics::FontMetricsProvider;
use properties::{ComputedValues, PropertyDeclarationBlock};
#[cfg(feature = "gecko")] use properties::animated_properties::AnimationValue;
#[cfg(feature = "gecko")] use properties::animated_properties::TransitionProperty;
use rule_tree::CascadeLevel;
use selector_parser::{ElementExt, PreExistingComputedValues, PseudoElement};
use selectors::matching::ElementSelectorFlags;
use shared_lock::Locked;
use sink::Push;
+use smallvec::VecLike;
use std::fmt;
#[cfg(feature = "gecko")] use std::collections::HashMap;
use std::fmt::Debug;
use std::hash::Hash;
use std::ops::Deref;
use stylearc::Arc;
use stylist::ApplicableDeclarationBlock;
use thread_state;
@@ -545,16 +546,26 @@ pub trait TElement : Eq + PartialEq + De
let data = match self.borrow_data() {
Some(d) => d,
None => return false,
};
return data.get_restyle()
.map_or(false, |r| r.hint.has_animation_hint());
}
+ /// Returns true if the element has the xbl binding. Only gecko elements could have this.
+ fn has_xbl_binding(&self) -> bool {
+ false
+ }
+
+ /// Gets declarations_from_xbl binding from the element. Only gecko element could have this.
+ fn get_declarations_from_xbl_binding<V>(&self,
+ _: &mut V)
+ where V: Push<ApplicableDeclarationBlock> + VecLike<ApplicableDeclarationBlock> {}
+
/// Gets the current existing CSS transitions, by |property, end value| pairs in a HashMap.
#[cfg(feature = "gecko")]
fn get_css_transitions_info(&self)
-> HashMap<TransitionProperty, Arc<AnimationValue>>;
/// Does a rough (and cheap) check for whether or not transitions might need to be updated that
/// will quickly return false for the common case of no transitions specified or running. If
/// this returns false, we definitely don't need to update transitions but if it returns true
--- a/servo/components/style/gecko/wrapper.rs
+++ b/servo/components/style/gecko/wrapper.rs
@@ -18,16 +18,17 @@ use app_units::Au;
use atomic_refcell::AtomicRefCell;
use context::{QuirksMode, SharedStyleContext, UpdateAnimationsTasks};
use data::ElementData;
use dom::{self, AnimationRules, DescendantsBit, LayoutIterator, NodeInfo, TElement, TNode, UnsafeNode};
use dom::{OpaqueNode, PresentationalHintsSynthesizer};
use element_state::ElementState;
use error_reporting::RustLogReporter;
use font_metrics::{FontMetrics, FontMetricsProvider, FontMetricsQueryResult};
+use gecko::data::PerDocumentStyleData;
use gecko::global_style_data::GLOBAL_STYLE_DATA;
use gecko::selector_parser::{SelectorImpl, NonTSPseudoClass, PseudoElement};
use gecko::snapshot_helpers;
use gecko_bindings::bindings;
use gecko_bindings::bindings::{Gecko_DropStyleChildrenIterator, Gecko_MaybeCreateStyleChildrenIterator};
use gecko_bindings::bindings::{Gecko_ElementState, Gecko_GetLastChild, Gecko_GetNextStyleChild};
use gecko_bindings::bindings::{Gecko_IsRootElement, Gecko_MatchesElement, Gecko_Namespace};
use gecko_bindings::bindings::{Gecko_SetNodeFlags, Gecko_UnsetNodeFlags};
@@ -49,30 +50,31 @@ use gecko_bindings::structs::{RawGeckoEl
use gecko_bindings::structs::{nsIAtom, nsIContent, nsStyleContext};
use gecko_bindings::structs::ELEMENT_HANDLED_SNAPSHOT;
use gecko_bindings::structs::ELEMENT_HAS_ANIMATION_ONLY_DIRTY_DESCENDANTS_FOR_SERVO;
use gecko_bindings::structs::ELEMENT_HAS_DIRTY_DESCENDANTS_FOR_SERVO;
use gecko_bindings::structs::ELEMENT_HAS_SNAPSHOT;
use gecko_bindings::structs::EffectCompositor_CascadeLevel as CascadeLevel;
use gecko_bindings::structs::NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE;
use gecko_bindings::structs::NODE_IS_NATIVE_ANONYMOUS;
-use gecko_bindings::sugar::ownership::HasArcFFI;
+use gecko_bindings::sugar::ownership::{HasArcFFI, HasSimpleFFI};
use logical_geometry::WritingMode;
use media_queries::Device;
use properties::{ComputedValues, parse_style_attribute};
use properties::{Importance, PropertyDeclaration, PropertyDeclarationBlock};
use properties::animated_properties::{AnimationValue, AnimationValueMap, TransitionProperty};
use properties::style_structs::Font;
use rule_tree::CascadeLevel as ServoCascadeLevel;
use selector_parser::ElementExt;
use selectors::Element;
use selectors::matching::{ElementSelectorFlags, MatchingContext, MatchingMode};
use selectors::parser::{AttrSelector, NamespaceConstraint};
use shared_lock::Locked;
use sink::Push;
+use smallvec::VecLike;
use std::cell::RefCell;
use std::collections::HashMap;
use std::fmt;
use std::hash::{Hash, Hasher};
use std::ptr;
use string_cache::{Atom, Namespace, WeakAtom, WeakNamespace};
use stylearc::Arc;
use stylesheets::UrlExtraData;
@@ -772,16 +774,63 @@ impl<'le> TElement for GeckoElement<'le>
fn has_css_animations(&self) -> bool {
self.may_have_animations() && unsafe { Gecko_ElementHasCSSAnimations(self.0) }
}
fn has_css_transitions(&self) -> bool {
self.may_have_animations() && unsafe { Gecko_ElementHasCSSTransitions(self.0) }
}
+ fn has_xbl_binding(&self) -> bool {
+ use gecko_bindings::bindings::Gecko_ElementGetXBLBinding;
+ let binding = unsafe { Gecko_ElementGetXBLBinding(self.0) };
+ !binding.is_null()
+ }
+
+ fn get_declarations_from_xbl_binding<V>(&self,
+ applicable_declarations: &mut V)
+ where V: Push<ApplicableDeclarationBlock> + VecLike<ApplicableDeclarationBlock> {
+ use gecko_bindings::bindings::Gecko_ElementGetXBLBinding;
+ use gecko_bindings::bindings::Gecko_XBLBinding_GetBaseBinding;
+ use gecko_bindings::bindings::Gecko_XBLBinding_GetRawServoStyleSet;
+
+ // XXX: Those child contents generated by XBL bindings do not have
+ // bindings themselves. Thus they'll fail to get declarations in
+ // <stylesheets>. Need to fix this.
+ if self.has_xbl_binding() {
+ let mut set_selector_flags = |_: &Self, _: ElementSelectorFlags| {};
+
+ let mut bindings = Vec::new();
+ let mut binding = unsafe { Gecko_ElementGetXBLBinding(self.0) };
+
+ // Implement nsXBLBinding::WalkRules().
+ while !binding.is_null() {
+ bindings.push(binding);
+ binding = unsafe { Gecko_XBLBinding_GetBaseBinding(binding) };
+ }
+
+ bindings.reverse();
+
+ for b in bindings {
+ unsafe {
+ let raw_data = Gecko_XBLBinding_GetRawServoStyleSet(b);
+ if !raw_data.is_null() {
+ let data = PerDocumentStyleData::from_ffi(&*raw_data).borrow();
+ data.stylist.push_applicable_declarations_xbl(self,
+ applicable_declarations,
+ &mut set_selector_flags);
+ }
+ }
+ }
+
+ // XXX: Need to implement nsBindingManager::WalkRules(), i.e.
+ // walk binding parent and cut off inheritance, etc.
+ }
+ }
+
fn get_css_transitions_info(&self)
-> HashMap<TransitionProperty, Arc<AnimationValue>> {
use gecko_bindings::bindings::Gecko_ElementTransitions_EndValueAt;
use gecko_bindings::bindings::Gecko_ElementTransitions_Length;
use gecko_bindings::bindings::Gecko_ElementTransitions_PropertyAt;
let collection_length =
unsafe { Gecko_ElementTransitions_Length(self.0) };
--- a/servo/components/style/rule_tree/mod.rs
+++ b/servo/components/style/rule_tree/mod.rs
@@ -382,16 +382,18 @@ const RULE_TREE_GC_INTERVAL: usize = 300
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub enum CascadeLevel {
/// Normal User-Agent rules.
UANormal = 0,
/// Presentational hints.
PresHints,
/// User normal rules.
UserNormal,
+ /// XBL <stylesheet> rules.
+ XBL,
/// Author normal rules.
AuthorNormal,
/// Style attribute normal rules.
StyleAttributeNormal,
/// SVG SMIL animations.
SMILOverride,
/// CSS animations and script-generated animations.
Animations,
@@ -1021,17 +1023,18 @@ impl StrongRuleNode {
}
});
match node.cascade_level() {
// Non-author rules:
CascadeLevel::UANormal |
CascadeLevel::UAImportant |
CascadeLevel::UserNormal |
- CascadeLevel::UserImportant => {
+ CascadeLevel::UserImportant |
+ CascadeLevel::XBL => {
for (id, declaration) in longhands {
if properties.contains(id) {
// This property was set by a non-author rule. Stop looking for it in
// this element's rule nodes.
properties.remove(id);
// However, if it is inherited, then it might be inherited from an
// author rule from an ancestor element's rule nodes.
--- a/servo/components/style/stylist.rs
+++ b/servo/components/style/stylist.rs
@@ -423,16 +423,17 @@ impl Stylist {
}
// Cheap `Arc` clone so that the closure below can borrow `&mut Stylist`.
let device = self.device.clone();
stylesheet.effective_rules(&device, guard, |rule| {
match *rule {
CssRule::Style(ref locked) => {
+ debug!("Found valid style rule: {:?}", *locked);
let style_rule = locked.read_with(&guard);
self.num_declarations += style_rule.block.read_with(&guard).len();
for selector in &style_rule.selectors.0 {
self.num_selectors += 1;
self.add_rule_to_map(selector, locked, stylesheet);
self.dependencies.note_selector(selector);
self.note_for_revalidation(selector);
self.note_attribute_and_state_dependencies(selector);
@@ -820,16 +821,36 @@ impl Stylist {
// during multiple layout passes, but this is totally bogus, in the
// sense that it's updated asynchronously.
//
// This should probably be an argument to `update`, and use the quirks
// mode info in the `SharedLayoutContext`.
self.quirks_mode = quirks_mode;
}
+ /// XBL
+ pub fn push_applicable_declarations_xbl<E, V, F>(&self,
+ element: &E,
+ applicable_declarations: &mut V,
+ flags_setter: &mut F)
+ where E: TElement,
+ V: Push<ApplicableDeclarationBlock> + VecLike<ApplicableDeclarationBlock>,
+ F: FnMut(&E, ElementSelectorFlags),
+ {
+ let mut matching_context =
+ MatchingContext::new(MatchingMode::Normal, None);
+
+ self.element_map.author.get_all_matching_rules(element,
+ element,
+ applicable_declarations,
+ &mut matching_context,
+ flags_setter,
+ CascadeLevel::XBL);
+ }
+
/// Returns the applicable CSS declarations for the given element.
///
/// This corresponds to `ElementRuleCollector` in WebKit.
///
/// The `StyleRelations` recorded in `MatchingContext` indicate hints about
/// which kind of rules have matched.
pub fn push_applicable_declarations<E, V, F>(
&self,
@@ -893,16 +914,18 @@ impl Stylist {
}
}
// Never share style for elements with preshints
context.relations |= AFFECTED_BY_PRESENTATIONAL_HINTS;
}
debug!("preshints: {:?}", context.relations);
}
+ element.get_declarations_from_xbl_binding(applicable_declarations);
+
// NB: the following condition, although it may look somewhat
// inaccurate, would be equivalent to something like:
//
// element.matches_user_and_author_rules() ||
// (is_implemented_pseudo &&
// rule_hash_target.matches_user_and_author_rules())
//
// Which may be more what you would probably expect.