commit 0e183810c4857a2e2b012a3a9de76b8572152944
parent a12d799f5b9b6d96025791ceaf5daa3ffb634c99
Author: agoloman <agoloman@mozilla.com>
Date: Mon, 5 Jan 2026 20:49:07 +0200
Revert "Bug 2008530 - Part 2 - Use `nsGlyphTable::IsUnicodeTable()` instead of raw pointer comparison. r=layout-reviewers,dshin,sergesanspaille" for causing build bustages @nsMathMLChar.cpp.
This reverts commit 7a3c4b556acb00cc3a6f067e0a394d3a7ad898eb.
Revert "Bug 2008530 - Part 1 Statically initialize the MathML unicode table for stretchy operators. r=layout-reviewers,dshin"
This reverts commit 2e216f0f8869446dee03f3d12f233dfdbbe5cfb8.
Revert "Bug 2006706 - Document OOM Handling reality r=jandem"
This reverts commit c96f3ae833a3612015ea23101b651699904b66ae.
Diffstat:
2 files changed, 125 insertions(+), 64 deletions(-)
diff --git a/js/public/Exception.h b/js/public/Exception.h
@@ -31,42 +31,8 @@ enum class ExceptionStackBehavior : bool {
extern JS_PUBLIC_API bool JS_IsExceptionPending(JSContext* cx);
-// [SMDOC] Out Of Memory (OOM) Handling
-//
-// Many functions in SpiderMonkey can throw exceptions, and sometimes
-// the exception thrown is out of memory. Unlike other exceptions,
-// this is not an object, but rather the literal string "out of memory".
-//
-// **Out of Memory handling in SpiderMonkey is best-effort!**
-//
-// While the developers of SpiderMonkey do attempt to convert various scenarios
-// into OutOfMemory calls, such that embedders can attempt to do some sort of
-// recovery, we do not guarantee this in all cases.
-//
-// There are some places where attempting to convey OOM is challenging
-// or where it would leave the engine in a state with invariants
-// no longer holding. In those cases **the process will crash**.
-//
-// An example, though not comprehensive, signal of this to a curious
-// reader would be AutoEnterOOMUnsafeRegion, which flags various
-// places developers have indicated that crashing is better than
-// throwing OOM.
-//
-// Currently we endeavour to always throw out-of-memory when we
-// encounter GC heap limits. We also will sometimes throw OOM
-// exceptions for things which are not really OOM: For example
-// our executable code limits.
-//
-// It is important to not rely on OOM generation in SpiderMonkey
-// as your only reliability measure, as it is not guaranteed.
-
-// Check for pending out of memory exception.
extern JS_PUBLIC_API bool JS_IsThrowingOutOfMemory(JSContext* cx);
-// Try and get the pending exception. This can return false
-// if there is no pending exception -or- if there is a problem
-// attempting to produce the exception (for example if wrapping
-// the exception fails.)
extern JS_PUBLIC_API bool JS_GetPendingException(JSContext* cx,
JS::MutableHandleValue vp);
diff --git a/layout/mathml/nsMathMLChar.cpp b/layout/mathml/nsMathMLChar.cpp
@@ -23,6 +23,7 @@
#include "mozilla/dom/Document.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/intl/UnicodeScriptCodes.h"
+#include "nsCOMPtr.h"
#include "nsCSSRendering.h"
#include "nsContentUtils.h"
#include "nsDeviceContext.h"
@@ -73,7 +74,6 @@ static const nsGlyphCode kNullGlyph = {{0}, false};
class nsGlyphTable {
public:
virtual ~nsGlyphTable() = default;
- virtual bool IsUnicodeTable() const { return false; }
virtual const nsCString& FontNameFor(const nsGlyphCode& aGlyphCode) const = 0;
@@ -97,10 +97,16 @@ class nsGlyphTable {
gfxFontGroup* aFontGroup, const nsGlyphCode& aGlyph) = 0;
protected:
+ nsGlyphTable() : mCharCache(0), mFlags(gfx::ShapedTextFlags()) {}
+ explicit nsGlyphTable(gfx::ShapedTextFlags aFlags)
+ : mCharCache(0), mFlags(aFlags) {}
+
// For speedy re-use, we always cache the last data used in the table.
// mCharCache is the Unicode point of the last char that was queried in this
// table.
- char16_t mCharCache = 0;
+ char16_t mCharCache;
+
+ gfx::ShapedTextFlags mFlags;
};
// A Unicode construction is a set of all the stretchy MathML characters that
@@ -168,12 +174,10 @@ static const UnicodeConstruction gUnicodeTableConstructions[] = {
class nsUnicodeTable final : public nsGlyphTable {
public:
- constexpr nsUnicodeTable() { MOZ_COUNT_CTOR(nsUnicodeTable); }
+ nsUnicodeTable() { MOZ_COUNT_CTOR(nsUnicodeTable); }
MOZ_COUNTED_DTOR(nsUnicodeTable)
- bool IsUnicodeTable() const final { return true; };
-
const nsCString& FontNameFor(const nsGlyphCode& aGlyphCode) const override {
MOZ_ASSERT_UNREACHABLE();
return VoidCString();
@@ -228,11 +232,9 @@ class nsUnicodeTable final : public nsGlyphTable {
: mTarget(aTarget) {}
const char16_t mTarget;
};
- size_t mCachedIndex = 0;
+ size_t mCachedIndex;
};
-static constinit nsUnicodeTable gUnicodeTable;
-
/* virtual */
nsGlyphCode nsUnicodeTable::ElementAt(DrawTarget* /* aDrawTarget */,
int32_t /* aAppUnitsPerDevPixel */,
@@ -270,7 +272,7 @@ already_AddRefed<gfxTextRun> nsUnicodeTable::MakeTextRun(
NS_ASSERTION(!aGlyph.isGlyphID,
"nsUnicodeTable can only access glyphs by code point");
return aFontGroup->MakeTextRun(&aGlyph.code, 1, aDrawTarget,
- aAppUnitsPerDevPixel, gfx::ShapedTextFlags(),
+ aAppUnitsPerDevPixel, mFlags,
nsTextFrameUtils::Flags(), nullptr);
}
@@ -319,13 +321,12 @@ class nsOpenTypeTable final : public nsGlyphTable {
RefPtr<gfxFont> mFont;
nsCString mFontFamilyName;
uint32_t mGlyphID;
- gfx::ShapedTextFlags mFlags;
nsOpenTypeTable(gfxFont* aFont, gfx::ShapedTextFlags aFlags)
- : mFont(aFont),
+ : nsGlyphTable(aFlags),
+ mFont(aFont),
mFontFamilyName(aFont->GetFontEntry()->FamilyName()),
- mGlyphID(0),
- mFlags(aFlags) {
+ mGlyphID(0) {
MOZ_COUNT_CTOR(nsOpenTypeTable);
}
@@ -438,6 +439,96 @@ already_AddRefed<gfxTextRun> nsOpenTypeTable::MakeTextRun(
}
// -----------------------------------------------------------------------------
+// This is the list of all the applicable glyph tables.
+// We will maintain a single global instance that will only reveal those
+// glyph tables that are associated to fonts currently installed on the
+// user' system. The class is an XPCOM shutdown observer to allow us to
+// free its allocated data at shutdown
+
+class nsGlyphTableList final : public nsIObserver {
+ public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIOBSERVER
+
+ nsUnicodeTable mUnicodeTable;
+
+ nsGlyphTableList() {}
+
+ nsresult Initialize();
+ nsresult Finalize();
+
+ private:
+ ~nsGlyphTableList() = default;
+};
+
+NS_IMPL_ISUPPORTS(nsGlyphTableList, nsIObserver)
+
+// -----------------------------------------------------------------------------
+// Here is the global list of applicable glyph tables that we will be using
+static nsGlyphTableList* gGlyphTableList = nullptr;
+
+static bool gGlyphTableInitialized = false;
+
+// XPCOM shutdown observer
+NS_IMETHODIMP
+nsGlyphTableList::Observe(nsISupports* aSubject, const char* aTopic,
+ const char16_t* someData) {
+ Finalize();
+ return NS_OK;
+}
+
+// Add an observer to XPCOM shutdown so that we can free our data at shutdown
+nsresult nsGlyphTableList::Initialize() {
+ nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
+ if (!obs) {
+ return NS_ERROR_FAILURE;
+ }
+
+ nsresult rv = obs->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ return NS_OK;
+}
+
+// Remove our observer and free the memory that were allocated for us
+nsresult nsGlyphTableList::Finalize() {
+ // Remove our observer from the observer service
+ nsresult rv = NS_OK;
+ nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
+ if (obs) {
+ rv = obs->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
+ } else {
+ rv = NS_ERROR_FAILURE;
+ }
+
+ gGlyphTableInitialized = false;
+ // our oneself will be destroyed when our |Release| is called by the observer
+ NS_IF_RELEASE(gGlyphTableList);
+ return rv;
+}
+
+// -----------------------------------------------------------------------------
+
+static nsresult InitCharGlobals() {
+ NS_ASSERTION(!gGlyphTableInitialized, "Error -- already initialized");
+ gGlyphTableInitialized = true;
+
+ // Allocate the placeholders for the preferred parts and variants
+ nsresult rv = NS_ERROR_OUT_OF_MEMORY;
+ auto glyphTableList = MakeRefPtr<nsGlyphTableList>();
+ if (glyphTableList) {
+ rv = glyphTableList->Initialize();
+ }
+ if (NS_FAILED(rv)) {
+ return rv;
+ }
+ // The gGlyphTableList has been successfully registered as a shutdown
+ // observer and will be deleted at shutdown.
+ glyphTableList.forget(&gGlyphTableList);
+ return rv;
+}
+
+// -----------------------------------------------------------------------------
// And now the implementation of nsMathMLChar
nsMathMLChar::~nsMathMLChar() { MOZ_COUNT_DTOR(nsMathMLChar); }
@@ -453,13 +544,16 @@ void nsMathMLChar::SetComputedStyle(ComputedStyle* aComputedStyle) {
}
void nsMathMLChar::SetData(nsString& aData) {
+ if (!gGlyphTableInitialized) {
+ InitCharGlobals();
+ }
mData = aData;
// some assumptions until proven otherwise
// note that mGlyph is not initialized
mDirection = NS_STRETCH_DIRECTION_UNSUPPORTED;
mBoundingMetrics = nsBoundingMetrics();
// check if stretching is applicable ...
- if (1 == mData.Length()) {
+ if (gGlyphTableList && (1 == mData.Length())) {
mDirection = nsMathMLOperators::GetStretchyDirection(mData);
// default tentative table (not the one that is necessarily going
// to be used)
@@ -664,7 +758,7 @@ bool nsMathMLChar::SetFontFamily(nsPresContext* aPresContext,
// Set the font if it is an unicode table or if the same family name has
// been found.
const bool shouldSetFont = [&] {
- if (aGlyphTable && aGlyphTable->IsUnicodeTable()) {
+ if (aGlyphTable == &gGlyphTableList->mUnicodeTable) {
return true;
}
@@ -940,7 +1034,7 @@ bool nsMathMLChar::StretchEnumContext::TryParts(
// For the Unicode table, we check that all the glyphs are actually found and
// come from the same font.
- if (aGlyphTable->IsUnicodeTable()) {
+ if (aGlyphTable == &gGlyphTableList->mUnicodeTable) {
gfxFont* unicodeFont = nullptr;
for (int32_t i = 0; i < 4; i++) {
if (!textRun[i]) {
@@ -1095,20 +1189,20 @@ bool nsMathMLChar::StretchEnumContext::EnumCallback(
// Determine the glyph table to use for this font.
UniquePtr<nsOpenTypeTable> openTypeTable;
- auto glyphTable = [&aFamily, &fontGroup, &openTypeTable,
- &aFlags]() -> nsGlyphTable* {
- if (!aFamily.IsGeneric()) {
- // If the font contains an Open Type MATH table, use it.
- RefPtr<gfxFont> font = fontGroup->GetFirstValidFont();
- openTypeTable = nsOpenTypeTable::Create(font, aFlags);
- if (openTypeTable) {
- return openTypeTable.get();
- }
+ nsGlyphTable* glyphTable;
+ if (aFamily.IsGeneric()) {
+ // This is a generic font, use the Unicode table.
+ glyphTable = &gGlyphTableList->mUnicodeTable;
+ } else {
+ // If the font contains an Open Type MATH table, use it.
+ RefPtr<gfxFont> font = fontGroup->GetFirstValidFont();
+ openTypeTable = nsOpenTypeTable::Create(font, aFlags);
+ if (openTypeTable) {
+ glyphTable = openTypeTable.get();
+ } else {
+ glyphTable = &gGlyphTableList->mUnicodeTable;
}
- // Fallback to the Unicode table.
- return &gUnicodeTable;
- }();
- MOZ_ASSERT(glyphTable);
+ }
if (!openTypeTable) {
// Make sure we only try the UnicodeTable once.
@@ -1122,7 +1216,8 @@ bool nsMathMLChar::StretchEnumContext::EnumCallback(
// special table is being used then the font in this family should have the
// specified glyphs.
const StyleFontFamilyList& familyList =
- glyphTable->IsUnicodeTable() ? context->mFamilyList : family;
+ glyphTable == &gGlyphTableList->mUnicodeTable ? context->mFamilyList
+ : family;
return (context->mTryVariants &&
context->TryVariants(glyphTable, &fontGroup, familyList, aRtl)) ||