Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/base/nsRange.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
 * Implementation of the DOM Range object.
9
 */
10
11
#ifndef nsRange_h___
12
#define nsRange_h___
13
14
#include "nsCOMPtr.h"
15
#include "nsINode.h"
16
#include "nsIDocument.h"
17
#include "nsLayoutUtils.h"
18
#include "prmon.h"
19
#include "nsStubMutationObserver.h"
20
#include "nsWrapperCache.h"
21
#include "mozilla/Attributes.h"
22
#include "mozilla/GuardObjects.h"
23
#include "mozilla/LinkedList.h"
24
#include "mozilla/RangeBoundary.h"
25
26
namespace mozilla {
27
class ErrorResult;
28
namespace dom {
29
struct ClientRectsAndTexts;
30
class DocGroup;
31
class DocumentFragment;
32
class DOMRect;
33
class DOMRectList;
34
class InspectorFontFace;
35
class Selection;
36
} // namespace dom
37
} // namespace mozilla
38
39
class nsRange final : public nsStubMutationObserver,
40
                      public nsWrapperCache,
41
                      // For linking together selection-associated ranges.
42
                      public mozilla::LinkedListElement<nsRange>
43
{
44
  typedef mozilla::ErrorResult ErrorResult;
45
  typedef mozilla::dom::DocGroup DocGroup;
46
  typedef mozilla::dom::DOMRect DOMRect;
47
  typedef mozilla::dom::DOMRectList DOMRectList;
48
  typedef mozilla::RangeBoundary RangeBoundary;
49
  typedef mozilla::RawRangeBoundary RawRangeBoundary;
50
51
  virtual ~nsRange();
52
53
public:
54
  explicit nsRange(nsINode* aNode);
55
56
  static nsresult CreateRange(nsINode* aStartContainer,
57
                              uint32_t aStartOffset,
58
                              nsINode* aEndContainer,
59
                              uint32_t aEndOffset,
60
                              nsRange** aRange);
61
  static nsresult CreateRange(const RawRangeBoundary& aStart,
62
                              const RawRangeBoundary& aEnd,
63
                              nsRange** aRange);
64
65
  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
66
  NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsRange)
67
68
  nsrefcnt GetRefCount() const
69
0
  {
70
0
    return mRefCnt;
71
0
  }
72
73
  nsINode* GetRoot() const
74
0
  {
75
0
    return mRoot;
76
0
  }
77
78
  const RangeBoundary& StartRef() const
79
0
  {
80
0
    return mStart;
81
0
  }
82
83
  nsINode* GetStartContainer() const
84
0
  {
85
0
    return mStart.Container();
86
0
  }
87
88
  const RangeBoundary& EndRef() const
89
0
  {
90
0
    return mEnd;
91
0
  }
92
93
  nsINode* GetEndContainer() const
94
0
  {
95
0
    return mEnd.Container();
96
0
  }
97
98
  uint32_t StartOffset() const
99
0
  {
100
0
    return static_cast<uint32_t>(mStart.Offset());
101
0
  }
102
103
  uint32_t EndOffset() const
104
0
  {
105
0
    return static_cast<uint32_t>(mEnd.Offset());
106
0
  }
107
108
  nsIContent* GetChildAtStartOffset() const
109
0
  {
110
0
    return mStart.GetChildAtOffset();
111
0
  }
112
113
  nsIContent* GetChildAtEndOffset() const
114
0
  {
115
0
    return mEnd.GetChildAtOffset();
116
0
  }
117
118
  bool IsPositioned() const
119
0
  {
120
0
    return mIsPositioned;
121
0
  }
122
123
  /**
124
   * Return true iff this range is part of a Selection object
125
   * and isn't detached.
126
   */
127
  bool IsInSelection() const
128
0
  {
129
0
    return !!mSelection;
130
0
  }
131
132
  /**
133
   * Called when the range is added/removed from a Selection.
134
   */
135
  void SetSelection(mozilla::dom::Selection* aSelection);
136
137
  /**
138
   * Returns pointer to a Selection if the range is associated with a Selection.
139
   */
140
0
  mozilla::dom::Selection* GetSelection() const { return mSelection; }
141
142
  /**
143
   * Return true if this range was generated.
144
   * @see SetIsGenerated
145
   */
