Bug 1944313 - Propagate XSLT expression failure correctly. r=farre, a=dmeehan

Differential Revision: https://phabricator.services.mozilla.com/D235895
This commit is contained in:
Peter Van der Beken 2025-02-04 17:28:39 +00:00
parent 90e6ebd641
commit 26960c9b19
4 changed files with 60 additions and 92 deletions

View file

@ -92,8 +92,12 @@ nsresult txNodeSorter::addSortElement(Expr* aSelectExpr, Expr* aLangExpr,
}
}
key->mComparator =
new txResultStringComparator(ascending, upperFirst, lang);
UniquePtr<txResultStringComparator> comparator =
MakeUnique<txResultStringComparator>(ascending, upperFirst);
rv = comparator->init(lang);
NS_ENSURE_SUCCESS(rv, rv);
key->mComparator = comparator.release();
} else if (TX_StringEqualsAtom(dataType, nsGkAtoms::number)) {
// Number comparator
key->mComparator = new txResultNumberComparator(ascending);
@ -134,7 +138,7 @@ nsresult txNodeSorter::sortNodeSet(txNodeSet* aNodes, txExecutionState* aEs,
nsTArray<uint32_t> indexes(len.value());
indexes.SetLengthAndRetainStorage(len.value());
nsTArray<txObject*> sortValues(numSortValues.value());
nsTArray<UniquePtr<txObject>> sortValues(numSortValues.value());
sortValues.SetLengthAndRetainStorage(numSortValues.value());
// txObject* has no null initializing constructor, so we init manually.
memset(sortValues.Elements(), 0, sortValuesSize.value());
@ -147,11 +151,7 @@ nsresult txNodeSorter::sortNodeSet(txNodeSet* aNodes, txExecutionState* aEs,
auto nodeSetContext = MakeUnique<txNodeSetContext>(aNodes, aEs);
// Sort the indexarray
SortData sortData{};
sortData.mNodeSorter = this;
sortData.mContext = nodeSetContext.get();
sortData.mSortValues = sortValues.Elements();
sortData.mRv = NS_OK;
SortData sortData{this, nodeSetContext.get(), sortValues.Elements(), NS_OK};
aEs->pushEvalContext(nodeSetContext.release());
@ -159,12 +159,6 @@ nsresult txNodeSorter::sortNodeSet(txNodeSet* aNodes, txExecutionState* aEs,
return compareNodes(left, right, sortData);
});
// Delete these here so we don't have to deal with them at every possible
// failurepoint
for (i = 0; i < numSortValues.value(); ++i) {
delete sortValues[i];
}
if (NS_FAILED(sortData.mRv)) {
// The txExecutionState owns the evalcontext so no need to handle it
return sortData.mRv;
@ -188,12 +182,10 @@ nsresult txNodeSorter::sortNodeSet(txNodeSet* aNodes, txExecutionState* aEs,
int txNodeSorter::compareNodes(uint32_t aIndexA, uint32_t aIndexB,
SortData& aSortData) {
NS_ENSURE_SUCCESS(aSortData.mRv, -1);
txListIterator iter(&aSortData.mNodeSorter->mSortKeys);
txObject** sortValuesA =
UniquePtr<txObject>* sortValuesA =
aSortData.mSortValues + aIndexA * aSortData.mNodeSorter->mNKeys;
txObject** sortValuesB =
UniquePtr<txObject>* sortValuesB =
aSortData.mSortValues + aIndexB * aSortData.mNodeSorter->mNKeys;
unsigned int i;
@ -201,19 +193,19 @@ int txNodeSorter::compareNodes(uint32_t aIndexA, uint32_t aIndexB,
for (i = 0; i < aSortData.mNodeSorter->mNKeys; ++i) {
SortKey* key = (SortKey*)iter.next();
// Lazy create sort values
if (!sortValuesA[i] &&
!calcSortValue(sortValuesA[i], key, &aSortData, aIndexA)) {
return -1;
if (!sortValuesA[i]) {
sortValuesA[i] = calcSortValue(key, &aSortData, aIndexA);
}
if (!sortValuesB[i] &&
!calcSortValue(sortValuesB[i], key, &aSortData, aIndexB)) {
return 1;
if (!sortValuesB[i]) {
sortValuesB[i] = calcSortValue(key, &aSortData, aIndexB);
}
// Compare node values
int compRes =
key->mComparator->compareValues(sortValuesA[i], sortValuesB[i]);
if (compRes != 0) return compRes;
int compRes = key->mComparator->compareValues(sortValuesA[i].get(),
sortValuesB[i].get());
if (compRes != 0) {
return compRes;
}
}
// All keys have the same value for these nodes.
@ -221,16 +213,18 @@ int txNodeSorter::compareNodes(uint32_t aIndexA, uint32_t aIndexB,
}
// static
bool txNodeSorter::calcSortValue(txObject*& aSortValue, SortKey* aKey,
SortData* aSortData, uint32_t aNodeIndex) {
UniquePtr<txObject> txNodeSorter::calcSortValue(SortKey* aKey,
SortData* aSortData,
uint32_t aNodeIndex) {
aSortData->mContext->setPosition(aNodeIndex + 1); // position is 1-based
nsresult rv = aKey->mComparator->createSortableValue(
aKey->mExpr, aSortData->mContext, aSortValue);
if (NS_FAILED(rv)) {
UniquePtr<txObject> sortValue;
nsresult rv;
std::tie(sortValue, rv) =
aKey->mComparator->createSortableValue(aKey->mExpr, aSortData->mContext);
if (NS_FAILED(rv) && NS_SUCCEEDED(aSortData->mRv)) {
// Record the first failure.
aSortData->mRv = rv;
return false;
}
return true;
return sortValue;
}

View file

@ -36,7 +36,7 @@ class txNodeSorter {
struct SortData {
txNodeSorter* mNodeSorter;
txNodeSetContext* mContext;
txObject** mSortValues;
mozilla::UniquePtr<txObject>* mSortValues;
nsresult mRv;
};
struct SortKey {
@ -46,8 +46,9 @@ class txNodeSorter {
static int compareNodes(uint32_t aIndexA, uint32_t aIndexB,
SortData& aSortData);
static bool calcSortValue(txObject*& aSortValue, SortKey* aKey,
SortData* aSortData, uint32_t aNodeIndex);
static mozilla::UniquePtr<txObject> calcSortValue(SortKey* aKey,
SortData* aSortData,
uint32_t aNodeIndex);
txList mSortKeys;
unsigned int mNKeys;
};

View file

@ -19,13 +19,10 @@ using Collator = mozilla::intl::Collator;
#define kUpperFirst (1 << 1)
txResultStringComparator::txResultStringComparator(bool aAscending,
bool aUpperFirst,
const nsString& aLanguage) {
bool aUpperFirst) {
mSorting = 0;
if (aAscending) mSorting |= kAscending;
if (aUpperFirst) mSorting |= kUpperFirst;
nsresult rv = init(aLanguage);
if (NS_FAILED(rv)) NS_ERROR("Failed to initialize txResultStringComparator");
}
nsresult txResultStringComparator::init(const nsString& aLanguage) {
@ -49,61 +46,35 @@ nsresult txResultStringComparator::init(const nsString& aLanguage) {
return NS_OK;
}
nsresult txResultStringComparator::createSortableValue(Expr* aExpr,
txIEvalContext* aContext,
txObject*& aResult) {
UniquePtr<StringValue> val(new StringValue);
if (!mCollator) {
return NS_ERROR_FAILURE;
}
val->mString = MakeUnique<nsString>();
nsString& string = *val->mString;
nsresult rv = aExpr->evaluateToString(aContext, string);
NS_ENSURE_SUCCESS(rv, rv);
aResult = val.release();
return NS_OK;
std::pair<UniquePtr<txObject>, nsresult>
txResultStringComparator::createSortableValue(Expr* aExpr,
txIEvalContext* aContext) {
UniquePtr<nsString> string = MakeUnique<nsString>();
nsresult rv = aExpr->evaluateToString(aContext, *string);
return std::make_pair(MakeUnique<StringValue>(std::move(string)), rv);
}
int txResultStringComparator::compareValues(txObject* aVal1, txObject* aVal2) {
nsString& dval1 = *((StringValue*)aVal1)->mString;
nsString& dval2 = *((StringValue*)aVal2)->mString;
if (!mCollator) {
MOZ_ASSERT_UNREACHABLE("No mCollator");
return -1;
}
int32_t result = mCollator->CompareStrings(dval1, dval2);
return (mSorting & kAscending) ? result : -result;
}
txResultStringComparator::StringValue::StringValue() = default;
txResultStringComparator::StringValue::~StringValue() = default;
txResultNumberComparator::txResultNumberComparator(bool aAscending) {
mAscending = aAscending ? 1 : -1;
}
nsresult txResultNumberComparator::createSortableValue(Expr* aExpr,
txIEvalContext* aContext,
txObject*& aResult) {
UniquePtr<NumberValue> numval(new NumberValue);
std::pair<UniquePtr<txObject>, nsresult>
txResultNumberComparator::createSortableValue(Expr* aExpr,
txIEvalContext* aContext) {
RefPtr<txAExprResult> exprRes;
nsresult rv = aExpr->evaluate(aContext, getter_AddRefs(exprRes));
NS_ENSURE_SUCCESS(rv, rv);
numval->mVal = exprRes->numberValue();
aResult = numval.release();
return NS_OK;
return std::make_pair(
MakeUnique<NumberValue>(NS_SUCCEEDED(rv) ? exprRes->numberValue() : 0),
rv);
}
int txResultNumberComparator::compareValues(txObject* aVal1, txObject* aVal2) {

View file

@ -31,10 +31,11 @@ class txXPathResultComparator {
virtual int compareValues(txObject* val1, txObject* val2) = 0;
/*
* Create a sortable value.
* Create a sortable value. This always needs to return a value, but can
* indicate failure in the nsresult.
*/
virtual nsresult createSortableValue(Expr* aExpr, txIEvalContext* aContext,
txObject*& aResult) = 0;
virtual std::pair<mozilla::UniquePtr<txObject>, nsresult> createSortableValue(
Expr* aExpr, txIEvalContext* aContext) = 0;
};
/*
@ -42,22 +43,21 @@ class txXPathResultComparator {
*/
class txResultStringComparator : public txXPathResultComparator {
public:
txResultStringComparator(bool aAscending, bool aUpperFirst,
const nsString& aLanguage);
txResultStringComparator(bool aAscending, bool aUpperFirst);
nsresult init(const nsString& aLanguage);
int compareValues(txObject* aVal1, txObject* aVal2) override;
nsresult createSortableValue(Expr* aExpr, txIEvalContext* aContext,
txObject*& aResult) override;
std::pair<mozilla::UniquePtr<txObject>, nsresult> createSortableValue(
Expr* aExpr, txIEvalContext* aContext) override;
private:
mozilla::UniquePtr<const mozilla::intl::Collator> mCollator;
nsresult init(const nsString& aLanguage);
int mSorting;
class StringValue : public txObject {
public:
StringValue();
~StringValue();
explicit StringValue(mozilla::UniquePtr<nsString> aString)
: mString(std::move(aString)) {}
mozilla::UniquePtr<nsString> mString;
};
@ -71,14 +71,16 @@ class txResultNumberComparator : public txXPathResultComparator {
explicit txResultNumberComparator(bool aAscending);
int compareValues(txObject* aVal1, txObject* aVal2) override;
nsresult createSortableValue(Expr* aExpr, txIEvalContext* aContext,
txObject*& aResult) override;
std::pair<mozilla::UniquePtr<txObject>, nsresult> createSortableValue(
Expr* aExpr, txIEvalContext* aContext) override;
private:
int mAscending;
class NumberValue : public txObject {
public:
explicit NumberValue(double aVal) : mVal(aVal) {}
double mVal;
};
};