summaryrefslogtreecommitdiffstats
path: root/xpcom
diff options
context:
space:
mode:
Diffstat (limited to 'xpcom')
-rw-r--r--xpcom/base/AppShutdown.cpp18
-rw-r--r--xpcom/base/AvailableMemoryWatcherLinux.cpp2
-rw-r--r--xpcom/base/AvailableMemoryWatcherMac.cpp30
-rw-r--r--xpcom/base/AvailableMemoryWatcherWin.cpp9
-rw-r--r--xpcom/base/CFTypeRefPtr.h194
-rw-r--r--xpcom/base/CycleCollectedJSRuntime.cpp6
-rw-r--r--xpcom/base/EnumeratedArrayCycleCollection.h12
-rw-r--r--xpcom/base/MacHelpers.mm3
-rw-r--r--xpcom/base/MacStringHelpers.h6
-rw-r--r--xpcom/base/MacStringHelpers.mm36
-rw-r--r--xpcom/base/moz.build14
-rw-r--r--xpcom/base/nsCycleCollector.cpp4
-rw-r--r--xpcom/base/nsDebugImpl.cpp7
-rw-r--r--xpcom/base/nsISupportsImpl.cpp18
-rw-r--r--xpcom/base/nsISupportsImpl.h15
-rw-r--r--xpcom/base/nsrootidl.idl27
-rw-r--r--xpcom/components/StaticComponents.cpp.in15
-rw-r--r--xpcom/components/gen_static_components.py19
-rw-r--r--xpcom/components/nsIComponentManager.idl2
-rw-r--r--xpcom/components/nsIServiceManager.idl3
-rw-r--r--xpcom/docs/stringguide.rst8
-rw-r--r--xpcom/ds/HTMLAtoms.py2
-rw-r--r--xpcom/ds/StaticAtoms.py14
-rw-r--r--xpcom/ds/nsObserverService.cpp9
-rw-r--r--xpcom/ds/tools/perfecthash.py31
-rw-r--r--xpcom/idl-parser/xpidl/fixtures/xpctest.d.json1402
-rw-r--r--xpcom/idl-parser/xpidl/header.py2
-rwxr-xr-xxpcom/idl-parser/xpidl/runtests.py41
-rw-r--r--xpcom/idl-parser/xpidl/rust.py4
-rw-r--r--xpcom/idl-parser/xpidl/typescript.py94
-rwxr-xr-xxpcom/idl-parser/xpidl/xpidl.py136
-rw-r--r--xpcom/io/CocoaFileUtils.mm2
-rw-r--r--xpcom/io/nsLocalFileCommon.cpp3
-rw-r--r--xpcom/io/nsLocalFileCommon.h4
-rw-r--r--xpcom/reflect/xptcall/md/unix/xptcinvoke_loongarch64.cpp4
-rw-r--r--xpcom/system/nsIDeviceSensors.idl4
-rw-r--r--xpcom/system/nsIXULRuntime.idl9
-rw-r--r--xpcom/tests/gtest/TestAutoOwningEventTarget.cpp120
-rw-r--r--xpcom/tests/gtest/TestThreadUtils.cpp327
-rw-r--r--xpcom/tests/gtest/moz.build7
-rw-r--r--xpcom/threads/MozPromise.h200
-rw-r--r--xpcom/threads/Mutex.h4
-rw-r--r--xpcom/threads/nsThreadManager.cpp6
-rw-r--r--xpcom/threads/nsThreadUtils.h301
44 files changed, 2443 insertions, 731 deletions
diff --git a/xpcom/base/AppShutdown.cpp b/xpcom/base/AppShutdown.cpp
index c68dedef31..53ae4e3ba9 100644
--- a/xpcom/base/AppShutdown.cpp
+++ b/xpcom/base/AppShutdown.cpp
@@ -309,32 +309,32 @@ bool AppShutdown::IsRestarting() {
void AppShutdown::AnnotateShutdownReason(AppShutdownReason aReason) {
auto key = CrashReporter::Annotation::ShutdownReason;
- nsCString reasonStr;
+ const char* reasonStr;
switch (aReason) {
case AppShutdownReason::AppClose:
- reasonStr = "AppClose"_ns;
+ reasonStr = "AppClose";
break;
case AppShutdownReason::AppRestart:
- reasonStr = "AppRestart"_ns;
+ reasonStr = "AppRestart";
break;
case AppShutdownReason::OSForceClose:
- reasonStr = "OSForceClose"_ns;
+ reasonStr = "OSForceClose";
break;
case AppShutdownReason::OSSessionEnd:
- reasonStr = "OSSessionEnd"_ns;
+ reasonStr = "OSSessionEnd";
break;
case AppShutdownReason::OSShutdown:
- reasonStr = "OSShutdown"_ns;
+ reasonStr = "OSShutdown";
break;
case AppShutdownReason::WinUnexpectedMozQuit:
- reasonStr = "WinUnexpectedMozQuit"_ns;
+ reasonStr = "WinUnexpectedMozQuit";
break;
default:
MOZ_ASSERT_UNREACHABLE("We should know the given reason for shutdown.");
- reasonStr = "Unknown"_ns;
+ reasonStr = "Unknown";
break;
}
- CrashReporter::AnnotateCrashReport(key, reasonStr);
+ CrashReporter::RecordAnnotationCString(key, reasonStr);
}
#ifdef DEBUG
diff --git a/xpcom/base/AvailableMemoryWatcherLinux.cpp b/xpcom/base/AvailableMemoryWatcherLinux.cpp
index 04927b7d46..de8a1d79fc 100644
--- a/xpcom/base/AvailableMemoryWatcherLinux.cpp
+++ b/xpcom/base/AvailableMemoryWatcherLinux.cpp
@@ -206,7 +206,7 @@ void nsAvailableMemoryWatcher::HandleLowMemory() {
void nsAvailableMemoryWatcher::UpdateCrashAnnotation(const MutexAutoLock&)
MOZ_REQUIRES(mMutex) {
- CrashReporter::AnnotateCrashReport(
+ CrashReporter::RecordAnnotationBool(
CrashReporter::Annotation::LinuxUnderMemoryPressure,
mUnderMemoryPressure);
}
diff --git a/xpcom/base/AvailableMemoryWatcherMac.cpp b/xpcom/base/AvailableMemoryWatcherMac.cpp
index d6f2d16b30..de6901f8d5 100644
--- a/xpcom/base/AvailableMemoryWatcherMac.cpp
+++ b/xpcom/base/AvailableMemoryWatcherMac.cpp
@@ -95,11 +95,11 @@ class nsAvailableMemoryWatcher final : public nsITimerCallback,
void AddParentAnnotation(CrashReporter::Annotation aAnnotation,
nsAutoCString aString) {
- CrashReporter::AnnotateCrashReport(aAnnotation, aString);
+ CrashReporter::RecordAnnotationNSCString(aAnnotation, aString);
}
void AddParentAnnotation(CrashReporter::Annotation aAnnotation,
uint32_t aData) {
- CrashReporter::AnnotateCrashReport(aAnnotation, aData);
+ CrashReporter::RecordAnnotationU32(aAnnotation, aData);
}
void LowMemoryResponse();
@@ -251,18 +251,18 @@ nsresult nsAvailableMemoryWatcher::Init() {
// Set the initial state of all annotations for parent crash reports.
// Content process crash reports are set when a crash occurs and
// AddChildAnnotations() is called.
- CrashReporter::AnnotateCrashReport(
+ CrashReporter::RecordAnnotationNSCString(
CrashReporter::Annotation::MacMemoryPressure, mLevelStr);
- CrashReporter::AnnotateCrashReport(
+ CrashReporter::RecordAnnotationNSCString(
CrashReporter::Annotation::MacMemoryPressureNormalTime, mNormalTimeStr);
- CrashReporter::AnnotateCrashReport(
+ CrashReporter::RecordAnnotationNSCString(
CrashReporter::Annotation::MacMemoryPressureWarningTime, mWarningTimeStr);
- CrashReporter::AnnotateCrashReport(
+ CrashReporter::RecordAnnotationNSCString(
CrashReporter::Annotation::MacMemoryPressureCriticalTime,
mCriticalTimeStr);
- CrashReporter::AnnotateCrashReport(
+ CrashReporter::RecordAnnotationU32(
CrashReporter::Annotation::MacMemoryPressureSysctl, mLevelSysctl);
- CrashReporter::AnnotateCrashReport(
+ CrashReporter::RecordAnnotationU32(
CrashReporter::Annotation::MacAvailableMemorySysctl, mAvailMemSysctl);
// To support running experiments, handle pref
@@ -441,18 +441,18 @@ void nsAvailableMemoryWatcher::OnMemoryPressureChangedInternal(
// Add all annotations to the provided crash reporter instance.
void nsAvailableMemoryWatcher::AddChildAnnotations(
const UniquePtr<ipc::CrashReporterHost>& aCrashReporter) {
- aCrashReporter->AddAnnotation(CrashReporter::Annotation::MacMemoryPressure,
- mLevelStr);
- aCrashReporter->AddAnnotation(
+ aCrashReporter->AddAnnotationNSCString(
+ CrashReporter::Annotation::MacMemoryPressure, mLevelStr);
+ aCrashReporter->AddAnnotationNSCString(
CrashReporter::Annotation::MacMemoryPressureNormalTime, mNormalTimeStr);
- aCrashReporter->AddAnnotation(
+ aCrashReporter->AddAnnotationNSCString(
CrashReporter::Annotation::MacMemoryPressureWarningTime, mWarningTimeStr);
- aCrashReporter->AddAnnotation(
+ aCrashReporter->AddAnnotationNSCString(
CrashReporter::Annotation::MacMemoryPressureCriticalTime,
mCriticalTimeStr);
- aCrashReporter->AddAnnotation(
+ aCrashReporter->AddAnnotationU32(
CrashReporter::Annotation::MacMemoryPressureSysctl, mLevelSysctl);
- aCrashReporter->AddAnnotation(
+ aCrashReporter->AddAnnotationU32(
CrashReporter::Annotation::MacAvailableMemorySysctl, mAvailMemSysctl);
}
diff --git a/xpcom/base/AvailableMemoryWatcherWin.cpp b/xpcom/base/AvailableMemoryWatcherWin.cpp
index cd027366de..1effbe3226 100644
--- a/xpcom/base/AvailableMemoryWatcherWin.cpp
+++ b/xpcom/base/AvailableMemoryWatcherWin.cpp
@@ -121,6 +121,12 @@ nsresult nsAvailableMemoryWatcher::Init() {
return NS_ERROR_FAILURE;
}
+ static_assert(sizeof(sNumLowPhysicalMemEvents) == sizeof(uint32_t));
+
+ CrashReporter::RegisterAnnotationU32(
+ CrashReporter::Annotation::LowPhysicalMemoryEvents,
+ reinterpret_cast<uint32_t*>(&sNumLowPhysicalMemEvents));
+
return NS_OK;
}
@@ -172,9 +178,6 @@ VOID CALLBACK nsAvailableMemoryWatcher::LowMemoryCallback(PVOID aContext,
// static
void nsAvailableMemoryWatcher::RecordLowMemoryEvent() {
sNumLowPhysicalMemEvents++;
- CrashReporter::AnnotateCrashReport(
- CrashReporter::Annotation::LowPhysicalMemoryEvents,
- sNumLowPhysicalMemEvents);
}
bool nsAvailableMemoryWatcher::RegisterMemoryResourceHandler(
diff --git a/xpcom/base/CFTypeRefPtr.h b/xpcom/base/CFTypeRefPtr.h
new file mode 100644
index 0000000000..185355777e
--- /dev/null
+++ b/xpcom/base/CFTypeRefPtr.h
@@ -0,0 +1,194 @@
+/* -*- 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/. */
+
+#ifndef CFTypeRefPtr_h
+#define CFTypeRefPtr_h
+
+#include "mozilla/Assertions.h"
+#include "mozilla/Attributes.h"
+#include "mozilla/DbgMacro.h"
+#include "mozilla/HashFunctions.h"
+
+// A smart pointer for CoreFoundation classes which does reference counting.
+//
+// Manual reference counting:
+//
+// UInt32 someNumber = 10;
+// CFNumberRef numberObject =
+// CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &someNumber);
+// // do something with numberObject
+// CFRelease(numberObject);
+//
+// Automatic reference counting using CFTypeRefPtr:
+//
+// UInt32 someNumber = 10;
+// auto numberObject =
+// CFTypeRefPtr<CFNumberRef>::WrapUnderCreateRule(
+// CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &someNumber));
+// // do something with numberObject
+// // no CFRelease
+
+template <class PtrT>
+class CFTypeRefPtr {
+ private:
+ void assign_with_CFRetain(PtrT aRawPtr) {
+ CFRetain(aRawPtr);
+ assign_assuming_CFRetain(aRawPtr);
+ }
+
+ void assign_assuming_CFRetain(PtrT aNewPtr) {
+ PtrT oldPtr = mRawPtr;
+ mRawPtr = aNewPtr;
+ if (oldPtr) {
+ CFRelease(oldPtr);
+ }
+ }
+
+ private:
+ PtrT mRawPtr;
+
+ public:
+ ~CFTypeRefPtr() {
+ if (mRawPtr) {
+ CFRelease(mRawPtr);
+ }
+ }
+
+ // Constructors
+
+ CFTypeRefPtr() : mRawPtr(nullptr) {}
+
+ CFTypeRefPtr(const CFTypeRefPtr<PtrT>& aSmartPtr)
+ : mRawPtr(aSmartPtr.mRawPtr) {
+ if (mRawPtr) {
+ CFRetain(mRawPtr);
+ }
+ }
+
+ CFTypeRefPtr(CFTypeRefPtr<PtrT>&& aRefPtr) : mRawPtr(aRefPtr.mRawPtr) {
+ aRefPtr.mRawPtr = nullptr;
+ }
+
+ MOZ_IMPLICIT CFTypeRefPtr(decltype(nullptr)) : mRawPtr(nullptr) {}
+
+ // There is no constructor from a raw pointer value.
+ // Use one of the static WrapUnder*Rule methods below instead.
+
+ static CFTypeRefPtr<PtrT> WrapUnderCreateRule(PtrT aRawPtr) {
+ CFTypeRefPtr<PtrT> ptr;
+ ptr.AssignUnderCreateRule(aRawPtr);
+ return ptr;
+ }
+
+ static CFTypeRefPtr<PtrT> WrapUnderGetRule(PtrT aRawPtr) {
+ CFTypeRefPtr<PtrT> ptr;
+ ptr.AssignUnderGetRule(aRawPtr);
+ return ptr;
+ }
+
+ // Assignment operators
+
+ CFTypeRefPtr<PtrT>& operator=(decltype(nullptr)) {
+ assign_assuming_CFRetain(nullptr);
+ return *this;
+ }
+
+ CFTypeRefPtr<PtrT>& operator=(const CFTypeRefPtr<PtrT>& aRhs) {
+ assign_with_CFRetain(aRhs.mRawPtr);
+ return *this;
+ }
+
+ CFTypeRefPtr<PtrT>& operator=(CFTypeRefPtr<PtrT>&& aRefPtr) {
+ assign_assuming_CFRetain(aRefPtr.mRawPtr);
+ aRefPtr.mRawPtr = nullptr;
+ return *this;
+ }
+
+ // There is no operator= for a raw pointer value.
+ // Use one of the AssignUnder*Rule methods below instead.
+
+ CFTypeRefPtr<PtrT>& AssignUnderCreateRule(PtrT aRawPtr) {
+ // Freshly-created objects come with a retain count of 1.
+ assign_assuming_CFRetain(aRawPtr);
+ return *this;
+ }
+
+ CFTypeRefPtr<PtrT>& AssignUnderGetRule(PtrT aRawPtr) {
+ assign_with_CFRetain(aRawPtr);
+ return *this;
+ }
+
+ // Other pointer operators
+
+ // This is the only way to get the raw pointer out of the smart pointer.
+ // There is no implicit conversion to a raw pointer.
+ PtrT get() const { return mRawPtr; }
+
+ // Don't allow implicit conversion of temporary CFTypeRefPtr to raw pointer,
+ // because the refcount might be one and the pointer will immediately become
+ // invalid.
+ operator PtrT() const&& = delete;
+ // Also don't allow implicit conversion of non-temporary CFTypeRefPtr.
+ operator PtrT() const& = delete;
+
+ // These let you null-check a pointer without calling get().
+ explicit operator bool() const { return !!mRawPtr; }
+};
+
+template <class PtrT>
+inline bool operator==(const CFTypeRefPtr<PtrT>& aLhs,
+ const CFTypeRefPtr<PtrT>& aRhs) {
+ return aLhs.get() == aRhs.get();
+}
+
+template <class PtrT>
+inline bool operator!=(const CFTypeRefPtr<PtrT>& aLhs,
+ const CFTypeRefPtr<PtrT>& aRhs) {
+ return !(aLhs == aRhs);
+}
+
+// Comparing an |CFTypeRefPtr| to |nullptr|
+
+template <class PtrT>
+inline bool operator==(const CFTypeRefPtr<PtrT>& aLhs, decltype(nullptr)) {
+ return aLhs.get() == nullptr;
+}
+
+template <class PtrT>
+inline bool operator==(decltype(nullptr), const CFTypeRefPtr<PtrT>& aRhs) {
+ return nullptr == aRhs.get();
+}
+
+template <class PtrT>
+inline bool operator!=(const CFTypeRefPtr<PtrT>& aLhs, decltype(nullptr)) {
+ return aLhs.get() != nullptr;
+}
+
+template <class PtrT>
+inline bool operator!=(decltype(nullptr), const CFTypeRefPtr<PtrT>& aRhs) {
+ return nullptr != aRhs.get();
+}
+
+// MOZ_DBG support
+
+template <class PtrT>
+std::ostream& operator<<(std::ostream& aOut, const CFTypeRefPtr<PtrT>& aObj) {
+ return mozilla::DebugValue(aOut, aObj.get());
+}
+
+// std::hash support (e.g. for unordered_map)
+namespace std {
+template <class PtrT>
+struct hash<CFTypeRefPtr<PtrT>> {
+ typedef CFTypeRefPtr<PtrT> argument_type;
+ typedef std::size_t result_type;
+ result_type operator()(argument_type const& aPtr) const {
+ return mozilla::HashGeneric(reinterpret_cast<uintptr_t>(aPtr.get()));
+ }
+};
+} // namespace std
+
+#endif /* CFTypeRefPtr_h */
diff --git a/xpcom/base/CycleCollectedJSRuntime.cpp b/xpcom/base/CycleCollectedJSRuntime.cpp
index 03af9e3074..c3f9d56857 100644
--- a/xpcom/base/CycleCollectedJSRuntime.cpp
+++ b/xpcom/base/CycleCollectedJSRuntime.cpp
@@ -1046,7 +1046,7 @@ struct GCMajorMarker : public BaseMarkerType<GCMajorMarker> {
using MS = MarkerSchema;
static constexpr MS::PayloadField PayloadFields[] = {
- {"timings", MS::InputType::String, "GC timings"}};
+ {"timings", MS::InputType::CString, "GC timings"}};
static constexpr MS::Location Locations[] = {MS::Location::MarkerChart,
MS::Location::MarkerTable,
@@ -1793,8 +1793,8 @@ void CycleCollectedJSRuntime::AnnotateAndSetOutOfMemory(OOMState* aStatePtr,
? CrashReporter::Annotation::JSOutOfMemory
: CrashReporter::Annotation::JSLargeAllocationFailure;
- CrashReporter::AnnotateCrashReport(
- annotation, nsDependentCString(OOMStateToString(aNewState)));
+ CrashReporter::RecordAnnotationCString(annotation,
+ OOMStateToString(aNewState));
}
void CycleCollectedJSRuntime::OnGC(JSContext* aContext, JSGCStatus aStatus,
diff --git a/xpcom/base/EnumeratedArrayCycleCollection.h b/xpcom/base/EnumeratedArrayCycleCollection.h
index 465d4cf38a..863b990de7 100644
--- a/xpcom/base/EnumeratedArrayCycleCollection.h
+++ b/xpcom/base/EnumeratedArrayCycleCollection.h
@@ -10,21 +10,21 @@
#include "mozilla/EnumeratedArray.h"
#include "nsCycleCollectionTraversalCallback.h"
-template <typename IndexType, IndexType SizeAsEnumValue, typename ValueType>
+template <typename IndexType, typename ValueType, size_t Size>
inline void ImplCycleCollectionUnlink(
- mozilla::EnumeratedArray<IndexType, SizeAsEnumValue, ValueType>& aField) {
- for (size_t i = 0; i < size_t(SizeAsEnumValue); ++i) {
+ mozilla::EnumeratedArray<IndexType, ValueType, Size>& aField) {
+ for (size_t i = 0; i < Size; ++i) {
aField[IndexType(i)] = nullptr;
}
}
-template <typename IndexType, IndexType SizeAsEnumValue, typename ValueType>
+template <typename IndexType, typename ValueType, size_t Size>
inline void ImplCycleCollectionTraverse(
nsCycleCollectionTraversalCallback& aCallback,
- mozilla::EnumeratedArray<IndexType, SizeAsEnumValue, ValueType>& aField,
+ mozilla::EnumeratedArray<IndexType, ValueType, Size>& aField,
const char* aName, uint32_t aFlags = 0) {
aFlags |= CycleCollectionEdgeNameArrayFlag;
- for (size_t i = 0; i < size_t(SizeAsEnumValue); ++i) {
+ for (size_t i = 0; i < Size; ++i) {
ImplCycleCollectionTraverse(aCallback, aField[IndexType(i)], aName, aFlags);
}
}
diff --git a/xpcom/base/MacHelpers.mm b/xpcom/base/MacHelpers.mm
index 26c04c49dd..9d53fd5b56 100644
--- a/xpcom/base/MacHelpers.mm
+++ b/xpcom/base/MacHelpers.mm
@@ -24,8 +24,7 @@ nsresult GetSelectedCityInfo(nsAString& aCountryCode) {
return NS_ERROR_FAILURE;
}
- return mozilla::CopyCocoaStringToXPCOMString((NSString*)countryCode,
- aCountryCode);
+ mozilla::CopyNSStringToXPCOMString((NSString*)countryCode, aCountryCode);
NS_OBJC_END_TRY_BLOCK_RETURN(NS_ERROR_FAILURE);
}
diff --git a/xpcom/base/MacStringHelpers.h b/xpcom/base/MacStringHelpers.h
index c2f9ee82dc..f43046cfb6 100644
--- a/xpcom/base/MacStringHelpers.h
+++ b/xpcom/base/MacStringHelpers.h
@@ -13,7 +13,11 @@
namespace mozilla {
-nsresult CopyCocoaStringToXPCOMString(NSString* aFrom, nsAString& aTo);
+void CopyNSStringToXPCOMString(const NSString* aFrom, nsAString& aTo);
+
+NSString* XPCOMStringToNSString(const nsAString& aFrom);
+
+NSString* XPCOMStringToNSString(const nsACString& aFrom);
} // namespace mozilla
diff --git a/xpcom/base/MacStringHelpers.mm b/xpcom/base/MacStringHelpers.mm
index cf0b03665d..30b447548a 100644
--- a/xpcom/base/MacStringHelpers.mm
+++ b/xpcom/base/MacStringHelpers.mm
@@ -12,24 +12,42 @@
namespace mozilla {
-nsresult CopyCocoaStringToXPCOMString(NSString* aFrom, nsAString& aTo) {
- NS_OBJC_BEGIN_TRY_BLOCK_RETURN;
+void CopyNSStringToXPCOMString(const NSString* aFrom, nsAString& aTo) {
+ NS_OBJC_BEGIN_TRY_IGNORE_BLOCK;
- NSUInteger len = [aFrom length];
- if (len > std::numeric_limits<nsAString::size_type>::max()) {
- return NS_ERROR_OUT_OF_MEMORY;
+ if (!aFrom) {
+ aTo.Truncate();
+ return;
}
- if (!aTo.SetLength(len, mozilla::fallible)) {
- return NS_ERROR_OUT_OF_MEMORY;
+ NSUInteger len = [aFrom length];
+ if (len > std::numeric_limits<nsAString::size_type>::max()) {
+ aTo.AllocFailed(std::numeric_limits<nsAString::size_type>::max());
}
+ aTo.SetLength(len);
[aFrom getCharacters:reinterpret_cast<unichar*>(aTo.BeginWriting())
range:NSMakeRange(0, len)];
- return NS_OK;
+ NS_OBJC_END_TRY_IGNORE_BLOCK;
+}
- NS_OBJC_END_TRY_BLOCK_RETURN(NS_ERROR_FAILURE);
+NSString* XPCOMStringToNSString(const nsAString& aFrom) {
+ if (aFrom.IsEmpty()) {
+ return [NSString string];
+ }
+ return [NSString stringWithCharacters:reinterpret_cast<const unichar*>(
+ aFrom.BeginReading())
+ length:aFrom.Length()];
+}
+
+NSString* XPCOMStringToNSString(const nsACString& aFrom) {
+ if (aFrom.IsEmpty()) {
+ return [NSString string];
+ }
+ return [[[NSString alloc] initWithBytes:aFrom.BeginReading()
+ length:aFrom.Length()
+ encoding:NSUTF8StringEncoding] autorelease];
}
} // namespace mozilla
diff --git a/xpcom/base/moz.build b/xpcom/base/moz.build
index 1ac409ed04..16870a9dbc 100644
--- a/xpcom/base/moz.build
+++ b/xpcom/base/moz.build
@@ -27,18 +27,24 @@ if CONFIG["MOZ_WIDGET_TOOLKIT"] == "cocoa":
XPIDL_SOURCES += [
"nsIMacPreferencesReader.idl",
]
+ EXPORTS.mozilla += [
+ "MacHelpers.h",
+ "nsMacPreferencesReader.h",
+ ]
+ UNIFIED_SOURCES += [
+ "MacHelpers.mm",
+ "nsMacPreferencesReader.mm",
+ ]
+if CONFIG["OS_ARCH"] == "Darwin":
EXPORTS += [
+ "CFTypeRefPtr.h",
"nsObjCExceptions.h",
]
EXPORTS.mozilla += [
- "MacHelpers.h",
"MacStringHelpers.h",
- "nsMacPreferencesReader.h",
]
UNIFIED_SOURCES += [
- "MacHelpers.mm",
"MacStringHelpers.mm",
- "nsMacPreferencesReader.mm",
"nsObjCExceptions.mm",
]
diff --git a/xpcom/base/nsCycleCollector.cpp b/xpcom/base/nsCycleCollector.cpp
index 9c885b6ef1..9c39dee475 100644
--- a/xpcom/base/nsCycleCollector.cpp
+++ b/xpcom/base/nsCycleCollector.cpp
@@ -628,8 +628,8 @@ void PtrInfo::AnnotatedReleaseAssert(bool aCondition, const char* aMessage) {
}
nsPrintfCString msg("%s, for class %s", aMessage, piName);
NS_WARNING(msg.get());
- CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::CycleCollector,
- msg);
+ CrashReporter::RecordAnnotationNSCString(
+ CrashReporter::Annotation::CycleCollector, msg);
MOZ_CRASH();
}
diff --git a/xpcom/base/nsDebugImpl.cpp b/xpcom/base/nsDebugImpl.cpp
index 4023efd0ec..81305ccdb9 100644
--- a/xpcom/base/nsDebugImpl.cpp
+++ b/xpcom/base/nsDebugImpl.cpp
@@ -452,13 +452,12 @@ NS_DebugBreak(uint32_t aSeverity, const char* aStr, const char* aExpr,
if (XRE_IsParentProcess()) {
// Don't include the PID in the crash report annotation to
// allow faceting on crash-stats.mozilla.org.
- nsCString note("xpcom_runtime_abort(");
+ nsAutoCString note("xpcom_runtime_abort(");
note += nonPIDBuf.buffer;
note += ")";
CrashReporter::AppendAppNotesToCrashReport(note);
- CrashReporter::AnnotateCrashReport(
- CrashReporter::Annotation::AbortMessage,
- nsDependentCString(nonPIDBuf.buffer));
+ CrashReporter::RecordAnnotationNSCString(
+ CrashReporter::Annotation::AbortMessage, note);
}
#if defined(DEBUG) && defined(_WIN32)
diff --git a/xpcom/base/nsISupportsImpl.cpp b/xpcom/base/nsISupportsImpl.cpp
index c282ec14db..5ae4b3914b 100644
--- a/xpcom/base/nsISupportsImpl.cpp
+++ b/xpcom/base/nsISupportsImpl.cpp
@@ -50,13 +50,25 @@ bool nsAutoOwningThread::IsCurrentThread() const {
nsAutoOwningEventTarget::nsAutoOwningEventTarget()
: mTarget(GetCurrentSerialEventTarget()) {
- mTarget->AddRef();
+ NS_ADDREF(mTarget);
}
-nsAutoOwningEventTarget::~nsAutoOwningEventTarget() {
- nsCOMPtr<nsISerialEventTarget> target = dont_AddRef(mTarget);
+nsAutoOwningEventTarget::nsAutoOwningEventTarget(
+ const nsAutoOwningEventTarget& aOther)
+ : mTarget(aOther.mTarget) {
+ NS_ADDREF(mTarget);
}
+nsAutoOwningEventTarget& nsAutoOwningEventTarget::operator=(
+ const nsAutoOwningEventTarget& aRhs) {
+ nsISerialEventTarget* previous = std::exchange(mTarget, aRhs.mTarget);
+ NS_ADDREF(mTarget);
+ NS_RELEASE(previous);
+ return *this;
+}
+
+nsAutoOwningEventTarget::~nsAutoOwningEventTarget() { NS_RELEASE(mTarget); }
+
void nsAutoOwningEventTarget ::AssertCurrentThreadOwnsMe(
const char* msg) const {
if (MOZ_UNLIKELY(!IsCurrentThread())) {
diff --git a/xpcom/base/nsISupportsImpl.h b/xpcom/base/nsISupportsImpl.h
index 27ff85b385..0485a98812 100644
--- a/xpcom/base/nsISupportsImpl.h
+++ b/xpcom/base/nsISupportsImpl.h
@@ -71,6 +71,20 @@ class nsISerialEventTarget;
class nsAutoOwningEventTarget {
public:
nsAutoOwningEventTarget();
+
+ nsAutoOwningEventTarget(const nsAutoOwningEventTarget& aOther);
+
+ // Per https://en.cppreference.com/w/cpp/language/move_constructor
+ // there's no implicitly-declared move constructor if there are user-declared
+ // copy constructors, and we have one, immediately above.
+
+ nsAutoOwningEventTarget& operator=(const nsAutoOwningEventTarget& aRhs);
+
+ // Per https://en.cppreference.com/w/cpp/language/move_assignment
+ // there's no implicitly-declared move assignment operator if there are
+ // user-declared copy assignment operators, and we have one, immediately
+ // above.
+
~nsAutoOwningEventTarget();
// We move the actual assertion checks out-of-line to minimize code bloat,
@@ -88,6 +102,7 @@ class nsAutoOwningEventTarget {
private:
void AssertCurrentThreadOwnsMe(const char* aMsg) const;
+ // A raw pointer to avoid nsCOMPtr.h dependency.
nsISerialEventTarget* mTarget;
};
diff --git a/xpcom/base/nsrootidl.idl b/xpcom/base/nsrootidl.idl
index 28e643e312..292ea54890 100644
--- a/xpcom/base/nsrootidl.idl
+++ b/xpcom/base/nsrootidl.idl
@@ -35,18 +35,21 @@ class Promise;
#if 0
%}
-typedef boolean bool ;
-typedef octet uint8_t ;
-typedef unsigned short uint16_t ;
-typedef unsigned short char16_t;
-typedef unsigned long uint32_t ;
-typedef unsigned long long uint64_t ;
-typedef long long PRTime ;
-typedef short int16_t ;
-typedef long int32_t ;
-typedef long long int64_t ;
-
-typedef unsigned long nsresult ;
+// [substitute] typedefs emit the underlying builtin type directly, and
+// avoid polluting bindings for other languages with C++ stdint types.
+
+[substitute] typedef boolean bool ;
+[substitute] typedef octet uint8_t ;
+[substitute] typedef unsigned short uint16_t ;
+[substitute] typedef unsigned long uint32_t ;
+[substitute] typedef unsigned long long uint64_t ;
+[substitute] typedef short int16_t ;
+[substitute] typedef long int32_t ;
+[substitute] typedef long long int64_t ;
+
+ typedef unsigned short char16_t ;
+ typedef unsigned long nsresult ;
+ typedef long long PRTime ;
// If we ever want to use `size_t` in scriptable interfaces, this will need to
// be built into the xpidl compiler, as the size varies based on platform.
diff --git a/xpcom/components/StaticComponents.cpp.in b/xpcom/components/StaticComponents.cpp.in
index 7f3fee6859..d717b9f64a 100644
--- a/xpcom/components/StaticComponents.cpp.in
+++ b/xpcom/components/StaticComponents.cpp.in
@@ -83,9 +83,14 @@ const nsXPTInterface gInterfaces[] = {
//# @interfaces@
};
+//# @define_has_component_jsms@
+
+#ifdef HAS_COMPONENT_JSMS
+// TODO: Remove this once m-c and c-c migrations finish (bug 1881887).
const StringOffset gComponentJSMs[] = {
//# @component_jsms@
};
+#endif
const StringOffset gComponentESModules[] = {
//# @component_esmodules@
@@ -148,9 +153,9 @@ static nsresult ConstructJSMOrESMComponent(const nsACString& aURI,
(void**)aResult);
}
-static nsresult ConstructJSMComponent(const nsACString& aURI,
- const char* aConstructor,
- nsISupports** aResult) {
+[[maybe_unused]] static nsresult ConstructJSMComponent(const nsACString& aURI,
+ const char* aConstructor,
+ nsISupports** aResult) {
return ConstructJSMOrESMComponent<ComponentType::JSM>(
aURI, aConstructor, aResult);
}
@@ -351,11 +356,15 @@ const StaticProtocolHandler* StaticProtocolHandler::Lookup(const nsACString& aSc
/* static */ already_AddRefed<nsIUTF8StringEnumerator>
StaticComponents::GetComponentJSMs() {
+#ifdef HAS_COMPONENT_JSMS
auto jsms = MakeUnique<nsTArray<nsCString>>(MOZ_ARRAY_LENGTH(gComponentJSMs));
for (const auto& entry : gComponentJSMs) {
jsms->AppendElement(GetString(entry));
}
+#else
+ auto jsms = MakeUnique<nsTArray<nsCString>>(0);
+#endif
nsCOMPtr<nsIUTF8StringEnumerator> result;
MOZ_ALWAYS_SUCCEEDS(NS_NewAdoptingUTF8StringEnumerator(getter_AddRefs(result),
diff --git a/xpcom/components/gen_static_components.py b/xpcom/components/gen_static_components.py
index f759dc3132..122b7b21ca 100644
--- a/xpcom/components/gen_static_components.py
+++ b/xpcom/components/gen_static_components.py
@@ -920,14 +920,18 @@ def gen_substs(manifests):
cid_phf = PerfectHash(modules, PHF_SIZE, key=lambda module: module.cid.bytes)
- contract_phf = PerfectHash(contracts, PHF_SIZE, key=lambda entry: entry.contract)
+ contract_phf = PerfectHash(
+ contracts, PHF_SIZE, key=lambda entry: entry.contract.encode()
+ )
js_services_phf = PerfectHash(
- list(js_services.values()), PHF_SIZE, key=lambda entry: entry.js_name
+ list(js_services.values()), PHF_SIZE, key=lambda entry: entry.js_name.encode()
)
protocol_handlers_phf = PerfectHash(
- list(protocol_handlers.values()), TINY_PHF_SIZE, key=lambda entry: entry.scheme
+ list(protocol_handlers.values()),
+ TINY_PHF_SIZE,
+ key=lambda entry: entry.scheme.encode(),
)
js_services_json = {}
@@ -945,7 +949,7 @@ def gen_substs(manifests):
substs["contract_count"] = len(contracts)
substs["protocol_handler_count"] = len(protocol_handlers)
- substs["default_protocol_handler_idx"] = protocol_handlers_phf.get_index("default")
+ substs["default_protocol_handler_idx"] = protocol_handlers_phf.get_index(b"default")
gen_module_funcs(substs, module_funcs)
@@ -954,6 +958,9 @@ def gen_substs(manifests):
substs["component_jsms"] = (
"\n".join(" %s," % strings.entry_to_cxx(jsm) for jsm in sorted(jsms)) + "\n"
)
+ substs["define_has_component_jsms"] = (
+ "#define HAS_COMPONENT_JSMS" if len(jsms) > 0 else ""
+ )
substs["component_esmodules"] = (
"\n".join(
" %s," % strings.entry_to_cxx(esModule) for esModule in sorted(esModules)
@@ -1021,7 +1028,9 @@ def gen_substs(manifests):
key_length="aKey.Length()",
)
- substs["js_services_json"] = json.dumps(js_services_json, sort_keys=True, indent=4)
+ substs["js_services_json"] = (
+ json.dumps(js_services_json, sort_keys=True, indent=2) + "\n"
+ )
# Do this only after everything else has been emitted so we're sure the
# string table is complete.
diff --git a/xpcom/components/nsIComponentManager.idl b/xpcom/components/nsIComponentManager.idl
index 9abde9960c..6b921be004 100644
--- a/xpcom/components/nsIComponentManager.idl
+++ b/xpcom/components/nsIComponentManager.idl
@@ -99,6 +99,8 @@ interface nsIComponentManager : nsISupports
/**
* Returns a list of JSM URLs which are used to create components. This
* should only be used in automation.
+ *
+ * TODO: Remove this once m-c and c-c migrations finish (bug 1881887).
*/
nsIUTF8StringEnumerator getComponentJSMs();
diff --git a/xpcom/components/nsIServiceManager.idl b/xpcom/components/nsIServiceManager.idl
index dd613070e9..e327b49d79 100644
--- a/xpcom/components/nsIServiceManager.idl
+++ b/xpcom/components/nsIServiceManager.idl
@@ -59,9 +59,6 @@ interface nsIServiceManager : nsISupports
%{C++
-// Observing xpcom autoregistration. Topics will be 'start' and 'stop'.
-#define NS_XPCOM_AUTOREGISTRATION_OBSERVER_ID "xpcom-autoregistration"
-
#ifdef MOZILLA_INTERNAL_API
#include "nsXPCOM.h"
#include "nsComponentManagerUtils.h"
diff --git a/xpcom/docs/stringguide.rst b/xpcom/docs/stringguide.rst
index a3266d9604..ceba003245 100644
--- a/xpcom/docs/stringguide.rst
+++ b/xpcom/docs/stringguide.rst
@@ -342,11 +342,11 @@ bucket could accommodate the new logical length.
Helper Classes and Functions
----------------------------
-Converting Cocoa strings
-~~~~~~~~~~~~~~~~~~~~~~~~
+Converting NSString strings
+~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Use ``mozilla::CopyCocoaStringToXPCOMString()`` in
-``mozilla/MacStringHelpers.h`` to convert Cocoa strings to XPCOM strings.
+Use ``mozilla::CopyNSStringToXPCOMString()`` in
+``mozilla/MacStringHelpers.h`` to convert NSString strings to XPCOM strings.
Searching strings - looking for substrings, characters, etc.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/xpcom/ds/HTMLAtoms.py b/xpcom/ds/HTMLAtoms.py
index ddaf52ae9f..927be525e3 100644
--- a/xpcom/ds/HTMLAtoms.py
+++ b/xpcom/ds/HTMLAtoms.py
@@ -41,6 +41,8 @@ HTML_PARSER_ATOMS = [
# ATOM GENERATED BY HTML PARSER TRANSLATOR (WILL BE AUTOMATICALLY OVERWRITTEN):
Atom("shadowrootmode", "shadowrootmode"),
# ATOM GENERATED BY HTML PARSER TRANSLATOR (WILL BE AUTOMATICALLY OVERWRITTEN):
+ Atom("shadowrootclonable", "shadowrootclonable"),
+ # ATOM GENERATED BY HTML PARSER TRANSLATOR (WILL BE AUTOMATICALLY OVERWRITTEN):
Atom("stddeviation", "stddeviation"),
# ATOM GENERATED BY HTML PARSER TRANSLATOR (WILL BE AUTOMATICALLY OVERWRITTEN):
Atom("shadowrootdelegatesfocus", "shadowrootdelegatesfocus"),
diff --git a/xpcom/ds/StaticAtoms.py b/xpcom/ds/StaticAtoms.py
index ca4ac97813..2a0a25431e 100644
--- a/xpcom/ds/StaticAtoms.py
+++ b/xpcom/ds/StaticAtoms.py
@@ -121,6 +121,8 @@ STATIC_ATOMS = [
Atom("aria_activedescendant", "aria-activedescendant"),
Atom("aria_atomic", "aria-atomic"),
Atom("aria_autocomplete", "aria-autocomplete"),
+ Atom("aria_braillelabel", "aria-braillelabel"),
+ Atom("aria_brailleroledescription", "aria-brailleroledescription"),
Atom("aria_busy", "aria-busy"),
Atom("aria_checked", "aria-checked"),
Atom("aria_controls", "aria-controls"),
@@ -206,7 +208,6 @@ STATIC_ATOMS = [
Atom("box", "box"),
Atom("br", "br"),
Atom("browser", "browser"),
- Atom("mozbrowser", "mozbrowser"),
Atom("button", "button"),
Atom("callTemplate", "call-template"),
Atom("canvas", "canvas"),
@@ -340,7 +341,6 @@ STATIC_ATOMS = [
Atom("difference", "difference"),
Atom("digit", "digit"),
Atom("dir", "dir"),
- Atom("dirAutoSetBy", "dirAutoSetBy"),
Atom("directory", "directory"),
Atom("dirname", "dirname"),
Atom("disableOutputEscaping", "disable-output-escaping"),
@@ -453,7 +453,6 @@ STATIC_ATOMS = [
Atom("flags", "flags"),
Atom("flex", "flex"),
Atom("flip", "flip"),
- Atom("floating", "floating"),
Atom("floor", "floor"),
Atom("flowlength", "flowlength"),
Atom("focus", "focus"),
@@ -731,6 +730,7 @@ STATIC_ATOMS = [
Atom("noembed", "noembed"),
Atom("noframes", "noframes"),
Atom("nohref", "nohref"),
+ Atom("noinitialselection", "noinitialselection"),
Atom("nomodule", "nomodule"),
Atom("nonce", "nonce"),
Atom("none", "none"),
@@ -832,6 +832,7 @@ STATIC_ATOMS = [
Atom("onfocusout", "onfocusout"),
Atom("onfullscreenchange", "onfullscreenchange"),
Atom("onfullscreenerror", "onfullscreenerror"),
+ Atom("ongatheringstatechange", "ongatheringstatechange"),
Atom("onget", "onget"),
Atom("onhashchange", "onhashchange"),
Atom("oninput", "oninput"),
@@ -1062,6 +1063,7 @@ STATIC_ATOMS = [
Atom("rem", "rem"),
Atom("remote", "remote"),
Atom("removeelement", "removeelement"),
+ Atom("render", "render"),
Atom("renderingobserverset", "renderingobserverset"),
Atom("repeat", "repeat"),
Atom("replace", "replace"),
@@ -1234,7 +1236,6 @@ STATIC_ATOMS = [
Atom("textarea", "textarea"),
Atom("textbox", "textbox"),
Atom("textLink", "text-link"),
- Atom("textNodeDirectionalityMap", "textNodeDirectionalityMap"),
Atom("textOverlay", "text-overlay"),
Atom("tfoot", "tfoot"),
Atom("th", "th"),
@@ -1242,7 +1243,6 @@ STATIC_ATOMS = [
Atom("thumb", "thumb"),
Atom("time", "time"),
Atom("title", "title"),
- Atom("titlebar", "titlebar"),
Atom("titletip", "titletip"),
Atom("toggle", "toggle"),
Atom("token", "token"),
@@ -2262,6 +2262,7 @@ STATIC_ATOMS = [
Atom("_moz_swipe_animation_enabled", "-moz-swipe-animation-enabled"),
Atom("_moz_gtk_csd_available", "-moz-gtk-csd-available"),
Atom("_moz_gtk_csd_titlebar_radius", "-moz-gtk-csd-titlebar-radius"),
+ Atom("_moz_gtk_csd_titlebar_button_spacing", "-moz-gtk-csd-titlebar-button-spacing"),
Atom("_moz_gtk_csd_minimize_button", "-moz-gtk-csd-minimize-button"),
Atom("_moz_gtk_csd_minimize_button_position", "-moz-gtk-csd-minimize-button-position"),
Atom("_moz_gtk_csd_maximize_button", "-moz-gtk-csd-maximize-button"),
@@ -2409,6 +2410,8 @@ STATIC_ATOMS = [
Atom("mathml_legacy_mathvariant_attribute_disabled", "mathml.legacy_mathvariant_attribute.disabled"),
Atom("layout_css_always_underline_links", "layout.css.always_underline_links"),
Atom("layout_css_cached_scrollbar_styles_enabled", "layout.css.cached-scrollbar-styles.enabled"),
+ Atom("layout_css_h1_in_section_ua_styles_enabled", "layout.css.h1-in-section-ua-styles.enabled"),
+ Atom("dom_forms_number_hide_spin_buttons_when_no_hover_or_focus", "dom.forms.number.hide_spin_buttons_when_no_hover_or_focus"),
# Contextual Identity / Containers
Atom("usercontextid", "usercontextid"),
Atom("geckoViewSessionContextId", "geckoViewSessionContextId"),
@@ -2525,7 +2528,6 @@ STATIC_ATOMS = [
InheritingAnonBoxAtom("AnonBox_cellContent", ":-moz-cell-content"),
InheritingAnonBoxAtom("AnonBox_dropDownList", ":-moz-dropdown-list"),
InheritingAnonBoxAtom("AnonBox_fieldsetContent", ":-moz-fieldset-content"),
- InheritingAnonBoxAtom("AnonBox_mozDisplayComboboxControlFrame", ":-moz-display-comboboxcontrol-frame"),
InheritingAnonBoxAtom("AnonBox_htmlCanvasContent", ":-moz-html-canvas-content"),
InheritingAnonBoxAtom("AnonBox_inlineTable", ":-moz-inline-table"),
InheritingAnonBoxAtom("AnonBox_table", ":-moz-table"),
diff --git a/xpcom/ds/nsObserverService.cpp b/xpcom/ds/nsObserverService.cpp
index e0fd430cd4..882d867474 100644
--- a/xpcom/ds/nsObserverService.cpp
+++ b/xpcom/ds/nsObserverService.cpp
@@ -180,13 +180,14 @@ nsresult nsObserverService::EnsureValidCall() const {
}
nsresult nsObserverService::FilterHttpOnTopics(const char* aTopic) {
- // Specifically allow http-on-opening-request and http-on-stop-request in the
- // child process; see bug 1269765.
+ // Specifically allow some http-on-* observer notifications in the child
+ // process.
if (mozilla::net::IsNeckoChild() && !strncmp(aTopic, "http-on-", 8) &&
+ strcmp(aTopic, "http-on-before-stop-request") &&
strcmp(aTopic, "http-on-failed-opening-request") &&
+ strcmp(aTopic, "http-on-image-cache-response") &&
strcmp(aTopic, "http-on-opening-request") &&
- strcmp(aTopic, "http-on-stop-request") &&
- strcmp(aTopic, "http-on-image-cache-response")) {
+ strcmp(aTopic, "http-on-stop-request")) {
nsCOMPtr<nsIConsoleService> console(
do_GetService(NS_CONSOLESERVICE_CONTRACTID));
nsCOMPtr<nsIScriptError> error(
diff --git a/xpcom/ds/tools/perfecthash.py b/xpcom/ds/tools/perfecthash.py
index 929b643a30..2a5778e86d 100644
--- a/xpcom/ds/tools/perfecthash.py
+++ b/xpcom/ds/tools/perfecthash.py
@@ -24,18 +24,6 @@ small dataset it was designed for. In the future we may want to optimize further
import textwrap
from collections import namedtuple
-import six
-from mozbuild.util import ensure_bytes
-
-
-# Iteration over bytestrings works differently in Python 2 and 3; this function
-# captures the two possibilities. Returns an 'int' given the output of iterating
-# through a bytestring regardless of the input.
-def _ord(c):
- if six.PY3:
- return c
- return ord(c)
-
class PerfectHash(object):
"""PerfectHash objects represent a computed perfect hash function, which
@@ -88,7 +76,7 @@ class PerfectHash(object):
for bucket in buckets:
# Once we've reached an empty bucket, we're done.
- if len(bucket.entries) == 0:
+ if not bucket.entries:
break
# Try values for the basis until we find one with no conflicts.
@@ -103,7 +91,7 @@ class PerfectHash(object):
# There was a conflict, try the next basis.
basis += 1
idx = 0
- del slots[:]
+ slots.clear()
assert basis < self.U32_MAX, "table too small"
else:
slots.append(slot)
@@ -127,15 +115,16 @@ class PerfectHash(object):
32-bit FNV is used for indexing into the first table, and the value
stored in that table is used as the offset basis for indexing into the
values table."""
- for byte in memoryview(ensure_bytes(key)):
- obyte = _ord(byte)
+ FNV_PRIME = cls.FNV_PRIME
+ U32_MAX = cls.U32_MAX
+ for obyte in memoryview(key):
basis ^= obyte # xor-in the byte
- basis *= cls.FNV_PRIME # Multiply by the FNV prime
- basis &= cls.U32_MAX # clamp to 32-bits
+ basis *= FNV_PRIME # Multiply by the FNV prime
+ basis &= U32_MAX # clamp to 32-bits
return basis
def key(self, entry):
- return memoryview(ensure_bytes(self._key(entry)))
+ return memoryview(self._key(entry))
def get_raw_index(self, key):
"""Determine the index in self.entries without validating"""
@@ -145,7 +134,7 @@ class PerfectHash(object):
def get_index(self, key):
"""Given a key, determine the index in self.entries"""
idx = self.get_raw_index(key)
- if memoryview(ensure_bytes(key)) != self.key(self.entries[idx]):
+ if memoryview(key) != self.key(self.entries[idx]):
return None
return idx
@@ -334,7 +323,7 @@ class CGHelper(object):
not in the table."""
assert all(
- _ord(b) <= 0x7F for e in self.phf.entries for b in self.phf.key(e)
+ b <= 0x7F for e in self.phf.entries for b in self.phf.key(e)
), "non-ASCII key"
if return_type is None:
diff --git a/xpcom/idl-parser/xpidl/fixtures/xpctest.d.json b/xpcom/idl-parser/xpidl/fixtures/xpctest.d.json
new file mode 100644
index 0000000000..fb3cb7e6b7
--- /dev/null
+++ b/xpcom/idl-parser/xpidl/fixtures/xpctest.d.json
@@ -0,0 +1,1402 @@
+[
+ {
+ "interfaces": [
+ {
+ "base": "nsISupports",
+ "callable": false,
+ "consts": [],
+ "enums": [],
+ "id": "nsIXPCTestObjectReadOnly",
+ "members": [
+ {
+ "name": "strReadOnly",
+ "readonly": true,
+ "type": "string"
+ },
+ {
+ "name": "boolReadOnly",
+ "readonly": true,
+ "type": "boolean"
+ },
+ {
+ "name": "shortReadOnly",
+ "readonly": true,
+ "type": "i16"
+ },
+ {
+ "name": "longReadOnly",
+ "readonly": true,
+ "type": "i32"
+ },
+ {
+ "name": "floatReadOnly",
+ "readonly": true,
+ "type": "float"
+ },
+ {
+ "name": "charReadOnly",
+ "readonly": true,
+ "type": "string"
+ },
+ {
+ "name": "timeReadOnly",
+ "readonly": true,
+ "type": "PRTime"
+ }
+ ]
+ },
+ {
+ "base": "nsISupports",
+ "callable": false,
+ "consts": [],
+ "enums": [],
+ "id": "nsIXPCTestObjectReadWrite",
+ "members": [
+ {
+ "name": "stringProperty",
+ "readonly": false,
+ "type": "string"
+ },
+ {
+ "name": "booleanProperty",
+ "readonly": false,
+ "type": "boolean"
+ },
+ {
+ "name": "shortProperty",
+ "readonly": false,
+ "type": "i16"
+ },
+ {
+ "name": "longProperty",
+ "readonly": false,
+ "type": "i32"
+ },
+ {
+ "name": "floatProperty",
+ "readonly": false,
+ "type": "float"
+ },
+ {
+ "name": "charProperty",
+ "readonly": false,
+ "type": "string"
+ },
+ {
+ "name": "timeProperty",
+ "readonly": false,
+ "type": "PRTime"
+ }
+ ]
+ }
+ ],
+ "path": "js/xpconnect/tests/idl/xpctest_attributes.idl",
+ "typedefs": [
+ [
+ "PRTime",
+ "i64"
+ ],
+ [
+ "char16_t",
+ "u16"
+ ],
+ [
+ "nsresult",
+ "u32"
+ ]
+ ]
+ },
+ {
+ "interfaces": [
+ {
+ "base": "nsISupports",
+ "callable": false,
+ "consts": [],
+ "enums": [],
+ "id": "nsIXPCTestBug809674",
+ "members": [
+ {
+ "args": [
+ {
+ "name": "x",
+ "optional": false,
+ "type": "u32"
+ },
+ {
+ "name": "y",
+ "optional": false,
+ "type": "u32"
+ }
+ ],
+ "iid_is": null,
+ "name": "addArgs",
+ "type": "u32"
+ },
+ {
+ "args": [
+ {
+ "name": "x",
+ "optional": false,
+ "type": "u32"
+ },
+ {
+ "name": "y",
+ "optional": false,
+ "type": "u32"
+ },
+ {
+ "name": "subOut",
+ "optional": false,
+ "type": "OutParam<u32>"
+ },
+ {
+ "name": "mulOut",
+ "optional": false,
+ "type": "OutParam<u32>"
+ }
+ ],
+ "iid_is": null,
+ "name": "addSubMulArgs",
+ "type": "u32"
+ },
+ {
+ "args": [
+ {
+ "name": "x",
+ "optional": false,
+ "type": "any"
+ },
+ {
+ "name": "y",
+ "optional": false,
+ "type": "any"
+ }
+ ],
+ "iid_is": null,
+ "name": "addVals",
+ "type": "any"
+ },
+ {
+ "args": [],
+ "iid_is": null,
+ "name": "methodNoArgs",
+ "type": "u32"
+ },
+ {
+ "args": [],
+ "iid_is": null,
+ "name": "methodNoArgsNoRetVal",
+ "type": "void"
+ },
+ {
+ "args": [
+ {
+ "name": "x1",
+ "optional": false,
+ "type": "u32"
+ },
+ {
+ "name": "x2",
+ "optional": false,
+ "type": "u32"
+ },
+ {
+ "name": "x3",
+ "optional": false,
+ "type": "u32"
+ },
+ {
+ "name": "x4",
+ "optional": false,
+ "type": "u32"
+ },
+ {
+ "name": "x5",
+ "optional": false,
+ "type": "u32"
+ },
+ {
+ "name": "x6",
+ "optional": false,
+ "type": "u32"
+ },
+ {
+ "name": "x7",
+ "optional": false,
+ "type": "u32"
+ },
+ {
+ "name": "x8",
+ "optional": false,
+ "type": "u32"
+ }
+ ],
+ "iid_is": null,
+ "name": "addMany",
+ "type": "u32"
+ },
+ {
+ "name": "valProperty",
+ "readonly": false,
+ "type": "any"
+ },
+ {
+ "name": "uintProperty",
+ "readonly": false,
+ "type": "u32"
+ },
+ {
+ "args": [],
+ "iid_is": null,
+ "name": "methodWithOptionalArgc",
+ "type": "void"
+ }
+ ]
+ }
+ ],
+ "path": "js/xpconnect/tests/idl/xpctest_bug809674.idl",
+ "typedefs": [
+ [
+ "PRTime",
+ "i64"
+ ],
+ [
+ "char16_t",
+ "u16"
+ ],
+ [
+ "nsresult",
+ "u32"
+ ]
+ ]
+ },
+ {
+ "interfaces": [
+ {
+ "base": "nsISupports",
+ "callable": false,
+ "consts": [
+ {
+ "name": "testConst",
+ "value": 1
+ }
+ ],
+ "enums": [
+ {
+ "id": "testFlagsExplicit",
+ "variants": [
+ {
+ "name": "shouldBe1Explicit",
+ "value": 1
+ },
+ {
+ "name": "shouldBe2Explicit",
+ "value": 2
+ },
+ {
+ "name": "shouldBe4Explicit",
+ "value": 4
+ },
+ {
+ "name": "shouldBe8Explicit",
+ "value": 8
+ },
+ {
+ "name": "shouldBe12Explicit",
+ "value": 12
+ }
+ ]
+ },
+ {
+ "id": "testFlagsImplicit",
+ "variants": [
+ {
+ "name": "shouldBe0Implicit",
+ "value": 0
+ },
+ {
+ "name": "shouldBe1Implicit",
+ "value": 1
+ },
+ {
+ "name": "shouldBe2Implicit",
+ "value": 2
+ },
+ {
+ "name": "shouldBe3Implicit",
+ "value": 3
+ },
+ {
+ "name": "shouldBe5Implicit",
+ "value": 5
+ },
+ {
+ "name": "shouldBe6Implicit",
+ "value": 6
+ },
+ {
+ "name": "shouldBe2AgainImplicit",
+ "value": 2
+ },
+ {
+ "name": "shouldBe3AgainImplicit",
+ "value": 3
+ }
+ ]
+ }
+ ],
+ "id": "nsIXPCTestCEnums",
+ "members": [
+ {
+ "args": [
+ {
+ "name": "abc",
+ "optional": false,
+ "type": "nsIXPCTestCEnums.testFlagsExplicit"
+ }
+ ],
+ "iid_is": null,
+ "name": "testCEnumInput",
+ "type": "void"
+ },
+ {
+ "args": [],
+ "iid_is": null,
+ "name": "testCEnumOutput",
+ "type": "nsIXPCTestCEnums.testFlagsExplicit"
+ }
+ ]
+ }
+ ],
+ "path": "js/xpconnect/tests/idl/xpctest_cenums.idl",
+ "typedefs": [
+ [
+ "PRTime",
+ "i64"
+ ],
+ [
+ "char16_t",
+ "u16"
+ ],
+ [
+ "nsresult",
+ "u32"
+ ]
+ ]
+ },
+ {
+ "interfaces": [
+ {
+ "base": "nsISupports",
+ "callable": false,
+ "consts": [],
+ "enums": [],
+ "id": "nsIXPCTestInterfaceA",
+ "members": [
+ {
+ "name": "name",
+ "readonly": false,
+ "type": "string"
+ }
+ ]
+ },
+ {
+ "base": "nsISupports",
+ "callable": false,
+ "consts": [],
+ "enums": [],
+ "id": "nsIXPCTestInterfaceB",
+ "members": [
+ {
+ "name": "name",
+ "readonly": false,
+ "type": "string"
+ }
+ ]
+ },
+ {
+ "base": "nsISupports",
+ "callable": false,
+ "consts": [],
+ "enums": [],
+ "id": "nsIXPCTestInterfaceC",
+ "members": [
+ {
+ "name": "someInteger",
+ "readonly": false,
+ "type": "i32"
+ }
+ ]
+ }
+ ],
+ "path": "js/xpconnect/tests/idl/xpctest_interfaces.idl",
+ "typedefs": [
+ [
+ "PRTime",
+ "i64"
+ ],
+ [
+ "char16_t",
+ "u16"
+ ],
+ [
+ "nsresult",
+ "u32"
+ ]
+ ]
+ },
+ {
+ "interfaces": [
+ {
+ "base": "nsISupports",
+ "callable": false,
+ "consts": [],
+ "enums": [],
+ "id": "nsIXPCTestParams",
+ "members": [
+ {
+ "args": [
+ {
+ "name": "a",
+ "optional": false,
+ "type": "boolean"
+ },
+ {
+ "name": "b",
+ "optional": false,
+ "type": "InOutParam<boolean>"
+ }
+ ],
+ "iid_is": null,
+ "name": "testBoolean",
+ "type": "boolean"
+ },
+ {
+ "args": [
+ {
+ "name": "a",
+ "optional": false,
+ "type": "u8"
+ },
+ {
+ "name": "b",
+ "optional": false,
+ "type": "InOutParam<u8>"
+ }
+ ],
+ "iid_is": null,
+ "name": "testOctet",
+ "type": "u8"
+ },
+ {
+ "args": [
+ {
+ "name": "a",
+ "optional": false,
+ "type": "i16"
+ },
+ {
+ "name": "b",
+ "optional": false,
+ "type": "InOutParam<i16>"
+ }
+ ],
+ "iid_is": null,
+ "name": "testShort",
+ "type": "i16"
+ },
+ {
+ "args": [
+ {
+ "name": "a",
+ "optional": false,
+ "type": "i32"
+ },
+ {
+ "name": "b",
+ "optional": false,
+ "type": "InOutParam<i32>"
+ }
+ ],
+ "iid_is": null,
+ "name": "testLong",
+ "type": "i32"
+ },
+ {
+ "args": [
+ {
+ "name": "a",
+ "optional": false,
+ "type": "i64"
+ },
+ {
+ "name": "b",
+ "optional": false,
+ "type": "InOutParam<i64>"
+ }
+ ],
+ "iid_is": null,
+ "name": "testLongLong",
+ "type": "i64"
+ },
+ {
+ "args": [
+ {
+ "name": "a",
+ "optional": false,
+ "type": "u16"
+ },
+ {
+ "name": "b",
+ "optional": false,
+ "type": "InOutParam<u16>"
+ }
+ ],
+ "iid_is": null,
+ "name": "testUnsignedShort",
+ "type": "u16"
+ },
+ {
+ "args": [
+ {
+ "name": "a",
+ "optional": false,
+ "type": "u32"
+ },
+ {
+ "name": "b",
+ "optional": false,
+ "type": "InOutParam<u32>"
+ }
+ ],
+ "iid_is": null,
+ "name": "testUnsignedLong",
+ "type": "u32"
+ },
+ {
+ "args": [
+ {
+ "name": "a",
+ "optional": false,
+ "type": "u64"
+ },
+ {
+ "name": "b",
+ "optional": false,
+ "type": "InOutParam<u64>"
+ }
+ ],
+ "iid_is": null,
+ "name": "testUnsignedLongLong",
+ "type": "u64"
+ },
+ {
+ "args": [
+ {
+ "name": "a",
+ "optional": false,
+ "type": "float"
+ },
+ {
+ "name": "b",
+ "optional": false,
+ "type": "InOutParam<float>"
+ }
+ ],
+ "iid_is": null,
+ "name": "testFloat",
+ "type": "float"
+ },
+ {
+ "args": [
+ {
+ "name": "a",
+ "optional": false,
+ "type": "double"
+ },
+ {
+ "name": "b",
+ "optional": false,
+ "type": "InOutParam<float>"
+ }
+ ],
+ "iid_is": null,
+ "name": "testDouble",
+ "type": "double"
+ },
+ {
+ "args": [
+ {
+ "name": "a",
+ "optional": false,
+ "type": "string"
+ },
+ {
+ "name": "b",
+ "optional": false,
+ "type": "InOutParam<string>"
+ }
+ ],
+ "iid_is": null,
+ "name": "testChar",
+ "type": "string"
+ },
+ {
+ "args": [
+ {
+ "name": "a",
+ "optional": false,
+ "type": "string"
+ },
+ {
+ "name": "b",
+ "optional": false,
+ "type": "InOutParam<string>"
+ }
+ ],
+ "iid_is": null,
+ "name": "testString",
+ "type": "string"
+ },
+ {
+ "args": [
+ {
+ "name": "a",
+ "optional": false,
+ "type": "string"
+ },
+ {
+ "name": "b",
+ "optional": false,
+ "type": "InOutParam<string>"
+ }
+ ],
+ "iid_is": null,
+ "name": "testWchar",
+ "type": "string"
+ },
+ {
+ "args": [
+ {
+ "name": "a",
+ "optional": false,
+ "type": "string"
+ },
+ {
+ "name": "b",
+ "optional": false,
+ "type": "InOutParam<string>"
+ }
+ ],
+ "iid_is": null,
+ "name": "testWstring",
+ "type": "string"
+ },
+ {
+ "args": [
+ {
+ "name": "a",
+ "optional": false,
+ "type": "string"
+ },
+ {
+ "name": "b",
+ "optional": false,
+ "type": "InOutParam<string>"
+ }
+ ],
+ "iid_is": null,
+ "name": "testAString",
+ "type": "string"
+ },
+ {
+ "args": [
+ {
+ "name": "a",
+ "optional": false,
+ "type": "string"
+ },
+ {
+ "name": "b",
+ "optional": false,
+ "type": "InOutParam<string>"
+ }
+ ],
+ "iid_is": null,
+ "name": "testAUTF8String",
+ "type": "string"
+ },
+ {
+ "args": [
+ {
+ "name": "a",
+ "optional": false,
+ "type": "string"
+ },
+ {
+ "name": "b",
+ "optional": false,
+ "type": "InOutParam<string>"
+ }
+ ],
+ "iid_is": null,
+ "name": "testACString",
+ "type": "string"
+ },
+ {
+ "args": [
+ {
+ "name": "a",
+ "optional": false,
+ "type": "any"
+ },
+ {
+ "name": "b",
+ "optional": false,
+ "type": "InOutParam<any>"
+ }
+ ],
+ "iid_is": null,
+ "name": "testJsval",
+ "type": "any"
+ },
+ {
+ "args": [
+ {
+ "name": "a",
+ "optional": false,
+ "type": "i16[]"
+ },
+ {
+ "name": "b",
+ "optional": false,
+ "type": "InOutParam<i16[]>"
+ }
+ ],
+ "iid_is": null,
+ "name": "testShortSequence",
+ "type": "i16[]"
+ },
+ {
+ "args": [
+ {
+ "name": "a",
+ "optional": false,
+ "type": "double[]"
+ },
+ {
+ "name": "b",
+ "optional": false,
+ "type": "InOutParam<double[]>"
+ }
+ ],
+ "iid_is": null,
+ "name": "testDoubleSequence",
+ "type": "double[]"
+ },
+ {
+ "args": [
+ {
+ "name": "a",
+ "optional": false,
+ "type": "nsIXPCTestInterfaceA[]"
+ },
+ {
+ "name": "b",
+ "optional": false,
+ "type": "InOutParam<nsIXPCTestInterfaceA[]>"
+ }
+ ],
+ "iid_is": null,
+ "name": "testInterfaceSequence",
+ "type": "nsIXPCTestInterfaceA[]"
+ },
+ {
+ "args": [
+ {
+ "name": "a",
+ "optional": false,
+ "type": "string[]"
+ },
+ {
+ "name": "b",
+ "optional": false,
+ "type": "InOutParam<string[]>"
+ }
+ ],
+ "iid_is": null,
+ "name": "testAStringSequence",
+ "type": "string[]"
+ },
+ {
+ "args": [
+ {
+ "name": "a",
+ "optional": false,
+ "type": "string[]"
+ },
+ {
+ "name": "b",
+ "optional": false,
+ "type": "InOutParam<string[]>"
+ }
+ ],
+ "iid_is": null,
+ "name": "testACStringSequence",
+ "type": "string[]"
+ },
+ {
+ "args": [
+ {
+ "name": "a",
+ "optional": false,
+ "type": "any[]"
+ },
+ {
+ "name": "b",
+ "optional": false,
+ "type": "InOutParam<any[]>"
+ }
+ ],
+ "iid_is": null,
+ "name": "testJsvalSequence",
+ "type": "any[]"
+ },
+ {
+ "args": [
+ {
+ "name": "a",
+ "optional": false,
+ "type": "i16[][]"
+ },
+ {
+ "name": "b",
+ "optional": false,
+ "type": "InOutParam<i16[][]>"
+ }
+ ],
+ "iid_is": null,
+ "name": "testSequenceSequence",
+ "type": "i16[][]"
+ },
+ {
+ "args": [
+ {
+ "name": "arr",
+ "optional": true,
+ "type": "u8[]"
+ }
+ ],
+ "iid_is": null,
+ "name": "testOptionalSequence",
+ "type": "u8[]"
+ },
+ {
+ "args": [
+ {
+ "name": "aLength",
+ "optional": false,
+ "type": "u32"
+ },
+ {
+ "name": "a",
+ "optional": false,
+ "type": "i16[]"
+ },
+ {
+ "name": "bLength",
+ "optional": false,
+ "type": "InOutParam<u32>"
+ },
+ {
+ "name": "b",
+ "optional": false,
+ "type": "InOutParam<i16[]>"
+ },
+ {
+ "name": "rvLength",
+ "optional": false,
+ "type": "OutParam<u32>"
+ }
+ ],
+ "iid_is": null,
+ "name": "testShortArray",
+ "type": "OutParam<i16[]>"
+ },
+ {
+ "args": [
+ {
+ "name": "aLength",
+ "optional": false,
+ "type": "u32"
+ },
+ {
+ "name": "a",
+ "optional": false,
+ "type": "double[]"
+ },
+ {
+ "name": "bLength",
+ "optional": false,
+ "type": "InOutParam<u32>"
+ },
+ {
+ "name": "b",
+ "optional": false,
+ "type": "InOutParam<double[]>"
+ },
+ {
+ "name": "rvLength",
+ "optional": false,
+ "type": "OutParam<u32>"
+ }
+ ],
+ "iid_is": null,
+ "name": "testDoubleArray",
+ "type": "OutParam<double[]>"
+ },
+ {
+ "args": [
+ {
+ "name": "aLength",
+ "optional": false,
+ "type": "u32"
+ },
+ {
+ "name": "a",
+ "optional": false,
+ "type": "string[]"
+ },
+ {
+ "name": "bLength",
+ "optional": false,
+ "type": "InOutParam<u32>"
+ },
+ {
+ "name": "b",
+ "optional": false,
+ "type": "InOutParam<string[]>"
+ },
+ {
+ "name": "rvLength",
+ "optional": false,
+ "type": "OutParam<u32>"
+ }
+ ],
+ "iid_is": null,
+ "name": "testStringArray",
+ "type": "OutParam<string[]>"
+ },
+ {
+ "args": [
+ {
+ "name": "aLength",
+ "optional": false,
+ "type": "u32"
+ },
+ {
+ "name": "a",
+ "optional": false,
+ "type": "string[]"
+ },
+ {
+ "name": "bLength",
+ "optional": false,
+ "type": "InOutParam<u32>"
+ },
+ {
+ "name": "b",
+ "optional": false,
+ "type": "InOutParam<string[]>"
+ },
+ {
+ "name": "rvLength",
+ "optional": false,
+ "type": "OutParam<u32>"
+ }
+ ],
+ "iid_is": null,
+ "name": "testWstringArray",
+ "type": "OutParam<string[]>"
+ },
+ {
+ "args": [
+ {
+ "name": "aLength",
+ "optional": false,
+ "type": "u32"
+ },
+ {
+ "name": "a",
+ "optional": false,
+ "type": "nsIXPCTestInterfaceA[]"
+ },
+ {
+ "name": "bLength",
+ "optional": false,
+ "type": "InOutParam<u32>"
+ },
+ {
+ "name": "b",
+ "optional": false,
+ "type": "InOutParam<nsIXPCTestInterfaceA[]>"
+ },
+ {
+ "name": "rvLength",
+ "optional": false,
+ "type": "OutParam<u32>"
+ }
+ ],
+ "iid_is": null,
+ "name": "testInterfaceArray",
+ "type": "OutParam<nsIXPCTestInterfaceA[]>"
+ },
+ {
+ "args": [
+ {
+ "name": "a",
+ "optional": false,
+ "type": "u8[]"
+ },
+ {
+ "name": "aLength",
+ "optional": true,
+ "type": "u32"
+ }
+ ],
+ "iid_is": null,
+ "name": "testByteArrayOptionalLength",
+ "type": "u32"
+ },
+ {
+ "args": [
+ {
+ "name": "aLength",
+ "optional": false,
+ "type": "u32"
+ },
+ {
+ "name": "a",
+ "optional": false,
+ "type": "string"
+ },
+ {
+ "name": "bLength",
+ "optional": false,
+ "type": "InOutParam<u32>"
+ },
+ {
+ "name": "b",
+ "optional": false,
+ "type": "InOutParam<string>"
+ },
+ {
+ "name": "rvLength",
+ "optional": false,
+ "type": "OutParam<u32>"
+ }
+ ],
+ "iid_is": null,
+ "name": "testSizedString",
+ "type": "OutParam<string>"
+ },
+ {
+ "args": [
+ {
+ "name": "aLength",
+ "optional": false,
+ "type": "u32"
+ },
+ {
+ "name": "a",
+ "optional": false,
+ "type": "string"
+ },
+ {
+ "name": "bLength",
+ "optional": false,
+ "type": "InOutParam<u32>"
+ },
+ {
+ "name": "b",
+ "optional": false,
+ "type": "InOutParam<string>"
+ },
+ {
+ "name": "rvLength",
+ "optional": false,
+ "type": "OutParam<u32>"
+ }
+ ],
+ "iid_is": null,
+ "name": "testSizedWstring",
+ "type": "OutParam<string>"
+ },
+ {
+ "args": [
+ {
+ "name": "aLength",
+ "optional": false,
+ "type": "u32"
+ },
+ {
+ "name": "a",
+ "optional": false,
+ "type": "any[]"
+ },
+ {
+ "name": "bLength",
+ "optional": false,
+ "type": "InOutParam<u32>"
+ },
+ {
+ "name": "b",
+ "optional": false,
+ "type": "InOutParam<any[]>"
+ },
+ {
+ "name": "rvLength",
+ "optional": false,
+ "type": "OutParam<u32>"
+ }
+ ],
+ "iid_is": null,
+ "name": "testJsvalArray",
+ "type": "OutParam<any[]>"
+ },
+ {
+ "args": [
+ {
+ "name": "o",
+ "optional": false,
+ "type": "OutParam<string>"
+ }
+ ],
+ "iid_is": null,
+ "name": "testOutAString",
+ "type": "void"
+ },
+ {
+ "args": [
+ {
+ "name": "a",
+ "optional": false,
+ "type": "string[]"
+ },
+ {
+ "name": "aLength",
+ "optional": true,
+ "type": "u32"
+ }
+ ],
+ "iid_is": null,
+ "name": "testStringArrayOptionalSize",
+ "type": "string"
+ },
+ {
+ "args": [
+ {
+ "name": "aJSObj",
+ "optional": false,
+ "type": "nsIXPCTestParams"
+ },
+ {
+ "name": "aOut",
+ "optional": true,
+ "type": "OutParam<nsIURI>"
+ }
+ ],
+ "iid_is": null,
+ "name": "testOmittedOptionalOut",
+ "type": "void"
+ },
+ {
+ "name": "testNaN",
+ "readonly": true,
+ "type": "double"
+ }
+ ]
+ }
+ ],
+ "path": "js/xpconnect/tests/idl/xpctest_params.idl",
+ "typedefs": [
+ [
+ "PRTime",
+ "i64"
+ ],
+ [
+ "char16_t",
+ "u16"
+ ],
+ [
+ "nsresult",
+ "u32"
+ ]
+ ]
+ },
+ {
+ "interfaces": [
+ {
+ "base": "nsISupports",
+ "callable": false,
+ "consts": [],
+ "enums": [],
+ "id": "nsIXPCTestReturnCodeParent",
+ "members": [
+ {
+ "args": [
+ {
+ "name": "childBehavior",
+ "optional": false,
+ "type": "i32"
+ }
+ ],
+ "iid_is": null,
+ "name": "callChild",
+ "type": "nsresult"
+ }
+ ]
+ },
+ {
+ "base": "nsISupports",
+ "callable": false,
+ "consts": [
+ {
+ "name": "CHILD_SHOULD_THROW",
+ "value": 0
+ },
+ {
+ "name": "CHILD_SHOULD_RETURN_SUCCESS",
+ "value": 1
+ },
+ {
+ "name": "CHILD_SHOULD_RETURN_RESULTCODE",
+ "value": 2
+ },
+ {
+ "name": "CHILD_SHOULD_NEST_RESULTCODES",
+ "value": 3
+ }
+ ],
+ "enums": [],
+ "id": "nsIXPCTestReturnCodeChild",
+ "members": [
+ {
+ "args": [
+ {
+ "name": "behavior",
+ "optional": false,
+ "type": "i32"
+ }
+ ],
+ "iid_is": null,
+ "name": "doIt",
+ "type": "void"
+ }
+ ]
+ }
+ ],
+ "path": "js/xpconnect/tests/idl/xpctest_returncode.idl",
+ "typedefs": [
+ [
+ "PRTime",
+ "i64"
+ ],
+ [
+ "char16_t",
+ "u16"
+ ],
+ [
+ "nsresult",
+ "u32"
+ ]
+ ]
+ },
+ {
+ "interfaces": [
+ {
+ "base": "nsISupports",
+ "callable": true,
+ "consts": [],
+ "enums": [],
+ "id": "nsIXPCTestFunctionInterface",
+ "members": [
+ {
+ "args": [
+ {
+ "name": "arg",
+ "optional": false,
+ "type": "string"
+ }
+ ],
+ "iid_is": null,
+ "name": "echo",
+ "type": "string"
+ }
+ ]
+ },
+ {
+ "base": "nsISupports",
+ "callable": false,
+ "consts": [],
+ "enums": [],
+ "id": "nsIXPCTestUtils",
+ "members": [
+ {
+ "args": [
+ {
+ "name": "f",
+ "optional": false,
+ "type": "nsIXPCTestFunctionInterface"
+ }
+ ],
+ "iid_is": null,
+ "name": "doubleWrapFunction",
+ "type": "nsIXPCTestFunctionInterface"
+ }
+ ]
+ },
+ {
+ "base": "nsISupports",
+ "callable": false,
+ "consts": [],
+ "enums": [],
+ "id": "nsIXPCTestNoScriptMembers",
+ "members": [
+ {
+ "name": "exposedProp",
+ "readonly": false,
+ "type": "i32"
+ },
+ {
+ "args": [
+ {
+ "name": "arg",
+ "optional": false,
+ "type": "i32"
+ }
+ ],
+ "iid_is": null,
+ "name": "exposedMethod",
+ "type": "void"
+ }
+ ]
+ }
+ ],
+ "path": "js/xpconnect/tests/idl/xpctest_utils.idl",
+ "typedefs": [
+ [
+ "PRTime",
+ "i64"
+ ],
+ [
+ "char16_t",
+ "u16"
+ ],
+ [
+ "nsresult",
+ "u32"
+ ]
+ ]
+ }
+] \ No newline at end of file
diff --git a/xpcom/idl-parser/xpidl/header.py b/xpcom/idl-parser/xpidl/header.py
index ed179b1bad..7f6c65dfc0 100644
--- a/xpcom/idl-parser/xpidl/header.py
+++ b/xpcom/idl-parser/xpidl/header.py
@@ -339,6 +339,8 @@ def print_header(idl, fd, filename, relpath):
write_interface(p, fd)
continue
if p.kind == "typedef":
+ if p.substitute:
+ continue
printComments(fd, p.doccomments, "")
fd.write("typedef %s %s;\n\n" % (p.realtype.nativeType("in"), p.name))
diff --git a/xpcom/idl-parser/xpidl/runtests.py b/xpcom/idl-parser/xpidl/runtests.py
index 2dd269dfd9..b889d40010 100755
--- a/xpcom/idl-parser/xpidl/runtests.py
+++ b/xpcom/idl-parser/xpidl/runtests.py
@@ -5,6 +5,8 @@
#
# Unit tests for xpidl.py
+import json
+import os
import sys
# Hack: the first entry in sys.path is the directory containing the script.
@@ -16,7 +18,7 @@ import unittest
import mozunit
-from xpidl import header, xpidl
+from xpidl import header, typescript, xpidl
class TestParser(unittest.TestCase):
@@ -253,5 +255,42 @@ attribute long bar;
self.assertEqual(e.args[0], ("cannot find symbol 'Y'"))
+class TestTypescript(unittest.TestCase):
+ """A few basic smoke tests for typescript generation."""
+
+ dir = os.path.dirname(__file__)
+ src = os.path.join(dir, "..", "..", "..")
+
+ # We use the xpctest.xpt *.idl files from:
+ tests_dir = os.path.join(src, "js/xpconnect/tests/idl")
+ files = [
+ "xpctest_attributes.idl",
+ "xpctest_bug809674.idl",
+ "xpctest_cenums.idl",
+ "xpctest_interfaces.idl",
+ "xpctest_params.idl",
+ "xpctest_returncode.idl",
+ "xpctest_utils.idl",
+ ]
+
+ fixtures = os.path.join(dir, "fixtures")
+ inc_dirs = [os.path.join(src, "xpcom/base")]
+
+ def setUp(self):
+ self.parser = xpidl.IDLParser()
+
+ def test_d_json(self):
+ mods = []
+ for file in self.files:
+ path = os.path.join(self.tests_dir, file)
+ idl = self.parser.parse(open(path).read(), path)
+ idl.resolve(self.inc_dirs, self.parser, {})
+ mods.append(typescript.ts_source(idl))
+
+ result = json.dumps(mods, indent=2, sort_keys=True)
+ expected = open(os.path.join(self.fixtures, "xpctest.d.json")).read()
+ self.assertEqual(result, expected, "types data json does not match")
+
+
if __name__ == "__main__":
mozunit.main(runwith="unittest")
diff --git a/xpcom/idl-parser/xpidl/rust.py b/xpcom/idl-parser/xpidl/rust.py
index b9fc6627fb..5d906d85ea 100644
--- a/xpcom/idl-parser/xpidl/rust.py
+++ b/xpcom/idl-parser/xpidl/rust.py
@@ -363,8 +363,8 @@ def print_rust_bindings(idl, fd, relpath):
if p.kind == "typedef":
try:
- # We have to skip the typedef of bool to bool (it doesn't make any sense anyways)
- if p.name == "bool":
+ # Skip bool and C++ stdint typedefs marked with [substitute].
+ if p.substitute:
continue
if printdoccomments:
diff --git a/xpcom/idl-parser/xpidl/typescript.py b/xpcom/idl-parser/xpidl/typescript.py
new file mode 100644
index 0000000000..614a328edf
--- /dev/null
+++ b/xpcom/idl-parser/xpidl/typescript.py
@@ -0,0 +1,94 @@
+#!/usr/bin/env python
+# typescript.py - Collect .d.json TypeScript info from xpidl.
+#
+# 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/.
+
+import json
+
+import mozpack.path as mozpath
+
+from xpidl import xpidl
+
+
+def ts_enum(e):
+ variants = [{"name": v.name, "value": v.getValue()} for v in e.variants]
+ return {"id": e.basename, "variants": variants}
+
+
+def ts_attribute(a):
+ return {"name": a.name, "type": a.realtype.tsType(), "readonly": a.readonly}
+
+
+def ts_method(m):
+ args = []
+ for p in m.params:
+ if p.iid_is and not p.retval:
+ raise xpidl.TSNoncompat(f"{m.name} has unsupported iid_is argument")
+ args.append({"name": p.name, "optional": p.optional, "type": p.tsType()})
+
+ iid_is = None
+ type = m.realtype.tsType()
+ if args and m.params[-1].retval:
+ type = args.pop()["type"]
+ iid_is = m.params[-1].iid_is
+
+ return {"name": m.name, "type": type, "iid_is": iid_is, "args": args}
+
+
+def ts_interface(iface):
+ enums = []
+ consts = []
+ members = []
+
+ for m in iface.members:
+ try:
+ if isinstance(m, xpidl.CEnum):
+ enums.append(ts_enum(m))
+ elif isinstance(m, xpidl.ConstMember):
+ consts.append({"name": m.name, "value": m.getValue()})
+ elif isinstance(m, xpidl.Attribute) and m.isScriptable():
+ members.append(ts_attribute(m))
+ elif isinstance(m, xpidl.Method) and m.isScriptable():
+ members.append(ts_method(m))
+ except xpidl.TSNoncompat:
+ # Omit member if any type is unsupported.
+ pass
+
+ return {
+ "id": iface.name,
+ "base": iface.base,
+ "callable": iface.attributes.function,
+ "enums": enums,
+ "consts": consts,
+ "members": members,
+ }
+
+
+def ts_typedefs(idl):
+ for p in idl.getNames():
+ if isinstance(p, xpidl.Typedef) and not p.substitute:
+ try:
+ yield (p.name, p.realtype.tsType())
+ except xpidl.TSNoncompat:
+ pass
+
+
+def ts_source(idl):
+ """Collect typescript interface .d.json from a source idl file."""
+ root = mozpath.join(mozpath.dirname(__file__), "../../..")
+ return {
+ "path": mozpath.relpath(idl.productions[0].location._file, root),
+ "interfaces": [
+ ts_interface(p)
+ for p in idl.productions
+ if isinstance(p, xpidl.Interface) and p.attributes.scriptable
+ ],
+ "typedefs": sorted(ts_typedefs(idl)),
+ }
+
+
+def write(d_json, fd):
+ """Write json type info into fd"""
+ json.dump(d_json, fd, indent=2, sort_keys=True)
diff --git a/xpcom/idl-parser/xpidl/xpidl.py b/xpcom/idl-parser/xpidl/xpidl.py
index b95fd14bc5..19d042d1b0 100755
--- a/xpcom/idl-parser/xpidl/xpidl.py
+++ b/xpcom/idl-parser/xpidl/xpidl.py
@@ -122,10 +122,13 @@ class Builtin(object):
kind = "builtin"
location = BuiltinLocation
- def __init__(self, name, nativename, rustname, signed=False, maybeConst=False):
+ def __init__(
+ self, name, nativename, rustname, tsname, signed=False, maybeConst=False
+ ):
self.name = name
self.nativename = nativename
self.rustname = rustname
+ self.tsname = tsname
self.signed = signed
self.maybeConst = maybeConst
@@ -171,28 +174,37 @@ class Builtin(object):
return "%s%s" % ("*mut " if "out" in calltype else "", rustname)
+ def tsType(self):
+ if self.tsname:
+ return self.tsname
+
+ raise TSNoncompat(f"Builtin type {self.name} unsupported in TypeScript")
+
builtinNames = [
- Builtin("boolean", "bool", "bool"),
- Builtin("void", "void", "libc::c_void"),
- Builtin("octet", "uint8_t", "u8", False, True),
- Builtin("short", "int16_t", "i16", True, True),
- Builtin("long", "int32_t", "i32", True, True),
- Builtin("long long", "int64_t", "i64", True, True),
- Builtin("unsigned short", "uint16_t", "u16", False, True),
- Builtin("unsigned long", "uint32_t", "u32", False, True),
- Builtin("unsigned long long", "uint64_t", "u64", False, True),
- Builtin("float", "float", "libc::c_float", True, False),
- Builtin("double", "double", "libc::c_double", True, False),
- Builtin("char", "char", "libc::c_char", True, False),
- Builtin("string", "char *", "*const libc::c_char", False, False),
- Builtin("wchar", "char16_t", "u16", False, False),
- Builtin("wstring", "char16_t *", "*const u16", False, False),
+ Builtin("boolean", "bool", "bool", "boolean"),
+ Builtin("void", "void", "libc::c_void", "void"),
+ Builtin("octet", "uint8_t", "u8", "u8", False, True),
+ Builtin("short", "int16_t", "i16", "i16", True, True),
+ Builtin("long", "int32_t", "i32", "i32", True, True),
+ Builtin("long long", "int64_t", "i64", "i64", True, True),
+ Builtin("unsigned short", "uint16_t", "u16", "u16", False, True),
+ Builtin("unsigned long", "uint32_t", "u32", "u32", False, True),
+ Builtin("unsigned long long", "uint64_t", "u64", "u64", False, True),
+ Builtin("float", "float", "libc::c_float", "float"),
+ Builtin("double", "double", "libc::c_double", "double"),
+ Builtin("char", "char", "libc::c_char", "string"),
+ Builtin("string", "char *", "*const libc::c_char", "string"),
+ Builtin("wchar", "char16_t", "u16", "string"),
+ Builtin("wstring", "char16_t *", "*const u16", "string"),
# As seen in mfbt/RefCountType.h, this type has special handling to
# maintain binary compatibility with MSCOM's IUnknown that cannot be
# expressed in XPIDL.
Builtin(
- "MozExternalRefCountType", "MozExternalRefCountType", "MozExternalRefCountType"
+ "MozExternalRefCountType",
+ "MozExternalRefCountType",
+ "MozExternalRefCountType",
+ None,
),
]
@@ -308,6 +320,16 @@ class RustNoncompat(Exception):
return self.reason
+class TSNoncompat(Exception):
+ """Raised when a type cannot be exposed to TypeScript."""
+
+ def __init__(self, reason):
+ self.reason = reason
+
+ def __str__(self):
+ return self.reason
+
+
class IDLError(Exception):
def __init__(self, message, location, warning=False, notes=None):
self.message = message
@@ -458,12 +480,20 @@ class CDATA(object):
class Typedef(object):
kind = "typedef"
- def __init__(self, type, name, location, doccomments):
+ def __init__(self, type, name, attlist, location, doccomments):
self.type = type
self.name = name
self.location = location
self.doccomments = doccomments
+ # C++ stdint types and the bool typedef from nsrootidl.idl are marked
+ # with [substitute], and emit as the underlying builtin type directly.
+ self.substitute = False
+ for name, value, aloc in attlist:
+ if name != "substitute" or value is not None:
+ raise IDLError(f"Unexpected attribute {name}({value})", aloc)
+ self.substitute = True
+
def __eq__(self, other):
return self.name == other.name and self.type == other.type
@@ -475,14 +505,26 @@ class Typedef(object):
raise IDLError("Unsupported typedef target type", self.location)
def nativeType(self, calltype):
+ if self.substitute:
+ return self.realtype.nativeType(calltype)
+
return "%s %s" % (self.name, "*" if "out" in calltype else "")
def rustType(self, calltype):
+ if self.substitute:
+ return self.realtype.rustType(calltype)
+
if self.name == "nsresult":
return "%s::nserror::nsresult" % ("*mut " if "out" in calltype else "")
return "%s%s" % ("*mut " if "out" in calltype else "", self.name)
+ def tsType(self):
+ if self.substitute:
+ return self.realtype.tsType()
+
+ return self.name
+
def __str__(self):
return "typedef %s %s\n" % (self.type, self.name)
@@ -524,6 +566,9 @@ class Forward(object):
return "Option<RefPtr<%s>>" % self.name
return "%s*const %s" % ("*mut" if "out" in calltype else "", self.name)
+ def tsType(self):
+ return self.name
+
def __str__(self):
return "forward-declared %s\n" % self.name
@@ -701,6 +746,21 @@ class Native(object):
raise RustNoncompat("native type %s unsupported" % self.nativename)
+ ts_special = {
+ "astring": "string",
+ "cstring": "string",
+ "jsval": "any",
+ "nsid": "nsID",
+ "promise": "Promise<any>",
+ "utf8string": "string",
+ }
+
+ def tsType(self):
+ if type := self.ts_special.get(self.specialtype, None):
+ return type
+
+ raise TSNoncompat(f"Native type {self.name} unsupported in TypeScript")
+
def __str__(self):
return "native %s(%s)\n" % (self.name, self.nativename)
@@ -749,6 +809,9 @@ class WebIDL(object):
# Just expose the type as a void* - we can't do any better.
return "%s*const libc::c_void" % ("*mut " if "out" in calltype else "")
+ def tsType(self):
+ return self.name
+
def __str__(self):
return "webidl %s\n" % self.name
@@ -923,6 +986,9 @@ class Interface(object):
total += realbase.countEntries()
return total
+ def tsType(self):
+ return self.name
+
class InterfaceAttributes(object):
uuid = None
@@ -1110,6 +1176,9 @@ class CEnum(object):
def rustType(self, calltype):
return "%s u%d" % ("*mut" if "out" in calltype else "", self.width)
+ def tsType(self):
+ return f"{self.iface.name}.{self.basename}"
+
def __str__(self):
body = ", ".join("%s = %s" % v for v in self.variants)
return "\tcenum %s : %d { %s };\n" % (self.name, self.width, body)
@@ -1523,8 +1592,22 @@ class Param(object):
self.name,
)
+ def tsType(self):
+ # A generic retval param type needs special handling.
+ if self.retval and self.iid_is:
+ return "nsQIResult"
+
+ type = self.realtype.tsType()
+ if self.paramtype == "inout":
+ return f"InOutParam<{type}>"
+ if self.paramtype == "out":
+ return f"OutParam<{type}>"
+ return type
+
class LegacyArray(object):
+ kind = "legacyarray"
+
def __init__(self, basetype):
self.type = basetype
self.location = self.type.location
@@ -1555,6 +1638,9 @@ class LegacyArray(object):
self.type.rustType("legacyelement"),
)
+ def tsType(self):
+ return self.type.tsType() + "[]"
+
class Array(object):
kind = "array"
@@ -1594,6 +1680,9 @@ class Array(object):
else:
return base
+ def tsType(self):
+ return self.type.tsType() + "[]"
+
TypeId = namedtuple("TypeId", "name params")
@@ -1751,12 +1840,13 @@ class IDLParser(object):
p[0].insert(0, p[1])
def p_typedef(self, p):
- """typedef : TYPEDEF type IDENTIFIER ';'"""
+ """typedef : attributes TYPEDEF type IDENTIFIER ';'"""
p[0] = Typedef(
- type=p[2],
- name=p[3],
- location=self.getLocation(p, 1),
- doccomments=p.slice[1].doccomments,
+ type=p[3],
+ name=p[4],
+ attlist=p[1]["attlist"],
+ location=self.getLocation(p, 2),
+ doccomments=getattr(p[1], "doccomments", []) + p.slice[2].doccomments,
)
def p_native(self, p):
diff --git a/xpcom/io/CocoaFileUtils.mm b/xpcom/io/CocoaFileUtils.mm
index 3710be864c..f45da3ec66 100644
--- a/xpcom/io/CocoaFileUtils.mm
+++ b/xpcom/io/CocoaFileUtils.mm
@@ -309,7 +309,7 @@ void CopyQuarantineReferrerUrl(const CFStringRef aFilePath,
::CFDictionaryGetValue(mutQuarantineProps, kLSQuarantineOriginURLKey);
if (referrerRef && ::CFGetTypeID(referrerRef) == ::CFURLGetTypeID()) {
// URL string must be copied prior to releasing the dictionary.
- mozilla::CopyCocoaStringToXPCOMString(
+ mozilla::CopyNSStringToXPCOMString(
(NSString*)::CFURLGetString(static_cast<CFURLRef>(referrerRef)),
aReferrer);
}
diff --git a/xpcom/io/nsLocalFileCommon.cpp b/xpcom/io/nsLocalFileCommon.cpp
index f6eabf2d0f..7e9d7151c1 100644
--- a/xpcom/io/nsLocalFileCommon.cpp
+++ b/xpcom/io/nsLocalFileCommon.cpp
@@ -139,7 +139,8 @@ const char* const sExecutableExts[] = {
".wsc",
".wsf",
".wsh",
- ".xll" // MS Excel dynamic link library
+ ".xll", // MS Excel dynamic link library
+ ".xrm-ms"
// clang-format on
};
diff --git a/xpcom/io/nsLocalFileCommon.h b/xpcom/io/nsLocalFileCommon.h
index 3db0ac9e89..96b7e1f06a 100644
--- a/xpcom/io/nsLocalFileCommon.h
+++ b/xpcom/io/nsLocalFileCommon.h
@@ -8,9 +8,9 @@
#define _NS_LOCAL_FILE_COMMON_H_
#ifdef MOZ_ESR
-extern const char* const sExecutableExts[107];
-#else
extern const char* const sExecutableExts[108];
+#else
+extern const char* const sExecutableExts[109];
#endif
#endif
diff --git a/xpcom/reflect/xptcall/md/unix/xptcinvoke_loongarch64.cpp b/xpcom/reflect/xptcall/md/unix/xptcinvoke_loongarch64.cpp
index 61bb7b2efd..e73dd023cb 100644
--- a/xpcom/reflect/xptcall/md/unix/xptcinvoke_loongarch64.cpp
+++ b/xpcom/reflect/xptcall/md/unix/xptcinvoke_loongarch64.cpp
@@ -44,7 +44,9 @@ extern "C" void invoke_copy_to_stack(uint64_t* gpregs, double* fpregs,
value = s->val.u16;
break;
case nsXPTType::T_U32:
- value = s->val.u32;
+ // 32-bit values need to be sign-extended in 64-bit registers,
+ // so use the signed value here.
+ value = s->val.i32;
break;
case nsXPTType::T_U64:
value = s->val.u64;
diff --git a/xpcom/system/nsIDeviceSensors.idl b/xpcom/system/nsIDeviceSensors.idl
index dcb67cb925..a173421ebf 100644
--- a/xpcom/system/nsIDeviceSensors.idl
+++ b/xpcom/system/nsIDeviceSensors.idl
@@ -51,10 +51,6 @@ interface nsIDeviceSensors : nsISupports
%{C++
-#define NS_DEVICE_SENSORS_CID \
-{ 0xecba5203, 0x77da, 0x465a, \
-{ 0x86, 0x5e, 0x78, 0xb7, 0xaf, 0x10, 0xd8, 0xf7 } }
-
#define NS_DEVICE_SENSORS_CONTRACTID "@mozilla.org/devicesensors;1"
%}
diff --git a/xpcom/system/nsIXULRuntime.idl b/xpcom/system/nsIXULRuntime.idl
index 8beadae9f1..9d187bcbba 100644
--- a/xpcom/system/nsIXULRuntime.idl
+++ b/xpcom/system/nsIXULRuntime.idl
@@ -30,6 +30,10 @@ bool FissionExperimentEnrolled();
// fission.disableSessionHistoryInParent is false.
bool SessionHistoryInParent();
+// Returns true if SessionHistoryInParent() is true and
+// browser.sessionstore.disable_platform_collection is false.
+bool SessionStorePlatformCollection();
+
// Returns true if SessionHistoryInParent() returns true and
// fission.bfcacheInParent is true.
bool BFCacheInParent();
@@ -169,6 +173,11 @@ interface nsIXULRuntime : nsISupports
readonly attribute boolean sessionHistoryInParent;
/**
+ * Whether Gecko code drives session store collection data.
+ */
+ readonly attribute boolean sessionStorePlatformCollection;
+
+ /**
* Whether to write console errors to a log file. If a component
* encounters startup errors that might prevent the app from showing
* proper UI, it should set this flag to "true".
diff --git a/xpcom/tests/gtest/TestAutoOwningEventTarget.cpp b/xpcom/tests/gtest/TestAutoOwningEventTarget.cpp
new file mode 100644
index 0000000000..2bd34ecfee
--- /dev/null
+++ b/xpcom/tests/gtest/TestAutoOwningEventTarget.cpp
@@ -0,0 +1,120 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+// vim:cindent:ts=4:et:sw=4:
+/* 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 "nsCOMPtr.h"
+#include "nsISupportsImpl.h"
+#include "nsNetCID.h"
+#include "nsServiceManagerUtils.h"
+#include "nsThreadUtils.h"
+#include "gtest/gtest.h"
+#include "mozilla/SyncRunnable.h"
+#include "mozilla/TaskQueue.h"
+#include "mozilla/gtest/MozAssertions.h"
+
+namespace TestAutoOwningEventTarget {
+
+using namespace mozilla;
+
+#ifdef MOZ_THREAD_SAFETY_OWNERSHIP_CHECKS_SUPPORTED
+
+namespace {
+
+static MozExternalRefCountType GetRefCount(nsISupports* aSupports) {
+ aSupports->AddRef();
+ return aSupports->Release();
+}
+
+void CheckAutoOwningEventTarget(
+ nsISerialEventTarget* aSerialEventTarget,
+ const nsAutoOwningEventTarget& aAutoOwningEventTarget,
+ const bool aIsCurrent) {
+ ASSERT_TRUE(aSerialEventTarget);
+
+ ASSERT_EQ(aAutoOwningEventTarget.IsCurrentThread(), aIsCurrent);
+
+ {
+ const auto refCountBefore = GetRefCount(aSerialEventTarget);
+
+ {
+ nsAutoOwningEventTarget copyConstructedEventTarget(
+ aAutoOwningEventTarget);
+ ASSERT_EQ(copyConstructedEventTarget.IsCurrentThread(), aIsCurrent);
+ }
+
+ const auto refCountAfter = GetRefCount(aSerialEventTarget);
+
+ ASSERT_GE(refCountAfter, refCountBefore);
+ ASSERT_EQ(refCountAfter - refCountBefore, 0u);
+ }
+
+ {
+ const auto refCountBefore = GetRefCount(aSerialEventTarget);
+
+ {
+ nsAutoOwningEventTarget copyAssignedEventTarget;
+ ASSERT_TRUE(copyAssignedEventTarget.IsCurrentThread());
+
+ copyAssignedEventTarget = aAutoOwningEventTarget;
+ ASSERT_EQ(copyAssignedEventTarget.IsCurrentThread(), aIsCurrent);
+ }
+
+ const auto refCountAfter = GetRefCount(aSerialEventTarget);
+
+ ASSERT_GE(refCountAfter, refCountBefore);
+ ASSERT_EQ(refCountAfter - refCountBefore, 0u);
+ }
+}
+
+} // namespace
+
+TEST(TestAutoOwningEventTarget, Simple)
+{
+ {
+ nsAutoOwningEventTarget autoOwningEventTarget;
+
+ ASSERT_NO_FATAL_FAILURE(CheckAutoOwningEventTarget(
+ GetCurrentSerialEventTarget(), autoOwningEventTarget,
+ /* aIsCurrent */ true));
+ }
+}
+
+TEST(TestAutoOwningEventTarget, TaskQueue)
+{
+ nsresult rv;
+ nsCOMPtr<nsIEventTarget> threadPool =
+ do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID, &rv);
+ ASSERT_NS_SUCCEEDED(rv);
+
+ auto taskQueue = TaskQueue::Create(threadPool.forget(), "TestTaskQueue",
+ /* aSupportsTailDispatch */ false);
+
+ nsAutoOwningEventTarget autoOwningEventTarget;
+
+ // XXX This call can't be wrapped with ASSERT_NS_SUCCEEDED directly because
+ // base-toolchains builds fail with: error: duplicate label
+ // 'gtest_label_testnofatal_111'
+ rv = SyncRunnable::DispatchToThread(
+ taskQueue,
+ NS_NewRunnableFunction(
+ "TestRunnable", [taskQueue, &autoOwningEventTarget] {
+ {
+ ASSERT_NO_FATAL_FAILURE(CheckAutoOwningEventTarget(
+ taskQueue, autoOwningEventTarget, /* aIsCurrent */ false));
+ }
+
+ {
+ nsAutoOwningEventTarget autoOwningEventTarget;
+
+ ASSERT_NO_FATAL_FAILURE(CheckAutoOwningEventTarget(
+ taskQueue, autoOwningEventTarget, /* aIsCurrent */ true));
+ }
+ }));
+ ASSERT_NS_SUCCEEDED(rv);
+}
+
+#endif
+
+} // namespace TestAutoOwningEventTarget
diff --git a/xpcom/tests/gtest/TestThreadUtils.cpp b/xpcom/tests/gtest/TestThreadUtils.cpp
index 2b9ff97192..96b1342885 100644
--- a/xpcom/tests/gtest/TestThreadUtils.cpp
+++ b/xpcom/tests/gtest/TestThreadUtils.cpp
@@ -885,122 +885,88 @@ TEST(ThreadUtils, IdleTaskRunner)
TEST(ThreadUtils, TypeTraits)
{
- static_assert(!mozilla::IsRefcountedSmartPointer<int>::value,
- "IsRefcountedSmartPointer<int> should be false");
- static_assert(mozilla::IsRefcountedSmartPointer<RefPtr<int>>::value,
- "IsRefcountedSmartPointer<RefPtr<...>> should be true");
- static_assert(mozilla::IsRefcountedSmartPointer<const RefPtr<int>>::value,
- "IsRefcountedSmartPointer<const RefPtr<...>> should be true");
- static_assert(
- mozilla::IsRefcountedSmartPointer<volatile RefPtr<int>>::value,
- "IsRefcountedSmartPointer<volatile RefPtr<...>> should be true");
- static_assert(
- mozilla::IsRefcountedSmartPointer<const volatile RefPtr<int>>::value,
- "IsRefcountedSmartPointer<const volatile RefPtr<...>> should be true");
- static_assert(mozilla::IsRefcountedSmartPointer<nsCOMPtr<int>>::value,
- "IsRefcountedSmartPointer<nsCOMPtr<...>> should be true");
- static_assert(mozilla::IsRefcountedSmartPointer<const nsCOMPtr<int>>::value,
- "IsRefcountedSmartPointer<const nsCOMPtr<...>> should be true");
- static_assert(
- mozilla::IsRefcountedSmartPointer<volatile nsCOMPtr<int>>::value,
- "IsRefcountedSmartPointer<volatile nsCOMPtr<...>> should be true");
- static_assert(
- mozilla::IsRefcountedSmartPointer<const volatile nsCOMPtr<int>>::value,
- "IsRefcountedSmartPointer<const volatile nsCOMPtr<...>> should be true");
-
- static_assert(std::is_same_v<int, mozilla::RemoveSmartPointer<int>::Type>,
- "RemoveSmartPointer<int>::Type should be int");
- static_assert(std::is_same_v<int*, mozilla::RemoveSmartPointer<int*>::Type>,
- "RemoveSmartPointer<int*>::Type should be int*");
- static_assert(
- std::is_same_v<UniquePtr<int>,
- mozilla::RemoveSmartPointer<UniquePtr<int>>::Type>,
- "RemoveSmartPointer<UniquePtr<int>>::Type should be UniquePtr<int>");
- static_assert(
- std::is_same_v<int, mozilla::RemoveSmartPointer<RefPtr<int>>::Type>,
- "RemoveSmartPointer<RefPtr<int>>::Type should be int");
- static_assert(
- std::is_same_v<int, mozilla::RemoveSmartPointer<const RefPtr<int>>::Type>,
- "RemoveSmartPointer<const RefPtr<int>>::Type should be int");
+ static_assert(std::is_same_v<int, mozilla::RemoveSmartPointer<int>>,
+ "RemoveSmartPointer<int> should be int");
+ static_assert(std::is_same_v<int*, mozilla::RemoveSmartPointer<int*>>,
+ "RemoveSmartPointer<int*> should be int*");
+ static_assert(std::is_same_v<UniquePtr<int>,
+ mozilla::RemoveSmartPointer<UniquePtr<int>>>,
+ "RemoveSmartPointer<UniquePtr<int>> should be UniquePtr<int>");
+ static_assert(std::is_same_v<int, mozilla::RemoveSmartPointer<RefPtr<int>>>,
+ "RemoveSmartPointer<RefPtr<int>> should be int");
+ static_assert(
+ std::is_same_v<int, mozilla::RemoveSmartPointer<const RefPtr<int>>>,
+ "RemoveSmartPointer<const RefPtr<int>> should be int");
+ static_assert(
+ std::is_same_v<int, mozilla::RemoveSmartPointer<volatile RefPtr<int>>>,
+ "RemoveSmartPointer<volatile RefPtr<int>> should be int");
static_assert(
std::is_same_v<int,
- mozilla::RemoveSmartPointer<volatile RefPtr<int>>::Type>,
- "RemoveSmartPointer<volatile RefPtr<int>>::Type should be int");
- static_assert(
- std::is_same_v<
- int, mozilla::RemoveSmartPointer<const volatile RefPtr<int>>::Type>,
- "RemoveSmartPointer<const volatile RefPtr<int>>::Type should be int");
+ mozilla::RemoveSmartPointer<const volatile RefPtr<int>>>,
+ "RemoveSmartPointer<const volatile RefPtr<int>> should be int");
+ static_assert(std::is_same_v<int, mozilla::RemoveSmartPointer<nsCOMPtr<int>>>,
+ "RemoveSmartPointer<nsCOMPtr<int>> should be int");
static_assert(
- std::is_same_v<int, mozilla::RemoveSmartPointer<nsCOMPtr<int>>::Type>,
- "RemoveSmartPointer<nsCOMPtr<int>>::Type should be int");
+ std::is_same_v<int, mozilla::RemoveSmartPointer<const nsCOMPtr<int>>>,
+ "RemoveSmartPointer<const nsCOMPtr<int>> should be int");
static_assert(
- std::is_same_v<int,
- mozilla::RemoveSmartPointer<const nsCOMPtr<int>>::Type>,
- "RemoveSmartPointer<const nsCOMPtr<int>>::Type should be int");
+ std::is_same_v<int, mozilla::RemoveSmartPointer<volatile nsCOMPtr<int>>>,
+ "RemoveSmartPointer<volatile nsCOMPtr<int>> should be int");
static_assert(
std::is_same_v<int,
- mozilla::RemoveSmartPointer<volatile nsCOMPtr<int>>::Type>,
- "RemoveSmartPointer<volatile nsCOMPtr<int>>::Type should be int");
- static_assert(
- std::is_same_v<
- int, mozilla::RemoveSmartPointer<const volatile nsCOMPtr<int>>::Type>,
- "RemoveSmartPointer<const volatile nsCOMPtr<int>>::Type should be int");
+ mozilla::RemoveSmartPointer<const volatile nsCOMPtr<int>>>,
+ "RemoveSmartPointer<const volatile nsCOMPtr<int>> should be int");
- static_assert(
- std::is_same_v<int, mozilla::RemoveRawOrSmartPointer<int>::Type>,
- "RemoveRawOrSmartPointer<int>::Type should be int");
+ static_assert(std::is_same_v<int, mozilla::RemoveRawOrSmartPointer<int>>,
+ "RemoveRawOrSmartPointer<int> should be int");
static_assert(
std::is_same_v<UniquePtr<int>,
- mozilla::RemoveRawOrSmartPointer<UniquePtr<int>>::Type>,
- "RemoveRawOrSmartPointer<UniquePtr<int>>::Type should be UniquePtr<int>");
- static_assert(
- std::is_same_v<int, mozilla::RemoveRawOrSmartPointer<int*>::Type>,
- "RemoveRawOrSmartPointer<int*>::Type should be int");
+ mozilla::RemoveRawOrSmartPointer<UniquePtr<int>>>,
+ "RemoveRawOrSmartPointer<UniquePtr<int>> should be UniquePtr<int>");
+ static_assert(std::is_same_v<int, mozilla::RemoveRawOrSmartPointer<int*>>,
+ "RemoveRawOrSmartPointer<int*> should be int");
static_assert(
- std::is_same_v<const int,
- mozilla::RemoveRawOrSmartPointer<const int*>::Type>,
- "RemoveRawOrSmartPointer<const int*>::Type should be const int");
+ std::is_same_v<const int, mozilla::RemoveRawOrSmartPointer<const int*>>,
+ "RemoveRawOrSmartPointer<const int*> should be const int");
static_assert(
std::is_same_v<volatile int,
- mozilla::RemoveRawOrSmartPointer<volatile int*>::Type>,
- "RemoveRawOrSmartPointer<volatile int*>::Type should be volatile int");
+ mozilla::RemoveRawOrSmartPointer<volatile int*>>,
+ "RemoveRawOrSmartPointer<volatile int*> should be volatile int");
static_assert(
- std::is_same_v<const volatile int, mozilla::RemoveRawOrSmartPointer<
- const volatile int*>::Type>,
- "RemoveRawOrSmartPointer<const volatile int*>::Type should be const "
+ std::is_same_v<const volatile int,
+ mozilla::RemoveRawOrSmartPointer<const volatile int*>>,
+ "RemoveRawOrSmartPointer<const volatile int*> should be const "
"volatile int");
static_assert(
- std::is_same_v<int, mozilla::RemoveRawOrSmartPointer<RefPtr<int>>::Type>,
- "RemoveRawOrSmartPointer<RefPtr<int>>::Type should be int");
+ std::is_same_v<int, mozilla::RemoveRawOrSmartPointer<RefPtr<int>>>,
+ "RemoveRawOrSmartPointer<RefPtr<int>> should be int");
+ static_assert(
+ std::is_same_v<int, mozilla::RemoveRawOrSmartPointer<const RefPtr<int>>>,
+ "RemoveRawOrSmartPointer<const RefPtr<int>> should be int");
static_assert(
std::is_same_v<int,
- mozilla::RemoveRawOrSmartPointer<const RefPtr<int>>::Type>,
- "RemoveRawOrSmartPointer<const RefPtr<int>>::Type should be int");
+ mozilla::RemoveRawOrSmartPointer<volatile RefPtr<int>>>,
+ "RemoveRawOrSmartPointer<volatile RefPtr<int>> should be int");
static_assert(
std::is_same_v<
- int, mozilla::RemoveRawOrSmartPointer<volatile RefPtr<int>>::Type>,
- "RemoveRawOrSmartPointer<volatile RefPtr<int>>::Type should be int");
- static_assert(
- std::is_same_v<int, mozilla::RemoveRawOrSmartPointer<
- const volatile RefPtr<int>>::Type>,
- "RemoveRawOrSmartPointer<const volatile RefPtr<int>>::Type should be "
+ int, mozilla::RemoveRawOrSmartPointer<const volatile RefPtr<int>>>,
+ "RemoveRawOrSmartPointer<const volatile RefPtr<int>> should be "
"int");
static_assert(
+ std::is_same_v<int, mozilla::RemoveRawOrSmartPointer<nsCOMPtr<int>>>,
+ "RemoveRawOrSmartPointer<nsCOMPtr<int>> should be int");
+ static_assert(
std::is_same_v<int,
- mozilla::RemoveRawOrSmartPointer<nsCOMPtr<int>>::Type>,
- "RemoveRawOrSmartPointer<nsCOMPtr<int>>::Type should be int");
+ mozilla::RemoveRawOrSmartPointer<const nsCOMPtr<int>>>,
+ "RemoveRawOrSmartPointer<const nsCOMPtr<int>> should be int");
static_assert(
- std::is_same_v<
- int, mozilla::RemoveRawOrSmartPointer<const nsCOMPtr<int>>::Type>,
- "RemoveRawOrSmartPointer<const nsCOMPtr<int>>::Type should be int");
+ std::is_same_v<int,
+ mozilla::RemoveRawOrSmartPointer<volatile nsCOMPtr<int>>>,
+ "RemoveRawOrSmartPointer<volatile nsCOMPtr<int>> should be int");
static_assert(
std::is_same_v<
- int, mozilla::RemoveRawOrSmartPointer<volatile nsCOMPtr<int>>::Type>,
- "RemoveRawOrSmartPointer<volatile nsCOMPtr<int>>::Type should be int");
- static_assert(
- std::is_same_v<int, mozilla::RemoveRawOrSmartPointer<
- const volatile nsCOMPtr<int>>::Type>,
- "RemoveRawOrSmartPointer<const volatile nsCOMPtr<int>>::Type should be "
+ int, mozilla::RemoveRawOrSmartPointer<const volatile nsCOMPtr<int>>>,
+ "RemoveRawOrSmartPointer<const volatile nsCOMPtr<int>> should be "
"int");
}
@@ -1289,15 +1255,9 @@ TEST(ThreadUtils, main)
static_assert(!IsParameterStorageClass<int>::value,
"'int' should not be recognized as Storage Class");
static_assert(
- IsParameterStorageClass<StoreCopyPassByValue<int>>::value,
- "StoreCopyPassByValue<int> should be recognized as Storage Class");
- static_assert(
IsParameterStorageClass<StoreCopyPassByConstLRef<int>>::value,
"StoreCopyPassByConstLRef<int> should be recognized as Storage Class");
static_assert(
- IsParameterStorageClass<StoreCopyPassByLRef<int>>::value,
- "StoreCopyPassByLRef<int> should be recognized as Storage Class");
- static_assert(
IsParameterStorageClass<StoreCopyPassByRRef<int>>::value,
"StoreCopyPassByRRef<int> should be recognized as Storage Class");
static_assert(
@@ -1315,12 +1275,6 @@ TEST(ThreadUtils, main)
static_assert(
IsParameterStorageClass<StoreConstPtrPassByConstPtr<int>>::value,
"StoreConstPtrPassByConstPtr<int> should be recognized as Storage Class");
- static_assert(
- IsParameterStorageClass<StoreCopyPassByConstPtr<int>>::value,
- "StoreCopyPassByConstPtr<int> should be recognized as Storage Class");
- static_assert(
- IsParameterStorageClass<StoreCopyPassByPtr<int>>::value,
- "StoreCopyPassByPtr<int> should be recognized as Storage Class");
RefPtr<ThreadUtilsObject> rpt(new ThreadUtilsObject);
int count = 0;
@@ -1359,11 +1313,6 @@ TEST(ThreadUtils, main)
StoreCopyPassByConstLRef<int>>,
"detail::ParameterStorage<int>::Type should be "
"StoreCopyPassByConstLRef<int>");
- static_assert(std::is_same_v<
- ::detail::ParameterStorage<StoreCopyPassByValue<int>>::Type,
- StoreCopyPassByValue<int>>,
- "detail::ParameterStorage<StoreCopyPassByValue<int>>::Type "
- "should be StoreCopyPassByValue<int>");
r1 = NewRunnableMethod<int>("TestThreadUtils::ThreadUtilsObject::Test1i", rpt,
&ThreadUtilsObject::Test1i, 12);
@@ -1480,37 +1429,6 @@ TEST(ThreadUtils, main)
EXPECT_EQ(i, rpt->mA0);
}
- // Raw pointer to copy.
- static_assert(std::is_same_v<StoreCopyPassByPtr<int>::stored_type, int>,
- "StoreCopyPassByPtr<int>::stored_type should be int");
- static_assert(std::is_same_v<StoreCopyPassByPtr<int>::passed_type, int*>,
- "StoreCopyPassByPtr<int>::passed_type should be int*");
- {
- int i = 1202;
- r1 = NewRunnableMethod<StoreCopyPassByPtr<int>>(
- "TestThreadUtils::ThreadUtilsObject::Test1pi", rpt,
- &ThreadUtilsObject::Test1pi, i);
- r1->Run();
- EXPECT_EQ(count += 2, rpt->mCount);
- EXPECT_EQ(i, rpt->mA0);
- }
-
- // Raw pointer to const copy.
- static_assert(std::is_same_v<StoreCopyPassByConstPtr<int>::stored_type, int>,
- "StoreCopyPassByConstPtr<int>::stored_type should be int");
- static_assert(
- std::is_same_v<StoreCopyPassByConstPtr<int>::passed_type, const int*>,
- "StoreCopyPassByConstPtr<int>::passed_type should be const int*");
- {
- int i = 1203;
- r1 = NewRunnableMethod<StoreCopyPassByConstPtr<int>>(
- "TestThreadUtils::ThreadUtilsObject::Test1pci", rpt,
- &ThreadUtilsObject::Test1pci, i);
- r1->Run();
- EXPECT_EQ(count += 2, rpt->mCount);
- EXPECT_EQ(i, rpt->mA0);
- }
-
// nsRefPtr to pointer.
static_assert(
std::is_same_v<::detail::ParameterStorage<
@@ -1536,7 +1454,7 @@ TEST(ThreadUtils, main)
// (more nsRefPtr tests below)
// nsRefPtr for ref-countable classes that do not derive from ISupports.
- static_assert(::detail::HasRefCountMethods<ThreadUtilsRefCountedFinal>::value,
+ static_assert(::detail::HasRefCountMethods<ThreadUtilsRefCountedFinal>,
"ThreadUtilsRefCountedFinal has AddRef() and Release()");
static_assert(
std::is_same_v<
@@ -1544,7 +1462,7 @@ TEST(ThreadUtils, main)
StoreRefPtrPassByPtr<ThreadUtilsRefCountedFinal>>,
"ParameterStorage<ThreadUtilsRefCountedFinal*>::Type should be "
"StoreRefPtrPassByPtr<ThreadUtilsRefCountedFinal>");
- static_assert(::detail::HasRefCountMethods<ThreadUtilsRefCountedBase>::value,
+ static_assert(::detail::HasRefCountMethods<ThreadUtilsRefCountedBase>,
"ThreadUtilsRefCountedBase has AddRef() and Release()");
static_assert(
std::is_same_v<
@@ -1552,9 +1470,8 @@ TEST(ThreadUtils, main)
StoreRefPtrPassByPtr<ThreadUtilsRefCountedBase>>,
"ParameterStorage<ThreadUtilsRefCountedBase*>::Type should be "
"StoreRefPtrPassByPtr<ThreadUtilsRefCountedBase>");
- static_assert(
- ::detail::HasRefCountMethods<ThreadUtilsRefCountedDerived>::value,
- "ThreadUtilsRefCountedDerived has AddRef() and Release()");
+ static_assert(::detail::HasRefCountMethods<ThreadUtilsRefCountedDerived>,
+ "ThreadUtilsRefCountedDerived has AddRef() and Release()");
static_assert(
std::is_same_v<
::detail::ParameterStorage<ThreadUtilsRefCountedDerived*>::Type,
@@ -1562,7 +1479,7 @@ TEST(ThreadUtils, main)
"ParameterStorage<ThreadUtilsRefCountedDerived*>::Type should be "
"StoreRefPtrPassByPtr<ThreadUtilsRefCountedDerived>");
- static_assert(!::detail::HasRefCountMethods<ThreadUtilsNonRefCounted>::value,
+ static_assert(!::detail::HasRefCountMethods<ThreadUtilsNonRefCounted>,
"ThreadUtilsNonRefCounted doesn't have AddRef() and Release()");
static_assert(!std::is_same_v<
::detail::ParameterStorage<ThreadUtilsNonRefCounted*>::Type,
@@ -1738,126 +1655,6 @@ TEST(ThreadUtils, main)
Spy::ClearAll();
if (gDebug) {
- printf("%d - Test: Store copy from lvalue, pass by value\n", __LINE__);
- }
- { // Block around nsCOMPtr lifetime.
- nsCOMPtr<nsIRunnable> r2;
- { // Block around Spy lifetime.
- if (gDebug) {
- printf("%d - Spy s(10)\n", __LINE__);
- }
- Spy s(10);
- EXPECT_EQ(1, gConstructions);
- EXPECT_EQ(1, gAlive);
- if (gDebug) {
- printf(
- "%d - r2 = "
- "NewRunnableMethod<StoreCopyPassByValue<Spy>>(&TestByValue, s)\n",
- __LINE__);
- }
- r2 = NewRunnableMethod<StoreCopyPassByValue<Spy>>(
- "TestThreadUtils::ThreadUtilsObject::TestByValue", rpt,
- &ThreadUtilsObject::TestByValue, s);
- EXPECT_EQ(2, gAlive);
- EXPECT_LE(1, gCopyConstructions); // At least 1 copy-construction.
- Spy::ClearActions();
- if (gDebug) {
- printf("%d - End block with Spy s(10)\n", __LINE__);
- }
- }
- EXPECT_EQ(1, gDestructions);
- EXPECT_EQ(1, gAlive);
- Spy::ClearActions();
- if (gDebug) {
- printf("%d - Run()\n", __LINE__);
- }
- r2->Run();
- EXPECT_LE(1, gCopyConstructions); // Another copy-construction in call.
- EXPECT_EQ(10, rpt->mSpy.mID);
- EXPECT_LE(1, gDestructions);
- EXPECT_EQ(1, gAlive);
- Spy::ClearActions();
- if (gDebug) {
- printf("%d - End block with r\n", __LINE__);
- }
- }
- if (gDebug) {
- printf("%d - After end block with r\n", __LINE__);
- }
- EXPECT_EQ(1, gDestructions);
- EXPECT_EQ(0, gAlive);
-
- Spy::ClearAll();
- if (gDebug) {
- printf("%d - Test: Store copy from prvalue, pass by value\n", __LINE__);
- }
- {
- if (gDebug) {
- printf(
- "%d - r3 = "
- "NewRunnableMethod<StoreCopyPassByValue<Spy>>(&TestByValue, "
- "Spy(11))\n",
- __LINE__);
- }
- nsCOMPtr<nsIRunnable> r3 = NewRunnableMethod<StoreCopyPassByValue<Spy>>(
- "TestThreadUtils::ThreadUtilsObject::TestByValue", rpt,
- &ThreadUtilsObject::TestByValue, Spy(11));
- EXPECT_EQ(1, gAlive);
- EXPECT_EQ(1, gConstructions);
- EXPECT_LE(1, gMoveConstructions);
- Spy::ClearActions();
- if (gDebug) {
- printf("%d - Run()\n", __LINE__);
- }
- r3->Run();
- EXPECT_LE(1, gCopyConstructions); // Another copy-construction in call.
- EXPECT_EQ(11, rpt->mSpy.mID);
- EXPECT_LE(1, gDestructions);
- EXPECT_EQ(1, gAlive);
- Spy::ClearActions();
- if (gDebug) {
- printf("%d - End block with r\n", __LINE__);
- }
- }
- if (gDebug) {
- printf("%d - After end block with r\n", __LINE__);
- }
- EXPECT_EQ(1, gDestructions);
- EXPECT_EQ(0, gAlive);
-
- Spy::ClearAll();
- { // Store copy from xvalue, pass by value.
- nsCOMPtr<nsIRunnable> r4;
- {
- Spy s(12);
- EXPECT_EQ(1, gConstructions);
- EXPECT_EQ(1, gAlive);
- Spy::ClearActions();
- r4 = NewRunnableMethod<StoreCopyPassByValue<Spy>>(
- "TestThreadUtils::ThreadUtilsObject::TestByValue", rpt,
- &ThreadUtilsObject::TestByValue, std::move(s));
- EXPECT_LE(1, gMoveConstructions);
- EXPECT_EQ(1, gAlive);
- EXPECT_EQ(1, gZombies);
- Spy::ClearActions();
- }
- EXPECT_EQ(1, gDestructions);
- EXPECT_EQ(1, gAlive);
- EXPECT_EQ(0, gZombies);
- Spy::ClearActions();
- r4->Run();
- EXPECT_LE(1, gCopyConstructions); // Another copy-construction in call.
- EXPECT_EQ(12, rpt->mSpy.mID);
- EXPECT_LE(1, gDestructions);
- EXPECT_EQ(1, gAlive);
- Spy::ClearActions();
- }
- EXPECT_EQ(1, gDestructions);
- EXPECT_EQ(0, gAlive);
- // Won't test xvalues anymore, prvalues are enough to verify all rvalues.
-
- Spy::ClearAll();
- if (gDebug) {
printf("%d - Test: Store copy from lvalue, pass by const lvalue ref\n",
__LINE__);
}
diff --git a/xpcom/tests/gtest/moz.build b/xpcom/tests/gtest/moz.build
index 57ec43a371..6fd509d7b2 100644
--- a/xpcom/tests/gtest/moz.build
+++ b/xpcom/tests/gtest/moz.build
@@ -9,6 +9,7 @@ UNIFIED_SOURCES += [
"TestArenaAllocator.cpp",
"TestArrayAlgorithm.cpp",
"TestAtoms.cpp",
+ "TestAutoOwningEventTarget.cpp",
"TestAutoRefCnt.cpp",
"TestBase64.cpp",
"TestCallTemplates.cpp",
@@ -120,10 +121,14 @@ else:
if CONFIG["OS_TARGET"] == "Darwin":
UNIFIED_SOURCES += [
"TestAvailableMemoryWatcherMac.cpp",
- "TestMacNSURLEscaping.mm",
"TestThreads_mac.mm",
]
+if CONFIG["TARGET_OS"] == "OSX":
+ UNIFIED_SOURCES += [
+ "TestMacNSURLEscaping.mm",
+ ]
+
if CONFIG["OS_TARGET"] == "Linux":
UNIFIED_SOURCES += [
"TestAvailableMemoryWatcherLinux.cpp",
diff --git a/xpcom/threads/MozPromise.h b/xpcom/threads/MozPromise.h
index f17e085c2f..af4ac657fd 100644
--- a/xpcom/threads/MozPromise.h
+++ b/xpcom/threads/MozPromise.h
@@ -82,24 +82,22 @@ struct MethodTrait : MethodTraitsHelper<std::remove_reference_t<T>> {};
} // namespace detail
-template <typename MethodType>
-using TakesArgument =
- std::integral_constant<bool, detail::MethodTrait<MethodType>::ArgSize != 0>;
+template <typename T>
+using MethodReturnType = typename detail::MethodTrait<T>::ReturnType;
-template <typename MethodType, typename TargetType>
-using ReturnTypeIs =
- std::is_convertible<typename detail::MethodTrait<MethodType>::ReturnType,
- TargetType>;
+template <typename MethodType>
+constexpr bool TakesAnyArguments =
+ detail::MethodTrait<MethodType>::ArgSize != 0;
template <typename ResolveValueT, typename RejectValueT, bool IsExclusive>
class MozPromise;
-template <typename Return>
-struct IsMozPromise : std::false_type {};
+template <typename T>
+constexpr bool IsMozPromise = false;
template <typename ResolveValueT, typename RejectValueT, bool IsExclusive>
-struct IsMozPromise<MozPromise<ResolveValueT, RejectValueT, IsExclusive>>
- : std::true_type {};
+constexpr bool
+ IsMozPromise<MozPromise<ResolveValueT, RejectValueT, IsExclusive>> = true;
/*
* A promise manages an asynchronous request that may or may not be able to be
@@ -176,8 +174,8 @@ class MozPromise : public MozPromiseBase {
}
public:
- typedef ResolveValueT ResolveValueType;
- typedef RejectValueT RejectValueType;
+ using ResolveValueType = ResolveValueT;
+ using RejectValueType = RejectValueT;
class ResolveOrRejectValue {
public:
template <typename ResolveValueType_>
@@ -288,12 +286,10 @@ class MozPromise : public MozPromiseBase {
return p;
}
- typedef MozPromise<CopyableTArray<ResolveValueType>, RejectValueType,
- IsExclusive>
- AllPromiseType;
-
- typedef MozPromise<CopyableTArray<ResolveOrRejectValue>, bool, IsExclusive>
- AllSettledPromiseType;
+ using AllPromiseType = MozPromise<CopyableTArray<ResolveValueType>,
+ RejectValueType, IsExclusive>;
+ using AllSettledPromiseType =
+ MozPromise<CopyableTArray<ResolveOrRejectValue>, bool, IsExclusive>;
private:
class AllPromiseHolder : public MozPromiseRefcountable {
@@ -350,17 +346,17 @@ class MozPromise : public MozPromiseBase {
// Trying to pass ResolveOrRejectValue by value fails static analysis checks,
// so we need to use either a const& or an rvalue reference, depending on
// whether IsExclusive is true or not.
- typedef std::conditional_t<IsExclusive, ResolveOrRejectValue&&,
- const ResolveOrRejectValue&>
- ResolveOrRejectValueParam;
+ using ResolveOrRejectValueParam =
+ std::conditional_t<IsExclusive, ResolveOrRejectValue&&,
+ const ResolveOrRejectValue&>;
- typedef std::conditional_t<IsExclusive, ResolveValueType&&,
- const ResolveValueType&>
- ResolveValueTypeParam;
+ using ResolveValueTypeParam =
+ std::conditional_t<IsExclusive, ResolveValueType&&,
+ const ResolveValueType&>;
- typedef std::conditional_t<IsExclusive, RejectValueType&&,
- const RejectValueType&>
- RejectValueTypeParam;
+ using RejectValueTypeParam =
+ std::conditional_t<IsExclusive, RejectValueType&&,
+ const RejectValueType&>;
class AllSettledPromiseHolder : public MozPromiseRefcountable {
public:
@@ -648,15 +644,15 @@ class MozPromise : public MozPromiseBase {
* make the resolve/reject value argument "optional".
*/
template <typename ThisType, typename MethodType, typename ValueType>
- static std::enable_if_t<TakesArgument<MethodType>::value,
- typename detail::MethodTrait<MethodType>::ReturnType>
+ static std::enable_if_t<TakesAnyArguments<MethodType>,
+ MethodReturnType<MethodType>>
InvokeMethod(ThisType* aThisVal, MethodType aMethod, ValueType&& aValue) {
return (aThisVal->*aMethod)(std::forward<ValueType>(aValue));
}
template <typename ThisType, typename MethodType, typename ValueType>
- static std::enable_if_t<!TakesArgument<MethodType>::value,
- typename detail::MethodTrait<MethodType>::ReturnType>
+ static std::enable_if_t<!TakesAnyArguments<MethodType>,
+ MethodReturnType<MethodType>>
InvokeMethod(ThisType* aThisVal, MethodType aMethod, ValueType&& aValue) {
return (aThisVal->*aMethod)();
}
@@ -697,18 +693,14 @@ class MozPromise : public MozPromiseBase {
: public ThenValueBase {
friend class ThenCommand<ThenValue>;
- using R1 = typename RemoveSmartPointer<
- typename detail::MethodTrait<ResolveMethodType>::ReturnType>::Type;
- using R2 = typename RemoveSmartPointer<
- typename detail::MethodTrait<RejectMethodType>::ReturnType>::Type;
- using SupportChaining =
- std::integral_constant<bool, IsMozPromise<R1>::value &&
- std::is_same_v<R1, R2>>;
+ using R1 = RemoveSmartPointer<MethodReturnType<ResolveMethodType>>;
+ using R2 = RemoveSmartPointer<MethodReturnType<RejectMethodType>>;
+ constexpr static bool SupportChaining =
+ IsMozPromise<R1> && std::is_same_v<R1, R2>;
// Fall back to MozPromise when promise chaining is not supported to make
// code compile.
- using PromiseType =
- std::conditional_t<SupportChaining::value, R1, MozPromise>;
+ using PromiseType = std::conditional_t<SupportChaining, R1, MozPromise>;
public:
ThenValue(nsISerialEventTarget* aResponseTarget, ThisType* aThisVal,
@@ -736,13 +728,13 @@ class MozPromise : public MozPromiseBase {
void DoResolveOrRejectInternal(ResolveOrRejectValue& aValue) override {
if (aValue.IsResolve()) {
- InvokeCallbackMethod<SupportChaining::value>(
- mThisVal.get(), mResolveMethod, MaybeMove(aValue.ResolveValue()),
- std::move(mCompletionPromise));
+ InvokeCallbackMethod<SupportChaining>(mThisVal.get(), mResolveMethod,
+ MaybeMove(aValue.ResolveValue()),
+ std::move(mCompletionPromise));
} else {
- InvokeCallbackMethod<SupportChaining::value>(
- mThisVal.get(), mRejectMethod, MaybeMove(aValue.RejectValue()),
- std::move(mCompletionPromise));
+ InvokeCallbackMethod<SupportChaining>(mThisVal.get(), mRejectMethod,
+ MaybeMove(aValue.RejectValue()),
+ std::move(mCompletionPromise));
}
// Null out mThisVal after invoking the callback so that any references
@@ -764,15 +756,12 @@ class MozPromise : public MozPromiseBase {
class ThenValue<ThisType*, ResolveRejectMethodType> : public ThenValueBase {
friend class ThenCommand<ThenValue>;
- using R1 = typename RemoveSmartPointer<typename detail::MethodTrait<
- ResolveRejectMethodType>::ReturnType>::Type;
- using SupportChaining =
- std::integral_constant<bool, IsMozPromise<R1>::value>;
+ using R1 = RemoveSmartPointer<MethodReturnType<ResolveRejectMethodType>>;
+ constexpr static bool SupportChaining = IsMozPromise<R1>;
// Fall back to MozPromise when promise chaining is not supported to make
// code compile.
- using PromiseType =
- std::conditional_t<SupportChaining::value, R1, MozPromise>;
+ using PromiseType = std::conditional_t<SupportChaining, R1, MozPromise>;
public:
ThenValue(nsISerialEventTarget* aResponseTarget, ThisType* aThisVal,
@@ -798,7 +787,7 @@ class MozPromise : public MozPromiseBase {
}
void DoResolveOrRejectInternal(ResolveOrRejectValue& aValue) override {
- InvokeCallbackMethod<SupportChaining::value>(
+ InvokeCallbackMethod<SupportChaining>(
mThisVal.get(), mResolveRejectMethod, MaybeMove(aValue),
std::move(mCompletionPromise));
@@ -822,18 +811,14 @@ class MozPromise : public MozPromiseBase {
class ThenValue<ResolveFunction, RejectFunction> : public ThenValueBase {
friend class ThenCommand<ThenValue>;
- using R1 = typename RemoveSmartPointer<
- typename detail::MethodTrait<ResolveFunction>::ReturnType>::Type;
- using R2 = typename RemoveSmartPointer<
- typename detail::MethodTrait<RejectFunction>::ReturnType>::Type;
- using SupportChaining =
- std::integral_constant<bool, IsMozPromise<R1>::value &&
- std::is_same_v<R1, R2>>;
+ using R1 = RemoveSmartPointer<MethodReturnType<ResolveFunction>>;
+ using R2 = RemoveSmartPointer<MethodReturnType<RejectFunction>>;
+ constexpr static bool SupportChaining =
+ IsMozPromise<R1> && std::is_same_v<R1, R2>;
// Fall back to MozPromise when promise chaining is not supported to make
// code compile.
- using PromiseType =
- std::conditional_t<SupportChaining::value, R1, MozPromise>;
+ using PromiseType = std::conditional_t<SupportChaining, R1, MozPromise>;
public:
ThenValue(nsISerialEventTarget* aResponseTarget,
@@ -867,11 +852,11 @@ class MozPromise : public MozPromiseBase {
// easily. We could fix this if need be, though it's quite easy to work
// around by just capturing something.
if (aValue.IsResolve()) {
- InvokeCallbackMethod<SupportChaining::value>(
+ InvokeCallbackMethod<SupportChaining>(
mResolveFunction.ptr(), &ResolveFunction::operator(),
MaybeMove(aValue.ResolveValue()), std::move(mCompletionPromise));
} else {
- InvokeCallbackMethod<SupportChaining::value>(
+ InvokeCallbackMethod<SupportChaining>(
mRejectFunction.ptr(), &RejectFunction::operator(),
MaybeMove(aValue.RejectValue()), std::move(mCompletionPromise));
}
@@ -896,15 +881,12 @@ class MozPromise : public MozPromiseBase {
class ThenValue<ResolveRejectFunction> : public ThenValueBase {
friend class ThenCommand<ThenValue>;
- using R1 = typename RemoveSmartPointer<
- typename detail::MethodTrait<ResolveRejectFunction>::ReturnType>::Type;
- using SupportChaining =
- std::integral_constant<bool, IsMozPromise<R1>::value>;
+ using R1 = RemoveSmartPointer<MethodReturnType<ResolveRejectFunction>>;
+ constexpr static bool SupportChaining = IsMozPromise<R1>;
// Fall back to MozPromise when promise chaining is not supported to make
// code compile.
- using PromiseType =
- std::conditional_t<SupportChaining::value, R1, MozPromise>;
+ using PromiseType = std::conditional_t<SupportChaining, R1, MozPromise>;
public:
ThenValue(nsISerialEventTarget* aResponseTarget,
@@ -935,7 +917,7 @@ class MozPromise : public MozPromiseBase {
// classes with ::operator()), since it allows us to share code more
// easily. We could fix this if need be, though it's quite easy to work
// around by just capturing something.
- InvokeCallbackMethod<SupportChaining::value>(
+ InvokeCallbackMethod<SupportChaining>(
mResolveRejectFunction.ptr(), &ResolveRejectFunction::operator(),
MaybeMove(aValue), std::move(mCompletionPromise));
@@ -998,7 +980,7 @@ class MozPromise : public MozPromiseBase {
MozPromise* aReceiver)
: mCallSite(aCallSite), mThenValue(aThenValue), mReceiver(aReceiver) {}
- ThenCommand(ThenCommand&& aOther) = default;
+ ThenCommand(ThenCommand&& aOther) noexcept = default;
public:
~ThenCommand() {
@@ -1013,7 +995,7 @@ class MozPromise : public MozPromiseBase {
// p->Then(thread2, ...);
operator RefPtr<PromiseType>() {
static_assert(
- ThenValueType::SupportChaining::value,
+ ThenValueType::SupportChaining,
"The resolve/reject callback needs to return a RefPtr<MozPromise> "
"in order to do promise chaining.");
@@ -1336,12 +1318,18 @@ class MozPromise<ResolveValueT, RejectValueT, IsExclusive>::Private
};
// A generic promise type that does the trick for simple use cases.
-typedef MozPromise<bool, nsresult, /* IsExclusive = */ true> GenericPromise;
+//
+// Vaguely deprecated: prefer explicitly naming the resolve- and reject-type.
+// Additionally, prefer `mozilla::Ok` as the resolve-type if the boolean's value
+// is irrelevant.
+using GenericPromise = MozPromise<bool, nsresult, /* IsExclusive = */ true>;
// A generic, non-exclusive promise type that does the trick for simple use
// cases.
-typedef MozPromise<bool, nsresult, /* IsExclusive = */ false>
- GenericNonExclusivePromise;
+//
+// Vaguely deprecated, as above.
+using GenericNonExclusivePromise =
+ MozPromise<bool, nsresult, /* IsExclusive = */ false>;
/*
* Class to encapsulate a promise for a particular role. Use this as the member
@@ -1352,8 +1340,9 @@ class MozPromiseHolderBase {
public:
MozPromiseHolderBase() = default;
- MozPromiseHolderBase(MozPromiseHolderBase&& aOther) = default;
- MozPromiseHolderBase& operator=(MozPromiseHolderBase&& aOther) = default;
+ MozPromiseHolderBase(MozPromiseHolderBase&& aOther) noexcept = default;
+ MozPromiseHolderBase& operator=(MozPromiseHolderBase&& aOther) noexcept =
+ default;
~MozPromiseHolderBase() { MOZ_ASSERT(!mPromise); }
@@ -1511,8 +1500,8 @@ class MozPromiseRequestHolder {
// will never be called.
void Disconnect() {
MOZ_ASSERT(Exists());
- mRequest->Disconnect();
- mRequest = nullptr;
+ RefPtr request = std::move(mRequest);
+ request->Disconnect();
}
void DisconnectIfExists() {
@@ -1700,30 +1689,26 @@ class ProxyFunctionRunnable : public CancelableRunnable {
UniquePtr<FunctionStorage> mFunction;
};
-// Note: The following struct and function are not for public consumption (yet?)
-// as we would prefer all calls to pass on-the-spot lambdas (or at least moved
-// function objects). They could be moved outside of detail if really needed.
+template <typename T>
+constexpr static bool IsRefPtrMozPromise = false;
+template <typename T, typename U, bool B>
+constexpr static bool IsRefPtrMozPromise<RefPtr<MozPromise<T, U, B>>> = true;
-// We prefer getting function objects by non-lvalue-ref (to avoid copying them
-// and their captures). This struct is a tag that allows the use of objects
-// through lvalue-refs where necessary.
-struct AllowInvokeAsyncFunctionLVRef {};
+} // namespace detail
-// Invoke a function object (e.g., lambda or std/mozilla::function)
-// asynchronously; note that the object will be copied if provided by
-// lvalue-ref. Return a promise that the function should eventually resolve or
-// reject.
+// Invoke a function object (e.g., lambda) asynchronously.
+// Return a promise that the function should eventually resolve or reject.
template <typename Function>
static auto InvokeAsync(nsISerialEventTarget* aTarget, const char* aCallerName,
- AllowInvokeAsyncFunctionLVRef, Function&& aFunction)
- -> decltype(aFunction()) {
- static_assert(
- IsRefcountedSmartPointer<decltype(aFunction())>::value &&
- IsMozPromise<
- typename RemoveSmartPointer<decltype(aFunction())>::Type>::value,
- "Function object must return RefPtr<MozPromise>");
+ Function&& aFunction) -> decltype(aFunction()) {
+ static_assert(!std::is_lvalue_reference_v<Function>,
+ "Function object must not be passed by lvalue-ref (to avoid "
+ "unplanned copies); Consider move()ing the object.");
+
+ static_assert(detail::IsRefPtrMozPromise<decltype(aFunction())>,
+ "Function object must return RefPtr<MozPromise>");
MOZ_ASSERT(aTarget);
- typedef typename RemoveSmartPointer<decltype(aFunction())>::Type PromiseType;
+ typedef RemoveSmartPointer<decltype(aFunction())> PromiseType;
typedef detail::ProxyFunctionRunnable<Function, PromiseType>
ProxyRunnableType;
@@ -1733,21 +1718,6 @@ static auto InvokeAsync(nsISerialEventTarget* aTarget, const char* aCallerName,
return p;
}
-} // namespace detail
-
-// Invoke a function object (e.g., lambda) asynchronously.
-// Return a promise that the function should eventually resolve or reject.
-template <typename Function>
-static auto InvokeAsync(nsISerialEventTarget* aTarget, const char* aCallerName,
- Function&& aFunction) -> decltype(aFunction()) {
- static_assert(!std::is_lvalue_reference_v<Function>,
- "Function object must not be passed by lvalue-ref (to avoid "
- "unplanned copies); Consider move()ing the object.");
- return detail::InvokeAsync(aTarget, aCallerName,
- detail::AllowInvokeAsyncFunctionLVRef(),
- std::forward<Function>(aFunction));
-}
-
# undef PROMISE_LOG
# undef PROMISE_ASSERT
# undef PROMISE_DEBUG
diff --git a/xpcom/threads/Mutex.h b/xpcom/threads/Mutex.h
index 5116f1d7c3..8edb6ee773 100644
--- a/xpcom/threads/Mutex.h
+++ b/xpcom/threads/Mutex.h
@@ -227,7 +227,7 @@ class MOZ_RAII MOZ_SCOPED_CAPABILITY BaseAutoLock {
public:
/**
* Constructor
- * The constructor aquires the given lock. The destructor
+ * The constructor acquires the given lock. The destructor
* releases the lock.
*
* @param aLock A valid mozilla::Mutex* returned by
@@ -343,7 +343,7 @@ class MOZ_RAII MOZ_SCOPED_CAPABILITY ReleasableBaseAutoLock {
public:
/**
* Constructor
- * The constructor aquires the given lock. The destructor
+ * The constructor acquires the given lock. The destructor
* releases the lock.
*
* @param aLock A valid mozilla::Mutex& returned by
diff --git a/xpcom/threads/nsThreadManager.cpp b/xpcom/threads/nsThreadManager.cpp
index 805be6ee64..3ea324a6c6 100644
--- a/xpcom/threads/nsThreadManager.cpp
+++ b/xpcom/threads/nsThreadManager.cpp
@@ -672,11 +672,11 @@ void AutoNestedEventLoopAnnotation::AnnotateXPCOMSpinEventLoopStack(
if (aStack.Length() > 0) {
nsCString prefixedStack(XRE_GetProcessTypeString());
prefixedStack += ": "_ns + aStack;
- CrashReporter::AnnotateCrashReport(
+ CrashReporter::RecordAnnotationNSCString(
CrashReporter::Annotation::XPCOMSpinEventLoopStack, prefixedStack);
} else {
- CrashReporter::AnnotateCrashReport(
- CrashReporter::Annotation::XPCOMSpinEventLoopStack, ""_ns);
+ CrashReporter::UnrecordAnnotation(
+ CrashReporter::Annotation::XPCOMSpinEventLoopStack);
}
}
diff --git a/xpcom/threads/nsThreadUtils.h b/xpcom/threads/nsThreadUtils.h
index 72041da295..755ec21c95 100644
--- a/xpcom/threads/nsThreadUtils.h
+++ b/xpcom/threads/nsThreadUtils.h
@@ -562,71 +562,40 @@ using RunnableFunctionImpl =
namespace detail {
-template <typename CVRemoved>
-struct IsRefcountedSmartPointerHelper : std::false_type {};
-
-template <typename Pointee>
-struct IsRefcountedSmartPointerHelper<RefPtr<Pointee>> : std::true_type {};
-
-template <typename Pointee>
-struct IsRefcountedSmartPointerHelper<nsCOMPtr<Pointee>> : std::true_type {};
-
-} // namespace detail
-
template <typename T>
-struct IsRefcountedSmartPointer
- : detail::IsRefcountedSmartPointerHelper<std::remove_cv_t<T>> {};
-
-namespace detail {
-
-template <typename T, typename CVRemoved>
struct RemoveSmartPointerHelper {
- typedef T Type;
+ using Type = T;
};
-template <typename T, typename Pointee>
-struct RemoveSmartPointerHelper<T, RefPtr<Pointee>> {
- typedef Pointee Type;
+template <typename T>
+struct RemoveSmartPointerHelper<RefPtr<T>> {
+ using Type = T;
};
-template <typename T, typename Pointee>
-struct RemoveSmartPointerHelper<T, nsCOMPtr<Pointee>> {
- typedef Pointee Type;
+template <typename T>
+struct RemoveSmartPointerHelper<nsCOMPtr<T>> {
+ using Type = T;
};
-} // namespace detail
-
template <typename T>
-struct RemoveSmartPointer
- : detail::RemoveSmartPointerHelper<T, std::remove_cv_t<T>> {};
-
-namespace detail {
-
-template <typename T, typename CVRemoved>
struct RemoveRawOrSmartPointerHelper {
- typedef T Type;
-};
-
-template <typename T, typename Pointee>
-struct RemoveRawOrSmartPointerHelper<T, Pointee*> {
- typedef Pointee Type;
+ using Type = typename RemoveSmartPointerHelper<T>::Type;
};
-template <typename T, typename Pointee>
-struct RemoveRawOrSmartPointerHelper<T, RefPtr<Pointee>> {
- typedef Pointee Type;
-};
-
-template <typename T, typename Pointee>
-struct RemoveRawOrSmartPointerHelper<T, nsCOMPtr<Pointee>> {
- typedef Pointee Type;
+template <typename T>
+struct RemoveRawOrSmartPointerHelper<T*> {
+ using Type = T;
};
} // namespace detail
template <typename T>
-struct RemoveRawOrSmartPointer
- : detail::RemoveRawOrSmartPointerHelper<T, std::remove_cv_t<T>> {};
+using RemoveSmartPointer =
+ typename detail::RemoveSmartPointerHelper<std::remove_cv_t<T>>::Type;
+
+template <typename T>
+using RemoveRawOrSmartPointer =
+ typename detail::RemoveRawOrSmartPointerHelper<std::remove_cv_t<T>>::Type;
} // namespace mozilla
@@ -797,23 +766,22 @@ struct nsRunnableMethodTraits;
template <typename PtrType, class C, typename R, bool Owning,
mozilla::RunnableKind Kind, typename... As>
struct nsRunnableMethodTraits<PtrType, R (C::*)(As...), Owning, Kind> {
- typedef typename mozilla::RemoveRawOrSmartPointer<PtrType>::Type class_type;
+ using class_type = mozilla::RemoveRawOrSmartPointer<PtrType>;
static_assert(std::is_base_of<C, class_type>::value,
"Stored class must inherit from method's class");
- typedef R return_type;
- typedef nsRunnableMethod<C, R, Owning, Kind> base_type;
+ using return_type = R;
+ using base_type = nsRunnableMethod<C, R, Owning, Kind>;
static const bool can_cancel = Kind == mozilla::RunnableKind::Cancelable;
};
template <typename PtrType, class C, typename R, bool Owning,
mozilla::RunnableKind Kind, typename... As>
struct nsRunnableMethodTraits<PtrType, R (C::*)(As...) const, Owning, Kind> {
- typedef const typename mozilla::RemoveRawOrSmartPointer<PtrType>::Type
- class_type;
+ using class_type = const mozilla::RemoveRawOrSmartPointer<PtrType>;
static_assert(std::is_base_of<C, class_type>::value,
"Stored class must inherit from method's class");
- typedef R return_type;
- typedef nsRunnableMethod<C, R, Owning, Kind> base_type;
+ using return_type = R;
+ using base_type = nsRunnableMethod<C, R, Owning, Kind>;
static const bool can_cancel = Kind == mozilla::RunnableKind::Cancelable;
};
@@ -822,22 +790,22 @@ template <typename PtrType, class C, typename R, bool Owning,
mozilla::RunnableKind Kind, typename... As>
struct nsRunnableMethodTraits<PtrType, R (__stdcall C::*)(As...), Owning,
Kind> {
- typedef typename mozilla::RemoveRawOrSmartPointer<PtrType>::Type class_type;
+ using class_type = mozilla::RemoveRawOrSmartPointer<PtrType>;
static_assert(std::is_base_of<C, class_type>::value,
"Stored class must inherit from method's class");
- typedef R return_type;
- typedef nsRunnableMethod<C, R, Owning, Kind> base_type;
+ using return_type = R;
+ using base_type = nsRunnableMethod<C, R, Owning, Kind>;
static const bool can_cancel = Kind == mozilla::RunnableKind::Cancelable;
};
template <typename PtrType, class C, typename R, bool Owning,
mozilla::RunnableKind Kind>
struct nsRunnableMethodTraits<PtrType, R (NS_STDCALL C::*)(), Owning, Kind> {
- typedef typename mozilla::RemoveRawOrSmartPointer<PtrType>::Type class_type;
+ using class_type = mozilla::RemoveRawOrSmartPointer<PtrType>;
static_assert(std::is_base_of<C, class_type>::value,
"Stored class must inherit from method's class");
- typedef R return_type;
- typedef nsRunnableMethod<C, R, Owning, Kind> base_type;
+ using return_type = R;
+ using base_type = nsRunnableMethod<C, R, Owning, Kind>;
static const bool can_cancel = Kind == mozilla::RunnableKind::Cancelable;
};
@@ -845,12 +813,11 @@ template <typename PtrType, class C, typename R, bool Owning,
mozilla::RunnableKind Kind, typename... As>
struct nsRunnableMethodTraits<PtrType, R (__stdcall C::*)(As...) const, Owning,
Kind> {
- typedef const typename mozilla::RemoveRawOrSmartPointer<PtrType>::Type
- class_type;
+ using class_type = const mozilla::RemoveRawOrSmartPointer<PtrType>;
static_assert(std::is_base_of<C, class_type>::value,
"Stored class must inherit from method's class");
- typedef R return_type;
- typedef nsRunnableMethod<C, R, Owning, Kind> base_type;
+ using return_type = R;
+ using base_type = nsRunnableMethod<C, R, Owning, Kind>;
static const bool can_cancel = Kind == mozilla::RunnableKind::Cancelable;
};
@@ -858,12 +825,11 @@ template <typename PtrType, class C, typename R, bool Owning,
mozilla::RunnableKind Kind>
struct nsRunnableMethodTraits<PtrType, R (NS_STDCALL C::*)() const, Owning,
Kind> {
- typedef const typename mozilla::RemoveRawOrSmartPointer<PtrType>::Type
- class_type;
+ using class_type = const mozilla::RemoveRawOrSmartPointer<PtrType>;
static_assert(std::is_base_of<C, class_type>::value,
"Stored class must inherit from method's class");
- typedef R return_type;
- typedef nsRunnableMethod<C, R, Owning, Kind> base_type;
+ using return_type = R;
+ using base_type = nsRunnableMethod<C, R, Owning, Kind>;
static const bool can_cancel = Kind == mozilla::RunnableKind::Cancelable;
};
# endif
@@ -881,19 +847,6 @@ struct IsParameterStorageClass : public std::false_type {};
// store arguments, and how to pass them to the target method.
template <typename T>
-struct StoreCopyPassByValue {
- using stored_type = std::decay_t<T>;
- typedef stored_type passed_type;
- stored_type m;
- template <typename A>
- MOZ_IMPLICIT StoreCopyPassByValue(A&& a) : m(std::forward<A>(a)) {}
- passed_type PassAsParameter() { return m; }
-};
-template <typename S>
-struct IsParameterStorageClass<StoreCopyPassByValue<S>>
- : public std::true_type {};
-
-template <typename T>
struct StoreCopyPassByConstLRef {
using stored_type = std::decay_t<T>;
typedef const stored_type& passed_type;
@@ -907,19 +860,6 @@ struct IsParameterStorageClass<StoreCopyPassByConstLRef<S>>
: public std::true_type {};
template <typename T>
-struct StoreCopyPassByLRef {
- using stored_type = std::decay_t<T>;
- typedef stored_type& passed_type;
- stored_type m;
- template <typename A>
- MOZ_IMPLICIT StoreCopyPassByLRef(A&& a) : m(std::forward<A>(a)) {}
- passed_type PassAsParameter() { return m; }
-};
-template <typename S>
-struct IsParameterStorageClass<StoreCopyPassByLRef<S>> : public std::true_type {
-};
-
-template <typename T>
struct StoreCopyPassByRRef {
using stored_type = std::decay_t<T>;
typedef stored_type&& passed_type;
@@ -996,32 +936,6 @@ template <typename S>
struct IsParameterStorageClass<StoreConstPtrPassByConstPtr<S>>
: public std::true_type {};
-template <typename T>
-struct StoreCopyPassByConstPtr {
- typedef T stored_type;
- typedef const T* passed_type;
- stored_type m;
- template <typename A>
- MOZ_IMPLICIT StoreCopyPassByConstPtr(A&& a) : m(std::forward<A>(a)) {}
- passed_type PassAsParameter() { return &m; }
-};
-template <typename S>
-struct IsParameterStorageClass<StoreCopyPassByConstPtr<S>>
- : public std::true_type {};
-
-template <typename T>
-struct StoreCopyPassByPtr {
- typedef T stored_type;
- typedef T* passed_type;
- stored_type m;
- template <typename A>
- MOZ_IMPLICIT StoreCopyPassByPtr(A&& a) : m(std::forward<A>(a)) {}
- passed_type PassAsParameter() { return &m; }
-};
-template <typename S>
-struct IsParameterStorageClass<StoreCopyPassByPtr<S>> : public std::true_type {
-};
-
namespace detail {
template <typename>
@@ -1035,94 +949,101 @@ template <class>
static auto HasRefCountMethodsTest(long) -> std::false_type;
template <class T>
-struct HasRefCountMethods : decltype(HasRefCountMethodsTest<T>(0)) {};
-
-template <typename TWithoutPointer>
-struct NonnsISupportsPointerStorageClass
- : std::conditional<
- std::is_const_v<TWithoutPointer>,
- StoreConstPtrPassByConstPtr<std::remove_const_t<TWithoutPointer>>,
- StorePtrPassByPtr<TWithoutPointer>> {
- using Type = typename NonnsISupportsPointerStorageClass::conditional::type;
+constexpr static bool HasRefCountMethods =
+ decltype(HasRefCountMethodsTest<T>(0))::value;
+
+// Choose storage&passing strategy based on preferred storage type:
+// - If IsParameterStorageClass<T>::value is true, use as-is.
+// - RC* -> StoreRefPtrPassByPtr<RC> :Store RefPtr<RC>, pass RC*
+// ^^ RC quacks like a ref-counted type (i.e., has AddRef and Release methods)
+// - const T* -> StoreConstPtrPassByConstPtr<T> :Store const T*, pass const T*
+// - T* -> StorePtrPassByPtr<T> :Store T*, pass T*.
+// - const T& -> StoreConstRefPassByConstLRef<T>:Store const T&, pass const T&.
+// - T& -> StoreRefPassByLRef<T> :Store T&, pass T&.
+// - T&& -> StoreCopyPassByRRef<T> :Store T, pass std::move(T).
+// - RefPtr<T>, nsCOMPtr<T>
+// -> StoreRefPtrPassByPtr<T> :Store RefPtr<T>, pass T*
+// - Other T -> StoreCopyPassByConstLRef<T> :Store T, pass const T&.
+//
+// For anything less common, please use a lambda function rather than devising
+// new parameter-storage classes. (In fact, consider doing that anyway.)
+
+template <typename T>
+struct OtherParameterStorage;
+
+// The `IsParameterStorageClass` and `RC*` cases must be handled separately (see
+// `ParameterStorageHelper`, below) until we can use C++20 concepts.
+
+template <typename T>
+struct OtherParameterStorage<const T*> {
+ using Type = StoreConstPtrPassByConstPtr<T>;
};
-template <typename TWithoutPointer>
-struct PointerStorageClass
- : std::conditional<
- HasRefCountMethods<TWithoutPointer>::value,
- StoreRefPtrPassByPtr<TWithoutPointer>,
- typename NonnsISupportsPointerStorageClass<TWithoutPointer>::Type> {
- using Type = typename PointerStorageClass::conditional::type;
+template <typename T>
+struct OtherParameterStorage<T*> {
+ using Type = StorePtrPassByPtr<T>;
};
-template <typename TWithoutRef>
-struct LValueReferenceStorageClass
- : std::conditional<
- std::is_const_v<TWithoutRef>,
- StoreConstRefPassByConstLRef<std::remove_const_t<TWithoutRef>>,
- StoreRefPassByLRef<TWithoutRef>> {
- using Type = typename LValueReferenceStorageClass::conditional::type;
+template <typename T>
+struct OtherParameterStorage<const T&> {
+ using Type = StoreConstRefPassByConstLRef<T>;
};
template <typename T>
-struct SmartPointerStorageClass
- : std::conditional<
- mozilla::IsRefcountedSmartPointer<T>::value,
- StoreRefPtrPassByPtr<typename mozilla::RemoveSmartPointer<T>::Type>,
- StoreCopyPassByConstLRef<T>> {
- using Type = typename SmartPointerStorageClass::conditional::type;
+struct OtherParameterStorage<T&> {
+ using Type = StoreRefPassByLRef<T>;
};
template <typename T>
-struct NonLValueReferenceStorageClass
- : std::conditional<std::is_rvalue_reference_v<T>,
- StoreCopyPassByRRef<std::remove_reference_t<T>>,
- typename SmartPointerStorageClass<T>::Type> {
- using Type = typename NonLValueReferenceStorageClass::conditional::type;
+struct OtherParameterStorage<RefPtr<T>> {
+ using Type = StoreRefPtrPassByPtr<T>;
};
template <typename T>
-struct NonPointerStorageClass
- : std::conditional<std::is_lvalue_reference_v<T>,
- typename LValueReferenceStorageClass<
- std::remove_reference_t<T>>::Type,
- typename NonLValueReferenceStorageClass<T>::Type> {
- using Type = typename NonPointerStorageClass::conditional::type;
+struct OtherParameterStorage<nsCOMPtr<T>> {
+ using Type = StoreRefPtrPassByPtr<T>;
};
template <typename T>
-struct NonParameterStorageClass
- : std::conditional<
- std::is_pointer_v<T>,
- typename PointerStorageClass<std::remove_pointer_t<T>>::Type,
- typename NonPointerStorageClass<T>::Type> {
- using Type = typename NonParameterStorageClass::conditional::type;
+struct OtherParameterStorage<T&&> {
+ using Type = StoreCopyPassByRRef<T>;
+};
+
+template <typename T>
+struct OtherParameterStorage<const T&&> {
+ // This is good advice regardless of the types you're handling.
+ static_assert(!SFINAE1True<T>::value, "please use a lambda function");
+};
+
+// default impl.
+template <typename T>
+struct OtherParameterStorage {
+ using Type = StoreCopyPassByConstLRef<T>;
+};
+
+template <typename T, bool A = IsParameterStorageClass<T>::value,
+ bool B = std::is_pointer_v<T> &&
+ HasRefCountMethods<std::remove_pointer_t<T>>>
+struct ParameterStorageHelper;
+
+template <typename T, bool B>
+struct ParameterStorageHelper<T, true, B> {
+ using Type = T;
+};
+
+template <typename T>
+struct ParameterStorageHelper<T, false, true> {
+ using Type = StoreRefPtrPassByPtr<std::remove_pointer_t<T>>;
+};
+
+template <typename T>
+struct ParameterStorageHelper<T, false, false> {
+ using Type = typename OtherParameterStorage<std::remove_cv_t<T>>::Type;
};
-// Choose storage&passing strategy based on preferred storage type:
-// - If IsParameterStorageClass<T>::value is true, use as-is.
-// - RC* -> StoreRefPtrPassByPtr<RC> :Store RefPtr<RC>, pass RC*
-// ^^ RC quacks like a ref-counted type (i.e., has AddRef and Release methods)
-// - const T* -> StoreConstPtrPassByConstPtr<T> :Store const T*, pass const T*
-// - T* -> StorePtrPassByPtr<T> :Store T*, pass T*.
-// - const T& -> StoreConstRefPassByConstLRef<T>:Store const T&, pass const T&.
-// - T& -> StoreRefPassByLRef<T> :Store T&, pass T&.
-// - T&& -> StoreCopyPassByRRef<T> :Store T, pass std::move(T).
-// - RefPtr<T>, nsCOMPtr<T>
-// -> StoreRefPtrPassByPtr<T> :Store RefPtr<T>, pass T*
-// - Other T -> StoreCopyPassByConstLRef<T> :Store T, pass const T&.
-// Other available explicit options:
-// - StoreCopyPassByValue<T> :Store T, pass T.
-// - StoreCopyPassByLRef<T> :Store T, pass T& (of copy!)
-// - StoreCopyPassByConstPtr<T> :Store T, pass const T*
-// - StoreCopyPassByPtr<T> :Store T, pass T* (of copy!)
-// Or create your own class with PassAsParameter() method, optional
-// clean-up in destructor, and with associated IsParameterStorageClass<>.
template <typename T>
-struct ParameterStorage
- : std::conditional<IsParameterStorageClass<T>::value, T,
- typename NonParameterStorageClass<T>::Type> {
- using Type = typename ParameterStorage::conditional::type;
+struct ParameterStorage {
+ using Type = typename ParameterStorageHelper<T>::Type;
};
template <class T>