Bug 2059312 - Part 2: Add MathMLAnchorElement class and WebIDL bindings r=emilio,webidl,firefox-svg-reviewers
Add the MathMLAnchorElement C++ class, WebIDL binding, and feature pref (mathml.a.element.enabled). Add basic href navigation, target attribute handling and HyperlinkElementUtils mixin implementation. Extract a helper function in the Link base class to handle focusability decisions for HTML, SVG, and MathML anchor elements. I2P: https://groups.google.com/u/1/a/mozilla.org/g/dev-platform/c/UHg0HwA_A6I Differential Revision: https://phabricator.services.mozilla.com/D315266
This commit is contained in:
committed by
ealvarez@mozilla.com
parent
df4e34ff76
commit
15734edd64
@@ -5,6 +5,7 @@
|
||||
#include "Link.h"
|
||||
|
||||
#include "mozilla/Components.h"
|
||||
#include "mozilla/FocusModel.h"
|
||||
#include "mozilla/IHistory.h"
|
||||
#include "mozilla/StaticPrefs_dom.h"
|
||||
#include "mozilla/dom/BindContext.h"
|
||||
@@ -15,6 +16,7 @@
|
||||
#include "mozilla/dom/SpeculationRules.h"
|
||||
#include "nsAttrValueInlines.h"
|
||||
#include "nsGkAtoms.h"
|
||||
#include "nsIContentInlines.h" // for nsINode::IsInDesignMode()
|
||||
#include "nsIURIMutator.h"
|
||||
#include "nsIURIWithSizeOf.h"
|
||||
#include "nsLayoutUtils.h"
|
||||
@@ -393,6 +395,39 @@ void Link::BindToTree(const BindContext& aContext) {
|
||||
ResetLinkState(false);
|
||||
}
|
||||
|
||||
Focusable Link::IsLinkFocusableWithoutStyle(IsFocusableFlags aFlags) const {
|
||||
Element* element = GetElement();
|
||||
MOZ_ASSERT(element);
|
||||
|
||||
// Links/Elements cannot be focused if:
|
||||
// 1. Not in a composed document.
|
||||
// 2. In designMode (where only the document itself is focusable).
|
||||
// 3. Document link handling is disabled.
|
||||
// 4. Node is inside an editable region (Links in an editable region should
|
||||
// never be focusable, even if in a contenteditable="false" region).
|
||||
if (!element->IsInComposedDoc() || element->IsInDesignMode() ||
|
||||
!element->OwnerDoc()->LinkHandlingEnabled() ||
|
||||
nsContentUtils::IsNodeInEditableRegion(element)) {
|
||||
return {};
|
||||
}
|
||||
|
||||
int32_t tabIndex = element->TabIndex();
|
||||
|
||||
// If the element is not actually a link (e.g. <a> without href):
|
||||
// Not tabbable or focusable unless forced to be via the presence of a
|
||||
// tabindex attribute (Bug 17605).
|
||||
if (!element->IsLink()) {
|
||||
return element->GetTabIndexAttrValue().isSome() ? Focusable{true, tabIndex}
|
||||
: Focusable{};
|
||||
}
|
||||
|
||||
if (!FocusModel::IsTabFocusable(TabFocusableType::Links)) {
|
||||
tabIndex = -1;
|
||||
}
|
||||
|
||||
return {true, tabIndex};
|
||||
}
|
||||
|
||||
void Link::ResetLinkState(bool aNotify, bool aHasHref) {
|
||||
// If we have an href, we should register with the history.
|
||||
mNeedsRegistration = aHasHref;
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
#include "mozilla/dom/RustTypes.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsWrapperCache.h" // For nsWrapperCache::FlagsType
|
||||
|
||||
class nsIURI;
|
||||
@@ -78,6 +79,12 @@ class Link : public nsISupports {
|
||||
void GetPort(nsACString& aPort);
|
||||
void GetHash(nsACString& aHash);
|
||||
|
||||
/**
|
||||
* Helper function for link elements (HTML/SVG/MathML anchor elements)
|
||||
* to evaluate focusability based on common link-handling constraints.
|
||||
*/
|
||||
Focusable IsLinkFocusableWithoutStyle(IsFocusableFlags aFlags) const;
|
||||
|
||||
/**
|
||||
* Invalidates any link caching, and resets the state to the default.
|
||||
*
|
||||
|
||||
@@ -814,6 +814,10 @@ DOMInterfaces = {
|
||||
'concrete': True,
|
||||
},
|
||||
|
||||
'MathMLElement': {
|
||||
'concrete': True,
|
||||
},
|
||||
|
||||
'SVGFEFuncAElement': {
|
||||
'headerFile': 'mozilla/dom/SVGComponentTransferFunctionElement.h',
|
||||
},
|
||||
|
||||
@@ -90,36 +90,10 @@ bool HTMLAnchorElement::IsHTMLFocusable(IsFocusableFlags aFlags,
|
||||
return true;
|
||||
}
|
||||
|
||||
// cannot focus links if there is no link handler
|
||||
if (!OwnerDoc()->LinkHandlingEnabled()) {
|
||||
*aTabIndex = -1;
|
||||
*aIsFocusable = false;
|
||||
return false;
|
||||
}
|
||||
Focusable focusable = Link::IsLinkFocusableWithoutStyle(aFlags);
|
||||
*aIsFocusable = focusable.mFocusable;
|
||||
*aTabIndex = focusable.mTabIndex;
|
||||
|
||||
// Links that are in an editable region should never be focusable, even if
|
||||
// they are in a contenteditable="false" region.
|
||||
if (nsContentUtils::IsNodeInEditableRegion(this)) {
|
||||
*aTabIndex = -1;
|
||||
*aIsFocusable = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (GetTabIndexAttrValue().isNothing()) {
|
||||
// check whether we're actually a link
|
||||
if (!IsLink()) {
|
||||
// Not tabbable or focusable without href (bug 17605), unless
|
||||
// forced to be via presence of nonnegative tabindex attribute
|
||||
*aTabIndex = -1;
|
||||
*aIsFocusable = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!FocusModel::IsTabFocusable(TabFocusableType::Links)) {
|
||||
*aTabIndex = -1;
|
||||
}
|
||||
*aIsFocusable = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
/* 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/. */
|
||||
|
||||
#include "mozilla/dom/MathMLAnchorElement.h"
|
||||
|
||||
#include "mozilla/dom/Document.h"
|
||||
#include "mozilla/dom/MathMLAnchorElementBinding.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsGkAtoms.h"
|
||||
|
||||
namespace mozilla::dom {
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED(MathMLAnchorElement, MathMLElement)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(MathMLAnchorElement)
|
||||
NS_INTERFACE_MAP_ENTRY(Link)
|
||||
NS_INTERFACE_MAP_END_INHERITING(MathMLElement)
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(MathMLAnchorElement, MathMLElement)
|
||||
NS_IMPL_RELEASE_INHERITED(MathMLAnchorElement, MathMLElement)
|
||||
|
||||
MathMLAnchorElement::MathMLAnchorElement(
|
||||
already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo)
|
||||
: MathMLElement(std::move(aNodeInfo)) {}
|
||||
|
||||
JSObject* MathMLAnchorElement::WrapNode(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aGivenProto) {
|
||||
return MathMLAnchorElement_Binding::Wrap(aCx, this, aGivenProto);
|
||||
}
|
||||
|
||||
void MathMLAnchorElement::GetBaseTarget(nsAString& aValue) const {
|
||||
OwnerDoc()->GetBaseTarget(aValue);
|
||||
}
|
||||
|
||||
void MathMLAnchorElement::GetLinkTargetImpl(nsAString& aTarget) {
|
||||
GetAttr(nsGkAtoms::target, aTarget);
|
||||
if (aTarget.IsEmpty()) {
|
||||
GetBaseTarget(aTarget);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMPL_ELEMENT_CLONE(MathMLAnchorElement)
|
||||
|
||||
} // namespace mozilla::dom
|
||||
@@ -0,0 +1,67 @@
|
||||
/* 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 mozilla_dom_MathMLAnchorElement_h
|
||||
#define mozilla_dom_MathMLAnchorElement_h
|
||||
|
||||
#include "MathMLElement.h"
|
||||
#include "nsDOMTokenList.h"
|
||||
|
||||
namespace mozilla::dom {
|
||||
|
||||
// FIXME: We should also inherit from Link once we migrate link behavior from
|
||||
// MathMLElement. Since MathMLElement already inherits from Link, we need to
|
||||
// prevent diamond inheritance for now.
|
||||
class MathMLAnchorElement final : public MathMLElement {
|
||||
public:
|
||||
explicit MathMLAnchorElement(
|
||||
already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo);
|
||||
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(MathMLAnchorElement, MathMLElement)
|
||||
|
||||
// nsISupports
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
void GetHref(nsAString& aHref) const {
|
||||
GetURIAttr(nsGkAtoms::href, nullptr, aHref);
|
||||
}
|
||||
|
||||
void SetHref(const nsAString& aHref, ErrorResult& aRv) {
|
||||
SetAttr(nsGkAtoms::href, aHref, aRv);
|
||||
}
|
||||
|
||||
void GetTarget(nsAString& aValue) const {
|
||||
if (!GetAttr(nsGkAtoms::target, aValue)) {
|
||||
GetBaseTarget(aValue);
|
||||
}
|
||||
}
|
||||
void SetTarget(const nsAString& aValue, ErrorResult& aRv) {
|
||||
SetAttr(nsGkAtoms::target, aValue, aRv);
|
||||
}
|
||||
|
||||
void GetHreflang(DOMString& aValue) const {
|
||||
GetAttr(nsGkAtoms::hreflang, aValue);
|
||||
}
|
||||
void SetHreflang(const nsAString& aValue, mozilla::ErrorResult& rv) {
|
||||
SetAttr(nsGkAtoms::hreflang, aValue, rv);
|
||||
}
|
||||
void GetType(DOMString& aValue) const { GetAttr(nsGkAtoms::type, aValue); }
|
||||
void SetType(const nsAString& aValue, mozilla::ErrorResult& rv) {
|
||||
SetAttr(nsGkAtoms::type, aValue, rv);
|
||||
}
|
||||
|
||||
void GetBaseTarget(nsAString& aValue) const;
|
||||
void GetLinkTargetImpl(nsAString& aTarget) override;
|
||||
|
||||
nsresult Clone(dom::NodeInfo*, nsINode** aResult) const override;
|
||||
|
||||
protected:
|
||||
virtual ~MathMLAnchorElement() = default;
|
||||
JSObject* WrapNode(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aGivenProto) override;
|
||||
};
|
||||
|
||||
} // namespace mozilla::dom
|
||||
|
||||
#endif
|
||||
@@ -687,37 +687,8 @@ int32_t MathMLElement::TabIndexDefault() {
|
||||
return mNodeInfo->Equals(nsGkAtoms::a) ? 0 : -1;
|
||||
}
|
||||
|
||||
// XXX Bug 1586011: Share logic with other element classes.
|
||||
Focusable MathMLElement::IsFocusableWithoutStyle(IsFocusableFlags) {
|
||||
if (!IsInComposedDoc() || IsInDesignMode()) {
|
||||
// In designMode documents we only allow focusing the document.
|
||||
return {};
|
||||
}
|
||||
|
||||
int32_t tabIndex = TabIndex();
|
||||
if (!IsLink()) {
|
||||
// If a tabindex is specified at all we're focusable
|
||||
if (GetTabIndexAttrValue().isSome()) {
|
||||
return {true, tabIndex};
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!OwnerDoc()->LinkHandlingEnabled()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
// Links that are in an editable region should never be focusable, even if
|
||||
// they are in a contenteditable="false" region.
|
||||
if (nsContentUtils::IsNodeInEditableRegion(this)) {
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!FocusModel::IsTabFocusable(TabFocusableType::Links)) {
|
||||
tabIndex = -1;
|
||||
}
|
||||
|
||||
return {true, tabIndex};
|
||||
Focusable MathMLElement::IsFocusableWithoutStyle(IsFocusableFlags aFlags) {
|
||||
return Link::IsLinkFocusableWithoutStyle(aFlags);
|
||||
}
|
||||
|
||||
already_AddRefed<nsIURI> MathMLElement::GetHrefURI() const {
|
||||
|
||||
@@ -22,7 +22,7 @@ using MathMLElementBase = nsStyledElement;
|
||||
/*
|
||||
* The base class for MathML elements.
|
||||
*/
|
||||
class MathMLElement final : public MathMLElementBase, public Link {
|
||||
class MathMLElement : public MathMLElementBase, public Link {
|
||||
public:
|
||||
explicit MathMLElement(already_AddRefed<mozilla::dom::NodeInfo>& aNodeInfo);
|
||||
explicit MathMLElement(already_AddRefed<mozilla::dom::NodeInfo> aNodeInfo);
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
* 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/StaticPrefs_mathml.h"
|
||||
#include "mozilla/dom/MathMLAnchorElement.h"
|
||||
#include "mozilla/dom/MathMLElement.h"
|
||||
#include "nsContentCreatorFunctions.h"
|
||||
|
||||
@@ -11,7 +13,15 @@ using namespace mozilla::dom;
|
||||
nsresult NS_NewMathMLElement(
|
||||
Element** aResult, already_AddRefed<mozilla::dom::NodeInfo> aNodeInfo) {
|
||||
RefPtr<mozilla::dom::NodeInfo> nodeInfo(aNodeInfo);
|
||||
|
||||
auto* nim = nodeInfo->NodeInfoManager();
|
||||
|
||||
if (nodeInfo->NameAtom() == nsGkAtoms::a &&
|
||||
mozilla::StaticPrefs::mathml_a_element_enabled()) {
|
||||
NS_ADDREF(*aResult = new (nim) MathMLAnchorElement(nodeInfo.forget()));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_ADDREF(*aResult = new (nim) MathMLElement(nodeInfo.forget()));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@@ -6,10 +6,12 @@ with Files("**"):
|
||||
BUG_COMPONENT = ("Core", "MathML")
|
||||
|
||||
EXPORTS.mozilla.dom += [
|
||||
"MathMLAnchorElement.h",
|
||||
"MathMLElement.h",
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
"MathMLAnchorElement.cpp",
|
||||
"MathMLElement.cpp",
|
||||
"MathMLElementFactory.cpp",
|
||||
]
|
||||
|
||||
+2
-23
@@ -145,34 +145,13 @@ void SVGAElement::UnbindFromTree(UnbindContext& aContext) {
|
||||
|
||||
int32_t SVGAElement::TabIndexDefault() { return 0; }
|
||||
|
||||
Focusable SVGAElement::IsFocusableWithoutStyle(IsFocusableFlags) {
|
||||
Focusable SVGAElement::IsFocusableWithoutStyle(IsFocusableFlags aFlags) {
|
||||
Focusable result;
|
||||
if (IsSVGFocusable(&result.mFocusable, &result.mTabIndex)) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (!OwnerDoc()->LinkHandlingEnabled()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
// Links that are in an editable region should never be focusable, even if
|
||||
// they are in a contenteditable="false" region.
|
||||
if (nsContentUtils::IsNodeInEditableRegion(this)) {
|
||||
return {};
|
||||
}
|
||||
|
||||
if (GetTabIndexAttrValue().isNothing()) {
|
||||
// check whether we're actually a link
|
||||
if (!IsLink()) {
|
||||
// Not tabbable or focusable without href (bug 17605), unless
|
||||
// forced to be via presence of nonnegative tabindex attribute
|
||||
return {};
|
||||
}
|
||||
}
|
||||
if (!FocusModel::IsTabFocusable(TabFocusableType::Links)) {
|
||||
result.mTabIndex = -1;
|
||||
}
|
||||
return result;
|
||||
return Link::IsLinkFocusableWithoutStyle(aFlags);
|
||||
}
|
||||
|
||||
bool SVGAElement::HasHref() const {
|
||||
|
||||
@@ -979,6 +979,8 @@ let interfaceNamesInGlobalScope = [
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{ name: "MIDIPort", android: false },
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{ name: "MathMLAnchorElement", insecureContext: true, nightly: true },
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{ name: "MathMLElement", insecureContext: true },
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{ name: "MediaCapabilities", insecureContext: true },
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
/* 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/.
|
||||
*
|
||||
* The origin of this IDL file is
|
||||
* https://w3c.github.io/mathml-core/#dom-mathmlanchorelement
|
||||
*/
|
||||
|
||||
[
|
||||
Exposed=Window,
|
||||
Pref="mathml.a.element.enabled"
|
||||
]
|
||||
interface MathMLAnchorElement : MathMLElement {
|
||||
[HTMLConstructor] constructor();
|
||||
|
||||
[CEReactions, SetterThrows] attribute USVString href;
|
||||
[CEReactions, SetterThrows] attribute DOMString target;
|
||||
};
|
||||
|
||||
MathMLAnchorElement includes HyperlinkElementUtils;
|
||||
@@ -784,6 +784,7 @@ WEBIDL_FILES = [
|
||||
"Lock.webidl",
|
||||
"LockManager.webidl",
|
||||
"LoginStatus.webidl",
|
||||
"MathMLAnchorElement.webidl",
|
||||
"MathMLElement.webidl",
|
||||
"MediaCapabilities.webidl",
|
||||
"MediaDebugInfo.webidl",
|
||||
|
||||
@@ -12004,6 +12004,12 @@
|
||||
# Prefs starting with "mathml."
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# Enable MathMLAnchorElement dom interface (MathML <a> element).
|
||||
- name: mathml.a.element.enabled
|
||||
type: bool
|
||||
value: @IS_NIGHTLY_BUILD@
|
||||
mirror: always
|
||||
|
||||
# Enable scale transform for stretchy MathML operators. See bug 414277.
|
||||
- name: mathml.scale_stretchy_operators.enabled
|
||||
type: bool
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
[a-hreflang-getter.html]
|
||||
[Test anchor's hreflang getter]
|
||||
expected: FAIL
|
||||
@@ -1,3 +0,0 @@
|
||||
[a-hreflang-setter.html]
|
||||
[Test anchor's hreflang setter]
|
||||
expected: FAIL
|
||||
@@ -1,3 +0,0 @@
|
||||
[a-type-getter-001.html]
|
||||
[Test anchor's type getter when empty]
|
||||
expected: FAIL
|
||||
@@ -1,3 +0,0 @@
|
||||
[a-type-getter-002.html]
|
||||
[Test anchor's type getter]
|
||||
expected: FAIL
|
||||
@@ -1,3 +0,0 @@
|
||||
[a-type-setter.html]
|
||||
[Test anchor's type setter]
|
||||
expected: FAIL
|
||||
-42
@@ -1,42 +0,0 @@
|
||||
[anchor-hyperlinkutils-getter-setter.html]
|
||||
[Getter and setter for attribute of anchor element(0): hash]
|
||||
expected: FAIL
|
||||
|
||||
[Getter and setter for attribute of anchor element(1): hash]
|
||||
expected: FAIL
|
||||
|
||||
[Getter and setter for attribute of anchor element(2): host]
|
||||
expected: FAIL
|
||||
|
||||
[Getter and setter for attribute of anchor element(3): hostname]
|
||||
expected: FAIL
|
||||
|
||||
[Getter and setter for attribute of anchor element(5): password]
|
||||
expected: FAIL
|
||||
|
||||
[Getter and setter for attribute of anchor element(6): pathname]
|
||||
expected: FAIL
|
||||
|
||||
[Getter and setter for attribute of anchor element(7): port]
|
||||
expected: FAIL
|
||||
|
||||
[Getter and setter for attribute of anchor element(8): protocol]
|
||||
expected: FAIL
|
||||
|
||||
[Getter and setter for attribute of anchor element(9): protocol]
|
||||
expected: FAIL
|
||||
|
||||
[Getter and setter for attribute of anchor element(10): search]
|
||||
expected: FAIL
|
||||
|
||||
[Getter and setter for attribute of anchor element(11): search]
|
||||
expected: FAIL
|
||||
|
||||
[Getter and setter for attribute of anchor element(12): search]
|
||||
expected: FAIL
|
||||
|
||||
[Getter and setter for attribute of anchor element(13): search]
|
||||
expected: FAIL
|
||||
|
||||
[Getter and setter for attribute of anchor element(14): username]
|
||||
expected: FAIL
|
||||
-30
@@ -1,30 +0,0 @@
|
||||
[anchor-hyperlinkutils-getter.html]
|
||||
[Getter for attribute of anchor element(0): search]
|
||||
expected: FAIL
|
||||
|
||||
[Getter for attribute of anchor element(1): hash]
|
||||
expected: FAIL
|
||||
|
||||
[Getter for attribute of anchor element(2): host]
|
||||
expected: FAIL
|
||||
|
||||
[Getter for attribute of anchor element(3): hostname]
|
||||
expected: FAIL
|
||||
|
||||
[Getter for attribute of anchor element(4): href]
|
||||
expected: FAIL
|
||||
|
||||
[Getter for attribute of anchor element(5): password]
|
||||
expected: FAIL
|
||||
|
||||
[Getter for attribute of anchor element(6): pathname]
|
||||
expected: FAIL
|
||||
|
||||
[Getter for attribute of anchor element(7): port]
|
||||
expected: FAIL
|
||||
|
||||
[Getter for attribute of anchor element(8): protocol]
|
||||
expected: FAIL
|
||||
|
||||
[Getter for attribute of anchor element(9): username]
|
||||
expected: FAIL
|
||||
@@ -1,5 +0,0 @@
|
||||
[href-navigation.html]
|
||||
expected:
|
||||
if (os == "android") and debug: [ERROR, CRASH]
|
||||
if (os == "android") and not debug: [ERROR, CRASH]
|
||||
ERROR
|
||||
@@ -0,0 +1,51 @@
|
||||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<title>MathML a element target attribute navigation and base element fallback</title>
|
||||
<link rel="help" href="https://html.spec.whatwg.org/multipage/links.html#get-an-element's-target">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script src="/resources/testdriver.js"></script>
|
||||
<script src="/resources/testdriver-vendor.js"></script>
|
||||
|
||||
<base target="frame_base_target">
|
||||
|
||||
<iframe name="frame_base_target" id="frame_base_target"></iframe>
|
||||
|
||||
<math>
|
||||
<!-- Link with target="" (empty string); Empty target falls back to <base target> -->
|
||||
<a id="link_empty_target" href="/common/blank.html?target=empty_fallback" target="">
|
||||
<mtext>Link Empty Target</mtext>
|
||||
</a>
|
||||
</math>
|
||||
|
||||
<script>
|
||||
function waitForFrameLoad(iframe) {
|
||||
return new Promise(resolve => {
|
||||
function checkAndResolve() {
|
||||
const currentUrl = iframe.contentWindow.location.href;
|
||||
if (currentUrl && currentUrl !== "about:blank") {
|
||||
iframe.removeEventListener('load', checkAndResolve);
|
||||
resolve(currentUrl);
|
||||
}
|
||||
}
|
||||
iframe.addEventListener('load', checkAndResolve);
|
||||
});
|
||||
}
|
||||
|
||||
// Target attribute set to empty string ("") falls back to <base target> in engines
|
||||
promise_test(async () => {
|
||||
const frameBase = document.getElementById("frame_base_target");
|
||||
const link = document.getElementById("link_empty_target");
|
||||
|
||||
const navigationLoaded = waitForFrameLoad(frameBase);
|
||||
|
||||
await test_driver.click(link);
|
||||
|
||||
const url = await navigationLoaded;
|
||||
assert_true(
|
||||
url.includes("target=empty_fallback"),
|
||||
"Link with target='' falls back to <base target> when <base> is present"
|
||||
);
|
||||
|
||||
}, "MathML <a> with target='' falls back to <base target>");
|
||||
</script>
|
||||
Reference in New Issue
Block a user