146
  bool IsGenerated() const
147
0
  {
148
0
    return mIsGenerated;
149
0
  }
150
151
  /**
152
   * Mark this range as being generated or not.
153
   * Currently it is used for marking ranges that are created when splitting up
154
   * a range to exclude a -moz-user-select:none region.
155
   * @see Selection::AddItem
156
   * @see ExcludeNonSelectableNodes
157
   */
158
  void SetIsGenerated(bool aIsGenerated)
159
0
  {
160
0
    mIsGenerated = aIsGenerated;
161
0
  }
162
163
  nsINode* GetCommonAncestor() const;
164
  void Reset();
165
166
  /**
167
   * ResetTemporarily() is called when Selection starts to cache the instance
168
   * to reuse later.  This method clears mStart, mEnd and mIsPositioned but
169
   * does not clear mRoot for reducing the cost to register this as a mutation
170
   * observer again.
171
   */
172
  void ResetTemporarily()
173
0
  {
174
0
    DoSetRange(RawRangeBoundary(), RawRangeBoundary(), mRoot);
175
0
  }
176
177
  /**
178
   * SetStart() and SetEnd() sets start point or end point separately.
179
   * However, this is expensive especially when it's a range of Selection.
180
   * When you set both start and end of a range, you should use
181
   * SetStartAndEnd() instead.
182
   */
183
  nsresult SetStart(nsINode* aContainer, uint32_t aOffset)
184
0
  {
185
0
    ErrorResult error;
186
0
    SetStart(RawRangeBoundary(aContainer, aOffset), error);
187
0
    return error.StealNSResult();
188
0
  }
189
  nsresult SetEnd(nsINode* aContainer, uint32_t aOffset)
190
0
  {
191
0
    ErrorResult error;
192
0
    SetEnd(RawRangeBoundary(aContainer, aOffset), error);
193
0
    return error.StealNSResult();
194
0
  }
195
196
  already_AddRefed<nsRange> CloneRange() const;
197
198
  /**
199
   * SetStartAndEnd() works similar to call both SetStart() and SetEnd().
200
   * Different from calls them separately, this does nothing if either
201
   * the start point or the end point is invalid point.
202
   * If the specified start point is after the end point, the range will be
203
   * collapsed at the end point.  Similarly, if they are in different root,
204
   * the range will be collapsed at the end point.
205
   */
206
  nsresult SetStartAndEnd(nsINode* aStartContainer, uint32_t aStartOffset,
207
                          nsINode* aEndContainer, uint32_t aEndOffset)
208
0
  {
209
0
    return SetStartAndEnd(RawRangeBoundary(aStartContainer, aStartOffset),
210
0
                          RawRangeBoundary(aEndContainer, aEndOffset));
211
0
  }
212
  nsresult SetStartAndEnd(const RawRangeBoundary& aStart,
213
                          const RawRangeBoundary& aEnd);
214
215
  /**
216
   * Adds all nodes between |aStartContent| and |aEndContent| to the range.
217
   * The start offset will be set before |aStartContent|,
218
   * while the end offset will be set immediately after |aEndContent|.
219
   *
220
   * Caller must guarantee both nodes are non null and
221
   * children of |aContainer| and that |aEndContent| is after |aStartContent|.
222
   */
223
  void
224
  SelectNodesInContainer(nsINode* aContainer,
225
                         nsIContent* aStartContent,
226
                         nsIContent* aEndContent);
227
228
  /**
229
   * CollapseTo() works similar to call both SetStart() and SetEnd() with
230
   * same node and offset.  This just calls SetStartAndParent() to set
231
   * collapsed range at aContainer and aOffset.
232
   */
233
  nsresult CollapseTo(nsINode* aContainer, uint32_t aOffset)
234
0
  {
235
0
    return CollapseTo(RawRangeBoundary(aContainer, aOffset));
236
0
  }
237
  nsresult CollapseTo(const RawRangeBoundary& aPoint)
238
0
  {
239
0
    return SetStartAndEnd(aPoint, aPoint);
240
0
  }
241
242
  /**
243
   * Retrieves node and offset for setting start or end of a range to
244
   * before or after aNode.
245
   */
246
  static nsINode* GetContainerAndOffsetAfter(nsINode* aNode, uint32_t* aOffset)
