diff --git a/Source/JavaScriptCore/API/OpaqueJSString.cpp b/Source/JavaScriptCore/API/OpaqueJSString.cpp index 252f14d8deb0..4b04db4997ba 100644 --- a/Source/JavaScriptCore/API/OpaqueJSString.cpp +++ b/Source/JavaScriptCore/API/OpaqueJSString.cpp @@ -91,9 +91,8 @@ const UChar* OpaqueJSString::characters() if (m_string.isNull()) return nullptr; - unsigned length = m_string.length(); - UChar* newCharacters = static_cast(fastMalloc(length * sizeof(UChar))); - StringView(m_string).getCharactersWithUpconvert(newCharacters); + UChar* newCharacters = static_cast(fastMalloc(m_string.length() * sizeof(UChar))); + StringView { m_string }.getCharacters(newCharacters); if (!m_characters.compare_exchange_strong(characters, newCharacters)) { fastFree(newCharacters); diff --git a/Source/JavaScriptCore/jit/ExecutableAllocationFuzz.cpp b/Source/JavaScriptCore/jit/ExecutableAllocationFuzz.cpp index 6d486e511e7d..9eb8a6d37ae8 100644 --- a/Source/JavaScriptCore/jit/ExecutableAllocationFuzz.cpp +++ b/Source/JavaScriptCore/jit/ExecutableAllocationFuzz.cpp @@ -29,6 +29,7 @@ #include "TestRunnerUtils.h" #include #include +#include #include namespace JSC { diff --git a/Source/JavaScriptCore/parser/Lexer.cpp b/Source/JavaScriptCore/parser/Lexer.cpp index be1403897ea8..55983aeb0257 100644 --- a/Source/JavaScriptCore/parser/Lexer.cpp +++ b/Source/JavaScriptCore/parser/Lexer.cpp @@ -1839,35 +1839,27 @@ ALWAYS_INLINE void Lexer::parseCommentDirective() } } -template -ALWAYS_INLINE String Lexer::parseCommentDirectiveValue() +template ALWAYS_INLINE String Lexer::parseCommentDirectiveValue() { skipWhitespace(); - bool hasNonLatin1 = false; - const T* stringStart = currentSourcePtr(); + UChar mergedCharacterBits = 0; + auto stringStart = currentSourcePtr(); while (!isWhiteSpace(m_current) && !isLineTerminator(m_current) && m_current != '"' && m_current != '\'' && !atEnd()) { - if (!isLatin1(m_current)) - hasNonLatin1 = true; + if constexpr (std::is_same_v) + mergedCharacterBits |= m_current; shift(); } - const T* stringEnd = currentSourcePtr(); - skipWhitespace(); + unsigned length = currentSourcePtr() - stringStart; + skipWhitespace(); if (!isLineTerminator(m_current) && !atEnd()) return String(); - unsigned length = stringEnd - stringStart; - if (hasNonLatin1) { - UChar* buffer = nullptr; - String result = StringImpl::createUninitialized(length, buffer); - StringImpl::copyCharacters(buffer, stringStart, length); - return result; + if constexpr (std::is_same_v) { + if (isLatin1(mergedCharacterBits)) + return String::make8Bit(stringStart, length); } - - LChar* buffer = nullptr; - String result = StringImpl::createUninitialized(length, buffer); - StringImpl::copyCharacters(buffer, stringStart, length); - return result; + return { stringStart, length }; } template diff --git a/Source/JavaScriptCore/runtime/IntlLocale.cpp b/Source/JavaScriptCore/runtime/IntlLocale.cpp index c06f2200fe20..c3c346163a18 100644 --- a/Source/JavaScriptCore/runtime/IntlLocale.cpp +++ b/Source/JavaScriptCore/runtime/IntlLocale.cpp @@ -185,10 +185,7 @@ void LocaleIDBuilder::setKeywordValue(ASCIILiteral key, StringView value) ASSERT(value.isAllASCII()); Vector rawValue(value.length() + 1); - if (value.is8Bit()) - StringImpl::copyCharacters(reinterpret_cast(rawValue.data()), value.characters8(), value.length()); - else - StringImpl::copyCharacters(reinterpret_cast(rawValue.data()), value.characters16(), value.length()); + value.getCharacters(reinterpret_cast(rawValue.data())); rawValue[value.length()] = '\0'; UErrorCode status = U_ZERO_ERROR; diff --git a/Source/JavaScriptCore/runtime/IntlObjectInlines.h b/Source/JavaScriptCore/runtime/IntlObjectInlines.h index 30784c6aac07..3e54733c4619 100644 --- a/Source/JavaScriptCore/runtime/IntlObjectInlines.h +++ b/Source/JavaScriptCore/runtime/IntlObjectInlines.h @@ -314,14 +314,8 @@ class ListFormatInput { m_stringPointers.reserveInitialCapacity(m_strings.size()); m_stringLengths.reserveInitialCapacity(m_strings.size()); for (auto& string : m_strings) { - if (string.is8Bit()) { - auto vector = makeUnique>(); - vector->resize(string.length()); - StringImpl::copyCharacters(vector->data(), string.characters8(), string.length()); - m_retainedUpconvertedStrings.append(WTFMove(vector)); - m_stringPointers.append(m_retainedUpconvertedStrings.last()->data()); - } else - m_stringPointers.append(string.characters16()); + string.convertTo16Bit(); + m_stringPointers.append(string.characters16()); m_stringLengths.append(string.length()); } } @@ -332,7 +326,6 @@ class ListFormatInput { private: Vector m_strings; - Vector>, 4> m_retainedUpconvertedStrings; Vector m_stringPointers; Vector m_stringLengths; }; diff --git a/Source/JavaScriptCore/runtime/JSString.cpp b/Source/JavaScriptCore/runtime/JSString.cpp index 4db36b91bc13..da8ff371722b 100644 --- a/Source/JavaScriptCore/runtime/JSString.cpp +++ b/Source/JavaScriptCore/runtime/JSString.cpp @@ -145,16 +145,12 @@ template void JSRopeString::resolveRopeInternal(CharacterType* buffer) const { if (isSubstring()) { - // It is possible that underlying string becomes 8bit/16bit while wrapper substring is saying it is 16bit/8bit. - // But It is definitely true that substring part can be represented as its parent's status 8bit/16bit, which is described as CharacterType. - auto& string = substringBase()->valueInternal(); - if (string.is8Bit()) - StringImpl::copyCharacters(buffer, string.characters8() + substringOffset(), length()); - else - StringImpl::copyCharacters(buffer, string.characters16() + substringOffset(), length()); + // It is possible underlying string is now 8-bit/16-bit even if wrapper substring says it is 16-bit/8-bit. + // But it's guaranteed substring characters can be represented in parent rope's character width, passed as CharacterType. + StringView { substringBase()->valueInternal() }.substring(substringOffset(), length()).getCharacters(buffer); return; } - + resolveRopeInternalNoSubstring(buffer); } @@ -170,13 +166,9 @@ void JSRopeString::resolveRopeInternalNoSubstring(CharacterType* buffer) const CharacterType* position = buffer; for (size_t i = 0; i < s_maxInternalRopeLength && fiber(i); ++i) { - const StringImpl& fiberString = *fiber(i)->valueInternal().impl(); - unsigned length = fiberString.length(); - if (fiberString.is8Bit()) - StringImpl::copyCharacters(position, fiberString.characters8(), length); - else - StringImpl::copyCharacters(position, fiberString.characters16(), length); - position += length; + StringView view = *fiber(i)->valueInternal().impl(); + view.getCharacters(position); + position += view.length(); } ASSERT((buffer + length()) == position); } @@ -336,15 +328,11 @@ void JSRopeString::resolveRopeSlowCase(CharacterType* buffer) const JSRopeString* currentFiberAsRope = static_cast(currentFiber); if (currentFiberAsRope->isSubstring()) { ASSERT(!currentFiberAsRope->substringBase()->isRope()); - StringImpl* string = static_cast( - currentFiberAsRope->substringBase()->valueInternal().impl()); + StringView view = *currentFiberAsRope->substringBase()->valueInternal().impl(); unsigned offset = currentFiberAsRope->substringOffset(); unsigned length = currentFiberAsRope->length(); position -= length; - if (string->is8Bit()) - StringImpl::copyCharacters(position, string->characters8() + offset, length); - else - StringImpl::copyCharacters(position, string->characters16() + offset, length); + view.substring(offset, length).getCharacters(position); continue; } for (size_t i = 0; i < s_maxInternalRopeLength && currentFiberAsRope->fiber(i); ++i) @@ -352,13 +340,9 @@ void JSRopeString::resolveRopeSlowCase(CharacterType* buffer) const continue; } - StringImpl* string = static_cast(currentFiber->valueInternal().impl()); - unsigned length = string->length(); - position -= length; - if (string->is8Bit()) - StringImpl::copyCharacters(position, string->characters8(), length); - else - StringImpl::copyCharacters(position, string->characters16(), length); + StringView view = *currentFiber->valueInternal().impl(); + position -= view.length(); + view.getCharacters(position); } ASSERT(buffer == position); diff --git a/Source/JavaScriptCore/runtime/JSStringJoiner.cpp b/Source/JavaScriptCore/runtime/JSStringJoiner.cpp index eed9134ae737..0970e0a36d17 100644 --- a/Source/JavaScriptCore/runtime/JSStringJoiner.cpp +++ b/Source/JavaScriptCore/runtime/JSStringJoiner.cpp @@ -37,7 +37,7 @@ JSStringJoiner::~JSStringJoiner() template static inline void appendStringToData(CharacterType*& data, StringView string) { - string.getCharactersWithUpconvert(data); + string.getCharacters(data); data += string.length(); } diff --git a/Source/JavaScriptCore/runtime/StringPrototype.cpp b/Source/JavaScriptCore/runtime/StringPrototype.cpp index cedd58a09d46..121067a3f227 100644 --- a/Source/JavaScriptCore/runtime/StringPrototype.cpp +++ b/Source/JavaScriptCore/runtime/StringPrototype.cpp @@ -313,10 +313,9 @@ static ALWAYS_INLINE JSString* jsSpliceSubstrings(JSGlobalObject* globalObject, Checked bufferPos = 0; for (int i = 0; i < rangeCount; i++) { - if (int srcLen = substringRanges[i].distance()) { - StringImpl::copyCharacters(buffer + bufferPos.value(), sourceData + substringRanges[i].begin(), srcLen); - bufferPos += srcLen; - } + int srcLen = substringRanges[i].distance(); + StringImpl::copyCharacters(buffer + bufferPos.value(), sourceData + substringRanges[i].begin(), srcLen); + bufferPos += srcLen; } RELEASE_AND_RETURN(scope, jsString(vm, impl.releaseNonNull())); @@ -333,10 +332,9 @@ static ALWAYS_INLINE JSString* jsSpliceSubstrings(JSGlobalObject* globalObject, Checked bufferPos = 0; for (int i = 0; i < rangeCount; i++) { - if (int srcLen = substringRanges[i].distance()) { - StringImpl::copyCharacters(buffer + bufferPos.value(), sourceData + substringRanges[i].begin(), srcLen); - bufferPos += srcLen; - } + int srcLen = substringRanges[i].distance(); + StringImpl::copyCharacters(buffer + bufferPos.value(), sourceData + substringRanges[i].begin(), srcLen); + bufferPos += srcLen; } RELEASE_AND_RETURN(scope, jsString(vm, impl.releaseNonNull())); diff --git a/Source/JavaScriptCore/runtime/StringPrototypeInlines.h b/Source/JavaScriptCore/runtime/StringPrototypeInlines.h index f718b5853d4a..252529950970 100644 --- a/Source/JavaScriptCore/runtime/StringPrototypeInlines.h +++ b/Source/JavaScriptCore/runtime/StringPrototypeInlines.h @@ -138,8 +138,6 @@ ALWAYS_INLINE JSString* jsSpliceSubstringsWithSeparators(JSGlobalObject* globalO if (source.is8Bit() && allSeparators8Bit) { LChar* buffer; - const LChar* sourceData = source.characters8(); - auto impl = StringImpl::tryCreateUninitialized(totalLength, buffer); if (!impl) { throwOutOfMemoryError(globalObject, scope); @@ -150,16 +148,14 @@ ALWAYS_INLINE JSString* jsSpliceSubstringsWithSeparators(JSGlobalObject* globalO Checked bufferPos = 0; for (int i = 0; i < maxCount; i++) { if (i < rangeCount) { - if (int srcLen = substringRanges[i].distance()) { - StringImpl::copyCharacters(buffer + bufferPos.value(), sourceData + substringRanges[i].begin(), srcLen); - bufferPos += srcLen; - } + auto substring = StringView { source }.substring(substringRanges[i].begin(), substringRanges[i].distance()); + substring.getCharacters8(buffer + bufferPos.value()); + bufferPos += substring.length(); } if (i < separatorCount) { - if (int sepLen = separators[i].length()) { - StringImpl::copyCharacters(buffer + bufferPos.value(), separators[i].characters8(), sepLen); - bufferPos += sepLen; - } + StringView separator = separators[i]; + separator.getCharacters8(buffer + bufferPos.value()); + bufferPos += separator.length(); } } @@ -177,22 +173,14 @@ ALWAYS_INLINE JSString* jsSpliceSubstringsWithSeparators(JSGlobalObject* globalO Checked bufferPos = 0; for (int i = 0; i < maxCount; i++) { if (i < rangeCount) { - if (int srcLen = substringRanges[i].distance()) { - if (source.is8Bit()) - StringImpl::copyCharacters(buffer + bufferPos.value(), source.characters8() + substringRanges[i].begin(), srcLen); - else - StringImpl::copyCharacters(buffer + bufferPos.value(), source.characters16() + substringRanges[i].begin(), srcLen); - bufferPos += srcLen; - } + auto substring = StringView { source }.substring(substringRanges[i].begin(), substringRanges[i].distance()); + substring.getCharacters(buffer + bufferPos.value()); + bufferPos += substring.length(); } if (i < separatorCount) { - if (int sepLen = separators[i].length()) { - if (separators[i].is8Bit()) - StringImpl::copyCharacters(buffer + bufferPos.value(), separators[i].characters8(), sepLen); - else - StringImpl::copyCharacters(buffer + bufferPos.value(), separators[i].characters16(), sepLen); - bufferPos += sepLen; - } + StringView separator = separators[i]; + separator.getCharacters(buffer + bufferPos.value()); + bufferPos += separator.length(); } } diff --git a/Source/JavaScriptCore/tools/JSDollarVM.cpp b/Source/JavaScriptCore/tools/JSDollarVM.cpp index 3dbd38870a33..4accd11ced7f 100644 --- a/Source/JavaScriptCore/tools/JSDollarVM.cpp +++ b/Source/JavaScriptCore/tools/JSDollarVM.cpp @@ -3640,12 +3640,8 @@ JSC_DEFINE_HOST_FUNCTION(functionMake16BitStringIfPossible, (JSGlobalObject* glo auto scope = DECLARE_THROW_SCOPE(vm); String string = callFrame->argument(0).toWTFString(globalObject); RETURN_IF_EXCEPTION(scope, { }); - if (!string.is8Bit()) - return JSValue::encode(jsString(vm, WTFMove(string))); - Vector buffer; - buffer.resize(string.length()); - StringImpl::copyCharacters(buffer.data(), string.characters8(), string.length()); - return JSValue::encode(jsString(vm, String::adopt(WTFMove(buffer)))); + string.convertTo16Bit(); + return JSValue::encode(jsString(vm, WTFMove(string))); } JSC_DEFINE_HOST_FUNCTION(functionGetStructureTransitionList, (JSGlobalObject* globalObject, CallFrame* callFrame)) diff --git a/Source/WTF/wtf/DateMath.cpp b/Source/WTF/wtf/DateMath.cpp index 36ff56dac6fc..47e1985ba014 100644 --- a/Source/WTF/wtf/DateMath.cpp +++ b/Source/WTF/wtf/DateMath.cpp @@ -1039,11 +1039,10 @@ String makeRFC2822DateString(unsigned dayOfWeek, unsigned day, unsigned month, u static std::optional> validateTimeZone(StringView timeZone) { - Vector buffer(timeZone.length()); - timeZone.getCharactersWithUpconvert(buffer.data()); - + auto buffer = timeZone.upconvertedCharacters(); + const UChar* characters = buffer; Vector canonicalBuffer; - auto status = callBufferProducingFunction(ucal_getCanonicalTimeZoneID, buffer.data(), buffer.size(), canonicalBuffer, nullptr); + auto status = callBufferProducingFunction(ucal_getCanonicalTimeZoneID, characters, timeZone.length(), canonicalBuffer, nullptr); if (!U_SUCCESS(status)) return std::nullopt; return canonicalBuffer; diff --git a/Source/WTF/wtf/LogInitialization.cpp b/Source/WTF/wtf/LogInitialization.cpp index 0508873a20a6..b353c3f8ba8d 100644 --- a/Source/WTF/wtf/LogInitialization.cpp +++ b/Source/WTF/wtf/LogInitialization.cpp @@ -28,6 +28,7 @@ #include #include +#include namespace WTF { diff --git a/Source/WTF/wtf/Logger.cpp b/Source/WTF/wtf/Logger.cpp index c8d86c045a35..29d8595cce2b 100644 --- a/Source/WTF/wtf/Logger.cpp +++ b/Source/WTF/wtf/Logger.cpp @@ -28,6 +28,7 @@ #include #include +#include #include namespace WTF { diff --git a/Source/WTF/wtf/SortedArrayMap.h b/Source/WTF/wtf/SortedArrayMap.h index df00e1c562d5..eac490d74682 100644 --- a/Source/WTF/wtf/SortedArrayMap.h +++ b/Source/WTF/wtf/SortedArrayMap.h @@ -76,6 +76,10 @@ struct ComparableStringView { StringView string; }; +template struct SortedArrayKeyTraits { + static std::optional parse(const SortedArrayKeyType& key) { return key; } +}; + // NoUppercaseLettersOptimized means no characters with the 0x20 bit set. // That means the strings can't include control characters, uppercase letters, or any of @[\]_. enum class ASCIISubset : uint8_t { All, NoUppercaseLetters, NoUppercaseLettersOptimized }; @@ -83,16 +87,15 @@ enum class ASCIISubset : uint8_t { All, NoUppercaseLetters, NoUppercaseLettersOp template struct ComparableASCIISubsetLiteral { ASCIILiteral literal; template constexpr ComparableASCIISubsetLiteral(const char (&characters)[size]); - static std::optional parse(StringView string) { return { { string } }; } }; +template constexpr bool operator==(ComparableASCIISubsetLiteral, ComparableASCIISubsetLiteral); +template constexpr bool operator<(ComparableASCIISubsetLiteral, ComparableASCIISubsetLiteral); + using ComparableASCIILiteral = ComparableASCIISubsetLiteral; using ComparableCaseFoldingASCIILiteral = ComparableASCIISubsetLiteral; using ComparableLettersLiteral = ComparableASCIISubsetLiteral; -template constexpr bool operator==(ComparableASCIISubsetLiteral, ComparableASCIISubsetLiteral); -template constexpr bool operator<(ComparableASCIISubsetLiteral, ComparableASCIISubsetLiteral); - bool operator==(ComparableStringView, ComparableASCIILiteral); bool operator==(ComparableStringView, ComparableCaseFoldingASCIILiteral); bool operator==(ComparableStringView, ComparableLettersLiteral); @@ -105,22 +108,27 @@ bool operator<(ComparableLettersLiteral, ComparableStringView); template bool operator==(OtherType, ComparableStringView); -template class PackedASCIILowerCodes { +template class PackedASCIISubsetLiteral { public: static_assert(std::is_unsigned_v); - template constexpr PackedASCIILowerCodes(const char (&characters)[size]); - static std::optional parse(StringView); + template constexpr PackedASCIISubsetLiteral(const char (&characters)[size]); constexpr StorageInteger value() const { return m_value; } + template static std::optional parse(Span); + private: template static constexpr StorageInteger pack(const char (&characters)[size]); - explicit constexpr PackedASCIILowerCodes(StorageInteger); + explicit constexpr PackedASCIISubsetLiteral(StorageInteger); StorageInteger m_value { 0 }; }; -template constexpr bool operator==(PackedASCIILowerCodes, PackedASCIILowerCodes); -template constexpr bool operator<(PackedASCIILowerCodes, PackedASCIILowerCodes); +template constexpr bool operator==(PackedASCIISubsetLiteral, PackedASCIISubsetLiteral); +template constexpr bool operator<(PackedASCIISubsetLiteral, PackedASCIISubsetLiteral); + +template using PackedASCIILiteral = PackedASCIISubsetLiteral; +template using PackedASCIILowerCodes = PackedASCIISubsetLiteral; +template using PackedLettersLiteral = PackedASCIISubsetLiteral; template constexpr bool isInSubset(char character) { @@ -136,6 +144,18 @@ template constexpr bool isInSubset(char character) } } +template constexpr std::make_unsigned_t foldForComparison(CharacterType character) +{ + switch (subset) { + case ASCIISubset::All: + return character; + case ASCIISubset::NoUppercaseLetters: + return toASCIILower(character); + case ASCIISubset::NoUppercaseLettersOptimized: + return toASCIILowerUnchecked(character); + } +} + template template constexpr ComparableASCIISubsetLiteral::ComparableASCIISubsetLiteral(const char (&characters)[size]) : literal { ASCIILiteral::fromLiteralUnsafe(characters) } { @@ -153,18 +173,10 @@ template constexpr SortedArrayMap::SortedArrayMap })); } -template constexpr bool HasParseMember = false; -template constexpr bool HasParseMember().parse)>> = true; - template template inline auto SortedArrayMap::tryGet(const KeyArgument& key) const -> const ValueType* { using KeyType = typename ElementType::first_type; - auto parsedKey = [&key] { - if constexpr (HasParseMember) - return KeyType::parse(key); - else - return std::make_optional(key); - }(); + auto parsedKey = SortedArrayKeyTraits::parse(key); if (!parsedKey) return nullptr; decltype(std::begin(m_array)) iterator; @@ -204,12 +216,7 @@ template constexpr SortedArraySet::SortedArraySet template template inline bool SortedArraySet::contains(const KeyArgument& key) const { using KeyType = typename std::remove_extent_t; - auto parsedKey = [&key] { - if constexpr (HasParseMember) - return KeyType::parse(key); - else - return std::make_optional(key); - }(); + auto parsedKey = SortedArrayKeyTraits::parse(key); if (!parsedKey) return false; if (std::size(m_array) < binarySearchThreshold) @@ -323,17 +330,17 @@ template inline bool operator==(OtherType a, ComparableStrin return b == a; } -template template constexpr PackedASCIILowerCodes::PackedASCIILowerCodes(const char (&string)[size]) +template template constexpr PackedASCIISubsetLiteral::PackedASCIISubsetLiteral(const char (&string)[size]) : m_value { pack(string) } { } -template constexpr PackedASCIILowerCodes::PackedASCIILowerCodes(StorageInteger value) +template constexpr PackedASCIISubsetLiteral::PackedASCIISubsetLiteral(StorageInteger value) : m_value { value } { } -template template constexpr StorageInteger PackedASCIILowerCodes::pack(const char (&string)[size]) +template template constexpr StorageInteger PackedASCIISubsetLiteral::pack(const char (&string)[size]) { ASSERT_UNDER_CONSTEXPR_CONTEXT(size); constexpr unsigned length = size - 1; @@ -341,36 +348,55 @@ template template constexpr StorageInteg ASSERT_UNDER_CONSTEXPR_CONTEXT(length <= sizeof(StorageInteger)); StorageInteger result = 0; for (unsigned index = 0; index < length; ++index) { + ASSERT_UNDER_CONSTEXPR_CONTEXT(isInSubset(string[index])); StorageInteger code = static_cast(string[index]); result |= code << ((sizeof(StorageInteger) - index - 1) * 8); } return result; } -template auto PackedASCIILowerCodes::parse(StringView string) -> std::optional +template template auto PackedASCIISubsetLiteral::parse(Span span) -> std::optional { - if (string.length() > sizeof(StorageInteger)) + if (span.size() > sizeof(StorageInteger)) return std::nullopt; StorageInteger result = 0; - for (unsigned index = 0; index < string.length(); ++index) { - UChar code = string[index]; + for (unsigned index = 0; index < span.size(); ++index) { + auto code = span[index]; if (!isASCII(code)) return std::nullopt; - result |= static_cast(toASCIILower(code)) << ((sizeof(StorageInteger) - index - 1) * 8); + result |= static_cast(foldForComparison(code)) << ((sizeof(StorageInteger) - index - 1) * 8); } - return PackedASCIILowerCodes(result); + return PackedASCIISubsetLiteral(result); } -template constexpr bool operator==(PackedASCIILowerCodes a, PackedASCIILowerCodes b) +template constexpr bool operator==(PackedASCIISubsetLiteral a, PackedASCIISubsetLiteral b) { return a.value() == b.value(); } -template constexpr bool operator<(PackedASCIILowerCodes a, PackedASCIILowerCodes b) +template constexpr bool operator<(PackedASCIISubsetLiteral a, PackedASCIISubsetLiteral b) { return a.value() < b.value(); } +template struct SortedArrayKeyTraits> { + static std::optional parse(StringView string) + { + return { { string } }; + } +}; + +template struct SortedArrayKeyTraits> { + template static std::optional> parse(Span span) + { + return PackedASCIISubsetLiteral::parse(span); + } + static std::optional> parse(StringView string) + { + return string.is8Bit() ? parse(string.span8()) : parse(string.span16()); + } +}; + template constexpr std::optional makeOptionalFromPointer(const ValueType* pointer) { if (!pointer) @@ -386,7 +412,9 @@ using WTF::ComparableASCIILiteral; using WTF::ComparableASCIISubsetLiteral; using WTF::ComparableCaseFoldingASCIILiteral; using WTF::ComparableLettersLiteral; +using WTF::PackedASCIILiteral; using WTF::PackedASCIILowerCodes; +using WTF::PackedLettersLiteral; using WTF::SortedArrayMap; using WTF::SortedArraySet; using WTF::makeOptionalFromPointer; diff --git a/Source/WTF/wtf/Threading.cpp b/Source/WTF/wtf/Threading.cpp index 8483156a7c9c..bcda055048b3 100644 --- a/Source/WTF/wtf/Threading.cpp +++ b/Source/WTF/wtf/Threading.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include diff --git a/Source/WTF/wtf/generic/RunLoopGeneric.cpp b/Source/WTF/wtf/generic/RunLoopGeneric.cpp index ba0df7917aae..ca25fb5f360c 100644 --- a/Source/WTF/wtf/generic/RunLoopGeneric.cpp +++ b/Source/WTF/wtf/generic/RunLoopGeneric.cpp @@ -28,6 +28,7 @@ #include #include +#include #include namespace WTF { diff --git a/Source/WTF/wtf/linux/RealTimeThreads.cpp b/Source/WTF/wtf/linux/RealTimeThreads.cpp index 48e38b35ea97..10ca6c7f18a6 100644 --- a/Source/WTF/wtf/linux/RealTimeThreads.cpp +++ b/Source/WTF/wtf/linux/RealTimeThreads.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #if USE(GLIB) diff --git a/Source/WTF/wtf/text/ASCIIFastPath.h b/Source/WTF/wtf/text/ASCIIFastPath.h index 3d55b716e84a..779671cb68c1 100644 --- a/Source/WTF/wtf/text/ASCIIFastPath.h +++ b/Source/WTF/wtf/text/ASCIIFastPath.h @@ -106,91 +106,6 @@ inline bool charactersAreAllASCII(const CharacterType* characters, size_t length return !(allCharBits & nonASCIIBitMask); } -inline void copyLCharsFromUCharSource(LChar* destination, const UChar* source, size_t length) -{ -#if CPU(X86_SSE2) - const uintptr_t memoryAccessSize = 16; // Memory accesses on 16 byte (128 bit) alignment - const uintptr_t memoryAccessMask = memoryAccessSize - 1; - - size_t i = 0; - for (;i < length && !isAlignedTo(&source[i]); ++i) { - ASSERT(!(source[i] & 0xff00)); - destination[i] = static_cast(source[i]); - } - - const uintptr_t sourceLoadSize = 32; // Process 32 bytes (16 UChars) each iteration - const size_t ucharsPerLoop = sourceLoadSize / sizeof(UChar); - if (length > ucharsPerLoop) { - const size_t endLength = length - ucharsPerLoop + 1; - for (; i < endLength; i += ucharsPerLoop) { -#ifndef NDEBUG - for (unsigned checkIndex = 0; checkIndex < ucharsPerLoop; ++checkIndex) - ASSERT(!(source[i+checkIndex] & 0xff00)); -#endif - __m128i first8UChars = _mm_load_si128(reinterpret_cast(&source[i])); - __m128i second8UChars = _mm_load_si128(reinterpret_cast(&source[i+8])); - __m128i packedChars = _mm_packus_epi16(first8UChars, second8UChars); - _mm_storeu_si128(reinterpret_cast<__m128i*>(&destination[i]), packedChars); - } - } - - for (; i < length; ++i) { - ASSERT(!(source[i] & 0xff00)); - destination[i] = static_cast(source[i]); - } -#elif COMPILER(GCC_COMPATIBLE) && CPU(ARM64) && !defined(__ILP32__) && defined(NDEBUG) - const LChar* const end = destination + length; - const uintptr_t memoryAccessSize = 16; - - if (length >= memoryAccessSize) { - const uintptr_t memoryAccessMask = memoryAccessSize - 1; - - // Vector interleaved unpack, we only store the lower 8 bits. - const uintptr_t lengthLeft = end - destination; - const LChar* const simdEnd = destination + (lengthLeft & ~memoryAccessMask); - do { - asm("ld2 { v0.16B, v1.16B }, [%[SOURCE]], #32\n\t" - "st1 { v0.16B }, [%[DESTINATION]], #16\n\t" - : [SOURCE]"+r" (source), [DESTINATION]"+r" (destination) - : - : "memory", "v0", "v1"); - } while (destination != simdEnd); - } - - while (destination != end) - *destination++ = static_cast(*source++); -#elif COMPILER(GCC_COMPATIBLE) && CPU(ARM_NEON) && !(CPU(BIG_ENDIAN) || CPU(MIDDLE_ENDIAN)) && defined(NDEBUG) - const LChar* const end = destination + length; - const uintptr_t memoryAccessSize = 8; - - if (length >= (2 * memoryAccessSize) - 1) { - // Prefix: align dst on 64 bits. - const uintptr_t memoryAccessMask = memoryAccessSize - 1; - while (!isAlignedTo(destination)) - *destination++ = static_cast(*source++); - - // Vector interleaved unpack, we only store the lower 8 bits. - const uintptr_t lengthLeft = end - destination; - const LChar* const simdEnd = end - (lengthLeft % memoryAccessSize); - do { - asm("vld2.8 { d0-d1 }, [%[SOURCE]] !\n\t" - "vst1.8 { d0 }, [%[DESTINATION],:64] !\n\t" - : [SOURCE]"+r" (source), [DESTINATION]"+r" (destination) - : - : "memory", "d0", "d1"); - } while (destination != simdEnd); - } - - while (destination != end) - *destination++ = static_cast(*source++); -#else - for (size_t i = 0; i < length; ++i) { - ASSERT(!(source[i] & 0xff00)); - destination[i] = static_cast(source[i]); - } -#endif -} - } // namespace WTF using WTF::charactersAreAllASCII; diff --git a/Source/WTF/wtf/text/AtomString.h b/Source/WTF/wtf/text/AtomString.h index 8db09a5af997..d482aa7d2d40 100644 --- a/Source/WTF/wtf/text/AtomString.h +++ b/Source/WTF/wtf/text/AtomString.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004-2019 Apple Inc. All rights reserved. + * Copyright (C) 2004-2022 Apple Inc. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -21,15 +21,9 @@ #pragma once #include -#include #include -#include #include -#if OS(WINDOWS) -#include -#endif - namespace WTF { class AtomString final { @@ -41,12 +35,6 @@ class AtomString final { ALWAYS_INLINE static AtomString fromLatin1(const char* characters) { return AtomString(characters); } - template - explicit AtomString(const Vector& characters) - : m_string(AtomStringImpl::add(characters.data(), characters.size())) - { - } - AtomString(AtomStringImpl*); AtomString(RefPtr&&); AtomString(Ref&&); @@ -61,12 +49,7 @@ class AtomString final { AtomString(ASCIILiteral); - // We have to declare the copy constructor and copy assignment operator as well, otherwise - // they'll be implicitly deleted by adding the move constructor and move assignment operator. - AtomString(const AtomString& other) : m_string(other.m_string) { } - AtomString(AtomString&& other) : m_string(WTFMove(other.m_string)) { } - AtomString& operator=(const AtomString& other) { m_string = other.m_string; return *this; } - AtomString& operator=(AtomString&& other) { m_string = WTFMove(other.m_string); return *this; } + static AtomString lookUp(const UChar* characters, unsigned length) { return AtomStringImpl::lookUp(characters, length); } // Hash table deleted values, which are only constructed and never copied or destroyed. AtomString(WTF::HashTableDeletedValueType) : m_string(WTF::HashTableDeletedValue) { } diff --git a/Source/WTF/wtf/text/Base64.h b/Source/WTF/wtf/text/Base64.h index 1b5062fb93ce..14c2cb8cbcdb 100644 --- a/Source/WTF/wtf/text/Base64.h +++ b/Source/WTF/wtf/text/Base64.h @@ -31,7 +31,7 @@ #include #include #include -#include +#include namespace WTF { @@ -86,7 +86,6 @@ WTF_EXPORT_PRIVATE std::optional> base64Decode(Span> base64Decode(StringView, OptionSet = { }, Base64DecodeMap = Base64DecodeMap::Default); std::optional> base64Decode(Span, OptionSet = { }, Base64DecodeMap = Base64DecodeMap::Default); std::optional> base64Decode(Span, OptionSet = { }, Base64DecodeMap = Base64DecodeMap::Default); -std::optional> base64Decode(const String&, OptionSet = { }, Base64DecodeMap = Base64DecodeMap::Default); std::optional> base64Decode(const void*, unsigned, OptionSet = { }, Base64DecodeMap = Base64DecodeMap::Default); // All the same functions modified for base64url, as defined in RFC 4648. @@ -106,7 +105,6 @@ String base64URLEncodeToString(const void*, unsigned); std::optional> base64URLDecode(StringView); inline std::optional> base64URLDecode(ASCIILiteral literal) { return base64URLDecode(StringView { literal }); } -std::optional> base64URLDecode(const String&); std::optional> base64URLDecode(Span); std::optional> base64URLDecode(Span); std::optional> base64URLDecode(Span); @@ -175,11 +173,6 @@ inline std::optional> base64Decode(Span input, Optio return base64Decode(asBytes(input), options, map); } -inline std::optional> base64Decode(const String& input, OptionSet options, Base64DecodeMap map) -{ - return base64Decode(StringView { input }, options, map); -} - inline std::optional> base64Decode(const void* input, unsigned length, OptionSet options, Base64DecodeMap map) { return base64Decode({ static_cast(input), length }, options, map); @@ -240,11 +233,6 @@ inline std::optional> base64URLDecode(StringView input) return base64Decode(input, { }, Base64DecodeMap::URL); } -inline std::optional> base64URLDecode(const String& input) -{ - return base64Decode(input, { }, Base64DecodeMap::URL); -} - inline std::optional> base64URLDecode(Span input) { return base64Decode(input, { }, Base64DecodeMap::URL); diff --git a/Source/WTF/wtf/text/IntegerToStringConversion.h b/Source/WTF/wtf/text/IntegerToStringConversion.h index 0c9a2f10c3d2..f8765be31e3a 100644 --- a/Source/WTF/wtf/text/IntegerToStringConversion.h +++ b/Source/WTF/wtf/text/IntegerToStringConversion.h @@ -22,6 +22,7 @@ #pragma once #include +#include #include namespace WTF { diff --git a/Source/WTF/wtf/text/StringConcatenate.h b/Source/WTF/wtf/text/StringConcatenate.h index 4068d70cadd7..d7868a948126 100644 --- a/Source/WTF/wtf/text/StringConcatenate.h +++ b/Source/WTF/wtf/text/StringConcatenate.h @@ -185,7 +185,7 @@ template<> class StringTypeAdapter { bool is8Bit() const { return !m_string || m_string->is8Bit(); } template void writeTo(CharacterType* destination) const { - StringView { m_string }.getCharactersWithUpconvert(destination); + StringView { m_string }.getCharacters(destination); WTF_STRINGTYPEADAPTER_COPIED_WTF_STRING(); } @@ -228,7 +228,7 @@ template<> class StringTypeAdapter { bool is8Bit() const { return m_string.is8Bit(); } template void writeTo(CharacterType* destination) const { - StringView { m_string }.getCharactersWithUpconvert(destination); + StringView { m_string }.getCharacters(destination); WTF_STRINGTYPEADAPTER_COPIED_WTF_STRING(); } diff --git a/Source/WTF/wtf/text/StringImpl.h b/Source/WTF/wtf/text/StringImpl.h index e8fd7b9a9f35..1762ed609dce 100644 --- a/Source/WTF/wtf/text/StringImpl.h +++ b/Source/WTF/wtf/text/StringImpl.h @@ -406,8 +406,10 @@ class StringImpl : private StringImplShape { WTF_EXPORT_PRIVATE static StaticStringImpl s_emptyAtomString; ALWAYS_INLINE static StringImpl* empty() { return reinterpret_cast(&s_emptyAtomString); } - // FIXME: Does this really belong in StringImpl? - template static void copyCharacters(DestinationCharacterType* destination, const SourceCharacterType* source, unsigned numCharacters); + // FIXME: Do these functions really belong in StringImpl? + template static void copyCharacters(CharacterType* destination, const CharacterType* source, unsigned length); + static void copyCharacters(UChar* destination, const LChar* source, unsigned length); + static void copyCharacters(LChar* destination, const UChar* source, unsigned length); // Some string features, like reference counting and the atomicity flag, are not // thread-safe. We achieve thread safety by isolation, giving each thread @@ -861,10 +863,10 @@ inline bool StringImpl::isAllLatin1() const if (is8Bit()) return true; auto* characters = characters16(); - UChar ored = 0; - for (size_t i = 0; i < length(); ++i) - ored |= characters[i]; - return !(ored & 0xFF00); + UChar mergedCharacterBits = 0; + for (unsigned i = 0; i < length(); ++i) + mergedCharacterBits |= characters[i]; + return isLatin1(mergedCharacterBits); } template inline bool isAllSpecialCharacters(const CharacterType* characters, size_t length) @@ -1141,54 +1143,126 @@ inline void StringImpl::deref() m_refCount = tempRefCount; } -template -inline void StringImpl::copyCharacters(DestinationCharacterType* destination, const SourceCharacterType* source, unsigned numCharacters) +template inline void StringImpl::copyCharacters(CharacterType* destination, const CharacterType* source, unsigned length) +{ + if (length == 1) + *destination = *source; + else if (length) + std::memcpy(destination, source, length * sizeof(CharacterType)); +} + +inline void StringImpl::copyCharacters(UChar* destination, const LChar* source, unsigned length) { - ASSERT(destination || !numCharacters); // Workaround for clang static analyzer (). - static_assert(std::is_same_v || std::is_same_v); - static_assert(std::is_same_v || std::is_same_v); - if constexpr (std::is_same_v) { - if (numCharacters == 1) { - *destination = *source; - return; - } - memcpy(destination, source, numCharacters * sizeof(DestinationCharacterType)); - } else { #if CPU(ARM64) - // SIMD Upconvert. - if constexpr (std::is_same_v && std::is_same_v) { - const auto* end = destination + numCharacters; - constexpr uintptr_t memoryAccessSize = 64; - - if (numCharacters >= memoryAccessSize) { - constexpr uintptr_t memoryAccessMask = memoryAccessSize - 1; - const auto* simdEnd = destination + (numCharacters & ~memoryAccessMask); - uint8x16_t zeros = vdupq_n_u8(0); - do { - uint8x16x4_t bytes = vld1q_u8_x4(bitwise_cast(source)); - source += memoryAccessSize; - - vst2q_u8(bitwise_cast(destination), (uint8x16x2_t { bytes.val[0], zeros })); - destination += memoryAccessSize / 4; - vst2q_u8(bitwise_cast(destination), (uint8x16x2_t { bytes.val[1], zeros })); - destination += memoryAccessSize / 4; - vst2q_u8(bitwise_cast(destination), (uint8x16x2_t { bytes.val[2], zeros })); - destination += memoryAccessSize / 4; - vst2q_u8(bitwise_cast(destination), (uint8x16x2_t { bytes.val[3], zeros })); - destination += memoryAccessSize / 4; - } while (destination != simdEnd); - } - - while (destination != end) - *destination++ = *source++; - return; - } + // SIMD Upconvert. + const auto* end = destination + length; + constexpr uintptr_t memoryAccessSize = 64; + + if (length >= memoryAccessSize) { + constexpr uintptr_t memoryAccessMask = memoryAccessSize - 1; + const auto* simdEnd = destination + (length & ~memoryAccessMask); + uint8x16_t zeros = vdupq_n_u8(0); + do { + uint8x16x4_t bytes = vld1q_u8_x4(bitwise_cast(source)); + source += memoryAccessSize; + + vst2q_u8(bitwise_cast(destination), (uint8x16x2_t { bytes.val[0], zeros })); + destination += memoryAccessSize / 4; + vst2q_u8(bitwise_cast(destination), (uint8x16x2_t { bytes.val[1], zeros })); + destination += memoryAccessSize / 4; + vst2q_u8(bitwise_cast(destination), (uint8x16x2_t { bytes.val[2], zeros })); + destination += memoryAccessSize / 4; + vst2q_u8(bitwise_cast(destination), (uint8x16x2_t { bytes.val[3], zeros })); + destination += memoryAccessSize / 4; + } while (destination != simdEnd); + } + + while (destination != end) + *destination++ = *source++; +#else + for (unsigned i = 0; i < length; ++i) + destination[i] = source[i]; #endif - // FIXME: We should ensure that UChar -> LChar copying happens when UChar only contains Latin-1. - // https://bugs.webkit.org/show_bug.cgi?id=205355 - for (unsigned i = 0; i < numCharacters; ++i) - destination[i] = source[i]; +} + +inline void StringImpl::copyCharacters(LChar* destination, const UChar* source, unsigned length) +{ +#if ASSERT_ENABLED + for (unsigned i = 0; i < length; ++i) + ASSERT(isLatin1(source[i])); +#endif + +#if CPU(X86_SSE2) + const uintptr_t memoryAccessSize = 16; // Memory accesses on 16 byte (128 bit) alignment + const uintptr_t memoryAccessMask = memoryAccessSize - 1; + + unsigned i = 0; + for (; i < length && !isAlignedTo(&source[i]); ++i) + destination[i] = source[i]; + + const uintptr_t sourceLoadSize = 32; // Process 32 bytes (16 UChars) each iteration + const unsigned ucharsPerLoop = sourceLoadSize / sizeof(UChar); + if (length > ucharsPerLoop) { + const unsigned endLength = length - ucharsPerLoop + 1; + for (; i < endLength; i += ucharsPerLoop) { + __m128i first8UChars = _mm_load_si128(reinterpret_cast(&source[i])); + __m128i second8UChars = _mm_load_si128(reinterpret_cast(&source[i+8])); + __m128i packedChars = _mm_packus_epi16(first8UChars, second8UChars); + _mm_storeu_si128(reinterpret_cast<__m128i*>(&destination[i]), packedChars); + } + } + + for (; i < length; ++i) + destination[i] = source[i]; +#elif COMPILER(GCC_COMPATIBLE) && CPU(ARM64) && !defined(__ILP32__) && defined(NDEBUG) + const LChar* const end = destination + length; + const uintptr_t memoryAccessSize = 16; + + if (length >= memoryAccessSize) { + const uintptr_t memoryAccessMask = memoryAccessSize - 1; + + // Vector interleaved unpack, we only store the lower 8 bits. + const uintptr_t lengthLeft = end - destination; + const LChar* const simdEnd = destination + (lengthLeft & ~memoryAccessMask); + do { + asm("ld2 { v0.16B, v1.16B }, [%[SOURCE]], #32\n\t" + "st1 { v0.16B }, [%[DESTINATION]], #16\n\t" + : [SOURCE]"+r" (source), [DESTINATION]"+r" (destination) + : + : "memory", "v0", "v1"); + } while (destination != simdEnd); } + + while (destination != end) + *destination++ = static_cast(*source++); +#elif COMPILER(GCC_COMPATIBLE) && CPU(ARM_NEON) && !(CPU(BIG_ENDIAN) || CPU(MIDDLE_ENDIAN)) && defined(NDEBUG) + const LChar* const end = destination + length; + const uintptr_t memoryAccessSize = 8; + + if (length >= (2 * memoryAccessSize) - 1) { + // Prefix: align dst on 64 bits. + const uintptr_t memoryAccessMask = memoryAccessSize - 1; + while (!isAlignedTo(destination)) + *destination++ = static_cast(*source++); + + // Vector interleaved unpack, we only store the lower 8 bits. + const uintptr_t lengthLeft = end - destination; + const LChar* const simdEnd = end - (lengthLeft % memoryAccessSize); + do { + asm("vld2.8 { d0-d1 }, [%[SOURCE]] !\n\t" + "vst1.8 { d0 }, [%[DESTINATION],:64] !\n\t" + : [SOURCE]"+r" (source), [DESTINATION]"+r" (destination) + : + : "memory", "d0", "d1"); + } while (destination != simdEnd); + } + + while (destination != end) + *destination++ = static_cast(*source++); +#else + for (unsigned i = 0; i < length; ++i) + destination[i] = static_cast(source[i]); +#endif } inline UChar StringImpl::at(unsigned i) const @@ -1344,8 +1418,7 @@ template ALWAYS_INLINE Ref span8() const { return { characters8(), length() }; } + Span span16() const { return { characters16(), length() }; } unsigned hash() const; @@ -130,8 +132,9 @@ class StringView final { class UpconvertedCharacters; UpconvertedCharacters upconvertedCharacters() const; - void getCharactersWithUpconvert(LChar*) const; - void getCharactersWithUpconvert(UChar*) const; + template void getCharacters(CharacterType*) const; + template void getCharacters8(CharacterType*) const; + template void getCharacters16(CharacterType*) const; enum class CaseConvertType { Upper, Lower }; WTF_EXPORT_PRIVATE void getCharactersWithASCIICase(CaseConvertType, LChar*) const; @@ -568,29 +571,24 @@ template inline bool StringView::isAllSpecialCha return WTF::isAllSpecialCharacters(characters16(), length()); } -inline void StringView::getCharactersWithUpconvert(LChar* destination) const +template inline void StringView::getCharacters8(CharacterType* destination) const { - if (!characters8()) - return; - - ASSERT(is8Bit()); StringImpl::copyCharacters(destination, characters8(), m_length); } -inline void StringView::getCharactersWithUpconvert(UChar* destination) const +template inline void StringView::getCharacters16(CharacterType* destination) const { - if (is8Bit()) { - if (!characters8()) - return; - - StringImpl::copyCharacters(destination, characters8(), m_length); - return; - } - if (!characters16()) - return; StringImpl::copyCharacters(destination, characters16(), m_length); } +template inline void StringView::getCharacters(CharacterType* destination) const +{ + if (is8Bit()) + getCharacters8(destination); + else + getCharacters16(destination); +} + inline StringView::UpconvertedCharacters::UpconvertedCharacters(StringView string) { if (!string.is8Bit()) { @@ -685,7 +683,7 @@ template<> class StringTypeAdapter { unsigned length() { return m_string.length(); } bool is8Bit() { return m_string.is8Bit(); } - template void writeTo(CharacterType* destination) { m_string.getCharactersWithUpconvert(destination); } + template void writeTo(CharacterType* destination) { m_string.getCharacters(destination); } private: StringView m_string; @@ -695,7 +693,7 @@ template void append(Vector String::charactersWithoutNullTermination() const if (is8Bit()) { const LChar* characters8 = m_impl->characters8(); - for (size_t i = 0; i < length(); ++i) + for (unsigned i = 0; i < length(); ++i) result.uncheckedAppend(characters8[i]); } else { const UChar* characters16 = m_impl->characters16(); @@ -470,37 +470,30 @@ CString String::utf8(ConversionMode mode) const return expectedString.value(); } -String String::make8BitFrom16BitSource(const UChar* source, size_t length) +String String::make8Bit(const UChar* source, unsigned length) { - if (!length) - return String(); - LChar* destination; String result = String::createUninitialized(length, destination); - - copyLCharsFromUCharSource(destination, source, length); - + StringImpl::copyCharacters(destination, source, length); return result; } -String String::make16BitFrom8BitSource(const LChar* source, size_t length) +void String::convertTo16Bit() { - if (!length) - return String(); - + if (isNull() || !is8Bit()) + return; + auto length = this->length(); UChar* destination; - String result = String::createUninitialized(length, destination); - - StringImpl::copyCharacters(destination, source, length); - - return result; + auto convertedString = String::createUninitialized(length, destination); + StringImpl::copyCharacters(destination, characters8(), length); + *this = WTFMove(convertedString); } template String fromUTF8Impl(const LChar* stringStart, size_t length) { - if (length > StringImplShape::MaxLength) - CRASH(); + // Do this assertion before chopping the size_t down to unsigned. + RELEASE_ASSERT(length <= String::MaxLength); if (!stringStart) return String(); @@ -550,8 +543,11 @@ String String::fromUTF8(const CString& s) String String::fromUTF8WithLatin1Fallback(const LChar* string, size_t size) { String utf8 = fromUTF8(string, size); - if (!utf8) + if (!utf8) { + // Do this assertion before chopping the size_t down to unsigned. + RELEASE_ASSERT(size <= String::MaxLength); return String(string, size); + } return utf8; } diff --git a/Source/WTF/wtf/text/WTFString.h b/Source/WTF/wtf/text/WTFString.h index fcdfc6594b31..69133bf2e763 100644 --- a/Source/WTF/wtf/text/WTFString.h +++ b/Source/WTF/wtf/text/WTFString.h @@ -24,9 +24,6 @@ // This file would be called String.h, but that conflicts with // on systems without case-sensitive file systems. -#include -#include -#include #include #include @@ -63,17 +60,6 @@ class String final { WTF_EXPORT_PRIVATE String(const UChar* characters, unsigned length); ALWAYS_INLINE String(Span characters) : String(characters.data(), characters.size()) { } - // Construct a string by copying the contents of a vector. To avoid - // copying, consider using String::adopt instead. - // This method will never create a null string. Vectors with size() == 0 - // will return the empty string. - // NOTE: This is different from String(vector.data(), vector.size()) - // which will sometimes return a null string when vector.data() is null - // which can only occur for vectors without inline capacity. - // See: https://bugs.webkit.org/show_bug.cgi?id=109792 - template - explicit String(const Vector&); - // Construct a string with Latin-1 data. WTF_EXPORT_PRIVATE String(const LChar* characters, unsigned length); WTF_EXPORT_PRIVATE String(const char* characters, unsigned length); @@ -279,24 +265,21 @@ class String final { WTF_EXPORT_PRIVATE Vector wideCharacters() const; #endif - WTF_EXPORT_PRIVATE static String make8BitFrom16BitSource(const UChar*, size_t); - template static String make8BitFrom16BitSource(const Vector&); - - WTF_EXPORT_PRIVATE static String make16BitFrom8BitSource(const LChar*, size_t); + WTF_EXPORT_PRIVATE static String make8Bit(const UChar*, unsigned); + WTF_EXPORT_PRIVATE void convertTo16Bit(); - // String::fromUTF8 will return a null string if - // the input data contains invalid UTF-8 sequences. + // String::fromUTF8 will return a null string if the input data contains invalid UTF-8 sequences. WTF_EXPORT_PRIVATE static String fromUTF8(const LChar*, size_t); WTF_EXPORT_PRIVATE static String fromUTF8(const LChar*); - static String fromUTF8(const char* characters, size_t length) { return fromUTF8(reinterpret_cast(characters), length); }; - static String fromUTF8(const char* string) { return fromUTF8(reinterpret_cast(string)); }; + static String fromUTF8(const char* characters, size_t length) { return fromUTF8(reinterpret_cast(characters), length); } + static String fromUTF8(const char* string) { return fromUTF8(reinterpret_cast(string)); } WTF_EXPORT_PRIVATE static String fromUTF8(const CString&); static String fromUTF8(const Vector& characters); static String fromUTF8ReplacingInvalidSequences(const LChar*, size_t); // Tries to convert the passed in string to UTF-8, but will fall back to Latin-1 if the string is not valid UTF-8. WTF_EXPORT_PRIVATE static String fromUTF8WithLatin1Fallback(const LChar*, size_t); - static String fromUTF8WithLatin1Fallback(const char* characters, size_t length) { return fromUTF8WithLatin1Fallback(reinterpret_cast(characters), length); }; + static String fromUTF8WithLatin1Fallback(const char* characters, size_t length) { return fromUTF8WithLatin1Fallback(reinterpret_cast(characters), length); } WTF_EXPORT_PRIVATE static String fromCodePoint(UChar32 codePoint); @@ -458,11 +441,6 @@ inline String::String(ASCIILiteral characters) { } -template String::String(const Vector& vector) - : m_impl(vector.size() ? StringImpl::create(vector.data(), vector.size()) : Ref { *StringImpl::empty() }) -{ -} - template<> inline const LChar* String::characters() const { return characters8(); @@ -496,11 +474,6 @@ ALWAYS_INLINE String WARN_UNUSED_RETURN makeStringByReplacingAll(const String& s WTF_EXPORT_PRIVATE String WARN_UNUSED_RETURN makeStringByRemoving(const String&, unsigned position, unsigned lengthToRemove); -template inline String String::make8BitFrom16BitSource(const Vector& buffer) -{ - return make8BitFrom16BitSource(buffer.data(), buffer.size()); -} - inline std::optional String::defaultWritingDirection() const { if (m_impl) diff --git a/Source/WTF/wtf/text/icu/UTextProviderLatin1.cpp b/Source/WTF/wtf/text/icu/UTextProviderLatin1.cpp index 49980f95ba79..de098fc4896b 100644 --- a/Source/WTF/wtf/text/icu/UTextProviderLatin1.cpp +++ b/Source/WTF/wtf/text/icu/UTextProviderLatin1.cpp @@ -140,7 +140,7 @@ static UBool uTextLatin1Access(UText* uText, int64_t index, UBool forward) } uText->chunkLength = static_cast(uText->chunkNativeLimit - uText->chunkNativeStart); - StringImpl::copyCharacters(const_cast(uText->chunkContents), static_cast(uText->context) + uText->chunkNativeStart, static_cast(uText->chunkLength)); + StringImpl::copyCharacters(const_cast(uText->chunkContents), static_cast(uText->context) + uText->chunkNativeStart, uText->chunkLength); uText->nativeIndexingLimit = uText->chunkLength; @@ -178,7 +178,7 @@ static int32_t uTextLatin1Extract(UText* uText, int64_t start, int64_t limit, UC if (trimmedLength > destCapacity) trimmedLength = destCapacity; - StringImpl::copyCharacters(dest, static_cast(uText->context) + start, static_cast(trimmedLength)); + StringImpl::copyCharacters(dest, static_cast(uText->context) + start, trimmedLength); } if (length < destCapacity) { @@ -291,7 +291,7 @@ static void textLatin1ContextAwareMoveInPrimaryContext(UText* text, int64_t nati text->chunkLength = length < std::numeric_limits::max() ? static_cast(length) : 0; text->nativeIndexingLimit = text->chunkLength; text->chunkOffset = forward ? 0 : text->chunkLength; - StringImpl::copyCharacters(const_cast(text->chunkContents), static_cast(text->p) + (text->chunkNativeStart - text->b), static_cast(text->chunkLength)); + StringImpl::copyCharacters(const_cast(text->chunkContents), static_cast(text->p) + (text->chunkNativeStart - text->b), text->chunkLength); } static void textLatin1ContextAwareSwitchToPrimaryContext(UText* text, int64_t nativeIndex, int64_t nativeLength, UBool forward) diff --git a/Source/WebCore/Modules/websockets/ThreadableWebSocketChannelClientWrapper.cpp b/Source/WebCore/Modules/websockets/ThreadableWebSocketChannelClientWrapper.cpp index a9cc5410a83c..551f9a30c2c0 100644 --- a/Source/WebCore/Modules/websockets/ThreadableWebSocketChannelClientWrapper.cpp +++ b/Source/WebCore/Modules/websockets/ThreadableWebSocketChannelClientWrapper.cpp @@ -107,7 +107,7 @@ void ThreadableWebSocketChannelClientWrapper::setSubprotocol(const String& subpr { unsigned length = subprotocol.length(); m_subprotocol.resize(length); - StringView(subprotocol).getCharactersWithUpconvert(m_subprotocol.data()); + StringView(subprotocol).getCharacters(m_subprotocol.data()); } String ThreadableWebSocketChannelClientWrapper::extensions() const @@ -121,7 +121,7 @@ void ThreadableWebSocketChannelClientWrapper::setExtensions(const String& extens { unsigned length = extensions.length(); m_extensions.resize(length); - StringView(extensions).getCharactersWithUpconvert(m_extensions.data()); + StringView(extensions).getCharacters(m_extensions.data()); } ThreadableWebSocketChannel::SendResult ThreadableWebSocketChannelClientWrapper::sendRequestResult() const diff --git a/Source/WebCore/html/HTMLImageElement.cpp b/Source/WebCore/html/HTMLImageElement.cpp index 7339aaf4cc1c..9b174404c762 100644 --- a/Source/WebCore/html/HTMLImageElement.cpp +++ b/Source/WebCore/html/HTMLImageElement.cpp @@ -278,7 +278,7 @@ void HTMLImageElement::selectImageSource(RelevantMutation relevantMutation) document().addDynamicMediaQueryDependentImage(*this); } -bool HTMLImageElement::hasLazyLoadableAttributeValue(const AtomString& attributeValue) +bool HTMLImageElement::hasLazyLoadableAttributeValue(StringView attributeValue) { return equalLettersIgnoringASCIICase(attributeValue, "lazy"_s); } diff --git a/Source/WebCore/html/HTMLImageElement.h b/Source/WebCore/html/HTMLImageElement.h index 7f361b2318c4..12609942aec8 100644 --- a/Source/WebCore/html/HTMLImageElement.h +++ b/Source/WebCore/html/HTMLImageElement.h @@ -141,7 +141,7 @@ class HTMLImageElement : public HTMLElement, public FormNamedItem, public Active void setLoadingForBindings(const AtomString&); bool isLazyLoadable() const; - static bool hasLazyLoadableAttributeValue(const AtomString&); + static bool hasLazyLoadableAttributeValue(StringView); bool isDeferred() const; diff --git a/Source/WebCore/html/LinkRelAttribute.cpp b/Source/WebCore/html/LinkRelAttribute.cpp index 21ae23a3042e..300e61f16b42 100644 --- a/Source/WebCore/html/LinkRelAttribute.cpp +++ b/Source/WebCore/html/LinkRelAttribute.cpp @@ -40,23 +40,8 @@ namespace WebCore { -LinkRelAttribute::LinkRelAttribute() - : iconType() - , isStyleSheet(false) - , isAlternate(false) - , isDNSPrefetch(false) - , isLinkPreload(false) - , isLinkPreconnect(false) - , isLinkPrefetch(false) -#if ENABLE(APPLICATION_MANIFEST) - , isApplicationManifest(false) -#endif -{ -} - // Keep LinkRelAttribute::isSupported() in sync when updating this constructor. -LinkRelAttribute::LinkRelAttribute(Document& document, const String& rel) - : LinkRelAttribute() +LinkRelAttribute::LinkRelAttribute(Document& document, StringView rel) { if (equalLettersIgnoringASCIICase(rel, "stylesheet"_s)) isStyleSheet = true; @@ -83,18 +68,19 @@ LinkRelAttribute::LinkRelAttribute(Document& document, const String& rel) #endif } else { // Tokenize the rel attribute and set bits based on specific keywords that we find. - String relCopy = makeStringByReplacingAll(rel, '\n', ' '); - for (auto word : StringView(relCopy).split(' ')) { - if (equalLettersIgnoringASCIICase(word, "stylesheet"_s)) - isStyleSheet = true; - else if (equalLettersIgnoringASCIICase(word, "alternate"_s)) - isAlternate = true; - else if (equalLettersIgnoringASCIICase(word, "icon"_s)) - iconType = LinkIconType::Favicon; - else if (equalLettersIgnoringASCIICase(word, "apple-touch-icon"_s)) - iconType = LinkIconType::TouchIcon; - else if (equalLettersIgnoringASCIICase(word, "apple-touch-icon-precomposed"_s)) - iconType = LinkIconType::TouchPrecomposedIcon; + for (auto line : rel.split('\n')) { + for (auto word : line.split(' ')) { + if (equalLettersIgnoringASCIICase(word, "stylesheet"_s)) + isStyleSheet = true; + else if (equalLettersIgnoringASCIICase(word, "alternate"_s)) + isAlternate = true; + else if (equalLettersIgnoringASCIICase(word, "icon"_s)) + iconType = LinkIconType::Favicon; + else if (equalLettersIgnoringASCIICase(word, "apple-touch-icon"_s)) + iconType = LinkIconType::TouchIcon; + else if (equalLettersIgnoringASCIICase(word, "apple-touch-icon-precomposed"_s)) + iconType = LinkIconType::TouchPrecomposedIcon; + } } } } diff --git a/Source/WebCore/html/LinkRelAttribute.h b/Source/WebCore/html/LinkRelAttribute.h index 929df7f7b77d..69cfce5ea8ea 100644 --- a/Source/WebCore/html/LinkRelAttribute.h +++ b/Source/WebCore/html/LinkRelAttribute.h @@ -42,18 +42,18 @@ enum class LinkIconType : uint8_t; struct LinkRelAttribute { Markable> iconType; - bool isStyleSheet : 1; - bool isAlternate : 1; - bool isDNSPrefetch : 1; - bool isLinkPreload : 1; - bool isLinkPreconnect : 1; - bool isLinkPrefetch : 1; + bool isStyleSheet : 1 { false }; + bool isAlternate : 1 { false }; + bool isDNSPrefetch : 1 { false }; + bool isLinkPreload : 1 { false }; + bool isLinkPreconnect : 1 { false }; + bool isLinkPrefetch : 1 { false }; #if ENABLE(APPLICATION_MANIFEST) - bool isApplicationManifest : 1; + bool isApplicationManifest : 1 { false }; #endif - LinkRelAttribute(); - LinkRelAttribute(Document&, const String&); + LinkRelAttribute() = default; + LinkRelAttribute(Document&, StringView); static bool isSupported(Document&, StringView); }; diff --git a/Source/WebCore/html/canvas/CanvasRenderingContext2DBase.cpp b/Source/WebCore/html/canvas/CanvasRenderingContext2DBase.cpp index 74bdd8863510..b8060614b5ab 100644 --- a/Source/WebCore/html/canvas/CanvasRenderingContext2DBase.cpp +++ b/Source/WebCore/html/canvas/CanvasRenderingContext2DBase.cpp @@ -2409,7 +2409,7 @@ String CanvasRenderingContext2DBase::normalizeSpaces(const String& text) unsigned textLength = text.length(); Vector charVector(textLength); - StringView(text).getCharactersWithUpconvert(charVector.data()); + StringView(text).getCharacters(charVector.data()); charVector[i++] = ' '; diff --git a/Source/WebCore/html/parser/AtomHTMLToken.h b/Source/WebCore/html/parser/AtomHTMLToken.h index fd89b15c5a19..40763035cebe 100644 --- a/Source/WebCore/html/parser/AtomHTMLToken.h +++ b/Source/WebCore/html/parser/AtomHTMLToken.h @@ -259,12 +259,13 @@ inline AtomHTMLToken::AtomHTMLToken(HTMLToken& token) m_name = AtomString(token.name().data(), token.name().size()); initializeAttributes(token.attributes()); return; - case Type::Comment: + case Type::Comment: { if (token.commentIsAll8BitData()) - m_data = String::make8BitFrom16BitSource(token.comment()); + m_data = String::make8Bit(token.comment().data(), token.comment().size()); else - m_data = String(token.comment()); + m_data = String(token.comment().data(), token.comment().size()); return; + } case Type::Character: m_externalCharacters = token.characters().span(); m_externalCharactersIsAll8BitData = token.charactersIsAll8BitData(); diff --git a/Source/WebCore/html/parser/HTMLMetaCharsetParser.cpp b/Source/WebCore/html/parser/HTMLMetaCharsetParser.cpp index 6d0bb8610aaa..39cbe58f3025 100644 --- a/Source/WebCore/html/parser/HTMLMetaCharsetParser.cpp +++ b/Source/WebCore/html/parser/HTMLMetaCharsetParser.cpp @@ -41,7 +41,7 @@ HTMLMetaCharsetParser::HTMLMetaCharsetParser() { } -static StringView extractCharset(const String& value) +static StringView extractCharset(StringView value) { unsigned length = value.length(); for (size_t pos = 0; pos < length; ) { @@ -78,22 +78,21 @@ static StringView extractCharset(const String& value) if (quoteMark && (end == length)) break; // Close quote not found. - return StringView(value).substring(pos, end - pos); + return value.substring(pos, end - pos); } - return StringView(); + return { }; } bool HTMLMetaCharsetParser::processMeta(HTMLToken& token) { auto attributes = token.attributes().map([](auto& attribute) { - return std::pair { AtomString(attribute.name), AtomString(attribute.value) }; + return std::pair { StringView { attribute.name.data(), static_cast(attribute.name.size()) }, StringView { attribute.value.data(), static_cast(attribute.value.size()) } }; }); - m_encoding = encodingFromMetaAttributes(attributes); return m_encoding.isValid(); } -PAL::TextEncoding HTMLMetaCharsetParser::encodingFromMetaAttributes(const AttributeList& attributes) +PAL::TextEncoding HTMLMetaCharsetParser::encodingFromMetaAttributes(Span> attributes) { bool gotPragma = false; enum { None, Charset, Pragma } mode = None; @@ -103,15 +102,15 @@ PAL::TextEncoding HTMLMetaCharsetParser::encodingFromMetaAttributes(const Attrib auto& attributeName = attribute.first; auto& attributeValue = attribute.second; - if (attributeName == http_equivAttr) { + if (attributeName == "http-equiv"_s) { if (equalLettersIgnoringASCIICase(attributeValue, "content-type"_s)) gotPragma = true; - } else if (attributeName == charsetAttr) { + } else if (attributeName == "charset"_s) { charset = attributeValue; mode = Charset; // Charset attribute takes precedence break; - } else if (attributeName == contentAttr) { + } else if (attributeName == "content"_s) { charset = extractCharset(attributeValue); if (charset.length()) mode = Pragma; @@ -119,7 +118,7 @@ PAL::TextEncoding HTMLMetaCharsetParser::encodingFromMetaAttributes(const Attrib } if (mode == Charset || (mode == Pragma && gotPragma)) - return PAL::TextEncoding(charset.stripLeadingAndTrailingMatchedCharacters(isHTMLSpace)); + return charset.stripLeadingAndTrailingMatchedCharacters(isHTMLSpace); return PAL::TextEncoding(); } @@ -157,21 +156,21 @@ bool HTMLMetaCharsetParser::checkForMetaCharset(const char* data, size_t length) while (auto token = m_tokenizer.nextToken(m_input)) { bool isEnd = token->type() == HTMLToken::Type::EndTag; if (isEnd || token->type() == HTMLToken::Type::StartTag) { - AtomString tagName(token->name()); + auto knownTagName = AtomString::lookUp(token->name().data(), token->name().size()); if (!isEnd) { - m_tokenizer.updateStateFor(tagName); - if (tagName == metaTag && processMeta(*token)) { + m_tokenizer.updateStateFor(knownTagName); + if (knownTagName == metaTag && processMeta(*token)) { m_doneChecking = true; return true; } } - if (tagName != scriptTag && tagName != noscriptTag - && tagName != styleTag && tagName != linkTag - && tagName != metaTag && tagName != objectTag - && tagName != titleTag && tagName != baseTag - && (isEnd || tagName != htmlTag) - && (isEnd || tagName != headTag)) { + if (knownTagName != scriptTag && knownTagName != noscriptTag + && knownTagName != styleTag && knownTagName != linkTag + && knownTagName != metaTag && knownTagName != objectTag + && knownTagName != titleTag && knownTagName != baseTag + && (isEnd || knownTagName != htmlTag) + && (isEnd || knownTagName != headTag)) { m_inHeadSection = false; } } diff --git a/Source/WebCore/html/parser/HTMLMetaCharsetParser.h b/Source/WebCore/html/parser/HTMLMetaCharsetParser.h index df1dd701373b..d5ae54d83f89 100644 --- a/Source/WebCore/html/parser/HTMLMetaCharsetParser.h +++ b/Source/WebCore/html/parser/HTMLMetaCharsetParser.h @@ -46,8 +46,7 @@ class HTMLMetaCharsetParser { const PAL::TextEncoding& encoding() { return m_encoding; } // The returned encoding might not be valid. - typedef Vector> AttributeList; - static PAL::TextEncoding encodingFromMetaAttributes(const AttributeList&); + static PAL::TextEncoding encodingFromMetaAttributes(Span>); private: bool processMeta(HTMLToken&); diff --git a/Source/WebCore/html/parser/HTMLPreloadScanner.cpp b/Source/WebCore/html/parser/HTMLPreloadScanner.cpp index 4b1d49c3b6d1..e4c0c7ffb9e2 100644 --- a/Source/WebCore/html/parser/HTMLPreloadScanner.cpp +++ b/Source/WebCore/html/parser/HTMLPreloadScanner.cpp @@ -46,6 +46,7 @@ #include "Settings.h" #include "SizesAttributeParser.h" #include +#include namespace WebCore { @@ -53,28 +54,20 @@ using namespace HTMLNames; TokenPreloadScanner::TagId TokenPreloadScanner::tagIdFor(const HTMLToken::DataVector& data) { - AtomString tagName(data); - if (tagName == imgTag) - return TagId::Img; - if (tagName == inputTag) - return TagId::Input; - if (tagName == linkTag) - return TagId::Link; - if (tagName == scriptTag) - return TagId::Script; - if (tagName == styleTag) - return TagId::Style; - if (tagName == baseTag) - return TagId::Base; - if (tagName == templateTag) - return TagId::Template; - if (tagName == metaTag) - return TagId::Meta; - if (tagName == pictureTag) - return TagId::Picture; - if (tagName == sourceTag) - return TagId::Source; - return TagId::Unknown; + static constexpr std::pair, TokenPreloadScanner::TagId> mappings[] = { + { "base", TagId::Base }, + { "img", TagId::Img }, + { "input", TagId::Input }, + { "link", TagId::Link }, + { "meta", TagId::Meta }, + { "picture", TagId::Picture }, + { "script", TagId::Script }, + { "source", TagId::Source }, + { "style", TagId::Style }, + { "template", TagId::Template }, + }; + static constexpr SortedArrayMap map { mappings }; + return map.get(data.span(), TagId::Unknown); } ASCIILiteral TokenPreloadScanner::initiatorFor(TagId tagId) @@ -121,28 +114,27 @@ class TokenPreloadScanner::StartTagScanner { ASSERT(isMainThread()); if (m_tagId >= TagId::Unknown) return; - + for (auto& attribute : attributes) { - AtomString attributeName(attribute.name); - AtomString attributeValue(attribute.value); - processAttribute(WTFMove(attributeName), WTFMove(attributeValue), pictureState); + auto knownAttributeName = AtomString::lookUp(attribute.name.data(), attribute.name.size()); + StringView attributeValue { attribute.value.data(), static_cast(attribute.value.size()) }; + processAttribute(knownAttributeName, attributeValue, pictureState); } - + if (m_tagId == TagId::Source && !pictureState.isEmpty() && !pictureState.last() && m_mediaMatched && m_typeMatched && !m_srcSetAttribute.isEmpty()) { - auto sourceSize = SizesAttributeParser(m_sizesAttribute, m_document).length(); ImageCandidate imageCandidate = bestFitSourceForImageAttributes(m_deviceScaleFactor, AtomString { m_urlToLoad }, m_srcSetAttribute, sourceSize); if (!imageCandidate.isEmpty()) { pictureState.last() = true; - setUrlToLoad(imageCandidate.string.toString(), true); + setURLToLoadAllowingReplacement(imageCandidate.string); } } - + // Resolve between src and srcSet if we have them and the tag is img. if (m_tagId == TagId::Img && !m_srcSetAttribute.isEmpty()) { auto sourceSize = SizesAttributeParser(m_sizesAttribute, m_document).length(); ImageCandidate imageCandidate = bestFitSourceForImageAttributes(m_deviceScaleFactor, AtomString { m_urlToLoad }, m_srcSetAttribute, sourceSize); - setUrlToLoad(imageCandidate.string.toString(), true); + setURLToLoadAllowingReplacement(imageCandidate.string); } if (m_metaIsViewport && !m_metaContent.isNull()) @@ -187,17 +179,17 @@ class TokenPreloadScanner::StartTagScanner { } private: - void processImageAndScriptAttribute(const AtomString& attributeName, const String& attributeValue) + void processImageAndScriptAttribute(const AtomString& attributeName, StringView attributeValue) { if (match(attributeName, srcAttr)) - setUrlToLoad(attributeValue); + setURLToLoad(attributeValue); else if (match(attributeName, crossoriginAttr)) - m_crossOriginMode = stripLeadingAndTrailingHTMLSpaces(attributeValue); + m_crossOriginMode = attributeValue.stripLeadingAndTrailingMatchedCharacters(isHTMLSpace).toString(); else if (match(attributeName, charsetAttr)) - m_charset = attributeValue; + m_charset = attributeValue.toString(); } - void processAttribute(AtomString&& attributeName, AtomString&& attributeValue, const Vector& pictureState) + void processAttribute(const AtomString& attributeName, StringView attributeValue, const Vector& pictureState) { bool inPicture = !pictureState.isEmpty(); bool alreadyMatchedSource = inPicture && pictureState.last(); @@ -207,16 +199,16 @@ class TokenPreloadScanner::StartTagScanner { if (inPicture && alreadyMatchedSource) break; if (match(attributeName, srcsetAttr) && m_srcSetAttribute.isNull()) { - m_srcSetAttribute = WTFMove(attributeValue); + m_srcSetAttribute = attributeValue.toString(); break; } if (match(attributeName, sizesAttr) && m_sizesAttribute.isNull()) { - m_sizesAttribute = WTFMove(attributeValue); + m_sizesAttribute = attributeValue.toString(); break; } if (m_document.settings().lazyImageLoadingEnabled()) { if (match(attributeName, loadingAttr) && m_lazyloadAttribute.isNull()) { - m_lazyloadAttribute = WTFMove(attributeValue); + m_lazyloadAttribute = attributeValue.toString(); break; } } @@ -226,23 +218,23 @@ class TokenPreloadScanner::StartTagScanner { if (inPicture && alreadyMatchedSource) break; if (match(attributeName, srcsetAttr) && m_srcSetAttribute.isNull()) { - m_srcSetAttribute = WTFMove(attributeValue); + m_srcSetAttribute = attributeValue.toString(); break; } if (match(attributeName, sizesAttr) && m_sizesAttribute.isNull()) { - m_sizesAttribute = WTFMove(attributeValue); + m_sizesAttribute = attributeValue.toString(); break; } if (match(attributeName, mediaAttr) && m_mediaAttribute.isNull()) { - m_mediaAttribute = attributeValue; - auto mediaSet = MediaQuerySet::create(attributeValue, MediaQueryParserContext(m_document)); + m_mediaAttribute = attributeValue.toString(); + auto mediaSet = MediaQuerySet::create(m_mediaAttribute, MediaQueryParserContext(m_document)); RefPtr documentElement = m_document.documentElement(); LOG(MediaQueries, "HTMLPreloadScanner %p processAttribute evaluating media queries", this); m_mediaMatched = MediaQueryEvaluator { m_document.printing() ? "print"_s : "screen"_s, m_document, documentElement ? documentElement->computedStyle() : nullptr }.evaluate(mediaSet.get()); } if (match(attributeName, typeAttr) && m_typeAttribute.isNull()) { // when multiple type attributes present: first value wins, ignore subsequent (to match ImageElement parser and Blink behaviours) - m_typeAttribute = WTFMove(attributeValue); + m_typeAttribute = attributeValue.toString(); m_typeMatched &= MIMETypeRegistry::isSupportedImageVideoOrSVGMIMEType(m_typeAttribute); } break; @@ -254,7 +246,7 @@ class TokenPreloadScanner::StartTagScanner { m_scriptType = ScriptType::ImportMap; break; } else if (match(attributeName, nonceAttr)) { - m_nonceAttribute = WTFMove(attributeValue); + m_nonceAttribute = attributeValue.toString(); break; } else if (match(attributeName, referrerpolicyAttr)) { m_referrerPolicy = parseReferrerPolicy(attributeValue, ReferrerPolicySource::ReferrerPolicyAttribute).value_or(ReferrerPolicy::EmptyString); @@ -270,35 +262,35 @@ class TokenPreloadScanner::StartTagScanner { break; case TagId::Link: if (match(attributeName, hrefAttr)) - setUrlToLoad(attributeValue); + setURLToLoad(attributeValue); else if (match(attributeName, relAttr)) { LinkRelAttribute parsedAttribute { m_document, attributeValue }; m_linkIsStyleSheet = relAttributeIsStyleSheet(parsedAttribute); m_linkIsPreload = parsedAttribute.isLinkPreload; } else if (match(attributeName, mediaAttr)) - m_mediaAttribute = WTFMove(attributeValue); + m_mediaAttribute = attributeValue.toString(); else if (match(attributeName, charsetAttr)) - m_charset = WTFMove(attributeValue); + m_charset = attributeValue.toString(); else if (match(attributeName, crossoriginAttr)) - m_crossOriginMode = stripLeadingAndTrailingHTMLSpaces(attributeValue); + m_crossOriginMode = attributeValue.stripLeadingAndTrailingMatchedCharacters(isHTMLSpace).toString(); else if (match(attributeName, nonceAttr)) - m_nonceAttribute = WTFMove(attributeValue); + m_nonceAttribute = attributeValue.toString(); else if (match(attributeName, asAttr)) - m_asAttribute = WTFMove(attributeValue); + m_asAttribute = attributeValue.toString(); else if (match(attributeName, typeAttr)) - m_typeAttribute = WTFMove(attributeValue); + m_typeAttribute = attributeValue.toString(); else if (match(attributeName, referrerpolicyAttr)) m_referrerPolicy = parseReferrerPolicy(attributeValue, ReferrerPolicySource::ReferrerPolicyAttribute).value_or(ReferrerPolicy::EmptyString); break; case TagId::Input: if (match(attributeName, srcAttr)) - setUrlToLoad(attributeValue); + setURLToLoad(attributeValue); else if (match(attributeName, typeAttr)) m_inputIsImage = equalLettersIgnoringASCIICase(attributeValue, "image"_s); break; case TagId::Meta: if (match(attributeName, contentAttr)) - m_metaContent = WTFMove(attributeValue); + m_metaContent = attributeValue.toString(); else if (match(attributeName, nameAttr)) m_metaIsViewport = equalLettersIgnoringASCIICase(attributeValue, "viewport"_s); else if (m_document.settings().disabledAdaptationsMetaTagEnabled() && match(attributeName, nameAttr)) @@ -318,16 +310,21 @@ class TokenPreloadScanner::StartTagScanner { return parsedAttribute.isStyleSheet && !parsedAttribute.isAlternate && !parsedAttribute.iconType && !parsedAttribute.isDNSPrefetch; } - void setUrlToLoad(const String& value, bool allowReplacement = false) + void setURLToLoad(StringView value) { // We only respect the first src/href, per HTML5: // http://www.whatwg.org/specs/web-apps/current-work/multipage/tokenization.html#attribute-name-state - if (!allowReplacement && !m_urlToLoad.isEmpty()) + if (!m_urlToLoad.isEmpty()) return; - String url = stripLeadingAndTrailingHTMLSpaces(value); - if (url.isEmpty()) + setURLToLoadAllowingReplacement(value); + } + + void setURLToLoadAllowingReplacement(StringView value) + { + auto strippedURL = value.stripLeadingAndTrailingMatchedCharacters(isHTMLSpace); + if (strippedURL.isEmpty()) return; - m_urlToLoad = url; + m_urlToLoad = strippedURL.toString(); } const String& charset() const @@ -386,20 +383,20 @@ class TokenPreloadScanner::StartTagScanner { Document& m_document; TagId m_tagId; String m_urlToLoad; - AtomString m_srcSetAttribute; - AtomString m_sizesAttribute; + String m_srcSetAttribute; + String m_sizesAttribute; bool m_mediaMatched { true }; bool m_typeMatched { true }; String m_charset; String m_crossOriginMode; bool m_linkIsStyleSheet; bool m_linkIsPreload; - AtomString m_mediaAttribute; - AtomString m_nonceAttribute; + String m_mediaAttribute; + String m_nonceAttribute; String m_metaContent; - AtomString m_asAttribute; - AtomString m_typeAttribute; - AtomString m_lazyloadAttribute; + String m_asAttribute; + String m_typeAttribute; + String m_lazyloadAttribute; bool m_metaIsViewport; bool m_metaIsDisabledAdaptations; bool m_inputIsImage; @@ -515,7 +512,7 @@ void HTMLPreloadScanner::scan(HTMLResourcePreloader& preloader, Document& docume while (auto token = m_tokenizer.nextToken(m_source)) { if (token->type() == HTMLToken::Type::StartTag) - m_tokenizer.updateStateFor(AtomString(token->name())); + m_tokenizer.updateStateFor(AtomString::lookUp(token->name().data(), token->name().size())); m_scanner.scan(*token, requests, document); } diff --git a/Source/WebCore/html/parser/HTMLSrcsetParser.cpp b/Source/WebCore/html/parser/HTMLSrcsetParser.cpp index baed32dc589d..dbfcf52311da 100644 --- a/Source/WebCore/html/parser/HTMLSrcsetParser.cpp +++ b/Source/WebCore/html/parser/HTMLSrcsetParser.cpp @@ -257,7 +257,7 @@ static ImageCandidate pickBestImageCandidate(float deviceScaleFactor, Vector parseImageCandidatesFromSrcsetAttribute(StringView attribute); diff --git a/Source/WebCore/html/parser/HTMLTreeBuilder.cpp b/Source/WebCore/html/parser/HTMLTreeBuilder.cpp index 2a8dd78a999d..669c4b1d086a 100644 --- a/Source/WebCore/html/parser/HTMLTreeBuilder.cpp +++ b/Source/WebCore/html/parser/HTMLTreeBuilder.cpp @@ -243,7 +243,7 @@ class HTMLTreeBuilder::ExternalCharacterTokenBuffer { { if (stringView.is8Bit() || !isAll8BitData()) return stringView.toString(); - return String::make8BitFrom16BitSource(stringView.characters16(), stringView.length()); + return String::make8Bit(stringView.characters16(), stringView.length()); } StringView m_text; diff --git a/Source/WebCore/layout/formattingContexts/inline/InlineLineBuilder.cpp b/Source/WebCore/layout/formattingContexts/inline/InlineLineBuilder.cpp index 40f0a85e44eb..823da13bf94d 100644 --- a/Source/WebCore/layout/formattingContexts/inline/InlineLineBuilder.cpp +++ b/Source/WebCore/layout/formattingContexts/inline/InlineLineBuilder.cpp @@ -114,10 +114,10 @@ static inline bool endsWithSoftWrapOpportunity(const InlineTextItem& currentText // We need at least 1 character in the current inline text item and 2 more from previous inline items. auto previousContent = currentTextItem.inlineTextBox().content(); auto currentContent = nextInlineTextItem.inlineTextBox().content(); - if (currentContent.is8Bit() && !previousContent.is8Bit()) { - // FIXME: Remove this workaround when we move over to a better way of handling prior-context with unicode. + if (!previousContent.is8Bit()) { + // FIXME: Remove this workaround when we move over to a better way of handling prior-context with Unicode. // See the templated CharacterType in nextBreakablePosition for last and lastlast characters. - currentContent = String::make16BitFrom8BitSource(currentContent.characters8(), currentContent.length()); + currentContent.convertTo16Bit(); } auto& style = nextInlineTextItem.style(); auto lineBreakIterator = LazyLineBreakIterator { currentContent, style.computedLocale(), TextUtil::lineBreakIteratorMode(style.lineBreak()) }; diff --git a/Source/WebCore/page/PageSerializer.cpp b/Source/WebCore/page/PageSerializer.cpp index 5c9c432eb646..c2bbcecc0461 100644 --- a/Source/WebCore/page/PageSerializer.cpp +++ b/Source/WebCore/page/PageSerializer.cpp @@ -45,6 +45,7 @@ #include "HTMLImageElement.h" #include "HTMLLinkElement.h" #include "HTMLMetaCharsetParser.h" +#include "HTMLMetaElement.h" #include "HTMLNames.h" #include "HTMLObjectElement.h" #include "HTMLStyleElement.h" @@ -66,24 +67,25 @@ namespace WebCore { -static bool isCharsetSpecifyingNode(const Node& node) +static bool isCharsetSpecifyingNode(const HTMLMetaElement& element) { - if (!is(node)) + if (!element.hasAttributes()) return false; - - const HTMLElement& element = downcast(node); - if (!element.hasTagName(HTMLNames::metaTag)) - return false; - HTMLMetaCharsetParser::AttributeList attributes; - if (element.hasAttributes()) { - for (const Attribute& attribute : element.attributesIterator()) { - // FIXME: We should deal appropriately with the attribute if they have a namespace. - attributes.append({ attribute.name().toAtomString(), attribute.value() }); - } + Vector> attributes; + for (auto& attribute : element.attributesIterator()) { + if (attribute.name().hasPrefix()) + continue; + attributes.append({ StringView { attribute.name().localName() }, StringView { attribute.value() } }); } return HTMLMetaCharsetParser::encodingFromMetaAttributes(attributes).isValid(); } +template static bool isCharsetSpecifyingNode(const NodeType& node) +{ + auto* metaElement = dynamicDowncast(node); + return metaElement && isCharsetSpecifyingNode(*metaElement); +} + static bool shouldIgnoreElement(const Element& element) { return element.hasTagName(HTMLNames::scriptTag) || element.hasTagName(HTMLNames::noscriptTag) || isCharsetSpecifyingNode(element); diff --git a/Source/WebCore/platform/glib/ApplicationGLib.cpp b/Source/WebCore/platform/glib/ApplicationGLib.cpp index 629a7ae54d9d..2d55de923a0b 100644 --- a/Source/WebCore/platform/glib/ApplicationGLib.cpp +++ b/Source/WebCore/platform/glib/ApplicationGLib.cpp @@ -19,6 +19,7 @@ #include "config.h" #include "ApplicationGLib.h" +#include #include namespace WebCore { diff --git a/Source/WebCore/platform/graphics/ComplexTextController.cpp b/Source/WebCore/platform/graphics/ComplexTextController.cpp index 0e98f21cabec..0aa22fa2fc2a 100644 --- a/Source/WebCore/platform/graphics/ComplexTextController.cpp +++ b/Source/WebCore/platform/graphics/ComplexTextController.cpp @@ -329,9 +329,11 @@ void ComplexTextController::collectComplexTextRuns() // We need a 16-bit string to pass to Core Text. if (!m_run.is8Bit()) return m_run.characters16(); - String stringFor8BitRun = String::make16BitFrom8BitSource(m_run.characters8(), m_run.length()); - m_stringsFor8BitRuns.append(WTFMove(stringFor8BitRun)); - return m_stringsFor8BitRuns.last().characters16(); + String stringConvertedTo16Bit = m_run.textAsString(); + stringConvertedTo16Bit.convertTo16Bit(); + auto characters = stringConvertedTo16Bit.characters16(); + m_stringsFor8BitRuns.append(WTFMove(stringConvertedTo16Bit)); + return characters; }(); auto fontVariantCaps = m_font.fontDescription().variantCaps(); diff --git a/Source/WebCore/platform/graphics/StringTruncator.cpp b/Source/WebCore/platform/graphics/StringTruncator.cpp index 23b39958ddf6..cd01a12f32f6 100644 --- a/Source/WebCore/platform/graphics/StringTruncator.cpp +++ b/Source/WebCore/platform/graphics/StringTruncator.cpp @@ -93,10 +93,10 @@ static unsigned centerTruncateToBuffer(const String& string, unsigned length, un unsigned truncatedLength = omitStart + shouldInsertEllipsis + (length - omitEnd); ASSERT(truncatedLength <= length); - StringView(string).left(omitStart).getCharactersWithUpconvert(buffer); + StringView(string).left(omitStart).getCharacters(buffer); if (shouldInsertEllipsis) buffer[omitStart++] = horizontalEllipsis; - StringView(string).substring(omitEnd, length - omitEnd).getCharactersWithUpconvert(&buffer[omitStart]); + StringView(string).substring(omitEnd, length - omitEnd).getCharacters(&buffer[omitStart]); return truncatedLength; } @@ -123,7 +123,7 @@ static unsigned rightTruncateToBuffer(const String& string, unsigned length, uns unsigned keepLength = textBreakAtOrPreceding(it, keepCount); unsigned truncatedLength = shouldInsertEllipsis ? keepLength + 1 : keepLength; - StringView(string).left(keepLength).getCharactersWithUpconvert(buffer); + StringView(string).left(keepLength).getCharacters(buffer); if (shouldInsertEllipsis) buffer[keepLength] = horizontalEllipsis; @@ -137,7 +137,7 @@ static unsigned rightClipToCharacterBuffer(const String& string, unsigned length NonSharedCharacterBreakIterator it(StringView(string).left(length)); unsigned keepLength = textBreakAtOrPreceding(it, keepCount); - StringView(string).left(keepLength).getCharactersWithUpconvert(buffer); + StringView(string).left(keepLength).getCharacters(buffer); return keepLength; } @@ -149,7 +149,7 @@ static unsigned rightClipToWordBuffer(const String& string, unsigned length, uns UBreakIterator* it = wordBreakIterator(StringView(string).left(length)); unsigned keepLength = textBreakAtOrPreceding(it, keepCount); - StringView(string).left(keepLength).getCharactersWithUpconvert(buffer); + StringView(string).left(keepLength).getCharacters(buffer); #if PLATFORM(IOS_FAMILY) // FIXME: We should guard this code behind an editing behavior. Then we can remove the PLATFORM(IOS_FAMILY)-guard. @@ -186,10 +186,10 @@ static unsigned leftTruncateToBuffer(const String& string, unsigned length, unsi if (shouldInsertEllipsis) { buffer[0] = horizontalEllipsis; - StringView(string).substring(adjustedStartIndex, length - adjustedStartIndex + 1).getCharactersWithUpconvert(&buffer[1]); + StringView(string).substring(adjustedStartIndex, length - adjustedStartIndex + 1).getCharacters(&buffer[1]); return length - adjustedStartIndex + 1; } - StringView(string).substring(adjustedStartIndex, length - adjustedStartIndex + 1).getCharactersWithUpconvert(&buffer[0]); + StringView(string).substring(adjustedStartIndex, length - adjustedStartIndex + 1).getCharacters(&buffer[0]); return length - adjustedStartIndex; } @@ -224,7 +224,7 @@ static String truncateString(const String& string, float maxWidth, const FontCas truncatedLength = centerTruncateToBuffer(string, length, keepCount, stringBuffer, shouldInsertEllipsis); } else { keepCount = length; - StringView(string).getCharactersWithUpconvert(stringBuffer); + StringView(string).getCharacters(stringBuffer); truncatedLength = length; } diff --git a/Source/WebCore/platform/graphics/TextRun.h b/Source/WebCore/platform/graphics/TextRun.h index 408dcffaec7b..cfac8fd8394b 100644 --- a/Source/WebCore/platform/graphics/TextRun.h +++ b/Source/WebCore/platform/graphics/TextRun.h @@ -154,6 +154,8 @@ class TextRun { TextRun isolatedCopy() const; + const String& textAsString() const { return m_text; } + private: String m_text; diff --git a/Source/WebCore/platform/graphics/gstreamer/eme/GStreamerEMEUtilities.h b/Source/WebCore/platform/graphics/gstreamer/eme/GStreamerEMEUtilities.h index f78f876f1a68..184c5c3e5f77 100644 --- a/Source/WebCore/platform/graphics/gstreamer/eme/GStreamerEMEUtilities.h +++ b/Source/WebCore/platform/graphics/gstreamer/eme/GStreamerEMEUtilities.h @@ -180,7 +180,7 @@ class GStreamerEMEUtilities { return { }; } - static const ASCIILiteral& uuidToKeySystem(const String& uuid) + static ASCIILiteral uuidToKeySystem(const String& uuid) { if (isClearKeyUUID(uuid)) return s_ClearKeyKeySystem; @@ -197,8 +197,7 @@ class GStreamerEMEUtilities { #endif ASSERT_NOT_REACHED(); - static NeverDestroyed empty(""_s); - return empty; + return ""_s; } }; diff --git a/Source/WebCore/platform/graphics/win/FontCacheWin.cpp b/Source/WebCore/platform/graphics/win/FontCacheWin.cpp index 8976ec43288d..86dcc0584a54 100644 --- a/Source/WebCore/platform/graphics/win/FontCacheWin.cpp +++ b/Source/WebCore/platform/graphics/win/FontCacheWin.cpp @@ -326,7 +326,7 @@ RefPtr FontCache::systemFallbackForCharacters(const FontDescription& descr LOGFONT logFont; logFont.lfCharSet = DEFAULT_CHARSET; - StringView(linkedFonts->at(linkedFontIndex)).getCharactersWithUpconvert(ucharFrom(logFont.lfFaceName)); + StringView(linkedFonts->at(linkedFontIndex)).getCharacters(ucharFrom(logFont.lfFaceName)); logFont.lfFaceName[linkedFonts->at(linkedFontIndex).length()] = 0; EnumFontFamiliesEx(hdc, &logFont, linkedFontEnumProc, reinterpret_cast(&hfont), 0); linkedFontIndex++; @@ -518,7 +518,7 @@ static GDIObject createGDIFont(const AtomString& family, LONG desiredWeig LOGFONT logFont; logFont.lfCharSet = DEFAULT_CHARSET; StringView truncatedFamily = StringView(family).left(static_cast(LF_FACESIZE - 1)); - truncatedFamily.getCharactersWithUpconvert(ucharFrom(logFont.lfFaceName)); + truncatedFamily.getCharacters(ucharFrom(logFont.lfFaceName)); logFont.lfFaceName[truncatedFamily.length()] = 0; logFont.lfPitchAndFamily = 0; @@ -632,7 +632,7 @@ Vector FontCache::getFontSelectionCapabilitiesInFamil LOGFONT logFont; logFont.lfCharSet = DEFAULT_CHARSET; StringView truncatedFamily = StringView(familyName).left(static_cast(LF_FACESIZE - 1)); - truncatedFamily.getCharactersWithUpconvert(ucharFrom(logFont.lfFaceName)); + truncatedFamily.getCharacters(ucharFrom(logFont.lfFaceName)); logFont.lfFaceName[truncatedFamily.length()] = 0; logFont.lfPitchAndFamily = 0; diff --git a/Source/WebCore/platform/mediastream/CaptureDevice.h b/Source/WebCore/platform/mediastream/CaptureDevice.h index e50dccf5d5dd..7a4acc94f3a3 100644 --- a/Source/WebCore/platform/mediastream/CaptureDevice.h +++ b/Source/WebCore/platform/mediastream/CaptureDevice.h @@ -25,6 +25,7 @@ #pragma once +#include #include namespace WebCore { diff --git a/Source/WebCore/platform/win/ClipboardUtilitiesWin.cpp b/Source/WebCore/platform/win/ClipboardUtilitiesWin.cpp index 8d57fb62da9b..726b26ae3157 100644 --- a/Source/WebCore/platform/win/ClipboardUtilitiesWin.cpp +++ b/Source/WebCore/platform/win/ClipboardUtilitiesWin.cpp @@ -167,7 +167,7 @@ HGLOBAL createGlobalData(const String& str) if (!vm) return 0; UChar* buffer = static_cast(GlobalLock(vm)); - StringView(str).getCharactersWithUpconvert(buffer); + StringView(str).getCharacters(buffer); buffer[str.length()] = 0; GlobalUnlock(vm); return vm; diff --git a/Source/WebCore/platform/win/PasteboardWin.cpp b/Source/WebCore/platform/win/PasteboardWin.cpp index cff81b5ce4fd..c9f46f585142 100644 --- a/Source/WebCore/platform/win/PasteboardWin.cpp +++ b/Source/WebCore/platform/win/PasteboardWin.cpp @@ -605,7 +605,7 @@ static String fileSystemPathFromURLOrTitle(const String& urlString, const String if (!title.isEmpty()) { size_t len = std::min(title.length(), fsPathMaxLengthExcludingExtension); - StringView(title).left(len).getCharactersWithUpconvert(fsPathBuffer); + StringView(title).left(len).getCharacters(fsPathBuffer); fsPathBuffer[len] = 0; pathRemoveBadFSCharacters(wcharFrom(fsPathBuffer), len); } @@ -620,10 +620,10 @@ static String fileSystemPathFromURLOrTitle(const String& urlString, const String auto lastComponent = url.lastPathComponent(); if (url.isLocalFile() || (!isLink && !lastComponent.isEmpty())) { len = std::min(fsPathMaxLengthExcludingExtension, lastComponent.length()); - lastComponent.left(len).getCharactersWithUpconvert(fsPathBuffer); + lastComponent.left(len).getCharacters(fsPathBuffer); } else { len = std::min(fsPathMaxLengthExcludingExtension, urlString.length()); - StringView(urlString).left(len).getCharactersWithUpconvert(fsPathBuffer); + StringView(urlString).left(len).getCharacters(fsPathBuffer); } fsPathBuffer[len] = 0; pathRemoveBadFSCharacters(wcharFrom(fsPathBuffer), len); @@ -721,7 +721,7 @@ void Pasteboard::writeURLToDataObject(const URL& kurl, const String& titleStr) fgd->fgd[0].nFileSizeLow = content.length(); unsigned maxSize = std::min(fsPath.length(), WTF_ARRAY_LENGTH(fgd->fgd[0].cFileName)); - StringView(fsPath).left(maxSize).getCharactersWithUpconvert(ucharFrom(fgd->fgd[0].cFileName)); + StringView(fsPath).left(maxSize).getCharacters(ucharFrom(fgd->fgd[0].cFileName)); GlobalUnlock(urlFileDescriptor); char* fileContents = static_cast(GlobalLock(urlFileContent)); @@ -959,7 +959,7 @@ static HGLOBAL createGlobalImageFileDescriptor(const String& url, const String& } int maxSize = std::min(fsPath.length(), WTF_ARRAY_LENGTH(fgd->fgd[0].cFileName)); - StringView(fsPath).left(maxSize).getCharactersWithUpconvert(ucharFrom(fgd->fgd[0].cFileName)); + StringView(fsPath).left(maxSize).getCharacters(ucharFrom(fgd->fgd[0].cFileName)); GlobalUnlock(memObj); return memObj; diff --git a/Source/WebCore/platform/xr/openxr/OpenXRInstance.cpp b/Source/WebCore/platform/xr/openxr/OpenXRInstance.cpp index d5ca70875f1d..6ac0863d5b9f 100644 --- a/Source/WebCore/platform/xr/openxr/OpenXRInstance.cpp +++ b/Source/WebCore/platform/xr/openxr/OpenXRInstance.cpp @@ -23,7 +23,7 @@ #include "OpenXRExtensions.h" #include "PlatformXROpenXR.h" - +#include #include using namespace WebCore; diff --git a/Source/WebKit/Platform/LogInitialization.cpp b/Source/WebKit/Platform/LogInitialization.cpp index 1c63a54b0c1d..aa8b8636f01f 100644 --- a/Source/WebKit/Platform/LogInitialization.cpp +++ b/Source/WebKit/Platform/LogInitialization.cpp @@ -27,6 +27,7 @@ #include "LogInitialization.h" #include "Logging.h" +#include #include namespace WebKit { diff --git a/Source/WebKit/Shared/API/c/WKString.cpp b/Source/WebKit/Shared/API/c/WKString.cpp index 48238eba0556..43b7e5ec683d 100644 --- a/Source/WebKit/Shared/API/c/WKString.cpp +++ b/Source/WebKit/Shared/API/c/WKString.cpp @@ -60,7 +60,7 @@ size_t WKStringGetCharacters(WKStringRef stringRef, WKChar* buffer, size_t buffe unsigned unsignedBufferLength = std::min(bufferLength, std::numeric_limits::max()); auto substring = WebKit::toImpl(stringRef)->stringView().left(unsignedBufferLength); - substring.getCharactersWithUpconvert(reinterpret_cast(buffer)); + substring.getCharacters(reinterpret_cast(buffer)); return substring.length(); } diff --git a/Source/WebKit/UIProcess/Inspector/mac/WebInspectorUIProxyMac.mm b/Source/WebKit/UIProcess/Inspector/mac/WebInspectorUIProxyMac.mm index 484d81c67442..a5d33eed0c22 100644 --- a/Source/WebKit/UIProcess/Inspector/mac/WebInspectorUIProxyMac.mm +++ b/Source/WebKit/UIProcess/Inspector/mac/WebInspectorUIProxyMac.mm @@ -399,7 +399,8 @@ - (IBAction)_popUpButtonAction:(id)sender ASSERT(actualURL); if ([controller base64Encoded]) { - auto decodedData = base64Decode([controller content], Base64DecodeOptions::ValidatePadding); + String contentString = [controller content]; + auto decodedData = base64Decode(contentString, Base64DecodeOptions::ValidatePadding); if (!decodedData) return; auto dataContent = adoptNS([[NSData alloc] initWithBytes:decodedData->data() length:decodedData->size()]); diff --git a/Source/WebKit/webpushd/PushService.mm b/Source/WebKit/webpushd/PushService.mm index f0b3627c5087..b57c48592ff5 100644 --- a/Source/WebKit/webpushd/PushService.mm +++ b/Source/WebKit/webpushd/PushService.mm @@ -599,6 +599,18 @@ void reject(WebCore::ExceptionData&& data) }; +static std::optional> base64URLDecode(NSString *string) +{ + String coreString = string; + return WTF::base64URLDecode(coreString); +} + +static std::optional> base64Decode(NSString *string) +{ + String coreString = string; + return WTF::base64Decode(coreString); +} + static std::optional makeRawPushMessage(NSString *topic, NSDictionary* userInfo) { RawPushMessage message; diff --git a/Source/WebKitLegacy/win/DOMCoreClasses.cpp b/Source/WebKitLegacy/win/DOMCoreClasses.cpp index fc43aa13bdc7..13b52fc32bce 100644 --- a/Source/WebKitLegacy/win/DOMCoreClasses.cpp +++ b/Source/WebKitLegacy/win/DOMCoreClasses.cpp @@ -1292,9 +1292,9 @@ HRESULT DOMElement::font(_Out_ WebFontDescription* webFontDescription) auto fontDescription = renderer->style().fontCascade().fontDescription(); AtomString family = fontDescription.firstFamily(); - // FIXME: This leaks. Delete this whole function to get rid of the leak. + // FIXME: This leaks. Delete this whole function, which probably is unused, to get rid of the leak. UChar* familyCharactersBuffer = new UChar[family.length()]; - StringView(family.string()).getCharactersWithUpconvert(familyCharactersBuffer); + StringView(family.string()).getCharacters(familyCharactersBuffer); webFontDescription->family = wcharFrom(familyCharactersBuffer); webFontDescription->familyLength = family.length(); diff --git a/Source/WebKitLegacy/win/WebKitGraphics.cpp b/Source/WebKitLegacy/win/WebKitGraphics.cpp index 9ab97b3c862f..5724715943a4 100644 --- a/Source/WebKitLegacy/win/WebKitGraphics.cpp +++ b/Source/WebKitLegacy/win/WebKitGraphics.cpp @@ -113,7 +113,7 @@ unsigned CenterTruncateStringToWidth(LPCTSTR text, int length, const WebFontDesc ASSERT(buffer); String result = StringTruncator::centerTruncate(String(text, length), width, makeFont(description)); - StringView(result).getCharactersWithUpconvert(buffer); + StringView(result).getCharacters(buffer); buffer[result.length()] = '\0'; return result.length(); } @@ -123,7 +123,7 @@ unsigned RightTruncateStringToWidth(LPCTSTR text, int length, const WebFontDescr ASSERT(buffer); String result = StringTruncator::rightTruncate(String(text, length), width, makeFont(description)); - StringView(result).getCharactersWithUpconvert(buffer); + StringView(result).getCharacters(buffer); buffer[result.length()] = '\0'; return result.length(); } diff --git a/Source/WebKitLegacy/win/WebView.cpp b/Source/WebKitLegacy/win/WebView.cpp index 6b8d6a839652..536129beeaf9 100644 --- a/Source/WebKitLegacy/win/WebView.cpp +++ b/Source/WebKitLegacy/win/WebView.cpp @@ -6217,7 +6217,7 @@ LRESULT WebView::onIMERequestReconvertString(Frame* targetFrame, RECONVERTSTRING reconvertString->dwStrLen = text.length(); reconvertString->dwTargetStrLen = text.length(); reconvertString->dwStrOffset = sizeof(RECONVERTSTRING); - StringView(text).getCharactersWithUpconvert(reinterpret_cast(reconvertString + 1)); + StringView(text).getCharacters(reinterpret_cast(reconvertString + 1)); return totalSize; } diff --git a/Tools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp b/Tools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp index dc5a8ef79267..9a231a11463d 100644 --- a/Tools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp +++ b/Tools/WebKitTestRunner/InjectedBundle/InjectedBundlePage.cpp @@ -49,6 +49,7 @@ #include #include #include +#include #include #include #include