Files
tubestation/dom/html/HTMLOutputElement.cpp
Nathan Froyd f93834868a Bug 1492894 - part 1 - make the node hierarchy consistently constructed with NodeInfo&&; r=mccr8
Various places in dom/ use the pattern:

  already_AddRefed<NodeInfo> ni = ...;

which is supposed to be disallowed by our static analysis code, but
isn't, for whatever reason.  To fix our static analysis code, we need to
eliminate instances of the above pattern.

Unfortunately, eliminating this pattern requires restructuring how Nodes
are created.  Most Node subclasses take `already_AddRefed<NodeInfo>&` in
their constructors, and a few accept `already_AddRefed<NodeInfo>&&`.  We
need to enforce the latter pattern consistently, which requires changing
dozens of source files.
2018-09-21 16:45:49 -04:00

210 lines
5.9 KiB
C++

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/dom/HTMLOutputElement.h"
#include "mozAutoDocUpdate.h"
#include "mozilla/EventStates.h"
#include "mozilla/dom/HTMLFormElement.h"
#include "mozilla/dom/HTMLFormSubmission.h"
#include "mozilla/dom/HTMLOutputElementBinding.h"
#include "nsContentUtils.h"
#include "nsDOMTokenList.h"
NS_IMPL_NS_NEW_HTML_ELEMENT_CHECK_PARSER(Output)
namespace mozilla {
namespace dom {
HTMLOutputElement::HTMLOutputElement(already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo,
FromParser aFromParser)
: nsGenericHTMLFormElement(std::move(aNodeInfo), NS_FORM_OUTPUT)
, mValueModeFlag(eModeDefault)
, mIsDoneAddingChildren(!aFromParser)
{
AddMutationObserver(this);
// We start out valid and ui-valid (since we have no form).
AddStatesSilently(NS_EVENT_STATE_VALID | NS_EVENT_STATE_MOZ_UI_VALID);
}
HTMLOutputElement::~HTMLOutputElement()
{
}
NS_IMPL_CYCLE_COLLECTION_INHERITED(HTMLOutputElement,
nsGenericHTMLFormElement,
mValidity,
mTokenList)
NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED(HTMLOutputElement,
nsGenericHTMLFormElement,
nsIMutationObserver,
nsIConstraintValidation)
NS_IMPL_ELEMENT_CLONE(HTMLOutputElement)
void
HTMLOutputElement::SetCustomValidity(const nsAString& aError)
{
nsIConstraintValidation::SetCustomValidity(aError);
UpdateState(true);
}
NS_IMETHODIMP
HTMLOutputElement::Reset()
{
mValueModeFlag = eModeDefault;
return nsContentUtils::SetNodeTextContent(this, mDefaultValue, true);
}
NS_IMETHODIMP
HTMLOutputElement::SubmitNamesValues(HTMLFormSubmission* aFormSubmission)
{
// The output element is not submittable.
return NS_OK;
}
bool
HTMLOutputElement::ParseAttribute(int32_t aNamespaceID,
nsAtom* aAttribute,
const nsAString& aValue,
nsIPrincipal* aMaybeScriptedPrincipal,
nsAttrValue& aResult)
{
if (aNamespaceID == kNameSpaceID_None) {
if (aAttribute == nsGkAtoms::_for) {
aResult.ParseAtomArray(aValue);
return true;
}
}
return nsGenericHTMLFormElement::ParseAttribute(aNamespaceID, aAttribute,
aValue,
aMaybeScriptedPrincipal,
aResult);
}
void
HTMLOutputElement::DoneAddingChildren(bool aHaveNotified)
{
mIsDoneAddingChildren = true;
}
EventStates
HTMLOutputElement::IntrinsicState() const
{
EventStates states = nsGenericHTMLFormElement::IntrinsicState();
// We don't have to call IsCandidateForConstraintValidation()
// because <output> can't be barred from constraint validation.
if (IsValid()) {
states |= NS_EVENT_STATE_VALID;
if (!mForm || !mForm->HasAttr(kNameSpaceID_None, nsGkAtoms::novalidate)) {
states |= NS_EVENT_STATE_MOZ_UI_VALID;
}
} else {
states |= NS_EVENT_STATE_INVALID;
if (!mForm || !mForm->HasAttr(kNameSpaceID_None, nsGkAtoms::novalidate)) {
states |= NS_EVENT_STATE_MOZ_UI_INVALID;
}
}
return states;
}
nsresult
HTMLOutputElement::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
nsIContent* aBindingParent)
{
nsresult rv = nsGenericHTMLFormElement::BindToTree(aDocument, aParent,
aBindingParent);
NS_ENSURE_SUCCESS(rv, rv);
// Unfortunately, we can actually end up having to change our state
// as a result of being bound to a tree even from the parser: we
// might end up a in a novalidate form, and unlike other form
// controls that on its own is enough to make change ui-valid state.
// So just go ahead and update our state now.
UpdateState(false);
return rv;
}
void
HTMLOutputElement::GetValue(nsAString& aValue)
{
nsContentUtils::GetNodeTextContent(this, true, aValue);
}
void
HTMLOutputElement::SetValue(const nsAString& aValue, ErrorResult& aRv)
{
mValueModeFlag = eModeValue;
aRv = nsContentUtils::SetNodeTextContent(this, aValue, true);
}
void
HTMLOutputElement::SetDefaultValue(const nsAString& aDefaultValue, ErrorResult& aRv)
{
mDefaultValue = aDefaultValue;
if (mValueModeFlag == eModeDefault) {
// We can't pass mDefaultValue, because it'll be truncated when
// the element's descendants are changed.
aRv = nsContentUtils::SetNodeTextContent(this, aDefaultValue, true);
}
}
nsDOMTokenList*
HTMLOutputElement::HtmlFor()
{
if (!mTokenList) {
mTokenList = new nsDOMTokenList(this, nsGkAtoms::_for);
}
return mTokenList;
}
void HTMLOutputElement::DescendantsChanged()
{
if (mIsDoneAddingChildren && mValueModeFlag == eModeDefault) {
nsContentUtils::GetNodeTextContent(this, true, mDefaultValue);
}
}
// nsIMutationObserver
void HTMLOutputElement::CharacterDataChanged(nsIContent* aContent,
const CharacterDataChangeInfo&)
{
DescendantsChanged();
}
void HTMLOutputElement::ContentAppended(nsIContent* aFirstNewContent)
{
DescendantsChanged();
}
void HTMLOutputElement::ContentInserted(nsIContent* aChild)
{
DescendantsChanged();
}
void HTMLOutputElement::ContentRemoved(nsIContent* aChild,
nsIContent* aPreviousSibling)
{
DescendantsChanged();
}
JSObject*
HTMLOutputElement::WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
{
return HTMLOutputElement_Binding::Wrap(aCx, this, aGivenProto);
}
} // namespace dom
} // namespace mozilla