Skip to content

Commit

Permalink
RUM-3531 WebView slot cache
Browse files Browse the repository at this point in the history
  • Loading branch information
maxep committed Apr 4, 2024
1 parent e25a3bf commit 7fca08d
Show file tree
Hide file tree
Showing 22 changed files with 474 additions and 82 deletions.
28 changes: 18 additions & 10 deletions Datadog/Datadog.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -481,8 +481,6 @@
61F2728B25C9561A00D54BF8 /* PLCrashReporterIntegration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61F2728A25C9561A00D54BF8 /* PLCrashReporterIntegration.swift */; };
61F272B125C95ED800D54BF8 /* Mocks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61F2729A25C95EB200D54BF8 /* Mocks.swift */; };
61F74AF426F20E4600E5F5ED /* DebugCrashReportingWithRUMViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61F74AF326F20E4600E5F5ED /* DebugCrashReportingWithRUMViewController.swift */; };
61F930CB2BA213AC005F0EE2 /* AppHang.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61F930CA2BA213AC005F0EE2 /* AppHang.swift */; };
61F930CC2BA213AC005F0EE2 /* AppHang.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61F930CA2BA213AC005F0EE2 /* AppHang.swift */; };
61F930BE2BA1ACAC005F0EE2 /* Storage+TLV.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61F930BD2BA1ACAC005F0EE2 /* Storage+TLV.swift */; };
61F930BF2BA1ACAC005F0EE2 /* Storage+TLV.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61F930BD2BA1ACAC005F0EE2 /* Storage+TLV.swift */; };
61F930C22BA1C41A005F0EE2 /* TLVBlockReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61F930C12BA1C41A005F0EE2 /* TLVBlockReader.swift */; };
Expand All @@ -491,6 +489,8 @@
61F930C62BA1C4EB005F0EE2 /* TLVBlockReaderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61F930C42BA1C4EB005F0EE2 /* TLVBlockReaderTests.swift */; };
61F930C82BA1C51C005F0EE2 /* Storage+TLVTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61F930C72BA1C51C005F0EE2 /* Storage+TLVTests.swift */; };
61F930C92BA1C51C005F0EE2 /* Storage+TLVTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61F930C72BA1C51C005F0EE2 /* Storage+TLVTests.swift */; };
61F930CB2BA213AC005F0EE2 /* AppHang.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61F930CA2BA213AC005F0EE2 /* AppHang.swift */; };
61F930CC2BA213AC005F0EE2 /* AppHang.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61F930CA2BA213AC005F0EE2 /* AppHang.swift */; };
61F9CABA2513A7F5000A5E61 /* RUMSessionMatcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61F9CA982513977A000A5E61 /* RUMSessionMatcher.swift */; };
61FC5F3525CC1898006BB4DE /* CrashContextProviderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61FC5F3425CC1898006BB4DE /* CrashContextProviderTests.swift */; };
61FDBA1326971953001D9D43 /* CrashReportMinifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61FDBA1226971953001D9D43 /* CrashReportMinifier.swift */; };
Expand Down Expand Up @@ -736,6 +736,7 @@
D23354FD2A42E32000AFCAE2 /* InternalExtended.swift in Sources */ = {isa = PBXBuildFile; fileRef = D23354FB2A42E32000AFCAE2 /* InternalExtended.swift */; };
D234613128B7713000055D4C /* FeatureContextTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D234613028B7712F00055D4C /* FeatureContextTests.swift */; };
D234613228B7713000055D4C /* FeatureContextTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D234613028B7712F00055D4C /* FeatureContextTests.swift */; };
D23BFFEE2BBECA1C00ED6DD6 /* WebViewSlotCacheTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D23BFFED2BBECA1C00ED6DD6 /* WebViewSlotCacheTests.swift */; };
D23F8E5229DDCD28001CFAE8 /* UIViewControllerHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61F3CDA2251118FB00C816E5 /* UIViewControllerHandler.swift */; };
D23F8E5329DDCD28001CFAE8 /* RUMCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = 61C3E63A24BF1A4B008053F2 /* RUMCommand.swift */; };
D23F8E5429DDCD28001CFAE8 /* ValuePublisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 611529A425E3DD51004F740E /* ValuePublisher.swift */; };
Expand Down Expand Up @@ -947,6 +948,7 @@
D270CDE12B46E5A50002EACD /* URLSessionDataDelegateSwizzlerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D270CDDF2B46E5A50002EACD /* URLSessionDataDelegateSwizzlerTests.swift */; };
D2777D9D29F6A75800FFBB40 /* TelemetryReceiverTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2777D9C29F6A75800FFBB40 /* TelemetryReceiverTests.swift */; };
D2777D9E29F6A75800FFBB40 /* TelemetryReceiverTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D2777D9C29F6A75800FFBB40 /* TelemetryReceiverTests.swift */; };
D27B8A402BB171BA0031D37E /* WebViewSlotCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = D27B8A3F2BB171BA0031D37E /* WebViewSlotCache.swift */; };
D27D81C12A5D415200281CC2 /* CrashReporter.xcframework in Frameworks */ = {isa = PBXBuildFile; fileRef = 614ED36B260352DC00C8C519 /* CrashReporter.xcframework */; };
D27D81C22A5D415200281CC2 /* DatadogCrashReporting.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 61B7885425C180CB002675B5 /* DatadogCrashReporting.framework */; };
D27D81C32A5D415200281CC2 /* DatadogInternal.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D23039A5298D513C001A1FA3 /* DatadogInternal.framework */; };
Expand Down Expand Up @@ -2409,11 +2411,11 @@
61F3CDA62512144600C816E5 /* UIKitRUMViewsPredicate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIKitRUMViewsPredicate.swift; sourceTree = "<group>"; };
61F3CDAA25121FB500C816E5 /* UIViewControllerSwizzlerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIViewControllerSwizzlerTests.swift; sourceTree = "<group>"; };
61F74AF326F20E4600E5F5ED /* DebugCrashReportingWithRUMViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DebugCrashReportingWithRUMViewController.swift; sourceTree = "<group>"; };
61F930CA2BA213AC005F0EE2 /* AppHang.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppHang.swift; sourceTree = "<group>"; };
61F930BD2BA1ACAC005F0EE2 /* Storage+TLV.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Storage+TLV.swift"; sourceTree = "<group>"; };
61F930C12BA1C41A005F0EE2 /* TLVBlockReader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TLVBlockReader.swift; sourceTree = "<group>"; };
61F930C42BA1C4EB005F0EE2 /* TLVBlockReaderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TLVBlockReaderTests.swift; sourceTree = "<group>"; };
61F930C72BA1C51C005F0EE2 /* Storage+TLVTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Storage+TLVTests.swift"; sourceTree = "<group>"; };
61F930CA2BA213AC005F0EE2 /* AppHang.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppHang.swift; sourceTree = "<group>"; };
61F9CA982513977A000A5E61 /* RUMSessionMatcher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RUMSessionMatcher.swift; sourceTree = "<group>"; };
61FB222C244A21ED00902D19 /* LoggingFeatureMocks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoggingFeatureMocks.swift; sourceTree = "<group>"; };
61FB222F244E1BE900902D19 /* DatadogLogsFeatureTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DatadogLogsFeatureTests.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -2586,6 +2588,7 @@
D23354FB2A42E32000AFCAE2 /* InternalExtended.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InternalExtended.swift; sourceTree = "<group>"; };
D234613028B7712F00055D4C /* FeatureContextTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeatureContextTests.swift; sourceTree = "<group>"; };
D236BE2729520FED00676E67 /* CrashReportReceiver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CrashReportReceiver.swift; sourceTree = "<group>"; };
D23BFFED2BBECA1C00ED6DD6 /* WebViewSlotCacheTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebViewSlotCacheTests.swift; sourceTree = "<group>"; };
D23F8E9929DDCD28001CFAE8 /* DatadogRUM.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = DatadogRUM.framework; sourceTree = BUILT_PRODUCTS_DIR; };
D23F8ECD29DDCD38001CFAE8 /* DatadogRUMTests tvOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "DatadogRUMTests tvOS.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
D240684D27CE6C9E00C04F44 /* Example tvOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Example tvOS.app"; sourceTree = BUILT_PRODUCTS_DIR; };
Expand Down Expand Up @@ -2650,6 +2653,7 @@
D270CDDC2B46E3DB0002EACD /* URLSessionDataDelegateSwizzler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLSessionDataDelegateSwizzler.swift; sourceTree = "<group>"; };
D270CDDF2B46E5A50002EACD /* URLSessionDataDelegateSwizzlerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLSessionDataDelegateSwizzlerTests.swift; sourceTree = "<group>"; };
D2777D9C29F6A75800FFBB40 /* TelemetryReceiverTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TelemetryReceiverTests.swift; sourceTree = "<group>"; };
D27B8A3F2BB171BA0031D37E /* WebViewSlotCache.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebViewSlotCache.swift; sourceTree = "<group>"; };
D286626D2A43487500852CE3 /* Datadog.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Datadog.swift; sourceTree = "<group>"; };
D28F836729C9E71C00EF8EA2 /* DDSpanTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DDSpanTests.swift; sourceTree = "<group>"; };
D28F836A29C9E7A300EF8EA2 /* TracingURLSessionHandlerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TracingURLSessionHandlerTests.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -3269,10 +3273,11 @@
61054E242A6EE10A00AAA894 /* ViewTreeSnapshot.swift */,
61054E252A6EE10A00AAA894 /* ViewTreeSnapshotBuilder.swift */,
61054E262A6EE10A00AAA894 /* ViewTreeRecorder.swift */,
61054E272A6EE10A00AAA894 /* NodeRecorders */,
61054E372A6EE10A00AAA894 /* ViewAttributes+Copy.swift */,
61054E382A6EE10A00AAA894 /* ViewTreeRecordingContext.swift */,
61054E392A6EE10A00AAA894 /* NodeIDGenerator.swift */,
D27B8A3F2BB171BA0031D37E /* WebViewSlotCache.swift */,
61054E272A6EE10A00AAA894 /* NodeRecorders */,
);
path = ViewTreeSnapshot;
sourceTree = "<group>";
Expand Down Expand Up @@ -3349,7 +3354,7 @@
A7B932F42B1F694000AE6477 /* ResourcesProcessor.swift */,
61054E492A6EE10A00AAA894 /* Privacy */,
61054E4C2A6EE10A00AAA894 /* Diffing */,
61054E4F2A6EE10A00AAA894 /* SRDataModelsBuilder */,
61054E4F2A6EE10A00AAA894 /* Builders */,
61054E522A6EE10A00AAA894 /* Flattening */,
);
path = Processor;
Expand All @@ -3372,13 +3377,13 @@
path = Diffing;
sourceTree = "<group>";
};
61054E4F2A6EE10A00AAA894 /* SRDataModelsBuilder */ = {
61054E4F2A6EE10A00AAA894 /* Builders */ = {
isa = PBXGroup;
children = (
61054E502A6EE10A00AAA894 /* RecordsBuilder.swift */,
61054E512A6EE10A00AAA894 /* WireframesBuilder.swift */,
);
path = SRDataModelsBuilder;
path = Builders;
sourceTree = "<group>";
};
61054E522A6EE10A00AAA894 /* Flattening */ = {
Expand Down Expand Up @@ -3449,7 +3454,7 @@
children = (
61054F4F2A6EE1BA00AAA894 /* Privacy */,
61054F512A6EE1BA00AAA894 /* Diffing */,
61054F542A6EE1BA00AAA894 /* SRDataModelsBuilder */,
61054F542A6EE1BA00AAA894 /* Builders */,
61054F562A6EE1BA00AAA894 /* SnapshotProcessorTests.swift */,
A7D9528B2B28C18D004C79B1 /* ResourceProcessorTests.swift */,
61054F572A6EE1BA00AAA894 /* Flattening */,
Expand All @@ -3474,12 +3479,12 @@
path = Diffing;
sourceTree = "<group>";
};
61054F542A6EE1BA00AAA894 /* SRDataModelsBuilder */ = {
61054F542A6EE1BA00AAA894 /* Builders */ = {
isa = PBXGroup;
children = (
61054F552A6EE1BA00AAA894 /* RecordsBuilderTests.swift */,
);
path = SRDataModelsBuilder;
path = Builders;
sourceTree = "<group>";
};
61054F572A6EE1BA00AAA894 /* Flattening */ = {
Expand Down Expand Up @@ -3543,6 +3548,7 @@
61054F662A6EE1BA00AAA894 /* ViewTreeRecordingContextTests.swift */,
61054F672A6EE1BA00AAA894 /* ViewTreeSnapshotBuilderTests.swift */,
61054F682A6EE1BA00AAA894 /* NodeIDGeneratorTests.swift */,
D23BFFED2BBECA1C00ED6DD6 /* WebViewSlotCacheTests.swift */,
61054F692A6EE1BA00AAA894 /* NodeRecorders */,
61054F792A6EE1BA00AAA894 /* ViewTreeRecorderTests.swift */,
61054F7A2A6EE1BA00AAA894 /* ViewTreeSnapshotTests.swift */,
Expand Down Expand Up @@ -7757,6 +7763,7 @@
61054E962A6EE10A00AAA894 /* Diff+SRWireframes.swift in Sources */,
D22C5BD02A98A6660024CC1F /* Baggages.swift in Sources */,
61054E902A6EE10A00AAA894 /* SegmentJSON.swift in Sources */,
D27B8A402BB171BA0031D37E /* WebViewSlotCache.swift in Sources */,
61054E672A6EE10A00AAA894 /* Recorder.swift in Sources */,
61054E6B2A6EE10A00AAA894 /* CFType+Safety.swift in Sources */,
61054E852A6EE10A00AAA894 /* UISegmentRecorder.swift in Sources */,
Expand Down Expand Up @@ -7878,6 +7885,7 @@
61054F9B2A6EE1BA00AAA894 /* QueueTests.swift in Sources */,
61054F992A6EE1BA00AAA894 /* ColorsTests.swift in Sources */,
61054FBF2A6EE1BA00AAA894 /* UIPickerViewRecorderTests.swift in Sources */,
D23BFFEE2BBECA1C00ED6DD6 /* WebViewSlotCacheTests.swift in Sources */,
61054FAE2A6EE1BA00AAA894 /* TouchIdentifierGeneratorTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ class WebRecordIntegrationTests: XCTestCase {

func testWebRecordIntegration() throws {
// Given
let webView = WKWebView()
let randomApplicationID: String = .mockRandom()
let randomUUID: UUID = .mockRandom()
let randomBrowserViewID: UUID = .mockRandom()
Expand All @@ -65,7 +66,7 @@ class WebRecordIntegrationTests: XCTestCase {

// When
RUMMonitor.shared(in: core).startView(key: "web-view")
controller.send(body: body)
controller.send(body: body, from: webView)
controller.flush()

// Then
Expand All @@ -74,7 +75,7 @@ class WebRecordIntegrationTests: XCTestCase {
let segment = try XCTUnwrap(segments.first)

let expectedUUID = randomUUID.uuidString.lowercased()
let expectedSlotID = "\(controller.hash as Int)" // explicitly get the NSObject.hash
let expectedSlotID = String(webView.hash)

XCTAssertEqual(segment.applicationID, randomApplicationID)
XCTAssertEqual(segment.sessionID, expectedUUID)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ final class WKUserContentControllerMock: WKUserContentController {
handlers[name] = nil
}

func send(body: Any) {
func send(body: Any, from webView: WKWebView? = nil) {
let handler = handlers[DDScriptMessageHandler.name]
let message = WKScriptMessageMock(body: body, name: DDScriptMessageHandler.name)
let message = WKScriptMessageMock(body: body, name: DDScriptMessageHandler.name, webView: webView)
handler?.userContentController(self, didReceive: message)
}

Expand All @@ -41,14 +41,17 @@ final class WKUserContentControllerMock: WKUserContentController {
private final class WKScriptMessageMock: WKScriptMessage {
private let _body: Any
private let _name: String
private weak var _webView: WKWebView?

init(body: Any, name: String) {
init(body: Any, name: String, webView: WKWebView? = nil) {
_body = body
_name = name
_webView = webView
}

override var body: Any { _body }
override var name: String { _name }
override weak var webView: WKWebView? { _webView }
}

#endif
Original file line number Diff line number Diff line change
Expand Up @@ -165,10 +165,7 @@ class WebViewEventReceiverTests: XCTestCase {

func testGivenRUMContextAvailable_whenReceivingWebEvent_itGetsEnrichedWithOtherMobileContextAndWritten() throws {
let core = PassthroughCoreMock(
context: .mockWith(
source: "react-native",
serverTimeOffset: .mockRandom(min: -10, max: 10).rounded()
)
context: .mockWith(source: "react-native")
)

// Given
Expand Down
10 changes: 9 additions & 1 deletion DatadogSessionReplay/Sources/Models/SRDataModels.swift
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,9 @@ public struct SRWebviewWireframe: Codable, Hashable {
/// Defines the unique ID of the wireframe. This is persistent throughout the view lifetime.
public let id: Int64

/// Whether this web-view is visible or not.
public let isVisible: Bool?

/// The style of this wireframe.
public let shapeStyle: SRShapeStyle?

Expand All @@ -475,6 +478,7 @@ public struct SRWebviewWireframe: Codable, Hashable {
case clip = "clip"
case height = "height"
case id = "id"
case isVisible = "isVisible"
case shapeStyle = "shapeStyle"
case slotId = "slotId"
case type = "type"
Expand Down Expand Up @@ -970,6 +974,9 @@ public struct SRIncrementalSnapshotRecord: Codable {
/// Defines the unique ID of the wireframe. This is persistent throughout the view lifetime.
public let id: Int64

/// Whether this web-view is visible or not.
public let isVisible: Bool?

/// The style of this wireframe.
public let shapeStyle: SRShapeStyle?

Expand All @@ -993,6 +1000,7 @@ public struct SRIncrementalSnapshotRecord: Codable {
case clip = "clip"
case height = "height"
case id = "id"
case isVisible = "isVisible"
case shapeStyle = "shapeStyle"
case slotId = "slotId"
case type = "type"
Expand Down Expand Up @@ -1322,4 +1330,4 @@ public enum SRRecord: Codable {
}
}
#endif
// Generated from https://github.com/DataDog/rum-events-format/tree/c3747b3facf75e51cbad4c32f77ec3894f5a7249
// Generated from https://github.com/DataDog/rum-events-format/tree/be033e3251da4a20891a774f9843c489a693c80d
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,34 @@ public typealias WireframeID = NodeID
/// Note: `WireframesBuilder` is used by `Processor` on a single background thread.
@_spi(Internal)
public class SessionReplayWireframesBuilder {
/// The cache of webview slots in memory during snapshot.
private(set) var webviews: [Int: WebViewSlot]

/// Creates a builder for builder wireframes in snapshot processing.
///
/// The builder takes optional webview slots in cache that can be updated
/// while traversing the node. The cache will be used to create wireframes
/// that are not visible be still need to be kept by the player.
///
/// - Parameter webviews: The webview slot cache.
init(webviews: [Int: WebViewSlot] = [:]) {
self.webviews = webviews
}

/// Removes a webview slot.
///
/// Any node builder should remove the slot that is visible so it can be
/// placed at the right index in the wireframe list. Any remaining slot in
/// cache are considered hidden.
///
/// - Parameter id: The id of the slot to remove.
func removeWebView(withSlotID id: Int) {
webviews[id] = nil
}
}

@_spi(Internal)
extension SessionReplayWireframesBuilder {
/// A set of fallback values to use if the actual value cannot be read or converted.
///
/// The idea is to always provide value, which would make certain element visible in the player.
Expand Down Expand Up @@ -186,13 +214,15 @@ public class SessionReplayWireframesBuilder {
borderWidth: CGFloat? = nil,
backgroundColor: CGColor? = nil,
cornerRadius: CGFloat? = nil,
opacity: CGFloat? = nil
opacity: CGFloat? = nil,
isVisible: Bool? = nil
) -> SRWireframe {
let wireframe = SRWebviewWireframe(
border: createShapeBorder(borderColor: borderColor, borderWidth: borderWidth),
clip: clip,
height: Int64(withNoOverflow: frame.height),
id: id,
isVisible: isVisible,
shapeStyle: createShapeStyle(backgroundColor: backgroundColor, cornerRadius: cornerRadius, opacity: opacity),
slotId: slotId,
width: Int64(withNoOverflow: frame.size.width),
Expand Down
Loading

0 comments on commit 7fca08d

Please sign in to comment.