Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/base/nsContentList.h
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
3
/* This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
/*
8
 * nsBaseContentList is a basic list of content nodes; nsContentList
9
 * is a commonly used NodeList implementation (used for
10
 * getElementsByTagName, some properties on HTMLDocument/Document, etc).
11
 */
12
13
#ifndef nsContentList_h___
14
#define nsContentList_h___
15
16
#include "mozilla/Attributes.h"
17
#include "nsContentListDeclarations.h"
18
#include "nsISupports.h"
19
#include "nsTArray.h"
20
#include "nsString.h"
21
#include "nsIHTMLCollection.h"
22
#include "nsINodeList.h"
23
#include "nsStubMutationObserver.h"
24
#include "nsAtom.h"
25
#include "nsCycleCollectionParticipant.h"
26
#include "nsNameSpaceManager.h"
27
#include "nsWrapperCache.h"
28
#include "nsHashKeys.h"
29
#include "mozilla/HashFunctions.h"
30
#include "mozilla/MemoryReporting.h"
31
#include "mozilla/dom/NameSpaceConstants.h"
32
33
namespace mozilla {
34
namespace dom {
35
class Element;
36
} // namespace dom
37
} // namespace mozilla
38
39
40
class nsBaseContentList : public nsINodeList
41
{
42
public:
43
  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
44
45
  // nsINodeList
46
  virtual int32_t IndexOf(nsIContent* aContent) override;
47
  virtual nsIContent* Item(uint32_t aIndex) override;
48
49
0
  uint32_t Length() override {
50
0
    return mElements.Length();
51
0
  }
52
53
  NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS(nsBaseContentList)
54
55
  void AppendElement(nsIContent *aContent)
56
0
  {
57
0
    mElements.AppendElement(aContent);
58
0
  }
59
  void MaybeAppendElement(nsIContent* aContent)
60
0
  {
61
0
    if (aContent)
62
0
      AppendElement(aContent);
63
0
  }
64
65
  /**
66
   * Insert the element at a given index, shifting the objects at
67
   * the given index and later to make space.
68
   * @param aContent Element to insert, must not be null
69
   * @param aIndex Index to insert the element at.
70
   */
71
  void InsertElementAt(nsIContent* aContent, int32_t aIndex)
72
0
  {
73
0
    NS_ASSERTION(aContent, "Element to insert must not be null");
74
0
    mElements.InsertElementAt(aIndex, aContent);
75
0
  }
76
77
  void RemoveElement(nsIContent *aContent)
78
0
  {
79
0
    mElements.RemoveElement(aContent);
80
0
  }
81
82
0
  void Reset() {
83
0
    mElements.Clear();
84
0
  }
85
86
  virtual int32_t IndexOf(nsIContent *aContent, bool aDoFlush);
87
88
  virtual JSObject* WrapObject(JSContext *cx, JS::Handle<JSObject*> aGivenProto)
89
    override = 0;
90
91
  void SetCapacity(uint32_t aCapacity)
92
0
  {
93
0
    mElements.SetCapacity(aCapacity);
94
0
  }
95
96
0
  virtual void LastRelease() {}
97
98
  // Memory reporting.  For now, subclasses of nsBaseContentList don't really
99
  // need to report any members that are not part of the object itself, so we
100
  // don't need to make this virtual.
101
  size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
102
103
protected:
104
  virtual ~nsBaseContentList();
105
106
  /**
107
   * To be called from non-destructor locations (e.g. unlink) that want to
108
   * remove from caches.  Cacheable subclasses should override.
109
   */
110
  virtual void RemoveFromCaches()
111
0
  {
112
0
  }
113
114
  AutoTArray<nsCOMPtr<nsIContent>, 10> mElements;
115
};
116
117
118
class nsSimpleContentList : public nsBaseContentList
119
{
120
public:
121
  explicit nsSimpleContentList(nsINode* aRoot) : nsBaseContentList(),
122
                                                 mRoot(aRoot)
123
0
  {
124
0
  }
125
126
  NS_DECL_ISUPPORTS_INHERITED
127
  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsSimpleContentList,
128
                                           nsBaseContentList)
129
130
  virtual nsINode* GetParentObject() override
131
0
  {
132
0
    return mRoot;
133
0
  }
134
  virtual JSObject* WrapObject(JSContext *cx, JS::Handle<JSObject*> aGivenProto) override;
135
136
protected:
137
0
  virtual ~nsSimpleContentList() {}