247
0
  {
248
0
    MOZ_ASSERT(aNode);
249
0
    MOZ_ASSERT(aOffset);
250
0
    *aOffset = 0;
251
0
    nsINode* parentNode = aNode->GetParentNode();
252
0
    if (!parentNode) {
253
0
      return nullptr;
254
0
    }
255
0
    int32_t indexInParent = parentNode->ComputeIndexOf(aNode);
256
0
    if (NS_WARN_IF(indexInParent < 0)) {
257
0
      return nullptr;
258
0
    }
259
0
    *aOffset = static_cast<uint32_t>(indexInParent) + 1;
260
0
    return parentNode;
261
0
  }
262
  static nsINode* GetContainerAndOffsetBefore(nsINode* aNode, uint32_t* aOffset)
263
0
  {
264
0
    MOZ_ASSERT(aNode);
265
0
    MOZ_ASSERT(aOffset);
266
0
    *aOffset = 0;
267
0
    nsINode* parentNode = aNode->GetParentNode();
268
0
    if (!parentNode) {
269
0
      return nullptr;
270
0
    }
271
0
    int32_t indexInParent = parentNode->ComputeIndexOf(aNode);
272
0
    if (NS_WARN_IF(indexInParent < 0)) {
273
0
      return nullptr;
274
0
    }
275
0
    *aOffset = static_cast<uint32_t>(indexInParent);
276
0
    return parentNode;
277
0
  }
278
279
  // aMaxRanges is the maximum number of text ranges to record for each face
280
  // (pass 0 to just get the list of faces, without recording exact ranges
281
  // where each face was used).
282
  nsresult GetUsedFontFaces(
283
      nsTArray<nsAutoPtr<mozilla::dom::InspectorFontFace>>& aResult,
284
      uint32_t aMaxRanges,
285
      bool aSkipCollapsedWhitespace);
286
287
  // nsIMutationObserver methods
288
  NS_DECL_NSIMUTATIONOBSERVER_CHARACTERDATACHANGED
289
  NS_DECL_NSIMUTATIONOBSERVER_CONTENTINSERTED
290
  NS_DECL_NSIMUTATIONOBSERVER_CONTENTREMOVED
291
  NS_DECL_NSIMUTATIONOBSERVER_PARENTCHAINCHANGED
292
  NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
293
294
  // WebIDL
295
  static already_AddRefed<nsRange>
296
  Constructor(const mozilla::dom::GlobalObject& global,
297
              mozilla::ErrorResult& aRv);
298
299
  bool Collapsed() const
300
0
  {
301
0
    return mIsPositioned && mStart.Container() == mEnd.Container() &&
302
0
           mStart.Offset() == mEnd.Offset();
303
0
  }
304
  already_AddRefed<mozilla::dom::DocumentFragment>
305
  CreateContextualFragment(const nsAString& aString, ErrorResult& aError);
306
  already_AddRefed<mozilla::dom::DocumentFragment>
307
  CloneContents(ErrorResult& aErr);
308
  int16_t CompareBoundaryPoints(uint16_t aHow, nsRange& aOther,
309
                                ErrorResult& aErr);
310
  int16_t ComparePoint(nsINode& aContainer, uint32_t aOffset,
311
                       ErrorResult& aErr)
312
0
  {
313
0
    return ComparePoint(RawRangeBoundary(&aContainer, aOffset), aErr);
314
0
  }
315
  int16_t ComparePoint(const RawRangeBoundary& aPoint, ErrorResult& aErr);
316
  void DeleteContents(ErrorResult& aRv);
317
  already_AddRefed<mozilla::dom::DocumentFragment>
318
    ExtractContents(ErrorResult& aErr);
319
  nsINode* GetCommonAncestorContainer(ErrorResult& aRv) const;
320
  nsINode* GetStartContainer(ErrorResult& aRv) const;
321
  uint32_t GetStartOffset(ErrorResult& aRv) const;
322
  nsINode* GetEndContainer(ErrorResult& aRv) const;
323
  uint32_t GetEndOffset(ErrorResult& aRv) const;
324
  void InsertNode(nsINode& aNode, ErrorResult& aErr);
325
  bool IntersectsNode(nsINode& aNode, ErrorResult& aRv);
