diff --git a/layout/style/nsRuleNode.cpp b/layout/style/nsRuleNode.cpp index 6a2c25b4d..b82a94317 100644 --- a/layout/style/nsRuleNode.cpp +++ b/layout/style/nsRuleNode.cpp @@ -1649,9 +1649,10 @@ nsRuleNode::ConvertChildrenToHash(int32_t aNumKids) sizeof(ChildrenHashEntry), aNumKids); for (nsRuleNode* curr = ChildrenList(); curr; curr = curr->mNextSibling) { + Key key = curr->GetKey(); // This will never fail because of the initial size we gave the table. auto entry = - static_cast(hash->Add(curr->mRule, fallible)); + static_cast(hash->Add(&key)); NS_ASSERTION(!entry->mRuleNode, "duplicate entries in list"); entry->mRuleNode = curr; } diff --git a/toolkit/components/places/SQLFunctions.cpp b/toolkit/components/places/SQLFunctions.cpp index 295fee1c5..791bae43b 100644 --- a/toolkit/components/places/SQLFunctions.cpp +++ b/toolkit/components/places/SQLFunctions.cpp @@ -171,6 +171,17 @@ namespace { return false; } + static + MOZ_ALWAYS_INLINE nsDependentCString + getSharedString(mozIStorageValueArray* aValues, uint32_t aIndex) { + uint32_t len; + const char* str = aValues->AsSharedUTF8String(aIndex, &len); + if (!str) { + return nsDependentCString("", (uint32_t)0); + } + return nsDependentCString(str, len); + } + } // End anonymous namespace namespace mozilla { @@ -202,36 +213,40 @@ namespace places { } /* static */ - void - MatchAutoCompleteFunction::fixupURISpec(const nsCString &aURISpec, + nsDependentCSubstring + MatchAutoCompleteFunction::fixupURISpec(const nsACString &aURISpec, int32_t aMatchBehavior, - nsCString &_fixedSpec) + nsACString &aSpecBuf) { - nsCString unescapedSpec; - (void)NS_UnescapeURL(aURISpec, esc_SkipControl | esc_AlwaysCopy, - unescapedSpec); + nsDependentCSubstring fixedSpec; - // If this unescaped string is valid UTF-8, we'll use it. Otherwise, - // we will simply use our original string. - NS_ASSERTION(_fixedSpec.IsEmpty(), - "Passing a non-empty string as an out parameter!"); - if (IsUTF8(unescapedSpec)) - _fixedSpec.Assign(unescapedSpec); - else - _fixedSpec.Assign(aURISpec); + // Try to unescape the string. If that succeeds and yields a different + // string which is also valid UTF-8, we'll use it. + // Otherwise, we will simply use our original string. + bool unescaped = NS_UnescapeURL(aURISpec.BeginReading(), + aURISpec.Length(), esc_SkipControl, aSpecBuf); + if (unescaped && IsUTF8(aSpecBuf)) { + fixedSpec.Rebind(aSpecBuf, 0); + } else { + fixedSpec.Rebind(aURISpec, 0); + } if (aMatchBehavior == mozIPlacesAutoComplete::MATCH_ANYWHERE_UNMODIFIED) - return; + return fixedSpec; - if (StringBeginsWith(_fixedSpec, NS_LITERAL_CSTRING("http://"))) - _fixedSpec.Cut(0, 7); - else if (StringBeginsWith(_fixedSpec, NS_LITERAL_CSTRING("https://"))) - _fixedSpec.Cut(0, 8); - else if (StringBeginsWith(_fixedSpec, NS_LITERAL_CSTRING("ftp://"))) - _fixedSpec.Cut(0, 6); + if (StringBeginsWith(fixedSpec, NS_LITERAL_CSTRING("http://"))) { + fixedSpec.Rebind(fixedSpec, 7); + } else if (StringBeginsWith(fixedSpec, NS_LITERAL_CSTRING("https://"))) { + fixedSpec.Rebind(fixedSpec, 8); + } else if (StringBeginsWith(fixedSpec, NS_LITERAL_CSTRING("ftp://"))) { + fixedSpec.Rebind(fixedSpec, 6); + } - if (StringBeginsWith(_fixedSpec, NS_LITERAL_CSTRING("www."))) - _fixedSpec.Cut(0, 4); + if (StringBeginsWith(fixedSpec, NS_LITERAL_CSTRING("www."))) { + fixedSpec.Rebind(fixedSpec, 4); + } + + return fixedSpec; } /* static */ @@ -337,19 +352,19 @@ namespace places { #define HAS_BEHAVIOR(aBitName) \ (searchBehavior & mozIPlacesAutoComplete::BEHAVIOR_##aBitName) - nsAutoCString searchString; - (void)aArguments->GetUTF8String(kArgSearchString, searchString); - nsCString url; - (void)aArguments->GetUTF8String(kArgIndexURL, url); + nsDependentCString searchString = + getSharedString(aArguments, kArgSearchString); + nsDependentCString url = + getSharedString(aArguments, kArgIndexURL); int32_t matchBehavior = aArguments->AsInt32(kArgIndexMatchBehavior); // We only want to filter javascript: URLs if we are not supposed to search // for them, and the search does not start with "javascript:". if (matchBehavior != mozIPlacesAutoComplete::MATCH_ANYWHERE_UNMODIFIED && + StringBeginsWith(url, NS_LITERAL_CSTRING("javascript:")) && !HAS_BEHAVIOR(JAVASCRIPT) && - !StringBeginsWith(searchString, NS_LITERAL_CSTRING("javascript:")) && - StringBeginsWith(url, NS_LITERAL_CSTRING("javascript:"))) { + !StringBeginsWith(searchString, NS_LITERAL_CSTRING("javascript:"))) { NS_ADDREF(*_result = new IntegerVariant(0)); return NS_OK; } @@ -357,8 +372,7 @@ namespace places { int32_t visitCount = aArguments->AsInt32(kArgIndexVisitCount); bool typed = aArguments->AsInt32(kArgIndexTyped) ? true : false; bool bookmark = aArguments->AsInt32(kArgIndexBookmark) ? true : false; - nsAutoCString tags; - (void)aArguments->GetUTF8String(kArgIndexTags, tags); + nsDependentCString tags = getSharedString(aArguments, kArgIndexTags); int32_t openPageCount = aArguments->AsInt32(kArgIndexOpenPageCount); bool matches = false; if (HAS_BEHAVIOR(RESTRICT)) { @@ -388,11 +402,11 @@ namespace places { searchFunctionPtr searchFunction = getSearchFunction(matchBehavior); // Clean up our URI spec and prepare it for searching. - nsCString fixedURI; - fixupURISpec(url, matchBehavior, fixedURI); + nsCString fixedUrlBuf; + nsDependentCSubstring fixedURI = + fixupURISpec(url, matchBehavior, fixedUrlBuf); - nsAutoCString title; - (void)aArguments->GetUTF8String(kArgIndexTitle, title); + nsDependentCString title = getSharedString(aArguments, kArgIndexTitle); // Determine if every token matches either the bookmark title, tags, page // title, or page URL. diff --git a/toolkit/components/places/SQLFunctions.h b/toolkit/components/places/SQLFunctions.h index f7619bf63..f3485075e 100644 --- a/toolkit/components/places/SQLFunctions.h +++ b/toolkit/components/places/SQLFunctions.h @@ -166,11 +166,13 @@ private: * @param aMatchBehavior * The matching behavior to use defined by one of the * mozIPlacesAutoComplete::MATCH_* values. - * @param _fixedSpec - * An out parameter that is the fixed up string. + * @param aSpecBuf + * A string buffer that the returned slice can point into, if needed. + * @return the fixed up string. */ - static void fixupURISpec(const nsCString &aURISpec, int32_t aMatchBehavior, - nsCString &_fixedSpec); + static nsDependentCSubstring fixupURISpec(const nsACString &aURISpec, + int32_t aMatchBehavior, + nsACString &aSpecBuf); }; diff --git a/toolkit/components/places/UnifiedComplete.js b/toolkit/components/places/UnifiedComplete.js index c4296c30e..29aeb197a 100644 --- a/toolkit/components/places/UnifiedComplete.js +++ b/toolkit/components/places/UnifiedComplete.js @@ -112,6 +112,8 @@ const SQL_BOOKMARK_TAGS_FRAGMENT = // TODO bug 412736: in case of a frecency tie, we might break it with h.typed // and h.visit_count. That is slower though, so not doing it yet... +// NB: as a slight performance optimization, we only evaluate the "btitle" +// and "tags" queries for bookmarked entries. function defaultQuery(conditions = "") { let query = `SELECT :query_type, h.url, h.title, f.url, ${SQL_BOOKMARK_TAGS_FRAGMENT}, @@ -121,7 +123,12 @@ function defaultQuery(conditions = "") { LEFT JOIN moz_openpages_temp t ON t.url = h.url WHERE h.frecency <> 0 AND AUTOCOMPLETE_MATCH(:searchString, h.url, - IFNULL(btitle, h.title), tags, + CASE WHEN bookmarked THEN + IFNULL(btitle, h.title) + ELSE h.title END, + CASE WHEN bookmarked THEN + tags + ELSE '' END, h.visit_count, h.typed, bookmarked, t.open_count, :matchBehavior, :searchBehavior) diff --git a/xpcom/ds/nsAtomTable.cpp b/xpcom/ds/nsAtomTable.cpp index ae8f61f91..55e9e3a22 100644 --- a/xpcom/ds/nsAtomTable.cpp +++ b/xpcom/ds/nsAtomTable.cpp @@ -654,7 +654,7 @@ NS_NewAtom(const char16_t* aUTF16String) return NS_NewAtom(nsDependentString(aUTF16String)); } -// Equivalent to current NS_Atomize and called by NS_AtomizeMainThread. +// Equivalent to current NS_Atomize. // Left as such for legacy callers in our older 45-era codebase. already_AddRefed NS_NewAtom(const nsAString& aUTF16String) @@ -680,6 +680,7 @@ NS_NewAtom(const nsAString& aUTF16String) already_AddRefed NS_AtomizeMainThread(const nsAString& aUTF16String) { +#if(0) MOZ_ASSERT(NS_IsMainThread()); nsCOMPtr retVal; uint32_t hash; @@ -687,7 +688,7 @@ NS_AtomizeMainThread(const nsAString& aUTF16String) uint32_t index = hash % RECENTLY_USED_MAIN_THREAD_ATOM_CACHE_SIZE; nsIAtom* atom = sRecentlyUsedMainThreadAtoms[index]; - if (atom) { + if (atom && atom->GetUTF16String()) { // wallpaper // This isn't ideal, but covers for the collision case, I guess. // The atom names shouldn't be very long in any event. uint32_t length = atom->GetLength(); @@ -711,6 +712,9 @@ NS_AtomizeMainThread(const nsAString& aUTF16String) sRecentlyUsedMainThreadAtoms[index] = retVal; return retVal.forget(); +#else + return NS_NewAtom(aUTF16String); +#endif } nsIAtom* diff --git a/xpcom/io/nsEscape.cpp b/xpcom/io/nsEscape.cpp index f099a8ca1..25d851175 100644 --- a/xpcom/io/nsEscape.cpp +++ b/xpcom/io/nsEscape.cpp @@ -540,6 +540,9 @@ NS_UnescapeURL(const char* aStr, int32_t aLen, uint32_t aFlags, return false; } + MOZ_ASSERT(aResult.IsEmpty(), + "Passing a non-empty string as an out parameter!"); + if (aLen < 0) { aLen = strlen(aStr); } @@ -550,6 +553,10 @@ NS_UnescapeURL(const char* aStr, int32_t aLen, uint32_t aFlags, bool skipControl = !!(aFlags & esc_SkipControl); bool skipInvalidHostChar = !!(aFlags & esc_Host); + if (writing) { + aResult.SetCapacity(aLen); + } + const char* last = aStr; const char* p = aStr; @@ -563,7 +570,10 @@ NS_UnescapeURL(const char* aStr, int32_t aLen, uint32_t aFlags, ((c1 < '8' && !ignoreAscii) || (c1 >= '8' && !ignoreNonAscii)) && !(skipControl && (c1 < '2' || (c1 == '7' && (c2 == 'f' || c2 == 'F'))))) { - writing = true; + if (!writing) { + writing = true; + aResult.SetCapacity(aLen); + } if (p > last) { aResult.Append(last, p - last); last = p;