138
139
private:
140
  // This has to be a strong reference, the root might go away before the list.
141
  nsCOMPtr<nsINode> mRoot;
142
};
143
144
// Used for returning lists that will always be empty, such as the applets list
145
// in HTML Documents
146
class nsEmptyContentList final : public nsBaseContentList,
147
                                 public nsIHTMLCollection
148
{
149
public:
150
  explicit nsEmptyContentList(nsINode* aRoot) : nsBaseContentList(),
151
                                                mRoot(aRoot)
152
0
  {
153
0
  }
154
155
  NS_DECL_ISUPPORTS_INHERITED
156
  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsEmptyContentList,
157
                                           nsBaseContentList)
158
159
  virtual nsINode* GetParentObject() override
160
0
  {
161
0
    return mRoot;
162
0
  }
163
164
  virtual JSObject* WrapObject(JSContext *cx, JS::Handle<JSObject*> aGivenProto) override;
165
166
  virtual JSObject* GetWrapperPreserveColorInternal() override
167
0
  {
168
0
    return nsWrapperCache::GetWrapperPreserveColor();
169
0
  }
170
  virtual void PreserveWrapperInternal(nsISupports* aScriptObjectHolder) override
171
0
  {
172
0
    nsWrapperCache::PreserveWrapper(aScriptObjectHolder);
173
0
  }
174
175
  uint32_t Length() final
176
0
  {
177
0
    return 0;
178
0
  }
179
  virtual nsIContent* Item(uint32_t aIndex) override;
180
  virtual mozilla::dom::Element* GetElementAt(uint32_t index) override;
181
  virtual mozilla::dom::Element*
182
  GetFirstNamedElement(const nsAString& aName, bool& aFound) override;
183
  virtual void GetSupportedNames(nsTArray<nsString>& aNames) override;
184
185
protected:
186
0
  virtual ~nsEmptyContentList() {}
187
private:
188
  // This has to be a strong reference, the root might go away before the list.
189
  nsCOMPtr<nsINode> mRoot;
190
};
191
192
/**
193
 * Class that's used as the key to hash nsContentList implementations
194
 * for fast retrieval
195
 */
196
struct nsContentListKey
197
{
198
  // We have to take an aIsHTMLDocument arg for two reasons:
199
  // 1) We don't want to include nsIDocument.h in this header.
200
  // 2) We need to do that to make nsContentList::RemoveFromHashtable
201
  //    work, because by the time it's called the document of the
202
  //    list's root node might have changed.
203
  nsContentListKey(nsINode* aRootNode,
204
                   int32_t aMatchNameSpaceId,
205
                   const nsAString& aTagname,
206
                   bool aIsHTMLDocument)
207
    : mRootNode(aRootNode),
208
      mMatchNameSpaceId(aMatchNameSpaceId),
209
      mTagname(aTagname),
210
      mIsHTMLDocument(aIsHTMLDocument),
211
      mHash(mozilla::AddToHash(mozilla::HashString(aTagname), mRootNode,
212
                               mMatchNameSpaceId, mIsHTMLDocument))
213
0
  {
214
0
  }
215
216
  nsContentListKey(const nsContentListKey& aContentListKey)
217
    : mRootNode(aContentListKey.mRootNode),
218
      mMatchNameSpaceId(aContentListKey.mMatchNameSpaceId),
219
      mTagname(aContentListKey.mTagname),
220
      mIsHTMLDocument(aContentListKey.mIsHTMLDocument),
221
      mHash(aContentListKey.mHash)
222
0
  {
223
0
  }
224
225
  inline uint32_t GetHash(void) const
226
0
  {
227
0
    return mHash;
228
0
  }
229
230
  nsINode* const mRootNode; // Weak ref
231
  const int32_t mMatchNameSpaceId;
232
  const nsAString& mTagname;
233
  bool mIsHTMLDocument;
234
  const uint32_t mHash;
235
};
236
237
/**
238
 * LIST_UP_TO_DATE means that the list is up to date and need not do
239
 * any walking to be able to answer any questions anyone may have.
240
 */
241
0
#define LIST_UP_TO_DATE 0
242
/**
243
 * LIST_DIRTY means that the list contains no useful information and
244
 * if anyone asks it anything it will have to populate itself before
245
 * answering.
246
 */
247
0
#define LIST_DIRTY 1
248
/**
249
 * LIST_LAZY means that the list has populated itself to a certain
250
 * extent and that that part of the list is still valid.  Requests for
251
 * things outside that part of the list will require walking the tree
252
 * some more.  When a list is in this state, the last thing in
253
 * mElements is the last node in the tree that the list looked at.
254
 */
255
0
#define LIST_LAZY 2
256
257
/**
258
 * Class that implements a possibly live NodeList that matches Elements
259
 * in the tree based on some criterion.
260
 */
261
class nsContentList : public nsBaseContentList,
262
                      public nsIHTMLCollection,
263
                      public nsStubMutationObserver
264
{
265
public:
266
  NS_DECL_ISUPPORTS_INHERITED
267
268
  /**
269
   * @param aRootNode The node under which to limit our search.
270
   * @param aMatchAtom An atom whose meaning depends on aMatchNameSpaceId.
271
   *                   The special value "*" always matches whatever aMatchAtom
272
   *                   is matched against.
273
   * @param aMatchNameSpaceId If kNameSpaceID_Unknown, then aMatchAtom is the
274
   *                          tagName to match.
275
   *                          If kNameSpaceID_Wildcard, then aMatchAtom is the
276
   *                          localName to match.
277
   *                          Otherwise we match nodes whose namespace is
278
   *                          aMatchNameSpaceId and localName matches
279
   *                          aMatchAtom.
280
   * @param aDeep If false, then look only at children of the root, nothing
281
   *              deeper.  If true, then look at the whole subtree rooted at
282
   *              our root.
283
   * @param aLiveList Whether the created list should be a live list observing
284
   *                  mutations to the DOM tree.
285
   */
286
  nsContentList(nsINode* aRootNode,
287
                int32_t aMatchNameSpaceId,
288
                nsAtom* aHTMLMatchAtom,
289
                nsAtom* aXMLMatchAtom,
290
                bool aDeep = true,
291
                bool aLiveList = true);
292
293
  /**
294
   * @param aRootNode The node under which to limit our search.
295
   * @param aFunc the function to be called to determine whether we match.
296
   *              This function MUST NOT ever cause mutation of the DOM.
297
   *              The nsContentList implementation guarantees that everything
298
   *              passed to the function will be IsElement().
299
   * @param aDestroyFunc the function that will be called to destroy aData
300
   * @param aData closure data that will need to be passed back to aFunc
301
   * @param aDeep If false, then look only at children of the root, nothing
302
   *              deeper.  If true, then look at the whole subtree rooted at
303
   *              our root.
304
   * @param aMatchAtom an atom to be passed back to aFunc
305
   * @param aMatchNameSpaceId a namespace id to be passed back to aFunc
306
   * @param aFuncMayDependOnAttr a boolean that indicates whether this list is
307
   *                             sensitive to attribute changes.
308
   * @param aLiveList Whether the created list should be a live list observing
309
   *                  mutations to the DOM tree.
310
   */
311
  nsContentList(nsINode* aRootNode,
312
                nsContentListMatchFunc aFunc,
313
                nsContentListDestroyFunc aDestroyFunc,
314
                void* aData,
315
                bool aDeep = true,
316
                nsAtom* aMatchAtom = nullptr,
317
                int32_t aMatchNameSpaceId = kNameSpaceID_None,
318
                bool aFuncMayDependOnAttr = true,
319
                bool aLiveList = true);
320
321
  // nsWrapperCache
322
  using nsWrapperCache::GetWrapperPreserveColor;
323
  using nsWrapperCache::PreserveWrapper;
324
  virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
325
protected:
326
  virtual ~nsContentList();
327
328
  virtual JSObject* GetWrapperPreserveColorInternal() override
329
0
  {
330
0
    return nsWrapperCache::GetWrapperPreserveColor();
331
0
  }
332
  virtual void PreserveWrapperInternal(nsISupports* aScriptObjectHolder) override
333
0
  {
334
0
    nsWrapperCache::PreserveWrapper(aScriptObjectHolder);
335
0
  }
336
public:
337
338
  // nsBaseContentList overrides
339
  virtual int32_t IndexOf(nsIContent *aContent, bool aDoFlush) override;
340
  virtual int32_t IndexOf(nsIContent* aContent) override;
341
  virtual nsINode* GetParentObject() override
342
0
  {
343
0
    return mRootNode;
344
0
  }
345
346
  uint32_t Length() final
347
0
  {
348
0
    return Length(true);
349
0
  }
350
  nsIContent* Item(uint32_t aIndex) final;
351
  virtual mozilla::dom::Element* GetElementAt(uint32_t index) override;
352
  virtual mozilla::dom::Element*
353
  GetFirstNamedElement(const nsAString& aName, bool& aFound) override
354
0
  {
355
0
    mozilla::dom::Element* item = NamedItem(aName, true);
356
0
    aFound = !!item;
357
0
    return item;
358
0
  }
359
  virtual void GetSupportedNames(nsTArray<nsString>& aNames) override;
360
361
  // nsContentList public methods
362
  uint32_t Length(bool aDoFlush);
363
  nsIContent* Item(uint32_t aIndex, bool aDoFlush);
364
  mozilla::dom::Element*
365
  NamedItem(const nsAString& aName, bool aDoFlush);
366
367
  // nsIMutationObserver
368
  NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
369
  NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
370
  NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
371
  NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
372
  NS_DECL_NSIMUTATIONOBSERVER_NODEWILLBEDESTROYED
373
374
  static nsContentList* FromSupports(nsISupports* aSupports)
375
0
  {
376
0
    nsINodeList* list = static_cast<nsINodeList*>(aSupports);
377
0
#ifdef DEBUG
378
0
    {
379
0
      nsCOMPtr<nsINodeList> list_qi = do_QueryInterface(aSupports);
380
0
381
0
      // If this assertion fires the QI implementation for the object in
382
0
      // question doesn't use the nsINodeList pointer as the nsISupports
383
0
      // pointer. That must be fixed, or we'll crash...
384
0
      NS_ASSERTION(list_qi == list, "Uh, fix QI!");
385
0
    }
386
0
#endif
387
0
    return static_cast<nsContentList*>(list);
388
0
  }
389
390
  bool MatchesKey(const nsContentListKey& aKey) const
391
0
  {
392
0
    // The root node is most commonly the same: the document.  And the
393
0
    // most common namespace id is kNameSpaceID_Unknown.  So check the
394
0
    // string first.  Cases in which whether our root's ownerDocument
395
0
    // is HTML changes are extremely rare, so check those last.
396
0
    MOZ_ASSERT(mXMLMatchAtom,
397
0
               "How did we get here with a null match atom on our list?");
398
0
    return
399
0
      mXMLMatchAtom->Equals(aKey.mTagname) &&
400
0
      mRootNode == aKey.mRootNode &&
401
0
      mMatchNameSpaceId == aKey.mMatchNameSpaceId &&
402
0
      mIsHTMLDocument == aKey.mIsHTMLDocument;
403
0
  }
404
405
  /**
406
   * Sets the state to LIST_DIRTY and clears mElements array.
407
   * @note This is the only acceptable way to set state to LIST_DIRTY.
408
   */
409
  void SetDirty()
410
0
  {
411
0
    mState = LIST_DIRTY;
412
0
    Reset();
413
0
  }
414
415
  virtual void LastRelease() override;
416
417
protected:
418
  /**
419
   * Returns whether the element matches our criterion
420
   *
421
   * @param  aElement the element to attempt to match
422
   * @return whether we match
423
   */
424
  bool Match(mozilla::dom::Element *aElement);
425
  /**
426
   * See if anything in the subtree rooted at aContent, including
427
   * aContent itself, matches our criterion.
428
   *
429
   * @param  aContent the root of the subtree to match against
430
   * @return whether we match something in the tree rooted at aContent
431
   */
432
  bool MatchSelf(nsIContent *aContent);
433
434
  /**
435
   * Populate our list.  Stop once we have at least aNeededLength
436
   * elements.  At the end of PopulateSelf running, either the last
437
   * node we examined is the last node in our array or we have
438
   * traversed the whole document (or both).
439
   *
440
   * @param aNeededLength the length the list should have when we are
441
   *        done (unless it exhausts the document)
442
   * @param aExpectedElementsIfDirty is for debugging only to
443
   *        assert that mElements has expected number of entries.
444
   */
445
  virtual void PopulateSelf(uint32_t aNeededLength,
446
                            uint32_t aExpectedElementsIfDirty = 0);
447
448
  /**
449
   * @param  aContainer a content node which must be a descendant of
450
   *         mRootNode
451
   * @return true if children or descendants of aContainer could match our
452
   *                 criterion.
453
   *         false otherwise.
454
   */
455
  bool MayContainRelevantNodes(nsINode* aContainer)
456
0
  {
457
0
    return mDeep || aContainer == mRootNode;
458
0
  }
459
460
  /**
461
   * Remove ourselves from the hashtable that caches commonly accessed
462
   * content lists.  Generally done on destruction.
463
   */
464
  void RemoveFromHashtable();
465
  /**
466
   * If state is not LIST_UP_TO_DATE, fully populate ourselves with
467
   * all the nodes we can find.
468
   */
469
  inline void BringSelfUpToDate(bool aDoFlush);
470
471
  /**
472
   * To be called from non-destructor locations that want to remove from caches.
473
   * Needed because if subclasses want to have cache behavior they can't just
474
   * override RemoveFromHashtable(), since we call that in our destructor.
475
   */
476
  virtual void RemoveFromCaches() override
477
0
  {
478
0
    RemoveFromHashtable();
479
0
  }
480
481
  nsINode* mRootNode; // Weak ref
482
  int32_t mMatchNameSpaceId;
483
  RefPtr<nsAtom> mHTMLMatchAtom;
484
  RefPtr<nsAtom> mXMLMatchAtom;
485
486
  /**
487
   * Function to use to determine whether a piece of content matches
488
   * our criterion
489
   */
490
  nsContentListMatchFunc mFunc;
491
  /**
492
   * Cleanup closure data with this.
493
   */
494
  nsContentListDestroyFunc mDestroyFunc;
495
  /**
496
   * Closure data to pass to mFunc when we call it
497
   */
498
  void* mData;
499
  /**
500
   * The current state of the list (possible values are:
501
   * LIST_UP_TO_DATE, LIST_LAZY, LIST_DIRTY
502
   */
503
  uint8_t mState;
504
505
  // The booleans have to use uint8_t to pack with mState, because MSVC won't
506
  // pack different typedefs together.  Once we no longer have to worry about
507
  // flushes in XML documents, we can go back to using bool for the
508
  // booleans.
509
510
  /**
511
   * True if we are looking for elements named "*"
512
   */
513
  uint8_t mMatchAll : 1;
514
  /**
515
   * Whether to actually descend the tree.  If this is false, we won't
516
   * consider grandkids of mRootNode.
517
   */
518
  uint8_t mDeep : 1;
519
  /**
520
   * Whether the return value of mFunc could depend on the values of
521
   * attributes.
522
   */
523
  uint8_t mFuncMayDependOnAttr : 1;
524
  /**
525
   * Whether we actually need to flush to get our state correct.
526
   */
527
  uint8_t mFlushesNeeded : 1;
528
  /**
529
   * Whether the ownerDocument of our root node at list creation time was an
530
   * HTML document.  Only needed when we're doing a namespace/atom match, not
531
   * when doing function matching, always false otherwise.
532
   */
533
  uint8_t mIsHTMLDocument : 1;
534
  /**
535
   * Whether the list observes mutations to the DOM tree.
536
   */
537
  const uint8_t mIsLiveList : 1;
538
539
#ifdef DEBUG_CONTENT_LIST
540
  void AssertInSync();
541
#endif
542
};
543
544
/**
545
 * A class of cacheable content list; cached on the combination of aRootNode + aFunc + aDataString
546
 */
