Bug 1637307 - Push/Pop dialog to top layer when needed r=smaug

This patch completes the top layer requirement for showModal()
Spec: https://html.spec.whatwg.org/multipage/interactive-elements.html#dom-dialog-showmodal

Differential Revision: https://phabricator.services.mozilla.com/D74922
This commit is contained in:
sefeng 2020-05-19 15:40:08 +00:00
Родитель 093f9492b3
Коммит ca6d5ba134
4 изменённых файлов: 45 добавлений и 0 удалений

Просмотреть файл

@ -13415,6 +13415,17 @@ Element* Document::GetTopLayerTop() {
return element;
}
bool Document::DoesTopLayerContain(const Element* aElement) const {
for (const nsWeakPtr& weakPtr : mTopLayer) {
nsCOMPtr<Element> element(do_QueryReferent(weakPtr));
if (element && element == aElement) {
return true;
}
}
return false;
}
Element* Document::GetUnretargetedFullScreenElement() {
for (const nsWeakPtr& weakPtr : Reversed(mTopLayer)) {
nsCOMPtr<Element> element(do_QueryReferent(weakPtr));

Просмотреть файл

@ -3405,6 +3405,9 @@ class Document : public nsINode,
// Not const because all the fullscreen goop is not const
bool FullscreenEnabled(CallerType aCallerType);
Element* GetTopLayerTop();
bool DoesTopLayerContain(const Element* aElement) const;
// Return the fullscreen element in the top layer
Element* GetUnretargetedFullScreenElement();
bool Fullscreen() { return !!GetFullscreenElement(); }

Просмотреть файл

@ -44,6 +44,13 @@ void HTMLDialogElement::Close(
ErrorResult ignored;
SetOpen(false, ignored);
ignored.SuppressException();
Document* doc = OwnerDoc();
auto predictFunc = [self = RefPtr<HTMLDialogElement>(this)](
Element* element) { return element == self; };
doc->TopLayerPop(predictFunc);
RefPtr<AsyncEventDispatcher> eventDispatcher = new AsyncEventDispatcher(
this, NS_LITERAL_STRING("close"), CanBubble::eNo);
eventDispatcher->PostDOMEvent();
@ -58,12 +65,32 @@ void HTMLDialogElement::Show() {
ignored.SuppressException();
}
bool HTMLDialogElement::IsInTopLayer() const {
return OwnerDoc()->DoesTopLayerContain(this);
}
void HTMLDialogElement::UnbindFromTree(bool aNullParent) {
if (IsInTopLayer()) {
Document* doc = OwnerDoc();
auto predictFunc = [self = RefPtr<HTMLDialogElement>(this)](
Element* element) { return element == self; };
doc->TopLayerPop(predictFunc);
}
nsGenericHTMLElement::UnbindFromTree(aNullParent);
}
void HTMLDialogElement::ShowModal(ErrorResult& aError) {
if (!IsInComposedDoc() || Open()) {
aError.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return;
}
Document* doc = OwnerDoc();
if (!IsInTopLayer()) {
doc->TopLayerPush(this);
}
SetOpen(true, aError);
aError.SuppressException();
}

Просмотреть файл

@ -37,10 +37,14 @@ class HTMLDialogElement final : public nsGenericHTMLElement {
mReturnValue = aReturnValue;
}
virtual void UnbindFromTree(bool aNullParent = true) override;
void Close(const mozilla::dom::Optional<nsAString>& aReturnValue);
void Show();
void ShowModal(ErrorResult& aError);
bool IsInTopLayer() const;
nsString mReturnValue;
protected: