Everywhere: Abandon Swift adoption

After making no progress on this for a very long time, let's acknowledge
it's not going anywhere and remove it from the codebase.
This commit is contained in:
Andreas Kling 2026-02-17 14:23:39 +01:00 committed by Tim Flynn
parent b3231ea2a0
commit e87f889e31
84 changed files with 22 additions and 4747 deletions

View file

@ -74,51 +74,6 @@ runs:
with:
xcode-version: 26.2
- name: 'Install Swift toolchain'
if: ${{ inputs.toolchain == 'Swift' }}
shell: bash
run: |
set -e
export SWIFTLY_HOME_DIR=${{ github.workspace }}/.swiftly/share
export SWIFTLY_BIN_DIR=${{ github.workspace }}/.swiftly/bin
echo "$SWIFTLY_BIN_DIR" >> $GITHUB_PATH
echo "SWIFTLY_HOME_DIR=$SWIFTLY_HOME_DIR" >> $GITHUB_ENV
echo "SWIFTLY_BIN_DIR=$SWIFTLY_BIN_DIR" >> $GITHUB_ENV
export PATH=$SWIFTLY_BIN_DIR:$PATH
mkdir -p $SWIFTLY_HOME_DIR
mkdir -p $SWIFTLY_BIN_DIR
if ${{ inputs.os == 'Linux' }} ; then
curl -O https://download.swift.org/swiftly/linux/swiftly-${{ inputs.arch }}.tar.gz
file swiftly-${{ inputs.arch }}.tar.gz
tar -xzf swiftly-${{ inputs.arch }}.tar.gz -C $SWIFTLY_BIN_DIR
rm swiftly-${{ inputs.arch }}.tar.gz
else
# FIXME: https://github.com/swiftlang/swiftly/issues/271
# Why does this drop files in $HOME? That's not very CI-friendly
curl -O https://download.swift.org/swiftly/darwin/swiftly.pkg
installer -pkg swiftly.pkg -target CurrentUserHomeDirectory
cp ~/.swiftly/bin/swiftly $SWIFTLY_BIN_DIR
rm swiftly.pkg
fi
swiftly init \
--no-modify-profile \
--quiet-shell-followup \
--assume-yes \
--skip-install \
--verbose
echo "swiftly version: $(swiftly --version)" >&2
# installs version listed in .swift-version
swiftly install
swiftly list
- name: 'Install Dependencies'
if: ${{ inputs.os == 'macOS' || inputs.os == 'Android' }}
shell: bash

View file

@ -66,11 +66,7 @@ jobs:
id: 'build-parameters'
run: |
CMAKE_OPTIONS="-DENABLE_CI_BASELINE_CPU=ON"
if ${{ inputs.toolchain == 'Swift' }} ; then
echo "host_cc=$(swiftly use --print-location)/usr/bin/clang" >> "$GITHUB_OUTPUT"
echo "host_cxx=$(swiftly use --print-location)/usr/bin/clang++" >> "$GITHUB_OUTPUT"
CMAKE_OPTIONS="$CMAKE_OPTIONS -DENABLE_SWIFT=ON"
elif ${{ inputs.os_name == 'Linux' }} ; then
if ${{ inputs.os_name == 'Linux' }} ; then
# FIXME: https://github.com/WebAssembly/wabt/issues/2533
# wabt doesn't have binary releases for arm64 Linux
if ${{ inputs.arch == 'arm64' }} ; then

View file

@ -15,7 +15,7 @@ jobs:
run: |
set -e
brew install curl llvm@20 ninja optipng ruff shellcheck swift-format unzip
brew install curl llvm@20 ninja optipng ruff shellcheck unzip
# Note: gn isn't available in homebrew :(
# Corresponds to https://gn.googlesource.com/gn/+/225e90c5025bf74f41dbee60d9cde4512c846fe7

View file

@ -47,20 +47,6 @@ jobs:
clang_plugins: false
runner_labels: '["blacksmith-8vcpu-ubuntu-2404-arm"]'
- os_name: 'Linux'
arch: 'x86_64'
build_preset: 'Sanitizer'
toolchain: 'Swift'
clang_plugins: false
runner_labels: '["blacksmith-8vcpu-ubuntu-2404"]'
- os_name: 'macOS'
arch: 'arm64'
build_preset: 'Sanitizer'
toolchain: 'Swift'
clang_plugins: false
runner_labels: '["macos-15", "self-hosted"]'
- os_name: 'Windows'
arch: 'x86_64'
build_preset: 'Sanitizer'

View file

@ -1,8 +0,0 @@
{
"version": 1,
"indentation": {
"spaces": 4
},
"tabWidth": 4,
"lineLength": 320
}

View file

@ -1 +0,0 @@
main-snapshot-2025-06-22

View file