326
  bool IsPointInRange(nsINode& aContainer, uint32_t aOffset, ErrorResult& aErr)
327
0
  {
328
0
    return IsPointInRange(RawRangeBoundary(&aContainer, aOffset), aErr);
329
0
  }
330
  bool IsPointInRange(const RawRangeBoundary& aPoint, ErrorResult& aErr);
331
  void ToString(nsAString& aReturn, ErrorResult& aErr);
332
  void Detach();
333
334
  // *JS() methods are mapped to Range.*() of DOM.
335
  // They may move focus only when the range represents normal selection.
336
  // These methods shouldn't be used from internal.
337
  void CollapseJS(bool aToStart);
338
  void SelectNodeJS(nsINode& aNode, ErrorResult& aErr);
339
  void SelectNodeContentsJS(nsINode& aNode, ErrorResult& aErr);
340
  void SetEndJS(nsINode& aNode, uint32_t aOffset, ErrorResult& aErr);
341
  void SetEndAfterJS(nsINode& aNode, ErrorResult& aErr);
342
  void SetEndBeforeJS(nsINode& aNode, ErrorResult& aErr);
343
  void SetStartJS(nsINode& aNode, uint32_t aOffset, ErrorResult& aErr);
344
  void SetStartAfterJS(nsINode& aNode, ErrorResult& aErr);
345
  void SetStartBeforeJS(nsINode& aNode, ErrorResult& aErr);
346
347
  void SurroundContents(nsINode& aNode, ErrorResult& aErr);
348
  already_AddRefed<DOMRect> GetBoundingClientRect(bool aClampToEdge = true,
349
                                                  bool aFlushLayout = true);
350
  already_AddRefed<DOMRectList> GetClientRects(bool aClampToEdge = true,
351
                                               bool aFlushLayout = true);
352
  void GetClientRectsAndTexts(
353
    mozilla::dom::ClientRectsAndTexts& aResult,
354
    ErrorResult& aErr);
355
356
  // Following methods should be used for internal use instead of *JS().
357
  void SelectNode(nsINode& aNode, ErrorResult& aErr);
358
  void SelectNodeContents(nsINode& aNode, ErrorResult& aErr);
359
  void SetEnd(nsINode& aNode, uint32_t aOffset, ErrorResult& aErr);
360
  void SetEnd(const RawRangeBoundary& aPoint, ErrorResult& aErr);
361
  void SetEndAfter(nsINode& aNode, ErrorResult& aErr);
362
  void SetEndBefore(nsINode& aNode, ErrorResult& aErr);
363
  void SetStart(nsINode& aNode, uint32_t aOffset, ErrorResult& aErr);
364
  void SetStart(const RawRangeBoundary& aPoint, ErrorResult& aErr);
365
  void SetStartAfter(nsINode& aNode, ErrorResult& aErr);
366
  void SetStartBefore(nsINode& aNode, ErrorResult& aErr);
367
  void Collapse(bool aToStart);
368
369
  static void GetInnerTextNoFlush(mozilla::dom::DOMString& aValue,
370
                                  mozilla::ErrorResult& aError,
371
                                  nsIContent* aContainer);
372
373
0
  nsINode* GetParentObject() const { return mOwner; }
374
  JSObject* WrapObject(JSContext* cx, JS::Handle<JSObject*> aGivenProto) final;
375
  DocGroup* GetDocGroup() const;
376
377
private:
378
  // no copy's or assigns
379
  nsRange(const nsRange&);
380
  nsRange& operator=(const nsRange&);
381
382
  /**
383
   * Cut or delete the range's contents.
384
   *
385
   * @param aFragment DocumentFragment containing the nodes.
386
   *                  May be null to indicate the caller doesn't want a fragment.
387
   */
388
  nsresult CutContents(mozilla::dom::DocumentFragment** frag);
389
390
  static nsresult CloneParentsBetween(nsINode* aAncestor,
391
                                      nsINode* aNode,
392
                                      nsINode** aClosestAncestor,
393
                                      nsINode** aFarthestAncestor);
