diff options
Diffstat (limited to 'src/bun.js')
m--------- | src/bun.js/WebKit | 0 | ||||
-rw-r--r-- | src/bun.js/bindings/URLDecomposition.cpp | 37 | ||||
-rw-r--r-- | src/bun.js/bindings/ZigGlobalObject.cpp | 2 | ||||
-rw-r--r-- | src/bun.js/bindings/bindings.cpp | 2 | ||||
-rw-r--r-- | src/bun.js/bindings/sqlite/JSSQLStatement.cpp | 2 | ||||
-rw-r--r-- | src/bun.js/bindings/webcore/FetchHeaders.cpp | 8 | ||||
-rw-r--r-- | src/bun.js/bindings/webcore/HTTPHeaderField.cpp | 20 | ||||
-rw-r--r-- | src/bun.js/bindings/webcore/HTTPParsers.cpp | 393 | ||||
-rw-r--r-- | src/bun.js/bindings/webcore/HTTPParsers.h | 114 | ||||
-rw-r--r-- | src/bun.js/bindings/webcore/JSDOMConvertStrings.cpp | 2 | ||||
-rw-r--r-- | src/bun.js/bindings/webcore/JSTextEncoder.cpp | 13 | ||||
-rw-r--r-- | src/bun.js/bindings/webcore/ParsedContentType.cpp | 10 | ||||
-rw-r--r-- | src/bun.js/bindings/webcore/ReadableStreamSink.cpp | 2 | ||||
-rw-r--r-- | src/bun.js/bindings/webcore/ReadableStreamSink.h | 7 | ||||
-rw-r--r-- | src/bun.js/bindings/webcore/SerializedScriptValue.cpp | 10 | ||||
-rw-r--r-- | src/bun.js/bindings/webcore/SharedBuffer.cpp | 6 | ||||
-rw-r--r-- | src/bun.js/bindings/webcore/SharedBuffer.h | 14 |
17 files changed, 262 insertions, 380 deletions
diff --git a/src/bun.js/WebKit b/src/bun.js/WebKit -Subproject ecf1b9c4bc2247020add7b14a732bb0085f25d5 +Subproject 284095ff91529df883cf5ab30d66048a3207bad diff --git a/src/bun.js/bindings/URLDecomposition.cpp b/src/bun.js/bindings/URLDecomposition.cpp index 14cf25b6c..d3f11b27f 100644 --- a/src/bun.js/bindings/URLDecomposition.cpp +++ b/src/bun.js/bindings/URLDecomposition.cpp @@ -62,7 +62,7 @@ String URLDecomposition::username() const void URLDecomposition::setUsername(StringView user) { auto fullURL = this->fullURL(); - if (fullURL.host().isEmpty() || fullURL.cannotBeABaseURL() || fullURL.protocolIs("file"_s)) + if (fullURL.host().isEmpty() || fullURL.protocolIsFile()) return; fullURL.setUser(user); setFullURL(fullURL); @@ -76,7 +76,7 @@ String URLDecomposition::password() const void URLDecomposition::setPassword(StringView password) { auto fullURL = this->fullURL(); - if (fullURL.host().isEmpty() || fullURL.cannotBeABaseURL() || fullURL.protocolIs("file"_s)) + if (fullURL.host().isEmpty() || fullURL.protocolIsFile()) return; fullURL.setPassword(password); setFullURL(fullURL); @@ -100,14 +100,14 @@ static unsigned countASCIIDigits(StringView string) void URLDecomposition::setHost(StringView value) { auto fullURL = this->fullURL(); - if (value.isEmpty() && !fullURL.protocolIs("file"_s) && fullURL.hasSpecialScheme()) + if (value.isEmpty() && !fullURL.protocolIsFile() && fullURL.hasSpecialScheme()) return; size_t separator = value.reverseFind(':'); if (!separator) return; - if (fullURL.cannotBeABaseURL() || !fullURL.canSetHostOrPort()) + if (fullURL.hasOpaquePath()) return; // No port if no colon or rightmost colon is within the IPv6 section. @@ -120,13 +120,13 @@ void URLDecomposition::setHost(StringView value) return; unsigned portLength = countASCIIDigits(value.substring(separator + 1)); if (!portLength) { - fullURL.setHost(value.substring(0, separator)); + fullURL.setHost(value.left(separator)); } else { auto portNumber = parseInteger<uint16_t>(value.substring(separator + 1, portLength)); if (portNumber && WTF::isDefaultPortForProtocol(*portNumber, fullURL.protocol())) - fullURL.setHostAndPort(value.substring(0, separator)); + fullURL.setHostAndPort(value.left(separator)); else - fullURL.setHostAndPort(value.substring(0, separator + 1 + portLength)); + fullURL.setHostAndPort(value.left(separator + 1 + portLength)); } } if (fullURL.isValid()) @@ -138,24 +138,12 @@ String URLDecomposition::hostname() const return fullURL().host().toString(); } -static StringView removeAllLeadingSolidusCharacters(StringView string) -{ - unsigned i; - unsigned length = string.length(); - for (i = 0; i < length; ++i) { - if (string[i] != '/') - break; - } - return string.substring(i); -} - -void URLDecomposition::setHostname(StringView value) +void URLDecomposition::setHostname(StringView host) { auto fullURL = this->fullURL(); - auto host = removeAllLeadingSolidusCharacters(value); - if (host.isEmpty() && !fullURL.protocolIs("file"_s) && fullURL.hasSpecialScheme()) + if (host.isEmpty() && !fullURL.protocolIsFile() && fullURL.hasSpecialScheme()) return; - if (fullURL.cannotBeABaseURL() || !fullURL.canSetHostOrPort()) + if (fullURL.hasOpaquePath()) return; fullURL.setHost(host); if (fullURL.isValid()) @@ -200,7 +188,7 @@ static std::optional<std::optional<uint16_t>> parsePort(StringView string, Strin void URLDecomposition::setPort(StringView value) { auto fullURL = this->fullURL(); - if (fullURL.host().isEmpty() || fullURL.cannotBeABaseURL() || fullURL.protocolIs("file"_s) || !fullURL.canSetHostOrPort()) + if (fullURL.host().isEmpty() || fullURL.protocolIsFile()) return; auto port = parsePort(value, fullURL.protocol()); if (!port) @@ -217,7 +205,7 @@ String URLDecomposition::pathname() const void URLDecomposition::setPathname(StringView value) { auto fullURL = this->fullURL(); - if (fullURL.cannotBeABaseURL() || !fullURL.canSetPathname()) + if (fullURL.hasOpaquePath()) return; fullURL.setPath(value); setFullURL(fullURL); @@ -236,7 +224,6 @@ void URLDecomposition::setSearch(const String& value) // If the given value is the empty string, set url's query to null. fullURL.setQuery({}); } else { - String newSearch = value; // Make sure that '#' in the query does not leak to the hash. fullURL.setQuery(makeStringByReplacingAll(value, '#', "%23"_s)); } diff --git a/src/bun.js/bindings/ZigGlobalObject.cpp b/src/bun.js/bindings/ZigGlobalObject.cpp index 52f633f3d..759217ed1 100644 --- a/src/bun.js/bindings/ZigGlobalObject.cpp +++ b/src/bun.js/bindings/ZigGlobalObject.cpp @@ -1312,7 +1312,7 @@ JSC_DEFINE_HOST_FUNCTION(functionBTOA, return JSC::JSValue::encode(JSC::jsEmptyString(vm)); } - if (!encodedString.isAllLatin1()) { + if (!encodedString.containsOnlyLatin1()) { throwException(globalObject, throwScope, createDOMException(globalObject, InvalidCharacterError)); return JSC::JSValue::encode(JSC::JSValue {}); } diff --git a/src/bun.js/bindings/bindings.cpp b/src/bun.js/bindings/bindings.cpp index 9fb0c18d5..981a475a3 100644 --- a/src/bun.js/bindings/bindings.cpp +++ b/src/bun.js/bindings/bindings.cpp @@ -1256,7 +1256,7 @@ void WebCore__DOMURL__pathname_(WebCore__DOMURL* domURL, ZigString* arg1) BunString WebCore__DOMURL__fileSystemPath(WebCore__DOMURL* arg0) { const WTF::URL& url = arg0->href(); - if (url.isLocalFile()) { + if (url.protocolIsFile()) { return Bun::toString(url.fileSystemPath()); } diff --git a/src/bun.js/bindings/sqlite/JSSQLStatement.cpp b/src/bun.js/bindings/sqlite/JSSQLStatement.cpp index 61ac91ba7..0e5fa18d8 100644 --- a/src/bun.js/bindings/sqlite/JSSQLStatement.cpp +++ b/src/bun.js/bindings/sqlite/JSSQLStatement.cpp @@ -358,7 +358,7 @@ static inline bool rebindValue(JSC::JSGlobalObject* lexicalGlobalObject, sqlite3 return false; } - if (roped.is8Bit() && roped.isAllASCII()) { + if (roped.is8Bit() && roped.containsOnlyASCII()) { CHECK_BIND(sqlite3_bind_text(stmt, i, reinterpret_cast<const char*>(roped.characters8()), roped.length(), transientOrStatic)); } else if (!roped.is8Bit()) { CHECK_BIND(sqlite3_bind_text16(stmt, i, roped.characters16(), roped.length() * 2, transientOrStatic)); diff --git a/src/bun.js/bindings/webcore/FetchHeaders.cpp b/src/bun.js/bindings/webcore/FetchHeaders.cpp index 9d8572faf..02a3c8b3a 100644 --- a/src/bun.js/bindings/webcore/FetchHeaders.cpp +++ b/src/bun.js/bindings/webcore/FetchHeaders.cpp @@ -63,7 +63,7 @@ static ExceptionOr<bool> canWriteHeader(const String& name, const String& value, static ExceptionOr<void> appendToHeaderMap(const String& name, const String& value, HTTPHeaderMap& headers, FetchHeaders::Guard guard) { - String normalizedValue = stripLeadingAndTrailingHTTPSpaces(value); + String normalizedValue = value.trim(isHTTPSpace); String combinedValue = normalizedValue; HTTPHeaderName headerName; if (findHTTPHeaderName(name, headerName)) { @@ -107,7 +107,7 @@ static ExceptionOr<void> appendToHeaderMap(const String& name, const String& val static ExceptionOr<void> appendToHeaderMap(const HTTPHeaderMap::HTTPHeaderMapConstIterator::KeyValue& header, HTTPHeaderMap& headers, FetchHeaders::Guard guard) { - String normalizedValue = stripLeadingAndTrailingHTTPSpaces(header.value); + String normalizedValue = header.value.trim(isHTTPSpace); auto canWriteResult = canWriteHeader(header.key, normalizedValue, header.value, guard); if (canWriteResult.hasException()) return canWriteResult.releaseException(); @@ -229,7 +229,7 @@ ExceptionOr<bool> FetchHeaders::has(const String& name) const ExceptionOr<void> FetchHeaders::set(const String& name, const String& value) { - String normalizedValue = stripLeadingAndTrailingHTTPSpaces(value); + String normalizedValue = value.trim(isHTTPSpace); auto canWriteResult = canWriteHeader(name, normalizedValue, normalizedValue, m_guard); if (canWriteResult.hasException()) return canWriteResult.releaseException(); @@ -248,7 +248,7 @@ ExceptionOr<void> FetchHeaders::set(const String& name, const String& value) void FetchHeaders::filterAndFill(const HTTPHeaderMap& headers, Guard guard) { for (auto& header : headers) { - String normalizedValue = stripLeadingAndTrailingHTTPSpaces(header.value); + String normalizedValue = header.value.trim(isHTTPSpace); auto canWriteResult = canWriteHeader(header.key, normalizedValue, header.value, guard); if (canWriteResult.hasException()) continue; diff --git a/src/bun.js/bindings/webcore/HTTPHeaderField.cpp b/src/bun.js/bindings/webcore/HTTPHeaderField.cpp index a4d101bdd..bdcd3e3be 100644 --- a/src/bun.js/bindings/webcore/HTTPHeaderField.cpp +++ b/src/bun.js/bindings/webcore/HTTPHeaderField.cpp @@ -29,7 +29,7 @@ namespace WebCore { namespace RFC7230 { - + bool isTokenCharacter(UChar c) { return isASCIIAlpha(c) || isASCIIDigit(c) @@ -118,7 +118,7 @@ static bool isValidValue(StringView value) State state = State::OptionalWhitespace; size_t commentDepth = 0; bool hadNonWhitespace = false; - + for (size_t i = 0; i < value.length(); ++i) { UChar c = value[i]; switch (state) { @@ -141,7 +141,7 @@ static bool isValidValue(StringView value) continue; } return false; - + case State::Token: if (isTokenCharacter(c)) continue; @@ -187,7 +187,7 @@ static bool isValidValue(StringView value) continue; } } - + switch (state) { case State::OptionalWhitespace: case State::Token: @@ -204,14 +204,14 @@ static bool isValidValue(StringView value) std::optional<HTTPHeaderField> HTTPHeaderField::create(String&& unparsedName, String&& unparsedValue) { - StringView strippedName = StringView(unparsedName).stripLeadingAndTrailingMatchedCharacters(RFC7230::isWhitespace); - StringView strippedValue = StringView(unparsedValue).stripLeadingAndTrailingMatchedCharacters(RFC7230::isWhitespace); - if (!RFC7230::isValidName(strippedName) || !RFC7230::isValidValue(strippedValue)) + auto trimmedName = StringView(unparsedName).trim(isTabOrSpace<UChar>); + auto trimmedValue = StringView(unparsedValue).trim(isTabOrSpace<UChar>); + if (!RFC7230::isValidName(trimmedName) || !RFC7230::isValidValue(trimmedValue)) return std::nullopt; - String name = strippedName.length() == unparsedName.length() ? WTFMove(unparsedName) : strippedName.toString(); - String value = strippedValue.length() == unparsedValue.length() ? WTFMove(unparsedValue) : strippedValue.toString(); - return {{ WTFMove(name), WTFMove(value) }}; + auto name = trimmedName.length() == unparsedName.length() ? WTFMove(unparsedName) : trimmedName.toString(); + auto value = trimmedValue.length() == unparsedValue.length() ? WTFMove(unparsedValue) : trimmedValue.toString(); + return { { WTFMove(name), WTFMove(value) } }; } } diff --git a/src/bun.js/bindings/webcore/HTTPParsers.cpp b/src/bun.js/bindings/webcore/HTTPParsers.cpp index a696be94c..f2c4ff989 100644 --- a/src/bun.js/bindings/webcore/HTTPParsers.cpp +++ b/src/bun.js/bindings/webcore/HTTPParsers.cpp @@ -62,7 +62,7 @@ static inline bool skipWhile(const String& str, unsigned& pos, const Function<bo // Note: Might return pos == str.length() static inline bool skipWhiteSpace(const String& str, unsigned& pos) { - skipWhile(str, pos, RFC7230::isWhitespace); + skipWhile(str, pos, isTabOrSpace<UChar>); return pos < str.length(); } @@ -100,7 +100,7 @@ static inline bool skipValue(const String& str, unsigned& pos) unsigned start = pos; unsigned len = str.length(); while (pos < len) { - if (str[pos] == ' ' || str[pos] == '\t' || str[pos] == ';') + if (isTabOrSpace(str[pos]) || str[pos] == ';') break; ++pos; } @@ -122,20 +122,28 @@ bool isValidReasonPhrase(const String& value) bool isValidHTTPHeaderValue(const String& value) { UChar c = value[0]; - if (c == ' ' || c == '\t') + if (isTabOrSpace(c)) return false; c = value[value.length() - 1]; - if (c == ' ' || c == '\t') + if (isTabOrSpace(c)) return false; - for (unsigned i = 0; i < value.length(); ++i) { - c = value[i]; - if (c == 0x00 || c == 0x0A || c == 0x0D) - return false; - - //NOTE: The spec doesn't require ASCII or Latin1 but common - // implementations, including Node, disallow codepoints > 255 - if (c > 255) return false; + if (value.is8Bit()) { + const LChar* end = value.characters8() + value.length(); + for (const LChar* p = value.characters8(); p != end; ++p) { + if (UNLIKELY(*p <= 13)) { + LChar c = *p; + if (c == 0x00 || c == 0x0A || c == 0x0D) + return false; + } + } + } else { + for (unsigned i = 0; i < value.length(); ++i) { + c = value[i]; + if (c == 0x00 || c == 0x0A || c == 0x0D || c > 0x7F) + return false; + } } + return true; } @@ -342,12 +350,12 @@ StringView filenameFromHTTPContentDisposition(StringView value) if (valueStartPos == notFound) continue; - auto key = keyValuePair.left(valueStartPos).stripWhiteSpace(); + auto key = keyValuePair.left(valueStartPos).trim(isUnicodeCompatibleASCIIWhitespace<UChar>); if (key.isEmpty() || key != "filename"_s) continue; - auto value = keyValuePair.substring(valueStartPos + 1).stripWhiteSpace(); + auto value = keyValuePair.substring(valueStartPos + 1).trim(isUnicodeCompatibleASCIIWhitespace<UChar>); // Remove quotes if there are any if (value.length() > 1 && value[0] == '\"') @@ -366,7 +374,7 @@ String extractMIMETypeFromMediaType(const String& mediaType) for (; position < length; ++position) { UChar c = mediaType[position]; - if (c != '\t' && c != ' ') + if (!isTabOrSpace(c)) break; } @@ -388,7 +396,7 @@ String extractMIMETypeFromMediaType(const String& mediaType) if (c == ',') break; - if (c == '\t' || c == ' ' || c == ';') + if (isTabOrSpace(c) || c == ';') break; typeEnd = position + 1; @@ -535,7 +543,7 @@ XSSProtectionDisposition parseXSSProtectionHeader(const String& header, String& ContentTypeOptionsDisposition parseContentTypeOptionsHeader(StringView header) { StringView leftToken = header.left(header.find(',')); - if (equalLettersIgnoringASCIICase(stripLeadingAndTrailingHTTPSpaces(leftToken), "nosniff"_s)) + if (equalLettersIgnoringASCIICase(leftToken.trim(isJSONOrHTTPWhitespace<UChar>), "nosniff"_s)) return ContentTypeOptionsDisposition::Nosniff; return ContentTypeOptionsDisposition::None; } @@ -562,8 +570,8 @@ XFrameOptionsDisposition parseXFrameOptionsHeader(StringView header) if (header.isEmpty()) return result; - for (auto currentHeader : header.split(',')) { - currentHeader = currentHeader.stripWhiteSpace(); + for (auto currentHeader : header.splitAllowingEmptyEntries(',')) { + currentHeader = currentHeader.trim(isUnicodeCompatibleASCIIWhitespace<UChar>); XFrameOptionsDisposition currentValue = XFrameOptionsDisposition::None; if (equalLettersIgnoringASCIICase(currentHeader, "deny"_s)) currentValue = XFrameOptionsDisposition::Deny; @@ -582,108 +590,54 @@ XFrameOptionsDisposition parseXFrameOptionsHeader(StringView header) return result; } -// https://fetch.spec.whatwg.org/#concept-header-list-get-structured-header -// FIXME: For now, this assumes the type is "item". -std::optional<std::pair<StringView, HashMap<String, String>>> parseStructuredFieldValue(StringView header) -{ - header = stripLeadingAndTrailingHTTPSpaces(header); - if (header.isEmpty()) - return std::nullopt; - - // Parse a token (https://datatracker.ietf.org/doc/html/rfc8941#section-4.2.6). - if (!isASCIIAlpha(header[0]) && header[0] != '*') - return std::nullopt; - size_t index = 1; - while (index < header.length()) { - UChar c = header[index]; - if (!RFC7230::isTokenCharacter(c) && c != ':' && c != '/') - break; - ++index; - } - StringView bareItem = header.left(index); - - // Parse parameters (https://datatracker.ietf.org/doc/html/rfc8941#section-4.2.3.2). - HashMap<String, String> parameters; - while (index < header.length()) { - if (header[index] != ';') - break; - ++index; // Consume ';'. - while (index < header.length() && header[index] == ' ') - ++index; - if (index == header.length()) - return std::nullopt; - // Parse a key (https://datatracker.ietf.org/doc/html/rfc8941#section-4.2.3.3) - if (!isASCIILower(header[index])) - return std::nullopt; - size_t keyStart = index++; - while (index < header.length()) { - UChar c = header[index]; - if (!isASCIILower(c) && !isASCIIDigit(c) && c != '_' && c != '-' && c != '.' && c != '*') - break; - ++index; - } - StringView key = header.substring(keyStart, index - keyStart); - String value = trueAtom(); - if (index < header.length() && header[index] == '=') { - ++index; // Consume '='. - if (isASCIIAlpha(header[index]) || header[index] == '*') { - // https://datatracker.ietf.org/doc/html/rfc8941#section-4.2.6 - size_t valueStart = index++; - while (index < header.length()) { - UChar c = header[index]; - if (!RFC7230::isTokenCharacter(c) && c != ':' && c != '/') - break; - ++index; - } - value = header.substring(valueStart, index - valueStart).toString(); - } else if (header[index] == '"') { - // https://datatracker.ietf.org/doc/html/rfc8941#section-4.2.5 - StringBuilder valueBuilder; - ++index; // Skip DQUOTE. - while (index < header.length()) { - if (header[index] == '\\') { - ++index; - if (index == header.length()) - return std::nullopt; - if (header[index] != '\\' && header[index] != '"') - return std::nullopt; - valueBuilder.append(header[index]); - } else if (header[index] == '\"') { - value = valueBuilder.toString(); - break; - } else if (header[index] <= 0x1F || (header[index] >= 0x7F && header[index] <= 0xFF)) // Not in VCHAR or SP. - return std::nullopt; - else - valueBuilder.append(header[index]); - ++index; - } - if (index == header.length()) - return std::nullopt; - ++index; // Skip DQUOTE. - } else - return std::nullopt; - } - parameters.set(key.toString(), WTFMove(value)); - } - if (index != header.length()) - return std::nullopt; - return std::make_pair(bareItem, parameters); -} +// OptionSet<ClearSiteDataValue> parseClearSiteDataHeader(const ResourceResponse& response) +// { +// OptionSet<ClearSiteDataValue> result; + +// auto headerValue = response.httpHeaderField(HTTPHeaderName::ClearSiteData); +// if (headerValue.isEmpty()) +// return result; + +// if (!WebCore::shouldTreatAsPotentiallyTrustworthy(response.url())) +// return result; + +// for (auto value : StringView(headerValue).split(',')) { +// auto trimmedValue = value.trim(isJSONOrHTTPWhitespace<UChar>); +// if (trimmedValue == "\"cache\""_s) +// result.add(ClearSiteDataValue::Cache); +// else if (trimmedValue == "\"cookies\""_s) +// result.add(ClearSiteDataValue::Cookies); +// else if (trimmedValue == "\"executionContexts\""_s) +// result.add(ClearSiteDataValue::ExecutionContexts); +// else if (trimmedValue == "\"storage\""_s) +// result.add(ClearSiteDataValue::Storage); +// else if (trimmedValue == "\"*\""_s) +// result.add({ ClearSiteDataValue::Cache, ClearSiteDataValue::Cookies, ClearSiteDataValue::ExecutionContexts, ClearSiteDataValue::Storage }); +// } +// return result; +// } + +// Implements <https://fetch.spec.whatwg.org/#simple-range-header-value>. +// FIXME: this whole function could be more efficient by walking through the range value once. +bool parseRange(StringView range, RangeAllowWhitespace allowWhitespace, long long& rangeStart, long long& rangeEnd) +{ + rangeStart = rangeEnd = -1; + + // Only 0x20 and 0x09 matter as newlines are already gone by the time we parse a header value. + if (allowWhitespace == RangeAllowWhitespace::No && range.find(isTabOrSpace<UChar>) != notFound) + return false; -bool parseRange(StringView range, long long& rangeOffset, long long& rangeEnd, long long& rangeSuffixLength) -{ - // The format of "Range" header is defined in RFC 2616 Section 14.35.1. - // http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35.1 - // We don't support multiple range requests. + // The "bytes" unit identifier should be present. + static const unsigned bytesLength = 5; + if (!startsWithLettersIgnoringASCIICase(range, "bytes"_s)) + return false; - rangeOffset = rangeEnd = rangeSuffixLength = -1; + auto byteRange = range.substring(bytesLength).trim(isJSONOrHTTPWhitespace<UChar>); - // The "bytes" unit identifier should be present. - static const unsigned bytesLength = 6; - if (!startsWithLettersIgnoringASCIICase(range, "bytes="_s)) + if (!byteRange.startsWith('=')) return false; - StringView byteRange = range.substring(bytesLength); + byteRange = byteRange.substring(1); // The '-' character needs to be present. int index = byteRange.find('-'); @@ -694,8 +648,10 @@ bool parseRange(StringView range, long long& rangeOffset, long long& rangeEnd, l // Example: // -500 if (!index) { - if (auto value = parseInteger<long long>(byteRange.substring(index + 1))) - rangeSuffixLength = *value; + auto value = parseInteger<long long>(byteRange.substring(index + 1)); + if (!value) + return false; + rangeEnd = *value; return true; } @@ -707,7 +663,7 @@ bool parseRange(StringView range, long long& rangeOffset, long long& rangeEnd, l if (!firstBytePos) return false; - auto lastBytePosStr = stripLeadingAndTrailingHTTPSpaces(byteRange.substring(index + 1)); + auto lastBytePosStr = byteRange.substring(index + 1); long long lastBytePos = -1; if (!lastBytePosStr.isEmpty()) { auto value = parseInteger<long long>(lastBytePosStr); @@ -719,7 +675,7 @@ bool parseRange(StringView range, long long& rangeOffset, long long& rangeEnd, l if (*firstBytePos < 0 || !(lastBytePos == -1 || lastBytePos >= *firstBytePos)) return false; - rangeOffset = *firstBytePos; + rangeStart = *firstBytePos; rangeEnd = lastBytePos; return true; } @@ -854,35 +810,11 @@ size_t parseHTTPRequestBody(const uint8_t* data, size_t length, Vector<uint8_t>& bool isForbiddenHeaderName(const String& name) { return false; - // HTTPHeaderName headerName; - // if (findHTTPHeaderName(name, headerName)) { - // switch (headerName) { - // case HTTPHeaderName::AcceptCharset: - // case HTTPHeaderName::AcceptEncoding: - // case HTTPHeaderName::AccessControlRequestHeaders: - // case HTTPHeaderName::AccessControlRequestMethod: - // case HTTPHeaderName::Connection: - // case HTTPHeaderName::ContentLength: - // case HTTPHeaderName::Cookie: - // case HTTPHeaderName::Cookie2: - // case HTTPHeaderName::Date: - // case HTTPHeaderName::DNT: - // case HTTPHeaderName::Expect: - // case HTTPHeaderName::Host: - // case HTTPHeaderName::KeepAlive: - // case HTTPHeaderName::Origin: - // case HTTPHeaderName::Referer: - // case HTTPHeaderName::TE: - // case HTTPHeaderName::Trailer: - // case HTTPHeaderName::TransferEncoding: - // case HTTPHeaderName::Upgrade: - // case HTTPHeaderName::Via: - // return true; - // default: - // break; - // } - // } - // return startsWithLettersIgnoringASCIICase(name, "sec-"_s) || startsWithLettersIgnoringASCIICase(name, "proxy-"_s); +} + +bool isForbiddenHeader(const String& name, StringView value) +{ + return false; } // Implements <https://fetch.spec.whatwg.org/#no-cors-safelisted-request-header-name>. @@ -906,99 +838,65 @@ bool isNoCORSSafelistedRequestHeaderName(const String& name) // Implements <https://fetch.spec.whatwg.org/#privileged-no-cors-request-header-name>. bool isPriviledgedNoCORSRequestHeaderName(const String& name) { - return equalLettersIgnoringASCIICase(name, "range"_s); + return false; + // return equalLettersIgnoringASCIICase(name, "range"_s); } // Implements <https://fetch.spec.whatwg.org/#forbidden-response-header-name>. bool isForbiddenResponseHeaderName(const String& name) { - return equalLettersIgnoringASCIICase(name, "set-cookie"_s) || equalLettersIgnoringASCIICase(name, "set-cookie2"_s); + return false; + // return equalLettersIgnoringASCIICase(name, "set-cookie"_s) || equalLettersIgnoringASCIICase(name, "set-cookie2"_s); } // Implements <https://fetch.spec.whatwg.org/#forbidden-method>. -bool isForbiddenMethod(const String& name) +bool isForbiddenMethod(StringView name) { - return equalLettersIgnoringASCIICase(name, "connect"_s) || equalLettersIgnoringASCIICase(name, "trace"_s) || equalLettersIgnoringASCIICase(name, "track"_s); + // return equalLettersIgnoringASCIICase(name, "connect"_s) || equalLettersIgnoringASCIICase(name, "trace"_s) || equalLettersIgnoringASCIICase(name, "track"_s); + return false; } bool isSimpleHeader(const String& name, const String& value) { HTTPHeaderName headerName; - if (!findHTTPHeaderName(name, headerName)) - return false; - return isCrossOriginSafeRequestHeader(headerName, value); -} - -bool isCrossOriginSafeHeader(HTTPHeaderName name, const HTTPHeaderSet& accessControlExposeHeaderSet) -{ - switch (name) { - case HTTPHeaderName::CacheControl: - case HTTPHeaderName::ContentLanguage: - case HTTPHeaderName::ContentLength: - case HTTPHeaderName::ContentType: - case HTTPHeaderName::Expires: - case HTTPHeaderName::LastModified: - case HTTPHeaderName::Pragma: - case HTTPHeaderName::Accept: - return true; - case HTTPHeaderName::SetCookie: - case HTTPHeaderName::SetCookie2: - return false; - default: - break; - } - return accessControlExposeHeaderSet.contains<ASCIICaseInsensitiveStringViewHashTranslator>(httpHeaderNameString(name)); -} - -bool isCrossOriginSafeHeader(const String& name, const HTTPHeaderSet& accessControlExposeHeaderSet) -{ -#if ASSERT_ENABLED - HTTPHeaderName headerName; - ASSERT(!findHTTPHeaderName(name, headerName)); -#endif - return accessControlExposeHeaderSet.contains(name); -} - -static bool isSimpleRangeHeaderValue(const String& value) -{ - if (!value.startsWith("bytes="_s)) - return false; - - unsigned start = 0; - unsigned end = 0; - bool hasHyphen = false; - - for (size_t cptr = 6; cptr < value.length(); ++cptr) { - auto character = value[cptr]; - if (character >= '0' && character <= '9') { - if (productOverflows<unsigned>(hasHyphen ? end : start, 10)) - return false; - auto newDecimal = (hasHyphen ? end : start) * 10; - auto sum = Checked<unsigned, RecordOverflow>(newDecimal) + Checked<unsigned, RecordOverflow>(character - '0'); - if (sum.hasOverflowed()) - return false; - - if (hasHyphen) - end = sum.value(); - else - start = sum.value(); - continue; - } - if (character == '-' && !hasHyphen) { - hasHyphen = true; - continue; - } - return false; - } - - return hasHyphen && (!end || start < end); -} + return !findHTTPHeaderName(name, headerName); +} + +// bool isCrossOriginSafeHeader(HTTPHeaderName name, const HTTPHeaderSet& accessControlExposeHeaderSet) +// { +// // switch (name) { +// // case HTTPHeaderName::CacheControl: +// // case HTTPHeaderName::ContentLanguage: +// // case HTTPHeaderName::ContentLength: +// // case HTTPHeaderName::ContentType: +// // case HTTPHeaderName::Expires: +// // case HTTPHeaderName::LastModified: +// // case HTTPHeaderName::Pragma: +// // case HTTPHeaderName::Accept: +// // return true; +// // case HTTPHeaderName::SetCookie: +// // case HTTPHeaderName::SetCookie2: +// // return false; +// // default: +// // break; +// // } +// // return accessControlExposeHeaderSet.contains<HashTranslatorASCIILiteralCaseInsensitive>(httpHeaderNameString(name)); +// } + +// bool isCrossOriginSafeHeader(const String& name, const HTTPHeaderSet& accessControlExposeHeaderSet) +// { +// #if ASSERT_ENABLED +// HTTPHeaderName headerName; +// ASSERT(!findHTTPHeaderName(name, headerName)); +// #endif +// return accessControlExposeHeaderSet.contains(name); +// } // Implements https://fetch.spec.whatwg.org/#cors-safelisted-request-header bool isCrossOriginSafeRequestHeader(HTTPHeaderName name, const String& value) { - if (value.length() > 128) - return false; + // if (value.length() > 128) + // return false; // switch (name) { // case HTTPHeaderName::Accept: @@ -1023,11 +921,14 @@ bool isCrossOriginSafeRequestHeader(HTTPHeaderName name, const String& value) // break; // } // case HTTPHeaderName::Range: - // if (!isSimpleRangeHeaderValue(value)) + // long long start; + // long long end; + // if (!parseRange(value, RangeAllowWhitespace::No, start, end)) + // return false; + // if (start == -1) // return false; // break; // default: - // // FIXME: Should we also make safe other headers (DPR, Downlink, Save-Data...)? That would require validating their values. // return false; // } return true; @@ -1036,43 +937,43 @@ bool isCrossOriginSafeRequestHeader(HTTPHeaderName name, const String& value) // Implements <https://fetch.spec.whatwg.org/#concept-method-normalize>. String normalizeHTTPMethod(const String& method) { - const ASCIILiteral methods[] = { "DELETE"_s, "GET"_s, "HEAD"_s, "OPTIONS"_s, "POST"_s, "PUT"_s }; - for (auto value : methods) { - if (equalIgnoringASCIICase(method, value)) { - // Don't bother allocating a new string if it's already all uppercase. - if (method == value) - break; - return value; - } - } + // static constexpr ASCIILiteral methods[] = { "DELETE"_s, "GET"_s, "HEAD"_s, "OPTIONS"_s, "POST"_s, "PUT"_s }; + // for (auto value : methods) { + // if (equalIgnoringASCIICase(method, value)) { + // // Don't bother allocating a new string if it's already all uppercase. + // if (method == value) + // break; + // return value; + // } + // } return method; } // Defined by https://tools.ietf.org/html/rfc7231#section-4.2.1 bool isSafeMethod(const String& method) { - const ASCIILiteral safeMethods[] = { "GET"_s, "HEAD"_s, "OPTIONS"_s, "TRACE"_s }; - for (auto value : safeMethods) { - if (equalIgnoringASCIICase(method, value)) - return true; - } - return false; + // const ASCIILiteral safeMethods[] = { "GET"_s, "HEAD"_s, "OPTIONS"_s, "TRACE"_s }; + // for (auto value : safeMethods) { + // if (equalIgnoringASCIICase(method, value)) + // return true; + // } + return true; } CrossOriginResourcePolicy parseCrossOriginResourcePolicyHeader(StringView header) { - auto strippedHeader = stripLeadingAndTrailingHTTPSpaces(header); + auto trimmedHeader = header.trim(isJSONOrHTTPWhitespace<UChar>); - if (strippedHeader.isEmpty()) + if (trimmedHeader.isEmpty()) return CrossOriginResourcePolicy::None; - if (strippedHeader == "same-origin"_s) + if (trimmedHeader == "same-origin"_s) return CrossOriginResourcePolicy::SameOrigin; - if (strippedHeader == "same-site"_s) + if (trimmedHeader == "same-site"_s) return CrossOriginResourcePolicy::SameSite; - if (strippedHeader == "cross-origin"_s) + if (trimmedHeader == "cross-origin"_s) return CrossOriginResourcePolicy::CrossOrigin; return CrossOriginResourcePolicy::Invalid; diff --git a/src/bun.js/bindings/webcore/HTTPParsers.h b/src/bun.js/bindings/webcore/HTTPParsers.h index 0bc922a04..bf56caccb 100644 --- a/src/bun.js/bindings/webcore/HTTPParsers.h +++ b/src/bun.js/bindings/webcore/HTTPParsers.h @@ -30,6 +30,7 @@ #pragma once +#include <wtf/text/StringImpl.h> #include <wtf/HashSet.h> #include <wtf/WallTime.h> #include <wtf/text/StringHash.h> @@ -69,6 +70,9 @@ enum class CrossOriginResourcePolicy : uint8_t { Invalid }; +enum class RangeAllowWhitespace : bool { No, + Yes }; + bool isValidReasonPhrase(const String&); bool isValidHTTPHeaderValue(const String&); bool isValidAcceptHeaderValue(const String&); @@ -103,8 +107,8 @@ bool isPriviledgedNoCORSRequestHeaderName(const String&); bool isForbiddenResponseHeaderName(const String&); bool isForbiddenMethod(const String&); bool isSimpleHeader(const String& name, const String& value); -bool isCrossOriginSafeHeader(HTTPHeaderName, const HTTPHeaderSet&); -bool isCrossOriginSafeHeader(const String&, const HTTPHeaderSet&); +// bool isCrossOriginSafeHeader(HTTPHeaderName, const HTTPHeaderSet&); +// bool isCrossOriginSafeHeader(const String&, const HTTPHeaderSet&); bool isCrossOriginSafeRequestHeader(HTTPHeaderName, const String&); String normalizeHTTPMethod(const String&); @@ -112,67 +116,59 @@ bool isSafeMethod(const String&); WEBCORE_EXPORT CrossOriginResourcePolicy parseCrossOriginResourcePolicyHeader(StringView); +// -1 could be set to one of the return parameters to indicate the value is not specified. +WEBCORE_EXPORT bool parseRange(StringView, RangeAllowWhitespace, long long& rangeStart, long long& rangeEnd); + inline bool isHTTPSpace(UChar character) { return character <= ' ' && (character == ' ' || character == '\n' || character == '\t' || character == '\r'); } -// Strip leading and trailing whitespace as defined in https://fetch.spec.whatwg.org/#concept-header-value-normalize. -inline String stripLeadingAndTrailingHTTPSpaces(const String& string) -{ - return string.stripLeadingAndTrailingCharacters(isHTTPSpace); -} - -inline StringView stripLeadingAndTrailingHTTPSpaces(StringView string) -{ - return string.stripLeadingAndTrailingMatchedCharacters(isHTTPSpace); -} - -template<class HashType> -bool addToAccessControlAllowList(const String& string, unsigned start, unsigned end, HashSet<String, HashType>& set) -{ - StringImpl* stringImpl = string.impl(); - if (!stringImpl) - return true; - - // Skip white space from start. - while (start <= end && isHTTPSpace((*stringImpl)[start])) - ++start; - - // only white space - if (start > end) - return true; - - // Skip white space from end. - while (end && isHTTPSpace((*stringImpl)[end])) - --end; - - auto token = string.substring(start, end - start + 1); - if (!isValidHTTPToken(token)) - return false; - - set.add(WTFMove(token)); - return true; -} - -template<class HashType = DefaultHash<String>> -std::optional<HashSet<String, HashType>> parseAccessControlAllowList(const String& string) -{ - HashSet<String, HashType> set; - unsigned start = 0; - size_t end; - while ((end = string.find(',', start)) != notFound) { - if (start != end) { - if (!addToAccessControlAllowList(string, start, end - 1, set)) - return {}; - } - start = end + 1; - } - if (start != string.length()) { - if (!addToAccessControlAllowList(string, start, string.length() - 1, set)) - return {}; - } - return set; -} +// template<class HashType> +// bool addToAccessControlAllowList(const String& string, unsigned start, unsigned end, HashSet<String, HashType>& set) +// { +// StringImpl* stringImpl = string.impl(); +// if (!stringImpl) +// return true; + +// // Skip white space from start. +// while (start <= end && isJSONOrHTTPWhitespace((*stringImpl)[start])) +// ++start; + +// // only white space +// if (start > end) +// return true; + +// // Skip white space from end. +// while (end && isJSONOrHTTPWhitespace((*stringImpl)[end])) +// --end; + +// auto token = string.substring(start, end - start + 1); +// if (!isValidHTTPToken(token)) +// return false; + +// set.add(WTFMove(token)); +// return true; +// } + +// template<class HashType = DefaultHash<String>> +// std::optional<HashSet<String, HashType>> parseAccessControlAllowList(const String& string) +// { +// HashSet<String, HashType> set; +// unsigned start = 0; +// size_t end; +// while ((end = string.find(',', start)) != notFound) { +// if (start != end) { +// if (!addToAccessControlAllowList(string, start, end - 1, set)) +// return {}; +// } +// start = end + 1; +// } +// if (start != string.length()) { +// if (!addToAccessControlAllowList(string, start, string.length() - 1, set)) +// return {}; +// } +// return set; +// } } diff --git a/src/bun.js/bindings/webcore/JSDOMConvertStrings.cpp b/src/bun.js/bindings/webcore/JSDOMConvertStrings.cpp index 00f385e07..d5ae21304 100644 --- a/src/bun.js/bindings/webcore/JSDOMConvertStrings.cpp +++ b/src/bun.js/bindings/webcore/JSDOMConvertStrings.cpp @@ -44,7 +44,7 @@ String identifierToString(JSGlobalObject& lexicalGlobalObject, const Identifier& static inline bool throwIfInvalidByteString(JSGlobalObject& lexicalGlobalObject, JSC::ThrowScope& scope, const String& string) { - if (UNLIKELY(!string.isAllLatin1())) { + if (UNLIKELY(!string.containsOnlyLatin1())) { throwTypeError(&lexicalGlobalObject, scope); return true; } diff --git a/src/bun.js/bindings/webcore/JSTextEncoder.cpp b/src/bun.js/bindings/webcore/JSTextEncoder.cpp index 5d764619b..3029028fe 100644 --- a/src/bun.js/bindings/webcore/JSTextEncoder.cpp +++ b/src/bun.js/bindings/webcore/JSTextEncoder.cpp @@ -216,9 +216,9 @@ template<> void JSTextEncoderDOMConstructor::initializeProperties(VM& vm, JSDOMG constexpr JSC::DFG::AbstractHeapKind heapKinds[4] = { JSC::DFG::HeapObjectCount }; -// This is the equivalent of DataView.set -constexpr JSC::DFG::AbstractHeapKind encodeIntoRead[4] = { JSC::DFG::MiscFields, JSC::DFG::TypedArrayProperties, JSC::DFG::Absolute }; -constexpr JSC::DFG::AbstractHeapKind encodeIntoWrite[4] = { JSC::DFG::TypedArrayProperties, JSC::DFG::Absolute }; +// TODO: figure out why the test fails after JSC upgrade and re-enable this! +// constexpr JSC::DFG::AbstractHeapKind encodeIntoRead[4] = { JSC::DFG::Heap, JSC::DFG::MiscFields, JSC::DFG::TypedArrayProperties, JSC::DFG::Absolute }; +// constexpr JSC::DFG::AbstractHeapKind encodeIntoWrite[4] = { JSC::DFG::SideState, JSC::DFG::Absolute, JSC::DFG::JSCell_structureID, JSC::DFG::HeapObjectCount }; static const JSC::DOMJIT::Signature DOMJITSignatureForJSTextEncoderEncodeWithoutTypeCheck( jsTextEncoderEncodeWithoutTypeCheck, @@ -230,10 +230,9 @@ static const JSC::DOMJIT::Signature DOMJITSignatureForJSTextEncoderEncodeWithout static const JSC::DOMJIT::Signature DOMJITSignatureForJSTextEncoderEncodeIntoWithoutTypeCheck( jsTextEncoderPrototypeFunction_encodeIntoWithoutTypeCheck, JSTextEncoder::info(), - // this is slightly incorrect - // there could be cases where the object returned by encodeInto will appear to be reused - // it impacts HeapObjectCount - JSC::DOMJIT::Effect::forReadWriteKinds(encodeIntoRead, encodeIntoWrite), + + JSC::DOMJIT::Effect {}, + // JSC::DOMJIT::Effect::forReadWriteKinds(encodeIntoRead, encodeIntoWrite), DOMJIT::IDLResultTypeFilter<IDLObject>::value, DOMJIT::IDLArgumentTypeFilter<IDLDOMString>::value, DOMJIT::IDLArgumentTypeFilter<IDLUint8Array>::value); diff --git a/src/bun.js/bindings/webcore/ParsedContentType.cpp b/src/bun.js/bindings/webcore/ParsedContentType.cpp index 04b30cf9b..c4773b3ee 100644 --- a/src/bun.js/bindings/webcore/ParsedContentType.cpp +++ b/src/bun.js/bindings/webcore/ParsedContentType.cpp @@ -40,7 +40,7 @@ namespace WebCore { static void skipSpaces(StringView input, unsigned& startIndex) { - while (startIndex < input.length() && isHTTPSpace(input[startIndex])) + while (startIndex < input.length() && isJSONOrHTTPWhitespace(input[startIndex])) ++startIndex; } @@ -78,7 +78,7 @@ static StringView parseToken(StringView input, unsigned& startIndex, CharacterMe while (input[tokenEnd - 1] == ' ') --tokenEnd; } else { - while (isHTTPSpace(input[tokenEnd - 1])) + while (isJSONOrHTTPWhitespace(input[tokenEnd - 1])) --tokenEnd; } } @@ -328,7 +328,7 @@ bool ParsedContentType::parseContentType(Mode mode) std::optional<ParsedContentType> ParsedContentType::create(const String& contentType, Mode mode) { - ParsedContentType parsedContentType(mode == Mode::Rfc2045 ? contentType : stripLeadingAndTrailingHTTPSpaces(contentType)); + ParsedContentType parsedContentType(mode == Mode::Rfc2045 ? contentType : contentType.trim(isJSONOrHTTPWhitespace<UChar>)); if (!parsedContentType.parseContentType(mode)) return std::nullopt; return { WTFMove(parsedContentType) }; @@ -368,9 +368,9 @@ void ParsedContentType::setContentType(String&& contentRange, Mode mode) { m_mimeType = WTFMove(contentRange); if (mode == Mode::MimeSniff) - m_mimeType = stripLeadingAndTrailingHTTPSpaces(StringView(m_mimeType)).convertToASCIILowercase(); + m_mimeType = StringView(m_mimeType).trim(isJSONOrHTTPWhitespace<UChar>).convertToASCIILowercase(); else - m_mimeType = m_mimeType.stripWhiteSpace(); + m_mimeType = m_mimeType.trim(deprecatedIsSpaceOrNewline); } static bool containsNonQuoteStringTokenCharacters(const String& input) diff --git a/src/bun.js/bindings/webcore/ReadableStreamSink.cpp b/src/bun.js/bindings/webcore/ReadableStreamSink.cpp index ff2f1ebe3..d79e7d358 100644 --- a/src/bun.js/bindings/webcore/ReadableStreamSink.cpp +++ b/src/bun.js/bindings/webcore/ReadableStreamSink.cpp @@ -48,7 +48,7 @@ void ReadableStreamToSharedBufferSink::enqueue(const BufferSource& buffer) return; if (m_callback) { - Span<const uint8_t> chunk { buffer.data(), buffer.length() }; + std::span<const uint8_t> chunk { buffer.data(), buffer.length() }; m_callback(&chunk); } } diff --git a/src/bun.js/bindings/webcore/ReadableStreamSink.h b/src/bun.js/bindings/webcore/ReadableStreamSink.h index fee988422..7db31e38a 100644 --- a/src/bun.js/bindings/webcore/ReadableStreamSink.h +++ b/src/bun.js/bindings/webcore/ReadableStreamSink.h @@ -23,13 +23,12 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ - #pragma once #include "ExceptionOr.h" #include <wtf/Function.h> #include <wtf/RefCounted.h> -#include <wtf/Span.h> +#include <span> namespace WebCore { @@ -47,10 +46,10 @@ public: class ReadableStreamToSharedBufferSink final : public ReadableStreamSink { public: - using Callback = Function<void(ExceptionOr<Span<const uint8_t>*>&&)>; + using Callback = Function<void(ExceptionOr<std::span<const uint8_t>*>&&)>; static Ref<ReadableStreamToSharedBufferSink> create(Callback&& callback) { return adoptRef(*new ReadableStreamToSharedBufferSink(WTFMove(callback))); } void pipeFrom(ReadableStream&); - void clearCallback() { m_callback = { }; } + void clearCallback() { m_callback = {}; } private: explicit ReadableStreamToSharedBufferSink(Callback&&); diff --git a/src/bun.js/bindings/webcore/SerializedScriptValue.cpp b/src/bun.js/bindings/webcore/SerializedScriptValue.cpp index 176e805b8..e80bc9493 100644 --- a/src/bun.js/bindings/webcore/SerializedScriptValue.cpp +++ b/src/bun.js/bindings/webcore/SerializedScriptValue.cpp @@ -2528,7 +2528,7 @@ public: Vector<std::unique_ptr<DetachedRTCDataChannel>>&& detachedRTCDataChannels #endif , - ArrayBufferContentsArray* arrayBufferContentsArray, const Span<uint8_t>& buffer, const Vector<String>& blobURLs, const Vector<String> blobFilePaths, ArrayBufferContentsArray* sharedBuffers + ArrayBufferContentsArray* arrayBufferContentsArray, const std::span<uint8_t>& buffer, const Vector<String>& blobURLs, const Vector<String> blobFilePaths, ArrayBufferContentsArray* sharedBuffers #if ENABLE(WEBASSEMBLY) , WasmModuleArray* wasmModules, WasmMemoryHandleArray* wasmMemoryHandles @@ -2541,7 +2541,7 @@ public: { if (!buffer.size()) return std::make_pair(jsNull(), SerializationReturnCode::UnspecifiedError); - CloneDeserializer deserializer(lexicalGlobalObject, globalObject, arrayBufferContentsArray, Span<uint8_t> { buffer.begin(), buffer.end() }, blobURLs, blobFilePaths, sharedBuffers + CloneDeserializer deserializer(lexicalGlobalObject, globalObject, arrayBufferContentsArray, std::span<uint8_t> { buffer.begin(), buffer.end() }, blobURLs, blobFilePaths, sharedBuffers #if ENABLE(OFFSCREEN_CANVAS_IN_WORKERS) , WTFMove(detachedOffscreenCanvases) @@ -2675,7 +2675,7 @@ private: // m_version = 0xFFFFFFFF; // } - CloneDeserializer(JSGlobalObject* lexicalGlobalObject, JSGlobalObject* globalObject, ArrayBufferContentsArray* arrayBufferContents, const Span<uint8_t>& buffer + CloneDeserializer(JSGlobalObject* lexicalGlobalObject, JSGlobalObject* globalObject, ArrayBufferContentsArray* arrayBufferContents, const std::span<uint8_t>& buffer #if ENABLE(OFFSCREEN_CANVAS_IN_WORKERS) , Vector<std::unique_ptr<DetachedOffscreenCanvas>>&& detachedOffscreenCanvases = {} @@ -2781,7 +2781,7 @@ private: // m_version = 0xFFFFFFFF; // } - CloneDeserializer(JSGlobalObject* lexicalGlobalObject, JSGlobalObject* globalObject, ArrayBufferContentsArray* arrayBufferContents, const Span<uint8_t>& buffer, const Vector<String>& blobURLs, const Vector<String> blobFilePaths, ArrayBufferContentsArray* sharedBuffers + CloneDeserializer(JSGlobalObject* lexicalGlobalObject, JSGlobalObject* globalObject, ArrayBufferContentsArray* arrayBufferContents, const std::span<uint8_t>& buffer, const Vector<String>& blobURLs, const Vector<String> blobFilePaths, ArrayBufferContentsArray* sharedBuffers #if ENABLE(OFFSCREEN_CANVAS_IN_WORKERS) , Vector<std::unique_ptr<DetachedOffscreenCanvas>>&& detachedOffscreenCanvases @@ -5406,7 +5406,7 @@ JSC::JSValue SerializedScriptValue::fromArrayBuffer(JSC::JSGlobalObject& domGlob auto* data = static_cast<uint8_t*>(arrayBuffer->data()) + byteOffset; auto size = std::min(arrayBuffer->byteLength(), maxByteLength); - auto span = Span<uint8_t> { data, size }; + auto span = std::span<uint8_t> { data, size }; auto result = CloneDeserializer::deserialize(&domGlobal, globalObject, nullptr, span, blobURLs, blobFiles, nullptr #if ENABLE(WEBASSEMBLY) diff --git a/src/bun.js/bindings/webcore/SharedBuffer.cpp b/src/bun.js/bindings/webcore/SharedBuffer.cpp index 6ade267de..32b19626b 100644 --- a/src/bun.js/bindings/webcore/SharedBuffer.cpp +++ b/src/bun.js/bindings/webcore/SharedBuffer.cpp @@ -261,14 +261,14 @@ Ref<FragmentedSharedBuffer> FragmentedSharedBuffer::copy() const return clone; } -void FragmentedSharedBuffer::forEachSegment(const Function<void(const Span<const uint8_t>&)>& apply) const +void FragmentedSharedBuffer::forEachSegment(const Function<void(const std::span<const uint8_t>&)>& apply) const { auto segments = m_segments; for (auto& segment : segments) segment.segment->iterate(apply); } -void DataSegment::iterate(const Function<void(const Span<const uint8_t>&)>& apply) const +void DataSegment::iterate(const Function<void(const std::span<const uint8_t>&)>& apply) const { #if USE(FOUNDATION) if (auto* data = std::get_if<RetainPtr<CFDataRef>>(&m_immutableData)) @@ -284,7 +284,7 @@ void FragmentedSharedBuffer::forEachSegmentAsSharedBuffer(const Function<void(Re apply(SharedBuffer::create(segment.segment.copyRef())); } -bool FragmentedSharedBuffer::startsWith(const Span<const uint8_t>& prefix) const +bool FragmentedSharedBuffer::startsWith(const std::span<const uint8_t>& prefix) const { if (prefix.empty()) return true; diff --git a/src/bun.js/bindings/webcore/SharedBuffer.h b/src/bun.js/bindings/webcore/SharedBuffer.h index 5c2e70486..9cffa0bad 100644 --- a/src/bun.js/bindings/webcore/SharedBuffer.h +++ b/src/bun.js/bindings/webcore/SharedBuffer.h @@ -32,7 +32,7 @@ #include <wtf/FileSystem.h> #include <wtf/Forward.h> #include <wtf/Function.h> -#include <wtf/Span.h> +#include <span> #include <wtf/ThreadSafeRefCounted.h> #include <wtf/TypeCasts.h> #include <wtf/Vector.h> @@ -102,9 +102,9 @@ public: WEBCORE_EXPORT bool containsMappedFileData() const; private: - void iterate(const Function<void(const Span<const uint8_t> &)> &apply) const; + void iterate(const Function<void(const std::span<const uint8_t> &)> &apply) const; #if USE(FOUNDATION) - void iterate(CFDataRef, const Function<void(const Span<const uint8_t> &)> &apply) const; + void iterate(CFDataRef, const Function<void(const std::span<const uint8_t> &)> &apply) const; #endif explicit DataSegment(Vector<uint8_t> &&data) @@ -197,8 +197,8 @@ public: WEBCORE_EXPORT void copyTo(void *destination, size_t length) const; WEBCORE_EXPORT void copyTo(void *destination, size_t offset, size_t length) const; - WEBCORE_EXPORT void forEachSegment(const Function<void(const Span<const uint8_t> &)> &) const; - WEBCORE_EXPORT bool startsWith(const Span<const uint8_t> &prefix) const; + WEBCORE_EXPORT void forEachSegment(const Function<void(const std::span<const uint8_t> &)> &) const; + WEBCORE_EXPORT bool startsWith(const std::span<const uint8_t> &prefix) const; WEBCORE_EXPORT void forEachSegmentAsSharedBuffer(const Function<void(Ref<SharedBuffer> &&)> &) const; using DataSegment = WebCore::DataSegment; // To keep backward compatibility when using FragmentedSharedBuffer::DataSegment @@ -253,7 +253,7 @@ private: friend class SharedBufferBuilder; WEBCORE_EXPORT void append(const FragmentedSharedBuffer &); WEBCORE_EXPORT void append(const uint8_t *, size_t); - void append(Span<const uint8_t> value) { append(value.data(), value.size()); } + void append(std::span<const uint8_t> value) { append(value.data(), value.size()); } void append(const char *data, size_t length) { append(reinterpret_cast<const uint8_t *>(data), length); } WEBCORE_EXPORT void append(Vector<uint8_t> &&); #if USE(FOUNDATION) @@ -296,7 +296,7 @@ public: WEBCORE_EXPORT const uint8_t *data() const; const char *dataAsCharPtr() const { return reinterpret_cast<const char *>(data()); } - Span<const uint8_t> dataAsSpanForContiguousData() const { return Span<const uint8_t>(data(), isContiguous() ? size() : 0); } + std::span<const uint8_t> dataAsSpanForContiguousData() const { return std::span<const uint8_t>(data(), isContiguous() ? size() : 0); } WTF::Persistence::Decoder decoder() const; enum class MayUseFileMapping : bool { No, |