@ -1,47 +0,0 @@
/*
* Copyright (c) 2024, Andrew Kaster <akaster@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@_exported import AKCxx
import Foundation
extension Swift.String {
public init?(akString: AK.String) {
let bytes = akString.__bytes_as_string_viewUnsafe().bytes()
let data = Foundation.Data(bytesNoCopy: UnsafeMutableRawPointer(mutating: bytes.data()), count: bytes.size(), deallocator: .none)
self.init(data: data, encoding: .utf8)
}
public init?(akStringView: AK.StringView) {
let bytes = akStringView.bytes()
let data = Foundation.Data(bytesNoCopy: UnsafeMutableRawPointer(mutating: bytes.data()), count: bytes.size(), deallocator: .none)
self.init(data: data, encoding: .utf8)
}
}
extension AK.String {
public init(swiftString: consuming Swift.String) {
self.init() // Create empty string first, using default constructor
swiftString.withUTF8 { buffer in
self = AK.String.from_utf8_without_validation(AK.ReadonlyBytes(buffer.baseAddress!, buffer.count))
}
}
}
extension AK.StringView: ExpressibleByStringLiteral {
public typealias StringLiteralType = Swift.StaticString
public init(stringLiteral value: StringLiteralType) {
self.init(value.utf8Start, value.utf8CodeUnitCount)
}
public func endsWith(_ suffix: AK.StringView) -> Bool {
if suffix.length() == 1 {
return self.ends_with(suffix[0])
}
return self.ends_with(suffix, AK.CaseSensitivity.sensitive)
}
}

View file

@ -68,11 +68,9 @@ endif()
configure_file(Backtrace.h.in Backtrace.h @ONLY)
find_package(simdutf REQUIRED)
swizzle_target_properties_for_swift(simdutf::simdutf)
target_link_libraries(AK PRIVATE simdutf::simdutf)
find_package(FastFloat CONFIG REQUIRED)
swizzle_target_properties_for_swift(FastFloat::fast_float)
target_link_libraries(AK PRIVATE FastFloat::fast_float)
# FIXME: Make this generic for all imported shared library dependencies and apply globally
@ -83,16 +81,6 @@ if (BUILD_SHARED_LIBS AND NOT CMAKE_SKIP_INSTALL_RULES AND NOT "${VCPKG_INSTALLE
)
endif()
if (ENABLE_SWIFT)
generate_clang_module_map(AK
GENERATED_FILES
"${CMAKE_CURRENT_BINARY_DIR}/Backtrace.h"
"${CMAKE_CURRENT_BINARY_DIR}/Debug.h"
)
target_sources(AK PRIVATE AK+Swift.swift)
add_swift_target_properties(AK)
endif()
if (WIN32)
# FIXME: Windows on ARM
target_link_libraries(AK PRIVATE clang_rt.builtins-x86_64.lib)

View file

@ -35,7 +35,6 @@
#include <AK/ScopeGuard.h>
#include <AK/Span.h>
#include <AK/StdLibExtras.h>
#include <AK/Swift.h>
#include <AK/TypeCasts.h>
#include <AK/Types.h>
@ -380,7 +379,7 @@ private:
static constexpr size_t inline_capacity = 4 * sizeof(void*);
alignas(inline_alignment) u8 m_storage[inline_capacity];
} SWIFT_UNSAFE_REFERENCE;
};
}

View file

@ -1,47 +0,0 @@
/*
* Copyright (c) 2024, Andrew Kaster <andrew@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#if __has_include(<swift/bridging>)
# include <swift/bridging>
// FIXME: Workaround for Xcode 14/15. When swif becomes required, we should bump the
// required Xcode version to one that supports all the features we are using.
# ifndef SWIFT_UNCHECKED_SENDABLE
# define SWIFT_UNCHECKED_SENDABLE
# define SWIFT_NONCOPYABLE
# define SWIFT_NONESCAPABLE
# define SWIFT_ESCAPABLE
# define SWIFT_ESCAPABLE_IF(...)
# define SWIFT_RETURNS_RETAINED
# define SWIFT_RETURNS_UNRETAINED
# endif
#else
# define SWIFT_SELF_CONTAINED
# define SWIFT_RETURNS_INDEPENDENT_VALUE
# define SWIFT_SHARED_REFERENCE(retain, release)
# define SWIFT_IMMORTAL_REFERENCE
# define SWIFT_UNSAFE_REFERENCE
# define SWIFT_NAME(name)
# define SWIFT_CONFORMS_TO_PROTOCOL(protocol)
# define SWIFT_COMPUTED_PROPERTY
# define SWIFT_MUTATING
# define SWIFT_UNCHECKED_SENDABLE
# define SWIFT_NONCOPYABLE
# define SWIFT_NONESCAPABLE
# define SWIFT_ESCAPABLE
# define SWIFT_ESCAPABLE_IF(...)
# define SWIFT_RETURNS_RETAINED
# define SWIFT_RETURNS_UNRETAINED
#endif
// FIXME: This needs to be in the global namespace for reasons
// https://github.com/swiftlang/swift/issues/80231
template<class From, class To>
To cxxCast(From i)
{
return static_cast<To>(i);
}

View file

@ -15,7 +15,7 @@
#include <AK/Diagnostics.h>
#include <AK/Platform.h>
#ifdef AK_OS_WINDOWS // needed for Swift
#ifdef AK_OS_WINDOWS
# define timeval dummy_timeval
# include <ntstatus.h>
# include <winsock2.h>

View file

@ -11,11 +11,7 @@ endif()
include("Meta/CMake/use_linker.cmake")
if (APPLE AND NOT CMAKE_OSX_DEPLOYMENT_TARGET)
if (ENABLE_SWIFT)
set(CMAKE_OSX_DEPLOYMENT_TARGET 15.0)
else()
set(CMAKE_OSX_DEPLOYMENT_TARGET 14.0)
endif()
set(CMAKE_OSX_DEPLOYMENT_TARGET 14.0)
endif()
# Pass additional information to vcpkg toolchain files if we are using vcpkg.

View file

@ -187,61 +187,3 @@ After youve finished debugging your code changes with that build, you can rev
That will restore your git environment to the state it was in before you patched the build file.
## Building with Swift support
There is experimental Swift 6 support in the Ladybird codebase. This experiment intends to determine whether Swift 6 and
its improved C++ interoperability is a good choice for new memory-safe and concurrent code for Ladybird.
Building with Swift 6 support requires a main snapshot toolchain. The Ladybird team is actively working with the Swift
team to improve the C++ interop features to meet the needs of our project.
The best way to get started is with `swiftly`. After setting up a `swiftly` toolchain, any of the existing build presets
can be modified to use the Swift toolchain. However, note that in order to build Swift support into the project, the
build must use a version of Clang that is built from an LLVM fork with Swift support. The two places this can be found
are from the swift.org snapshot/release toolchains, and Xcode toolchains. Upstream llvm.org Clang does not support
Swift, and GCC does not support Swift either.
### Get Swiftly
`swiftly` is a tool that helps you manage Swift toolchains. It can be installed from https://www.swift.org/install/linux/
or https://www.swift.org/install/macos/ as applicable. After following the instructions on the swift.org install page,
`swiftly` installs the latest release toolchain. If you wish to save space, add the `--skip-install` flag to the `swiftly
init` invocation. If you wish to avoid `swiftly` messing with your shellrc files, add `--no-modify-profile`. On some Linux
platforms, it may be necessary to add a `--platform` flag to the `swiftly init` invocation to instruct `swiftly` on which
supported platform to masquerade as. This is especially necessary on Fedora or other non-Debian based distributions.
Note that while `$SWIFTLY_HOME_DIR` and `$SWIFTLY_BIN_DIR` can be used
to set the installed location of the `swiftly` binary and its associated files, the install location of toolchains is not
nearly as customizable. On Linux they will always be placed in `$XDG_DATA_HOME/swiftly/toolchains`, and on macOS they will always be
placed in `$HOME/Library/Developer/Toolchains`. On macOS, the `.pkg` file will always drop temporary files in `$HOME/.swiftly`,
so be sure to clear them out if you change the default home/bin directories.
### Build with Swift
The simplest way to enable Swift is to use the `Swift_Release` preset and `ladybird.py`.
```bash
./Meta/ladybird.py build --preset Swift_Release
```
Note that because building with Swift support requires use of `clang` and `clang++` from a Swift toolchain, a standard
install of Clang or GCC will not work. Additional IDE settings are be required to ensure that the IDE uses the correct
compiler paths. Trying to use just `clang` or `$SWIFTLY_BIN_DIR/clang` will both fail, due to https://github.com/swiftlang/swiftly/issues/272.
The full paths that must be configured for the C and C++ compilers in your IDE are
`$(swiftly use --print-location)/usr/bin/clang` and `$(swiftly use --print-location)/usr/bin/clang++`. These paths
will change depending on the version of the Swift toolchain specified in `.swift-version`.
As another note, the main-snapshot toolchains from swift.org are `+assertion` builds. This means that both `clang` and
`swiftc` are built with extra assertions that will cause compile-times to be longer than a standard release build.
To configure the build preset manually, you must first install the specified Swift toolchain, and then set the C and C++
compiler paths manually.
```bash
swiftly install
cmake --preset Swift_Release \
-DCMAKE_C_COMPILER=$(swiftly use --print-location)/usr/bin/clang \
-DCMAKE_CXX_COMPILER=$(swiftly use --print-location)/usr/bin/clang++
```

View file

@ -99,7 +99,6 @@ Heres a short timeline:
## Do you have some general details about the code and basic architecture?
- C++ while selectively migrating parts to Swift and while keeping an eye on things like Sean Baxters [Circle](https://github.com/seanbaxter/circle) & [Safe C++](https://safecpp.org/draft.html).
- Some use of third-party libraries (e.g., Harfbuzz, Skia, [simdutf](https://github.com/simdutf/simdutf), libcurl).
- Performance optimizing is not yet a super-high priority (but performance-boosting changes are regularly getting made).
- Code size:

View file

@ -149,27 +149,3 @@ endif()
if (ANDROID)
target_link_libraries(LibCore PRIVATE log)
endif()
if (ENABLE_SWIFT)
if(WIN32)
list(APPEND SWIFT_EXCLUDE_HEADERS "EventLoopImplementationUnix.h")
else()
list(APPEND SWIFT_EXCLUDE_HEADERS "EventLoopImplementationWindows.h")
endif()
if (NOT APPLE)
list(APPEND SWIFT_EXCLUDE_HEADERS
IOSurface.h
MachPort.h
MachMessageTypes.h
ProcessStatisticsMach.h
)
endif()
generate_clang_module_map(LibCore EXCLUDE_FILES ${SWIFT_EXCLUDE_HEADERS})
target_sources(LibCore PRIVATE
EventSwift.mm
EventLoopExecutor.swift)
set_source_files_properties(EventSwift.mm PRIVATE PROPERTIES COMPILE_FLAGS -fblocks)
target_link_libraries(LibCore PRIVATE AK)
add_swift_target_properties(LibCore LAGOM_LIBRARIES AK)
endif()

View file

@ -13,7 +13,6 @@
#include <AK/Function.h>
#include <AK/Noncopyable.h>
#include <AK/NonnullOwnPtr.h>
#include <AK/Swift.h>
#include <AK/Time.h>
#include <LibCore/Event.h>
#include <LibCore/Forward.h>
@ -99,7 +98,7 @@ public:
private:
NonnullOwnPtr<EventLoopImplementation> m_impl;
RefPtr<WeakEventLoopReference> m_weak;
} SWIFT_UNSAFE_REFERENCE;
};
class StrongEventLoopReference;

View file

@ -1,53 +0,0 @@
/*
* Copyright (c) 2025, Andrew Kaster <andrew@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
import AK
@_exported import CoreCxx
extension Core.EventLoop: Equatable {
func deferred_invoke(_ task: @escaping () -> Void) {
Core.deferred_invoke_block(self, task)
}
public static func == (lhs: Core.EventLoop, rhs: Core.EventLoop) -> Bool {
Unmanaged.passUnretained(lhs).toOpaque() == Unmanaged.passUnretained(rhs).toOpaque()
}
}
public class EventLoopExecutor: SerialExecutor, TaskExecutor, @unchecked Sendable {
nonisolated private let eventLoop: Core.EventLoop
public init() {
eventLoop = Core.EventLoop.current()
}
public init(eventLoop: Core.EventLoop) {
self.eventLoop = eventLoop
}
public nonisolated func enqueue(_ job: consuming ExecutorJob) {
let job = UnownedJob(job)
eventLoop.deferred_invoke { [self, job] in
job.runSynchronously(
isolatedTo: self.asUnownedSerialExecutor(),
taskExecutor: self.asUnownedTaskExecutor())
}
}
public func checkIsolated() {
precondition(Core.EventLoop.current() == eventLoop)
}
}
public protocol EventLoopActor: Actor {
nonisolated var executor: EventLoopExecutor { get } // impl with a let
}
extension EventLoopActor {
public nonisolated var unownedExecutor: UnownedSerialExecutor {
executor.asUnownedSerialExecutor()
}
}

View file

@ -1,17 +0,0 @@
/*
* Copyright (c) 2025, Andrew Kaster <andrew@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibCore/EventLoop.h>
#include <LibCore/EventSwift.h>
namespace Core {
void deferred_invoke_block(EventLoop& event_loop, void (^invokee)(void))
{
event_loop.deferred_invoke(invokee);
}
}

View file

@ -3,7 +3,6 @@ set(SOURCES
Cell.cpp
CellAllocator.cpp
ConservativeVector.cpp
ForeignCell.cpp
Root.cpp
RootHashMap.cpp
RootVector.cpp
@ -16,15 +15,6 @@ set(SOURCES
ladybird_lib(LibGC gc EXPLICIT_SYMBOL_EXPORT)
target_link_libraries(LibGC PRIVATE LibCore)
if (ENABLE_SWIFT)
generate_clang_module_map(LibGC)
target_sources(LibGC PRIVATE
Heap+Swift.swift
)
target_link_libraries(LibGC PRIVATE AK)
add_swift_target_properties(LibGC LAGOM_LIBRARIES AK)
endif()
# TODO: Use lagom_generate_export_header and annotate entire LibGC with export macros
include(GenerateExportHeader)
generate_export_header(LibGC EXPORT_MACRO_NAME GC_API EXPORT_FILE_NAME "Export.h")

View file

@ -13,7 +13,6 @@
#include <AK/Noncopyable.h>
#include <AK/Platform.h>
#include <AK/StringView.h>
#include <AK/Swift.h>
#include <AK/Weakable.h>
#include <LibGC/Forward.h>
#include <LibGC/Internals.h>
@ -72,17 +71,17 @@ public:
visit_impl(*cell);
}
void visit(Cell& cell) SWIFT_NAME(visitRef(_:))
void visit(Cell& cell)
{
visit_impl(cell);
}
void visit(Cell const* cell) SWIFT_NAME(visitConst(_:))
void visit(Cell const* cell)
{
visit(const_cast<Cell*>(cell));
}
void visit(Cell const& cell) SWIFT_NAME(visitConstRef(_:))
void visit(Cell const& cell)
{
visit(const_cast<Cell&>(cell));
}
@ -185,7 +184,7 @@ public:
visit(optional.value());
}
void visit(NanBoxedValue const& value) SWIFT_NAME(visitValue(_:));
void visit(NanBoxedValue const& value);
// Allow explicitly ignoring a GC-allocated member in a visit_edges implementation instead
// of just not using it.
@ -200,7 +199,7 @@ public:
virtual void visit_impl(Cell&) = 0;
virtual void visit_impl(ReadonlySpan<NanBoxedValue>) = 0;
virtual ~Visitor() = default;
} SWIFT_UNSAFE_REFERENCE;
};
MUST_UPCALL virtual void visit_edges(Visitor&) { }
@ -220,7 +219,7 @@ protected:
private:
bool m_mark { false };
State m_state { State::Live };
} SWIFT_UNSAFE_REFERENCE;
};
}

View file

@ -6,7 +6,6 @@
#pragma once
#include <AK/Swift.h>
#include <LibGC/Heap.h>
namespace GC {
@ -26,6 +25,6 @@ public:
private:
Heap& m_heap;
} SWIFT_NONCOPYABLE;
};
}

View file

@ -1,61 +0,0 @@
/*
* Copyright (c) 2024, Andrew Kaster <andrew@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibGC/DeferGC.h>
#include <LibGC/ForeignCell.h>
#include <LibGC/Heap.h>
namespace GC {
void* ForeignCell::foreign_data()
{
// !!!
auto offset = round_up_to_power_of_two(sizeof(ForeignCell), m_vtable.alignment);
return static_cast<void*>(reinterpret_cast<u8*>(this) + offset);
}
ForeignCell::ForeignCell(ForeignCell::Vtable vtable)
: m_vtable(move(vtable))
{
if (m_vtable.initialize)
m_vtable.initialize(foreign_data(), m_vtable.class_metadata_pointer, *this);
}
ForeignCell::~ForeignCell()
{
if (m_vtable.destroy)
m_vtable.destroy(foreign_data(), m_vtable.class_metadata_pointer);
}
Ref<ForeignCell> ForeignCell::create(Heap& heap, size_t size, ForeignCell::Vtable vtable)
{
// NOTE: GC must be deferred so that a collection during allocation doesn't get tripped
// up looking for the Cell pointer on the stack or in a register when it might only exist in the heap.
// We can't guarantee that the ForeignCell will be stashed in a proper ForeignRef/ForeignPtr or similar
// foreign type until after all the dust has settled on both sides of the FFI boundary.
VERIFY(heap.is_gc_deferred());
VERIFY(is_power_of_two(vtable.alignment));
auto& allocator = heap.allocator_for_size(sizeof(ForeignCell) + round_up_to_power_of_two(size, vtable.alignment));
auto* memory = allocator.allocate_cell(heap);
auto* foreign_cell = new (memory) ForeignCell(move(vtable));
return *foreign_cell;
}
void ForeignCell::finalize()
{
Base::finalize();
if (m_vtable.finalize)
m_vtable.finalize(foreign_data(), m_vtable.class_metadata_pointer);
}
void ForeignCell::visit_edges(Cell::Visitor& visitor)
{
Base::visit_edges(visitor);
if (m_vtable.visit_edges)
m_vtable.visit_edges(foreign_data(), m_vtable.class_metadata_pointer, visitor);
}
}

View file

@ -1,182 +0,0 @@
/*
* Copyright (c) 2024, Andrew Kaster <andrew@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/String.h>
#include <AK/Swift.h>
#include <AK/TypeCasts.h>
#include <LibGC/Cell.h>
#include <LibGC/DeferGC.h>
namespace GC {
template<typename T>
struct ForeignRef;
template<typename T>
struct ForeignPtr;
#define FOREIGN_CELL(class_, base_class) \
using Base = base_class; \
friend class GC::Heap;
class GC_API ForeignCell : public Cell {
FOREIGN_CELL(ForeignCell, Cell);
public:
static constexpr bool OVERRIDES_FINALIZE = true;
struct Vtable {
// Holds a pointer to the foreign vtable information such as
// a jclass in Java, or a Swift type metadata pointer
void* class_metadata_pointer = nullptr;
// FIXME: FlyString? The class name must be owned by the ForeignCell so it can vend StringViews
// We should properly cache the name and class info pointer to avoid string churn
String class_name;
size_t alignment { 1 };
void (*initialize)(void* thiz, void* clazz, Ref<Cell>);
void (*destroy)(void* thiz, void* clazz);
void (*finalize)(void* thiz, void* clazz);
void (*visit_edges)(void* thiz, void* clazz, Cell::Visitor&);
};
static Ref<ForeignCell> create(Heap&, size_t size, Vtable);
void* foreign_data() SWIFT_RETURNS_INDEPENDENT_VALUE; // technically lying to swift, but it's fiiiiine
// ^Cell
virtual void finalize() override;
virtual void visit_edges(Cell::Visitor& visitor) override;
virtual StringView class_name() const override { return m_vtable.class_name; }
~ForeignCell();
private:
ForeignCell(Vtable vtable);
Vtable m_vtable;
} SWIFT_IMMORTAL_REFERENCE;
template<typename T>
struct ForeignRef {
friend struct ForeignPtr<T>;
template<typename... Args>
static ForeignRef allocate(Heap& heap, Args... args)
{
DeferGC const defer_gc(heap);
auto* cell = T::create(&heap, forward<Args>(args)...);
if constexpr (IsSame<decltype(cell), Cell*>) {
return ForeignRef(*as<ForeignCell>(cell));
} else {
static_assert(IsSame<decltype(cell), void*>);
auto* cast_cell = static_cast<Cell*>(cell);
return ForeignRef(*as<ForeignCell>(cast_cell));
}
}
ForeignRef() = delete;
// This constructor should only be called directly after allocating a foreign cell by calling an FFI create method
ForeignRef(ForeignCell& cell)
: m_cell(cell)
{
// FIXME: This is super dangerous. How can we assert that the cell is actually a T?
m_data = static_cast<T*>(m_cell->foreign_data());
}
~ForeignRef() = default;
ForeignRef(ForeignRef const& other) = default;
ForeignRef& operator=(ForeignRef const& other) = default;
RETURNS_NONNULL T* operator->() const { return m_data; }
[[nodiscard]] T& operator*() const { return *m_data; }
RETURNS_NONNULL T* ptr() const { return m_data; }
RETURNS_NONNULL operator T*() const { return m_data; }
operator T&() const { return *m_data; }
Ref<ForeignCell> cell() const { return m_cell; }
void visit_edges(Cell::Visitor& visitor)
{
visitor.visit(m_cell);
}
private:
Ref<ForeignCell> m_cell;
T* m_data { nullptr };
};
template<typename T>
struct ForeignPtr {
constexpr ForeignPtr() = default;
// This constructor should only be called directly after allocating a foreign cell by calling an FFI create method
ForeignPtr(ForeignCell& cell)
: m_cell(&cell)
{
// FIXME: This is super dangerous. How can we assert that the cell is actually a T?
m_data = static_cast<T*>(m_cell->foreign_data());
}
// This constructor should only be called directly after allocating a foreign cell by calling an FFI create method
ForeignPtr(ForeignCell* cell)
: m_cell(cell)
{
// FIXME: This is super dangerous. How can we assert that the cell is actually a T?
m_data = m_cell ? static_cast<T*>(m_cell->foreign_data()) : nullptr;
}
ForeignPtr(ForeignRef<T> const& other)
: m_cell(other.m_cell)
, m_data(other.m_data)
{
}
ForeignPtr(nullptr_t)
: m_cell(nullptr)
{
}
ForeignPtr(ForeignPtr const& other) = default;
ForeignPtr& operator=(ForeignPtr const& other) = default;
T* operator->() const
{
ASSERT(m_cell && m_data);
return m_data;
}
[[nodiscard]] T& operator*() const
{
ASSERT(m_cell && m_data);
return *m_data;
}
operator T*() const { return m_data; }
T* ptr() const { return m_data; }
explicit operator bool() const { return !!m_cell; }
bool operator!() const { return !m_cell; }
Ptr<ForeignCell> cell() const { return m_cell; }
void visit_edges(Cell::Visitor& visitor)
{
visitor.visit(m_cell);
}
private:
Ptr<ForeignCell> m_cell;
T* m_data { nullptr };
};
}

View file

@ -14,7 +14,6 @@ namespace GC {
class Cell;
class CellAllocator;
class DeferGC;
class ForeignCell;
class RootImpl;
class Heap;
class HeapBlock;

View file

@ -1,82 +0,0 @@
/*
* Copyright (c) 2024, Andrew Kaster <andrew@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
import AK
@_exported import GCCxx
extension GC.Heap {
public func withDeferredGC<R, E>(_ body: () throws(E) -> R) throws(E) -> R {
let deferredRAII = GC.DeferGC(self)
_ = deferredRAII
return try body()
}
}
public protocol HeapAllocatable {
static func allocate(on heap: GC.Heap) -> UnsafeMutablePointer<Self>
init(cell: GC.Cell)
func finalize()
func visitEdges(_ visitor: GC.Cell.Visitor)
var cell: GC.Cell { get }
}
// Here be dragons
func asTypeMetadataPointer(_ type: Any.Type) -> UnsafeMutableRawPointer {
unsafeBitCast(type, to: UnsafeMutableRawPointer.self)
}
func asHeapAllocatableType(_ typeMetadata: UnsafeMutableRawPointer) -> any HeapAllocatable.Type {
let typeObject = unsafeBitCast(typeMetadata, to: Any.Type.self)
guard let type = typeObject as? any HeapAllocatable.Type else {
fatalError("Passed foreign class but it wasn't a Swift type!")
}
return type
}
extension HeapAllocatable {
fileprivate static func initializeFromFFI(at this: UnsafeMutableRawPointer, cell: GC.Cell) {
this.assumingMemoryBound(to: Self.self).initialize(to: Self.self.init(cell: cell))
}
fileprivate static func destroyFromFFI(at this: UnsafeMutableRawPointer) {
this.assumingMemoryBound(to: Self.self).deinitialize(count: 1)
}
fileprivate static func finalizeFromFFI(at this: UnsafeMutableRawPointer) {
this.assumingMemoryBound(to: Self.self).pointee.finalize()
}
fileprivate static func visitEdgesFromFFI(at this: UnsafeMutableRawPointer, visitor: GC.Cell.Visitor) {
this.assumingMemoryBound(to: Self.self).pointee.visitEdges(visitor)
}
public static func allocate(on heap: GC.Heap) -> UnsafeMutablePointer<Self> {
let vtable = GC.ForeignCell.Vtable(
class_metadata_pointer: asTypeMetadataPointer(Self.self),
class_name: AK.String(swiftString: Swift.String(describing: Self.self)),
alignment: MemoryLayout<Self>.alignment,
initialize: { this, typeMetadata, cell in
asHeapAllocatableType(typeMetadata!).initializeFromFFI(at: this!, cell: cell.ptr())
},
destroy: { this, typeMetadata in
asHeapAllocatableType(typeMetadata!).destroyFromFFI(at: this!)
},
finalize: { this, typeMetadata in
asHeapAllocatableType(typeMetadata!).finalizeFromFFI(at: this!)
},
visit_edges: nil
)
let cell = GC.ForeignCell.create(heap, MemoryLayout<Self>.stride, vtable)
return cell.pointee.foreign_data().assumingMemoryBound(to: Self.self)
}
public func finalize() {}
public func visitEdges(_ visitor: GC.Cell.Visitor) {}
}

View file

@ -12,7 +12,6 @@
#include <AK/Noncopyable.h>
#include <AK/NonnullOwnPtr.h>
#include <AK/StackInfo.h>
#include <AK/Swift.h>
#include <AK/Types.h>
#include <AK/Vector.h>
#include <LibCore/Forward.h>
@ -90,7 +89,6 @@ private:
friend class MarkingVisitor;
friend class GraphConstructorVisitor;
friend class DeferGC;
friend class ForeignCell;
void defer_gc();
void undefer_gc();
@ -179,7 +177,7 @@ private:
WeakBlock::List m_usable_weak_blocks;
WeakBlock::List m_full_weak_blocks;
} SWIFT_IMMORTAL_REFERENCE;
};
inline void Heap::did_create_root(Badge<RootImpl>, RootImpl& impl)
{

View file

@ -61,14 +61,6 @@ set(SOURCES
YUVData.cpp
)
set(SWIFT_EXCLUDE_HEADERS
FilterImpl.h
GlobalFontConfig.h
MetalContext.h
VulkanContext.h
SkiaUtils.h
)
if (APPLE)
list(APPEND SOURCES MetalContext.mm)
endif()
@ -157,15 +149,6 @@ else()
target_link_libraries(LibGfx PRIVATE libjxl::libjxl hwy::hwy)
endif()
if (ENABLE_SWIFT)
generate_clang_module_map(LibGfx GENERATED_FILES ${generated_headers} EXCLUDE_FILES ${SWIFT_EXCLUDE_HEADERS})
target_sources(LibGfx PRIVATE
Color.swift
)
target_link_libraries(LibGfx PRIVATE AK)
add_swift_target_properties(LibGfx LAGOM_LIBRARIES AK)
endif()
if (APPLE)
target_link_libraries(LibCore PUBLIC "-framework Metal")
target_link_libraries(LibCore PUBLIC "-framework Accelerate")

View file

@ -10,7 +10,6 @@
#include <AK/ByteString.h>
#include <AK/Optional.h>
#include <AK/StringConversions.h>
#include <AK/Swift.h>
#include <AK/Utf16String.h>
#include <AK/Utf16View.h>
#include <AK/Vector.h>
@ -19,10 +18,6 @@
#include <LibIPC/Encoder.h>
#include <ctype.h>
#ifdef LIBGFX_USE_SWIFT
# include <LibGfx-Swift.h>
#endif
namespace Gfx {
namespace {
@ -355,15 +350,6 @@ Optional<Color> Color::from_named_css_color_string(StringView string)
return {};
}
#if defined(LIBGFX_USE_SWIFT)
static Optional<Color> hex_string_to_color(StringView string)
{
auto color = parseHexString(string);
if (color.getCount() == 0)
return {};
return color[0];
}
#else
static Optional<Color> hex_string_to_color(StringView string)
{
auto hex_nibble_to_u8 = [](char nibble) -> Optional<u8> {
@ -414,7 +400,6 @@ static Optional<Color> hex_string_to_color(StringView string)
return Color(r.value(), g.value(), b.value(), a.value());
}
#endif
Optional<Color> Color::from_string(StringView string)
{

View file

@ -1,89 +0,0 @@
/*
* Copyright (c) 2024, Andrew Kaster <andrew@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
import AK
@_exported import GfxCxx
// FIXME: Do this without extending String with an index operation that was explicitly deleted :^)
extension Swift.String {
subscript(_ index: Int) -> Character {
return self[self.index(self.startIndex, offsetBy: index)]
}
}
private func hexNibbleToUInt8(_ nibble: Character) -> UInt8? {
guard nibble.isHexDigit else {
return nil
}
return UInt8(nibble.hexDigitValue!)
}
private func hexNibblesToUInt8(_ nib1: Character, _ nib2: Character) -> UInt8? {
guard let n1 = hexNibbleToUInt8(nib1) else {
return nil
}
guard let n2 = hexNibbleToUInt8(nib2) else {
return nil
}
return n1 << 4 | n2
}
// FIXME: Return Gfx.Color? When swift ABI bug is fixed
public func parseHexString(_ rawString: AK.StringView) -> [Gfx.Color] {
guard let string = Swift.String(akStringView: rawString) else {
return []
}
assert(string.hasPrefix("#"))
switch string.count {
case 4:
let r = hexNibbleToUInt8(string[1])
let g = hexNibbleToUInt8(string[2])
let b = hexNibbleToUInt8(string[3])
guard r != nil && g != nil && b != nil else {
return []
}
return [Gfx.Color(r! * 17, g! * 17, b! * 17)]
case 5:
let r = hexNibbleToUInt8(string[1])
let g = hexNibbleToUInt8(string[2])
let b = hexNibbleToUInt8(string[3])
let a = hexNibbleToUInt8(string[4])
guard r != nil && g != nil && b != nil && a != nil else {
return []
}
return [Gfx.Color(r! * 17, g! * 17, b! * 17, a! * 17)]
case 6: return []
case 7:
let r = hexNibblesToUInt8(string[1], string[2])
let g = hexNibblesToUInt8(string[3], string[4])
let b = hexNibblesToUInt8(string[5], string[6])
guard r != nil && g != nil && b != nil else {
return []
}
return [Gfx.Color(r!, g!, b!, UInt8(255))]
case 8: return []
case 9:
let r = hexNibblesToUInt8(string[1], string[2])
let g = hexNibblesToUInt8(string[3], string[4])
let b = hexNibblesToUInt8(string[5], string[6])
let a = hexNibblesToUInt8(string[7], string[8])
guard r != nil && g != nil && b != nil && a != nil else {
return []
}
return [Gfx.Color(r!, g!, b!, a!)]
default: return []
}
}

View file

@ -1210,23 +1210,3 @@ target_link_libraries(LibWeb PRIVATE LibCore LibCompress LibCrypto LibJS LibHTTP
target_include_directories(LibWeb PRIVATE ${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/include)
generate_js_bindings(LibWeb)
if (ENABLE_SWIFT)
include(collections)
set(generated_headers ${GENERATED_SOURCES})
list(FILTER generated_headers INCLUDE REGEX "\\.h$")
list(TRANSFORM generated_headers PREPEND "${CMAKE_CURRENT_BINARY_DIR}/")
list(APPEND LIBWEB_ALL_GENERATED_HEADERS ${generated_headers})
generate_clang_module_map(LibWeb GENERATED_FILES ${LIBWEB_ALL_GENERATED_HEADERS})
target_sources(LibWeb PRIVATE
HTML/Parser/HTMLToken.swift
HTML/Parser/HTMLTokenizer.swift
HTML/Parser/HTMLTokenizerHelpers.cpp
HTML/Parser/SpeculativeHTMLParser.swift
)
target_link_libraries(LibWeb PRIVATE AK Collections)
add_swift_target_properties(LibWeb LAGOM_LIBRARIES AK LibGfx LibGC)
endif()

View file

@ -51,10 +51,6 @@
#include <LibWeb/SVG/SVGScriptElement.h>
#include <LibWeb/SVG/TagNames.h>
#ifdef LIBWEB_USE_SWIFT
# include <LibWeb-Swift.h>
#endif
namespace Web::HTML {
GC_DEFINE_ALLOCATOR(HTMLParser);
@ -205,10 +201,6 @@ void HTMLParser::visit_edges(Cell::Visitor& visitor)
void HTMLParser::initialize(JS::Realm& realm)
{
Base::initialize(realm);
#if defined(LIBWEB_USE_SWIFT)
m_speculative_parser = GC::ForeignRef<Web::SpeculativeHTMLParser>::allocate(realm.heap(), this);
#endif
}
void HTMLParser::run(HTMLTokenizer::StopAtInsertionPoint stop_at_insertion_point)

View file

@ -15,16 +15,6 @@
#include <LibWeb/HTML/Parser/StackOfOpenElements.h>
#include <LibWeb/MimeSniff/MimeType.h>
#ifdef LIBWEB_USE_SWIFT
# include <LibGC/ForeignCell.h>
namespace Web {
class SpeculativeHTMLParser;
}
#endif
namespace Web::HTML {
#define ENUMERATE_INSERTION_MODES \
@ -221,22 +211,14 @@ private:
GC::Ptr<HTMLFormElement> m_form_element;
GC::Ptr<DOM::Element> m_context_element;
#ifdef LIBWEB_USE_SWIFT
GC::ForeignPtr<Web::SpeculativeHTMLParser> m_speculative_parser;
#endif
Vector<HTMLToken> m_pending_table_character_tokens;
GC::Ptr<DOM::Text> m_character_insertion_node;
StringBuilder m_character_insertion_builder { StringBuilder::Mode::UTF16 };
} SWIFT_UNSAFE_REFERENCE;
};
RefPtr<CSS::StyleValue const> parse_dimension_value(StringView);
RefPtr<CSS::StyleValue const> parse_nonzero_dimension_value(StringView);
Optional<Color> parse_legacy_color_value(StringView);
// Swift interop
using HTMLParserGCPtr = GC::Ptr<HTMLParser>;
using HTMLParserGCRef = GC::Ref<HTMLParser>;
}

View file

@ -1,286 +0,0 @@
/*
* Copyright (c) 2024, Andrew Kaster <andrew@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
@_exported import WebCxx
public class HTMLToken {
public struct Position: Equatable {
var line = UInt()
var column = UInt()
var byteOffset = UInt()
}
public struct Attribute: Equatable {
public var prefix: Swift.String? = nil
public var localName: Swift.String
public var namespace_: Swift.String? = nil
public var value: Swift.String
public var nameStartPosition = Position()
public var nameEndPosition = Position()
public var valueStartPosition = Position()
public var valueEndPosition = Position()
public init(localName: Swift.String, value: Swift.String) {
self.localName = localName
self.value = value
}
}
public enum TokenType: Equatable {
case Invalid
case DOCTYPE(
name: Swift.String?,
publicIdentifier: Swift.String?,
systemIdentifier: Swift.String?,
forceQuirksMode: Bool)
case StartTag(
tagName: Swift.String,
selfClosing: Bool = false,
selfClosingAcknowledged: Bool = false,
attributes: [Attribute] = [])
case EndTag(
tagName: Swift.String,
selfClosing: Bool = false,
selfClosingAcknowledged: Bool = false,
attributes: [Attribute] = [])
case Comment(data: Swift.String)
case Character(codePoint: Character)
case EndOfFile
}
public func isCharacter() -> Bool {
if case .Character(_) = self.type {
return true
}
return false
}
public func isEndTag() -> Bool {
if case .EndTag(_, _, _, _) = self.type {
return true
}
return false
}
public func isStartTag() -> Bool {
if case .StartTag(_, _, _, _) = self.type {
return true
}
return false
}
public func isTag() -> Bool {
return isStartTag() || isEndTag()
}
public func isParserWhitespace() -> Bool {
precondition(isCharacter(), "isParserWhitespace() called on non-character token")
// NOTE: The parser considers '\r' to be whitespace, while the tokenizer does not.
switch self.type {
case .Character(codePoint: "\t"),
.Character(codePoint: "\n"),
.Character(codePoint: "\u{000C}"), // \f
.Character(codePoint: "\r"),
.Character(codePoint: " "):
return true
default:
return false
}
}
public var type = TokenType.Invalid
public var startPosition = Position()
public var endPosition = Position()
// Is in-place mutating enums a thing? Seems not https://forums.swift.org/t/in-place-mutation-of-an-enum-associated-value/11747
public var attributes: [Attribute] {
get {
switch self.type {
case .StartTag(_, _, _, let attributes):
return attributes
case .EndTag(_, _, _, let attributes):
return attributes
default:
preconditionFailure("attributes called on non-tag token")
}
}
set {
switch self.type {
case .StartTag(let tagName, let selfClosing, let selfClosingAcknowledged, attributes: _):
self.type = .StartTag(tagName: tagName, selfClosing: selfClosing, selfClosingAcknowledged: selfClosingAcknowledged, attributes: newValue)
case .EndTag(let tagName, let selfClosing, let selfClosingAcknowledged, attributes: _):
self.type = .EndTag(tagName: tagName, selfClosing: selfClosing, selfClosingAcknowledged: selfClosingAcknowledged, attributes: newValue)
default:
preconditionFailure("attributes= called on non-tag token")
}
}
}
public var tagName: Swift.String {
get {
switch self.type {
case .StartTag(let tagName, _, _, _):
return tagName
case .EndTag(let tagName, _, _, _):
return tagName
default:
preconditionFailure("tagName called on non-tag token")
}
}
set {
switch self.type {
case .StartTag(tagName: _, let selfClosing, let selfClosingAcknowledged, let attributes):
self.type = .StartTag(tagName: newValue, selfClosing: selfClosing, selfClosingAcknowledged: selfClosingAcknowledged, attributes: attributes)
case .EndTag(tagName: _, let selfClosing, let selfClosingAcknowledged, let attributes):
self.type = .EndTag(tagName: newValue, selfClosing: selfClosing, selfClosingAcknowledged: selfClosingAcknowledged, attributes: attributes)
default:
preconditionFailure("tagName= called on non-tag token")
}
}
}
public var selfClosing: Bool {
get {
switch self.type {
case .StartTag(_, let selfClosing, _, _):
return selfClosing
case .EndTag(_, let selfClosing, _, _):
return selfClosing
default:
preconditionFailure("selfClosing called on non-tag token")
}
}
set {
switch self.type {
case .StartTag(let tagName, _, let selfClosingAcknowledged, let attributes):
self.type = .StartTag(tagName: tagName, selfClosing: newValue, selfClosingAcknowledged: selfClosingAcknowledged, attributes: attributes)
case .EndTag(let tagName, _, let selfClosingAcknowledged, let attributes):
self.type = .EndTag(tagName: tagName, selfClosing: newValue, selfClosingAcknowledged: selfClosingAcknowledged, attributes: attributes)
default:
preconditionFailure("selfClosing= called on non-tag token")
}
}
}
public var name: Swift.String? {
get {
switch self.type {
case .DOCTYPE(let name, _, _, _):
return name
default:
preconditionFailure("doctypeName called on non-doctype token")
}
}
set {
switch self.type {
case .DOCTYPE(_, let publicIdentifier, let systemIdentifier, let forceQuirksMode):
self.type = .DOCTYPE(name: newValue, publicIdentifier: publicIdentifier, systemIdentifier: systemIdentifier, forceQuirksMode: forceQuirksMode)
default:
preconditionFailure("doctypeName= called on non-doctype token")
}
}
}
public var forceQuirks: Bool {
get {
switch self.type {
case .DOCTYPE(_, _, _, let forceQuirksMode):
return forceQuirksMode
default:
preconditionFailure("forceQuirks called on non-doctype token")
}
}
set {
switch self.type {
case .DOCTYPE(let name, let publicIdentifier, let systemIdentifier, _):
self.type = .DOCTYPE(name: name, publicIdentifier: publicIdentifier, systemIdentifier: systemIdentifier, forceQuirksMode: newValue)
default:
preconditionFailure("forceQuirks= called on non-doctype token")
}
}
}
public var publicIdentifier: Swift.String? {
get {
switch self.type {
case .DOCTYPE(_, let publicIdentifier, _, _):
return publicIdentifier
default:
preconditionFailure("publicIdentifier called on non-doctype token")
}
}
set {
switch self.type {
case .DOCTYPE(let name, _, let systemIdentifier, let forceQuirksMode):
self.type = .DOCTYPE(name: name, publicIdentifier: newValue, systemIdentifier: systemIdentifier, forceQuirksMode: forceQuirksMode)
default:
preconditionFailure("publicIdentifier= called on non-doctype token")
}
}
}
public var systemIdentifier: Swift.String? {
get {
switch self.type {
case .DOCTYPE(_, _, let systemIdentifier, _):
return systemIdentifier
default:
preconditionFailure("systemIdentifier called on non-doctype token")
}
}
set {
switch self.type {
case .DOCTYPE(let name, let publicIdentifier, _, let forceQuirksMode):
self.type = .DOCTYPE(name: name, publicIdentifier: publicIdentifier, systemIdentifier: newValue, forceQuirksMode: forceQuirksMode)
default:
preconditionFailure("systemIdentifier= called on non-doctype token")
}
}
}
public init() {}
public init(type: TokenType) {
self.type = type
}
}
extension HTMLToken.Position: CustomStringConvertible {
public var description: Swift.String {
return "\(self.line):\(self.column)"
}
}
extension HTMLToken.TokenType: CustomStringConvertible {
// FIXME: Print attributes for start/end tags
public var description: Swift.String {
switch self {
case .Invalid:
return "Invalid"
case .DOCTYPE(let name, let publicIdentifier, let systemIdentifier, let forceQuirksMode):
return "DOCTYPE(name: \(name ?? "nil"), publicIdentifier: \(publicIdentifier ?? "nil"), systemIdentifier: \(systemIdentifier ?? "nil"), forceQuirksMode: \(forceQuirksMode))"
case .StartTag(let tagName, let selfClosing, let selfClosingAcknowledged, let attributes):
return "StartTag(tagName: \(tagName), selfClosing: \(selfClosing), selfClosingAcknowledged: \(selfClosingAcknowledged), attributes: \(attributes))"
case .EndTag(let tagName, let selfClosing, let selfClosingAcknowledged, let attributes):
return "EndTag(tagName: \(tagName), selfClosing: \(selfClosing), selfClosingAcknowledged: \(selfClosingAcknowledged), attributes: \(attributes))"
case .Comment(let data):
return "Comment(data: \(data))"
case .Character(let codePoint):
return "Character(codePoint: \(codePoint))"
case .EndOfFile:
return "EndOfFile"
}
}
}
extension HTMLToken: CustomStringConvertible {
public var description: Swift.String {
if self.startPosition == Position() {
return "HTMLToken(type: \(self.type))"
} else if self.endPosition == Position() {
return "HTMLToken(type: \(self.type))@\(self.startPosition)"
} else {
return "HTMLToken(type: \(self.type))@\(self.startPosition)-\(self.endPosition)"
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,51 +0,0 @@
/*
* Copyright (c) 2024, Andrew Kaster <akaster@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibTextCodec/Decoder.h>
#include <LibWeb/HTML/Parser/Entities.h>
#include <LibWeb/HTML/Parser/HTMLTokenizerHelpers.h>
#include <LibWeb/HTML/Parser/NamedCharacterReferences.h>
namespace Web::HTML {
OptionalString decode_to_utf8(StringView text, StringView encoding)
{
auto decoder = TextCodec::decoder_for(encoding);
if (!decoder.has_value())
return std::nullopt;
auto decoded_or_error = decoder.value().to_utf8(text);
if (decoded_or_error.is_error())
return std::nullopt;
return decoded_or_error.release_value();
}
OptionalEntityMatch match_entity_for_named_character_reference(StringView entity)
{
NamedCharacterReferenceMatcher matcher;
int consumed_length = 0;
for (auto c : entity) {
if (!matcher.try_consume_ascii_char(c))
break;
consumed_length++;
}
auto codepoints = matcher.code_points();
if (codepoints.has_value()) {
EntityMatch match;
auto matched_length = consumed_length - matcher.overconsumed_code_points();
auto matched_string_view = entity.substring_view(0, matched_length);
auto second_codepoint = named_character_reference_second_codepoint_value(codepoints.value().second);
if (second_codepoint.has_value()) {
match = { { codepoints.value().first, second_codepoint.release_value() }, matched_string_view };
} else {
match = { { codepoints.value().first }, matched_string_view };
}
return match;
}
return std::nullopt;
}
}

View file

@ -1,32 +0,0 @@
/*
* Copyright (c) 2024, Andrew Kaster <akaster@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/String.h>
#include <AK/StringView.h>
#include <optional>
namespace Web::HTML {
// FIXME: This is a temporary stop-gap solution, and it should be removed once the C++
// NamedCharacterReference state implementation is implemented in Swift.
struct EntityMatch {
Vector<u32, 2> code_points;
StringView entity;
};
// Swift-friendly wrapper for TextCodec::Decoder::to_utf8
using OptionalString = std::optional<String>;
OptionalString decode_to_utf8(StringView text, StringView encoding);
// Swift-friendly wrapper for HTML::code_points_from_entity
// FIXME: This is a temporary stop-gap solution, and it should be removed once the C++
// NamedCharacterReference state implementation is implemented in Swift.
using OptionalEntityMatch = std::optional<EntityMatch>;
OptionalEntityMatch match_entity_for_named_character_reference(StringView entity);
}

View file

@ -1,60 +0,0 @@
/*
* Copyright (c) 2025, Andrew Kaster <andrew@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
import AK
import Collections
import Foundation
import GC
@_exported import WebCxx
// Workaround for https://github.com/swiftlang/swift/issues/80231
// If any line of this changes, the whole thing breaks though
extension GC.Cell.Visitor {
public func visit(_ parser: Web.HTML.HTMLParserGCPtr) {
if let parser = parser.ptr() {
let cell: GC.Cell = cxxCast(parser)
visit(cell)
}
}
}
struct SpeculativeMockElement {
let name: Swift.String
let localName: Swift.String
let attributes: [HTMLToken.Attribute]
var children: [SpeculativeMockElement]
init(name: Swift.String, localName: Swift.String, attributes: [HTMLToken.Attribute]) {
self.name = name
self.localName = localName
self.attributes = attributes
self.children = []
}
mutating func appendChild(_ child: consuming SpeculativeMockElement) {
children.append(child)
}
}
public final class SpeculativeHTMLParser: HeapAllocatable {
var parser = Web.HTML.HTMLParserGCPtr() // FIXME: Want HTMLParserGCRef here, but how to initialize it?
public init(cell: GC.Cell) {
self.cell = cell
}
public var cell: GC.Cell
public static func create(on heap: GC.Heap, `for` parser: Web.HTML.HTMLParserGCPtr) -> GC.Cell {
precondition(heap.is_gc_deferred())
let _self = allocate(on: heap)
_self.pointee.parser = parser
return _self.pointee.cell
}
public func visitEdges(_ visitor: GC.Cell.Visitor) {
visitor.visit(parser)
}
}

View file

@ -9,7 +9,6 @@
#include <AK/ByteString.h>
#include <AK/Error.h>
#include <AK/Function.h>
#include <AK/Swift.h>
#include <LibWeb/Export.h>
namespace Web {
@ -24,6 +23,6 @@ public:
private:
ByteString m_path {};
} SWIFT_UNSAFE_REFERENCE; // FIXME: This type is actually move-only, not unsafe
};
}

View file

@ -9,7 +9,6 @@
#include <AK/ByteString.h>
#include <AK/LexicalPath.h>
#include <AK/Optional.h>
#include <AK/Swift.h>
#include <LibCore/EventLoop.h>
#include <LibCore/Forward.h>
#include <LibDatabase/Forward.h>
@ -268,7 +267,7 @@ private:
OwnPtr<DevTools::DevToolsServer> m_devtools;
mutable HashMap<u64, u64> m_navigation_listener_ids;
} SWIFT_IMMORTAL_REFERENCE;
};
}

View file

@ -1,9 +1,7 @@
# Finds the BlocksRuntime library
# On Apple platforms, this does not exist and is folded into other System libraries
find_library(BLOCKS_RUNTIME NAMES BlocksRuntime
PATHS ${SWIFT_LIBRARY_SEARCH_PATHS}
)
find_library(BLOCKS_RUNTIME NAMES BlocksRuntime)
if (BLOCKS_RUNTIME)
if (NOT TARGET BlocksRuntime::BlocksRuntime)
add_library(BlocksRuntime::BlocksRuntime IMPORTED UNKNOWN)
@ -12,7 +10,7 @@ if (BLOCKS_RUNTIME)
set_target_properties(BlocksRuntime::BlocksRuntime PROPERTIES
IMPORTED_LOCATION "${BLOCKS_RUNTIME}"
INTERFACE_LINK_DIRECTORIES "${_BLOCKS_RUNTIME_DIR}"
INTERFACE_COMPILE_OPTIONS "$<$<COMPILE_LANGUAGE:C,CXX>:-fblocks>;SHELL:$<$<COMPILE_LANGUAGE:Swift>:-Xcc -fblocks>"
INTERFACE_COMPILE_OPTIONS "$<$<COMPILE_LANGUAGE:C,CXX>:-fblocks>"
)
endif()
set(BlocksRuntime_FOUND TRUE)

View file

@ -1,60 +0,0 @@
# Finds the swift-testing library
# On Apple platforms, this is a framework included in the Xcode release
include_guard()
if (NOT TARGET SwiftTesting::SwiftTesting)
cmake_policy(PUSH)
if (POLICY CMP0152)
cmake_policy(SET CMP0152 NEW)
endif()
set(_SEARCH_PATHS "")
set(_PLUGIN_PATHS "")
foreach(path IN LISTS SWIFT_LIBRARY_SEARCH_PATHS)
file(REAL_PATH ${path} real_path)
if (EXISTS ${real_path})
list(APPEND _SEARCH_PATHS ${real_path})
if (EXISTS "${real_path}/testing")
list(APPEND _SEARCH_PATHS "${real_path}/testing")
endif()
endif()
if (EXISTS "${real_path}/../host/plugins")
file(REAL_PATH "${real_path}/../host/plugins" plugin_path)
list(APPEND _PLUGIN_PATHS ${plugin_path})
if (EXISTS "${plugin_path}/testing")
list(APPEND _PLUGIN_PATHS "${plugin_path}/testing")
endif()
endif()
endforeach()
list(REMOVE_DUPLICATES _SEARCH_PATHS)
list(REMOVE_DUPLICATES _PLUGIN_PATHS)
find_library(SWIFT_TESTING NAMES Testing
PATHS ${_SEARCH_PATHS}
)
if (SWIFT_TESTING)
add_library(SwiftTesting::SwiftTesting IMPORTED UNKNOWN)
message(STATUS "Found SwiftTesting: ${SWIFT_TESTING}")
cmake_path(GET SWIFT_TESTING PARENT_PATH _SWIFT_TESTING_DIR)
find_library(SWIFT_TESTING_MACROS NAMES TestingMacros
PATHS ${_PLUGIN_PATHS}
NO_DEFAULT_PATH
)
if (NOT SWIFT_TESTING_MACROS)
message(FATAL_ERROR "Could not find associated TestingMacros plugin for ${SWIFT_TESTING}")
else()
message(VERBOSE "Found SwiftTesting macros: ${SWIFT_TESTING_MACROS}")
endif()
set_target_properties(SwiftTesting::SwiftTesting PROPERTIES
IMPORTED_LOCATION "${SWIFT_TESTING}"
INTERFACE_LINK_DIRECTORIES "${_SWIFT_TESTING_DIR}"
INTERFACE_INCLUDE_DIRECTORIES "${_SWIFT_TESTING_DIR}"
INTERFACE_COMPILE_OPTIONS "$<$<COMPILE_LANGUAGE:Swift>:SHELL:-load-plugin-library ${SWIFT_TESTING_MACROS}>"
INTERFACE_LINK_OPTIONS "-load-plugin-library;${SWIFT_TESTING_MACROS}"
)
set(SwiftTesting_FOUND TRUE)
endif()
cmake_policy(POP)
endif()

View file

@ -1,92 +0,0 @@
# This source file is part of the Swift open source project
#
# Copyright (c) 2023 Apple Inc. and the Swift project authors.
# Licensed under Apache License v2.0 with Runtime Library Exception
#
# See https://swift.org/LICENSE.txt for license information
# Generate the bridging header from Swift to C++
#
# target: the name of the target to generate headers for.
# This target must build swift source files.
# header: the name of the header file to generate.
#
# NOTE: This logic will eventually be unstreamed into CMake.
function(_swift_generate_cxx_header target header)
if(NOT TARGET ${target})
message(FATAL_ERROR "Target ${target} not defined.")
endif()
if(NOT DEFINED CMAKE_Swift_COMPILER)
message(WARNING "Swift not enabled in project. Cannot generate headers for Swift files.")
return()
endif()
cmake_parse_arguments(PARSE_ARGV 2 "ARG" "" "MODULE_NAME;CXX_STD_VERSION" "SEARCH_PATHS;COMPILE_OPTIONS")
if(NOT ARG_MODULE_NAME)
set(target_module_name $<TARGET_PROPERTY:${target},Swift_MODULE_NAME>)
set(ARG_MODULE_NAME $<IF:$<BOOL:${target_module_name}>,${target_module_name},${target}>)
endif()
if(ARG_SEARCH_PATHS)
list(TRANSFORM ARG_SEARCH_PATHS PREPEND "-I")
endif()
if(APPLE)
set(SDK_FLAGS "-sdk" "${CMAKE_OSX_SYSROOT}")
list(APPEND SDK_FLAGS "-target" "${CMAKE_Swift_COMPILER_TARGET}")
elseif(WIN32)
set(SDK_FLAGS "-sdk" "$ENV{SDKROOT}")
elseif(DEFINED ${CMAKE_SYSROOT})
set(SDK_FLAGS "-sdk" "${CMAKE_SYSROOT}")
list(APPEND SDK_FLAGS "-target" "${CMAKE_Swift_COMPILER_TARGET}")
endif()
cmake_path(APPEND CMAKE_CURRENT_BINARY_DIR include
OUTPUT_VARIABLE base_path)
cmake_path(APPEND base_path ${header}
OUTPUT_VARIABLE header_path)
if (NOT ARG_CXX_STD_VERSION)
set(ARG_CXX_STD_VERSION "14")
get_target_property(CxxFeatures ${target} COMPILE_FEATURES)
list(FILTER CxxFeatures INCLUDE REGEX "cxx_std_[0-9]+$")
if (NOT "${CxxFeatures}" STREQUAL "")
string(SUBSTRING ${CxxFeatures} 8 2 ARG_CXX_STD_VERSION)
endif()
endif()
set(CXX_STD_FLAGS -Xcc -std=c++${ARG_CXX_STD_VERSION})
set(_AllSources $<TARGET_PROPERTY:${target},SOURCES>)
set(_SwiftSources $<FILTER:${_AllSources},INCLUDE,\\.swift$>)
add_custom_command(OUTPUT ${header_path}
DEPENDS ${_SwiftSources}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMAND
${CMAKE_Swift_COMPILER} -frontend -typecheck
${ARG_SEARCH_PATHS}
${_SwiftSources}
${SDK_FLAGS}
${CXX_STD_FLAGS}
${ARG_COMPILE_OPTIONS}
-Xcc -Wno-unqualified-std-cast-call
-Xcc -Wno-user-defined-literals
-Xcc -Wno-unknown-warning-option
-Xcc -Wno-invalid-offsetof
-module-name "${ARG_MODULE_NAME}"
-cxx-interoperability-mode=default
-emit-clang-header-path ${header_path}
COMMENT
"Generating '${header_path}'"
COMMAND_EXPAND_LISTS)
# Added to public interface for dependees to find.
target_include_directories(${target} PUBLIC $<BUILD_INTERFACE:${base_path}>)
# Added to the target to ensure target rebuilds if header changes and is used
# by sources in the target.
target_sources(${target} PRIVATE ${header_path})
endfunction()

View file

@ -1,109 +0,0 @@
# This source file is part of the Swift open source project
#
# Copyright (c) 2023 Apple Inc. and the Swift project authors.
# Licensed under Apache License v2.0 with Runtime Library Exception
#
# See https://swift.org/LICENSE.txt for license information
# Compute the name of the architecture directory on Windows from the CMake
# system processor name.
function(_swift_windows_arch_name output_variable_name target_arch)
if(NOT WIN32)
return()
endif()
if("${target_arch}" STREQUAL "AMD64")
set("${output_variable_name}" "x86_64" PARENT_SCOPE)
elseif("${target_arch}" STREQUAL "ARM64")
set("${output_variable_name}" "aarch64" PARENT_SCOPE)
else()
message(FATAL_ERROR "Unknown windows architecture: ${target_arch}")
endif()
endfunction()
# Compute flags and search paths
# NOTE: This logic will eventually move to CMake
function(_setup_swift_paths)
# If we haven't set the swift library search paths, do that now
if(NOT SWIFT_LIBRARY_SEARCH_PATHS OR NOT SWIFT_INCLUDE_PATHS OR (APPLE AND NOT SWIFT_TARGET_TRIPLE))
if(APPLE)
set(SDK_FLAGS "-sdk" "${CMAKE_OSX_SYSROOT}")
endif()
# Note: This does not handle cross-compiling correctly.
# To handle it correctly, we would need to pass the target triple and
# flags to this compiler invocation.
execute_process(
COMMAND ${CMAKE_Swift_COMPILER} ${SDK_FLAGS} -print-target-info
OUTPUT_VARIABLE SWIFT_TARGET_INFO
)
# FIXME: https://gitlab.kitware.com/cmake/cmake/-/issues/26174
if (APPLE)
if (CMAKE_OSX_DEPLOYMENT_TARGET)
set(SWIFT_TARGET_TRIPLE "${CMAKE_SYSTEM_PROCESSOR}-apple-macosx${CMAKE_OSX_DEPLOYMENT_TARGET}" CACHE STRING "Swift target triple")
else()
string(JSON SWIFT_TARGET_TARGET GET ${SWIFT_TARGET_INFO} "target")
string(JSON SWIFT_TARGET_TARGET_TRIPLE GET ${SWIFT_TARGET_TARGET} "triple")
set(SWIFT_TARGET_TRIPLE ${SWIFT_TARGET_TARGET_TRIPLE} CACHE STRING "Swift target triple")
endif()
endif()
# extract search paths from swift driver response
string(JSON SWIFT_TARGET_PATHS GET ${SWIFT_TARGET_INFO} "paths")
string(JSON SWIFT_TARGET_LIBRARY_PATHS GET ${SWIFT_TARGET_PATHS} "runtimeLibraryPaths")
string(JSON SWIFT_TARGET_LIBRARY_PATHS_LENGTH LENGTH ${SWIFT_TARGET_LIBRARY_PATHS})
math(EXPR SWIFT_TARGET_LIBRARY_PATHS_LENGTH "${SWIFT_TARGET_LIBRARY_PATHS_LENGTH} - 1 ")
string(JSON SWIFT_TARGET_LIBRARY_IMPORT_PATHS GET ${SWIFT_TARGET_PATHS} "runtimeLibraryImportPaths")
string(JSON SWIFT_TARGET_LIBRARY_IMPORT_PATHS_LENGTH LENGTH ${SWIFT_TARGET_LIBRARY_IMPORT_PATHS})
math(EXPR SWIFT_TARGET_LIBRARY_IMPORT_PATHS_LENGTH "${SWIFT_TARGET_LIBRARY_IMPORT_PATHS_LENGTH} - 1 ")
string(JSON SWIFT_SDK_IMPORT_PATH ERROR_VARIABLE errno GET ${SWIFT_TARGET_PATHS} "sdkPath")
foreach(JSON_ARG_IDX RANGE ${SWIFT_TARGET_LIBRARY_PATHS_LENGTH})
string(JSON SWIFT_LIB GET ${SWIFT_TARGET_LIBRARY_PATHS} ${JSON_ARG_IDX})
list(APPEND SWIFT_SEARCH_PATHS ${SWIFT_LIB})
endforeach()
foreach(JSON_ARG_IDX RANGE ${SWIFT_TARGET_LIBRARY_IMPORT_PATHS_LENGTH})
string(JSON SWIFT_LIB GET ${SWIFT_TARGET_LIBRARY_IMPORT_PATHS} ${JSON_ARG_IDX})
list(APPEND SWIFT_SEARCH_PATHS ${SWIFT_LIB})
endforeach()
if(SWIFT_SDK_IMPORT_PATH)
list(APPEND SWIFT_SEARCH_PATHS ${SWIFT_SDK_IMPORT_PATH})
endif()
# Save the swift library search paths
set(SWIFT_LIBRARY_SEARCH_PATHS ${SWIFT_SEARCH_PATHS} CACHE FILEPATH "Swift driver search paths")
string(JSON SWIFT_RUNTIME_RESOURCE_PATH GET ${SWIFT_TARGET_PATHS} "runtimeResourcePath")
set(SWIFT_TOOLCHAIN_INCLUDE_DIR "${SWIFT_RUNTIME_RESOURCE_PATH}/../../include")
cmake_path(ABSOLUTE_PATH SWIFT_TOOLCHAIN_INCLUDE_DIR NORMALIZE)
if (NOT IS_DIRECTORY "${SWIFT_TOOLCHAIN_INCLUDE_DIR}")
message(WARNING "Expected toolchain include dir ${SWIFT_TOOLCHAIN_INCLUDE_DIR} does not exist")
endif()
set(SWIFT_INCLUDE_PATHS ${SWIFT_TOOLCHAIN_INCLUDE_DIR} CACHE FILEPATH "Swift interop include paths")
endif()
link_directories(${SWIFT_LIBRARY_SEARCH_PATHS})
include_directories(${SWIFT_INCLUDE_PATHS})
if(WIN32)
_swift_windows_arch_name(SWIFT_WIN_ARCH_DIR "${CMAKE_SYSTEM_PROCESSOR}")
set(SWIFT_SWIFTRT_FILE "$ENV{SDKROOT}/usr/lib/swift/windows/${SWIFT_WIN_ARCH_DIR}/swiftrt.obj")
add_link_options("$<$<LINK_LANGUAGE:Swift>:${SWIFT_SWIFTRT_FILE}>")
elseif(NOT APPLE)
find_file(SWIFT_SWIFTRT_FILE
swiftrt.o
PATHS ${SWIFT_LIBRARY_SEARCH_PATHS}
NO_CACHE
REQUIRED
NO_DEFAULT_PATH)
add_link_options("$<$<LINK_LANGUAGE:Swift>:${SWIFT_SWIFTRT_FILE}>")
endif()
endfunction()
_setup_swift_paths()

View file

@ -1,82 +0,0 @@
enable_language(Swift)
if (CMAKE_Swift_COMPILER_VERSION VERSION_LESS 6.0)
message(FATAL_ERROR "Swift 6.0 or newer is required to parse C++ headers in C++23 mode")
endif()
# Check for a Swift-aware clang
include(CheckCXXSourceCompiles)
check_cxx_source_compiles([=[
struct __attribute__((swift_name("CxxS"))) __attribute__((swift_attr("~Copyable"))) S { int& x; };
int main() {}
]=] CXX_COMPILER_SUPPORTS_SWIFT_ATTRS)
if (NOT CXX_COMPILER_SUPPORTS_SWIFT_ATTRS)
message(FATAL_ERROR "A Swift-aware C++ compiler is required to build with Swift interop enabled")
endif()
include(${CMAKE_CURRENT_LIST_DIR}/InitializeSwift.cmake)
include(${CMAKE_CURRENT_LIST_DIR}/GenerateSwiftHeader.cmake)
find_package(SwiftTesting REQUIRED)
# FIXME: https://gitlab.kitware.com/cmake/cmake/-/issues/26174
if (APPLE)
set(CMAKE_Swift_COMPILER_TARGET "${SWIFT_TARGET_TRIPLE}")
endif()
add_compile_options("SHELL:$<$<COMPILE_LANGUAGE:Swift>:-enable-experimental-feature Extern>")
set(VFS_OVERLAY_DIRECTORY "${CMAKE_BINARY_DIR}/vfs_overlays" CACHE PATH "Directory to put VFS overlays in")
# FIXME: https://gitlab.kitware.com/cmake/cmake/-/issues/26195
# For now, we'll just manually massage the flags.
function(swizzle_target_properties_for_swift target_name)
get_property(compile_options TARGET ${target_name} PROPERTY INTERFACE_COMPILE_OPTIONS)
set(munged_properties "")
foreach(property IN LISTS compile_options)
set(cxx_property "$<$<COMPILE_LANGUAGE:C,CXX,ASM>:${property}>")
set(swift_property "SHELL:$<$<COMPILE_LANGUAGE:Swift>:-Xcc ${property}>")
list(APPEND munged_properties "${cxx_property}" "${swift_property}")
endforeach()
set_property(TARGET ${target_name} PROPERTY INTERFACE_COMPILE_OPTIONS ${munged_properties})
endfunction()
function(add_swift_target_properties target_name)
cmake_parse_arguments(PARSE_ARGV 1 SWIFT_TARGET "" "" "LAGOM_LIBRARIES;COMPILE_DEFINITIONS;COMPILE_OPTIONS")
target_compile_features(${target_name} PUBLIC cxx_std_${CMAKE_CXX_STANDARD})
target_compile_options(${target_name} PUBLIC "SHELL:$<$<COMPILE_LANGUAGE:Swift>:-Xcc -std=c++23 -cxx-interoperability-mode=default>")
string(REPLACE "Lib" "" module_name ${target_name})
string(TOUPPER ${target_name} TARGET_NAME_UPPER)
target_compile_definitions(${target_name} PRIVATE "${TARGET_NAME_UPPER}_USE_SWIFT")
set_target_properties(${target_name} PROPERTIES Swift_MODULE_NAME ${module_name})
# FIXME: These should be pulled automatically from interface compile options for the target
set(VFS_OVERLAY_OPTIONS "-Xcc" "-ivfsoverlay${VFS_OVERLAY_DIRECTORY}/${target_name}_vfs_overlay.yaml")
foreach(internal_library IN LISTS SWIFT_TARGET_LAGOM_LIBRARIES)
list(APPEND VFS_OVERLAY_OPTIONS "-Xcc" "-ivfsoverlay${VFS_OVERLAY_DIRECTORY}/${internal_library}_vfs_overlay.yaml")
endforeach()
get_target_property(_NATIVE_DIRS ${target_name} INCLUDE_DIRECTORIES)
list(APPEND _NATIVE_DIRS ${CMAKE_Swift_MODULE_DIRECTORY})
# Swift-testing in swift.org toolchains on macOS has its .swiftmodule in a testing/ subdirectory of
# the swift compiler's built-in lib dirs.
get_target_property(DEPENDENCIES ${target_name} LINK_LIBRARIES)
if (SwiftTesting::SwiftTesting IN_LIST DEPENDENCIES)
get_target_property(SWIFT_TESTING_INCLUDE_DIRS SwiftTesting::SwiftTesting INTERFACE_INCLUDE_DIRECTORIES)
list(APPEND _NATIVE_DIRS ${SWIFT_TESTING_INCLUDE_DIRS})
endif()
set(EXTRA_COMPILE_DEFINITIONS "")
foreach (compile_definition IN LISTS SWIFT_TARGET_COMPILE_DEFINITIONS)
list(APPEND EXTRA_COMPILE_DEFINITIONS "-Xcc" "-D${compile_definition}")
endforeach()
_swift_generate_cxx_header(${target_name} "${target_name}-Swift.h"
SEARCH_PATHS ${_NATIVE_DIRS}
COMPILE_OPTIONS ${VFS_OVERLAY_OPTIONS} ${EXTRA_COMPILE_DEFINITIONS} ${SWIFT_TARGET_COMPILE_OPTIONS}
)
endfunction()

View file

@ -23,40 +23,6 @@ function(embed_as_string name source_file output source_variable_name)
add_dependencies(ladybird_codegen_accumulator "generate_${name}")
endfunction()
function(generate_clang_module_map target_name)
cmake_parse_arguments(PARSE_ARGV 1 MODULE_MAP "" "DIRECTORY" "GENERATED_FILES;EXCLUDE_FILES")
if (NOT MODULE_MAP_DIRECTORY)
set(MODULE_MAP_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}")
endif()
string(REPLACE "Lib" "" module_name ${target_name})
set(module_name "${module_name}Cxx")
set(module_map_file "${CMAKE_CURRENT_BINARY_DIR}/module/module.modulemap")
set(vfs_overlay_file "${VFS_OVERLAY_DIRECTORY}/${target_name}_vfs_overlay.yaml")
find_package(Python3 REQUIRED COMPONENTS Interpreter)
# FIXME: Make this depend on the public headers of the target
add_custom_command(
OUTPUT "${module_map_file}"
COMMAND "${Python3_EXECUTABLE}" "${SerenityOS_SOURCE_DIR}/Meta/generate_clang_module_map.py"
"${MODULE_MAP_DIRECTORY}"
--module-name "${module_name}"
--module-map "${module_map_file}"
--vfs-map ${vfs_overlay_file}
--exclude-files ${MODULE_MAP_EXCLUDE_FILES}
--generated-files ${MODULE_MAP_GENERATED_FILES}
VERBATIM
DEPENDS "${SerenityOS_SOURCE_DIR}/Meta/generate_clang_module_map.py"
)
add_custom_target("generate_${target_name}_module_map" DEPENDS "${module_map_file}")
add_dependencies(ladybird_codegen_accumulator "generate_${target_name}_module_map")
add_dependencies("${target_name}" "generate_${target_name}_module_map")
target_compile_options(${target_name} PUBLIC "SHELL:$<$<COMPILE_LANGUAGE:Swift>:-Xcc -ivfsoverlay${vfs_overlay_file}>")
endfunction()
function(compile_ipc source output)
if (NOT IS_ABSOLUTE ${source})
set(source ${CMAKE_CURRENT_SOURCE_DIR}/${source})

View file

@ -1,25 +0,0 @@
include_guard(GLOBAL)
include(FetchContent)
set(FETCHCONTENT_TRY_FIND_PACKAGE_MODE OPT_IN)
FetchContent_Declare(SwiftCollections
GIT_REPOSITORY https://github.com/apple/swift-collections.git
GIT_TAG 1.1.2
PATCH_COMMAND "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_LIST_DIR}/patches/git-patch.cmake"
"${CMAKE_CURRENT_LIST_DIR}/patches/swift-collections/0001-CMake-Remove-top-level-binary-module-locations.patch"
OVERRIDE_FIND_PACKAGE
)
set(BUILD_TESTING_SAVE ${BUILD_TESTING})
set(BUILD_TESTING OFF)
set(BUILD_EXAMPLES OFF)
# FIXME: https://github.com/apple/swift-collections/issues/440
set(BUILD_SHARED_LIBS_SAVE ${BUILD_SHARED_LIBS})
set(BUILD_SHARED_LIBS OFF)
FetchContent_MakeAvailable(SwiftCollections)
set(BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS_SAVE})
set(BUILD_TESTING ${BUILD_TESTING_SAVE})

View file

@ -11,7 +11,6 @@ macro(add_cxx_compile_options)
set(args "")
foreach(arg ${ARGN})
string(APPEND args ${arg}$<SEMICOLON>)
add_compile_options("SHELL:$<$<COMPILE_LANGUAGE:Swift>:-Xcc ${arg}>")
endforeach()
add_compile_options($<$<COMPILE_LANGUAGE:C,CXX,ASM>:${args}>)
endmacro()
@ -20,7 +19,6 @@ macro(add_cxx_compile_definitions)
set(args "")
foreach(arg ${ARGN})
string(APPEND args ${arg}$<SEMICOLON>)
add_compile_options("SHELL:$<$<COMPILE_LANGUAGE:Swift>:-Xcc -D${arg}>")
endforeach()
add_compile_definitions($<$<COMPILE_LANGUAGE:C,CXX,ASM>:${args}>)
endmacro()
@ -33,22 +31,6 @@ macro(add_cxx_link_options)
add_link_options($<$<LINK_LANGUAGE:C,CXX>:${args}>)
endmacro()
macro(add_swift_compile_options)
set(args "")
foreach(arg ${ARGN})
string(APPEND args ${arg}$<SEMICOLON>)
endforeach()
add_compile_options($<$<COMPILE_LANGUAGE:Swift>:${args}>)
endmacro()
macro(add_swift_link_options)
set(args "")
foreach(arg ${ARGN})
string(APPEND args ${arg}$<SEMICOLON>)
endforeach()
add_link_options($<$<LINK_LANGUAGE:Swift>:${args}>)
endmacro()
include(CheckLinkerFlag)
include(CMakePushCheckState)
function(add_cxx_link_option_if_supported option)

View file

@ -3,12 +3,6 @@ if (POLICY CMP0116)
cmake_policy(SET CMP0116 NEW)
endif()
# Enable better flags for configuring swift compilation mode
if (POLICY CMP0157)
cmake_policy(SET CMP0157 NEW)
set(CMAKE_Swift_COMPILATION_MODE "$<IF:$<CONFIG:Release>,wholemodule,incremental>")
endif()
# Check arguments to return()
if (POLICY CMP0140)
cmake_policy(SET CMP0140 NEW)
@ -39,7 +33,6 @@ endif()
ladybird_option(ENABLE_GUI_TARGETS ON CACHE BOOL "Enable building GUI targets")
ladybird_option(ENABLE_INSTALL_HEADERS ON CACHE BOOL "Enable installing headers")
ladybird_option(ENABLE_INSTALL_FREEDESKTOP_FILES ${freedesktop_files_default} CACHE BOOL "Enable installing .desktop and .service files")
ladybird_option(ENABLE_SWIFT OFF CACHE BOOL "Enable building Swift files")
ladybird_option(LADYBIRD_ENABLE_CPPTRACE ON CACHE BOOL "Enable use of cpptrace as the default library for stacktraces. If not available falls back to backtrace.h")
ladybird_option(ENABLE_CI_BASELINE_CPU OFF CACHE BOOL "Use a baseline CPU target for improved ccache sharing")
@ -48,10 +41,6 @@ if (ENABLE_FUZZERS_LIBFUZZER)
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY CACHE STRING "Type of target to use for try_compile()" FORCE)
endif()
if (ENABLE_SWIFT)
include(${CMAKE_CURRENT_LIST_DIR}/Swift/swift-settings.cmake)
endif()
include(CheckCXXSourceCompiles)
set(BLOCKS_REQUIRED_LIBRARIES "")
if (NOT APPLE)

View file

@ -15,10 +15,6 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${IN_BUILD_PREFIX}${CMAK
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${IN_BUILD_PREFIX}${CMAKE_INSTALL_LIBDIR}")
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${IN_BUILD_PREFIX}${CMAKE_INSTALL_LIBDIR}")
# FIXME: Stop setting this when we have a good way to retrieve the directory that has the swift module
# file for use by the swift frontend's header generator
set(CMAKE_Swift_MODULE_DIRECTORY "${CMAKE_BINARY_DIR}/${IN_BUILD_PREFIX}swift")
set(CMAKE_SKIP_BUILD_RPATH FALSE)
if ("${VCPKG_INSTALLED_DIR}" STREQUAL "")

View file

@ -1,170 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Andrew Kaster <andrew@ladybird.org>
Date: Thu, 22 Aug 2024 20:51:38 -0600
Subject: [PATCH] CMake: Remove top-level binary/module locations
---
CMakeLists.txt | 13 +++++--------
Sources/BitCollections/CMakeLists.txt | 2 --
Sources/CMakeLists.txt | 2 --
Sources/Collections/CMakeLists.txt | 4 ++--
Sources/DequeModule/CMakeLists.txt | 2 --
Sources/HashTreeCollections/CMakeLists.txt | 2 --
Sources/HeapModule/CMakeLists.txt | 2 --
Sources/InternalCollectionsUtilities/CMakeLists.txt | 2 --
Sources/OrderedCollections/CMakeLists.txt | 2 --
Sources/RopeModule/CMakeLists.txt | 2 --
10 files changed, 7 insertions(+), 26 deletions(-)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 939a29e48ee386c0dac32350c6f6dfb4c4279170..2692814e02971e1469fc236a89c825a5c1547932 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -11,22 +11,19 @@ if(POLICY CMP0091)
cmake_policy(SET CMP0091 NEW)
endif()
+if(POLICY CMP0157)
+ cmake_policy(SET CMP0157 OLD)
+endif()
+
+
cmake_minimum_required(VERSION 3.16)
project(SwiftCollections
LANGUAGES C Swift)
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules)
-set(CMAKE_Swift_MODULE_DIRECTORY ${CMAKE_BINARY_DIR}/swift)
set(CMAKE_Swift_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY MultiThreadedDLL)
-set(CMAKE_Swift_MODULE_DIRECTORY ${CMAKE_BINARY_DIR}/swift)
-set(CMAKE_Swift_COMPILE_OPTIONS_MSVC_RUNTIME_LIBRARY MultiThreadedDLL)
-
-set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
-set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
-set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
-
set(CMAKE_MSVC_RUNTIME_LIBRARY MultiThreadedDLL)
if(CMAKE_SYSTEM_NAME STREQUAL Windows OR CMAKE_SYSTEM_NAME STREQUAL Darwin)
diff --git a/Sources/BitCollections/CMakeLists.txt b/Sources/BitCollections/CMakeLists.txt
index c5becdeec08a91978aa8b00dc2fc272299ca16b0..3f52e47220362de9c47e3e2527a2b78260d6f45e 100644
--- a/Sources/BitCollections/CMakeLists.txt
+++ b/Sources/BitCollections/CMakeLists.txt
@@ -15,8 +15,6 @@ else()
${COLLECTIONS_BIT_SOURCES})
target_link_libraries(BitCollections PRIVATE
InternalCollectionsUtilities)
- set_target_properties(BitCollections PROPERTIES
- INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_Swift_MODULE_DIRECTORY})
_install_target(BitCollections)
set_property(GLOBAL APPEND PROPERTY SWIFT_COLLECTIONS_EXPORTS BitCollections)
diff --git a/Sources/CMakeLists.txt b/Sources/CMakeLists.txt
index ad39dd9be70a3d3fd7f3176e9a607c6fa1413d82..a54e494c81a552282735bd926a05cb3d9527b169 100644
--- a/Sources/CMakeLists.txt
+++ b/Sources/CMakeLists.txt
@@ -24,8 +24,6 @@ if(COLLECTIONS_SINGLE_MODULE)
endif()
target_compile_definitions(${COLLECTIONS_MODULE_NAME} PRIVATE COLLECTIONS_SINGLE_MODULE)
- set_target_properties(${COLLECTIONS_MODULE_NAME} PROPERTIES
- INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_Swift_MODULE_DIRECTORY})
if(COLLECTIONS_FOUNDATION_TOOLCHAIN_MODULE)
get_swift_host_os(swift_os)
diff --git a/Sources/Collections/CMakeLists.txt b/Sources/Collections/CMakeLists.txt
index 9f534a46c80475e2ef39ba39d386be00d25b7c30..6be24ce21145f14718e90d67247d2ea56c21ffd4 100644
--- a/Sources/Collections/CMakeLists.txt
+++ b/Sources/Collections/CMakeLists.txt
@@ -15,9 +15,9 @@ target_link_libraries(Collections PRIVATE
HeapModule
OrderedCollections
HashTreeCollections
+ InternalCollectionsUtilities
)
-set_target_properties(Collections PROPERTIES
- INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_Swift_MODULE_DIRECTORY})
_install_target(Collections)
set_property(GLOBAL APPEND PROPERTY SWIFT_COLLECTIONS_EXPORTS Collections)
+
diff --git a/Sources/DequeModule/CMakeLists.txt b/Sources/DequeModule/CMakeLists.txt
index 07364b66e32257c098edfbfdd3204206dee56709..da1a79becc36893a90d797bee610b973c3c12853 100644
--- a/Sources/DequeModule/CMakeLists.txt
+++ b/Sources/DequeModule/CMakeLists.txt
@@ -15,8 +15,6 @@ else()
${COLLECTIONS_DEQUE_SOURCES})
target_link_libraries(DequeModule PRIVATE
InternalCollectionsUtilities)
- set_target_properties(DequeModule PROPERTIES
- INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_Swift_MODULE_DIRECTORY})
_install_target(DequeModule)
set_property(GLOBAL APPEND PROPERTY SWIFT_COLLECTIONS_EXPORTS DequeModule)
diff --git a/Sources/HashTreeCollections/CMakeLists.txt b/Sources/HashTreeCollections/CMakeLists.txt
index 0329fe664fd103348f55ce34dee71da9f437dfd6..56566f36a63c834f0c7d40f787504adede820808 100644
--- a/Sources/HashTreeCollections/CMakeLists.txt
+++ b/Sources/HashTreeCollections/CMakeLists.txt
@@ -15,8 +15,6 @@ else()
${COLLECTIONS_HASHTREE_SOURCES})
target_link_libraries(HashTreeCollections PRIVATE
InternalCollectionsUtilities)
- set_target_properties(HashTreeCollections PROPERTIES
- INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_Swift_MODULE_DIRECTORY})
_install_target(HashTreeCollections)
set_property(GLOBAL APPEND PROPERTY SWIFT_COLLECTIONS_EXPORTS HashTreeCollections)
diff --git a/Sources/HeapModule/CMakeLists.txt b/Sources/HeapModule/CMakeLists.txt
index a1cc57a63b5bcd140ea207298fbd0c6d48f784de..6bf9edeed5bfdeb9120869dfdbaed21a2376e3c3 100644
--- a/Sources/HeapModule/CMakeLists.txt
+++ b/Sources/HeapModule/CMakeLists.txt
@@ -15,8 +15,6 @@ else()
${COLLECTIONS_HEAP_SOURCES})
target_link_libraries(HeapModule PRIVATE
InternalCollectionsUtilities)
- set_target_properties(HeapModule PROPERTIES
- INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_Swift_MODULE_DIRECTORY})
_install_target(HeapModule)
set_property(GLOBAL APPEND PROPERTY SWIFT_COLLECTIONS_EXPORTS HeapModule)
diff --git a/Sources/InternalCollectionsUtilities/CMakeLists.txt b/Sources/InternalCollectionsUtilities/CMakeLists.txt
index 808e36c2eb43f26f8009d4982e5cd095c3a3639d..f25f3da067e8d6ce540ba911a3df43d6e3b5b561 100644
--- a/Sources/InternalCollectionsUtilities/CMakeLists.txt
+++ b/Sources/InternalCollectionsUtilities/CMakeLists.txt
@@ -13,8 +13,6 @@ else()
set(module_name InternalCollectionsUtilities)
add_library(InternalCollectionsUtilities
${COLLECTIONS_UTILITIES_SOURCES})
- set_target_properties(InternalCollectionsUtilities PROPERTIES
- INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_Swift_MODULE_DIRECTORY})
_install_target(InternalCollectionsUtilities)
set_property(GLOBAL APPEND PROPERTY SWIFT_COLLECTIONS_EXPORTS InternalCollectionsUtilities)
diff --git a/Sources/OrderedCollections/CMakeLists.txt b/Sources/OrderedCollections/CMakeLists.txt
index 017113861101c5acfb3f77a8feca86f1b9a6fd50..16e63aec3d0e317191b59637ef02aba9b0e76a76 100644
--- a/Sources/OrderedCollections/CMakeLists.txt
+++ b/Sources/OrderedCollections/CMakeLists.txt
@@ -15,8 +15,6 @@ else()
${COLLECTIONS_ORDERED_SOURCES})
target_link_libraries(OrderedCollections PRIVATE
InternalCollectionsUtilities)
- set_target_properties(OrderedCollections PROPERTIES
- INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_Swift_MODULE_DIRECTORY})
_install_target(OrderedCollections)
set_property(GLOBAL APPEND PROPERTY SWIFT_COLLECTIONS_EXPORTS OrderedCollections)
diff --git a/Sources/RopeModule/CMakeLists.txt b/Sources/RopeModule/CMakeLists.txt
index d33fac9213f939fcfccb1f702039b421814d3dfd..19e08d235a14348dac983cb4bf1972a039ea3fbb 100644
--- a/Sources/RopeModule/CMakeLists.txt
+++ b/Sources/RopeModule/CMakeLists.txt
@@ -15,8 +15,6 @@ else()
${COLLECTIONS_ROPE_SOURCES})
target_link_libraries(_RopeModule PRIVATE
InternalCollectionsUtilities)
- set_target_properties(_RopeModule PROPERTIES
- INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_Swift_MODULE_DIRECTORY})
_install_target(_RopeModule)
set_property(GLOBAL APPEND PROPERTY SWIFT_COLLECTIONS_EXPORTS _RopeModule)

View file

@ -96,25 +96,6 @@
"ENABLE_FUZZERS_LIBFUZZER": "ON",
"ENABLE_ADDRESS_SANITIZER": "ON"
}
},
{
"hidden": true,
"name": "Swift_Release_base",
"displayName": "Swift Release Config",
"description": "Swift-enabled release build",
"binaryDir": "$env{LADYBIRD_SOURCE_DIR}/Build/swift",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "RelWithDebInfo",
"VCPKG_OVERLAY_TRIPLETS": "$env{LADYBIRD_SOURCE_DIR}/Meta/CMake/vcpkg/release-triplets",
"ENABLE_SWIFT": "ON",
"CMAKE_C_COMPILER": "MustBeSetManually",
"CMAKE_CXX_COMPILER": "MustBeSetManually++"
},
"vendor": {
"jetbrains.com/clion": {
"toolchain": "Swift"
}
}
}
],
"buildPresets": [

View file

@ -55,13 +55,6 @@
"unix_base",
"All_Debug_base"
]
},
{
"name": "Swift_Release",
"inherits": [
"unix_base",
"Swift_Release_base"
]
}
],
"buildPresets": [
@ -71,13 +64,6 @@
"configurePreset": "Distribution",
"displayName": "Distribution Build",
"description": "Build the project for distribution"
},
{
"name": "Swift_Release",
"inherits": "base",
"configurePreset": "Swift_Release",
"displayName": "Swift Release Build",
"description": "Build the project for Swift release on Unix"
}
],
"testPresets": [
@ -85,11 +71,6 @@
"name": "Distribution",
"inherits": "base",
"configurePreset": "Distribution"
},
{
"name": "Swift_Release",
"inherits": "base",
"configurePreset": "Swift_Release"
}
]
}

View file

@ -16,8 +16,6 @@ if (ENABLE_ADDRESS_SANITIZER)
else()
add_cxx_compile_options(-fsanitize=address -fno-omit-frame-pointer)
add_cxx_link_options(-fsanitize=address)
add_swift_compile_options(-sanitize=address)
add_swift_link_options(-sanitize=address)
endif()
endif()
@ -31,7 +29,7 @@ if (ENABLE_UNDEFINED_SANITIZER)
add_cxx_compile_options(-fsanitize=undefined)
# FIXME: Windows on ARM
link_libraries(clang_rt.ubsan_standalone-x86_64.lib clang_rt.ubsan_standalone_cxx-x86_64.lib)
elseif (APPLE OR NOT ENABLE_SWIFT)
else()
add_cxx_compile_options(-fsanitize=undefined -fno-omit-frame-pointer)
if (UNDEFINED_BEHAVIOR_IS_FATAL)
add_cxx_compile_options(-fno-sanitize-recover=undefined)
@ -40,7 +38,5 @@ if (ENABLE_UNDEFINED_SANITIZER)
add_cxx_compile_options(-fno-sanitize=function)
endif()
add_cxx_link_options(-fsanitize=undefined)
add_swift_compile_options(-sanitize=undefined)
add_swift_link_options(-sanitize=undefined)
endif()
endif()

View file

@ -40,5 +40,4 @@ else()
set(SKIA_TARGET PkgConfig::skia)
set_property(TARGET PkgConfig::skia APPEND PROPERTY INTERFACE_COMPILE_DEFINITIONS "SKCMS_DLL")
endif()
swizzle_target_properties_for_swift(${SKIA_TARGET})
add_library(skia ALIAS ${SKIA_TARGET})

View file

@ -203,8 +203,3 @@ function(add_lagom_library_install_rules target_name)
INCLUDES DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)
endfunction()
if (NOT COMMAND swizzle_target_properties_for_swift)
function(swizzle_target_properties_for_swift target)
endfunction()
endif()

View file

@ -757,9 +757,6 @@ static std::optional<CellTypeWithOrigin> find_cell_type_with_origin(clang::CXXRe
if (base_name == "GC::Cell")
return CellTypeWithOrigin { *base_record, LibJSCellMacro::Type::GCCell };
if (base_name == "GC::ForeignCell")
return CellTypeWithOrigin { *base_record, LibJSCellMacro::Type::ForeignCell };
if (base_name == "JS::Object")
return CellTypeWithOrigin { *base_record, LibJSCellMacro::Type::JSObject };
@ -782,9 +779,6 @@ static std::optional<CellTypeWithOrigin> find_cell_type_with_origin(clang::CXXRe
LibJSGCVisitor::CellMacroExpectation LibJSGCVisitor::get_record_cell_macro_expectation(clang::CXXRecordDecl const& record)
{
if (record.getQualifiedNameAsString() == "GC::ForeignCell")
return { LibJSCellMacro::Type::ForeignCell, "Cell" };
auto origin = find_cell_type_with_origin(record);
assert(origin.has_value());
@ -921,8 +915,6 @@ char const* LibJSCellMacro::type_name(Type type)
switch (type) {
case Type::GCCell:
return "GC_CELL";
case Type::ForeignCell:
return "FOREIGN_CELL";
case Type::JSObject:
return "JS_OBJECT";
case Type::JSEnvironment:
@ -951,7 +943,6 @@ void LibJSPPCallbacks::MacroExpands(clang::Token const& name_token, clang::Macro
if (auto* ident_info = name_token.getIdentifierInfo()) {
static llvm::StringMap<LibJSCellMacro::Type> libjs_macro_types {
{ "GC_CELL", LibJSCellMacro::Type::GCCell },
{ "FOREIGN_CELL", LibJSCellMacro::Type::ForeignCell },
{ "JS_OBJECT", LibJSCellMacro::Type::JSObject },
{ "JS_ENVIRONMENT", LibJSCellMacro::Type::JSEnvironment },
{ "JS_PROTOTYPE_OBJECT", LibJSCellMacro::Type::JSPrototypeObject },

View file

@ -13,7 +13,6 @@
struct LibJSCellMacro {
enum class Type {
GCCell,
ForeignCell,
JSObject,
JSEnvironment,
JSPrototypeObject,

View file

@ -5,7 +5,7 @@ import re
import subprocess
import sys
RE_RELEVANT_FILE_EXTENSION = re.compile("\\.(cpp|h|mm|swift|gml|html|js|css|sh|py|json|txt|cmake|gn|gni)$")
RE_RELEVANT_FILE_EXTENSION = re.compile("\\.(cpp|h|mm|gml|html|js|css|sh|py|json|txt|cmake|gn|gni)$")
def should_check_file(filename):

View file

@ -165,34 +165,6 @@ def pick_host_compiler(platform: Platform, cc: str, cxx: str) -> tuple[str, str]
sys.exit(1)
def pick_swift_compilers(platform: Platform, project_root: Path) -> tuple[Path, Path, Path]:
if platform.host_system == HostSystem.Windows:
print("Swift builds are not supported on Windows", file=sys.stderr)
sys.exit(1)
if not shutil.which("swiftly"):
print("swiftly is required to manage Swift toolchains", file=sys.stderr)
sys.exit(1)
swiftly_toolchain_path = run_command(["swiftly", "use", "--print-location"], return_output=True, cwd=project_root)
if not swiftly_toolchain_path:
run_command(["swiftly", "install"], exit_on_failure=True, cwd=project_root)
swiftly_toolchain_path = run_command(
["swiftly", "use", "--print-location"], return_output=True, exit_on_failure=True, cwd=project_root
)
assert swiftly_toolchain_path
swiftly_toolchain_path = Path(swiftly_toolchain_path.strip())
swiftly_bin_dir = swiftly_toolchain_path.joinpath("usr", "bin")
if not swiftly_toolchain_path.exists() or not swiftly_bin_dir.exists():
print(f"swiftly toolchain path {swiftly_toolchain_path} does not exist", file=sys.stderr)
sys.exit(1)
return swiftly_bin_dir / "clang", swiftly_bin_dir / "clang++", swiftly_bin_dir / "swiftc"
def main():
platform = Platform()
(default_cc, default_cxx) = platform.default_compiler()

View file

@ -1,72 +0,0 @@
#!/usr/bin/env python3
"""
Generates a clang module map for a given directory
"""
import argparse
import pathlib
import sys
import yaml
def write_file_if_not_same(file_path, content):
try:
with open(file_path, "r") as f:
if f.read() == content:
return
except FileNotFoundError:
pass
with open(file_path, "w") as f:
f.write(content)
def main():
parser = argparse.ArgumentParser(epilog=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument("directory", help="source directory to generate module map for")
parser.add_argument("--module-name", help="top-level module name")
parser.add_argument("--module-map", required=True, help="output module map file")
parser.add_argument("--vfs-map", required=True, help="output VFS map file")
parser.add_argument("--exclude-files", nargs="*", required=False, help="files to exclude in the module map")
parser.add_argument("--generated-files", nargs="*", help="extra files to include in the module map")
args = parser.parse_args()
root = pathlib.Path(args.directory)
if not root.is_dir():
print(f"Error: {args.directory} is not a directory", file=sys.stderr)
return 1
pathlib.Path(args.module_map).parent.mkdir(parents=True, exist_ok=True)
pathlib.Path(args.vfs_map).parent.mkdir(parents=True, exist_ok=True)
exclude_files = set(args.exclude_files) if args.exclude_files else set()
header_files = [f for f in root.rglob("**/*.h") if f.is_file() and f.name not in exclude_files]
module_name = args.module_name if args.module_name else root.name
module_map = f"module {module_name} {{\n"
for header_file in header_files:
module_map += f' header "{header_file.relative_to(root)}"\n'
for generated_file in args.generated_files:
module_map += f' header "{generated_file}"\n'
module_map += " requires cplusplus\n"
module_map += " export *\n"
module_map += "}\n"
vfs_map = {
"version": 0,
"use-external-names": False,
"roots": [
{
"name": f"{root}/module.modulemap",
"type": "file",
"external-contents": f"{args.module_map}",
}
],
}
write_file_if_not_same(args.module_map, module_map)
write_file_if_not_same(args.vfs_map, yaml.dump(vfs_map))
if __name__ == "__main__":
sys.exit(main())

