Skip to content

Commit b3c13bf

Browse files
committed
Bug 1772006 - Part 6: Simplify and move the string searching APIs from ns[T]StringObsolete, r=xpcom-reviewers,necko-reviewers,eeejay,dragana,barret
The biggest set of APIs from ns[T]StringObsolete which are still heavily used are the string searching APIs. It appears the intention was for these to be replaced by the `FindInReadable` APIs, however that doesn't appear to have happened. In addition, the APIs have some quirks around their handling of mixed character widths. These APIs generally supported both narrow strings and the native string type, probably because char16_t string literals weren't available until c++11. Finally they also used easy-to-confuse unlabeled boolean and integer optional arguments to control behaviour. These patches do the following major changes to the searching APIs: 1. The ASCII case-insensitive search method was split out as LowerCaseFindASCII, rather than using a boolean. This should be less error-prone and more explicit, and allows the method to continue to use narrow string literals for all string types (as only ASCII is supported). 2. The other [R]Find methods were restricted to only support arguments with matching character types. I considered adding a FindASCII method which would use narrow string literals for both wide and narrow strings but it would've been the same amount of work as changing all of the literals to unicode literals. This ends up being the bulk of the changes in the patch. 3. All find methods were re-implemented using std::basic_string_view's find algorithm or stl algorithms to reduce code complexity, and avoid the need to carry around the logic from nsStringObsolete.cpp. 4. The implementations were moved to nsTStringRepr.cpp. 5. An overload of Find was added to try to catch callers which previously called `Find(..., false)` or `Find(..., true)` to set case-sensitivity, due to booleans normally implicitly coercing to `index_type`. This should probably be removed at some point, but may be useful during the transition. Differential Revision: https://phabricator.services.mozilla.com/D148300
1 parent 1475267 commit b3c13bf

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+368
-631
lines changed