394
395
public:
396
  /**
397
   * Compute the root node of aNode for initializing range classes.
398
   * When aNode is in an anonymous subtree, this returns the shadow root or
399
   * binding parent.  Otherwise, the root node of the document or document
400
   * fragment.  If this returns nullptr, that means aNode can be neither the
401
   * start container nor end container of any range.
402
   */
403
  static nsINode* ComputeRootNode(nsINode* aNode);
404
405
  /**
406
   * Return true if aStartContainer/aStartOffset and aEndContainer/aEndOffset
407
   * are valid start and end points for a range.  Otherwise, return false.
408
   */
409
  static bool IsValidPoints(nsINode* aStartContainer, uint32_t aStartOffset,
410
                            nsINode* aEndContainer, uint32_t aEndOffset);
411
412
/******************************************************************************
413
 *  Utility routine to detect if a content node starts before a range and/or
414
 *  ends after a range.  If neither it is contained inside the range.
415
 *
416
 *  XXX - callers responsibility to ensure node in same doc as range!
417
 *
418
 *****************************************************************************/
419
  static nsresult CompareNodeToRange(nsINode* aNode, nsRange* aRange,
420
                                     bool *outNodeBefore,
421
                                     bool *outNodeAfter);
422
423
  /**
424
   * Return true if any part of (aNode, aStartOffset) .. (aNode, aEndOffset)
425
   * overlaps any nsRange in aNode's GetNextRangeCommonAncestor ranges (i.e.
426
   * where aNode is a descendant of a range's common ancestor node).
427
   * If a nsRange starts in (aNode, aEndOffset) or if it ends in
428
   * (aNode, aStartOffset) then it is non-overlapping and the result is false
429
   * for that nsRange.  Collapsed ranges always counts as non-overlapping.
430
   */
431
  static bool IsNodeSelected(nsINode* aNode, uint32_t aStartOffset,
432
                             uint32_t aEndOffset);
433
434
  /**
435
   * This helper function gets rects and correlated text for the given range.
436
   * @param aTextList optional where nullptr = don't retrieve text
437
   */
438
  static void CollectClientRectsAndText(nsLayoutUtils::RectCallback* aCollector,
439
                                        mozilla::dom::Sequence<nsString>* aTextList,
440
                                        nsRange* aRange,
441
                                        nsINode* aStartContainer,
442
                                        uint32_t aStartOffset,
443
                                        nsINode* aEndContainer,
444
                                        uint32_t aEndOffset,
445
                                        bool aClampToEdge, bool aFlushLayout);
446
447
  /**
448
   * Scan this range for -moz-user-select:none nodes and split it up into
449
   * multiple ranges to exclude those nodes.  The resulting ranges are put
450
   * in aOutRanges.  If no -moz-user-select:none node is found in the range
451
   * then |this| is unmodified and is the only range in aOutRanges.
452
   * Otherwise, |this| will be modified so that it ends before the first
453
   * -moz-user-select:none node and additional ranges may also be created.
454
   * If all nodes in the range are -moz-user-select:none then aOutRanges
455
   * will be empty.
456
   * @param aOutRanges the resulting set of ranges
457
   */
458
  void ExcludeNonSelectableNodes(nsTArray<RefPtr<nsRange>>* aOutRanges);
459
460
  /**
461
   * Notify the selection listeners after a range has been modified.
462
   */
463
  MOZ_CAN_RUN_SCRIPT void NotifySelectionListenersAfterRangeSet();
464
465
  typedef nsTHashtable<nsPtrHashKey<nsRange> > RangeHashTable;
466
protected:
467
468
  void RegisterCommonAncestor(nsINode* aNode);
469
  void UnregisterCommonAncestor(nsINode* aNode, bool aIsUnlinking);
470
  nsINode* IsValidBoundary(nsINode* aNode) const
471
0
  {
472
0
    return ComputeRootNode(aNode);
473
0
  }
474
475
  /**
476
   * XXX nsRange should accept 0 - UINT32_MAX as offset.  However, users of
477
   *     nsRange treat offset as int32_t.  Additionally, some other internal
478
   *     APIs like nsINode::ComputeIndexOf() use int32_t.  Therefore,
479
   *     nsRange should accept only 0 - INT32_MAX as valid offset for now.
480
   */
481
  static bool IsValidOffset(uint32_t aOffset)
482
0
  {
483
0
    return aOffset <= INT32_MAX;
484
0
  }
