gecko-dev/dom/base/ScriptableContentIterator.cpp
Masayuki Nakano f421d7b889 Bug 181137 - part 8: Make ContentIteratorBase and its subclasses non-refcountable r=smaug
This patch makes ContentIteratorBase, PostContentIterator, PreContentIterator
and ContentSubtreeIterator classes non-refcountable because most users can
create their instances in stack and such users may be in a hot path.  So,
we can save a lot of cost of instantiation.

Unfortunately, only ScriptableContentIterator creates one of the concrete
classes and needs to destroy it properly.  Therefore, its
EnsureContentIterator(), destructor, traverse and unlink code becomes messy.
However, ScriptableContentIterator was designed for automated tests and we
need to maintain it not so many times.  Therefore, improvement of other
users must be worthwhiler than this demerit.

Differential Revision: https://phabricator.services.mozilla.com/D15928

--HG--
extra : moz-landing-system : lando
2019-01-11 01:52:26 +00:00

190 lines
5.3 KiB
C++

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "ScriptableContentIterator.h"
#include "mozilla/ContentIterator.h"
#include "nsINode.h"
#include "nsRange.h"
namespace mozilla {
NS_IMPL_CYCLE_COLLECTING_ADDREF(ScriptableContentIterator)
NS_IMPL_CYCLE_COLLECTING_RELEASE(ScriptableContentIterator)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ScriptableContentIterator)
NS_INTERFACE_MAP_ENTRY(nsIScriptableContentIterator)
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
NS_IMPL_CYCLE_COLLECTION_CLASS(ScriptableContentIterator)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ScriptableContentIterator)
if (tmp->mContentIterator) {
switch (tmp->mIteratorType) {
case POST_ORDER_ITERATOR:
default:
ImplCycleCollectionUnlink(
static_cast<PostContentIterator&>(*tmp->mContentIterator));
break;
case PRE_ORDER_ITERATOR:
ImplCycleCollectionUnlink(
static_cast<PreContentIterator&>(*tmp->mContentIterator));
break;
case SUBTREE_ITERATOR:
ImplCycleCollectionUnlink(
static_cast<ContentSubtreeIterator&>(*tmp->mContentIterator));
break;
}
}
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(ScriptableContentIterator)
if (tmp->mContentIterator) {
switch (tmp->mIteratorType) {
case POST_ORDER_ITERATOR:
default:
ImplCycleCollectionTraverse(
cb, static_cast<PostContentIterator&>(*tmp->mContentIterator),
"mContentIterator");
break;
case PRE_ORDER_ITERATOR:
ImplCycleCollectionTraverse(
cb, static_cast<PreContentIterator&>(*tmp->mContentIterator),
"mContentIterator");
break;
case SUBTREE_ITERATOR:
ImplCycleCollectionTraverse(
cb, static_cast<ContentSubtreeIterator&>(*tmp->mContentIterator),
"mContentIterator");
break;
}
}
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
ScriptableContentIterator::ScriptableContentIterator()
: mIteratorType(NOT_INITIALIZED) {}
void ScriptableContentIterator::EnsureContentIterator() {
if (mContentIterator) {
return;
}
switch (mIteratorType) {
case POST_ORDER_ITERATOR:
default:
mContentIterator = MakeUnique<PostContentIterator>();
break;
case PRE_ORDER_ITERATOR:
mContentIterator = MakeUnique<PreContentIterator>();
break;
case SUBTREE_ITERATOR:
mContentIterator = MakeUnique<ContentSubtreeIterator>();
break;
}
}
NS_IMETHODIMP
ScriptableContentIterator::InitWithRootNode(IteratorType aType,
nsINode* aRoot) {
if (aType == NOT_INITIALIZED ||
(mIteratorType != NOT_INITIALIZED && aType != mIteratorType)) {
return NS_ERROR_INVALID_ARG;
}
mIteratorType = aType;
EnsureContentIterator();
return mContentIterator->Init(aRoot);
}
NS_IMETHODIMP
ScriptableContentIterator::InitWithRange(IteratorType aType, nsRange* aRange) {
if (aType == NOT_INITIALIZED ||
(mIteratorType != NOT_INITIALIZED && aType != mIteratorType)) {
return NS_ERROR_INVALID_ARG;
}
mIteratorType = aType;
EnsureContentIterator();
return mContentIterator->Init(aRange);
}
NS_IMETHODIMP
ScriptableContentIterator::InitWithPositions(IteratorType aType,
nsINode* aStartContainer,
uint32_t aStartOffset,
nsINode* aEndContainer,
uint32_t aEndOffset) {
if (aType == NOT_INITIALIZED ||
(mIteratorType != NOT_INITIALIZED && aType != mIteratorType)) {
return NS_ERROR_INVALID_ARG;
}
mIteratorType = aType;
EnsureContentIterator();
return mContentIterator->Init(aStartContainer, aStartOffset, aEndContainer,
aEndOffset);
}
NS_IMETHODIMP
ScriptableContentIterator::First() {
if (!mContentIterator) {
return NS_ERROR_NOT_INITIALIZED;
}
mContentIterator->First();
return NS_OK;
}
NS_IMETHODIMP
ScriptableContentIterator::Last() {
if (!mContentIterator) {
return NS_ERROR_NOT_INITIALIZED;
}
mContentIterator->Last();
return NS_OK;
}
NS_IMETHODIMP
ScriptableContentIterator::Next() {
if (!mContentIterator) {
return NS_ERROR_NOT_INITIALIZED;
}
mContentIterator->Next();
return NS_OK;
}
NS_IMETHODIMP
ScriptableContentIterator::Prev() {
if (!mContentIterator) {
return NS_ERROR_NOT_INITIALIZED;
}
mContentIterator->Prev();
return NS_OK;
}
NS_IMETHODIMP
ScriptableContentIterator::GetCurrentNode(nsINode** aNode) {
if (!mContentIterator) {
return NS_ERROR_NOT_INITIALIZED;
}
NS_IF_ADDREF(*aNode = mContentIterator->GetCurrentNode());
return NS_OK;
}
NS_IMETHODIMP
ScriptableContentIterator::GetIsDone(bool* aIsDone) {
if (!mContentIterator) {
return NS_ERROR_NOT_INITIALIZED;
}
*aIsDone = mContentIterator->IsDone();
return NS_OK;
}
NS_IMETHODIMP
ScriptableContentIterator::PositionAt(nsINode* aNode) {
if (!mContentIterator) {
return NS_ERROR_NOT_INITIALIZED;
}
return mContentIterator->PositionAt(aNode);
}
} // namespace mozilla