547
class nsCacheableFuncStringContentList;
548
549
class MOZ_STACK_CLASS nsFuncStringCacheKey {
550
public:
551
  nsFuncStringCacheKey(nsINode* aRootNode,
552
                       nsContentListMatchFunc aFunc,
553
                       const nsAString& aString) :
554
    mRootNode(aRootNode),
555
    mFunc(aFunc),
556
    mString(aString)
557
0
    {}
558
559
  uint32_t GetHash(void) const
560
0
  {
561
0
    uint32_t hash = mozilla::HashString(mString);
562
0
    return mozilla::AddToHash(hash, mRootNode, mFunc);
563
0
  }
564
565
private:
566
  friend class nsCacheableFuncStringContentList;
567
568
  nsINode* const mRootNode;
569
  const nsContentListMatchFunc mFunc;
570
  const nsAString& mString;
571
};
572
573
// aDestroyFunc is allowed to be null
574
// aDataAllocator must always return a non-null pointer
575
class nsCacheableFuncStringContentList : public nsContentList {
576
public:
577
  virtual ~nsCacheableFuncStringContentList();
578
579
0
  bool Equals(const nsFuncStringCacheKey* aKey) {
580
0
    return mRootNode == aKey->mRootNode && mFunc == aKey->mFunc &&
581
0
      mString == aKey->mString;
582
0
  }
583
584
  enum ContentListType {
585
    eNodeList,
586
    eHTMLCollection
587
  };
588
#ifdef DEBUG
589
  ContentListType mType;
590
#endif
591
592
protected:
593
  nsCacheableFuncStringContentList(nsINode* aRootNode,
594
                                   nsContentListMatchFunc aFunc,
595
                                   nsContentListDestroyFunc aDestroyFunc,
596
                                   nsFuncStringContentListDataAllocator aDataAllocator,
597
                                   const nsAString& aString,
598
                                   mozilla::DebugOnly<ContentListType> aType) :
599
    nsContentList(aRootNode, aFunc, aDestroyFunc, nullptr),
600
#ifdef DEBUG
601
    mType(aType),
602
#endif
603
    mString(aString)
604
0
  {
605
0
    mData = (*aDataAllocator)(aRootNode, &mString);
606
0
    MOZ_ASSERT(mData);
607
0
  }
608
609
0
  virtual void RemoveFromCaches() override {
610
0
    RemoveFromFuncStringHashtable();
611
0
  }
612
  void RemoveFromFuncStringHashtable();
613
614
  nsString mString;
615
};
616
617
class nsCachableElementsByNameNodeList
618
  : public nsCacheableFuncStringContentList