485
  static bool IsValidOffset(nsINode* aNode, uint32_t aOffset);
486
487
  // CharacterDataChanged set aNotInsertedYet to true to disable an assertion
488
  // and suppress re-registering a range common ancestor node since
489
  // the new text node of a splitText hasn't been inserted yet.
490
  // CharacterDataChanged does the re-registering when needed.
491
  MOZ_CAN_RUN_SCRIPT_BOUNDARY
492
  void DoSetRange(const RawRangeBoundary& lowerBound,
493
                  const RawRangeBoundary& upperBound,
494
                  nsINode* aRoot, bool aNotInsertedYet = false);
495
496
  /**
497
   * For a range for which IsInSelection() is true, return the common ancestor
498
   * for the range, which we had to compute when the common ancestor changed or
499
   * IsInSelection became true, so we could register with it.  That is, it's a
500
   * faster version of GetCommonAncestor that only works for ranges in a
501
   * Selection.  The method will assert and the behavior is undefined if called
502
   * on a range where IsInSelection() is false.
503
   */
504
  nsINode* GetRegisteredCommonAncestor();
505
506
  // Helper to IsNodeSelected.
507
  static bool IsNodeInSortedRanges(nsINode* aNode,
508
                                   uint32_t aStartOffset,
509
                                   uint32_t aEndOffset,
510
                                   const nsTArray<const nsRange*>& aRanges,
511
                                   size_t aRangeStart,
512
                                   size_t aRangeEnd);
513
514
  // Assume that this is guaranteed that this is held by the caller when
515
  // this is used.  (Note that we cannot use AutoRestore for mCalledByJS
516
  // due to a bit field.)
517
  class MOZ_RAII AutoCalledByJSRestore final
518
  {
519
  private:
520
    nsRange& mRange;
521
    bool mOldValue;
522
    MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
523
524
  public:
525
    explicit AutoCalledByJSRestore(nsRange& aRange
526
                                   MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
527
      : mRange(aRange)
528
      , mOldValue(aRange.mCalledByJS)
529
0
    {
530
0
      MOZ_GUARD_OBJECT_NOTIFIER_INIT;
531
0
    }
532
    ~AutoCalledByJSRestore()
533
0
    {
534
0
      mRange.mCalledByJS = mOldValue;
535
0
    }
536
0
    bool SavedValue() const { return mOldValue; }
537
  };
538
539
  struct MOZ_STACK_CLASS AutoInvalidateSelection
540
  {
541
    explicit AutoInvalidateSelection(nsRange* aRange) : mRange(aRange)
542
0
    {
543
0
      if (!mRange->IsInSelection() || sIsNested) {
544
0
        return;
545
0
      }
546
0
      sIsNested = true;
547
0
      mCommonAncestor = mRange->GetRegisteredCommonAncestor();
548
0
    }
549
    ~AutoInvalidateSelection();
550
    nsRange* mRange;
551
    RefPtr<nsINode> mCommonAncestor;
552
    static bool sIsNested;
553
  };
554
555
  nsCOMPtr<nsIDocument> mOwner;
556
  nsCOMPtr<nsINode> mRoot;
557
  // mRegisteredCommonAncestor is only non-null when the range
558
  // IsInSelection().  It's kept alive via mStartContainer/mEndContainer,
559
  // because we update it any time those could become disconnected from it.
560
  nsINode* MOZ_NON_OWNING_REF mRegisteredCommonAncestor;
561
  RefPtr<mozilla::dom::Selection> mSelection;
562
563
  // These raw pointers are used to remember a child that is about
564
  // to be inserted between a CharacterData call and a subsequent
565
  // ContentInserted or ContentAppended call. It is safe to store
566
  // these refs because the caller is guaranteed to trigger both
567
  // notifications while holding a strong reference to the new child.
568
  nsIContent* MOZ_NON_OWNING_REF mNextStartRef;
569
  nsIContent* MOZ_NON_OWNING_REF mNextEndRef;
570
571
  RangeBoundary mStart;
572
  RangeBoundary mEnd;
573
574
  bool mIsPositioned : 1;
575
  bool mIsGenerated : 1;
576
  bool mCalledByJS : 1;
577
};
578
579
#endif /* nsRange_h___ */