/* -*- 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/. */
/* * Base class for DOM Core's Comment, DocumentType, Text, * CDATASection and ProcessingInstruction nodes.
*/
CharacterData::~CharacterData() {
MOZ_ASSERT(!IsInUncomposedDoc(), "Please remove this from the document properly"); if (GetParent()) {
NS_RELEASE(mParent);
}
}
// Note, _INHERITED macro isn't used here since nsINode implementations are // rather special.
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(CharacterData)
// We purposefully don't TRAVERSE_BEGIN_INHERITED here. All the bits // we should traverse should be added here or in nsINode::Traverse.
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(CharacterData) if (MOZ_UNLIKELY(cb.WantDebugInfo())) { char name[40];
SprintfLiteral(name, "CharacterData (len=%d)", tmp->mText.GetLength());
cb.DescribeRefCountedNode(tmp->mRefCnt.get(), name);
} else {
NS_IMPL_CYCLE_COLLECTION_DESCRIBE(CharacterData, tmp->mRefCnt.get())
}
if (!nsIContent::Traverse(tmp, cb)) { return NS_SUCCESS_INTERRUPTED_TRAVERSE;
}
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
// We purposefully don't UNLINK_BEGIN_INHERITED here.
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(CharacterData)
nsIContent::Unlink(tmp);
if (nsContentSlots* slots = tmp->GetExistingContentSlots()) {
slots->Unlink(*tmp);
}
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
if (aOffset == 0 && endOffset == textLength) { // Replacing whole text or old text was empty. // If this is marked as "maybe modified frequently", the text should be // stored as char16_t since converting char* to char16_t* is expensive. bool ok = mText.SetTo(aBuffer, aLength, true,
HasFlag(NS_MAYBE_MODIFIED_FREQUENTLY));
NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY);
} elseif (aOffset == textLength) { // Appending to existing. bool ok = mText.Append(aBuffer, aLength, !mText.IsBidi(),
HasFlag(NS_MAYBE_MODIFIED_FREQUENTLY));
NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY);
} else { // Merging old and new
bool bidi = mText.IsBidi();
// Allocate new buffer const uint32_t newLength = textLength - aCount + aLength; // Use nsString and not nsAutoString so that we get a nsStringBuffer which // can be just AddRefed in nsTextFragment.
nsString to;
to.SetCapacity(newLength);
// Copy over appropriate data if (aOffset) {
mText.AppendTo(to, 0, aOffset);
} if (aLength) {
to.Append(aBuffer, aLength); if (!bidi) {
bidi = HasRTLChars(Span(aBuffer, aLength));
}
} if (endOffset != textLength) {
mText.AppendTo(to, endOffset, textLength - endOffset);
}
// If this is marked as "maybe modified frequently", the text should be // stored as char16_t since converting char* to char16_t* is expensive. // Use char16_t also when we have bidi characters. bool use2b = HasFlag(NS_MAYBE_MODIFIED_FREQUENTLY) || bidi; bool ok = mText.SetTo(to, false, use2b);
mText.SetBidi(bidi);
NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY);
}
UnsetFlags(NS_CACHED_TEXT_IS_ONLY_WHITESPACE);
if (document && mText.IsBidi()) { // If we found bidi characters in mText.SetTo() above, indicate that the // document contains bidi characters.
document->SetBidiEnabled();
}
if (dirAffectsAncestor) { // dirAffectsAncestor being true implies that we have a text node, see // above.
MOZ_ASSERT(IsText());
TextNodeChangedDirection(AsText(), oldDir, aNotify);
}
// Notify observers if (aNotify) {
CharacterDataChangeInfo info = {aOffset == textLength, aOffset, endOffset,
aLength, aDetails};
MutationObservers::NotifyCharacterDataChanged(this, info);
if (haveMutationListeners) {
InternalMutationEvent mutation(true, eLegacyCharacterDataModified);
nsresult CharacterData::BindToTree(BindContext& aContext, nsINode& aParent) {
MOZ_ASSERT(aParent.IsContent() || aParent.IsDocument(), "Must have content or document parent!");
MOZ_ASSERT(aParent.OwnerDoc() == OwnerDoc(), "Must have the same owner document");
MOZ_ASSERT(OwnerDoc() == &aContext.OwnerDoc(), "These should match too");
MOZ_ASSERT(!IsInUncomposedDoc(), "Already have a document. Unbind first!");
MOZ_ASSERT(!IsInComposedDoc(), "Already have a document. Unbind first!"); // 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.
MOZ_ASSERT(!GetParentNode() || &aParent == GetParentNode(), "Already have a parent. Unbind first!");
constbool hadParent = !!GetParentNode();
if (aParent.IsInNativeAnonymousSubtree()) {
SetFlags(NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE);
} if (IsRootOfNativeAnonymousSubtree()) {
aParent.SetMayHaveAnonymousChildren();
} elseif (aParent.HasFlag(NODE_HAS_BEEN_IN_UA_WIDGET)) {
SetFlags(NODE_HAS_BEEN_IN_UA_WIDGET);
}
// Set parent
mParent = &aParent; if (!hadParent && aParent.IsContent()) {
SetParentIsContent(true);
NS_ADDREF(mParent);
}
MOZ_ASSERT(!!GetParent() == aParent.IsContent());
if (aParent.IsInUncomposedDoc() || aParent.IsInShadowTree()) { // We no longer need to track the subtree pointer (and in fact we'll assert // if we do this any later).
ClearSubtreeRootPointer();
SetIsConnected(aParent.IsInComposedDoc());
if (IsInComposedDoc() && mText.IsBidi()) {
aContext.OwnerDoc().SetBidiEnabled();
}
// Clear the lazy frame construction bits.
UnsetFlags(NODE_NEEDS_FRAME | NODE_DESCENDANTS_NEED_FRAMES);
} else { // If we're not in the doc and not in a shadow tree, // update our subtree pointer.
SetSubtreeRootPointer(aParent.SubtreeRoot());
}
// Ensure we only do these once, in the case we move the shadow host around. if (aContext.SubtreeRootChanges()) {
HandleShadowDOMRelatedInsertionSteps(hadParent);
}
void CharacterData::UnbindFromTree(UnbindContext& aContext) { // Unset frame flags; if we need them again later, they'll get set again.
UnsetFlags(NS_CREATE_FRAME_IF_NON_WHITESPACE | NS_REFRAME_IF_WHITESPACE);
#ifdefined(ACCESSIBILITY) && defined(DEBUG)
MOZ_ASSERT(!GetAccService() || !GetAccService()->HasAccessible(this), "An accessible for this element still exists!"); #endif
}
bool CharacterData::ThreadSafeTextIsOnlyWhitespace() const { // FIXME: should this method take content language into account? if (mText.Is2b()) { // The fragment contains non-8bit characters and such characters // are never considered whitespace. // // FIXME(emilio): This is not quite true in presence of the // NS_MAYBE_MODIFIED_FREQUENTLY flag... But looks like we only set that on // anonymous nodes, so should be fine... returnfalse;
}
if (HasFlag(NS_CACHED_TEXT_IS_ONLY_WHITESPACE)) { return HasFlag(NS_TEXT_IS_ONLY_WHITESPACE);
}
constchar* cp = mText.Get1b(); constchar* end = cp + mText.GetLength();
while (cp < end) { char ch = *cp;
// NOTE(emilio): If you ever change the definition of "whitespace" here, you // need to change it too in RestyleManager::CharacterDataChanged. if (!dom::IsSpaceCharacter(ch)) { returnfalse;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.