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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions Sources/COpenSwiftUI/Util/AppleInternal.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
//
// AppleInternal.c
// COpenSwiftUI
//
// Audited for 6.5.4
// Status: Complete

#include "AppleInternal.h"

#if OPENSWIFTUI_TARGET_OS_DARWIN
#include <dispatch/dispatch.h>

extern bool os_variant_allows_internal_security_policies(const char *subsystem);
extern bool os_variant_has_internal_content(const char *subsystem);
#endif

bool _OpenSwiftUIIsAppleInternalBuild(void) {
#if OPENSWIFTUI_TARGET_OS_DARWIN
static bool isInternal;
static dispatch_once_t once;
dispatch_once(&once, ^{
isInternal = os_variant_allows_internal_security_policies("org.OpenSwiftUIProject.OpenSwiftUI")
&& os_variant_has_internal_content("org.OpenSwiftUIProject.OpenSwiftUI");
});
return isInternal;
#else
return false;
#endif
}
20 changes: 20 additions & 0 deletions Sources/COpenSwiftUI/Util/AppleInternal.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//
// AppleInternal.h
// COpenSwiftUI
//
// Audited for 6.5.4
// Status: Complete

#ifndef AppleInternal_h
#define AppleInternal_h

#include "OpenSwiftUIBase.h"

OPENSWIFTUI_EXTERN_C_BEGIN

OPENSWIFTUI_EXPORT
bool _OpenSwiftUIIsAppleInternalBuild(void);

OPENSWIFTUI_EXTERN_C_END

#endif /* AppleInternal_h */
Original file line number Diff line number Diff line change
Expand Up @@ -539,6 +539,34 @@ open class NSHostingView<Content>: NSView, XcodeViewDebugDataProvider where Cont

private var isInsertingRenderedSubview: Bool = false

// Audited for 6.5.4
override dynamic open func didAddSubview(_ subview: NSView) {
super.didAddSubview(subview)
guard !isInsertingRenderedSubview else { return }
foreignSubviews.add(subview)
if isLinkedOnOrAfter(.v7) {
let hostName = if viewController == nil {
"NSHostingView"
} else {
"NSHostingController.view"
}
Log.runtimeIssues(
"Adding '%s' as a subview of %s is not supported and may result in a broken view hierarchy. Add your view above %s in a common superview or insert it into your OpenSwiftUI content in a NSViewRepresentable instead.",
[
"\(type(of: subview))",
hostName,
hostName,
]
)
}
}

// Audited for 6.5.4
override dynamic open func willRemoveSubview(_ subview: NSView) {
super.willRemoveSubview(subview)
foreignSubviews.remove(subview)
}

private var sizeConstraints: SizeConstraints?

private struct SizeConstraints {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -413,9 +413,38 @@ open class _UIHostingView<Content>: UIView, XcodeViewDebugDataProvider where Con
}
}

private lazy var foreignSubviews: NSHashTable<UIView>? = NSHashTable.weakObjects()
private lazy var foreignSubviews: NSHashTable<UIView> = NSHashTable.weakObjects()

private var isInsertingRenderedSubview: Bool = false

// Audited for 6.5.4
override dynamic open func didAddSubview(_ subview: UIView) {
super.didAddSubview(subview)
guard !isInsertingRenderedSubview else { return }
foreignSubviews.add(subview)
if isLinkedOnOrAfter(.v7) {
let hostName = if _OpenSwiftUIIsAppleInternalBuild(), viewController == nil {
"_UIHostingView"
} else {
"UIHostingController.view"
}
Log.runtimeIssues(
"Adding '%s' as a subview of %s is not supported and may result in a broken view hierarchy. Add your view above %s in a common superview or insert it into your OpenSwiftUI content in a UIViewRepresentable instead.",
[
"\(type(of: subview))",
hostName,
hostName,
]
)
}
}

// Audited for 6.5.4
override dynamic open func willRemoveSubview(_ subview: UIView) {
super.willRemoveSubview(subview)
foreignSubviews.remove(subview)
}


/// The UIKit notion of the safe area insets.
open override var safeAreaInsets: UIEdgeInsets {
Expand Down Expand Up @@ -486,8 +515,12 @@ open class _UIHostingView<Content>: UIView, XcodeViewDebugDataProvider where Con
}
}

