Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Source/WTF/WTF.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
14022F4118F5C3FC007FF0EB /* libbmalloc.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 14022F4018F5C3FC007FF0EB /* libbmalloc.a */; };
143DDE9620C8BC37007F76FA /* Entitlements.mm in Sources */ = {isa = PBXBuildFile; fileRef = 143DDE9520C8BC37007F76FA /* Entitlements.mm */; };
143F611F1565F0F900DB514A /* RAMSize.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 143F611D1565F0F900DB514A /* RAMSize.cpp */; };
144177D62D89B7C100F5099E /* ValueOrReference.h in Headers */ = {isa = PBXBuildFile; fileRef = 144177D52D89B7C100F5099E /* ValueOrReference.h */; settings = {ATTRIBUTES = (Private, ); }; };
1469419D16EAB10A0024E146 /* AutodrainedPool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1469419B16EAB10A0024E146 /* AutodrainedPool.cpp */; };
1A1D8B9E1731879800141DA4 /* FunctionDispatcher.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A1D8B9D1731879800141DA4 /* FunctionDispatcher.cpp */; };
1C181C7F1D3078DA00F5FA16 /* TextBreakIterator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1C181C7D1D3078DA00F5FA16 /* TextBreakIterator.cpp */; };
Expand Down Expand Up @@ -1011,6 +1012,7 @@
143DDE9720C8BE99007F76FA /* Entitlements.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Entitlements.h; sourceTree = "<group>"; };
143F611D1565F0F900DB514A /* RAMSize.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RAMSize.cpp; sourceTree = "<group>"; };
143F611E1565F0F900DB514A /* RAMSize.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RAMSize.h; sourceTree = "<group>"; };
144177D52D89B7C100F5099E /* ValueOrReference.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ValueOrReference.h; sourceTree = "<group>"; };
1447AEC518FCE57700B3D7FF /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; };
1447AECA18FCE5B900B3D7FF /* libicucore.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libicucore.dylib; path = /usr/lib/libicucore.dylib; sourceTree = "<absolute>"; };
1469419416EAAFF80024E146 /* SchedulePair.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SchedulePair.h; sourceTree = "<group>"; };
Expand Down Expand Up @@ -2310,6 +2312,7 @@
7AFEC6B01EB22B5900DADE36 /* UUID.cpp */,
7AFEC6AE1EB22AC600DADE36 /* UUID.h */,
A8A4736F151A825B004123FF /* ValueCheck.h */,
144177D52D89B7C100F5099E /* ValueOrReference.h */,
0F95B63420CB53C100479635 /* Vector.cpp */,
A8A47370151A825B004123FF /* Vector.h */,
E419F2E623AB9E2300B26129 /* VectorHash.h */,
Expand Down Expand Up @@ -3241,6 +3244,7 @@
DDF306F527C086CC006A526F /* utils.h in Headers */,
DD3DC8C227A4BF8E007E5B61 /* UUID.h in Headers */,
DD3DC86D27A4BF8E007E5B61 /* ValueCheck.h in Headers */,
144177D62D89B7C100F5099E /* ValueOrReference.h in Headers */,
DD3DC90B27A4BF8E007E5B61 /* Vector.h in Headers */,
DDF3079727C086CD006A526F /* VectorCocoa.h in Headers */,
DD3DC8B127A4BF8E007E5B61 /* VectorHash.h in Headers */,
Expand Down
1 change: 1 addition & 0 deletions Source/WTF/wtf/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,7 @@ set(WTF_PUBLIC_HEADERS
UnsafePointer.h
VMTags.h
ValueCheck.h
ValueOrReference.h
Vector.h
VectorHash.h
VectorTraits.h
Expand Down
10 changes: 10 additions & 0 deletions Source/WTF/wtf/Compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,16 @@
#define WARN_UNUSED_RETURN
#endif

/* LIFETIME_BOUND */

#if !defined(LIFETIME_BOUND) && COMPILER(CLANG)
#define LIFETIME_BOUND [[clang::lifetimebound]]
#endif

#if !defined(LIFETIME_BOUND)
#define LIFETIME_BOUND
#endif

/* DEBUGGER_ANNOTATION_MARKER */

#if !defined(DEBUGGER_ANNOTATION_MARKER) && COMPILER(GCC)
Expand Down
78 changes: 78 additions & 0 deletions Source/WTF/wtf/ValueOrReference.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
* Copyright (C) 2025 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/

#pragma once

#include <wtf/StdLibExtras.h>

namespace WTF {

// ValueOrReference<T> is just like const T&, except that it can also optionally hold T.

// ValueOrReference<T> is an optimization when you need to return a value that is
// usually an existing reference, but sometimes a temporary, e.g.:
//
// ValueOrReference<String> append(const String& string LIFETIME_BOUND, std::optional<String&> suffix)
// {
// if (LIKELY(!suffix))
// return string; // existing reference -- ValueOrReference<T> avoids a copy
// return makeString(string, suffix.value()); // temporary -- ValueOrReference<T> holds T
// }
template<typename T> class ValueOrReference {
public:
ValueOrReference()
: m_reference(m_value)
{
}

ValueOrReference(ValueOrReference&& other)
: m_value(WTFMove(other.m_value))
, m_reference(&other.m_reference == &other.m_value ? m_value : other.m_reference)
{
}

ValueOrReference(const T& reference LIFETIME_BOUND)
: m_reference(reference)
{
}

ValueOrReference(T&& temporary)
: m_value(WTFMove(temporary))
, m_reference(m_value)
{
}

operator const T&() const LIFETIME_BOUND { return m_reference; }
const T& get() const LIFETIME_BOUND { return m_reference; }
const T* operator->() const LIFETIME_BOUND { return &m_reference; }

private:
T m_value;
const T& m_reference;
};

} // namespace WTF

using WTF::ValueOrReference;
11 changes: 11 additions & 0 deletions Source/WTF/wtf/Vector.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

#pragma once

#include <algorithm>
#include <initializer_list>
#include <limits>
#include <optional>
Expand Down Expand Up @@ -1909,6 +1910,15 @@ inline auto copyToVector(const Collection& collection) -> Vector<typename CopyTo
return copyToVectorOf<typename CopyToVectorResult<Collection>::Type>(collection);
}

