content/base/src/nsGenericDOMDataNode.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 /*
michael@0 7 * Base class for DOM Core's nsIDOMComment, nsIDOMDocumentType, nsIDOMText,
michael@0 8 * nsIDOMCDATASection, and nsIDOMProcessingInstruction nodes.
michael@0 9 */
michael@0 10
michael@0 11 #include "mozilla/DebugOnly.h"
michael@0 12
michael@0 13 #include "nsGenericDOMDataNode.h"
michael@0 14 #include "mozilla/AsyncEventDispatcher.h"
michael@0 15 #include "mozilla/MemoryReporting.h"
michael@0 16 #include "mozilla/dom/Element.h"
michael@0 17 #include "mozilla/dom/ShadowRoot.h"
michael@0 18 #include "nsIDocument.h"
michael@0 19 #include "nsIDOMDocument.h"
michael@0 20 #include "nsReadableUtils.h"
michael@0 21 #include "mozilla/InternalMutationEvent.h"
michael@0 22 #include "nsIURI.h"
michael@0 23 #include "nsIDOMEvent.h"
michael@0 24 #include "nsIDOMText.h"
michael@0 25 #include "nsCOMPtr.h"
michael@0 26 #include "nsDOMString.h"
michael@0 27 #include "nsIDOMUserDataHandler.h"
michael@0 28 #include "nsChangeHint.h"
michael@0 29 #include "nsCOMArray.h"
michael@0 30 #include "nsNodeUtils.h"
michael@0 31 #include "mozilla/dom/DirectionalityUtils.h"
michael@0 32 #include "nsBindingManager.h"
michael@0 33 #include "nsCCUncollectableMarker.h"
michael@0 34 #include "mozAutoDocUpdate.h"
michael@0 35
michael@0 36 #include "pldhash.h"
michael@0 37 #include "prprf.h"
michael@0 38 #include "nsWrapperCacheInlines.h"
michael@0 39
michael@0 40 using namespace mozilla;
michael@0 41 using namespace mozilla::dom;
michael@0 42
michael@0 43 nsGenericDOMDataNode::nsGenericDOMDataNode(already_AddRefed<nsINodeInfo>& aNodeInfo)
michael@0 44 : nsIContent(aNodeInfo)
michael@0 45 {
michael@0 46 NS_ABORT_IF_FALSE(mNodeInfo->NodeType() == nsIDOMNode::TEXT_NODE ||
michael@0 47 mNodeInfo->NodeType() == nsIDOMNode::CDATA_SECTION_NODE ||
michael@0 48 mNodeInfo->NodeType() == nsIDOMNode::COMMENT_NODE ||
michael@0 49 mNodeInfo->NodeType() ==
michael@0 50 nsIDOMNode::PROCESSING_INSTRUCTION_NODE ||
michael@0 51 mNodeInfo->NodeType() == nsIDOMNode::DOCUMENT_TYPE_NODE,
michael@0 52 "Bad NodeType in aNodeInfo");
michael@0 53 }
michael@0 54
michael@0 55 nsGenericDOMDataNode::nsGenericDOMDataNode(already_AddRefed<nsINodeInfo>&& aNodeInfo)
michael@0 56 : nsIContent(aNodeInfo)
michael@0 57 {
michael@0 58 NS_ABORT_IF_FALSE(mNodeInfo->NodeType() == nsIDOMNode::TEXT_NODE ||
michael@0 59 mNodeInfo->NodeType() == nsIDOMNode::CDATA_SECTION_NODE ||
michael@0 60 mNodeInfo->NodeType() == nsIDOMNode::COMMENT_NODE ||
michael@0 61 mNodeInfo->NodeType() ==
michael@0 62 nsIDOMNode::PROCESSING_INSTRUCTION_NODE ||
michael@0 63 mNodeInfo->NodeType() == nsIDOMNode::DOCUMENT_TYPE_NODE,
michael@0 64 "Bad NodeType in aNodeInfo");
michael@0 65 }
michael@0 66
michael@0 67 nsGenericDOMDataNode::~nsGenericDOMDataNode()
michael@0 68 {
michael@0 69 NS_PRECONDITION(!IsInDoc(),
michael@0 70 "Please remove this from the document properly");
michael@0 71 if (GetParent()) {
michael@0 72 NS_RELEASE(mParent);
michael@0 73 }
michael@0 74 }
michael@0 75
michael@0 76 NS_IMPL_CYCLE_COLLECTION_CLASS(nsGenericDOMDataNode)
michael@0 77
michael@0 78 NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(nsGenericDOMDataNode)
michael@0 79
michael@0 80 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsGenericDOMDataNode)
michael@0 81 return Element::CanSkip(tmp, aRemovingAllowed);
michael@0 82 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END
michael@0 83
michael@0 84 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(nsGenericDOMDataNode)
michael@0 85 return Element::CanSkipInCC(tmp);
michael@0 86 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END
michael@0 87
michael@0 88 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(nsGenericDOMDataNode)
michael@0 89 return Element::CanSkipThis(tmp);
michael@0 90 NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END
michael@0 91
michael@0 92 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsGenericDOMDataNode)
michael@0 93 // Always need to traverse script objects, so do that before we check
michael@0 94 // if we're uncollectable.
michael@0 95 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
michael@0 96
michael@0 97 if (!nsINode::Traverse(tmp, cb)) {
michael@0 98 return NS_SUCCESS_INTERRUPTED_TRAVERSE;
michael@0 99 }
michael@0 100
michael@0 101 nsDataSlots *slots = tmp->GetExistingDataSlots();
michael@0 102 if (slots) {
michael@0 103 slots->Traverse(cb);
michael@0 104 }
michael@0 105
michael@0 106 tmp->OwnerDoc()->BindingManager()->Traverse(tmp, cb);
michael@0 107 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
michael@0 108
michael@0 109 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGenericDOMDataNode)
michael@0 110 nsINode::Unlink(tmp);
michael@0 111
michael@0 112 nsDataSlots *slots = tmp->GetExistingDataSlots();
michael@0 113 if (slots) {
michael@0 114 slots->Unlink();
michael@0 115 }
michael@0 116 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
michael@0 117
michael@0 118 NS_INTERFACE_MAP_BEGIN(nsGenericDOMDataNode)
michael@0 119 NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
michael@0 120 NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(nsGenericDOMDataNode)
michael@0 121 NS_INTERFACE_MAP_ENTRY(nsIContent)
michael@0 122 NS_INTERFACE_MAP_ENTRY(nsINode)
michael@0 123 NS_INTERFACE_MAP_ENTRY(nsIDOMEventTarget)
michael@0 124 NS_INTERFACE_MAP_ENTRY(mozilla::dom::EventTarget)
michael@0 125 NS_INTERFACE_MAP_ENTRY_TEAROFF(nsISupportsWeakReference,
michael@0 126 new nsNodeSupportsWeakRefTearoff(this))
michael@0 127 NS_INTERFACE_MAP_ENTRY_TEAROFF(nsIDOMXPathNSResolver,
michael@0 128 new nsNode3Tearoff(this))
michael@0 129 // DOM bindings depend on the identity pointer being the
michael@0 130 // same as nsINode (which nsIContent inherits).
michael@0 131 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIContent)
michael@0 132 NS_INTERFACE_MAP_END
michael@0 133
michael@0 134 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsGenericDOMDataNode)
michael@0 135 NS_IMPL_CYCLE_COLLECTING_RELEASE_WITH_LAST_RELEASE(nsGenericDOMDataNode,
michael@0 136 nsNodeUtils::LastRelease(this))
michael@0 137
michael@0 138
michael@0 139 void
michael@0 140 nsGenericDOMDataNode::GetNodeValueInternal(nsAString& aNodeValue)
michael@0 141 {
michael@0 142 DebugOnly<nsresult> rv = GetData(aNodeValue);
michael@0 143 NS_ASSERTION(NS_SUCCEEDED(rv), "GetData() failed!");
michael@0 144 }
michael@0 145
michael@0 146 void
michael@0 147 nsGenericDOMDataNode::SetNodeValueInternal(const nsAString& aNodeValue,
michael@0 148 ErrorResult& aError)
michael@0 149 {
michael@0 150 aError = SetTextInternal(0, mText.GetLength(), aNodeValue.BeginReading(),
michael@0 151 aNodeValue.Length(), true);
michael@0 152 }
michael@0 153
michael@0 154 //----------------------------------------------------------------------
michael@0 155
michael@0 156 // Implementation of nsIDOMCharacterData
michael@0 157
michael@0 158 nsresult
michael@0 159 nsGenericDOMDataNode::GetData(nsAString& aData) const
michael@0 160 {
michael@0 161 if (mText.Is2b()) {
michael@0 162 aData.Assign(mText.Get2b(), mText.GetLength());
michael@0 163 } else {
michael@0 164 // Must use Substring() since nsDependentCString() requires null
michael@0 165 // terminated strings.
michael@0 166
michael@0 167 const char *data = mText.Get1b();
michael@0 168
michael@0 169 if (data) {
michael@0 170 CopyASCIItoUTF16(Substring(data, data + mText.GetLength()), aData);
michael@0 171 } else {
michael@0 172 aData.Truncate();
michael@0 173 }
michael@0 174 }
michael@0 175
michael@0 176 return NS_OK;
michael@0 177 }
michael@0 178
michael@0 179 nsresult
michael@0 180 nsGenericDOMDataNode::SetData(const nsAString& aData)
michael@0 181 {
michael@0 182 return SetTextInternal(0, mText.GetLength(), aData.BeginReading(),
michael@0 183 aData.Length(), true);
michael@0 184 }
michael@0 185
michael@0 186 nsresult
michael@0 187 nsGenericDOMDataNode::GetLength(uint32_t* aLength)
michael@0 188 {
michael@0 189 *aLength = mText.GetLength();
michael@0 190 return NS_OK;
michael@0 191 }
michael@0 192
michael@0 193 nsresult
michael@0 194 nsGenericDOMDataNode::SubstringData(uint32_t aStart, uint32_t aCount,
michael@0 195 nsAString& aReturn)
michael@0 196 {
michael@0 197 ErrorResult rv;
michael@0 198 SubstringData(aStart, aCount, aReturn, rv);
michael@0 199 return rv.ErrorCode();
michael@0 200 }
michael@0 201
michael@0 202 void
michael@0 203 nsGenericDOMDataNode::SubstringData(uint32_t aStart, uint32_t aCount,
michael@0 204 nsAString& aReturn, ErrorResult& rv)
michael@0 205 {
michael@0 206 aReturn.Truncate();
michael@0 207
michael@0 208 uint32_t textLength = mText.GetLength();
michael@0 209 if (aStart > textLength) {
michael@0 210 rv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
michael@0 211 return;
michael@0 212 }
michael@0 213
michael@0 214 uint32_t amount = aCount;
michael@0 215 if (amount > textLength - aStart) {
michael@0 216 amount = textLength - aStart;
michael@0 217 }
michael@0 218
michael@0 219 if (mText.Is2b()) {
michael@0 220 aReturn.Assign(mText.Get2b() + aStart, amount);
michael@0 221 } else {
michael@0 222 // Must use Substring() since nsDependentCString() requires null
michael@0 223 // terminated strings.
michael@0 224
michael@0 225 const char *data = mText.Get1b() + aStart;
michael@0 226 CopyASCIItoUTF16(Substring(data, data + amount), aReturn);
michael@0 227 }
michael@0 228 }
michael@0 229
michael@0 230 NS_IMETHODIMP
michael@0 231 nsGenericDOMDataNode::MozRemove()
michael@0 232 {
michael@0 233 Remove();
michael@0 234 return NS_OK;
michael@0 235 }
michael@0 236
michael@0 237 //----------------------------------------------------------------------
michael@0 238
michael@0 239 nsresult
michael@0 240 nsGenericDOMDataNode::AppendData(const nsAString& aData)
michael@0 241 {
michael@0 242 return SetTextInternal(mText.GetLength(), 0, aData.BeginReading(),
michael@0 243 aData.Length(), true);
michael@0 244 }
michael@0 245
michael@0 246 nsresult
michael@0 247 nsGenericDOMDataNode::InsertData(uint32_t aOffset,
michael@0 248 const nsAString& aData)
michael@0 249 {
michael@0 250 return SetTextInternal(aOffset, 0, aData.BeginReading(),
michael@0 251 aData.Length(), true);
michael@0 252 }
michael@0 253
michael@0 254 nsresult
michael@0 255 nsGenericDOMDataNode::DeleteData(uint32_t aOffset, uint32_t aCount)
michael@0 256 {
michael@0 257 return SetTextInternal(aOffset, aCount, nullptr, 0, true);
michael@0 258 }
michael@0 259
michael@0 260 nsresult
michael@0 261 nsGenericDOMDataNode::ReplaceData(uint32_t aOffset, uint32_t aCount,
michael@0 262 const nsAString& aData)
michael@0 263 {
michael@0 264 return SetTextInternal(aOffset, aCount, aData.BeginReading(),
michael@0 265 aData.Length(), true);
michael@0 266 }
michael@0 267
michael@0 268 nsresult
michael@0 269 nsGenericDOMDataNode::SetTextInternal(uint32_t aOffset, uint32_t aCount,
michael@0 270 const char16_t* aBuffer,
michael@0 271 uint32_t aLength, bool aNotify,
michael@0 272 CharacterDataChangeInfo::Details* aDetails)
michael@0 273 {
michael@0 274 NS_PRECONDITION(aBuffer || !aLength,
michael@0 275 "Null buffer passed to SetTextInternal!");
michael@0 276
michael@0 277 // sanitize arguments
michael@0 278 uint32_t textLength = mText.GetLength();
michael@0 279 if (aOffset > textLength) {
michael@0 280 return NS_ERROR_DOM_INDEX_SIZE_ERR;
michael@0 281 }
michael@0 282
michael@0 283 if (aCount > textLength - aOffset) {
michael@0 284 aCount = textLength - aOffset;
michael@0 285 }
michael@0 286
michael@0 287 uint32_t endOffset = aOffset + aCount;
michael@0 288
michael@0 289 // Make sure the text fragment can hold the new data.
michael@0 290 if (aLength > aCount && !mText.CanGrowBy(aLength - aCount)) {
michael@0 291 return NS_ERROR_OUT_OF_MEMORY;
michael@0 292 }
michael@0 293
michael@0 294 nsIDocument *document = GetCurrentDoc();
michael@0 295 mozAutoDocUpdate updateBatch(document, UPDATE_CONTENT_MODEL, aNotify);
michael@0 296
michael@0 297 bool haveMutationListeners = aNotify &&
michael@0 298 nsContentUtils::HasMutationListeners(this,
michael@0 299 NS_EVENT_BITS_MUTATION_CHARACTERDATAMODIFIED,
michael@0 300 this);
michael@0 301
michael@0 302 nsCOMPtr<nsIAtom> oldValue;
michael@0 303 if (haveMutationListeners) {
michael@0 304 oldValue = GetCurrentValueAtom();
michael@0 305 }
michael@0 306
michael@0 307 if (aNotify) {
michael@0 308 CharacterDataChangeInfo info = {
michael@0 309 aOffset == textLength,
michael@0 310 aOffset,
michael@0 311 endOffset,
michael@0 312 aLength,
michael@0 313 aDetails
michael@0 314 };
michael@0 315 nsNodeUtils::CharacterDataWillChange(this, &info);
michael@0 316 }
michael@0 317
michael@0 318 Directionality oldDir = eDir_NotSet;
michael@0 319 bool dirAffectsAncestor = (NodeType() == nsIDOMNode::TEXT_NODE &&
michael@0 320 TextNodeWillChangeDirection(this, &oldDir, aOffset));
michael@0 321
michael@0 322 if (aOffset == 0 && endOffset == textLength) {
michael@0 323 // Replacing whole text or old text was empty. Don't bother to check for
michael@0 324 // bidi in this string if the document already has bidi enabled.
michael@0 325 bool ok = mText.SetTo(aBuffer, aLength, !document || !document->GetBidiEnabled());
michael@0 326 NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY);
michael@0 327 }
michael@0 328 else if (aOffset == textLength) {
michael@0 329 // Appending to existing
michael@0 330 bool ok = mText.Append(aBuffer, aLength, !document || !document->GetBidiEnabled());
michael@0 331 NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY);
michael@0 332 }
michael@0 333 else {
michael@0 334 // Merging old and new
michael@0 335
michael@0 336 // Allocate new buffer
michael@0 337 int32_t newLength = textLength - aCount + aLength;
michael@0 338 char16_t* to = new char16_t[newLength];
michael@0 339 NS_ENSURE_TRUE(to, NS_ERROR_OUT_OF_MEMORY);
michael@0 340
michael@0 341 // Copy over appropriate data
michael@0 342 if (aOffset) {
michael@0 343 mText.CopyTo(to, 0, aOffset);
michael@0 344 }
michael@0 345 if (aLength) {
michael@0 346 memcpy(to + aOffset, aBuffer, aLength * sizeof(char16_t));
michael@0 347 }
michael@0 348 if (endOffset != textLength) {
michael@0 349 mText.CopyTo(to + aOffset + aLength, endOffset, textLength - endOffset);
michael@0 350 }
michael@0 351
michael@0 352 bool ok = mText.SetTo(to, newLength, !document || !document->GetBidiEnabled());
michael@0 353
michael@0 354 delete [] to;
michael@0 355
michael@0 356 NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY);
michael@0 357 }
michael@0 358
michael@0 359 UnsetFlags(NS_CACHED_TEXT_IS_ONLY_WHITESPACE);
michael@0 360
michael@0 361 if (document && mText.IsBidi()) {
michael@0 362 // If we found bidi characters in mText.SetTo() above, indicate that the
michael@0 363 // document contains bidi characters.
michael@0 364 document->SetBidiEnabled();
michael@0 365 }
michael@0 366
michael@0 367 if (dirAffectsAncestor) {
michael@0 368 TextNodeChangedDirection(this, oldDir, aNotify);
michael@0 369 }
michael@0 370
michael@0 371 // Notify observers
michael@0 372 if (aNotify) {
michael@0 373 CharacterDataChangeInfo info = {
michael@0 374 aOffset == textLength,
michael@0 375 aOffset,
michael@0 376 endOffset,
michael@0 377 aLength,
michael@0 378 aDetails
michael@0 379 };
michael@0 380 nsNodeUtils::CharacterDataChanged(this, &info);
michael@0 381
michael@0 382 if (haveMutationListeners) {
michael@0 383 InternalMutationEvent mutation(true, NS_MUTATION_CHARACTERDATAMODIFIED);
michael@0 384
michael@0 385 mutation.mPrevAttrValue = oldValue;
michael@0 386 if (aLength > 0) {
michael@0 387 nsAutoString val;
michael@0 388 mText.AppendTo(val);
michael@0 389 mutation.mNewAttrValue = do_GetAtom(val);
michael@0 390 }
michael@0 391
michael@0 392 mozAutoSubtreeModified subtree(OwnerDoc(), this);
michael@0 393 (new AsyncEventDispatcher(this, mutation))->RunDOMEventWhenSafe();
michael@0 394 }
michael@0 395 }
michael@0 396
michael@0 397 return NS_OK;
michael@0 398 }
michael@0 399
michael@0 400 //----------------------------------------------------------------------
michael@0 401
michael@0 402 // Implementation of nsIContent
michael@0 403
michael@0 404 #ifdef DEBUG
michael@0 405 void
michael@0 406 nsGenericDOMDataNode::ToCString(nsAString& aBuf, int32_t aOffset,
michael@0 407 int32_t aLen) const
michael@0 408 {
michael@0 409 if (mText.Is2b()) {
michael@0 410 const char16_t* cp = mText.Get2b() + aOffset;
michael@0 411 const char16_t* end = cp + aLen;
michael@0 412
michael@0 413 while (cp < end) {
michael@0 414 char16_t ch = *cp++;
michael@0 415 if (ch == '&') {
michael@0 416 aBuf.AppendLiteral("&amp;");
michael@0 417 } else if (ch == '<') {
michael@0 418 aBuf.AppendLiteral("&lt;");
michael@0 419 } else if (ch == '>') {
michael@0 420 aBuf.AppendLiteral("&gt;");
michael@0 421 } else if ((ch < ' ') || (ch >= 127)) {
michael@0 422 char buf[10];
michael@0 423 PR_snprintf(buf, sizeof(buf), "\\u%04x", ch);
michael@0 424 AppendASCIItoUTF16(buf, aBuf);
michael@0 425 } else {
michael@0 426 aBuf.Append(ch);
michael@0 427 }
michael@0 428 }
michael@0 429 } else {
michael@0 430 unsigned char* cp = (unsigned char*)mText.Get1b() + aOffset;
michael@0 431 const unsigned char* end = cp + aLen;
michael@0 432
michael@0 433 while (cp < end) {
michael@0 434 char16_t ch = *cp++;
michael@0 435 if (ch == '&') {
michael@0 436 aBuf.AppendLiteral("&amp;");
michael@0 437 } else if (ch == '<') {
michael@0 438 aBuf.AppendLiteral("&lt;");
michael@0 439 } else if (ch == '>') {
michael@0 440 aBuf.AppendLiteral("&gt;");
michael@0 441 } else if ((ch < ' ') || (ch >= 127)) {
michael@0 442 char buf[10];
michael@0 443 PR_snprintf(buf, sizeof(buf), "\\u%04x", ch);
michael@0 444 AppendASCIItoUTF16(buf, aBuf);
michael@0 445 } else {
michael@0 446 aBuf.Append(ch);
michael@0 447 }
michael@0 448 }
michael@0 449 }
michael@0 450 }
michael@0 451 #endif
michael@0 452
michael@0 453
michael@0 454 nsresult
michael@0 455 nsGenericDOMDataNode::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
michael@0 456 nsIContent* aBindingParent,
michael@0 457 bool aCompileEventHandlers)
michael@0 458 {
michael@0 459 NS_PRECONDITION(aParent || aDocument, "Must have document if no parent!");
michael@0 460 NS_PRECONDITION(NODE_FROM(aParent, aDocument)->OwnerDoc() == OwnerDoc(),
michael@0 461 "Must have the same owner document");
michael@0 462 NS_PRECONDITION(!aParent || aDocument == aParent->GetCurrentDoc(),
michael@0 463 "aDocument must be current doc of aParent");
michael@0 464 NS_PRECONDITION(!GetCurrentDoc() && !IsInDoc(),
michael@0 465 "Already have a document. Unbind first!");
michael@0 466 // Note that as we recurse into the kids, they'll have a non-null parent. So
michael@0 467 // only assert if our parent is _changing_ while we have a parent.
michael@0 468 NS_PRECONDITION(!GetParent() || aParent == GetParent(),
michael@0 469 "Already have a parent. Unbind first!");
michael@0 470 NS_PRECONDITION(!GetBindingParent() ||
michael@0 471 aBindingParent == GetBindingParent() ||
michael@0 472 (!aBindingParent && aParent &&
michael@0 473 aParent->GetBindingParent() == GetBindingParent()),
michael@0 474 "Already have a binding parent. Unbind first!");
michael@0 475 NS_PRECONDITION(aBindingParent != this,
michael@0 476 "Content must not be its own binding parent");
michael@0 477 NS_PRECONDITION(!IsRootOfNativeAnonymousSubtree() ||
michael@0 478 aBindingParent == aParent,
michael@0 479 "Native anonymous content must have its parent as its "
michael@0 480 "own binding parent");
michael@0 481
michael@0 482 if (!aBindingParent && aParent) {
michael@0 483 aBindingParent = aParent->GetBindingParent();
michael@0 484 }
michael@0 485
michael@0 486 // First set the binding parent
michael@0 487 if (aBindingParent) {
michael@0 488 NS_ASSERTION(IsRootOfNativeAnonymousSubtree() ||
michael@0 489 !HasFlag(NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE) ||
michael@0 490 (aParent && aParent->IsInNativeAnonymousSubtree()),
michael@0 491 "Trying to re-bind content from native anonymous subtree to "
michael@0 492 "non-native anonymous parent!");
michael@0 493 DataSlots()->mBindingParent = aBindingParent; // Weak, so no addref happens.
michael@0 494 if (aParent->IsInNativeAnonymousSubtree()) {
michael@0 495 SetFlags(NODE_IS_IN_NATIVE_ANONYMOUS_SUBTREE);
michael@0 496 }
michael@0 497 if (aParent->HasFlag(NODE_CHROME_ONLY_ACCESS)) {
michael@0 498 SetFlags(NODE_CHROME_ONLY_ACCESS);
michael@0 499 }
michael@0 500 if (aParent->HasFlag(NODE_IS_IN_SHADOW_TREE)) {
michael@0 501 SetFlags(NODE_IS_IN_SHADOW_TREE);
michael@0 502 }
michael@0 503 ShadowRoot* parentContainingShadow = aParent->GetContainingShadow();
michael@0 504 if (parentContainingShadow) {
michael@0 505 DataSlots()->mContainingShadow = parentContainingShadow;
michael@0 506 }
michael@0 507 }
michael@0 508
michael@0 509 // Set parent
michael@0 510 if (aParent) {
michael@0 511 if (!GetParent()) {
michael@0 512 NS_ADDREF(aParent);
michael@0 513 }
michael@0 514 mParent = aParent;
michael@0 515 }
michael@0 516 else {
michael@0 517 mParent = aDocument;
michael@0 518 }
michael@0 519 SetParentIsContent(aParent);
michael@0 520
michael@0 521 // XXXbz sXBL/XBL2 issue!
michael@0 522
michael@0 523 // Set document
michael@0 524 if (aDocument) {
michael@0 525 // We no longer need to track the subtree pointer (and in fact we'll assert
michael@0 526 // if we do this any later).
michael@0 527 ClearSubtreeRootPointer();
michael@0 528
michael@0 529 // XXX See the comment in Element::BindToTree
michael@0 530 SetInDocument();
michael@0 531 if (mText.IsBidi()) {
michael@0 532 aDocument->SetBidiEnabled();
michael@0 533 }
michael@0 534 // Clear the lazy frame construction bits.
michael@0 535 UnsetFlags(NODE_NEEDS_FRAME | NODE_DESCENDANTS_NEED_FRAMES);
michael@0 536 } else {
michael@0 537 // If we're not in the doc, update our subtree pointer.
michael@0 538 SetSubtreeRootPointer(aParent->SubtreeRoot());
michael@0 539 }
michael@0 540
michael@0 541 nsNodeUtils::ParentChainChanged(this);
michael@0 542
michael@0 543 UpdateEditableState(false);
michael@0 544
michael@0 545 NS_POSTCONDITION(aDocument == GetCurrentDoc(), "Bound to wrong document");
michael@0 546 NS_POSTCONDITION(aParent == GetParent(), "Bound to wrong parent");
michael@0 547 NS_POSTCONDITION(aBindingParent == GetBindingParent(),
michael@0 548 "Bound to wrong binding parent");
michael@0 549
michael@0 550 return NS_OK;
michael@0 551 }
michael@0 552
michael@0 553 void
michael@0 554 nsGenericDOMDataNode::UnbindFromTree(bool aDeep, bool aNullParent)
michael@0 555 {
michael@0 556 // Unset frame flags; if we need them again later, they'll get set again.
michael@0 557 UnsetFlags(NS_CREATE_FRAME_IF_NON_WHITESPACE |
michael@0 558 NS_REFRAME_IF_WHITESPACE |
michael@0 559 // Also unset the shadow tree flag because it can
michael@0 560 // no longer be a descendant of a ShadowRoot.
michael@0 561 NODE_IS_IN_SHADOW_TREE);
michael@0 562
michael@0 563 nsIDocument *document = GetCurrentDoc();
michael@0 564 if (document) {
michael@0 565 // Notify XBL- & nsIAnonymousContentCreator-generated
michael@0 566 // anonymous content that the document is changing.
michael@0 567 // This is needed to update the insertion point.
michael@0 568 document->BindingManager()->RemovedFromDocument(this, document);
michael@0 569 }
michael@0 570
michael@0 571 if (aNullParent) {
michael@0 572 if (GetParent()) {
michael@0 573 NS_RELEASE(mParent);
michael@0 574 } else {
michael@0 575 mParent = nullptr;
michael@0 576 }
michael@0 577 SetParentIsContent(false);
michael@0 578 }
michael@0 579 ClearInDocument();
michael@0 580
michael@0 581 // Begin keeping track of our subtree root.
michael@0 582 SetSubtreeRootPointer(aNullParent ? this : mParent->SubtreeRoot());
michael@0 583
michael@0 584 nsDataSlots *slots = GetExistingDataSlots();
michael@0 585 if (slots) {
michael@0 586 slots->mBindingParent = nullptr;
michael@0 587 slots->mContainingShadow = nullptr;
michael@0 588 }
michael@0 589
michael@0 590 nsNodeUtils::ParentChainChanged(this);
michael@0 591 }
michael@0 592
michael@0 593 already_AddRefed<nsINodeList>
michael@0 594 nsGenericDOMDataNode::GetChildren(uint32_t aFilter)
michael@0 595 {
michael@0 596 return nullptr;
michael@0 597 }
michael@0 598
michael@0 599 nsIAtom *
michael@0 600 nsGenericDOMDataNode::GetIDAttributeName() const
michael@0 601 {
michael@0 602 return nullptr;
michael@0 603 }
michael@0 604
michael@0 605 nsresult
michael@0 606 nsGenericDOMDataNode::SetAttr(int32_t aNameSpaceID, nsIAtom* aAttr,
michael@0 607 nsIAtom* aPrefix, const nsAString& aValue,
michael@0 608 bool aNotify)
michael@0 609 {
michael@0 610 return NS_OK;
michael@0 611 }
michael@0 612
michael@0 613 nsresult
michael@0 614 nsGenericDOMDataNode::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aAttr,
michael@0 615 bool aNotify)
michael@0 616 {
michael@0 617 return NS_OK;
michael@0 618 }
michael@0 619
michael@0 620 const nsAttrName*
michael@0 621 nsGenericDOMDataNode::GetAttrNameAt(uint32_t aIndex) const
michael@0 622 {
michael@0 623 return nullptr;
michael@0 624 }
michael@0 625
michael@0 626 uint32_t
michael@0 627 nsGenericDOMDataNode::GetAttrCount() const
michael@0 628 {
michael@0 629 return 0;
michael@0 630 }
michael@0 631
michael@0 632 uint32_t
michael@0 633 nsGenericDOMDataNode::GetChildCount() const
michael@0 634 {
michael@0 635 return 0;
michael@0 636 }
michael@0 637
michael@0 638 nsIContent *
michael@0 639 nsGenericDOMDataNode::GetChildAt(uint32_t aIndex) const
michael@0 640 {
michael@0 641 return nullptr;
michael@0 642 }
michael@0 643
michael@0 644 nsIContent * const *
michael@0 645 nsGenericDOMDataNode::GetChildArray(uint32_t* aChildCount) const
michael@0 646 {
michael@0 647 *aChildCount = 0;
michael@0 648 return nullptr;
michael@0 649 }
michael@0 650
michael@0 651 int32_t
michael@0 652 nsGenericDOMDataNode::IndexOf(const nsINode* aPossibleChild) const
michael@0 653 {
michael@0 654 return -1;
michael@0 655 }
michael@0 656
michael@0 657 nsresult
michael@0 658 nsGenericDOMDataNode::InsertChildAt(nsIContent* aKid, uint32_t aIndex,
michael@0 659 bool aNotify)
michael@0 660 {
michael@0 661 return NS_OK;
michael@0 662 }
michael@0 663
michael@0 664 void
michael@0 665 nsGenericDOMDataNode::RemoveChildAt(uint32_t aIndex, bool aNotify)
michael@0 666 {
michael@0 667 }
michael@0 668
michael@0 669 nsIContent *
michael@0 670 nsGenericDOMDataNode::GetBindingParent() const
michael@0 671 {
michael@0 672 nsDataSlots *slots = GetExistingDataSlots();
michael@0 673 return slots ? slots->mBindingParent : nullptr;
michael@0 674 }
michael@0 675
michael@0 676 ShadowRoot *
michael@0 677 nsGenericDOMDataNode::GetShadowRoot() const
michael@0 678 {
michael@0 679 return nullptr;
michael@0 680 }
michael@0 681
michael@0 682 ShadowRoot *
michael@0 683 nsGenericDOMDataNode::GetContainingShadow() const
michael@0 684 {
michael@0 685 nsDataSlots *slots = GetExistingDataSlots();
michael@0 686 return slots ? slots->mContainingShadow : nullptr;
michael@0 687 }
michael@0 688
michael@0 689 void
michael@0 690 nsGenericDOMDataNode::SetShadowRoot(ShadowRoot* aShadowRoot)
michael@0 691 {
michael@0 692 }
michael@0 693
michael@0 694 nsXBLBinding *
michael@0 695 nsGenericDOMDataNode::GetXBLBinding() const
michael@0 696 {
michael@0 697 return nullptr;
michael@0 698 }
michael@0 699
michael@0 700 void
michael@0 701 nsGenericDOMDataNode::SetXBLBinding(nsXBLBinding* aBinding,
michael@0 702 nsBindingManager* aOldBindingManager)
michael@0 703 {
michael@0 704 }
michael@0 705
michael@0 706 nsIContent *
michael@0 707 nsGenericDOMDataNode::GetXBLInsertionParent() const
michael@0 708 {
michael@0 709 if (HasFlag(NODE_MAY_BE_IN_BINDING_MNGR)) {
michael@0 710 nsDataSlots *slots = GetExistingDataSlots();
michael@0 711 if (slots) {
michael@0 712 return slots->mXBLInsertionParent;
michael@0 713 }
michael@0 714 }
michael@0 715
michael@0 716 return nullptr;
michael@0 717 }
michael@0 718
michael@0 719 void
michael@0 720 nsGenericDOMDataNode::SetXBLInsertionParent(nsIContent* aContent)
michael@0 721 {
michael@0 722 nsDataSlots *slots = DataSlots();
michael@0 723 if (aContent) {
michael@0 724 SetFlags(NODE_MAY_BE_IN_BINDING_MNGR);
michael@0 725 }
michael@0 726 slots->mXBLInsertionParent = aContent;
michael@0 727 }
michael@0 728
michael@0 729 CustomElementData *
michael@0 730 nsGenericDOMDataNode::GetCustomElementData() const
michael@0 731 {
michael@0 732 return nullptr;
michael@0 733 }
michael@0 734
michael@0 735 void
michael@0 736 nsGenericDOMDataNode::SetCustomElementData(CustomElementData* aData)
michael@0 737 {
michael@0 738 }
michael@0 739
michael@0 740 bool
michael@0 741 nsGenericDOMDataNode::IsNodeOfType(uint32_t aFlags) const
michael@0 742 {
michael@0 743 return !(aFlags & ~(eCONTENT | eDATA_NODE));
michael@0 744 }
michael@0 745
michael@0 746 void
michael@0 747 nsGenericDOMDataNode::SaveSubtreeState()
michael@0 748 {
michael@0 749 }
michael@0 750
michael@0 751 void
michael@0 752 nsGenericDOMDataNode::DestroyContent()
michael@0 753 {
michael@0 754 // XXX We really should let cycle collection do this, but that currently still
michael@0 755 // leaks (see https://bugzilla.mozilla.org/show_bug.cgi?id=406684).
michael@0 756 ReleaseWrapper(this);
michael@0 757 }
michael@0 758
michael@0 759 #ifdef DEBUG
michael@0 760 void
michael@0 761 nsGenericDOMDataNode::List(FILE* out, int32_t aIndent) const
michael@0 762 {
michael@0 763 }
michael@0 764
michael@0 765 void
michael@0 766 nsGenericDOMDataNode::DumpContent(FILE* out, int32_t aIndent,
michael@0 767 bool aDumpAll) const
michael@0 768 {
michael@0 769 }
michael@0 770 #endif
michael@0 771
michael@0 772 bool
michael@0 773 nsGenericDOMDataNode::IsLink(nsIURI** aURI) const
michael@0 774 {
michael@0 775 *aURI = nullptr;
michael@0 776 return false;
michael@0 777 }
michael@0 778
michael@0 779 nsINode::nsSlots*
michael@0 780 nsGenericDOMDataNode::CreateSlots()
michael@0 781 {
michael@0 782 return new nsDataSlots();
michael@0 783 }
michael@0 784
michael@0 785 nsGenericDOMDataNode::nsDataSlots::nsDataSlots()
michael@0 786 : nsINode::nsSlots(), mBindingParent(nullptr)
michael@0 787 {
michael@0 788 }
michael@0 789
michael@0 790 void
michael@0 791 nsGenericDOMDataNode::nsDataSlots::Traverse(nsCycleCollectionTraversalCallback &cb)
michael@0 792 {
michael@0 793 NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mXBLInsertionParent");
michael@0 794 cb.NoteXPCOMChild(mXBLInsertionParent.get());
michael@0 795
michael@0 796 NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mSlots->mContainingShadow");
michael@0 797 cb.NoteXPCOMChild(NS_ISUPPORTS_CAST(nsIContent*, mContainingShadow));
michael@0 798 }
michael@0 799
michael@0 800 void
michael@0 801 nsGenericDOMDataNode::nsDataSlots::Unlink()
michael@0 802 {
michael@0 803 mXBLInsertionParent = nullptr;
michael@0 804 mContainingShadow = nullptr;
michael@0 805 }
michael@0 806
michael@0 807 //----------------------------------------------------------------------
michael@0 808
michael@0 809 // Implementation of the nsIDOMText interface
michael@0 810
michael@0 811 nsresult
michael@0 812 nsGenericDOMDataNode::SplitData(uint32_t aOffset, nsIContent** aReturn,
michael@0 813 bool aCloneAfterOriginal)
michael@0 814 {
michael@0 815 *aReturn = nullptr;
michael@0 816 nsresult rv = NS_OK;
michael@0 817 nsAutoString cutText;
michael@0 818 uint32_t length = TextLength();
michael@0 819
michael@0 820 if (aOffset > length) {
michael@0 821 return NS_ERROR_DOM_INDEX_SIZE_ERR;
michael@0 822 }
michael@0 823
michael@0 824 uint32_t cutStartOffset = aCloneAfterOriginal ? aOffset : 0;
michael@0 825 uint32_t cutLength = aCloneAfterOriginal ? length - aOffset : aOffset;
michael@0 826 rv = SubstringData(cutStartOffset, cutLength, cutText);
michael@0 827 if (NS_FAILED(rv)) {
michael@0 828 return rv;
michael@0 829 }
michael@0 830
michael@0 831 nsIDocument* document = GetCurrentDoc();
michael@0 832 mozAutoDocUpdate updateBatch(document, UPDATE_CONTENT_MODEL, true);
michael@0 833
michael@0 834 // Use Clone for creating the new node so that the new node is of same class
michael@0 835 // as this node!
michael@0 836 nsCOMPtr<nsIContent> newContent = CloneDataNode(mNodeInfo, false);
michael@0 837 if (!newContent) {
michael@0 838 return NS_ERROR_OUT_OF_MEMORY;
michael@0 839 }
michael@0 840 newContent->SetText(cutText, true); // XXX should be false?
michael@0 841
michael@0 842 CharacterDataChangeInfo::Details details = {
michael@0 843 CharacterDataChangeInfo::Details::eSplit, newContent
michael@0 844 };
michael@0 845 rv = SetTextInternal(cutStartOffset, cutLength, nullptr, 0, true,
michael@0 846 aCloneAfterOriginal ? &details : nullptr);
michael@0 847 if (NS_FAILED(rv)) {
michael@0 848 return rv;
michael@0 849 }
michael@0 850
michael@0 851 nsCOMPtr<nsINode> parent = GetParentNode();
michael@0 852 if (parent) {
michael@0 853 int32_t insertionIndex = parent->IndexOf(this);
michael@0 854 if (aCloneAfterOriginal) {
michael@0 855 ++insertionIndex;
michael@0 856 }
michael@0 857 parent->InsertChildAt(newContent, insertionIndex, true);
michael@0 858 }
michael@0 859
michael@0 860 newContent.swap(*aReturn);
michael@0 861 return rv;
michael@0 862 }
michael@0 863
michael@0 864 nsresult
michael@0 865 nsGenericDOMDataNode::SplitText(uint32_t aOffset, nsIDOMText** aReturn)
michael@0 866 {
michael@0 867 nsCOMPtr<nsIContent> newChild;
michael@0 868 nsresult rv = SplitData(aOffset, getter_AddRefs(newChild));
michael@0 869 if (NS_SUCCEEDED(rv)) {
michael@0 870 rv = CallQueryInterface(newChild, aReturn);
michael@0 871 }
michael@0 872 return rv;
michael@0 873 }
michael@0 874
michael@0 875 /* static */ int32_t
michael@0 876 nsGenericDOMDataNode::FirstLogicallyAdjacentTextNode(nsIContent* aParent,
michael@0 877 int32_t aIndex)
michael@0 878 {
michael@0 879 while (aIndex-- > 0) {
michael@0 880 nsIContent* sibling = aParent->GetChildAt(aIndex);
michael@0 881 if (!sibling->IsNodeOfType(nsINode::eTEXT))
michael@0 882 return aIndex + 1;
michael@0 883 }
michael@0 884 return 0;
michael@0 885 }
michael@0 886
michael@0 887 /* static */ int32_t
michael@0 888 nsGenericDOMDataNode::LastLogicallyAdjacentTextNode(nsIContent* aParent,
michael@0 889 int32_t aIndex,
michael@0 890 uint32_t aCount)
michael@0 891 {
michael@0 892 while (++aIndex < int32_t(aCount)) {
michael@0 893 nsIContent* sibling = aParent->GetChildAt(aIndex);
michael@0 894 if (!sibling->IsNodeOfType(nsINode::eTEXT))
michael@0 895 return aIndex - 1;
michael@0 896 }
michael@0 897 return aCount - 1;
michael@0 898 }
michael@0 899
michael@0 900 nsresult
michael@0 901 nsGenericDOMDataNode::GetWholeText(nsAString& aWholeText)
michael@0 902 {
michael@0 903 nsIContent* parent = GetParent();
michael@0 904
michael@0 905 // Handle parent-less nodes
michael@0 906 if (!parent)
michael@0 907 return GetData(aWholeText);
michael@0 908
michael@0 909 int32_t index = parent->IndexOf(this);
michael@0 910 NS_WARN_IF_FALSE(index >= 0,
michael@0 911 "Trying to use .wholeText with an anonymous"
michael@0 912 "text node child of a binding parent?");
michael@0 913 NS_ENSURE_TRUE(index >= 0, NS_ERROR_DOM_NOT_SUPPORTED_ERR);
michael@0 914 int32_t first =
michael@0 915 FirstLogicallyAdjacentTextNode(parent, index);
michael@0 916 int32_t last =
michael@0 917 LastLogicallyAdjacentTextNode(parent, index, parent->GetChildCount());
michael@0 918
michael@0 919 aWholeText.Truncate();
michael@0 920
michael@0 921 nsCOMPtr<nsIDOMText> node;
michael@0 922 nsAutoString tmp;
michael@0 923 do {
michael@0 924 node = do_QueryInterface(parent->GetChildAt(first));
michael@0 925 node->GetData(tmp);
michael@0 926 aWholeText.Append(tmp);
michael@0 927 } while (first++ < last);
michael@0 928
michael@0 929 return NS_OK;
michael@0 930 }
michael@0 931
michael@0 932 //----------------------------------------------------------------------
michael@0 933
michael@0 934 // Implementation of the nsIContent interface text functions
michael@0 935
michael@0 936 const nsTextFragment *
michael@0 937 nsGenericDOMDataNode::GetText()
michael@0 938 {
michael@0 939 return &mText;
michael@0 940 }
michael@0 941
michael@0 942 uint32_t
michael@0 943 nsGenericDOMDataNode::TextLength() const
michael@0 944 {
michael@0 945 return mText.GetLength();
michael@0 946 }
michael@0 947
michael@0 948 nsresult
michael@0 949 nsGenericDOMDataNode::SetText(const char16_t* aBuffer,
michael@0 950 uint32_t aLength,
michael@0 951 bool aNotify)
michael@0 952 {
michael@0 953 return SetTextInternal(0, mText.GetLength(), aBuffer, aLength, aNotify);
michael@0 954 }
michael@0 955
michael@0 956 nsresult
michael@0 957 nsGenericDOMDataNode::AppendText(const char16_t* aBuffer,
michael@0 958 uint32_t aLength,
michael@0 959 bool aNotify)
michael@0 960 {
michael@0 961 return SetTextInternal(mText.GetLength(), 0, aBuffer, aLength, aNotify);
michael@0 962 }
michael@0 963
michael@0 964 bool
michael@0 965 nsGenericDOMDataNode::TextIsOnlyWhitespace()
michael@0 966 {
michael@0 967 // FIXME: should this method take content language into account?
michael@0 968 if (mText.Is2b()) {
michael@0 969 // The fragment contains non-8bit characters and such characters
michael@0 970 // are never considered whitespace.
michael@0 971 return false;
michael@0 972 }
michael@0 973
michael@0 974 if (HasFlag(NS_CACHED_TEXT_IS_ONLY_WHITESPACE)) {
michael@0 975 return HasFlag(NS_TEXT_IS_ONLY_WHITESPACE);
michael@0 976 }
michael@0 977
michael@0 978 const char* cp = mText.Get1b();
michael@0 979 const char* end = cp + mText.GetLength();
michael@0 980
michael@0 981 while (cp < end) {
michael@0 982 char ch = *cp;
michael@0 983
michael@0 984 if (!dom::IsSpaceCharacter(ch)) {
michael@0 985 UnsetFlags(NS_TEXT_IS_ONLY_WHITESPACE);
michael@0 986 SetFlags(NS_CACHED_TEXT_IS_ONLY_WHITESPACE);
michael@0 987 return false;
michael@0 988 }
michael@0 989
michael@0 990 ++cp;
michael@0 991 }
michael@0 992
michael@0 993 SetFlags(NS_CACHED_TEXT_IS_ONLY_WHITESPACE | NS_TEXT_IS_ONLY_WHITESPACE);
michael@0 994 return true;
michael@0 995 }
michael@0 996
michael@0 997 bool
michael@0 998 nsGenericDOMDataNode::HasTextForTranslation()
michael@0 999 {
michael@0 1000 if (mText.Is2b()) {
michael@0 1001 // The fragment contains non-8bit characters which means there
michael@0 1002 // was at least one "interesting" character to trigger non-8bit.
michael@0 1003 return true;
michael@0 1004 }
michael@0 1005
michael@0 1006 if (HasFlag(NS_CACHED_TEXT_IS_ONLY_WHITESPACE) &&
michael@0 1007 HasFlag(NS_TEXT_IS_ONLY_WHITESPACE)) {
michael@0 1008 return false;
michael@0 1009 }
michael@0 1010
michael@0 1011 const char* cp = mText.Get1b();
michael@0 1012 const char* end = cp + mText.GetLength();
michael@0 1013
michael@0 1014 unsigned char ch;
michael@0 1015 for (; cp < end; cp++) {
michael@0 1016 ch = *cp;
michael@0 1017
michael@0 1018 // These are the characters that are letters
michael@0 1019 // in the first 256 UTF-8 codepoints.
michael@0 1020 if ((ch >= 'a' && ch <= 'z') ||
michael@0 1021 (ch >= 'A' && ch <= 'Z') ||
michael@0 1022 (ch >= 192 && ch <= 214) ||
michael@0 1023 (ch >= 216 && ch <= 246) ||
michael@0 1024 (ch >= 248)) {
michael@0 1025 return true;
michael@0 1026 }
michael@0 1027 }
michael@0 1028
michael@0 1029 return false;
michael@0 1030 }
michael@0 1031
michael@0 1032 void
michael@0 1033 nsGenericDOMDataNode::AppendTextTo(nsAString& aResult)
michael@0 1034 {
michael@0 1035 mText.AppendTo(aResult);
michael@0 1036 }
michael@0 1037
michael@0 1038 bool
michael@0 1039 nsGenericDOMDataNode::AppendTextTo(nsAString& aResult, const mozilla::fallible_t&)
michael@0 1040 {
michael@0 1041 return mText.AppendTo(aResult, mozilla::fallible_t());
michael@0 1042 }
michael@0 1043
michael@0 1044 already_AddRefed<nsIAtom>
michael@0 1045 nsGenericDOMDataNode::GetCurrentValueAtom()
michael@0 1046 {
michael@0 1047 nsAutoString val;
michael@0 1048 GetData(val);
michael@0 1049 return NS_NewAtom(val);
michael@0 1050 }
michael@0 1051
michael@0 1052 nsIAtom*
michael@0 1053 nsGenericDOMDataNode::DoGetID() const
michael@0 1054 {
michael@0 1055 return nullptr;
michael@0 1056 }
michael@0 1057
michael@0 1058 const nsAttrValue*
michael@0 1059 nsGenericDOMDataNode::DoGetClasses() const
michael@0 1060 {
michael@0 1061 NS_NOTREACHED("Shouldn't ever be called");
michael@0 1062 return nullptr;
michael@0 1063 }
michael@0 1064
michael@0 1065 NS_IMETHODIMP
michael@0 1066 nsGenericDOMDataNode::WalkContentStyleRules(nsRuleWalker* aRuleWalker)
michael@0 1067 {
michael@0 1068 return NS_OK;
michael@0 1069 }
michael@0 1070
michael@0 1071 NS_IMETHODIMP_(bool)
michael@0 1072 nsGenericDOMDataNode::IsAttributeMapped(const nsIAtom* aAttribute) const
michael@0 1073 {
michael@0 1074 return false;
michael@0 1075 }
michael@0 1076
michael@0 1077 nsChangeHint
michael@0 1078 nsGenericDOMDataNode::GetAttributeChangeHint(const nsIAtom* aAttribute,
michael@0 1079 int32_t aModType) const
michael@0 1080 {
michael@0 1081 NS_NOTREACHED("Shouldn't be calling this!");
michael@0 1082 return nsChangeHint(0);
michael@0 1083 }
michael@0 1084
michael@0 1085 nsIAtom*
michael@0 1086 nsGenericDOMDataNode::GetClassAttributeName() const
michael@0 1087 {
michael@0 1088 return nullptr;
michael@0 1089 }
michael@0 1090
michael@0 1091 size_t
michael@0 1092 nsGenericDOMDataNode::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
michael@0 1093 {
michael@0 1094 size_t n = nsIContent::SizeOfExcludingThis(aMallocSizeOf);
michael@0 1095 n += mText.SizeOfExcludingThis(aMallocSizeOf);
michael@0 1096 return n;
michael@0 1097 }
michael@0 1098

mercurial