View file

@ -177,7 +177,6 @@ shared_library("AK") {
"StringUtils.h",
"StringView.cpp",
"StringView.h",
"Swift.h",
"TemporaryChange.h",
"Time.cpp",
"Time.h",

View file

@ -7,7 +7,6 @@ source_set("Parser") {
"HTMLParser.cpp",
"HTMLToken.cpp",
"HTMLTokenizer.cpp",
"HTMLTokenizerHelpers.cpp",
"ListOfActiveFormattingElements.cpp",
"StackOfOpenElements.cpp",
]

View file

@ -18,7 +18,6 @@ from typing import Optional
sys.path.append(str(Path(__file__).resolve().parent.parent))
from Meta.find_compiler import pick_host_compiler
from Meta.find_compiler import pick_swift_compilers
from Meta.host_platform import HostArchitecture
from Meta.host_platform import HostSystem
from Meta.host_platform import Platform
@ -194,14 +193,9 @@ def configure_main(platform: Platform, preset: str, cc: str, cxx: str) -> Path:
if build_preset_dir.joinpath("build.ninja").exists() or build_preset_dir.joinpath("ladybird.sln").exists():
return build_preset_dir
swiftc: Optional[str] = None
validate_cmake_version()
if "Swift" in preset:
compilers = pick_swift_compilers(platform, ladybird_source_dir)
(cc, cxx, swiftc) = tuple(map(str, compilers))
else:
(cc, cxx) = pick_host_compiler(platform, cc, cxx)
(cc, cxx) = pick_host_compiler(platform, cc, cxx)
config_args = [
"cmake",
@ -215,9 +209,6 @@ def configure_main(platform: Platform, preset: str, cc: str, cxx: str) -> Path:
f"-DCMAKE_CXX_COMPILER={cxx}",
]
if swiftc:
config_args.append(f"-DCMAKE_Swift_COMPILER={swiftc}")
if platform.host_system == HostSystem.Linux and platform.host_architecture == HostArchitecture.AArch64:
config_args.extend(configure_skia_jemalloc())
@ -273,7 +264,6 @@ def configure_build_env(platform: Platform, preset: str) -> tuple[Path, Path]:
"Distribution": build_root_dir / "distribution",
"Release": build_root_dir / "release",
"Sanitizer": build_root_dir / "sanitizers",
"Swift_Release": build_root_dir / "swift",
}
build_preset_dir = known_presets.get(preset, None)