template<typename T, size_t inlineCapacity = 0> static bool insertInUniquedSortedVector(Vector<T, inlineCapacity>& vector, const T& value)
{
auto it = std::lower_bound(vector.begin(), vector.end(), value);
if (UNLIKELY(it != vector.end() && *it == value))
return false;
vector.insert(it - vector.begin(), value);
return true;
}

} // namespace WTF

using WTF::UnsafeVectorOverflow;
Expand All @@ -1917,4 +1927,5 @@ using WTF::copyToVector;
using WTF::copyToVectorOf;
using WTF::copyToVectorSpecialization;
using WTF::compactMap;
using WTF::insertInUniquedSortedVector;
using WTF::removeRepeatedElements;
1 change: 1 addition & 0 deletions Source/WTF/wtf/text/StringImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "config.h"
#include <wtf/text/StringImpl.h>

#include <atomic>
#include <wtf/StdLibExtras.h>
#include <wtf/text/AtomString.h>
#include <wtf/text/CString.h>
Expand Down
22 changes: 11 additions & 11 deletions Source/WTF/wtf/text/StringImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

#pragma once

#include <atomic>
#include <limits.h>
#include <unicode/ustring.h>
#include <wtf/ASCIICType.h>
Expand Down Expand Up @@ -154,7 +155,7 @@ class STRING_IMPL_ALIGNMENT StringImplShape {
template<unsigned characterCount> constexpr StringImplShape(unsigned refCount, unsigned length, const char (&characters)[characterCount], unsigned hashAndFlags, ConstructWithConstExprTag);
template<unsigned characterCount> constexpr StringImplShape(unsigned refCount, unsigned length, const char16_t (&characters)[characterCount], unsigned hashAndFlags, ConstructWithConstExprTag);

unsigned m_refCount;
std::atomic<unsigned> m_refCount;
unsigned m_length;
union {
const LChar* m_data8;
Expand Down Expand Up @@ -350,11 +351,11 @@ class StringImpl : private StringImplShape {
unsigned symbolAwareHash() const;
unsigned existingSymbolAwareHash() const;

SUPPRESS_TSAN bool isStatic() const { return m_refCount & s_refCountFlagIsStaticString; }
SUPPRESS_TSAN bool isStatic() const { return m_refCount.load(std::memory_order_relaxed) & s_refCountFlagIsStaticString; }

size_t refCount() const { return m_refCount / s_refCountIncrement; }
bool hasOneRef() const { return m_refCount == s_refCountIncrement; }
bool hasAtLeastOneRef() const { return m_refCount; } // For assertions.
size_t refCount() const { return m_refCount.load(std::memory_order_relaxed) / s_refCountIncrement; }
bool hasOneRef() const { return m_refCount.load(std::memory_order_relaxed) == s_refCountIncrement; }
bool hasAtLeastOneRef() const { return m_refCount.load(std::memory_order_relaxed); } // For assertions.

void ref();
void deref();
Expand Down Expand Up @@ -1104,7 +1105,7 @@ inline void StringImpl::ref()
return;
#endif

m_refCount += s_refCountIncrement;
m_refCount.fetch_add(s_refCountIncrement, std::memory_order_relaxed);
}

inline void StringImpl::deref()
Expand All @@ -1116,12 +1117,11 @@ inline void StringImpl::deref()
return;
#endif

unsigned tempRefCount = m_refCount - s_refCountIncrement;
if (!tempRefCount) {
StringImpl::destroy(this);
auto oldRefCount = m_refCount.fetch_sub(s_refCountIncrement, std::memory_order_relaxed);
if (oldRefCount != s_refCountIncrement)
return;
}
m_refCount = tempRefCount;

StringImpl::destroy(this);
}

template<typename SourceCharacterType, typename DestinationCharacterType>
Expand Down
6 changes: 3 additions & 3 deletions Source/WebCore/accessibility/AccessibilityRenderObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2100,7 +2100,7 @@ VisiblePosition AccessibilityRenderObject::visiblePositionForIndex(int index) co

if (isNativeTextControl()) {
auto& textControl = downcast<RenderTextControl>(*m_renderer).textFormControlElement();
return textControl.visiblePositionForIndex(std::clamp(index, 0, static_cast<int>(textControl.value().length())));
return textControl.visiblePositionForIndex(std::clamp(index, 0, static_cast<int>(textControl.value()->length())));
}

if (!allowsTextRanges() && !is<RenderText>(*m_renderer))
Expand Down Expand Up @@ -2309,13 +2309,13 @@ void AccessibilityRenderObject::setSelectedVisiblePositionRange(const VisiblePos
auto innerRange = makeVisiblePositionRange(AXObjectCache::rangeForNodeContents(*innerText));

if (range.start.equals(textControlRange.end))
start = textControl->value().length();
start = textControl->value()->length();
else if (range.start <= innerRange.start)
start = 0;

if (range.end >= innerRange.end
|| range.end.equals(textControlRange.end))
end = textControl->value().length();
end = textControl->value()->length();
}
}