619
{
620
public:
621
  nsCachableElementsByNameNodeList(nsINode* aRootNode,
622
                                   nsContentListMatchFunc aFunc,
623
                                   nsContentListDestroyFunc aDestroyFunc,
624
                                   nsFuncStringContentListDataAllocator aDataAllocator,
625
                                   const nsAString& aString)
626
    : nsCacheableFuncStringContentList(aRootNode, aFunc, aDestroyFunc,
627
                                       aDataAllocator, aString, eNodeList)
628
0
  {
629
0
  }
630
631
  NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
632
633
  virtual JSObject* WrapObject(JSContext *cx, JS::Handle<JSObject*> aGivenProto) override;
634
635
#ifdef DEBUG
636
  static const ContentListType sType;
637
#endif
638
};
639
640
class nsCacheableFuncStringHTMLCollection
641
  : public nsCacheableFuncStringContentList
642
{
643
public:
644
  nsCacheableFuncStringHTMLCollection(nsINode* aRootNode,
645
                                      nsContentListMatchFunc aFunc,
646
                                      nsContentListDestroyFunc aDestroyFunc,
647
                                      nsFuncStringContentListDataAllocator aDataAllocator,
648
                                      const nsAString& aString)
649
    : nsCacheableFuncStringContentList(aRootNode, aFunc, aDestroyFunc,
650
                                       aDataAllocator, aString, eHTMLCollection)
651
0
  {
652
0
  }
653
654
  virtual JSObject* WrapObject(JSContext *cx, JS::Handle<JSObject*> aGivenProto) override;
655
656
#ifdef DEBUG
657
  static const ContentListType sType;
658
#endif
659
};
660
661
class nsLabelsNodeList final : public nsContentList
662
{
663
public:
664
  nsLabelsNodeList(nsINode* aRootNode,
665
                   nsContentListMatchFunc aFunc,
666
                   nsContentListDestroyFunc aDestroyFunc,
667
                   void* aData)
668
    : nsContentList(aRootNode, aFunc, aDestroyFunc, aData)
669
0
  {
670
0
  }
671
672
  NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
673
  NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
674
  NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
675
  NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
676
677
  virtual JSObject* WrapObject(JSContext *cx, JS::Handle<JSObject*> aGivenProto) override;
678
679
 /**
680
  * Reset root, mutation observer, and clear content list
681
  * if the root has been changed.
682
  *
683
  * @param aRootNode The node under which to limit our search.
684
  */
685
  void MaybeResetRoot(nsINode* aRootNode);
686
687
private:
688
 /**
689
  * Start searching at the last one if we already have nodes, otherwise
690
  * start searching at the root.
691
  *
692
  * @param aNeededLength The list of length should have when we are
693
  *                      done (unless it exhausts the document).
694
  * @param aExpectedElementsIfDirty is for debugging only to
695
  *        assert that mElements has expected number of entries.
696
  */
697
  void PopulateSelf(uint32_t aNeededLength,
698
                    uint32_t aExpectedElementsIfDirty = 0) override;
699
};
700
#endif // nsContentList_h___