2015-05-03 22:32:37 +03:00
|
|
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
2012-05-21 15:12:37 +04:00
|
|
|
/* 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/. */
|
2006-03-31 12:00:42 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Base class for all element classes; this provides an implementation
|
2006-03-31 12:41:49 +04:00
|
|
|
* of DOM Core's nsIDOMElement, implements nsIContent, provides
|
|
|
|
* utility methods for subclasses, and so forth.
|
2006-03-31 12:00:42 +04:00
|
|
|
*/
|
|
|
|
|
2013-10-03 00:09:18 +04:00
|
|
|
#include "mozilla/dom/ElementInlines.h"
|
1998-11-12 01:06:16 +03:00
|
|
|
|
2014-07-16 04:02:31 +04:00
|
|
|
#include "AnimationCommon.h"
|
2013-08-14 10:55:46 +04:00
|
|
|
#include "mozilla/DebugOnly.h"
|
2015-04-21 04:22:09 +03:00
|
|
|
#include "mozilla/dom/Animation.h"
|
2013-04-09 19:29:44 +04:00
|
|
|
#include "mozilla/dom/Attr.h"
|
2016-07-06 21:45:18 +03:00
|
|
|
#include "mozilla/dom/Grid.h"
|
1999-01-12 19:37:24 +03:00
|
|
|
#include "nsDOMAttributeMap.h"
|
1998-11-12 01:06:16 +03:00
|
|
|
#include "nsIAtom.h"
|
2013-10-02 15:40:07 +04:00
|
|
|
#include "nsIContentInlines.h"
|
2014-06-20 06:01:40 +04:00
|
|
|
#include "mozilla/dom/NodeInfo.h"
|
2013-01-13 01:53:01 +04:00
|
|
|
#include "nsIDocumentInlines.h"
|
2016-01-29 04:37:52 +03:00
|
|
|
#include "mozilla/dom/DocumentTimeline.h"
|
1998-11-12 01:06:16 +03:00
|
|
|
#include "nsIDOMNodeList.h"
|
1998-11-30 10:59:11 +03:00
|
|
|
#include "nsIDOMDocument.h"
|
2005-06-01 17:59:38 +04:00
|
|
|
#include "nsIContentIterator.h"
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
#include "nsFocusManager.h"
|
2014-11-20 21:24:09 +03:00
|
|
|
#include "nsFrameManager.h"
|
1998-11-12 01:06:16 +03:00
|
|
|
#include "nsILinkHandler.h"
|
|
|
|
#include "nsIScriptGlobalObject.h"
|
|
|
|
#include "nsIURL.h"
|
2014-05-25 02:20:39 +04:00
|
|
|
#include "nsContainerFrame.h"
|
2010-02-11 20:34:01 +03:00
|
|
|
#include "nsIAnonymousContentCreator.h"
|
1998-11-12 01:06:16 +03:00
|
|
|
#include "nsIPresShell.h"
|
2004-08-01 03:15:21 +04:00
|
|
|
#include "nsPresContext.h"
|
2001-07-16 06:40:48 +04:00
|
|
|
#include "nsStyleConsts.h"
|
1998-11-12 01:06:16 +03:00
|
|
|
#include "nsString.h"
|
2001-12-16 14:58:03 +03:00
|
|
|
#include "nsUnicharUtils.h"
|
2000-12-30 22:22:22 +03:00
|
|
|
#include "nsIDOMEvent.h"
|
1998-11-12 01:06:16 +03:00
|
|
|
#include "nsDOMCID.h"
|
|
|
|
#include "nsIServiceManager.h"
|
|
|
|
#include "nsIDOMCSSStyleDeclaration.h"
|
2009-09-03 04:28:37 +04:00
|
|
|
#include "nsDOMCSSAttrDeclaration.h"
|
2014-02-28 03:04:46 +04:00
|
|
|
#include "nsNameSpaceManager.h"
|
1999-01-18 06:43:43 +03:00
|
|
|
#include "nsContentList.h"
|
2014-02-18 05:12:54 +04:00
|
|
|
#include "nsVariant.h"
|
2009-08-12 12:55:14 +04:00
|
|
|
#include "nsDOMTokenList.h"
|
2011-02-11 10:47:00 +03:00
|
|
|
#include "nsXBLPrototypeBinding.h"
|
2012-07-27 18:03:27 +04:00
|
|
|
#include "nsError.h"
|
2004-04-01 23:44:17 +04:00
|
|
|
#include "nsDOMString.h"
|
2003-10-22 02:11:49 +04:00
|
|
|
#include "nsIScriptSecurityManager.h"
|
2000-11-27 10:55:20 +03:00
|
|
|
#include "nsIDOMMutationEvent.h"
|
2016-01-29 04:37:52 +03:00
|
|
|
#include "mozilla/dom/AnimatableBinding.h"
|
2015-06-09 05:13:54 +03:00
|
|
|
#include "mozilla/AnimationComparator.h"
|
2014-03-17 10:56:54 +04:00
|
|
|
#include "mozilla/AsyncEventDispatcher.h"
|
2013-09-25 15:21:20 +04:00
|
|
|
#include "mozilla/ContentEvents.h"
|
2015-11-26 10:53:53 +03:00
|
|
|
#include "mozilla/EffectSet.h"
|
2014-03-18 08:48:21 +04:00
|
|
|
#include "mozilla/EventDispatcher.h"
|
2014-03-17 10:56:53 +04:00
|
|
|
#include "mozilla/EventListenerManager.h"
|
2014-04-01 08:09:23 +04:00
|
|
|
#include "mozilla/EventStateManager.h"
|
2014-04-03 08:18:36 +04:00
|
|
|
#include "mozilla/EventStates.h"
|
2014-02-27 14:51:15 +04:00
|
|
|
#include "mozilla/InternalMutationEvent.h"
|
2013-09-25 15:21:18 +04:00
|
|
|
#include "mozilla/MouseEvents.h"
|
2013-09-25 15:21:19 +04:00
|
|
|
#include "mozilla/TextEvents.h"
|
2006-07-02 11:23:10 +04:00
|
|
|
#include "nsNodeUtils.h"
|
2012-04-17 08:03:10 +04:00
|
|
|
#include "mozilla/dom/DirectionalityUtils.h"
|
2007-02-01 18:14:00 +03:00
|
|
|
#include "nsDocument.h"
|
2012-02-14 06:00:56 +04:00
|
|
|
#include "nsAttrValueOrString.h"
|
2012-09-30 20:40:24 +04:00
|
|
|
#include "nsAttrValueInlines.h"
|
2016-02-18 04:21:00 +03:00
|
|
|
#include "nsCSSPseudoElements.h"
|
2007-07-09 04:58:15 +04:00
|
|
|
#ifdef MOZ_XUL
|
2007-05-16 05:13:47 +04:00
|
|
|
#include "nsXULElement.h"
|
2007-07-09 04:58:15 +04:00
|
|
|
#endif /* MOZ_XUL */
|
2014-05-30 11:36:53 +04:00
|
|
|
#include "nsSVGElement.h"
|
2008-02-20 10:40:04 +03:00
|
|
|
#include "nsFrameSelection.h"
|
2011-12-20 13:15:41 +04:00
|
|
|
#ifdef DEBUG
|
2012-01-10 18:19:54 +04:00
|
|
|
#include "nsRange.h"
|
2011-12-20 13:15:41 +04:00
|
|
|
#endif
|
1998-11-12 01:06:16 +03:00
|
|
|
|
2007-02-17 02:02:08 +03:00
|
|
|
#include "nsBindingManager.h"
|
2005-02-26 01:07:01 +03:00
|
|
|
#include "nsXBLBinding.h"
|
2000-11-27 10:55:20 +03:00
|
|
|
#include "nsPIDOMWindow.h"
|
2000-12-10 12:19:59 +03:00
|
|
|
#include "nsPIBoxObject.h"
|
2013-09-20 14:21:03 +04:00
|
|
|
#include "mozilla/dom/DOMRect.h"
|
2007-05-31 02:32:54 +04:00
|
|
|
#include "nsSVGUtils.h"
|
|
|
|
#include "nsLayoutUtils.h"
|
2007-01-30 03:06:41 +03:00
|
|
|
#include "nsGkAtoms.h"
|
2001-02-19 15:55:42 +03:00
|
|
|
#include "nsContentUtils.h"
|
2013-05-02 02:50:08 +04:00
|
|
|
#include "ChildIterator.h"
|
2000-05-26 03:48:45 +04:00
|
|
|
|
2001-03-13 14:37:16 +03:00
|
|
|
#include "nsIDOMEventListener.h"
|
2004-11-04 04:24:05 +03:00
|
|
|
#include "nsIWebNavigation.h"
|
|
|
|
#include "nsIBaseWindow.h"
|
2011-11-27 15:51:53 +04:00
|
|
|
#include "nsIWidget.h"
|
2004-11-04 04:24:05 +03:00
|
|
|
|
2004-06-25 16:26:02 +04:00
|
|
|
#include "nsNodeInfoManager.h"
|
2005-02-19 00:32:46 +03:00
|
|
|
#include "nsICategoryManager.h"
|
2005-10-01 00:06:33 +04:00
|
|
|
#include "nsIDOMDocumentType.h"
|
2009-02-10 23:56:51 +03:00
|
|
|
#include "nsGenericHTMLElement.h"
|
2008-02-20 10:40:04 +03:00
|
|
|
#include "nsIEditor.h"
|
2010-05-04 21:40:39 +04:00
|
|
|
#include "nsIEditorIMESupport.h"
|
2006-07-19 08:36:36 +04:00
|
|
|
#include "nsContentCreatorFunctions.h"
|
2007-03-08 14:17:16 +03:00
|
|
|
#include "nsIControllers.h"
|
2013-01-03 17:23:11 +04:00
|
|
|
#include "nsView.h"
|
2013-01-05 07:12:24 +04:00
|
|
|
#include "nsViewManager.h"
|
2008-08-16 02:26:37 +04:00
|
|
|
#include "nsIScrollableFrame.h"
|
2011-03-11 05:48:57 +03:00
|
|
|
#include "mozilla/css/StyleRule.h" /* For nsCSSSelectorList */
|
2008-07-22 04:55:52 +04:00
|
|
|
#include "nsCSSRuleProcessor.h"
|
2009-08-01 19:53:40 +04:00
|
|
|
#include "nsRuleProcessorData.h"
|
2011-08-16 04:55:20 +04:00
|
|
|
#include "nsTextNode.h"
|
2008-07-22 04:55:52 +04:00
|
|
|
|
2007-07-09 04:58:15 +04:00
|
|
|
#ifdef MOZ_XUL
|
2007-05-25 04:28:20 +04:00
|
|
|
#include "nsIXULDocument.h"
|
2007-07-09 04:58:15 +04:00
|
|
|
#endif /* MOZ_XUL */
|
2007-01-05 01:31:26 +03:00
|
|
|
|
|
|
|
#include "nsCycleCollectionParticipant.h"
|
2007-05-11 00:21:12 +04:00
|
|
|
#include "nsCCUncollectableMarker.h"
|
2007-01-05 01:31:26 +03:00
|
|
|
|
2008-04-11 21:29:06 +04:00
|
|
|
#include "mozAutoDocUpdate.h"
|
|
|
|
|
2010-03-02 23:59:32 +03:00
|
|
|
#include "nsCSSParser.h"
|
2010-09-15 08:46:40 +04:00
|
|
|
#include "prprf.h"
|
2012-03-31 20:30:13 +04:00
|
|
|
#include "nsDOMMutationObserver.h"
|
2009-05-07 23:37:33 +04:00
|
|
|
#include "nsSVGFeatures.h"
|
2011-05-26 23:58:35 +04:00
|
|
|
#include "nsWrapperCacheInlines.h"
|
2011-08-24 23:49:25 +04:00
|
|
|
#include "xpcpublic.h"
|
2012-05-18 12:29:40 +04:00
|
|
|
#include "nsIScriptError.h"
|
2012-03-01 17:09:00 +04:00
|
|
|
#include "mozilla/Telemetry.h"
|
2011-08-24 23:49:25 +04:00
|
|
|
|
2012-03-10 20:13:51 +04:00
|
|
|
#include "mozilla/CORSMode.h"
|
2013-12-02 14:26:11 +04:00
|
|
|
#include "mozilla/dom/ShadowRoot.h"
|
2014-05-22 10:11:53 +04:00
|
|
|
#include "mozilla/dom/NodeListBinding.h"
|
2012-03-10 20:13:51 +04:00
|
|
|
|
2012-03-22 08:10:51 +04:00
|
|
|
#include "nsStyledElement.h"
|
2012-10-16 15:51:00 +04:00
|
|
|
#include "nsXBLService.h"
|
2012-12-24 06:38:41 +04:00
|
|
|
#include "nsITextControlElement.h"
|
2013-04-07 17:30:25 +04:00
|
|
|
#include "nsITextControlFrame.h"
|
2013-08-08 00:23:08 +04:00
|
|
|
#include "nsISupportsImpl.h"
|
2016-03-04 02:54:00 +03:00
|
|
|
#include "mozilla/dom/CSSPseudoElement.h"
|
2013-04-10 18:15:54 +04:00
|
|
|
#include "mozilla/dom/DocumentFragment.h"
|
2016-03-04 02:54:00 +03:00
|
|
|
#include "mozilla/dom/KeyframeEffectBinding.h"
|
Bug 1045754 - Part 1 - Implement updated CSSOM-View smooth-scrolling specification. r=bz
- Added new WebIDL dictionary, ScrollToOptions. This dictionary extends
ScrollOptions by adding "left" and "top", specifying the scroll offset.
This will be later extended with more members to allow scroll offsets to be
specified with logical axes.
- Implemented Window.Scroll, Window.ScrollTo, Window.ScrollBy, Element.Scroll,
Element.ScrollTo, and Element.ScrollBy functions that accept ScrollToOptions
as a single parameter.
- Removed ScrollOptions dictionary parameter from existing Window.Scroll,
Window.ScrollTo, and Window.ScrollBy functions as these have been replaced
with functions accepting a single parameter, ScrollToOptions.
- Added new WebIDL dictionary, ScrollIntoViewOptions. This dictionary
extends ScrollOptions by adding "block", specifying whether the element
start or end will be scrolled into view.
- Replaced Element.ScrollIntoView(bool,ScrollOptions) with
Element.ScrollIntoView(ScrollIntoViewOptions) to match updated
CSSOM-View scroll-behavior specification.
2014-10-01 21:47:56 +04:00
|
|
|
#include "mozilla/dom/WindowBinding.h"
|
|
|
|
#include "mozilla/dom/ElementBinding.h"
|
2016-04-13 03:39:28 +03:00
|
|
|
#include "mozilla/dom/VRDisplay.h"
|
2016-03-04 02:54:00 +03:00
|
|
|
#include "mozilla/IntegerPrintfMacros.h"
|
2015-07-14 04:04:42 +03:00
|
|
|
#include "mozilla/Preferences.h"
|
2016-03-04 02:54:00 +03:00
|
|
|
#include "nsComputedDOMStyle.h"
|
2016-08-11 23:56:34 +03:00
|
|
|
#include "nsDOMStringMap.h"
|
2012-03-22 08:10:51 +04:00
|
|
|
|
2011-10-11 09:50:08 +04:00
|
|
|
using namespace mozilla;
|
2010-04-30 17:12:05 +04:00
|
|
|
using namespace mozilla::dom;
|
2001-08-03 11:34:28 +04:00
|
|
|
|
2014-05-30 11:36:53 +04:00
|
|
|
nsIAtom*
|
|
|
|
nsIContent::DoGetID() const
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(HasID(), "Unexpected call");
|
|
|
|
MOZ_ASSERT(IsElement(), "Only elements can have IDs");
|
|
|
|
|
|
|
|
return AsElement()->GetParsedAttr(nsGkAtoms::id)->GetAtomValue();
|
|
|
|
}
|
|
|
|
|
|
|
|
const nsAttrValue*
|
|
|
|
nsIContent::DoGetClasses() const
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(HasFlag(NODE_MAY_HAVE_CLASS), "Unexpected call");
|
|
|
|
MOZ_ASSERT(IsElement(), "Only elements can have classes");
|
|
|
|
|
2015-03-03 14:08:59 +03:00
|
|
|
if (IsSVGElement()) {
|
2014-05-30 11:36:53 +04:00
|
|
|
const nsAttrValue* animClass =
|
|
|
|
static_cast<const nsSVGElement*>(this)->GetAnimatedClassName();
|
|
|
|
if (animClass) {
|
|
|
|
return animClass;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return AsElement()->GetParsedAttr(nsGkAtoms::_class);
|
|
|
|
}
|
|
|
|
|
2013-08-08 00:23:08 +04:00
|
|
|
NS_IMETHODIMP
|
|
|
|
Element::QueryInterface(REFNSIID aIID, void** aInstancePtr)
|
|
|
|
{
|
|
|
|
NS_ASSERTION(aInstancePtr,
|
|
|
|
"QueryInterface requires a non-NULL destination!");
|
|
|
|
nsresult rv = FragmentOrElement::QueryInterface(aIID, aInstancePtr);
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Give the binding manager a chance to get an interface for this element.
|
|
|
|
return OwnerDoc()->BindingManager()->GetBindingImplementation(this, aIID,
|
|
|
|
aInstancePtr);
|
|
|
|
}
|
|
|
|
|
2014-04-03 08:18:36 +04:00
|
|
|
EventStates
|
2011-06-01 05:46:56 +04:00
|
|
|
Element::IntrinsicState() const
|
2007-06-28 06:48:16 +04:00
|
|
|
{
|
2007-07-11 17:05:05 +04:00
|
|
|
return IsEditable() ? NS_EVENT_STATE_MOZ_READWRITE :
|
|
|
|
NS_EVENT_STATE_MOZ_READONLY;
|
2007-06-28 06:48:16 +04:00
|
|
|
}
|
|
|
|
|
2011-06-01 05:46:56 +04:00
|
|
|
void
|
2014-04-03 08:18:36 +04:00
|
|
|
Element::NotifyStateChange(EventStates aStates)
|
2011-06-01 05:46:56 +04:00
|
|
|
{
|
2016-03-31 15:20:14 +03:00
|
|
|
nsIDocument* doc = GetComposedDoc();
|
2011-06-01 05:46:56 +04:00
|
|
|
if (doc) {
|
|
|
|
nsAutoScriptBlocker scriptBlocker;
|
|
|
|
doc->ContentStateChanged(this, aStates);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-06-01 05:46:57 +04:00
|
|
|
void
|
2014-04-03 08:18:36 +04:00
|
|
|
Element::UpdateLinkState(EventStates aState)
|
2011-06-01 05:46:57 +04:00
|
|
|
{
|
2015-02-10 01:34:50 +03:00
|
|
|
MOZ_ASSERT(!aState.HasAtLeastOneOfStates(~(NS_EVENT_STATE_VISITED |
|
|
|
|
NS_EVENT_STATE_UNVISITED)),
|
|
|
|
"Unexpected link state bits");
|
2011-06-01 05:46:57 +04:00
|
|
|
mState =
|
|
|
|
(mState & ~(NS_EVENT_STATE_VISITED | NS_EVENT_STATE_UNVISITED)) |
|
|
|
|
aState;
|
|
|
|
}
|
|
|
|
|
2007-06-28 06:48:16 +04:00
|
|
|
void
|
2011-06-01 05:46:57 +04:00
|
|
|
Element::UpdateState(bool aNotify)
|
2007-06-28 06:48:16 +04:00
|
|
|
{
|
2014-04-03 08:18:36 +04:00
|
|
|
EventStates oldState = mState;
|
2011-06-01 05:46:57 +04:00
|
|
|
mState = IntrinsicState() | (oldState & ESM_MANAGED_STATES);
|
|
|
|
if (aNotify) {
|
2014-04-03 08:18:36 +04:00
|
|
|
EventStates changedStates = oldState ^ mState;
|
2011-06-01 05:46:57 +04:00
|
|
|
if (!changedStates.IsEmpty()) {
|
2016-03-31 15:20:14 +03:00
|
|
|
nsIDocument* doc = GetComposedDoc();
|
2011-06-01 05:46:57 +04:00
|
|
|
if (doc) {
|
|
|
|
nsAutoScriptBlocker scriptBlocker;
|
|
|
|
doc->ContentStateChanged(this, changedStates);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2011-09-29 10:19:26 +04:00
|
|
|
nsIContent::UpdateEditableState(bool aNotify)
|
2011-06-01 05:46:57 +04:00
|
|
|
{
|
|
|
|
// Guaranteed to be non-element content
|
|
|
|
NS_ASSERTION(!IsElement(), "What happened here?");
|
2007-06-28 06:48:16 +04:00
|
|
|
nsIContent *parent = GetParent();
|
|
|
|
|
2013-04-07 17:30:25 +04:00
|
|
|
// Skip over unknown native anonymous content to avoid setting a flag we
|
|
|
|
// can't clear later
|
|
|
|
bool isUnknownNativeAnon = false;
|
|
|
|
if (IsInNativeAnonymousSubtree()) {
|
|
|
|
isUnknownNativeAnon = true;
|
|
|
|
nsCOMPtr<nsIContent> root = this;
|
|
|
|
while (root && !root->IsRootOfNativeAnonymousSubtree()) {
|
|
|
|
root = root->GetParent();
|
|
|
|
}
|
|
|
|
// root should always be true here, but isn't -- bug 999416
|
|
|
|
if (root) {
|
|
|
|
nsIFrame* rootFrame = root->GetPrimaryFrame();
|
|
|
|
if (rootFrame) {
|
2014-05-25 02:20:39 +04:00
|
|
|
nsContainerFrame* parentFrame = rootFrame->GetParent();
|
2013-04-07 17:30:25 +04:00
|
|
|
nsITextControlFrame* textCtrl = do_QueryFrame(parentFrame);
|
|
|
|
isUnknownNativeAnon = !textCtrl;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SetEditableFlag(parent && parent->HasFlag(NODE_IS_EDITABLE) &&
|
|
|
|
!isUnknownNativeAnon);
|
2007-06-28 06:48:16 +04:00
|
|
|
}
|
|
|
|
|
2011-06-01 05:46:57 +04:00
|
|
|
void
|
2012-11-15 02:10:08 +04:00
|
|
|
Element::UpdateEditableState(bool aNotify)
|
2011-06-01 05:46:57 +04:00
|
|
|
{
|
|
|
|
nsIContent *parent = GetParent();
|
|
|
|
|
|
|
|
SetEditableFlag(parent && parent->HasFlag(NODE_IS_EDITABLE));
|
2011-07-20 23:58:25 +04:00
|
|
|
if (aNotify) {
|
|
|
|
UpdateState(aNotify);
|
|
|
|
} else {
|
|
|
|
// Avoid calling UpdateState in this very common case, because
|
|
|
|
// this gets called for pretty much every single element on
|
|
|
|
// insertion into the document and UpdateState can be slow for
|
|
|
|
// some kinds of elements even when not notifying.
|
|
|
|
if (IsEditable()) {
|
|
|
|
RemoveStatesSilently(NS_EVENT_STATE_MOZ_READONLY);
|
|
|
|
AddStatesSilently(NS_EVENT_STATE_MOZ_READWRITE);
|
2011-06-01 05:46:57 +04:00
|
|
|
} else {
|
2011-07-20 23:58:25 +04:00
|
|
|
RemoveStatesSilently(NS_EVENT_STATE_MOZ_READWRITE);
|
|
|
|
AddStatesSilently(NS_EVENT_STATE_MOZ_READONLY);
|
2011-06-01 05:46:57 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-24 07:22:17 +03:00
|
|
|
int32_t
|
|
|
|
Element::TabIndex()
|
|
|
|
{
|
|
|
|
const nsAttrValue* attrVal = mAttrsAndChildren.GetAttr(nsGkAtoms::tabindex);
|
|
|
|
if (attrVal && attrVal->Type() == nsAttrValue::eInteger) {
|
|
|
|
return attrVal->GetIntegerValue();
|
|
|
|
}
|
|
|
|
|
|
|
|
return TabIndexDefault();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Element::Focus(mozilla::ErrorResult& aError)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIDOMElement> domElement = do_QueryInterface(this);
|
|
|
|
nsIFocusManager* fm = nsFocusManager::GetFocusManager();
|
|
|
|
if (fm && domElement) {
|
|
|
|
aError = fm->SetFocus(domElement, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Element::SetTabIndex(int32_t aTabIndex, mozilla::ErrorResult& aError)
|
|
|
|
{
|
|
|
|
nsAutoString value;
|
|
|
|
value.AppendInt(aTabIndex);
|
|
|
|
|
|
|
|
SetAttr(nsGkAtoms::tabindex, value, aError);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Element::Blur(mozilla::ErrorResult& aError)
|
|
|
|
{
|
|
|
|
if (!ShouldBlur(this)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsIDocument* doc = GetComposedDoc();
|
|
|
|
if (!doc) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsPIDOMWindowOuter* win = doc->GetWindow();
|
|
|
|
nsIFocusManager* fm = nsFocusManager::GetFocusManager();
|
|
|
|
if (win && fm) {
|
|
|
|
aError = fm->ClearFocus(win);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-03 08:18:36 +04:00
|
|
|
EventStates
|
2012-02-08 22:42:38 +04:00
|
|
|
Element::StyleStateFromLocks() const
|
|
|
|
{
|
2014-04-03 08:18:36 +04:00
|
|
|
EventStates locks = LockedStyleStates();
|
|
|
|
EventStates state = mState | locks;
|
2012-02-08 22:42:38 +04:00
|
|
|
|
|
|
|
if (locks.HasState(NS_EVENT_STATE_VISITED)) {
|
|
|
|
return state & ~NS_EVENT_STATE_UNVISITED;
|
|
|
|
}
|
|
|
|
if (locks.HasState(NS_EVENT_STATE_UNVISITED)) {
|
|
|
|
return state & ~NS_EVENT_STATE_VISITED;
|
|
|
|
}
|
|
|
|
return state;
|
|
|
|
}
|
|
|
|
|
2014-04-03 08:18:36 +04:00
|
|
|
EventStates
|
2012-02-08 22:42:38 +04:00
|
|
|
Element::LockedStyleStates() const
|
|
|
|
{
|
2014-04-03 08:18:36 +04:00
|
|
|
EventStates* locks =
|
|
|
|
static_cast<EventStates*>(GetProperty(nsGkAtoms::lockedStyleStates));
|
2012-02-08 22:42:38 +04:00
|
|
|
if (locks) {
|
|
|
|
return *locks;
|
|
|
|
}
|
2014-04-03 08:18:36 +04:00
|
|
|
return EventStates();
|
2012-02-08 22:42:38 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2014-04-03 08:18:36 +04:00
|
|
|
Element::NotifyStyleStateChange(EventStates aStates)
|
2012-02-08 22:42:38 +04:00
|
|
|
{
|
2014-08-06 03:23:02 +04:00
|
|
|
nsIDocument* doc = GetComposedDoc();
|
2012-02-08 22:42:38 +04:00
|
|
|
if (doc) {
|
|
|
|
nsIPresShell *presShell = doc->GetShell();
|
|
|
|
if (presShell) {
|
|
|
|
nsAutoScriptBlocker scriptBlocker;
|
|
|
|
presShell->ContentStateChanged(doc, this, aStates);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2014-04-03 08:18:36 +04:00
|
|
|
Element::LockStyleStates(EventStates aStates)
|
2012-02-08 22:42:38 +04:00
|
|
|
{
|
2014-04-03 08:18:36 +04:00
|
|
|
EventStates* locks = new EventStates(LockedStyleStates());
|
2012-02-08 22:42:38 +04:00
|
|
|
|
|
|
|
*locks |= aStates;
|
|
|
|
|
|
|
|
if (aStates.HasState(NS_EVENT_STATE_VISITED)) {
|
|
|
|
*locks &= ~NS_EVENT_STATE_UNVISITED;
|
|
|
|
}
|
|
|
|
if (aStates.HasState(NS_EVENT_STATE_UNVISITED)) {
|
|
|
|
*locks &= ~NS_EVENT_STATE_VISITED;
|
|
|
|
}
|
|
|
|
|
2014-03-25 17:25:47 +04:00
|
|
|
SetProperty(nsGkAtoms::lockedStyleStates, locks,
|
2014-04-03 08:18:36 +04:00
|
|
|
nsINode::DeleteProperty<EventStates>);
|
2012-02-08 22:42:38 +04:00
|
|
|
SetHasLockedStyleStates();
|
|
|
|
|
|
|
|
NotifyStyleStateChange(aStates);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2014-04-03 08:18:36 +04:00
|
|
|
Element::UnlockStyleStates(EventStates aStates)
|
2012-02-08 22:42:38 +04:00
|
|
|
{
|
2014-04-03 08:18:36 +04:00
|
|
|
EventStates* locks = new EventStates(LockedStyleStates());
|
2012-02-08 22:42:38 +04:00
|
|
|
|
|
|
|
*locks &= ~aStates;
|
|
|
|
|
|
|
|
if (locks->IsEmpty()) {
|
|
|
|
DeleteProperty(nsGkAtoms::lockedStyleStates);
|
|
|
|
ClearHasLockedStyleStates();
|
|
|
|
delete locks;
|
|
|
|
}
|
|
|
|
else {
|
2014-03-25 17:25:47 +04:00
|
|
|
SetProperty(nsGkAtoms::lockedStyleStates, locks,
|
2014-04-03 08:18:36 +04:00
|
|
|
nsINode::DeleteProperty<EventStates>);
|
2012-02-08 22:42:38 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
NotifyStyleStateChange(aStates);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Element::ClearStyleStateLocks()
|
|
|
|
{
|
2014-04-03 08:18:36 +04:00
|
|
|
EventStates locks = LockedStyleStates();
|
2012-02-08 22:42:38 +04:00
|
|
|
|
|
|
|
DeleteProperty(nsGkAtoms::lockedStyleStates);
|
|
|
|
ClearHasLockedStyleStates();
|
|
|
|
|
|
|
|
NotifyStyleStateChange(locks);
|
|
|
|
}
|
|
|
|
|
2012-10-16 15:51:00 +04:00
|
|
|
bool
|
|
|
|
Element::GetBindingURL(nsIDocument *aDocument, css::URLValue **aResult)
|
|
|
|
{
|
|
|
|
// If we have a frame the frame has already loaded the binding. And
|
|
|
|
// otherwise, don't do anything else here unless we're dealing with
|
|
|
|
// XUL or an HTML element that may have a plugin-related overlay
|
|
|
|
// (i.e. object, embed, or applet).
|
2015-03-03 14:08:59 +03:00
|
|
|
bool isXULorPluginElement = (IsXULElement() ||
|
|
|
|
IsHTMLElement(nsGkAtoms::object) ||
|
|
|
|
IsHTMLElement(nsGkAtoms::embed) ||
|
|
|
|
IsHTMLElement(nsGkAtoms::applet));
|
2015-05-05 07:00:28 +03:00
|
|
|
nsCOMPtr<nsIPresShell> shell = aDocument->GetShell();
|
2012-10-16 15:51:00 +04:00
|
|
|
if (!shell || GetPrimaryFrame() || !isXULorPluginElement) {
|
|
|
|
*aResult = nullptr;
|
2008-08-05 04:58:16 +04:00
|
|
|
|
2012-10-16 15:51:00 +04:00
|
|
|
return true;
|
2008-08-05 04:58:16 +04:00
|
|
|
}
|
|
|
|
|
2012-10-16 15:51:00 +04:00
|
|
|
// Get the computed -moz-binding directly from the style context
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<nsStyleContext> sc =
|
2015-05-05 07:00:28 +03:00
|
|
|
nsComputedDOMStyle::GetStyleContextForElementNoFlush(this, nullptr, shell);
|
2012-10-16 15:51:00 +04:00
|
|
|
NS_ENSURE_TRUE(sc, false);
|
2008-08-05 04:58:16 +04:00
|
|
|
|
2013-02-17 01:51:02 +04:00
|
|
|
*aResult = sc->StyleDisplay()->mBinding;
|
2008-08-05 04:58:16 +04:00
|
|
|
|
2012-10-16 15:51:00 +04:00
|
|
|
return true;
|
2008-08-05 04:58:16 +04:00
|
|
|
}
|
|
|
|
|
2012-10-16 15:51:00 +04:00
|
|
|
JSObject*
|
Bug 1117172 part 3. Change the wrappercached WrapObject methods to allow passing in aGivenProto. r=peterv
The only manual changes here are to BindingUtils.h, BindingUtils.cpp,
Codegen.py, Element.cpp, IDBFileRequest.cpp, IDBObjectStore.cpp,
dom/workers/Navigator.cpp, WorkerPrivate.cpp, DeviceStorageRequestChild.cpp,
Notification.cpp, nsGlobalWindow.cpp, MessagePort.cpp, nsJSEnvironment.cpp,
Sandbox.cpp, XPCConvert.cpp, ExportHelpers.cpp, and DataStoreService.cpp. The
rest of this diff was generated by running the following commands:
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapObjectInternal\(JSContext *\* *(?:aCx|cx|aContext|aCtx|js))\)/\1, JS::Handle<JSObject*> aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapObjectInternal\((?:aCx|cx|aContext|aCtx|js))\)/\1, aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapNode\(JSContext *\* *(?:aCx|cx|aContext|aCtx|js))\)/\1, JS::Handle<JSObject*> aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapNode\((?:aCx|cx|aContext|aCtx|js))\)/\1, aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapObject\(JSContext *\* *(?:aCx|cx|aContext|aCtx|js))\)/\1, JS::Handle<JSObject*> aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(Binding(?:_workers)?::Wrap\((?:aCx|cx|aContext|aCtx|js), [^,)]+)\)/\1, aGivenProto)/g'
2015-03-19 17:13:33 +03:00
|
|
|
Element::WrapObject(JSContext *aCx, JS::Handle<JSObject*> aGivenProto)
|
2008-08-05 04:58:16 +04:00
|
|
|
{
|
2015-03-20 07:34:08 +03:00
|
|
|
JS::Rooted<JSObject*> givenProto(aCx, aGivenProto);
|
|
|
|
JS::Rooted<JSObject*> customProto(aCx);
|
|
|
|
|
|
|
|
if (!givenProto) {
|
|
|
|
// Custom element prototype swizzling.
|
|
|
|
CustomElementData* data = GetCustomElementData();
|
|
|
|
if (data) {
|
|
|
|
// If this is a registered custom element then fix the prototype.
|
|
|
|
nsDocument* document = static_cast<nsDocument*>(OwnerDoc());
|
|
|
|
document->GetCustomPrototype(NodeInfo()->NamespaceID(), data->mType, &customProto);
|
|
|
|
if (customProto &&
|
|
|
|
NodePrincipal()->SubsumesConsideringDomain(nsContentUtils::ObjectPrincipal(customProto))) {
|
|
|
|
// Just go ahead and create with the right proto up front. Set
|
|
|
|
// customProto to null to flag that we don't need to do any post-facto
|
|
|
|
// proto fixups here.
|
|
|
|
givenProto = customProto;
|
|
|
|
customProto = nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
JS::Rooted<JSObject*> obj(aCx, nsINode::WrapObject(aCx, givenProto));
|
2012-10-16 15:51:00 +04:00
|
|
|
if (!obj) {
|
2012-07-30 18:20:58 +04:00
|
|
|
return nullptr;
|
2008-08-05 04:58:16 +04:00
|
|
|
}
|
|
|
|
|
2015-03-20 07:34:08 +03:00
|
|
|
if (customProto) {
|
|
|
|
// We want to set the custom prototype in the compartment where it was
|
|
|
|
// registered. In the case that |obj| and |prototype| are in different
|
|
|
|
// compartments, this will set the prototype on the |obj|'s wrapper and
|
|
|
|
// thus only visible in the wrapper's compartment, since we know obj's
|
|
|
|
// principal does not subsume customProto's in this case.
|
|
|
|
JSAutoCompartment ac(aCx, customProto);
|
|
|
|
JS::Rooted<JSObject*> wrappedObj(aCx, obj);
|
|
|
|
if (!JS_WrapObject(aCx, &wrappedObj) ||
|
|
|
|
!JS_SetPrototype(aCx, wrappedObj, customProto)) {
|
|
|
|
return nullptr;
|
2014-02-24 01:01:26 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-16 15:51:00 +04:00
|
|
|
nsIDocument* doc;
|
|
|
|
if (HasFlag(NODE_FORCE_XBL_BINDINGS)) {
|
|
|
|
doc = OwnerDoc();
|
2008-08-05 04:58:16 +04:00
|
|
|
}
|
2012-10-16 15:51:00 +04:00
|
|
|
else {
|
2014-10-02 22:45:44 +04:00
|
|
|
doc = GetComposedDoc();
|
2008-08-05 04:58:16 +04:00
|
|
|
}
|
2010-04-19 19:41:37 +04:00
|
|
|
|
2012-10-16 15:51:00 +04:00
|
|
|
if (!doc) {
|
|
|
|
// There's no baseclass that cares about this call so we just
|
|
|
|
// return here.
|
|
|
|
return obj;
|
|
|
|
}
|
2011-12-18 14:06:23 +04:00
|
|
|
|
2012-10-16 15:51:00 +04:00
|
|
|
// We must ensure that the XBL Binding is installed before we hand
|
|
|
|
// back this object.
|
2011-12-18 14:06:23 +04:00
|
|
|
|
2013-07-17 20:05:03 +04:00
|
|
|
if (HasFlag(NODE_MAY_BE_IN_BINDING_MNGR) && GetXBLBinding()) {
|
2012-10-16 15:51:00 +04:00
|
|
|
// There's already a binding for this element so nothing left to
|
|
|
|
// be done here.
|
2010-04-19 19:41:37 +04:00
|
|
|
|
2012-10-16 15:51:00 +04:00
|
|
|
// In theory we could call ExecuteAttachedHandler here when it's safe to
|
|
|
|
// run script if we also removed the binding from the PAQ queue, but that
|
|
|
|
// seems like a scary change that would mosly just add more
|
|
|
|
// inconsistencies.
|
|
|
|
return obj;
|
|
|
|
}
|
2010-04-19 19:41:37 +04:00
|
|
|
|
2012-10-16 15:51:00 +04:00
|
|
|
// Make sure the style context goes away _before_ we load the binding
|
|
|
|
// since that can destroy the relevant presshell.
|
|
|
|
mozilla::css::URLValue *bindingURL;
|
|
|
|
bool ok = GetBindingURL(doc, &bindingURL);
|
|
|
|
if (!ok) {
|
2013-09-09 07:29:21 +04:00
|
|
|
dom::Throw(aCx, NS_ERROR_FAILURE);
|
2012-10-16 15:51:00 +04:00
|
|
|
return nullptr;
|
|
|
|
}
|
2010-04-19 19:41:37 +04:00
|
|
|
|
2012-10-16 15:51:00 +04:00
|
|
|
if (!bindingURL) {
|
|
|
|
// No binding, nothing left to do here.
|
|
|
|
return obj;
|
|
|
|
}
|
2010-04-19 19:41:37 +04:00
|
|
|
|
2012-10-16 15:51:00 +04:00
|
|
|
nsCOMPtr<nsIURI> uri = bindingURL->GetURI();
|
2016-05-21 03:02:54 +03:00
|
|
|
nsCOMPtr<nsIPrincipal> principal = bindingURL->mOriginPrincipal.get();
|
2010-04-19 19:41:37 +04:00
|
|
|
|
2012-10-16 15:51:00 +04:00
|
|
|
// We have a binding that must be installed.
|
|
|
|
bool dummy;
|
2010-04-19 19:41:37 +04:00
|
|
|
|
2012-10-16 15:51:00 +04:00
|
|
|
nsXBLService* xblService = nsXBLService::GetInstance();
|
|
|
|
if (!xblService) {
|
2013-09-09 07:29:21 +04:00
|
|
|
dom::Throw(aCx, NS_ERROR_NOT_AVAILABLE);
|
2012-10-16 15:51:00 +04:00
|
|
|
return nullptr;
|
|
|
|
}
|
2010-04-19 19:41:37 +04:00
|
|
|
|
2014-06-26 02:35:36 +04:00
|
|
|
{
|
|
|
|
// Make a scope so that ~nsRefPtr can GC before returning obj.
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<nsXBLBinding> binding;
|
2014-06-26 02:35:36 +04:00
|
|
|
xblService->LoadBindings(this, uri, principal, getter_AddRefs(binding), &dummy);
|
|
|
|
|
|
|
|
if (binding) {
|
|
|
|
if (nsContentUtils::IsSafeToRunScript()) {
|
|
|
|
binding->ExecuteAttachedHandler();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
nsContentUtils::AddScriptRunner(
|
2016-05-05 11:45:00 +03:00
|
|
|
NewRunnableMethod(binding, &nsXBLBinding::ExecuteAttachedHandler));
|
2014-06-26 02:35:36 +04:00
|
|
|
}
|
2012-10-16 15:51:00 +04:00
|
|
|
}
|
|
|
|
}
|
2010-04-19 19:41:37 +04:00
|
|
|
|
2012-10-16 15:51:00 +04:00
|
|
|
return obj;
|
2010-04-19 19:41:37 +04:00
|
|
|
}
|
|
|
|
|
2014-10-31 00:38:48 +03:00
|
|
|
/* virtual */
|
|
|
|
nsINode*
|
|
|
|
Element::GetScopeChainParent() const
|
|
|
|
{
|
|
|
|
return OwnerDoc();
|
|
|
|
}
|
|
|
|
|
2011-08-22 13:14:13 +04:00
|
|
|
nsDOMTokenList*
|
2014-05-30 11:36:53 +04:00
|
|
|
Element::ClassList()
|
2010-04-19 19:41:37 +04:00
|
|
|
{
|
2014-05-30 11:36:53 +04:00
|
|
|
Element::nsDOMSlots* slots = DOMSlots();
|
2008-08-05 04:58:16 +04:00
|
|
|
|
2010-04-19 19:41:37 +04:00
|
|
|
if (!slots->mClassList) {
|
2014-05-30 11:36:53 +04:00
|
|
|
slots->mClassList = new nsDOMTokenList(this, nsGkAtoms::_class);
|
2010-04-19 19:41:37 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
return slots->mClassList;
|
2008-08-05 04:58:16 +04:00
|
|
|
}
|
|
|
|
|
2012-10-16 15:51:00 +04:00
|
|
|
void
|
2013-01-15 12:35:59 +04:00
|
|
|
Element::GetClassList(nsISupports** aClassList)
|
2009-08-12 12:55:14 +04:00
|
|
|
{
|
2014-05-30 11:36:53 +04:00
|
|
|
NS_ADDREF(*aClassList = ClassList());
|
2009-08-12 12:55:14 +04:00
|
|
|
}
|
|
|
|
|
2015-12-03 00:04:53 +03:00
|
|
|
void
|
|
|
|
Element::GetAttributeNames(nsTArray<nsString>& aResult)
|
|
|
|
{
|
|
|
|
uint32_t count = mAttrsAndChildren.AttrCount();
|
|
|
|
for (uint32_t i = 0; i < count; ++i) {
|
|
|
|
const nsAttrName* name = mAttrsAndChildren.AttrNameAt(i);
|
|
|
|
name->GetQualifiedName(*aResult.AppendElement());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-16 15:51:00 +04:00
|
|
|
already_AddRefed<nsIHTMLCollection>
|
2012-11-15 02:10:08 +04:00
|
|
|
Element::GetElementsByTagName(const nsAString& aLocalName)
|
2009-09-13 17:13:16 +04:00
|
|
|
{
|
2012-10-16 15:51:00 +04:00
|
|
|
return NS_GetContentList(this, kNameSpaceID_Unknown, aLocalName);
|
2010-05-06 16:32:14 +04:00
|
|
|
}
|
|
|
|
|
2012-10-16 15:51:00 +04:00
|
|
|
void
|
2012-11-15 02:10:08 +04:00
|
|
|
Element::GetElementsByTagName(const nsAString& aLocalName,
|
|
|
|
nsIDOMHTMLCollection** aResult)
|
2009-09-13 17:13:16 +04:00
|
|
|
{
|
2014-03-15 23:00:15 +04:00
|
|
|
*aResult = GetElementsByTagName(aLocalName).take();
|
2009-09-13 17:13:16 +04:00
|
|
|
}
|
|
|
|
|
2008-08-16 02:26:37 +04:00
|
|
|
nsIFrame*
|
2012-11-15 02:10:08 +04:00
|
|
|
Element::GetStyledFrame()
|
2008-08-16 02:26:37 +04:00
|
|
|
{
|
|
|
|
nsIFrame *frame = GetPrimaryFrame(Flush_Layout);
|
2012-07-30 18:20:58 +04:00
|
|
|
return frame ? nsLayoutUtils::GetStyleFrame(frame) : nullptr;
|
2008-08-16 02:26:37 +04:00
|
|
|
}
|
|
|
|
|
2009-09-03 07:57:36 +04:00
|
|
|
nsIScrollableFrame*
|
2013-09-30 21:32:02 +04:00
|
|
|
Element::GetScrollFrame(nsIFrame **aStyledFrame, bool aFlushLayout)
|
2008-08-16 02:26:37 +04:00
|
|
|
{
|
|
|
|
// it isn't clear what to return for SVG nodes, so just return nothing
|
2015-03-03 14:08:59 +03:00
|
|
|
if (IsSVGElement()) {
|
2009-09-03 07:57:36 +04:00
|
|
|
if (aStyledFrame) {
|
2012-07-30 18:20:58 +04:00
|
|
|
*aStyledFrame = nullptr;
|
2009-09-03 07:57:36 +04:00
|
|
|
}
|
2012-07-30 18:20:58 +04:00
|
|
|
return nullptr;
|
2008-08-16 02:26:37 +04:00
|
|
|
}
|
|
|
|
|
2013-09-30 21:32:02 +04:00
|
|
|
// Inline version of GetStyledFrame to use Flush_None if needed.
|
|
|
|
nsIFrame* frame = GetPrimaryFrame(aFlushLayout ? Flush_Layout : Flush_None);
|
|
|
|
if (frame) {
|
|
|
|
frame = nsLayoutUtils::GetStyleFrame(frame);
|
|
|
|
}
|
2008-08-16 02:26:37 +04:00
|
|
|
|
2009-09-03 07:57:36 +04:00
|
|
|
if (aStyledFrame) {
|
|
|
|
*aStyledFrame = frame;
|
2008-08-16 02:26:37 +04:00
|
|
|
}
|
|
|
|
if (!frame) {
|
2012-07-30 18:20:58 +04:00
|
|
|
return nullptr;
|
2008-08-16 02:26:37 +04:00
|
|
|
}
|
|
|
|
|
2009-09-03 07:57:36 +04:00
|
|
|
// menu frames implement GetScrollTargetFrame but we don't want
|
2011-10-19 00:17:45 +04:00
|
|
|
// to use it here. Similar for comboboxes.
|
2013-10-23 02:46:40 +04:00
|
|
|
nsIAtom* type = frame->GetType();
|
|
|
|
if (type != nsGkAtoms::menuFrame && type != nsGkAtoms::comboboxControlFrame) {
|
2009-09-03 07:57:36 +04:00
|
|
|
nsIScrollableFrame *scrollFrame = frame->GetScrollTargetFrame();
|
|
|
|
if (scrollFrame)
|
|
|
|
return scrollFrame;
|
|
|
|
}
|
2008-08-16 02:26:37 +04:00
|
|
|
|
2011-10-18 14:53:36 +04:00
|
|
|
nsIDocument* doc = OwnerDoc();
|
2011-09-29 10:19:26 +04:00
|
|
|
bool quirksMode = doc->GetCompatibilityMode() == eCompatibility_NavQuirks;
|
2010-04-30 17:12:05 +04:00
|
|
|
Element* elementWithRootScrollInfo =
|
|
|
|
quirksMode ? doc->GetBodyElement() : doc->GetRootElement();
|
2010-04-19 19:41:37 +04:00
|
|
|
if (this == elementWithRootScrollInfo) {
|
2009-09-03 07:57:36 +04:00
|
|
|
// In quirks mode, the scroll info for the body element should map to the
|
|
|
|
// root scrollable frame.
|
|
|
|
// In strict mode, the scroll info for the root element should map to the
|
|
|
|
// the root scrollable frame.
|
|
|
|
return frame->PresContext()->PresShell()->GetRootScrollFrameAsScrollable();
|
2008-08-16 02:26:37 +04:00
|
|
|
}
|
|
|
|
|
2012-07-30 18:20:58 +04:00
|
|
|
return nullptr;
|
2008-08-16 02:26:37 +04:00
|
|
|
}
|
|
|
|
|
2012-10-16 15:51:00 +04:00
|
|
|
void
|
2014-08-06 02:01:32 +04:00
|
|
|
Element::ScrollIntoView()
|
|
|
|
{
|
Bug 1045754 - Part 1 - Implement updated CSSOM-View smooth-scrolling specification. r=bz
- Added new WebIDL dictionary, ScrollToOptions. This dictionary extends
ScrollOptions by adding "left" and "top", specifying the scroll offset.
This will be later extended with more members to allow scroll offsets to be
specified with logical axes.
- Implemented Window.Scroll, Window.ScrollTo, Window.ScrollBy, Element.Scroll,
Element.ScrollTo, and Element.ScrollBy functions that accept ScrollToOptions
as a single parameter.
- Removed ScrollOptions dictionary parameter from existing Window.Scroll,
Window.ScrollTo, and Window.ScrollBy functions as these have been replaced
with functions accepting a single parameter, ScrollToOptions.
- Added new WebIDL dictionary, ScrollIntoViewOptions. This dictionary
extends ScrollOptions by adding "block", specifying whether the element
start or end will be scrolled into view.
- Replaced Element.ScrollIntoView(bool,ScrollOptions) with
Element.ScrollIntoView(ScrollIntoViewOptions) to match updated
CSSOM-View scroll-behavior specification.
2014-10-01 21:47:56 +04:00
|
|
|
ScrollIntoView(ScrollIntoViewOptions());
|
2014-08-06 02:01:32 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
Bug 1045754 - Part 1 - Implement updated CSSOM-View smooth-scrolling specification. r=bz
- Added new WebIDL dictionary, ScrollToOptions. This dictionary extends
ScrollOptions by adding "left" and "top", specifying the scroll offset.
This will be later extended with more members to allow scroll offsets to be
specified with logical axes.
- Implemented Window.Scroll, Window.ScrollTo, Window.ScrollBy, Element.Scroll,
Element.ScrollTo, and Element.ScrollBy functions that accept ScrollToOptions
as a single parameter.
- Removed ScrollOptions dictionary parameter from existing Window.Scroll,
Window.ScrollTo, and Window.ScrollBy functions as these have been replaced
with functions accepting a single parameter, ScrollToOptions.
- Added new WebIDL dictionary, ScrollIntoViewOptions. This dictionary
extends ScrollOptions by adding "block", specifying whether the element
start or end will be scrolled into view.
- Replaced Element.ScrollIntoView(bool,ScrollOptions) with
Element.ScrollIntoView(ScrollIntoViewOptions) to match updated
CSSOM-View scroll-behavior specification.
2014-10-01 21:47:56 +04:00
|
|
|
Element::ScrollIntoView(bool aTop)
|
|
|
|
{
|
|
|
|
ScrollIntoViewOptions options;
|
|
|
|
if (!aTop) {
|
|
|
|
options.mBlock = ScrollLogicalPosition::End;
|
|
|
|
}
|
|
|
|
ScrollIntoView(options);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Element::ScrollIntoView(const ScrollIntoViewOptions &aOptions)
|
2008-08-16 02:26:37 +04:00
|
|
|
{
|
2014-10-02 22:45:44 +04:00
|
|
|
nsIDocument *document = GetComposedDoc();
|
2012-10-16 15:51:00 +04:00
|
|
|
if (!document) {
|
|
|
|
return;
|
2008-08-16 02:26:37 +04:00
|
|
|
}
|
|
|
|
|
2012-10-16 15:51:00 +04:00
|
|
|
// Get the presentation shell
|
|
|
|
nsCOMPtr<nsIPresShell> presShell = document->GetShell();
|
|
|
|
if (!presShell) {
|
|
|
|
return;
|
|
|
|
}
|
2010-04-19 19:41:37 +04:00
|
|
|
|
Bug 1045754 - Part 1 - Implement updated CSSOM-View smooth-scrolling specification. r=bz
- Added new WebIDL dictionary, ScrollToOptions. This dictionary extends
ScrollOptions by adding "left" and "top", specifying the scroll offset.
This will be later extended with more members to allow scroll offsets to be
specified with logical axes.
- Implemented Window.Scroll, Window.ScrollTo, Window.ScrollBy, Element.Scroll,
Element.ScrollTo, and Element.ScrollBy functions that accept ScrollToOptions
as a single parameter.
- Removed ScrollOptions dictionary parameter from existing Window.Scroll,
Window.ScrollTo, and Window.ScrollBy functions as these have been replaced
with functions accepting a single parameter, ScrollToOptions.
- Added new WebIDL dictionary, ScrollIntoViewOptions. This dictionary
extends ScrollOptions by adding "block", specifying whether the element
start or end will be scrolled into view.
- Replaced Element.ScrollIntoView(bool,ScrollOptions) with
Element.ScrollIntoView(ScrollIntoViewOptions) to match updated
CSSOM-View scroll-behavior specification.
2014-10-01 21:47:56 +04:00
|
|
|
int16_t vpercent = (aOptions.mBlock == ScrollLogicalPosition::Start)
|
|
|
|
? nsIPresShell::SCROLL_TOP
|
|
|
|
: nsIPresShell::SCROLL_BOTTOM;
|
2008-08-16 02:26:37 +04:00
|
|
|
|
2014-08-06 02:01:34 +04:00
|
|
|
uint32_t flags = nsIPresShell::SCROLL_OVERFLOW_HIDDEN;
|
|
|
|
if (aOptions.mBehavior == ScrollBehavior::Smooth) {
|
|
|
|
flags |= nsIPresShell::SCROLL_SMOOTH;
|
2014-09-15 23:30:03 +04:00
|
|
|
} else if (aOptions.mBehavior == ScrollBehavior::Auto) {
|
|
|
|
flags |= nsIPresShell::SCROLL_SMOOTH_AUTO;
|
2014-08-06 02:01:34 +04:00
|
|
|
}
|
|
|
|
|
2012-10-16 15:51:00 +04:00
|
|
|
presShell->ScrollContentIntoView(this,
|
|
|
|
nsIPresShell::ScrollAxis(
|
|
|
|
vpercent,
|
|
|
|
nsIPresShell::SCROLL_ALWAYS),
|
|
|
|
nsIPresShell::ScrollAxis(),
|
2014-08-06 02:01:34 +04:00
|
|
|
flags);
|
2008-08-16 02:26:37 +04:00
|
|
|
}
|
|
|
|
|
Bug 1045754 - Part 1 - Implement updated CSSOM-View smooth-scrolling specification. r=bz
- Added new WebIDL dictionary, ScrollToOptions. This dictionary extends
ScrollOptions by adding "left" and "top", specifying the scroll offset.
This will be later extended with more members to allow scroll offsets to be
specified with logical axes.
- Implemented Window.Scroll, Window.ScrollTo, Window.ScrollBy, Element.Scroll,
Element.ScrollTo, and Element.ScrollBy functions that accept ScrollToOptions
as a single parameter.
- Removed ScrollOptions dictionary parameter from existing Window.Scroll,
Window.ScrollTo, and Window.ScrollBy functions as these have been replaced
with functions accepting a single parameter, ScrollToOptions.
- Added new WebIDL dictionary, ScrollIntoViewOptions. This dictionary
extends ScrollOptions by adding "block", specifying whether the element
start or end will be scrolled into view.
- Replaced Element.ScrollIntoView(bool,ScrollOptions) with
Element.ScrollIntoView(ScrollIntoViewOptions) to match updated
CSSOM-View scroll-behavior specification.
2014-10-01 21:47:56 +04:00
|
|
|
void
|
|
|
|
Element::Scroll(const CSSIntPoint& aScroll, const ScrollOptions& aOptions)
|
|
|
|
{
|
|
|
|
nsIScrollableFrame* sf = GetScrollFrame();
|
|
|
|
if (sf) {
|
|
|
|
nsIScrollableFrame::ScrollMode scrollMode = nsIScrollableFrame::INSTANT;
|
|
|
|
if (aOptions.mBehavior == ScrollBehavior::Smooth) {
|
|
|
|
scrollMode = nsIScrollableFrame::SMOOTH_MSD;
|
|
|
|
} else if (aOptions.mBehavior == ScrollBehavior::Auto) {
|
|
|
|
ScrollbarStyles styles = sf->GetScrollbarStyles();
|
|
|
|
if (styles.mScrollBehavior == NS_STYLE_SCROLL_BEHAVIOR_SMOOTH) {
|
|
|
|
scrollMode = nsIScrollableFrame::SMOOTH_MSD;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sf->ScrollToCSSPixels(aScroll, scrollMode);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Element::Scroll(double aXScroll, double aYScroll)
|
|
|
|
{
|
|
|
|
// Convert -Inf, Inf, and NaN to 0; otherwise, convert by C-style cast.
|
2016-07-26 17:48:30 +03:00
|
|
|
auto scrollPos = CSSIntPoint::Truncate(mozilla::ToZeroIfNonfinite(aXScroll),
|
|
|
|
mozilla::ToZeroIfNonfinite(aYScroll));
|
Bug 1045754 - Part 1 - Implement updated CSSOM-View smooth-scrolling specification. r=bz
- Added new WebIDL dictionary, ScrollToOptions. This dictionary extends
ScrollOptions by adding "left" and "top", specifying the scroll offset.
This will be later extended with more members to allow scroll offsets to be
specified with logical axes.
- Implemented Window.Scroll, Window.ScrollTo, Window.ScrollBy, Element.Scroll,
Element.ScrollTo, and Element.ScrollBy functions that accept ScrollToOptions
as a single parameter.
- Removed ScrollOptions dictionary parameter from existing Window.Scroll,
Window.ScrollTo, and Window.ScrollBy functions as these have been replaced
with functions accepting a single parameter, ScrollToOptions.
- Added new WebIDL dictionary, ScrollIntoViewOptions. This dictionary
extends ScrollOptions by adding "block", specifying whether the element
start or end will be scrolled into view.
- Replaced Element.ScrollIntoView(bool,ScrollOptions) with
Element.ScrollIntoView(ScrollIntoViewOptions) to match updated
CSSOM-View scroll-behavior specification.
2014-10-01 21:47:56 +04:00
|
|
|
|
|
|
|
Scroll(scrollPos, ScrollOptions());
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Element::Scroll(const ScrollToOptions& aOptions)
|
|
|
|
{
|
|
|
|
nsIScrollableFrame *sf = GetScrollFrame();
|
|
|
|
if (sf) {
|
|
|
|
CSSIntPoint scrollPos = sf->GetScrollPositionCSSPixels();
|
|
|
|
if (aOptions.mLeft.WasPassed()) {
|
|
|
|
scrollPos.x = mozilla::ToZeroIfNonfinite(aOptions.mLeft.Value());
|
|
|
|
}
|
|
|
|
if (aOptions.mTop.WasPassed()) {
|
|
|
|
scrollPos.y = mozilla::ToZeroIfNonfinite(aOptions.mTop.Value());
|
|
|
|
}
|
|
|
|
Scroll(scrollPos, aOptions);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Element::ScrollTo(double aXScroll, double aYScroll)
|
|
|
|
{
|
|
|
|
Scroll(aXScroll, aYScroll);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Element::ScrollTo(const ScrollToOptions& aOptions)
|
|
|
|
{
|
|
|
|
Scroll(aOptions);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Element::ScrollBy(double aXScrollDif, double aYScrollDif)
|
|
|
|
{
|
|
|
|
nsIScrollableFrame *sf = GetScrollFrame();
|
|
|
|
if (sf) {
|
|
|
|
CSSIntPoint scrollPos = sf->GetScrollPositionCSSPixels();
|
2016-07-26 17:48:30 +03:00
|
|
|
scrollPos += CSSIntPoint::Truncate(mozilla::ToZeroIfNonfinite(aXScrollDif),
|
|
|
|
mozilla::ToZeroIfNonfinite(aYScrollDif));
|
Bug 1045754 - Part 1 - Implement updated CSSOM-View smooth-scrolling specification. r=bz
- Added new WebIDL dictionary, ScrollToOptions. This dictionary extends
ScrollOptions by adding "left" and "top", specifying the scroll offset.
This will be later extended with more members to allow scroll offsets to be
specified with logical axes.
- Implemented Window.Scroll, Window.ScrollTo, Window.ScrollBy, Element.Scroll,
Element.ScrollTo, and Element.ScrollBy functions that accept ScrollToOptions
as a single parameter.
- Removed ScrollOptions dictionary parameter from existing Window.Scroll,
Window.ScrollTo, and Window.ScrollBy functions as these have been replaced
with functions accepting a single parameter, ScrollToOptions.
- Added new WebIDL dictionary, ScrollIntoViewOptions. This dictionary
extends ScrollOptions by adding "block", specifying whether the element
start or end will be scrolled into view.
- Replaced Element.ScrollIntoView(bool,ScrollOptions) with
Element.ScrollIntoView(ScrollIntoViewOptions) to match updated
CSSOM-View scroll-behavior specification.
2014-10-01 21:47:56 +04:00
|
|
|
Scroll(scrollPos, ScrollOptions());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Element::ScrollBy(const ScrollToOptions& aOptions)
|
|
|
|
{
|
|
|
|
nsIScrollableFrame *sf = GetScrollFrame();
|
|
|
|
if (sf) {
|
|
|
|
CSSIntPoint scrollPos = sf->GetScrollPositionCSSPixels();
|
|
|
|
if (aOptions.mLeft.WasPassed()) {
|
|
|
|
scrollPos.x += mozilla::ToZeroIfNonfinite(aOptions.mLeft.Value());
|
|
|
|
}
|
|
|
|
if (aOptions.mTop.WasPassed()) {
|
|
|
|
scrollPos.y += mozilla::ToZeroIfNonfinite(aOptions.mTop.Value());
|
|
|
|
}
|
|
|
|
Scroll(scrollPos, aOptions);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int32_t
|
|
|
|
Element::ScrollTop()
|
|
|
|
{
|
|
|
|
nsIScrollableFrame* sf = GetScrollFrame();
|
|
|
|
return sf ? sf->GetScrollPositionCSSPixels().y : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Element::SetScrollTop(int32_t aScrollTop)
|
|
|
|
{
|
|
|
|
nsIScrollableFrame* sf = GetScrollFrame();
|
|
|
|
if (sf) {
|
|
|
|
nsIScrollableFrame::ScrollMode scrollMode = nsIScrollableFrame::INSTANT;
|
|
|
|
if (sf->GetScrollbarStyles().mScrollBehavior == NS_STYLE_SCROLL_BEHAVIOR_SMOOTH) {
|
|
|
|
scrollMode = nsIScrollableFrame::SMOOTH_MSD;
|
|
|
|
}
|
|
|
|
sf->ScrollToCSSPixels(CSSIntPoint(sf->GetScrollPositionCSSPixels().x,
|
|
|
|
aScrollTop),
|
|
|
|
scrollMode);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int32_t
|
|
|
|
Element::ScrollLeft()
|
|
|
|
{
|
|
|
|
nsIScrollableFrame* sf = GetScrollFrame();
|
|
|
|
return sf ? sf->GetScrollPositionCSSPixels().x : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Element::SetScrollLeft(int32_t aScrollLeft)
|
|
|
|
{
|
|
|
|
nsIScrollableFrame* sf = GetScrollFrame();
|
|
|
|
if (sf) {
|
|
|
|
nsIScrollableFrame::ScrollMode scrollMode = nsIScrollableFrame::INSTANT;
|
|
|
|
if (sf->GetScrollbarStyles().mScrollBehavior == NS_STYLE_SCROLL_BEHAVIOR_SMOOTH) {
|
|
|
|
scrollMode = nsIScrollableFrame::SMOOTH_MSD;
|
|
|
|
}
|
|
|
|
|
|
|
|
sf->ScrollToCSSPixels(CSSIntPoint(aScrollLeft,
|
|
|
|
sf->GetScrollPositionCSSPixels().y),
|
|
|
|
scrollMode);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-09-30 21:32:02 +04:00
|
|
|
bool
|
|
|
|
Element::ScrollByNoFlush(int32_t aDx, int32_t aDy)
|
|
|
|
{
|
|
|
|
nsIScrollableFrame* sf = GetScrollFrame(nullptr, false);
|
|
|
|
if (!sf) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsWeakFrame weakRef(sf->GetScrolledFrame());
|
|
|
|
|
|
|
|
CSSIntPoint before = sf->GetScrollPositionCSSPixels();
|
|
|
|
sf->ScrollToCSSPixelsApproximate(CSSIntPoint(before.x + aDx, before.y + aDy));
|
|
|
|
|
|
|
|
// The frame was destroyed, can't keep on scrolling.
|
|
|
|
if (!weakRef.IsAlive()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
CSSIntPoint after = sf->GetScrollPositionCSSPixels();
|
|
|
|
return (before != after);
|
|
|
|
}
|
|
|
|
|
2015-02-20 03:03:07 +03:00
|
|
|
void
|
|
|
|
Element::MozScrollSnap()
|
|
|
|
{
|
|
|
|
nsIScrollableFrame* sf = GetScrollFrame(nullptr, false);
|
|
|
|
if (sf) {
|
|
|
|
sf->ScrollSnap();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-29 05:38:22 +04:00
|
|
|
static nsSize GetScrollRectSizeForOverflowVisibleFrame(nsIFrame* aFrame)
|
|
|
|
{
|
|
|
|
if (!aFrame) {
|
|
|
|
return nsSize(0,0);
|
|
|
|
}
|
|
|
|
|
2013-04-09 04:05:12 +04:00
|
|
|
nsRect paddingRect = aFrame->GetPaddingRectRelativeToSelf();
|
2013-04-16 11:23:46 +04:00
|
|
|
nsOverflowAreas overflowAreas(paddingRect, paddingRect);
|
2013-04-09 04:05:12 +04:00
|
|
|
// Add the scrollable overflow areas of children (if any) to the paddingRect.
|
|
|
|
// It's important to start with the paddingRect, otherwise if there are no
|
|
|
|
// children the overflow rect will be 0,0,0,0 which will force the point 0,0
|
|
|
|
// to be included in the final rect.
|
2013-04-16 11:23:46 +04:00
|
|
|
nsLayoutUtils::UnionChildOverflow(aFrame, overflowAreas);
|
2013-04-09 04:05:12 +04:00
|
|
|
// Make sure that an empty padding-rect's edges are included, by adding
|
|
|
|
// the padding-rect in again with UnionEdges.
|
|
|
|
nsRect overflowRect =
|
|
|
|
overflowAreas.ScrollableOverflow().UnionEdges(paddingRect);
|
2013-01-29 05:38:22 +04:00
|
|
|
return nsLayoutUtils::GetScrolledRect(aFrame,
|
2013-04-09 04:05:12 +04:00
|
|
|
overflowRect, paddingRect.Size(),
|
2013-02-17 01:51:02 +04:00
|
|
|
aFrame->StyleVisibility()->mDirection).Size();
|
2013-01-29 05:38:22 +04:00
|
|
|
}
|
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t
|
2012-11-15 02:10:08 +04:00
|
|
|
Element::ScrollHeight()
|
2008-08-16 02:26:37 +04:00
|
|
|
{
|
2015-03-03 14:08:59 +03:00
|
|
|
if (IsSVGElement())
|
2010-04-19 19:41:37 +04:00
|
|
|
return 0;
|
2008-08-16 02:26:37 +04:00
|
|
|
|
2009-09-03 07:57:36 +04:00
|
|
|
nsIScrollableFrame* sf = GetScrollFrame();
|
2013-01-29 05:38:22 +04:00
|
|
|
nscoord height;
|
|
|
|
if (sf) {
|
|
|
|
height = sf->GetScrollRange().height + sf->GetScrollPortRect().height;
|
|
|
|
} else {
|
|
|
|
height = GetScrollRectSizeForOverflowVisibleFrame(GetStyledFrame()).height;
|
2008-08-16 02:26:37 +04:00
|
|
|
}
|
|
|
|
|
2010-04-19 19:41:37 +04:00
|
|
|
return nsPresContext::AppUnitsToIntCSSPixels(height);
|
2008-08-16 02:26:37 +04:00
|
|
|
}
|
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t
|
2012-11-15 02:10:08 +04:00
|
|
|
Element::ScrollWidth()
|
2010-04-19 19:41:37 +04:00
|
|
|
{
|
2015-03-03 14:08:59 +03:00
|
|
|
if (IsSVGElement())
|
2010-04-19 19:41:37 +04:00
|
|
|
return 0;
|
2008-08-16 02:26:37 +04:00
|
|
|
|
2009-09-03 07:57:36 +04:00
|
|
|
nsIScrollableFrame* sf = GetScrollFrame();
|
2013-01-29 05:38:22 +04:00
|
|
|
nscoord width;
|
|
|
|
if (sf) {
|
|
|
|
width = sf->GetScrollRange().width + sf->GetScrollPortRect().width;
|
|
|
|
} else {
|
|
|
|
width = GetScrollRectSizeForOverflowVisibleFrame(GetStyledFrame()).width;
|
2008-08-16 02:26:37 +04:00
|
|
|
}
|
|
|
|
|
2010-04-19 19:41:37 +04:00
|
|
|
return nsPresContext::AppUnitsToIntCSSPixels(width);
|
|
|
|
}
|
|
|
|
|
2008-08-16 02:26:37 +04:00
|
|
|
nsRect
|
2012-11-15 02:10:08 +04:00
|
|
|
Element::GetClientAreaRect()
|
2008-08-16 02:26:37 +04:00
|
|
|
{
|
2009-09-03 07:57:36 +04:00
|
|
|
nsIFrame* styledFrame;
|
|
|
|
nsIScrollableFrame* sf = GetScrollFrame(&styledFrame);
|
2008-08-16 02:26:37 +04:00
|
|
|
|
2009-09-03 07:57:36 +04:00
|
|
|
if (sf) {
|
|
|
|
return sf->GetScrollPortRect();
|
2008-08-16 02:26:37 +04:00
|
|
|
}
|
|
|
|
|
2009-09-03 07:57:36 +04:00
|
|
|
if (styledFrame &&
|
2013-02-17 01:51:02 +04:00
|
|
|
(styledFrame->StyleDisplay()->mDisplay != NS_STYLE_DISPLAY_INLINE ||
|
2009-09-03 07:57:36 +04:00
|
|
|
styledFrame->IsFrameOfType(nsIFrame::eReplaced))) {
|
2008-08-16 02:26:37 +04:00
|
|
|
// Special case code to make client area work even when there isn't
|
|
|
|
// a scroll view, see bug 180552, bug 227567.
|
2009-09-03 07:57:36 +04:00
|
|
|
return styledFrame->GetPaddingRect() - styledFrame->GetPositionIgnoringScrolling();
|
2008-08-16 02:26:37 +04:00
|
|
|
}
|
|
|
|
|
2009-09-03 07:57:36 +04:00
|
|
|
// SVG nodes reach here and just return 0
|
2008-08-16 02:26:37 +04:00
|
|
|
return nsRect(0, 0, 0, 0);
|
|
|
|
}
|
|
|
|
|
2013-09-20 14:21:03 +04:00
|
|
|
already_AddRefed<DOMRect>
|
2012-11-15 02:10:08 +04:00
|
|
|
Element::GetBoundingClientRect()
|
2007-05-31 02:32:54 +04:00
|
|
|
{
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<DOMRect> rect = new DOMRect(this);
|
2016-02-15 03:34:47 +03:00
|
|
|
|
2010-04-19 19:41:37 +04:00
|
|
|
nsIFrame* frame = GetPrimaryFrame(Flush_Layout);
|
2007-05-31 02:32:54 +04:00
|
|
|
if (!frame) {
|
|
|
|
// display:none, perhaps? Return the empty rect
|
2012-10-16 15:51:00 +04:00
|
|
|
return rect.forget();
|
2007-05-31 02:32:54 +04:00
|
|
|
}
|
2008-02-27 12:26:15 +03:00
|
|
|
|
|
|
|
nsRect r = nsLayoutUtils::GetAllInFlowRectsUnion(frame,
|
2011-12-28 07:26:46 +04:00
|
|
|
nsLayoutUtils::GetContainingBlockForClientRect(frame),
|
|
|
|
nsLayoutUtils::RECTS_ACCOUNT_FOR_TRANSFORMS);
|
2009-09-04 08:49:18 +04:00
|
|
|
rect->SetLayoutRect(r);
|
2012-10-16 15:51:00 +04:00
|
|
|
return rect.forget();
|
2007-05-31 02:32:54 +04:00
|
|
|
}
|
|
|
|
|
2013-09-20 14:21:03 +04:00
|
|
|
already_AddRefed<DOMRectList>
|
2013-03-17 11:55:16 +04:00
|
|
|
Element::GetClientRects()
|
2011-08-11 17:29:50 +04:00
|
|
|
{
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<DOMRectList> rectList = new DOMRectList(this);
|
2008-02-27 12:26:15 +03:00
|
|
|
|
2010-04-19 19:41:37 +04:00
|
|
|
nsIFrame* frame = GetPrimaryFrame(Flush_Layout);
|
2008-01-28 20:42:52 +03:00
|
|
|
if (!frame) {
|
|
|
|
// display:none, perhaps? Return an empty list
|
2012-10-16 15:51:00 +04:00
|
|
|
return rectList.forget();
|
2008-01-28 20:42:52 +03:00
|
|
|
}
|
|
|
|
|
2009-09-25 01:01:48 +04:00
|
|
|
nsLayoutUtils::RectListBuilder builder(rectList);
|
2008-02-27 12:26:15 +03:00
|
|
|
nsLayoutUtils::GetAllInFlowRects(frame,
|
2011-12-28 07:26:46 +04:00
|
|
|
nsLayoutUtils::GetContainingBlockForClientRect(frame), &builder,
|
|
|
|
nsLayoutUtils::RECTS_ACCOUNT_FOR_TRANSFORMS);
|
2012-10-16 15:51:00 +04:00
|
|
|
return rectList.forget();
|
2007-05-31 02:32:54 +04:00
|
|
|
}
|
|
|
|
|
2007-02-01 18:14:00 +03:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
|
2013-12-02 14:26:11 +04:00
|
|
|
void
|
|
|
|
Element::AddToIdTable(nsIAtom* aId)
|
|
|
|
{
|
|
|
|
NS_ASSERTION(HasID(), "Node doesn't have an ID?");
|
2014-07-03 21:02:07 +04:00
|
|
|
if (IsInShadowTree()) {
|
2013-12-02 14:26:11 +04:00
|
|
|
ShadowRoot* containingShadow = GetContainingShadow();
|
|
|
|
containingShadow->AddToIdTable(this, aId);
|
|
|
|
} else {
|
2014-10-02 22:45:44 +04:00
|
|
|
nsIDocument* doc = GetUncomposedDoc();
|
2015-03-03 14:08:59 +03:00
|
|
|
if (doc && (!IsInAnonymousSubtree() || doc->IsXULDocument())) {
|
2013-12-02 14:26:11 +04:00
|
|
|
doc->AddToIdTable(this, aId);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Element::RemoveFromIdTable()
|
|
|
|
{
|
2014-05-30 11:36:53 +04:00
|
|
|
if (!HasID()) {
|
|
|
|
return;
|
2014-03-05 08:13:20 +04:00
|
|
|
}
|
|
|
|
|
2014-05-30 11:36:53 +04:00
|
|
|
nsIAtom* id = DoGetID();
|
2014-07-03 21:02:07 +04:00
|
|
|
if (IsInShadowTree()) {
|
2014-03-05 08:13:20 +04:00
|
|
|
ShadowRoot* containingShadow = GetContainingShadow();
|
|
|
|
// Check for containingShadow because it may have
|
|
|
|
// been deleted during unlinking.
|
|
|
|
if (containingShadow) {
|
2014-05-30 11:36:53 +04:00
|
|
|
containingShadow->RemoveFromIdTable(this, id);
|
2014-03-05 08:13:20 +04:00
|
|
|
}
|
|
|
|
} else {
|
2014-10-02 22:45:44 +04:00
|
|
|
nsIDocument* doc = GetUncomposedDoc();
|
2015-03-03 14:08:59 +03:00
|
|
|
if (doc && (!IsInAnonymousSubtree() || doc->IsXULDocument())) {
|
2014-05-30 11:36:53 +04:00
|
|
|
doc->RemoveFromIdTable(this, id);
|
2013-12-02 14:26:11 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
already_AddRefed<ShadowRoot>
|
|
|
|
Element::CreateShadowRoot(ErrorResult& aError)
|
|
|
|
{
|
|
|
|
nsAutoScriptBlocker scriptBlocker;
|
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<mozilla::dom::NodeInfo> nodeInfo;
|
2013-12-02 14:26:11 +04:00
|
|
|
nodeInfo = mNodeInfo->NodeInfoManager()->GetNodeInfo(
|
|
|
|
nsGkAtoms::documentFragmentNodeName, nullptr, kNameSpaceID_None,
|
|
|
|
nsIDOMNode::DOCUMENT_FRAGMENT_NODE);
|
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<nsXBLDocumentInfo> docInfo = new nsXBLDocumentInfo(OwnerDoc());
|
2013-12-02 14:26:11 +04:00
|
|
|
|
|
|
|
nsXBLPrototypeBinding* protoBinding = new nsXBLPrototypeBinding();
|
|
|
|
aError = protoBinding->Init(NS_LITERAL_CSTRING("shadowroot"),
|
2014-10-23 21:50:39 +04:00
|
|
|
docInfo, nullptr, true);
|
2013-12-02 14:26:11 +04:00
|
|
|
if (aError.Failed()) {
|
|
|
|
delete protoBinding;
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2016-03-31 15:20:14 +03:00
|
|
|
nsIDocument* doc = GetComposedDoc();
|
2014-10-23 17:19:25 +04:00
|
|
|
nsIContent* destroyedFramesFor = nullptr;
|
|
|
|
if (doc) {
|
|
|
|
nsIPresShell* shell = doc->GetShell();
|
|
|
|
if (shell) {
|
|
|
|
shell->DestroyFramesFor(this, &destroyedFramesFor);
|
2014-11-20 21:24:09 +03:00
|
|
|
MOZ_ASSERT(!shell->FrameManager()->GetDisplayContentsStyleFor(this));
|
2014-10-23 17:19:25 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
MOZ_ASSERT(!GetPrimaryFrame());
|
|
|
|
|
2013-12-02 14:26:12 +04:00
|
|
|
// Unlike for XBL, false is the default for inheriting style.
|
|
|
|
protoBinding->SetInheritsStyle(false);
|
|
|
|
|
2013-12-02 14:26:11 +04:00
|
|
|
// Calling SetPrototypeBinding takes ownership of protoBinding.
|
|
|
|
docInfo->SetPrototypeBinding(NS_LITERAL_CSTRING("shadowroot"), protoBinding);
|
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<ShadowRoot> shadowRoot = new ShadowRoot(this, nodeInfo.forget(),
|
2013-12-02 14:26:12 +04:00
|
|
|
protoBinding);
|
2013-12-21 10:43:58 +04:00
|
|
|
|
2015-02-09 21:01:23 +03:00
|
|
|
shadowRoot->SetIsComposedDocParticipant(IsInComposedDoc());
|
|
|
|
|
2013-12-21 10:43:58 +04:00
|
|
|
// Replace the old ShadowRoot with the new one and let the old
|
|
|
|
// ShadowRoot know about the younger ShadowRoot because the old
|
|
|
|
// ShadowRoot is projected into the younger ShadowRoot's shadow
|
|
|
|
// insertion point (if it exists).
|
|
|
|
ShadowRoot* olderShadow = GetShadowRoot();
|
2013-12-02 14:26:11 +04:00
|
|
|
SetShadowRoot(shadowRoot);
|
2013-12-21 10:43:58 +04:00
|
|
|
if (olderShadow) {
|
|
|
|
olderShadow->SetYoungerShadow(shadowRoot);
|
2014-09-27 02:07:40 +04:00
|
|
|
|
|
|
|
// Unbind children of older shadow root because they
|
|
|
|
// are no longer in the composed tree.
|
|
|
|
for (nsIContent* child = olderShadow->GetFirstChild(); child;
|
|
|
|
child = child->GetNextSibling()) {
|
|
|
|
child->UnbindFromTree(true, false);
|
|
|
|
}
|
2015-02-09 21:01:23 +03:00
|
|
|
|
|
|
|
olderShadow->SetIsComposedDocParticipant(false);
|
2013-12-21 10:43:58 +04:00
|
|
|
}
|
2013-12-02 14:26:11 +04:00
|
|
|
|
|
|
|
// xblBinding takes ownership of docInfo.
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<nsXBLBinding> xblBinding = new nsXBLBinding(shadowRoot, protoBinding);
|
2013-12-02 14:26:12 +04:00
|
|
|
shadowRoot->SetAssociatedBinding(xblBinding);
|
2013-12-02 14:26:11 +04:00
|
|
|
xblBinding->SetBoundElement(this);
|
|
|
|
|
|
|
|
SetXBLBinding(xblBinding);
|
|
|
|
|
|
|
|
// Recreate the frame for the bound content because binding a ShadowRoot
|
|
|
|
// changes how things are rendered.
|
|
|
|
if (doc) {
|
2016-03-31 15:20:14 +03:00
|
|
|
MOZ_ASSERT(doc == GetComposedDoc());
|
2014-10-23 17:19:25 +04:00
|
|
|
nsIPresShell* shell = doc->GetShell();
|
2013-12-02 14:26:11 +04:00
|
|
|
if (shell) {
|
2014-10-23 17:19:25 +04:00
|
|
|
shell->CreateFramesFor(destroyedFramesFor);
|
2013-12-02 14:26:11 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return shadowRoot.forget();
|
|
|
|
}
|
2007-02-01 18:14:00 +03:00
|
|
|
|
2015-07-18 01:16:43 +03:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(DestinationInsertionPointList, mParent,
|
|
|
|
mDestinationPoints)
|
2014-05-22 10:11:53 +04:00
|
|
|
|
|
|
|
NS_INTERFACE_TABLE_HEAD(DestinationInsertionPointList)
|
2015-07-18 01:16:43 +03:00
|
|
|
NS_WRAPPERCACHE_INTERFACE_TABLE_ENTRY
|
|
|
|
NS_INTERFACE_TABLE(DestinationInsertionPointList, nsINodeList, nsIDOMNodeList)
|
2014-05-22 10:11:53 +04:00
|
|
|
NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(DestinationInsertionPointList)
|
|
|
|
NS_INTERFACE_MAP_END
|
|
|
|
|
|
|
|
NS_IMPL_CYCLE_COLLECTING_ADDREF(DestinationInsertionPointList)
|
|
|
|
NS_IMPL_CYCLE_COLLECTING_RELEASE(DestinationInsertionPointList)
|
|
|
|
|
|
|
|
DestinationInsertionPointList::DestinationInsertionPointList(Element* aElement)
|
|
|
|
: mParent(aElement)
|
|
|
|
{
|
|
|
|
nsTArray<nsIContent*>* destPoints = aElement->GetExistingDestInsertionPoints();
|
|
|
|
if (destPoints) {
|
|
|
|
for (uint32_t i = 0; i < destPoints->Length(); i++) {
|
|
|
|
mDestinationPoints.AppendElement(destPoints->ElementAt(i));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
DestinationInsertionPointList::~DestinationInsertionPointList()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
nsIContent*
|
|
|
|
DestinationInsertionPointList::Item(uint32_t aIndex)
|
|
|
|
{
|
|
|
|
return mDestinationPoints.SafeElementAt(aIndex);
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
DestinationInsertionPointList::Item(uint32_t aIndex, nsIDOMNode** aReturn)
|
|
|
|
{
|
|
|
|
nsIContent* item = Item(aIndex);
|
|
|
|
if (!item) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return CallQueryInterface(item, aReturn);
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32_t
|
|
|
|
DestinationInsertionPointList::Length() const
|
|
|
|
{
|
|
|
|
return mDestinationPoints.Length();
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
DestinationInsertionPointList::GetLength(uint32_t* aLength)
|
|
|
|
{
|
|
|
|
*aLength = Length();
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
int32_t
|
|
|
|
DestinationInsertionPointList::IndexOf(nsIContent* aContent)
|
|
|
|
{
|
|
|
|
return mDestinationPoints.IndexOf(aContent);
|
|
|
|
}
|
|
|
|
|
|
|
|
JSObject*
|
Bug 1117172 part 3. Change the wrappercached WrapObject methods to allow passing in aGivenProto. r=peterv
The only manual changes here are to BindingUtils.h, BindingUtils.cpp,
Codegen.py, Element.cpp, IDBFileRequest.cpp, IDBObjectStore.cpp,
dom/workers/Navigator.cpp, WorkerPrivate.cpp, DeviceStorageRequestChild.cpp,
Notification.cpp, nsGlobalWindow.cpp, MessagePort.cpp, nsJSEnvironment.cpp,
Sandbox.cpp, XPCConvert.cpp, ExportHelpers.cpp, and DataStoreService.cpp. The
rest of this diff was generated by running the following commands:
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapObjectInternal\(JSContext *\* *(?:aCx|cx|aContext|aCtx|js))\)/\1, JS::Handle<JSObject*> aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapObjectInternal\((?:aCx|cx|aContext|aCtx|js))\)/\1, aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapNode\(JSContext *\* *(?:aCx|cx|aContext|aCtx|js))\)/\1, JS::Handle<JSObject*> aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapNode\((?:aCx|cx|aContext|aCtx|js))\)/\1, aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapObject\(JSContext *\* *(?:aCx|cx|aContext|aCtx|js))\)/\1, JS::Handle<JSObject*> aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(Binding(?:_workers)?::Wrap\((?:aCx|cx|aContext|aCtx|js), [^,)]+)\)/\1, aGivenProto)/g'
2015-03-19 17:13:33 +03:00
|
|
|
DestinationInsertionPointList::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
|
2014-05-22 10:11:53 +04:00
|
|
|
{
|
Bug 1117172 part 3. Change the wrappercached WrapObject methods to allow passing in aGivenProto. r=peterv
The only manual changes here are to BindingUtils.h, BindingUtils.cpp,
Codegen.py, Element.cpp, IDBFileRequest.cpp, IDBObjectStore.cpp,
dom/workers/Navigator.cpp, WorkerPrivate.cpp, DeviceStorageRequestChild.cpp,
Notification.cpp, nsGlobalWindow.cpp, MessagePort.cpp, nsJSEnvironment.cpp,
Sandbox.cpp, XPCConvert.cpp, ExportHelpers.cpp, and DataStoreService.cpp. The
rest of this diff was generated by running the following commands:
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapObjectInternal\(JSContext *\* *(?:aCx|cx|aContext|aCtx|js))\)/\1, JS::Handle<JSObject*> aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapObjectInternal\((?:aCx|cx|aContext|aCtx|js))\)/\1, aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapNode\(JSContext *\* *(?:aCx|cx|aContext|aCtx|js))\)/\1, JS::Handle<JSObject*> aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapNode\((?:aCx|cx|aContext|aCtx|js))\)/\1, aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(WrapObject\(JSContext *\* *(?:aCx|cx|aContext|aCtx|js))\)/\1, JS::Handle<JSObject*> aGivenProto)/g'
find . -name "*.h" -o -name "*.cpp" | xargs perl -pi -e 'BEGIN { $/ = undef } s/(Binding(?:_workers)?::Wrap\((?:aCx|cx|aContext|aCtx|js), [^,)]+)\)/\1, aGivenProto)/g'
2015-03-19 17:13:33 +03:00
|
|
|
return NodeListBinding::Wrap(aCx, this, aGivenProto);
|
2014-05-22 10:11:53 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
already_AddRefed<DestinationInsertionPointList>
|
|
|
|
Element::GetDestinationInsertionPoints()
|
|
|
|
{
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<DestinationInsertionPointList> list =
|
2014-05-22 10:11:53 +04:00
|
|
|
new DestinationInsertionPointList(this);
|
|
|
|
return list.forget();
|
|
|
|
}
|
|
|
|
|
2012-10-16 15:51:00 +04:00
|
|
|
void
|
2013-01-29 18:42:15 +04:00
|
|
|
Element::GetAttribute(const nsAString& aName, DOMString& aReturn)
|
2006-11-11 03:36:03 +03:00
|
|
|
{
|
2012-07-31 19:36:21 +04:00
|
|
|
const nsAttrValue* val =
|
|
|
|
mAttrsAndChildren.GetAttr(aName,
|
2015-03-03 14:08:59 +03:00
|
|
|
IsHTMLElement() && IsInHTMLDocument() ?
|
2012-07-31 19:36:21 +04:00
|
|
|
eIgnoreCase : eCaseMatters);
|
|
|
|
if (val) {
|
|
|
|
val->ToString(aReturn);
|
|
|
|
} else {
|
2015-03-03 14:08:59 +03:00
|
|
|
if (IsXULElement()) {
|
2012-07-31 19:36:21 +04:00
|
|
|
// XXX should be SetDOMStringToNull(aReturn);
|
|
|
|
// See bug 232598
|
2013-01-29 18:42:15 +04:00
|
|
|
// aReturn is already empty
|
2012-07-31 19:36:21 +04:00
|
|
|
} else {
|
2013-01-29 18:42:15 +04:00
|
|
|
aReturn.SetNull();
|
2012-07-31 19:36:21 +04:00
|
|
|
}
|
2006-11-11 03:36:03 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-16 15:51:00 +04:00
|
|
|
void
|
2012-11-15 02:10:08 +04:00
|
|
|
Element::SetAttribute(const nsAString& aName,
|
|
|
|
const nsAString& aValue,
|
|
|
|
ErrorResult& aError)
|
2012-07-31 19:36:21 +04:00
|
|
|
{
|
2016-04-15 16:01:00 +03:00
|
|
|
aError = nsContentUtils::CheckQName(aName, false);
|
|
|
|
if (aError.Failed()) {
|
|
|
|
return;
|
|
|
|
}
|
2016-05-31 18:56:20 +03:00
|
|
|
|
|
|
|
nsAutoString nameToUse;
|
|
|
|
const nsAttrName* name = InternalGetAttrNameFromQName(aName, &nameToUse);
|
2012-07-31 19:36:21 +04:00
|
|
|
if (!name) {
|
2016-05-31 18:56:20 +03:00
|
|
|
nsCOMPtr<nsIAtom> nameAtom = NS_Atomize(nameToUse);
|
2012-10-16 15:51:00 +04:00
|
|
|
if (!nameAtom) {
|
|
|
|
aError.Throw(NS_ERROR_OUT_OF_MEMORY);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
aError = SetAttr(kNameSpaceID_None, nameAtom, aValue, true);
|
|
|
|
return;
|
2012-07-31 19:36:21 +04:00
|
|
|
}
|
2008-07-22 04:55:52 +04:00
|
|
|
|
2012-10-16 15:51:00 +04:00
|
|
|
aError = SetAttr(name->NamespaceID(), name->LocalName(), name->GetPrefix(),
|
|
|
|
aValue, true);
|
|
|
|
return;
|
2008-07-22 04:55:52 +04:00
|
|
|
}
|
|
|
|
|
2012-10-16 15:51:00 +04:00
|
|
|
void
|
2012-11-15 02:10:08 +04:00
|
|
|
Element::RemoveAttribute(const nsAString& aName, ErrorResult& aError)
|
2008-07-22 04:55:52 +04:00
|
|
|
{
|
2016-05-31 18:56:20 +03:00
|
|
|
const nsAttrName* name = InternalGetAttrNameFromQName(aName);
|
2008-07-22 04:55:52 +04:00
|
|
|
|
2012-07-31 19:36:21 +04:00
|
|
|
if (!name) {
|
|
|
|
// If there is no canonical nsAttrName for this attribute name, then the
|
|
|
|
// attribute does not exist and we can't get its namespace ID and
|
|
|
|
// local name below, so we return early.
|
2012-10-16 15:51:00 +04:00
|
|
|
return;
|
2012-07-31 19:36:21 +04:00
|
|
|
}
|
2011-08-24 23:49:25 +04:00
|
|
|
|
2012-07-31 19:36:21 +04:00
|
|
|
// Hold a strong reference here so that the atom or nodeinfo doesn't go
|
|
|
|
// away during UnsetAttr. If it did UnsetAttr would be left with a
|
|
|
|
// dangling pointer as argument without knowing it.
|
|
|
|
nsAttrName tmp(*name);
|
2011-08-24 23:49:25 +04:00
|
|
|
|
2012-10-16 15:51:00 +04:00
|
|
|
aError = UnsetAttr(name->NamespaceID(), name->LocalName(), true);
|
2012-07-31 19:36:21 +04:00
|
|
|
}
|
2011-08-24 23:49:25 +04:00
|
|
|
|
2013-04-09 19:29:47 +04:00
|
|
|
Attr*
|
2012-11-15 02:10:08 +04:00
|
|
|
Element::GetAttributeNode(const nsAString& aName)
|
2012-07-31 19:36:21 +04:00
|
|
|
{
|
2012-10-16 15:51:00 +04:00
|
|
|
OwnerDoc()->WarnOnceAbout(nsIDocument::eGetAttributeNode);
|
2013-03-10 11:58:47 +04:00
|
|
|
return Attributes()->GetNamedItem(aName);
|
2002-08-13 04:50:50 +04:00
|
|
|
}
|
|
|
|
|
2013-04-09 19:29:47 +04:00
|
|
|
already_AddRefed<Attr>
|
|
|
|
Element::SetAttributeNode(Attr& aNewAttr, ErrorResult& aError)
|
2006-08-25 14:00:11 +04:00
|
|
|
{
|
2015-12-04 17:51:04 +03:00
|
|
|
// XXXbz can we just remove this warning and the one in setAttributeNodeNS and
|
|
|
|
// alias setAttributeNode to setAttributeNodeNS?
|
2012-07-31 19:36:21 +04:00
|
|
|
OwnerDoc()->WarnOnceAbout(nsIDocument::eSetAttributeNode);
|
2011-08-28 18:07:24 +04:00
|
|
|
|
2015-12-04 17:51:04 +03:00
|
|
|
return Attributes()->SetNamedItemNS(aNewAttr, aError);
|
2011-08-28 18:07:24 +04:00
|
|
|
}
|
|
|
|
|
2013-04-09 19:29:47 +04:00
|
|
|
already_AddRefed<Attr>
|
|
|
|
Element::RemoveAttributeNode(Attr& aAttribute,
|
2012-11-15 02:10:08 +04:00
|
|
|
ErrorResult& aError)
|
1998-11-12 01:06:16 +03:00
|
|
|
{
|
2015-01-25 17:39:05 +03:00
|
|
|
Element *elem = aAttribute.GetElement();
|
|
|
|
if (elem != this) {
|
|
|
|
aError.Throw(NS_ERROR_DOM_NOT_FOUND_ERR);
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2011-10-18 15:19:44 +04:00
|
|
|
OwnerDoc()->WarnOnceAbout(nsIDocument::eRemoveAttributeNode);
|
2015-09-22 20:13:26 +03:00
|
|
|
nsAutoString nameSpaceURI;
|
|
|
|
aAttribute.NodeInfo()->GetNamespaceURI(nameSpaceURI);
|
|
|
|
return Attributes()->RemoveNamedItemNS(nameSpaceURI, aAttribute.NodeInfo()->LocalName(), aError);
|
1998-11-12 01:06:16 +03:00
|
|
|
}
|
|
|
|
|
2012-10-16 15:51:00 +04:00
|
|
|
void
|
2012-11-15 02:10:08 +04:00
|
|
|
Element::GetAttributeNS(const nsAString& aNamespaceURI,
|
|
|
|
const nsAString& aLocalName,
|
|
|
|
nsAString& aReturn)
|
2000-05-16 00:31:55 +04:00
|
|
|
{
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t nsid =
|
2016-06-28 17:24:48 +03:00
|
|
|
nsContentUtils::NameSpaceManager()->GetNameSpaceID(aNamespaceURI,
|
|
|
|
nsContentUtils::IsChromeDoc(OwnerDoc()));
|
2000-05-16 00:31:55 +04:00
|
|
|
|
|
|
|
if (nsid == kNameSpaceID_Unknown) {
|
2012-03-11 12:48:16 +04:00
|
|
|
// Unknown namespace means no attribute.
|
|
|
|
SetDOMStringToNull(aReturn);
|
2012-10-16 15:51:00 +04:00
|
|
|
return;
|
2000-05-16 00:31:55 +04:00
|
|
|
}
|
|
|
|
|
2016-03-29 02:09:43 +03:00
|
|
|
nsCOMPtr<nsIAtom> name = NS_Atomize(aLocalName);
|
2012-03-11 12:48:16 +04:00
|
|
|
bool hasAttr = GetAttr(nsid, name, aReturn);
|
|
|
|
if (!hasAttr) {
|
|
|
|
SetDOMStringToNull(aReturn);
|
|
|
|
}
|
2000-05-16 00:31:55 +04:00
|
|
|
}
|
|
|
|
|
2012-10-16 15:51:00 +04:00
|
|
|
void
|
2012-11-15 02:10:08 +04:00
|
|
|
Element::SetAttributeNS(const nsAString& aNamespaceURI,
|
|
|
|
const nsAString& aQualifiedName,
|
|
|
|
const nsAString& aValue,
|
|
|
|
ErrorResult& aError)
|
2000-05-16 00:31:55 +04:00
|
|
|
{
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<mozilla::dom::NodeInfo> ni;
|
2012-10-16 15:51:00 +04:00
|
|
|
aError =
|
2004-02-10 13:58:13 +03:00
|
|
|
nsContentUtils::GetNodeInfoFromQName(aNamespaceURI, aQualifiedName,
|
|
|
|
mNodeInfo->NodeInfoManager(),
|
2011-06-14 11:56:49 +04:00
|
|
|
nsIDOMNode::ATTRIBUTE_NODE,
|
2004-02-10 13:58:13 +03:00
|
|
|
getter_AddRefs(ni));
|
2012-10-16 15:51:00 +04:00
|
|
|
if (aError.Failed()) {
|
|
|
|
return;
|
|
|
|
}
|
2000-05-16 00:31:55 +04:00
|
|
|
|
2012-10-16 15:51:00 +04:00
|
|
|
aError = SetAttr(ni->NamespaceID(), ni->NameAtom(), ni->GetPrefixAtom(),
|
|
|
|
aValue, true);
|
2000-05-16 00:31:55 +04:00
|
|
|
}
|
|
|
|
|
2012-10-16 15:51:00 +04:00
|
|
|
void
|
2012-11-15 02:10:08 +04:00
|
|
|
Element::RemoveAttributeNS(const nsAString& aNamespaceURI,
|
|
|
|
const nsAString& aLocalName,
|
|
|
|
ErrorResult& aError)
|
2000-05-16 00:31:55 +04:00
|
|
|
{
|
2016-03-29 02:09:43 +03:00
|
|
|
nsCOMPtr<nsIAtom> name = NS_Atomize(aLocalName);
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t nsid =
|
2016-06-28 17:24:48 +03:00
|
|
|
nsContentUtils::NameSpaceManager()->GetNameSpaceID(aNamespaceURI,
|
|
|
|
nsContentUtils::IsChromeDoc(OwnerDoc()));
|
2000-05-16 00:31:55 +04:00
|
|
|
|
|
|
|
if (nsid == kNameSpaceID_Unknown) {
|
2012-03-05 03:38:03 +04:00
|
|
|
// If the namespace ID is unknown, it means there can't possibly be an
|
|
|
|
// existing attribute. We would need a known namespace ID to pass into
|
|
|
|
// UnsetAttr, so we return early if we don't have one.
|
2012-10-16 15:51:00 +04:00
|
|
|
return;
|
2000-05-16 00:31:55 +04:00
|
|
|
}
|
|
|
|
|
2012-10-16 15:51:00 +04:00
|
|
|
aError = UnsetAttr(nsid, name, true);
|
2000-05-16 00:31:55 +04:00
|
|
|
}
|
|
|
|
|
2013-04-09 19:29:47 +04:00
|
|
|
Attr*
|
2012-11-15 02:10:08 +04:00
|
|
|
Element::GetAttributeNodeNS(const nsAString& aNamespaceURI,
|
2013-04-04 16:01:11 +04:00
|
|
|
const nsAString& aLocalName)
|
2000-05-16 00:31:55 +04:00
|
|
|
{
|
2011-10-18 15:19:44 +04:00
|
|
|
OwnerDoc()->WarnOnceAbout(nsIDocument::eGetAttributeNodeNS);
|
2011-06-23 12:30:48 +04:00
|
|
|
|
2013-04-04 16:01:11 +04:00
|
|
|
return GetAttributeNodeNSInternal(aNamespaceURI, aLocalName);
|
2012-02-28 03:57:28 +04:00
|
|
|
}
|
|
|
|
|
2013-04-09 19:29:47 +04:00
|
|
|
Attr*
|
2012-11-15 02:10:08 +04:00
|
|
|
Element::GetAttributeNodeNSInternal(const nsAString& aNamespaceURI,
|
2013-04-04 16:01:11 +04:00
|
|
|
const nsAString& aLocalName)
|
2012-02-28 03:57:28 +04:00
|
|
|
{
|
2013-04-04 16:01:11 +04:00
|
|
|
return Attributes()->GetNamedItemNS(aNamespaceURI, aLocalName);
|
2000-05-16 00:31:55 +04:00
|
|
|
}
|
|
|
|
|
2013-04-09 19:29:47 +04:00
|
|
|
already_AddRefed<Attr>
|
|
|
|
Element::SetAttributeNodeNS(Attr& aNewAttr,
|
2012-11-15 02:10:08 +04:00
|
|
|
ErrorResult& aError)
|
2000-05-16 00:31:55 +04:00
|
|
|
{
|
2011-10-18 15:19:44 +04:00
|
|
|
OwnerDoc()->WarnOnceAbout(nsIDocument::eSetAttributeNodeNS);
|
2013-04-26 10:48:23 +04:00
|
|
|
return Attributes()->SetNamedItemNS(aNewAttr, aError);
|
2000-05-16 00:31:55 +04:00
|
|
|
}
|
|
|
|
|
2012-10-16 15:51:00 +04:00
|
|
|
already_AddRefed<nsIHTMLCollection>
|
2012-11-15 02:10:08 +04:00
|
|
|
Element::GetElementsByTagNameNS(const nsAString& aNamespaceURI,
|
|
|
|
const nsAString& aLocalName,
|
|
|
|
ErrorResult& aError)
|
2000-05-16 00:31:55 +04:00
|
|
|
{
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t nameSpaceId = kNameSpaceID_Wildcard;
|
2000-12-23 13:56:31 +03:00
|
|
|
|
2004-05-23 02:15:22 +04:00
|
|
|
if (!aNamespaceURI.EqualsLiteral("*")) {
|
2012-10-16 15:51:00 +04:00
|
|
|
aError =
|
2006-07-20 07:25:39 +04:00
|
|
|
nsContentUtils::NameSpaceManager()->RegisterNameSpace(aNamespaceURI,
|
|
|
|
nameSpaceId);
|
2012-10-16 15:51:00 +04:00
|
|
|
if (aError.Failed()) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
2000-05-16 00:31:55 +04:00
|
|
|
}
|
|
|
|
|
2010-11-23 22:10:56 +03:00
|
|
|
NS_ASSERTION(nameSpaceId != kNameSpaceID_Unknown, "Unexpected namespace ID!");
|
2003-02-01 02:21:22 +03:00
|
|
|
|
2012-10-16 15:51:00 +04:00
|
|
|
return NS_GetContentList(this, nameSpaceId, aLocalName);
|
2000-05-16 00:31:55 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
2012-11-15 02:10:08 +04:00
|
|
|
Element::GetElementsByTagNameNS(const nsAString& namespaceURI,
|
|
|
|
const nsAString& localName,
|
|
|
|
nsIDOMHTMLCollection** aResult)
|
2000-05-16 00:31:55 +04:00
|
|
|
{
|
2012-10-16 15:51:00 +04:00
|
|
|
mozilla::ErrorResult rv;
|
|
|
|
nsCOMPtr<nsIHTMLCollection> list =
|
|
|
|
GetElementsByTagNameNS(namespaceURI, localName, rv);
|
|
|
|
if (rv.Failed()) {
|
2015-04-27 16:18:51 +03:00
|
|
|
return rv.StealNSResult();
|
2012-10-16 15:51:00 +04:00
|
|
|
}
|
|
|
|
list.forget(aResult);
|
2000-05-16 00:31:55 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2012-10-16 15:51:00 +04:00
|
|
|
bool
|
2012-11-15 02:10:08 +04:00
|
|
|
Element::HasAttributeNS(const nsAString& aNamespaceURI,
|
|
|
|
const nsAString& aLocalName) const
|
2000-05-16 00:31:55 +04:00
|
|
|
{
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t nsid =
|
2016-06-28 17:24:48 +03:00
|
|
|
nsContentUtils::NameSpaceManager()->GetNameSpaceID(aNamespaceURI,
|
|
|
|
nsContentUtils::IsChromeDoc(OwnerDoc()));
|
2000-05-16 00:31:55 +04:00
|
|
|
|
|
|
|
if (nsid == kNameSpaceID_Unknown) {
|
2004-04-13 05:27:25 +04:00
|
|
|
// Unknown namespace means no attr...
|
2012-10-16 15:51:00 +04:00
|
|
|
return false;
|
2000-05-16 00:31:55 +04:00
|
|
|
}
|
|
|
|
|
2016-03-29 02:09:43 +03:00
|
|
|
nsCOMPtr<nsIAtom> name = NS_Atomize(aLocalName);
|
2012-10-16 15:51:00 +04:00
|
|
|
return HasAttr(nsid, name);
|
2000-05-16 00:31:55 +04:00
|
|
|
}
|
|
|
|
|
2012-10-16 15:51:00 +04:00
|
|
|
already_AddRefed<nsIHTMLCollection>
|
2012-11-15 02:10:08 +04:00
|
|
|
Element::GetElementsByClassName(const nsAString& aClassNames)
|
2012-10-16 15:51:00 +04:00
|
|
|
{
|
|
|
|
return nsContentUtils::GetElementsByClassName(this, aClassNames);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
2012-11-15 02:10:08 +04:00
|
|
|
Element::GetElementsByClassName(const nsAString& aClassNames,
|
|
|
|
nsIDOMHTMLCollection** aResult)
|
2012-10-16 15:51:00 +04:00
|
|
|
{
|
2014-03-15 23:00:15 +04:00
|
|
|
*aResult =
|
|
|
|
nsContentUtils::GetElementsByClassName(this, aClassNames).take();
|
2012-10-16 15:51:00 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2015-08-14 20:52:38 +03:00
|
|
|
/**
|
|
|
|
* Returns the count of descendants (inclusive of aContent) in
|
|
|
|
* the uncomposed document that are explicitly set as editable.
|
|
|
|
*/
|
|
|
|
static uint32_t
|
|
|
|
EditableInclusiveDescendantCount(nsIContent* aContent)
|
|
|
|
{
|
|
|
|
auto htmlElem = nsGenericHTMLElement::FromContent(aContent);
|
|
|
|
if (htmlElem) {
|
|
|
|
return htmlElem->EditableInclusiveDescendantCount();
|
|
|
|
}
|
|
|
|
|
|
|
|
return aContent->EditableDescendantCount();
|
|
|
|
}
|
|
|
|
|
2005-04-06 03:54:35 +04:00
|
|
|
nsresult
|
2012-11-15 02:10:08 +04:00
|
|
|
Element::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
|
|
|
|
nsIContent* aBindingParent,
|
|
|
|
bool aCompileEventHandlers)
|
2005-04-06 03:54:35 +04:00
|
|
|
{
|
|
|
|
NS_PRECONDITION(aParent || aDocument, "Must have document if no parent!");
|
2013-08-02 14:24:41 +04:00
|
|
|
NS_PRECONDITION((NODE_FROM(aParent, aDocument)->OwnerDoc() == OwnerDoc()),
|
2006-11-22 21:35:05 +03:00
|
|
|
"Must have the same owner document");
|
2014-10-02 22:45:44 +04:00
|
|
|
NS_PRECONDITION(!aParent || aDocument == aParent->GetUncomposedDoc(),
|
2005-04-06 03:54:35 +04:00
|
|
|
"aDocument must be current doc of aParent");
|
2014-10-02 22:45:44 +04:00
|
|
|
NS_PRECONDITION(!GetUncomposedDoc(), "Already have a document. Unbind first!");
|
2005-04-06 03:54:35 +04:00
|
|
|
// Note that as we recurse into the kids, they'll have a non-null parent. So
|
|
|
|
// only assert if our parent is _changing_ while we have a parent.
|
|
|
|
NS_PRECONDITION(!GetParent() || aParent == GetParent(),
|
|
|
|
"Already have a parent. Unbind first!");
|
|
|
|
NS_PRECONDITION(!GetBindingParent() ||
|
|
|
|
aBindingParent == GetBindingParent() ||
|
|
|
|
(!aBindingParent && aParent &&
|
|
|
|
aParent->GetBindingParent() == GetBindingParent()),
|
|
|
|
"Already have a binding parent. Unbind first!");
|
2007-05-22 02:26:48 +04:00
|
|
|
NS_PRECONDITION(!aParent || !aDocument ||
|
|
|
|
!aParent->HasFlag(NODE_FORCE_XBL_BINDINGS),
|
|
|
|
"Parent in document but flagged as forcing XBL");
|
2008-07-23 08:50:20 +04:00
|
|
|
NS_PRECONDITION(aBindingParent != this,
|
|
|
|
"Content must not be its own binding parent");
|
|
|
|
NS_PRECONDITION(!IsRootOfNativeAnonymousSubtree() ||
|
|
|
|
aBindingParent == aParent,
|
|
|
|
"Native anonymous content must have its parent as its "
|
2008-02-26 15:40:18 +03:00
|
|
|
"own binding parent");
|
2012-03-22 08:10:51 +04:00
|
|
|
NS_PRECONDITION(aBindingParent || !aParent ||
|
|
|
|
aBindingParent == aParent->GetBindingParent(),
|
|
|
|
"We should be passed the right binding parent");
|
1998-11-12 01:06:16 +03:00
|
|
|
|
2007-07-09 04:58:15 +04:00
|
|
|
#ifdef MOZ_XUL
|
2005-04-06 03:54:35 +04:00
|
|
|
// First set the binding parent
|
2007-05-16 05:13:47 +04:00
|
|
|
nsXULElement* xulElem = nsXULElement::FromContent(this);
|
|
|
|
if (xulElem) {
|
|
|
|
xulElem->SetXULBindingParent(aBindingParent);
|
|
|
|
}
|
2016-02-15 03:34:47 +03:00
|
|
|
else
|
2007-07-09 04:58:15 +04:00
|
|
|
#endif
|
|
|
|
{
|
2007-05-16 05:13:47 +04:00
|
|
|
if (aBindingParent) {
|
2010-12-22 04:04:00 +03:00
|
|
|
nsDOMSlots *slots = DOMSlots();
|
2000-05-10 05:09:45 +04:00
|
|
|
|
2007-05-16 05:13:47 +04:00
|
|
|
slots->mBindingParent = aBindingParent; // Weak, so no addref happens.
|
|
|
|
}
|
2005-04-06 03:54:35 +04:00
|
|
|
}
|
2008-07-23 08:50:20 +04:00
|
|
|
NS_ASSERTION(!aBindingParent || IsRootOfNativeAnonymousSubtree() ||
|
2014-04-06 23:32:38 +04:00
|
|
|
!HasFlag(NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE) ||
|
2008-12-03 13:18:57 +03:00
|
|
|
(aParent && aParent->IsInNativeAnonymousSubtree()),
|
2008-10-23 04:55:04 +04:00
|
|
|
"Trying to re-bind content from native anonymous subtree to "
|
2008-04-12 02:44:48 +04:00
|
|
|
"non-native anonymous parent!");
|
2012-10-10 23:04:42 +04:00
|
|
|
if (aParent) {
|
|
|
|
if (aParent->IsInNativeAnonymousSubtree()) {
|
2014-04-06 23:32:38 +04:00
|
|
|
SetFlags(NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE);
|
2012-10-10 23:04:42 +04:00
|
|
|
}
|
|
|
|
if (aParent->HasFlag(NODE_CHROME_ONLY_ACCESS)) {
|
|
|
|
SetFlags(NODE_CHROME_ONLY_ACCESS);
|
|
|
|
}
|
2014-07-03 21:02:07 +04:00
|
|
|
if (aParent->IsInShadowTree()) {
|
2014-06-07 12:42:53 +04:00
|
|
|
ClearSubtreeRootPointer();
|
2013-12-02 14:26:11 +04:00
|
|
|
SetFlags(NODE_IS_IN_SHADOW_TREE);
|
|
|
|
}
|
|
|
|
ShadowRoot* parentContainingShadow = aParent->GetContainingShadow();
|
|
|
|
if (parentContainingShadow) {
|
|
|
|
DOMSlots()->mContainingShadow = parentContainingShadow;
|
|
|
|
}
|
2008-04-12 02:44:48 +04:00
|
|
|
}
|
2004-08-10 14:22:36 +04:00
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool hadForceXBL = HasFlag(NODE_FORCE_XBL_BINDINGS);
|
2007-05-22 02:26:48 +04:00
|
|
|
|
2015-08-14 20:52:38 +03:00
|
|
|
bool hadParent = !!GetParentNode();
|
|
|
|
|
2007-05-16 05:13:47 +04:00
|
|
|
// Now set the parent and set the "Force attach xbl" flag if needed.
|
2006-04-15 09:09:16 +04:00
|
|
|
if (aParent) {
|
2011-07-26 15:11:14 +04:00
|
|
|
if (!GetParent()) {
|
|
|
|
NS_ADDREF(aParent);
|
|
|
|
}
|
2011-04-08 06:29:49 +04:00
|
|
|
mParent = aParent;
|
2007-05-16 05:13:47 +04:00
|
|
|
|
|
|
|
if (aParent->HasFlag(NODE_FORCE_XBL_BINDINGS)) {
|
|
|
|
SetFlags(NODE_FORCE_XBL_BINDINGS);
|
|
|
|
}
|
2006-04-15 09:09:16 +04:00
|
|
|
}
|
|
|
|
else {
|
2011-04-08 06:29:49 +04:00
|
|
|
mParent = aDocument;
|
2006-04-15 09:09:16 +04:00
|
|
|
}
|
2011-04-08 06:29:49 +04:00
|
|
|
SetParentIsContent(aParent);
|
2004-08-24 22:50:29 +04:00
|
|
|
|
2006-04-11 07:49:44 +04:00
|
|
|
// XXXbz sXBL/XBL2 issue!
|
|
|
|
|
2005-04-06 03:54:35 +04:00
|
|
|
// Finally, set the document
|
|
|
|
if (aDocument) {
|
|
|
|
// Notify XBL- & nsIAnonymousContentCreator-generated
|
|
|
|
// anonymous content that the document is changing.
|
|
|
|
// XXXbz ordering issues here? Probably not, since ChangeDocumentFor is
|
|
|
|
// just pretty broken anyway.... Need to get it working.
|
|
|
|
// XXXbz XBL doesn't handle this (asserts), and we don't really want
|
2016-02-15 03:34:47 +03:00
|
|
|
// to be doing this during parsing anyway... sort this out.
|
2012-07-30 18:20:58 +04:00
|
|
|
// aDocument->BindingManager()->ChangeDocumentFor(this, nullptr,
|
2005-04-06 03:54:35 +04:00
|
|
|
// aDocument);
|
|
|
|
|
2012-03-15 00:14:02 +04:00
|
|
|
// We no longer need to track the subtree pointer (and in fact we'll assert
|
|
|
|
// if we do this any later).
|
|
|
|
ClearSubtreeRootPointer();
|
|
|
|
|
2005-04-06 03:54:35 +04:00
|
|
|
// Being added to a document.
|
2016-07-08 10:07:06 +03:00
|
|
|
SetIsInDocument();
|
2007-05-16 05:13:47 +04:00
|
|
|
|
|
|
|
// Unset this flag since we now really are in a document.
|
2010-01-18 12:26:40 +03:00
|
|
|
UnsetFlags(NODE_FORCE_XBL_BINDINGS |
|
|
|
|
// And clear the lazy frame construction bits.
|
2016-07-15 10:21:38 +03:00
|
|
|
NODE_NEEDS_FRAME | NODE_DESCENDANTS_NEED_FRAMES);
|
|
|
|
// And the restyle bits
|
|
|
|
UnsetRestyleFlagsIfGecko();
|
2014-11-15 01:08:21 +03:00
|
|
|
} else if (IsInShadowTree()) {
|
|
|
|
// We're not in a document, but we did get inserted into a shadow tree.
|
|
|
|
// Since we won't have any restyle data in the document's restyle trackers,
|
|
|
|
// don't let us get inserted with restyle bits set incorrectly.
|
|
|
|
//
|
|
|
|
// Also clear all the other flags that are cleared above when we do get
|
|
|
|
// inserted into a document.
|
|
|
|
UnsetFlags(NODE_FORCE_XBL_BINDINGS |
|
2016-07-15 10:21:38 +03:00
|
|
|
NODE_NEEDS_FRAME | NODE_DESCENDANTS_NEED_FRAMES);
|
|
|
|
UnsetRestyleFlagsIfGecko();
|
2014-11-15 01:08:21 +03:00
|
|
|
} else {
|
2014-06-07 12:42:53 +04:00
|
|
|
// If we're not in the doc and not in a shadow tree,
|
|
|
|
// update our subtree pointer.
|
2012-03-15 00:14:02 +04:00
|
|
|
SetSubtreeRootPointer(aParent->SubtreeRoot());
|
1998-11-12 01:06:16 +03:00
|
|
|
}
|
|
|
|
|
2015-02-09 21:01:24 +03:00
|
|
|
nsIDocument* composedDoc = GetComposedDoc();
|
|
|
|
if (composedDoc) {
|
|
|
|
// Attached callback must be enqueued whenever custom element is inserted into a
|
|
|
|
// document and this document has a browsing context.
|
|
|
|
if (GetCustomElementData() && composedDoc->GetDocShell()) {
|
|
|
|
// Enqueue an attached callback for the custom element.
|
|
|
|
composedDoc->EnqueueLifecycleCallback(nsIDocument::eAttached, this);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-06-06 09:23:40 +04:00
|
|
|
// Propagate scoped style sheet tracking bit.
|
|
|
|
if (mParent->IsContent()) {
|
|
|
|
nsIContent* parent;
|
|
|
|
ShadowRoot* shadowRootParent = ShadowRoot::FromNode(mParent);
|
|
|
|
if (shadowRootParent) {
|
|
|
|
parent = shadowRootParent->GetHost();
|
|
|
|
} else {
|
|
|
|
parent = mParent->AsContent();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool inStyleScope = parent->IsElementInStyleScope();
|
|
|
|
|
|
|
|
SetIsElementInStyleScope(inStyleScope);
|
|
|
|
SetIsElementInStyleScopeFlagOnShadowTree(inStyleScope);
|
|
|
|
}
|
|
|
|
|
2013-01-06 13:45:28 +04:00
|
|
|
// This has to be here, rather than in nsGenericHTMLElement::BindToTree,
|
2012-04-17 08:03:10 +04:00
|
|
|
// because it has to happen after updating the parent pointer, but before
|
|
|
|
// recursively binding the kids.
|
2015-03-03 14:08:59 +03:00
|
|
|
if (IsHTMLElement()) {
|
2013-01-06 13:45:28 +04:00
|
|
|
SetDirOnBind(this, aParent);
|
2012-04-17 08:03:10 +04:00
|
|
|
}
|
|
|
|
|
2015-08-14 20:52:38 +03:00
|
|
|
uint32_t editableDescendantCount = 0;
|
|
|
|
|
2007-05-22 02:26:48 +04:00
|
|
|
// If NODE_FORCE_XBL_BINDINGS was set we might have anonymous children
|
|
|
|
// that also need to be told that they are moving.
|
2006-11-22 21:35:05 +03:00
|
|
|
nsresult rv;
|
2007-05-22 02:26:48 +04:00
|
|
|
if (hadForceXBL) {
|
2011-10-18 15:19:44 +04:00
|
|
|
nsBindingManager* bmgr = OwnerDoc()->BindingManager();
|
|
|
|
|
2013-05-02 02:50:08 +04:00
|
|
|
nsXBLBinding* contBinding = bmgr->GetBindingWithContent(this);
|
2011-10-18 15:19:44 +04:00
|
|
|
// First check if we have a binding...
|
|
|
|
if (contBinding) {
|
|
|
|
nsCOMPtr<nsIContent> anonRoot = contBinding->GetAnonymousContent();
|
|
|
|
bool allowScripts = contBinding->AllowScripts();
|
|
|
|
for (nsCOMPtr<nsIContent> child = anonRoot->GetFirstChild();
|
|
|
|
child;
|
|
|
|
child = child->GetNextSibling()) {
|
|
|
|
rv = child->BindToTree(aDocument, this, this, allowScripts);
|
2007-05-23 02:41:32 +04:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2015-08-14 20:52:38 +03:00
|
|
|
|
|
|
|
editableDescendantCount += EditableInclusiveDescendantCount(child);
|
2007-05-22 02:26:48 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-10-17 18:59:28 +04:00
|
|
|
UpdateEditableState(false);
|
2007-06-28 06:48:16 +04:00
|
|
|
|
2007-05-22 02:26:48 +04:00
|
|
|
// Now recurse into our kids
|
2010-07-27 22:39:13 +04:00
|
|
|
for (nsIContent* child = GetFirstChild(); child;
|
|
|
|
child = child->GetNextSibling()) {
|
2006-10-03 21:52:22 +04:00
|
|
|
rv = child->BindToTree(aDocument, this, aBindingParent,
|
|
|
|
aCompileEventHandlers);
|
2005-04-06 03:54:35 +04:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2015-08-14 20:52:38 +03:00
|
|
|
|
|
|
|
editableDescendantCount += EditableInclusiveDescendantCount(child);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (aDocument) {
|
|
|
|
// Update our editable descendant count because we don't keep track of it
|
|
|
|
// for content that is not in the uncomposed document.
|
|
|
|
MOZ_ASSERT(EditableDescendantCount() == 0);
|
|
|
|
ChangeEditableDescendantCount(editableDescendantCount);
|
|
|
|
|
|
|
|
if (!hadParent) {
|
|
|
|
uint32_t editableDescendantChange = EditableInclusiveDescendantCount(this);
|
|
|
|
if (editableDescendantChange != 0) {
|
|
|
|
// If we are binding a subtree root to the document, we need to update
|
|
|
|
// the editable descendant count of all the ancestors.
|
|
|
|
nsIContent* parent = GetParent();
|
|
|
|
while (parent) {
|
|
|
|
parent->ChangeEditableDescendantCount(editableDescendantChange);
|
|
|
|
parent = parent->GetParent();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
1998-11-12 01:06:16 +03:00
|
|
|
}
|
|
|
|
|
2007-03-10 16:49:43 +03:00
|
|
|
nsNodeUtils::ParentChainChanged(this);
|
2015-09-24 18:23:32 +03:00
|
|
|
if (!hadParent && IsRootOfNativeAnonymousSubtree()) {
|
|
|
|
nsNodeUtils::NativeAnonymousChildListChange(this, false);
|
|
|
|
}
|
2007-03-10 16:49:43 +03:00
|
|
|
|
2013-12-02 14:26:11 +04:00
|
|
|
if (HasID()) {
|
|
|
|
AddToIdTable(DoGetID());
|
2012-03-22 08:10:51 +04:00
|
|
|
}
|
|
|
|
|
2015-03-03 14:08:59 +03:00
|
|
|
if (MayHaveStyle() && !IsXULElement()) {
|
2012-03-22 08:10:51 +04:00
|
|
|
// XXXbz if we already have a style attr parsed, this won't do
|
|
|
|
// anything... need to fix that.
|
|
|
|
// If MayHaveStyle() is true, we must be an nsStyledElement
|
|
|
|
static_cast<nsStyledElement*>(this)->ReparseStyleAttribute(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (aDocument) {
|
|
|
|
// If we're in a document now, let our mapped attrs know what their new
|
|
|
|
// sheet is. This is safe to run for non-mapped-attribute elements too;
|
|
|
|
// it'll just do a small bit of unnecessary work. But most elements in
|
|
|
|
// practice are mapped-attribute elements.
|
|
|
|
nsHTMLStyleSheet* sheet = aDocument->GetAttributeStyleSheet();
|
|
|
|
if (sheet) {
|
|
|
|
mAttrsAndChildren.SetMappedAttrStyleSheet(sheet);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-27 02:07:40 +04:00
|
|
|
// Call BindToTree on shadow root children.
|
|
|
|
ShadowRoot* shadowRoot = GetShadowRoot();
|
|
|
|
if (shadowRoot) {
|
2015-02-09 21:01:23 +03:00
|
|
|
shadowRoot->SetIsComposedDocParticipant(IsInComposedDoc());
|
2014-09-27 02:07:40 +04:00
|
|
|
for (nsIContent* child = shadowRoot->GetFirstChild(); child;
|
|
|
|
child = child->GetNextSibling()) {
|
|
|
|
rv = child->BindToTree(nullptr, shadowRoot,
|
|
|
|
shadowRoot->GetBindingParent(),
|
|
|
|
aCompileEventHandlers);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-04-06 03:54:35 +04:00
|
|
|
// XXXbz script execution during binding can trigger some of these
|
|
|
|
// postcondition asserts.... But we do want that, since things will
|
|
|
|
// generally be quite broken when that happens.
|
2014-10-02 22:45:44 +04:00
|
|
|
NS_POSTCONDITION(aDocument == GetUncomposedDoc(), "Bound to wrong document");
|
2005-04-06 03:54:35 +04:00
|
|
|
NS_POSTCONDITION(aParent == GetParent(), "Bound to wrong parent");
|
|
|
|
NS_POSTCONDITION(aBindingParent == GetBindingParent(),
|
|
|
|
"Bound to wrong binding parent");
|
2007-03-10 16:49:43 +03:00
|
|
|
|
2005-04-06 03:54:35 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
1998-11-12 01:06:16 +03:00
|
|
|
|
2014-10-02 22:45:44 +04:00
|
|
|
RemoveFromBindingManagerRunnable::RemoveFromBindingManagerRunnable(nsBindingManager* aManager,
|
|
|
|
nsIContent* aContent,
|
|
|
|
nsIDocument* aDoc):
|
|
|
|
mManager(aManager), mContent(aContent), mDoc(aDoc)
|
|
|
|
{}
|
2012-06-12 02:22:26 +04:00
|
|
|
|
2014-10-02 22:45:44 +04:00
|
|
|
RemoveFromBindingManagerRunnable::~RemoveFromBindingManagerRunnable() {}
|
2014-03-08 03:48:20 +04:00
|
|
|
|
2014-10-02 22:45:44 +04:00
|
|
|
NS_IMETHODIMP
|
|
|
|
RemoveFromBindingManagerRunnable::Run()
|
|
|
|
{
|
|
|
|
// It may be the case that the element was removed from the
|
|
|
|
// DOM, causing this runnable to be created, then inserted back
|
|
|
|
// into the document before the this runnable had a chance to
|
|
|
|
// tear down the binding. Only tear down the binding if the element
|
|
|
|
// is still no longer in the DOM. nsXBLService::LoadBinding tears
|
|
|
|
// down the old binding if the element is inserted back into the
|
|
|
|
// DOM and loads a different binding.
|
|
|
|
if (!mContent->IsInComposedDoc()) {
|
2016-02-19 22:13:42 +03:00
|
|
|
mManager->RemovedFromDocumentInternal(mContent, mDoc,
|
|
|
|
nsBindingManager::eRunDtor);
|
2012-06-12 02:22:26 +04:00
|
|
|
}
|
|
|
|
|
2014-10-02 22:45:44 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2012-06-12 02:22:26 +04:00
|
|
|
|
2004-01-10 02:54:21 +03:00
|
|
|
void
|
2012-11-15 02:10:08 +04:00
|
|
|
Element::UnbindFromTree(bool aDeep, bool aNullParent)
|
1998-11-12 01:06:16 +03:00
|
|
|
{
|
2014-10-02 22:45:44 +04:00
|
|
|
NS_PRECONDITION(aDeep || (!GetUncomposedDoc() && !GetBindingParent()),
|
2005-04-06 03:54:35 +04:00
|
|
|
"Shallow unbind won't clear document and binding parent on "
|
|
|
|
"kids!");
|
2012-03-22 08:10:51 +04:00
|
|
|
|
|
|
|
RemoveFromIdTable();
|
|
|
|
|
2005-04-06 03:54:35 +04:00
|
|
|
// Make sure to unbind this node before doing the kids
|
2014-10-02 22:45:44 +04:00
|
|
|
nsIDocument* document =
|
2015-02-09 21:01:23 +03:00
|
|
|
HasFlag(NODE_FORCE_XBL_BINDINGS) ? OwnerDoc() : GetComposedDoc();
|
2009-02-05 12:42:55 +03:00
|
|
|
|
2015-10-20 02:02:03 +03:00
|
|
|
if (HasPointerLock()) {
|
|
|
|
nsIDocument::UnlockPointer();
|
|
|
|
}
|
2016-06-30 02:24:41 +03:00
|
|
|
if (mState.HasState(NS_EVENT_STATE_FULL_SCREEN)) {
|
|
|
|
// The element being removed is an ancestor of the full-screen element,
|
|
|
|
// exit full-screen state.
|
|
|
|
nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
|
|
|
|
NS_LITERAL_CSTRING("DOM"), OwnerDoc(),
|
|
|
|
nsContentUtils::eDOM_PROPERTIES,
|
|
|
|
"RemovedFullscreenElement");
|
|
|
|
// Fully exit full-screen.
|
|
|
|
nsIDocument::ExitFullscreenInDocTree(OwnerDoc());
|
|
|
|
}
|
2011-04-08 06:29:49 +04:00
|
|
|
if (aNullParent) {
|
2015-08-14 20:52:38 +03:00
|
|
|
if (GetParent() && GetParent()->IsInUncomposedDoc()) {
|
|
|
|
// Update the editable descendant count in the ancestors before we
|
|
|
|
// lose the reference to the parent.
|
|
|
|
int32_t editableDescendantChange = -1 * EditableInclusiveDescendantCount(this);
|
|
|
|
if (editableDescendantChange != 0) {
|
|
|
|
nsIContent* parent = GetParent();
|
|
|
|
while (parent) {
|
|
|
|
parent->ChangeEditableDescendantCount(editableDescendantChange);
|
|
|
|
parent = parent->GetParent();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-24 18:23:32 +03:00
|
|
|
if (this->IsRootOfNativeAnonymousSubtree()) {
|
|
|
|
nsNodeUtils::NativeAnonymousChildListChange(this, true);
|
|
|
|
}
|
|
|
|
|
2011-07-26 15:11:14 +04:00
|
|
|
if (GetParent()) {
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<nsINode> p;
|
2015-09-18 10:16:00 +03:00
|
|
|
p.swap(mParent);
|
2011-07-26 15:11:14 +04:00
|
|
|
} else {
|
2012-07-30 18:20:58 +04:00
|
|
|
mParent = nullptr;
|
2011-07-26 15:11:14 +04:00
|
|
|
}
|
2011-04-08 06:29:49 +04:00
|
|
|
SetParentIsContent(false);
|
|
|
|
}
|
2015-11-16 20:44:55 +03:00
|
|
|
|
|
|
|
// Ensure that CSS transitions don't continue on an element at a
|
|
|
|
// different place in the tree (even if reinserted before next
|
|
|
|
// animation refresh).
|
|
|
|
// We need to delete the properties while we're still in document
|
|
|
|
// (if we were in document).
|
|
|
|
// FIXME (Bug 522599): Need a test for this.
|
2016-01-19 02:04:25 +03:00
|
|
|
if (MayHaveAnimations()) {
|
2015-11-16 20:44:55 +03:00
|
|
|
DeleteProperty(nsGkAtoms::transitionsOfBeforeProperty);
|
|
|
|
DeleteProperty(nsGkAtoms::transitionsOfAfterProperty);
|
|
|
|
DeleteProperty(nsGkAtoms::transitionsProperty);
|
|
|
|
DeleteProperty(nsGkAtoms::animationsOfBeforeProperty);
|
|
|
|
DeleteProperty(nsGkAtoms::animationsOfAfterProperty);
|
|
|
|
DeleteProperty(nsGkAtoms::animationsProperty);
|
|
|
|
}
|
|
|
|
|
2011-04-08 06:29:49 +04:00
|
|
|
ClearInDocument();
|
2009-02-05 12:42:55 +03:00
|
|
|
|
2016-07-21 22:51:10 +03:00
|
|
|
#ifdef MOZ_STYLO
|
|
|
|
// Drop any servo node data, since it will generally need to be recomputed on
|
|
|
|
// re-insertion anyway.
|
|
|
|
ServoData().reset();
|
|
|
|
#endif
|
|
|
|
|
2015-08-14 20:52:38 +03:00
|
|
|
// Editable descendant count only counts descendants that
|
|
|
|
// are in the uncomposed document.
|
|
|
|
ResetEditableDescendantCount();
|
|
|
|
|
2014-09-27 02:07:40 +04:00
|
|
|
if (aNullParent || !mParent->IsInShadowTree()) {
|
|
|
|
UnsetFlags(NODE_IS_IN_SHADOW_TREE);
|
|
|
|
|
|
|
|
// Begin keeping track of our subtree root.
|
|
|
|
SetSubtreeRootPointer(aNullParent ? this : mParent->SubtreeRoot());
|
|
|
|
}
|
2012-03-15 00:14:02 +04:00
|
|
|
|
2005-04-06 03:54:35 +04:00
|
|
|
if (document) {
|
|
|
|
// Notify XBL- & nsIAnonymousContentCreator-generated
|
|
|
|
// anonymous content that the document is changing.
|
2014-10-04 05:32:05 +04:00
|
|
|
// Unlike XBL, bindings for web components shadow DOM
|
|
|
|
// do not get uninstalled.
|
|
|
|
if (HasFlag(NODE_MAY_BE_IN_BINDING_MNGR) && !GetShadowRoot()) {
|
2012-06-12 02:22:26 +04:00
|
|
|
nsContentUtils::AddScriptRunner(
|
|
|
|
new RemoveFromBindingManagerRunnable(document->BindingManager(), this,
|
2013-05-02 02:50:08 +04:00
|
|
|
document));
|
2012-06-12 02:22:26 +04:00
|
|
|
}
|
2004-08-10 14:22:36 +04:00
|
|
|
|
2008-02-19 01:52:19 +03:00
|
|
|
document->ClearBoxObjectFor(this);
|
2014-02-24 01:01:26 +04:00
|
|
|
|
2014-12-23 09:35:32 +03:00
|
|
|
// Detached must be enqueued whenever custom element is removed from
|
|
|
|
// the document and this document has a browsing context.
|
|
|
|
if (GetCustomElementData() && document->GetDocShell()) {
|
2014-03-01 05:45:31 +04:00
|
|
|
// Enqueue a detached callback for the custom element.
|
|
|
|
document->EnqueueLifecycleCallback(nsIDocument::eDetached, this);
|
2014-02-24 01:01:26 +04:00
|
|
|
}
|
2005-04-06 03:54:35 +04:00
|
|
|
}
|
|
|
|
|
2007-05-16 05:13:47 +04:00
|
|
|
// Unset this since that's what the old code effectively did.
|
2014-06-07 12:42:53 +04:00
|
|
|
UnsetFlags(NODE_FORCE_XBL_BINDINGS);
|
2014-08-28 15:53:21 +04:00
|
|
|
bool clearBindingParent = true;
|
|
|
|
|
2007-07-09 04:58:15 +04:00
|
|
|
#ifdef MOZ_XUL
|
2007-05-16 05:13:47 +04:00
|
|
|
nsXULElement* xulElem = nsXULElement::FromContent(this);
|
|
|
|
if (xulElem) {
|
2012-07-30 18:20:58 +04:00
|
|
|
xulElem->SetXULBindingParent(nullptr);
|
2014-08-28 15:53:21 +04:00
|
|
|
clearBindingParent = false;
|
2007-05-16 05:13:47 +04:00
|
|
|
}
|
2007-07-09 04:58:15 +04:00
|
|
|
#endif
|
2014-08-28 15:53:21 +04:00
|
|
|
|
|
|
|
nsDOMSlots* slots = GetExistingDOMSlots();
|
|
|
|
if (slots) {
|
|
|
|
if (clearBindingParent) {
|
2012-07-30 18:20:58 +04:00
|
|
|
slots->mBindingParent = nullptr;
|
2007-05-16 05:13:47 +04:00
|
|
|
}
|
2014-09-27 02:07:40 +04:00
|
|
|
if (aNullParent || !mParent->IsInShadowTree()) {
|
|
|
|
slots->mContainingShadow = nullptr;
|
|
|
|
}
|
2005-04-06 03:54:35 +04:00
|
|
|
}
|
|
|
|
|
2016-02-15 03:34:47 +03:00
|
|
|
// This has to be here, rather than in nsGenericHTMLElement::UnbindFromTree,
|
2012-04-17 08:03:10 +04:00
|
|
|
// because it has to happen after unsetting the parent pointer, but before
|
|
|
|
// recursively unbinding the kids.
|
2015-03-03 14:08:59 +03:00
|
|
|
if (IsHTMLElement()) {
|
2013-01-06 13:45:28 +04:00
|
|
|
ResetDir(this);
|
2012-04-17 08:03:10 +04:00
|
|
|
}
|
|
|
|
|
2005-04-06 03:54:35 +04:00
|
|
|
if (aDeep) {
|
2007-05-16 05:13:47 +04:00
|
|
|
// Do the kids. Don't call GetChildCount() here since that'll force
|
|
|
|
// XUL to generate template children, which there is no need for since
|
|
|
|
// all we're going to do is unbind them anyway.
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t i, n = mAttrsAndChildren.ChildCount();
|
2004-08-10 14:22:36 +04:00
|
|
|
|
2005-04-06 03:54:35 +04:00
|
|
|
for (i = 0; i < n; ++i) {
|
2011-10-17 18:59:28 +04:00
|
|
|
// Note that we pass false for aNullParent here, since we don't want
|
2005-04-06 03:54:35 +04:00
|
|
|
// the kids to forget us. We _do_ want them to forget their binding
|
|
|
|
// parent, though, since this only walks non-anonymous kids.
|
2011-10-17 18:59:28 +04:00
|
|
|
mAttrsAndChildren.ChildAt(i)->UnbindFromTree(true, false);
|
2005-04-06 03:54:35 +04:00
|
|
|
}
|
2001-09-23 09:53:32 +04:00
|
|
|
}
|
2007-03-10 16:49:43 +03:00
|
|
|
|
|
|
|
nsNodeUtils::ParentChainChanged(this);
|
2014-09-27 02:07:40 +04:00
|
|
|
|
|
|
|
// Unbind children of shadow root.
|
|
|
|
ShadowRoot* shadowRoot = GetShadowRoot();
|
|
|
|
if (shadowRoot) {
|
|
|
|
for (nsIContent* child = shadowRoot->GetFirstChild(); child;
|
|
|
|
child = child->GetNextSibling()) {
|
|
|
|
child->UnbindFromTree(true, false);
|
|
|
|
}
|
2015-02-09 21:01:23 +03:00
|
|
|
|
|
|
|
shadowRoot->SetIsComposedDocParticipant(false);
|
2014-09-27 02:07:40 +04:00
|
|
|
}
|
1998-11-12 01:06:16 +03:00
|
|
|
}
|
|
|
|
|
2012-07-31 19:36:21 +04:00
|
|
|
nsICSSDeclaration*
|
2012-11-15 02:10:08 +04:00
|
|
|
Element::GetSMILOverrideStyle()
|
2010-02-11 20:34:01 +03:00
|
|
|
{
|
2012-11-15 02:10:08 +04:00
|
|
|
Element::nsDOMSlots *slots = DOMSlots();
|
2010-02-11 20:34:01 +03:00
|
|
|
|
2012-07-31 19:36:21 +04:00
|
|
|
if (!slots->mSMILOverrideStyle) {
|
|
|
|
slots->mSMILOverrideStyle = new nsDOMCSSAttributeDeclaration(this, true);
|
2010-02-11 20:34:01 +03:00
|
|
|
}
|
|
|
|
|
2012-07-31 19:36:21 +04:00
|
|
|
return slots->mSMILOverrideStyle;
|
2010-02-11 20:34:01 +03:00
|
|
|
}
|
|
|
|
|
2015-11-09 10:57:16 +03:00
|
|
|
css::Declaration*
|
|
|
|
Element::GetSMILOverrideStyleDeclaration()
|
2008-03-12 13:26:12 +03:00
|
|
|
{
|
2012-11-15 02:10:08 +04:00
|
|
|
Element::nsDOMSlots *slots = GetExistingDOMSlots();
|
2015-11-09 10:57:16 +03:00
|
|
|
return slots ? slots->mSMILOverrideStyleDeclaration.get() : nullptr;
|
2008-03-12 13:26:12 +03:00
|
|
|
}
|
|
|
|
|
2006-05-17 20:14:33 +04:00
|
|
|
nsresult
|
2015-11-09 10:57:16 +03:00
|
|
|
Element::SetSMILOverrideStyleDeclaration(css::Declaration* aDeclaration,
|
|
|
|
bool aNotify)
|
2009-09-03 04:28:37 +04:00
|
|
|
{
|
2012-11-15 02:10:08 +04:00
|
|
|
Element::nsDOMSlots *slots = DOMSlots();
|
2009-09-03 04:28:37 +04:00
|
|
|
|
2015-11-09 10:57:16 +03:00
|
|
|
slots->mSMILOverrideStyleDeclaration = aDeclaration;
|
2009-09-03 04:28:37 +04:00
|
|
|
|
|
|
|
if (aNotify) {
|
2014-10-02 22:45:44 +04:00
|
|
|
nsIDocument* doc = GetComposedDoc();
|
2010-03-12 09:03:49 +03:00
|
|
|
// Only need to request a restyle if we're in a document. (We might not
|
2009-10-20 20:54:47 +04:00
|
|
|
// be in a document, if we're clearing animation effects on a target node
|
|
|
|
// that's been detached since the previous animation sample.)
|
|
|
|
if (doc) {
|
2010-06-25 17:59:57 +04:00
|
|
|
nsCOMPtr<nsIPresShell> shell = doc->GetShell();
|
2010-01-07 13:36:11 +03:00
|
|
|
if (shell) {
|
2015-02-19 11:22:05 +03:00
|
|
|
// Pass both eRestyle_StyleAttribute and
|
|
|
|
// eRestyle_StyleAttribute_Animations since we don't know if
|
|
|
|
// this style represents only the ticking of an existing
|
|
|
|
// animation or whether it's a new or changed animation.
|
|
|
|
shell->RestyleForAnimation(this, eRestyle_StyleAttribute |
|
|
|
|
eRestyle_StyleAttribute_Animations);
|
2009-10-20 20:54:47 +04:00
|
|
|
}
|
2009-09-03 04:28:37 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2012-06-07 22:41:23 +04:00
|
|
|
bool
|
2012-11-15 02:10:08 +04:00
|
|
|
Element::IsLabelable() const
|
2012-06-07 22:41:23 +04:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2015-01-20 23:39:28 +03:00
|
|
|
bool
|
2015-03-17 23:42:14 +03:00
|
|
|
Element::IsInteractiveHTMLContent(bool aIgnoreTabindex) const
|
2015-01-20 23:39:28 +03:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2015-11-09 10:57:16 +03:00
|
|
|
css::Declaration*
|
|
|
|
Element::GetInlineStyleDeclaration()
|
2000-12-23 13:56:31 +03:00
|
|
|
{
|
2012-07-30 18:20:58 +04:00
|
|
|
return nullptr;
|
2000-12-23 13:56:31 +03:00
|
|
|
}
|
|
|
|
|
2012-04-14 17:09:19 +04:00
|
|
|
nsresult
|
2015-11-09 10:57:16 +03:00
|
|
|
Element::SetInlineStyleDeclaration(css::Declaration* aDeclaration,
|
|
|
|
const nsAString* aSerialized,
|
|
|
|
bool aNotify)
|
2003-10-30 04:40:33 +03:00
|
|
|
{
|
2015-11-09 10:57:16 +03:00
|
|
|
NS_NOTYETIMPLEMENTED("Element::SetInlineStyleDeclaration");
|
2003-10-30 04:40:33 +03:00
|
|
|
return NS_ERROR_NOT_IMPLEMENTED;
|
|
|
|
}
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
NS_IMETHODIMP_(bool)
|
2012-11-15 02:10:08 +04:00
|
|
|
Element::IsAttributeMapped(const nsIAtom* aAttribute) const
|
2003-07-12 01:16:12 +04:00
|
|
|
{
|
2011-10-17 18:59:28 +04:00
|
|
|
return false;
|
2003-07-12 01:16:12 +04:00
|
|
|
}
|
|
|
|
|
2004-10-24 21:10:32 +04:00
|
|
|
nsChangeHint
|
2012-11-15 02:10:08 +04:00
|
|
|
Element::GetAttributeChangeHint(const nsIAtom* aAttribute,
|
|
|
|
int32_t aModType) const
|
2000-12-23 13:56:31 +03:00
|
|
|
{
|
2004-10-24 21:10:32 +04:00
|
|
|
return nsChangeHint(0);
|
2000-12-23 13:56:31 +03:00
|
|
|
}
|
|
|
|
|
2012-07-31 19:36:21 +04:00
|
|
|
bool
|
2012-11-15 02:10:08 +04:00
|
|
|
Element::FindAttributeDependence(const nsIAtom* aAttribute,
|
|
|
|
const MappedAttributeEntry* const aMaps[],
|
|
|
|
uint32_t aMapCount)
|
2012-07-31 19:36:21 +04:00
|
|
|
{
|
2012-08-22 19:56:38 +04:00
|
|
|
for (uint32_t mapindex = 0; mapindex < aMapCount; ++mapindex) {
|
2012-07-31 19:36:21 +04:00
|
|
|
for (const MappedAttributeEntry* map = aMaps[mapindex];
|
|
|
|
map->attribute; ++map) {
|
|
|
|
if (aAttribute == *map->attribute) {
|
|
|
|
return true;
|
2012-06-28 02:09:15 +04:00
|
|
|
}
|
|
|
|
}
|
2012-02-11 05:21:26 +04:00
|
|
|
}
|
|
|
|
|
2012-07-31 19:36:21 +04:00
|
|
|
return false;
|
|
|
|
}
|
2012-01-31 00:08:13 +04:00
|
|
|
|
2014-06-20 06:01:40 +04:00
|
|
|
already_AddRefed<mozilla::dom::NodeInfo>
|
2012-11-15 02:10:08 +04:00
|
|
|
Element::GetExistingAttrNameFromQName(const nsAString& aStr) const
|
2012-07-31 19:36:21 +04:00
|
|
|
{
|
2016-05-31 18:56:20 +03:00
|
|
|
const nsAttrName* name = InternalGetAttrNameFromQName(aStr);
|
2012-07-31 19:36:21 +04:00
|
|
|
if (!name) {
|
|
|
|
return nullptr;
|
2012-01-31 00:08:13 +04:00
|
|
|
}
|
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<mozilla::dom::NodeInfo> nodeInfo;
|
2012-07-31 19:36:21 +04:00
|
|
|
if (name->IsAtom()) {
|
|
|
|
nodeInfo = mNodeInfo->NodeInfoManager()->
|
|
|
|
GetNodeInfo(name->Atom(), nullptr, kNameSpaceID_None,
|
2013-04-22 15:15:59 +04:00
|
|
|
nsIDOMNode::ATTRIBUTE_NODE);
|
2012-01-31 00:08:13 +04:00
|
|
|
}
|
2012-07-31 19:36:21 +04:00
|
|
|
else {
|
2013-04-22 15:15:59 +04:00
|
|
|
nodeInfo = name->NodeInfo();
|
2012-07-31 19:36:21 +04:00
|
|
|
}
|
|
|
|
|
2013-04-22 15:15:59 +04:00
|
|
|
return nodeInfo.forget();
|
2012-01-31 00:08:13 +04:00
|
|
|
}
|
|
|
|
|
2012-07-31 19:36:21 +04:00
|
|
|
// static
|
2012-01-31 00:08:13 +04:00
|
|
|
bool
|
2012-11-15 02:10:08 +04:00
|
|
|
Element::ShouldBlur(nsIContent *aContent)
|
2012-01-31 00:08:13 +04:00
|
|
|
{
|
2012-07-31 19:36:21 +04:00
|
|
|
// Determine if the current element is focused, if it is not focused
|
|
|
|
// then we should not try to blur
|
2014-08-23 00:11:27 +04:00
|
|
|
nsIDocument* document = aContent->GetComposedDoc();
|
2012-07-31 19:36:21 +04:00
|
|
|
if (!document)
|
2012-01-31 00:08:13 +04:00
|
|
|
return false;
|
2012-07-31 19:36:21 +04:00
|
|
|
|
2016-01-30 20:05:36 +03:00
|
|
|
nsCOMPtr<nsPIDOMWindowOuter> window = document->GetWindow();
|
2012-07-31 19:36:21 +04:00
|
|
|
if (!window)
|
|
|
|
return false;
|
|
|
|
|
2016-01-30 20:05:36 +03:00
|
|
|
nsCOMPtr<nsPIDOMWindowOuter> focusedFrame;
|
2012-07-31 19:36:21 +04:00
|
|
|
nsIContent* contentToBlur =
|
|
|
|
nsFocusManager::GetFocusedDescendant(window, false, getter_AddRefs(focusedFrame));
|
|
|
|
if (contentToBlur == aContent)
|
2012-01-31 00:08:13 +04:00
|
|
|
return true;
|
2012-07-31 19:36:21 +04:00
|
|
|
|
|
|
|
// if focus on this element would get redirected, then check the redirected
|
|
|
|
// content as well when blurring.
|
|
|
|
return (contentToBlur && nsFocusManager::GetRedirectedFocus(aContent) == contentToBlur);
|
2012-01-31 00:08:13 +04:00
|
|
|
}
|
|
|
|
|
2012-07-31 19:36:21 +04:00
|
|
|
bool
|
2012-11-15 02:10:08 +04:00
|
|
|
Element::IsNodeOfType(uint32_t aFlags) const
|
2012-01-31 00:08:13 +04:00
|
|
|
{
|
2012-07-31 19:36:21 +04:00
|
|
|
return !(aFlags & ~eCONTENT);
|
2012-01-31 00:08:13 +04:00
|
|
|
}
|
|
|
|
|
2012-07-31 19:36:21 +04:00
|
|
|
/* static */
|
|
|
|
nsresult
|
2012-11-15 02:10:08 +04:00
|
|
|
Element::DispatchEvent(nsPresContext* aPresContext,
|
2013-10-02 07:46:04 +04:00
|
|
|
WidgetEvent* aEvent,
|
2012-11-15 02:10:08 +04:00
|
|
|
nsIContent* aTarget,
|
|
|
|
bool aFullDispatch,
|
|
|
|
nsEventStatus* aStatus)
|
2012-07-31 19:36:21 +04:00
|
|
|
{
|
|
|
|
NS_PRECONDITION(aTarget, "Must have target");
|
|
|
|
NS_PRECONDITION(aEvent, "Must have source event");
|
|
|
|
NS_PRECONDITION(aStatus, "Null out param?");
|
2012-02-11 15:03:54 +04:00
|
|
|
|
2012-07-31 19:36:21 +04:00
|
|
|
if (!aPresContext) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2012-02-11 15:03:54 +04:00
|
|
|
|
2012-07-31 19:36:21 +04:00
|
|
|
nsCOMPtr<nsIPresShell> shell = aPresContext->GetPresShell();
|
|
|
|
if (!shell) {
|
|
|
|
return NS_OK;
|
2009-02-27 17:48:26 +03:00
|
|
|
}
|
2012-07-31 19:36:21 +04:00
|
|
|
|
|
|
|
if (aFullDispatch) {
|
|
|
|
return shell->HandleEventWithTarget(aEvent, nullptr, aTarget, aStatus);
|
2009-02-27 17:48:26 +03:00
|
|
|
}
|
|
|
|
|
2012-07-31 19:36:21 +04:00
|
|
|
return shell->HandleDOMEventWithTarget(aTarget, aEvent, aStatus);
|
|
|
|
}
|
2009-05-13 00:20:42 +04:00
|
|
|
|
2012-07-31 19:36:21 +04:00
|
|
|
/* static */
|
|
|
|
nsresult
|
2012-11-15 02:10:08 +04:00
|
|
|
Element::DispatchClickEvent(nsPresContext* aPresContext,
|
2013-10-01 11:23:02 +04:00
|
|
|
WidgetInputEvent* aSourceEvent,
|
2012-11-15 02:10:08 +04:00
|
|
|
nsIContent* aTarget,
|
|
|
|
bool aFullDispatch,
|
2013-09-14 06:39:41 +04:00
|
|
|
const EventFlags* aExtraEventFlags,
|
2012-11-15 02:10:08 +04:00
|
|
|
nsEventStatus* aStatus)
|
2012-07-31 19:36:21 +04:00
|
|
|
{
|
|
|
|
NS_PRECONDITION(aTarget, "Must have target");
|
|
|
|
NS_PRECONDITION(aSourceEvent, "Must have source event");
|
|
|
|
NS_PRECONDITION(aStatus, "Null out param?");
|
2007-05-11 00:21:12 +04:00
|
|
|
|
2016-03-17 10:01:30 +03:00
|
|
|
WidgetMouseEvent event(aSourceEvent->IsTrusted(), eMouseClick,
|
2016-04-14 11:03:14 +03:00
|
|
|
aSourceEvent->mWidget, WidgetMouseEvent::eReal);
|
2016-04-18 17:09:02 +03:00
|
|
|
event.mRefPoint = aSourceEvent->mRefPoint;
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t clickCount = 1;
|
2012-07-31 19:36:21 +04:00
|
|
|
float pressure = 0;
|
2012-08-22 19:56:38 +04:00
|
|
|
uint16_t inputSource = 0;
|
2013-10-22 12:55:20 +04:00
|
|
|
WidgetMouseEvent* sourceMouseEvent = aSourceEvent->AsMouseEvent();
|
|
|
|
if (sourceMouseEvent) {
|
2016-05-10 17:29:14 +03:00
|
|
|
clickCount = sourceMouseEvent->mClickCount;
|
2013-10-22 12:55:20 +04:00
|
|
|
pressure = sourceMouseEvent->pressure;
|
|
|
|
inputSource = sourceMouseEvent->inputSource;
|
2014-08-04 09:28:48 +04:00
|
|
|
} else if (aSourceEvent->mClass == eKeyboardEventClass) {
|
2012-07-31 19:36:21 +04:00
|
|
|
inputSource = nsIDOMMouseEvent::MOZ_SOURCE_KEYBOARD;
|
2007-03-08 14:17:16 +03:00
|
|
|
}
|
2012-07-31 19:36:21 +04:00
|
|
|
event.pressure = pressure;
|
2016-05-10 17:29:14 +03:00
|
|
|
event.mClickCount = clickCount;
|
2012-07-31 19:36:21 +04:00
|
|
|
event.inputSource = inputSource;
|
2016-03-31 11:03:00 +03:00
|
|
|
event.mModifiers = aSourceEvent->mModifiers;
|
2012-12-16 05:26:04 +04:00
|
|
|
if (aExtraEventFlags) {
|
|
|
|
// Be careful not to overwrite existing flags!
|
2012-12-28 18:13:18 +04:00
|
|
|
event.mFlags.Union(*aExtraEventFlags);
|
2012-12-16 05:26:04 +04:00
|
|
|
}
|
2007-03-08 14:17:16 +03:00
|
|
|
|
2012-07-31 19:36:21 +04:00
|
|
|
return DispatchEvent(aPresContext, &event, aTarget, aFullDispatch, aStatus);
|
|
|
|
}
|
2008-03-28 17:09:00 +03:00
|
|
|
|
2012-07-31 19:36:21 +04:00
|
|
|
nsIFrame*
|
2012-11-15 02:10:08 +04:00
|
|
|
Element::GetPrimaryFrame(mozFlushType aType)
|
2012-07-31 19:36:21 +04:00
|
|
|
{
|
2014-07-29 22:42:31 +04:00
|
|
|
nsIDocument* doc = GetComposedDoc();
|
2012-07-31 19:36:21 +04:00
|
|
|
if (!doc) {
|
|
|
|
return nullptr;
|
2007-01-05 01:31:26 +03:00
|
|
|
}
|
|
|
|
|
2012-07-31 19:36:21 +04:00
|
|
|
// Cause a flush, so we get up-to-date frame
|
|
|
|
// information
|
2013-09-30 21:32:02 +04:00
|
|
|
if (aType != Flush_None) {
|
|
|
|
doc->FlushPendingNotifications(aType);
|
|
|
|
}
|
2000-12-23 13:56:31 +03:00
|
|
|
|
2012-07-31 19:36:21 +04:00
|
|
|
return GetPrimaryFrame();
|
2002-01-24 12:17:00 +03:00
|
|
|
}
|
|
|
|
|
1998-11-12 01:06:16 +03:00
|
|
|
//----------------------------------------------------------------------
|
2002-11-20 03:44:26 +03:00
|
|
|
nsresult
|
2012-11-15 02:10:08 +04:00
|
|
|
Element::LeaveLink(nsPresContext* aPresContext)
|
2002-11-20 03:44:26 +03:00
|
|
|
{
|
2004-02-01 13:09:07 +03:00
|
|
|
nsILinkHandler *handler = aPresContext->GetLinkHandler();
|
|
|
|
if (!handler) {
|
|
|
|
return NS_OK;
|
2002-11-20 03:44:26 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
return handler->OnLeaveLink();
|
|
|
|
}
|
1998-11-12 01:06:16 +03:00
|
|
|
|
|
|
|
nsresult
|
2012-11-15 02:10:08 +04:00
|
|
|
Element::SetEventHandler(nsIAtom* aEventName,
|
|
|
|
const nsAString& aValue,
|
|
|
|
bool aDefer)
|
1998-11-12 01:06:16 +03:00
|
|
|
{
|
2011-10-18 14:53:36 +04:00
|
|
|
nsIDocument *ownerDoc = OwnerDoc();
|
2011-10-18 15:19:44 +04:00
|
|
|
if (ownerDoc->IsLoadedAsData()) {
|
2007-07-27 06:49:18 +04:00
|
|
|
// Make this a no-op rather than throwing an error to avoid
|
|
|
|
// the error causing problems setting the attribute.
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2005-10-28 06:59:38 +04:00
|
|
|
NS_PRECONDITION(aEventName, "Must have event name!");
|
2011-09-29 10:19:26 +04:00
|
|
|
bool defer = true;
|
2014-03-17 10:56:53 +04:00
|
|
|
EventListenerManager* manager =
|
|
|
|
GetEventListenerManagerForAttr(aEventName, &defer);
|
2009-09-16 13:09:12 +04:00
|
|
|
if (!manager) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2000-12-23 13:56:31 +03:00
|
|
|
|
2009-06-23 15:23:52 +04:00
|
|
|
defer = defer && aDefer; // only defer if everyone agrees...
|
2012-08-30 20:25:10 +04:00
|
|
|
manager->SetEventHandler(aEventName, aValue,
|
2013-11-26 20:44:37 +04:00
|
|
|
defer, !nsContentUtils::IsChromeDoc(ownerDoc),
|
|
|
|
this);
|
2011-06-24 06:18:02 +04:00
|
|
|
return NS_OK;
|
1998-11-12 01:06:16 +03:00
|
|
|
}
|
|
|
|
|
1999-01-12 19:37:24 +03:00
|
|
|
|
1998-11-12 01:06:16 +03:00
|
|
|
//----------------------------------------------------------------------
|
|
|
|
|
2004-01-15 20:07:27 +03:00
|
|
|
const nsAttrName*
|
2016-05-31 18:56:20 +03:00
|
|
|
Element::InternalGetAttrNameFromQName(const nsAString& aStr,
|
|
|
|
nsAutoString* aNameToUse) const
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(!aNameToUse || aNameToUse->IsEmpty());
|
|
|
|
const nsAttrName* val = nullptr;
|
|
|
|
if (IsHTMLElement() && IsInHTMLDocument()) {
|
|
|
|
nsAutoString lower;
|
|
|
|
nsAutoString& outStr = aNameToUse ? *aNameToUse : lower;
|
|
|
|
nsContentUtils::ASCIIToLower(aStr, outStr);
|
|
|
|
val = mAttrsAndChildren.GetExistingAttrNameFromQName(outStr);
|
|
|
|
if (val) {
|
|
|
|
outStr.Truncate();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
val = mAttrsAndChildren.GetExistingAttrNameFromQName(aStr);
|
|
|
|
if (!val && aNameToUse) {
|
|
|
|
*aNameToUse = aStr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return val;
|
2000-08-31 04:36:31 +04:00
|
|
|
}
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool
|
2012-11-15 02:10:08 +04:00
|
|
|
Element::MaybeCheckSameAttrVal(int32_t aNamespaceID,
|
|
|
|
nsIAtom* aName,
|
|
|
|
nsIAtom* aPrefix,
|
|
|
|
const nsAttrValueOrString& aValue,
|
|
|
|
bool aNotify,
|
|
|
|
nsAttrValue& aOldValue,
|
|
|
|
uint8_t* aModType,
|
|
|
|
bool* aHasListeners)
|
2000-06-23 04:21:32 +04:00
|
|
|
{
|
2011-09-29 10:19:26 +04:00
|
|
|
bool modification = false;
|
2011-02-01 22:41:50 +03:00
|
|
|
*aHasListeners = aNotify &&
|
2006-04-24 23:52:21 +04:00
|
|
|
nsContentUtils::HasMutationListeners(this,
|
2007-07-05 00:39:10 +04:00
|
|
|
NS_EVENT_BITS_MUTATION_ATTRMODIFIED,
|
|
|
|
this);
|
2011-02-01 22:41:50 +03:00
|
|
|
|
2005-10-28 06:59:38 +04:00
|
|
|
// If we have no listeners and aNotify is false, we are almost certainly
|
|
|
|
// coming from the content sink and will almost certainly have no previous
|
|
|
|
// value. Even if we do, setting the value is cheap when we have no
|
|
|
|
// listeners and don't plan to notify. The check for aNotify here is an
|
2011-02-01 22:41:50 +03:00
|
|
|
// optimization, the check for *aHasListeners is a correctness issue.
|
|
|
|
if (*aHasListeners || aNotify) {
|
2016-07-23 00:11:41 +03:00
|
|
|
BorrowedAttrInfo info(GetAttrInfo(aNamespaceID, aName));
|
2005-10-28 06:59:38 +04:00
|
|
|
if (info.mValue) {
|
|
|
|
// Check whether the old value is the same as the new one. Note that we
|
2014-02-24 01:01:26 +04:00
|
|
|
// only need to actually _get_ the old value if we have listeners or
|
|
|
|
// if the element is a custom element (because it may have an
|
|
|
|
// attribute changed callback).
|
|
|
|
if (*aHasListeners || GetCustomElementData()) {
|
2012-02-14 06:00:56 +04:00
|
|
|
// Need to store the old value.
|
|
|
|
//
|
|
|
|
// If the current attribute value contains a pointer to some other data
|
|
|
|
// structure that gets updated in the process of setting the attribute
|
|
|
|
// we'll no longer have the old value of the attribute. Therefore, we
|
|
|
|
// should serialize the attribute value now to keep a snapshot.
|
|
|
|
//
|
|
|
|
// We have to serialize the value anyway in order to create the
|
|
|
|
// mutation event so there's no cost in doing it now.
|
|
|
|
aOldValue.SetToSerialized(*info.mValue);
|
2005-10-28 06:59:38 +04:00
|
|
|
}
|
2012-02-14 06:00:56 +04:00
|
|
|
bool valueMatches = aValue.EqualsAsStrings(*info.mValue);
|
2005-10-28 06:59:38 +04:00
|
|
|
if (valueMatches && aPrefix == info.mName->GetPrefix()) {
|
2012-08-15 14:06:01 +04:00
|
|
|
return true;
|
2005-10-28 06:59:38 +04:00
|
|
|
}
|
2011-10-17 18:59:28 +04:00
|
|
|
modification = true;
|
1998-11-12 01:06:16 +03:00
|
|
|
}
|
|
|
|
}
|
2011-02-01 22:41:50 +03:00
|
|
|
*aModType = modification ?
|
2012-08-22 19:56:38 +04:00
|
|
|
static_cast<uint8_t>(nsIDOMMutationEvent::MODIFICATION) :
|
|
|
|
static_cast<uint8_t>(nsIDOMMutationEvent::ADDITION);
|
2011-10-17 18:59:28 +04:00
|
|
|
return false;
|
2011-02-01 22:41:50 +03:00
|
|
|
}
|
|
|
|
|
2013-02-01 03:11:49 +04:00
|
|
|
bool
|
|
|
|
Element::OnlyNotifySameValueSet(int32_t aNamespaceID, nsIAtom* aName,
|
|
|
|
nsIAtom* aPrefix,
|
|
|
|
const nsAttrValueOrString& aValue,
|
|
|
|
bool aNotify, nsAttrValue& aOldValue,
|
|
|
|
uint8_t* aModType, bool* aHasListeners)
|
|
|
|
{
|
|
|
|
if (!MaybeCheckSameAttrVal(aNamespaceID, aName, aPrefix, aValue, aNotify,
|
|
|
|
aOldValue, aModType, aHasListeners)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsAutoScriptBlocker scriptBlocker;
|
|
|
|
nsNodeUtils::AttributeSetToCurrentValue(this, aNamespaceID, aName);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2011-02-01 22:41:50 +03:00
|
|
|
nsresult
|
2012-11-15 02:10:08 +04:00
|
|
|
Element::SetAttr(int32_t aNamespaceID, nsIAtom* aName,
|
|
|
|
nsIAtom* aPrefix, const nsAString& aValue,
|
|
|
|
bool aNotify)
|
2011-02-01 22:41:50 +03:00
|
|
|
{
|
|
|
|
// Keep this in sync with SetParsedAttr below
|
|
|
|
|
|
|
|
NS_ENSURE_ARG_POINTER(aName);
|
|
|
|
NS_ASSERTION(aNamespaceID != kNameSpaceID_Unknown,
|
|
|
|
"Don't call SetAttr with unknown namespace");
|
2000-12-23 13:56:31 +03:00
|
|
|
|
2011-02-01 22:41:50 +03:00
|
|
|
if (!mAttrsAndChildren.CanFitMoreAttrs()) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
uint8_t modType;
|
2011-09-29 10:19:26 +04:00
|
|
|
bool hasListeners;
|
2012-02-14 06:00:56 +04:00
|
|
|
nsAttrValueOrString value(aValue);
|
|
|
|
nsAttrValue oldValue;
|
2011-02-01 22:41:50 +03:00
|
|
|
|
2012-08-15 14:06:01 +04:00
|
|
|
if (OnlyNotifySameValueSet(aNamespaceID, aName, aPrefix, value, aNotify,
|
|
|
|
oldValue, &modType, &hasListeners)) {
|
2011-02-01 22:41:50 +03:00
|
|
|
return NS_OK;
|
|
|
|
}
|
2010-02-24 07:37:47 +03:00
|
|
|
|
2012-02-14 06:00:56 +04:00
|
|
|
nsresult rv = BeforeSetAttr(aNamespaceID, aName, &value, aNotify);
|
2005-10-28 06:59:38 +04:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2015-07-22 06:53:35 +03:00
|
|
|
nsAttrValue* preparsedAttrValue = value.GetStoredAttrValue();
|
2011-02-01 22:41:50 +03:00
|
|
|
|
2010-02-24 07:37:47 +03:00
|
|
|
if (aNotify) {
|
2015-07-22 06:53:35 +03:00
|
|
|
nsNodeUtils::AttributeWillChange(this, aNamespaceID, aName, modType,
|
|
|
|
preparsedAttrValue);
|
2010-02-24 07:37:47 +03:00
|
|
|
}
|
|
|
|
|
2011-03-02 08:33:56 +03:00
|
|
|
// Hold a script blocker while calling ParseAttribute since that can call
|
|
|
|
// out to id-observers
|
2011-05-25 21:58:23 +04:00
|
|
|
nsAutoScriptBlocker scriptBlocker;
|
2011-03-02 08:33:56 +03:00
|
|
|
|
2005-10-28 06:59:38 +04:00
|
|
|
nsAttrValue attrValue;
|
2015-08-01 08:14:06 +03:00
|
|
|
if (preparsedAttrValue) {
|
|
|
|
attrValue.SwapValueWith(*preparsedAttrValue);
|
|
|
|
}
|
|
|
|
// Even the value was pre-parsed in BeforeSetAttr, we still need to call
|
|
|
|
// ParseAttribute because it can have side effects.
|
2005-11-29 19:37:15 +03:00
|
|
|
if (!ParseAttribute(aNamespaceID, aName, aValue, attrValue)) {
|
2005-10-28 06:59:38 +04:00
|
|
|
attrValue.SetTo(aValue);
|
|
|
|
}
|
|
|
|
|
2011-03-02 17:36:19 +03:00
|
|
|
return SetAttrAndNotify(aNamespaceID, aName, aPrefix, oldValue,
|
|
|
|
attrValue, modType, hasListeners, aNotify,
|
2012-02-14 06:00:56 +04:00
|
|
|
kCallAfterSetAttr);
|
2005-10-28 06:59:38 +04:00
|
|
|
}
|
2011-02-01 22:41:50 +03:00
|
|
|
|
|
|
|
nsresult
|
2012-11-15 02:10:08 +04:00
|
|
|
Element::SetParsedAttr(int32_t aNamespaceID, nsIAtom* aName,
|
|
|
|
nsIAtom* aPrefix, nsAttrValue& aParsedValue,
|
|
|
|
bool aNotify)
|
2011-02-01 22:41:50 +03:00
|
|
|
{
|
|
|
|
// Keep this in sync with SetAttr above
|
|
|
|
|
|
|
|
NS_ENSURE_ARG_POINTER(aName);
|
|
|
|
NS_ASSERTION(aNamespaceID != kNameSpaceID_Unknown,
|
|
|
|
"Don't call SetAttr with unknown namespace");
|
|
|
|
|
|
|
|
if (!mAttrsAndChildren.CanFitMoreAttrs()) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
uint8_t modType;
|
2011-09-29 10:19:26 +04:00
|
|
|
bool hasListeners;
|
2012-02-14 06:00:56 +04:00
|
|
|
nsAttrValueOrString value(aParsedValue);
|
|
|
|
nsAttrValue oldValue;
|
2011-02-01 22:41:50 +03:00
|
|
|
|
2012-08-15 14:06:01 +04:00
|
|
|
if (OnlyNotifySameValueSet(aNamespaceID, aName, aPrefix, value, aNotify,
|
|
|
|
oldValue, &modType, &hasListeners)) {
|
2011-02-01 22:41:50 +03:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2012-02-14 06:00:56 +04:00
|
|
|
nsresult rv = BeforeSetAttr(aNamespaceID, aName, &value, aNotify);
|
2011-02-01 22:41:50 +03:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
if (aNotify) {
|
2015-07-22 06:53:35 +03:00
|
|
|
nsNodeUtils::AttributeWillChange(this, aNamespaceID, aName, modType,
|
|
|
|
&aParsedValue);
|
2011-02-01 22:41:50 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
return SetAttrAndNotify(aNamespaceID, aName, aPrefix, oldValue,
|
|
|
|
aParsedValue, modType, hasListeners, aNotify,
|
2012-02-14 06:00:56 +04:00
|
|
|
kCallAfterSetAttr);
|
2011-02-01 22:41:50 +03:00
|
|
|
}
|
|
|
|
|
2005-10-28 06:59:38 +04:00
|
|
|
nsresult
|
2012-11-15 02:10:08 +04:00
|
|
|
Element::SetAttrAndNotify(int32_t aNamespaceID,
|
|
|
|
nsIAtom* aName,
|
|
|
|
nsIAtom* aPrefix,
|
|
|
|
const nsAttrValue& aOldValue,
|
|
|
|
nsAttrValue& aParsedValue,
|
|
|
|
uint8_t aModType,
|
|
|
|
bool aFireMutation,
|
|
|
|
bool aNotify,
|
|
|
|
bool aCallAfterSetAttr)
|
2005-10-28 06:59:38 +04:00
|
|
|
{
|
|
|
|
nsresult rv;
|
|
|
|
|
2014-10-02 22:45:44 +04:00
|
|
|
nsIDocument* document = GetComposedDoc();
|
2005-10-28 06:59:38 +04:00
|
|
|
mozAutoDocUpdate updateBatch(document, UPDATE_CONTENT_MODEL, aNotify);
|
2007-07-13 00:05:45 +04:00
|
|
|
|
2010-09-02 02:48:24 +04:00
|
|
|
nsMutationGuard::DidMutate();
|
|
|
|
|
2012-02-14 06:00:56 +04:00
|
|
|
// Copy aParsedValue for later use since it will be lost when we call
|
2015-07-22 05:09:41 +03:00
|
|
|
// SetAndSwapMappedAttr below
|
2015-07-25 08:57:13 +03:00
|
|
|
nsAttrValue valueForAfterSetAttr;
|
2012-02-14 06:00:56 +04:00
|
|
|
if (aCallAfterSetAttr) {
|
2015-07-25 08:57:13 +03:00
|
|
|
valueForAfterSetAttr.SetTo(aParsedValue);
|
2012-02-14 06:00:56 +04:00
|
|
|
}
|
|
|
|
|
2012-11-21 14:13:57 +04:00
|
|
|
bool hadValidDir = false;
|
2013-03-08 00:53:08 +04:00
|
|
|
bool hadDirAuto = false;
|
2012-11-21 14:13:57 +04:00
|
|
|
|
2004-01-15 20:07:27 +03:00
|
|
|
if (aNamespaceID == kNameSpaceID_None) {
|
2012-11-21 14:13:57 +04:00
|
|
|
if (aName == nsGkAtoms::dir) {
|
2015-03-03 14:08:59 +03:00
|
|
|
hadValidDir = HasValidDir() || IsHTMLElement(nsGkAtoms::bdi);
|
2013-03-08 00:53:08 +04:00
|
|
|
hadDirAuto = HasDirAuto(); // already takes bdi into account
|
2012-11-21 14:13:57 +04:00
|
|
|
}
|
|
|
|
|
2005-10-28 06:59:38 +04:00
|
|
|
// XXXbz Perhaps we should push up the attribute mapping function
|
2012-11-15 02:10:08 +04:00
|
|
|
// stuff to Element?
|
2005-10-28 06:59:38 +04:00
|
|
|
if (!IsAttributeMapped(aName) ||
|
|
|
|
!SetMappedAttribute(document, aName, aParsedValue, &rv)) {
|
2015-07-22 05:09:41 +03:00
|
|
|
rv = mAttrsAndChildren.SetAndSwapAttr(aName, aParsedValue);
|
2004-11-23 20:21:37 +03:00
|
|
|
}
|
2004-01-15 20:07:27 +03:00
|
|
|
}
|
|
|
|
else {
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<mozilla::dom::NodeInfo> ni;
|
2008-09-13 02:32:18 +04:00
|
|
|
ni = mNodeInfo->NodeInfoManager()->GetNodeInfo(aName, aPrefix,
|
2011-06-14 11:56:49 +04:00
|
|
|
aNamespaceID,
|
|
|
|
nsIDOMNode::ATTRIBUTE_NODE);
|
2000-06-23 04:21:32 +04:00
|
|
|
|
2015-07-22 05:09:41 +03:00
|
|
|
rv = mAttrsAndChildren.SetAndSwapAttr(ni, aParsedValue);
|
2000-06-23 04:21:32 +04:00
|
|
|
}
|
2015-07-25 08:57:13 +03:00
|
|
|
|
|
|
|
// If the old value owns its own data, we know it is OK to keep using it.
|
|
|
|
const nsAttrValue* oldValue =
|
|
|
|
aParsedValue.StoresOwnData() ? &aParsedValue : &aOldValue;
|
|
|
|
|
2005-10-28 06:59:38 +04:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
1998-12-20 04:21:23 +03:00
|
|
|
|
2008-03-04 04:25:06 +03:00
|
|
|
if (document || HasFlag(NODE_FORCE_XBL_BINDINGS)) {
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<nsXBLBinding> binding = GetXBLBinding();
|
2011-10-18 15:19:44 +04:00
|
|
|
if (binding) {
|
|
|
|
binding->AttributeChanged(aName, aNamespaceID, false, aNotify);
|
2005-10-28 06:59:38 +04:00
|
|
|
}
|
2006-06-02 04:58:04 +04:00
|
|
|
}
|
2000-05-10 06:15:47 +04:00
|
|
|
|
2011-06-01 05:46:57 +04:00
|
|
|
UpdateState(aNotify);
|
|
|
|
|
2014-02-24 01:01:26 +04:00
|
|
|
nsIDocument* ownerDoc = OwnerDoc();
|
|
|
|
if (ownerDoc && GetCustomElementData()) {
|
2015-07-25 08:57:13 +03:00
|
|
|
nsCOMPtr<nsIAtom> oldValueAtom = oldValue->GetAsAtom();
|
|
|
|
nsCOMPtr<nsIAtom> newValueAtom = valueForAfterSetAttr.GetAsAtom();
|
2014-02-24 01:01:26 +04:00
|
|
|
LifecycleCallbackArgs args = {
|
|
|
|
nsDependentAtomString(aName),
|
|
|
|
aModType == nsIDOMMutationEvent::ADDITION ?
|
|
|
|
NullString() : nsDependentAtomString(oldValueAtom),
|
|
|
|
nsDependentAtomString(newValueAtom)
|
|
|
|
};
|
|
|
|
|
|
|
|
ownerDoc->EnqueueLifecycleCallback(nsIDocument::eAttributeChanged, this, &args);
|
|
|
|
}
|
|
|
|
|
2012-02-14 06:00:56 +04:00
|
|
|
if (aCallAfterSetAttr) {
|
2015-07-25 08:57:13 +03:00
|
|
|
rv = AfterSetAttr(aNamespaceID, aName, &valueForAfterSetAttr, aNotify);
|
2008-12-03 13:39:21 +03:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2012-11-21 14:13:57 +04:00
|
|
|
|
|
|
|
if (aNamespaceID == kNameSpaceID_None && aName == nsGkAtoms::dir) {
|
2015-07-25 08:57:13 +03:00
|
|
|
OnSetDirAttr(this, &valueForAfterSetAttr,
|
2013-03-08 00:53:08 +04:00
|
|
|
hadValidDir, hadDirAuto, aNotify);
|
2012-11-21 14:13:57 +04:00
|
|
|
}
|
2008-12-03 13:39:21 +03:00
|
|
|
}
|
|
|
|
|
2013-09-10 20:17:51 +04:00
|
|
|
if (aNotify) {
|
2015-07-21 07:13:53 +03:00
|
|
|
// Don't pass aOldValue to AttributeChanged since it may not be reliable.
|
|
|
|
// Callers only compute aOldValue under certain conditions which may not
|
|
|
|
// be triggered by all nsIMutationObservers.
|
|
|
|
nsNodeUtils::AttributeChanged(this, aNamespaceID, aName, aModType,
|
|
|
|
oldValue == &aParsedValue ? &aParsedValue : nullptr);
|
2013-09-10 20:17:51 +04:00
|
|
|
}
|
|
|
|
|
2006-06-02 04:58:04 +04:00
|
|
|
if (aFireMutation) {
|
2015-09-07 17:55:51 +03:00
|
|
|
InternalMutationEvent mutation(true, eLegacyAttrModified);
|
2000-11-27 10:55:20 +03:00
|
|
|
|
2008-04-18 21:20:11 +04:00
|
|
|
nsAutoString ns;
|
|
|
|
nsContentUtils::NameSpaceManager()->GetNameSpaceURI(aNamespaceID, ns);
|
2013-04-09 19:29:47 +04:00
|
|
|
Attr* attrNode =
|
2013-04-04 16:01:11 +04:00
|
|
|
GetAttributeNodeNSInternal(ns, nsDependentAtomString(aName));
|
2008-04-18 21:20:11 +04:00
|
|
|
mutation.mRelatedNode = attrNode;
|
|
|
|
|
|
|
|
mutation.mAttrName = aName;
|
|
|
|
nsAutoString newValue;
|
|
|
|
GetAttr(aNamespaceID, aName, newValue);
|
|
|
|
if (!newValue.IsEmpty()) {
|
2016-03-29 02:09:43 +03:00
|
|
|
mutation.mNewAttrValue = NS_Atomize(newValue);
|
2008-04-18 21:20:11 +04:00
|
|
|
}
|
2015-07-25 08:57:13 +03:00
|
|
|
if (!oldValue->IsEmptyString()) {
|
|
|
|
mutation.mPrevAttrValue = oldValue->GetAsAtom();
|
2000-01-29 02:43:12 +03:00
|
|
|
}
|
2010-02-24 07:37:47 +03:00
|
|
|
mutation.mAttrChange = aModType;
|
2008-04-18 21:20:11 +04:00
|
|
|
|
2011-10-18 14:53:36 +04:00
|
|
|
mozAutoSubtreeModified subtree(OwnerDoc(), this);
|
2014-03-17 10:56:54 +04:00
|
|
|
(new AsyncEventDispatcher(this, mutation))->RunDOMEventWhenSafe();
|
2006-06-02 04:58:04 +04:00
|
|
|
}
|
|
|
|
|
2003-06-22 10:34:08 +04:00
|
|
|
return NS_OK;
|
1998-11-12 01:06:16 +03:00
|
|
|
}
|
|
|
|
|
2015-08-01 08:46:15 +03:00
|
|
|
nsresult
|
|
|
|
Element::BeforeSetAttr(int32_t aNamespaceID, nsIAtom* aName,
|
|
|
|
nsAttrValueOrString* aValue, bool aNotify)
|
|
|
|
{
|
|
|
|
if (aNamespaceID == kNameSpaceID_None) {
|
|
|
|
if (aName == nsGkAtoms::_class) {
|
|
|
|
// aValue->GetAttrValue will only be non-null here when this is called
|
|
|
|
// via Element::SetParsedAttr. This shouldn't happen for "class", but
|
|
|
|
// this will handle it.
|
|
|
|
if (aValue && !aValue->GetAttrValue()) {
|
|
|
|
nsAttrValue attr;
|
|
|
|
attr.ParseAtomArray(aValue->String());
|
|
|
|
aValue->TakeParsedValue(attr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool
|
2012-11-15 02:10:08 +04:00
|
|
|
Element::ParseAttribute(int32_t aNamespaceID,
|
|
|
|
nsIAtom* aAttribute,
|
|
|
|
const nsAString& aValue,
|
|
|
|
nsAttrValue& aResult)
|
2005-10-28 06:59:38 +04:00
|
|
|
{
|
2014-05-30 11:36:53 +04:00
|
|
|
if (aNamespaceID == kNameSpaceID_None) {
|
|
|
|
if (aAttribute == nsGkAtoms::_class) {
|
|
|
|
SetFlags(NODE_MAY_HAVE_CLASS);
|
2015-08-01 08:46:15 +03:00
|
|
|
// Result should have been preparsed above.
|
2014-05-30 11:36:53 +04:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if (aAttribute == nsGkAtoms::id) {
|
|
|
|
// Store id as an atom. id="" means that the element has no id,
|
|
|
|
// not that it has an emptystring as the id.
|
|
|
|
RemoveFromIdTable();
|
|
|
|
if (aValue.IsEmpty()) {
|
|
|
|
ClearHasID();
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
aResult.ParseAtom(aValue);
|
|
|
|
SetHasID();
|
|
|
|
AddToIdTable(aResult.GetAtomValue());
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-10-17 18:59:28 +04:00
|
|
|
return false;
|
2005-10-28 06:59:38 +04:00
|
|
|
}
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool
|
2012-11-15 02:10:08 +04:00
|
|
|
Element::SetMappedAttribute(nsIDocument* aDocument,
|
|
|
|
nsIAtom* aName,
|
|
|
|
nsAttrValue& aValue,
|
|
|
|
nsresult* aRetval)
|
2005-10-28 06:59:38 +04:00
|
|
|
{
|
|
|
|
*aRetval = NS_OK;
|
2011-10-17 18:59:28 +04:00
|
|
|
return false;
|
2005-10-28 06:59:38 +04:00
|
|
|
}
|
|
|
|
|
2014-03-17 10:56:53 +04:00
|
|
|
EventListenerManager*
|
2012-11-15 02:10:08 +04:00
|
|
|
Element::GetEventListenerManagerForAttr(nsIAtom* aAttrName,
|
|
|
|
bool* aDefer)
|
2005-10-28 06:59:38 +04:00
|
|
|
{
|
2011-10-17 18:59:28 +04:00
|
|
|
*aDefer = true;
|
2013-10-23 03:32:04 +04:00
|
|
|
return GetOrCreateListenerManager();
|
2005-10-28 06:59:38 +04:00
|
|
|
}
|
|
|
|
|
2016-07-23 00:11:41 +03:00
|
|
|
BorrowedAttrInfo
|
2012-11-15 02:10:08 +04:00
|
|
|
Element::GetAttrInfo(int32_t aNamespaceID, nsIAtom* aName) const
|
2005-10-28 06:59:38 +04:00
|
|
|
{
|
2012-07-30 18:20:58 +04:00
|
|
|
NS_ASSERTION(nullptr != aName, "must have attribute name");
|
2005-10-28 06:59:38 +04:00
|
|
|
NS_ASSERTION(aNamespaceID != kNameSpaceID_Unknown,
|
|
|
|
"must have a real namespace ID!");
|
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t index = mAttrsAndChildren.IndexOfAttr(aName, aNamespaceID);
|
2016-07-22 06:10:23 +03:00
|
|
|
if (index < 0) {
|
2016-07-23 00:11:41 +03:00
|
|
|
return BorrowedAttrInfo(nullptr, nullptr);
|
2005-10-28 06:59:38 +04:00
|
|
|
}
|
|
|
|
|
2016-07-22 06:10:23 +03:00
|
|
|
return mAttrsAndChildren.AttrInfoAt(index);
|
2005-10-28 06:59:38 +04:00
|
|
|
}
|
2016-02-15 03:34:47 +03:00
|
|
|
|
2016-07-23 00:11:41 +03:00
|
|
|
BorrowedAttrInfo
|
2016-07-22 06:10:23 +03:00
|
|
|
Element::GetAttrInfoAt(uint32_t aIndex) const
|
|
|
|
{
|
|
|
|
if (aIndex >= mAttrsAndChildren.AttrCount()) {
|
2016-07-23 00:11:41 +03:00
|
|
|
return BorrowedAttrInfo(nullptr, nullptr);
|
2016-07-22 06:10:23 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
return mAttrsAndChildren.AttrInfoAt(aIndex);
|
|
|
|
}
|
2005-10-28 06:59:38 +04:00
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool
|
2012-11-15 02:10:08 +04:00
|
|
|
Element::GetAttr(int32_t aNameSpaceID, nsIAtom* aName,
|
|
|
|
nsAString& aResult) const
|
2000-05-17 04:21:53 +04:00
|
|
|
{
|
2013-01-29 18:42:14 +04:00
|
|
|
DOMString str;
|
|
|
|
bool haveAttr = GetAttr(aNameSpaceID, aName, str);
|
|
|
|
str.ToString(aResult);
|
|
|
|
return haveAttr;
|
1998-11-12 01:06:16 +03:00
|
|
|
}
|
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t
|
2012-11-15 02:10:08 +04:00
|
|
|
Element::FindAttrValueIn(int32_t aNameSpaceID,
|
|
|
|
nsIAtom* aName,
|
|
|
|
AttrValuesArray* aValues,
|
|
|
|
nsCaseTreatment aCaseSensitive) const
|
2006-01-18 07:09:33 +03:00
|
|
|
{
|
|
|
|
NS_ASSERTION(aName, "Must have attr name");
|
|
|
|
NS_ASSERTION(aNameSpaceID != kNameSpaceID_Unknown, "Must have namespace");
|
|
|
|
NS_ASSERTION(aValues, "Null value array");
|
2016-02-15 03:34:47 +03:00
|
|
|
|
2006-01-18 07:09:33 +03:00
|
|
|
const nsAttrValue* val = mAttrsAndChildren.GetAttr(aName, aNameSpaceID);
|
|
|
|
if (val) {
|
2012-08-22 19:56:38 +04:00
|
|
|
for (int32_t i = 0; aValues[i]; ++i) {
|
2006-01-18 07:09:33 +03:00
|
|
|
if (val->Equals(*aValues[i], aCaseSensitive)) {
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ATTR_VALUE_NO_MATCH;
|
|
|
|
}
|
|
|
|
return ATTR_MISSING;
|
|
|
|
}
|
|
|
|
|
2000-12-23 13:56:31 +03:00
|
|
|
nsresult
|
2012-11-15 02:10:08 +04:00
|
|
|
Element::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aName,
|
|
|
|
bool aNotify)
|
1998-11-12 01:06:16 +03:00
|
|
|
{
|
2012-07-30 18:20:58 +04:00
|
|
|
NS_ASSERTION(nullptr != aName, "must have attribute name");
|
1998-12-20 04:21:23 +03:00
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t index = mAttrsAndChildren.IndexOfAttr(aName, aNameSpaceID);
|
2004-01-15 20:07:27 +03:00
|
|
|
if (index < 0) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
1998-11-12 01:06:16 +03:00
|
|
|
|
2012-07-30 18:20:58 +04:00
|
|
|
nsresult rv = BeforeSetAttr(aNameSpaceID, aName, nullptr, aNotify);
|
2007-12-04 19:50:32 +03:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2012-02-14 06:00:56 +04:00
|
|
|
|
2014-10-02 22:45:44 +04:00
|
|
|
nsIDocument *document = GetComposedDoc();
|
2004-08-10 14:22:36 +04:00
|
|
|
mozAutoDocUpdate updateBatch(document, UPDATE_CONTENT_MODEL, aNotify);
|
2005-08-11 00:21:44 +04:00
|
|
|
|
2009-06-29 22:36:25 +04:00
|
|
|
if (aNotify) {
|
|
|
|
nsNodeUtils::AttributeWillChange(this, aNameSpaceID, aName,
|
2015-07-22 06:53:35 +03:00
|
|
|
nsIDOMMutationEvent::REMOVAL,
|
|
|
|
nullptr);
|
2009-06-29 22:36:25 +04:00
|
|
|
}
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool hasMutationListeners = aNotify &&
|
2006-11-11 03:04:46 +03:00
|
|
|
nsContentUtils::HasMutationListeners(this,
|
2007-07-05 00:39:10 +04:00
|
|
|
NS_EVENT_BITS_MUTATION_ATTRMODIFIED,
|
|
|
|
this);
|
2006-06-02 04:58:04 +04:00
|
|
|
|
2006-11-11 03:04:46 +03:00
|
|
|
// Grab the attr node if needed before we remove it from the attr map
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<Attr> attrNode;
|
2006-11-11 03:04:46 +03:00
|
|
|
if (hasMutationListeners) {
|
2006-12-01 11:44:38 +03:00
|
|
|
nsAutoString ns;
|
|
|
|
nsContentUtils::NameSpaceManager()->GetNameSpaceURI(aNameSpaceID, ns);
|
2013-04-04 16:01:11 +04:00
|
|
|
attrNode = GetAttributeNodeNSInternal(ns, nsDependentAtomString(aName));
|
2004-01-15 20:07:27 +03:00
|
|
|
}
|
2003-10-16 22:14:25 +04:00
|
|
|
|
2013-03-10 12:00:33 +04:00
|
|
|
// Clear binding to nsIDOMMozNamedAttrMap
|
2005-06-01 17:46:20 +04:00
|
|
|
nsDOMSlots *slots = GetExistingDOMSlots();
|
|
|
|
if (slots && slots->mAttributeMap) {
|
|
|
|
slots->mAttributeMap->DropAttribute(aNameSpaceID, aName);
|
|
|
|
}
|
|
|
|
|
2010-09-02 02:48:24 +04:00
|
|
|
// The id-handling code, and in the future possibly other code, need to
|
|
|
|
// react to unexpected attribute changes.
|
|
|
|
nsMutationGuard::DidMutate();
|
|
|
|
|
2014-05-30 11:36:53 +04:00
|
|
|
if (aName == nsGkAtoms::id && aNameSpaceID == kNameSpaceID_None) {
|
|
|
|
// Have to do this before clearing flag. See RemoveFromIdTable
|
|
|
|
RemoveFromIdTable();
|
|
|
|
ClearHasID();
|
|
|
|
}
|
|
|
|
|
2012-11-21 14:13:57 +04:00
|
|
|
bool hadValidDir = false;
|
2013-03-08 00:53:08 +04:00
|
|
|
bool hadDirAuto = false;
|
2012-11-21 14:13:57 +04:00
|
|
|
|
|
|
|
if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::dir) {
|
2015-03-03 14:08:59 +03:00
|
|
|
hadValidDir = HasValidDir() || IsHTMLElement(nsGkAtoms::bdi);
|
2013-03-08 00:53:08 +04:00
|
|
|
hadDirAuto = HasDirAuto(); // already takes bdi into account
|
2012-11-21 14:13:57 +04:00
|
|
|
}
|
|
|
|
|
2006-11-11 03:04:46 +03:00
|
|
|
nsAttrValue oldValue;
|
2007-12-04 19:50:32 +03:00
|
|
|
rv = mAttrsAndChildren.RemoveAttrAt(index, oldValue);
|
2004-01-26 22:22:05 +03:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2003-10-16 22:14:25 +04:00
|
|
|
|
2008-03-04 04:25:06 +03:00
|
|
|
if (document || HasFlag(NODE_FORCE_XBL_BINDINGS)) {
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<nsXBLBinding> binding = GetXBLBinding();
|
2011-10-18 15:19:44 +04:00
|
|
|
if (binding) {
|
|
|
|
binding->AttributeChanged(aName, aNameSpaceID, true, aNotify);
|
2008-03-04 04:25:06 +03:00
|
|
|
}
|
2006-07-02 11:23:10 +04:00
|
|
|
}
|
2000-05-10 06:15:47 +04:00
|
|
|
|
2011-06-01 05:46:57 +04:00
|
|
|
UpdateState(aNotify);
|
|
|
|
|
2014-02-24 01:01:26 +04:00
|
|
|
nsIDocument* ownerDoc = OwnerDoc();
|
|
|
|
if (ownerDoc && GetCustomElementData()) {
|
|
|
|
nsCOMPtr<nsIAtom> oldValueAtom = oldValue.GetAsAtom();
|
|
|
|
LifecycleCallbackArgs args = {
|
|
|
|
nsDependentAtomString(aName),
|
|
|
|
nsDependentAtomString(oldValueAtom),
|
|
|
|
NullString()
|
|
|
|
};
|
|
|
|
|
|
|
|
ownerDoc->EnqueueLifecycleCallback(nsIDocument::eAttributeChanged, this, &args);
|
|
|
|
}
|
|
|
|
|
2006-07-02 11:23:10 +04:00
|
|
|
if (aNotify) {
|
2015-07-21 07:13:53 +03:00
|
|
|
// We can always pass oldValue here since there is no new value which could
|
|
|
|
// have corrupted it.
|
2006-07-02 11:23:10 +04:00
|
|
|
nsNodeUtils::AttributeChanged(this, aNameSpaceID, aName,
|
2015-07-21 07:13:53 +03:00
|
|
|
nsIDOMMutationEvent::REMOVAL, &oldValue);
|
1998-11-12 01:06:16 +03:00
|
|
|
}
|
|
|
|
|
2012-07-30 18:20:58 +04:00
|
|
|
rv = AfterSetAttr(aNameSpaceID, aName, nullptr, aNotify);
|
2008-12-03 13:39:21 +03:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
2012-11-21 14:13:57 +04:00
|
|
|
if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::dir) {
|
2013-03-08 00:53:08 +04:00
|
|
|
OnSetDirAttr(this, nullptr, hadValidDir, hadDirAuto, aNotify);
|
2012-11-21 14:13:57 +04:00
|
|
|
}
|
|
|
|
|
2006-11-11 03:04:46 +03:00
|
|
|
if (hasMutationListeners) {
|
2015-09-07 17:55:51 +03:00
|
|
|
InternalMutationEvent mutation(true, eLegacyAttrModified);
|
2006-11-11 03:04:46 +03:00
|
|
|
|
2008-04-18 21:20:11 +04:00
|
|
|
mutation.mRelatedNode = attrNode;
|
|
|
|
mutation.mAttrName = aName;
|
2006-11-11 03:04:46 +03:00
|
|
|
|
2008-04-18 21:20:11 +04:00
|
|
|
nsAutoString value;
|
|
|
|
oldValue.ToString(value);
|
|
|
|
if (!value.IsEmpty())
|
2016-03-29 02:09:43 +03:00
|
|
|
mutation.mPrevAttrValue = NS_Atomize(value);
|
2008-04-18 21:20:11 +04:00
|
|
|
mutation.mAttrChange = nsIDOMMutationEvent::REMOVAL;
|
2008-03-15 02:08:57 +03:00
|
|
|
|
2011-10-18 14:53:36 +04:00
|
|
|
mozAutoSubtreeModified subtree(OwnerDoc(), this);
|
2014-03-17 10:56:54 +04:00
|
|
|
(new AsyncEventDispatcher(this, mutation))->RunDOMEventWhenSafe();
|
2006-11-11 03:04:46 +03:00
|
|
|
}
|
|
|
|
|
2008-12-03 13:39:21 +03:00
|
|
|
return NS_OK;
|
1998-11-12 01:06:16 +03:00
|
|
|
}
|
|
|
|
|
2005-12-29 00:52:39 +03:00
|
|
|
const nsAttrName*
|
2012-11-15 02:10:08 +04:00
|
|
|
Element::GetAttrNameAt(uint32_t aIndex) const
|
1998-11-12 01:06:16 +03:00
|
|
|
{
|
2005-12-29 00:52:39 +03:00
|
|
|
return mAttrsAndChildren.GetSafeAttrNameAt(aIndex);
|
1998-11-12 01:06:16 +03:00
|
|
|
}
|
|
|
|
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t
|
2012-11-15 02:10:08 +04:00
|
|
|
Element::GetAttrCount() const
|
1998-11-12 01:06:16 +03:00
|
|
|
{
|
2004-01-15 20:07:27 +03:00
|
|
|
return mAttrsAndChildren.AttrCount();
|
1998-11-12 01:06:16 +03:00
|
|
|
}
|
|
|
|
|
2014-01-23 01:15:05 +04:00
|
|
|
void
|
|
|
|
Element::DescribeAttribute(uint32_t index, nsAString& aOutDescription) const
|
|
|
|
{
|
|
|
|
// name
|
|
|
|
mAttrsAndChildren.AttrNameAt(index)->GetQualifiedName(aOutDescription);
|
|
|
|
|
|
|
|
// value
|
|
|
|
aOutDescription.AppendLiteral("=\"");
|
|
|
|
nsAutoString value;
|
|
|
|
mAttrsAndChildren.AttrAt(index)->ToString(value);
|
|
|
|
for (int i = value.Length(); i >= 0; --i) {
|
|
|
|
if (value[i] == char16_t('"'))
|
|
|
|
value.Insert(char16_t('\\'), uint32_t(i));
|
|
|
|
}
|
|
|
|
aOutDescription.Append(value);
|
2014-05-26 22:54:58 +04:00
|
|
|
aOutDescription.Append('"');
|
2014-01-23 01:15:05 +04:00
|
|
|
}
|
|
|
|
|
2001-10-16 09:31:36 +04:00
|
|
|
#ifdef DEBUG
|
1998-11-12 01:06:16 +03:00
|
|
|
void
|
2012-11-15 02:10:08 +04:00
|
|
|
Element::ListAttributes(FILE* out) const
|
1998-11-12 01:06:16 +03:00
|
|
|
{
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t index, count = mAttrsAndChildren.AttrCount();
|
2006-12-27 20:26:32 +03:00
|
|
|
for (index = 0; index < count; index++) {
|
2014-01-23 01:15:05 +04:00
|
|
|
nsAutoString attributeDescription;
|
|
|
|
DescribeAttribute(index, attributeDescription);
|
1998-12-20 04:21:23 +03:00
|
|
|
|
|
|
|
fputs(" ", out);
|
2014-01-23 01:15:05 +04:00
|
|
|
fputs(NS_LossyConvertUTF16toASCII(attributeDescription).get(), out);
|
1998-11-12 01:06:16 +03:00
|
|
|
}
|
2006-12-27 20:26:32 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2012-11-15 02:10:08 +04:00
|
|
|
Element::List(FILE* out, int32_t aIndent,
|
|
|
|
const nsCString& aPrefix) const
|
2006-12-27 20:26:32 +03:00
|
|
|
{
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t indent;
|
2006-12-27 20:26:32 +03:00
|
|
|
for (indent = aIndent; --indent >= 0; ) fputs(" ", out);
|
|
|
|
|
|
|
|
fputs(aPrefix.get(), out);
|
|
|
|
|
2011-05-05 20:26:33 +04:00
|
|
|
fputs(NS_LossyConvertUTF16toASCII(mNodeInfo->QualifiedName()).get(), out);
|
2006-12-27 20:26:32 +03:00
|
|
|
|
|
|
|
fprintf(out, "@%p", (void *)this);
|
|
|
|
|
|
|
|
ListAttributes(out);
|
1998-11-12 01:06:16 +03:00
|
|
|
|
2013-08-01 05:15:26 +04:00
|
|
|
fprintf(out, " state=[%llx]",
|
|
|
|
static_cast<unsigned long long>(State().GetInternalValue()));
|
2010-05-12 04:30:42 +04:00
|
|
|
fprintf(out, " flags=[%08x]", static_cast<unsigned int>(GetFlags()));
|
2011-12-20 13:15:41 +04:00
|
|
|
if (IsCommonAncestorForRangeInSelection()) {
|
2012-01-10 18:19:54 +04:00
|
|
|
nsRange::RangeHashTable* ranges =
|
|
|
|
static_cast<nsRange::RangeHashTable*>(GetProperty(nsGkAtoms::range));
|
2011-12-20 13:15:41 +04:00
|
|
|
fprintf(out, " ranges:%d", ranges ? ranges->Count() : 0);
|
|
|
|
}
|
2010-05-01 22:42:47 +04:00
|
|
|
fprintf(out, " primaryframe=%p", static_cast<void*>(GetPrimaryFrame()));
|
2014-03-28 00:38:33 +04:00
|
|
|
fprintf(out, " refcount=%" PRIuPTR "<", mRefCnt.get());
|
1998-11-12 01:06:16 +03:00
|
|
|
|
2011-09-27 11:54:58 +04:00
|
|
|
nsIContent* child = GetFirstChild();
|
|
|
|
if (child) {
|
2006-12-27 20:26:32 +03:00
|
|
|
fputs("\n", out);
|
2016-02-15 03:34:47 +03:00
|
|
|
|
2011-09-27 11:54:58 +04:00
|
|
|
for (; child; child = child->GetNextSibling()) {
|
|
|
|
child->List(out, aIndent + 1);
|
2006-12-27 20:26:32 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
for (indent = aIndent; --indent >= 0; ) fputs(" ", out);
|
1998-11-12 01:06:16 +03:00
|
|
|
}
|
2004-03-06 03:22:03 +03:00
|
|
|
|
1998-11-12 01:06:16 +03:00
|
|
|
fputs(">\n", out);
|
2016-02-15 03:34:47 +03:00
|
|
|
|
2012-11-15 02:10:08 +04:00
|
|
|
Element* nonConstThis = const_cast<Element*>(this);
|
1998-11-12 01:06:16 +03:00
|
|
|
|
2006-12-27 20:26:32 +03:00
|
|
|
// XXX sXBL/XBL2 issue! Owner or current document?
|
2011-10-18 14:53:36 +04:00
|
|
|
nsIDocument *document = OwnerDoc();
|
2001-08-03 11:34:28 +04:00
|
|
|
|
2011-10-18 15:19:44 +04:00
|
|
|
// Note: not listing nsIAnonymousContentCreator-created content...
|
|
|
|
|
|
|
|
nsBindingManager* bindingManager = document->BindingManager();
|
|
|
|
nsCOMPtr<nsIDOMNodeList> anonymousChildren;
|
|
|
|
bindingManager->GetAnonymousNodesFor(nonConstThis,
|
|
|
|
getter_AddRefs(anonymousChildren));
|
|
|
|
|
|
|
|
if (anonymousChildren) {
|
2013-05-02 02:50:08 +04:00
|
|
|
uint32_t length = 0;
|
2011-10-18 15:19:44 +04:00
|
|
|
anonymousChildren->GetLength(&length);
|
|
|
|
|
2013-05-02 02:50:08 +04:00
|
|
|
for (indent = aIndent; --indent >= 0; ) fputs(" ", out);
|
|
|
|
fputs("anonymous-children<\n", out);
|
2011-10-18 15:19:44 +04:00
|
|
|
|
2013-05-02 02:50:08 +04:00
|
|
|
for (uint32_t i = 0; i < length; ++i) {
|
|
|
|
nsCOMPtr<nsIDOMNode> node;
|
|
|
|
anonymousChildren->Item(i, getter_AddRefs(node));
|
|
|
|
nsCOMPtr<nsIContent> child = do_QueryInterface(node);
|
|
|
|
child->List(out, aIndent + 1);
|
2005-02-19 13:31:27 +03:00
|
|
|
}
|
2001-08-03 11:34:28 +04:00
|
|
|
|
2013-05-02 02:50:08 +04:00
|
|
|
for (indent = aIndent; --indent >= 0; ) fputs(" ", out);
|
|
|
|
fputs(">\n", out);
|
2001-08-03 11:34:28 +04:00
|
|
|
|
2013-05-02 02:50:08 +04:00
|
|
|
bool outHeader = false;
|
|
|
|
ExplicitChildIterator iter(nonConstThis);
|
|
|
|
for (nsIContent* child = iter.GetNextChild(); child; child = iter.GetNextChild()) {
|
|
|
|
if (!outHeader) {
|
|
|
|
outHeader = true;
|
2011-10-18 15:19:44 +04:00
|
|
|
|
2013-05-02 02:50:08 +04:00
|
|
|
for (indent = aIndent; --indent >= 0; ) fputs(" ", out);
|
|
|
|
fputs("content-list<\n", out);
|
2001-08-03 11:34:28 +04:00
|
|
|
}
|
2011-10-18 15:19:44 +04:00
|
|
|
|
2013-05-02 02:50:08 +04:00
|
|
|
child->List(out, aIndent + 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (outHeader) {
|
2011-10-18 15:19:44 +04:00
|
|
|
for (indent = aIndent; --indent >= 0; ) fputs(" ", out);
|
|
|
|
fputs(">\n", out);
|
2001-08-03 11:34:28 +04:00
|
|
|
}
|
|
|
|
}
|
1998-11-12 01:06:16 +03:00
|
|
|
}
|
|
|
|
|
2004-01-10 02:54:21 +03:00
|
|
|
void
|
2012-11-15 02:10:08 +04:00
|
|
|
Element::DumpContent(FILE* out, int32_t aIndent,
|
|
|
|
bool aDumpAll) const
|
2004-01-10 02:54:21 +03:00
|
|
|
{
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t indent;
|
2006-12-27 20:26:32 +03:00
|
|
|
for (indent = aIndent; --indent >= 0; ) fputs(" ", out);
|
|
|
|
|
2011-05-05 20:26:33 +04:00
|
|
|
const nsString& buf = mNodeInfo->QualifiedName();
|
2006-12-27 20:26:32 +03:00
|
|
|
fputs("<", out);
|
|
|
|
fputs(NS_LossyConvertUTF16toASCII(buf).get(), out);
|
|
|
|
|
|
|
|
if(aDumpAll) ListAttributes(out);
|
|
|
|
|
|
|
|
fputs(">", out);
|
|
|
|
|
|
|
|
if(aIndent) fputs("\n", out);
|
|
|
|
|
2011-09-27 11:54:58 +04:00
|
|
|
for (nsIContent* child = GetFirstChild();
|
|
|
|
child;
|
|
|
|
child = child->GetNextSibling()) {
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t indent = aIndent ? aIndent + 1 : 0;
|
2011-09-27 11:54:58 +04:00
|
|
|
child->DumpContent(out, indent, aDumpAll);
|
2006-12-27 20:26:32 +03:00
|
|
|
}
|
|
|
|
for (indent = aIndent; --indent >= 0; ) fputs(" ", out);
|
|
|
|
fputs("</", out);
|
|
|
|
fputs(NS_LossyConvertUTF16toASCII(buf).get(), out);
|
|
|
|
fputs(">", out);
|
|
|
|
|
|
|
|
if(aIndent) fputs("\n", out);
|
2000-05-26 23:45:37 +04:00
|
|
|
}
|
2001-10-16 09:31:36 +04:00
|
|
|
#endif
|
2000-05-26 23:45:37 +04:00
|
|
|
|
2014-01-23 01:15:05 +04:00
|
|
|
void
|
|
|
|
Element::Describe(nsAString& aOutDescription) const
|
|
|
|
{
|
|
|
|
aOutDescription.Append(mNodeInfo->QualifiedName());
|
|
|
|
aOutDescription.AppendPrintf("@%p", (void *)this);
|
|
|
|
|
|
|
|
uint32_t index, count = mAttrsAndChildren.AttrCount();
|
|
|
|
for (index = 0; index < count; index++) {
|
|
|
|
aOutDescription.Append(' ');
|
|
|
|
nsAutoString attributeDescription;
|
|
|
|
DescribeAttribute(index, attributeDescription);
|
|
|
|
aOutDescription.Append(attributeDescription);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool
|
2014-03-18 08:48:18 +04:00
|
|
|
Element::CheckHandleEventForLinksPrecondition(EventChainVisitor& aVisitor,
|
2012-11-15 02:10:08 +04:00
|
|
|
nsIURI** aURI) const
|
2007-04-23 11:31:21 +04:00
|
|
|
{
|
|
|
|
if (aVisitor.mEventStatus == nsEventStatus_eConsumeNoDefault ||
|
2016-03-17 10:01:30 +03:00
|
|
|
(!aVisitor.mEvent->IsTrusted() &&
|
2015-08-29 02:58:32 +03:00
|
|
|
(aVisitor.mEvent->mMessage != eMouseClick) &&
|
2015-08-29 02:58:27 +03:00
|
|
|
(aVisitor.mEvent->mMessage != eKeyPress) &&
|
2015-09-02 09:08:01 +03:00
|
|
|
(aVisitor.mEvent->mMessage != eLegacyDOMActivate)) ||
|
2010-12-27 23:42:10 +03:00
|
|
|
!aVisitor.mPresContext ||
|
2012-12-16 05:26:04 +04:00
|
|
|
aVisitor.mEvent->mFlags.mMultipleActionsPrevented) {
|
2011-10-17 18:59:28 +04:00
|
|
|
return false;
|
2007-04-23 11:31:21 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// Make sure we actually are a link
|
|
|
|
return IsLink(aURI);
|
|
|
|
}
|
|
|
|
|
2007-01-04 13:53:59 +03:00
|
|
|
nsresult
|
2014-03-18 08:48:19 +04:00
|
|
|
Element::PreHandleEventForLinks(EventChainPreVisitor& aVisitor)
|
2007-01-04 13:53:59 +03:00
|
|
|
{
|
|
|
|
// Optimisation: return early if this event doesn't interest us.
|
|
|
|
// IMPORTANT: this switch and the switch below it must be kept in sync!
|
2015-08-22 04:34:51 +03:00
|
|
|
switch (aVisitor.mEvent->mMessage) {
|
2015-08-29 02:58:32 +03:00
|
|
|
case eMouseOver:
|
2015-09-02 09:08:00 +03:00
|
|
|
case eFocus:
|
2015-08-29 02:58:32 +03:00
|
|
|
case eMouseOut:
|
2015-09-02 09:08:00 +03:00
|
|
|
case eBlur:
|
2007-01-04 13:53:59 +03:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2007-04-23 11:31:21 +04:00
|
|
|
// Make sure we meet the preconditions before continuing
|
|
|
|
nsCOMPtr<nsIURI> absURI;
|
|
|
|
if (!CheckHandleEventForLinksPrecondition(aVisitor, getter_AddRefs(absURI))) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult rv = NS_OK;
|
|
|
|
|
|
|
|
// We do the status bar updates in PreHandleEvent so that the status bar gets
|
|
|
|
// updated even if the event is consumed before we have a chance to set it.
|
2015-08-22 04:34:51 +03:00
|
|
|
switch (aVisitor.mEvent->mMessage) {
|
2010-10-18 22:12:18 +04:00
|
|
|
// Set the status bar similarly for mouseover and focus
|
2015-08-29 02:58:32 +03:00
|
|
|
case eMouseOver:
|
2007-04-23 11:31:21 +04:00
|
|
|
aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
|
2015-11-26 10:26:32 +03:00
|
|
|
MOZ_FALLTHROUGH;
|
2015-09-02 09:08:00 +03:00
|
|
|
case eFocus: {
|
2013-10-18 10:10:22 +04:00
|
|
|
InternalFocusEvent* focusEvent = aVisitor.mEvent->AsFocusEvent();
|
2016-03-27 08:46:07 +03:00
|
|
|
if (!focusEvent || !focusEvent->mIsRefocus) {
|
2007-04-23 11:31:21 +04:00
|
|
|
nsAutoString target;
|
|
|
|
GetLinkTarget(target);
|
2007-07-11 17:05:05 +04:00
|
|
|
nsContentUtils::TriggerLink(this, aVisitor.mPresContext, absURI, target,
|
2011-10-17 18:59:28 +04:00
|
|
|
false, true, true);
|
2010-12-27 23:42:10 +03:00
|
|
|
// Make sure any ancestor links don't also TriggerLink
|
2012-12-16 05:26:04 +04:00
|
|
|
aVisitor.mEvent->mFlags.mMultipleActionsPrevented = true;
|
2007-04-23 11:31:21 +04:00
|
|
|
}
|
|
|
|
break;
|
2013-10-18 10:10:22 +04:00
|
|
|
}
|
2015-08-29 02:58:32 +03:00
|
|
|
case eMouseOut:
|
2007-04-23 11:31:21 +04:00
|
|
|
aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
|
2015-11-26 10:26:32 +03:00
|
|
|
MOZ_FALLTHROUGH;
|
2015-09-02 09:08:00 +03:00
|
|
|
case eBlur:
|
2007-04-23 11:31:21 +04:00
|
|
|
rv = LeaveLink(aVisitor.mPresContext);
|
2010-12-27 23:42:10 +03:00
|
|
|
if (NS_SUCCEEDED(rv)) {
|
2012-12-16 05:26:04 +04:00
|
|
|
aVisitor.mEvent->mFlags.mMultipleActionsPrevented = true;
|
2010-12-27 23:42:10 +03:00
|
|
|
}
|
2007-04-23 11:31:21 +04:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
// switch not in sync with the optimization switch earlier in this function
|
|
|
|
NS_NOTREACHED("switch statements not in sync");
|
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
2014-03-18 08:48:20 +04:00
|
|
|
Element::PostHandleEventForLinks(EventChainPostVisitor& aVisitor)
|
2007-04-23 11:31:21 +04:00
|
|
|
{
|
|
|
|
// Optimisation: return early if this event doesn't interest us.
|
|
|
|
// IMPORTANT: this switch and the switch below it must be kept in sync!
|
2015-08-22 04:34:51 +03:00
|
|
|
switch (aVisitor.mEvent->mMessage) {
|
2015-08-29 02:58:30 +03:00
|
|
|
case eMouseDown:
|
2015-08-29 02:58:32 +03:00
|
|
|
case eMouseClick:
|
2015-09-02 09:08:01 +03:00
|
|
|
case eLegacyDOMActivate:
|
2015-08-29 02:58:27 +03:00
|
|
|
case eKeyPress:
|
2007-04-23 11:31:21 +04:00
|
|
|
break;
|
|
|
|
default:
|
2007-01-04 13:53:59 +03:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2007-04-23 11:31:21 +04:00
|
|
|
// Make sure we meet the preconditions before continuing
|
2007-01-04 13:53:59 +03:00
|
|
|
nsCOMPtr<nsIURI> absURI;
|
2007-04-23 11:31:21 +04:00
|
|
|
if (!CheckHandleEventForLinksPrecondition(aVisitor, getter_AddRefs(absURI))) {
|
2007-01-04 13:53:59 +03:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult rv = NS_OK;
|
|
|
|
|
2015-08-22 04:34:51 +03:00
|
|
|
switch (aVisitor.mEvent->mMessage) {
|
2015-08-29 02:58:30 +03:00
|
|
|
case eMouseDown:
|
2007-01-04 13:53:59 +03:00
|
|
|
{
|
2013-10-22 12:55:20 +04:00
|
|
|
if (aVisitor.mEvent->AsMouseEvent()->button ==
|
2013-10-02 10:38:27 +04:00
|
|
|
WidgetMouseEvent::eLeftButton) {
|
2007-01-04 13:53:59 +03:00
|
|
|
// don't make the link grab the focus if there is no link handler
|
|
|
|
nsILinkHandler *handler = aVisitor.mPresContext->GetLinkHandler();
|
2014-10-02 22:45:44 +04:00
|
|
|
nsIDocument *document = GetComposedDoc();
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
if (handler && document) {
|
|
|
|
nsIFocusManager* fm = nsFocusManager::GetFocusManager();
|
|
|
|
if (fm) {
|
2012-12-16 05:26:04 +04:00
|
|
|
aVisitor.mEvent->mFlags.mMultipleActionsPrevented = true;
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(this);
|
2009-09-21 19:58:16 +04:00
|
|
|
fm->SetFocus(elem, nsIFocusManager::FLAG_BYMOUSE |
|
|
|
|
nsIFocusManager::FLAG_NOSCROLL);
|
2007-01-04 13:53:59 +03:00
|
|
|
}
|
Bug 178324, refactor focus by moving all focus handling into one place and simplifying it, add many tests, fixes many other bugs too numerous to mention in this small checkin comment, r=josh,smichaud,ere,dbaron,marco,neil,gavin,smaug,sr=smaug (CLOSED TREE)
2009-06-10 22:00:39 +04:00
|
|
|
|
2014-04-01 08:09:23 +04:00
|
|
|
EventStateManager::SetActiveManager(
|
2011-04-21 21:35:52 +04:00
|
|
|
aVisitor.mPresContext->EventStateManager(), this);
|
2007-01-04 13:53:59 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2015-08-29 02:58:32 +03:00
|
|
|
case eMouseClick: {
|
2013-10-28 13:03:19 +04:00
|
|
|
WidgetMouseEvent* mouseEvent = aVisitor.mEvent->AsMouseEvent();
|
|
|
|
if (mouseEvent->IsLeftClickEvent()) {
|
|
|
|
if (mouseEvent->IsControl() || mouseEvent->IsMeta() ||
|
|
|
|
mouseEvent->IsAlt() ||mouseEvent->IsShift()) {
|
2009-10-13 21:23:48 +04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2007-01-04 13:53:59 +03:00
|
|
|
// The default action is simply to dispatch DOMActivate
|
2007-03-26 09:38:22 +04:00
|
|
|
nsCOMPtr<nsIPresShell> shell = aVisitor.mPresContext->GetPresShell();
|
2007-01-04 13:53:59 +03:00
|
|
|
if (shell) {
|
|
|
|
// single-click
|
|
|
|
nsEventStatus status = nsEventStatus_eIgnore;
|
2015-08-22 07:02:39 +03:00
|
|
|
// DOMActive event should be trusted since the activation is actually
|
|
|
|
// occurred even if the cause is an untrusted click event.
|
2015-09-02 09:08:01 +03:00
|
|
|
InternalUIEvent actEvent(true, eLegacyDOMActivate, mouseEvent);
|
2016-03-26 10:22:27 +03:00
|
|
|
actEvent.mDetail = 1;
|
2007-01-04 13:53:59 +03:00
|
|
|
|
|
|
|
rv = shell->HandleDOMEventWithTarget(this, &actEvent, &status);
|
2010-12-27 23:42:10 +03:00
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
|
|
|
|
}
|
2007-01-04 13:53:59 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
2013-10-28 13:03:19 +04:00
|
|
|
}
|
2015-09-02 09:08:01 +03:00
|
|
|
case eLegacyDOMActivate:
|
2007-01-04 13:53:59 +03:00
|
|
|
{
|
2016-04-18 19:33:23 +03:00
|
|
|
if (aVisitor.mEvent->mOriginalTarget == this) {
|
2010-12-27 23:42:10 +03:00
|
|
|
nsAutoString target;
|
|
|
|
GetLinkTarget(target);
|
2015-08-22 07:02:39 +03:00
|
|
|
const InternalUIEvent* activeEvent = aVisitor.mEvent->AsUIEvent();
|
|
|
|
MOZ_ASSERT(activeEvent);
|
2010-12-27 23:42:10 +03:00
|
|
|
nsContentUtils::TriggerLink(this, aVisitor.mPresContext, absURI, target,
|
2015-08-22 07:02:39 +03:00
|
|
|
true, true, activeEvent->IsTrustable());
|
2010-12-27 23:42:10 +03:00
|
|
|
aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
|
|
|
|
}
|
2007-01-04 13:53:59 +03:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2015-08-29 02:58:27 +03:00
|
|
|
case eKeyPress:
|
2007-01-04 13:53:59 +03:00
|
|
|
{
|
2013-10-18 10:10:24 +04:00
|
|
|
WidgetKeyboardEvent* keyEvent = aVisitor.mEvent->AsKeyboardEvent();
|
2016-05-12 11:13:49 +03:00
|
|
|
if (keyEvent && keyEvent->mKeyCode == NS_VK_RETURN) {
|
2013-10-18 10:10:24 +04:00
|
|
|
nsEventStatus status = nsEventStatus_eIgnore;
|
|
|
|
rv = DispatchClickEvent(aVisitor.mPresContext, keyEvent, this,
|
|
|
|
false, nullptr, &status);
|
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
aVisitor.mEventStatus = nsEventStatus_eConsumeNoDefault;
|
2007-01-04 13:53:59 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
// switch not in sync with the optimization switch earlier in this function
|
|
|
|
NS_NOTREACHED("switch statements not in sync");
|
|
|
|
return NS_ERROR_UNEXPECTED;
|
|
|
|
}
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2012-11-15 02:10:08 +04:00
|
|
|
Element::GetLinkTarget(nsAString& aTarget)
|
2007-01-04 13:53:59 +03:00
|
|
|
{
|
|
|
|
aTarget.Truncate();
|
|
|
|
}
|
|
|
|
|
2014-02-18 05:12:54 +04:00
|
|
|
static void
|
2016-02-12 01:50:42 +03:00
|
|
|
nsDOMTokenListPropertyDestructor(void *aObject, nsIAtom *aProperty,
|
|
|
|
void *aPropertyValue, void *aData)
|
2014-02-18 05:12:54 +04:00
|
|
|
{
|
2016-02-12 01:50:42 +03:00
|
|
|
nsDOMTokenList* list =
|
|
|
|
static_cast<nsDOMTokenList*>(aPropertyValue);
|
2014-02-18 05:12:54 +04:00
|
|
|
NS_RELEASE(list);
|
|
|
|
}
|
|
|
|
|
|
|
|
static nsIAtom** sPropertiesToTraverseAndUnlink[] =
|
|
|
|
{
|
|
|
|
&nsGkAtoms::sandbox,
|
|
|
|
&nsGkAtoms::sizes,
|
|
|
|
nullptr
|
|
|
|
};
|
|
|
|
|
|
|
|
// static
|
|
|
|
nsIAtom***
|
2014-05-15 13:05:42 +04:00
|
|
|
Element::HTMLSVGPropertiesToTraverseAndUnlink()
|
2014-02-18 05:12:54 +04:00
|
|
|
{
|
|
|
|
return sPropertiesToTraverseAndUnlink;
|
|
|
|
}
|
|
|
|
|
2016-02-12 01:50:42 +03:00
|
|
|
nsDOMTokenList*
|
2016-05-05 06:41:24 +03:00
|
|
|
Element::GetTokenList(nsIAtom* aAtom,
|
|
|
|
const DOMTokenListSupportedTokenArray aSupportedTokens)
|
2014-02-18 05:12:54 +04:00
|
|
|
{
|
|
|
|
#ifdef DEBUG
|
|
|
|
nsIAtom*** props =
|
2014-05-15 13:05:42 +04:00
|
|
|
HTMLSVGPropertiesToTraverseAndUnlink();
|
2014-02-18 05:12:54 +04:00
|
|
|
bool found = false;
|
|
|
|
for (uint32_t i = 0; props[i]; ++i) {
|
|
|
|
if (*props[i] == aAtom) {
|
|
|
|
found = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
MOZ_ASSERT(found, "Trying to use an unknown tokenlist!");
|
|
|
|
#endif
|
|
|
|
|
2016-02-12 01:50:42 +03:00
|
|
|
nsDOMTokenList* list = nullptr;
|
2014-02-18 05:12:54 +04:00
|
|
|
if (HasProperties()) {
|
2016-02-12 01:50:42 +03:00
|
|
|
list = static_cast<nsDOMTokenList*>(GetProperty(aAtom));
|
2014-02-18 05:12:54 +04:00
|
|
|
}
|
|
|
|
if (!list) {
|
2016-05-05 06:41:24 +03:00
|
|
|
list = new nsDOMTokenList(this, aAtom, aSupportedTokens);
|
2014-02-18 05:12:54 +04:00
|
|
|
NS_ADDREF(list);
|
2016-02-12 01:50:42 +03:00
|
|
|
SetProperty(aAtom, list, nsDOMTokenListPropertyDestructor);
|
2014-02-18 05:12:54 +04:00
|
|
|
}
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
2014-09-13 17:08:00 +04:00
|
|
|
Element*
|
|
|
|
Element::Closest(const nsAString& aSelector, ErrorResult& aResult)
|
|
|
|
{
|
|
|
|
nsCSSSelectorList* selectorList = ParseSelectorList(aSelector, aResult);
|
|
|
|
if (!selectorList) {
|
|
|
|
// Either we failed (and aResult already has the exception), or this
|
|
|
|
// is a pseudo-element-only selector that matches nothing.
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
OwnerDoc()->FlushPendingLinkUpdates();
|
|
|
|
TreeMatchContext matchingContext(false,
|
|
|
|
nsRuleWalker::eRelevantLinkUnvisited,
|
|
|
|
OwnerDoc(),
|
|
|
|
TreeMatchContext::eNeverMatchVisited);
|
|
|
|
matchingContext.SetHasSpecifiedScope();
|
|
|
|
matchingContext.AddScopeElement(this);
|
|
|
|
for (nsINode* node = this; node; node = node->GetParentNode()) {
|
|
|
|
if (node->IsElement() &&
|
|
|
|
nsCSSRuleProcessor::SelectorListMatches(node->AsElement(),
|
|
|
|
matchingContext,
|
|
|
|
selectorList)) {
|
|
|
|
return node->AsElement();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool
|
2014-08-02 07:37:09 +04:00
|
|
|
Element::Matches(const nsAString& aSelector, ErrorResult& aError)
|
2009-10-01 02:17:14 +04:00
|
|
|
{
|
2013-12-16 22:06:36 +04:00
|
|
|
nsCSSSelectorList* selectorList = ParseSelectorList(aSelector, aError);
|
|
|
|
if (!selectorList) {
|
|
|
|
// Either we failed (and aError already has the exception), or this
|
|
|
|
// is a pseudo-element-only selector that matches nothing.
|
2012-10-16 15:51:00 +04:00
|
|
|
return false;
|
2009-10-01 02:17:14 +04:00
|
|
|
}
|
|
|
|
|
2012-10-16 15:51:00 +04:00
|
|
|
OwnerDoc()->FlushPendingLinkUpdates();
|
|
|
|
TreeMatchContext matchingContext(false,
|
|
|
|
nsRuleWalker::eRelevantLinkUnvisited,
|
|
|
|
OwnerDoc(),
|
|
|
|
TreeMatchContext::eNeverMatchVisited);
|
2012-12-05 08:15:47 +04:00
|
|
|
matchingContext.SetHasSpecifiedScope();
|
|
|
|
matchingContext.AddScopeElement(this);
|
2012-10-16 15:51:00 +04:00
|
|
|
return nsCSSRuleProcessor::SelectorListMatches(this, matchingContext,
|
|
|
|
selectorList);
|
2010-04-19 19:41:37 +04:00
|
|
|
}
|
2011-08-27 02:39:00 +04:00
|
|
|
|
2012-03-10 20:13:51 +04:00
|
|
|
static const nsAttrValue::EnumTable kCORSAttributeTable[] = {
|
|
|
|
// Order matters here
|
|
|
|
// See ParseCORSValue
|
|
|
|
{ "anonymous", CORS_ANONYMOUS },
|
|
|
|
{ "use-credentials", CORS_USE_CREDENTIALS },
|
|
|
|
{ 0 }
|
|
|
|
};
|
|
|
|
|
|
|
|
/* static */ void
|
2012-11-15 02:10:08 +04:00
|
|
|
Element::ParseCORSValue(const nsAString& aValue,
|
|
|
|
nsAttrValue& aResult)
|
2012-03-10 20:13:51 +04:00
|
|
|
{
|
|
|
|
DebugOnly<bool> success =
|
|
|
|
aResult.ParseEnumValue(aValue, kCORSAttributeTable, false,
|
|
|
|
// default value is anonymous if aValue is
|
|
|
|
// not a value we understand
|
|
|
|
&kCORSAttributeTable[0]);
|
|
|
|
MOZ_ASSERT(success);
|
|
|
|
}
|
|
|
|
|
2012-03-10 20:13:52 +04:00
|
|
|
/* static */ CORSMode
|
2012-11-15 02:10:08 +04:00
|
|
|
Element::StringToCORSMode(const nsAString& aValue)
|
2012-03-10 20:13:52 +04:00
|
|
|
{
|
|
|
|
if (aValue.IsVoid()) {
|
|
|
|
return CORS_NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsAttrValue val;
|
2012-11-15 02:10:08 +04:00
|
|
|
Element::ParseCORSValue(aValue, val);
|
2012-03-10 20:13:52 +04:00
|
|
|
return CORSMode(val.GetEnumValue());
|
|
|
|
}
|
|
|
|
|
2012-03-10 20:13:52 +04:00
|
|
|
/* static */ CORSMode
|
2012-11-15 02:10:08 +04:00
|
|
|
Element::AttrValueToCORSMode(const nsAttrValue* aValue)
|
2012-03-10 20:13:52 +04:00
|
|
|
{
|
|
|
|
if (!aValue) {
|
|
|
|
return CORS_NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return CORSMode(aValue->GetEnumValue());
|
|
|
|
}
|
|
|
|
|
2012-05-09 01:47:18 +04:00
|
|
|
static const char*
|
|
|
|
GetFullScreenError(nsIDocument* aDoc)
|
|
|
|
{
|
2012-08-13 20:58:38 +04:00
|
|
|
if (aDoc->NodePrincipal()->GetAppStatus() >= nsIPrincipal::APP_STATUS_INSTALLED) {
|
2012-07-31 06:09:31 +04:00
|
|
|
// Request is in a web app and in the same origin as the web app.
|
|
|
|
// Don't enforce as strict security checks for web apps, the user
|
|
|
|
// is supposed to have trust in them. However documents cross-origin
|
|
|
|
// to the web app must still confirm to the normal security checks.
|
2012-07-30 18:20:58 +04:00
|
|
|
return nullptr;
|
2012-06-28 12:54:37 +04:00
|
|
|
}
|
|
|
|
|
2012-05-09 01:47:18 +04:00
|
|
|
if (!nsContentUtils::IsRequestFullScreenAllowed()) {
|
2016-02-17 03:47:11 +03:00
|
|
|
return "FullscreenDeniedNotInputDriven";
|
2012-05-09 01:47:18 +04:00
|
|
|
}
|
2012-07-31 06:09:31 +04:00
|
|
|
|
2012-07-30 18:20:58 +04:00
|
|
|
return nullptr;
|
2012-05-09 01:47:18 +04:00
|
|
|
}
|
|
|
|
|
2012-10-16 15:51:00 +04:00
|
|
|
void
|
2016-04-18 22:12:38 +03:00
|
|
|
Element::RequestFullscreen(ErrorResult& aError)
|
2012-03-24 08:37:04 +04:00
|
|
|
{
|
|
|
|
// Only grant full-screen requests if this is called from inside a trusted
|
|
|
|
// event handler (i.e. inside an event handler for a user initiated event).
|
|
|
|
// This stops the full-screen from being abused similar to the popups of old,
|
|
|
|
// and it also makes it harder for bad guys' script to go full-screen and
|
|
|
|
// spoof the browser chrome/window and phish logins etc.
|
2012-07-31 06:09:31 +04:00
|
|
|
// Note that requests for fullscreen inside a web app's origin are exempt
|
|
|
|
// from this restriction.
|
2016-02-17 03:47:11 +03:00
|
|
|
if (const char* error = GetFullScreenError(OwnerDoc())) {
|
|
|
|
OwnerDoc()->DispatchFullscreenError(error);
|
2012-10-16 15:51:00 +04:00
|
|
|
return;
|
2012-03-24 08:37:04 +04:00
|
|
|
}
|
|
|
|
|
2015-06-19 03:09:52 +03:00
|
|
|
auto request = MakeUnique<FullscreenRequest>(this);
|
|
|
|
request->mIsCallerChrome = nsContentUtils::IsCallerChrome();
|
2015-01-05 22:49:04 +03:00
|
|
|
|
2015-06-19 03:09:52 +03:00
|
|
|
OwnerDoc()->AsyncRequestFullScreen(Move(request));
|
2012-03-24 08:37:04 +04:00
|
|
|
}
|
2012-12-24 06:38:41 +04:00
|
|
|
|
2014-02-27 16:54:32 +04:00
|
|
|
void
|
2016-07-28 10:15:21 +03:00
|
|
|
Element::RequestPointerLock()
|
2014-02-27 16:54:32 +04:00
|
|
|
{
|
|
|
|
OwnerDoc()->RequestPointerLock(this);
|
|
|
|
}
|
|
|
|
|
2016-07-06 21:45:18 +03:00
|
|
|
void
|
|
|
|
Element::GetGridFragments(nsTArray<RefPtr<Grid>>& aResult)
|
|
|
|
{
|
2016-07-07 21:38:12 +03:00
|
|
|
nsGridContainerFrame* frame =
|
|
|
|
nsGridContainerFrame::GetGridFrameWithComputedInfo(GetPrimaryFrame());
|
|
|
|
|
|
|
|
// If we get a nsGridContainerFrame from the prior call,
|
|
|
|
// all the next-in-flow frames will also be nsGridContainerFrames.
|
|
|
|
while (frame) {
|
|
|
|
aResult.AppendElement(
|
|
|
|
new Grid(this, frame)
|
|
|
|
);
|
|
|
|
frame = static_cast<nsGridContainerFrame*>(frame->GetNextInFlow());
|
2016-07-06 21:45:18 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-01-29 04:37:52 +03:00
|
|
|
already_AddRefed<Animation>
|
|
|
|
Element::Animate(JSContext* aContext,
|
2016-05-13 03:40:52 +03:00
|
|
|
JS::Handle<JSObject*> aKeyframes,
|
2016-01-29 04:37:52 +03:00
|
|
|
const UnrestrictedDoubleOrKeyframeAnimationOptions& aOptions,
|
|
|
|
ErrorResult& aError)
|
|
|
|
{
|
2016-03-04 02:54:00 +03:00
|
|
|
Nullable<ElementOrCSSPseudoElement> target;
|
|
|
|
target.SetValue().SetAsElement() = this;
|
2016-05-13 03:40:52 +03:00
|
|
|
return Animate(target, aContext, aKeyframes, aOptions, aError);
|
2016-03-04 02:54:00 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/* static */ already_AddRefed<Animation>
|
|
|
|
Element::Animate(const Nullable<ElementOrCSSPseudoElement>& aTarget,
|
|
|
|
JSContext* aContext,
|
2016-05-13 03:40:52 +03:00
|
|
|
JS::Handle<JSObject*> aKeyframes,
|
2016-03-04 02:54:00 +03:00
|
|
|
const UnrestrictedDoubleOrKeyframeAnimationOptions& aOptions,
|
|
|
|
ErrorResult& aError)
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(!aTarget.IsNull() &&
|
|
|
|
(aTarget.Value().IsElement() ||
|
|
|
|
aTarget.Value().IsCSSPseudoElement()),
|
|
|
|
"aTarget should be initialized");
|
|
|
|
|
|
|
|
RefPtr<Element> referenceElement;
|
|
|
|
if (aTarget.Value().IsElement()) {
|
|
|
|
referenceElement = &aTarget.Value().GetAsElement();
|
|
|
|
} else {
|
|
|
|
referenceElement = aTarget.Value().GetAsCSSPseudoElement().ParentElement();
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIGlobalObject> ownerGlobal = referenceElement->GetOwnerGlobal();
|
2016-01-29 04:37:52 +03:00
|
|
|
if (!ownerGlobal) {
|
|
|
|
aError.Throw(NS_ERROR_FAILURE);
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
GlobalObject global(aContext, ownerGlobal->GetGlobalJSObject());
|
|
|
|
MOZ_ASSERT(!global.Failed());
|
|
|
|
|
2016-05-13 03:40:52 +03:00
|
|
|
// Wrap the aKeyframes object for the cross-compartment case.
|
|
|
|
JS::Rooted<JSObject*> keyframes(aContext);
|
|
|
|
keyframes = aKeyframes;
|
2016-01-29 04:37:52 +03:00
|
|
|
Maybe<JSAutoCompartment> ac;
|
|
|
|
if (js::GetContextCompartment(aContext) !=
|
|
|
|
js::GetObjectCompartment(ownerGlobal->GetGlobalJSObject())) {
|
|
|
|
ac.emplace(aContext, ownerGlobal->GetGlobalJSObject());
|
2016-05-13 03:40:52 +03:00
|
|
|
if (!JS_WrapObject(aContext, &keyframes)) {
|
2016-01-29 04:37:52 +03:00
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-15 03:34:47 +03:00
|
|
|
RefPtr<KeyframeEffect> effect =
|
2016-05-13 03:40:52 +03:00
|
|
|
KeyframeEffect::Constructor(global, aTarget, keyframes, aOptions, aError);
|
2016-01-29 04:37:52 +03:00
|
|
|
if (aError.Failed()) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2016-05-30 03:01:11 +03:00
|
|
|
AnimationTimeline* timeline = referenceElement->OwnerDoc()->Timeline();
|
2016-01-29 04:37:52 +03:00
|
|
|
RefPtr<Animation> animation =
|
2016-03-04 02:54:00 +03:00
|
|
|
Animation::Constructor(global, effect,
|
2016-05-30 03:01:11 +03:00
|
|
|
Optional<AnimationTimeline*>(timeline), aError);
|
2016-01-29 04:37:52 +03:00
|
|
|
if (aError.Failed()) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (aOptions.IsKeyframeAnimationOptions()) {
|
|
|
|
animation->SetId(aOptions.GetAsKeyframeAnimationOptions().mId);
|
|
|
|
}
|
|
|
|
|
|
|
|
animation->Play(aError, Animation::LimitBehavior::AutoRewind);
|
|
|
|
if (aError.Failed()) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
return animation.forget();
|
|
|
|
}
|
|
|
|
|
2014-07-16 04:02:31 +04:00
|
|
|
void
|
2016-03-22 03:33:02 +03:00
|
|
|
Element::GetAnimations(const AnimationFilter& filter,
|
|
|
|
nsTArray<RefPtr<Animation>>& aAnimations)
|
2014-07-16 04:02:31 +04:00
|
|
|
{
|
2014-10-02 10:14:13 +04:00
|
|
|
nsIDocument* doc = GetComposedDoc();
|
|
|
|
if (doc) {
|
|
|
|
doc->FlushPendingNotifications(Flush_Style);
|
|
|
|
}
|
|
|
|
|
2016-03-11 05:50:00 +03:00
|
|
|
Element* elem = this;
|
|
|
|
CSSPseudoElementType pseudoType = CSSPseudoElementType::NotPseudo;
|
|
|
|
// For animations on generated-content elements, the animations are stored
|
|
|
|
// on the parent element.
|
|
|
|
nsIAtom* name = NodeInfo()->NameAtom();
|
|
|
|
if (name == nsGkAtoms::mozgeneratedcontentbefore) {
|
|
|
|
elem = GetParentElement();
|
|
|
|
pseudoType = CSSPseudoElementType::before;
|
|
|
|
} else if (name == nsGkAtoms::mozgeneratedcontentafter) {
|
|
|
|
elem = GetParentElement();
|
|
|
|
pseudoType = CSSPseudoElementType::after;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!elem) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-03-22 03:33:02 +03:00
|
|
|
if (!filter.mSubtree ||
|
|
|
|
pseudoType == CSSPseudoElementType::before ||
|
|
|
|
pseudoType == CSSPseudoElementType::after) {
|
|
|
|
GetAnimationsUnsorted(elem, pseudoType, aAnimations);
|
|
|
|
} else {
|
|
|
|
for (nsIContent* node = this;
|
|
|
|
node;
|
|
|
|
node = node->GetNextNode(this)) {
|
|
|
|
if (!node->IsElement()) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
Element* element = node->AsElement();
|
|
|
|
Element::GetAnimationsUnsorted(element, CSSPseudoElementType::NotPseudo,
|
|
|
|
aAnimations);
|
|
|
|
Element::GetAnimationsUnsorted(element, CSSPseudoElementType::before,
|
|
|
|
aAnimations);
|
|
|
|
Element::GetAnimationsUnsorted(element, CSSPseudoElementType::after,
|
|
|
|
aAnimations);
|
|
|
|
}
|
|
|
|
}
|
2016-01-06 22:21:00 +03:00
|
|
|
aAnimations.Sort(AnimationPtrComparator<RefPtr<Animation>>());
|
|
|
|
}
|
|
|
|
|
2016-02-18 04:21:00 +03:00
|
|
|
/* static */ void
|
|
|
|
Element::GetAnimationsUnsorted(Element* aElement,
|
|
|
|
CSSPseudoElementType aPseudoType,
|
|
|
|
nsTArray<RefPtr<Animation>>& aAnimations)
|
2016-01-06 22:21:00 +03:00
|
|
|
{
|
2016-02-18 04:21:00 +03:00
|
|
|
MOZ_ASSERT(aPseudoType == CSSPseudoElementType::NotPseudo ||
|
|
|
|
aPseudoType == CSSPseudoElementType::after ||
|
|
|
|
aPseudoType == CSSPseudoElementType::before,
|
|
|
|
"Unsupported pseudo type");
|
2016-03-11 05:50:00 +03:00
|
|
|
MOZ_ASSERT(aElement, "Null element");
|
2016-02-18 04:21:00 +03:00
|
|
|
|
|
|
|
EffectSet* effects = EffectSet::GetEffectSet(aElement, aPseudoType);
|
2015-11-26 10:53:53 +03:00
|
|
|
if (!effects) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (KeyframeEffectReadOnly* effect : *effects) {
|
|
|
|
MOZ_ASSERT(effect && effect->GetAnimation(),
|
|
|
|
"Only effects associated with an animation should be "
|
|
|
|
"added to an element's effect set");
|
|
|
|
Animation* animation = effect->GetAnimation();
|
|
|
|
|
|
|
|
MOZ_ASSERT(animation->IsRelevant(),
|
|
|
|
"Only relevant animations should be added to an element's "
|
|
|
|
"effect set");
|
|
|
|
aAnimations.AppendElement(animation);
|
2014-07-16 04:02:31 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-10-08 23:25:01 +04:00
|
|
|
NS_IMETHODIMP
|
|
|
|
Element::GetInnerHTML(nsAString& aInnerHTML)
|
2012-12-24 06:38:41 +04:00
|
|
|
{
|
2013-10-08 23:25:01 +04:00
|
|
|
GetMarkup(false, aInnerHTML);
|
|
|
|
return NS_OK;
|
2012-12-24 06:38:41 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Element::SetInnerHTML(const nsAString& aInnerHTML, ErrorResult& aError)
|
|
|
|
{
|
2013-12-02 14:26:12 +04:00
|
|
|
SetInnerHTMLInternal(aInnerHTML, aError);
|
2012-12-24 06:38:41 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2013-10-08 23:25:01 +04:00
|
|
|
Element::GetOuterHTML(nsAString& aOuterHTML)
|
2012-12-24 06:38:41 +04:00
|
|
|
{
|
2013-10-08 23:25:01 +04:00
|
|
|
GetMarkup(true, aOuterHTML);
|
2012-12-24 06:38:41 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Element::SetOuterHTML(const nsAString& aOuterHTML, ErrorResult& aError)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsINode> parent = GetParentNode();
|
|
|
|
if (!parent) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (parent->NodeType() == nsIDOMNode::DOCUMENT_NODE) {
|
|
|
|
aError.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-03-03 14:08:59 +03:00
|
|
|
if (OwnerDoc()->IsHTMLDocument()) {
|
2012-12-24 06:38:41 +04:00
|
|
|
nsIAtom* localName;
|
|
|
|
int32_t namespaceID;
|
|
|
|
if (parent->IsElement()) {
|
2015-03-03 14:09:00 +03:00
|
|
|
localName = parent->NodeInfo()->NameAtom();
|
|
|
|
namespaceID = parent->NodeInfo()->NamespaceID();
|
2012-12-24 06:38:41 +04:00
|
|
|
} else {
|
|
|
|
NS_ASSERTION(parent->NodeType() == nsIDOMNode::DOCUMENT_FRAGMENT_NODE,
|
|
|
|
"How come the parent isn't a document, a fragment or an element?");
|
|
|
|
localName = nsGkAtoms::body;
|
|
|
|
namespaceID = kNameSpaceID_XHTML;
|
|
|
|
}
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<DocumentFragment> fragment =
|
2013-04-10 18:15:54 +04:00
|
|
|
new DocumentFragment(OwnerDoc()->NodeInfoManager());
|
2012-12-24 06:38:41 +04:00
|
|
|
nsContentUtils::ParseFragmentHTML(aOuterHTML,
|
|
|
|
fragment,
|
|
|
|
localName,
|
|
|
|
namespaceID,
|
|
|
|
OwnerDoc()->GetCompatibilityMode() ==
|
|
|
|
eCompatibility_NavQuirks,
|
|
|
|
true);
|
|
|
|
parent->ReplaceChild(*fragment, *this, aError);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsINode> context;
|
|
|
|
if (parent->IsElement()) {
|
|
|
|
context = parent;
|
|
|
|
} else {
|
|
|
|
NS_ASSERTION(parent->NodeType() == nsIDOMNode::DOCUMENT_FRAGMENT_NODE,
|
|
|
|
"How come the parent isn't a document, a fragment or an element?");
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<mozilla::dom::NodeInfo> info =
|
2012-12-24 06:38:41 +04:00
|
|
|
OwnerDoc()->NodeInfoManager()->GetNodeInfo(nsGkAtoms::body,
|
|
|
|
nullptr,
|
|
|
|
kNameSpaceID_XHTML,
|
|
|
|
nsIDOMNode::ELEMENT_NODE);
|
|
|
|
context = NS_NewHTMLBodyElement(info.forget(), FROM_PARSER_FRAGMENT);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMDocumentFragment> df;
|
|
|
|
aError = nsContentUtils::CreateContextualFragment(context,
|
|
|
|
aOuterHTML,
|
|
|
|
true,
|
|
|
|
getter_AddRefs(df));
|
|
|
|
if (aError.Failed()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
nsCOMPtr<nsINode> fragment = do_QueryInterface(df);
|
|
|
|
parent->ReplaceChild(*fragment, *this, aError);
|
|
|
|
}
|
|
|
|
|
|
|
|
enum nsAdjacentPosition {
|
|
|
|
eBeforeBegin,
|
|
|
|
eAfterBegin,
|
|
|
|
eBeforeEnd,
|
|
|
|
eAfterEnd
|
|
|
|
};
|
|
|
|
|
|
|
|
void
|
|
|
|
Element::InsertAdjacentHTML(const nsAString& aPosition, const nsAString& aText,
|
|
|
|
ErrorResult& aError)
|
|
|
|
{
|
|
|
|
nsAdjacentPosition position;
|
|
|
|
if (aPosition.LowerCaseEqualsLiteral("beforebegin")) {
|
|
|
|
position = eBeforeBegin;
|
|
|
|
} else if (aPosition.LowerCaseEqualsLiteral("afterbegin")) {
|
|
|
|
position = eAfterBegin;
|
|
|
|
} else if (aPosition.LowerCaseEqualsLiteral("beforeend")) {
|
|
|
|
position = eBeforeEnd;
|
|
|
|
} else if (aPosition.LowerCaseEqualsLiteral("afterend")) {
|
|
|
|
position = eAfterEnd;
|
|
|
|
} else {
|
|
|
|
aError.Throw(NS_ERROR_DOM_SYNTAX_ERR);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIContent> destination;
|
|
|
|
if (position == eBeforeBegin || position == eAfterEnd) {
|
|
|
|
destination = GetParent();
|
|
|
|
if (!destination) {
|
|
|
|
aError.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
destination = this;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsIDocument* doc = OwnerDoc();
|
|
|
|
|
|
|
|
// Needed when insertAdjacentHTML is used in combination with contenteditable
|
|
|
|
mozAutoDocUpdate updateBatch(doc, UPDATE_CONTENT_MODEL, true);
|
|
|
|
nsAutoScriptLoaderDisabler sld(doc);
|
2016-02-15 03:34:47 +03:00
|
|
|
|
2012-12-24 06:38:41 +04:00
|
|
|
// Batch possible DOMSubtreeModified events.
|
|
|
|
mozAutoSubtreeModified subtree(doc, nullptr);
|
|
|
|
|
|
|
|
// Parse directly into destination if possible
|
2015-03-03 14:08:59 +03:00
|
|
|
if (doc->IsHTMLDocument() && !OwnerDoc()->MayHaveDOMMutationObservers() &&
|
2012-12-24 06:38:41 +04:00
|
|
|
(position == eBeforeEnd ||
|
|
|
|
(position == eAfterEnd && !GetNextSibling()) ||
|
|
|
|
(position == eAfterBegin && !GetFirstChild()))) {
|
|
|
|
int32_t oldChildCount = destination->GetChildCount();
|
|
|
|
int32_t contextNs = destination->GetNameSpaceID();
|
2015-03-03 14:09:00 +03:00
|
|
|
nsIAtom* contextLocal = destination->NodeInfo()->NameAtom();
|
2012-12-24 06:38:41 +04:00
|
|
|
if (contextLocal == nsGkAtoms::html && contextNs == kNameSpaceID_XHTML) {
|
|
|
|
// For compat with IE6 through IE9. Willful violation of HTML5 as of
|
|
|
|
// 2011-04-06. CreateContextualFragment does the same already.
|
|
|
|
// Spec bug: http://www.w3.org/Bugs/Public/show_bug.cgi?id=12434
|
|
|
|
contextLocal = nsGkAtoms::body;
|
|
|
|
}
|
|
|
|
aError = nsContentUtils::ParseFragmentHTML(aText,
|
|
|
|
destination,
|
|
|
|
contextLocal,
|
|
|
|
contextNs,
|
|
|
|
doc->GetCompatibilityMode() ==
|
|
|
|
eCompatibility_NavQuirks,
|
|
|
|
true);
|
|
|
|
// HTML5 parser has notified, but not fired mutation events.
|
2013-12-02 14:26:12 +04:00
|
|
|
nsContentUtils::FireMutationEventsForDirectParsing(doc, destination,
|
|
|
|
oldChildCount);
|
2012-12-24 06:38:41 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// couldn't parse directly
|
|
|
|
nsCOMPtr<nsIDOMDocumentFragment> df;
|
|
|
|
aError = nsContentUtils::CreateContextualFragment(destination,
|
|
|
|
aText,
|
|
|
|
true,
|
|
|
|
getter_AddRefs(df));
|
|
|
|
if (aError.Failed()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsINode> fragment = do_QueryInterface(df);
|
|
|
|
|
|
|
|
// Suppress assertion about node removal mutation events that can't have
|
|
|
|
// listeners anyway, because no one has had the chance to register mutation
|
|
|
|
// listeners on the fragment that comes from the parser.
|
|
|
|
nsAutoScriptBlockerSuppressNodeRemoved scriptBlocker;
|
|
|
|
|
|
|
|
nsAutoMutationBatch mb(destination, true, false);
|
|
|
|
switch (position) {
|
|
|
|
case eBeforeBegin:
|
|
|
|
destination->InsertBefore(*fragment, this, aError);
|
|
|
|
break;
|
|
|
|
case eAfterBegin:
|
|
|
|
static_cast<nsINode*>(this)->InsertBefore(*fragment, GetFirstChild(),
|
|
|
|
aError);
|
|
|
|
break;
|
|
|
|
case eBeforeEnd:
|
|
|
|
static_cast<nsINode*>(this)->AppendChild(*fragment, aError);
|
|
|
|
break;
|
|
|
|
case eAfterEnd:
|
|
|
|
destination->InsertBefore(*fragment, GetNextSibling(), aError);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-28 11:42:57 +03:00
|
|
|
nsINode*
|
|
|
|
Element::InsertAdjacent(const nsAString& aWhere,
|
|
|
|
nsINode* aNode,
|
|
|
|
ErrorResult& aError)
|
|
|
|
{
|
|
|
|
if (aWhere.LowerCaseEqualsLiteral("beforebegin")) {
|
|
|
|
nsCOMPtr<nsINode> parent = GetParentNode();
|
|
|
|
if (!parent) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
parent->InsertBefore(*aNode, this, aError);
|
|
|
|
} else if (aWhere.LowerCaseEqualsLiteral("afterbegin")) {
|
|
|
|
static_cast<nsINode*>(this)->InsertBefore(*aNode, GetFirstChild(), aError);
|
|
|
|
} else if (aWhere.LowerCaseEqualsLiteral("beforeend")) {
|
|
|
|
static_cast<nsINode*>(this)->AppendChild(*aNode, aError);
|
|
|
|
} else if (aWhere.LowerCaseEqualsLiteral("afterend")) {
|
|
|
|
nsCOMPtr<nsINode> parent = GetParentNode();
|
|
|
|
if (!parent) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
parent->InsertBefore(*aNode, GetNextSibling(), aError);
|
|
|
|
} else {
|
|
|
|
aError.Throw(NS_ERROR_DOM_SYNTAX_ERR);
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
return aError.Failed() ? nullptr : aNode;
|
|
|
|
}
|
|
|
|
|
|
|
|
Element*
|
|
|
|
Element::InsertAdjacentElement(const nsAString& aWhere,
|
|
|
|
Element& aElement,
|
|
|
|
ErrorResult& aError) {
|
|
|
|
nsINode* newNode = InsertAdjacent(aWhere, &aElement, aError);
|
|
|
|
MOZ_ASSERT(!newNode || newNode->IsElement());
|
|
|
|
|
|
|
|
return newNode ? newNode->AsElement() : nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Element::InsertAdjacentText(
|
|
|
|
const nsAString& aWhere, const nsAString& aData, ErrorResult& aError)
|
|
|
|
{
|
|
|
|
RefPtr<nsTextNode> textNode = OwnerDoc()->CreateTextNode(aData);
|
|
|
|
InsertAdjacent(aWhere, textNode, aError);
|
|
|
|
}
|
|
|
|
|
2012-12-24 06:38:41 +04:00
|
|
|
nsIEditor*
|
|
|
|
Element::GetEditorInternal()
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsITextControlElement> textCtrl = do_QueryInterface(this);
|
|
|
|
return textCtrl ? textCtrl->GetTextEditor() : nullptr;
|
|
|
|
}
|
2013-01-09 03:25:48 +04:00
|
|
|
|
|
|
|
nsresult
|
|
|
|
Element::SetBoolAttr(nsIAtom* aAttr, bool aValue)
|
|
|
|
{
|
|
|
|
if (aValue) {
|
|
|
|
return SetAttr(kNameSpaceID_None, aAttr, EmptyString(), true);
|
|
|
|
}
|
|
|
|
|
|
|
|
return UnsetAttr(kNameSpaceID_None, aAttr, true);
|
|
|
|
}
|
2013-07-02 18:04:27 +04:00
|
|
|
|
2014-09-06 06:42:32 +04:00
|
|
|
void
|
|
|
|
Element::GetEnumAttr(nsIAtom* aAttr,
|
|
|
|
const char* aDefault,
|
|
|
|
nsAString& aResult) const
|
|
|
|
{
|
|
|
|
GetEnumAttr(aAttr, aDefault, aDefault, aResult);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Element::GetEnumAttr(nsIAtom* aAttr,
|
|
|
|
const char* aDefaultMissing,
|
|
|
|
const char* aDefaultInvalid,
|
|
|
|
nsAString& aResult) const
|
|
|
|
{
|
|
|
|
const nsAttrValue* attrVal = mAttrsAndChildren.GetAttr(aAttr);
|
|
|
|
|
|
|
|
aResult.Truncate();
|
|
|
|
|
|
|
|
if (!attrVal) {
|
|
|
|
if (aDefaultMissing) {
|
|
|
|
AppendASCIItoUTF16(nsDependentCString(aDefaultMissing), aResult);
|
2014-09-06 06:42:33 +04:00
|
|
|
} else {
|
|
|
|
SetDOMStringToNull(aResult);
|
2014-09-06 06:42:32 +04:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (attrVal->Type() == nsAttrValue::eEnum) {
|
|
|
|
attrVal->GetEnumString(aResult, true);
|
|
|
|
} else if (aDefaultInvalid) {
|
|
|
|
AppendASCIItoUTF16(nsDependentCString(aDefaultInvalid), aResult);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-06 06:42:33 +04:00
|
|
|
void
|
|
|
|
Element::SetOrRemoveNullableStringAttr(nsIAtom* aName, const nsAString& aValue,
|
|
|
|
ErrorResult& aError)
|
|
|
|
{
|
|
|
|
if (DOMStringIsNull(aValue)) {
|
|
|
|
UnsetAttr(aName, aError);
|
|
|
|
} else {
|
|
|
|
SetAttr(aName, aValue, aError);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-13 15:21:05 +04:00
|
|
|
Directionality
|
|
|
|
Element::GetComputedDirectionality() const
|
|
|
|
{
|
|
|
|
nsIFrame* frame = GetPrimaryFrame();
|
|
|
|
if (frame) {
|
|
|
|
return frame->StyleVisibility()->mDirection == NS_STYLE_DIRECTION_LTR
|
|
|
|
? eDir_LTR : eDir_RTL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return GetDirectionality();
|
|
|
|
}
|
|
|
|
|
2013-07-02 18:04:27 +04:00
|
|
|
float
|
|
|
|
Element::FontSizeInflation()
|
|
|
|
{
|
2013-07-10 23:47:50 +04:00
|
|
|
nsIFrame* frame = GetPrimaryFrame();
|
2013-07-02 18:04:27 +04:00
|
|
|
if (!frame) {
|
|
|
|
return -1.0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (nsLayoutUtils::FontSizeInflationEnabled(frame->PresContext())) {
|
|
|
|
return nsLayoutUtils::FontSizeInflationFor(frame);
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1.0;
|
|
|
|
}
|
2015-07-14 04:04:42 +03:00
|
|
|
|
|
|
|
net::ReferrerPolicy
|
2015-12-01 03:13:03 +03:00
|
|
|
Element::GetReferrerPolicyAsEnum()
|
2015-07-14 04:04:42 +03:00
|
|
|
{
|
2015-12-02 13:12:12 +03:00
|
|
|
if (Preferences::GetBool("network.http.enablePerElementReferrer", true) &&
|
2015-07-14 04:04:42 +03:00
|
|
|
IsHTMLElement()) {
|
2015-12-01 03:13:03 +03:00
|
|
|
const nsAttrValue* referrerValue = GetParsedAttr(nsGkAtoms::referrerpolicy);
|
2015-07-14 04:04:42 +03:00
|
|
|
if (referrerValue && referrerValue->Type() == nsAttrValue::eEnum) {
|
|
|
|
return net::ReferrerPolicy(referrerValue->GetEnumValue());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return net::RP_Unset;
|
2015-08-01 08:14:06 +03:00
|
|
|
}
|
2016-08-11 23:56:34 +03:00
|
|
|
|
|
|
|
already_AddRefed<nsDOMStringMap>
|
|
|
|
Element::Dataset()
|
|
|
|
{
|
|
|
|
nsDOMSlots *slots = DOMSlots();
|
|
|
|
|
|
|
|
if (!slots->mDataset) {
|
|
|
|
// mDataset is a weak reference so assignment will not AddRef.
|
|
|
|
// AddRef is called before returning the pointer.
|
|
|
|
slots->mDataset = new nsDOMStringMap(this);
|
|
|
|
}
|
|
|
|
|
|
|
|
RefPtr<nsDOMStringMap> ret = slots->mDataset;
|
|
|
|
return ret.forget();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
Element::ClearDataset()
|
|
|
|
{
|
|
|
|
nsDOMSlots *slots = GetExistingDOMSlots();
|
|
|
|
|
|
|
|
MOZ_ASSERT(slots && slots->mDataset,
|
|
|
|
"Slots should exist and dataset should not be null.");
|
|
|
|
slots->mDataset = nullptr;
|
|
|
|
}
|
|
|
|
|