Merge autoland to mozilla-central. r=merge a=merge

This commit is contained in:
Cosmin Sabou 2018-01-02 11:34:54 +02:00
commit 49ce665b6e
31 changed files with 758 additions and 828 deletions

View File

@ -40,20 +40,17 @@ AC_DEFUN([MOZ_ANDROID_CPU_ARCH],
[
if test "$OS_TARGET" = "Android"; then
case "${CPU_ARCH}-${MOZ_ARCH}" in
arm-armv7*)
case "${CPU_ARCH}" in
arm)
ANDROID_CPU_ARCH=armeabi-v7a
;;
arm-*)
ANDROID_CPU_ARCH=armeabi
;;
x86-*)
x86)
ANDROID_CPU_ARCH=x86
;;
mips32-*) # When target_cpu is mipsel, CPU_ARCH is mips32
mips32) # When target_cpu is mipsel, CPU_ARCH is mips32
ANDROID_CPU_ARCH=mips
;;
aarch64-*)
aarch64)
ANDROID_CPU_ARCH=arm64-v8a
;;
esac

View File

@ -42,8 +42,7 @@ if test -z "$MOZ_ARCH"; then
fi
if test "$MOZ_ARCH" = "armv6" -a "$OS_TARGET" = "Android"; then
MOZ_FPU=vfp
MOZ_FLOAT_ABI=softfp
AC_MSG_ERROR([Android/armv6 is not supported])
fi
MOZ_ARG_WITH_STRING(thumb,

View File

@ -363,6 +363,54 @@ Element::SetTabIndex(int32_t aTabIndex, mozilla::ErrorResult& aError)
SetAttr(nsGkAtoms::tabindex, value, aError);
}
void
Element::SetXBLBinding(nsXBLBinding* aBinding,
nsBindingManager* aOldBindingManager)
{
nsBindingManager* bindingManager;
if (aOldBindingManager) {
MOZ_ASSERT(!aBinding, "aOldBindingManager should only be provided "
"when removing a binding.");
bindingManager = aOldBindingManager;
} else {
bindingManager = OwnerDoc()->BindingManager();
}
// After this point, aBinding will be the most-derived binding for aContent.
// If we already have a binding for aContent, make sure to
// remove it from the attached stack. Otherwise we might end up firing its
// constructor twice (if aBinding inherits from it) or firing its constructor
// after aContent has been deleted (if aBinding is null and the content node
// dies before we process mAttachedStack).
RefPtr<nsXBLBinding> oldBinding = GetXBLBinding();
if (oldBinding) {
bindingManager->RemoveFromAttachedQueue(oldBinding);
}
if (aBinding) {
SetFlags(NODE_MAY_BE_IN_BINDING_MNGR);
nsExtendedDOMSlots* slots = ExtendedDOMSlots();
slots->mXBLBinding = aBinding;
bindingManager->AddBoundContent(this);
} else {
nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
if (slots) {
slots->mXBLBinding = nullptr;
}
bindingManager->RemoveBoundContent(this);
if (oldBinding) {
oldBinding->SetBoundElement(nullptr);
}
}
}
void
Element::SetShadowRoot(ShadowRoot* aShadowRoot)
{
nsExtendedDOMSlots* slots = ExtendedDOMSlots();
slots->mShadowRoot = aShadowRoot;
}
void
Element::Blur(mozilla::ErrorResult& aError)
{

View File

@ -266,6 +266,30 @@ public:
*/
void SetTabIndex(int32_t aTabIndex, mozilla::ErrorResult& aError);
/**
* Sets or unsets an XBL binding for this element. Setting a
* binding on an element that already has a binding will remove the
* old binding.
*
* @param aBinding The binding to bind to this content. If nullptr is
* provided as the argument, then existing binding will be
* removed.
*
* @param aOldBindingManager The old binding manager that contains
* this content if this content was adopted
* to another document.
*/
void SetXBLBinding(nsXBLBinding* aBinding,
nsBindingManager* aOldBindingManager = nullptr);
/**
* Sets the ShadowRoot binding for this element. The contents of the
* binding is rendered in place of this node's children.
*
* @param aShadowRoot The ShadowRoot to be bound to this element.
*/
void SetShadowRoot(ShadowRoot* aShadowRoot);
/**
* Make focus on this element.
*/
@ -552,13 +576,11 @@ public:
*/
inline CustomElementData* GetCustomElementData() const
{
nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
if (slots) {
return slots->mCustomElementData;
}
return nullptr;
const nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
return slots ? slots->mCustomElementData.get() : nullptr;
}
/**
* Sets the custom element data, ownership of the
* callback data is taken by this element.
@ -1295,9 +1317,11 @@ public:
// [deprecated] Shadow DOM v0
already_AddRefed<ShadowRoot> CreateShadowRoot(ErrorResult& aError);
ShadowRoot *FastGetShadowRoot() const
// FIXME(emilio): Should just shadow GetShadowRoot(), that way we get the fast
// version by default everywhere we already have an Element...
ShadowRoot* FastGetShadowRoot() const
{
nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
const nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
return slots ? slots->mShadowRoot.get() : nullptr;
}
@ -1481,9 +1505,9 @@ public:
*
* @return existing attribute map or nullptr.
*/
nsDOMAttributeMap *GetAttributeMap()
nsDOMAttributeMap* GetAttributeMap()
{
nsDOMSlots *slots = GetExistingDOMSlots();
nsDOMSlots* slots = GetExistingDOMSlots();
return slots ? slots->mAttributeMap.get() : nullptr;
}

View File

@ -710,7 +710,7 @@ nsParentNodeChildContentList::ValidateCache()
nsIHTMLCollection*
FragmentOrElement::Children()
{
FragmentOrElement::nsDOMSlots *slots = DOMSlots();
nsDOMSlots* slots = DOMSlots();
if (!slots->mChildrenList) {
slots->mChildrenList = new nsContentList(this, kNameSpaceID_Wildcard,
@ -788,8 +788,36 @@ static_assert(sizeof(nsINode::nsSlots) <= MaxDOMSlotSizeAllowed,
static_assert(sizeof(FragmentOrElement::nsDOMSlots) <= MaxDOMSlotSizeAllowed,
"DOM slots cannot be grown without consideration");
void
nsIContent::nsExtendedContentSlots::Unlink()
{
mXBLInsertionPoint = nullptr;
mContainingShadow = nullptr;
mAssignedSlot = nullptr;
}
void
nsIContent::nsExtendedContentSlots::Traverse(nsCycleCollectionTraversalCallback& aCb)
{
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(aCb, "mExtendedSlots->mContainingShadow");
aCb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIContent*, mContainingShadow));
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(aCb, "mExtendedSlots->mAssignedSlot");
aCb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIContent*, mAssignedSlot.get()));
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(aCb, "mExtendedSlots->mXBLInsertionPoint");
aCb.NoteXPCOMChild(mXBLInsertionPoint.get());
}
nsIContent::nsExtendedContentSlots::nsExtendedContentSlots()
: mBindingParent(nullptr)
{
}
nsIContent::nsExtendedContentSlots::~nsExtendedContentSlots() = default;
FragmentOrElement::nsDOMSlots::nsDOMSlots()
: nsINode::nsSlots(),
: nsIContent::nsContentSlots(),
mDataset(nullptr)
{
}
@ -802,60 +830,27 @@ FragmentOrElement::nsDOMSlots::~nsDOMSlots()
}
void
FragmentOrElement::nsDOMSlots::Traverse(nsCycleCollectionTraversalCallback &cb)
FragmentOrElement::nsDOMSlots::Traverse(nsCycleCollectionTraversalCallback& aCb)
{
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mStyle");
cb.NoteXPCOMChild(mStyle.get());
nsIContent::nsContentSlots::Traverse(aCb);
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mAttributeMap");
cb.NoteXPCOMChild(mAttributeMap.get());
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(aCb, "mSlots->mStyle");
aCb.NoteXPCOMChild(mStyle.get());
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mChildrenList");
cb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIDOMNodeList*, mChildrenList));
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(aCb, "mSlots->mAttributeMap");
aCb.NoteXPCOMChild(mAttributeMap.get());
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mClassList");
cb.NoteXPCOMChild(mClassList.get());
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(aCb, "mSlots->mChildrenList");
aCb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIDOMNodeList*, mChildrenList));
if (!mExtendedSlots) {
return;
}
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mExtendedSlots->mSMILOverrideStyle");
cb.NoteXPCOMChild(mExtendedSlots->mSMILOverrideStyle.get());
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mExtendedSlots->mControllers");
cb.NoteXPCOMChild(mExtendedSlots->mControllers);
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mExtendedSlots->mLabelsList");
cb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIDOMNodeList*,mExtendedSlots-> mLabelsList));
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mExtendedSlots->mShadowRoot");
cb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIContent*, mExtendedSlots->mShadowRoot));
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mExtendedSlots->mContainingShadow");
cb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIContent*, mExtendedSlots->mContainingShadow));
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mExtendedSlots->mAssignedSlot");
cb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIContent*, mExtendedSlots->mAssignedSlot.get()));
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mExtendedSlots->mXBLBinding");
cb.NoteNativeChild(mExtendedSlots->mXBLBinding,
NS_CYCLE_COLLECTION_PARTICIPANT(nsXBLBinding));
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mExtendedSlots->mXBLInsertionPoint");
cb.NoteXPCOMChild(mExtendedSlots->mXBLInsertionPoint.get());
if (mExtendedSlots->mCustomElementData) {
mExtendedSlots->mCustomElementData->Traverse(cb);
}
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mExtendedSlots->mFrameLoaderOrOpener");
cb.NoteXPCOMChild(mExtendedSlots->mFrameLoaderOrOpener);
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(aCb, "mSlots->mClassList");
aCb.NoteXPCOMChild(mClassList.get());
}
void
FragmentOrElement::nsDOMSlots::Unlink()
{
nsIContent::nsContentSlots::Unlink();
mStyle = nullptr;
if (mAttributeMap) {
mAttributeMap->DropReference();
@ -863,29 +858,6 @@ FragmentOrElement::nsDOMSlots::Unlink()
}
mChildrenList = nullptr;
mClassList = nullptr;
if (!mExtendedSlots) {
return;
}
mExtendedSlots->mSMILOverrideStyle = nullptr;
mExtendedSlots->mControllers = nullptr;
mExtendedSlots->mLabelsList = nullptr;
mExtendedSlots->mShadowRoot = nullptr;
mExtendedSlots->mContainingShadow = nullptr;
mExtendedSlots->mAssignedSlot = nullptr;
MOZ_ASSERT(!(mExtendedSlots->mXBLBinding));
mExtendedSlots->mXBLInsertionPoint = nullptr;
if (mExtendedSlots->mCustomElementData) {
mExtendedSlots->mCustomElementData->Unlink();
mExtendedSlots->mCustomElementData = nullptr;
}
nsCOMPtr<nsIFrameLoader> frameLoader =
do_QueryInterface(mExtendedSlots->mFrameLoaderOrOpener);
if (frameLoader) {
static_cast<nsFrameLoader*>(frameLoader.get())->Destroy();
}
mExtendedSlots->mFrameLoaderOrOpener = nullptr;
}
size_t
@ -915,10 +887,7 @@ FragmentOrElement::nsDOMSlots::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) c
return n;
}
FragmentOrElement::nsExtendedDOMSlots::nsExtendedDOMSlots()
: mBindingParent(nullptr)
{
}
FragmentOrElement::nsExtendedDOMSlots::nsExtendedDOMSlots() = default;
FragmentOrElement::nsExtendedDOMSlots::~nsExtendedDOMSlots()
{
@ -928,6 +897,58 @@ FragmentOrElement::nsExtendedDOMSlots::~nsExtendedDOMSlots()
}
}
void
FragmentOrElement::nsExtendedDOMSlots::Unlink()
{
nsIContent::nsExtendedContentSlots::Unlink();
// Don't clear mXBLBinding, it'll be done in
// BindingManager::RemovedFromDocument from FragmentOrElement::Unlink.
mSMILOverrideStyle = nullptr;
mControllers = nullptr;
mLabelsList = nullptr;
mShadowRoot = nullptr;
if (mCustomElementData) {
mCustomElementData->Unlink();
mCustomElementData = nullptr;
}
nsCOMPtr<nsIFrameLoader> frameLoader =
do_QueryInterface(mFrameLoaderOrOpener);
if (frameLoader) {
static_cast<nsFrameLoader*>(frameLoader.get())->Destroy();
}
mFrameLoaderOrOpener = nullptr;
}
void
FragmentOrElement::nsExtendedDOMSlots::Traverse(nsCycleCollectionTraversalCallback& aCb)
{
nsIContent::nsExtendedContentSlots::Traverse(aCb);
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(aCb, "mExtendedSlots->mSMILOverrideStyle");
aCb.NoteXPCOMChild(mSMILOverrideStyle.get());
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(aCb, "mExtendedSlots->mControllers");
aCb.NoteXPCOMChild(mControllers);
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(aCb, "mExtendedSlots->mLabelsList");
aCb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIDOMNodeList*, mLabelsList));
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(aCb, "mExtendedSlots->mShadowRoot");
aCb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIContent*, mShadowRoot));
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(aCb, "mExtendedSlots->mXBLBinding");
aCb.NoteNativeChild(mXBLBinding,
NS_CYCLE_COLLECTION_PARTICIPANT(nsXBLBinding));
if (mCustomElementData) {
mCustomElementData->Traverse(aCb);
}
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(aCb, "mExtendedSlots->mFrameLoaderOrOpener");
aCb.NoteXPCOMChild(mFrameLoaderOrOpener);
}
FragmentOrElement::FragmentOrElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo)
: nsIContent(aNodeInfo)
{
@ -1162,123 +1183,31 @@ FragmentOrElement::IsLink(nsIURI** aURI) const
return false;
}
nsIContent*
FragmentOrElement::GetBindingParent() const
{
nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
if (slots) {
return slots->mBindingParent;
}
return nullptr;
}
nsXBLBinding*
FragmentOrElement::DoGetXBLBinding() const
{
MOZ_ASSERT(HasFlag(NODE_MAY_BE_IN_BINDING_MNGR));
if (nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots()) {
return slots->mXBLBinding;
}
return nullptr;
const nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
return slots ? slots->mXBLBinding.get() : nullptr;
}
void
FragmentOrElement::SetXBLBinding(nsXBLBinding* aBinding,
nsBindingManager* aOldBindingManager)
nsIContent::SetAssignedSlot(HTMLSlotElement* aSlot)
{
nsBindingManager* bindingManager;
if (aOldBindingManager) {
MOZ_ASSERT(!aBinding, "aOldBindingManager should only be provided "
"when removing a binding.");
bindingManager = aOldBindingManager;
} else {
bindingManager = OwnerDoc()->BindingManager();
}
// After this point, aBinding will be the most-derived binding for aContent.
// If we already have a binding for aContent, make sure to
// remove it from the attached stack. Otherwise we might end up firing its
// constructor twice (if aBinding inherits from it) or firing its constructor
// after aContent has been deleted (if aBinding is null and the content node
// dies before we process mAttachedStack).
RefPtr<nsXBLBinding> oldBinding = GetXBLBinding();
if (oldBinding) {
bindingManager->RemoveFromAttachedQueue(oldBinding);
}
if (aBinding) {
SetFlags(NODE_MAY_BE_IN_BINDING_MNGR);
nsExtendedDOMSlots* slots = ExtendedDOMSlots();
slots->mXBLBinding = aBinding;
bindingManager->AddBoundContent(this);
} else {
nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
if (slots) {
slots->mXBLBinding = nullptr;
}
bindingManager->RemoveBoundContent(this);
if (oldBinding) {
oldBinding->SetBoundElement(nullptr);
}
}
}
nsIContent*
FragmentOrElement::GetXBLInsertionPoint() const
{
if (HasFlag(NODE_MAY_BE_IN_BINDING_MNGR)) {
nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
if (slots) {
return slots->mXBLInsertionPoint;
}
}
return nullptr;
}
ShadowRoot*
FragmentOrElement::GetContainingShadow() const
{
nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
if (slots) {
return slots->mContainingShadow;
}
return nullptr;
ExtendedContentSlots()->mAssignedSlot = aSlot;
}
void
FragmentOrElement::SetShadowRoot(ShadowRoot* aShadowRoot)
{
nsExtendedDOMSlots* slots = ExtendedDOMSlots();
slots->mShadowRoot = aShadowRoot;
}
HTMLSlotElement*
FragmentOrElement::GetAssignedSlot() const
{
nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots();
return slots ? slots->mAssignedSlot.get() : nullptr;
}
void
FragmentOrElement::SetAssignedSlot(HTMLSlotElement* aSlot)
{
nsExtendedDOMSlots* slots = ExtendedDOMSlots();
slots->mAssignedSlot = aSlot;
}
void
FragmentOrElement::SetXBLInsertionPoint(nsIContent* aContent)
nsIContent::SetXBLInsertionPoint(nsIContent* aContent)
{
nsCOMPtr<nsIContent> oldInsertionPoint = nullptr;
if (aContent) {
nsExtendedDOMSlots* slots = ExtendedDOMSlots();
nsExtendedContentSlots* slots = ExtendedContentSlots();
SetFlags(NODE_MAY_BE_IN_BINDING_MNGR);
oldInsertionPoint = slots->mXBLInsertionPoint.forget();
slots->mXBLInsertionPoint = aContent;
} else {
if (nsExtendedDOMSlots* slots = GetExistingExtendedDOMSlots()) {
if (nsExtendedContentSlots* slots = GetExistingExtendedContentSlots()) {
oldInsertionPoint = slots->mXBLInsertionPoint.forget();
slots->mXBLInsertionPoint = nullptr;
}
@ -1570,15 +1499,6 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(FragmentOrElement)
nsIDocument* doc = tmp->OwnerDoc();
doc->BindingManager()->RemovedFromDocument(tmp, doc,
nsBindingManager::eDoNotRunDtor);
// Unlink any DOM slots of interest.
{
nsDOMSlots *slots = tmp->GetExistingDOMSlots();
if (slots) {
slots->Unlink();
}
}
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(FragmentOrElement)
@ -2148,14 +2068,6 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(FragmentOrElement)
cb.NoteXPCOMChild(tmp->mAttrsAndChildren.GetSafeChildAt(i));
}
}
// Traverse any DOM slots of interest.
{
nsDOMSlots *slots = tmp->GetExistingDOMSlots();
if (slots) {
slots->Traverse(cb);
}
}
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
@ -2501,12 +2413,6 @@ FragmentOrElement::SetInnerHTMLInternal(const nsAString& aInnerHTML, ErrorResult
}
}
nsINode::nsSlots*
FragmentOrElement::CreateSlots()
{
return new nsDOMSlots();
}
void
FragmentOrElement::FireNodeRemovedForChildren()
{

View File

@ -148,16 +148,7 @@ public:
virtual void AppendTextTo(nsAString& aResult) override;
MOZ_MUST_USE
virtual bool AppendTextTo(nsAString& aResult, const mozilla::fallible_t&) override;
virtual nsIContent* GetBindingParent() const override;
virtual nsXBLBinding* DoGetXBLBinding() const override;
virtual void SetXBLBinding(nsXBLBinding* aBinding,
nsBindingManager* aOldBindingManager = nullptr) override;
virtual ShadowRoot *GetContainingShadow() const override;
virtual void SetShadowRoot(ShadowRoot* aBinding) override;
virtual mozilla::dom::HTMLSlotElement* GetAssignedSlot() const override;
virtual void SetAssignedSlot(mozilla::dom::HTMLSlotElement* aSlot) override;
virtual nsIContent *GetXBLInsertionPoint() const override;
virtual void SetXBLInsertionPoint(nsIContent* aContent) override;
virtual bool IsLink(nsIURI** aURI) const override;
virtual void DestroyContent() override;
@ -246,12 +237,14 @@ public:
* accessed through the DOM.
*/
class nsExtendedDOMSlots
class nsExtendedDOMSlots final : public nsIContent::nsExtendedContentSlots
{
public:
nsExtendedDOMSlots();
~nsExtendedDOMSlots() final;
~nsExtendedDOMSlots();
void Traverse(nsCycleCollectionTraversalCallback&) final;
void Unlink() final;
/**
* SMIL Overridde style rules (for SMIL animation of CSS properties)
@ -264,12 +257,6 @@ public:
*/
RefPtr<mozilla::DeclarationBlock> mSMILOverrideStyleDeclaration;
/**
* The nearest enclosing content node with a binding that created us.
* @see FragmentOrElement::GetBindingParent
*/
nsIContent* mBindingParent; // [Weak]
/**
* The controllers of the XUL Element.
*/
@ -285,26 +272,11 @@ public:
*/
RefPtr<ShadowRoot> mShadowRoot;
/**
* The root ShadowRoot of this element if it is in a shadow tree.
*/
RefPtr<ShadowRoot> mContainingShadow;
/**
* The assigned slot associated with this element.
*/
RefPtr<mozilla::dom::HTMLSlotElement> mAssignedSlot;
/**
* XBL binding installed on the element.
*/
RefPtr<nsXBLBinding> mXBLBinding;
/**
* XBL binding insertion point.
*/
nsCOMPtr<nsIContent> mXBLInsertionPoint;
/**
* Web components custom element data.
*/
@ -317,14 +289,14 @@ public:
};
class nsDOMSlots : public nsINode::nsSlots
class nsDOMSlots final : public nsIContent::nsContentSlots
{
public:
nsDOMSlots();
virtual ~nsDOMSlots();
~nsDOMSlots() final;
void Traverse(nsCycleCollectionTraversalCallback &cb);
void Unlink();
void Traverse(nsCycleCollectionTraversalCallback&) final;
void Unlink() final;
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
@ -356,8 +328,6 @@ public:
* An object implementing the .classList property for this element.
*/
RefPtr<nsDOMTokenList> mClassList;
mozilla::UniquePtr<nsExtendedDOMSlots> mExtendedSlots;
};
protected:
@ -365,9 +335,17 @@ protected:
void SetInnerHTMLInternal(const nsAString& aInnerHTML, ErrorResult& aError);
// Override from nsINode
virtual nsINode::nsSlots* CreateSlots() override;
nsIContent::nsContentSlots* CreateSlots() override
{
return new nsDOMSlots();
}
nsDOMSlots *DOMSlots()
nsIContent::nsExtendedContentSlots* CreateExtendedSlots() final
{
return new nsExtendedDOMSlots();
}
nsDOMSlots* DOMSlots()
{
return static_cast<nsDOMSlots*>(Slots());
}
@ -379,22 +357,18 @@ protected:
nsExtendedDOMSlots* ExtendedDOMSlots()
{
nsDOMSlots* slots = DOMSlots();
if (!slots->mExtendedSlots) {
slots->mExtendedSlots = MakeUnique<nsExtendedDOMSlots>();
}
return slots->mExtendedSlots.get();
return static_cast<nsExtendedDOMSlots*>(ExtendedContentSlots());
}
nsExtendedDOMSlots* GetExistingExtendedDOMSlots() const
const nsExtendedDOMSlots* GetExistingExtendedDOMSlots() const
{
nsDOMSlots* slots = GetExistingDOMSlots();
if (slots) {
return slots->mExtendedSlots.get();
}
return static_cast<const nsExtendedDOMSlots*>(
GetExistingExtendedContentSlots());
}
return nullptr;
nsExtendedDOMSlots* GetExistingExtendedDOMSlots()
{
return static_cast<nsExtendedDOMSlots*>(GetExistingExtendedContentSlots());
}
/**

View File

@ -7758,7 +7758,9 @@ nsIDocument::AdoptNode(nsINode& aAdoptedNode, ErrorResult& rv)
// have a binding applied. Remove the binding from the element now
// that it's getting adopted into a new document.
// TODO Fully tear down the binding.
adoptedNode->AsContent()->SetXBLBinding(nullptr);
if (adoptedNode->IsElement()) {
adoptedNode->AsElement()->SetXBLBinding(nullptr);
}
}
break;

View File

@ -99,24 +99,19 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsGenericDOMDataNode)
NS_IMPL_CYCLE_COLLECTION_DESCRIBE(nsGenericDOMDataNode, tmp->mRefCnt.get())
}
if (!nsINode::Traverse(tmp, cb)) {
if (!nsIContent::Traverse(tmp, cb)) {
return NS_SUCCESS_INTERRUPTED_TRAVERSE;
}
nsDataSlots *slots = tmp->GetExistingDataSlots();
if (slots) {
slots->Traverse(cb);
}
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGenericDOMDataNode)
nsINode::Unlink(tmp);
nsIContent::Unlink(tmp);
// Clear flag here because unlinking slots will clear the
// containing shadow root pointer.
tmp->UnsetFlags(NODE_IS_IN_SHADOW_TREE);
nsDataSlots *slots = tmp->GetExistingDataSlots();
nsContentSlots* slots = tmp->GetExistingContentSlots();
if (slots) {
slots->Unlink();
}
@ -508,7 +503,7 @@ nsGenericDOMDataNode::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
(aParent && aParent->IsInNativeAnonymousSubtree()),
"Trying to re-bind content from native anonymous subtree to "
"non-native anonymous parent!");
DataSlots()->mBindingParent = aBindingParent; // Weak, so no addref happens.
ExtendedContentSlots()->mBindingParent = aBindingParent; // Weak, so no addref happens.
if (aParent->IsInNativeAnonymousSubtree()) {
SetFlags(NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE);
}
@ -524,7 +519,7 @@ nsGenericDOMDataNode::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
}
ShadowRoot* parentContainingShadow = aParent->GetContainingShadow();
if (parentContainingShadow) {
DataSlots()->mContainingShadow = parentContainingShadow;
ExtendedContentSlots()->mContainingShadow = parentContainingShadow;
}
}
@ -620,7 +615,7 @@ nsGenericDOMDataNode::UnbindFromTree(bool aDeep, bool aNullParent)
}
}
nsDataSlots *slots = GetExistingDataSlots();
nsExtendedContentSlots* slots = GetExistingExtendedContentSlots();
if (slots) {
slots->mBindingParent = nullptr;
if (aNullParent || !mParent->IsInShadowTree()) {
@ -668,82 +663,12 @@ nsGenericDOMDataNode::RemoveChildAt(uint32_t aIndex, bool aNotify)
{
}
nsIContent *
nsGenericDOMDataNode::GetBindingParent() const
{
nsDataSlots *slots = GetExistingDataSlots();
return slots ? slots->mBindingParent : nullptr;
}
ShadowRoot *
nsGenericDOMDataNode::GetContainingShadow() const
{
nsDataSlots *slots = GetExistingDataSlots();
if (!slots) {
return nullptr;
}
return slots->mContainingShadow;
}
void
nsGenericDOMDataNode::SetShadowRoot(ShadowRoot* aShadowRoot)
{
}
HTMLSlotElement*
nsGenericDOMDataNode::GetAssignedSlot() const
{
nsDataSlots *slots = GetExistingDataSlots();
return slots ? slots->mAssignedSlot.get() : nullptr;
}
void
nsGenericDOMDataNode::SetAssignedSlot(HTMLSlotElement* aSlot)
{
nsDataSlots *slots = DataSlots();
slots->mAssignedSlot = aSlot;
}
nsXBLBinding *
nsGenericDOMDataNode::DoGetXBLBinding() const
{
return nullptr;
}
void
nsGenericDOMDataNode::SetXBLBinding(nsXBLBinding* aBinding,
nsBindingManager* aOldBindingManager)
{
}
nsIContent *
nsGenericDOMDataNode::GetXBLInsertionPoint() const
{
if (HasFlag(NODE_MAY_BE_IN_BINDING_MNGR)) {
nsDataSlots *slots = GetExistingDataSlots();
if (slots) {
return slots->mXBLInsertionPoint;
}
}
return nullptr;
}
void
nsGenericDOMDataNode::SetXBLInsertionPoint(nsIContent* aContent)
{
if (aContent) {
nsDataSlots *slots = DataSlots();
SetFlags(NODE_MAY_BE_IN_BINDING_MNGR);
slots->mXBLInsertionPoint = aContent;
} else {
nsDataSlots *slots = GetExistingDataSlots();
if (slots) {
slots->mXBLInsertionPoint = nullptr;
}
}
}
bool
nsGenericDOMDataNode::IsNodeOfType(uint32_t aFlags) const
{
@ -775,38 +700,6 @@ nsGenericDOMDataNode::IsLink(nsIURI** aURI) const
return false;
}
nsINode::nsSlots*
nsGenericDOMDataNode::CreateSlots()
{
return new nsDataSlots();
}
nsGenericDOMDataNode::nsDataSlots::nsDataSlots()
: nsINode::nsSlots(), mBindingParent(nullptr)
{
}
void
nsGenericDOMDataNode::nsDataSlots::Traverse(nsCycleCollectionTraversalCallback &cb)
{
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mXBLInsertionPoint");
cb.NoteXPCOMChild(mXBLInsertionPoint.get());
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mContainingShadow");
cb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIContent*, mContainingShadow));
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mAssignedSlot");
cb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIContent*, mAssignedSlot.get()));
}
void
nsGenericDOMDataNode::nsDataSlots::Unlink()
{
mXBLInsertionPoint = nullptr;
mContainingShadow = nullptr;
mAssignedSlot = nullptr;
}
//----------------------------------------------------------------------
// Implementation of the nsIDOMText interface

View File

@ -158,16 +158,7 @@ public:
virtual void DumpContent(FILE* out, int32_t aIndent, bool aDumpAll) const override;
#endif
virtual nsIContent* GetBindingParent() const override;
virtual nsXBLBinding* DoGetXBLBinding() const override;
virtual void SetXBLBinding(nsXBLBinding* aBinding,
nsBindingManager* aOldBindingManager = nullptr) override;
virtual mozilla::dom::ShadowRoot *GetContainingShadow() const override;
virtual void SetShadowRoot(mozilla::dom::ShadowRoot* aShadowRoot) override;
virtual mozilla::dom::HTMLSlotElement* GetAssignedSlot() const override;
virtual void SetAssignedSlot(mozilla::dom::HTMLSlotElement* aSlot) override;
virtual nsIContent *GetXBLInsertionPoint() const override;
virtual void SetXBLInsertionPoint(nsIContent* aContent) override;
virtual bool IsNodeOfType(uint32_t aFlags) const override;
virtual bool IsLink(nsIURI** aURI) const override;
@ -238,57 +229,6 @@ protected:
return parent && parent->IsElement() ? parent->AsElement() : nullptr;
}
/**
* There are a set of DOM- and scripting-specific instance variables
* that may only be instantiated when a content object is accessed
* through the DOM. Rather than burn actual slots in the content
* objects for each of these instance variables, we put them off
* in a side structure that's only allocated when the content is
* accessed through the DOM.
*/
class nsDataSlots : public nsINode::nsSlots
{
public:
nsDataSlots();
void Traverse(nsCycleCollectionTraversalCallback &cb);
void Unlink();
/**
* The nearest enclosing content node with a binding that created us.
* @see nsIContent::GetBindingParent
*/
nsIContent* mBindingParent; // [Weak]
/**
* @see nsIContent::GetXBLInsertionPoint
*/
nsCOMPtr<nsIContent> mXBLInsertionPoint;
/**
* @see nsIContent::GetContainingShadow
*/
RefPtr<mozilla::dom::ShadowRoot> mContainingShadow;
/**
* @see nsIContent::GetAssignedSlot
*/
RefPtr<mozilla::dom::HTMLSlotElement> mAssignedSlot;
};
// Override from nsINode
virtual nsINode::nsSlots* CreateSlots() override;
nsDataSlots* DataSlots()
{
return static_cast<nsDataSlots*>(Slots());
}
nsDataSlots *GetExistingDataSlots() const
{
return static_cast<nsDataSlots*>(GetExistingSlots());
}
nsresult SplitText(uint32_t aOffset, nsIDOMText** aReturn);
nsresult GetWholeText(nsAString& aWholeText);

View File

@ -507,7 +507,11 @@ public:
*
* @return the binding parent
*/
virtual nsIContent* GetBindingParent() const = 0;
virtual nsIContent* GetBindingParent() const
{
const nsExtendedContentSlots* slots = GetExistingExtendedContentSlots();
return slots ? slots->mBindingParent : nullptr;
}
/**
* Gets the current XBL binding that is bound to this element.
@ -525,30 +529,6 @@ public:
virtual nsXBLBinding* DoGetXBLBinding() const = 0;
/**
* Sets or unsets an XBL binding for this element. Setting a
* binding on an element that already has a binding will remove the
* old binding.
*
* @param aBinding The binding to bind to this content. If nullptr is
* provided as the argument, then existing binding will be
* removed.
*
* @param aOldBindingManager The old binding manager that contains
* this content if this content was adopted
* to another document.
*/
virtual void SetXBLBinding(nsXBLBinding* aBinding,
nsBindingManager* aOldBindingManager = nullptr) = 0;
/**
* Sets the ShadowRoot binding for this element. The contents of the
* binding is rendered in place of this node's children.
*
* @param aShadowRoot The ShadowRoot to be bound to this element.
*/
virtual void SetShadowRoot(mozilla::dom::ShadowRoot* aShadowRoot) = 0;
/**
* Gets the ShadowRoot binding for this element.
*
@ -563,21 +543,29 @@ public:
*
* @return The ShadowRoot that is the root of the node tree.
*/
virtual mozilla::dom::ShadowRoot *GetContainingShadow() const = 0;
mozilla::dom::ShadowRoot* GetContainingShadow() const
{
const nsExtendedContentSlots* slots = GetExistingExtendedContentSlots();
return slots ? slots->mContainingShadow.get() : nullptr;
}
/**
* Gets the assigned slot associated with this content.
*
* @return The assigned slot element or null.
*/
virtual mozilla::dom::HTMLSlotElement* GetAssignedSlot() const = 0;
mozilla::dom::HTMLSlotElement* GetAssignedSlot() const
{
const nsExtendedContentSlots* slots = GetExistingExtendedContentSlots();
return slots ? slots->mAssignedSlot.get() : nullptr;
}
/**
* Sets the assigned slot associated with this content.
*
* @param aSlot The assigned slot.
*/
virtual void SetAssignedSlot(mozilla::dom::HTMLSlotElement* aSlot) = 0;
void SetAssignedSlot(mozilla::dom::HTMLSlotElement* aSlot);
/**
* Gets the assigned slot associated with this content based on parent's
@ -600,14 +588,18 @@ public:
*
* @return the insertion parent element.
*/
virtual nsIContent* GetXBLInsertionPoint() const = 0;
nsIContent* GetXBLInsertionPoint() const
{
const nsExtendedContentSlots* slots = GetExistingExtendedContentSlots();
return slots ? slots->mXBLInsertionPoint.get() : nullptr;
}
/**
* Sets the insertion parent element of the XBL binding.
*
* @param aContent The insertion parent element.
*/
virtual void SetXBLInsertionPoint(nsIContent* aContent) = 0;
void SetXBLInsertionPoint(nsIContent* aContent);
/**
* Same as GetFlattenedTreeParentNode, but returns null if the parent is
@ -849,6 +841,114 @@ public:
}
protected:
/**
* Lazily allocated extended slots to avoid
* that may only be instantiated when a content object is accessed
* through the DOM. Rather than burn actual slots in the content
* objects for each of these instance variables, we put them off
* in a side structure that's only allocated when the content is
* accessed through the DOM.
*/
class nsExtendedContentSlots
{
public:
nsExtendedContentSlots();
virtual ~nsExtendedContentSlots();
virtual void Traverse(nsCycleCollectionTraversalCallback&);
virtual void Unlink();
/**
* The nearest enclosing content node with a binding that created us.
* @see nsIContent::GetBindingParent
*/
nsIContent* mBindingParent; // [Weak]
/**
* @see nsIContent::GetXBLInsertionPoint
*/
nsCOMPtr<nsIContent> mXBLInsertionPoint;
/**
* @see nsIContent::GetContainingShadow
*/
RefPtr<mozilla::dom::ShadowRoot> mContainingShadow;
/**
* @see nsIContent::GetAssignedSlot
*/
RefPtr<mozilla::dom::HTMLSlotElement> mAssignedSlot;
};
class nsContentSlots : public nsINode::nsSlots
{
public:
void Traverse(nsCycleCollectionTraversalCallback& aCb) override
{
nsINode::nsSlots::Traverse(aCb);
if (mExtendedSlots) {
mExtendedSlots->Traverse(aCb);
}
}
void Unlink() override
{
nsINode::nsSlots::Unlink();
if (mExtendedSlots) {
mExtendedSlots->Unlink();
}
}
mozilla::UniquePtr<nsExtendedContentSlots> mExtendedSlots;
};
// Override from nsINode
nsContentSlots* CreateSlots() override
{
return new nsContentSlots();
}
nsContentSlots* ContentSlots()
{
return static_cast<nsContentSlots*>(Slots());
}
const nsContentSlots* GetExistingContentSlots() const
{
return static_cast<nsContentSlots*>(GetExistingSlots());
}
nsContentSlots* GetExistingContentSlots()
{
return static_cast<nsContentSlots*>(GetExistingSlots());
}
virtual nsExtendedContentSlots* CreateExtendedSlots()
{
return new nsExtendedContentSlots();
}
const nsExtendedContentSlots* GetExistingExtendedContentSlots() const
{
const nsContentSlots* slots = GetExistingContentSlots();
return slots ? slots->mExtendedSlots.get() : nullptr;
}
nsExtendedContentSlots* GetExistingExtendedContentSlots()
{
nsContentSlots* slots = GetExistingContentSlots();
return slots ? slots->mExtendedSlots.get() : nullptr;
}
nsExtendedContentSlots* ExtendedContentSlots()
{
nsContentSlots* slots = ContentSlots();
if (!slots->mExtendedSlots) {
slots->mExtendedSlots.reset(CreateExtendedSlots());
}
return slots->mExtendedSlots.get();
}
/**
* Hook for implementing GetID. This is guaranteed to only be
* called if HasID() is true.

View File

@ -1112,8 +1112,8 @@ public:
// putting a DestroySlots function on nsINode
virtual ~nsSlots();
void Traverse(nsCycleCollectionTraversalCallback &cb);
void Unlink();
virtual void Traverse(nsCycleCollectionTraversalCallback&);
virtual void Unlink();
/**
* A list of mutation observers

View File

@ -216,7 +216,7 @@ nsBindingManager::RemovedFromDocumentInternal(nsIContent* aContent,
binding->ChangeDocument(aOldDocument, nullptr);
}
aContent->SetXBLBinding(nullptr, this);
aContent->AsElement()->SetXBLBinding(nullptr, this);
}
// Clear out insertion point and content lists.

View File

@ -1680,12 +1680,6 @@ nsXULElement::DoCommand()
}
}
nsIContent *
nsXULElement::GetBindingParent() const
{
return mBindingParent;
}
bool
nsXULElement::IsNodeOfType(uint32_t aFlags) const
{

View File

@ -384,7 +384,11 @@ public:
bool aIsTrustedEvent) override;
void ClickWithInputSource(uint16_t aInputSource, bool aIsTrustedEvent);
virtual nsIContent *GetBindingParent() const override;
nsIContent* GetBindingParent() const final
{
return mBindingParent;
}
virtual bool IsNodeOfType(uint32_t aFlags) const override;
virtual bool IsFocusableInternal(int32_t* aTabIndex, bool aWithMouse) override;

View File

@ -16,7 +16,7 @@ V1_CUTOFF = 20150801000000 # YYYYmmddHHMMSS
def android_version_code_v0(buildid, cpu_arch=None, min_sdk=0, max_sdk=0):
base = int(str(buildid)[:10])
# None is interpreted as arm.
if not cpu_arch or cpu_arch in ['armeabi', 'armeabi-v7a']:
if not cpu_arch or cpu_arch == 'armeabi-v7a':
# Increment by MIN_SDK_VERSION -- this adds 9 to every build ID as a
# minimum. Our split APK starts at 15.
return base + min_sdk + 0
@ -114,7 +114,7 @@ def android_version_code_v1(buildid, cpu_arch=None, min_sdk=0, max_sdk=0):
version |= base << 3
# None is interpreted as arm.
if not cpu_arch or cpu_arch in ['armeabi', 'armeabi-v7a']:
if not cpu_arch or cpu_arch == 'armeabi-v7a':
# 0 is interpreted as SDK 9.
if not min_sdk or min_sdk == 9:
pass

View File

@ -775,8 +775,6 @@ pub struct NormalBorder {
pub style: SideOffsets2D<border_style::T>,
/// Border radii.
///
/// TODO(pcwalton): Elliptical radii.
pub radius: BorderRadii<Au>,
}
@ -845,8 +843,6 @@ pub struct BorderDisplayItem {
}
/// Information about the border radii.
///
/// TODO(pcwalton): Elliptical radii.
#[derive(Clone, Copy, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize)]
pub struct BorderRadii<T> {
pub top_left: Size2D<T>,

View File

@ -798,6 +798,7 @@ fn convert_gradient_stops(gradient_items: &[GradientItem],
position_to_offset(position, total_length)
}
};
assert!(offset.is_finite());
stops.push(GradientStop {
offset: offset,
color: stop.color.to_gfx_color()
@ -1544,7 +1545,6 @@ impl FragmentDisplayListBuilding for Fragment {
Au::from(box_shadow.spread),
);
// TODO(pcwalton): Multiple border radii; elliptical border radii.
let base = state.create_base_display_item(&bounds,
LocalClip::from(clip.to_rectf()),
self.node,
@ -3271,6 +3271,9 @@ struct StopRun {
}
fn position_to_offset(position: LengthOrPercentage, total_length: Au) -> f32 {
if total_length == Au(0) {
return 0.0
}
match position {
LengthOrPercentage::Length(l) => l.to_i32_au() as f32 / total_length.0 as f32,
LengthOrPercentage::Percentage(percentage) => percentage.0 as f32,

File diff suppressed because one or more lines are too long

View File

@ -536,8 +536,9 @@ impl<'le> GeckoElement<'le> {
fn get_extended_slots(
&self,
) -> Option<&structs::FragmentOrElement_nsExtendedDOMSlots> {
self.get_dom_slots()
.and_then(|s| unsafe { s.mExtendedSlots.mPtr.as_ref() })
self.get_dom_slots().and_then(|s| unsafe {
(s._base.mExtendedSlots.mPtr as *const structs::FragmentOrElement_nsExtendedDOMSlots).as_ref()
})
}
#[inline]
@ -592,7 +593,7 @@ impl<'le> GeckoElement<'le> {
fn get_non_xul_xbl_binding_parent_raw_content(&self) -> *mut nsIContent {
debug_assert!(!self.is_xul_element());
self.get_extended_slots()
.map_or(ptr::null_mut(), |slots| slots.mBindingParent)
.map_or(ptr::null_mut(), |slots| slots._base.mBindingParent)
}
fn has_xbl_binding_parent(&self) -> bool {

View File

@ -13,229 +13,36 @@
//
// We allow "display" to apply to placeholders because we need to make the
// placeholder pseudo-element an inline-block in the UA stylesheet in Gecko.
<%helpers:longhand name="display"
animation_value_type="discrete"
custom_cascade="${product == 'servo'}"
flags="APPLIES_TO_PLACEHOLDER"
spec="https://drafts.csswg.org/css-display/#propdef-display">
<%
values = """inline block inline-block
table inline-table table-row-group table-header-group table-footer-group
table-row table-column-group table-column table-cell table-caption
list-item none
""".split()
webkit_prefixed_values = "flex inline-flex".split()
values += webkit_prefixed_values
if product == "gecko":
values += """grid inline-grid ruby ruby-base ruby-base-container
ruby-text ruby-text-container contents flow-root -webkit-box
-webkit-inline-box -moz-box -moz-inline-box -moz-grid -moz-inline-grid
-moz-grid-group -moz-grid-line -moz-stack -moz-inline-stack -moz-deck
-moz-popup -moz-groupbox""".split()
%>
use style_traits::ToCss;
${helpers.predefined_type(
"display",
"Display",
"computed::Display::inline()",
initial_specified_value="specified::Display::inline()",
animation_value_type="discrete",
needs_context=False,
custom_cascade= product == 'servo',
custom_cascade_function="specified::Display::cascade_property_custom",
flags="APPLIES_TO_PLACEHOLDER",
spec="https://drafts.csswg.org/css-display/#propdef-display",
)}
pub mod computed_value {
pub use super::SpecifiedValue as T;
use super::SpecifiedValue as Display;
impl Display {
/// Returns whether this "display" value is the display of a flex or
/// grid container.
///
/// This is used to implement various style fixups.
pub fn is_item_container(&self) -> bool {
matches!(*self,
Display::Flex
| Display::InlineFlex
% if product == "gecko":
| Display::Grid
| Display::InlineGrid
% endif
)
}
/// Returns whether an element with this display type is a line
/// participant, which means it may lay its children on the same
/// line as itself.
pub fn is_line_participant(&self) -> bool {
matches!(*self,
Display::Inline
% if product == "gecko":
| Display::Contents
| Display::Ruby
| Display::RubyBaseContainer
% endif
)
}
/// Whether `new_display` should be ignored, given a previous
/// `old_display` value.
///
/// This is used to ignore `display: -moz-box` declarations after an
/// equivalent `display: -webkit-box` declaration, since the former
/// has a vastly different meaning. See bug 1107378 and bug 1407701.
///
/// FIXME(emilio): This is a pretty decent hack, we should try to
/// remove it.
pub fn should_ignore_parsed_value(
_old_display: Self,
_new_display: Self,
) -> bool {
#[cfg(feature = "gecko")]
{
match (_old_display, _new_display) {
(Display::WebkitBox, Display::MozBox) |
(Display::WebkitInlineBox, Display::MozInlineBox) => {
return true;
}
_ => {},
}
}
return false;
}
/// Returns whether this "display" value is one of the types for
/// ruby.
#[cfg(feature = "gecko")]
pub fn is_ruby_type(&self) -> bool {
matches!(*self,
Display::Ruby |
Display::RubyBase |
Display::RubyText |
Display::RubyBaseContainer |
Display::RubyTextContainer)
}
/// Returns whether this "display" value is a ruby level container.
#[cfg(feature = "gecko")]
pub fn is_ruby_level_container(&self) -> bool {
matches!(*self,
Display::RubyBaseContainer |
Display::RubyTextContainer)
}
/// Convert this display into an equivalent block display.
///
/// Also used for style adjustments.
pub fn equivalent_block_display(&self, _is_root_element: bool) -> Self {
match *self {
// Values that have a corresponding block-outside version.
Display::InlineTable => Display::Table,
Display::InlineFlex => Display::Flex,
% if product == "gecko":
Display::InlineGrid => Display::Grid,
Display::WebkitInlineBox => Display::WebkitBox,
% endif
// Special handling for contents and list-item on the root
// element for Gecko.
% if product == "gecko":
Display::Contents | Display::ListItem if _is_root_element => Display::Block,
% endif
// These are not changed by blockification.
Display::None |
Display::Block |
Display::Flex |
Display::ListItem |
Display::Table => *self,
% if product == "gecko":
Display::Contents |
Display::FlowRoot |
Display::Grid |
Display::WebkitBox => *self,
% endif
// Everything else becomes block.
_ => Display::Block,
}
}
/// Convert this display into an inline-outside display.
///
/// Ideally it should implement spec: https://drafts.csswg.org/css-display/#inlinify
/// but the spec isn't stable enough, so we copy what Gecko does for now.
#[cfg(feature = "gecko")]
pub fn inlinify(&self) -> Self {
match *self {
Display::Block |
Display::FlowRoot => Display::InlineBlock,
Display::Table => Display::InlineTable,
Display::Flex => Display::InlineFlex,
Display::Grid => Display::InlineGrid,
Display::MozBox => Display::MozInlineBox,
Display::MozStack => Display::MozInlineStack,
Display::WebkitBox => Display::WebkitInlineBox,
other => other,
}
}
}
}
// FIXME(emilio): Why does this reinvent the wheel, again?
#[allow(non_camel_case_types)]
#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq, ToComputedValue)]
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
pub enum SpecifiedValue {
% for value in values:
${to_camel_case(value)},
% endfor
}
// TODO(emilio): derive.
impl ToCss for SpecifiedValue {
fn to_css<W>(&self, dest: &mut W) -> ::std::fmt::Result
where W: ::std::fmt::Write,
{
match *self {
% for value in values:
SpecifiedValue::${to_camel_case(value)} => dest.write_str("${value}"),
% endfor
}
}
}
/// The initial display value.
#[inline]
pub fn get_initial_value() -> computed_value::T {
computed_value::T::${to_camel_case(values[0])}
}
/// Parse a display value.
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
-> Result<SpecifiedValue, ParseError<'i>> {
try_match_ident_ignore_ascii_case! { input,
% for value in values:
"${value}" => {
Ok(computed_value::T::${to_camel_case(value)})
},
% endfor
% for value in webkit_prefixed_values:
"-webkit-${value}" => {
Ok(computed_value::T::${to_camel_case(value)})
},
% endfor
}
}
% if product == "servo":
fn cascade_property_custom(_declaration: &PropertyDeclaration,
context: &mut computed::Context) {
longhands::_servo_display_for_hypothetical_box::derive_from_display(context);
longhands::_servo_text_decorations_in_effect::derive_from_display(context);
}
% endif
${helpers.gecko_keyword_conversion(Keyword('display', ' '.join(values),
gecko_enum_prefix='StyleDisplay',
gecko_strip_moz_prefix=False))}
</%helpers:longhand>
// FIXME(emilio): Listing all the display values here is very unfortunate, we should teach C++ to use the
// Rust enum directly, or generate the conversions to `StyleDisplay`.
${helpers.gecko_keyword_conversion(
Keyword('display', """
inline block inline-block
table inline-table table-row-group table-header-group table-footer-group
table-row table-column-group table-column table-cell table-caption
list-item none flex inline-flex grid inline-grid ruby ruby-base ruby-base-container
ruby-text ruby-text-container contents flow-root -webkit-box
-webkit-inline-box -moz-box -moz-inline-box -moz-grid -moz-inline-grid
-moz-grid-group -moz-grid-line -moz-stack -moz-inline-stack -moz-deck
-moz-popup -moz-groupbox
""",
gecko_enum_prefix='StyleDisplay',
gecko_strip_moz_prefix=False),
type="::values::specified::Display"
)}
${helpers.single_keyword("-moz-top-layer", "none top",
gecko_constant_prefix="NS_STYLE_TOP_LAYER",

View File

@ -3079,21 +3079,13 @@ bitflags! {
/// that it may affect global state, like the Device's root font-size.
const IS_ROOT_ELEMENT = 1 << 3;
/// Whether to convert display:contents into display:inline. This
/// is used by Gecko to prevent display:contents on generated
/// content.
const PROHIBIT_DISPLAY_CONTENTS = 1 << 4;
/// Whether we're styling the ::-moz-fieldset-content anonymous box.
const IS_FIELDSET_CONTENT = 1 << 5;
/// Whether we're computing the style of a link, either visited or
/// unvisited.
const IS_LINK = 1 << 6;
const IS_LINK = 1 << 4;
/// Whether we're computing the style of a link element that happens to
/// be visited.
const IS_VISITED_LINK = 1 << 7;
const IS_VISITED_LINK = 1 << 5;
}
}

View File

@ -320,12 +320,13 @@ impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> {
/// Native anonymous content converts display:contents into display:inline.
#[cfg(feature = "gecko")]
fn adjust_for_prohibited_display_contents(&mut self, flags: CascadeFlags) {
use properties::CascadeFlags;
fn adjust_for_prohibited_display_contents(&mut self) {
// TODO: We should probably convert display:contents into display:none
// in some cases too: https://drafts.csswg.org/css-display/#unbox
if !flags.contains(CascadeFlags::PROHIBIT_DISPLAY_CONTENTS) ||
//
// FIXME(emilio): ::before and ::after should support display: contents,
// see bug 1418138.
if self.style.pseudo.is_none() ||
self.style.get_box().clone_display() != Display::Contents {
return;
}
@ -343,12 +344,12 @@ impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> {
fn adjust_for_fieldset_content(
&mut self,
layout_parent_style: &ComputedValues,
flags: CascadeFlags,
) {
use properties::CascadeFlags;
if !flags.contains(CascadeFlags::IS_FIELDSET_CONTENT) {
return;
match self.style.pseudo {
Some(ref p) if p.is_fieldset_content() => {},
_ => return,
}
debug_assert_eq!(self.style.get_box().clone_display(), Display::Block);
// TODO We actually want style from parent rather than layout
// parent, so that this fixup doesn't happen incorrectly when
@ -569,8 +570,8 @@ impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> {
self.adjust_for_visited(flags);
#[cfg(feature = "gecko")]
{
self.adjust_for_prohibited_display_contents(flags);
self.adjust_for_fieldset_content(layout_parent_style, flags);
self.adjust_for_prohibited_display_contents();
self.adjust_for_fieldset_content(layout_parent_style);
}
self.adjust_for_top_layer();
self.blockify_if_necessary(layout_parent_style, flags);

View File

@ -566,9 +566,10 @@ where
}
cascade_flags.insert(CascadeFlags::VISITED_DEPENDENT_ONLY);
}
if self.element.is_native_anonymous() || pseudo.is_some() {
cascade_flags.insert(CascadeFlags::PROHIBIT_DISPLAY_CONTENTS);
} else if self.element.is_root() {
if !self.element.is_native_anonymous() &&
pseudo.is_none() &&
self.element.is_root()
{
cascade_flags.insert(CascadeFlags::IS_ROOT_ELEMENT);
}

View File

@ -9,8 +9,8 @@ use values::computed::length::LengthOrPercentage;
use values::generics::box_::AnimationIterationCount as GenericAnimationIterationCount;
use values::generics::box_::VerticalAlign as GenericVerticalAlign;
pub use values::specified::box_::{AnimationName, OverflowClipBox, OverscrollBehavior};
pub use values::specified::box_::{ScrollSnapType, TouchAction, WillChange};
pub use values::specified::box_::{AnimationName, Display, OverflowClipBox};
pub use values::specified::box_::{OverscrollBehavior, ScrollSnapType, TouchAction, WillChange};
/// A computed value for the `vertical-align` property.
pub type VerticalAlign = GenericVerticalAlign<LengthOrPercentage>;

View File

@ -40,7 +40,7 @@ pub use self::font::{FontSize, FontSizeAdjust, FontSynthesis, FontWeight, FontVa
pub use self::font::{FontFamily, FontLanguageOverride, FontVariantSettings, FontVariantEastAsian};
pub use self::font::{FontVariantLigatures, FontVariantNumeric, FontFeatureSettings};
pub use self::font::{MozScriptLevel, MozScriptMinSize, MozScriptSizeMultiplier, XTextZoom, XLang};
pub use self::box_::{AnimationIterationCount, AnimationName, OverscrollBehavior};
pub use self::box_::{AnimationIterationCount, AnimationName, Display, OverscrollBehavior};
pub use self::box_::{OverflowClipBox, ScrollSnapType, TouchAction, VerticalAlign, WillChange};
pub use self::color::{Color, ColorPropertyValue, RGBAColor};
pub use self::effects::{BoxShadow, Filter, SimpleShadow};

View File

@ -7,15 +7,231 @@
use Atom;
use cssparser::Parser;
use parser::{Parse, ParserContext};
#[cfg(feature = "servo")]
use properties::{longhands, PropertyDeclaration};
use std::fmt;
use style_traits::{ParseError, ToCss};
use values::CustomIdent;
use values::KeyframesName;
#[cfg(feature = "servo")]
use values::computed::Context;
use values::generics::box_::AnimationIterationCount as GenericAnimationIterationCount;
use values::generics::box_::VerticalAlign as GenericVerticalAlign;
use values::specified::{AllowQuirks, Number};
use values::specified::length::LengthOrPercentage;
#[allow(missing_docs)]
#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, Parse, PartialEq, ToComputedValue, ToCss)]
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
/// Defines an elements display type, which consists of
/// the two basic qualities of how an element generates boxes
/// <https://drafts.csswg.org/css-display/#propdef-display>
pub enum Display {
Inline, Block, InlineBlock,
Table, InlineTable, TableRowGroup, TableHeaderGroup,
TableFooterGroup, TableRow, TableColumnGroup,
TableColumn, TableCell, TableCaption, ListItem, None,
#[parse(aliases = "-webkit-flex")]
Flex,
#[parse(aliases = "-webkit-inline-flex")]
InlineFlex,
#[cfg(feature = "gecko")]
Grid,
#[cfg(feature = "gecko")]
InlineGrid,
#[cfg(feature = "gecko")]
Ruby,
#[cfg(feature = "gecko")]
RubyBase,
#[cfg(feature = "gecko")]
RubyBaseContainer,
#[cfg(feature = "gecko")]
RubyText,
#[cfg(feature = "gecko")]
RubyTextContainer,
#[cfg(feature = "gecko")]
Contents,
#[cfg(feature = "gecko")]
FlowRoot,
#[cfg(feature = "gecko")]
WebkitBox,
#[cfg(feature = "gecko")]
WebkitInlineBox,
#[cfg(feature = "gecko")]
MozBox,
#[cfg(feature = "gecko")]
MozInlineBox,
#[cfg(feature = "gecko")]
MozGrid,
#[cfg(feature = "gecko")]
MozInlineGrid,
#[cfg(feature = "gecko")]
MozGridGroup,
#[cfg(feature = "gecko")]
MozGridLine,
#[cfg(feature = "gecko")]
MozStack,
#[cfg(feature = "gecko")]
MozInlineStack,
#[cfg(feature = "gecko")]
MozDeck,
#[cfg(feature = "gecko")]
MozPopup,
#[cfg(feature = "gecko")]
MozGroupbox,
}
impl Display {
/// The initial display value.
#[inline]
pub fn inline() -> Self {
Display::Inline
}
/// Returns whether this "display" value is the display of a flex or
/// grid container.
///
/// This is used to implement various style fixups.
pub fn is_item_container(&self) -> bool {
match *self {
Display::Flex | Display::InlineFlex => true,
#[cfg(feature = "gecko")]
Display::Grid | Display::InlineGrid => true,
_ => false,
}
}
/// Returns whether an element with this display type is a line
/// participant, which means it may lay its children on the same
/// line as itself.
pub fn is_line_participant(&self) -> bool {
match *self {
Display::Inline => true,
#[cfg(feature = "gecko")]
Display::Contents |
Display::Ruby |
Display::RubyBaseContainer => true,
_ => false,
}
}
/// Whether `new_display` should be ignored, given a previous
/// `old_display` value.
///
/// This is used to ignore `display: -moz-box` declarations after an
/// equivalent `display: -webkit-box` declaration, since the former
/// has a vastly different meaning. See bug 1107378 and bug 1407701.
///
/// FIXME(emilio): This is a pretty decent hack, we should try to
/// remove it.
pub fn should_ignore_parsed_value(
_old_display: Self,
_new_display: Self,
) -> bool {
#[cfg(feature = "gecko")] {
match (_old_display, _new_display) {
(Display::WebkitBox, Display::MozBox) |
(Display::WebkitInlineBox, Display::MozInlineBox) => {
return true;
}
_ => {},
}
}
return false;
}
/// Returns whether this "display" value is one of the types for
/// ruby.
#[cfg(feature = "gecko")]
pub fn is_ruby_type(&self) -> bool {
matches!(*self,
Display::Ruby |
Display::RubyBase |
Display::RubyText |
Display::RubyBaseContainer |
Display::RubyTextContainer
)
}
/// Returns whether this "display" value is a ruby level container.
#[cfg(feature = "gecko")]
pub fn is_ruby_level_container(&self) -> bool {
matches!(*self,
Display::RubyBaseContainer |
Display::RubyTextContainer
)
}
/// Convert this display into an equivalent block display.
///
/// Also used for style adjustments.
pub fn equivalent_block_display(&self, _is_root_element: bool) -> Self {
match *self {
// Values that have a corresponding block-outside version.
Display::InlineTable => Display::Table,
Display::InlineFlex => Display::Flex,
#[cfg(feature = "gecko")]
Display::InlineGrid => Display::Grid,
#[cfg(feature = "gecko")]
Display::WebkitInlineBox => Display::WebkitBox,
// Special handling for contents and list-item on the root
// element for Gecko.
#[cfg(feature = "gecko")]
Display::Contents | Display::ListItem if _is_root_element => Display::Block,
// These are not changed by blockification.
Display::None |
Display::Block |
Display::Flex |
Display::ListItem |
Display::Table => *self,
#[cfg(feature = "gecko")]
Display::Contents |
Display::FlowRoot |
Display::Grid |
Display::WebkitBox => *self,
// Everything else becomes block.
_ => Display::Block,
}
}
/// Convert this display into an inline-outside display.
///
/// Ideally it should implement spec: https://drafts.csswg.org/css-display/#inlinify
/// but the spec isn't stable enough, so we copy what Gecko does for now.
#[cfg(feature = "gecko")]
pub fn inlinify(&self) -> Self {
match *self {
Display::Block |
Display::FlowRoot => Display::InlineBlock,
Display::Table => Display::InlineTable,
Display::Flex => Display::InlineFlex,
Display::Grid => Display::InlineGrid,
Display::MozBox => Display::MozInlineBox,
Display::MozStack => Display::MozInlineStack,
Display::WebkitBox => Display::WebkitInlineBox,
other => other,
}
}
#[cfg(feature = "servo")]
#[inline]
/// Custom cascade for the `display` property in servo
pub fn cascade_property_custom(
_declaration: &PropertyDeclaration,
context: &mut Context
) {
longhands::_servo_display_for_hypothetical_box::derive_from_display(context);
longhands::_servo_text_decorations_in_effect::derive_from_display(context);
}
}
/// A specified value for the `vertical-align` property.
pub type VerticalAlign = GenericVerticalAlign<LengthOrPercentage>;

View File

@ -34,7 +34,7 @@ pub use self::font::{FontSize, FontSizeAdjust, FontSynthesis, FontWeight, FontVa
pub use self::font::{FontFamily, FontLanguageOverride, FontVariantSettings, FontVariantEastAsian};
pub use self::font::{FontVariantLigatures, FontVariantNumeric, FontFeatureSettings};
pub use self::font::{MozScriptLevel, MozScriptMinSize, MozScriptSizeMultiplier, XTextZoom, XLang};
pub use self::box_::{AnimationIterationCount, AnimationName, OverscrollBehavior};
pub use self::box_::{AnimationIterationCount, AnimationName, Display, OverscrollBehavior};
pub use self::box_::{OverflowClipBox, ScrollSnapType, TouchAction, VerticalAlign, WillChange};
pub use self::color::{Color, ColorPropertyValue, RGBAColor};
pub use self::effects::{BoxShadow, Filter, SimpleShadow};

View File

@ -39,7 +39,7 @@ pub fn derive_to_animated_value(stream: TokenStream) -> TokenStream {
to_animated_value::derive(input).to_string().parse().unwrap()
}
#[proc_macro_derive(Parse)]
#[proc_macro_derive(Parse, attributes(parse))]
pub fn derive_parse(stream: TokenStream) -> TokenStream {
let input = syn::parse_derive_input(&stream.to_string()).unwrap();
parse::derive(input).to_string().parse().unwrap()

View File

@ -19,11 +19,25 @@ pub fn derive(input: DeriveInput) -> Tokens {
"Parse is only supported for single-variant enums for now"
);
let variant_attrs = cg::parse_variant_attrs::<ParseVariantAttrs>(variant);
let identifier = cg::to_css_identifier(variant.ident.as_ref());
let ident = &variant.ident;
match_body = quote! {
#match_body
#identifier => Ok(#name::#ident),
};
let aliases = match variant_attrs.aliases {
Some(aliases) => aliases,
None => return,
};
for alias in aliases.split(",") {
match_body = quote! {
#match_body
#alias => Ok(#name::#ident),
};
}
});
@ -73,3 +87,11 @@ pub fn derive(input: DeriveInput) -> Tokens {
#methods_impl
}
}
#[darling(attributes(parse), default)]
#[derive(Default, FromVariant)]
struct ParseVariantAttrs {
/// The comma-separated list of aliases this variant should be aliased to at
/// parse time.
aliases: Option<String>,
}

View File

@ -1987,10 +1987,6 @@ pub extern "C" fn Servo_ComputedValues_GetForAnonymousBox(parent_style_or_null:
let pseudo = PseudoElement::from_anon_box_atom(&atom)
.expect("Not an anon box pseudo?");
let mut cascade_flags = CascadeFlags::SKIP_ROOT_AND_ITEM_BASED_DISPLAY_FIXUP;
if pseudo.is_fieldset_content() {
cascade_flags.insert(CascadeFlags::IS_FIELDSET_CONTENT);
}
let metrics = get_metrics_provider_for_product();
// If the pseudo element is PageContent, we should append the precomputed
@ -2023,6 +2019,7 @@ pub extern "C" fn Servo_ComputedValues_GetForAnonymousBox(parent_style_or_null:
page_decls,
);
let cascade_flags = CascadeFlags::SKIP_ROOT_AND_ITEM_BASED_DISPLAY_FIXUP;
data.stylist.precomputed_values_for_pseudo_with_rule_node(
&guards,
&pseudo,
@ -3629,21 +3626,10 @@ pub extern "C" fn Servo_ReparentStyle(
if let Some(element) = element {
if element.is_link() {
cascade_flags.insert(CascadeFlags::IS_LINK);
if element.is_visited_link() &&
doc_data.visited_styles_enabled() {
if element.is_visited_link() && doc_data.visited_styles_enabled() {
cascade_flags.insert(CascadeFlags::IS_VISITED_LINK);
}
};
if element.is_native_anonymous() {
cascade_flags.insert(CascadeFlags::PROHIBIT_DISPLAY_CONTENTS);
}
}
if let Some(pseudo) = pseudo.as_ref() {
cascade_flags.insert(CascadeFlags::PROHIBIT_DISPLAY_CONTENTS);
if pseudo.is_fieldset_content() {
cascade_flags.insert(CascadeFlags::IS_FIELDSET_CONTENT);
}
}
doc_data.stylist.compute_style_with_inputs(

View File

@ -103,9 +103,6 @@ if CONFIG['MOZ_GECKO_PROFILER']:
if not CONFIG['MOZ_CRASHREPORTER'] and CONFIG['OS_TARGET'] == 'Android':
SOURCES += ['/toolkit/crashreporter/google-breakpad/src/common/android/breakpad_getcontext.S']
if CONFIG['ANDROID_CPU_ARCH'] == 'armeabi':
DEFINES['ARCH_ARMV6'] = True
if CONFIG['ENABLE_TESTS']:
DIRS += ['tests/gtest']