accessible/base/AccAttributes.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ class AccAttributes {
214214

215215
void NameAsString(nsString& aName) {
216216
mName->ToString(aName);
217-
if (aName.Find("aria-", false, 0, 1) == 0) {
217+
if (StringBeginsWith(aName, u"aria-"_ns)) {
218218
// Found 'aria-'
219219
aName.ReplaceLiteral(0, 5, u"");
220220
}

accessible/mac/AccessibleWrap.mm

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "DocAccessibleWrap.h"
99
#include "nsObjCExceptions.h"
1010
#include "nsCocoaUtils.h"
11+
#include "nsUnicharUtils.h"
1112

1213
#include "LocalAccessible-inl.h"
1314
#include "nsAccUtils.h"
@@ -293,7 +294,7 @@
293294
"Only search text supported");
294295
nsAutoString name;
295296
Name(name);
296-
return name.Find(aSearchText, true) != kNotFound;
297+
return CaseInsensitiveFindInReadable(aSearchText, name);
297298
}
298299

299300
////////////////////////////////////////////////////////////////////////////////

accessible/windows/ia2/ia2Accessible.cpp

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,6 @@
2929
using namespace mozilla;
3030
using namespace mozilla::a11y;
3131

32-
template <typename String>
33-
static void EscapeAttributeChars(String& aStr);
34-
3532
////////////////////////////////////////////////////////////////////////////////
3633
// ia2Accessible
3734
////////////////////////////////////////////////////////////////////////////////
@@ -589,10 +586,9 @@ ia2Accessible::get_selectionRanges(IA2Range** aRanges, long* aNRanges) {
589586
////////////////////////////////////////////////////////////////////////////////
590587
// Helpers
591588

592-
template <typename String>
593-
static inline void EscapeAttributeChars(String& aStr) {
589+
static inline void EscapeAttributeChars(nsString& aStr) {
594590
int32_t offset = 0;
595-
static const char kCharsToEscape[] = ":;=,\\";
591+
static const char16_t kCharsToEscape[] = u":;=,\\";
596592
while ((offset = aStr.FindCharInSet(kCharsToEscape, offset)) != kNotFound) {
597593
aStr.Insert('\\', offset);
598594
offset += 2;

accessible/windows/uia/uiaRawElmProvider.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ uiaRawElmProvider::GetPropertyValue(PROPERTYID aPropertyId,
169169
nsAutoString value;
170170
attribIter.AttrName()->ToString(attribName);
171171
attribIter.AttrValue(attribValue);
172-
if (attribName.Find("aria-", false, 0, 1) == 0) {
172+
if (StringBeginsWith(attribName, u"aria-"_ns)) {
173173
// Found 'aria-'
174174
attribName.ReplaceLiteral(0, 5, u"");
175175
}

accessible/xul/XULMenuAccessible.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -206,12 +206,12 @@ KeyBinding XULMenuitemAccessible::KeyboardShortcut() const {
206206
keyElm->GetAttr(kNameSpaceID_None, nsGkAtoms::modifiers, modifiersStr);
207207

208208
uint32_t modifierMask = 0;
209-
if (modifiersStr.Find("shift") != -1) modifierMask |= KeyBinding::kShift;
210-
if (modifiersStr.Find("alt") != -1) modifierMask |= KeyBinding::kAlt;
211-
if (modifiersStr.Find("meta") != -1) modifierMask |= KeyBinding::kMeta;
212-
if (modifiersStr.Find("os") != -1) modifierMask |= KeyBinding::kOS;
213-
if (modifiersStr.Find("control") != -1) modifierMask |= KeyBinding::kControl;
214-
if (modifiersStr.Find("accel") != -1) {
209+
if (modifiersStr.Find(u"shift") != -1) modifierMask |= KeyBinding::kShift;
210+
if (modifiersStr.Find(u"alt") != -1) modifierMask |= KeyBinding::kAlt;
211+
if (modifiersStr.Find(u"meta") != -1) modifierMask |= KeyBinding::kMeta;
212+
if (modifiersStr.Find(u"os") != -1) modifierMask |= KeyBinding::kOS;
213+
if (modifiersStr.Find(u"control") != -1) modifierMask |= KeyBinding::kControl;
214+
if (modifiersStr.Find(u"accel") != -1) {
215215
modifierMask |= KeyBinding::AccelModifier();
216216
}
217217

dom/base/Document.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10456,8 +10456,8 @@ nsViewportInfo Document::GetViewportInfo(const ScreenIntSize& aDisplaySize) {
1045610456
if (RefPtr<DocumentType> docType = GetDoctype()) {
1045710457
nsAutoString docId;
1045810458
docType->GetPublicId(docId);
10459-
if ((docId.Find("WAP") != -1) || (docId.Find("Mobile") != -1) ||
10460-
(docId.Find("WML") != -1)) {
10459+
if ((docId.Find(u"WAP") != -1) || (docId.Find(u"Mobile") != -1) ||
10460+
(docId.Find(u"WML") != -1)) {
1046110461
// We're making an assumption that the docType can't change here
1046210462
mViewportType = DisplayWidthHeight;
1046310463
return nsViewportInfo(aDisplaySize, defaultScale,

dom/base/nsContentUtils.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10624,7 +10624,7 @@ bool nsContentUtils::IsURIInList(nsIURI* aURI, const nsCString& aList) {
1062410624
ToLowerCase(host);
1062510625

1062610626
for (;;) {
10627-
int32_t index = token.Find(host, false);
10627+
int32_t index = token.Find(host);
1062810628
if (index >= 0 &&
1062910629
static_cast<uint32_t>(index) + host.Length() <= token.Length()) {
1063010630
// If we found a full match, return true.
@@ -10653,7 +10653,7 @@ bool nsContentUtils::IsURIInList(nsIURI* aURI, const nsCString& aList) {
1065310653
}
1065410654
int32_t startIndexOfCurrentLevel = host[0] == '*' ? 1 : 0;
1065510655
int32_t startIndexOfNextLevel =
10656-
host.Find(".", false, startIndexOfCurrentLevel + 1);
10656+
host.Find(".", startIndexOfCurrentLevel + 1);
1065710657
if (startIndexOfNextLevel <= 0) {
1065810658
break;
1065910659
}

dom/cache/QuotaClient.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ Result<UsageInfo, nsresult> CacheQuotaClient::InitOrigin(
281281
// Ignore transient sqlite files and marker files
282282
if (leafName.EqualsLiteral("caches.sqlite-journal") ||
283283
leafName.EqualsLiteral("caches.sqlite-shm") ||
284-
leafName.Find("caches.sqlite-mj"_ns, false, 0, 0) == 0 ||
284+
StringBeginsWith(leafName, u"caches.sqlite-mj"_ns) ||
285285
leafName.EqualsLiteral("context_open.marker")) {
286286
break;
287287
}

dom/l10n/DocumentL10n.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -281,18 +281,18 @@ void DocumentL10n::MaybeRecordTelemetry() {
281281

282282
nsCString key;
283283

284-
if (documentURI.Find("chrome://browser/content/browser.xhtml") == 0) {
284+
if (documentURI.Find(u"chrome://browser/content/browser.xhtml") == 0) {
285285
if (mIsFirstBrowserWindow) {
286286
key = "browser_first_window";
287287
mIsFirstBrowserWindow = false;
288288
} else {
289289
key = "browser_new_window";
290290
}
291-
} else if (documentURI.Find("about:home") == 0) {
291+
} else if (documentURI.Find(u"about:home") == 0) {
292292
key = "about:home";
293-
} else if (documentURI.Find("about:newtab") == 0) {
293+
} else if (documentURI.Find(u"about:newtab") == 0) {
294294
key = "about:newtab";
295-
} else if (documentURI.Find("about:preferences") == 0) {
295+
} else if (documentURI.Find(u"about:preferences") == 0) {
296296
key = "about:preferences";
297297
} else {
298298
return;

dom/media/webrtc/jsapi/PeerConnectionCtx.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,7 @@ static void RecordCommonRtpTelemetry(const T& list, const T& lastList,
322322
const bool isRemote) {
323323
using namespace Telemetry;
324324
for (const auto& s : list) {
325-
const bool isAudio = s.mKind.Value().Find("audio") != -1;
325+
const bool isAudio = s.mKind.Value().Find(u"audio") != -1;
326326
if (s.mPacketsLost.WasPassed() && s.mPacketsReceived.WasPassed()) {
327327
if (const uint64_t total =
328328
s.mPacketsLost.Value() + s.mPacketsReceived.Value()) {
@@ -372,7 +372,7 @@ void PeerConnectionCtx::DeliverStats(
372372
// Record bandwidth telemetry
373373
for (const auto& s : aReport->mInboundRtpStreamStats) {
374374
if (s.mBytesReceived.WasPassed()) {
375-
const bool isAudio = s.mKind.Value().Find("audio") != -1;
375+
const bool isAudio = s.mKind.Value().Find(u"audio") != -1;
376376
for (const auto& lastS : lastReport->mInboundRtpStreamStats) {
377377
if (lastS.mId == s.mId) {
378378
int32_t deltaMs = s.mTimestamp.Value() - lastS.mTimestamp.Value();
@@ -400,7 +400,7 @@ void PeerConnectionCtx::DeliverStats(
400400
lastReport->mRemoteInboundRtpStreamStats, true);
401401
for (const auto& s : aReport->mRemoteInboundRtpStreamStats) {
402402
if (s.mRoundTripTime.WasPassed()) {
403-
const bool isAudio = s.mKind.Value().Find("audio") != -1;
403+
const bool isAudio = s.mKind.Value().Find(u"audio") != -1;
404404
HistogramID id = isAudio ? WEBRTC_AUDIO_QUALITY_OUTBOUND_RTT
405405
: WEBRTC_VIDEO_QUALITY_OUTBOUND_RTT;
406406
Accumulate(id, s.mRoundTripTime.Value() * 1000);

dom/media/webrtc/jsapi/WebrtcGlobalInformation.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -418,8 +418,7 @@ void WebrtcGlobalInformation::GetLogging(
418418

419419
MOZ_ASSERT(XRE_IsParentProcess());
420420

421-
nsAutoCString pattern;
422-
CopyUTF16toUTF8(aPattern, pattern);
421+
nsAutoString pattern(aPattern);
423422

424423
// CallbackObject does not support threadsafe refcounting, and must be
425424
// destroyed on main.
@@ -625,7 +624,7 @@ static void StoreLongTermICEStatisticsImpl_m(RTCStatsReportInternal* report) {
625624
report->mClosed = true;
626625

627626
for (const auto& inboundRtpStats : report->mInboundRtpStreamStats) {
628-
bool isVideo = (inboundRtpStats.mId.Value().Find("video") != -1);
627+
bool isVideo = (inboundRtpStats.mId.Value().Find(u"video") != -1);
629628
if (!isVideo) {
630629
continue;
631630
}

dom/security/nsContentSecurityUtils.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1122,26 +1122,26 @@ void nsContentSecurityUtils::AssertAboutPageHasCSP(Document* aDocument) {
11221122
nsAutoString parsedPolicyStr;
11231123
for (uint32_t i = 0; i < policyCount; ++i) {
11241124
csp->GetPolicyString(i, parsedPolicyStr);
1125-
if (parsedPolicyStr.Find("default-src") >= 0) {
1125+
if (parsedPolicyStr.Find(u"default-src") >= 0) {
11261126
foundDefaultSrc = true;
11271127
}
1128-
if (parsedPolicyStr.Find("object-src 'none'") >= 0) {
1128+
if (parsedPolicyStr.Find(u"object-src 'none'") >= 0) {
11291129
foundObjectSrc = true;
11301130
}
1131-
if (parsedPolicyStr.Find("'unsafe-eval'") >= 0) {
1131+
if (parsedPolicyStr.Find(u"'unsafe-eval'") >= 0) {
11321132
foundUnsafeEval = true;
11331133
}
1134-
if (parsedPolicyStr.Find("'unsafe-inline'") >= 0) {
1134+
if (parsedPolicyStr.Find(u"'unsafe-inline'") >= 0) {
11351135
foundUnsafeInline = true;
11361136
}
1137-
if (parsedPolicyStr.Find("script-src") >= 0) {
1137+
if (parsedPolicyStr.Find(u"script-src") >= 0) {
11381138
foundScriptSrc = true;
11391139
}
1140-
if (parsedPolicyStr.Find("worker-src") >= 0) {
1140+
if (parsedPolicyStr.Find(u"worker-src") >= 0) {
11411141
foundWorkerSrc = true;
11421142
}
1143-
if (parsedPolicyStr.Find("http:") >= 0 ||
1144-
parsedPolicyStr.Find("https:") >= 0) {
1143+
if (parsedPolicyStr.Find(u"http:") >= 0 ||
1144+
parsedPolicyStr.Find(u"https:") >= 0) {
11451145
foundWebScheme = true;
11461146
}
11471147
}

dom/serializers/nsPlainTextSerializer.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -436,7 +436,7 @@ nsPlainTextSerializer::AppendText(nsIContent* aText, int32_t aStartOffset,
436436
// We have to split the string across newlines
437437
// to match parser behavior
438438
int32_t start = 0;
439-
int32_t offset = textstr.FindCharInSet("\n\r");
439+
int32_t offset = textstr.FindCharInSet(u"\n\r");
440440
while (offset != kNotFound) {
441441
if (offset > start) {
442442
// Pass in the line
@@ -447,7 +447,7 @@ nsPlainTextSerializer::AppendText(nsIContent* aText, int32_t aStartOffset,
447447
DoAddText();
448448

449449
start = offset + 1;
450-
offset = textstr.FindCharInSet("\n\r", start);
450+
offset = textstr.FindCharInSet(u"\n\r", start);
451451
}
452452

453453
// Consume the last bit of the string if there's any left
@@ -644,13 +644,13 @@ nsresult nsPlainTextSerializer::DoOpenContainer(const nsAtom* aTag) {
644644
nsAutoString style;
645645
int32_t whitespace;
646646
if (NS_SUCCEEDED(GetAttributeValue(nsGkAtoms::style, style)) &&
647-
(kNotFound != (whitespace = style.Find("white-space:")))) {
648-
if (kNotFound != style.Find("pre-wrap", true, whitespace)) {
647+
(kNotFound != (whitespace = style.Find(u"white-space:")))) {
648+
if (kNotFound != style.LowerCaseFindASCII("pre-wrap", whitespace)) {
649649
#ifdef DEBUG_preformatted
650650
printf("Set mPreFormattedMail based on style pre-wrap\n");
651651
#endif
652652
mPreFormattedMail = true;
653-
} else if (kNotFound != style.Find("pre", true, whitespace)) {
653+
} else if (kNotFound != style.LowerCaseFindASCII("pre", whitespace)) {
654654
#ifdef DEBUG_preformatted
655655
printf("Set mPreFormattedMail based on style pre\n");
656656
#endif
@@ -1583,7 +1583,7 @@ void nsPlainTextSerializer::Write(const nsAString& aStr) {
15831583
int32_t bol = 0;
15841584
while (bol < totLen) { // Loop over lines
15851585
// Find a place where we may have to do whitespace compression
1586-
nextpos = str.FindCharInSet(" \t\n\r", bol);
1586+
nextpos = str.FindCharInSet(u" \t\n\r", bol);
15871587
#ifdef DEBUG_wrapping
15881588
nsAutoString remaining;
15891589
str.Right(remaining, totLen - bol);

dom/webbrowserpersist/nsWebBrowserPersist.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1418,7 +1418,7 @@ nsresult nsWebBrowserPersist::SaveURIInternal(
14181418
const char* kWhitespace = "\b\t\r\n ";
14191419
nsAutoCString extraHeaders(aExtraHeaders);
14201420
while (true) {
1421-
crlf = extraHeaders.Find("\r\n", true);
1421+
crlf = extraHeaders.Find("\r\n");
14221422
if (crlf == -1) break;
14231423
extraHeaders.Mid(oneHeader, 0, crlf);
14241424
extraHeaders.Cut(0, crlf + 2);

dom/xhr/XMLHttpRequestMainThread.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1984,7 +1984,7 @@ XMLHttpRequestMainThread::OnStartRequest(nsIRequest* request) {
19841984
}
19851985
} else if (!(type.EqualsLiteral("text/xml") ||
19861986
type.EqualsLiteral("application/xml") ||
1987-
type.RFind("+xml", true, -1, 4) != kNotFound)) {
1987+
StringEndsWith(type, "+xml"_ns))) {
19881988
// Follow https://xhr.spec.whatwg.org/
19891989
// If final MIME type is not null, text/html, text/xml, application/xml,
19901990
// or does not end in +xml, return null.

editor/libeditor/EditorBase.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5894,9 +5894,9 @@ NS_IMETHODIMP EditorBase::GetWrapWidth(int32_t* aWrapColumn) {
58945894
//
58955895
static void CutStyle(const char* stylename, nsString& styleValue) {
58965896
// Find the current wrapping type:
5897-
int32_t styleStart = styleValue.Find(stylename, true);
5897+
int32_t styleStart = styleValue.LowerCaseFindASCII(stylename);
58985898
if (styleStart >= 0) {
5899-
int32_t styleEnd = styleValue.Find(";", false, styleStart);
5899+
int32_t styleEnd = styleValue.Find(u";", styleStart);
59005900
if (styleEnd > styleStart) {
59015901
styleValue.Cut(styleStart, styleEnd - styleStart + 1);
59025902
} else {

editor/libeditor/HTMLEditSubActionHandler.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1268,13 +1268,12 @@ EditActionResult HTMLEditor::HandleInsertText(
12681268
}
12691269
constexpr auto tabStr = u"\t"_ns;
12701270
constexpr auto spacesStr = u" "_ns;
1271-
char specialChars[] = {TAB, nsCRT::LF, 0};
12721271
nsAutoString insertionString(aInsertionString); // For FindCharInSet().
12731272
while (pos != -1 &&
12741273
pos < AssertedCast<int32_t>(insertionString.Length())) {
12751274
int32_t oldPos = pos;
12761275
int32_t subStrLen;
1277-
pos = insertionString.FindCharInSet(specialChars, oldPos);
1276+
pos = insertionString.FindCharInSet(u"\t\n", oldPos);
12781277

12791278
if (pos != -1) {
12801279
subStrLen = pos - oldPos;

editor/libeditor/HTMLEditorDataTransfer.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1449,14 +1449,14 @@ void RemoveFragComments(nsCString& aStr) {
14491449
// remove the StartFragment/EndFragment comments from the str, if present
14501450
int32_t startCommentIndx = aStr.Find("<!--StartFragment");
14511451
if (startCommentIndx >= 0) {
1452-
int32_t startCommentEnd = aStr.Find("-->", false, startCommentIndx);
1452+
int32_t startCommentEnd = aStr.Find("-->", startCommentIndx);
14531453
if (startCommentEnd > startCommentIndx) {
14541454
aStr.Cut(startCommentIndx, (startCommentEnd + 3) - startCommentIndx);
14551455
}
14561456
}
14571457
int32_t endCommentIndx = aStr.Find("<!--EndFragment");
14581458
if (endCommentIndx >= 0) {
1459-
int32_t endCommentEnd = aStr.Find("-->", false, endCommentIndx);
1459+
int32_t endCommentEnd = aStr.Find("-->", endCommentIndx);
14601460
if (endCommentEnd > endCommentIndx) {
14611461
aStr.Cut(endCommentIndx, (endCommentEnd + 3) - endCommentIndx);
14621462
}

gfx/thebes/gfxPlatform.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2857,7 +2857,7 @@ void gfxPlatform::InitWebGLConfig() {
28572857
// It causes the linking of some shaders to fail. See bug 1485441.
28582858
nsAutoString renderer;
28592859
gfxInfo->GetAdapterDeviceID(renderer);
2860-
if (renderer.Find("Adreno (TM) 630") != -1) {
2860+
if (renderer.Find(u"Adreno (TM) 630") != -1) {
28612861
gfxVars::SetAllowEglRbab(false);
28622862
}
28632863
}

gfx/thebes/gfxPlatformGtk.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -974,10 +974,10 @@ gfxPlatformGtk::CreateGlobalHardwareVsyncSource() {
974974
nsCOMPtr<nsIGfxInfo> gfxInfo = components::GfxInfo::Service();
975975
nsString windowProtocol;
976976
gfxInfo->GetWindowProtocol(windowProtocol);
977-
bool isXwayland = windowProtocol.Find("xwayland") != -1;
977+
bool isXwayland = windowProtocol.Find(u"xwayland") != -1;
978978
nsString adapterDriverVendor;
979979
gfxInfo->GetAdapterDriverVendor(adapterDriverVendor);
980-
bool isMesa = adapterDriverVendor.Find("mesa") != -1;
980+
bool isMesa = adapterDriverVendor.Find(u"mesa") != -1;
981981

982982
// Only use GLX vsync when the OpenGL compositor / WebRender is being used.
983983
// The extra cost of initializing a GLX context while blocking the main thread

0 commit comments

Comments
 (0)