Skip to content

Commit

Permalink
Fix TextStream dumping of Objective-C types
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=262160
rdar://116094853

Reviewed by Richard Robinson.

Having both `operator<<(id)` and `operator<<(NSArray *)` caused problems, specifically
trying to dump a Class would hit the latter for some reason.

Remove ambiguity by removing `operator<<(NSArray *)` and have all dumping of Objective-C
types go through `operator<<(id)` which internally queries the object type. Add support
for dumping `Class` and `NSDictionary`.

Move functions that dump CG types out of TextStream and into TextStreamCocoa.h as standalone
functions, so that platform-independent headers aren't polluted with CG types.

* Source/WTF/WTF.xcodeproj/project.pbxproj:
* Source/WTF/wtf/text/TextStream.cpp:
* Source/WTF/wtf/text/TextStream.h:
* Source/WTF/wtf/text/TextStreamCocoa.h: Added.
* Source/WTF/wtf/text/cocoa/TextStreamCocoa.mm:
(WTF::TextStream::operator<<):
(WTF::operator<<):
* Tools/TestWebKitAPI/Tests/WTF/cocoa/TextStreamCocoa.mm:
(TEST):

Canonical link: https://commits.webkit.org/270118@main
  • Loading branch information
smfr committed Nov 2, 2023
1 parent a1e59cf commit 71add0a
Show file tree
Hide file tree
Showing 6 changed files with 128 additions and 38 deletions.
4 changes: 4 additions & 0 deletions Source/WTF/WTF.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
0FA6F38F20CC580F00A03DCD /* SegmentedVector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FA6F38E20CC580E00A03DCD /* SegmentedVector.cpp */; };
0FA6F39320CC73A300A03DCD /* SmallSet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FA6F39220CC73A200A03DCD /* SmallSet.cpp */; };
0FA6F39520CCACE900A03DCD /* UniqueArray.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FA6F39420CCACE900A03DCD /* UniqueArray.cpp */; };
0FC0CD722AF1ADC5009E2AD4 /* TextStreamCocoa.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC0CD712AF1ADC5009E2AD4 /* TextStreamCocoa.h */; settings = {ATTRIBUTES = (Private, ); }; };
0FDDBFA71666DFA300C55FEF /* StringPrintStream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FDDBFA51666DFA300C55FEF /* StringPrintStream.cpp */; };
0FE1646A1B6FFC9600400E7C /* Lock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FE164681B6FFC9600400E7C /* Lock.cpp */; };
0FE4479C1B7AAA03009498EB /* WordLock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FE4479A1B7AAA03009498EB /* WordLock.cpp */; };
Expand Down Expand Up @@ -1025,6 +1026,7 @@
0FB399B820AF5A580017E213 /* BooleanLattice.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BooleanLattice.h; sourceTree = "<group>"; };
0FB467821FDE282B003FCB09 /* ConcurrentBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConcurrentBuffer.h; sourceTree = "<group>"; };
0FB467831FDE282C003FCB09 /* ConcurrentVector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConcurrentVector.h; sourceTree = "<group>"; };
0FC0CD712AF1ADC5009E2AD4 /* TextStreamCocoa.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextStreamCocoa.h; sourceTree = "<group>"; };
0FC4488216FE9FE100844BE9 /* ProcessID.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProcessID.h; sourceTree = "<group>"; };
0FC4EDE51696149600F65041 /* CommaPrinter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CommaPrinter.h; sourceTree = "<group>"; };
0FD81AC4154FB22E00983E72 /* FastBitVector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FastBitVector.h; sourceTree = "<group>"; };
Expand Down Expand Up @@ -2543,6 +2545,7 @@
A8A4732C151A825B004123FF /* TextPosition.h */,
A3E4DD911F3A803400DED0B4 /* TextStream.cpp */,
A3E4DD921F3A803400DED0B4 /* TextStream.h */,
0FC0CD712AF1ADC5009E2AD4 /* TextStreamCocoa.h */,
70ECA60C1B02426800449739 /* UniquedStringImpl.h */,
FEF295BF20B49DCB00CF283A /* UTF8ConversionError.h */,
A8A4732D151A825B004123FF /* WTFString.cpp */,
Expand Down Expand Up @@ -3353,6 +3356,7 @@
DDF307E727C086DF006A526F /* TextBreakIteratorInternalICU.h in Headers */,
DDF307E027C086DF006A526F /* TextPosition.h in Headers */,
DDF307EE27C086DF006A526F /* TextStream.h in Headers */,
0FC0CD722AF1ADC5009E2AD4 /* TextStreamCocoa.h in Headers */,
DD3DC8AB27A4BF8E007E5B61 /* ThreadAssertions.h in Headers */,
DD3DC87327A4BF8E007E5B61 /* ThreadGroup.h in Headers */,
DD3DC8A327A4BF8E007E5B61 /* Threading.h in Headers */,
Expand Down
2 changes: 1 addition & 1 deletion Source/WTF/wtf/text/TextStream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -209,4 +209,4 @@ void writeIndent(TextStream& ts, int indent)
ts << " ";
}

}
} // namespace WTF
6 changes: 0 additions & 6 deletions Source/WTF/wtf/text/TextStream.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,12 +84,6 @@ class TextStream {

#if PLATFORM(COCOA)
WTF_EXPORT_PRIVATE TextStream& operator<<(id);
#ifdef __OBJC__
WTF_EXPORT_PRIVATE TextStream& operator<<(NSArray *);
WTF_EXPORT_PRIVATE TextStream& operator<<(CGRect);
WTF_EXPORT_PRIVATE TextStream& operator<<(CGSize);
WTF_EXPORT_PRIVATE TextStream& operator<<(CGPoint);
#endif
#endif

OptionSet<Formatting> formattingFlags() const { return m_formattingFlags; }
Expand Down
41 changes: 41 additions & 0 deletions Source/WTF/wtf/text/TextStreamCocoa.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Copyright (C) 2023 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. ``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
* 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 <CoreGraphics/CGGeometry.h>
#include <wtf/text/TextStream.h>

namespace WTF {

#if PLATFORM(COCOA)

WTF_EXPORT_PRIVATE TextStream& operator<<(TextStream&, CGRect);
WTF_EXPORT_PRIVATE TextStream& operator<<(TextStream&, CGSize);
WTF_EXPORT_PRIVATE TextStream& operator<<(TextStream&, CGPoint);

#endif

} // namespace WTF
86 changes: 58 additions & 28 deletions Source/WTF/wtf/text/cocoa/TextStreamCocoa.mm
Original file line number Diff line number Diff line change
Expand Up @@ -19,54 +19,84 @@
*/

#import "config.h"
#import <wtf/text/TextStream.h>
#import <wtf/text/TextStreamCocoa.h>

#import <objc/runtime.h>
#import <wtf/text/cf/StringConcatenateCF.h>

namespace WTF {

TextStream& TextStream::operator<<(id object)
{
if ([object isKindOfClass:[NSArray class]])
return *this << static_cast<NSArray *>(object);
if (object_isClass(object)) {
m_text.append(NSStringFromClass(object));
return *this;
}

if ([object conformsToProtocol:@protocol(NSObject)])
m_text.append([object description]);
else
m_text.append("(id)");
return *this;
}
auto outputArray = [&](NSArray *array) {
*this << "[";

TextStream& TextStream::operator<<(NSArray *array)
{
*this << "[";
for (NSUInteger i = 0; i < array.count; ++i) {
id item = array[i];
*this << item;
if (i < array.count - 1)
*this << ", ";
}

*this << "]";
};

for (NSUInteger i = 0; i < array.count; ++i) {
id item = array[i];
*this << item;
if (i < array.count - 1)
*this << ", ";
if ([object isKindOfClass:[NSArray class]]) {
outputArray(object);
return *this;
}

return *this << "]";
}
auto outputDictionary = [&](NSDictionary *dictionary) {
*this << "{";
bool needLeadingComma = false;

[dictionary enumerateKeysAndObjectsUsingBlock:[&](id key, id value, BOOL *) {
if (needLeadingComma)
*this << ", ";
needLeadingComma = true;

*this << key;
*this << ": ";
*this << value;
}];

*this << "}";
};

if ([object isKindOfClass:[NSDictionary class]]) {
outputDictionary(object);
return *this;
}

if ([object conformsToProtocol:@protocol(NSObject)])
m_text.append([object description]);
else
*this << "(id)";

TextStream& TextStream::operator<<(CGRect rect)
{
*this << "{{" << rect.origin.x << ", " << rect.origin.y << "}, {" << rect.size.width << ", " << rect.size.height << "}}";
return *this;
}

TextStream& TextStream::operator<<(CGSize size)
TextStream& operator<<(TextStream& ts, CGRect rect)
{
*this << "{" << size.width << ", " << size.height << "}";
return *this;
ts << "{{" << rect.origin.x << ", " << rect.origin.y << "}, {" << rect.size.width << ", " << rect.size.height << "}}";
return ts;
}

TextStream& TextStream::operator<<(CGPoint point)
TextStream& operator<<(TextStream& ts, CGSize size)
{
*this << "{" << point.x << ", " << point.y << "}";
return *this;
ts << "{" << size.width << ", " << size.height << "}";
return ts;
}

TextStream& operator<<(TextStream& ts, CGPoint point)
{
ts << "{" << point.x << ", " << point.y << "}";
return ts;
}

} // namespace WTF
27 changes: 24 additions & 3 deletions Tools/TestWebKitAPI/Tests/WTF/cocoa/TextStreamCocoa.mm
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
*/

#import "config.h"
#import <wtf/text/TextStream.h>
#import <wtf/text/TextStreamCocoa.h>

#import <Foundation/Foundation.h>

Expand All @@ -35,20 +35,41 @@
EXPECT_EQ(ts.release(), "Test"_s);
}

TEST(WTF_TextStream, Class)
{
TextStream ts;
ts << [NSString class];
EXPECT_EQ(ts.release(), "NSString"_s);
}

TEST(WTF_TextStream, NSArray)
{
{
TextStream ts;
ts << @[@"Test1", @"Test2"];
ts << @[ @"Test1", @"Test2" ];
EXPECT_EQ(ts.release(), "[Test1, Test2]"_s);
}
{
TextStream ts;
ts << @[@"Test1", @[@"Test2", @"Test3"]];
ts << @[ @"Test1", @[ @"Test2", @"Test3" ] ];
EXPECT_EQ(ts.release(), "[Test1, [Test2, Test3]]"_s);
}
}

TEST(WTF_TextStream, NSDictionary)
{
{
TextStream ts;
ts << @{ @"Test1" : @(3), @"Test2" : @"Hello" };
EXPECT_EQ(ts.release(), "{Test1: 3, Test2: Hello}"_s);
}
{
TextStream ts;
ts << @{ @"Test1" : @(3), @"Test2" : @[ @"Hello", @" ", @"there" ] };
EXPECT_EQ(ts.release(), "{Test1: 3, Test2: [Hello, , there]}"_s);
}
}

TEST(WTF_TextStream, NSNumber)
{
TextStream ts;
Expand Down

0 comments on commit 71add0a

Please sign in to comment.