Expand Down
2 changes: 1 addition & 1 deletion Source/WebCore/accessibility/AccessibilitySlider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ AXCoreObject* AccessibilitySlider::elementAccessibilityHitTest(const IntPoint& p
float AccessibilitySlider::valueForRange() const
{
if (auto* input = inputElement())
return input->value().toFloat();
return input->value()->toFloat();
return 0;
}

Expand Down
2 changes: 1 addition & 1 deletion Source/WebCore/accessibility/ios/AccessibilityObjectIOS.mm
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@
return false;

HTMLInputElement& inputElement = downcast<HTMLInputElement>(*renderObject->node());
return inputElement.value().length();
return inputElement.value()->length();
}

bool AccessibilityObject::accessibilityIgnoreAttachment() const
Expand Down
6 changes: 6 additions & 0 deletions Source/WebCore/dom/Attribute.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@ class Attribute {
{
}

Attribute(QualifiedName&& name, AtomString&& value)
: m_name(WTFMove(name))
, m_value(WTFMove(value))
{
}

// NOTE: The references returned by these functions are only valid for as long
// as the Attribute stays in place. For example, calling a function that mutates
// an Element's internal attribute storage may invalidate them.
Expand Down
4 changes: 2 additions & 2 deletions Source/WebCore/editing/cocoa/AutofillElements.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ std::optional<AutofillElements> AutofillElements::computeAutofillElements(Ref<HT
auto nextElement = nextAutofillableElement(start.ptr(), focusController);

bool previousFieldIsTextField = previousElement && !previousElement->isPasswordField();
bool hasSecondPasswordFieldToFill = nextElement && nextElement->isPasswordField() && nextElement->value().isEmpty();
bool hasSecondPasswordFieldToFill = nextElement && nextElement->isPasswordField() && nextElement->value()->isEmpty();

// Always allow AutoFill in a password field, even if we fill information only into it.
return {{ previousFieldIsTextField ? WTFMove(previousElement) : nullptr, WTFMove(start), hasSecondPasswordFieldToFill ? WTFMove(nextElement) : nullptr }};
Expand All @@ -98,7 +98,7 @@ std::optional<AutofillElements> AutofillElements::computeAutofillElements(Ref<HT
if (nextElement && is<HTMLInputElement>(*nextElement)) {
if (nextElement->isPasswordField()) {
auto elementAfterNextElement = nextAutofillableElement(nextElement.get(), focusController);
bool hasSecondPasswordFieldToFill = elementAfterNextElement && elementAfterNextElement->isPasswordField() && elementAfterNextElement->value().isEmpty();
bool hasSecondPasswordFieldToFill = elementAfterNextElement && elementAfterNextElement->isPasswordField() && elementAfterNextElement->value()->isEmpty();

return {{ WTFMove(start), WTFMove(nextElement), hasSecondPasswordFieldToFill ? WTFMove(elementAfterNextElement) : nullptr }};
}
Expand Down
4 changes: 2 additions & 2 deletions Source/WebCore/editing/cocoa/HTMLConverter.mm
Original file line number Diff line number Diff line change
Expand Up @@ -1867,15 +1867,15 @@ static NSInteger _colCompare(id block1, id block2, void *)
if (is<HTMLInputElement>(element)) {
HTMLInputElement& inputElement = downcast<HTMLInputElement>(element);
if (inputElement.type() == textAtom()) {
NSString *value = inputElement.value();
NSString *value = inputElement.value().get();
if (value && [value length] > 0)
_addValue(value, element);
}
}
} else if (element.hasTagName(textareaTag)) {
if (is<HTMLTextAreaElement>(element)) {
HTMLTextAreaElement& textAreaElement = downcast<HTMLTextAreaElement>(element);
NSString *value = textAreaElement.value();
NSString *value = textAreaElement.value().get();
if (value && [value length] > 0)
_addValue(value, element);
}
Expand Down
4 changes: 2 additions & 2 deletions Source/WebCore/html/BaseCheckableInputType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,9 +98,9 @@ bool BaseCheckableInputType::accessKeyAction(bool sendMouseEvents)
return InputType::accessKeyAction(sendMouseEvents) || element()->dispatchSimulatedClick(0, sendMouseEvents ? SendMouseUpDownEvents : SendNoEvents);
}

String BaseCheckableInputType::fallbackValue() const
ValueOrReference<String> BaseCheckableInputType::fallbackValue() const
{
return onAtom();
return onAtom().string();
}

bool BaseCheckableInputType::storesValueSeparateFromAttribute()
Expand Down
2 changes: 1 addition & 1 deletion Source/WebCore/html/BaseCheckableInputType.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ class BaseCheckableInputType : public InputType {
bool appendFormData(DOMFormData&) const final;
void handleKeypressEvent(KeyboardEvent&) final;
bool accessKeyAction(bool sendMouseEvents) final;
String fallbackValue() const final;
ValueOrReference<String> fallbackValue() const final;
bool storesValueSeparateFromAttribute() final;
void setValue(const String&, bool, TextFieldEventBehavior, TextControlSetValueSelection) final;
};
Expand Down
10 changes: 6 additions & 4 deletions Source/WebCore/html/BaseDateAndTimeInputType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -225,9 +225,11 @@ String BaseDateAndTimeInputType::visibleValue() const
return localizeValue(element()->value());
}

String BaseDateAndTimeInputType::sanitizeValue(const String& proposedValue) const
ValueOrReference<String> BaseDateAndTimeInputType::sanitizeValue(const String& proposedValue LIFETIME_BOUND) const
{
return typeMismatchFor(proposedValue) ? String() : proposedValue;
if (typeMismatchFor(proposedValue))
return String();
return proposedValue;
}

bool BaseDateAndTimeInputType::supportsReadOnly() const
Expand Down Expand Up @@ -355,7 +357,7 @@ void BaseDateAndTimeInputType::updateInnerTextValue()

DateTimeEditElement::LayoutParameters layoutParameters(element()->locale());

auto date = parseToDateComponents(element()->value());
auto date = parseToDateComponents(element()->value().get());
if (date)
setupLayoutParameters(layoutParameters, *date);
else {
Expand Down Expand Up @@ -553,7 +555,7 @@ bool BaseDateAndTimeInputType::setupDateTimeChooserParameters(DateTimeChooserPar
parameters.isAnchorElementRTL = computedStyle->direction() == TextDirection::RTL;
parameters.useDarkAppearance = document.useDarkAppearance(computedStyle);

auto date = valueOrDefault(parseToDateComponents(element.value()));
auto date = valueOrDefault(parseToDateComponents(element.value().get()));
parameters.hasSecondField = shouldHaveSecondField(date);
parameters.hasMillisecondField = shouldHaveMillisecondField(date);

Expand Down
2 changes: 1 addition & 1 deletion Source/WebCore/html/BaseDateAndTimeInputType.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ class BaseDateAndTimeInputType : public InputType, private DateTimeChooserClient

// InputType functions:
String visibleValue() const final;
String sanitizeValue(const String&) const override;
ValueOrReference<String> sanitizeValue(const String& value LIFETIME_BOUND) const override;
void setValue(const String&, bool valueChanged, TextFieldEventBehavior, TextControlSetValueSelection) final;
WallTime valueAsDate() const override;
ExceptionOr<void> setValueAsDate(WallTime) const override;
Expand Down
Loading