summaryrefslogtreecommitdiffstats
path: root/dom/xslt/base
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--dom/xslt/base/moz.build23
-rw-r--r--dom/xslt/base/txCore.h42
-rw-r--r--dom/xslt/base/txDouble.cpp194
-rw-r--r--dom/xslt/base/txErrorObserver.h36
-rw-r--r--dom/xslt/base/txExpandedName.cpp37
-rw-r--r--dom/xslt/base/txExpandedName.h50
-rw-r--r--dom/xslt/base/txExpandedNameMap.cpp94
-rw-r--r--dom/xslt/base/txExpandedNameMap.h153
-rw-r--r--dom/xslt/base/txList.cpp249
-rw-r--r--dom/xslt/base/txList.h152
-rw-r--r--dom/xslt/base/txLog.h23
-rw-r--r--dom/xslt/base/txNamespaceMap.cpp81
-rw-r--r--dom/xslt/base/txNamespaceMap.h38
-rw-r--r--dom/xslt/base/txOwningArray.h29
-rw-r--r--dom/xslt/base/txStack.h99
-rw-r--r--dom/xslt/base/txStringUtils.h28
-rw-r--r--dom/xslt/base/txURIUtils.cpp87
-rw-r--r--dom/xslt/base/txURIUtils.h40
18 files changed, 1455 insertions, 0 deletions
diff --git a/dom/xslt/base/moz.build b/dom/xslt/base/moz.build
new file mode 100644
index 0000000000..1b22391983
--- /dev/null
+++ b/dom/xslt/base/moz.build
@@ -0,0 +1,23 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# 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/.
+
+UNIFIED_SOURCES += [
+ "txDouble.cpp",
+ "txExpandedName.cpp",
+ "txExpandedNameMap.cpp",
+ "txList.cpp",
+ "txNamespaceMap.cpp",
+ "txURIUtils.cpp",
+]
+
+LOCAL_INCLUDES += [
+ "..",
+ "../xml",
+ "../xpath",
+ "../xslt",
+]
+
+FINAL_LIBRARY = "xul"
diff --git a/dom/xslt/base/txCore.h b/dom/xslt/base/txCore.h
new file mode 100644
index 0000000000..6e462a5a31
--- /dev/null
+++ b/dom/xslt/base/txCore.h
@@ -0,0 +1,42 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#ifndef __txCore_h__
+#define __txCore_h__
+
+#include "nscore.h"
+#include "nsDebug.h"
+#include "nsISupportsImpl.h"
+#include "nsStringFwd.h"
+
+class txObject {
+ public:
+ MOZ_COUNTED_DEFAULT_CTOR(txObject)
+
+ /**
+ * Deletes this txObject
+ */
+ MOZ_COUNTED_DTOR_VIRTUAL(txObject)
+};
+
+/**
+ * Utility class for doubles
+ */
+class txDouble {
+ public:
+ /**
+ * Converts the value of the given double to a string, and appends
+ * the result to the destination string.
+ */
+ static void toString(double aValue, nsAString& aDest);
+
+ /**
+ * Converts the given String to a double, if the string value does not
+ * represent a double, NaN will be returned.
+ */
+ static double toDouble(const nsAString& aStr);
+};
+
+#endif
diff --git a/dom/xslt/base/txDouble.cpp b/dom/xslt/base/txDouble.cpp
new file mode 100644
index 0000000000..ad7fa690be
--- /dev/null
+++ b/dom/xslt/base/txDouble.cpp
@@ -0,0 +1,194 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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 "mozilla/FloatingPoint.h"
+
+#include "nsString.h"
+#include "txCore.h"
+#include "txXMLUtils.h"
+#include <math.h>
+#include <stdlib.h>
+#include <algorithm>
+#ifdef WIN32
+# include <float.h>
+#endif
+#include "prdtoa.h"
+
+/*
+ * Utility class for doubles
+ */
+
+/*
+ * Converts the given String to a double, if the String value does not
+ * represent a double, NaN will be returned
+ */
+class txStringToDouble {
+ public:
+ txStringToDouble() : mState(eWhitestart), mSign(ePositive) {}
+
+ void Parse(const nsAString& aSource) {
+ if (mState == eIllegal) {
+ return;
+ }
+ uint32_t i = 0;
+ char16_t c;
+ auto len = aSource.Length();
+ for (; i < len; ++i) {
+ c = aSource[i];
+ switch (mState) {
+ case eWhitestart:
+ if (c == '-') {
+ mState = eDecimal;
+ mSign = eNegative;
+ } else if (c >= '0' && c <= '9') {
+ mState = eDecimal;
+ mBuffer.Append((char)c);
+ } else if (c == '.') {
+ mState = eMantissa;
+ mBuffer.Append((char)c);
+ } else if (!XMLUtils::isWhitespace(c)) {
+ mState = eIllegal;
+ return;
+ }
+ break;
+ case eDecimal:
+ if (c >= '0' && c <= '9') {
+ mBuffer.Append((char)c);
+ } else if (c == '.') {
+ mState = eMantissa;
+ mBuffer.Append((char)c);
+ } else if (XMLUtils::isWhitespace(c)) {
+ mState = eWhiteend;
+ } else {
+ mState = eIllegal;
+ return;
+ }
+ break;
+ case eMantissa:
+ if (c >= '0' && c <= '9') {
+ mBuffer.Append((char)c);
+ } else if (XMLUtils::isWhitespace(c)) {
+ mState = eWhiteend;
+ } else {
+ mState = eIllegal;
+ return;
+ }
+ break;
+ case eWhiteend:
+ if (!XMLUtils::isWhitespace(c)) {
+ mState = eIllegal;
+ return;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ double getDouble() {
+ if (mState == eIllegal || mBuffer.IsEmpty() ||
+ (mBuffer.Length() == 1 && mBuffer[0] == '.')) {
+ return mozilla::UnspecifiedNaN<double>();
+ }
+ return static_cast<double>(mSign) * PR_strtod(mBuffer.get(), nullptr);
+ }
+
+ private:
+ nsAutoCString mBuffer;
+ enum { eWhitestart, eDecimal, eMantissa, eWhiteend, eIllegal } mState;
+ enum { eNegative = -1, ePositive = 1 } mSign;
+};
+
+double txDouble::toDouble(const nsAString& aSrc) {
+ txStringToDouble sink;
+ sink.Parse(aSrc);
+ return sink.getDouble();
+}
+
+/*
+ * Converts the value of the given double to a String, and places
+ * The result into the destination String.
+ * @return the given dest string
+ */
+void txDouble::toString(double aValue, nsAString& aDest) {
+ // check for special cases
+
+ if (std::isnan(aValue)) {
+ aDest.AppendLiteral("NaN");
+ return;
+ }
+ if (std::isinf(aValue)) {
+ if (aValue < 0) aDest.Append(char16_t('-'));
+ aDest.AppendLiteral("Infinity");
+ return;
+ }
+
+ // Mantissa length is 17, so this is plenty
+ const int buflen = 20;
+ char buf[buflen];
+
+ int intDigits, sign;
+ char* endp;
+ PR_dtoa(aValue, 0, 0, &intDigits, &sign, &endp, buf, buflen - 1);
+
+ // compute length
+ int32_t length = endp - buf;
+ if (length > intDigits) {
+ // decimal point needed
+ ++length;
+ if (intDigits < 1) {
+ // leading zeros, -intDigits + 1
+ length += 1 - intDigits;
+ }
+ } else {
+ // trailing zeros, total length given by intDigits
+ length = intDigits;
+ }
+ if (aValue < 0) ++length;
+ // grow the string
+ uint32_t oldlength = aDest.Length();
+ if (!aDest.SetLength(oldlength + length, mozilla::fallible))
+ return; // out of memory
+ auto dest = aDest.BeginWriting();
+ std::advance(dest, oldlength);
+ if (aValue < 0) {
+ *dest = '-';
+ ++dest;
+ }
+ int i;
+ // leading zeros
+ if (intDigits < 1) {
+ *dest = '0';
+ ++dest;
+ *dest = '.';
+ ++dest;
+ for (i = 0; i > intDigits; --i) {
+ *dest = '0';
+ ++dest;
+ }
+ }
+ // mantissa
+ int firstlen = std::min<size_t>(intDigits, endp - buf);
+ for (i = 0; i < firstlen; i++) {
+ *dest = buf[i];
+ ++dest;
+ }
+ if (i < endp - buf) {
+ if (i > 0) {
+ *dest = '.';
+ ++dest;
+ }
+ for (; i < endp - buf; i++) {
+ *dest = buf[i];
+ ++dest;
+ }
+ }
+ // trailing zeros
+ for (; i < intDigits; i++) {
+ *dest = '0';
+ ++dest;
+ }
+}
diff --git a/dom/xslt/base/txErrorObserver.h b/dom/xslt/base/txErrorObserver.h
new file mode 100644
index 0000000000..30b541f2a9
--- /dev/null
+++ b/dom/xslt/base/txErrorObserver.h
@@ -0,0 +1,36 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#ifndef MITRE_ERROROBSERVER_H
+#define MITRE_ERROROBSERVER_H
+
+#include "txCore.h"
+
+/**
+ * A simple interface for observing errors
+ **/
+class ErrorObserver {
+ public:
+ /**
+ * Default Destructor for ErrorObserver
+ **/
+ virtual ~ErrorObserver(){};
+
+ /**
+ * Notifies this Error observer of a new error aRes
+ **/
+ virtual void receiveError(const nsAString& errorMessage, nsresult aRes) = 0;
+
+ /**
+ * Notifies this Error observer of a new error, with default
+ * error code NS_ERROR_FAILURE
+ **/
+ void receiveError(const nsAString& errorMessage) {
+ receiveError(errorMessage, NS_ERROR_FAILURE);
+ }
+
+}; //-- ErrorObserver
+
+#endif
diff --git a/dom/xslt/base/txExpandedName.cpp b/dom/xslt/base/txExpandedName.cpp
new file mode 100644
index 0000000000..af11476056
--- /dev/null
+++ b/dom/xslt/base/txExpandedName.cpp
@@ -0,0 +1,37 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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 "txExpandedName.h"
+#include "nsString.h"
+#include "nsReadableUtils.h"
+#include "txStringUtils.h"
+#include "txNamespaceMap.h"
+#include "txXMLUtils.h"
+
+nsresult txExpandedName::init(const nsAString& aQName,
+ txNamespaceMap* aResolver, bool aUseDefault) {
+ const nsString& qName = PromiseFlatString(aQName);
+ const char16_t* colon;
+ bool valid = XMLUtils::isValidQName(qName, &colon);
+ if (!valid) {
+ return NS_ERROR_FAILURE;
+ }
+
+ if (colon) {
+ RefPtr<nsAtom> prefix = NS_Atomize(Substring(qName.get(), colon));
+ int32_t namespaceID = aResolver->lookupNamespace(prefix);
+ if (namespaceID == kNameSpaceID_Unknown) return NS_ERROR_FAILURE;
+ mNamespaceID = namespaceID;
+
+ const char16_t* end;
+ qName.EndReading(end);
+ mLocalName = NS_Atomize(Substring(colon + 1, end));
+ } else {
+ mNamespaceID =
+ aUseDefault ? aResolver->lookupNamespace(nullptr) : kNameSpaceID_None;
+ mLocalName = NS_Atomize(aQName);
+ }
+ return NS_OK;
+}
diff --git a/dom/xslt/base/txExpandedName.h b/dom/xslt/base/txExpandedName.h
new file mode 100644
index 0000000000..76d82a8eee
--- /dev/null
+++ b/dom/xslt/base/txExpandedName.h
@@ -0,0 +1,50 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#ifndef TRANSFRMX_EXPANDEDNAME_H
+#define TRANSFRMX_EXPANDEDNAME_H
+
+#include "nsCOMPtr.h"
+#include "nsAtom.h"
+#include "mozilla/dom/NameSpaceConstants.h"
+
+class txNamespaceMap;
+
+class txExpandedName {
+ public:
+ txExpandedName() : mNamespaceID(kNameSpaceID_None) {}
+
+ txExpandedName(int32_t aNsID, nsAtom* aLocalName)
+ : mNamespaceID(aNsID), mLocalName(aLocalName) {}
+
+ txExpandedName(const txExpandedName& aOther) = default;
+
+ nsresult init(const nsAString& aQName, txNamespaceMap* aResolver,
+ bool aUseDefault);
+
+ void reset() {
+ mNamespaceID = kNameSpaceID_None;
+ mLocalName = nullptr;
+ }
+
+ bool isNull() { return mNamespaceID == kNameSpaceID_None && !mLocalName; }
+
+ txExpandedName& operator=(const txExpandedName& rhs) = default;
+
+ bool operator==(const txExpandedName& rhs) const {
+ return ((mLocalName == rhs.mLocalName) &&
+ (mNamespaceID == rhs.mNamespaceID));
+ }
+
+ bool operator!=(const txExpandedName& rhs) const {
+ return ((mLocalName != rhs.mLocalName) ||
+ (mNamespaceID != rhs.mNamespaceID));
+ }
+
+ int32_t mNamespaceID;
+ RefPtr<nsAtom> mLocalName;
+};
+
+#endif
diff --git a/dom/xslt/base/txExpandedNameMap.cpp b/dom/xslt/base/txExpandedNameMap.cpp
new file mode 100644
index 0000000000..996799abf0
--- /dev/null
+++ b/dom/xslt/base/txExpandedNameMap.cpp
@@ -0,0 +1,94 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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 "txExpandedNameMap.h"
+#include "txCore.h"
+
+class txMapItemComparator {
+ public:
+ bool Equals(const txExpandedNameMap_base::MapItem& aItem,
+ const txExpandedName& aKey) const {
+ return aItem.mNamespaceID == aKey.mNamespaceID &&
+ aItem.mLocalName == aKey.mLocalName;
+ }
+};
+
+/**
+ * Adds an item, if an item with this key already exists an error is
+ * returned
+ * @param aKey key for item to add
+ * @param aValue value of item to add
+ * @return errorcode
+ */
+nsresult txExpandedNameMap_base::addItem(const txExpandedName& aKey,
+ void* aValue) {
+ size_t pos = mItems.IndexOf(aKey, 0, txMapItemComparator());
+ if (pos != mItems.NoIndex) {
+ return NS_ERROR_XSLT_ALREADY_SET;
+ }
+
+ MapItem* item = mItems.AppendElement();
+ item->mNamespaceID = aKey.mNamespaceID;
+ item->mLocalName = aKey.mLocalName;
+ item->mValue = aValue;
+
+ return NS_OK;
+}
+
+/**
+ * Sets an item, if an item with this key already exists it is overwritten
+ * with the new value
+ * @param aKey key for item to set
+ * @param aValue value of item to set
+ * @return errorcode
+ */
+nsresult txExpandedNameMap_base::setItem(const txExpandedName& aKey,
+ void* aValue, void** aOldValue) {
+ *aOldValue = nullptr;
+ size_t pos = mItems.IndexOf(aKey, 0, txMapItemComparator());
+ if (pos != mItems.NoIndex) {
+ *aOldValue = mItems[pos].mValue;
+ mItems[pos].mValue = aValue;
+ return NS_OK;
+ }
+
+ MapItem* item = mItems.AppendElement();
+ item->mNamespaceID = aKey.mNamespaceID;
+ item->mLocalName = aKey.mLocalName;
+ item->mValue = aValue;
+
+ return NS_OK;
+}
+
+/**
+ * Gets an item
+ * @param aKey key for item to get
+ * @return item with specified key, or null if no such item exists
+ */
+void* txExpandedNameMap_base::getItem(const txExpandedName& aKey) const {
+ size_t pos = mItems.IndexOf(aKey, 0, txMapItemComparator());
+ if (pos != mItems.NoIndex) {
+ return mItems[pos].mValue;
+ }
+
+ return nullptr;
+}
+
+/**
+ * Removes an item, deleting it if the map owns the values
+ * @param aKey key for item to remove
+ * @return item with specified key, or null if it has been deleted
+ * or no such item exists
+ */
+void* txExpandedNameMap_base::removeItem(const txExpandedName& aKey) {
+ void* value = nullptr;
+ size_t pos = mItems.IndexOf(aKey, 0, txMapItemComparator());
+ if (pos != mItems.NoIndex) {
+ value = mItems[pos].mValue;
+ mItems.RemoveElementAt(pos);
+ }
+
+ return value;
+}
diff --git a/dom/xslt/base/txExpandedNameMap.h b/dom/xslt/base/txExpandedNameMap.h
new file mode 100644
index 0000000000..6e308a65f8
--- /dev/null
+++ b/dom/xslt/base/txExpandedNameMap.h
@@ -0,0 +1,153 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#ifndef TRANSFRMX_EXPANDEDNAMEMAP_H
+#define TRANSFRMX_EXPANDEDNAMEMAP_H
+
+#include "mozilla/UniquePtr.h"
+#include "mozilla/UniquePtrExtensions.h"
+#include "nsError.h"
+#include "txExpandedName.h"
+#include "nsTArray.h"
+
+class txExpandedNameMap_base {
+ protected:
+ /**
+ * Adds an item, if an item with this key already exists an error is
+ * returned
+ * @param aKey key for item to add
+ * @param aValue value of item to add
+ * @return errorcode
+ */
+ nsresult addItem(const txExpandedName& aKey, void* aValue);
+
+ /**
+ * Sets an item, if an item with this key already exists it is overwritten
+ * with the new value
+ * @param aKey key for item to set
+ * @param aValue value of item to set
+ * @return errorcode
+ */
+ nsresult setItem(const txExpandedName& aKey, void* aValue, void** aOldValue);
+
+ /**
+ * Gets an item
+ * @param aKey key for item to get
+ * @return item with specified key, or null if no such item exists
+ */
+ void* getItem(const txExpandedName& aKey) const;
+
+ /**
+ * Removes an item, deleting it if the map owns the values
+ * @param aKey key for item to remove
+ * @return item with specified key, or null if it has been deleted
+ * or no such item exists
+ */
+ void* removeItem(const txExpandedName& aKey);
+
+ /**
+ * Clears the items
+ */
+ void clearItems() { mItems.Clear(); }
+
+ class iterator_base {
+ public:
+ explicit iterator_base(txExpandedNameMap_base& aMap)
+ : mMap(aMap), mCurrentPos(uint32_t(-1)) {}
+
+ bool next() { return ++mCurrentPos < mMap.mItems.Length(); }
+
+ const txExpandedName key() {
+ NS_ASSERTION(mCurrentPos < mMap.mItems.Length(),
+ "invalid position in txExpandedNameMap::iterator");
+ return txExpandedName(mMap.mItems[mCurrentPos].mNamespaceID,
+ mMap.mItems[mCurrentPos].mLocalName);
+ }
+
+ protected:
+ void* itemValue() {
+ NS_ASSERTION(mCurrentPos < mMap.mItems.Length(),
+ "invalid position in txExpandedNameMap::iterator");
+ return mMap.mItems[mCurrentPos].mValue;
+ }
+
+ private:
+ txExpandedNameMap_base& mMap;
+ uint32_t mCurrentPos;
+ };
+
+ friend class iterator_base;
+
+ friend class txMapItemComparator;
+ struct MapItem {
+ int32_t mNamespaceID;
+ RefPtr<nsAtom> mLocalName;
+ void* mValue;
+ };
+
+ nsTArray<MapItem> mItems;
+};
+
+template <class E>
+class txExpandedNameMap : public txExpandedNameMap_base {
+ public:
+ nsresult add(const txExpandedName& aKey, E* aValue) {
+ return addItem(aKey, (void*)aValue);
+ }
+
+ nsresult set(const txExpandedName& aKey, E* aValue) {
+ void* oldValue;
+ return setItem(aKey, (void*)aValue, &oldValue);
+ }
+
+ E* get(const txExpandedName& aKey) const { return (E*)getItem(aKey); }
+
+ E* remove(const txExpandedName& aKey) { return (E*)removeItem(aKey); }
+
+ void clear() { clearItems(); }
+
+ class iterator : public iterator_base {
+ public:
+ explicit iterator(txExpandedNameMap& aMap) : iterator_base(aMap) {}
+
+ E* value() { return (E*)itemValue(); }
+ };
+};
+
+template <class E>
+class txOwningExpandedNameMap : public txExpandedNameMap_base {
+ public:
+ ~txOwningExpandedNameMap() { clear(); }
+
+ nsresult add(const txExpandedName& aKey, E* aValue) {
+ return addItem(aKey, (void*)aValue);
+ }
+
+ nsresult set(const txExpandedName& aKey, E* aValue) {
+ mozilla::UniquePtr<E> oldValue;
+ return setItem(aKey, (void*)aValue, getter_Transfers(oldValue));
+ }
+
+ E* get(const txExpandedName& aKey) const { return (E*)getItem(aKey); }
+
+ void remove(const txExpandedName& aKey) { delete (E*)removeItem(aKey); }
+
+ void clear() {
+ uint32_t i, len = mItems.Length();
+ for (i = 0; i < len; ++i) {
+ delete (E*)mItems[i].mValue;
+ }
+ clearItems();
+ }
+
+ class iterator : public iterator_base {
+ public:
+ explicit iterator(txOwningExpandedNameMap& aMap) : iterator_base(aMap) {}
+
+ E* value() { return (E*)itemValue(); }
+ };
+};
+
+#endif // TRANSFRMX_EXPANDEDNAMEMAP_H
diff --git a/dom/xslt/base/txList.cpp b/dom/xslt/base/txList.cpp
new file mode 100644
index 0000000000..a361490784
--- /dev/null
+++ b/dom/xslt/base/txList.cpp
@@ -0,0 +1,249 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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 "txList.h"
+
+//----------------------------/
+//- Implementation of txList -/
+//----------------------------/
+
+/**
+ * Default constructor for a txList;
+ **/
+
+txList::txList() {
+ firstItem = 0;
+ lastItem = 0;
+ itemCount = 0;
+} //-- txList;
+
+/**
+ * txList destructor, cleans up ListItems, but will not delete the Object
+ * references
+ */
+txList::~txList() { clear(); } //-- ~txList
+
+void txList::add(void* objPtr) { insertBefore(objPtr, nullptr); } //-- add
+
+/**
+ * Returns the number of items in this txList
+ **/
+int32_t List::getLength() { return itemCount; } //-- getLength
+
+/**
+ * Inserts the given Object pointer as the item just after refItem.
+ * If refItem is a null pointer the Object will be inserted at the
+ * beginning of the txList (ie, insert after nothing).
+ * This method assumes refItem is a member of this list, and since this
+ * is a private method, I feel that's a valid assumption
+ **/
+void txList::insertAfter(void* objPtr, ListItem* refItem) {
+ insertBefore(objPtr, refItem ? refItem->nextItem : firstItem);
+} //-- insertAfter
+
+/**
+ * Inserts the given Object pointer as the item just before refItem.
+ * If refItem is a null pointer the Object will be inserted at the
+ * end of the txList (ie, insert before nothing).
+ * This method assumes refItem is a member of this list, and since this
+ * is a private method, I feel that's a valid assumption
+ **/
+void txList::insertBefore(void* objPtr, ListItem* refItem) {
+ ListItem* item = new ListItem;
+ item->objPtr = objPtr;
+ item->nextItem = 0;
+ item->prevItem = 0;
+
+ //-- if refItem == null insert at end
+ if (!refItem) {
+ //-- add to back of list
+ if (lastItem) {
+ lastItem->nextItem = item;
+ item->prevItem = lastItem;
+ }
+ lastItem = item;
+ if (!firstItem) firstItem = item;
+ } else {
+ //-- insert before given item
+ item->nextItem = refItem;
+ item->prevItem = refItem->prevItem;
+ refItem->prevItem = item;
+
+ if (item->prevItem)
+ item->prevItem->nextItem = item;
+ else
+ firstItem = item;
+ }
+
+ // increase the item count
+ ++itemCount;
+} //-- insertBefore
+
+txList::ListItem* txList::remove(ListItem* item) {
+ if (!item) return item;
+
+ //-- adjust the previous item's next pointer
+ if (item->prevItem) {
+ item->prevItem->nextItem = item->nextItem;
+ }
+ //-- adjust the next item's previous pointer
+ if (item->nextItem) {
+ item->nextItem->prevItem = item->prevItem;
+ }
+
+ //-- adjust first and last items
+ if (item == firstItem) firstItem = item->nextItem;
+ if (item == lastItem) lastItem = item->prevItem;
+
+ //-- decrease Item count
+ --itemCount;
+ return item;
+} //-- remove
+
+void txList::clear() {
+ ListItem* item = firstItem;
+ while (item) {
+ ListItem* tItem = item;
+ item = item->nextItem;
+ delete tItem;
+ }
+ firstItem = 0;
+ lastItem = 0;
+ itemCount = 0;
+}
+
+//------------------------------------/
+//- Implementation of txListIterator -/
+//------------------------------------/
+
+/**
+ * Creates a new txListIterator for the given txList
+ * @param list, the txList to create an Iterator for
+ **/
+txListIterator::txListIterator(txList* list) {
+ this->list = list;
+ currentItem = 0;
+ atEndOfList = false;
+} //-- txListIterator
+
+/**
+ * Adds the Object pointer to the txList pointed to by this txListIterator.
+ * The Object pointer is inserted as the next item in the txList
+ * based on the current position within the txList
+ * @param objPtr the Object pointer to add to the list
+ **/
+void txListIterator::addAfter(void* objPtr) {
+ if (currentItem || !atEndOfList) {
+ list->insertAfter(objPtr, currentItem);
+ } else {
+ list->insertBefore(objPtr, nullptr);
+ }
+} //-- addAfter
+
+/**
+ * Adds the Object pointer to the txList pointed to by this txListIterator.
+ * The Object pointer is inserted as the previous item in the txList
+ * based on the current position within the txList
+ * @param objPtr the Object pointer to add to the list
+ **/
+void txListIterator::addBefore(void* objPtr) {
+ if (currentItem || atEndOfList) {
+ list->insertBefore(objPtr, currentItem);
+ } else {
+ list->insertAfter(objPtr, nullptr);
+ }
+} //-- addBefore
+
+/**
+ * Returns true if a successful call to the next() method can be made
+ * @return true if a successful call to the next() method can be made,
+ * otherwise false
+ **/
+bool txListIterator::hasNext() {
+ bool hasNext = false;
+ if (currentItem)
+ hasNext = (currentItem->nextItem != 0);
+ else if (!atEndOfList)
+ hasNext = (list->firstItem != 0);
+
+ return hasNext;
+} //-- hasNext
+
+/**
+ * Returns the next Object pointer in the list
+ **/
+void* txListIterator::next() {
+ void* obj = 0;
+ if (currentItem)
+ currentItem = currentItem->nextItem;
+ else if (!atEndOfList)
+ currentItem = list->firstItem;
+
+ if (currentItem)
+ obj = currentItem->objPtr;
+ else
+ atEndOfList = true;
+
+ return obj;
+} //-- next
+
+/**
+ * Returns the previous Object in the list
+ **/
+void* txListIterator::previous() {
+ void* obj = 0;
+
+ if (currentItem)
+ currentItem = currentItem->prevItem;
+ else if (atEndOfList)
+ currentItem = list->lastItem;
+
+ if (currentItem) obj = currentItem->objPtr;
+
+ atEndOfList = false;
+
+ return obj;
+} //-- previous
+
+/**
+ * Returns the current Object
+ **/
+void* txListIterator::current() {
+ if (currentItem) return currentItem->objPtr;
+
+ return 0;
+} //-- current
+
+/**
+ * Removes the Object last returned by the next() or previous() methods;
+ * @return the removed Object pointer
+ **/
+void* txListIterator::remove() {
+ void* obj = 0;
+ if (currentItem) {
+ obj = currentItem->objPtr;
+ txList::ListItem* item = currentItem;
+ previous(); //-- make previous item the current item
+ list->remove(item);
+ delete item;
+ }
+ return obj;
+} //-- remove
+
+/**
+ * Resets the current location within the txList to the beginning of the txList
+ **/
+void txListIterator::reset() {
+ atEndOfList = false;
+ currentItem = 0;
+} //-- reset
+
+/**
+ * Move the iterator to right after the last element
+ **/
+void txListIterator::resetToEnd() {
+ atEndOfList = true;
+ currentItem = 0;
+} //-- moveToEnd
diff --git a/dom/xslt/base/txList.h b/dom/xslt/base/txList.h
new file mode 100644
index 0000000000..eeafd12dda
--- /dev/null
+++ b/dom/xslt/base/txList.h
@@ -0,0 +1,152 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#ifndef TRANSFRMX_LIST_H
+#define TRANSFRMX_LIST_H
+
+#include "txCore.h"
+
+class txListIterator;
+
+/**
+ * Represents an ordered list of Object pointers. Modeled after a Java 2 List.
+ **/
+class txList : public txObject {
+ friend class txListIterator;
+
+ public:
+ /**
+ * Creates an empty txList
+ **/
+ txList();
+
+ /**
+ * txList destructor, object references will not be deleted.
+ **/
+ ~txList();
+
+ /**
+ * Returns the number of items in this txList
+ **/
+ int32_t getLength();
+
+ /**
+ * Returns true if there are no items in this txList
+ */
+ inline bool isEmpty() { return itemCount == 0; }
+
+ /**
+ * Adds the given Object to the list
+ **/
+ void add(void* objPtr);
+
+ /*
+ * Removes all the objects from the list
+ */
+ void clear();
+
+ protected:
+ struct ListItem {
+ ListItem* nextItem;
+ ListItem* prevItem;
+ void* objPtr;
+ };
+
+ /**
+ * Removes the given ListItem pointer from the list
+ **/
+ ListItem* remove(ListItem* sItem);
+
+ private:
+ txList(const txList& aOther); // not implemented
+
+ ListItem* firstItem;
+ ListItem* lastItem;
+ int32_t itemCount;
+
+ void insertAfter(void* objPtr, ListItem* sItem);
+ void insertBefore(void* objPtr, ListItem* sItem);
+};
+
+/**
+ * An Iterator for the txList Class
+ **/
+class txListIterator {
+ public:
+ /**
+ * Creates a new txListIterator for the given txList
+ * @param list, the txList to create an Iterator for
+ **/
+ explicit txListIterator(txList* list);
+
+ /**
+ * Adds the Object pointer to the txList pointed to by this txListIterator.
+ * The Object pointer is inserted as the next item in the txList
+ * based on the current position within the txList
+ * @param objPtr the Object pointer to add to the list
+ **/
+ void addAfter(void* objPtr);
+
+ /**
+ * Adds the Object pointer to the txList pointed to by this txListIterator.
+ * The Object pointer is inserted as the previous item in the txList
+ * based on the current position within the txList
+ * @param objPtr the Object pointer to add to the list
+ **/
+ void addBefore(void* objPtr);
+
+ /**
+ * Returns true if a successful call to the next() method can be made
+ * @return true if a successful call to the next() method can be made,
+ * otherwise false
+ **/
+ bool hasNext();
+
+ /**
+ * Returns the next Object pointer from the list
+ **/
+ void* next();
+
+ /**
+ * Returns the previous Object pointer from the list
+ **/
+ void* previous();
+
+ /**
+ * Returns the current Object
+ **/
+ void* current();
+
+ /**
+ * Removes the Object last returned by the next() or previous() methods;
+ * @return the removed Object pointer
+ **/
+ void* remove();
+
+ /**
+ * Resets the current location within the txList to the beginning of the
+ * txList
+ **/
+ void reset();
+
+ /**
+ * Resets the current location within the txList to the end of the txList
+ **/
+ void resetToEnd();
+
+ private:
+ //-- points to the current list item
+ txList::ListItem* currentItem;
+
+ //-- points to the list to iterator over
+ txList* list;
+
+ //-- we've moved off the end of the list
+ bool atEndOfList;
+};
+
+using List = txList;
+
+#endif
diff --git a/dom/xslt/base/txLog.h b/dom/xslt/base/txLog.h
new file mode 100644
index 0000000000..c5b03ca83e
--- /dev/null
+++ b/dom/xslt/base/txLog.h
@@ -0,0 +1,23 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#ifndef txLog_h__
+#define txLog_h__
+
+#include "mozilla/Logging.h"
+
+class txLog {
+ public:
+ static mozilla::LazyLogModule xpath;
+ static mozilla::LazyLogModule xslt;
+};
+
+#define TX_LG_IMPL \
+ mozilla::LazyLogModule txLog::xpath("xpath"); \
+ mozilla::LazyLogModule txLog::xslt("xslt");
+
+#define TX_LG_CREATE
+
+#endif
diff --git a/dom/xslt/base/txNamespaceMap.cpp b/dom/xslt/base/txNamespaceMap.cpp
new file mode 100644
index 0000000000..284e08a705
--- /dev/null
+++ b/dom/xslt/base/txNamespaceMap.cpp
@@ -0,0 +1,81 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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 "txNamespaceMap.h"
+#include "nsGkAtoms.h"
+#include "txXPathNode.h"
+
+txNamespaceMap::txNamespaceMap() = default;
+
+txNamespaceMap::txNamespaceMap(const txNamespaceMap& aOther)
+ : mPrefixes(aOther.mPrefixes.Clone()),
+ mNamespaces(aOther.mNamespaces.Clone()) {}
+
+nsresult txNamespaceMap::mapNamespace(nsAtom* aPrefix,
+ const nsAString& aNamespaceURI) {
+ nsAtom* prefix = aPrefix == nsGkAtoms::_empty ? nullptr : aPrefix;
+
+ int32_t nsId;
+ if (prefix && aNamespaceURI.IsEmpty()) {
+ // Remove the mapping
+ int32_t index = mPrefixes.IndexOf(prefix);
+ if (index >= 0) {
+ mPrefixes.RemoveElementAt(index);
+ mNamespaces.RemoveElementAt(index);
+ }
+
+ return NS_OK;
+ }
+
+ if (aNamespaceURI.IsEmpty()) {
+ // Set default to empty namespace
+ nsId = kNameSpaceID_None;
+ } else {
+ nsId = txNamespaceManager::getNamespaceID(aNamespaceURI);
+ NS_ENSURE_FALSE(nsId == kNameSpaceID_Unknown, NS_ERROR_FAILURE);
+ }
+
+ // Check if the mapping already exists
+ int32_t index = mPrefixes.IndexOf(prefix);
+ if (index >= 0) {
+ mNamespaces.ElementAt(index) = nsId;
+
+ return NS_OK;
+ }
+
+ // New mapping
+ mPrefixes.AppendElement(prefix);
+ mNamespaces.AppendElement(nsId);
+
+ return NS_OK;
+}
+
+int32_t txNamespaceMap::lookupNamespace(nsAtom* aPrefix) {
+ if (aPrefix == nsGkAtoms::xml) {
+ return kNameSpaceID_XML;
+ }
+
+ nsAtom* prefix = aPrefix == nsGkAtoms::_empty ? 0 : aPrefix;
+
+ int32_t index = mPrefixes.IndexOf(prefix);
+ if (index >= 0) {
+ return mNamespaces.SafeElementAt(index, kNameSpaceID_Unknown);
+ }
+
+ if (!prefix) {
+ return kNameSpaceID_None;
+ }
+
+ return kNameSpaceID_Unknown;
+}
+
+int32_t txNamespaceMap::lookupNamespaceWithDefault(const nsAString& aPrefix) {
+ RefPtr<nsAtom> prefix = NS_Atomize(aPrefix);
+ if (prefix != nsGkAtoms::_poundDefault) {
+ return lookupNamespace(prefix);
+ }
+
+ return lookupNamespace(nullptr);
+}
diff --git a/dom/xslt/base/txNamespaceMap.h b/dom/xslt/base/txNamespaceMap.h
new file mode 100644
index 0000000000..e2be7ebf15
--- /dev/null
+++ b/dom/xslt/base/txNamespaceMap.h
@@ -0,0 +1,38 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#ifndef TRANSFRMX_TXNAMESPACEMAP_H
+#define TRANSFRMX_TXNAMESPACEMAP_H
+
+#include "nsAtom.h"
+#include "nsCOMPtr.h"
+#include "nsTArray.h"
+
+class txNamespaceMap {
+ public:
+ txNamespaceMap();
+ txNamespaceMap(const txNamespaceMap& aOther);
+
+ nsrefcnt AddRef() { return ++mRefCnt; }
+ nsrefcnt Release() {
+ if (--mRefCnt == 0) {
+ mRefCnt = 1; // stabilize
+ delete this;
+ return 0;
+ }
+ return mRefCnt;
+ }
+
+ nsresult mapNamespace(nsAtom* aPrefix, const nsAString& aNamespaceURI);
+ int32_t lookupNamespace(nsAtom* aPrefix);
+ int32_t lookupNamespaceWithDefault(const nsAString& aPrefix);
+
+ private:
+ nsAutoRefCnt mRefCnt;
+ nsTArray<RefPtr<nsAtom>> mPrefixes;
+ nsTArray<int32_t> mNamespaces;
+};
+
+#endif // TRANSFRMX_TXNAMESPACEMAP_H
diff --git a/dom/xslt/base/txOwningArray.h b/dom/xslt/base/txOwningArray.h
new file mode 100644
index 0000000000..f25015a597
--- /dev/null
+++ b/dom/xslt/base/txOwningArray.h
@@ -0,0 +1,29 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* 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/. */
+
+#ifndef txOwningArray_h__
+#define txOwningArray_h__
+
+// Class acting like a nsTArray except that it deletes its objects
+// on destruction. It does not however delete its objects on operations
+// like RemoveElementsAt or on |array[i] = bar|.
+
+template <class E>
+class txOwningArray : public nsTArray<E*> {
+ public:
+ typedef nsTArray<E*> base_type;
+ typedef typename base_type::value_type value_type;
+
+ ~txOwningArray() {
+ value_type* iter = base_type::Elements();
+ value_type* end = iter + base_type::Length();
+ for (; iter < end; ++iter) {
+ delete *iter;
+ }
+ }
+};
+
+#endif // txOwningArray_h__
diff --git a/dom/xslt/base/txStack.h b/dom/xslt/base/txStack.h
new file mode 100644
index 0000000000..9a9269ed69
--- /dev/null
+++ b/dom/xslt/base/txStack.h
@@ -0,0 +1,99 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#ifndef txStack_h___
+#define txStack_h___
+
+#include "nsTArray.h"
+
+class txStack : private nsTArray<void*> {
+ public:
+ /**
+ * Returns the specified object from the top of this stack,
+ * without removing it from the stack.
+ *
+ * @return a pointer to the object that is the top of this stack.
+ */
+ inline void* peek() {
+ NS_ASSERTION(!isEmpty(), "peeking at empty stack");
+ return !isEmpty() ? ElementAt(Length() - 1) : nullptr;
+ }
+
+ /**
+ * Adds the specified object to the top of this stack.
+ *
+ * @param obj a pointer to the object that is to be added to the
+ * top of this stack.
+ */
+ inline void push(void* aObject) { AppendElement(aObject); }
+
+ /**
+ * Removes and returns the specified object from the top of this
+ * stack.
+ *
+ * @return a pointer to the object that was the top of this stack.
+ */
+ inline void* pop() {
+ void* object = nullptr;
+ NS_ASSERTION(!isEmpty(), "popping from empty stack");
+ if (!isEmpty()) {
+ object = PopLastElement();
+ }
+ return object;
+ }
+
+ /**
+ * Returns true if there are no objects in the stack.
+ *
+ * @return true if there are no objects in the stack.
+ */
+ inline bool isEmpty() { return IsEmpty(); }
+
+ /**
+ * Returns the number of elements in the Stack.
+ *
+ * @return the number of elements in the Stack.
+ */
+ inline int32_t size() { return Length(); }
+
+ private:
+ friend class txStackIterator;
+};
+
+class txStackIterator {
+ public:
+ /**
+ * Creates an iterator for the given stack.
+ *
+ * @param aStack the stack to create an iterator for.
+ */
+ inline explicit txStackIterator(txStack* aStack)
+ : mStack(aStack), mPosition(0) {}
+
+ /**
+ * Returns true if there is more objects on the stack.
+ *
+ * @return .
+ */
+ inline bool hasNext() { return (mPosition < mStack->Length()); }
+
+ /**
+ * Returns the next object pointer from the stack.
+ *
+ * @return .
+ */
+ inline void* next() {
+ if (mPosition == mStack->Length()) {
+ return nullptr;
+ }
+ return mStack->ElementAt(mPosition++);
+ }
+
+ private:
+ txStack* mStack;
+ uint32_t mPosition;
+};
+
+#endif /* txStack_h___ */
diff --git a/dom/xslt/base/txStringUtils.h b/dom/xslt/base/txStringUtils.h
new file mode 100644
index 0000000000..2064c01720
--- /dev/null
+++ b/dom/xslt/base/txStringUtils.h
@@ -0,0 +1,28 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#ifndef txStringUtils_h__
+#define txStringUtils_h__
+
+#include "nsAString.h"
+#include "nsAtom.h"
+#include "nsUnicharUtils.h"
+#include "nsContentUtils.h" // For ASCIIToLower().
+
+/**
+ * Check equality between a string and an atom containing ASCII.
+ */
+inline bool TX_StringEqualsAtom(const nsAString& aString, nsAtom* aAtom) {
+ return aAtom->Equals(aString);
+}
+
+inline already_AddRefed<nsAtom> TX_ToLowerCaseAtom(nsAtom* aAtom) {
+ nsAutoString str;
+ aAtom->ToString(str);
+ nsContentUtils::ASCIIToLower(str);
+ return NS_Atomize(str);
+}
+
+#endif // txStringUtils_h__
diff --git a/dom/xslt/base/txURIUtils.cpp b/dom/xslt/base/txURIUtils.cpp
new file mode 100644
index 0000000000..bbb06221cf
--- /dev/null
+++ b/dom/xslt/base/txURIUtils.cpp
@@ -0,0 +1,87 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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 "txURIUtils.h"
+#include "nsNetUtil.h"
+#include "mozilla/dom/Document.h"
+#include "nsIPrincipal.h"
+#include "mozilla/LoadInfo.h"
+#include "mozilla/dom/nsCSPContext.h"
+
+using mozilla::dom::Document;
+using mozilla::net::LoadInfo;
+
+/**
+ * URIUtils
+ * A set of utilities for handling URIs
+ **/
+
+/**
+ * Resolves the given href argument, using the given documentBase
+ * if necessary.
+ * The new resolved href will be appended to the given dest String
+ **/
+void URIUtils::resolveHref(const nsAString& href, const nsAString& base,
+ nsAString& dest) {
+ if (base.IsEmpty()) {
+ dest.Append(href);
+ return;
+ }
+ if (href.IsEmpty()) {
+ dest.Append(base);
+ return;
+ }
+ nsCOMPtr<nsIURI> pURL;
+ nsAutoString resultHref;
+ nsresult result = NS_NewURI(getter_AddRefs(pURL), base);
+ if (NS_SUCCEEDED(result)) {
+ NS_MakeAbsoluteURI(resultHref, href, pURL);
+ dest.Append(resultHref);
+ }
+} //-- resolveHref
+
+// static
+void URIUtils::ResetWithSource(Document* aNewDoc, nsINode* aSourceNode) {
+ nsCOMPtr<Document> sourceDoc = aSourceNode->OwnerDoc();
+ nsIPrincipal* sourcePrincipal = sourceDoc->NodePrincipal();
+ nsIPrincipal* sourcePartitionedPrincipal = sourceDoc->PartitionedPrincipal();
+
+ // Copy the channel and loadgroup from the source document.
+ nsCOMPtr<nsILoadGroup> loadGroup = sourceDoc->GetDocumentLoadGroup();
+ nsCOMPtr<nsIChannel> channel = sourceDoc->GetChannel();
+ if (!channel) {
+ // Need to synthesize one
+ nsresult rv = NS_NewChannel(
+ getter_AddRefs(channel), sourceDoc->GetDocumentURI(), sourceDoc,
+ nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL, nsIContentPolicy::TYPE_OTHER,
+ nullptr, // aPerformanceStorage
+ loadGroup,
+ nullptr, // aCallbacks
+ nsIChannel::LOAD_BYPASS_SERVICE_WORKER);
+
+ if (NS_FAILED(rv)) {
+ return;
+ }
+ }
+
+ aNewDoc->Reset(channel, loadGroup);
+ aNewDoc->SetPrincipals(sourcePrincipal, sourcePartitionedPrincipal);
+ aNewDoc->SetBaseURI(sourceDoc->GetDocBaseURI());
+ aNewDoc->SetSandboxFlags(sourceDoc->GetSandboxFlags());
+ aNewDoc->SetReferrerInfo(sourceDoc->GetReferrerInfo());
+ aNewDoc->SetEmbedderPolicy(sourceDoc->GetEmbedderPolicy());
+
+ // Inherit the csp if there is one
+ nsCOMPtr<nsIContentSecurityPolicy> csp = sourceDoc->GetCsp();
+ if (csp) {
+ RefPtr<nsCSPContext> cspToInherit = new nsCSPContext();
+ cspToInherit->InitFromOther(static_cast<nsCSPContext*>(csp.get()));
+ aNewDoc->SetCsp(cspToInherit);
+ }
+ // Copy charset
+ aNewDoc->SetDocumentCharacterSetSource(
+ sourceDoc->GetDocumentCharacterSetSource());
+ aNewDoc->SetDocumentCharacterSet(sourceDoc->GetDocumentCharacterSet());
+}
diff --git a/dom/xslt/base/txURIUtils.h b/dom/xslt/base/txURIUtils.h
new file mode 100644
index 0000000000..96082b99f7
--- /dev/null
+++ b/dom/xslt/base/txURIUtils.h
@@ -0,0 +1,40 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#ifndef TRANSFRMX_URIUTILS_H
+#define TRANSFRMX_URIUTILS_H
+
+#include "txCore.h"
+
+class nsINode;
+
+namespace mozilla::dom {
+class Document;
+} // namespace mozilla::dom
+
+/**
+ * A utility class for URI handling
+ * Not yet finished, only handles file URI at this point
+ **/
+
+class URIUtils {
+ public:
+ /**
+ * Reset the given document with the document of the source node
+ */
+ static void ResetWithSource(mozilla::dom::Document* aNewDoc,
+ nsINode* aSourceNode);
+
+ /**
+ * Resolves the given href argument, using the given documentBase
+ * if necessary.
+ * The new resolved href will be appended to the given dest String
+ **/
+ static void resolveHref(const nsAString& href, const nsAString& base,
+ nsAString& dest);
+}; //-- URIUtils
+
+/* */
+#endif