View file

@ -52,11 +52,4 @@ else
((FAILURES+=1))
fi
if Meta/lint-swift.sh "$@" && git diff --exit-code -- ':*.swift'; then
echo -e "[${GREEN}OK${NC}]: Meta/lint-swift.sh"
else
echo -e "[${BOLD_RED}FAIL${NC}]: Meta/lint-swift.sh"
((FAILURES+=1))
fi
exit "${FAILURES}"

View file

@ -1,33 +0,0 @@
#!/usr/bin/env bash
set -e
script_path=$(cd -P -- "$(dirname -- "$0")" && pwd -P)
cd "${script_path}/.." || exit 1
if [ "$#" -eq "0" ]; then
files=()
while IFS= read -r file; do
files+=("$file")
done < <(
git ls-files '*.swift'
)
else
files=()
for file in "$@"; do
if [[ "${file}" == *".swift" ]] ; then
files+=("${file}")
fi
done
fi
if (( ${#files[@]} )); then
if ! command -v swift-format >/dev/null 2>&1 ; then
echo "swift-format is not available, but Swift files need linting! Either skip this script, or install swift-format."
exit 1
fi
swift-format -i "${files[@]}"
echo "Maybe some files have changed. Sorry, but swift-format doesn't indicate what happened."
else
echo "No .swift files to check."
fi

View file

@ -114,12 +114,3 @@ endif()
target_link_libraries(TestString PRIVATE LibUnicode)
target_link_libraries(TestUtf16String PRIVATE LibUnicode)
if (ENABLE_SWIFT)
# FIXME: Convert to use swift-testing after resolving https://github.com/LadybirdBrowser/ladybird/issues/1201
add_executable(TestAKBindings TestAKBindings.swift)
target_link_libraries(TestAKBindings PRIVATE AK)
target_compile_options(TestAKBindings PRIVATE -parse-as-library)
add_test(NAME TestAKBindings COMMAND TestAKBindings)
endif()

View file

@ -1,50 +0,0 @@
/*
* Copyright (c) 2024, Andrew Kaster <andrew@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
import AK
import Foundation
protocol ConformanceMarker {}
enum CxxSequenceMarker<T: ~Copyable> {}
extension CxxSequenceMarker: ConformanceMarker where T: CxxSequence {}
private func isCxxSequenceType<T: ~Copyable>(_ type: borrowing T.Type) -> Bool {
return CxxSequenceMarker<T>.self is ConformanceMarker.Type
}
class StandardError: TextOutputStream {
func write(_ string: Swift.String) {
try! FileHandle.standardError.write(contentsOf: Data(string.utf8))
}
}
@main
struct TestAKBindings {
static func testSequenceTypesAreBound() {
var standardError = StandardError()
print("Testing CxxSequence types...", to: &standardError)
//precondition(isCxxSequenceType(AK.StringView.self))
precondition(isCxxSequenceType(AK.Bytes.self))
precondition(isCxxSequenceType(AK.ReadonlyBytes.self))
precondition(!isCxxSequenceType(AK.Utf16View.self))
// FIXME: Not bound for some reason
//precondition(isCxxSequenceType(AK.Utf16String.self))
precondition(!isCxxSequenceType(AK.String.self))
precondition(!isCxxSequenceType(AK.Error.self))
print("CxxSequence types pass", to: &standardError)
}
static func main() {
var standardError = StandardError()
print("Starting test suite...", to: &standardError)
testSequenceTypesAreBound()
print("All tests pass", to: &standardError)
}
}

View file

@ -5,7 +5,6 @@ add_subdirectory(LibCrypto)
add_subdirectory(LibDatabase)
add_subdirectory(LibDiff)
add_subdirectory(LibDNS)
add_subdirectory(LibGC)
add_subdirectory(LibHTTP)
add_subdirectory(LibJS)
add_subdirectory(LibRegex)

View file

@ -6,7 +6,6 @@
// RUN: %clang++ -Xclang -verify %plugin_opts% -c %s -o %t 2>&1
#include <LibGC/ForeignCell.h>
#include <LibJS/Runtime/PrototypeObject.h>
#include <LibWeb/Bindings/PlatformObject.h>
@ -14,10 +13,6 @@
class TestCellClass : JS::Cell {
};
// expected-error@+1 {{Expected record to have a FOREIGN_CELL macro invocation}}
class TestForeignCellClass : GC::ForeignCell {
};
// expected-error@+1 {{Expected record to have a JS_OBJECT macro invocation}}
class TestObjectClass : JS::Object {
};

View file

@ -7,7 +7,6 @@
// RUN: %clang++ -Xclang -verify %plugin_opts% -c %s -o %t 2>&1
// expected-no-diagnostics
#include <LibGC/ForeignCell.h>
#include <LibJS/Runtime/PrototypeObject.h>
#include <LibWeb/Bindings/PlatformObject.h>
@ -15,10 +14,6 @@ class TestCellClass : JS::Cell {
GC_CELL(TestCellClass, JS::Cell);
};
class TestForeignCellClass : GC::ForeignCell {
FOREIGN_CELL(TestForeignCellClass, GC::ForeignCell);
};
class TestObjectClass : JS::Object {
JS_OBJECT(TestObjectClass, JS::Object);
};

View file

@ -6,7 +6,6 @@
// RUN: %clang++ -Xclang -verify %plugin_opts% -c %s -o %t 2>&1
#include <LibGC/ForeignCell.h>
#include <LibJS/Runtime/Object.h>
#include <LibJS/Runtime/PrototypeObject.h>
@ -35,16 +34,6 @@ class ObjectWithEnvironmentMacro : JS::Object {
JS_ENVIRONMENT(ObjectWithEnvironmentMacro, JS::Object);
};
class CellWithForeignCellMacro : GC::Cell {
// expected-error@+1 {{Invalid GC-CELL-like macro invocation; expected GC_CELL}}
FOREIGN_CELL(CellWithForeignCellMacro, GC::Cell);
};
class ObjectWithForeignCellMacro : JS::Object {
// expected-error@+1 {{Invalid GC-CELL-like macro invocation; expected JS_OBJECT}}
FOREIGN_CELL(ObjectWithForeignCellMacro, JS::Object);
};
// JS_PROTOTYPE_OBJECT can only be used in the JS namespace
namespace JS {

View file

@ -6,7 +6,6 @@
// RUN: %clang++ -Xclang -verify %plugin_opts% -c %s -o %t 2>&1
#include <LibGC/ForeignCell.h>
#include <LibJS/Runtime/PrototypeObject.h>
#include <LibWeb/Bindings/PlatformObject.h>
@ -17,11 +16,6 @@ class TestCellClass : JS::Cell {
GC_CELL(bad, JS::Cell);
};
class TestForeignCellClass : GC::ForeignCell {
// expected-error@+1 {{Expected first argument of FOREIGN_CELL macro invocation to be TestForeignCellClass}}
FOREIGN_CELL(bad, GC::ForeignCell);
};
class TestObjectClass : JS::Object {
// expected-error@+1 {{Expected first argument of JS_OBJECT macro invocation to be TestObjectClass}}
JS_OBJECT(bad, JS::Object);

View file

@ -29,20 +29,3 @@ if(NOT WIN32)
endif()
target_link_libraries(TestLibCoreSharedSingleProducerCircularQueue PRIVATE LibThreading)
if(ENABLE_SWIFT)
find_package(SwiftTesting REQUIRED)
add_executable(TestCoreSwift
TestEventLoopActor.swift
TestEventLoop.cpp
)
# FIXME: Swift doesn't seem to like object libraries for @main
target_sources(TestCoreSwift PRIVATE ../Resources/SwiftTestMain.swift)
set_target_properties(TestCoreSwift PROPERTIES SUFFIX .swift-testing)
target_include_directories(TestCoreSwift PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(TestCoreSwift PRIVATE AK LibCore SwiftTesting::SwiftTesting)
add_test(NAME TestCoreSwift COMMAND TestCoreSwift)
endif()

View file

@ -1,63 +0,0 @@
/*
* Copyright (c) 2025, Andrew Kaster <andrew@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
import AK
import Core
import CoreTesting
import Testing
actor TestEventLoopActor: EventLoopActor {
nonisolated public let executor: EventLoopExecutor
init() {
install_thread_local_event_loop()
executor = EventLoopExecutor()
}
nonisolated func submit(action: @escaping @Sendable () async -> Void) {
Task(executorPreference: self.executor) {
await action()
}
}
}
@Suite
struct TestEventLoop {
@Test
func testEventLoopActor() async {
// Creates an executor around EventLoop::current()
let actor = TestEventLoopActor()
let ev = Core.EventLoop.current()
print("Event loop at \(Unmanaged.passUnretained(ev).toOpaque())")
let (stream, continuation) = AsyncStream<Int>.makeStream()
var iterator = stream.makeAsyncIterator()
actor.submit {
#expect(ev == Core.EventLoop.current(), "Closure is executed on event loop")
print("Hello from event loop at \(Unmanaged.passUnretained(Core.EventLoop.current()).toOpaque())")
continuation.yield(42)
}
actor.submit {
#expect(ev == Core.EventLoop.current(), "Closure is executed on event loop")
Core.EventLoop.current().quit(4)
continuation.yield(1234)
continuation.finish()
}
let rc = ev.exec()
#expect(rc == 4)
// Values not available until event loop has processed tasks
#expect(await iterator.next() == 42)
#expect(await iterator.next() == 1234)
#expect(ev == Core.EventLoop.current(), "Event loop exists until end of function")
}
}

View file

@ -1,25 +0,0 @@
if (ENABLE_SWIFT)
find_package(SwiftTesting REQUIRED)
add_executable(TestGCSwift
TestGCBindings.swift
TestHeap.cpp
TestInterop.cpp
)
# FIXME: Swift doesn't seem to like object libraries for @main
target_sources(TestGCSwift PRIVATE ../Resources/SwiftTestMain.swift)
generate_clang_module_map(TestGCSwift)
set_target_properties(TestGCSwift PROPERTIES SUFFIX .swift-testing)
target_include_directories(TestGCSwift PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(TestGCSwift PRIVATE AK LibGC SwiftTesting::SwiftTesting)
get_property(testing_compile_options TARGET SwiftTesting::SwiftTesting PROPERTY INTERFACE_LINK_OPTIONS)
add_swift_target_properties(TestGCSwift
LAGOM_LIBRARIES AK LibGC
COMPILE_OPTIONS ${testing_compile_options} -enable-experimental-feature Extern
)
add_test(NAME TestGCSwift COMMAND TestGCSwift)
endif()

View file

@ -1,53 +0,0 @@
/*
* Copyright (c) 2024, Andrew Kaster <andrew@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
import AK
import GC
@_exported import TestGCSwiftCxx
import Testing
public struct HeapString: HeapAllocatable {
public var string: Swift.String
public init(cell: GC.Cell) {
self.cell = cell
self.string = ""
}
public static func create(on heap: GC.Heap, string: Swift.String) -> GC.Cell {
// NOTE: GC must be deferred so that a collection during allocation doesn't get tripped
// up looking for the Cell pointer on the stack or in a register when it might only exist in the heap
precondition(heap.is_gc_deferred())
let heapString = allocate(on: heap)
heapString.pointee.string = string
return heapString.pointee.cell
}
public var cell: GC.Cell
}
@Suite(.serialized)
struct TestGCSwiftBindings {
@Test func createBoundString() {
let heap = test_gc_heap()
let string = heap.withDeferredGC {
return HeapString.allocate(on: heap)
}
#expect(string.pointee.string == "")
heap.collect_garbage(GC.Heap.CollectionType.CollectGarbage)
string.pointee.string = "Hello, World!"
heap.collect_garbage(GC.Heap.CollectionType.CollectGarbage)
#expect(string.pointee.string == "Hello, World!")
heap.collect_garbage(GC.Heap.CollectionType.CollectEverything)
}
@Test func testInterop() {
test_interop()
}
}

View file

@ -1,15 +0,0 @@
/*
* Copyright (c) 2024, Andrew Kaster <andrew@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include "TestHeap.h"
#include <LibGC/Heap.h>
GC::Heap& test_gc_heap()
{
// FIXME: The GC heap should become thread aware!
thread_local GC::Heap heap(nullptr, [](auto&) { });
return heap;
}

View file

@ -1,11 +0,0 @@
/*
* Copyright (c) 2024, Andrew Kaster <andrew@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <LibGC/Forward.h>
GC::Heap& test_gc_heap();

View file

@ -1,44 +0,0 @@
/*
* Copyright (c) 2024, Andrew Kaster <andrew@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include "TestInterop.h"
#include "TestHeap.h"
#include <AK/TypeCasts.h>
#include <LibGC/ForeignCell.h>
#include <LibGC/Heap.h>
#include <TestGCSwift-Swift.h>
#define COLLECT heap.collect_garbage(GC::Heap::CollectionType::CollectGarbage)
#define COLLECT_ALL heap.collect_garbage(GC::Heap::CollectionType::CollectEverything)
void test_interop()
{
auto& heap = test_gc_heap();
COLLECT_ALL;
auto string = GC::ForeignRef<TestGCSwift::HeapString>::allocate(heap, "Hello, World!");
COLLECT;
auto strings_string = std::string(string->getString());
VERIFY(strings_string == "Hello, World!");
COLLECT;
auto* cell = string->getCell();
VERIFY(cell == static_cast<GC::Cell*>(string.cell()));
COLLECT;
strings_string = std::string(string->getString());
COLLECT;
VERIFY(strings_string == "Hello, World!");
COLLECT_ALL;
}

View file

@ -1,9 +0,0 @@
/*
* Copyright (c) 2024, Andrew Kaster <andrew@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
void test_interop();

View file

@ -21,20 +21,4 @@ endforeach()
target_link_libraries(TestContentFilter PRIVATE LibURL)
target_link_libraries(TestFetchURL PRIVATE LibURL)
if (ENABLE_SWIFT)
find_package(SwiftTesting REQUIRED)
add_executable(TestLibWebSwift
TestLibWebSwiftBindings.swift
TestHTMLTokenizerSwift.swift
)
# FIXME: Swift doesn't seem to like object libraries for @main
target_sources(TestLibWebSwift PRIVATE ../Resources/SwiftTestMain.swift)
set_target_properties(TestLibWebSwift PROPERTIES SUFFIX .swift-testing)
target_link_libraries(TestLibWebSwift PRIVATE AK LibWeb LibGC SwiftTesting::SwiftTesting)
add_test(NAME TestLibWebSwift COMMAND TestLibWebSwift)
endif()
add_subdirectory("test-web")

View file

@ -1,314 +0,0 @@
/*
* Copyright (c) 2024, Andrew Kaster <andrew@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
import AK
import Testing
import Web
@Suite
struct TestHTMLTokenizerSwift {
@Test func tokenTypes() {
let default_token = HTMLToken()
default_token.type = .Character(codePoint: "a")
#expect(default_token.isCharacter())
#expect("\(default_token)" == "HTMLToken(type: Character(codePoint: a))")
}
@Test func parserWhitespace() {
for codePoint: Character in ["\t", "\n", "\r", "\u{000C}", " "] {
let token = HTMLToken(type: .Character(codePoint: codePoint))
#expect(token.isParserWhitespace())
}
for codePoint: Character in ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"] {
let token = HTMLToken(type: .Character(codePoint: codePoint))
#expect(!token.isParserWhitespace())
}
}
@Test func dataStateNoInput() {
let tokenizer = HTMLTokenizer()
#expect(tokenizer.state == HTMLTokenizer.State.Data) // initial state
let token = tokenizer.nextToken()
#expect(token?.type == .EndOfFile)
let token2 = tokenizer.nextToken()
#expect(token2 == nil)
#expect(tokenizer.state == HTMLTokenizer.State.Data)
}
@Test func dataStateSingleChar() {
guard let tokenizer = HTMLTokenizer(input: "X") else {
Issue.record("Failed to create tokenizer for 'X'")
return
}
#expect(tokenizer.state == HTMLTokenizer.State.Data) // initial state
let token = tokenizer.nextToken()
#expect(token?.type == .Character(codePoint: "X"))
let token2 = tokenizer.nextToken()
#expect(token2?.type == .EndOfFile)
let token3 = tokenizer.nextToken()
#expect(token3 == nil)
#expect(tokenizer.state == HTMLTokenizer.State.Data)
}
@Test func dataStateAmpersand() {
guard let tokenizer = HTMLTokenizer(input: "&") else {
Issue.record("Failed to create tokenizer for '&'")
return
}
#expect(tokenizer.state == HTMLTokenizer.State.Data) // initial state
let token = tokenizer.nextToken()
#expect(token?.type == .Character(codePoint: "&"))
let token2 = tokenizer.nextToken()
#expect(token2?.type == .EndOfFile)
let token3 = tokenizer.nextToken()
#expect(token3 == nil)
}
@Test func tagOpenOnly() {
guard let tokenizer = HTMLTokenizer(input: "<") else {
Issue.record("Failed to create tokenizer for '<'")
return
}
#expect(tokenizer.state == HTMLTokenizer.State.Data) // initial state
let token = tokenizer.nextToken()
#expect(token?.type == .Character(codePoint: "<"))
let token2 = tokenizer.nextToken()
#expect(token2?.type == .EndOfFile)
#expect(tokenizer.state == HTMLTokenizer.State.TagOpen)
let token3 = tokenizer.nextToken()
#expect(token3 == nil)
}
@Test func dataStateNulChar() {
guard let tokenizer = HTMLTokenizer(input: "H\0I") else {
Issue.record("Failed to create tokenizer for 'H\\0I'")
return
}
#expect(tokenizer.state == HTMLTokenizer.State.Data) // initial state
let token = tokenizer.nextToken()
#expect(token?.type == .Character(codePoint: "H"))
let token2 = tokenizer.nextToken()
#expect(token2?.type == .Character(codePoint: "\u{FFFD}"))
let token3 = tokenizer.nextToken()
#expect(token3?.type == .Character(codePoint: "I"))
let token4 = tokenizer.nextToken()
#expect(token4?.type == .EndOfFile)
#expect(tokenizer.state == HTMLTokenizer.State.Data)
}
@Test func scriptTagWithAttributes() {
guard let tokenizer = HTMLTokenizer(input: "<script type=\"text/javascript\">") else {
Issue.record("Failed to create tokenizer for '<script type=\"text/javascript\">'")
return
}
#expect(tokenizer.state == HTMLTokenizer.State.Data) // initial state
let token = tokenizer.nextToken()
#expect(token?.type == .StartTag(tagName: "script", attributes: [HTMLToken.Attribute(localName: "type", value: "text/javascript")]))
let token2 = tokenizer.nextToken()
#expect(token2?.type == .EndOfFile)
#expect(tokenizer.state == HTMLTokenizer.State.Data)
}
@Test func scriptWithContent() {
guard let tokenizer = HTMLTokenizer(input: "<script>var x = 1;</script>") else {
Issue.record("Failed to create tokenizer for '<script>var x = 1;</script>'")
return
}
let token = tokenizer.nextToken()
#expect(token?.type == .StartTag(tagName: "script", attributes: []))
for codePoint in "var x = 1;" {
let token = tokenizer.nextToken()
#expect(token?.type == .Character(codePoint: codePoint))
}
let token2 = tokenizer.nextToken()
#expect(token2?.type == .EndTag(tagName: "script"))
let token3 = tokenizer.nextToken()
#expect(token3?.type == .EndOfFile)
}
@Test func simpleDivWithContent() {
guard let tokenizer = HTMLTokenizer(input: "<div>hi</div>") else {
Issue.record("Failed to create tokenizer for '<div>hi</div>'")
return
}
#expect(tokenizer.state == HTMLTokenizer.State.Data) // initial state
let token = tokenizer.nextToken()
#expect(token?.type == .StartTag(tagName: "div", attributes: []))
let token2 = tokenizer.nextToken()
#expect(token2?.type == .Character(codePoint: "h"))
let token3 = tokenizer.nextToken()
#expect(token3?.type == .Character(codePoint: "i"))
let token4 = tokenizer.nextToken()
#expect(token4?.type == .EndTag(tagName: "div"))
let token5 = tokenizer.nextToken()
#expect(token5?.type == .EndOfFile)
}
@Test func simpleDivWithContentAndAttributes() {
guard let tokenizer = HTMLTokenizer(input: "<div class=\"foo\">hi</div>") else {
Issue.record("Failed to create tokenizer for '<div class=\"foo\">hi</div>'")
return
}
#expect(tokenizer.state == HTMLTokenizer.State.Data) // initial state
let token = tokenizer.nextToken()
#expect(token?.type == .StartTag(tagName: "div", attributes: [HTMLToken.Attribute(localName: "class", value: "foo")]))
let token2 = tokenizer.nextToken()
#expect(token2?.type == .Character(codePoint: "h"))
let token3 = tokenizer.nextToken()
#expect(token3?.type == .Character(codePoint: "i"))
let token4 = tokenizer.nextToken()
#expect(token4?.type == .EndTag(tagName: "div"))
let token5 = tokenizer.nextToken()
#expect(token5?.type == .EndOfFile)
}
@Test func severalDivsWithAttributesAndContent() {
// Explicitly use unquoted and single quotes for attribute values
guard let tokenizer = HTMLTokenizer(input: "<div class=foo>hi</div><div class='bar'>bye</div>") else {
Issue.record("Failed to create tokenizer for '<div class=\"foo\">hi</div><div class=\"bar\">bye</div>'")
return
}
let token = tokenizer.nextToken()
#expect(token?.type == .StartTag(tagName: "div", attributes: [HTMLToken.Attribute(localName: "class", value: "foo")]))
for codePoint in "hi" {
let token = tokenizer.nextToken()
#expect(token?.type == .Character(codePoint: codePoint))
}
let token2 = tokenizer.nextToken()
#expect(token2?.type == .EndTag(tagName: "div"))
let token3 = tokenizer.nextToken()
#expect(token3?.type == .StartTag(tagName: "div", attributes: [HTMLToken.Attribute(localName: "class", value: "bar")]))
for codePoint in "bye" {
let token = tokenizer.nextToken()
#expect(token?.type == .Character(codePoint: codePoint))
}
let token4 = tokenizer.nextToken()
#expect(token4?.type == .EndTag(tagName: "div"))
let token5 = tokenizer.nextToken()
#expect(token5?.type == .EndOfFile)
}
@Test func startTagWithMultipleAttributes() {
guard let tokenizer = HTMLTokenizer(input: "<div class=\"foo\" id=\"bar\">hi</div attr=endTagAttributeWhee>") else {
Issue.record("Failed to create tokenizer for '<div class=\"foo\" id=\"bar\">hi</div>'")
return
}
let token = tokenizer.nextToken()
#expect(token?.type == .StartTag(tagName: "div", attributes: [HTMLToken.Attribute(localName: "class", value: "foo"), HTMLToken.Attribute(localName: "id", value: "bar")]))
for codePoint in "hi" {
let token = tokenizer.nextToken()
#expect(token?.type == .Character(codePoint: codePoint))
}
let token2 = tokenizer.nextToken()
#expect(token2?.type == .EndTag(tagName: "div", attributes: [HTMLToken.Attribute(localName: "attr", value: "endTagAttributeWhee")]))
let token3 = tokenizer.nextToken()
#expect(token3?.type == .EndOfFile)
}
@Test func xmlDeclaration() {
guard let tokenizer = HTMLTokenizer(input: "<?xml version=\"1.0\" encoding=\"UTF-8\"?>") else {
Issue.record("Failed to create tokenizer for '<?xml version=\"1.0\" encoding=\"UTF-8\"?>'")
return
}
let token = tokenizer.nextToken()
#expect(token?.type == .Comment(data: "?xml version=\"1.0\" encoding=\"UTF-8\"?"))
let token2 = tokenizer.nextToken()
#expect(token2?.type == .EndOfFile)
}
@Test func simpleComment() {
guard let tokenizer = HTMLTokenizer(input: "<!-- comment -->") else {
Issue.record("Failed to create tokenizer for '<!-- comment -->'")
return
}
let token = tokenizer.nextToken()
#expect(token?.type == .Comment(data: " comment "))
let token2 = tokenizer.nextToken()
#expect(token2?.type == .EndOfFile)
}
@Test func nestedComment() {
guard let tokenizer = HTMLTokenizer(input: "<!-- <!-- nested --> -->") else {
Issue.record("Failed to create tokenizer for '<!-- <!-- nested --> -->'")
return
}
let token = tokenizer.nextToken()
#expect(token?.type == .Comment(data: " <!-- nested "))
for codePoint in " -->" {
let token = tokenizer.nextToken()
#expect(token?.type == .Character(codePoint: codePoint))
}
let token2 = tokenizer.nextToken()
#expect(token2?.type == .EndOfFile)
}
@Test func commentWithScriptTagInside() {
guard let tokenizer = HTMLTokenizer(input: "<!-- <script>var x = 1;</script> -->") else {
Issue.record("Failed to create tokenizer for '<!-- <script>var x = 1;</script> -->'")
return
}
let token = tokenizer.nextToken()
#expect(token?.type == .Comment(data: " <script>var x = 1;</script> "))
let token2 = tokenizer.nextToken()
#expect(token2?.type == .EndOfFile)
}
}

View file

@ -1,24 +0,0 @@
/*
* Copyright (c) 2024, Andrew Kaster <andrew@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
import AK
import Testing
import Web
@Suite
struct TestLibWebSwiftBindings {
@Test func enumsAreBound() {
#expect(Web.DOM.NodeType.ELEMENT_NODE.rawValue == 1)
#expect(Web.Bindings.NavigationType.Push.rawValue == 0)
let end = Web.Bindings.idl_enum_to_string(Web.Bindings.ScrollLogicalPosition.End)
let end_string = Swift.String(akString: end)!
#expect(end_string == "end")
}
}

View file

@ -1,27 +0,0 @@
/*
* Copyright (c) 2024, Andrew Kaster <andrew@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
import Foundation
typealias EntryPoint = @convention(thin) @Sendable (_ configurationJSON: UnsafeRawBufferPointer?, _ recordHandler: @escaping @Sendable (_ recordJSON: UnsafeRawBufferPointer) -> Void) async throws -> Bool
@_extern(c, "swt_abiv0_getEntryPoint")
func swt_abiv0_getEntryPoint() -> UnsafeRawPointer
@main struct Runner {
static func main() async throws {
nonisolated(unsafe) let configurationJSON: UnsafeRawBufferPointer? = nil
let recordHandler: @Sendable (UnsafeRawBufferPointer) -> Void = { _ in }
let entryPoint = unsafeBitCast(swt_abiv0_getEntryPoint(), to: EntryPoint.self)
if try await entryPoint(configurationJSON, recordHandler) {
exit(EXIT_SUCCESS)
} else {
exit(EXIT_FAILURE)
}
}
}