@objc(swiftui_insertRenderedSubview:atIndex:) // FIXME: ViewUpdater -> CoreViewAddSubview
private func openswiftui_insertRenderedSubview(_ view: UIView, at index: Int) {
@_spi(ForOpenSwiftUIOnly)
#if OPENSWIFTUI_SWIFTUI_RENDERER
@objc(swiftui_insertRenderedSubview:atIndex:)
#endif
override public func openswiftui_insertRenderedSubview(_ subview: Any, at index: Int) {
let view = subview as! UIView
isInsertingRenderedSubview = true
insertSubview(view, at: index)
isInsertingRenderedSubview = false
Expand Down
4 changes: 0 additions & 4 deletions Sources/OpenSwiftUICore/Log/Logging.swift
Original file line number Diff line number Diff line change
Expand Up @@ -193,11 +193,7 @@ package enum Log {
#if OPENSWIFTUI_LINK_TESTING
if Test.current != nil {
let comment: Comment = #"[Runtime Issue] message: \#(message.description) args: \#(args)"#
#if swift(>=6.3)
Issue.record(comment, severity: .warning)
#else
Issue.record(comment)
#endif
}
#endif

Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
//
// RuntimeIssueHandlingTrait.swift
// OpenSwiftUICoreTests
// OpenSwiftUITestsSupport

import Foundation
import Testing
package import Testing

func containsRuntimeIssue(_ message: String) -> ContainsRuntimeIssueTrait {
package func containsRuntimeIssue(_ message: String) -> ContainsRuntimeIssueTrait {
ContainsRuntimeIssueTrait(message: message)
}

struct ContainsRuntimeIssueTrait: TestTrait, TestScoping {
typealias TestScopeProvider = ContainsRuntimeIssueTrait
package struct ContainsRuntimeIssueTrait: TestTrait, TestScoping {
package typealias TestScopeProvider = ContainsRuntimeIssueTrait

var message: String

func provideScope(
package func provideScope(
for test: Test,
testCase: Test.Case?,
performing function: @Sendable () async throws -> Void
Expand All @@ -29,12 +29,16 @@ struct ContainsRuntimeIssueTrait: TestTrait, TestScoping {
}
}
try await issueHandler.provideScope(for: test, testCase: testCase, performing: function)
#if !OPENSWIFTUI_LINK_TESTING
Issue.record("ContainsRuntimeIssueTrait requires OPENSWIFTUI_LINK_TESTING to be set", severity: .warning)
#else
if !state.hasMatch {
Issue.record(
#"Expected runtime issue was not recorded: "\#(message)""#,
sourceLocation: test.sourceLocation
)
}
#endif
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import OpenAttributeGraphShims
@testable import OpenSwiftUICore
import OpenSwiftUITestsSupport
import Testing

// FIXME: Remove after we implement forEachField
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import Foundation
import OpenAttributeGraphShims
@_spi(ForOpenSwiftUIOnly) @testable import OpenSwiftUICore
import OpenSwiftUITestsSupport
import Testing

@MainActor
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// OpenSwiftUICoreTests

import OpenSwiftUICore
import OpenSwiftUITestsSupport
import Testing

struct MainActorUtilsTests {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//
// NSHostingViewTests.swift
// OpenSwiftUITests

#if os(macOS)
import AppKit
import OpenSwiftUI
import OpenSwiftUICore
import OpenSwiftUITestsSupport
import Testing

@MainActor
struct NSHostingViewTests {
@Test(containsRuntimeIssue("Adding '%s' as a subview of %s is not supported and may result in a broken view hierarchy. Add your view above %s in a common superview or insert it into your OpenSwiftUI content in a NSViewRepresentable instead."))
func didAddSubviewRecordsRuntimeIssue() {
let hostingView = NSHostingView(rootView: EmptyView())
let subview = NSView()

Semantics.v7.test {
hostingView.addSubview(subview)
}

#expect(subview.superview === hostingView)
}
}
#endif
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//
// UIHostingViewTests.swift
// OpenSwiftUITests

#if os(iOS) || os(visionOS)
import OpenSwiftUI
import OpenSwiftUICore
import OpenSwiftUITestsSupport
import Testing
import UIKit

@MainActor
struct UIHostingViewTests {
@Test(containsRuntimeIssue("Adding '%s' as a subview of %s is not supported and may result in a broken view hierarchy. Add your view above %s in a common superview or insert it into your OpenSwiftUI content in a UIViewRepresentable instead."))
func didAddSubviewRecordsRuntimeIssue() {
let hostingView = _UIHostingView(rootView: EmptyView())
let subview = UIView()

Semantics.v7.test {
hostingView.addSubview(subview)
}

#expect(subview.superview === hostingView)
}
}
#endif
Loading