diff --git a/.circleci/config.yml b/.circleci/config.yml index f7682f33e..ef2198c66 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -11,7 +11,7 @@ version: 2 jobs: deploy-website: docker: - - image: circleci/node:14.11.0 + - image: cimg/node:16.14.0 steps: - checkout diff --git a/.github/workflows/build_and_deploy.yml b/.github/workflows/build_and_deploy.yml new file mode 100644 index 000000000..782644d65 --- /dev/null +++ b/.github/workflows/build_and_deploy.yml @@ -0,0 +1,20 @@ +name: facebook/idb/build_and_deploy +on: + push: + branches: + - main +jobs: + deploy-website: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4.1.0 + - uses: actions/setup-node@v4 + with: + node-version: 16.14.0 + - name: Deploying to GitHub Pages + run: | + git config --global user.email "docusaurus-bot@users.noreply.github.com" + git config --global user.name "Website Deployment Script" + echo "machine github.com login docusaurus-bot password ${{ secrets.GITHUB_TOKEN }}" > ~/.netrc + echo "Deploying website..." + cd website && yarn install && GIT_USER=docusaurus-bot USE_SSH=false yarn deploy diff --git a/CompanionLib/BridgeFuture/BridgeFuture.swift b/CompanionLib/BridgeFuture/BridgeFuture.swift new file mode 100644 index 000000000..7bc2c2ed8 --- /dev/null +++ b/CompanionLib/BridgeFuture/BridgeFuture.swift @@ -0,0 +1,205 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import FBControlCore +import Foundation +import IDBCompanionUtilities + +enum FBFutureError: Error { + + /// This indicates an error in objc code where result callback was called but no error or result provided. In case of this, debug `FBFuture` implementation. + case continuationFullfilledWithoutValues + + /// This indicates an error in `BridgeFuture.values` implementation. In case of this, debug `BridgeFuture.values` implementation. + case taskGroupReceivedNilResultInternalError +} + +/// Swift compiler does not allow usage of generic parameters of objc classes in extension +/// so we need to create a bridge for convenience. +public enum BridgeFuture { + + /// Use this to receive results from multiple futures. The results are **ordered in the same order as passed futures**, so you can safely access them from + /// array by indexes. + /// - Note: We should *not* use @discardableResult, results should be dropped explicitly by the callee. + public static func values(_ futures: FBFuture...) async throws -> [T] { + let futuresArr: [FBFuture] = futures + return try await values(futuresArr) + } + + /// Use this to receive results from multiple futures. The results are **ordered in the same order as passed futures**, so you can safely access them from + /// array by indexes. + /// - Note: We should *not* use @discardableResult, results should be dropped explicitly by the callee. + public static func values(_ futures: [FBFuture]) async throws -> [T] { + return try await withThrowingTaskGroup(of: (Int, T).self, returning: [T].self) { group in + var results = [T?].init(repeating: nil, count: futures.count) + + for (index, future) in futures.enumerated() { + group.addTask { + return try await (index, BridgeFuture.value(future)) + } + } + + for try await (index, value) in group { + results[index] = value + } + + return try results.map { value -> T in + guard let shouldDefinitelyExist = value else { + assertionFailure("This should never happen. We should fullfill all values at that moment") + throw FBFutureError.taskGroupReceivedNilResultInternalError + } + return shouldDefinitelyExist + } + } + } + + /// Awaitable value that waits for publishing from the wrapped future + /// - Note: We should *not* use @discardableResult, results should be dropped explicitly by the callee. + public static func value(_ future: FBFuture) async throws -> T { + try await withTaskCancellationHandler { + try await withCheckedThrowingContinuation { continuation in + future.onQueue(BridgeQueues.futureSerialFullfillmentQueue, notifyOfCompletion: { resultFuture in + if let error = resultFuture.error { + continuation.resume(throwing: error) + } else if let value = resultFuture.result { + // swiftlint:disable force_cast + continuation.resume(returning: value as! T) + } else { + continuation.resume(throwing: FBFutureError.continuationFullfilledWithoutValues) + } + }) + } + } onCancel: { + future.cancel() + } + } + + /// Awaitable value that waits for publishing from the wrapped future. + /// This is convenient bridgeable overload for dealing with objc `NSArray`. + /// - Warning: This operation not safe (as most of objc bridge). That means you should be sure that type bridging will succeed. + /// Consider this method as + /// + /// ``` + /// // ------- command_executor.m + /// - (FBFuture *> *)doTheThing; + /// + /// // ------- swiftfile.swift + /// let futureFromObjc: FBFuture = command_executor.doTheThing() // Note: NSNumber is lost + /// let withoutBridge = BridgeFuture.value(futureFromObjc) // withoutBridge: NSArray + /// let withBridge: [NSNumer] = BridgeFuture.value(futureFromObjc) // withBridge: [NSNumber] + /// + /// // But this starts to shine more when you have to pass results to methods/return results, e.g. + /// func operation() -> [Int] { + /// return BridgeFuture.value(futureFromObjc) + /// } + /// + /// // Or pass value to some oter method + /// func someMethod(accepts: [NSNumber]) { ... } + /// + /// self.someMethod(accepts: BridgeFuture.value(futureFromObjc) + /// ``` + public static func value(_ future: FBFuture) async throws -> [T] { + let objcValue = try await value(future) + // swiftlint:disable force_cast + return objcValue as! [T] + } + + /// Awaitable value that waits for publishing from the wrapped future. + /// This is convenient bridgeable overload for dealing with objc `NSDictionary`. + /// - Warning: This operation not safe (as most of objc bridge). That means you should be sure that type bridging will succeed. + /// Consider this method as + /// + /// ``` + /// // ------- command_executor.m + /// - (FBFuture *> *)doTheThing; + /// + /// // ------- swiftfile.swift + /// let futureFromObjc: FBFuture = command_executor.doTheThing() // Note: types is lost + /// let withoutBridge = BridgeFuture.value(futureFromObjc) // withoutBridge: NSDictionary + /// let withBridge: [FBInstalledApplication: Any] = BridgeFuture.value(futureFromObjc) // withBridge: [FBInstalledApplication: Any] + /// + /// // But this starts to shine more when you have to pass results to methods/return results, e.g. + /// func operation() -> [FBInstalledApplication: Any] { + /// return BridgeFuture.value(futureFromObjc) + /// } + /// + /// // Or pass value to some oter method + /// func someMethod(accepts: [FBInstalledApplication: Any]) { ... } + /// + /// self.someMethod(accepts: BridgeFuture.value(futureFromObjc) + /// ``` + public static func value(_ future: FBFuture) async throws -> [T: U] { + let objcValue = try await value(future) + // swiftlint:disable force_cast + return objcValue as! [T: U] + } + + /// NSNull is Void equivalent in objc reference world. So is is safe to ignore the result. + public static func await(_ future: FBFuture) async throws { + _ = try await Self.value(future) + } + + /// This overload exists because of `FBMutableFuture` does not convert its exact generic type automatically but it can be automatically converted to `FBFuture` + /// without any problems. This decision may be revisited in future. + public static func await(_ future: FBFuture) async throws { + _ = try await Self.value(future) + } + + /// Interop between swift and objc generics are quite bad, so we have to write wrappers like this. + /// By default swift bridge compiler could not convert generic type of `FBMutableFuture`. But this force cast is 100% valid and works in runtime + /// so we just use this little helper. + public static func convertToFuture(_ mutableFuture: FBMutableFuture) -> FBFuture { + let future: FBFuture = mutableFuture + // swiftlint:disable force_cast + return future as! FBFuture + } + + /// Split FBFutureContext to two pieces: result and later cleanup closure + /// - Parameter futureContext: source future context + /// - Returns: Tuple of extracted result and cleanup closure that **should** be called later to perform all required cleanups + public static func value(_ futureContext: FBFutureContext) async throws -> T { + try FBTeardownContext.current.addCleanup { + let cleanupFuture = futureContext.onQueue(BridgeQueues.futureSerialFullfillmentQueue) { (result: Any, teardown: FBMutableFuture) -> NSNull in + teardown.resolve(withResult: NSNull()) + return NSNull() + } + try await BridgeFuture.await(cleanupFuture) + } + + return try await value(futureContext.future) + } + + /// Awaitable value that waits for publishing from the wrapped futureContext. + /// This is convenient bridgeable overload for dealing with objc `NSArray`. + /// - Warning: This operation not safe (as most of objc bridge). That means you should be sure that type bridging will succeed. + /// Consider this method as + /// + /// ``` + /// // ------- command_executor.m + /// - (FBFuture *> *)doTheThing; + /// + /// // ------- swiftfile.swift + /// let futureFromObjc: FBFuture = command_executor.doTheThing() // Note: NSNumber is lost + /// let withoutBridge = BridgeFuture.value(futureFromObjc) // withoutBridge: NSArray + /// let withBridge: [NSNumer] = BridgeFuture.value(futureFromObjc) // withBridge: [NSNumber] + /// + /// // But this starts to shine more when you have to pass results to methods/return results, e.g. + /// func operation() -> [Int] { + /// return BridgeFuture.value(futureFromObjc) + /// } + /// + /// // Or pass value to some oter method + /// func someMethod(accepts: [NSNumber]) { ... } + /// + /// self.someMethod(accepts: BridgeFuture.value(futureFromObjc) + /// ``` + public static func values(_ futureContext: FBFutureContext) async throws -> [U] { + let objcValue = try await value(futureContext) + // swiftlint:disable force_cast + return objcValue as! [U] + } +} diff --git a/CompanionLib/BridgeFuture/BridgeQueues.swift b/CompanionLib/BridgeFuture/BridgeQueues.swift new file mode 100644 index 000000000..8ee3f8059 --- /dev/null +++ b/CompanionLib/BridgeFuture/BridgeQueues.swift @@ -0,0 +1,27 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import Foundation + +/// Queues collection to bring objc and async-swift worlds together +public enum BridgeQueues { + + /// Plain serial queue that is primarily used to convert *all* FBFuture calls to swift awaitable values + public static let futureSerialFullfillmentQueue = DispatchQueue(label: "com.facebook.fbfuture.fullfilment") + + /// Some of *commandExecutor* operations requires DispatchQueue to send response. + /// The only purpose of everything handled inside this queue is to passthrough call to swift async world via calling swift `Task` api + /// ``` + /// commandExecutor.doSomething(onQueue: BridgeQueues.miscEventReaderQueue) { jobResult in + /// Task { + /// try? await responseStream.send(jobResult) + /// } + /// } + /// ``` + /// + public static let miscEventReaderQueue = DispatchQueue(label: "com.facebook.miscellaneous.reader", qos: .userInitiated, attributes: .concurrent) +} diff --git a/CompanionLib/CompanionLib.h b/CompanionLib/CompanionLib.h new file mode 100644 index 000000000..28fb7c0ee --- /dev/null +++ b/CompanionLib/CompanionLib.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import diff --git a/idb_companion/Configuration/FBIDBAppHostedTestConfiguration.h b/CompanionLib/Configuration/FBIDBAppHostedTestConfiguration.h similarity index 93% rename from idb_companion/Configuration/FBIDBAppHostedTestConfiguration.h rename to CompanionLib/Configuration/FBIDBAppHostedTestConfiguration.h index 44a96b598..8a566a819 100644 --- a/idb_companion/Configuration/FBIDBAppHostedTestConfiguration.h +++ b/CompanionLib/Configuration/FBIDBAppHostedTestConfiguration.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/idb_companion/Configuration/FBIDBAppHostedTestConfiguration.m b/CompanionLib/Configuration/FBIDBAppHostedTestConfiguration.m similarity index 92% rename from idb_companion/Configuration/FBIDBAppHostedTestConfiguration.m rename to CompanionLib/Configuration/FBIDBAppHostedTestConfiguration.m index 5f46557a6..7f51f9dda 100644 --- a/idb_companion/Configuration/FBIDBAppHostedTestConfiguration.m +++ b/CompanionLib/Configuration/FBIDBAppHostedTestConfiguration.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/idb_companion/Server/FBIDBCommandExecutor.h b/CompanionLib/FBIDBCommandExecutor.h similarity index 84% rename from idb_companion/Server/FBIDBCommandExecutor.h rename to CompanionLib/FBIDBCommandExecutor.h index 6f224b5fe..3329acc6d 100644 --- a/idb_companion/Server/FBIDBCommandExecutor.h +++ b/CompanionLib/FBIDBCommandExecutor.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -9,11 +9,12 @@ #import -#import "FBXCTestDescriptor.h" - NS_ASSUME_NONNULL_BEGIN +@protocol FBXCTestDescriptor; +@protocol FBControlCoreLogger; @class FBBundleStorageManager; +@class FBDsymInstallLinkToBundle; @class FBIDBLogger; @class FBIDBPortsConfiguration; @class FBIDBStorageManager; @@ -21,9 +22,15 @@ NS_ASSUME_NONNULL_BEGIN @class FBInstalledArtifact; @class FBSimulatorHIDEvent; @class FBTemporaryDirectory; +@class FBXCTestRunRequest; @protocol FBXCTestReporter; +extern FBFileContainerKind const FBFileContainerKindXctest; +extern FBFileContainerKind const FBFileContainerKindDylib; +extern FBFileContainerKind const FBFileContainerKindDsym; +extern FBFileContainerKind const FBFileContainerKindFramework; + @interface FBIDBCommandExecutor : NSObject #pragma mark Initializers @@ -34,11 +41,11 @@ NS_ASSUME_NONNULL_BEGIN @param target the target to run against. @param storageManager storage for all bundles @param temporaryDirectory the temporary directory to use. - @param ports the ports to use. + @param debugserverPort will launch debug server at that port. @param logger a logger to log to. @return a new FBIDBCommandExecutor instance */ -+ (instancetype)commandExecutorForTarget:(id)target storageManager:(FBIDBStorageManager *)storageManager temporaryDirectory:(FBTemporaryDirectory *)temporaryDirectory ports:(FBIDBPortsConfiguration *)ports logger:(FBIDBLogger *)logger; ++ (instancetype)commandExecutorForTarget:(id)target storageManager:(FBIDBStorageManager *)storageManager temporaryDirectory:(FBTemporaryDirectory *)temporaryDirectory debugserverPort:(in_port_t)debugserverPort logger:(FBIDBLogger *)logger; #pragma mark Properties @@ -72,9 +79,10 @@ NS_ASSUME_NONNULL_BEGIN @param filePath the path to a file on disk with the file. @param makeDebuggable whether the app should be installed in a debuggable state or not. + @param overrideModificationTime if YES the archive contests' `mtime` will be ignored. Current timestamp will be used as mtime of extracted files/directories. @return A future that resolves with the App Bundle Id */ -- (FBFuture *)install_app_file_path:(NSString *)filePath make_debuggable:(BOOL)makeDebuggable; +- (FBFuture *)install_app_file_path:(NSString *)filePath make_debuggable:(BOOL)makeDebuggable override_modification_time:(BOOL)overrideModificationTime; /** Install an App via a Data stream. @@ -82,25 +90,28 @@ NS_ASSUME_NONNULL_BEGIN @param input the input to pipe. @param compression the compression type to use @param makeDebuggable whether the app should be installed in a debuggable state or not. + @param overrideModificationTime if YES the archive contests' `mtime` will be ignored. Current timestamp will be used as mtime of extracted files/directories. @return A future that resolves with the App Bundle Id */ -- (FBFuture *)install_app_stream:(FBProcessInput *)input compression:(FBCompressionFormat)compression make_debuggable:(BOOL)makeDebuggable; +- (FBFuture *)install_app_stream:(FBProcessInput *)input compression:(FBCompressionFormat)compression make_debuggable:(BOOL)makeDebuggable override_modification_time:(BOOL)overrideModificationTime; /** Installs an xctest bundle by file path. @param filePath the local file path of the xctest bundle + @param skipSigningBundles pass true to skip signing xctest bundles. @return a Future that resolves with the xctest identifier. */ -- (FBFuture *)install_xctest_app_file_path:(NSString *)filePath; +- (FBFuture *)install_xctest_app_file_path:(NSString *)filePath skipSigningBundles:(BOOL)skipSigningBundles; /** Installs an xctest bundle by a stream of tar data @param input a tar stream of the xctest data. + @param skipSigningBundles pass true to skip signing xctest bundles. @return a Future that resolves with the xctest identifier. */ -- (FBFuture *)install_xctest_app_stream:(FBProcessInput *)input; +- (FBFuture *)install_xctest_app_stream:(FBProcessInput *)input skipSigningBundles:(BOOL)skipSigningBundles; /** Installs a dylib from a file path. @@ -139,19 +150,20 @@ NS_ASSUME_NONNULL_BEGIN Installs a dSYM from a file path. @param filePath the input to pipe. - @param bundleID if specified installed dsym will be linked into the app bundle container. + @param linkTo if specified installed dsym will be linked into bundle container. @return A future that resolves with the dSYM Name */ -- (FBFuture *)install_dsym_file_path:(NSString *)filePath linkToApp:(nullable NSString *)bundleID; +- (FBFuture *)install_dsym_file_path:(NSString *)filePath linkTo:(nullable FBDsymInstallLinkToBundle *)linkTo; /** Installs dSYM(s) from a zip stream. @param input the input to pipe. - @param bundleID if specified installed dsym will be linked into the app bundle container. + @param compression the compression type to use + @param linkTo if specified installed dsym will be linked into bundle container. @return A future that resolves with the directory containing the dSYM(s) */ -- (FBFuture *)install_dsym_stream:(FBProcessInput *)input linkToApp:(nullable NSString *)bundleID; +- (FBFuture *)install_dsym_stream:(FBProcessInput *)input compression:(FBCompressionFormat)compression linkTo:(nullable FBDsymInstallLinkToBundle *)linkTo; /** Takes a Screenshot @@ -168,7 +180,7 @@ NS_ASSUME_NONNULL_BEGIN @param nestedFormat YES if the legacy format should be used, NO otherwise. @return A Future that resolves with the accessibility info */ -- (FBFuture *> *> *)accessibility_info_at_point:(nullable NSValue *)point nestedFormat:(BOOL)nestedFormat; +- (FBFuture *)accessibility_info_at_point:(nullable NSValue *)point nestedFormat:(BOOL)nestedFormat; /** Adds media files (photos, videos, ...) to the target @@ -211,7 +223,16 @@ NS_ASSUME_NONNULL_BEGIN @param bundleID app to approve services for @return a Future that resolves when complete. */ -- (FBFuture *)approve:(NSSet *)services for_application:(NSString *)bundleID; +- (FBFuture *)approve:(NSSet *)services for_application:(NSString *)bundleID; + +/** + Revokes the given services for an app + + @param services services to revoke + @param bundleID app to revoke services for + @return a Future that resolves when complete. + */ +- (FBFuture *)revoke:(NSSet *)services for_application:(NSString *)bundleID; /** Approves the deeplink given a schema and app. @@ -223,6 +244,16 @@ This allows to avoid the permission popup the first time we open a deeplink */ - (FBFuture *)approve_deeplink:(NSString *)scheme for_application:(NSString *)bundleID; +/** +Revokes the deeplink given a schema and app. +This enables the permission popup the first time we open a deeplink + +@param scheme scheme of the deeplink url (the part before ":") +@param bundleID app to revoke services for +@return a Future that resolves when complete. +*/ +- (FBFuture *)revoke_deeplink:(NSString *)scheme for_application:(NSString *)bundleID; + /** Open a url on the target @@ -249,9 +280,9 @@ This allows to avoid the permission popup the first time we open a deeplink /** List the xctests installed - @return a Future that resolves with a set of tests. + @return a Future that resolves with an array of tests. */ -- (FBFuture> *> *)list_test_bundles; +- (FBFuture> *> *)list_test_bundles; /** List the tests in an installed bundle @@ -368,10 +399,11 @@ This allows to avoid the permission popup the first time we open a deeplink @param name preference name @param value preference value + @param type preference value type @param domain preference domain - optional @return a Future that resolves when successful. */ -- (FBFuture *)set_preference:(NSString *)name value:(NSString *)value domain:(nullable NSString *)domain; +- (FBFuture *)set_preference:(NSString *)name value:(NSString *)value type:(nullable NSString *)type domain:(nullable NSString *)domain; /** Gets a preference value by its name and domain. If domain not specified assumed to be Apple Global Domain @@ -512,7 +544,7 @@ This allows to avoid the permission popup the first time we open a deeplink /** Spawn a dap protocol server from dapPath - + @param dapPath relative path to the root container where dap is installed @param stdIn where the dap process reads @param stdOut where the dap process writes diff --git a/idb_companion/Server/FBIDBCommandExecutor.m b/CompanionLib/FBIDBCommandExecutor.m similarity index 83% rename from idb_companion/Server/FBIDBCommandExecutor.m rename to CompanionLib/FBIDBCommandExecutor.m index fe06ca35e..a44bd6334 100644 --- a/idb_companion/Server/FBIDBCommandExecutor.m +++ b/CompanionLib/FBIDBCommandExecutor.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -10,17 +10,24 @@ #import #import +#import "FBXCTestDescriptor.h" +#import "FBXCTestRunRequest.h" #import "FBXCTestRunRequest.h" #import "FBIDBStorageManager.h" #import "FBIDBError.h" #import "FBIDBLogger.h" -#import "FBIDBPortsConfiguration.h" +#import "FBDsymInstallLinkToBundle.h" + +FBFileContainerKind const FBFileContainerKindXctest = @"xctest"; +FBFileContainerKind const FBFileContainerKindDylib = @"dylib"; +FBFileContainerKind const FBFileContainerKindDsym = @"dsym"; +FBFileContainerKind const FBFileContainerKindFramework = @"framework"; @interface FBIDBCommandExecutor () @property (nonatomic, strong, readonly) id target; @property (nonatomic, strong, readonly) FBIDBLogger *logger; -@property (nonatomic, strong, readonly) FBIDBPortsConfiguration *ports; +@property (nonatomic, readonly) in_port_t debugserverPort; @end @@ -28,12 +35,12 @@ @implementation FBIDBCommandExecutor #pragma mark Initializers -+ (instancetype)commandExecutorForTarget:(id)target storageManager:(FBIDBStorageManager *)storageManager temporaryDirectory:(FBTemporaryDirectory *)temporaryDirectory ports:(FBIDBPortsConfiguration *)ports logger:(FBIDBLogger *)logger ++ (instancetype)commandExecutorForTarget:(id)target storageManager:(FBIDBStorageManager *)storageManager temporaryDirectory:(FBTemporaryDirectory *)temporaryDirectory debugserverPort:(in_port_t)debugserverPort logger:(FBIDBLogger *)logger { - return [[self alloc] initWithTarget:target storageManager:storageManager temporaryDirectory:temporaryDirectory ports:ports logger:[logger withName:@"grpc_handler"]]; + return [[self alloc] initWithTarget:target storageManager:storageManager temporaryDirectory:temporaryDirectory debugserverPort:debugserverPort logger:[logger withName:@"grpc_handler"]]; } -- (instancetype)initWithTarget:(id)target storageManager:(FBIDBStorageManager *)storageManager temporaryDirectory:(FBTemporaryDirectory *)temporaryDirectory ports:(FBIDBPortsConfiguration *)ports logger:(FBIDBLogger *)logger +- (instancetype)initWithTarget:(id)target storageManager:(FBIDBStorageManager *)storageManager temporaryDirectory:(FBTemporaryDirectory *)temporaryDirectory debugserverPort:(in_port_t)debugserverPort logger:(FBIDBLogger *)logger { self = [super init]; if (!self) { @@ -43,7 +50,7 @@ - (instancetype)initWithTarget:(id)target storageManager:(FBIDBStor _target = target; _storageManager = storageManager; _temporaryDirectory = temporaryDirectory; - _ports = ports; + _debugserverPort = debugserverPort; _logger = logger; return self; @@ -69,29 +76,29 @@ - (instancetype)initWithTarget:(id)target storageManager:(FBIDBStor }]; } -- (FBFuture *)install_app_file_path:(NSString *)filePath make_debuggable:(BOOL)makeDebuggable +- (FBFuture *)install_app_file_path:(NSString *)filePath make_debuggable:(BOOL)makeDebuggable override_modification_time:(BOOL)overrideModificationTime { // Use .app directly, or extract an .ipa if ([FBBundleDescriptor isApplicationAtPath:filePath]) { return [self installAppBundle:[FBFutureContext futureContextWithFuture:[FBBundleDescriptor extractedApplicationAtPath:filePath]] makeDebuggable:makeDebuggable]; } else { - return [self installExtractedApp:[self.temporaryDirectory withArchiveExtractedFromFile:filePath] makeDebuggable:makeDebuggable]; + return [self installExtractedApp:[self.temporaryDirectory withArchiveExtractedFromFile:filePath overrideModificationTime:overrideModificationTime] makeDebuggable:makeDebuggable]; } } -- (FBFuture *)install_app_stream:(FBProcessInput *)input compression:(FBCompressionFormat)compression make_debuggable:(BOOL)makeDebuggable +- (FBFuture *)install_app_stream:(FBProcessInput *)input compression:(FBCompressionFormat)compression make_debuggable:(BOOL)makeDebuggable override_modification_time:(BOOL)overrideModificationTime { - return [self installExtractedApp:[self.temporaryDirectory withArchiveExtractedFromStream:input compression:compression] makeDebuggable:makeDebuggable]; + return [self installExtractedApp:[self.temporaryDirectory withArchiveExtractedFromStream:input compression:compression overrideModificationTime:overrideModificationTime] makeDebuggable:makeDebuggable]; } -- (FBFuture *)install_xctest_app_file_path:(NSString *)filePath +- (FBFuture *)install_xctest_app_file_path:(NSString *)filePath skipSigningBundles:(BOOL)skipSigningBundles { - return [self installXctestFilePath:[FBFutureContext futureContextWithFuture:[FBFuture futureWithResult:[NSURL fileURLWithPath:filePath]]]]; + return [self installXctestFilePath:[FBFutureContext futureContextWithFuture:[FBFuture futureWithResult:[NSURL fileURLWithPath:filePath]]] skipSigningBundles:skipSigningBundles]; } -- (FBFuture *)install_xctest_app_stream:(FBProcessInput *)stream +- (FBFuture *)install_xctest_app_stream:(FBProcessInput *)stream skipSigningBundles:(BOOL)skipSigningBundles { - return [self installXctest:[self.temporaryDirectory withArchiveExtractedFromStream:stream compression:FBCompressionFormatGZIP]]; + return [self installXctest:[self.temporaryDirectory withArchiveExtractedFromStream:stream compression:FBCompressionFormatGZIP] skipSigningBundles:skipSigningBundles]; } - (FBFuture *)install_dylib_file_path:(NSString *)filePath @@ -114,14 +121,14 @@ - (instancetype)initWithTarget:(id)target storageManager:(FBIDBStor return [self installBundle:[self.temporaryDirectory withArchiveExtractedFromStream:input compression:FBCompressionFormatGZIP] intoStorage:self.storageManager.framework]; } -- (FBFuture *)install_dsym_file_path:(NSString *)filePath linkToApp:(nullable NSString *)bundleID +- (FBFuture *)install_dsym_file_path:(NSString *)filePath linkTo:(nullable FBDsymInstallLinkToBundle *)linkTo { - return [self installAndLinkDsym:[FBFutureContext futureContextWithFuture:[FBFuture futureWithResult:[NSURL fileURLWithPath:filePath]]] intoStorage:self.storageManager.dsym linkToApp:bundleID]; + return [self installAndLinkDsym:[FBFutureContext futureContextWithFuture:[FBFuture futureWithResult:[NSURL fileURLWithPath:filePath]]] intoStorage:self.storageManager.dsym linkTo:linkTo]; } -- (FBFuture *)install_dsym_stream:(FBProcessInput *)input linkToApp:(nullable NSString *)bundleID +- (FBFuture *)install_dsym_stream:(FBProcessInput *)input compression:(FBCompressionFormat)compression linkTo:(nullable FBDsymInstallLinkToBundle *)linkTo { - return [self installAndLinkDsym:[self dsymDirnameFromUnzipDir:[self.temporaryDirectory withArchiveExtractedFromStream:input compression:FBCompressionFormatGZIP]] intoStorage:self.storageManager.dsym linkToApp:bundleID]; + return [self installAndLinkDsym:[self dsymDirnameFromUnzipDir:[self.temporaryDirectory withArchiveExtractedFromStream:input compression:compression]] intoStorage:self.storageManager.dsym linkTo:linkTo]; } #pragma mark Public Methods @@ -135,7 +142,7 @@ - (instancetype)initWithTarget:(id)target storageManager:(FBIDBStor }]; } -- (FBFuture *> *> *)accessibility_info_at_point:(nullable NSValue *)value nestedFormat:(BOOL)nestedFormat +- (FBFuture *)accessibility_info_at_point:(nullable NSValue *)value nestedFormat:(BOOL)nestedFormat { return [[self accessibilityCommands] @@ -175,7 +182,7 @@ - (instancetype)initWithTarget:(id)target storageManager:(FBIDBStor }]; } -- (FBFuture *)approve:(NSSet *)services for_application:(NSString *)bundleID +- (FBFuture *)approve:(NSSet *)services for_application:(NSString *)bundleID { return [self.settingsCommands onQueue:self.target.workQueue fmap:^FBFuture *(id commands) { @@ -183,6 +190,14 @@ - (instancetype)initWithTarget:(id)target storageManager:(FBIDBStor }]; } +- (FBFuture *)revoke:(NSSet *)services for_application:(NSString *)bundleID +{ + return [self.settingsCommands + onQueue:self.target.workQueue fmap:^FBFuture *(id commands) { + return [commands revokeAccess:[NSSet setWithObject:bundleID] toServices:services]; + }]; +} + - (FBFuture *)approve_deeplink:(NSString *)scheme for_application:(NSString *)bundleID { return [self.settingsCommands @@ -191,6 +206,14 @@ - (instancetype)initWithTarget:(id)target storageManager:(FBIDBStor }]; } +- (FBFuture *)revoke_deeplink:(NSString *)scheme for_application:(NSString *)bundleID +{ + return [self.settingsCommands + onQueue:self.target.workQueue fmap:^FBFuture *(id commands) { + return [commands revokeAccess:[NSSet setWithObject:bundleID] toDeeplink:scheme]; + }]; +} + - (FBFuture *)open_url:(NSString *)url { return [self.lifecycleCommands @@ -253,11 +276,11 @@ - (instancetype)initWithTarget:(id)target storageManager:(FBIDBStor }]; } -- (FBFuture> *> *)list_test_bundles +- (FBFuture> *> *)list_test_bundles { return [FBFuture onQueue:self.target.workQueue resolve:^{ NSError *error; - NSSet> *testDescriptors = [self.storageManager.xctest listTestDescriptorsWithError:&error]; + NSArray> *testDescriptors = [self.storageManager.xctest listTestDescriptorsWithError:&error]; if (testDescriptors == nil) { return [FBFuture futureWithError:error]; } @@ -265,7 +288,8 @@ - (instancetype)initWithTarget:(id)target storageManager:(FBIDBStor }]; } -static const NSTimeInterval ListTestBundleTimeout = 60.0; +// Some Mac tests are big that dlopen might take long +static const NSTimeInterval ListTestBundleTimeout = 180.0; - (FBFuture *> *)list_tests_in_bundle:(NSString *)bundleID with_app:(NSString *)appPath { @@ -302,7 +326,7 @@ - (instancetype)initWithTarget:(id)target storageManager:(FBIDBStor - (FBFuture *)kill_application:(NSString *)bundleID { - return [self.target killApplicationWithBundleID:bundleID]; + return [[self.target killApplicationWithBundleID:bundleID] fallback:NSNull.null]; } - (FBFuture> *)launch_app:(FBApplicationLaunchConfiguration *)configuration @@ -354,10 +378,13 @@ - (instancetype)initWithTarget:(id)target storageManager:(FBIDBStor failFuture]; } - return [[self + return [[[self debugserver_prepare:bundleID] onQueue:self.target.workQueue fmap:^(FBBundleDescriptor *application) { - return [commands launchDebugServerForHostApplication:application port:self.ports.debugserverPort]; + return [commands launchDebugServerForHostApplication:application port:self.debugserverPort]; + }] + onQueue:self.target.workQueue doOnResolved:^(id debugServer) { + self.debugServer = debugServer; }]; } @@ -482,12 +509,12 @@ - (instancetype)initWithTarget:(id)target storageManager:(FBIDBStor }]; } -- (FBFuture *)set_preference:(NSString *)name value:(NSString *)value domain:(nullable NSString *)domain +- (FBFuture *)set_preference:(NSString *)name value:(NSString *)value type:(nullable NSString *)type domain:(nullable NSString *)domain { return [[self settingsCommands] onQueue:self.target.workQueue fmap:^(id commands) { - return [commands setPreference:name value:value domain:domain]; + return [commands setPreference:name value:value type:type domain:domain]; }]; } @@ -505,7 +532,7 @@ - (instancetype)initWithTarget:(id)target storageManager:(FBIDBStor return [[self settingsCommands] onQueue:self.target.workQueue fmap:^(id commands) { - return [commands setPreference:@"AppleLocale" value:identifier domain:nil]; + return [commands setPreference:@"AppleLocale" value:identifier type:nil domain:nil]; }]; } @@ -561,7 +588,7 @@ - (instancetype)initWithTarget:(id)target storageManager:(FBIDBStor onQueue:self.target.workQueue pop:^FBFuture *(id container) { NSMutableArray *> *futures = NSMutableArray.array; for (NSURL *originPath in paths) { - [futures addObject:[container copyFromHost:originPath toContainer:destinationPath]]; + [futures addObject:[container copyFromHost:originPath.path toContainer:destinationPath]]; } return [[FBFuture futureWithFutures:futures] mapReplace:NSNull.null]; }]; @@ -661,7 +688,7 @@ - (instancetype)initWithTarget:(id)target storageManager:(FBIDBStor describeFormat:@"Target doesn't conform to FBDapServerCommand protocol %@", commands] failFuture]; } - + return [commands launchDapServer:dapPath stdIn:stdIn stdOut:stdOut]; } @@ -706,9 +733,24 @@ - (instancetype)initWithTarget:(id)target storageManager:(FBIDBStor if ([containerType isEqualToString:FBFileContainerKindDiskImages]) { return [commands fileCommandsForDiskImages]; } + if ([containerType isEqualToString:FBFileContainerKindSymbols]) { + return [commands fileCommandsForSymbols]; + } if ([containerType isEqualToString:FBFileContainerKindAuxillary]) { return [commands fileCommandsForAuxillary]; } + if ([containerType isEqualToString:FBFileContainerKindXctest]) { + return [FBFutureContext futureContextWithResult:self.storageManager.xctest.asFileContainer]; + } + if ([containerType isEqualToString:FBFileContainerKindDylib]) { + return [FBFutureContext futureContextWithResult:self.storageManager.dylib.asFileContainer]; + } + if ([containerType isEqualToString:FBFileContainerKindDsym]) { + return [FBFutureContext futureContextWithResult:self.storageManager.dsym.asFileContainer]; + } + if ([containerType isEqualToString:FBFileContainerKindFramework]) { + return [FBFutureContext futureContextWithResult:self.storageManager.framework.asFileContainer]; + } if (containerType == nil || containerType.length == 0) { // The Default for no, or null container for back-compat. return [self.target isKindOfClass:FBDevice.class] ? [commands fileCommandsForMediaDirectory] : [commands fileCommandsForRootFilesystem]; @@ -841,19 +883,19 @@ - (instancetype)initWithTarget:(id)target storageManager:(FBIDBStor }]; } -- (FBFuture *)installXctest:(FBFutureContext *)extractedXctest +- (FBFuture *)installXctest:(FBFutureContext *)extractedXctest skipSigningBundles:(BOOL)skipSigningBundles { return [extractedXctest onQueue:self.target.workQueue pop:^(NSURL *extractionDirectory) { - return [self.storageManager.xctest saveBundleOrTestRunFromBaseDirectory:extractionDirectory]; + return [self.storageManager.xctest saveBundleOrTestRunFromBaseDirectory:extractionDirectory skipSigningBundles:skipSigningBundles]; }]; } -- (FBFuture *)installXctestFilePath:(FBFutureContext *)bundle +- (FBFuture *)installXctestFilePath:(FBFutureContext *)bundle skipSigningBundles:(BOOL)skipSigningBundles { return [bundle onQueue:self.target.workQueue pop:^(NSURL *xctestURL) { - return [self.storageManager.xctest saveBundleOrTestRun:xctestURL]; + return [self.storageManager.xctest saveBundleOrTestRun:xctestURL skipSigningBundles:skipSigningBundles]; }]; } @@ -880,18 +922,19 @@ - (instancetype)initWithTarget:(id)target storageManager:(FBIDBStor if (!subDirs) { return [FBFuture futureWithError:error]; } - // TODO: support cases when more than one dSYM is included in the archive if ([subDirs count] != 1) { - return [FBFuture futureWithError:[FBControlCoreError errorForDescription:[NSString stringWithFormat:@"Expected only one dSYM directory: found: %tu", [subDirs count]]]]; + // if more than one dSYM is found + // then we treat the parent dir as the dSYM directory + return [FBFuture futureWithResult:parentDir]; } return [FBFuture futureWithResult:subDirs[0]]; }]; } // Will install the dsym under standard dsym location -// if linkToApp app is passed: -// after installation it will create a symlink in the app bundle -- (FBFuture *)installAndLinkDsym:(FBFutureContext *)extractedFileContext intoStorage:(FBFileStorage *)storage linkToApp:(nullable NSString *)bundleID +// if linkTo is passed: +// after installation it will create a symlink in the bundle container +- (FBFuture *)installAndLinkDsym:(FBFutureContext *)extractedFileContext intoStorage:(FBFileStorage *)storage linkTo:(nullable FBDsymInstallLinkToBundle *)linkTo { return [extractedFileContext onQueue:self.target.workQueue pop:^(NSURL *extractionDir) { @@ -900,26 +943,38 @@ - (instancetype)initWithTarget:(id)target storageManager:(FBIDBStor if (!artifact) { return [FBFuture futureWithError:error]; } - if (!bundleID) { + + if (!linkTo) { return [FBFuture futureWithResult:artifact]; } - - return [[self.target installedApplicationWithBundleID:bundleID] - onQueue:self.target.workQueue fmap:^(FBInstalledApplication *linkToApp) { + + FBFuture *future = nil; + if (linkTo.bundle_type == FBDsymBundleTypeApp) { + future = [[self.target installedApplicationWithBundleID:linkTo.bundle_id] onQueue:self.target.workQueue fmap:^(FBInstalledApplication *linkToApp) { [self.logger logFormat:@"Going to create a symlink for app bundle: %@", linkToApp.bundle.name]; - NSURL *appPath = [[NSURL fileURLWithPath:linkToApp.bundle.path] URLByDeletingLastPathComponent]; - NSURL *appDsymURL = [appPath URLByAppendingPathComponent:artifact.path.lastPathComponent]; - // delete a simlink if already exists - // TODO: check if what we are deleting is a symlink - [NSFileManager.defaultManager removeItemAtURL:appDsymURL error:nil]; - [self.logger logFormat:@"Deleted a symlink for dsym if it already exists: %@", appDsymURL]; - NSError *createLinkError = nil; - if (![NSFileManager.defaultManager createSymbolicLinkAtURL:appDsymURL withDestinationURL:artifact.path error:&createLinkError]){ - return [FBFuture futureWithError:error]; - } - [self.logger logFormat:@"Created a symlink for dsym from: %@ to %@", appDsymURL, artifact.path]; - return [FBFuture futureWithResult:artifact]; - }]; + return [FBFuture futureWithResult:[NSURL fileURLWithPath:linkToApp.bundle.path]]; + }]; + } else { + id testDescriptor = [self.storageManager.xctest testDescriptorWithID:linkTo.bundle_id error:&error]; + [self.logger logFormat:@"Going to create a symlink for test bundle: %@", testDescriptor.name]; + future = [FBFuture futureWithResult:testDescriptor.url]; + } + + return [future onQueue:self.target.workQueue fmap:^(NSURL *bundlePath) { + NSURL *bundleUrl = [bundlePath URLByDeletingLastPathComponent]; + NSURL *dsymURL = [bundleUrl URLByAppendingPathComponent:artifact.path.lastPathComponent]; + // delete a simlink if already exists + // TODO: check if what we are deleting is a symlink + [NSFileManager.defaultManager removeItemAtURL:dsymURL error:nil]; + [self.logger logFormat:@"Deleted a symlink for dsym if it already exists: %@", dsymURL]; + NSError *createLinkError = nil; + if (![NSFileManager.defaultManager createSymbolicLinkAtURL:dsymURL withDestinationURL:artifact.path error:&createLinkError]){ + return [FBFuture futureWithError:error]; + } + [self.logger logFormat:@"Created a symlink for dsym from: %@ to %@", dsymURL, artifact.path]; + return [FBFuture futureWithResult:artifact]; + }]; + }]; } diff --git a/idb_companion/Reporting/FBIDBError.h b/CompanionLib/Reporting/FBIDBError.h similarity index 90% rename from idb_companion/Reporting/FBIDBError.h rename to CompanionLib/Reporting/FBIDBError.h index f159cdc90..326e83507 100644 --- a/idb_companion/Reporting/FBIDBError.h +++ b/CompanionLib/Reporting/FBIDBError.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/idb_companion/Reporting/FBIDBError.m b/CompanionLib/Reporting/FBIDBError.m similarity index 87% rename from idb_companion/Reporting/FBIDBError.m rename to CompanionLib/Reporting/FBIDBError.m index 1338b841b..b5edab6e3 100644 --- a/idb_companion/Reporting/FBIDBError.m +++ b/CompanionLib/Reporting/FBIDBError.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/idb_companion/Request/FBCodeCoverageRequest.h b/CompanionLib/Request/FBCodeCoverageRequest.h similarity index 70% rename from idb_companion/Request/FBCodeCoverageRequest.h rename to CompanionLib/Request/FBCodeCoverageRequest.h index 44c8b7c8a..408b96375 100644 --- a/idb_companion/Request/FBCodeCoverageRequest.h +++ b/CompanionLib/Request/FBCodeCoverageRequest.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -27,7 +27,12 @@ NS_ASSUME_NONNULL_BEGIN */ @property (nonatomic, assign, readonly) FBCodeCoverageFormat format; -- (instancetype)initWithCollect:(BOOL)collect format:(FBCodeCoverageFormat)format; +/** + Determines whether should enable continuous coverage collection + */ +@property (nonatomic, assign, readonly) BOOL shouldEnableContinuousCoverageCollection; + +- (instancetype)initWithCollect:(BOOL)collect format:(FBCodeCoverageFormat)format enableContinuousCoverageCollection:(BOOL)enableContinuousCoverageCollection; @end diff --git a/idb_companion/Request/FBCodeCoverageRequest.m b/CompanionLib/Request/FBCodeCoverageRequest.m similarity index 63% rename from idb_companion/Request/FBCodeCoverageRequest.m rename to CompanionLib/Request/FBCodeCoverageRequest.m index 786b46dc4..1eca9f442 100644 --- a/idb_companion/Request/FBCodeCoverageRequest.m +++ b/CompanionLib/Request/FBCodeCoverageRequest.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -9,16 +9,16 @@ @implementation FBCodeCoverageRequest -- (instancetype)initWithCollect:(BOOL)collect format:(FBCodeCoverageFormat)format +- (instancetype)initWithCollect:(BOOL)collect format:(FBCodeCoverageFormat)format enableContinuousCoverageCollection:(BOOL)enableContinuousCoverageCollection { self = [super init]; if (!self) { return nil; } - + _collect = collect; _format = format; - + _shouldEnableContinuousCoverageCollection = enableContinuousCoverageCollection; return self; } diff --git a/CompanionLib/Request/FBDsymInstallLinkToBundle.h b/CompanionLib/Request/FBDsymInstallLinkToBundle.h new file mode 100644 index 000000000..31ebd5a1e --- /dev/null +++ b/CompanionLib/Request/FBDsymInstallLinkToBundle.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import + +#import + +NS_ASSUME_NONNULL_BEGIN + +typedef NS_ENUM(NSInteger, FBDsymBundleType) { + FBDsymBundleTypeXCTest, + FBDsymBundleTypeApp, +}; + +/** + Describes bundle needs to be linked with Dsym + */ +@interface FBDsymInstallLinkToBundle : NSObject + +/** + ID of the bundle the dsym needs to link + */ +@property (nonatomic, copy, readonly) NSString *bundle_id; + +/** + Type of bundle +*/ +@property (nonatomic, assign, readonly) FBDsymBundleType bundle_type; + +- (instancetype)initWith:(NSString *)bundle_id bundle_type:(FBDsymBundleType)bundle_type; + +@end + +NS_ASSUME_NONNULL_END diff --git a/CompanionLib/Request/FBDsymInstallLinkToBundle.m b/CompanionLib/Request/FBDsymInstallLinkToBundle.m new file mode 100644 index 000000000..62566648f --- /dev/null +++ b/CompanionLib/Request/FBDsymInstallLinkToBundle.m @@ -0,0 +1,25 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import "FBDsymInstallLinkToBundle.h" + +@implementation FBDsymInstallLinkToBundle + +- (instancetype)initWith:(NSString *)bundle_id bundle_type:(FBDsymBundleType)bundle_type +{ + self = [super init]; + if (!self) { + return nil; + } + + _bundle_id = bundle_id; + _bundle_type = bundle_type; + + return self; +} + +@end diff --git a/idb_companion/Request/FBXCTestRunRequest.h b/CompanionLib/Request/FBXCTestRunRequest.h similarity index 72% rename from idb_companion/Request/FBXCTestRunRequest.h rename to CompanionLib/Request/FBXCTestRunRequest.h index c9fca1ec7..f387c2da5 100644 --- a/idb_companion/Request/FBXCTestRunRequest.h +++ b/CompanionLib/Request/FBXCTestRunRequest.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -37,13 +37,13 @@ NS_ASSUME_NONNULL_BEGIN @param waitForDebugger a boolean describing whether the tests should stop after Run and wait for a debugger to be attached. @return an FBXCTestRunRequest instance. */ -+ (instancetype)logicTestWithTestBundleID:(NSString *)testBundleID environment:(NSDictionary *)environment arguments:(NSArray *)arguments testsToRun:(NSSet *)testsToRun testsToSkip:(NSSet *)testsToSkip testTimeout:(NSNumber *)testTimeout reportActivities:(BOOL)reportActivities reportAttachments:(BOOL)reportAttachments coverageRequest:(FBCodeCoverageRequest *)coverageRequest collectLogs:(BOOL)collectLogs waitForDebugger:(BOOL)waitForDebugger; ++ (instancetype)logicTestWithTestBundleID:(NSString *)testBundleID environment:(NSDictionary *)environment arguments:(NSArray *)arguments testsToRun:(nullable NSSet *)testsToRun testsToSkip:(NSSet *)testsToSkip testTimeout:(NSNumber *)testTimeout reportActivities:(BOOL)reportActivities reportAttachments:(BOOL)reportAttachments coverageRequest:(FBCodeCoverageRequest *)coverageRequest collectLogs:(BOOL)collectLogs waitForDebugger:(BOOL)waitForDebugger collectResultBundle:(BOOL)collectResultBundle; /** The Initializer for App Tests. @param testBundleID the bundle id of the test to run. - @param appBundleID the bundle id of the application to inject the test bundle into. + @param testHostAppBundleID the bundle id of the application to inject the test bundle into. @param environment environment for the application test process. @param arguments arguments for the application test process. @param testsToRun the tests to run. @@ -53,13 +53,12 @@ The Initializer for App Tests. @param coverageRequest information about llvm code coverage collection @return an FBXCTestRunRequest instance. */ -+ (instancetype)applicationTestWithTestBundleID:(NSString *)testBundleID appBundleID:(NSString *)appBundleID environment:(NSDictionary *)environment arguments:(NSArray *)arguments testsToRun:(NSSet *)testsToRun testsToSkip:(NSSet *)testsToSkip testTimeout:(NSNumber *)testTimeout reportActivities:(BOOL)reportActivities reportAttachments:(BOOL)reportAttachments coverageRequest:(FBCodeCoverageRequest *)coverageRequest collectLogs:(BOOL)collectLogs waitForDebugger:(BOOL)waitForDebugger; ++ (instancetype)applicationTestWithTestBundleID:(NSString *)testBundleID testHostAppBundleID:(NSString *)testHostAppBundleID environment:(NSDictionary *)environment arguments:(NSArray *)arguments testsToRun:(nullable NSSet *)testsToRun testsToSkip:(NSSet *)testsToSkip testTimeout:(NSNumber *)testTimeout reportActivities:(BOOL)reportActivities reportAttachments:(BOOL)reportAttachments coverageRequest:(FBCodeCoverageRequest *)coverageRequest collectLogs:(BOOL)collectLogs waitForDebugger:(BOOL)waitForDebugger collectResultBundle:(BOOL)collectResultBundle; /** The Initializer for UI Tests. @param testBundleID the bundle id of the test to run. - @param appBundleID the bundle id of the application to automatie. @param testHostAppBundleID the bundle id of the application hosting the test bundle. @param environment environment for the logic test process. @param arguments arguments for the logic test process. @@ -70,7 +69,7 @@ The Initializer for UI Tests. @param coverageRequest information about llvm code coverage collection @return an FBXCTestRunRequest instance. */ -+ (instancetype)uiTestWithTestBundleID:(NSString *)testBundleID appBundleID:(NSString *)appBundleID testHostAppBundleID:(NSString *)testHostAppBundleID environment:(NSDictionary *)environment arguments:(NSArray *)arguments testsToRun:(NSSet *)testsToRun testsToSkip:(NSSet *)testsToSkip testTimeout:(NSNumber *)testTimeout reportActivities:(BOOL)reportActivities reportAttachments:(BOOL)reportAttachments coverageRequest:(FBCodeCoverageRequest *)coverageRequest collectLogs:(BOOL)collectLogs; ++ (instancetype)uiTestWithTestBundleID:(NSString *)testBundleID testHostAppBundleID:(NSString *)testHostAppBundleID testTargetAppBundleID:(NSString *)testTargetAppBundleID environment:(NSDictionary *)environment arguments:(NSArray *)arguments testsToRun:(nullable NSSet *)testsToRun testsToSkip:(NSSet *)testsToSkip testTimeout:(NSNumber *)testTimeout reportActivities:(BOOL)reportActivities reportAttachments:(BOOL)reportAttachments coverageRequest:(FBCodeCoverageRequest *)coverageRequest collectLogs:(BOOL)collectLogs collectResultBundle:(BOOL)collectResultBundle; #pragma mark Properties @@ -90,14 +89,14 @@ The Initializer for UI Tests. @property (nonatomic, copy, readonly) NSString *testBundleID; /** - The Bundle ID of the Application to test in, if relevant. + The Bundle ID of the Test Host, if relevant. */ -@property (nonatomic, copy, nullable, readonly) NSString *appBundleID; +@property (nonatomic, copy, nullable, readonly) NSString *testHostAppBundleID; /** - The Bundle ID of the Test Host, if relevant. + The Bundle ID of the Test Target (a.k.a. App Under Test), if relevant. */ -@property (nonatomic, copy, nullable, readonly) NSString *testHostAppBundleID; +@property (nonatomic, copy, nullable, readonly) NSString *testTargetAppBundleID; /** The environment variables for the application, if relevant @@ -149,6 +148,11 @@ The Initializer for UI Tests. */ @property (nonatomic, assign, readonly) BOOL waitForDebugger; +/** + If set tests' result bundle will be collected + */ +@property (nonatomic, assign, readonly) BOOL collectResultBundle; + /** Starts the test operation. diff --git a/idb_companion/Request/FBXCTestRunRequest.m b/CompanionLib/Request/FBXCTestRunRequest.m similarity index 73% rename from idb_companion/Request/FBXCTestRunRequest.m rename to CompanionLib/Request/FBXCTestRunRequest.m index 64382d6e8..ab0218e77 100644 --- a/idb_companion/Request/FBXCTestRunRequest.m +++ b/CompanionLib/Request/FBXCTestRunRequest.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -49,7 +49,10 @@ - (BOOL)isUITest NSURL *dir = [temporaryDirectory ephemeralTemporaryDirectory]; NSString *coverageDirName =[NSString stringWithFormat:@"coverage_%@", NSUUID.UUID.UUIDString]; NSString *coverageDirPath = [dir.path stringByAppendingPathComponent:coverageDirName]; - coverageConfig = [[FBCodeCoverageConfiguration alloc] initWithDirectory:coverageDirPath format:self.coverageRequest.format]; + if (![NSFileManager.defaultManager createDirectoryAtPath:coverageDirPath withIntermediateDirectories:YES attributes:nil error:&error]) { + return [FBFuture futureWithError:error]; + } + coverageConfig = [[FBCodeCoverageConfiguration alloc] initWithDirectory:coverageDirPath format:self.coverageRequest.format enableContinuousCoverageCollection:self.coverageRequest.shouldEnableContinuousCoverageCollection]; } NSString *testFilter = nil; @@ -78,7 +81,8 @@ - (BOOL)isUITest mirroring:FBLogicTestMirrorFileLogs coverageConfiguration:coverageConfig binaryPath:testDescriptor.testBundle.binary.path - logDirectoryPath:logDirectoryPath]; + logDirectoryPath:logDirectoryPath + architectures:testDescriptor.architectures]; return [self startTestExecution:configuration target:target reporter:reporter logger:logger]; } @@ -96,7 +100,8 @@ - (BOOL)isUITest coverageConfiguration:configuration.coverageConfiguration logDirectoryPath:configuration.logDirectoryPath binariesPaths:@[configuration.binaryPath] - reportAttachments:self.reportAttachments]; + reportAttachments:self.reportAttachments + reportResultBundle:self.collectResultBundle]; FBIDBTestOperation *operation = [[FBIDBTestOperation alloc] initWithConfiguration:configuration reporterConfiguration:reporterConfiguration @@ -135,11 +140,11 @@ - (BOOL)isUITest }] onQueue:target.workQueue fmap:^ FBFuture * (FBIDBAppHostedTestConfiguration *appHostedTestConfig) { [logger logFormat:@"Obtained app-hosted test configuration %@", appHostedTestConfig]; - return [FBXCTestRunRequest_AppTest startTestExecution:appHostedTestConfig reportAttachments:self.reportAttachments target:target reporter:reporter logger:logger]; + return [FBXCTestRunRequest_AppTest startTestExecution:appHostedTestConfig reportAttachments:self.reportAttachments target:target reporter:reporter logger:logger reportResultBundle:self.collectResultBundle]; }]; } -+ (FBFuture *)startTestExecution:(FBIDBAppHostedTestConfiguration *)configuration reportAttachments:(BOOL)reportAttachments target:(id)target reporter:(id)reporter logger:(id)logger ++ (FBFuture *)startTestExecution:(FBIDBAppHostedTestConfiguration *)configuration reportAttachments:(BOOL)reportAttachments target:(id)target reporter:(id)reporter logger:(id)logger reportResultBundle:(BOOL)reportResultBundle { FBTestLaunchConfiguration *testLaunchConfiguration = configuration.testLaunchConfiguration; FBCodeCoverageConfiguration *coverageConfiguration = configuration.coverageConfiguration; @@ -164,7 +169,8 @@ - (BOOL)isUITest coverageConfiguration:coverageConfiguration logDirectoryPath:testLaunchConfiguration.logDirectoryPath binariesPaths:binariesPaths - reportAttachments:reportAttachments]; + reportAttachments:reportAttachments + reportResultBundle:reportResultBundle]; return [FBFuture futureWithResult:[[FBIDBTestOperation alloc] initWithConfiguration:testLaunchConfiguration reporterConfiguration:reporterConfiguration @@ -203,33 +209,33 @@ - (BOOL)isUITest @implementation FBXCTestRunRequest @synthesize testBundleID = _testBundleID; -@synthesize appBundleID = _appBundleID; @synthesize testHostAppBundleID = _testHostAppBundleID; @synthesize environment = _environment; @synthesize arguments = _arguments; @synthesize testsToRun = _testsToRun; @synthesize testsToSkip = _testsToSkip; @synthesize testTimeout = _testTimeout; +@synthesize collectResultBundle = _collectResultBundle; #pragma mark Initializers -+ (instancetype)logicTestWithTestBundleID:(NSString *)testBundleID environment:(NSDictionary *)environment arguments:(NSArray *)arguments testsToRun:(NSSet *)testsToRun testsToSkip:(NSSet *)testsToSkip testTimeout:(NSNumber *)testTimeout reportActivities:(BOOL)reportActivities reportAttachments:(BOOL)reportAttachments coverageRequest:(FBCodeCoverageRequest *)coverageRequest collectLogs:(BOOL)collectLogs waitForDebugger:(BOOL)waitForDebugger ++ (instancetype)logicTestWithTestBundleID:(NSString *)testBundleID environment:(NSDictionary *)environment arguments:(NSArray *)arguments testsToRun:(NSSet *)testsToRun testsToSkip:(NSSet *)testsToSkip testTimeout:(NSNumber *)testTimeout reportActivities:(BOOL)reportActivities reportAttachments:(BOOL)reportAttachments coverageRequest:(FBCodeCoverageRequest *)coverageRequest collectLogs:(BOOL)collectLogs waitForDebugger:(BOOL)waitForDebugger collectResultBundle:(BOOL)collectResultBundle { - return [[FBXCTestRunRequest_LogicTest alloc] initWithTestBundleID:testBundleID appBundleID:nil testHostAppBundleID:nil environment:environment arguments:arguments testsToRun:testsToRun testsToSkip:testsToSkip testTimeout:testTimeout reportActivities:reportActivities reportAttachments:reportAttachments coverageRequest:coverageRequest collectLogs:collectLogs waitForDebugger:waitForDebugger]; + return [[FBXCTestRunRequest_LogicTest alloc] initWithTestBundleID:testBundleID testHostAppBundleID:nil testTargetAppBundleID:nil environment:environment arguments:arguments testsToRun:testsToRun testsToSkip:testsToSkip testTimeout:testTimeout reportActivities:reportActivities reportAttachments:reportAttachments coverageRequest:coverageRequest collectLogs:collectLogs waitForDebugger:waitForDebugger collectResultBundle:collectResultBundle]; } -+ (instancetype)applicationTestWithTestBundleID:(NSString *)testBundleID appBundleID:(NSString *)appBundleID environment:(NSDictionary *)environment arguments:(NSArray *)arguments testsToRun:(NSSet *)testsToRun testsToSkip:(NSSet *)testsToSkip testTimeout:(NSNumber *)testTimeout reportActivities:(BOOL)reportActivities reportAttachments:(BOOL)reportAttachments coverageRequest:(FBCodeCoverageRequest *)coverageRequest collectLogs:(BOOL)collectLogs waitForDebugger:(BOOL)waitForDebugger ++ (instancetype)applicationTestWithTestBundleID:(NSString *)testBundleID testHostAppBundleID:(NSString *)testHostAppBundleID environment:(NSDictionary *)environment arguments:(NSArray *)arguments testsToRun:(NSSet *)testsToRun testsToSkip:(NSSet *)testsToSkip testTimeout:(NSNumber *)testTimeout reportActivities:(BOOL)reportActivities reportAttachments:(BOOL)reportAttachments coverageRequest:(FBCodeCoverageRequest *)coverageRequest collectLogs:(BOOL)collectLogs waitForDebugger:(BOOL)waitForDebugger collectResultBundle:(BOOL)collectResultBundle { - return [[FBXCTestRunRequest_AppTest alloc] initWithTestBundleID:testBundleID appBundleID:appBundleID testHostAppBundleID:nil environment:environment arguments:arguments testsToRun:testsToRun testsToSkip:testsToSkip testTimeout:testTimeout reportActivities:reportActivities reportAttachments:reportAttachments coverageRequest:coverageRequest collectLogs:collectLogs waitForDebugger:waitForDebugger]; + return [[FBXCTestRunRequest_AppTest alloc] initWithTestBundleID:testBundleID testHostAppBundleID:testHostAppBundleID testTargetAppBundleID:nil environment:environment arguments:arguments testsToRun:testsToRun testsToSkip:testsToSkip testTimeout:testTimeout reportActivities:reportActivities reportAttachments:reportAttachments coverageRequest:coverageRequest collectLogs:collectLogs waitForDebugger:waitForDebugger collectResultBundle:collectResultBundle]; } -+ (instancetype)uiTestWithTestBundleID:(NSString *)testBundleID appBundleID:(NSString *)appBundleID testHostAppBundleID:(NSString *)testHostAppBundleID environment:(NSDictionary *)environment arguments:(NSArray *)arguments testsToRun:(NSSet *)testsToRun testsToSkip:(NSSet *)testsToSkip testTimeout:(NSNumber *)testTimeout reportActivities:(BOOL)reportActivities reportAttachments:(BOOL)reportAttachments coverageRequest:(FBCodeCoverageRequest *)coverageRequest collectLogs:(BOOL)collectLogs ++ (instancetype)uiTestWithTestBundleID:(NSString *)testBundleID testHostAppBundleID:(NSString *)testHostAppBundleID testTargetAppBundleID:(NSString *)testTargetAppBundleID environment:(NSDictionary *)environment arguments:(NSArray *)arguments testsToRun:(NSSet *)testsToRun testsToSkip:(NSSet *)testsToSkip testTimeout:(NSNumber *)testTimeout reportActivities:(BOOL)reportActivities reportAttachments:(BOOL)reportAttachments coverageRequest:(FBCodeCoverageRequest *)coverageRequest collectLogs:(BOOL)collectLogs collectResultBundle:(BOOL)collectResultBundle { - return [[FBXCTestRunRequest_UITest alloc] initWithTestBundleID:testBundleID appBundleID:appBundleID testHostAppBundleID:testHostAppBundleID environment:environment arguments:arguments testsToRun:testsToRun testsToSkip:testsToSkip testTimeout:testTimeout reportActivities:reportActivities reportAttachments:reportAttachments coverageRequest:coverageRequest collectLogs:collectLogs waitForDebugger:NO]; + return [[FBXCTestRunRequest_UITest alloc] initWithTestBundleID:testBundleID testHostAppBundleID:testHostAppBundleID testTargetAppBundleID:testTargetAppBundleID environment:environment arguments:arguments testsToRun:testsToRun testsToSkip:testsToSkip testTimeout:testTimeout reportActivities:reportActivities reportAttachments:reportAttachments coverageRequest:coverageRequest collectLogs:collectLogs waitForDebugger:NO collectResultBundle:collectResultBundle]; } -- (instancetype)initWithTestBundleID:(NSString *)testBundleID appBundleID:(NSString *)appBundleID testHostAppBundleID:(NSString *)testHostAppBundleID environment:(NSDictionary *)environment arguments:(NSArray *)arguments testsToRun:(NSSet *)testsToRun testsToSkip:(NSSet *)testsToSkip testTimeout:(NSNumber *)testTimeout reportActivities:(BOOL)reportActivities reportAttachments:(BOOL)reportAttachments coverageRequest:(FBCodeCoverageRequest *)coverageRequest collectLogs:(BOOL)collectLogs waitForDebugger:(BOOL)waitForDebugger +- (instancetype)initWithTestBundleID:(NSString *)testBundleID testHostAppBundleID:(NSString *)testHostAppBundleID testTargetAppBundleID:(NSString *)testTargetAppBundleID environment:(NSDictionary *)environment arguments:(NSArray *)arguments testsToRun:(NSSet *)testsToRun testsToSkip:(NSSet *)testsToSkip testTimeout:(NSNumber *)testTimeout reportActivities:(BOOL)reportActivities reportAttachments:(BOOL)reportAttachments coverageRequest:(FBCodeCoverageRequest *)coverageRequest collectLogs:(BOOL)collectLogs waitForDebugger:(BOOL)waitForDebugger collectResultBundle:(BOOL)collectResultBundle { self = [super init]; if (!self) { @@ -237,8 +243,8 @@ - (instancetype)initWithTestBundleID:(NSString *)testBundleID appBundleID:(NSStr } _testBundleID = testBundleID; - _appBundleID = appBundleID; _testHostAppBundleID = testHostAppBundleID; + _testTargetAppBundleID = testTargetAppBundleID; _environment = environment; _arguments = arguments; _testsToRun = testsToRun; @@ -249,6 +255,7 @@ - (instancetype)initWithTestBundleID:(NSString *)testBundleID appBundleID:(NSStr _coverageRequest = coverageRequest; _collectLogs = collectLogs; _waitForDebugger = waitForDebugger; + _collectResultBundle = collectResultBundle; return self; } @@ -299,7 +306,3 @@ - (BOOL)isUITest } @end - - - - diff --git a/idb_companion/Utility/FBDataDownloadInput.h b/CompanionLib/Utility/FBDataDownloadInput.h similarity index 93% rename from idb_companion/Utility/FBDataDownloadInput.h rename to CompanionLib/Utility/FBDataDownloadInput.h index 5cfde25be..7de613bcc 100644 --- a/idb_companion/Utility/FBDataDownloadInput.h +++ b/CompanionLib/Utility/FBDataDownloadInput.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/idb_companion/Utility/FBDataDownloadInput.m b/CompanionLib/Utility/FBDataDownloadInput.m similarity index 96% rename from idb_companion/Utility/FBDataDownloadInput.m rename to CompanionLib/Utility/FBDataDownloadInput.m index 8fb6b60fa..3567725c5 100644 --- a/idb_companion/Utility/FBDataDownloadInput.m +++ b/CompanionLib/Utility/FBDataDownloadInput.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/idb_companion/Utility/FBIDBLogger.h b/CompanionLib/Utility/FBIDBLogger.h similarity index 93% rename from idb_companion/Utility/FBIDBLogger.h rename to CompanionLib/Utility/FBIDBLogger.h index a375a6279..00575cfe3 100644 --- a/idb_companion/Utility/FBIDBLogger.h +++ b/CompanionLib/Utility/FBIDBLogger.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/idb_companion/Utility/FBIDBLogger.m b/CompanionLib/Utility/FBIDBLogger.m similarity index 91% rename from idb_companion/Utility/FBIDBLogger.m rename to CompanionLib/Utility/FBIDBLogger.m index f6d7bbdc1..b70539aaa 100644 --- a/idb_companion/Utility/FBIDBLogger.m +++ b/CompanionLib/Utility/FBIDBLogger.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -90,7 +90,7 @@ + (dispatch_queue_t)loggerQueue + (instancetype)loggerWithUserDefaults:(NSUserDefaults *)userDefaults { BOOL debugLogging = [[userDefaults stringForKey:@"-log-level"].lowercaseString isEqualToString:@"info"] ? NO : YES; - id systemLogger = [FBControlCoreLogger systemLoggerWritingToStderr:YES withDebugLogging:debugLogging]; + id systemLogger = [FBControlCoreLoggerFactory systemLoggerWritingToStderr:YES withDebugLogging:debugLogging]; NSMutableArray> *loggers = [NSMutableArray arrayWithObject:systemLogger]; NSError *error; @@ -108,7 +108,7 @@ + (instancetype)loggerWithUserDefaults:(NSUserDefaults *)userDefaults exit(1); } - [loggers addObject:[FBControlCoreLogger loggerToFileDescriptor:fileDescriptor closeOnEndOfFile:YES]]; + [loggers addObject:[FBControlCoreLoggerFactory loggerToFileDescriptor:fileDescriptor closeOnEndOfFile:YES]]; } FBIDBLogger *logger = [[[FBIDBLogger alloc] initWithLoggers:loggers] withDateFormatEnabled:YES]; FBControlCoreGlobalConfiguration.defaultLogger = logger; @@ -145,7 +145,7 @@ - (instancetype)initWithLoggers:(NSArray> *)loggers { dispatch_queue_t queue = FBIDBLogger.loggerQueue; return [FBFuture onQueue:queue resolveValue:^(NSError **_) { - id logger = [FBControlCoreLogger loggerToConsumer:consumer]; + id logger = [FBControlCoreLoggerFactory loggerToConsumer:consumer]; id operation = [[FBIDBLogger_Operation alloc] initWithConsumer:consumer logger:logger queue:queue]; AddGlobalLogger(logger); return operation; diff --git a/idb_companion/Utility/FBIDBStorageManager.h b/CompanionLib/Utility/FBIDBStorageManager.h similarity index 91% rename from idb_companion/Utility/FBIDBStorageManager.h rename to CompanionLib/Utility/FBIDBStorageManager.h index acb9a4b36..314e8b296 100644 --- a/idb_companion/Utility/FBIDBStorageManager.h +++ b/CompanionLib/Utility/FBIDBStorageManager.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -7,7 +7,6 @@ #import #import -#import "FBXCTestDescriptor.h" NS_ASSUME_NONNULL_BEGIN @@ -17,6 +16,9 @@ extern NSString *const IdbDylibsFolder; extern NSString *const IdbDsymsFolder; extern NSString *const IdbFrameworksFolder; +@protocol FBControlCoreLogger; +@protocol FBXCTestDescriptor; + /** A wrapper around an installed artifact */ @@ -80,6 +82,13 @@ extern NSString *const IdbFrameworksFolder; */ @property (nonatomic, copy, readonly) NSDictionary *replacementMapping; +/** + Exposes the receiver as an FBFileContainer instance. + + @return a FBFileContainer instance. + */ +- (id)asFileContainer; + /** Cleans all storage @@ -177,24 +186,25 @@ extern NSString *const IdbFrameworksFolder; @param baseDirectory the directory containing the test bundle. @return the bundle id of the installed test, or nil if failed */ -- (FBFuture *)saveBundleOrTestRunFromBaseDirectory:(NSURL *)baseDirectory; +- (FBFuture *)saveBundleOrTestRunFromBaseDirectory:(NSURL *)baseDirectory skipSigningBundles:(BOOL)skipSigningBundles; /** Stores a test bundle, based on the file path of the actual test bundle. This is useful when the test bundle is from an existing and local file path, instead of passed in an archive. @param filePath the file path of the bundle. + @param skipSigningBundles pass true to skip signing xctest bundles. @return the bundle id of the installed test, or nil if failed */ -- (FBFuture *)saveBundleOrTestRun:(NSURL *)filePath; +- (FBFuture *)saveBundleOrTestRun:(NSURL *)filePath skipSigningBundles:(BOOL)skipSigningBundles; /** Get descriptors for all installed test bundles and xctestrun files. @param error Set if getting this bundle failed - @return Set of FBXCTestDescriptors of all installed test bundles and xctestrun files + @return List of FBXCTestDescriptors of all installed test bundles and xctestrun files */ -- (nullable NSSet> *)listTestDescriptorsWithError:(NSError **)error; +- (nullable NSArray> *)listTestDescriptorsWithError:(NSError **)error; /** Get test descriptor by bundle id. @@ -260,7 +270,7 @@ extern NSString *const IdbFrameworksFolder; /** Interpolate path replacements - + @return a dictionary with the replacements defined */ - (NSDictionary *)replacementMapping; diff --git a/idb_companion/Utility/FBIDBStorageManager.m b/CompanionLib/Utility/FBIDBStorageManager.m similarity index 90% rename from idb_companion/Utility/FBIDBStorageManager.m rename to CompanionLib/Utility/FBIDBStorageManager.m index 07aa818b2..0c369f59d 100644 --- a/idb_companion/Utility/FBIDBStorageManager.m +++ b/CompanionLib/Utility/FBIDBStorageManager.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -54,25 +54,32 @@ - (instancetype)initWithTarget:(id)target basePath:(NSURL *)basePat return self; } -#pragma mark Properties +#pragma mark Methods -- (NSDictionary *)replacementMapping +- (BOOL)clean:(NSError **)error { - NSMutableDictionary *replacementMapping = NSMutableDictionary.dictionary; for (NSURL *url in [NSFileManager.defaultManager contentsOfDirectoryAtURL:self.basePath includingPropertiesForKeys:nil options:0 error:nil]) { - replacementMapping[url.lastPathComponent] = url.path; + if (![NSFileManager.defaultManager removeItemAtPath:url.path error:error]) { + return NO; + } } - return replacementMapping; + return YES; } --(BOOL)clean:(NSError **)error +- (id)asFileContainer { + return [FBFileContainer fileContainerForBasePath:self.basePath.path]; +} + +#pragma mark Properties + +- (NSDictionary *)replacementMapping +{ + NSMutableDictionary *replacementMapping = NSMutableDictionary.dictionary; for (NSURL *url in [NSFileManager.defaultManager contentsOfDirectoryAtURL:self.basePath includingPropertiesForKeys:nil options:0 error:nil]) { - if (![NSFileManager.defaultManager removeItemAtPath:url.path error:error]) { - return NO; - } + replacementMapping[url.lastPathComponent] = url.path; } - return YES; + return replacementMapping; } @end @@ -129,23 +136,29 @@ - (instancetype)initWithTarget:(id)target basePath:(NSURL *)basePat - (BOOL)checkArchitecture:(FBBundleDescriptor *)bundle error:(NSError **)error { - NSSet *bundleArchs = bundle.binary.architectures; - NSString *targetArch = self.target.architecture; - - const BOOL containsExactArch = [bundleArchs containsObject:targetArch]; + NSSet *binaryArchitectures = bundle.binary.architectures; + NSArray *targetArchs = self.target.architectures; + NSSet *supportedArchitectures = [FBiOSTargetConfiguration baseArchsToCompatibleArch:targetArchs]; + + const BOOL containsExactArch = [binaryArchitectures intersectsSet:supportedArchitectures]; // arm64 binaries are acceptable on arm64e devices, but arm64e is not yet available - const BOOL arm64eEquivalent = [targetArch isEqualToString:@"arm64e"] && [bundleArchs containsObject:@"arm64"]; - + const BOOL arm64eEquivalent = [targetArchs containsObject:@"arm64e"] && [binaryArchitectures containsObject:@"arm64"]; + if (!(containsExactArch || arm64eEquivalent)) { return [[FBIDBError - describeFormat:@"Targets architecture %@ not in the bundles supported architectures: %@", targetArch, bundleArchs.allObjects] - failBool:error]; + describeFormat:@"The supported architectures of the target %@ do not intersect with any architectures in the bundle: %@", [FBCollectionInformation oneLineDescriptionFromArray:supportedArchitectures.allObjects], [FBCollectionInformation oneLineDescriptionFromArray:binaryArchitectures.allObjects]] + failBool:error]; } - + return YES; } - (FBFuture *)saveBundle:(FBBundleDescriptor *)bundle +{ + return [self saveBundle:bundle skipSigningBundles:NO]; +} + +- (FBFuture *)saveBundle:(FBBundleDescriptor *)bundle skipSigningBundles:(BOOL)skipSigningBundles { // Check that the bundle matches the architecture of the target. NSError *error = nil; @@ -162,14 +175,13 @@ - (BOOL)checkArchitecture:(FBBundleDescriptor *)bundle error:(NSError **)error // Copy over bundle NSURL *sourceBundlePath = [NSURL fileURLWithPath:bundle.path]; NSURL *destinationBundlePath = [storageDirectory URLByAppendingPathComponent:sourceBundlePath.lastPathComponent]; - [self.logger logFormat:@"Persisting %@ to %@", bundle.identifier, destinationBundlePath]; - if (![NSFileManager.defaultManager copyItemAtURL:sourceBundlePath toURL:destinationBundlePath error:&error]) { + [self.logger logFormat:@"Symlink %@ to %@", bundle.identifier, destinationBundlePath]; + if (![NSFileManager.defaultManager createSymbolicLinkAtURL:destinationBundlePath withDestinationURL:sourceBundlePath error:&error]) { return [FBFuture futureWithError:error]; } - [self.logger logFormat:@"Persisted %@", bundle.identifier]; FBInstalledArtifact *artifact = [[FBInstalledArtifact alloc] initWithName:bundle.identifier uuid:bundle.binary.uuid path:destinationBundlePath]; - if (!self.relocateLibraries || ![self.target requiresBundlesToBeSigned]) { + if (!self.relocateLibraries || ![self.target requiresBundlesToBeSigned] || skipSigningBundles) { return [FBFuture futureWithResult:artifact]; } bundle = [FBBundleDescriptor bundleFromPath:destinationBundlePath.path error:&error]; @@ -250,7 +262,7 @@ @implementation FBXCTestBundleStorage #pragma mark Public -- (FBFuture *)saveBundleOrTestRunFromBaseDirectory:(NSURL *)baseDirectory +- (FBFuture *)saveBundleOrTestRunFromBaseDirectory:(NSURL *)baseDirectory skipSigningBundles:(BOOL)skipSigningBundles { // Find .xctest or .xctestrun in directory. NSError *error = nil; @@ -279,7 +291,7 @@ @implementation FBXCTestBundleStorage } if (xctestBundleURL) { - return [self saveTestBundle:xctestBundleURL]; + return [self saveTestBundle:xctestBundleURL skipSigningBundles:skipSigningBundles]; } if (xctestrunURL) { return [self saveTestRun:xctestrunURL]; @@ -289,11 +301,11 @@ @implementation FBXCTestBundleStorage failFuture]; } -- (FBFuture *)saveBundleOrTestRun:(NSURL *)filePath +- (FBFuture *)saveBundleOrTestRun:(NSURL *)filePath skipSigningBundles:(BOOL)skipSigningBundles { // save .xctest or .xctestrun if ([filePath.pathExtension isEqualToString:XctestExtension]) { - return [self saveTestBundle:filePath]; + return [self saveTestBundle:filePath skipSigningBundles:skipSigningBundles]; } if ([filePath.pathExtension isEqualToString:XctestRunExtension]) { return [self saveTestRun:filePath]; @@ -303,9 +315,9 @@ @implementation FBXCTestBundleStorage failFuture]; } -- (NSSet> *)listTestDescriptorsWithError:(NSError **)error +- (NSArray> *)listTestDescriptorsWithError:(NSError **)error { - NSMutableSet> *testDescriptors = [[NSMutableSet alloc] init]; + NSMutableArray> *testDescriptors = [[NSMutableArray alloc] init]; // Get xctest bundles NSSet *testURLS = [self listTestBundlesWithError:error]; @@ -346,12 +358,12 @@ @implementation FBXCTestBundleStorage [testDescriptors addObjectsFromArray:descriptors]; } - return testDescriptors; + return [NSArray arrayWithArray:testDescriptors]; } - (id)testDescriptorWithID:(NSString *)bundleId error:(NSError **)error { - NSSet> *testDescriptors = [self listTestDescriptorsWithError:error]; + NSArray> *testDescriptors = [self listTestDescriptorsWithError:error]; for (id testDescriptor in testDescriptors) { if ([[testDescriptor testBundleID] isEqualToString: bundleId]) { return testDescriptor; @@ -403,7 +415,7 @@ - (NSURL *)xctestBundleWithID:(NSString *)bundleID error:(NSError **)error - (id)testDescriptorWithURL:(NSURL *)url error:(NSError **)error { - NSSet> *testDescriptors = [self listTestDescriptorsWithError:error]; + NSArray> *testDescriptors = [self listTestDescriptorsWithError:error]; for (id testDescriptor in testDescriptors) { if ([[[testDescriptor url] absoluteString] isEqualToString:[url absoluteString]]) { return testDescriptor; @@ -497,7 +509,7 @@ - (NSURL *)xctestBundleWithID:(NSString *)bundleID error:(NSError **)error return [[FBXCodebuildTestRunDescriptor alloc] initWithURL:xctestrunURL name:testTarget testBundle:testBundle testHostBundle:testHostBundle]; } -- (FBFuture *)saveTestBundle:(NSURL *)testBundleURL +- (FBFuture *)saveTestBundle:(NSURL *)testBundleURL skipSigningBundles:(BOOL)skipSigningBundles { // Test Bundles don't always have a bundle id, so fallback to another name if it's not there. NSError *error = nil; @@ -505,7 +517,7 @@ - (NSURL *)xctestBundleWithID:(NSString *)bundleID error:(NSError **)error if (!bundle) { return [FBFuture futureWithError:error]; } - return [self saveBundle:bundle]; + return [self saveBundle:bundle skipSigningBundles:skipSigningBundles]; } - (FBFuture *)saveTestRun:(NSURL *)XCTestRunURL diff --git a/idb_companion/Utility/FBIDBTestOperation.h b/CompanionLib/Utility/FBIDBTestOperation.h similarity index 96% rename from idb_companion/Utility/FBIDBTestOperation.h rename to CompanionLib/Utility/FBIDBTestOperation.h index 4b4979e67..534f3a870 100644 --- a/idb_companion/Utility/FBIDBTestOperation.h +++ b/CompanionLib/Utility/FBIDBTestOperation.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/idb_companion/Utility/FBIDBTestOperation.m b/CompanionLib/Utility/FBIDBTestOperation.m similarity index 96% rename from idb_companion/Utility/FBIDBTestOperation.m rename to CompanionLib/Utility/FBIDBTestOperation.m index d980e060d..a47f2b6ac 100644 --- a/idb_companion/Utility/FBIDBTestOperation.m +++ b/CompanionLib/Utility/FBIDBTestOperation.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/idb_companion/Utility/FBTestApplicationsPair.h b/CompanionLib/Utility/FBTestApplicationsPair.h similarity index 94% rename from idb_companion/Utility/FBTestApplicationsPair.h rename to CompanionLib/Utility/FBTestApplicationsPair.h index d5ed2e3cf..eb17d06b9 100644 --- a/idb_companion/Utility/FBTestApplicationsPair.h +++ b/CompanionLib/Utility/FBTestApplicationsPair.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/idb_companion/Utility/FBTestApplicationsPair.m b/CompanionLib/Utility/FBTestApplicationsPair.m similarity index 92% rename from idb_companion/Utility/FBTestApplicationsPair.m rename to CompanionLib/Utility/FBTestApplicationsPair.m index 584ab791c..85a896d03 100644 --- a/idb_companion/Utility/FBTestApplicationsPair.m +++ b/CompanionLib/Utility/FBTestApplicationsPair.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/idb_companion/Utility/FBXCTestDescriptor.h b/CompanionLib/Utility/FBXCTestDescriptor.h similarity index 98% rename from idb_companion/Utility/FBXCTestDescriptor.h rename to CompanionLib/Utility/FBXCTestDescriptor.h index 8650f238d..3aa975199 100644 --- a/idb_companion/Utility/FBXCTestDescriptor.h +++ b/CompanionLib/Utility/FBXCTestDescriptor.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/idb_companion/Utility/FBXCTestDescriptor.m b/CompanionLib/Utility/FBXCTestDescriptor.m similarity index 80% rename from idb_companion/Utility/FBXCTestDescriptor.m rename to CompanionLib/Utility/FBXCTestDescriptor.m index 338bbd82a..24e8c4fe2 100644 --- a/idb_companion/Utility/FBXCTestDescriptor.m +++ b/CompanionLib/Utility/FBXCTestDescriptor.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -26,9 +26,8 @@ if (processLogDirectory) { FBXCTestLogger *mirrorLogger = [FBXCTestLogger defaultLoggerInDirectory:processLogDirectory]; - NSUUID *udid = NSUUID.UUID; - stdOutFuture = [mirrorLogger logConsumptionToFile:stdOutConsumer outputKind:@"out" udid:udid logger:logger]; - stdErrFuture = [mirrorLogger logConsumptionToFile:stdErrConsumer outputKind:@"err" udid:udid logger:logger]; + stdOutFuture = [mirrorLogger logConsumptionOf:stdOutConsumer toFileNamed:@"test_process_stdout.out" logger:logger]; + stdErrFuture = [mirrorLogger logConsumptionOf:stdErrConsumer toFileNamed:@"test_process_stderr.err" logger:logger]; } return [[FBFuture @@ -141,7 +140,7 @@ - (NSSet *)architectures return [FBFuture futureWithResult:[[FBTestApplicationsPair alloc] initWithApplicationUnderTest:nil testHostApp:nil]]; } if (request.isUITest) { - if (!request.appBundleID) { + if (!request.testTargetAppBundleID) { return [[FBIDBError describe:@"Request for UI Test, but no app_bundle_id provided"] failFuture]; @@ -149,14 +148,15 @@ - (NSSet *)architectures NSString *testHostBundleID = request.testHostAppBundleID ?: @"com.apple.Preferences"; return [[FBFuture futureWithFutures:@[ - [target installedApplicationWithBundleID:request.appBundleID], + [target installedApplicationWithBundleID:request.testTargetAppBundleID], [target installedApplicationWithBundleID:testHostBundleID], ]] onQueue:target.asyncQueue map:^(NSArray *applications) { return [[FBTestApplicationsPair alloc] initWithApplicationUnderTest:applications[0] testHostApp:applications[1]]; }]; } - NSString *bundleID = request.testHostAppBundleID ?: request.appBundleID; + // it's an App Test then + NSString *bundleID = request.testHostAppBundleID; if (!bundleID) { return [[FBIDBError describe:@"Request for Application Test, but no app_bundle_id or test_host_app_bundle_id provided"] @@ -171,19 +171,13 @@ - (NSSet *)architectures - (FBFuture *)testConfigWithRunRequest:(FBXCTestRunRequest *)request testApps:(FBTestApplicationsPair *)testApps logDirectoryPath:(NSString *)logDirectoryPath logger:(id)logger queue:(dispatch_queue_t)queue { - BOOL uiTesting = NO; FBFuture *appLaunchConfigFuture = nil; - if (request.isUITest) { - appLaunchConfigFuture = BuildAppLaunchConfig(testApps.testHostApp.bundle.identifier, request.environment, request.arguments, logger, logDirectoryPath, request.waitForDebugger, queue); - uiTesting = YES; - } else { - appLaunchConfigFuture = BuildAppLaunchConfig(request.appBundleID, request.environment, request.arguments, logger, logDirectoryPath, request.waitForDebugger, queue); - } + appLaunchConfigFuture = BuildAppLaunchConfig(testApps.testHostApp.bundle.identifier, request.environment, request.arguments, logger, logDirectoryPath, request.waitForDebugger, queue); FBCodeCoverageConfiguration *coverageConfig = nil; if (request.coverageRequest.collect) { NSString *coverageDirName =[NSString stringWithFormat:@"coverage_%@", NSUUID.UUID.UUIDString]; NSString *coverageDirPath = [self.targetAuxillaryDirectory stringByAppendingPathComponent:coverageDirName]; - coverageConfig = [[FBCodeCoverageConfiguration alloc] initWithDirectory:coverageDirPath format:request.coverageRequest.format]; + coverageConfig = [[FBCodeCoverageConfiguration alloc] initWithDirectory:coverageDirPath format:request.coverageRequest.format enableContinuousCoverageCollection:request.coverageRequest.shouldEnableContinuousCoverageCollection]; } return [appLaunchConfigFuture onQueue:queue map:^ FBIDBAppHostedTestConfiguration * (FBApplicationLaunchConfiguration *applicationLaunchConfiguration) { @@ -192,7 +186,7 @@ - (NSSet *)architectures applicationLaunchConfiguration:applicationLaunchConfiguration testHostBundle:testApps.testHostApp.bundle timeout:(request.testTimeout ? request.testTimeout.doubleValue : 0) - initializeUITesting:uiTesting + initializeUITesting:request.isUITest useXcodebuild:NO testsToRun:request.testsToRun testsToSkip:request.testsToSkip @@ -201,7 +195,9 @@ - (NSSet *)architectures resultBundlePath:nil reportActivities:request.reportActivities coverageDirectoryPath:coverageConfig.coverageDirectory - logDirectoryPath:logDirectoryPath]; + enableContinuousCoverageCollection:coverageConfig.shouldEnableContinuousCoverageCollection + logDirectoryPath:logDirectoryPath + reportResultBundle:request.collectResultBundle]; return [[FBIDBAppHostedTestConfiguration alloc] initWithTestLaunchConfiguration:testLaunchConfig coverageConfiguration:coverageConfig]; }]; } @@ -278,26 +274,35 @@ - (NSSet *)architectures if (!properties) { return [FBFuture futureWithError:error]; } - - return [BuildAppLaunchConfig(request.appBundleID, request.environment, request.arguments, logger, nil, request.waitForDebugger, queue) - onQueue:queue map:^ FBIDBAppHostedTestConfiguration * (FBApplicationLaunchConfiguration *launchConfig) { - FBTestLaunchConfiguration *testLaunchConfiguration = [[FBTestLaunchConfiguration alloc] - initWithTestBundle:self.testBundle - applicationLaunchConfiguration:launchConfig - testHostBundle:self.testHostBundle - timeout:0 - initializeUITesting:request.isUITest - useXcodebuild:YES - testsToRun:request.testsToRun - testsToSkip:request.testsToSkip - targetApplicationBundle:nil - xcTestRunProperties:properties - resultBundlePath:resultBundlePath - reportActivities:request.reportActivities - coverageDirectoryPath:nil - logDirectoryPath:logDirectoryPath]; - return [[FBIDBAppHostedTestConfiguration alloc] initWithTestLaunchConfiguration:testLaunchConfiguration coverageConfiguration:nil]; - }]; + + FBApplicationLaunchConfiguration *launchConfig = [[FBApplicationLaunchConfiguration alloc] + initWithBundleID:@"not.used.bundleId" + bundleName:nil + arguments:request.arguments ?: @[] + environment:request.environment ?: @{} + waitForDebugger:request.waitForDebugger + io:[[FBProcessIO alloc] initWithStdIn:nil stdOut:nil stdErr:nil] + launchMode:FBApplicationLaunchModeFailIfRunning]; + + FBTestLaunchConfiguration *testLaunchConfiguration = [[FBTestLaunchConfiguration alloc] + initWithTestBundle:self.testBundle + applicationLaunchConfiguration:launchConfig + testHostBundle:self.testHostBundle + timeout:0 + initializeUITesting:request.isUITest + useXcodebuild:YES + testsToRun:request.testsToRun + testsToSkip:request.testsToSkip + targetApplicationBundle:nil + xcTestRunProperties:properties + resultBundlePath:resultBundlePath + reportActivities:request.reportActivities + coverageDirectoryPath:nil + enableContinuousCoverageCollection:NO + logDirectoryPath:logDirectoryPath + reportResultBundle:request.collectResultBundle]; + + return [FBFuture futureWithResult:[[FBIDBAppHostedTestConfiguration alloc] initWithTestLaunchConfiguration:testLaunchConfiguration coverageConfiguration:nil]]; } diff --git a/idb_companion/Utility/FBXCTestReporterConfiguration.h b/CompanionLib/Utility/FBXCTestReporterConfiguration.h similarity index 81% rename from idb_companion/Utility/FBXCTestReporterConfiguration.h rename to CompanionLib/Utility/FBXCTestReporterConfiguration.h index efc392bd9..ec9e7306d 100644 --- a/idb_companion/Utility/FBXCTestReporterConfiguration.h +++ b/CompanionLib/Utility/FBXCTestReporterConfiguration.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -41,7 +41,12 @@ NS_ASSUME_NONNULL_BEGIN */ @property (nonatomic, assign, readonly) BOOL reportAttachments; -- (instancetype)initWithResultBundlePath:(nullable NSString *)resultBundlePath coverageConfiguration:(nullable FBCodeCoverageConfiguration *)coverageConfiguration logDirectoryPath:(nullable NSString *)logDirectoryPath binariesPaths:(nullable NSArray *)binariesPaths reportAttachments:(BOOL)reportAttachments; +/** + Whether to report return result bundle or not. + */ +@property (nonatomic, assign, readonly) BOOL reportResultBundle; + +- (instancetype)initWithResultBundlePath:(nullable NSString *)resultBundlePath coverageConfiguration:(nullable FBCodeCoverageConfiguration *)coverageConfiguration logDirectoryPath:(nullable NSString *)logDirectoryPath binariesPaths:(nullable NSArray *)binariesPaths reportAttachments:(BOOL)reportAttachments reportResultBundle:(BOOL)reportResultBundle; @end diff --git a/idb_companion/Utility/FBXCTestReporterConfiguration.m b/CompanionLib/Utility/FBXCTestReporterConfiguration.m similarity index 65% rename from idb_companion/Utility/FBXCTestReporterConfiguration.m rename to CompanionLib/Utility/FBXCTestReporterConfiguration.m index db53d1d37..2206f8673 100644 --- a/idb_companion/Utility/FBXCTestReporterConfiguration.m +++ b/CompanionLib/Utility/FBXCTestReporterConfiguration.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -12,7 +12,7 @@ @implementation FBXCTestReporterConfiguration -- (instancetype)initWithResultBundlePath:(nullable NSString *)resultBundlePath coverageConfiguration:(nullable FBCodeCoverageConfiguration *)coverageConfiguration logDirectoryPath:(nullable NSString *)logDirectoryPath binariesPaths:(nullable NSArray *)binariesPaths reportAttachments:(BOOL)reportAttachments +- (instancetype)initWithResultBundlePath:(nullable NSString *)resultBundlePath coverageConfiguration:(nullable FBCodeCoverageConfiguration *)coverageConfiguration logDirectoryPath:(nullable NSString *)logDirectoryPath binariesPaths:(nullable NSArray *)binariesPaths reportAttachments:(BOOL)reportAttachments reportResultBundle:(BOOL)reportResultBundle { self = [super init]; if (!self) { @@ -24,13 +24,14 @@ - (instancetype)initWithResultBundlePath:(nullable NSString *)resultBundlePath c _logDirectoryPath = logDirectoryPath; _binariesPaths = binariesPaths; _reportAttachments = reportAttachments; + _reportResultBundle = reportResultBundle; return self; } - (NSString *)description { - return [NSString stringWithFormat:@"Result Bundle %@ | Coverage %@ | Log Path %@ | Binaries Paths %@ | Report Attachments %d", self.resultBundlePath, self.coverageConfiguration, self.logDirectoryPath, [FBCollectionInformation oneLineDescriptionFromArray:self.binariesPaths], self.reportAttachments]; + return [NSString stringWithFormat:@"Result Bundle %@ | Coverage %@ | Log Path %@ | Binaries Paths %@ | Report Attachments %d | Report Restul Bundle %d", self.resultBundlePath, self.coverageConfiguration, self.logDirectoryPath, [FBCollectionInformation oneLineDescriptionFromArray:self.binariesPaths], self.reportAttachments, self.reportResultBundle]; } @end diff --git a/idb_companion/Utility/FBXCTestRunFileReader.h b/CompanionLib/Utility/FBXCTestRunFileReader.h similarity index 94% rename from idb_companion/Utility/FBXCTestRunFileReader.h rename to CompanionLib/Utility/FBXCTestRunFileReader.h index 4caed33bd..2a2b3804d 100644 --- a/idb_companion/Utility/FBXCTestRunFileReader.h +++ b/CompanionLib/Utility/FBXCTestRunFileReader.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/idb_companion/Utility/FBXCTestRunFileReader.m b/CompanionLib/Utility/FBXCTestRunFileReader.m similarity index 62% rename from idb_companion/Utility/FBXCTestRunFileReader.m rename to CompanionLib/Utility/FBXCTestRunFileReader.m index 3569d3bd7..ecb67df81 100644 --- a/idb_companion/Utility/FBXCTestRunFileReader.m +++ b/CompanionLib/Utility/FBXCTestRunFileReader.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -28,16 +28,17 @@ @implementation FBXCTestRunFileReader : NSObject describeFormat:@"IDB app storage folder does not exist at: %@", idbAppStoragePath] fail:error]; } - // dictionaryWithContentsOfURL:error: is only available in NSDictionary not in NSMutableDictionary - NSMutableDictionary *xctestrunContents = [[NSDictionary dictionaryWithContentsOfURL:xctestrunURL error:error] mutableCopy]; + NSDictionary *xctestrunContents = [NSDictionary dictionaryWithContentsOfURL:xctestrunURL error:error]; + NSMutableDictionary *mutableContents = [NSMutableDictionary dictionaryWithCapacity:xctestrunContents.count]; if (!xctestrunContents) { return nil; } - for (NSString *testTarget in xctestrunContents) { - if ([testTarget isEqualToString:@"__xctestrun_metadata__"] || [testTarget isEqualToString:@"CodeCoverageBuildableInfos"]) { + for (NSString *contentKey in xctestrunContents) { + if ([contentKey isEqualToString:@"__xctestrun_metadata__"] || [contentKey isEqualToString:@"CodeCoverageBuildableInfos"]) { + [mutableContents setObject:xctestrunContents[contentKey] forKey:contentKey]; continue; } - NSMutableDictionary *testTargetProperties = [[xctestrunContents objectForKey:testTarget] mutableCopy]; + NSMutableDictionary *testTargetProperties = [[xctestrunContents objectForKey:contentKey] mutableCopy]; // Expand __TESTROOT__ and __IDB_APPSTORAGE__ in TestHostPath NSString *testHostPath = [testTargetProperties objectForKey:@"TestHostPath"]; if (testHostPath != nil) { @@ -56,11 +57,22 @@ @implementation FBXCTestRunFileReader : NSObject NSString *targetAppPath = [testTargetProperties objectForKey:@"UITargetAppPath"]; if (targetAppPath != nil) { targetAppPath = [targetAppPath stringByReplacingOccurrencesOfString:@"__IDB_APPSTORAGE__" withString:idbAppStoragePath]; + targetAppPath = [targetAppPath stringByReplacingOccurrencesOfString:@"__TESTROOT__" withString:testRoot]; [testTargetProperties setObject:targetAppPath forKey:@"UITargetAppPath"]; } - [xctestrunContents setObject:testTargetProperties forKey:testTarget]; + NSArray *dependencies = [testTargetProperties objectForKey:@"DependentProductPaths"]; + if (dependencies && dependencies.count) { + NSMutableArray *expandedDeps = [NSMutableArray arrayWithCapacity:dependencies.count]; + for (NSString *dep in dependencies) { + NSString *absPath = [dep stringByReplacingOccurrencesOfString:@"__IDB_APPSTORAGE__" withString:idbAppStoragePath]; + absPath = [absPath stringByReplacingOccurrencesOfString:@"__TESTROOT__" withString:testRoot]; + [expandedDeps addObject:absPath]; + } + [testTargetProperties setObject:[NSArray arrayWithArray:expandedDeps] forKey:@"DependentProductPaths"]; + } + [mutableContents setObject:testTargetProperties forKey:contentKey]; } - return xctestrunContents; + return [NSDictionary dictionaryWithDictionary:mutableContents]; } @end diff --git a/idb_companion/Utility/FBiOSTargetProvider.h b/CompanionLib/Utility/FBiOSTargetProvider.h similarity index 94% rename from idb_companion/Utility/FBiOSTargetProvider.h rename to CompanionLib/Utility/FBiOSTargetProvider.h index 9a5c3edca..fc1242364 100644 --- a/idb_companion/Utility/FBiOSTargetProvider.h +++ b/CompanionLib/Utility/FBiOSTargetProvider.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/idb_companion/Utility/FBiOSTargetProvider.m b/CompanionLib/Utility/FBiOSTargetProvider.m similarity index 98% rename from idb_companion/Utility/FBiOSTargetProvider.m rename to CompanionLib/Utility/FBiOSTargetProvider.m index cb92554ce..0f9213e57 100644 --- a/idb_companion/Utility/FBiOSTargetProvider.m +++ b/CompanionLib/Utility/FBiOSTargetProvider.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/Configuration/Framework.xcconfig b/Configuration/Framework.xcconfig index 5b6173e9f..d1937b411 100644 --- a/Configuration/Framework.xcconfig +++ b/Configuration/Framework.xcconfig @@ -10,3 +10,5 @@ DYLIB_INSTALL_NAME_BASE = @rpath FRAMEWORK_VERSION = A VERSIONING_SYSTEM = apple-generic LD_RUNPATH_SEARCH_PATHS = $(inherited) @executable_path @loader_path/Frameworks +// Only expose PrivateHeaders to Framework targets. Framework targets never expose PrivateHeader imports themselves. +HEADER_SEARCH_PATHS = $(inherited) $(SRCROOT)/PrivateHeaders diff --git a/Configuration/Shared.xcconfig b/Configuration/Shared.xcconfig index 6df425cf4..17a2014a7 100644 --- a/Configuration/Shared.xcconfig +++ b/Configuration/Shared.xcconfig @@ -1,5 +1,5 @@ // Warnings & Errors -CLANG_CXX_LIBRARY = "libc++" +CLANG_WARN__DUPLICATE_METHOD_MATCH = YES CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES CLANG_WARN_BOOL_CONVERSION = YES CLANG_WARN_COMMA = YES @@ -8,6 +8,7 @@ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR CLANG_WARN_DOCUMENTATION_COMMENTS = YES CLANG_WARN_DUPLICATE_METHOD_MATCH = YES +CLANG_WARN_DUPLICATE_METHOD_MATCH = YES CLANG_WARN_EMPTY_BODY = YES CLANG_WARN_ENUM_CONVERSION = YES CLANG_WARN_IMPLICIT_SIGN_CONVERSION = YES @@ -17,17 +18,12 @@ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES CLANG_WARN_OBJC_LITERAL_CONVERSION = YES CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR +CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES CLANG_WARN_RANGE_LOOP_ANALYSIS = YES CLANG_WARN_STRICT_PROTOTYPES = YES CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES CLANG_WARN_SUSPICIOUS_MOVE = YES CLANG_WARN_UNREACHABLE_CODE = YES -CLANG_WARN_DUPLICATE_METHOD_MATCH = YES -COMBINE_HIDPI_IMAGES = YES -DEBUG_INFORMATION_FORMAT = dwarf -ENABLE_STRICT_OBJC_MSGSEND = YES -ENABLE_TESTABILITY = YES -GCC_NO_COMMON_BLOCKS = YES GCC_OPTIMIZATION_LEVEL = 0 GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES @@ -53,24 +49,12 @@ GCC_WARN_UNUSED_FUNCTION = YES GCC_WARN_UNUSED_LABEL = YES GCC_WARN_UNUSED_VALUE = YES GCC_WARN_UNUSED_VARIABLE = YES -ONLY_ACTIVE_ARCH = YES - -// Inferred Directories. Important for the linker to be able to find and weak-link private symbols. -APPLE_FRAMEWORKS_DIR = $(DEVELOPER_DIR)/../Frameworks -APPLE_OTHER_FRAMEWORKS_DIR = $(DEVELOPER_DIR)/../OtherFrameworks -APPLE_PLUGINS_DIR = $(DEVELOPER_DIR)/../PlugIns -APPLE_SHARED_FRAMEWORKS_DIR = $(DEVELOPER_DIR)/../SharedFrameworks - -// Search Paths for Frameworks & Headers -ALWAYS_SEARCH_USER_PATHS = NO -FRAMEWORK_SEARCH_PATHS = $(inherited) $(APPLE_FRAMEWORKS_DIR) $(APPLE_PLUGINS_DIR) $(APPLE_OTHER_FRAMEWORKS_DIR) $(APPLE_SHARED_FRAMEWORKS_DIR) $(DEVELOPER_LIBRARY_DIR)/PrivateFrameworks $(SDKROOT)/System/Library/PrivateFrameworks /Library/Developer/PrivateFrameworks -HEADER_SEARCH_PATHS = $(inherited) $(SRCROOT)/PrivateHeaders // SDK & OS Versions MACOSX_DEPLOYMENT_TARGET = 10.14 SDKROOT = macosx -// Language Standards & Features +// Compile-Time Settings CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x" CLANG_CXX_LIBRARY = "libc++" CLANG_ENABLE_MODULES = YES @@ -83,10 +67,8 @@ GCC_SYMBOLS_PRIVATE_EXTERN = NO // Preprocessor ENABLE_NS_ASSERTIONS = YES ENABLE_STRICT_OBJC_MSGSEND = YES +ENABLE_TESTABILITY = YES // Deployment -COMBINE_HIDPI_IMAGES = YES COPY_PHASE_STRIP = NO -INSTALL_PATH = @rpath SKIP_INSTALL = YES - diff --git a/FBControlCore/Applications/FBBinaryDescriptor.h b/FBControlCore/Applications/FBBinaryDescriptor.h index 3d1aaad14..5381f43bd 100644 --- a/FBControlCore/Applications/FBBinaryDescriptor.h +++ b/FBControlCore/Applications/FBBinaryDescriptor.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Applications/FBBinaryDescriptor.m b/FBControlCore/Applications/FBBinaryDescriptor.m index 6ff42796b..c04be207d 100644 --- a/FBControlCore/Applications/FBBinaryDescriptor.m +++ b/FBControlCore/Applications/FBBinaryDescriptor.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Applications/FBBundleDescriptor+Application.h b/FBControlCore/Applications/FBBundleDescriptor+Application.h index c0e24b604..d81b0dd40 100644 --- a/FBControlCore/Applications/FBBundleDescriptor+Application.h +++ b/FBControlCore/Applications/FBBundleDescriptor+Application.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Applications/FBBundleDescriptor+Application.m b/FBControlCore/Applications/FBBundleDescriptor+Application.m index e26d923ef..b6579b206 100644 --- a/FBControlCore/Applications/FBBundleDescriptor+Application.m +++ b/FBControlCore/Applications/FBBundleDescriptor+Application.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Applications/FBBundleDescriptor.h b/FBControlCore/Applications/FBBundleDescriptor.h index 5d1bc3b48..4b0469d94 100644 --- a/FBControlCore/Applications/FBBundleDescriptor.h +++ b/FBControlCore/Applications/FBBundleDescriptor.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Applications/FBBundleDescriptor.m b/FBControlCore/Applications/FBBundleDescriptor.m index 5c14199a9..ebe8d0577 100644 --- a/FBControlCore/Applications/FBBundleDescriptor.m +++ b/FBControlCore/Applications/FBBundleDescriptor.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Applications/FBInstalledApplication.h b/FBControlCore/Applications/FBInstalledApplication.h index 61a4a50db..ece83cb2a 100644 --- a/FBControlCore/Applications/FBInstalledApplication.h +++ b/FBControlCore/Applications/FBInstalledApplication.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -23,17 +23,6 @@ typedef NS_ENUM(NSUInteger, FBApplicationInstallType) { FBApplicationInstallTypeUserDevelopment = 5, /** The Application has been installed by the user and signed with a development certificate */ }; -/** - String Representations of the Installed Type. - */ -typedef NSString *FBApplicationInstallTypeString NS_STRING_ENUM; -extern FBApplicationInstallTypeString const FBApplicationInstallTypeStringUnknown; -extern FBApplicationInstallTypeString const FBApplicationInstallTypeStringSystem; -extern FBApplicationInstallTypeString const FBApplicationInstallTypeStringMac; -extern FBApplicationInstallTypeString const FBApplicationInstallTypeStringUser; -extern FBApplicationInstallTypeString const FBApplicationInstallTypeStringUserEnterprise; -extern FBApplicationInstallTypeString const FBApplicationInstallTypeStringUserDevelopment; - /** Keys from UserInfo about Applications */ @@ -61,6 +50,16 @@ extern FBApplicationInstallInfoKey const FBApplicationInstallInfoKeySignerIdenti */ + (instancetype)installedApplicationWithBundle:(FBBundleDescriptor *)bundle installType:(FBApplicationInstallType)installType dataContainer:(nullable NSString *)dataContainer; +/** + The Designated Initializer. + + @param bundle the Application Bundle. This represents the bundle as-installed on the target, rather than pre-install. + @param installTypeString the string representation of the install type. + @param dataContainer the Data Container Path, may be nil. + @return a new Installed Application Instance. + */ ++ (instancetype)installedApplicationWithBundle:(FBBundleDescriptor *)bundle installTypeString:(nullable NSString *)installTypeString signerIdentity:(nullable NSString *)signerIdentity dataContainer:(nullable NSString *)dataContainer; + #pragma mark Properties /** @@ -74,28 +73,14 @@ extern FBApplicationInstallInfoKey const FBApplicationInstallInfoKeySignerIdenti @property (nonatomic, assign, readonly) FBApplicationInstallType installType; /** - The data container path of the Application. - */ -@property (nonatomic, copy, nullable, readonly) NSString *dataContainer; - -#pragma mark Install Type - -/** - Returns a String Represnting the Application Install Type. - - @param installType the install type enum. - @return a string of the install type. + The "Install Type" enum of the Application, represented as a string. */ -+ (FBApplicationInstallTypeString)stringFromApplicationInstallType:(FBApplicationInstallType)installType; +@property (nonatomic, copy, readonly) NSString *installTypeString; /** - Returns the FBApplicationInstallType from the string representation. - - @param installTypeString install type as a string - @param signerIdentity the signer identity. - @return an FBApplicationInstallType + The data container path of the Application. */ -+ (FBApplicationInstallType)installTypeFromString:(nullable FBApplicationInstallTypeString)installTypeString signerIdentity:(nullable NSString *)signerIdentity; +@property (nonatomic, copy, nullable, readonly) NSString *dataContainer; @end diff --git a/FBControlCore/Applications/FBInstalledApplication.m b/FBControlCore/Applications/FBInstalledApplication.m index 22cf76358..3a93db1c3 100644 --- a/FBControlCore/Applications/FBInstalledApplication.m +++ b/FBControlCore/Applications/FBInstalledApplication.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -9,12 +9,12 @@ #import "FBBundleDescriptor.h" -FBApplicationInstallTypeString const FBApplicationInstallTypeStringUnknown = @"unknown"; -FBApplicationInstallTypeString const FBApplicationInstallTypeStringSystem = @"system"; -FBApplicationInstallTypeString const FBApplicationInstallTypeStringMac = @"mac"; -FBApplicationInstallTypeString const FBApplicationInstallTypeStringUser = @"user"; -FBApplicationInstallTypeString const FBApplicationInstallTypeStringUserEnterprise = @"user_enterprise"; -FBApplicationInstallTypeString const FBApplicationInstallTypeStringUserDevelopment = @"user_development"; +static NSString *const FBApplicationInstallTypeStringUnknown = @"unknown"; +static NSString *const FBApplicationInstallTypeStringSystem = @"system"; +static NSString *const FBApplicationInstallTypeStringMac = @"mac"; +static NSString *const FBApplicationInstallTypeStringUser = @"user"; +static NSString *const FBApplicationInstallTypeStringUserEnterprise = @"user_enterprise"; +static NSString *const FBApplicationInstallTypeStringUserDevelopment = @"user_development"; FBApplicationInstallInfoKey const FBApplicationInstallInfoKeyApplicationType = @"ApplicationType"; FBApplicationInstallInfoKey const FBApplicationInstallInfoKeyBundleIdentifier = @"CFBundleIdentifier"; @@ -31,6 +31,11 @@ + (instancetype)installedApplicationWithBundle:(FBBundleDescriptor *)bundle inst return [[self alloc] initWithBundle:bundle installType:installType dataContainer:dataContainer]; } ++ (instancetype)installedApplicationWithBundle:(FBBundleDescriptor *)bundle installTypeString:(NSString *)installTypeString signerIdentity:(NSString *)signerIdentity dataContainer:(NSString *)dataContainer +{ + return [self installedApplicationWithBundle:bundle installType:[self installTypeFromString:installTypeString signerIdentity:signerIdentity] dataContainer:dataContainer]; +} + - (instancetype)initWithBundle:(FBBundleDescriptor *)bundle installType:(FBApplicationInstallType)installType dataContainer:(NSString *)dataContainer { self = [super init]; @@ -67,7 +72,7 @@ - (NSString *)description return [NSString stringWithFormat: @"Bundle %@ | Install Type %@ | Container %@", self.bundle.description, - [FBInstalledApplication stringFromApplicationInstallType:self.installType], + self.installTypeString, self.dataContainer ]; } @@ -79,9 +84,16 @@ - (instancetype)copyWithZone:(NSZone *)zone return self; } +#pragma mark Properties + +- (NSString *)installTypeString +{ + return [FBInstalledApplication stringFromApplicationInstallType:self.installType]; +} + #pragma mark Install Type -+ (FBApplicationInstallTypeString)stringFromApplicationInstallType:(FBApplicationInstallType)installType ++ (NSString *)stringFromApplicationInstallType:(FBApplicationInstallType)installType { switch (installType) { case FBApplicationInstallTypeUser: @@ -99,7 +111,7 @@ + (FBApplicationInstallTypeString)stringFromApplicationInstallType:(FBApplicatio } } -+ (FBApplicationInstallType)installTypeFromString:(nullable FBApplicationInstallTypeString)installTypeString signerIdentity:(nullable NSString *)signerIdentity ++ (FBApplicationInstallType)installTypeFromString:(nullable NSString *)installTypeString signerIdentity:(nullable NSString *)signerIdentity { if (!installTypeString) { return FBApplicationInstallTypeUnknown; diff --git a/FBControlCore/Async/FBFuture+Sync.h b/FBControlCore/Async/FBFuture+Sync.h index 970ccc18a..6ebd6b817 100644 --- a/FBControlCore/Async/FBFuture+Sync.h +++ b/FBControlCore/Async/FBFuture+Sync.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Async/FBFuture+Sync.m b/FBControlCore/Async/FBFuture+Sync.m index ce12d8ecc..0a75ea065 100644 --- a/FBControlCore/Async/FBFuture+Sync.m +++ b/FBControlCore/Async/FBFuture+Sync.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -91,7 +91,7 @@ - (nullable id)awaitCompletionOfFuture:(FBFuture *)future timeout:(NSTimeInterva static NSTimeInterval const ForeverTimeout = DBL_MAX; -static dispatch_queue_t blockQueue() +static dispatch_queue_t blockQueue(void) { return dispatch_queue_create("com.facebook.fbfuture.block", DISPATCH_QUEUE_SERIAL); } diff --git a/FBControlCore/Async/FBFuture.h b/FBControlCore/Async/FBFuture.h index bc3a3be9a..3b5f9719b 100644 --- a/FBControlCore/Async/FBFuture.h +++ b/FBControlCore/Async/FBFuture.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -135,7 +135,7 @@ extern dispatch_time_t FBCreateDispatchTimeFromDuration(NSTimeInterval inDuratio @param futures the futures to compose. @return a new future with the resolved results of all the composed futures. */ -+ (FBFuture *> *)futureWithFutures:(NSArray *> *)futures; ++ (FBFuture *> *)futureWithFutures:(NSArray *> *)futures NS_SWIFT_UNAVAILABLE("Use BridgeFuture.values instead"); /** Constructrs a Future from an Array of Futures. diff --git a/FBControlCore/Async/FBFuture.m b/FBControlCore/Async/FBFuture.m index 4570413da..52bf158ed 100644 --- a/FBControlCore/Async/FBFuture.m +++ b/FBControlCore/Async/FBFuture.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Async/FBFutureContextManager.h b/FBControlCore/Async/FBFutureContextManager.h index 19629c629..460fdea3f 100644 --- a/FBControlCore/Async/FBFutureContextManager.h +++ b/FBControlCore/Async/FBFutureContextManager.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Async/FBFutureContextManager.m b/FBControlCore/Async/FBFutureContextManager.m index bedf4da40..6b59b27cc 100644 --- a/FBControlCore/Async/FBFutureContextManager.m +++ b/FBControlCore/Async/FBFutureContextManager.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Codesigning/FBCodesignProvider.h b/FBControlCore/Codesigning/FBCodesignProvider.h index 3ea9db117..6bf67d738 100644 --- a/FBControlCore/Codesigning/FBCodesignProvider.h +++ b/FBControlCore/Codesigning/FBCodesignProvider.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Codesigning/FBCodesignProvider.m b/FBControlCore/Codesigning/FBCodesignProvider.m index 932705874..c7d6e926f 100644 --- a/FBControlCore/Codesigning/FBCodesignProvider.m +++ b/FBControlCore/Codesigning/FBCodesignProvider.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Commands/FBAccessibilityCommands.h b/FBControlCore/Commands/FBAccessibilityCommands.h index e94f519a9..ffa02b0fc 100644 --- a/FBControlCore/Commands/FBAccessibilityCommands.h +++ b/FBControlCore/Commands/FBAccessibilityCommands.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -25,7 +25,7 @@ NS_ASSUME_NONNULL_BEGIN @param nestedFormat if YES then data is returned in the nested format, NO for flat format @return the accessibility elements for the main screen, wrapped in a Future. */ -- (FBFuture *> *> *)accessibilityElementsWithNestedFormat:(BOOL)nestedFormat; +- (FBFuture *)accessibilityElementsWithNestedFormat:(BOOL)nestedFormat; /** Obtain the acessibility element for the main screen at the given point. @@ -35,7 +35,7 @@ NS_ASSUME_NONNULL_BEGIN @param nestedFormat if YES then data is returned in the nested format, NO for flat format @return the accessibility element at the provided point, wrapped in a Future. */ -- (FBFuture *> *)accessibilityElementAtPoint:(CGPoint)point nestedFormat:(BOOL)nestedFormat; +- (FBFuture *)accessibilityElementAtPoint:(CGPoint)point nestedFormat:(BOOL)nestedFormat; @end diff --git a/FBControlCore/Commands/FBApplicationCommands.h b/FBControlCore/Commands/FBApplicationCommands.h index 68aa1e4f6..6a275ecef 100644 --- a/FBControlCore/Commands/FBApplicationCommands.h +++ b/FBControlCore/Commands/FBApplicationCommands.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Commands/FBCrashLogCommands.h b/FBControlCore/Commands/FBCrashLogCommands.h index d59cbe971..77d6d40f3 100644 --- a/FBControlCore/Commands/FBCrashLogCommands.h +++ b/FBControlCore/Commands/FBCrashLogCommands.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Commands/FBDapServerCommands.h b/FBControlCore/Commands/FBDapServerCommands.h index 0f9b1b556..ab797a1a3 100644 --- a/FBControlCore/Commands/FBDapServerCommands.h +++ b/FBControlCore/Commands/FBDapServerCommands.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Commands/FBDebuggerCommands.h b/FBControlCore/Commands/FBDebuggerCommands.h index f4b788099..3c4b1dc8c 100644 --- a/FBControlCore/Commands/FBDebuggerCommands.h +++ b/FBControlCore/Commands/FBDebuggerCommands.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Commands/FBDeveloperDiskImageCommands.h b/FBControlCore/Commands/FBDeveloperDiskImageCommands.h index 8ec088b38..6feb7cf04 100644 --- a/FBControlCore/Commands/FBDeveloperDiskImageCommands.h +++ b/FBControlCore/Commands/FBDeveloperDiskImageCommands.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Commands/FBDiagnosticInformationCommands.h b/FBControlCore/Commands/FBDiagnosticInformationCommands.h index 5163848c4..49ba8ebf5 100644 --- a/FBControlCore/Commands/FBDiagnosticInformationCommands.h +++ b/FBControlCore/Commands/FBDiagnosticInformationCommands.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Commands/FBEraseCommands.h b/FBControlCore/Commands/FBEraseCommands.h index 665dc7b01..0dba65f0e 100644 --- a/FBControlCore/Commands/FBEraseCommands.h +++ b/FBControlCore/Commands/FBEraseCommands.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Commands/FBFileCommands.h b/FBControlCore/Commands/FBFileCommands.h index 11f69ee31..0e433058c 100644 --- a/FBControlCore/Commands/FBFileCommands.h +++ b/FBControlCore/Commands/FBFileCommands.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -98,6 +98,13 @@ NS_ASSUME_NONNULL_BEGIN */ - (FBFutureContext> *)fileCommandsForDiskImages; +/** + Returns a file container for manipulating device symbols. + + @return a Future context that resolves with an implementation of the file container. + */ +- (FBFutureContext> *)fileCommandsForSymbols; + @end NS_ASSUME_NONNULL_END diff --git a/FBControlCore/Commands/FBFileContainer.h b/FBControlCore/Commands/FBFileContainer.h index 4f7eadcd5..e35831052 100644 --- a/FBControlCore/Commands/FBFileContainer.h +++ b/FBControlCore/Commands/FBFileContainer.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -26,6 +26,7 @@ extern FBFileContainerKind const FBFileContainerKindMedia; extern FBFileContainerKind const FBFileContainerKindProvisioningProfiles; extern FBFileContainerKind const FBFileContainerKindRoot; extern FBFileContainerKind const FBFileContainerKindSpringboardIcons; +extern FBFileContainerKind const FBFileContainerKindSymbols; extern FBFileContainerKind const FBFileContainerKindWallpaper; @protocol FBDataConsumer; @@ -45,25 +46,25 @@ extern FBFileContainerKind const FBFileContainerKindWallpaper; @param destinationPath the destination path to copy to, relative to the root of the container. @return A future that resolves when successful. */ -- (FBFuture *)copyFromHost:(NSURL *)sourcePath toContainer:(NSString *)destinationPath; +- (FBFuture *)copyFromHost:(NSString *)sourcePath toContainer:(NSString *)destinationPath; /** Copy a path from inside the container, to the host. - @param containerPath the source path, relative to the root of the container. May be Files and/or Directories. + @param sourcePath the source path, relative to the root of the container. May be Files and/or Directories. @param destinationPath the destination path on the host. @return A future that resolves with the destination path when successful. */ -- (FBFuture *)copyFromContainer:(NSString *)containerPath toHost:(NSString *)destinationPath; +- (FBFuture *)copyFromContainer:(NSString *)sourcePath toHost:(NSString *)destinationPath; /** - Tails a path from inside the container, to a consumer. + Tails the contents of a file path inside the container, to a data consumer. - @param containerPath the source path to tail, relative to the root of the container. Must be a file + @param path the source path to tail, relative to the root of the container. Must be a file @param consumer the consumer to write to. @return a Future that resolves with a Future when the tailing has completed. The wrapped future can be cancelled to end the tailing operation. */ -- (FBFuture *> *)tail:(NSString *)containerPath toConsumer:(id)consumer; +- (FBFuture *> *)tail:(NSString *)path toConsumer:(id)consumer; /** Create a directory inside the container. @@ -100,6 +101,95 @@ extern FBFileContainerKind const FBFileContainerKindWallpaper; @end +/** + An abstraction over a file. The file can be local to the host, or remote. + */ +@protocol FBContainedFile + +/** + Removes a file path. + If the path is a directory, the entire directory is removed and all contents, recursively. + + @param error an error out for any error that occurs. + @return YES on success, NO otherwise. + */ +- (BOOL)removeItemWithError:(NSError **)error; + +/** + List the contents of a path. + + @param error an error out for any error that occurs. + @return an array of strings representing the directory contents. + */ +- (nullable NSArray *)contentsOfDirectoryWithError:(NSError **)error; + +/** + Obtains the contents of the contained file. + + @param error an error out for any error that occurs. + @return Data for the file, or an nil on error. + */ +- (nullable NSData *)contentsOfFileWithError:(NSError **)error; + +/** + Creates a directory at the given path. + + @param error an error out for any error that occurs. + @return YES on success, NO otherwise. + */ +- (BOOL)createDirectoryWithError:(NSError **)error; + +/** + Checks whether the path exists, optionally providing information about whether the path is a regular file or directory. + + @param isDirectoryOut an outparam for indicating if the path represents a directory. + @return YES if exists, NO otherwise. + */ +- (BOOL)fileExistsIsDirectory:(BOOL *)isDirectoryOut; + +/** + Moves the receiver to the provided destination file. + + @param destination the destination to move to. + @param error an error out for any error that occurs. + */ +- (BOOL)moveTo:(id)destination error:(NSError **)error; + +/** + Replaces the contents of the wrapped file with the provided path on the host filesystem. + + @param path the path to pull contents from. + @param error an error out for any error that occurs. + @return YES if successful, NO otherwise. + */ +- (BOOL)populateWithContentsOfHostPath:(NSString *)path error:(NSError **)error; + +/** + Replaces provided path on the host filesystem with the contents of the wrapped file. + + @param path the path to push contents to. + @param error an error out for any error that occurs. + @return YES if successful, NO otherwise. + */ +- (BOOL)populateHostPathWithContents:(NSString *)path error:(NSError **)error; + +/** + Constructs a new contained file by appending a path component. + + @param component the component to add. + @param error an error out if the path is invalid. + @return the new contained file. + */ +- (id)fileByAppendingPathComponent:(NSString *)component error:(NSError **)error; + +/** + The host path corresponding to this file, if any. + If the file is remote, this will be nil + */ +@property (nonatomic, copy, nullable, readonly) NSString *pathOnHostFileSystem; + +@end + /** Implementations of File Commands. */ diff --git a/FBControlCore/Commands/FBFileContainer.m b/FBControlCore/Commands/FBFileContainer.m index f2a821700..f7a042c87 100644 --- a/FBControlCore/Commands/FBFileContainer.m +++ b/FBControlCore/Commands/FBFileContainer.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -22,129 +22,280 @@ FBFileContainerKind const FBFileContainerKindProvisioningProfiles = @"provisioning_profiles"; FBFileContainerKind const FBFileContainerKindRoot = @"root"; FBFileContainerKind const FBFileContainerKindSpringboardIcons = @"springboard_icons"; +FBFileContainerKind const FBFileContainerKindSymbols = @"symbols"; FBFileContainerKind const FBFileContainerKindWallpaper = @"wallpaper"; -@interface FBFileContainer_ProvisioningProfile : NSObject +@interface FBContainedFile_Host : NSObject -@property (nonatomic, strong, readonly) id commands; -@property (nonatomic, strong, readonly) dispatch_queue_t queue; +@property (nonatomic, strong, readonly) NSFileManager *fileManager; +@property (nonatomic, copy, readonly) NSString *path; @end -@implementation FBFileContainer_ProvisioningProfile +@implementation FBContainedFile_Host -- (instancetype)initWithCommands:(id)commands queue:(dispatch_queue_t)queue +#pragma mark Initializers + +- (instancetype)initWithFileManager:(NSFileManager *)fileManager path:(NSString *)path { self = [super init]; if (!self) { return nil; } - _commands = commands; - _queue = queue; + _fileManager = fileManager; + _path = path; return self; } -#pragma mark FBFileContainer Implementation +#pragma mark FBContainedFile -- (FBFuture *)copyFromHost:(NSURL *)path toContainer:(NSString *)destinationPath +- (BOOL)removeItemWithError:(NSError **)error { - return [FBFuture - onQueue:self.queue resolve:^ FBFuture * { - NSError *error = nil; - NSData *data = [NSData dataWithContentsOfURL:path options:0 error:&error]; - if (!data) { - return [FBFuture futureWithError:error]; - } - return [[self.commands installProvisioningProfile:data] mapReplace:NSNull.null]; - }]; + return [self.fileManager removeItemAtPath:self.path error:error]; } -- (FBFuture *)copyFromContainer:(NSString *)containerPath toHost:(NSString *)destinationPath +- (NSArray *)contentsOfDirectoryWithError:(NSError **)error +{ + return [self.fileManager contentsOfDirectoryAtPath:self.path error:error]; +} + +- (NSData *)contentsOfFileWithError:(NSError **)error +{ + return [NSData dataWithContentsOfFile:self.path options:0 error:error]; +} + +- (BOOL)moveTo:(id)destination error:(NSError **)error +{ + if (![destination isKindOfClass:FBContainedFile_Host.class]) { + return [[FBControlCoreError + describeFormat:@"Cannot move to %@, it is not on the host filesystem", destination] + failBool:error]; + } + FBContainedFile_Host *hostDestination = (FBContainedFile_Host *) destination; + return [self.fileManager moveItemAtPath:self.path toPath:hostDestination.path error:error]; +} + +- (BOOL)createDirectoryWithError:(NSError **)error +{ + return [self.fileManager createDirectoryAtPath:self.path withIntermediateDirectories:YES attributes:nil error:error]; +} + +- (BOOL)fileExistsIsDirectory:(BOOL *)isDirectoryOut +{ + return [self.fileManager fileExistsAtPath:self.path isDirectory:isDirectoryOut]; +} + +- (BOOL)populateWithContentsOfHostPath:(NSString *)path error:(NSError **)error +{ + return [self.fileManager copyItemAtPath:path toPath:self.path error:error]; +} + +- (BOOL)populateHostPathWithContents:(NSString *)path error:(NSError **)error +{ + return [self.fileManager copyItemAtPath:self.path toPath:path error:error]; +} + +- (id)fileByAppendingPathComponent:(NSString *)component error:(NSError **)error +{ + return [[FBContainedFile_Host alloc] initWithFileManager:self.fileManager path:[self.path stringByAppendingPathComponent:component]]; +} + +- (NSString *)pathOnHostFileSystem +{ + return self.path; +} + +#pragma mark NSObject + +- (NSString *)description +{ + return [NSString stringWithFormat:@"Host File %@", self.path]; +} + +@end + +@interface FBContainedFile_Mapped_Host : NSObject + +@property (nonatomic, copy, readonly) NSDictionary *mappingPaths; +@property (nonatomic, strong, readonly) NSFileManager *fileManager; + +@end + +@implementation FBContainedFile_Mapped_Host + +- (instancetype)initWithMappingPaths:(NSDictionary *)mappingPaths fileManager:(NSFileManager *)fileManager; +{ + self = [super init]; + if (!self) { + return nil; + } + + _mappingPaths = mappingPaths; + _fileManager = fileManager; + + return self; +} + +#pragma mark FBContainedFile + +- (BOOL)removeItemWithError:(NSError **)error { return [[FBControlCoreError - describeFormat:@"-[%@ %@] is not implemented", NSStringFromClass(self.class), NSStringFromSelector(_cmd)] - failFuture]; + describeFormat:@"%@ does not operate on root virtual containers", NSStringFromSelector(_cmd)] + failBool:error]; } -- (FBFuture *> *)tail:(NSString *)containerPath toConsumer:(id)consumer +- (NSArray *)contentsOfDirectoryWithError:(NSError **)error +{ + return self.mappingPaths.allKeys; +} + +- (BOOL)createDirectoryWithError:(NSError **)error { return [[FBControlCoreError - describeFormat:@"-[%@ %@] is not implemented", NSStringFromClass(self.class), NSStringFromSelector(_cmd)] - failFuture]; + describeFormat:@"%@ does not operate on root virtual containers", NSStringFromSelector(_cmd)] + failBool:error]; } -- (FBFuture *)createDirectory:(NSString *)directoryPath +- (NSData *)contentsOfFileWithError:(NSError **)error { return [[FBControlCoreError - describeFormat:@"-[%@ %@] is not implemented", NSStringFromClass(self.class), NSStringFromSelector(_cmd)] - failFuture]; + describeFormat:@"%@ does not operate on root virtual containers", NSStringFromSelector(_cmd)] + fail:error]; } -- (FBFuture *)moveFrom:(NSString *)originPath to:(NSString *)destinationPath +- (BOOL)fileExistsIsDirectory:(BOOL *)isDirectoryOut +{ + return NO; +} + +- (BOOL)moveTo:(id)destination error:(NSError **)error { return [[FBControlCoreError - describeFormat:@"-[%@ %@] is not implemented", NSStringFromClass(self.class), NSStringFromSelector(_cmd)] - failFuture]; + describe:@"Moving files does not work on root virtual containers"] + failBool:error]; } -- (FBFuture *)remove:(NSString *)path +- (BOOL)populateWithContentsOfHostPath:(NSString *)path error:(NSError **)error { - return [[self.commands removeProvisioningProfile:path] mapReplace:NSNull.null]; + return [[FBControlCoreError + describeFormat:@"%@ does not operate on root virtual containers", NSStringFromSelector(_cmd)] + failBool:error]; } -- (FBFuture *> *)contentsOfDirectory:(NSString *)path +- (BOOL)populateHostPathWithContents:(NSString *)path error:(NSError **)error { - return [[self.commands - allProvisioningProfiles] - onQueue:self.queue map:^(NSArray *> *profiles) { - NSMutableArray *files = NSMutableArray.array; - for (NSDictionary *profile in profiles) { - [files addObject:profile[@"UUID"]]; - } - return files; - }]; + return [[FBControlCoreError + describeFormat:@"%@ does not operate on root virtual containers", NSStringFromSelector(_cmd)] + failBool:error]; +} + +- (id)fileByAppendingPathComponent:(NSString *)component error:(NSError **)error +{ + // If the provided path represents the root (the mapping itself), then there's nothing to map to. + NSArray *pathComponents = component.pathComponents; + if ([FBContainedFile_Mapped_Host isRootPathOfContainer:pathComponents]) { + return self; + } + NSString *firstComponent = pathComponents.firstObject; + NSString *nextPath = [FBContainedFile_Mapped_Host popFirstPathComponent:pathComponents]; + NSString *mappedPath = self.mappingPaths[firstComponent]; + if (!mappedPath) { + return [[FBControlCoreError + describeFormat:@"'%@' is not a valid root path out of %@", firstComponent, [FBCollectionInformation oneLineDescriptionFromArray:self.mappingPaths.allKeys]] + fail:error]; + } + id mapped = [[FBContainedFile_Host alloc] initWithFileManager:self.fileManager path:mappedPath]; + return [mapped fileByAppendingPathComponent:nextPath error:error]; +} + +- (NSString *)pathOnHostFileSystem +{ + return nil; +} + +#pragma mark NSObject + +- (NSString *)description +{ + return [NSString stringWithFormat:@"Root mapping: %@", [FBCollectionInformation oneLineDescriptionFromArray:self.mappingPaths.allKeys]]; +} + +#pragma mark Private + ++ (BOOL)isRootPathOfContainer:(NSArray *)pathComponents +{ + // If no path components this must be the root + if (pathComponents.count == 0) { + return YES; + } + // The root is also signified by a query for the root of the container. + NSString *firstPath = pathComponents.firstObject; + if (pathComponents.count == 1 && ([firstPath isEqualToString:@"."] || [firstPath isEqualToString:@"/"])) { + return YES; + } + // Otherwise we can't be the root path + return NO; +} + ++ (NSString *)popFirstPathComponent:(NSArray *)pathComponents +{ + // Re-assemble the mapped path, discarding the re-mapped first path component. + BOOL isFirstPathComponent = YES; + NSString *next = @""; + for (NSString *pathComponent in pathComponents) { + if (isFirstPathComponent) { + isFirstPathComponent = NO; + continue; + } + next = [next stringByAppendingPathComponent:pathComponent]; + } + return next; } @end -@interface FBFileContainerBase : NSObject +@interface FBContainedFile_ContainedRoot : NSObject @property (nonatomic, strong, readonly) dispatch_queue_t queue; -@property (nonatomic, strong, readonly) NSFileManager *fileManager; +@property (nonatomic, strong, readonly) id rootFile; @end -@implementation FBFileContainerBase +@implementation FBContainedFile_ContainedRoot -- (instancetype)initWithQueue:(dispatch_queue_t)queue +- (instancetype)initWithRootFile:(id)rootFile queue:(dispatch_queue_t)queue { self = [super init]; if (!self) { return nil; } + _rootFile = rootFile; _queue = queue; - _fileManager = NSFileManager.defaultManager; return self; } #pragma mark FBFileCommands -- (FBFuture *)copyFromHost:(NSURL *)sourcePath toContainer:(NSString *)destinationPath +- (FBFuture *)copyFromHost:(NSString *)sourcePath toContainer:(NSString *)destinationPath { return [[self - mappedPath:destinationPath] - onQueue:self.queue fmap:^ FBFuture * (NSString *mappedPath) { - NSError *error; - NSString *destPath = [mappedPath stringByAppendingPathComponent:sourcePath.lastPathComponent]; + mapToContainedFile:destinationPath] + onQueue:self.queue fmap:^ FBFuture * (id destination) { // Attempt to delete first to overwrite - [self removeItemAtPath:destPath error:nil]; - if (![self copyItemAtPath:sourcePath.path toPath:destPath error:&error]) { + NSError *error; + destination = [destination fileByAppendingPathComponent:sourcePath.lastPathComponent error:&error]; + if (!destination) { + return [FBFuture futureWithError:error]; + } + [destination removeItemWithError:nil]; + if (![destination populateWithContentsOfHostPath:sourcePath error:&error]) { return [[[FBControlCoreError - describeFormat:@"Could not copy from %@ to %@: %@", sourcePath, destPath, error] + describeFormat:@"Could not copy from %@ to %@: %@", sourcePath, destinationPath, error] causedBy:error] failFuture]; } @@ -152,32 +303,33 @@ - (instancetype)initWithQueue:(dispatch_queue_t)queue }]; } -- (FBFuture *)copyFromContainer:(NSString *)containerPath toHost:(NSString *)destinationPath +- (FBFuture *)copyFromContainer:(NSString *)sourcePath toHost:(NSString *)destinationPath { return [[self - mappedPath:containerPath] - onQueue:self.queue fmap:^ FBFuture * (NSString *source) { - BOOL srcIsDirecory = NO; - if (![self.fileManager fileExistsAtPath:source isDirectory:&srcIsDirecory]) { + mapToContainedFile:sourcePath] + onQueue:self.queue fmap:^ FBFuture * (id source) { + BOOL sourceIsDirectory = NO; + if (![source fileExistsIsDirectory:&sourceIsDirectory]) { return [[FBControlCoreError describeFormat:@"Source path does not exist: %@", source] failFuture]; } NSString *dstPath = destinationPath; - if (!srcIsDirecory) { + if (!sourceIsDirectory) { NSError *createDirectoryError; - if (![self createDirectoryAtPath:dstPath withIntermediateDirectories:YES attributes:nil error:&createDirectoryError]) { + if (![NSFileManager.defaultManager createDirectoryAtPath:dstPath withIntermediateDirectories:YES attributes:@{} error:&createDirectoryError]) { return [[[FBControlCoreError describeFormat:@"Could not create temporary directory: %@", createDirectoryError] causedBy:createDirectoryError] failFuture]; } - dstPath = [dstPath stringByAppendingPathComponent:[source lastPathComponent]]; + dstPath = [dstPath stringByAppendingPathComponent:[sourcePath lastPathComponent]]; } // if it already exists at the destination path we should remove it before copying again - if ([self.fileManager fileExistsAtPath:dstPath]) { + BOOL destinationIsDirectory = NO; + if ([NSFileManager.defaultManager fileExistsAtPath:dstPath isDirectory:&destinationIsDirectory]) { NSError *removeError; - if (![self removeItemAtPath:dstPath error:&removeError]) { + if (![NSFileManager.defaultManager removeItemAtPath:dstPath error:&removeError]) { return [[[FBControlCoreError describeFormat:@"Could not remove %@", dstPath] causedBy:removeError] @@ -186,7 +338,7 @@ - (instancetype)initWithQueue:(dispatch_queue_t)queue } NSError *copyError; - if (![self copyItemAtPath:source toPath:dstPath error:©Error]) { + if (![source populateHostPathWithContents:dstPath error:©Error]) { return [[[FBControlCoreError describeFormat:@"Could not copy from %@ to %@: %@", source, dstPath, copyError] causedBy:copyError] @@ -196,21 +348,27 @@ - (instancetype)initWithQueue:(dispatch_queue_t)queue }]; } -- (FBFuture *> *)tail:(NSString *)containerPath toConsumer:(id)consumer +- (FBFuture *> *)tail:(NSString *)path toConsumer:(id)consumer { return [[[self - mappedPath:containerPath] - onQueue:self.queue fmap:^(NSString *fullSourcePath) { + mapToContainedFile:path] + onQueue:self.queue fmap:^ FBFuture, NSData *> *> * (id fileToTail) { + NSString *pathOnHostFileSystem = fileToTail.pathOnHostFileSystem; + if (!pathOnHostFileSystem) { + return [[FBControlCoreError + describeFormat:@"Cannot tail %@, it is not on the local filesystem", fileToTail] + failFuture]; + } return [[[[FBProcessBuilder withLaunchPath:@"/usr/bin/tail"] - withArguments:@[@"-c+1", @"-f", fullSourcePath]] + withArguments:@[@"-c+1", @"-f", pathOnHostFileSystem]] withStdOutConsumer:consumer] start]; }] - onQueue:self.queue map:^(FBProcess *task) { - return [task.statLoc + onQueue:self.queue map:^(FBProcess *process) { + return [process.statLoc onQueue:self.queue respondToCancellation:^{ - return [task sendSignal:SIGTERM backingOffToKillWithTimeout:1 logger:nil]; + return [process sendSignal:SIGTERM backingOffToKillWithTimeout:1 logger:nil]; }]; }]; } @@ -218,12 +376,12 @@ - (instancetype)initWithQueue:(dispatch_queue_t)queue - (FBFuture *)createDirectory:(NSString *)directoryPath { return [[self - mappedPath:directoryPath] - onQueue:self.queue fmap:^ FBFuture * (NSString *fullPath) { + mapToContainedFile:directoryPath] + onQueue:self.queue fmap:^ FBFuture * (id directory) { NSError *error; - if (![self createDirectoryAtPath:fullPath withIntermediateDirectories:YES attributes:nil error:&error]) { + if (![directory createDirectoryWithError:&error]) { return [[[FBControlCoreError - describeFormat:@"Could not create directory %@ at container %@: %@", directoryPath, fullPath, error] + describeFormat:@"Could not create directory %@: %@", directory, error] causedBy:error] failFuture]; } @@ -235,16 +393,17 @@ - (instancetype)initWithQueue:(dispatch_queue_t)queue { return [[FBFuture futureWithFutures:@[ - [self mappedPath:sourcePath], - [self mappedPath:destinationPath], + [self mapToContainedFile:sourcePath], + [self mapToContainedFile:destinationPath], ]] - onQueue:self.queue fmap:^ FBFuture * (NSArray *mappedPaths) { - NSString *fullSourcePath = mappedPaths[0]; - NSString *fullDestinationPath = mappedPaths[1]; + onQueue:self.queue fmap:^ FBFuture * (NSArray> *providedFiles) { + // If the source and destination are on the same filesystem, they can be moved directly. + id source = providedFiles[0]; + id destination = providedFiles[1]; NSError *error = nil; - if (![self moveItemAtPath:fullSourcePath toPath:fullDestinationPath error:&error]) { + if (![source moveTo:destination error:&error]) { return [[[FBControlCoreError - describeFormat:@"Could not move item at %@ to %@: %@", fullSourcePath, fullDestinationPath, error] + describeFormat:@"Could not move item at %@ to %@: %@", source, destination, error] causedBy:error] failFuture]; } @@ -255,12 +414,12 @@ - (instancetype)initWithQueue:(dispatch_queue_t)queue - (FBFuture *)remove:(NSString *)path { return [[self - mappedPath:path] - onQueue:self.queue fmap:^ FBFuture * (NSString *fullPath) { + mapToContainedFile:path] + onQueue:self.queue fmap:^ FBFuture * (id file) { NSError *error; - if (![self removeItemAtPath:fullPath error:&error]) { + if (![file removeItemWithError:&error]) { return [[[FBControlCoreError - describeFormat:@"Could not remove item at path %@: %@", fullPath, error] + describeFormat:@"Could not remove item at path %@: %@", file, error] causedBy:error] failFuture]; } @@ -271,10 +430,10 @@ - (instancetype)initWithQueue:(dispatch_queue_t)queue - (FBFuture *> *)contentsOfDirectory:(NSString *)path { return [[self - mappedPath:path] - onQueue:self.queue fmap:^(NSString *fullPath) { + mapToContainedFile:path] + onQueue:self.queue fmap:^(id directory) { NSError *error; - NSArray *contents = [self contentsOfDirectoryAtPath:fullPath error:&error]; + NSArray *contents = [directory contentsOfDirectoryWithError:&error]; if (!contents) { return [FBFuture futureWithError:error]; } @@ -284,232 +443,99 @@ - (instancetype)initWithQueue:(dispatch_queue_t)queue #pragma mark Private -- (FBFuture *)mappedPath:(NSString *)path -{ - return [[FBControlCoreError - describeFormat:@"-[%@ %@] must be implemented by subclasses", NSStringFromClass(self.class), NSStringFromSelector(_cmd)] - failFuture]; -} - -- (NSArray *)contentsOfDirectoryAtPath:(NSString *)fullPath error:(NSError **)error -{ - return [self.fileManager contentsOfDirectoryAtPath:fullPath error:error]; -} - -- (BOOL)removeItemAtPath:(NSString *)path error:(NSError **)error -{ - return [self.fileManager removeItemAtPath:path error:error]; -} - -- (BOOL)moveItemAtPath:(NSString *)srcPath toPath:(NSString *)dstPath error:(NSError **)error -{ - return [self.fileManager moveItemAtPath:srcPath toPath:dstPath error:error]; -} - -- (BOOL)copyItemAtPath:(NSString *)srcPath toPath:(NSString *)dstPath error:(NSError **)error -{ - return [self.fileManager copyItemAtPath:srcPath toPath:dstPath error:error]; -} - -- (BOOL)createDirectoryAtPath:(NSString *)path withIntermediateDirectories:(BOOL)createIntermediates attributes:(NSDictionary *)attributes error:(NSError **)error +- (FBFuture> *)mapToContainedFile:(NSString *)path { - return [self.fileManager createDirectoryAtPath:path withIntermediateDirectories:createIntermediates attributes:attributes error:error]; -} - -@end - -@interface FBBasePathFileContainer : FBFileContainerBase - -@property (nonatomic, copy, readonly) NSString *containerPath; - -@end - -@implementation FBBasePathFileContainer - -- (instancetype)initWithContainerPath:(NSString *)containerPath queue:(dispatch_queue_t)queue -{ - self = [super initWithQueue:queue]; - if (!self) { - return nil; + NSError *error = nil; + id file = [self.rootFile fileByAppendingPathComponent:path error:&error]; + if (!file) { + return [FBFuture futureWithError:error]; } - - _containerPath = containerPath; - - return self; + return [FBFuture futureWithResult:file]; } -- (FBFuture *)mappedPath:(NSString *)path -{ - return [FBFuture futureWithResult:[self.containerPath stringByAppendingPathComponent:path]]; -} @end -@interface FBMappedFileContainer : FBFileContainerBase +@interface FBFileContainer_ProvisioningProfile : NSObject -@property (nonatomic, copy, readonly) NSDictionary *pathMapping; -@property (nonatomic, copy, readonly) NSSet *mappedPaths; +@property (nonatomic, strong, readonly) id commands; +@property (nonatomic, strong, readonly) dispatch_queue_t queue; @end -@implementation FBMappedFileContainer +@implementation FBFileContainer_ProvisioningProfile -- (instancetype)initWithPathMapping:(NSDictionary *)pathMapping queue:(dispatch_queue_t)queue +- (instancetype)initWithCommands:(id)commands queue:(dispatch_queue_t)queue { - self = [super initWithQueue:queue]; + self = [super init]; if (!self) { return nil; } - _pathMapping = pathMapping; - _mappedPaths = [NSSet setWithArray:pathMapping.allValues]; + _commands = commands; + _queue = queue; return self; } -- (FBFuture *)mappedPath:(NSString *)path -{ - NSArray *pathComponents = path.pathComponents; - // If we're the root, there's nothing to map to. - if ([self isRootPathOfContainer:pathComponents]) { - return [FBFuture futureWithResult:path]; - } - // Otherwise, take the first path component, which must be name of the container, so it must have a mapping. - NSString *firstPath = pathComponents.firstObject; - NSString *mappedPath = self.pathMapping[firstPath]; - if (!mappedPath) { - return [[FBControlCoreError - describeFormat:@"%@ is not a valid container id in %@", firstPath, [FBCollectionInformation oneLineDescriptionFromArray:self.pathMapping.allKeys]] - failFuture]; - } - // Re-assemble the mapped path, discarding the re-mapped first path component. - BOOL isFirstPathComponent = YES; - for (NSString *pathComponent in pathComponents) { - if (isFirstPathComponent) { - isFirstPathComponent = NO; - continue; - } - mappedPath = [mappedPath stringByAppendingPathComponent:pathComponent]; - } - return [FBFuture futureWithResult:mappedPath]; -} - -#pragma mark Private +#pragma mark FBFileContainer Implementation -- (NSArray *)contentsOfDirectoryAtPath:(NSString *)fullPath error:(NSError **)error +- (FBFuture *)copyFromHost:(NSString *)path toContainer:(NSString *)destinationPath { - NSArray *pathComponents = fullPath.pathComponents; - // Request for the root container, list all mapped names. - if ([self isRootPathOfContainer:pathComponents]) { - return self.pathMapping.allKeys; - } - return [super contentsOfDirectoryAtPath:fullPath error:error]; + return [FBFuture + onQueue:self.queue resolve:^ FBFuture * { + NSError *error = nil; + NSData *data = [NSData dataWithContentsOfFile:path options:0 error:&error]; + if (!data) { + return [FBFuture futureWithError:error]; + } + return [[self.commands installProvisioningProfile:data] mapReplace:NSNull.null]; + }]; } -- (BOOL)removeItemAtPath:(NSString *)path error:(NSError **)error +- (FBFuture *)copyFromContainer:(NSString *)containerPath toHost:(NSString *)destinationPath { - NSArray *pathComponents = path.pathComponents; - if ([self isRootPathOfContainer:pathComponents]) { - return [[FBControlCoreError - describeFormat:@"Cannot remove mapped container root at path %@", path] - failBool:error]; - } - if ([self isGroupContainerRoot:pathComponents]) { - return [[FBControlCoreError - describeFormat:@"Cannot remove mapped container at path %@", path] - failBool:error]; - } - return [super removeItemAtPath:path error:error]; + return [[FBControlCoreError + describeFormat:@"-[%@ %@] is not implemented", NSStringFromClass(self.class), NSStringFromSelector(_cmd)] + failFuture]; } -- (BOOL)moveItemAtPath:(NSString *)srcPath toPath:(NSString *)dstPath error:(NSError **)error +- (FBFuture *> *)tail:(NSString *)containerPath toConsumer:(id)consumer { - NSArray *srcPathComponents = srcPath.pathComponents; - NSArray *dstPathComponents = dstPath.pathComponents; - if ([self isRootPathOfContainer:srcPathComponents]) { - return [[FBControlCoreError - describeFormat:@"Cannot move mapped container root at path %@", srcPath] - failBool:error]; - } - if ([self isGroupContainerRoot:srcPathComponents]) { - return [[FBControlCoreError - describeFormat:@"Cannot move mapped container at path %@", srcPath] - failBool:error]; - } - if ([self isRootPathOfContainer:dstPathComponents]) { - return [[FBControlCoreError - describeFormat:@"Cannot move to mapped container root at path %@", dstPath] - failBool:error]; - } - if ([self isGroupContainerRoot:dstPathComponents]) { - return [[FBControlCoreError - describeFormat:@"Cannot move to mapped container at path %@", dstPath] - failBool:error]; - } - return [super moveItemAtPath:srcPath toPath:dstPath error:error]; + return [[FBControlCoreError + describeFormat:@"-[%@ %@] is not implemented", NSStringFromClass(self.class), NSStringFromSelector(_cmd)] + failFuture]; } -- (BOOL)copyItemAtPath:(NSString *)srcPath toPath:(NSString *)dstPath error:(NSError **)error +- (FBFuture *)createDirectory:(NSString *)directoryPath { - NSArray *srcPathComponents = srcPath.pathComponents; - NSArray *dstPathComponents = dstPath.pathComponents; - if ([self isRootPathOfContainer:srcPathComponents]) { - return [[FBControlCoreError - describeFormat:@"Cannot copy mapped container root at path %@", srcPath] - failBool:error]; - } - if ([self isRootPathOfContainer:dstPathComponents]) { - return [[FBControlCoreError - describeFormat:@"Cannot copy to mapped container root at path %@", dstPath] - failBool:error]; - } - if ([self isGroupContainerRoot:dstPathComponents]) { - return [[FBControlCoreError - describeFormat:@"Cannot copy to mapped container at path %@", dstPath] - failBool:error]; - } - return [super copyItemAtPath:srcPath toPath:dstPath error:error]; + return [[FBControlCoreError + describeFormat:@"-[%@ %@] is not implemented", NSStringFromClass(self.class), NSStringFromSelector(_cmd)] + failFuture]; } -- (BOOL)createDirectoryAtPath:(NSString *)path withIntermediateDirectories:(BOOL)createIntermediates attributes:(NSDictionary *)attributes error:(NSError **)error +- (FBFuture *)moveFrom:(NSString *)originPath to:(NSString *)destinationPath { - NSArray *pathComponents = path.pathComponents; - if ([self isRootPathOfContainer:pathComponents]) { - return [[FBControlCoreError - describeFormat:@"Cannot create mapped container root at path %@", path] - failBool:error]; - } - if ([self isGroupContainerRoot:pathComponents]) { - return [[FBControlCoreError - describeFormat:@"Cannot create mapped container at path %@", path] - failBool:error]; - } - return [super createDirectoryAtPath:path withIntermediateDirectories:createIntermediates attributes:attributes error:error]; + return [[FBControlCoreError + describeFormat:@"-[%@ %@] is not implemented", NSStringFromClass(self.class), NSStringFromSelector(_cmd)] + failFuture]; } -- (BOOL)isRootPathOfContainer:(NSArray *)pathComponents +- (FBFuture *)remove:(NSString *)path { - // If no path components this must be the root - if (pathComponents.count == 0) { - return YES; - } - // The root is also signified by a query for the root of the container. - NSString *firstPath = pathComponents.firstObject; - if (pathComponents.count == 1 && ([firstPath isEqualToString:@"."] || [firstPath isEqualToString:@"/"])) { - return YES; - } - // Otherwise we can't be the root path. - return NO; + return [[self.commands removeProvisioningProfile:path] mapReplace:NSNull.null]; } -- (BOOL)isGroupContainerRoot:(NSArray *)pathComponents +- (FBFuture *> *)contentsOfDirectory:(NSString *)path { - // Re-assemble the path, confirming whether it matches with one of the mapped paths - NSString *reassembled = [NSURL fileURLWithPathComponents:pathComponents].path; - if ([self.mappedPaths containsObject:reassembled]) { - return YES; - } - // If the canonical path does not match the known paths this can't be the group container root. - return NO; + return [[self.commands + allProvisioningProfiles] + onQueue:self.queue map:^(NSArray *> *profiles) { + NSMutableArray *files = NSMutableArray.array; + for (NSDictionary *profile in profiles) { + [files addObject:profile[@"UUID"]]; + } + return files; + }]; } @end @@ -523,14 +549,22 @@ @implementation FBFileContainer + (id)fileContainerForBasePath:(NSString *)basePath { - dispatch_queue_t queue = dispatch_queue_create("com.facebook.fbcontrolcore.file_container", DISPATCH_QUEUE_SERIAL); - return [[FBBasePathFileContainer alloc] initWithContainerPath:basePath queue:queue]; + id rootFile = [[FBContainedFile_Host alloc] initWithFileManager:NSFileManager.defaultManager path:basePath]; + return [self fileContainerForRootFile:rootFile]; } + (id)fileContainerForPathMapping:(NSDictionary *)pathMapping +{ + id rootFile = [[FBContainedFile_Mapped_Host alloc] initWithMappingPaths:pathMapping fileManager:NSFileManager.defaultManager]; + return [self fileContainerForRootFile:rootFile]; +} + +#pragma mark Private + ++ (id)fileContainerForRootFile:(id)root { dispatch_queue_t queue = dispatch_queue_create("com.facebook.fbcontrolcore.file_container", DISPATCH_QUEUE_SERIAL); - return [[FBMappedFileContainer alloc] initWithPathMapping:pathMapping queue:queue]; + return [[FBContainedFile_ContainedRoot alloc] initWithRootFile:root queue:queue]; } @end diff --git a/FBControlCore/Commands/FBInstrumentsCommands.h b/FBControlCore/Commands/FBInstrumentsCommands.h index 5fc63bfa7..069d30c00 100644 --- a/FBControlCore/Commands/FBInstrumentsCommands.h +++ b/FBControlCore/Commands/FBInstrumentsCommands.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Commands/FBInstrumentsCommands.m b/FBControlCore/Commands/FBInstrumentsCommands.m index d3ecbd6c9..fa8a40e81 100644 --- a/FBControlCore/Commands/FBInstrumentsCommands.m +++ b/FBControlCore/Commands/FBInstrumentsCommands.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Commands/FBLifecycleCommands.h b/FBControlCore/Commands/FBLifecycleCommands.h new file mode 100644 index 000000000..9cb915b4d --- /dev/null +++ b/FBControlCore/Commands/FBLifecycleCommands.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import + +#import +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + Defines an interface for power related commands. + */ +@protocol FBLifecycleCommands + +#pragma mark States + +/** + Asynchronously waits on the provided state. + + @param state the state to wait on + @return A future that resolves when it has transitioned to the given state. + */ +- (FBFuture *)resolveState:(FBiOSTargetState)state; + +/** + Asynchronously waits to leave the provided state. + + @param state the state to wait to leave + @return A future that resolves when it has transitioned away from the given state. + */ +- (FBFuture *)resolveLeavesState:(FBiOSTargetState)state; + +@end + +NS_ASSUME_NONNULL_END diff --git a/FBControlCore/Commands/FBLocationCommands.h b/FBControlCore/Commands/FBLocationCommands.h index 2328b6f21..9d7c7d253 100644 --- a/FBControlCore/Commands/FBLocationCommands.h +++ b/FBControlCore/Commands/FBLocationCommands.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Commands/FBLogCommands.h b/FBControlCore/Commands/FBLogCommands.h index 5e9cfda21..95b26c72f 100644 --- a/FBControlCore/Commands/FBLogCommands.h +++ b/FBControlCore/Commands/FBLogCommands.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Commands/FBLogCommands.m b/FBControlCore/Commands/FBLogCommands.m index 063ed1429..f39722744 100644 --- a/FBControlCore/Commands/FBLogCommands.m +++ b/FBControlCore/Commands/FBLogCommands.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Commands/FBMemoryCommands.h b/FBControlCore/Commands/FBMemoryCommands.h index d1379b6af..1226798c1 100644 --- a/FBControlCore/Commands/FBMemoryCommands.h +++ b/FBControlCore/Commands/FBMemoryCommands.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Commands/FBNotificationCommands.h b/FBControlCore/Commands/FBNotificationCommands.h index a026ab1b5..5adae5a87 100644 --- a/FBControlCore/Commands/FBNotificationCommands.h +++ b/FBControlCore/Commands/FBNotificationCommands.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Commands/FBPowerCommands.h b/FBControlCore/Commands/FBPowerCommands.h index e02142c2b..56b0bb893 100644 --- a/FBControlCore/Commands/FBPowerCommands.h +++ b/FBControlCore/Commands/FBPowerCommands.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Commands/FBProcessSpawnCommands.h b/FBControlCore/Commands/FBProcessSpawnCommands.h index 4d7321547..61c1d34b7 100644 --- a/FBControlCore/Commands/FBProcessSpawnCommands.h +++ b/FBControlCore/Commands/FBProcessSpawnCommands.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Commands/FBProcessSpawnCommands.m b/FBControlCore/Commands/FBProcessSpawnCommands.m index 52eb774e9..5813ab5ed 100644 --- a/FBControlCore/Commands/FBProcessSpawnCommands.m +++ b/FBControlCore/Commands/FBProcessSpawnCommands.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -60,14 +60,14 @@ + (void)resolveProcessFinishedWithStatLoc:(int)statLoc inTeardownOfIOAttachment: [statLocFuture resolveWithResult:@(statLoc)]; if (WIFSIGNALED(statLoc)) { int signalCode = WTERMSIG(statLoc); - NSString *message = [NSString stringWithFormat:@"Process %d (%@) died with signal %d", processIdentifier, configuration.processName, signalCode]; + NSString *message = [NSString stringWithFormat:@"Process %d (%@) exited with signal %d", processIdentifier, configuration.processName, signalCode]; [logger log:message]; NSError *error = [[FBControlCoreError describe:message] build]; [exitCodeFuture resolveWithError:error]; [signalFuture resolveWithResult:@(signalCode)]; } else { int exitCode = WEXITSTATUS(statLoc); - NSString *message = [NSString stringWithFormat:@"Process %d (%@) died with exit code %d", processIdentifier, configuration.processName, exitCode]; + NSString *message = [NSString stringWithFormat:@"Process %d (%@) exited with code %d", processIdentifier, configuration.processName, exitCode]; [logger log:message]; NSError *error = [[FBControlCoreError describe:message] build]; [signalFuture resolveWithError:error]; diff --git a/FBControlCore/Commands/FBProvisioningProfileCommands.h b/FBControlCore/Commands/FBProvisioningProfileCommands.h index 6ee6344bc..fef0309fc 100644 --- a/FBControlCore/Commands/FBProvisioningProfileCommands.h +++ b/FBControlCore/Commands/FBProvisioningProfileCommands.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Commands/FBScreenshotCommands.h b/FBControlCore/Commands/FBScreenshotCommands.h index 864245c7d..3c22618c4 100644 --- a/FBControlCore/Commands/FBScreenshotCommands.h +++ b/FBControlCore/Commands/FBScreenshotCommands.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Commands/FBScreenshotCommands.m b/FBControlCore/Commands/FBScreenshotCommands.m index 28909b636..29a3ae6e7 100644 --- a/FBControlCore/Commands/FBScreenshotCommands.m +++ b/FBControlCore/Commands/FBScreenshotCommands.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Commands/FBSettingsCommands.h b/FBControlCore/Commands/FBSettingsCommands.h index e6b2ee71a..d29cf6dde 100644 --- a/FBControlCore/Commands/FBSettingsCommands.h +++ b/FBControlCore/Commands/FBSettingsCommands.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -10,16 +10,16 @@ NS_ASSUME_NONNULL_BEGIN /** - An Enumeration Representing Approval of Services. + An Enumeration Representing Services. */ -typedef NSString *FBSettingsApprovalService NS_STRING_ENUM; +typedef NSString *FBTargetSettingsService NS_STRING_ENUM; -extern FBSettingsApprovalService const FBSettingsApprovalServiceContacts; -extern FBSettingsApprovalService const FBSettingsApprovalServicePhotos; -extern FBSettingsApprovalService const FBSettingsApprovalServiceCamera; -extern FBSettingsApprovalService const FBSettingsApprovalServiceLocation; -extern FBSettingsApprovalService const FBSettingsApprovalServiceMicrophone; -extern FBSettingsApprovalService const FBSettingsApprovalServiceUrl; -extern FBSettingsApprovalService const FBSettingsApprovalServiceNotification; +extern FBTargetSettingsService const FBTargetSettingsServiceContacts; +extern FBTargetSettingsService const FBTargetSettingsServicePhotos; +extern FBTargetSettingsService const FBTargetSettingsServiceCamera; +extern FBTargetSettingsService const FBTargetSettingsServiceLocation; +extern FBTargetSettingsService const FBTargetSettingsServiceMicrophone; +extern FBTargetSettingsService const FBTargetSettingsServiceUrl; +extern FBTargetSettingsService const FBTargetSettingsServiceNotification; NS_ASSUME_NONNULL_END diff --git a/FBControlCore/Commands/FBSettingsCommands.m b/FBControlCore/Commands/FBSettingsCommands.m index dc85ac590..cb8dbfc5c 100644 --- a/FBControlCore/Commands/FBSettingsCommands.m +++ b/FBControlCore/Commands/FBSettingsCommands.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -7,10 +7,10 @@ #import "FBSettingsCommands.h" -FBSettingsApprovalService const FBSettingsApprovalServiceContacts = @"contacts"; -FBSettingsApprovalService const FBSettingsApprovalServicePhotos = @"photos"; -FBSettingsApprovalService const FBSettingsApprovalServiceCamera = @"camera"; -FBSettingsApprovalService const FBSettingsApprovalServiceLocation = @"location"; -FBSettingsApprovalService const FBSettingsApprovalServiceMicrophone = @"microphone"; -FBSettingsApprovalService const FBSettingsApprovalServiceUrl = @"url"; -FBSettingsApprovalService const FBSettingsApprovalServiceNotification = @"notification"; +FBTargetSettingsService const FBTargetSettingsServiceContacts = @"contacts"; +FBTargetSettingsService const FBTargetSettingsServicePhotos = @"photos"; +FBTargetSettingsService const FBTargetSettingsServiceCamera = @"camera"; +FBTargetSettingsService const FBTargetSettingsServiceLocation = @"location"; +FBTargetSettingsService const FBTargetSettingsServiceMicrophone = @"microphone"; +FBTargetSettingsService const FBTargetSettingsServiceUrl = @"url"; +FBTargetSettingsService const FBTargetSettingsServiceNotification = @"notification"; diff --git a/FBControlCore/Commands/FBVideoRecordingCommands.h b/FBControlCore/Commands/FBVideoRecordingCommands.h index 8350354d9..a31dc429c 100644 --- a/FBControlCore/Commands/FBVideoRecordingCommands.h +++ b/FBControlCore/Commands/FBVideoRecordingCommands.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Commands/FBVideoStreamCommands.h b/FBControlCore/Commands/FBVideoStreamCommands.h index 834bb5e47..a841efc0c 100644 --- a/FBControlCore/Commands/FBVideoStreamCommands.h +++ b/FBControlCore/Commands/FBVideoStreamCommands.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Commands/FBXCTestCommands.h b/FBControlCore/Commands/FBXCTestCommands.h index 9a176f966..b2ad2e1c3 100644 --- a/FBControlCore/Commands/FBXCTestCommands.h +++ b/FBControlCore/Commands/FBXCTestCommands.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Commands/FBXCTraceRecordCommands.h b/FBControlCore/Commands/FBXCTraceRecordCommands.h index 2ea530d38..c19fd8016 100644 --- a/FBControlCore/Commands/FBXCTraceRecordCommands.h +++ b/FBControlCore/Commands/FBXCTraceRecordCommands.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Commands/FBXCTraceRecordCommands.m b/FBControlCore/Commands/FBXCTraceRecordCommands.m index c1203f7ca..1698f2144 100644 --- a/FBControlCore/Commands/FBXCTraceRecordCommands.m +++ b/FBControlCore/Commands/FBXCTraceRecordCommands.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Commands/FBiOSTargetCommandForwarder.h b/FBControlCore/Commands/FBiOSTargetCommandForwarder.h index a5b5da650..6974df027 100644 --- a/FBControlCore/Commands/FBiOSTargetCommandForwarder.h +++ b/FBControlCore/Commands/FBiOSTargetCommandForwarder.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Commands/FBiOSTargetCommandForwarder.m b/FBControlCore/Commands/FBiOSTargetCommandForwarder.m index 2a94f79c0..69576b6a8 100644 --- a/FBControlCore/Commands/FBiOSTargetCommandForwarder.m +++ b/FBControlCore/Commands/FBiOSTargetCommandForwarder.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Configuration/FBApplicationLaunchConfiguration.h b/FBControlCore/Configuration/FBApplicationLaunchConfiguration.h index f0c27a596..c380585aa 100644 --- a/FBControlCore/Configuration/FBApplicationLaunchConfiguration.h +++ b/FBControlCore/Configuration/FBApplicationLaunchConfiguration.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Configuration/FBApplicationLaunchConfiguration.m b/FBControlCore/Configuration/FBApplicationLaunchConfiguration.m index 9cfe82ca8..9eaec3ed3 100644 --- a/FBControlCore/Configuration/FBApplicationLaunchConfiguration.m +++ b/FBControlCore/Configuration/FBApplicationLaunchConfiguration.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Configuration/FBArchitectureProcessAdapter.h b/FBControlCore/Configuration/FBArchitectureProcessAdapter.h new file mode 100644 index 000000000..08bc0680f --- /dev/null +++ b/FBControlCore/Configuration/FBArchitectureProcessAdapter.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +@class FBProcessSpawnConfiguration; + +@interface FBArchitectureProcessAdapter : NSObject + +/// Force binaries to be launched in desired architectures. +/// +/// Convenience method for `-[FBArchitectureProcessAdapter adaptProcessConfiguration:toAnyArchitectureIn:hostArchitectures:queue:temporaryDirectory:]` +-(FBFuture *)adaptProcessConfiguration:(FBProcessSpawnConfiguration *)processConfiguration toAnyArchitectureIn:(NSSet *)requestedArchitectures queue:(dispatch_queue_t)queue temporaryDirectory:(NSURL *)temporaryDirectory; + +/// Force binaries to be launched in desired architectures. +/// +/// Up to Xcode 14.2, subprocesses were spawned in the same architecture as parent process by default. +/// But from Xcode 14.3, subprocesses are spawned in arm64 when running on a arm64, regardless of parent process architecture. +/// To force subprocess being spawned in other architecture, there is `arch` utility that does not work in simulator context. +/// +/// As a workaround, to bring predictability into which architecture spawned process will be spawned, +/// we lipo-thin the executable to an architecture supported by the host machine. +/// +/// The selection of the final architecture is done by comparing consiliating the architectures idb companion needs +/// the process to run with (often dictactated by the architecture of the binary code we want to inject into +/// the spawned process) and the architectures supported by the processor of the host machine. +/// +/// As an example, on an arm64 machine, when idb companion needs to inject an x86_64 lib into a process that could +/// run in either x86_64 or arm64, the target process needs to be thinned down to `x86_64` to ensure it runs in the +/// same of the lib that needs to be injected. +/// +/// - Parameters: +/// - processConfiguration: Initial process configuration +/// - toAnyArchitectureIn: Set of architectures the process needs to be spawned with. `arm64` will take precedence over `x86_64` +/// - queue: Target Queue +/// - hostArchitectures: Set of architectures supported by the host machine +/// - temporaryDirectory: Target directory where we put lipoed binary +-(FBFuture *)adaptProcessConfiguration:(FBProcessSpawnConfiguration *)processConfiguration toAnyArchitectureIn:(NSSet *)architectures hostArchitectures:(NSSet *)hostArchitectures queue:(dispatch_queue_t)queue temporaryDirectory:(NSURL *)temporaryDirectory; + + +/// Returns supported architectures based on companion launch architecture and launch under rosetta determination. ++(NSSet *)hostMachineSupportedArchitectures; + +@end + +NS_ASSUME_NONNULL_END diff --git a/FBControlCore/Configuration/FBArchitectureProcessAdapter.m b/FBControlCore/Configuration/FBArchitectureProcessAdapter.m new file mode 100644 index 000000000..1f599e338 --- /dev/null +++ b/FBControlCore/Configuration/FBArchitectureProcessAdapter.m @@ -0,0 +1,227 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import "FBArchitectureProcessAdapter.h" + +#import "FBProcessSpawnConfiguration.h" +#import "FBCollectionInformation.h" +#import "FBArchitecture.h" +#import "FBProcessBuilder.h" +#import "FBFuture.h" +#import "FBControlCoreError.h" +#import +#include + + +// https://developer.apple.com/documentation/apple-silicon/about-the-rosetta-translation-environment#Determine-Whether-Your-App-Is-Running-as-a-Translated-Binary +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-function" +static int processIsTranslated(void) +{ + int ret = 0; + size_t size = sizeof(ret); + // patternlint-disable-next-line prefer-metasystemcontrol-byname + if (sysctlbyname("sysctl.proc_translated", &ret, &size, NULL, 0) == -1) + { + if (errno == ENOENT) + return 0; + return -1; + } + return ret; +} +#pragma clang diagnostic pop + +@implementation FBArchitectureProcessAdapter + +-(FBFuture *)adaptProcessConfiguration:(FBProcessSpawnConfiguration *)processConfiguration toAnyArchitectureIn:(NSSet *)requestedArchitectures queue:(dispatch_queue_t)queue temporaryDirectory:(NSURL *)temporaryDirectory { + return [self adaptProcessConfiguration:processConfiguration toAnyArchitectureIn:requestedArchitectures hostArchitectures:[FBArchitectureProcessAdapter hostMachineSupportedArchitectures] queue:queue temporaryDirectory:temporaryDirectory]; +} + +- (nullable FBArchitecture)selectArchitectureFrom:(NSSet *)requestedArchitectures supportedArchitectures:(NSSet *)supportedArchitectures +{ + + if([requestedArchitectures containsObject:FBArchitectureArm64] && [supportedArchitectures containsObject:FBArchitectureArm64]) { + return FBArchitectureArm64; + } + + if([requestedArchitectures containsObject:FBArchitectureX86_64] && [supportedArchitectures containsObject:FBArchitectureX86_64]) { + return FBArchitectureX86_64; + } + return nil; +} + +-(FBFuture *)adaptProcessConfiguration:(FBProcessSpawnConfiguration *)processConfiguration toAnyArchitectureIn:(NSSet *)requestedArchitectures hostArchitectures:(NSSet *)hostArchitectures queue:(dispatch_queue_t)queue temporaryDirectory:(NSURL *)temporaryDirectory { + FBArchitecture architecture = [self selectArchitectureFrom:requestedArchitectures supportedArchitectures:hostArchitectures]; + if (!architecture) { + return [[FBControlCoreError + describeFormat:@"Could not select an architecture from %@ compatible with %@", [FBCollectionInformation oneLineDescriptionFromArray:requestedArchitectures.allObjects], [FBCollectionInformation oneLineDescriptionFromArray:hostArchitectures.allObjects] + ] failFuture]; + } + + return [[[self verifyArchitectureAvailable:processConfiguration.launchPath architecture:architecture queue:queue] + onQueue:queue fmap:^FBFuture *(NSNull * _) { + NSString *fileName = [[[[processConfiguration.launchPath lastPathComponent] stringByAppendingString:[[NSUUID new] UUIDString]] stringByAppendingString:@"."] stringByAppendingString:architecture]; + NSURL *filePath = [temporaryDirectory URLByAppendingPathComponent:fileName isDirectory:NO]; + return [[self extractArchitecture:architecture processConfiguration:processConfiguration queue:queue outputPath:filePath] mapReplace:[filePath path]]; + }] + onQueue:queue fmap:^FBFuture *(NSString *extractedBinary) { + return [[self getFixedupDyldFrameworkPathFromOriginalBinary:processConfiguration.launchPath queue:queue] + onQueue:queue map:^FBProcessSpawnConfiguration *(NSString *dyldFrameworkPath) { + NSMutableDictionary *updatedEnvironment = [processConfiguration.environment mutableCopy]; + // DYLD_FRAMEWORK_PATH adds additional search paths for required "*.framewosk"s in binary + // DYLD_LIBRARY_PATH adds additional search paths for required "*.dyld"s in binary + [updatedEnvironment setValue:dyldFrameworkPath forKey:@"DYLD_FRAMEWORK_PATH"]; + [updatedEnvironment setValue:dyldFrameworkPath forKey:@"DYLD_LIBRARY_PATH"]; + return [[FBProcessSpawnConfiguration alloc] initWithLaunchPath:extractedBinary arguments:processConfiguration.arguments environment:updatedEnvironment io:processConfiguration.io mode:processConfiguration.mode]; + }]; + }]; +} + +/// Verifies that we can extract desired architecture from binary +-(FBFuture *)verifyArchitectureAvailable:(NSString *)binary architecture:(FBArchitecture)architecture queue:(dispatch_queue_t)queue { + return [[[[[[[FBProcessBuilder + withLaunchPath:@"/usr/bin/lipo" arguments:@[binary, @"-verify_arch", architecture]] + withStdOutToDevNull] + withStdErrToDevNull] + runUntilCompletionWithAcceptableExitCodes:[NSSet setWithObject:@0]] + rephraseFailure:@"Desired architecture %@ not found in %@ binary", architecture, binary] + mapReplace:[NSNull null]] + timeout:10 waitingFor:@"lipo -verify_arch"]; +} + +-(FBFuture *)extractArchitecture:(FBArchitecture)architecture processConfiguration:(FBProcessSpawnConfiguration *)processConfiguration queue:(dispatch_queue_t)queue outputPath:(NSURL *)outputPath { + return [[[[[[[FBProcessBuilder + withLaunchPath:@"/usr/bin/lipo" arguments:@[processConfiguration.launchPath, @"-extract", architecture, @"-output", [outputPath path]]] + withStdOutToDevNull] + withStdErrLineReader:^(NSString * _Nonnull line) { + NSLog(@"LINE %@\n", line); + }] + runUntilCompletionWithAcceptableExitCodes:[NSSet setWithObject:@0]] + rephraseFailure:@"Failed to thin %@ architecture out from %@ binary", architecture, processConfiguration.launchPath] + mapReplace:[NSNull null]] + timeout:10 waitingFor:@"lipo -extract"]; +} + +/// After we lipoed out arch from binary, new binary placed into temporary folder. +/// That makes all dynamic library imports become incorrect. To fix that up we +/// have to specify `DYLD_FRAMEWORK_PATH` correctly. +-(FBFuture *)getFixedupDyldFrameworkPathFromOriginalBinary:(NSString *)binary queue:(dispatch_queue_t)queue { + NSString *binaryFolder = [[binary stringByResolvingSymlinksInPath] stringByDeletingLastPathComponent]; + return [[[self getOtoolInfoFromBinary:binary queue:queue] + onQueue:queue map:^NSSet *(NSString *result) { + return [self extractRpathsFromOtoolOutput:result]; + }] + onQueue:queue map:^NSString *(NSSet *result) { + NSMutableArray *rpaths = [NSMutableArray new]; + for (NSString *binaryRpath in result) { + if ([binaryRpath hasPrefix:@"@executable_path"]) { + [rpaths addObject:[binaryRpath stringByReplacingOccurrencesOfString:@"@executable_path" withString:binaryFolder]]; + } + } + return [rpaths componentsJoinedByString:@":"]; + }]; +} + +-(FBFuture *)getOtoolInfoFromBinary:(NSString *)binary queue:(dispatch_queue_t)queue { + return [[[[[[[FBProcessBuilder + withLaunchPath:@"/usr/bin/otool" arguments:@[@"-l", binary]] + withStdOutInMemoryAsString] + withStdErrToDevNull] + runUntilCompletionWithAcceptableExitCodes:[NSSet setWithObject:@0]] + rephraseFailure:@"Failed query otool -l from %@", binary] + onQueue:queue fmap:^FBFuture*(FBProcess *task) { + if (task.stdOut) { + return [FBFuture futureWithResult: task.stdOut]; + } + return [[FBControlCoreError describeFormat:@"Failed to call otool -l over %@", binary] failFuture]; + }] + timeout:10 waitingFor:@"otool -l"]; +} + +/// Extracts rpath from full otool output +/// Each `LC_RPATH` entry like +/// ``` +/// Load command 19 +/// cmd LC_RPATH +/// cmdsize 48 +/// path @executable_path/../../Frameworks/ (offset 12) +/// ``` +/// transforms to +/// ``` +/// @executable_path/../../Frameworks/ +/// ``` +-(NSSet *)extractRpathsFromOtoolOutput:(NSString *)otoolOutput { + NSArray *lines = [otoolOutput componentsSeparatedByString: @"\n"]; + NSMutableSet *result = [NSMutableSet new]; + + // Rpath entry looks like: + // ``` + // Load command 19 + // cmd LC_RPATH + // cmdsize 48 + // path @executable_path/../../Frameworks/ (offset 12) + // ``` + // So if we found occurence of `cmd LC_RPATH` rpath value will be two lines below. + NSUInteger lcRpathValueOffset = 2; + + [lines enumerateObjectsUsingBlock:^(NSString *line, NSUInteger index, BOOL *_) { + if ([self isLcPathDefinitionLine:line] && index + lcRpathValueOffset < lines.count) { + NSString *rpathLine = lines[index + lcRpathValueOffset]; + + NSString *rpath = [self extractRpathValueFromLine:rpathLine]; + if (rpath) { + [result addObject:rpath]; + } + } + }]; + return result; +} + +/// Checking for `LC_RPATH` in load commands +/// - Parameter line: Single line entry for otool output +-(bool)isLcPathDefinitionLine:(NSString *)line { + bool hasCMD = false; + bool hasLcRpath = false; + for (NSString *component in [line componentsSeparatedByString: @" "]) { + if ([component isEqualToString:@"cmd"]) { + hasCMD = true; + } else if ([component isEqualToString:@"LC_RPATH"]) { + hasLcRpath = true; + } + } + return (hasCMD && hasLcRpath); +} + +// Note: spaces in path names are not available. Currently we use adapter for binaries +// inside Xcode that has relative paths to original binary. +// And there is no spaces in paths over there. +-(nullable NSString *)extractRpathValueFromLine:(NSString *)line { + for (NSString *component in [line componentsSeparatedByString: @" "]) { + if ([component hasPrefix:@"@executable_path"]) { + return component; + } + } + return nil; +} + ++(NSSet *)hostMachineSupportedArchitectures { +#if TARGET_CPU_X86_64 + int isTranslated = processIsTranslated(); + if (isTranslated == 1) { + // Companion running as x86_64 with translation (Rosetta) -> Processor supports Arm64 and x86_64 + return [NSSet setWithArray:@[FBArchitectureArm64, FBArchitectureX86_64]]; + } else { + // Companion running as x86_64 and translation is disabled or unknown + // Assuming processor only supports x86_64 even if translation state is unknown + return [NSSet setWithArray:@[FBArchitectureX86_64]]; + } +#else + return [NSSet setWithArray:@[FBArchitectureArm64, FBArchitectureX86_64]]; +#endif +} + +@end diff --git a/FBControlCore/Configuration/FBInstrumentsConfiguration.h b/FBControlCore/Configuration/FBInstrumentsConfiguration.h index ce4f10398..6c1515fd2 100644 --- a/FBControlCore/Configuration/FBInstrumentsConfiguration.h +++ b/FBControlCore/Configuration/FBInstrumentsConfiguration.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Configuration/FBInstrumentsConfiguration.m b/FBControlCore/Configuration/FBInstrumentsConfiguration.m index 03a7dea4d..c4b9a11e9 100644 --- a/FBControlCore/Configuration/FBInstrumentsConfiguration.m +++ b/FBControlCore/Configuration/FBInstrumentsConfiguration.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Configuration/FBProcessLaunchConfiguration.h b/FBControlCore/Configuration/FBProcessLaunchConfiguration.h index 2e790b211..f0cc59c22 100644 --- a/FBControlCore/Configuration/FBProcessLaunchConfiguration.h +++ b/FBControlCore/Configuration/FBProcessLaunchConfiguration.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Configuration/FBProcessLaunchConfiguration.m b/FBControlCore/Configuration/FBProcessLaunchConfiguration.m index 2d50201f5..8829f05f4 100644 --- a/FBControlCore/Configuration/FBProcessLaunchConfiguration.m +++ b/FBControlCore/Configuration/FBProcessLaunchConfiguration.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Configuration/FBProcessSpawnConfiguration.h b/FBControlCore/Configuration/FBProcessSpawnConfiguration.h index ec10c0ab0..5a1959d25 100644 --- a/FBControlCore/Configuration/FBProcessSpawnConfiguration.h +++ b/FBControlCore/Configuration/FBProcessSpawnConfiguration.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Configuration/FBProcessSpawnConfiguration.m b/FBControlCore/Configuration/FBProcessSpawnConfiguration.m index eefd0d370..5aaeb0fd0 100644 --- a/FBControlCore/Configuration/FBProcessSpawnConfiguration.m +++ b/FBControlCore/Configuration/FBProcessSpawnConfiguration.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Configuration/FBTestLaunchConfiguration.h b/FBControlCore/Configuration/FBTestLaunchConfiguration.h index 0fcc33a85..07511d4c3 100644 --- a/FBControlCore/Configuration/FBTestLaunchConfiguration.h +++ b/FBControlCore/Configuration/FBTestLaunchConfiguration.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -21,7 +21,7 @@ NS_ASSUME_NONNULL_BEGIN /** The Designated Initializer */ -- (instancetype)initWithTestBundle:(FBBundleDescriptor *)testBundle applicationLaunchConfiguration:(FBApplicationLaunchConfiguration *)applicationLaunchConfiguration testHostBundle:(nullable FBBundleDescriptor *)testHostBundle timeout:(NSTimeInterval)timeout initializeUITesting:(BOOL)initializeUITesting useXcodebuild:(BOOL)useXcodebuild testsToRun:(nullable NSSet *)testsToRun testsToSkip:(nullable NSSet *)testsToSkip targetApplicationBundle:(nullable FBBundleDescriptor *)targetApplicationBundle xcTestRunProperties:(nullable NSDictionary *)xcTestRunProperties resultBundlePath:(nullable NSString *)resultBundlePath reportActivities:(BOOL)reportActivities coverageDirectoryPath:(nullable NSString *)coverageDirectoryPath logDirectoryPath:(nullable NSString *)logDirectoryPath; +- (instancetype)initWithTestBundle:(FBBundleDescriptor *)testBundle applicationLaunchConfiguration:(FBApplicationLaunchConfiguration *)applicationLaunchConfiguration testHostBundle:(nullable FBBundleDescriptor *)testHostBundle timeout:(NSTimeInterval)timeout initializeUITesting:(BOOL)initializeUITesting useXcodebuild:(BOOL)useXcodebuild testsToRun:(nullable NSSet *)testsToRun testsToSkip:(nullable NSSet *)testsToSkip targetApplicationBundle:(nullable FBBundleDescriptor *)targetApplicationBundle xcTestRunProperties:(nullable NSDictionary *)xcTestRunProperties resultBundlePath:(nullable NSString *)resultBundlePath reportActivities:(BOOL)reportActivities coverageDirectoryPath:(nullable NSString *)coverageDirectoryPath enableContinuousCoverageCollection:(BOOL)enableContinuousCoverageCollection logDirectoryPath:(nullable NSString *)logDirectoryPath reportResultBundle:(BOOL)reportResultBundle; /** XCTest bundle used for testing @@ -88,11 +88,21 @@ NS_ASSUME_NONNULL_BEGIN */ @property (nonatomic, copy, readonly, nullable) NSString *coverageDirectoryPath; +/** + Determines whether should enable continuous coverage collection + */ +@property (nonatomic, assign, readonly) BOOL shouldEnableContinuousCoverageCollection; + /** The Directory to use for storing logs generated during the execution of the test run. */ @property (nonatomic, nullable, copy, readonly) NSString *logDirectoryPath; +/* + Path to the result bundle. + */ +@property (nonatomic, assign, readonly) BOOL reportResultBundle; + @end NS_ASSUME_NONNULL_END diff --git a/FBControlCore/Configuration/FBTestLaunchConfiguration.m b/FBControlCore/Configuration/FBTestLaunchConfiguration.m index f3e9aa232..5682dcf53 100644 --- a/FBControlCore/Configuration/FBTestLaunchConfiguration.m +++ b/FBControlCore/Configuration/FBTestLaunchConfiguration.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -17,7 +17,7 @@ @implementation FBTestLaunchConfiguration -- (instancetype)initWithTestBundle:(FBBundleDescriptor *)testBundle applicationLaunchConfiguration:(FBApplicationLaunchConfiguration *)applicationLaunchConfiguration testHostBundle:(nullable FBBundleDescriptor *)testHostBundle timeout:(NSTimeInterval)timeout initializeUITesting:(BOOL)initializeUITesting useXcodebuild:(BOOL)useXcodebuild testsToRun:(NSSet *)testsToRun testsToSkip:(NSSet *)testsToSkip targetApplicationBundle:(nullable FBBundleDescriptor *)targetApplicationBundle xcTestRunProperties:(NSDictionary *)xcTestRunProperties resultBundlePath:(NSString *)resultBundlePath reportActivities:(BOOL)reportActivities coverageDirectoryPath:(NSString *)coverageDirectoryPath logDirectoryPath:(nullable NSString *)logDirectoryPath +- (instancetype)initWithTestBundle:(FBBundleDescriptor *)testBundle applicationLaunchConfiguration:(FBApplicationLaunchConfiguration *)applicationLaunchConfiguration testHostBundle:(nullable FBBundleDescriptor *)testHostBundle timeout:(NSTimeInterval)timeout initializeUITesting:(BOOL)initializeUITesting useXcodebuild:(BOOL)useXcodebuild testsToRun:(NSSet *)testsToRun testsToSkip:(NSSet *)testsToSkip targetApplicationBundle:(nullable FBBundleDescriptor *)targetApplicationBundle xcTestRunProperties:(NSDictionary *)xcTestRunProperties resultBundlePath:(NSString *)resultBundlePath reportActivities:(BOOL)reportActivities coverageDirectoryPath:(NSString *)coverageDirectoryPath enableContinuousCoverageCollection:(BOOL)enableContinuousCoverageCollection logDirectoryPath:(nullable NSString *)logDirectoryPath reportResultBundle:(BOOL)reportResultBundle { self = [super init]; if (!self) { @@ -37,7 +37,9 @@ - (instancetype)initWithTestBundle:(FBBundleDescriptor *)testBundle applicationL _resultBundlePath = resultBundlePath; _reportActivities = reportActivities; _coverageDirectoryPath = coverageDirectoryPath; + _shouldEnableContinuousCoverageCollection = enableContinuousCoverageCollection; _logDirectoryPath = logDirectoryPath; + _reportResultBundle = reportResultBundle; return self; } @@ -70,18 +72,20 @@ - (BOOL)isEqual:(FBTestLaunchConfiguration *)configuration (self.xcTestRunProperties == configuration.xcTestRunProperties || [self.xcTestRunProperties isEqual:configuration.xcTestRunProperties]) && (self.resultBundlePath == configuration.resultBundlePath || [self.resultBundlePath isEqual:configuration.resultBundlePath]) && (self.coverageDirectoryPath == configuration.coverageDirectoryPath || [self.coverageDirectoryPath isEqualToString:configuration.coverageDirectoryPath]) && - (self.logDirectoryPath == configuration.logDirectoryPath || [self.logDirectoryPath isEqualToString:configuration.logDirectoryPath]); + (self.shouldEnableContinuousCoverageCollection == configuration.shouldEnableContinuousCoverageCollection) && + (self.logDirectoryPath == configuration.logDirectoryPath || [self.logDirectoryPath isEqualToString:configuration.logDirectoryPath]) && + self.reportResultBundle == configuration.reportResultBundle; } - (NSUInteger)hash { - return self.testBundle.hash ^ self.applicationLaunchConfiguration.hash ^ self.testHostBundle.hash ^ (unsigned long) self.timeout ^ (unsigned long) self.shouldInitializeUITesting ^ (unsigned long) self.shouldUseXcodebuild ^ self.testsToRun.hash ^ self.testsToSkip.hash ^ self.targetApplicationBundle.hash ^ self.xcTestRunProperties.hash ^ self.resultBundlePath.hash ^ self.coverageDirectoryPath.hash ^ self.logDirectoryPath.hash; + return self.testBundle.hash ^ self.applicationLaunchConfiguration.hash ^ self.testHostBundle.hash ^ (unsigned long) self.timeout ^ (unsigned long) self.shouldInitializeUITesting ^ (unsigned long) self.shouldUseXcodebuild ^ self.testsToRun.hash ^ self.testsToSkip.hash ^ self.targetApplicationBundle.hash ^ self.xcTestRunProperties.hash ^ self.resultBundlePath.hash ^ self.coverageDirectoryPath.hash ^ (unsigned long) self.shouldEnableContinuousCoverageCollection ^ self.logDirectoryPath.hash; } - (NSString *)description { return [NSString stringWithFormat: - @"FBTestLaunchConfiguration TestBundle %@ | AppConfig %@ | HostBundle %@ | UITesting %d | UseXcodebuild %d | TestsToRun %@ | TestsToSkip %@ | Target application bundle %@ xcTestRunProperties %@ | ResultBundlePath %@ | CoverageDirPath %@ | LogDirectoryPath %@" , + @"FBTestLaunchConfiguration TestBundle %@ | AppConfig %@ | HostBundle %@ | UITesting %d | UseXcodebuild %d | TestsToRun %@ | TestsToSkip %@ | Target application bundle %@ xcTestRunProperties %@ | ResultBundlePath %@ | CoverageDirPath %@ | EnableContinuousCoverageCollection %d | LogDirectoryPath %@ | ReportResultBundle %d" , self.testBundle, self.applicationLaunchConfiguration, self.testHostBundle, @@ -93,7 +97,9 @@ - (NSString *)description self.xcTestRunProperties, self.resultBundlePath, self.coverageDirectoryPath, - self.logDirectoryPath + self.shouldEnableContinuousCoverageCollection, + self.logDirectoryPath, + self.reportResultBundle ]; } diff --git a/FBControlCore/Configuration/FBVideoStreamConfiguration.h b/FBControlCore/Configuration/FBVideoStreamConfiguration.h index e4b22e3f4..53b185512 100644 --- a/FBControlCore/Configuration/FBVideoStreamConfiguration.h +++ b/FBControlCore/Configuration/FBVideoStreamConfiguration.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -31,7 +31,7 @@ extern FBVideoStreamEncoding const FBVideoStreamEncodingMinicap; @param compressionQuality the compression quality to use. @param scaleFactor the scale factor, between 0-1. nil for no scaling. */ -- (instancetype)initWithEncoding:(FBVideoStreamEncoding)encoding framesPerSecond:(nullable NSNumber *)framesPerSecond compressionQuality:(nullable NSNumber *)compressionQuality scaleFactor:(nullable NSNumber *)scaleFactor; +- (instancetype)initWithEncoding:(FBVideoStreamEncoding)encoding framesPerSecond:(nullable NSNumber *)framesPerSecond compressionQuality:(nullable NSNumber *)compressionQuality scaleFactor:(nullable NSNumber *)scaleFactor avgBitrate:(nullable NSNumber *)avgBitrate keyFrameRate:(nullable NSNumber *)keyFrameRate; /** The encoding of the stream. @@ -54,6 +54,16 @@ extern FBVideoStreamEncoding const FBVideoStreamEncodingMinicap; */ @property (nonatomic, copy, nullable, readonly) NSNumber *scaleFactor; +/** + Average bitrate. + */ +@property (nonatomic, copy, nullable, readonly) NSNumber *avgBitrate; + +/** + Send a key frame every N seconds. + */ +@property (nonatomic, copy, nullable, readonly) NSNumber *keyFrameRate; + @end NS_ASSUME_NONNULL_END diff --git a/FBControlCore/Configuration/FBVideoStreamConfiguration.m b/FBControlCore/Configuration/FBVideoStreamConfiguration.m index 65ae9d67a..85cbd906e 100644 --- a/FBControlCore/Configuration/FBVideoStreamConfiguration.m +++ b/FBControlCore/Configuration/FBVideoStreamConfiguration.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -20,7 +20,7 @@ @implementation FBVideoStreamConfiguration #pragma mark Initializers -- (instancetype)initWithEncoding:(FBVideoStreamEncoding)encoding framesPerSecond:(nullable NSNumber *)framesPerSecond compressionQuality:(nullable NSNumber *)compressionQuality scaleFactor:(nullable NSNumber *)scaleFactor +- (instancetype)initWithEncoding:(FBVideoStreamEncoding)encoding framesPerSecond:(nullable NSNumber *)framesPerSecond compressionQuality:(nullable NSNumber *)compressionQuality scaleFactor:(nullable NSNumber *)scaleFactor avgBitrate:(nullable NSNumber *)avgBitrate keyFrameRate:(nullable NSNumber *) keyFrameRate { self = [super init]; if (!self) { @@ -31,6 +31,8 @@ - (instancetype)initWithEncoding:(FBVideoStreamEncoding)encoding framesPerSecond _framesPerSecond = framesPerSecond; _compressionQuality = compressionQuality ?: @0.2; _scaleFactor = scaleFactor; + _avgBitrate = avgBitrate; + _keyFrameRate = keyFrameRate ?: @10.0; return self; } @@ -54,22 +56,26 @@ - (BOOL)isEqual:(FBVideoStreamConfiguration *)object return (self.encoding == object.encoding || [self.encoding isEqualToString:object.encoding]) && (self.framesPerSecond == object.framesPerSecond || [self.framesPerSecond isEqualToNumber:object.framesPerSecond]) && (self.compressionQuality == object.compressionQuality || [self.compressionQuality isEqualToNumber:object.compressionQuality]) - && (self.scaleFactor == object.scaleFactor || [self.scaleFactor isEqualToNumber:object.scaleFactor]); + && (self.scaleFactor == object.scaleFactor || [self.scaleFactor isEqualToNumber:object.scaleFactor]) + && (self.avgBitrate == object.avgBitrate || [self.avgBitrate isEqualToNumber:object.avgBitrate]) + && (self.keyFrameRate == object.keyFrameRate || [self.keyFrameRate isEqualToNumber:object.keyFrameRate]); } - (NSUInteger)hash { - return self.encoding.hash ^ self.framesPerSecond.hash ^ self.compressionQuality.hash ^ self.scaleFactor.hash; + return self.encoding.hash ^ self.framesPerSecond.hash ^ self.compressionQuality.hash ^ self.scaleFactor.hash ^ self.avgBitrate.hash ^ self.keyFrameRate.hash; } - (NSString *)description { return [NSString stringWithFormat: - @"Encoding %@ | FPS %@ | Quality %@ | Scale %@", + @"Encoding %@ | FPS %@ | Quality %@ | Scale %@ | Avg Bitrate %@ | Key frame rate %@", self.encoding, self.framesPerSecond, self.compressionQuality, - self.scaleFactor + self.scaleFactor, + self.avgBitrate, + self.keyFrameRate ]; } diff --git a/FBControlCore/Configuration/FBXCTestShimConfiguration.h b/FBControlCore/Configuration/FBXCTestShimConfiguration.h index ef3d3db47..f81ce81d0 100644 --- a/FBControlCore/Configuration/FBXCTestShimConfiguration.h +++ b/FBControlCore/Configuration/FBXCTestShimConfiguration.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Configuration/FBXCTestShimConfiguration.m b/FBControlCore/Configuration/FBXCTestShimConfiguration.m index 587d2fbb3..ab919113d 100644 --- a/FBControlCore/Configuration/FBXCTestShimConfiguration.m +++ b/FBControlCore/Configuration/FBXCTestShimConfiguration.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Configuration/FBXCTraceConfiguration.h b/FBControlCore/Configuration/FBXCTraceConfiguration.h index 61f168437..77a317d2f 100644 --- a/FBControlCore/Configuration/FBXCTraceConfiguration.h +++ b/FBControlCore/Configuration/FBXCTraceConfiguration.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Configuration/FBXCTraceConfiguration.m b/FBControlCore/Configuration/FBXCTraceConfiguration.m index 531938465..d8cdc48cb 100644 --- a/FBControlCore/Configuration/FBXCTraceConfiguration.m +++ b/FBControlCore/Configuration/FBXCTraceConfiguration.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Configuration/FBiOSTargetConfiguration.h b/FBControlCore/Configuration/FBiOSTargetConfiguration.h index 4e92df6b8..3cd2273ef 100644 --- a/FBControlCore/Configuration/FBiOSTargetConfiguration.h +++ b/FBControlCore/Configuration/FBiOSTargetConfiguration.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -54,6 +54,18 @@ extern FBDeviceModel const FBDeviceModeliPhone12mini; extern FBDeviceModel const FBDeviceModeliPhone12; extern FBDeviceModel const FBDeviceModeliPhone12Pro; extern FBDeviceModel const FBDeviceModeliPhone12ProMax; +extern FBDeviceModel const FBDeviceModeliPhone13mini; +extern FBDeviceModel const FBDeviceModeliPhone13; +extern FBDeviceModel const FBDeviceModeliPhone13Pro; +extern FBDeviceModel const FBDeviceModeliPhone13ProMax; +extern FBDeviceModel const FBDeviceModeliPhone14; +extern FBDeviceModel const FBDeviceModeliPhone14Plus; +extern FBDeviceModel const FBDeviceModeliPhone14Pro; +extern FBDeviceModel const FBDeviceModeliPhone14ProMax; +extern FBDeviceModel const FBDeviceModeliPhone15; +extern FBDeviceModel const FBDeviceModeliPhone15Plus; +extern FBDeviceModel const FBDeviceModeliPhone15Pro; +extern FBDeviceModel const FBDeviceModeliPhone15ProMax; extern FBDeviceModel const FBDeviceModeliPodTouch_7thGeneration; extern FBDeviceModel const FBDeviceModeliPad2; extern FBDeviceModel const FBDeviceModeliPad_6thGeneration; @@ -226,11 +238,6 @@ extern FBOSVersionName const FBOSVersionNamemac; */ @property (nonatomic, copy, readonly) FBArchitecture deviceArchitecture; -/** - The Native Simulator Arhitecture. - */ -@property (nonatomic, copy, readonly) FBArchitecture simulatorArchitecture; - /** The Supported Product Family. */ @@ -310,7 +317,7 @@ extern FBOSVersionName const FBOSVersionNamemac; /** Maps the architechture of the target to the compatible architechtures for binaries on the target. */ -@property (class, nonatomic, copy, readonly) NSDictionary *> *baseArchToCompatibleArch; ++ (NSSet *)baseArchsToCompatibleArch:(NSArray*)architectures; @end diff --git a/FBControlCore/Configuration/FBiOSTargetConfiguration.m b/FBControlCore/Configuration/FBiOSTargetConfiguration.m index 18d4ac886..61aab70be 100644 --- a/FBControlCore/Configuration/FBiOSTargetConfiguration.m +++ b/FBControlCore/Configuration/FBiOSTargetConfiguration.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -34,6 +34,18 @@ FBDeviceModel const FBDeviceModeliPhone12 = @"iPhone 12"; FBDeviceModel const FBDeviceModeliPhone12Pro = @"iPhone 12 Pro"; FBDeviceModel const FBDeviceModeliPhone12ProMax = @"iPhone 12 Pro Max"; +FBDeviceModel const FBDeviceModeliPhone13mini = @"iPhone 13 mini"; +FBDeviceModel const FBDeviceModeliPhone13 = @"iPhone 13"; +FBDeviceModel const FBDeviceModeliPhone13Pro = @"iPhone 13 Pro"; +FBDeviceModel const FBDeviceModeliPhone13ProMax = @"iPhone 13 Pro Max"; +FBDeviceModel const FBDeviceModeliPhone14 = @"iPhone 14"; +FBDeviceModel const FBDeviceModeliPhone14Plus = @"iPhone 14 Plus"; +FBDeviceModel const FBDeviceModeliPhone14Pro = @"iPhone 14 Pro"; +FBDeviceModel const FBDeviceModeliPhone14ProMax = @"iPhone 14 Pro Max"; +FBDeviceModel const FBDeviceModeliPhone15 = @"iPhone 15"; +FBDeviceModel const FBDeviceModeliPhone15Plus = @"iPhone 15 Plus"; +FBDeviceModel const FBDeviceModeliPhone15Pro = @"iPhone 15 Pro"; +FBDeviceModel const FBDeviceModeliPhone15ProMax = @"iPhone 15 Pro Max"; FBDeviceModel const FBDeviceModeliPodTouch_7thGeneration = @"iPod touch (7th generation)"; FBDeviceModel const FBDeviceModeliPad2 = @"iPad 2"; FBDeviceModel const FBDeviceModeliPadRetina = @"iPad Retina"; @@ -217,10 +229,10 @@ @implementation FBDeviceType + (instancetype)genericWithName:(NSString *)name { - return [[self alloc] initWithModel:name productTypes:NSSet.set deviceArchitecture:FBArchitectureArm64 simulatorArchitecture:FBArchitectureX86_64 family:FBControlCoreProductFamilyUnknown]; + return [[self alloc] initWithModel:name productTypes:NSSet.set deviceArchitecture:FBArchitectureArm64 family:FBControlCoreProductFamilyUnknown]; } -- (instancetype)initWithModel:(FBDeviceModel)model productTypes:(NSSet *)productTypes deviceArchitecture:(FBArchitecture)deviceArchitecture simulatorArchitecture:(FBArchitecture)simulatorArchitecture family:(FBControlCoreProductFamily)family +- (instancetype)initWithModel:(FBDeviceModel)model productTypes:(NSSet *)productTypes deviceArchitecture:(FBArchitecture)deviceArchitecture family:(FBControlCoreProductFamily)family { self = [super init]; if (!self) { @@ -230,7 +242,6 @@ - (instancetype)initWithModel:(FBDeviceModel)model productTypes:(NSSet *)productTypes deviceArchitecture:(FBArchitecture)deviceArchitecture simulatorArchitecture:(FBArchitecture)simulatorArchitecture ++ (instancetype)iPhoneWithModel:(FBDeviceModel)model productTypes:(NSArray *)productTypes deviceArchitecture:(FBArchitecture)deviceArchitecture { - return [[self alloc] initWithModel:model productTypes:[NSSet setWithArray:productTypes] deviceArchitecture:deviceArchitecture simulatorArchitecture:simulatorArchitecture family:FBControlCoreProductFamilyiPhone]; + return [[self alloc] initWithModel:model productTypes:[NSSet setWithArray:productTypes] deviceArchitecture:deviceArchitecture family:FBControlCoreProductFamilyiPhone]; } -+ (instancetype)iPadWithModel:(FBDeviceModel)model productTypes:(NSArray *)productTypes deviceArchitecture:(FBArchitecture)deviceArchitecture simulatorArchitecture:(FBArchitecture)simulatorArchitecture ++ (instancetype)iPadWithModel:(FBDeviceModel)model productTypes:(NSArray *)productTypes deviceArchitecture:(FBArchitecture)deviceArchitecture { - return [[self alloc] initWithModel:model productTypes:[NSSet setWithArray:productTypes] deviceArchitecture:deviceArchitecture simulatorArchitecture:simulatorArchitecture family:FBControlCoreProductFamilyiPad]; + return [[self alloc] initWithModel:model productTypes:[NSSet setWithArray:productTypes] deviceArchitecture:deviceArchitecture family:FBControlCoreProductFamilyiPad]; } -+ (instancetype)tvWithModel:(FBDeviceModel)model productTypes:(NSArray *)productTypes deviceArchitecture:(FBArchitecture)deviceArchitecture simulatorArchitecture:(FBArchitecture)simulatorArchitecture ++ (instancetype)tvWithModel:(FBDeviceModel)model productTypes:(NSArray *)productTypes deviceArchitecture:(FBArchitecture)deviceArchitecture { - return [[self alloc] initWithModel:model productTypes:[NSSet setWithArray:productTypes] deviceArchitecture:deviceArchitecture simulatorArchitecture:simulatorArchitecture family:FBControlCoreProductFamilyAppleTV]; + return [[self alloc] initWithModel:model productTypes:[NSSet setWithArray:productTypes] deviceArchitecture:deviceArchitecture family:FBControlCoreProductFamilyAppleTV]; } -+ (instancetype)watchWithModel:(FBDeviceModel)model productTypes:(NSArray *)productTypes deviceArchitecture:(FBArchitecture)deviceArchitecture simulatorArchitecture:(FBArchitecture)simulatorArchitecture ++ (instancetype)watchWithModel:(FBDeviceModel)model productTypes:(NSArray *)productTypes deviceArchitecture:(FBArchitecture)deviceArchitecture { - return [[self alloc] initWithModel:model productTypes:[NSSet setWithArray:productTypes] deviceArchitecture:deviceArchitecture simulatorArchitecture:simulatorArchitecture family:FBControlCoreProductFamilyAppleWatch]; + return [[self alloc] initWithModel:model productTypes:[NSSet setWithArray:productTypes] deviceArchitecture:deviceArchitecture family:FBControlCoreProductFamilyAppleWatch]; } + (instancetype)genericWithModel:(NSString *)model { - return [[self alloc] initWithModel:model productTypes:[NSSet set] deviceArchitecture:FBArchitectureArm64 simulatorArchitecture:FBArchitectureX86_64 family:FBControlCoreProductFamilyUnknown]; + return [[self alloc] initWithModel:model productTypes:[NSSet set] deviceArchitecture:FBArchitectureArm64 family:FBControlCoreProductFamilyUnknown]; } @end @@ -434,77 +445,89 @@ @implementation FBiOSTargetConfiguration static NSArray *deviceConfigurations; dispatch_once(&onceToken, ^{ deviceConfigurations = @[ - [FBDeviceType iPhoneWithModel:FBDeviceModeliPhone4s productType:@"iPhone4,1" deviceArchitecture:FBArchitectureArmv7 simulatorArchitecture:FBArchitectureI386], - [FBDeviceType iPhoneWithModel:FBDeviceModeliPhone5 productTypes:@[@"iPhone5,1", @"iPhone5,2"] deviceArchitecture:FBArchitectureArmv7s simulatorArchitecture:FBArchitectureI386], - [FBDeviceType iPhoneWithModel:FBDeviceModeliPhone5c productTypes:@[@"iPhone5,3"] deviceArchitecture:FBArchitectureArmv7s simulatorArchitecture:FBArchitectureI386], - [FBDeviceType iPhoneWithModel:FBDeviceModeliPhone5s productTypes:@[@"iPhone6,1", @"iPhone6,2"] deviceArchitecture:FBArchitectureArm64 simulatorArchitecture:FBArchitectureX86_64], - [FBDeviceType iPhoneWithModel:FBDeviceModeliPhone6 productType:@"iPhone7,2" deviceArchitecture:FBArchitectureArm64 simulatorArchitecture:FBArchitectureX86_64], - [FBDeviceType iPhoneWithModel:FBDeviceModeliPhone6Plus productType:@"iPhone7,1" deviceArchitecture:FBArchitectureArm64 simulatorArchitecture:FBArchitectureX86_64], - [FBDeviceType iPhoneWithModel:FBDeviceModeliPhone6S productType:@"iPhone8,1" deviceArchitecture:FBArchitectureArm64 simulatorArchitecture:FBArchitectureX86_64], - [FBDeviceType iPhoneWithModel:FBDeviceModeliPhone6SPlus productType:@"iPhone8,2" deviceArchitecture:FBArchitectureArm64 simulatorArchitecture:FBArchitectureX86_64], - [FBDeviceType iPhoneWithModel:FBDeviceModeliPhoneSE_1stGeneration productType:@"iPhone8,4" deviceArchitecture:FBArchitectureArm64 simulatorArchitecture:FBArchitectureX86_64], - [FBDeviceType iPhoneWithModel:FBDeviceModeliPhoneSE_2ndGeneration productType:@"iPhone12,8" deviceArchitecture:FBArchitectureArm64 simulatorArchitecture:FBArchitectureX86_64], - [FBDeviceType iPhoneWithModel:FBDeviceModeliPhone7 productTypes:@[@"iPhone9,1", @"iPhone9,2"] deviceArchitecture:FBArchitectureArm64 simulatorArchitecture:FBArchitectureX86_64], - [FBDeviceType iPhoneWithModel:FBDeviceModeliPhone7Plus productTypes:@[@"iPhone9,2", @"iPhone9,4"] deviceArchitecture:FBArchitectureArm64 simulatorArchitecture:FBArchitectureX86_64], - [FBDeviceType iPhoneWithModel:FBDeviceModeliPhone8 productTypes:@[@"iPhone10,1", @"iPhone10,4"] deviceArchitecture:FBArchitectureArm64 simulatorArchitecture:FBArchitectureX86_64], - [FBDeviceType iPhoneWithModel:FBDeviceModeliPhone8Plus productTypes:@[@"iPhone10,2", @"iPhone10,5"] deviceArchitecture:FBArchitectureArm64 simulatorArchitecture:FBArchitectureX86_64], - [FBDeviceType iPhoneWithModel:FBDeviceModeliPhoneX productTypes:@[@"iPhone10,3", @"iPhone10,6"] deviceArchitecture:FBArchitectureArm64 simulatorArchitecture:FBArchitectureX86_64], - [FBDeviceType iPhoneWithModel:FBDeviceModeliPhoneXs productTypes:@[@"iPhone11,2"] deviceArchitecture:FBArchitectureArm64 simulatorArchitecture:FBArchitectureX86_64], - [FBDeviceType iPhoneWithModel:FBDeviceModeliPhoneXsMax productTypes:@[@"iPhone11,6"] deviceArchitecture:FBArchitectureArm64 simulatorArchitecture:FBArchitectureX86_64], - [FBDeviceType iPhoneWithModel:FBDeviceModeliPhoneXr productTypes:@[@"iPhone11,8"] deviceArchitecture:FBArchitectureArm64 simulatorArchitecture:FBArchitectureX86_64], - [FBDeviceType iPhoneWithModel:FBDeviceModeliPhone11 productTypes:@[@"iPhone12,1"] deviceArchitecture:FBArchitectureArm64 simulatorArchitecture:FBArchitectureX86_64], - [FBDeviceType iPhoneWithModel:FBDeviceModeliPhone11Pro productTypes:@[@"iPhone12,3"] deviceArchitecture:FBArchitectureArm64 simulatorArchitecture:FBArchitectureX86_64], - [FBDeviceType iPhoneWithModel:FBDeviceModeliPhone11ProMax productTypes:@[@"iPhone12,5"] deviceArchitecture:FBArchitectureArm64 simulatorArchitecture:FBArchitectureX86_64], - [FBDeviceType iPhoneWithModel:FBDeviceModeliPhone12mini productTypes:@[@"iPhone13,1"] deviceArchitecture:FBArchitectureArm64 simulatorArchitecture:FBArchitectureX86_64], - [FBDeviceType iPhoneWithModel:FBDeviceModeliPhone12 productTypes:@[@"iPhone13,2"] deviceArchitecture:FBArchitectureArm64 simulatorArchitecture:FBArchitectureX86_64], - [FBDeviceType iPhoneWithModel:FBDeviceModeliPhone12Pro productTypes:@[@"iPhone13,3"] deviceArchitecture:FBArchitectureArm64 simulatorArchitecture:FBArchitectureX86_64], - [FBDeviceType iPhoneWithModel:FBDeviceModeliPhone12ProMax productTypes:@[@"iPhone13,4"] deviceArchitecture:FBArchitectureArm64 simulatorArchitecture:FBArchitectureX86_64], - [FBDeviceType iPhoneWithModel:FBDeviceModeliPodTouch_7thGeneration productTypes:@[@"iPod9,1"] deviceArchitecture:FBArchitectureArm64 simulatorArchitecture:FBArchitectureX86_64], - [FBDeviceType iPadWithModel:FBDeviceModeliPad2 productTypes:@[@"iPad2,1", @"iPad2,2", @"iPad2,3", @"iPad2,4"] deviceArchitecture:FBArchitectureArmv7 simulatorArchitecture:FBArchitectureI386], - [FBDeviceType iPadWithModel:FBDeviceModeliPadRetina productTypes:@[@"iPad3,1", @"iPad3,2", @"iPad3,3", @"iPad3,4", @"iPad3,5", @"iPad3,6"] deviceArchitecture:FBArchitectureArmv7 simulatorArchitecture:FBArchitectureI386], - [FBDeviceType iPadWithModel:FBDeviceModeliPadAir productTypes:@[@"iPad4,1", @"iPad4,2", @"iPad4,3"] deviceArchitecture:FBArchitectureArm64 simulatorArchitecture:FBArchitectureX86_64], - [FBDeviceType iPadWithModel:FBDeviceModeliPadAir2 productTypes:@[@"iPad5,3", @"iPad5,4"] deviceArchitecture:FBArchitectureArm64 simulatorArchitecture:FBArchitectureX86_64], - [FBDeviceType iPadWithModel:FBDeviceModeliPadAir_3rdGeneration productTypes:@[@"iPad11,3", @"iPad11,4"] deviceArchitecture:FBArchitectureArm64 simulatorArchitecture:FBArchitectureX86_64], - [FBDeviceType iPadWithModel:FBDeviceModeliPadAir_4thGeneration productTypes:@[@"iPad13,1", @"iPad13,2"] deviceArchitecture:FBArchitectureArm64 simulatorArchitecture:FBArchitectureX86_64], - [FBDeviceType iPadWithModel:FBDeviceModeliPadPro productTypes:@[@"iPad6,7", @"iPad6,8", @"iPad6,3", @"iPad6,4"] deviceArchitecture:FBArchitectureArm64 simulatorArchitecture:FBArchitectureX86_64], - [FBDeviceType iPadWithModel:FBDeviceModeliPadPro_9_7_Inch productTypes:@[@"iPad6,3", @"iPad6,4"] deviceArchitecture:FBArchitectureArm64 simulatorArchitecture:FBArchitectureX86_64], - [FBDeviceType iPadWithModel:FBDeviceModeliPadPro_12_9_Inch productTypes:@[@"iPad6,7", @"iPad6,8"] deviceArchitecture:FBArchitectureArm64 simulatorArchitecture:FBArchitectureX86_64], - [FBDeviceType iPadWithModel:FBDeviceModeliPad_5thGeneration productTypes:@[@"iPad6,11", @"iPad6,12"] deviceArchitecture:FBArchitectureArm64 simulatorArchitecture:FBArchitectureX86_64], - [FBDeviceType iPadWithModel:FBDeviceModeliPadPro_12_9_Inch_2ndGeneration productTypes:@[@"iPad7,1", @"iPad7,2"] deviceArchitecture:FBArchitectureArm64 simulatorArchitecture:FBArchitectureX86_64], - [FBDeviceType iPadWithModel:FBDeviceModeliPadPro_10_5_Inch productTypes:@[@"iPad7,3", @"iPad7,4"] deviceArchitecture:FBArchitectureArm64 simulatorArchitecture:FBArchitectureX86_64], - [FBDeviceType iPadWithModel:FBDeviceModeliPad_6thGeneration productTypes:@[@"iPad7,5", @"iPad7,6"] deviceArchitecture:FBArchitectureArm64 simulatorArchitecture:FBArchitectureX86_64], - [FBDeviceType iPadWithModel:FBDeviceModeliPad_7thGeneration productTypes:@[@"iPad7,11", @"iPad7,12"] deviceArchitecture:FBArchitectureArm64 simulatorArchitecture:FBArchitectureX86_64], - [FBDeviceType iPadWithModel:FBDeviceModeliPad_8thGeneration productTypes:@[@"iPad11,6", @"iPad11,7"] deviceArchitecture:FBArchitectureArm64 simulatorArchitecture:FBArchitectureX86_64], - [FBDeviceType iPadWithModel:FBDeviceModeliPadPro_12_9_Inch_3rdGeneration productTypes:@[@"iPad8,5", @"iPad8,6", @"iPad8,7", @"iPad8,8"] deviceArchitecture:FBArchitectureArm64 simulatorArchitecture:FBArchitectureX86_64], - [FBDeviceType iPadWithModel:FBDeviceModeliPadPro_12_9_Inch_4thGeneration productTypes:@[@"iPad8,11", @"iPad8,12"] deviceArchitecture:FBArchitectureArm64 simulatorArchitecture:FBArchitectureX86_64], - [FBDeviceType iPadWithModel:FBDeviceModeliPadPro_11_Inch_1stGeneration productTypes:@[@"iPad8,1", @"iPad8,2", @"iPad8,3", @"iPad8,4"] deviceArchitecture:FBArchitectureArm64 simulatorArchitecture:FBArchitectureX86_64], - [FBDeviceType iPadWithModel:FBDeviceModeliPadPro_12_9nch_1stGeneration productTypes:@[@"iPad8,11", @"iPad8,12"] deviceArchitecture:FBArchitectureArm64 simulatorArchitecture:FBArchitectureX86_64], - [FBDeviceType iPadWithModel:FBDeviceModeliPadPro_12_9nch_5thGeneration productTypes:@[@"iPad13,8", @"iPad13,9", @"iPad13,10", @"iPad13,11"] deviceArchitecture:FBArchitectureArm64 simulatorArchitecture:FBArchitectureX86_64], - [FBDeviceType iPadWithModel:FBDeviceModeliPadPro_11_Inch_2ndGeneration productTypes:@[@"iPad8,9", @"iPad8,10"] deviceArchitecture:FBArchitectureArm64 simulatorArchitecture:FBArchitectureX86_64], - [FBDeviceType iPadWithModel:FBDeviceModeliPadPro_11_Inch_3ndGeneration productTypes:@[@"iPad13,4", @"iPad13,5", @"iPad13,6", @"iPad13,7"] deviceArchitecture:FBArchitectureArm64 simulatorArchitecture:FBArchitectureX86_64], - [FBDeviceType iPadWithModel:FBDeviceModeliPadMini_2 productTypes:@[@"iPad4,4", @"iPad4,5", @"iPad4,6",] deviceArchitecture:FBArchitectureArm64 simulatorArchitecture:FBArchitectureX86_64], - [FBDeviceType iPadWithModel:FBDeviceModeliPadMini_3 productTypes:@[@"iPad4,7", @"iPad4,8", @"iPad4,9"] deviceArchitecture:FBArchitectureArm64 simulatorArchitecture:FBArchitectureX86_64], - [FBDeviceType iPadWithModel:FBDeviceModeliPadMini_4 productTypes:@[@"iPad5,1", @"iPad5,2"] deviceArchitecture:FBArchitectureArm64 simulatorArchitecture:FBArchitectureX86_64], - [FBDeviceType iPadWithModel:FBDeviceModeliPadMini_5 productTypes:@[@"iPad11,1", @"iPad11,2"] deviceArchitecture:FBArchitectureArm64 simulatorArchitecture:FBArchitectureX86_64], - [FBDeviceType tvWithModel:FBDeviceModelAppleTV productTypes:@[@"AppleTV5,3"] deviceArchitecture:FBArchitectureArm64 simulatorArchitecture:FBArchitectureX86_64], - [FBDeviceType tvWithModel:FBDeviceModelAppleTV4K productTypes:@[@"AppleTV6,2"] deviceArchitecture:FBArchitectureArm64 simulatorArchitecture:FBArchitectureX86_64], - [FBDeviceType tvWithModel:FBDeviceModelAppleTV4KAt1080p productTypes:@[@"AppleTV6,2"] deviceArchitecture:FBArchitectureArm64 simulatorArchitecture:FBArchitectureX86_64], - [FBDeviceType tvWithModel:FBDeviceModelAppleTV4K_2ndGeneration productTypes:@[@"AppleTV11,1"] deviceArchitecture:FBArchitectureArm64 simulatorArchitecture:FBArchitectureX86_64], - [FBDeviceType tvWithModel:FBDeviceModelAppleTV4KAt1080p_2ndGeneration productTypes:@[@"AppleTV11,1"] deviceArchitecture:FBArchitectureArm64 simulatorArchitecture:FBArchitectureX86_64], - [FBDeviceType watchWithModel:FBDeviceModelAppleWatch38mm productTypes:@[@"Watch1,1"] deviceArchitecture:FBArchitectureArmv7 simulatorArchitecture:FBArchitectureI386], - [FBDeviceType watchWithModel:FBDeviceModelAppleWatch42mm productTypes:@[@"Watch1,2"] deviceArchitecture:FBArchitectureArmv7 simulatorArchitecture:FBArchitectureI386], - [FBDeviceType watchWithModel:FBDeviceModelAppleWatchSE_40mm productTypes:@[@"Watch1,1"] deviceArchitecture:FBArchitectureArmv7 simulatorArchitecture:FBArchitectureI386], - [FBDeviceType watchWithModel:FBDeviceModelAppleWatchSE_44mm productTypes:@[@"Watch1,2"] deviceArchitecture:FBArchitectureArmv7 simulatorArchitecture:FBArchitectureI386], - [FBDeviceType watchWithModel:FBDeviceModelAppleWatchSeries2_38mm productTypes:@[@"Watch2,1"] deviceArchitecture:FBArchitectureArmv7 simulatorArchitecture:FBArchitectureI386], - [FBDeviceType watchWithModel:FBDeviceModelAppleWatchSeries2_42mm productTypes:@[@"Watch2,2"] deviceArchitecture:FBArchitectureArmv7 simulatorArchitecture:FBArchitectureI386], - [FBDeviceType watchWithModel:FBDeviceModelAppleWatchSeries3_38mm productTypes:@[@"Watch3,1"] deviceArchitecture:FBArchitectureArmv7 simulatorArchitecture:FBArchitectureI386], - [FBDeviceType watchWithModel:FBDeviceModelAppleWatchSeries3_42mm productTypes:@[@"Watch3,2"] deviceArchitecture:FBArchitectureArmv7 simulatorArchitecture:FBArchitectureI386], - [FBDeviceType watchWithModel:FBDeviceModelAppleWatchSeries4_40mm productTypes:@[@"Watch4,1", @"Watch4,3"] deviceArchitecture:FBArchitectureArm64 simulatorArchitecture:FBArchitectureI386], - [FBDeviceType watchWithModel:FBDeviceModelAppleWatchSeries4_44mm productTypes:@[@"Watch4,2", @"Watch4,4"] deviceArchitecture:FBArchitectureArm64 simulatorArchitecture:FBArchitectureI386], - [FBDeviceType watchWithModel:FBDeviceModelAppleWatchSeries5_40mm productTypes:@[@"Watch5,1", @"Watch5,3"] deviceArchitecture:FBArchitectureArm64 simulatorArchitecture:FBArchitectureI386], - [FBDeviceType watchWithModel:FBDeviceModelAppleWatchSeries5_44mm productTypes:@[@"Watch5,2", @"Watch5,4"] deviceArchitecture:FBArchitectureArm64 simulatorArchitecture:FBArchitectureI386], - [FBDeviceType watchWithModel:FBDeviceModelAppleWatchSeries6_40mm productTypes:@[@"Watch6,1", @"Watch6,3"] deviceArchitecture:FBArchitectureArm64 simulatorArchitecture:FBArchitectureI386], - [FBDeviceType watchWithModel:FBDeviceModelAppleWatchSeries6_44mm productTypes:@[@"Watch6,2", @"Watch6,4"] deviceArchitecture:FBArchitectureArm64 simulatorArchitecture:FBArchitectureI386], + [FBDeviceType iPhoneWithModel:FBDeviceModeliPhone4s productType:@"iPhone4,1" deviceArchitecture:FBArchitectureArmv7], + [FBDeviceType iPhoneWithModel:FBDeviceModeliPhone5 productTypes:@[@"iPhone5,1", @"iPhone5,2"] deviceArchitecture:FBArchitectureArmv7s], + [FBDeviceType iPhoneWithModel:FBDeviceModeliPhone5c productTypes:@[@"iPhone5,3"] deviceArchitecture:FBArchitectureArmv7s], + [FBDeviceType iPhoneWithModel:FBDeviceModeliPhone5s productTypes:@[@"iPhone6,1", @"iPhone6,2"] deviceArchitecture:FBArchitectureArm64], + [FBDeviceType iPhoneWithModel:FBDeviceModeliPhone6 productType:@"iPhone7,2" deviceArchitecture:FBArchitectureArm64], + [FBDeviceType iPhoneWithModel:FBDeviceModeliPhone6Plus productType:@"iPhone7,1" deviceArchitecture:FBArchitectureArm64], + [FBDeviceType iPhoneWithModel:FBDeviceModeliPhone6S productType:@"iPhone8,1" deviceArchitecture:FBArchitectureArm64], + [FBDeviceType iPhoneWithModel:FBDeviceModeliPhone6SPlus productType:@"iPhone8,2" deviceArchitecture:FBArchitectureArm64], + [FBDeviceType iPhoneWithModel:FBDeviceModeliPhoneSE_1stGeneration productType:@"iPhone8,4" deviceArchitecture:FBArchitectureArm64], + [FBDeviceType iPhoneWithModel:FBDeviceModeliPhoneSE_2ndGeneration productType:@"iPhone12,8" deviceArchitecture:FBArchitectureArm64], + [FBDeviceType iPhoneWithModel:FBDeviceModeliPhone7 productTypes:@[@"iPhone9,1", @"iPhone9,2", @"iPhone9,3"] deviceArchitecture:FBArchitectureArm64], + [FBDeviceType iPhoneWithModel:FBDeviceModeliPhone7Plus productTypes:@[@"iPhone9,2", @"iPhone9,4"] deviceArchitecture:FBArchitectureArm64], + [FBDeviceType iPhoneWithModel:FBDeviceModeliPhone8 productTypes:@[@"iPhone10,1", @"iPhone10,4"] deviceArchitecture:FBArchitectureArm64], + [FBDeviceType iPhoneWithModel:FBDeviceModeliPhone8Plus productTypes:@[@"iPhone10,2", @"iPhone10,5"] deviceArchitecture:FBArchitectureArm64], + [FBDeviceType iPhoneWithModel:FBDeviceModeliPhoneX productTypes:@[@"iPhone10,3", @"iPhone10,6"] deviceArchitecture:FBArchitectureArm64], + [FBDeviceType iPhoneWithModel:FBDeviceModeliPhoneXs productTypes:@[@"iPhone11,2"] deviceArchitecture:FBArchitectureArm64], + [FBDeviceType iPhoneWithModel:FBDeviceModeliPhoneXsMax productTypes:@[@"iPhone11,6"] deviceArchitecture:FBArchitectureArm64], + [FBDeviceType iPhoneWithModel:FBDeviceModeliPhoneXr productTypes:@[@"iPhone11,8"] deviceArchitecture:FBArchitectureArm64], + [FBDeviceType iPhoneWithModel:FBDeviceModeliPhone11 productTypes:@[@"iPhone12,1"] deviceArchitecture:FBArchitectureArm64], + [FBDeviceType iPhoneWithModel:FBDeviceModeliPhone11Pro productTypes:@[@"iPhone12,3"] deviceArchitecture:FBArchitectureArm64], + [FBDeviceType iPhoneWithModel:FBDeviceModeliPhone11ProMax productTypes:@[@"iPhone12,5"] deviceArchitecture:FBArchitectureArm64], + [FBDeviceType iPhoneWithModel:FBDeviceModeliPhone12mini productTypes:@[@"iPhone13,1"] deviceArchitecture:FBArchitectureArm64], + [FBDeviceType iPhoneWithModel:FBDeviceModeliPhone12 productTypes:@[@"iPhone13,2"] deviceArchitecture:FBArchitectureArm64], + [FBDeviceType iPhoneWithModel:FBDeviceModeliPhone12Pro productTypes:@[@"iPhone13,3"] deviceArchitecture:FBArchitectureArm64], + [FBDeviceType iPhoneWithModel:FBDeviceModeliPhone12ProMax productTypes:@[@"iPhone13,4"] deviceArchitecture:FBArchitectureArm64], + [FBDeviceType iPhoneWithModel:FBDeviceModeliPhone13mini productTypes:@[@"iPhone14,4"] deviceArchitecture:FBArchitectureArm64], + [FBDeviceType iPhoneWithModel:FBDeviceModeliPhone13 productTypes:@[@"iPhone14,5"] deviceArchitecture:FBArchitectureArm64], + [FBDeviceType iPhoneWithModel:FBDeviceModeliPhone13Pro productTypes:@[@"iPhone14,2"] deviceArchitecture:FBArchitectureArm64], + [FBDeviceType iPhoneWithModel:FBDeviceModeliPhone13ProMax productTypes:@[@"iPhone14,3"] deviceArchitecture:FBArchitectureArm64], + [FBDeviceType iPhoneWithModel:FBDeviceModeliPhone14 productTypes:@[@"iPhone14,7"] deviceArchitecture:FBArchitectureArm64], + [FBDeviceType iPhoneWithModel:FBDeviceModeliPhone14Plus productTypes:@[@"iPhone14,8"] deviceArchitecture:FBArchitectureArm64], + [FBDeviceType iPhoneWithModel:FBDeviceModeliPhone14Pro productTypes:@[@"iPhone15,2"] deviceArchitecture:FBArchitectureArm64], + [FBDeviceType iPhoneWithModel:FBDeviceModeliPhone14ProMax productTypes:@[@"iPhone15,3"] deviceArchitecture:FBArchitectureArm64], + [FBDeviceType iPhoneWithModel:FBDeviceModeliPhone15 productTypes:@[@"iPhone15,4"] deviceArchitecture:FBArchitectureArm64], + [FBDeviceType iPhoneWithModel:FBDeviceModeliPhone15Plus productTypes:@[@"iPhone15,5"] deviceArchitecture:FBArchitectureArm64], + [FBDeviceType iPhoneWithModel:FBDeviceModeliPhone15Pro productTypes:@[@"iPhone16,1"] deviceArchitecture:FBArchitectureArm64], + [FBDeviceType iPhoneWithModel:FBDeviceModeliPhone15ProMax productTypes:@[@"iPhone16,2"] deviceArchitecture:FBArchitectureArm64], + [FBDeviceType iPhoneWithModel:FBDeviceModeliPodTouch_7thGeneration productTypes:@[@"iPod9,1"] deviceArchitecture:FBArchitectureArm64], + [FBDeviceType iPadWithModel:FBDeviceModeliPad2 productTypes:@[@"iPad2,1", @"iPad2,2", @"iPad2,3", @"iPad2,4"] deviceArchitecture:FBArchitectureArmv7], + [FBDeviceType iPadWithModel:FBDeviceModeliPadRetina productTypes:@[@"iPad3,1", @"iPad3,2", @"iPad3,3", @"iPad3,4", @"iPad3,5", @"iPad3,6"] deviceArchitecture:FBArchitectureArmv7], + [FBDeviceType iPadWithModel:FBDeviceModeliPadAir productTypes:@[@"iPad4,1", @"iPad4,2", @"iPad4,3"] deviceArchitecture:FBArchitectureArm64], + [FBDeviceType iPadWithModel:FBDeviceModeliPadAir2 productTypes:@[@"iPad5,3", @"iPad5,4"] deviceArchitecture:FBArchitectureArm64], + [FBDeviceType iPadWithModel:FBDeviceModeliPadAir_3rdGeneration productTypes:@[@"iPad11,3", @"iPad11,4"] deviceArchitecture:FBArchitectureArm64], + [FBDeviceType iPadWithModel:FBDeviceModeliPadAir_4thGeneration productTypes:@[@"iPad13,1", @"iPad13,2"] deviceArchitecture:FBArchitectureArm64], + [FBDeviceType iPadWithModel:FBDeviceModeliPadPro productTypes:@[@"iPad6,7", @"iPad6,8", @"iPad6,3", @"iPad6,4"] deviceArchitecture:FBArchitectureArm64], + [FBDeviceType iPadWithModel:FBDeviceModeliPadPro_9_7_Inch productTypes:@[@"iPad6,3", @"iPad6,4"] deviceArchitecture:FBArchitectureArm64], + [FBDeviceType iPadWithModel:FBDeviceModeliPadPro_12_9_Inch productTypes:@[@"iPad6,7", @"iPad6,8"] deviceArchitecture:FBArchitectureArm64], + [FBDeviceType iPadWithModel:FBDeviceModeliPad_5thGeneration productTypes:@[@"iPad6,11", @"iPad6,12"] deviceArchitecture:FBArchitectureArm64], + [FBDeviceType iPadWithModel:FBDeviceModeliPadPro_12_9_Inch_2ndGeneration productTypes:@[@"iPad7,1", @"iPad7,2"] deviceArchitecture:FBArchitectureArm64], + [FBDeviceType iPadWithModel:FBDeviceModeliPadPro_10_5_Inch productTypes:@[@"iPad7,3", @"iPad7,4"] deviceArchitecture:FBArchitectureArm64], + [FBDeviceType iPadWithModel:FBDeviceModeliPad_6thGeneration productTypes:@[@"iPad7,5", @"iPad7,6"] deviceArchitecture:FBArchitectureArm64], + [FBDeviceType iPadWithModel:FBDeviceModeliPad_7thGeneration productTypes:@[@"iPad7,11", @"iPad7,12"] deviceArchitecture:FBArchitectureArm64], + [FBDeviceType iPadWithModel:FBDeviceModeliPad_8thGeneration productTypes:@[@"iPad11,6", @"iPad11,7"] deviceArchitecture:FBArchitectureArm64], + [FBDeviceType iPadWithModel:FBDeviceModeliPadPro_12_9_Inch_3rdGeneration productTypes:@[@"iPad8,5", @"iPad8,6", @"iPad8,7", @"iPad8,8"] deviceArchitecture:FBArchitectureArm64], + [FBDeviceType iPadWithModel:FBDeviceModeliPadPro_12_9_Inch_4thGeneration productTypes:@[@"iPad8,11", @"iPad8,12"] deviceArchitecture:FBArchitectureArm64], + [FBDeviceType iPadWithModel:FBDeviceModeliPadPro_11_Inch_1stGeneration productTypes:@[@"iPad8,1", @"iPad8,2", @"iPad8,3", @"iPad8,4"] deviceArchitecture:FBArchitectureArm64], + [FBDeviceType iPadWithModel:FBDeviceModeliPadPro_12_9nch_1stGeneration productTypes:@[@"iPad8,11", @"iPad8,12"] deviceArchitecture:FBArchitectureArm64], + [FBDeviceType iPadWithModel:FBDeviceModeliPadPro_12_9nch_5thGeneration productTypes:@[@"iPad13,8", @"iPad13,9", @"iPad13,10", @"iPad13,11"] deviceArchitecture:FBArchitectureArm64], + [FBDeviceType iPadWithModel:FBDeviceModeliPadPro_11_Inch_2ndGeneration productTypes:@[@"iPad8,9", @"iPad8,10"] deviceArchitecture:FBArchitectureArm64], + [FBDeviceType iPadWithModel:FBDeviceModeliPadPro_11_Inch_3ndGeneration productTypes:@[@"iPad13,4", @"iPad13,5", @"iPad13,6", @"iPad13,7"] deviceArchitecture:FBArchitectureArm64], + [FBDeviceType iPadWithModel:FBDeviceModeliPadMini_2 productTypes:@[@"iPad4,4", @"iPad4,5", @"iPad4,6",] deviceArchitecture:FBArchitectureArm64], + [FBDeviceType iPadWithModel:FBDeviceModeliPadMini_3 productTypes:@[@"iPad4,7", @"iPad4,8", @"iPad4,9"] deviceArchitecture:FBArchitectureArm64], + [FBDeviceType iPadWithModel:FBDeviceModeliPadMini_4 productTypes:@[@"iPad5,1", @"iPad5,2"] deviceArchitecture:FBArchitectureArm64], + [FBDeviceType iPadWithModel:FBDeviceModeliPadMini_5 productTypes:@[@"iPad11,1", @"iPad11,2"] deviceArchitecture:FBArchitectureArm64], + [FBDeviceType tvWithModel:FBDeviceModelAppleTV productTypes:@[@"AppleTV5,3"] deviceArchitecture:FBArchitectureArm64], + [FBDeviceType tvWithModel:FBDeviceModelAppleTV4K productTypes:@[@"AppleTV6,2"] deviceArchitecture:FBArchitectureArm64], + [FBDeviceType tvWithModel:FBDeviceModelAppleTV4KAt1080p productTypes:@[@"AppleTV6,2"] deviceArchitecture:FBArchitectureArm64], + [FBDeviceType tvWithModel:FBDeviceModelAppleTV4K_2ndGeneration productTypes:@[@"AppleTV11,1"] deviceArchitecture:FBArchitectureArm64], + [FBDeviceType tvWithModel:FBDeviceModelAppleTV4KAt1080p_2ndGeneration productTypes:@[@"AppleTV11,1"] deviceArchitecture:FBArchitectureArm64], + [FBDeviceType watchWithModel:FBDeviceModelAppleWatch38mm productTypes:@[@"Watch1,1"] deviceArchitecture:FBArchitectureArmv7], + [FBDeviceType watchWithModel:FBDeviceModelAppleWatch42mm productTypes:@[@"Watch1,2"] deviceArchitecture:FBArchitectureArmv7], + [FBDeviceType watchWithModel:FBDeviceModelAppleWatchSE_40mm productTypes:@[@"Watch1,1"] deviceArchitecture:FBArchitectureArmv7], + [FBDeviceType watchWithModel:FBDeviceModelAppleWatchSE_44mm productTypes:@[@"Watch1,2"] deviceArchitecture:FBArchitectureArmv7], + [FBDeviceType watchWithModel:FBDeviceModelAppleWatchSeries2_38mm productTypes:@[@"Watch2,1"] deviceArchitecture:FBArchitectureArmv7], + [FBDeviceType watchWithModel:FBDeviceModelAppleWatchSeries2_42mm productTypes:@[@"Watch2,2"] deviceArchitecture:FBArchitectureArmv7], + [FBDeviceType watchWithModel:FBDeviceModelAppleWatchSeries3_38mm productTypes:@[@"Watch3,1"] deviceArchitecture:FBArchitectureArmv7], + [FBDeviceType watchWithModel:FBDeviceModelAppleWatchSeries3_42mm productTypes:@[@"Watch3,2"] deviceArchitecture:FBArchitectureArmv7], + [FBDeviceType watchWithModel:FBDeviceModelAppleWatchSeries4_40mm productTypes:@[@"Watch4,1", @"Watch4,3"] deviceArchitecture:FBArchitectureArm64], + [FBDeviceType watchWithModel:FBDeviceModelAppleWatchSeries4_44mm productTypes:@[@"Watch4,2", @"Watch4,4"] deviceArchitecture:FBArchitectureArm64], + [FBDeviceType watchWithModel:FBDeviceModelAppleWatchSeries5_40mm productTypes:@[@"Watch5,1", @"Watch5,3"] deviceArchitecture:FBArchitectureArm64], + [FBDeviceType watchWithModel:FBDeviceModelAppleWatchSeries5_44mm productTypes:@[@"Watch5,2", @"Watch5,4"] deviceArchitecture:FBArchitectureArm64], + [FBDeviceType watchWithModel:FBDeviceModelAppleWatchSeries6_40mm productTypes:@[@"Watch6,1", @"Watch6,3"] deviceArchitecture:FBArchitectureArm64], + [FBDeviceType watchWithModel:FBDeviceModelAppleWatchSeries6_44mm productTypes:@[@"Watch6,2", @"Watch6,4"] deviceArchitecture:FBArchitectureArm64], ]; }); @@ -656,15 +679,23 @@ @implementation FBiOSTargetConfiguration return mapping; } -+ (NSDictionary *> *)baseArchToCompatibleArch ++ (NSSet *)baseArchsToCompatibleArch:(NSArray*)architectures { - return @{ + + NSDictionary *> *mapping = @{ + FBArchitectureArm64e : [NSSet setWithArray:@[FBArchitectureArm64e, FBArchitectureArm64, FBArchitectureArmv7s, FBArchitectureArmv7]], FBArchitectureArm64 : [NSSet setWithArray:@[FBArchitectureArm64, FBArchitectureArmv7s, FBArchitectureArmv7]], FBArchitectureArmv7s : [NSSet setWithArray:@[FBArchitectureArmv7s, FBArchitectureArmv7]], FBArchitectureArmv7 : [NSSet setWithArray:@[FBArchitectureArmv7]], FBArchitectureI386 : [NSSet setWithObject:FBArchitectureI386], FBArchitectureX86_64 : [NSSet setWithArray:@[FBArchitectureX86_64, FBArchitectureI386]], }; + + NSMutableSet *result = [NSMutableSet new]; + for (FBArchitecture arch in architectures) { + [result unionSet:mapping[arch]]; + } + return result; } @end diff --git a/FBControlCore/Crashes/FBCrashLog.h b/FBControlCore/Crashes/FBCrashLog.h index 36ff5734c..8b6c4084c 100644 --- a/FBControlCore/Crashes/FBCrashLog.h +++ b/FBControlCore/Crashes/FBCrashLog.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -12,6 +12,7 @@ NS_ASSUME_NONNULL_BEGIN @class FBCrashLog; @protocol FBControlCoreLogger; +@protocol FBCrashLogParser; /** An emuration representing the kind of process that has crashed. @@ -80,6 +81,16 @@ typedef NS_OPTIONS(NSUInteger, FBCrashLogInfoProcessType) { */ @property (nonatomic, assign, readonly) FBCrashLogInfoProcessType processType; +/** + The description of the exception + */ +@property (nonatomic, copy, readonly, nullable) NSString *exceptionDescription; + +/** + List of symbols on the crashed thread + */ +@property (nonatomic, copy, readonly, nullable) NSString *crashedThreadDescription; + #pragma mark Helpers /** @@ -87,6 +98,7 @@ typedef NS_OPTIONS(NSUInteger, FBCrashLogInfoProcessType) { */ @property (nonatomic, class, copy, readonly) NSArray *diagnosticReportsPaths; + #pragma mark Initializers /** @@ -99,6 +111,7 @@ typedef NS_OPTIONS(NSUInteger, FBCrashLogInfoProcessType) { */ + (nullable instancetype)fromCrashLogAtPath:(NSString *)path error:(NSError **)error; + #pragma mark Public Methods /** @@ -129,6 +142,11 @@ typedef NS_OPTIONS(NSUInteger, FBCrashLogInfoProcessType) { */ - (nullable FBCrashLog *)obtainCrashLogWithError:(NSError **)error; +/** + Reads the contents of the crash log on disk, as a string. + */ + - (nullable NSString *)loadRawCrashLogStringWithError:(NSError **)error; + #pragma mark Predicates /** @@ -198,6 +216,10 @@ typedef NS_OPTIONS(NSUInteger, FBCrashLogInfoProcessType) { */ @property (nonatomic, copy, readonly) NSString *contents; + +/// Provides date formatted to parse date strings from Apple crash logs ++ (NSDateFormatter *)dateFormatter; + @end NS_ASSUME_NONNULL_END diff --git a/FBControlCore/Crashes/FBCrashLog.m b/FBControlCore/Crashes/FBCrashLog.m index 005ed6431..f7fc37b82 100644 --- a/FBControlCore/Crashes/FBCrashLog.m +++ b/FBControlCore/Crashes/FBCrashLog.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -14,9 +14,26 @@ #import "NSPredicate+FBControlCore.h" #import "FBControlCoreError.h" #import "FBControlCoreLogger.h" +#import "FBConcatedJsonParser.h" +#import "FBCrashLogParser.h" +#import @implementation FBCrashLog + ++ (NSDateFormatter *)dateFormatter +{ + static dispatch_once_t onceToken; + static NSDateFormatter *dateFormatter = nil; + dispatch_once(&onceToken, ^{ + dateFormatter = [NSDateFormatter new]; + dateFormatter.dateFormat = @"yyyy-MM-dd HH:mm:ss.SSS Z"; + dateFormatter.lenient = YES; + dateFormatter.locale = [NSLocale localeWithLocaleIdentifier:@"en_US"]; + }); + return dateFormatter; +} + #pragma mark Initializers - (instancetype)initWithInfo:(FBCrashLogInfo *)info contents:(NSString *)contents @@ -51,19 +68,52 @@ @implementation FBCrashLogInfo #pragma mark Initializers -+ (instancetype)fromCrashLogAtPath:(NSString *)crashPath error:(NSError **)error -{ ++ (nullable instancetype)fromCrashLogAtPath:(NSString *)crashPath error:(NSError **)error { if (!crashPath) { return [[FBControlCoreError describe:@"No crash path provided"] fail:error]; } - FILE *file = fopen(crashPath.UTF8String, "r"); - if (!file) { + if (![NSFileManager.defaultManager fileExistsAtPath:crashPath]) { return [[FBControlCoreError - describeFormat:@"Could not open file at path %@: %s", crashPath, strerror(errno)] + describeFormat:@"File does not exist at given crash path: %@", crashPath] fail:error]; } + if (![NSFileManager.defaultManager isReadableFileAtPath:crashPath]) { + return [[FBControlCoreError + describeFormat:@"Crash file at %@ is not readable", crashPath] + fail:error]; + } + NSData *crashFileData = [NSData dataWithContentsOfFile:crashPath options:0 error:error]; + if (!crashFileData) { + return [[FBControlCoreError + describeFormat:@"Could not read data from %@", crashPath] + fail:error]; + } else if (crashFileData.length == 0) { + return [[FBControlCoreError + describeFormat:@"Crash file at %@ is empty", crashPath] + fail:error]; + } + + NSString *crashString = [[NSString alloc] initWithData:crashFileData encoding:NSUTF8StringEncoding]; + if (!crashString) { + return [[FBControlCoreError + describeFormat:@"Could not extract string from %@", crashPath] + fail:error]; + } + + return [self fromCrashLogString:crashString crashPath:crashPath parser:[self getPreferredCrashLogParserForCrashString:crashString] error:error]; +} + ++ (id)getPreferredCrashLogParserForCrashString:(NSString *)crashString { + if (crashString.length > 0 && [crashString characterAtIndex:0] == '{') { + return [[FBConcatedJSONCrashLogParser alloc] init]; + } else { + return [[FBPlainTextCrashLogParser alloc] init]; + } +} + ++ (nullable instancetype)fromCrashLogString:(NSString *)crashString crashPath:(NSString *)crashPath parser:(id)parser error:(NSError **)error { NSString *executablePath = nil; NSString *identifier = nil; @@ -72,14 +122,65 @@ + (instancetype)fromCrashLogAtPath:(NSString *)crashPath error:(NSError **)error NSDate *date = nil; pid_t processIdentifier = -1; pid_t parentProcessIdentifier = -1; + NSString *exceptionDescription = nil; + NSString *crashedThreadDescription = nil; + + NSError *err; + [parser parseCrashLogFromString:crashString + executablePathOut:&executablePath + identifierOut:&identifier + processNameOut:&processName + parentProcessNameOut:&parentProcessName + processIdentifierOut:&processIdentifier + parentProcessIdentifierOut:&parentProcessIdentifier + dateOut:&date + exceptionDescription:&exceptionDescription + crashedThreadDescription:&crashedThreadDescription + error:&err]; + + if (err) { + return [[FBControlCoreError + describeFormat:@"Could not parse crash string %@", err] + fail:error]; + } - if (![self extractFromFile:file executablePathOut:&executablePath identifierOut:&identifier processNameOut:&processName parentProcessNameOut:&parentProcessName processIdentifierOut:&processIdentifier parentProcessIdentifierOut:&parentProcessIdentifier dateOut:&date error:error]) { - fclose(file); - return nil; + if (processName == nil) { + return [[FBControlCoreError + describe:@"Missing process name in crash log"] + fail:error]; + } + if (identifier == nil) { + return [[FBControlCoreError + describe:@"Missing identifier in crash log"] + fail:error]; + } + if (parentProcessName == nil) { + return [[FBControlCoreError + describe:@"Missing process name in crash log"] + fail:error]; + } + if (executablePath == nil) { + return [[FBControlCoreError + describe:@"Missing executable path in crash log"] + fail:error]; + } + if (processIdentifier == -1) { + return [[FBControlCoreError + describe:@"Missing process identifier in crash log"] + fail:error]; + } + if (parentProcessIdentifier == -1) { + return [[FBControlCoreError + describe:@"Missing parent process identifier in crash log"] + fail:error]; + } + if (date == nil) { + return [[FBControlCoreError + describe:@"Missing date in crash log"] + fail:error]; } FBCrashLogInfoProcessType processType = [self processTypeForExecutablePath:executablePath]; - fclose(file); return [[FBCrashLogInfo alloc] initWithCrashPath:crashPath @@ -90,11 +191,13 @@ + (instancetype)fromCrashLogAtPath:(NSString *)crashPath error:(NSError **)error parentProcessName:parentProcessName parentProcessIdentifier:parentProcessIdentifier date:date - processType:processType]; + processType:processType + exceptionDescription:exceptionDescription + crashedThreadDescription:crashedThreadDescription]; } -- (instancetype)initWithCrashPath:(NSString *)crashPath executablePath:(NSString *)executablePath identifier:(NSString *)identifier processName:(NSString *)processName processIdentifier:(pid_t)processIdentifer parentProcessName:(NSString *)parentProcessName parentProcessIdentifier:(pid_t)parentProcessIdentifier date:(NSDate *)date processType:(FBCrashLogInfoProcessType)processType -{ + +- (instancetype)initWithCrashPath:(NSString *)crashPath executablePath:(NSString *)executablePath identifier:(NSString *)identifier processName:(NSString *)processName processIdentifier:(pid_t)processIdentifer parentProcessName:(NSString *)parentProcessName parentProcessIdentifier:(pid_t)parentProcessIdentifier date:(NSDate *)date processType:(FBCrashLogInfoProcessType)processType exceptionDescription:(NSString *)exceptionDescription crashedThreadDescription:(NSString *)crashedThreadDescription{ self = [super init]; if (!self) { return nil; @@ -109,6 +212,8 @@ - (instancetype)initWithCrashPath:(NSString *)crashPath executablePath:(NSString _parentProcessIdentifier = parentProcessIdentifier; _date = date; _processType = processType; + _exceptionDescription = exceptionDescription; + _crashedThreadDescription = crashedThreadDescription; return self; } @@ -118,17 +223,9 @@ - (instancetype)initWithCrashPath:(NSString *)crashPath executablePath:(NSString + (BOOL)isParsableCrashLog:(NSData *)data { #if defined(__apple_build_version__) - if (@available(macOS 10.13, *)) { - FILE *file = fmemopen((void *)data.bytes, data.length, "r"); - if (!file) { - return NO; - } - BOOL parsable = [self extractFromFile:file executablePathOut:nil identifierOut:nil processNameOut:nil parentProcessNameOut:nil processIdentifierOut:nil parentProcessIdentifierOut:nil dateOut:nil error:nil]; - fclose(file); - return parsable; - } else { - return NO; - } + NSString *crashString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; + FBCrashLogInfo *parsable = [self fromCrashLogString:crashString crashPath:@"" parser:[self getPreferredCrashLogParserForCrashString:crashString] error:nil]; + return parsable != nil; #else return NO; #endif @@ -139,7 +236,7 @@ + (BOOL)isParsableCrashLog:(NSData *)data - (NSString *)description { return [NSString stringWithFormat: - @"Identifier %@ | Executable Path %@ | Process %@ | pid %d | Parent %@ | ppid %d | Date %@ | Path %@", + @"Identifier %@ | Executable Path %@ | Process %@ | pid %d | Parent %@ | ppid %d | Date %@ | Path %@ | Exception: %@ | Trace: %@", self.identifier, self.executablePath, self.processName, @@ -147,7 +244,9 @@ - (NSString *)description self.parentProcessName, self.parentProcessIdentifier, self.date, - self.crashPath + self.crashPath, + self.exceptionDescription, + self.crashedThreadDescription ]; } @@ -166,6 +265,11 @@ - (NSString *)name return self.crashPath.lastPathComponent; } +- (nullable NSString *)loadRawCrashLogStringWithError:(NSError **)error; +{ + return [NSString stringWithContentsOfFile:self.crashPath encoding:NSUTF8StringEncoding error:error]; +} + #pragma mark Bulk Collection + (NSArray *)crashInfoAfterDate:(NSDate *)date logger:(id)logger @@ -198,7 +302,7 @@ - (NSString *)name - (FBCrashLog *)obtainCrashLogWithError:(NSError **)error { NSError *innerError = nil; - NSString *contents = [NSString stringWithContentsOfFile:self.crashPath encoding:NSUTF8StringEncoding error:&innerError]; + NSString *contents = [self loadRawCrashLogStringWithError:&innerError]; if (!contents) { return [[[FBControlCoreError describeFormat:@"Failed to read crash log at path %@", self.crashPath] @@ -262,109 +366,6 @@ + (NSPredicate *)predicateForExecutablePathContains:(NSString *)contains #pragma mark Private -static NSUInteger MaxLineSearch = 20; - -+ (BOOL)extractFromFile:(FILE *)file executablePathOut:(NSString **)executablePathOut identifierOut:(NSString **)identifierOut processNameOut:(NSString **)processNameOut parentProcessNameOut:(NSString **)parentProcessNameOut processIdentifierOut:(pid_t *)processIdentifierOut parentProcessIdentifierOut:(pid_t *)parentProcessIdentifierOut dateOut:(NSDate **)dateOut error:(NSError **)error -{ - // Buffers for the sscanf - size_t lineSize = sizeof(char) * 4098; - char *line = malloc(lineSize); - char value[lineSize]; - - // Values that should exist after scanning - NSDate *date = nil; - NSString *executablePath = nil; - NSString *identifier = nil; - NSString *parentProcessName = nil; - NSString *processName = nil; - pid_t processIdentifier = -1; - pid_t parentProcessIdentifier = -1; - - NSUInteger lineNumber = 0; - while (lineNumber++ < MaxLineSearch && getline(&line, &lineSize, file) > 0) { - if (sscanf(line, "Process: %s [%d]", value, &processIdentifier) > 0) { - processName = [[NSString alloc] initWithCString:value encoding:NSUTF8StringEncoding]; - continue; - } - if (sscanf(line, "Identifier: %s", value) > 0) { - identifier = [[NSString alloc] initWithCString:value encoding:NSUTF8StringEncoding]; - continue; - } - if (sscanf(line, "Parent Process: %s [%d]", value, &parentProcessIdentifier) > 0) { - parentProcessName = [[NSString alloc] initWithCString:value encoding:NSUTF8StringEncoding]; - continue; - } - if (sscanf(line, "Path: %s", value) > 0) { - executablePath = [[NSString alloc] initWithCString:value encoding:NSUTF8StringEncoding]; - continue; - } - if (sscanf(line, "Date/Time: %[^\n]", value) > 0) { - NSString *dateString = [[NSString alloc] initWithCString:value encoding:NSUTF8StringEncoding]; - date = [self.dateFormatter dateFromString:dateString]; - continue; - } - } - - free(line); - if (processName == nil) { - return [[FBControlCoreError - describe:@"Missing process name in crash log"] - failBool:error]; - } - if (identifier == nil) { - return [[FBControlCoreError - describe:@"Missing identifier in crash log"] - failBool:error]; - } - if (parentProcessName == nil) { - return [[FBControlCoreError - describe:@"Missing process name in crash log"] - failBool:error]; - } - if (executablePath == nil) { - return [[FBControlCoreError - describe:@"Missing executable path in crash log"] - failBool:error]; - } - if (processIdentifier == -1) { - return [[FBControlCoreError - describe:@"Missing process identifier in crash log"] - failBool:error]; - } - if (parentProcessIdentifier == -1) { - return [[FBControlCoreError - describe:@"Missing parent process identifier in crash log"] - failBool:error]; - } - if (date == nil) { - return [[FBControlCoreError - describe:@"Missing date in crash log"] - failBool:error]; - } - if (executablePathOut) { - *executablePathOut = executablePath; - } - if (identifierOut) { - *identifierOut = identifier; - } - if (processNameOut) { - *processNameOut = processName; - } - if (parentProcessNameOut) { - *parentProcessNameOut = parentProcessName; - } - if (processIdentifierOut) { - *processIdentifierOut = processIdentifier; - } - if (parentProcessIdentifierOut) { - *parentProcessIdentifierOut = parentProcessIdentifier; - } - if (dateOut) { - *dateOut = date; - } - return YES; -} - + (FBCrashLogInfoProcessType)processTypeForExecutablePath:(NSString *)executablePath { if ([executablePath containsString:@"Platforms/iPhoneSimulator.platform"]) { @@ -393,17 +394,4 @@ + (NSPredicate *)predicateForFilesWithBasePath:(NSString *)basePath afterDate:(N ]]; } -+ (NSDateFormatter *)dateFormatter -{ - static dispatch_once_t onceToken; - static NSDateFormatter *dateFormatter = nil; - dispatch_once(&onceToken, ^{ - dateFormatter = [NSDateFormatter new]; - dateFormatter.dateFormat = @"yyyy-MM-dd HH:mm:ss.SSS Z"; - dateFormatter.lenient = YES; - dateFormatter.locale = [NSLocale localeWithLocaleIdentifier:@"en_US"]; - }); - return dateFormatter; -} - @end diff --git a/FBControlCore/Crashes/FBCrashLogNotifier.h b/FBControlCore/Crashes/FBCrashLogNotifier.h index 12df3b6e2..21b9500b3 100644 --- a/FBControlCore/Crashes/FBCrashLogNotifier.h +++ b/FBControlCore/Crashes/FBCrashLogNotifier.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Crashes/FBCrashLogNotifier.m b/FBControlCore/Crashes/FBCrashLogNotifier.m index aa415824b..be5cc8de3 100644 --- a/FBControlCore/Crashes/FBCrashLogNotifier.m +++ b/FBControlCore/Crashes/FBCrashLogNotifier.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Crashes/FBCrashLogParser.h b/FBControlCore/Crashes/FBCrashLogParser.h new file mode 100644 index 000000000..2b1722fbd --- /dev/null +++ b/FBControlCore/Crashes/FBCrashLogParser.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +@protocol FBCrashLogParser +-(void)parseCrashLogFromString:(NSString *)str executablePathOut:(NSString *_Nonnull * _Nonnull)executablePathOut identifierOut:(NSString *_Nonnull * _Nonnull)identifierOut processNameOut:(NSString *_Nonnull * _Nonnull)processNameOut parentProcessNameOut:(NSString *_Nonnull * _Nonnull)parentProcessNameOut processIdentifierOut:(pid_t *)processIdentifierOut parentProcessIdentifierOut:(pid_t *)parentProcessIdentifierOut dateOut:(NSDate *_Nonnull * _Nonnull)dateOut exceptionDescription:(NSString *_Nonnull * _Nonnull)exceptionDescription crashedThreadDescription:(NSString *_Nonnull * _Nonnull)crashedThreadDescription error:(NSError **)error; +@end + +/** + .ips file for macOS 12+ is two concatenated json strings. + 1st is is metadata json, second is content json. Some of the fields from metadata repeats in content json. Considering the facts that: + 1. The layout can be changed by apple easily + 2. Json structure inself can be easily changed + 3. Crashes is not often happening operation of idb + we prefer reliability over performance gain here and parse all json strings finding the fields that we need in all of json entries +*/ +@interface FBConcatedJSONCrashLogParser : NSObject +@end + +/** + This parser handles old plain text implementation of crash results + */ +@interface FBPlainTextCrashLogParser : NSObject +@end + +NS_ASSUME_NONNULL_END diff --git a/FBControlCore/Crashes/FBCrashLogParser.m b/FBControlCore/Crashes/FBCrashLogParser.m new file mode 100644 index 000000000..ef0537be8 --- /dev/null +++ b/FBControlCore/Crashes/FBCrashLogParser.m @@ -0,0 +1,163 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import + +#import "FBCrashLogParser.h" +#import "FBConcatedJsonParser.h" +#import "FBCrashLog.h" + +@implementation FBConcatedJSONCrashLogParser + +-(void)parseCrashLogFromString:(NSString *)str executablePathOut:(NSString *_Nonnull * _Nonnull)executablePathOut identifierOut:(NSString *_Nonnull * _Nonnull)identifierOut processNameOut:(NSString *_Nonnull * _Nonnull)processNameOut parentProcessNameOut:(NSString *_Nonnull * _Nonnull)parentProcessNameOut processIdentifierOut:(pid_t *)processIdentifierOut parentProcessIdentifierOut:(pid_t *)parentProcessIdentifierOut dateOut:(NSDate *_Nonnull * _Nonnull)dateOut exceptionDescription:(NSString *_Nonnull * _Nonnull)exceptionDescription crashedThreadDescription:(NSString *_Nonnull * _Nonnull)crashedThreadDescription error:(NSError **)error { + NSDictionary *parsedReport = [FBConcatedJsonParser parseConcatenatedJSONFromString:str error:error]; + if (!parsedReport) { + return; + } + + *executablePathOut = parsedReport[@"procPath"]; + + // Name and identifier is the same thing + *processNameOut = parsedReport[@"procName"]; + *identifierOut = parsedReport[@"procName"]; + if ([parsedReport valueForKey:@"pid"]) { + *processIdentifierOut = ((NSNumber *)parsedReport[@"pid"]).intValue; + } + + *parentProcessNameOut = parsedReport[@"parentProc"]; + if ([parsedReport valueForKey:@"parentPid"]) { + *parentProcessIdentifierOut = ((NSNumber *)parsedReport[@"parentPid"]).intValue; + } + if ([parsedReport valueForKey:@"captureTime"]) { + NSString *dateString = parsedReport[@"captureTime"]; + *dateOut = [FBCrashLog.dateFormatter dateFromString:dateString]; + } + + NSDictionary *exceptionDictionary = parsedReport[@"exception"]; + if ([exceptionDictionary isKindOfClass:[NSDictionary class]]) { + NSMutableString *exceptionDescriptionMutable = [NSMutableString new]; + NSString *exceptionType = [exceptionDictionary objectForKey:@"type"]; + NSString *exceptionSignal = [exceptionDictionary objectForKey:@"signal"]; + NSString *exceptionSubtype = [exceptionDictionary objectForKey:@"subtype"]; + + if ([exceptionType isKindOfClass:[NSString class]]) { + [exceptionDescriptionMutable appendString:exceptionType]; + } + if ([exceptionSignal isKindOfClass:[NSString class]]) { + [exceptionDescriptionMutable appendString:@" "]; + [exceptionDescriptionMutable appendString:exceptionSignal]; + } + if ([exceptionSubtype isKindOfClass:[NSString class]]) { + [exceptionDescriptionMutable appendString:@" "]; + [exceptionDescriptionMutable appendString:exceptionSubtype]; + } + *exceptionDescription = [NSString stringWithString:exceptionDescriptionMutable]; + } + + NSMutableArray *imageNames = [NSMutableArray new]; + NSArray *imageDictionaries = parsedReport[@"usedImages"]; + if ([imageDictionaries isKindOfClass:[NSArray class]]) { + for (NSDictionary *imageDictionary in imageDictionaries) { + NSString *imageName = imageDictionary[@"name"]; + if ([imageName isKindOfClass:[NSString class]]) { + [imageNames addObject:imageName]; + } + } + } + + NSArray *threads = parsedReport[@"threads"]; + + if ([threads isKindOfClass:[NSArray class]]) { + for (NSDictionary *threadDictionary in threads) { + if ([threadDictionary isKindOfClass:[NSDictionary class]] == NO) { + continue; + } + // This thread crashed + if ([[threadDictionary objectForKey:@"triggered"] boolValue]) { + NSArray *frames = threadDictionary[@"frames"]; + if ([frames isKindOfClass:[NSArray class]]) { + NSMutableString *crashedThreadDescriptionMutable = [NSMutableString new]; + for (NSDictionary *frameDictionary in frames) { + if ([frameDictionary isKindOfClass:[NSDictionary class]]) { + NSUInteger imageIndex = [frameDictionary[@"imageIndex"]unsignedIntegerValue]; + if (imageNames.count > imageIndex) { + NSString *imageNameString = imageNames[imageIndex]; + if (imageNameString.length < 30) { + imageNameString = [imageNameString stringByPaddingToLength:30 + withString:@" " + startingAtIndex:0]; + } + [crashedThreadDescriptionMutable appendString:imageNameString]; + [crashedThreadDescriptionMutable appendString:@"\t"]; + } + NSString *symbol = frameDictionary[@"symbol"]; + if ([symbol isKindOfClass:[NSString class]]) { + [crashedThreadDescriptionMutable appendString:symbol]; + [crashedThreadDescriptionMutable appendString:@"\n"]; + } + } + } + *crashedThreadDescription = [NSString stringWithString:[crashedThreadDescriptionMutable stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]]; + } + break; + } + } + } + +} + +@end + + +@implementation FBPlainTextCrashLogParser + +static NSUInteger MaxLineSearch = 20; + +-(void)parseCrashLogFromString:(NSString *)str executablePathOut:(NSString *_Nonnull * _Nonnull)executablePathOut identifierOut:(NSString *_Nonnull * _Nonnull)identifierOut processNameOut:(NSString *_Nonnull * _Nonnull)processNameOut parentProcessNameOut:(NSString *_Nonnull * _Nonnull)parentProcessNameOut processIdentifierOut:(pid_t *)processIdentifierOut parentProcessIdentifierOut:(pid_t *)parentProcessIdentifierOut dateOut:(NSDate *_Nonnull * _Nonnull)dateOut exceptionDescription:(NSString *_Nonnull * _Nonnull)exceptionDescription crashedThreadDescription:(NSString *_Nonnull * _Nonnull)crashedThreadDescription error:(NSError **)error { + + // Buffers for the sscanf + size_t lineSize = sizeof(char) * 4098; + const char *line = malloc(lineSize); + char value[lineSize]; + + NSUInteger length = [str length]; + NSUInteger paraStart = 0, paraEnd = 0, contentsEnd = 0; + NSRange currentRange; + NSUInteger linesParsed = 0; + + while (paraEnd < length && linesParsed < MaxLineSearch) + { + linesParsed += 1; + [str getParagraphStart:¶Start end:¶End contentsEnd:&contentsEnd forRange:NSMakeRange(paraEnd, 0)]; + currentRange = NSMakeRange(paraStart, contentsEnd - paraStart); + line = [[str substringWithRange:currentRange] UTF8String]; + + if (sscanf(line, "Process: %s [%d]", value, processIdentifierOut) > 0) { + *processNameOut = [[NSString alloc] initWithCString:value encoding:NSUTF8StringEncoding]; + continue; + } + if (sscanf(line, "Identifier: %s", value) > 0) { + *identifierOut = [[NSString alloc] initWithCString:value encoding:NSUTF8StringEncoding]; + continue; + } + if (sscanf(line, "Parent Process: %s [%d]", value, parentProcessIdentifierOut) > 0) { + *parentProcessNameOut = [[NSString alloc] initWithCString:value encoding:NSUTF8StringEncoding]; + continue; + } + if (sscanf(line, "Path: %s", value) > 0) { + *executablePathOut = [[NSString alloc] initWithCString:value encoding:NSUTF8StringEncoding]; + continue; + } + if (sscanf(line, "Date/Time: %[^\n]", value) > 0) { + NSString *dateString = [[NSString alloc] initWithCString:value encoding:NSUTF8StringEncoding]; + *dateOut = [FBCrashLog.dateFormatter dateFromString:dateString]; + continue; + } + } +} + +@end diff --git a/FBControlCore/FBControlCore.h b/FBControlCore/FBControlCore.h index 75a2441d9..3587d2703 100644 --- a/FBControlCore/FBControlCore.h +++ b/FBControlCore/FBControlCore.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -25,14 +25,13 @@ #import #import #import +#import #import #import #import -#import #import #import #import -#import #import #import #import @@ -50,15 +49,19 @@ #import #import #import +#import #import #import #import -#import +#import #import #import #import #import +#import #import +#import +#import #import #import #import @@ -73,9 +76,6 @@ #import #import #import -#import -#import -#import #import #import #import @@ -84,7 +84,6 @@ #import #import #import -#import #import #import #import @@ -93,3 +92,6 @@ #import #import #import +#import +#import +#import diff --git a/FBControlCore/Management/FBiOSTarget.h b/FBControlCore/Management/FBiOSTarget.h index 1244b4a6c..58114d1bd 100644 --- a/FBControlCore/Management/FBiOSTarget.h +++ b/FBControlCore/Management/FBiOSTarget.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -7,16 +7,18 @@ #import +#import #import #import -#import #import -#import #import +#import #import +#import #import #import #import +#import #import #import @@ -30,47 +32,6 @@ NS_ASSUME_NONNULL_BEGIN @class FBiOSTargetScreenInfo; @protocol FBControlCoreLogger; -/** - Uses the known values of SimDevice State, to construct an enumeration. - These mirror the values from -[SimDeviceState state]. - */ -typedef NS_ENUM(NSUInteger, FBiOSTargetState) { - FBiOSTargetStateCreating = 0, - FBiOSTargetStateShutdown = 1, - FBiOSTargetStateBooting = 2, - FBiOSTargetStateBooted = 3, - FBiOSTargetStateShuttingDown = 4, - FBiOSTargetStateDFU = 5, - FBiOSTargetStateRecovery = 6, - FBiOSTargetStateRestoreOS = 7, - FBiOSTargetStateUnknown = 99, -}; - -/** - Represents the kind of a target, device or simulator. - */ -typedef NS_OPTIONS(NSUInteger, FBiOSTargetType) { - FBiOSTargetTypeNone = 0, - FBiOSTargetTypeSimulator = 1 << 0, - FBiOSTargetTypeDevice = 1 << 1, - FBiOSTargetTypeLocalMac = 1 << 2, - FBiOSTargetTypeAll = FBiOSTargetTypeSimulator | FBiOSTargetTypeDevice | FBiOSTargetTypeLocalMac, -}; - -/** - String Representations of Simulator State. - */ -typedef NSString *FBiOSTargetStateString NS_STRING_ENUM; -extern FBiOSTargetStateString const FBiOSTargetStateStringCreating; -extern FBiOSTargetStateString const FBiOSTargetStateStringShutdown; -extern FBiOSTargetStateString const FBiOSTargetStateStringBooting; -extern FBiOSTargetStateString const FBiOSTargetStateStringBooted; -extern FBiOSTargetStateString const FBiOSTargetStateStringShuttingDown; -extern FBiOSTargetStateString const FBiOSTargetStateStringDFU; -extern FBiOSTargetStateString const FBiOSTargetStateStringRecovery; -extern FBiOSTargetStateString const FBiOSTargetStateStringRestoreOS; -extern FBiOSTargetStateString const FBiOSTargetStateStringUnknown; - /** A protocol that defines an informational target. */ @@ -98,9 +59,9 @@ extern FBiOSTargetStateString const FBiOSTargetStateStringUnknown; @property (nonatomic, copy, readonly) FBDeviceType *deviceType; /** - The Architecture of the iOS Target + Available architecture of the iOS Target */ -@property (nonatomic, copy, readonly) FBArchitecture architecture; +@property (nonatomic, copy, readonly) NSArray *architectures; /** The OS Version of the Target. @@ -129,7 +90,7 @@ extern FBiOSTargetStateString const FBiOSTargetStateStringUnknown; /** A protocol that defines an interactible and informational target. */ -@protocol FBiOSTarget +@protocol FBiOSTarget /** The Target's Logger. @@ -220,9 +181,9 @@ extern FBiOSTargetStateString FBiOSTargetStateStringFromState(FBiOSTargetState s extern FBiOSTargetState FBiOSTargetStateFromStateString(FBiOSTargetStateString stateString); /** - The canonical string representations of the target type Option Set. + The canonical string representations of the FBiOSTargetType Enum. */ -extern NSArray *FBiOSTargetTypeStringsFromTargetType(FBiOSTargetType targetType); +extern NSString *FBiOSTargetTypeStringFromTargetType(FBiOSTargetType targetType); /** A Default Comparison Function that can be called for different implementations of FBiOSTarget. @@ -244,6 +205,16 @@ extern NSPredicate *FBiOSTargetPredicateForUDID(NSString *udid); */ extern NSPredicate *FBiOSTargetPredicateForUDIDs(NSArray *udids); +/** + Constructs a future that resolves when the target resolves to a provided state. + */ +extern FBFuture *FBiOSTargetResolveState(id target, FBiOSTargetState state); + +/** + Constructs a future that resolves when the target leaves a provided state. + */ +extern FBFuture *FBiOSTargetResolveLeavesState(id target, FBiOSTargetState state); + #if defined __cplusplus }; #endif diff --git a/FBControlCore/Management/FBiOSTarget.m b/FBControlCore/Management/FBiOSTarget.m index a7707f74b..98ae60d2e 100644 --- a/FBControlCore/Management/FBiOSTarget.m +++ b/FBControlCore/Management/FBiOSTarget.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -9,17 +9,6 @@ #import "FBiOSTargetConfiguration.h" -FBiOSTargetStateString const FBiOSTargetStateStringCreating = @"Creating"; -FBiOSTargetStateString const FBiOSTargetStateStringShutdown = @"Shutdown"; -FBiOSTargetStateString const FBiOSTargetStateStringBooting = @"Booting"; -FBiOSTargetStateString const FBiOSTargetStateStringBooted = @"Booted"; -FBiOSTargetStateString const FBiOSTargetStateStringShuttingDown = @"Shutting Down"; -FBiOSTargetStateString const FBiOSTargetStateStringDFU = @"DFU"; -FBiOSTargetStateString const FBiOSTargetStateStringRecovery = @"Recovery"; -FBiOSTargetStateString const FBiOSTargetStateStringRestoreOS = @"RestoreOS"; -FBiOSTargetStateString const FBiOSTargetStateStringUnknown = @"Unknown"; - - NSString *FBiOSTargetStateStringFromState(FBiOSTargetState state) { switch (state) { @@ -74,19 +63,18 @@ FBiOSTargetState FBiOSTargetStateFromStateString(NSString *stateString) return FBiOSTargetStateUnknown; } -NSArray *FBiOSTargetTypeStringsFromTargetType(FBiOSTargetType targetType) +NSString *FBiOSTargetTypeStringFromTargetType(FBiOSTargetType targetType) { - NSMutableArray *strings = [NSMutableArray array]; - if ((targetType & FBiOSTargetTypeDevice) == FBiOSTargetTypeDevice) { - [strings addObject:@"Device"]; + if (targetType == FBiOSTargetTypeDevice) { + return @"Device"; } - if ((targetType & FBiOSTargetTypeSimulator) == FBiOSTargetTypeSimulator) { - [strings addObject:@"Simulator"]; + if (targetType == FBiOSTargetTypeSimulator) { + return @"Simulator"; } - if ((targetType & FBiOSTargetTypeLocalMac) == FBiOSTargetTypeLocalMac) { - [strings addObject:@"Mac"]; + if (targetType == FBiOSTargetTypeLocalMac) { + return @"Mac"; } - return [strings copy]; + return @"Unknown"; } NSComparisonResult FBiOSTargetComparison(id left, id right) @@ -117,13 +105,12 @@ NSComparisonResult FBiOSTargetComparison(id left, id r NSString *FBiOSTargetDescribe(id target) { return [NSString stringWithFormat: - @"%@ | %@ | %@ | %@ | %@ | %@", + @"%@ | %@ | %@ | %@ | %@ ", target.udid, target.name, FBiOSTargetStateStringFromState(target.state), target.deviceType.model, - target.osVersion, - target.architecture + target.osVersion ]; } @@ -141,3 +128,17 @@ NSComparisonResult FBiOSTargetComparison(id left, id r return [udidsSet containsObject:candidate.udid]; }]; } + +FBFuture *FBiOSTargetResolveState(id target, FBiOSTargetState state) +{ + return [FBFuture onQueue:target.workQueue resolveWhen:^ BOOL { + return target.state == state; + }]; +} + +FBFuture *FBiOSTargetResolveLeavesState(id target, FBiOSTargetState state) +{ + return [FBFuture onQueue:target.workQueue resolveWhen:^ BOOL { + return target.state != state; + }]; +} diff --git a/FBControlCore/Management/FBiOSTargetConstants.h b/FBControlCore/Management/FBiOSTargetConstants.h new file mode 100644 index 000000000..229cb9a7d --- /dev/null +++ b/FBControlCore/Management/FBiOSTargetConstants.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + An enum representing states. The values here are not guaranteed to be stable over time and should not be serialized. + FBiOSTargetStateString is guaranteed to be stable over time. + */ +typedef NS_ENUM(NSUInteger, FBiOSTargetState) { + FBiOSTargetStateCreating = 0, + FBiOSTargetStateShutdown = 1, + FBiOSTargetStateBooting = 2, + FBiOSTargetStateBooted = 3, + FBiOSTargetStateShuttingDown = 4, + FBiOSTargetStateDFU = 5, + FBiOSTargetStateRecovery = 6, + FBiOSTargetStateRestoreOS = 7, + FBiOSTargetStateUnknown = 99, +}; + +/** + Represents the kind of a target. + */ +typedef NS_ENUM(NSUInteger, FBiOSTargetType) { + FBiOSTargetTypeNone = 0, + FBiOSTargetTypeSimulator = 1 << 0, + FBiOSTargetTypeDevice = 1 << 1, + FBiOSTargetTypeLocalMac = 1 << 2, +}; + +/** + String representations of FBiOSTargetState. + */ +typedef NSString *FBiOSTargetStateString NS_STRING_ENUM; +extern FBiOSTargetStateString const FBiOSTargetStateStringCreating; +extern FBiOSTargetStateString const FBiOSTargetStateStringShutdown; +extern FBiOSTargetStateString const FBiOSTargetStateStringBooting; +extern FBiOSTargetStateString const FBiOSTargetStateStringBooted; +extern FBiOSTargetStateString const FBiOSTargetStateStringShuttingDown; +extern FBiOSTargetStateString const FBiOSTargetStateStringDFU; +extern FBiOSTargetStateString const FBiOSTargetStateStringRecovery; +extern FBiOSTargetStateString const FBiOSTargetStateStringRestoreOS; +extern FBiOSTargetStateString const FBiOSTargetStateStringUnknown; + +NS_ASSUME_NONNULL_END diff --git a/FBControlCore/Management/FBiOSTargetConstants.m b/FBControlCore/Management/FBiOSTargetConstants.m new file mode 100644 index 000000000..c15aa6c1c --- /dev/null +++ b/FBControlCore/Management/FBiOSTargetConstants.m @@ -0,0 +1,20 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import "FBiOSTarget.h" + +#import "FBiOSTargetConstants.h" + +FBiOSTargetStateString const FBiOSTargetStateStringCreating = @"Creating"; +FBiOSTargetStateString const FBiOSTargetStateStringShutdown = @"Shutdown"; +FBiOSTargetStateString const FBiOSTargetStateStringBooting = @"Booting"; +FBiOSTargetStateString const FBiOSTargetStateStringBooted = @"Booted"; +FBiOSTargetStateString const FBiOSTargetStateStringShuttingDown = @"Shutting Down"; +FBiOSTargetStateString const FBiOSTargetStateStringDFU = @"DFU"; +FBiOSTargetStateString const FBiOSTargetStateStringRecovery = @"Recovery"; +FBiOSTargetStateString const FBiOSTargetStateStringRestoreOS = @"RestoreOS"; +FBiOSTargetStateString const FBiOSTargetStateStringUnknown = @"Unknown"; diff --git a/FBControlCore/Management/FBiOSTargetOperation.h b/FBControlCore/Management/FBiOSTargetOperation.h index be63ad88a..b84e8da81 100644 --- a/FBControlCore/Management/FBiOSTargetOperation.h +++ b/FBControlCore/Management/FBiOSTargetOperation.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Management/FBiOSTargetOperation.m b/FBControlCore/Management/FBiOSTargetOperation.m index 97f23fc0b..775f07391 100644 --- a/FBControlCore/Management/FBiOSTargetOperation.m +++ b/FBControlCore/Management/FBiOSTargetOperation.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Management/FBiOSTargetSet.h b/FBControlCore/Management/FBiOSTargetSet.h index 0972cb25a..776256186 100644 --- a/FBControlCore/Management/FBiOSTargetSet.h +++ b/FBControlCore/Management/FBiOSTargetSet.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Processes/FBProcessFetcher.h b/FBControlCore/Processes/FBProcessFetcher.h index 78392ed06..fed8b60ac 100644 --- a/FBControlCore/Processes/FBProcessFetcher.h +++ b/FBControlCore/Processes/FBProcessFetcher.h @@ -1,12 +1,12 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #import -#include +#import NS_ASSUME_NONNULL_BEGIN @class FBProcessInfo; @@ -72,6 +72,33 @@ NS_ASSUME_NONNULL_BEGIN */ - (pid_t)processWithOpenFileTo:(const char *)filePath; +/** + Verify if process is running + + @param processIdentifier process to check. + @param error an error out for any error that occurs. + @return YES if process is Runnig and error is NOT set. False if process isn't running or error is set. + */ +- (BOOL) isProcessRunning:(pid_t)processIdentifier error:(NSError **)error; + +/** + Verify if process is stopped + + @param processIdentifier process to check. + @param error an error out for any error that occurs. + @return YES if process is Stopped and error is NOT set. False if process isn't stopped or error is set. + */ +- (BOOL) isProcessStopped:(pid_t)processIdentifier error:(NSError **)error; + +/** + Verify if process has a debugger attached to it. + + @param processIdentifier process to check. + @param error an error out for any error that occurs. + @return YES if process is has a debugger attached and error is NOT set.. False if process doesn't have a debugger attached or error is set. + */ +- (BOOL) isDebuggerAttachedTo:(pid_t)processIdentifier error:(NSError **)error; + /** Wait for a debugger to attach to the process and the process to be up running again. @@ -79,6 +106,25 @@ NS_ASSUME_NONNULL_BEGIN @return A future waitting for the debugger and process up running again. */ + (FBFuture *) waitForDebuggerToAttachAndContinueFor:(pid_t)processIdentifier; + +/** + Wait for process to receive SIGSTOP. + + @param processIdentifier the Process Identifier of the process. + @return A future waitting for the process to be in SSTOP state. + */ ++ (FBFuture *) waitStopSignalForProcess:(pid_t) processIdentifier; + +/** + Performs a stackshot on the provided process id. + Does not terminate the process after performing the stackshot. + Returns a future to a string containing the stackshot. + + @param processIdentifier the process identifier of the process to stackshot. + @param queue the queue to use. +*/ ++ (FBFuture *)performSampleStackshotForProcessIdentifier:(pid_t)processIdentifier queue:(dispatch_queue_t)queue; + @end NS_ASSUME_NONNULL_END diff --git a/FBControlCore/Processes/FBProcessFetcher.m b/FBControlCore/Processes/FBProcessFetcher.m index cab26b1c8..b6aaddf49 100644 --- a/FBControlCore/Processes/FBProcessFetcher.m +++ b/FBControlCore/Processes/FBProcessFetcher.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -15,9 +15,12 @@ #include #import "FBProcessInfo.h" +#import "FBProcessBuilder.h" #define PID_MAX 99999 +static NSTimeInterval const SampleDuration = 1; + #pragma mark Calling libproc typedef BOOL(^ProcessIterator)(pid_t pid); @@ -291,36 +294,36 @@ - (pid_t)parentOf:(pid_t)child return proc.kp_eproc.e_ppid; } - -- (BOOL) isProcessRunning:(pid_t)processIdentifier error:(NSError **)error +- (struct kinfo_proc) fetchProcessInfo:(pid_t)processIdentifier error:(NSError **)error { struct kinfo_proc proc_info; - if (!ProcInfoForProcessIdentifier(processIdentifier, &proc_info)) { - return [[FBControlCoreError - describeFormat:@"Failed fetching process info (pid %d)", processIdentifier] + if (!ProcInfoForProcessIdentifier(processIdentifier, &proc_info) || proc_info.kp_proc.p_pid != processIdentifier) { + [[FBControlCoreError + describeFormat:@"Failed fetching process info for (pid %d)", processIdentifier] failBool:error]; } - - return proc_info.kp_proc.p_stat == SRUN; + return proc_info; +} + +- (BOOL) isProcessRunning:(pid_t)processIdentifier error:(NSError **)error +{ + struct kinfo_proc proc_info = [self fetchProcessInfo:processIdentifier error:error]; + return *error == nil && proc_info.kp_proc.p_stat == SRUN; +} + +- (BOOL) isProcessStopped:(pid_t)processIdentifier error:(NSError **)error +{ + struct kinfo_proc proc_info = [self fetchProcessInfo:processIdentifier error:error]; + return *error == nil && proc_info.kp_proc.p_stat == SSTOP; } - (BOOL) isDebuggerAttachedTo:(pid_t)processIdentifier error:(NSError **)error { - struct kinfo_proc proc_info; - if (!ProcInfoForProcessIdentifier(processIdentifier, &proc_info)) { - return [[FBControlCoreError - describeFormat:@"Process cannot be found. Failed waiting for debugger for process (pid %d)", processIdentifier] - failBool:error]; - } - if (proc_info.kp_proc.p_pid != processIdentifier) { - return [[FBControlCoreError - describeFormat:@"Process (pid %d) seems to have died before a debugger was attached", processIdentifier] - failBool:error]; - } + struct kinfo_proc proc_info = [self fetchProcessInfo:processIdentifier error:error]; // When a debugger (a.k.a tracer) attaches to the test proccess, the parent of tracee will // change to tracer's pid with the original parent pid being store in `p_oppid`. // We detect debugger attachment by checking that parent pid has changed. - return proc_info.kp_proc.p_oppid != 0 && proc_info.kp_eproc.e_ppid != proc_info.kp_proc.p_oppid; + return *error == nil && proc_info.kp_proc.p_oppid != 0 && proc_info.kp_eproc.e_ppid != proc_info.kp_proc.p_oppid; } + (FBFuture *) waitForDebuggerToAttachAndContinueFor:(pid_t)processIdentifier @@ -343,4 +346,40 @@ - (BOOL) isDebuggerAttachedTo:(pid_t)processIdentifier error:(NSError **)error }]; } ++ (FBFuture *) waitStopSignalForProcess:(pid_t) processIdentifier +{ + FBProcessFetcher *processFetcher = [[FBProcessFetcher alloc] init]; + + dispatch_queue_t waitQueue = dispatch_queue_create("com.facebook.corecontrol.wait_for_stop", DISPATCH_QUEUE_SERIAL); + return [FBFuture + onQueue:waitQueue resolveOrFailWhen:^FBFutureLoopState (NSError **error){ + if ( + [processFetcher isProcessStopped:processIdentifier error:error] + ) { + return FBFutureLoopFinished; + } else if (*error != nil){ + return FBFutureLoopFailed; + } else { + return FBFutureLoopContinue; + } + }]; +} + ++ (FBFuture *)performSampleStackshotForProcessIdentifier:(pid_t)processIdentifier queue:(dispatch_queue_t)queue +{ + return [[[[[FBProcessBuilder + withLaunchPath:@"/usr/bin/sample" arguments:@[@(processIdentifier).stringValue, @(SampleDuration).stringValue]] + withStdOutInMemoryAsString] + runUntilCompletionWithAcceptableExitCodes:nil] + onQueue:queue handleError:^(NSError *error) { + return [[[FBControlCoreError + describeFormat:@"Failed to obtain a stack sample of process %d", processIdentifier] + causedBy:error] + failFuture]; + }] + onQueue:queue map:^(FBProcess *task) { + return task.stdOut; + }]; +} + @end diff --git a/FBControlCore/Processes/FBProcessInfo.h b/FBControlCore/Processes/FBProcessInfo.h index 3e3776846..66edd4d7a 100644 --- a/FBControlCore/Processes/FBProcessInfo.h +++ b/FBControlCore/Processes/FBProcessInfo.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Processes/FBProcessInfo.m b/FBControlCore/Processes/FBProcessInfo.m index f9c90f420..2f029a963 100644 --- a/FBControlCore/Processes/FBProcessInfo.m +++ b/FBControlCore/Processes/FBProcessInfo.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Processes/FBProcessTerminationStrategy.h b/FBControlCore/Processes/FBProcessTerminationStrategy.h index 0e4d96222..258a517b1 100644 --- a/FBControlCore/Processes/FBProcessTerminationStrategy.h +++ b/FBControlCore/Processes/FBProcessTerminationStrategy.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Processes/FBProcessTerminationStrategy.m b/FBControlCore/Processes/FBProcessTerminationStrategy.m index 93d1c74e7..518666276 100644 --- a/FBControlCore/Processes/FBProcessTerminationStrategy.m +++ b/FBControlCore/Processes/FBProcessTerminationStrategy.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Processes/FBServiceManagement.h b/FBControlCore/Processes/FBServiceManagement.h index 9de282313..a401ce137 100644 --- a/FBControlCore/Processes/FBServiceManagement.h +++ b/FBControlCore/Processes/FBServiceManagement.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Processes/FBServiceManagement.m b/FBControlCore/Processes/FBServiceManagement.m index 0e3f90f10..0f3cbe80b 100644 --- a/FBControlCore/Processes/FBServiceManagement.m +++ b/FBControlCore/Processes/FBServiceManagement.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Reporting/FBEventReporter.h b/FBControlCore/Reporting/FBEventReporter.h index f4085fe01..e3f5940fa 100644 --- a/FBControlCore/Reporting/FBEventReporter.h +++ b/FBControlCore/Reporting/FBEventReporter.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Reporting/FBEventReporterSubject.h b/FBControlCore/Reporting/FBEventReporterSubject.h index da1ccd327..83bcca0a9 100644 --- a/FBControlCore/Reporting/FBEventReporterSubject.h +++ b/FBControlCore/Reporting/FBEventReporterSubject.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -38,7 +38,7 @@ extern FBEventType const FBEventTypeFailure; @param arguments the arguments to the invoked call @return a scuba sample */ -+ (instancetype)subjectForStartedCall:(NSString *)call arguments:(NSArray *)arguments; ++ (instancetype)subjectForStartedCall:(NSString *)call arguments:(NSArray *)arguments reportNativeSwiftMethodCall:(BOOL)reportNativeSwiftMethodCall; /** Construct a sample for a successful call. @@ -49,7 +49,7 @@ extern FBEventType const FBEventTypeFailure; @param arguments the arguments to the invoked call. @return a scuba sample */ -+ (instancetype)subjectForSuccessfulCall:(NSString *)call duration:(NSTimeInterval)duration size:(nullable NSNumber *)size arguments:(NSArray *)arguments; ++ (instancetype)subjectForSuccessfulCall:(NSString *)call duration:(NSTimeInterval)duration size:(nullable NSNumber *)size arguments:(NSArray *)arguments reportNativeSwiftMethodCall:(BOOL)reportNativeSwiftMethodCall; /** Construct a sample for a failing call. @@ -61,7 +61,7 @@ extern FBEventType const FBEventTypeFailure; @param arguments the arguments to the invoked call @return a scuba sample */ -+ (instancetype)subjectForFailingCall:(NSString *)call duration:(NSTimeInterval)duration message:(NSString *)message size:(nullable NSNumber *)size arguments:(NSArray *)arguments; ++ (instancetype)subjectForFailingCall:(NSString *)call duration:(NSTimeInterval)duration message:(NSString *)message size:(nullable NSNumber *)size arguments:(NSArray *)arguments reportNativeSwiftMethodCall:(BOOL)reportNativeSwiftMethodCall; #pragma mark Properties @@ -95,6 +95,10 @@ extern FBEventType const FBEventTypeFailure; */ @property (nonatomic, copy, nullable, readonly) NSString *message; +/** + Marks is method was called natively in swift + */ +@property (readonly) BOOL reportNativeSwiftMethodCall; @end diff --git a/FBControlCore/Reporting/FBEventReporterSubject.m b/FBControlCore/Reporting/FBEventReporterSubject.m index d8d4b5052..39bc2a7a8 100644 --- a/FBControlCore/Reporting/FBEventReporterSubject.m +++ b/FBControlCore/Reporting/FBEventReporterSubject.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -23,27 +23,28 @@ @implementation FBEventReporterSubject @synthesize duration = _duration; @synthesize message = _message; @synthesize size = _size; +@synthesize reportNativeSwiftMethodCall = _reportNativeSwiftMethodCall; #pragma mark Initializers + (instancetype)subjectForEvent:(NSString *)eventName { - return [[FBEventReporterSubject alloc] initWithEventName:eventName eventType:FBEventTypeDiscrete arguments:nil duration:nil size:nil message:nil]; + return [[FBEventReporterSubject alloc] initWithEventName:eventName eventType:FBEventTypeDiscrete arguments:nil duration:nil size:nil message:nil reportNativeSwiftMethodCall:NO]; } -+ (instancetype)subjectForStartedCall:(NSString *)call arguments:(NSArray *)arguments ++ (instancetype)subjectForStartedCall:(NSString *)call arguments:(NSArray *)arguments reportNativeSwiftMethodCall:(BOOL)reportNativeSwiftMethodCall { - return [[FBEventReporterSubject alloc] initWithEventName:call eventType:FBEventTypeStarted arguments:arguments duration:nil size:nil message:nil]; + return [[FBEventReporterSubject alloc] initWithEventName:call eventType:FBEventTypeStarted arguments:arguments duration:nil size:nil message:nil reportNativeSwiftMethodCall:reportNativeSwiftMethodCall]; } -+ (instancetype)subjectForSuccessfulCall:(NSString *)call duration:(NSTimeInterval)duration size:(NSNumber *)size arguments:(NSArray *)arguments ++ (instancetype)subjectForSuccessfulCall:(NSString *)call duration:(NSTimeInterval)duration size:(NSNumber *)size arguments:(NSArray *)arguments reportNativeSwiftMethodCall:(BOOL)reportNativeSwiftMethodCall { - return [[FBEventReporterSubject alloc] initWithEventName:call eventType:FBEventTypeSuccess arguments:arguments duration:[self durationMilliseconds:duration] size:size message:nil]; + return [[FBEventReporterSubject alloc] initWithEventName:call eventType:FBEventTypeSuccess arguments:arguments duration:[self durationMilliseconds:duration] size:size message:nil reportNativeSwiftMethodCall:reportNativeSwiftMethodCall]; } -+ (instancetype)subjectForFailingCall:(NSString *)call duration:(NSTimeInterval)duration message:(NSString *)message size:(NSNumber *)size arguments:(NSArray *)arguments ++ (instancetype)subjectForFailingCall:(NSString *)call duration:(NSTimeInterval)duration message:(NSString *)message size:(NSNumber *)size arguments:(NSArray *)arguments reportNativeSwiftMethodCall:(BOOL)reportNativeSwiftMethodCall { - return [[FBEventReporterSubject alloc] initWithEventName:call eventType:FBEventTypeFailure arguments:arguments duration:[self durationMilliseconds:duration] size:size message:message]; + return [[FBEventReporterSubject alloc] initWithEventName:call eventType:FBEventTypeFailure arguments:arguments duration:[self durationMilliseconds:duration] size:size message:message reportNativeSwiftMethodCall:reportNativeSwiftMethodCall]; } + (NSNumber *)durationMilliseconds:(NSTimeInterval)timeInterval @@ -52,7 +53,7 @@ + (NSNumber *)durationMilliseconds:(NSTimeInterval)timeInterval return @(milliseconds); } -- (instancetype)initWithEventName:(NSString *)eventName eventType:(FBEventType)eventType arguments:(NSArray *)arguments duration:(NSNumber *)duration size:(NSNumber *)size message:(NSString *)message +- (instancetype)initWithEventName:(NSString *)eventName eventType:(FBEventType)eventType arguments:(NSArray *)arguments duration:(NSNumber *)duration size:(NSNumber *)size message:(NSString *)message reportNativeSwiftMethodCall:(BOOL)reportNativeSwiftMethodCall { self = [super init]; if (!self) { @@ -65,6 +66,7 @@ - (instancetype)initWithEventName:(NSString *)eventName eventType:(FBEventType)e _duration = duration; _size = size; _message = message; + _reportNativeSwiftMethodCall = reportNativeSwiftMethodCall; return self; } diff --git a/FBControlCore/Sockets/FBSocketServer.h b/FBControlCore/Sockets/FBSocketServer.h index 9d3814f14..614441686 100644 --- a/FBControlCore/Sockets/FBSocketServer.h +++ b/FBControlCore/Sockets/FBSocketServer.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Sockets/FBSocketServer.m b/FBControlCore/Sockets/FBSocketServer.m index 4f0b56605..2db34bb87 100644 --- a/FBControlCore/Sockets/FBSocketServer.m +++ b/FBControlCore/Sockets/FBSocketServer.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Tasks/FBLaunchedApplication.h b/FBControlCore/Tasks/FBLaunchedApplication.h index 8a142e7c1..581bdbfaf 100644 --- a/FBControlCore/Tasks/FBLaunchedApplication.h +++ b/FBControlCore/Tasks/FBLaunchedApplication.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Tasks/FBProcess.h b/FBControlCore/Tasks/FBProcess.h index 2d722219d..78868a9a4 100644 --- a/FBControlCore/Tasks/FBProcess.h +++ b/FBControlCore/Tasks/FBProcess.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Tasks/FBProcess.m b/FBControlCore/Tasks/FBProcess.m index c66051210..55a7f7eed 100644 --- a/FBControlCore/Tasks/FBProcess.m +++ b/FBControlCore/Tasks/FBProcess.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Tasks/FBProcessBuilder.h b/FBControlCore/Tasks/FBProcessBuilder.h index 99e14ea9c..ac19b641a 100644 --- a/FBControlCore/Tasks/FBProcessBuilder.h +++ b/FBControlCore/Tasks/FBProcessBuilder.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Tasks/FBProcessBuilder.m b/FBControlCore/Tasks/FBProcessBuilder.m index 765b5d006..7b0b2c184 100644 --- a/FBControlCore/Tasks/FBProcessBuilder.m +++ b/FBControlCore/Tasks/FBProcessBuilder.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Utility/FBAccessibilityTraits.h b/FBControlCore/Utility/FBAccessibilityTraits.h index 4dec4785b..243a0c2e9 100644 --- a/FBControlCore/Utility/FBAccessibilityTraits.h +++ b/FBControlCore/Utility/FBAccessibilityTraits.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Utility/FBAccessibilityTraits.m b/FBControlCore/Utility/FBAccessibilityTraits.m index 63a232b42..f257a9d63 100644 --- a/FBControlCore/Utility/FBAccessibilityTraits.m +++ b/FBControlCore/Utility/FBAccessibilityTraits.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Utility/FBArchitecture.h b/FBControlCore/Utility/FBArchitecture.h index f5dc84b2b..e5932d18e 100644 --- a/FBControlCore/Utility/FBArchitecture.h +++ b/FBControlCore/Utility/FBArchitecture.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -19,5 +19,6 @@ extern FBArchitecture const FBArchitectureX86_64; extern FBArchitecture const FBArchitectureArmv7; extern FBArchitecture const FBArchitectureArmv7s; extern FBArchitecture const FBArchitectureArm64; +extern FBArchitecture const FBArchitectureArm64e; NS_ASSUME_NONNULL_END diff --git a/FBControlCore/Utility/FBArchitecture.m b/FBControlCore/Utility/FBArchitecture.m index 5d02f16e3..8c5e34391 100644 --- a/FBControlCore/Utility/FBArchitecture.m +++ b/FBControlCore/Utility/FBArchitecture.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -12,3 +12,4 @@ FBArchitecture const FBArchitectureArmv7 = @"armv7"; FBArchitecture const FBArchitectureArmv7s = @"armv7s"; FBArchitecture const FBArchitectureArm64 = @"arm64"; +FBArchitecture const FBArchitectureArm64e = @"arm64e"; diff --git a/FBControlCore/Utility/FBArchiveOperations.h b/FBControlCore/Utility/FBArchiveOperations.h index ab57f7b54..ab2bc5c0c 100644 --- a/FBControlCore/Utility/FBArchiveOperations.h +++ b/FBControlCore/Utility/FBArchiveOperations.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -36,11 +36,12 @@ typedef NS_ENUM(NSUInteger, FBCompressionFormat) { @param path the path to the archive. @param extractPath the extraction path. + @param overrideMTime if YES the archive contests' `mtime` will be ignored. Current timestamp will be used as mtime of extracted files/directories. @param queue the queue to do work on. @param logger the logger to log to. @return a Future wrapping the extracted tar destination. */ -+ (FBFuture *)extractArchiveAtPath:(NSString *)path toPath:(NSString *)extractPath queue:(dispatch_queue_t)queue logger:(id)logger; ++ (FBFuture *)extractArchiveAtPath:(NSString *)path toPath:(NSString *)extractPath overrideModificationTime:(BOOL)overrideMTime queue:(dispatch_queue_t)queue logger:(id)logger; /** Extracts a tar, or zip stream archive to a directory. @@ -52,12 +53,13 @@ typedef NS_ENUM(NSUInteger, FBCompressionFormat) { @param stream the stream of the archive. @param extractPath the extraction path + @param overrideMTime if YES the archive contests' `mtime` will be ignored. Current timestamp will be used as mtime of extracted files/directories. @param queue the queue to do work on @param logger the logger to log to @param compression compression format used by client @return a Future wrapping the extracted tar destination. */ -+ (FBFuture *)extractArchiveFromStream:(FBProcessInput *)stream toPath:(NSString *)extractPath queue:(dispatch_queue_t)queue logger:(id)logger compression:(FBCompressionFormat)compression; ++ (FBFuture *)extractArchiveFromStream:(FBProcessInput *)stream toPath:(NSString *)extractPath overrideModificationTime:(BOOL)overrideMTime queue:(dispatch_queue_t)queue logger:(id)logger compression:(FBCompressionFormat)compression; /** Extracts a gzip from a stream to a single file. @@ -74,11 +76,11 @@ typedef NS_ENUM(NSUInteger, FBCompressionFormat) { /** Creates a gzipped archive compressing the data provided. - @param data the data to be compressed. + @param input the data to be compressed. @param logger the logger to log to. @return a Future wrapping the archive data. */ -+ (FBFuture *> *)createGzipDataFromData:(NSData *)data logger:(id)logger; ++ (FBFuture *> *)createGzipDataFromProcessInput:(FBProcessInput *)input logger:(id)logger; /** Creates a gzips archive, returning an task that has an NSInputStream attached to stdout. @@ -99,11 +101,10 @@ typedef NS_ENUM(NSUInteger, FBCompressionFormat) { To confirm that the stream has been correctly written, the caller should check the exit code of the returned task upon completion. @param path the path to archive. - @param queue the queue to do work on @param logger the logger to log to. @return a Future containing a task with an NSInputStream attached to stdout. */ -+ (FBFuture *> *)createGzippedTarForPath:(NSString *)path queue:(dispatch_queue_t)queue logger:(id)logger; ++ (FBFuture *> *)createGzippedTarForPath:(NSString *)path logger:(id)logger; /** Creates a gzipped tar archive, returning an the data of the tar. diff --git a/FBControlCore/Utility/FBArchiveOperations.m b/FBControlCore/Utility/FBArchiveOperations.m index 8055744ff..937f1bfd1 100644 --- a/FBControlCore/Utility/FBArchiveOperations.m +++ b/FBControlCore/Utility/FBArchiveOperations.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -16,11 +16,11 @@ @implementation FBArchiveOperations -+ (FBFuture *)extractArchiveAtPath:(NSString *)path toPath:(NSString *)extractPath queue:(dispatch_queue_t)queue logger:(id)logger ++ (FBFuture *)extractArchiveAtPath:(NSString *)path toPath:(NSString *)extractPath overrideModificationTime:(BOOL)overrideMTime queue:(dispatch_queue_t)queue logger:(id)logger { return [[[[[[[FBProcessBuilder withLaunchPath:BSDTarPath] - withArguments:@[@"-zxp", @"-C", extractPath, @"-f", path]] + withArguments:@[overrideMTime ? @"-zxpm" : @"-zxp", @"-C", extractPath, @"-f", path]] withStdErrToLoggerAndErrorMessage:logger.debug] withStdOutToLogger:logger.debug] withTaskLifecycleLoggingTo:logger] @@ -28,11 +28,11 @@ @implementation FBArchiveOperations mapReplace:extractPath]; } -+ (FBFuture *)extractArchiveFromStream:(FBProcessInput *)stream toPath:(NSString *)extractPath queue:(dispatch_queue_t)queue logger:(id)logger compression:(FBCompressionFormat)compression ++ (FBFuture *)extractArchiveFromStream:(FBProcessInput *)stream toPath:(NSString *)extractPath overrideModificationTime:(BOOL)overrideMTime queue:(dispatch_queue_t)queue logger:(id)logger compression:(FBCompressionFormat)compression { - NSArray *extractCommand = @[@"-zxp", @"-C", extractPath, @"-f", @"-"]; + NSArray *extractCommand = @[overrideMTime ? @"-zxpm" : @"-zxp", @"-C", extractPath, @"-f", @"-"]; if (compression == FBCompressionFormatZSTD) { - extractCommand = @[@"--use-compress-program", @"pzstd -d", @"-xp", @"-C", extractPath, @"-f", @"-"]; + extractCommand = @[@"--use-compress-program", @"pzstd -d", overrideMTime ? @"-xpm" : @"-xp", @"-C", extractPath, @"-f", @"-"]; } return [[[[[[[[FBProcessBuilder @@ -70,12 +70,13 @@ @implementation FBArchiveOperations start]; } -+ (FBFuture *> *)createGzipDataFromData:(NSData *)data logger:(id)logger + ++ (FBFuture *> *)createGzipDataFromProcessInput:(FBProcessInput *)input logger:(id)logger { - return (FBFuture *> *) [[[[[[[FBProcessBuilder + return (FBFuture *> *) [[[[[[[FBProcessBuilder withLaunchPath:@"/usr/bin/gzip"] withArguments:@[@"-", @"--to-stdout"]] - withStdInFromData:data] + withStdIn:input] withStdErrToLoggerAndErrorMessage:logger] withStdOutInMemoryAsData] withTaskLifecycleLoggingTo:logger] @@ -83,10 +84,11 @@ @implementation FBArchiveOperations ]; } -+ (FBFuture *> *)createGzippedTarForPath:(NSString *)path queue:(dispatch_queue_t)queue logger:(id)logger + ++ (FBFuture *> *)createGzippedTarForPath:(NSString *)path logger:(id)logger { NSError *error = nil; - FBProcessBuilder *builder = [self createGzippedTarTaskBuilderForPath:path queue:queue logger:logger error:&error]; + FBProcessBuilder *builder = [self createGzippedTarTaskBuilderForPath:path logger:logger error:&error]; if (!builder) { return [FBFuture futureWithError:error]; } @@ -98,7 +100,7 @@ @implementation FBArchiveOperations + (FBFuture *)createGzippedTarDataForPath:(NSString *)path queue:(dispatch_queue_t)queue logger:(id)logger { NSError *error = nil; - FBProcessBuilder *builder = [self createGzippedTarTaskBuilderForPath:path queue:queue logger:logger error:&error]; + FBProcessBuilder *builder = [self createGzippedTarTaskBuilderForPath:path logger:logger error:&error]; if (!builder) { return [FBFuture futureWithError:error]; } @@ -111,7 +113,7 @@ @implementation FBArchiveOperations #pragma mark Private -+ (FBProcessBuilder *)createGzippedTarTaskBuilderForPath:(NSString *)path queue:(dispatch_queue_t)queue logger:(id)logger error:(NSError **)error ++ (FBProcessBuilder *)createGzippedTarTaskBuilderForPath:(NSString *)path logger:(id)logger error:(NSError **)error { BOOL isDirectory; if (![NSFileManager.defaultManager fileExistsAtPath:path isDirectory:&isDirectory]) { diff --git a/FBControlCore/Utility/FBCollectionInformation.h b/FBControlCore/Utility/FBCollectionInformation.h index 26727b3e5..1d8a3b1cb 100644 --- a/FBControlCore/Utility/FBCollectionInformation.h +++ b/FBControlCore/Utility/FBCollectionInformation.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Utility/FBCollectionInformation.m b/FBControlCore/Utility/FBCollectionInformation.m index 52ba585e8..be9bca5a4 100644 --- a/FBControlCore/Utility/FBCollectionInformation.m +++ b/FBControlCore/Utility/FBCollectionInformation.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Utility/FBCollectionOperations.h b/FBControlCore/Utility/FBCollectionOperations.h index 442499a5c..a94f26543 100644 --- a/FBControlCore/Utility/FBCollectionOperations.h +++ b/FBControlCore/Utility/FBCollectionOperations.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -18,10 +18,10 @@ NS_ASSUME_NONNULL_BEGIN Creates and returns an Array of Numbers from an index set. Index Sets can be used for storing a collection of Integers, as can Arrays of Numbers. - @param indeces the indeces to extract numbers from. - @return an Array of Numbers of the indeces in the index set. + @param indices the indices to extract numbers from. + @return an Array of Numbers of the indices in the index set. */ -+ (NSArray *)arrayFromIndeces:(NSIndexSet *)indeces; ++ (NSArray *)arrayFromIndices:(NSIndexSet *)indices; /** Returns a recursive copy of the dictionary, filtering out any elements that are not JSON-Serializable. Values that are acceptable are: @@ -56,7 +56,7 @@ NS_ASSUME_NONNULL_BEGIN @param array an array of numbers to extract values from @return an Index Set of the values in the array. */ -+ (NSIndexSet *)indecesFromArray:(NSArray *)array; ++ (NSIndexSet *)indicesFromArray:(NSArray *)array; /** objectForKey, converting NSNull to nil. diff --git a/FBControlCore/Utility/FBCollectionOperations.m b/FBControlCore/Utility/FBCollectionOperations.m index 364b189af..bd866ad8a 100644 --- a/FBControlCore/Utility/FBCollectionOperations.m +++ b/FBControlCore/Utility/FBCollectionOperations.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -11,10 +11,10 @@ @implementation FBCollectionOperations #pragma mark Public -+ (NSArray *)arrayFromIndeces:(NSIndexSet *)indeces ++ (NSArray *)arrayFromIndices:(NSIndexSet *)indices { NSMutableArray *array = [NSMutableArray array]; - [indeces enumerateIndexesUsingBlock:^(NSUInteger index, BOOL *_) { + [indices enumerateIndexesUsingBlock:^(NSUInteger index, BOOL *_) { [array addObject:@(index)]; }]; return [array copy]; @@ -46,7 +46,7 @@ @implementation FBCollectionOperations return output; } -+ (NSIndexSet *)indecesFromArray:(NSArray *)array ++ (NSIndexSet *)indicesFromArray:(NSArray *)array { NSMutableIndexSet *indexSet = [NSMutableIndexSet indexSet]; for (NSNumber *number in array) { diff --git a/FBControlCore/Utility/FBConcatedJsonParser.h b/FBControlCore/Utility/FBConcatedJsonParser.h new file mode 100644 index 000000000..0edd3d3fd --- /dev/null +++ b/FBControlCore/Utility/FBConcatedJsonParser.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + New crash log format is just concated json files that *not* follows json spec. This is not array of json objects + delimited with comma, that is just several json files that glued together. We need to parse this to handle correctly + */ +@interface FBConcatedJsonParser : NSObject + ++ (nullable NSDictionary *)parseConcatenatedJSONFromString:(NSString *)str error:(NSError **)error; + +@end + +NS_ASSUME_NONNULL_END diff --git a/FBControlCore/Utility/FBConcatedJsonParser.m b/FBControlCore/Utility/FBConcatedJsonParser.m new file mode 100644 index 000000000..b84aad86b --- /dev/null +++ b/FBControlCore/Utility/FBConcatedJsonParser.m @@ -0,0 +1,71 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import +#import + +#import "FBConcatedJsonParser.h" + +@implementation FBConcatedJsonParser + +#pragma mark Public + ++ (nullable NSDictionary *)parseConcatenatedJSONFromString:(NSString *)str error:(NSError **)error{ + __block int bracketCounter = 0; + __block BOOL characterEscaped = false; + __block BOOL inString = false; + __block NSError *err = nil; + + NSMutableDictionary *concatenatedJson = [NSMutableDictionary new]; + __block NSMutableString *json = [NSMutableString new]; + + [str enumerateSubstringsInRange:NSMakeRange(0, [str length]) options:NSStringEnumerationByComposedCharacterSequences usingBlock:^(NSString * _Nullable substring, NSRange substringRange, NSRange enclosingRange, BOOL * _Nonnull stop) { + if (!substring) { + return; + } + NSString *c = substring; + BOOL escaped = characterEscaped; + characterEscaped = false; + if (escaped) { + [json appendString:c]; + return; + } + if (!inString) { + if ([c isEqualToString: @"\n"]) { + return; + } + if ([c isEqualToString: @"{"]) { + bracketCounter += 1; + } else if ([c isEqualToString:@"}"]) { + bracketCounter -= 1; + } + } + if ([c isEqualToString: @"\\"]) { + characterEscaped = true; + } + if ([c isEqualToString: @"\""]) { + inString = !inString; + } + [json appendString:c]; + if (bracketCounter == 0) { + NSDictionary *parsed = [NSJSONSerialization JSONObjectWithData:[json dataUsingEncoding:NSUTF8StringEncoding] options:0 error:&err]; + if (!parsed) { + *stop = YES; + } + json = [NSMutableString new]; + [concatenatedJson addEntriesFromDictionary:parsed]; + } + }]; + if (err) { + *error = err; + return nil; + } + + return concatenatedJson; +} + +@end diff --git a/FBControlCore/Utility/FBConcurrentCollectionOperations.h b/FBControlCore/Utility/FBConcurrentCollectionOperations.h index 5a8d49990..87f8d4845 100644 --- a/FBControlCore/Utility/FBConcurrentCollectionOperations.h +++ b/FBControlCore/Utility/FBConcurrentCollectionOperations.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -16,7 +16,7 @@ NS_ASSUME_NONNULL_BEGIN @interface FBConcurrentCollectionOperations : NSObject /** - Generate an array of objects from indeces. Indeces where nil is returned will contain `NSNull.null` + Generate an array of objects from indices. Indices where nil is returned will contain `NSNull.null` @param count the number of generations to execute @param block the block to generate objects from. diff --git a/FBControlCore/Utility/FBConcurrentCollectionOperations.m b/FBControlCore/Utility/FBConcurrentCollectionOperations.m index b19449047..1880e3507 100644 --- a/FBControlCore/Utility/FBConcurrentCollectionOperations.m +++ b/FBControlCore/Utility/FBConcurrentCollectionOperations.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Utility/FBControlCoreError.h b/FBControlCore/Utility/FBControlCoreError.h index 24af345d7..0a9856345 100644 --- a/FBControlCore/Utility/FBControlCoreError.h +++ b/FBControlCore/Utility/FBControlCoreError.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Utility/FBControlCoreError.m b/FBControlCore/Utility/FBControlCoreError.m index 8d296fdfc..eb1e73f37 100644 --- a/FBControlCore/Utility/FBControlCoreError.m +++ b/FBControlCore/Utility/FBControlCoreError.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Utility/FBControlCoreFrameworkLoader.h b/FBControlCore/Utility/FBControlCoreFrameworkLoader.h index ffea1cb78..7c7cf3075 100644 --- a/FBControlCore/Utility/FBControlCoreFrameworkLoader.h +++ b/FBControlCore/Utility/FBControlCoreFrameworkLoader.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Utility/FBControlCoreFrameworkLoader.m b/FBControlCore/Utility/FBControlCoreFrameworkLoader.m index f23e071e1..d8ec70213 100644 --- a/FBControlCore/Utility/FBControlCoreFrameworkLoader.m +++ b/FBControlCore/Utility/FBControlCoreFrameworkLoader.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -7,10 +7,11 @@ #import "FBControlCoreFrameworkLoader.h" -#import "FBControlCoreLogger.h" -#import "FBControlCoreGlobalConfiguration.h" +#import "FBCollectionInformation.h" #import "FBControlCoreError.h" -#import "FBWeakFrameworkLoader.h" +#import "FBControlCoreGlobalConfiguration.h" +#import "FBControlCoreLogger.h" +#import "FBWeakFramework.h" #include @@ -56,7 +57,7 @@ - (BOOL)loadPrivateFrameworks:(nullable id)logger error:(NS if (self.hasLoadedFrameworks) { return YES; } - BOOL result = [FBWeakFrameworkLoader loadPrivateFrameworks:self.frameworks logger:logger error:error]; + BOOL result = [FBControlCoreFrameworkLoader loadPrivateFrameworks:self.frameworks logger:logger error:error]; if (result) { _hasLoadedFrameworks = YES; } @@ -81,6 +82,26 @@ - (void)loadPrivateFrameworksOrAbort abort(); } +#pragma mark Private + ++ (BOOL)loadPrivateFrameworks:(NSArray *)weakFrameworks logger:(id)logger error:(NSError **)error +{ + for (FBWeakFramework *framework in weakFrameworks) { + NSError *innerError = nil; + if (![framework loadWithLogger:logger error:&innerError]) { + return [FBControlCoreError failBoolWithError:innerError errorOut:error]; + } + } + + // We're done with loading Frameworks. + [logger.debug logFormat: + @"Loaded All Private Frameworks %@", + [FBCollectionInformation oneLineDescriptionFromArray:[weakFrameworks valueForKeyPath:@"@unionOfObjects.name"] atKeyPath:@"lastPathComponent"] + ]; + + return YES; +} + @end @implementation NSBundle (FBControlCoreFrameworkLoader) diff --git a/FBControlCore/Utility/FBControlCoreGlobalConfiguration.h b/FBControlCore/Utility/FBControlCoreGlobalConfiguration.h index 552ff92d1..e1ea639c9 100644 --- a/FBControlCore/Utility/FBControlCoreGlobalConfiguration.h +++ b/FBControlCore/Utility/FBControlCoreGlobalConfiguration.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Utility/FBControlCoreGlobalConfiguration.m b/FBControlCore/Utility/FBControlCoreGlobalConfiguration.m index 603774990..d2972de4f 100644 --- a/FBControlCore/Utility/FBControlCoreGlobalConfiguration.m +++ b/FBControlCore/Utility/FBControlCoreGlobalConfiguration.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -83,7 +83,7 @@ - (NSString *)description + (id)createDefaultLogger { - return [FBControlCoreLogger systemLoggerWritingToStderr:self.stderrLoggingEnabledByDefault withDebugLogging:self.debugLoggingEnabledByDefault]; + return [FBControlCoreLoggerFactory systemLoggerWritingToStderr:self.stderrLoggingEnabledByDefault withDebugLogging:self.debugLoggingEnabledByDefault]; } + (BOOL)stderrLoggingEnabledByDefault diff --git a/FBControlCore/Utility/FBControlCoreLogger+OSLog.h b/FBControlCore/Utility/FBControlCoreLogger+OSLog.h index 63ef1b313..3ac5fab99 100644 --- a/FBControlCore/Utility/FBControlCoreLogger+OSLog.h +++ b/FBControlCore/Utility/FBControlCoreLogger+OSLog.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -14,7 +14,7 @@ NS_ASSUME_NONNULL_BEGIN /** A logger implementation on top of os_log. */ -@interface FBControlCoreLogger (OSLog) +@interface FBControlCoreLoggerFactory (OSLog) /* Construct a new OS Log logger. diff --git a/FBControlCore/Utility/FBControlCoreLogger+OSLog.m b/FBControlCore/Utility/FBControlCoreLogger+OSLog.m index d2da253ae..ad9bb6d8a 100644 --- a/FBControlCore/Utility/FBControlCoreLogger+OSLog.m +++ b/FBControlCore/Utility/FBControlCoreLogger+OSLog.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -97,7 +97,7 @@ - (instancetype)initWithClient:(os_log_t)client name:(NSString *)name level:(FBC #endif -@implementation FBControlCoreLogger (OSLog) +@implementation FBControlCoreLoggerFactory (OSLog) + (id)osLoggerWithLevel:(FBControlCoreLogLevel)level { diff --git a/FBControlCore/Utility/FBControlCoreLogger.h b/FBControlCore/Utility/FBControlCoreLogger.h index ae1adc8f1..2a453ea43 100644 --- a/FBControlCore/Utility/FBControlCoreLogger.h +++ b/FBControlCore/Utility/FBControlCoreLogger.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -117,7 +117,7 @@ typedef NS_ENUM(NSUInteger, FBControlCoreLogLevel) { /** Implementations of Loggers. */ -@interface FBControlCoreLogger : NSObject +@interface FBControlCoreLoggerFactory : NSObject /** An implementation of `FBControlCoreLogger` that logs using the OS's default logging framework. diff --git a/FBControlCore/Utility/FBControlCoreLogger.m b/FBControlCore/Utility/FBControlCoreLogger.m index 72f0c1ea1..004fd1f77 100644 --- a/FBControlCore/Utility/FBControlCoreLogger.m +++ b/FBControlCore/Utility/FBControlCoreLogger.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -93,7 +93,7 @@ - (instancetype)initWithLoggers:(NSArray> *)loggers - (id)log:(NSString *)message { - message = [FBControlCoreLogger loggableStringLine:message]; + message = [FBControlCoreLoggerFactory loggableStringLine:message]; if (!message) { return self; } @@ -203,7 +203,7 @@ - (instancetype)initWithConsumer:(id)consumer name:(NSString *)n - (id)log:(NSString *)message { - message = [FBControlCoreLogger loggableStringLine:message]; + message = [FBControlCoreLoggerFactory loggableStringLine:message]; if (!message) { return self; } @@ -266,7 +266,7 @@ - (instancetype)initWithConsumer:(id)consumer name:(NSString *)n @end -@implementation FBControlCoreLogger +@implementation FBControlCoreLoggerFactory #pragma mark Public @@ -286,7 +286,7 @@ @implementation FBControlCoreLogger // If the system logger will log to stderr in the current build environment or runtime // don't bother adding a logger that will additionally log to stderr. - if (FBControlCoreLogger.systemLoggerWillLogToStdErr) { + if (FBControlCoreLoggerFactory.systemLoggerWillLogToStdErr) { return systemLogger; } diff --git a/FBControlCore/Utility/FBCrashLogStore.h b/FBControlCore/Utility/FBCrashLogStore.h index 42653886b..02d526bb3 100644 --- a/FBControlCore/Utility/FBCrashLogStore.h +++ b/FBControlCore/Utility/FBCrashLogStore.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Utility/FBCrashLogStore.m b/FBControlCore/Utility/FBCrashLogStore.m index 1e4ff7cd5..596697b19 100644 --- a/FBControlCore/Utility/FBCrashLogStore.m +++ b/FBControlCore/Utility/FBCrashLogStore.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Utility/FBDataBuffer.h b/FBControlCore/Utility/FBDataBuffer.h index ed167fc03..825334230 100644 --- a/FBControlCore/Utility/FBDataBuffer.h +++ b/FBControlCore/Utility/FBDataBuffer.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Utility/FBDataBuffer.m b/FBControlCore/Utility/FBDataBuffer.m index e924dbb1a..ab2c74346 100644 --- a/FBControlCore/Utility/FBDataBuffer.m +++ b/FBControlCore/Utility/FBDataBuffer.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Utility/FBDataConsumer.h b/FBControlCore/Utility/FBDataConsumer.h index 6792807b1..c86443d40 100644 --- a/FBControlCore/Utility/FBDataConsumer.h +++ b/FBControlCore/Utility/FBDataConsumer.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -18,7 +18,7 @@ NS_ASSUME_NONNULL_BEGIN /** Consumes the provided binary data. - If the reciever implements FBDataConsumerSync, then stack allocated data is permitted. + If the receiver implements FBDataConsumerSync, then stack allocated data is permitted. Otherwise, the underlying buffer must survive data being consumed on a separate thread. @param data the data to consume. diff --git a/FBControlCore/Utility/FBDataConsumer.m b/FBControlCore/Utility/FBDataConsumer.m index 42498126e..84fe520d6 100644 --- a/FBControlCore/Utility/FBDataConsumer.m +++ b/FBControlCore/Utility/FBDataConsumer.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -11,6 +11,7 @@ #import "FBControlCoreError.h" #import "FBControlCoreLogger.h" #import "FBDataBuffer.h" +#import @interface FBDataConsumerAdaptor () @@ -162,7 +163,7 @@ @interface FBBlockDataConsumer_Dispatcher : NSObject @property (nonatomic, strong, nullable, readwrite) dispatch_queue_t queue; @property (nonatomic, strong, nullable, readwrite) dispatch_group_t group; @property (nonatomic, copy, nullable, readwrite) void (^consumer)(NSData *); -@property (atomic, readonly) int64_t numPendingTasks; +@property _Atomic int64_t numPendingTasks; @end @@ -178,20 +179,17 @@ - (instancetype)initWithQueue:(dispatch_queue_t)queue consumer:(void (^)(NSData _queue = queue; _group = dispatch_group_create(); _consumer = consumer; - _numPendingTasks = 0; +atomic_init(&_numPendingTasks, 0); return self; } -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wdeprecated" - - (void)consumeData:(NSData *)data { void (^consumer)(NSData *) = nil; dispatch_queue_t queue; dispatch_group_t group; - OSAtomicIncrement64(&_numPendingTasks); + atomic_fetch_add(&_numPendingTasks, 1); @synchronized (self) { consumer = self.consumer; @@ -203,11 +201,11 @@ - (void)consumeData:(NSData *)data if (queue) { dispatch_group_async(group, queue, ^{ consumer(data); - OSAtomicDecrement64(&self->_numPendingTasks); + atomic_fetch_sub(&self->_numPendingTasks, 1); }); } else { consumer(data); - OSAtomicDecrement64(&_numPendingTasks); + atomic_fetch_sub(&_numPendingTasks, 1); } } } @@ -225,8 +223,6 @@ - (void)consumeEndOfFile } } -#pragma clang diagnostic pop - @end @interface FBBlockDataConsumer () diff --git a/FBControlCore/Utility/FBDeveloperDiskImage.h b/FBControlCore/Utility/FBDeveloperDiskImage.h index 68fa44204..b96c731c9 100644 --- a/FBControlCore/Utility/FBDeveloperDiskImage.h +++ b/FBControlCore/Utility/FBDeveloperDiskImage.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -16,6 +16,14 @@ NS_ASSUME_NONNULL_BEGIN #pragma mark Initializers +/** + Returns Disk Image for already mounted disk image. + + @param signature Signature of the mounted image. + @return the path of the disk image. + */ ++ (FBDeveloperDiskImage *) unknownDiskImageWithSignature:(NSData *)signature; + /** Finds the Disk Image for the given device, if one can be found. If an exact match is not found, the closest match will be used. diff --git a/FBControlCore/Utility/FBDeveloperDiskImage.m b/FBControlCore/Utility/FBDeveloperDiskImage.m index 0e42279e5..dde1ebcb7 100644 --- a/FBControlCore/Utility/FBDeveloperDiskImage.m +++ b/FBControlCore/Utility/FBDeveloperDiskImage.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -9,6 +9,8 @@ #import +static NSString *const ExtraDeviceSupportDirEnv = @"IDB_EXTRA_DEVICE_SUPPORT_DIR"; + static NSInteger ScoreVersions(NSOperatingSystemVersion current, NSOperatingSystemVersion target) { NSInteger major = ABS((current.majorVersion - target.majorVersion) * 10); @@ -34,7 +36,7 @@ @implementation FBDeveloperDiskImage } [images addObject:image]; } - return images; + return [images sortedArrayUsingSelector:@selector(compare:)]; } + (nullable FBDeveloperDiskImage *)diskImageAtPath:(NSString *)path xcodeVersion:(NSOperatingSystemVersion)xcodeVersion error:(NSError **)error @@ -70,10 +72,24 @@ + (FBDeveloperDiskImage *)developerDiskImage:(NSOperatingSystemVersion)targetVer static NSArray *images = nil; dispatch_once(&onceToken, ^{ images = [self allDiskImagesFromSearchPath:[platformRootDirectory stringByAppendingPathComponent:@"DeviceSupport"] xcodeVersion:FBXcodeConfiguration.xcodeVersion logger:FBControlCoreGlobalConfiguration.defaultLogger]; + if ([[NSProcessInfo.processInfo.environment allKeys] containsObject:ExtraDeviceSupportDirEnv]) { + NSArray *extraImages = [self allDiskImagesFromSearchPath:NSProcessInfo.processInfo.environment[ExtraDeviceSupportDirEnv] xcodeVersion:FBXcodeConfiguration.xcodeVersion logger:FBControlCoreGlobalConfiguration.defaultLogger]; + images = [images arrayByAddingObjectsFromArray:extraImages]; + } }); return images; } ++ (FBDeveloperDiskImage *) unknownDiskImageWithSignature:(NSData *)signature +{ + NSOperatingSystemVersion unknownVersion = { + .majorVersion = 0, + .minorVersion = 0, + .patchVersion = 0, + }; + return [[self alloc] initWithDiskImagePath:@"unknown.dmg" signature:signature version:unknownVersion xcodeVersion:unknownVersion]; +} + - (instancetype)initWithDiskImagePath:(NSString *)diskImagePath signature:(NSData *)signature version:(NSOperatingSystemVersion)version xcodeVersion:(NSOperatingSystemVersion)xcodeVersion { self = [super init]; @@ -99,16 +115,40 @@ + (NSString *)pathForDeveloperSymbols:(NSString *)buildVersion logger:(id *paths = NSMutableArray.array; for (NSString *searchPath in searchPaths) { - for (NSString *fileName in [NSFileManager.defaultManager enumeratorAtPath:searchPath]) { - NSString *path = [searchPath stringByAppendingPathComponent:fileName]; - if ([path containsString:buildVersion]) { - return [path stringByAppendingPathComponent:@"Symbols"]; + NSError *innerError = nil; + NSArray *supportPaths = [NSFileManager.defaultManager contentsOfDirectoryAtPath:searchPath error:&innerError]; + if (!supportPaths) { + continue; + } + for (NSString *supportName in supportPaths) { + NSString *supportPath = [searchPath stringByAppendingPathComponent:supportName]; + BOOL isDirectory = NO; + if (![NSFileManager.defaultManager fileExistsAtPath:supportPath isDirectory:&isDirectory]) { + continue; + } + if (isDirectory == NO) { + continue; + } + NSString *symbolsPath = [supportPath stringByAppendingPathComponent:@"Symbols"]; + if (![NSFileManager.defaultManager fileExistsAtPath:symbolsPath isDirectory:&isDirectory]) { + continue; } + if (isDirectory == NO) { + continue; + } + [paths addObject:symbolsPath]; } } + for (NSString *path in paths) { + if (![path containsString:buildVersion]) { + continue; + } + return path; + } return [[FBControlCoreError - describeFormat:@"Could not find the Symbols for %@", self] + describeFormat:@"Could not find the Symbols for %@ in any of %@", buildVersion, [FBCollectionInformation oneLineDescriptionFromArray:paths]] fail:error]; } @@ -155,4 +195,17 @@ - (NSString *)description return [NSString stringWithFormat:@"%@: %lu.%lu", self.diskImagePath, self.version.majorVersion, self.version.minorVersion]; } +- (NSComparisonResult)compare:(FBDeveloperDiskImage *)other +{ + NSComparisonResult comparison = [@(self.version.majorVersion) compare:@(other.version.majorVersion)]; + if (comparison != NSOrderedSame) { + return comparison; + } + comparison = [@(self.version.minorVersion) compare:@(other.version.minorVersion)]; + if (comparison != NSOrderedSame) { + return comparison; + } + return [@(self.version.patchVersion) compare:@(other.version.patchVersion)]; +} + @end diff --git a/FBControlCore/Utility/FBDispatchSourceNotifier.h b/FBControlCore/Utility/FBDispatchSourceNotifier.h deleted file mode 100644 index 3cf8655f6..000000000 --- a/FBControlCore/Utility/FBDispatchSourceNotifier.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#import - -#import - -NS_ASSUME_NONNULL_BEGIN - -/** - A class for wrapping `dispatch_source` with some conveniences. - */ -@interface FBDispatchSourceNotifier : NSObject - -#pragma mark Constructors - -/** - A future that resolves when the given process identifier terminates. - - @param processIdentifier the process identifier to observe. - @return a Future that resolves when the process identifier terminates, with the process identifier. - */ -+ (FBFuture *)processTerminationFutureNotifierForProcessIdentifier:(pid_t)processIdentifier; - -/** - Creates and returns an `FBDispatchSourceNotifier` that will call the `handler` at a provided timing interval. - - @param timeInterval the time interval to wait for. - @param queue the queue to call back on. - @param handler the handler to call when the process exits - */ -+ (instancetype)timerNotifierNotifierWithTimeInterval:(uint64_t)timeInterval queue:(dispatch_queue_t)queue handler:(void (^)(FBDispatchSourceNotifier *))handler; - -#pragma mark Public Methods - -/** - Stops the Notifier. - */ -- (void)terminate; - -#pragma mark Properties - -/** - The Wrapped Dispatch Source. - */ -@property (nonatomic, strong, nullable, readonly) dispatch_source_t dispatchSource; - -@end - -NS_ASSUME_NONNULL_END diff --git a/FBControlCore/Utility/FBDispatchSourceNotifier.m b/FBControlCore/Utility/FBDispatchSourceNotifier.m deleted file mode 100644 index 5e439bb6a..000000000 --- a/FBControlCore/Utility/FBDispatchSourceNotifier.m +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#import "FBDispatchSourceNotifier.h" - -@implementation FBDispatchSourceNotifier - -#pragma mark Initializers - -+ (FBFuture *)processTerminationFutureNotifierForProcessIdentifier:(pid_t)processIdentifier -{ - dispatch_queue_t queue = dispatch_queue_create("com.facebook.fbcontrolcore.dispatch_notifier", DISPATCH_QUEUE_SERIAL); - dispatch_source_t source = dispatch_source_create( - DISPATCH_SOURCE_TYPE_PROC, - (unsigned long) processIdentifier, - DISPATCH_PROC_EXIT, - queue - ); - - FBMutableFuture *future = FBMutableFuture.future; - [future onQueue:queue respondToCancellation:^ FBFuture * { - dispatch_source_cancel(source); - return FBFuture.empty; - }]; - dispatch_source_set_event_handler(source, ^(){ - [future resolveWithResult:@(processIdentifier)]; - dispatch_source_cancel(source); - }); - dispatch_resume(source); - - return future; -} - -+ (instancetype)processTerminationNotifierForProcessIdentifier:(pid_t)processIdentifier queue:(dispatch_queue_t)queue handler:(void (^)(FBDispatchSourceNotifier *))handler -{ - dispatch_source_t dispatchSource = dispatch_source_create( - DISPATCH_SOURCE_TYPE_PROC, - (unsigned long) processIdentifier, - DISPATCH_PROC_EXIT, - queue - ); - return [[self alloc] initWithDispatchSource:dispatchSource handler:handler]; -} - -+ (instancetype)timerNotifierNotifierWithTimeInterval:(uint64_t)timeInterval queue:(dispatch_queue_t)queue handler:(void (^)(FBDispatchSourceNotifier *))handler -{ - dispatch_source_t dispatchSource = dispatch_source_create( - DISPATCH_SOURCE_TYPE_TIMER, - 0, - 0, - queue - ); - dispatch_source_set_timer(dispatchSource, dispatch_time(DISPATCH_TIME_NOW, (int64_t) timeInterval), timeInterval, 0); - return [[self alloc] initWithDispatchSource:dispatchSource handler:handler]; -} - -- (instancetype)initWithDispatchSource:(dispatch_source_t)dispatchSource handler:(void (^)(FBDispatchSourceNotifier *))handler -{ - self = [super init]; - if (!self) { - return nil; - } - - _dispatchSource = dispatchSource; - __weak typeof(self) weakSelf = self; - dispatch_source_set_event_handler(dispatchSource, ^(){ - __strong typeof(self) strongSelf = weakSelf; - handler(strongSelf); - }); - dispatch_resume(dispatchSource); - return self; -} - -#pragma mark Public - -- (void)terminate -{ - if (self.dispatchSource) { - dispatch_source_cancel(self.dispatchSource); - _dispatchSource = nil; - } -} - -- (void)dealloc -{ - [self terminate]; -} - -@end diff --git a/FBControlCore/Utility/FBFileReader.h b/FBControlCore/Utility/FBFileReader.h index c2ecfcfcc..30b931eae 100644 --- a/FBControlCore/Utility/FBFileReader.h +++ b/FBControlCore/Utility/FBFileReader.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Utility/FBFileReader.m b/FBControlCore/Utility/FBFileReader.m index 75fbd21a1..3c7121d22 100644 --- a/FBControlCore/Utility/FBFileReader.m +++ b/FBControlCore/Utility/FBFileReader.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Utility/FBFileWriter.h b/FBControlCore/Utility/FBFileWriter.h index 447762314..4e4ccea85 100644 --- a/FBControlCore/Utility/FBFileWriter.h +++ b/FBControlCore/Utility/FBFileWriter.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Utility/FBFileWriter.m b/FBControlCore/Utility/FBFileWriter.m index 1d1decf69..5372d74f1 100644 --- a/FBControlCore/Utility/FBFileWriter.m +++ b/FBControlCore/Utility/FBFileWriter.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Utility/FBInstrumentsOperation.h b/FBControlCore/Utility/FBInstrumentsOperation.h index 6caad95f6..3f5a36f0a 100644 --- a/FBControlCore/Utility/FBInstrumentsOperation.h +++ b/FBControlCore/Utility/FBInstrumentsOperation.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Utility/FBInstrumentsOperation.m b/FBControlCore/Utility/FBInstrumentsOperation.m index 48dde59a7..553df5a5d 100644 --- a/FBControlCore/Utility/FBInstrumentsOperation.m +++ b/FBControlCore/Utility/FBInstrumentsOperation.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -118,8 +118,8 @@ @implementation FBInstrumentsOperation } [logger logFormat:@"Starting instruments with arguments: %@", [FBCollectionInformation oneLineDescriptionFromArray:arguments]]; FBInstrumentsConsumer *instrumentsConsumer = [[FBInstrumentsConsumer alloc] init]; - id instrumentsLogger = [FBControlCoreLogger loggerToConsumer:instrumentsConsumer]; - id compositeLogger = [FBControlCoreLogger compositeLoggerWithLoggers:@[logger, instrumentsLogger]]; + id instrumentsLogger = [FBControlCoreLoggerFactory loggerToConsumer:instrumentsConsumer]; + id compositeLogger = [FBControlCoreLoggerFactory compositeLoggerWithLoggers:@[logger, instrumentsLogger]]; return [[[[[[[[FBProcessBuilder withLaunchPath:@"/usr/bin/instruments"] diff --git a/FBControlCore/Utility/FBLoggingWrapper.h b/FBControlCore/Utility/FBLoggingWrapper.h index 3bc92d2b0..8a00e825e 100644 --- a/FBControlCore/Utility/FBLoggingWrapper.h +++ b/FBControlCore/Utility/FBLoggingWrapper.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Utility/FBLoggingWrapper.m b/FBControlCore/Utility/FBLoggingWrapper.m index db72aa2f0..819e2306f 100644 --- a/FBControlCore/Utility/FBLoggingWrapper.m +++ b/FBControlCore/Utility/FBLoggingWrapper.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -100,7 +100,7 @@ - (void)runInvocation:(NSInvocation *)invocation + (FBEventReporterSubject *)subjectForBeforeInvocation:(NSString *)methodName descriptionOfArguments:(NSArray *)descriptionOfArguments logger:(id)logger { [logger.info logFormat:@"%@ called with: %@", methodName, [FBCollectionInformation oneLineDescriptionFromArray:descriptionOfArguments]]; - return [FBEventReporterSubject subjectForStartedCall:methodName arguments:descriptionOfArguments]; + return [FBEventReporterSubject subjectForStartedCall:methodName arguments:descriptionOfArguments reportNativeSwiftMethodCall: NO]; } + (FBEventReporterSubject *)subjectAfterCompletion:(FBFuture *)future methodName:(NSString *)methodName descriptionOfArguments:(NSArray *)descriptionOfArguments startDate:(NSDate *)startDate firstMethodArgument:(id)firstMethodArgument logger:(id)logger @@ -114,10 +114,10 @@ + (FBEventReporterSubject *)subjectAfterCompletion:(FBFuture *)future methodName if (error) { NSString *message = error.localizedDescription; [logger.debug logFormat:@"%@ failed with: %@", methodName, message]; - return [FBEventReporterSubject subjectForFailingCall:methodName duration:duration message:message size:size arguments:descriptionOfArguments]; + return [FBEventReporterSubject subjectForFailingCall:methodName duration:duration message:message size:size arguments:descriptionOfArguments reportNativeSwiftMethodCall: NO]; } else { [logger.debug logFormat:@"%@ succeeded", methodName]; - return [FBEventReporterSubject subjectForSuccessfulCall:methodName duration:duration size:size arguments:descriptionOfArguments]; + return [FBEventReporterSubject subjectForSuccessfulCall:methodName duration:duration size:size arguments:descriptionOfArguments reportNativeSwiftMethodCall: NO]; } } diff --git a/FBControlCore/Utility/FBProcessIO.h b/FBControlCore/Utility/FBProcessIO.h index 0031f8004..99bbc5f32 100644 --- a/FBControlCore/Utility/FBProcessIO.h +++ b/FBControlCore/Utility/FBProcessIO.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Utility/FBProcessIO.m b/FBControlCore/Utility/FBProcessIO.m index 01c89ac53..ea98a3593 100644 --- a/FBControlCore/Utility/FBProcessIO.m +++ b/FBControlCore/Utility/FBProcessIO.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Utility/FBProcessStream.h b/FBControlCore/Utility/FBProcessStream.h index c16785625..9dcaab36f 100644 --- a/FBControlCore/Utility/FBProcessStream.h +++ b/FBControlCore/Utility/FBProcessStream.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -37,6 +37,11 @@ typedef NS_ENUM(NSUInteger, FBProcessStreamAttachmentMode) { */ @property (nonatomic, assign, readonly) FBProcessStreamAttachmentMode mode; +/** + Checks fileDescriptor status and closes it if necessary; + */ +-(void)close; + @end /** diff --git a/FBControlCore/Utility/FBProcessStream.m b/FBControlCore/Utility/FBProcessStream.m index f2c3e8591..e03d43d14 100644 --- a/FBControlCore/Utility/FBProcessStream.m +++ b/FBControlCore/Utility/FBProcessStream.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -38,6 +38,12 @@ - (instancetype)initWithFileDescriptor:(int)fileDescriptor closeOnEndOfFile:(BOO return self; } +- (void)close +{ + if (self.fileDescriptor) { + close(self.fileDescriptor); + } +} @end #pragma mark FBProcessFileOutput diff --git a/FBControlCore/Utility/FBStorageUtils.h b/FBControlCore/Utility/FBStorageUtils.h index 65824cd5b..8e80596fb 100644 --- a/FBControlCore/Utility/FBStorageUtils.h +++ b/FBControlCore/Utility/FBStorageUtils.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Utility/FBStorageUtils.m b/FBControlCore/Utility/FBStorageUtils.m index fc9396471..1a3f4f3f2 100644 --- a/FBControlCore/Utility/FBStorageUtils.m +++ b/FBControlCore/Utility/FBStorageUtils.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Utility/FBTemporaryDirectory.h b/FBControlCore/Utility/FBTemporaryDirectory.h index ed069e675..e8fdf35ad 100644 --- a/FBControlCore/Utility/FBTemporaryDirectory.h +++ b/FBControlCore/Utility/FBTemporaryDirectory.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -49,7 +49,7 @@ NS_ASSUME_NONNULL_BEGIN /** Extracts archive data to a temporary location. - For the supported archives see -[FBArchiveOperations extractArchiveFromStream:toPath:queue:logger:] + For the supported archives see -[FBArchiveOperations extractArchiveAtPath:toPath:overrideModificationTime:queue:logger:] @param tarData NSData representation of the tar to extract @return a Context Future containing the root of the extraction tar @@ -58,23 +58,44 @@ NS_ASSUME_NONNULL_BEGIN /** Extracts a archive stream to a temporary location. - For the supported archives see -[FBArchiveOperations extractArchiveFromStream:toPath:queue:logger:] + For the supported archives see -[FBArchiveOperations extractArchiveAtPath:toPath:overrideModificationTime:queue:logger:] @param input stream containing tar data - @param compression compression format used by client + @param compression archive compression format @return a Context Future containing the root of the extraction tar */ - (FBFutureContext *)withArchiveExtractedFromStream:(FBProcessInput *)input compression:(FBCompressionFormat)compression; +/** + Extracts a archive stream to a temporary location. + For the supported archives see -[FBArchiveOperations extractArchiveAtPath:toPath:overrideModificationTime:queue:logger:] + + @param input stream containing tar data + @param compression archive compression format + @param overrideMTime if YES the archive contests' `mtime` will be ignored. Current timestamp will be used as mtime of extracted files/directories. + @return a Context Future containing the root of the extraction tar + */ +- (FBFutureContext *)withArchiveExtractedFromStream:(FBProcessInput *)input compression:(FBCompressionFormat)compression overrideModificationTime:(BOOL)overrideMTime; + /** Extracts an archive file to a temporary location. - For the supported archives see -[FBArchiveOperations extractArchiveAtPath:toPath:queue:logger:] + For the supported archives see -[FBArchiveOperations extractArchiveAtPath:toPath:overrideModificationTime:queue:logger:] @param filePath the file path to extract @return a Context Future containing the root of the extraction tar */ - (FBFutureContext *)withArchiveExtractedFromFile:(NSString *)filePath; +/** + Extracts an archive file to a temporary location. + For the supported archives see -[FBArchiveOperations extractArchiveAtPath:toPath:overrideModificationTime:queue:logger:] + + @param filePath the file path to extract + @param overrideMTime if YES the archive contests' `mtime` will be ignored. Current timestamp will be used as mtime of extracted files/directories. + @return a Context Future containing the root of the extraction tar + */ +- (FBFutureContext *)withArchiveExtractedFromFile:(NSString *)filePath overrideModificationTime:(BOOL)overrideMTime; + /** Takes the extraction directory of a tar and returns a list of files contained in the subfolders. diff --git a/FBControlCore/Utility/FBTemporaryDirectory.m b/FBControlCore/Utility/FBTemporaryDirectory.m index d67ff7d2c..18db92163 100644 --- a/FBControlCore/Utility/FBTemporaryDirectory.m +++ b/FBControlCore/Utility/FBTemporaryDirectory.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -82,20 +82,30 @@ - (NSURL *)ephemeralTemporaryDirectory } - (FBFutureContext *)withArchiveExtractedFromStream:(FBProcessInput *)input compression:(FBCompressionFormat)compression +{ + return [self withArchiveExtractedFromStream:input compression:compression overrideModificationTime:NO]; +} + +- (FBFutureContext *)withArchiveExtractedFromStream:(FBProcessInput *)input compression:(FBCompressionFormat)compression overrideModificationTime:(BOOL)overrideMTime { return [[self withTemporaryDirectory] onQueue:self.queue pend:^(NSURL *tempDir) { - return [[FBArchiveOperations extractArchiveFromStream:input toPath:tempDir.path queue:self.queue logger:self.logger compression:compression] mapReplace:tempDir]; + return [[FBArchiveOperations extractArchiveFromStream:input toPath:tempDir.path overrideModificationTime:overrideMTime queue:self.queue logger:self.logger compression:compression] mapReplace:tempDir]; }]; } - (FBFutureContext *)withArchiveExtractedFromFile:(NSString *)filePath +{ + return [self withArchiveExtractedFromFile:filePath overrideModificationTime:NO]; +} + +- (FBFutureContext *)withArchiveExtractedFromFile:(NSString *)filePath overrideModificationTime:(BOOL)overrideMTime { return [[self withTemporaryDirectory] onQueue:self.queue pend:^(NSURL *tempDir) { - return [[FBArchiveOperations extractArchiveAtPath:filePath toPath:tempDir.path queue:self.queue logger:self.logger] mapReplace:tempDir]; + return [[FBArchiveOperations extractArchiveAtPath:filePath toPath:tempDir.path overrideModificationTime:overrideMTime queue:self.queue logger:self.logger] mapReplace:tempDir]; }]; } diff --git a/FBControlCore/Utility/FBVideoFileWriter.h b/FBControlCore/Utility/FBVideoFileWriter.h index 22cbd0036..45869599b 100644 --- a/FBControlCore/Utility/FBVideoFileWriter.h +++ b/FBControlCore/Utility/FBVideoFileWriter.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Utility/FBVideoFileWriter.m b/FBControlCore/Utility/FBVideoFileWriter.m index a1502fe2d..c58ab45d8 100644 --- a/FBControlCore/Utility/FBVideoFileWriter.m +++ b/FBControlCore/Utility/FBVideoFileWriter.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Utility/FBVideoStream.h b/FBControlCore/Utility/FBVideoStream.h index 0f595822e..95dd4fbaa 100644 --- a/FBControlCore/Utility/FBVideoStream.h +++ b/FBControlCore/Utility/FBVideoStream.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Utility/FBVideoStream.m b/FBControlCore/Utility/FBVideoStream.m index 4bbc2f52a..c1bbabb09 100644 --- a/FBControlCore/Utility/FBVideoStream.m +++ b/FBControlCore/Utility/FBVideoStream.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -12,7 +12,7 @@ #import "FBControlCoreLogger.h" #import "FBDataConsumer.h" -static NSInteger const MaxAllowedUnprocessedDataCounts = 10; +static NSInteger const MaxAllowedUnprocessedDataCounts = 2; BOOL checkConsumerBufferLimit(id consumer, id logger) { if ([consumer conformsToProtocol:@protocol(FBDataConsumerAsync)]) { @@ -27,7 +27,7 @@ BOOL checkConsumerBufferLimit(id consumer, id failBool:error]; } NSData *headerData = AnnexBNALUStartCodeData(); - NSArray *attachmentsArray = (NSArray *) CMSampleBufferGetSampleAttachmentsArray(sampleBuffer, true); - BOOL hasKeyframe = attachmentsArray[0][(NSString *) kCMSampleAttachmentKey_NotSync] != nil; - if (hasKeyframe) { + NSMutableData *consumableData = [NSMutableData alloc]; + + bool isKeyFrame = false; + CFArrayRef attachments = + CMSampleBufferGetSampleAttachmentsArray(sampleBuffer, true); + if (CFArrayGetCount(attachments)) { + CFDictionaryRef attachment = (CFDictionaryRef)CFArrayGetValueAtIndex(attachments, 0); + CFBooleanRef dependsOnOthers = (CFBooleanRef)CFDictionaryGetValue( + attachment, kCMSampleAttachmentKey_DependsOnOthers); + isKeyFrame = (dependsOnOthers == kCFBooleanFalse); + } + + if (isKeyFrame) { CMFormatDescriptionRef format = CMSampleBufferGetFormatDescription(sampleBuffer); size_t spsSize, spsCount; const uint8_t *spsParameterSet; @@ -86,10 +96,10 @@ BOOL WriteFrameToAnnexBStream(CMSampleBufferRef sampleBuffer, id } NSData *spsData = [NSData dataWithBytes:spsParameterSet length:spsSize]; NSData *ppsData = [NSData dataWithBytes:ppsParameterSet length:ppsSize]; - [consumer consumeData:headerData]; - [consumer consumeData:spsData]; - [consumer consumeData:headerData]; - [consumer consumeData:ppsData]; + [consumableData appendData:headerData]; + [consumableData appendData:spsData]; + [consumableData appendData:headerData]; + [consumableData appendData:ppsData]; } // Get the underlying data buffer. @@ -113,7 +123,7 @@ BOOL WriteFrameToAnnexBStream(CMSampleBufferRef sampleBuffer, id size_t dataOffset = 0; while (dataOffset < dataLength - AVCCHeaderLength) { // Write start code to the elementary stream - [consumer consumeData:headerData]; + [consumableData appendData:headerData]; // Get our current position in the buffer void *currentDataPointer = dataPointer + dataOffset; @@ -129,15 +139,16 @@ BOOL WriteFrameToAnnexBStream(CMSampleBufferRef sampleBuffer, id void *nalUnitPointer = currentDataPointer + AVCCHeaderLength; if ([consumer conformsToProtocol:@protocol(FBDataConsumerSync)]) { NSData *nalUnitData = [NSData dataWithBytesNoCopy:nalUnitPointer length:nalLength freeWhenDone:NO]; - [consumer consumeData:nalUnitData]; + [consumableData appendData:nalUnitData]; } else { NSData *nalUnitData = [NSData dataWithBytes:nalUnitPointer length:nalLength]; - [consumer consumeData:nalUnitData]; + [consumableData appendData:nalUnitData]; } // Increment the offset for the next iteration. dataOffset += AVCCHeaderLength + nalLength; } + [consumer consumeData:consumableData]; return YES; } @@ -164,7 +175,7 @@ BOOL WriteJPEGDataToMJPEGStream(CMBlockBufferRef jpegDataBuffer, id *)requiredClassNames requiredFrameworks:(NSArray *)requiredFrameworks rootPermitted:(BOOL)rootPermitted; ++ (instancetype)xcodeFrameworkWithRelativePath:(NSString *)relativePath requiredClassNames:(NSArray *)requiredClassNames; /** Creates and returns FBWeakFramework with the provided absolute path @param absolutePath The Absolute Path of the Framework. @param requiredClassNames list of class names used to determin if framework load was successful - @param requiredFrameworks list of frameworks, that should be loaded before this framework loads @param rootPermitted YES if this Framework can be loaded from the root user, NO otherwise. @return a Weak Framework with given relativePath, list of checked class names and list of pre-loaded frameworks */ -+ (instancetype)frameworkWithPath:(NSString *)absolutePath requiredClassNames:(NSArray *)requiredClassNames requiredFrameworks:(NSArray *)requiredFrameworks rootPermitted:(BOOL)rootPermitted; ++ (instancetype)frameworkWithPath:(NSString *)absolutePath requiredClassNames:(NSArray *)requiredClassNames rootPermitted:(BOOL)rootPermitted; /** Loads framework by: diff --git a/FBControlCore/Utility/FBWeakFramework.m b/FBControlCore/Utility/FBWeakFramework.m index f1b0d4da1..6ffefb123 100644 --- a/FBControlCore/Utility/FBWeakFramework.m +++ b/FBControlCore/Utility/FBWeakFramework.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -24,10 +24,7 @@ @interface FBWeakFramework () @property (nonatomic, copy, readonly) NSString *name; @property (nonatomic, copy, readonly) NSString *basePath; @property (nonatomic, copy, readonly) NSString *relativePath; -@property (nonatomic, copy, readonly) NSArray *fallbackDirectories; @property (nonatomic, copy, readonly) NSArray *requiredClassNames; -@property (nonatomic, copy, readonly) NSArray *requiredFrameworks; -@property (nonatomic, assign, readonly) FBWeakFrameworkType type; @property (nonatomic, assign, readonly) BOOL rootPermitted; @@ -35,40 +32,27 @@ @interface FBWeakFramework () @implementation FBWeakFramework -+ (NSArray *)xcodeFallbackDirectories -{ - return @[ - [FBXcodeConfiguration.developerDirectory stringByAppendingPathComponent:@"../Frameworks"], - [FBXcodeConfiguration.developerDirectory stringByAppendingPathComponent:@"../SharedFrameworks"], - [FBXcodeConfiguration.developerDirectory stringByAppendingPathComponent:@"../Plugins"], - ]; -} - #pragma mark Initializers -+ (instancetype)xcodeFrameworkWithRelativePath:(NSString *)relativePath requiredClassNames:(NSArray *)requiredClassNames requiredFrameworks:(NSArray *)requiredFrameworks rootPermitted:(BOOL)rootPermitted ++ (instancetype)xcodeFrameworkWithRelativePath:(NSString *)relativePath requiredClassNames:(NSArray *)requiredClassNames { return [[FBWeakFramework alloc] initWithBasePath:FBXcodeConfiguration.developerDirectory relativePath:relativePath - fallbackDirectories:self.xcodeFallbackDirectories requiredClassNames:requiredClassNames - requiredFrameworks:requiredFrameworks rootPermitted:NO]; } -+ (instancetype)frameworkWithPath:(NSString *)absolutePath requiredClassNames:(NSArray *)requiredClassNames requiredFrameworks:(NSArray *)requiredFrameworks rootPermitted:(BOOL)rootPermitted ++ (instancetype)frameworkWithPath:(NSString *)absolutePath requiredClassNames:(NSArray *)requiredClassNames rootPermitted:(BOOL)rootPermitted { return [[FBWeakFramework alloc] initWithBasePath:absolutePath relativePath:@"" - fallbackDirectories:@[] requiredClassNames:requiredClassNames - requiredFrameworks:requiredFrameworks rootPermitted:rootPermitted]; } -- (instancetype)initWithBasePath:(NSString *)basePath relativePath:(NSString *)relativePath fallbackDirectories:(NSArray *)fallbackDirectories requiredClassNames:(NSArray *)requiredClassNames requiredFrameworks:(NSArray *)requiredFrameworks rootPermitted:(BOOL)rootPermitted +- (instancetype)initWithBasePath:(NSString *)basePath relativePath:(NSString *)relativePath requiredClassNames:(NSArray *)requiredClassNames rootPermitted:(BOOL)rootPermitted { self = [super init]; if (!self) { @@ -79,11 +63,8 @@ - (instancetype)initWithBasePath:(NSString *)basePath relativePath:(NSString *)r _basePath = basePath; _relativePath = relativePath; - _fallbackDirectories = fallbackDirectories; _requiredClassNames = requiredClassNames; - _requiredFrameworks = requiredFrameworks; _name = filename.stringByDeletingPathExtension; - _type = [filename.pathExtension isEqualToString:@"dylib"] ? FBWeakFrameworkDylib : FBWeakFrameworkTypeFramework; _rootPermitted = rootPermitted; return self; @@ -93,43 +74,11 @@ - (instancetype)initWithBasePath:(NSString *)basePath relativePath:(NSString *)r - (BOOL)loadWithLogger:(id)logger error:(NSError **)error; { - return [self loadFromRelativeDirectory:self.basePath fallbackDirectories:self.fallbackDirectories logger:logger error:error]; + return [self loadFromRelativeDirectory:self.basePath logger:logger error:error]; } #pragma mark Private -+ (NSString *)missingFrameworkNameWithErrorDescription:(NSString *)description -{ - if (!description) { - return nil; - } - - NSRange rpathRange = [description rangeOfString:@"@rpath/"]; - if (rpathRange.location == NSNotFound) { - return nil; - } - - NSRange searchRange = NSMakeRange(rpathRange.location, description.length - rpathRange.location); - - NSRange frameworkRange = [description rangeOfString:@".dylib" - options:NSCaseInsensitiveSearch - range:searchRange]; - - if (frameworkRange.location == NSNotFound) { - frameworkRange = [description rangeOfString:@".framework" - options:NSCaseInsensitiveSearch - range:searchRange]; - } - - if (frameworkRange.location == NSNotFound) { - frameworkRange = [description rangeOfString:@".ideplugin" options:NSCaseInsensitiveSearch range:NSMakeRange(rpathRange.location, description.length - rpathRange.location)]; - if (frameworkRange.location == NSNotFound) { - return nil; - } - } - return [description substringWithRange:NSMakeRange(rpathRange.location + rpathRange.length, frameworkRange.location - rpathRange.location - rpathRange.length + frameworkRange.length)]; -} - - (BOOL)allRequiredClassesExistsWithError:(NSError **)error { for (NSString *requiredClassName in self.requiredClassNames) { @@ -142,7 +91,7 @@ - (BOOL)allRequiredClassesExistsWithError:(NSError **)error return YES; } -- (BOOL)loadFromRelativeDirectory:(NSString *)relativeDirectory fallbackDirectories:(NSArray *)fallbackDirectories logger:(id)logger error:(NSError **)error +- (BOOL)loadFromRelativeDirectory:(NSString *)relativeDirectory logger:(id)logger error:(NSError **)error { // Checking if classes are already loaded. Error here is irrelevant (returning NO means something is not loaded) if ([self allRequiredClassesExistsWithError:nil] && self.requiredClassNames.count > 0) { @@ -155,14 +104,6 @@ - (BOOL)loadFromRelativeDirectory:(NSString *)relativeDirectory fallbackDirector return YES; } - // Load required frameworks - for (FBWeakFramework *requredFramework in self.requiredFrameworks) { - NSError *innerError = nil; - if (![requredFramework loadWithLogger:logger error:&innerError]) { - return [FBControlCoreError failBoolWithError:innerError errorOut:error]; - } - } - // Check that the framework can be loaded as root if root. if ([NSUserName() isEqualToString:@"root"] && self.rootPermitted == NO) { return [[FBControlCoreError @@ -178,130 +119,25 @@ - (BOOL)loadFromRelativeDirectory:(NSString *)relativeDirectory fallbackDirector failBool:error]; } - NSError *innerError = nil; - switch (self.type) { - case FBWeakFrameworkTypeFramework: { - NSBundle *bundle = [NSBundle bundleWithPath:path]; - if (!bundle) { - return [[FBControlCoreError - describeFormat:@"Failed to load the bundle for path %@", path] - failBool:error]; - } - - [logger.debug logFormat:@"%@: Loading from %@ ", self.name, path]; - if (![self loadBundle:bundle fallbackDirectories:fallbackDirectories logger:logger error:&innerError]) { - return [FBControlCoreError failBoolWithError:innerError errorOut:error]; - } - } - break; - - case FBWeakFrameworkDylib: - if (![self loadDylibNamed:self.relativePath - relativeDirectory:relativeDirectory - fallbackDirectories:fallbackDirectories - logger:logger - error:error]) { - return [[FBControlCoreError describeFormat:@"Failed to load %@", self.relativePath] failBool:error]; - } - break; - - default: - break; - } - - [logger.debug logFormat:@"%@: Successfully loaded", self.name]; - if (![self allRequiredClassesExistsWithError:&innerError]) { - [logger logFormat:@"Failed to load %@", path.lastPathComponent]; - return [FBControlCoreError failBoolWithError:innerError errorOut:error]; - } - if (![self verifyIfLoadedWithLogger:logger error:&innerError]) { - return [FBControlCoreError failBoolWithError:innerError errorOut:error]; - } - return YES; -} - -- (BOOL)loadBundle:(NSBundle *)bundle fallbackDirectories:(NSArray *)fallbackDirectories logger:(id)logger error:(NSError **)error -{ - NSError *innerError; - if ([bundle loadAndReturnError:&innerError]) { - return YES; - } - - BOOL isLinkingIssue = ([innerError.domain isEqualToString:NSCocoaErrorDomain] && innerError.code == NSExecutableLoadError); - if (!isLinkingIssue) { - return [[[FBControlCoreError - describeFormat:@"Error loading bundle at %@ and it was not a linking issue", bundle.bundlePath] - causedBy:innerError] - failBool:error]; - } - - // If it is linking issue, try to determine missing framework - [logger.debug logFormat:@"%@: Bundle could not be loaded from %@, attempting to find the Framework name", self.name, bundle.bundlePath]; - NSString *description = innerError.userInfo[@"NSDebugDescription"]; - NSString *missingFrameworkName = [self.class missingFrameworkNameWithErrorDescription:description]; - if (!missingFrameworkName) { - return [[[FBControlCoreError - describeFormat:@"Could not determine the missing framework name from %@", bundle.bundlePath] - causedBy:innerError] + NSBundle *bundle = [NSBundle bundleWithPath:path]; + if (!bundle) { + return [[FBControlCoreError + describeFormat:@"Failed to load the bundle for path %@", path] failBool:error]; } - if (![self loadMissingFrameworkNamed:missingFrameworkName - fallbackDirectories:fallbackDirectories - logger:logger - error:error]) { - return [[FBControlCoreError describeFormat:@"Could not load missing framework %@", missingFrameworkName] - failBool:error]; + [logger.debug logFormat:@"%@: Loading from %@ ", self.name, path]; + if (![bundle loadAndReturnError:error]) { + return NO; } - return [self loadBundle:bundle fallbackDirectories:fallbackDirectories logger:logger error:error]; - // Uncategorizable Error, return the original error - return [[FBControlCoreError - describeFormat:@"Missing Framework %@ could not be loaded from any fallback directories", missingFrameworkName] - failBool:error]; -} - -- (BOOL)loadDylibNamed:(NSString *)dylibName - relativeDirectory:(NSString *)relativeDirectory - fallbackDirectories:(NSArray *)fallbackDirectories - logger:(id)logger - error:(NSError **)error -{ - NSString *path = [relativeDirectory.stringByStandardizingPath stringByAppendingPathComponent:dylibName]; - if (!dlopen(path.UTF8String, RTLD_LAZY)) { - // Error may be - NSString *errorString = [NSString stringWithUTF8String:dlerror()]; - NSString *missingFrameworkName = [[self class] missingFrameworkNameWithErrorDescription:errorString]; - if (![self loadMissingFrameworkNamed:missingFrameworkName - fallbackDirectories:fallbackDirectories - logger:logger - error:error]) { - return [[FBControlCoreError describeFormat:@"Failed to load dylib %@ dependency %@", - dylibName, missingFrameworkName] - failBool:error]; - } - // Dependency loaded - retry - return [self loadDylibNamed:dylibName - relativeDirectory:relativeDirectory - fallbackDirectories:fallbackDirectories - logger:logger - error:error]; + [logger.debug logFormat:@"%@: Successfully loaded", self.name]; + if (![self allRequiredClassesExistsWithError:error]) { + [logger logFormat:@"Failed to load %@", path.lastPathComponent]; + return NO; } - return YES; -} - -- (BOOL)loadMissingFrameworkNamed:(NSString *)missingFrameworkName fallbackDirectories:(NSArray *)fallbackDirectories logger:(id)logger error:(NSError **)error -{ - // Try to load missing framework with locations from - FBWeakFramework *missingFramework = [FBWeakFramework xcodeFrameworkWithRelativePath:missingFrameworkName requiredClassNames:@[] requiredFrameworks:@[] rootPermitted:NO]; - [logger.debug logFormat:@"Attempting to load missing framework %@", missingFrameworkName]; - for (NSString *directory in fallbackDirectories) { - NSError *missingFrameworkLoadError = nil; - if (![missingFramework loadFromRelativeDirectory:directory fallbackDirectories:fallbackDirectories logger:logger error:&missingFrameworkLoadError]) { - [logger.debug logFormat:@"%@ could not be loaded from fallback directory %@", missingFrameworkName, directory]; - continue; - } - [logger.debug logFormat:@"%@ has been loaded from fallback directory '%@', re-attempting to load %@", missingFrameworkName, directory, self.name]; + if (![self verifyIfLoadedWithLogger:logger error:error]) { + return NO; } return YES; } diff --git a/FBControlCore/Utility/FBWeakFrameworkLoader.h b/FBControlCore/Utility/FBWeakFrameworkLoader.h deleted file mode 100644 index 95c79898f..000000000 --- a/FBControlCore/Utility/FBWeakFrameworkLoader.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#import - -@class FBWeakFramework; -@protocol FBControlCoreLogger; - -NS_ASSUME_NONNULL_BEGIN - -/** - A Utility Class for loading weak-linked Frameworks at runtime. - */ -@interface FBWeakFrameworkLoader : NSObject - -/** - Loads a list of Frameworks. - Will avoid re-loading already loaded Frameworks. - Will also completely bypass loading of user plugins to prevent compatability issues. - - @param weakFrameworks a list of frameworks to load - @param logger a logger for logging framework loading activities. - @param error an error out for any error that occurs. - @return YES if successful, NO otherwise. - */ -+ (BOOL)loadPrivateFrameworks:(NSArray *)weakFrameworks logger:(id)logger error:(NSError **)error; - -@end - -NS_ASSUME_NONNULL_END diff --git a/FBControlCore/Utility/FBWeakFrameworkLoader.m b/FBControlCore/Utility/FBWeakFrameworkLoader.m deleted file mode 100644 index d2f1901df..000000000 --- a/FBControlCore/Utility/FBWeakFrameworkLoader.m +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#import "FBWeakFrameworkLoader.h" - -#import - -#import - -#import "FBCollectionInformation.h" -#import "FBControlCoreError.h" -#import "FBControlCoreGlobalConfiguration.h" -#import "FBControlCoreLogger.h" -#import "FBWeakFramework.h" - -static BOOL (*originalNSBundleLoad)(NSBundle *, SEL, NSError **); -static NSString *const ignoredPathSlice = @"Library/Application Support/Developer/Shared/Xcode/Plug-ins"; - -/** - Loading xcplugins can pose an issue if the xcplugin statically links a symbol that the current process has linked dynamically. - If we bypass the loading of these plugins, we can be more confident that there won't be ambiguous symbols at runtime. - */ -static BOOL FBUserPluginBypassingBundleLoad(NSBundle *bundle, SEL selector, NSError **error) -{ - if (![bundle.bundlePath.pathExtension isEqualToString:@"xcplugin"]) { - return originalNSBundleLoad(bundle, selector, error); - } - NSString *pluginPath = bundle.bundlePath.stringByDeletingLastPathComponent; - if (![pluginPath hasSuffix:ignoredPathSlice]) { - return originalNSBundleLoad(bundle, selector, error); - } - id logger = FBControlCoreGlobalConfiguration.defaultLogger; - [logger.debug logFormat:@"Bypassing load of %@ as it is a User Plugin", bundle.bundlePath]; - return YES; -} - -@implementation FBWeakFrameworkLoader - -+ (void)swizzleBundleLoader -{ - static dispatch_once_t onceToken; - dispatch_once(&onceToken, ^{ - Method method = class_getInstanceMethod(NSBundle.class, @selector(loadAndReturnError:)); - originalNSBundleLoad = (BOOL(*)(NSBundle *, SEL, NSError **)) method_getImplementation(method); - method_setImplementation(method, (IMP) FBUserPluginBypassingBundleLoad); - }); -} - -// A Mapping of Class Names to the Frameworks that they belong to. This serves to: -// 1) Represent the Frameworks that FBControlCore is dependent on via their classes -// 2) Provide a path to the relevant Framework. -// 3) Provide a class for sanity checking the Framework load. -// 4) Provide a class that can be checked before the Framework load to avoid re-loading the same -// Framework if others have done so before. -// 5) Provide a sanity check that any preloaded Private Frameworks match the current xcode-select version -+ (BOOL)loadPrivateFrameworks:(NSArray *)weakFrameworks logger:(id)logger error:(NSError **)error -{ - // Swizzle the bundle loader to ensure that we don't load user plugins. - [self swizzleBundleLoader]; - - for (FBWeakFramework *framework in weakFrameworks) { - NSError *innerError = nil; - if (![framework loadWithLogger:logger error:&innerError]) { - return [FBControlCoreError failBoolWithError:innerError errorOut:error]; - } - } - - // We're done with loading Frameworks. - [logger.debug logFormat: - @"Loaded All Private Frameworks %@", - [FBCollectionInformation oneLineDescriptionFromArray:[weakFrameworks valueForKeyPath:@"@unionOfObjects.name"] atKeyPath:@"lastPathComponent"] - ]; - - return YES; -} - -@end diff --git a/FBControlCore/Utility/FBXCTraceOperation.h b/FBControlCore/Utility/FBXCTraceOperation.h index 4667c231d..4dec54aff 100644 --- a/FBControlCore/Utility/FBXCTraceOperation.h +++ b/FBControlCore/Utility/FBXCTraceOperation.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Utility/FBXCTraceOperation.m b/FBControlCore/Utility/FBXCTraceOperation.m index 4714e8739..2d3fc6e3d 100644 --- a/FBControlCore/Utility/FBXCTraceOperation.m +++ b/FBControlCore/Utility/FBXCTraceOperation.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Utility/FBXcodeConfiguration.h b/FBControlCore/Utility/FBXcodeConfiguration.h index 1b0e5da7b..effc8cbd5 100644 --- a/FBControlCore/Utility/FBXcodeConfiguration.h +++ b/FBControlCore/Utility/FBXcodeConfiguration.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -86,7 +86,7 @@ NS_ASSUME_NONNULL_BEGIN /** Return Developer directory if exist or nil. */ -+ (NSString *)getDeveloperDirectoryIfExists; ++ (nullable NSString *)getDeveloperDirectoryIfExists; @end diff --git a/FBControlCore/Utility/FBXcodeConfiguration.m b/FBControlCore/Utility/FBXcodeConfiguration.m index 8a339a610..9f9704d4e 100644 --- a/FBControlCore/Utility/FBXcodeConfiguration.m +++ b/FBControlCore/Utility/FBXcodeConfiguration.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -22,7 +22,7 @@ + (NSString *)developerDirectory return [self findXcodeDeveloperDirectoryOrAssert]; } -+ (NSString *)getDeveloperDirectoryIfExists ++ (nullable NSString *)getDeveloperDirectoryIfExists { return [self findXcodeDeveloperDirectoryFromXcodeSelect:nil]; } @@ -160,7 +160,7 @@ + (NSString *)findXcodeDeveloperDirectoryOrAssert return directory; } -+ (NSString *)findXcodeDeveloperDirectoryFromXcodeSelect:(NSError **)error ++ (nullable NSString *)findXcodeDeveloperDirectoryFromXcodeSelect:(NSError **)error { static dispatch_once_t onceToken; static NSString *directory; diff --git a/FBControlCore/Utility/FBXcodeDirectory.h b/FBControlCore/Utility/FBXcodeDirectory.h index 884ec9714..25e78e9d1 100644 --- a/FBControlCore/Utility/FBXcodeDirectory.h +++ b/FBControlCore/Utility/FBXcodeDirectory.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Utility/FBXcodeDirectory.m b/FBControlCore/Utility/FBXcodeDirectory.m index fc5bc30a6..caf26f68a 100644 --- a/FBControlCore/Utility/FBXcodeDirectory.m +++ b/FBControlCore/Utility/FBXcodeDirectory.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Utility/NSPredicate+FBControlCore.h b/FBControlCore/Utility/NSPredicate+FBControlCore.h index 5b42744c9..118335a03 100644 --- a/FBControlCore/Utility/NSPredicate+FBControlCore.h +++ b/FBControlCore/Utility/NSPredicate+FBControlCore.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCore/Utility/NSPredicate+FBControlCore.m b/FBControlCore/Utility/NSPredicate+FBControlCore.m index 9f6ac2731..7e1888c6c 100644 --- a/FBControlCore/Utility/NSPredicate+FBControlCore.m +++ b/FBControlCore/Utility/NSPredicate+FBControlCore.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCoreTests/Doubles/FBControlCoreLoggerDouble.h b/FBControlCoreTests/Doubles/FBControlCoreLoggerDouble.h index dd787b178..d1fbae8de 100644 --- a/FBControlCoreTests/Doubles/FBControlCoreLoggerDouble.h +++ b/FBControlCoreTests/Doubles/FBControlCoreLoggerDouble.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCoreTests/Doubles/FBControlCoreLoggerDouble.m b/FBControlCoreTests/Doubles/FBControlCoreLoggerDouble.m index 13b87a0dd..7128500a6 100644 --- a/FBControlCoreTests/Doubles/FBControlCoreLoggerDouble.m +++ b/FBControlCoreTests/Doubles/FBControlCoreLoggerDouble.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCoreTests/Doubles/FBiOSTargetDouble.h b/FBControlCoreTests/Doubles/FBiOSTargetDouble.h index aa0293a15..d7530871b 100644 --- a/FBControlCoreTests/Doubles/FBiOSTargetDouble.h +++ b/FBControlCoreTests/Doubles/FBiOSTargetDouble.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCoreTests/Doubles/FBiOSTargetDouble.m b/FBControlCoreTests/Doubles/FBiOSTargetDouble.m index e3a7cc45a..4d00f8a92 100644 --- a/FBControlCoreTests/Doubles/FBiOSTargetDouble.m +++ b/FBControlCoreTests/Doubles/FBiOSTargetDouble.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -9,7 +9,7 @@ @implementation FBiOSTargetDouble -@synthesize architecture; +@synthesize architectures; @synthesize logger; @synthesize platformRootDirectory; @synthesize runtimeRootDirectory; @@ -173,4 +173,14 @@ - (BOOL) requiresBundlesToBeSigned return NO; } +- (FBFuture *)resolveState:(FBiOSTargetState)state +{ + return FBMutableFuture.future; +} + +- (FBFuture *)resolveLeavesState:(FBiOSTargetState)state +{ + return FBMutableFuture.future; +} + @end diff --git a/FBControlCoreTests/FBControlCoreTests.xcconfig b/FBControlCoreTests/FBControlCoreTests.xcconfig index 8e4f09e4e..e1b3114fe 100644 --- a/FBControlCoreTests/FBControlCoreTests.xcconfig +++ b/FBControlCoreTests/FBControlCoreTests.xcconfig @@ -5,4 +5,6 @@ INFOPLIST_FILE = $(SRCROOT)/FBControlCoreTests/FBControlCoreTests-Info.plist LD_RUNPATH_SEARCH_PATHS = $(inherited) @executable_path/../Frameworks @loader_path/../Frameworks PRODUCT_BUNDLE_IDENTIFIER = com.facebook.FBControlCoreTests; -PRODUCT_NAME = FBControlCoreTests \ No newline at end of file +PRODUCT_NAME = FBControlCoreTests +// Only expose PrivateHeaders to Framework targets. Framework targets never expose PrivateHeader imports themselves. +HEADER_SEARCH_PATHS = $(inherited) $(SRCROOT)/PrivateHeaders diff --git a/FBControlCoreTests/Fixtures/FBControlCoreFixtures.h b/FBControlCoreTests/Fixtures/FBControlCoreFixtures.h index 735305695..5ccb63020 100644 --- a/FBControlCoreTests/Fixtures/FBControlCoreFixtures.h +++ b/FBControlCoreTests/Fixtures/FBControlCoreFixtures.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCoreTests/Fixtures/FBControlCoreFixtures.m b/FBControlCoreTests/Fixtures/FBControlCoreFixtures.m index d39946914..8b722f370 100644 --- a/FBControlCoreTests/Fixtures/FBControlCoreFixtures.m +++ b/FBControlCoreTests/Fixtures/FBControlCoreFixtures.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCoreTests/Fixtures/TestFixtures.swift b/FBControlCoreTests/Fixtures/TestFixtures.swift new file mode 100644 index 000000000..9b7ff45d8 --- /dev/null +++ b/FBControlCoreTests/Fixtures/TestFixtures.swift @@ -0,0 +1,31 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import Foundation + +private class BundleFinder {} + +enum TestFixtures { + + static let xctestBinary = Bundle(for: BundleFinder.self) + .path(forResource: "xctest", ofType: nil)! + + static let assetsdCrashPathWithCustomDeviceSet = Bundle(for: BundleFinder.self) + .path(forResource: "assetsd_custom_set", ofType: "crash")! + + static let appCrashPathWithDefaultDeviceSet = Bundle(for: BundleFinder.self) + .path(forResource: "app_default_set", ofType: "crash")! + + static let appCrashPathWithCustomDeviceSet = Bundle(for: BundleFinder.self) + .path(forResource: "app_custom_set", ofType: "crash")! + + static let agentCrashPathWithCustomDeviceSet = Bundle(for: BundleFinder.self) + .path(forResource: "agent_custom_set", ofType: "crash")! + + static let appCrashWithJSONFormat = Bundle(for: BundleFinder.self) + .path(forResource: "xctest-concated-json-crash", ofType: "ips")! +} diff --git a/FBControlCoreTests/Fixtures/xctest b/FBControlCoreTests/Fixtures/xctest new file mode 100755 index 000000000..e86fbbee9 Binary files /dev/null and b/FBControlCoreTests/Fixtures/xctest differ diff --git a/FBControlCoreTests/Fixtures/xctest-concated-json-crash.ips b/FBControlCoreTests/Fixtures/xctest-concated-json-crash.ips new file mode 100644 index 000000000..e56cc565a --- /dev/null +++ b/FBControlCoreTests/Fixtures/xctest-concated-json-crash.ips @@ -0,0 +1,157 @@ +{"app_name":"x{cte\"st","timestamp":"2022-04-20 14:36:33.00 +0100","app_version":"","slice_uuid":"d25eebb7-5d1a-3ffc-9705-8b3049bcfb7d","build_version":"","platform":7,"share_with_app_devs":0,"is_first_party":1,"bug_type":"309","os_version":"macOS 12.3.1 (21E258)","incident_id":"FC4D11AC-D309-4C8E-816E-7B6E676A86BB","name":"xctest2"} +{ + "uptime" : 63000, + "procLaunch" : "2022-04-20 14:36:33.4603 +0100", + "procRole" : "Unspecified", + "version" : 2, + "userID" : 501, + "deployVersion" : 210, + "modelCode" : "MacBookPro18,2", + "procStartAbsTime" : 1525933767136, + "coalitionID" : 6047, + "osVersion" : { + "train" : "macOS 12.3.1", + "build" : "21E258", + "releaseType" : "User" + }, + "captureTime" : "2022-04-20 14:36:33.5767 +0100", + "incident" : "FC4D11AC-D309-4C8E-816E-7B6E676A86BB", + "bug_type" : "309", + "pid" : 82406, + "procExitAbsTime" : 1525936544148, + "translated" : false, + "cpuType" : "ARM-64", + "procName" : "xctest3", + "procPath" : "\/Applications\/Xcode_13.3.0_fb.app\/Contents\/Developer\/Platforms\/iPhoneSimulator.platform\/Developer\/Library\/Xcode\/Agents\/xctest", + "parentProc" : "idb", + "parentPid" : 81861, + "coalitionName" : "com.facebook.idb", + "crashReporterKey" : "034E92EF-D66C-F5FC-58D9-A433F9468A97", + "responsiblePid" : 81861, + "responsibleProc" : "idb", + "wakeTime" : 2826, + "sleepWakeUUID" : "6E309954-1F0D-4F09-9842-DC2A0AC07EB8", + "sip" : "enabled", + "isCorpse" : 1, + "exception" : {"codes":"0x0000000000000001, 0x000000010482d290","rawCodes":[1,4370649744],"type":"EXC_BREAKPOINT","signal":"SIGTRAP"}, + "termination" : {"flags":0,"code":5,"namespace":"SIGNAL","indicator":"Trace\/BPT trap: 5","byProc":"exc handler","byPid":82406}, + "asi" : {"libsystem_sim_platform.dylib":["CoreSimulator 802.6 - Device: iPhone 13 (D95B17F2-6822-4CD1-B7AA-E73DB34FFD4E) - Runtime: iOS 15.4 (19E240) - DeviceType: iPhone 13"],"dyld_sim":["dyld4 config: DYLD_ROOT_PATH=\/Applications\/Xcode_13.3.0_fb.app\/Contents\/Developer\/Platforms\/iPhoneOS.platform\/Library\/Developer\/CoreSimulator\/Profiles\/Runtimes\/iOS.simruntime\/Contents\/Resources\/RuntimeRoot DYLD_INSERT_LIBRARIES=\/Users\/patskovn\/Library\/Developer\/Xcode\/DerivedData\/FocusedWorkspace-idb-fvgqoofcnsntizgjdlnrpvhmgdiy\/Build\/Products\/Debug\/idb.app\/Contents\/Resources\/libShimulator.dylib"],"dyld":["dyld4 config: DYLD_ROOT_PATH=\/Applications\/Xcode_13.3.0_fb.app\/Contents\/Developer\/Platforms\/iPhoneOS.platform\/Library\/Developer\/CoreSimulator\/Profiles\/Runtimes\/iOS.simruntime\/Contents\/Resources\/RuntimeRoot DYLD_INSERT_LIBRARIES=\/Users\/patskovn\/Library\/Developer\/Xcode\/DerivedData\/FocusedWorkspace-idb-fvgqoofcnsntizgjdlnrpvhmgdiy\/Build\/Products\/Debug\/idb.app\/Contents\/Resources\/libShimulator.dylib"]}, + "extMods" : {"caller":{"thread_create":0,"thread_set_state":0,"task_for_pid":0},"system":{"thread_create":0,"thread_set_state":1134,"task_for_pid":22},"targeted":{"thread_create":0,"thread_set_state":0,"task_for_pid":0},"warnings":0}, + "faultingThread" : 0, + "threads" : [{"triggered":true,"id":3149513,"threadState":{"x":[{"value":5326820104},{"value":5326819328},{"value":0},{"value":6443885816,"symbolLocation":0,"symbol":"nanov2_free_definite_size"},{"value":0},{"value":6099665664},{"value":52},{"value":18446744069414586112},{"value":8685750520079646824},{"value":8685750520079646824},{"value":18446744067265431187},{"value":2045},{"value":276},{"value":3644989709},{"value":3647088640},{"value":69},{"value":7711787404,"symbolLocation":0,"symbol":"pthread_setspecific"},{"value":1499463680},{"value":0},{"value":105553122837376},{"value":8027169688,"symbolLocation":230160,"symbol":"MethodSignatureROMTable"},{"value":6443986336,"symbolLocation":0,"symbol":"objc_msgSend"},{"value":5323639872},{"value":5323640192},{"value":105553122854592},{"value":105553122854592},{"value":4380798976},{"value":7955638240,"symbolLocation":0,"symbol":"_NSConcreteStackBlock"},{"value":7732979091,"objc-selector":"_duplicate"}],"flavor":"ARM_THREAD_STATE64","lr":{"value":4370649744},"cpsr":{"value":1610616832},"fp":{"value":6099666592},"sp":{"value":6099666304},"esr":{"value":4060086273,"description":"(Breakpoint) brk 1"},"pc":{"value":4370649744,"matchesCrashFrame":1},"far":{"value":7774058136}},"queue":"com.apple.main-thread","frames":[{"imageOffset":4752,"sourceLine":15,"sourceFile":"TpxUnitTests.m","symbol":"-[TpxUnitTests testExample1]","imageIndex":0,"symbolLocation":48},{"imageOffset":4752,"sourceLine":14,"sourceFile":"TpxUnitTests.m","symbol":"-[TpxUnitTests testExample1]","imageIndex":0,"symbolLocation":48},{"imageOffset":1170080,"symbol":"__invoking___","symbolLocation":144,"imageIndex":1},{"imageOffset":1159112,"symbol":"-[NSInvocation invoke]","symbolLocation":300,"imageIndex":1},{"imageOffset":392412,"symbol":"+[XCTFailableInvocation invokeStandardConventionInvocation:completion:]","symbolLocation":84,"imageIndex":2},{"imageOffset":392320,"symbol":"__90+[XCTFailableInvocation invokeInvocation:withTestMethodConvention:lastObservedErrorIssue:]_block_invoke_3","symbolLocation":24,"imageIndex":2},{"imageOffset":390872,"symbol":"__81+[XCTFailableInvocation invokeWithAsynchronousWait:lastObservedErrorIssue:block:]_block_invoke.13","symbolLocation":80,"imageIndex":2},{"imageOffset":125584,"symbol":"+[XCTSwiftErrorObservation observeErrorsInBlock:]","symbolLocation":140,"imageIndex":2},{"imageOffset":390500,"symbol":"+[XCTFailableInvocation invokeWithAsynchronousWait:lastObservedErrorIssue:block:]","symbolLocation":428,"imageIndex":2},{"imageOffset":391680,"symbol":"+[XCTFailableInvocation invokeInvocation:withTestMethodConvention:lastObservedErrorIssue:]","symbolLocation":252,"imageIndex":2},{"imageOffset":392532,"symbol":"+[XCTFailableInvocation invokeInvocation:lastObservedErrorIssue:]","symbolLocation":76,"imageIndex":2},{"imageOffset":316700,"symbol":"__24-[XCTestCase invokeTest]_block_invoke.287","symbolLocation":112,"imageIndex":2},{"imageOffset":93508,"symbol":"-[XCTestCase(XCTIssueHandling) _caughtUnhandledDeveloperExceptionPermittingControlFlowInterruptions:caughtInterruptionException:whileExecutingBlock:]","symbolLocation":172,"imageIndex":2},{"imageOffset":315628,"symbol":"-[XCTestCase invokeTest]","symbolLocation":836,"imageIndex":2},{"imageOffset":321708,"symbol":"__26-[XCTestCase performTest:]_block_invoke.396","symbolLocation":44,"imageIndex":2},{"imageOffset":93508,"symbol":"-[XCTestCase(XCTIssueHandling) _caughtUnhandledDeveloperExceptionPermittingControlFlowInterruptions:caughtInterruptionException:whileExecutingBlock:]","symbolLocation":172,"imageIndex":2},{"imageOffset":320252,"symbol":"__26-[XCTestCase performTest:]_block_invoke.375","symbolLocation":476,"imageIndex":2},{"imageOffset":211504,"symbol":"+[XCTContext runInContextForTestCase:markAsReportingBase:block:]","symbolLocation":220,"imageIndex":2},{"imageOffset":319276,"symbol":"-[XCTestCase performTest:]","symbolLocation":316,"imageIndex":2},{"imageOffset":23384,"sourceLine":428,"sourceFile":"XCTestReporterShim.m","symbol":"XCPerformTestWithSuppressedExpectedAssertionFailures","imageIndex":3,"symbolLocation":868},{"imageOffset":18988,"sourceLine":475,"sourceFile":"XCTestReporterShim.m","symbol":"XCTestCase_performTest","imageIndex":3,"symbolLocation":56},{"imageOffset":19300,"symbol":"-[XCTest runTest]","symbolLocation":60,"imageIndex":2},{"imageOffset":223820,"symbol":"-[XCTestSuite runTestBasedOnRepetitionPolicy:testRun:]","symbolLocation":156,"imageIndex":2},{"imageOffset":223416,"symbol":"__27-[XCTestSuite performTest:]_block_invoke","symbolLocation":208,"imageIndex":2},{"imageOffset":221888,"symbol":"__59-[XCTestSuite _performProtectedSectionForTest:testSection:]_block_invoke","symbolLocation":40,"imageIndex":2},{"imageOffset":211504,"symbol":"+[XCTContext runInContextForTestCase:markAsReportingBase:block:]","symbolLocation":220,"imageIndex":2},{"imageOffset":221800,"symbol":"-[XCTestSuite _performProtectedSectionForTest:testSection:]","symbolLocation":164,"imageIndex":2},{"imageOffset":222552,"symbol":"-[XCTestSuite performTest:]","symbolLocation":212,"imageIndex":2},{"imageOffset":19300,"symbol":"-[XCTest runTest]","symbolLocation":60,"imageIndex":2},{"imageOffset":223820,"symbol":"-[XCTestSuite runTestBasedOnRepetitionPolicy:testRun:]","symbolLocation":156,"imageIndex":2},{"imageOffset":223416,"symbol":"__27-[XCTestSuite performTest:]_block_invoke","symbolLocation":208,"imageIndex":2},{"imageOffset":221888,"symbol":"__59-[XCTestSuite _performProtectedSectionForTest:testSection:]_block_invoke","symbolLocation":40,"imageIndex":2},{"imageOffset":211504,"symbol":"+[XCTContext runInContextForTestCase:markAsReportingBase:block:]","symbolLocation":220,"imageIndex":2},{"imageOffset":221800,"symbol":"-[XCTestSuite _performProtectedSectionForTest:testSection:]","symbolLocation":164,"imageIndex":2},{"imageOffset":222552,"symbol":"-[XCTestSuite performTest:]","symbolLocation":212,"imageIndex":2},{"imageOffset":19300,"symbol":"-[XCTest runTest]","symbolLocation":60,"imageIndex":2},{"imageOffset":223820,"symbol":"-[XCTestSuite runTestBasedOnRepetitionPolicy:testRun:]","symbolLocation":156,"imageIndex":2},{"imageOffset":223416,"symbol":"__27-[XCTestSuite performTest:]_block_invoke","symbolLocation":208,"imageIndex":2},{"imageOffset":221888,"symbol":"__59-[XCTestSuite _performProtectedSectionForTest:testSection:]_block_invoke","symbolLocation":40,"imageIndex":2},{"imageOffset":211504,"symbol":"+[XCTContext runInContextForTestCase:markAsReportingBase:block:]","symbolLocation":220,"imageIndex":2},{"imageOffset":221800,"symbol":"-[XCTestSuite _performProtectedSectionForTest:testSection:]","symbolLocation":164,"imageIndex":2},{"imageOffset":222552,"symbol":"-[XCTestSuite performTest:]","symbolLocation":212,"imageIndex":2},{"imageOffset":19300,"symbol":"-[XCTest runTest]","symbolLocation":60,"imageIndex":2},{"imageOffset":26296,"symbol":"__89-[XCTTestRunSession executeTestsWithIdentifiers:skippingTestsWithIdentifiers:completion:]_block_invoke","symbolLocation":112,"imageIndex":2},{"imageOffset":211504,"symbol":"+[XCTContext runInContextForTestCase:markAsReportingBase:block:]","symbolLocation":220,"imageIndex":2},{"imageOffset":26024,"symbol":"-[XCTTestRunSession executeTestsWithIdentifiers:skippingTestsWithIdentifiers:completion:]","symbolLocation":260,"imageIndex":2},{"imageOffset":447948,"symbol":"__72-[XCTExecutionWorker enqueueTestIdentifiersToRun:testIdentifiersToSkip:]_block_invoke_2","symbolLocation":116,"imageIndex":2},{"imageOffset":448260,"symbol":"-[XCTExecutionWorker runWithError:]","symbolLocation":116,"imageIndex":2},{"imageOffset":200516,"symbol":"__25-[XCTestDriver _runTests]_block_invoke.322","symbolLocation":60,"imageIndex":2},{"imageOffset":62576,"symbol":"-[XCTestObservationCenter _observeTestExecutionForBlock:]","symbolLocation":312,"imageIndex":2},{"imageOffset":199732,"symbol":"-[XCTestDriver _runTests]","symbolLocation":1452,"imageIndex":2},{"imageOffset":20804,"symbol":"_XCTestMain","symbolLocation":116,"imageIndex":2},{"imageOffset":9628,"symbol":"main","symbolLocation":232,"imageIndex":4},{"imageOffset":7384,"symbol":"start_sim","symbolLocation":20,"imageIndex":5},{"imageOffset":20616,"symbol":"start","symbolLocation":516,"imageIndex":6}]},{"id":3149515,"frames":[{"imageOffset":10492,"symbol":"start_wqthread","symbolLocation":0,"imageIndex":7}]},{"id":3149516,"frames":[{"imageOffset":10492,"symbol":"start_wqthread","symbolLocation":0,"imageIndex":7}]}], + "usedImages" : [ + { + "source" : "P", + "arch" : "arm64", + "base" : 4370644992, + "CFBundleShortVersionString" : "1.0", + "CFBundleIdentifier" : "com.facebook.TpxUnitTests", + "size" : 16384, + "uuid" : "3cec66ab-9a13-32df-8d80-959d522d451e", + "path" : "\/Users\/USER\/Library\/Developer\/CoreSimulator\/Devices\/D95B17F2-6822-4CD1-B7AA-E73DB34FFD4E\/data\/fbsimulatorcontrol\/idb-test-bundles\/com.facebook.TpxUnitTests\/TpxUnitTests.xctest\/TpxUnitTests", + "name" : "TpxUnitTests", + "CFBundleVersion" : "1" + }, + { + "source" : "P", + "arch" : "arm64", + "base" : 6445445120, + "CFBundleShortVersionString" : "6.9", + "CFBundleIdentifier" : "com.apple.CoreFoundation", + "size" : 3862528, + "uuid" : "c913654a-e564-36de-a01e-7343a4defd27", + "path" : "\/Applications\/Xcode_13.3.0_fb.app\/Contents\/Developer\/Platforms\/iPhoneOS.platform\/Library\/Developer\/CoreSimulator\/Profiles\/Runtimes\/iOS.simruntime\/Contents\/Resources\/RuntimeRoot\/System\/Library\/Frameworks\/CoreFoundation.framework\/CoreFoundation", + "name" : "CoreFoundation", + "CFBundleVersion" : "1858.112" + }, + { + "source" : "P", + "arch" : "arm64", + "base" : 4380000256, + "CFBundleShortVersionString" : "13.3", + "CFBundleIdentifier" : "com.apple.dt.XCTestCore", + "size" : 655360, + "uuid" : "e8d1b91e-ec26-396c-98ae-fc24590fb33f", + "path" : "\/Applications\/Xcode_13.3.0_fb.app\/Contents\/Developer\/Platforms\/iPhoneSimulator.platform\/Developer\/Library\/PrivateFrameworks\/XCTestCore.framework\/XCTestCore", + "name" : "XCTestCore", + "CFBundleVersion" : "20076" + }, + { + "source" : "P", + "arch" : "arm64", + "base" : 4370169856, + "size" : 32768, + "uuid" : "720799db-4a78-3925-b0b3-3bf8a38240fa", + "path" : "\/Users\/USER\/Library\/Developer\/Xcode\/DerivedData\/FocusedWorkspace-idb-fvgqoofcnsntizgjdlnrpvhmgdiy\/Build\/Products\/Debug\/idb.app\/Contents\/Resources\/libShimulator.dylib", + "name" : "libShimulator.dylib" + }, + { + "source" : "P", + "arch" : "arm64", + "base" : 4367204352, + "size" : 16384, + "uuid" : "d25eebb7-5d1a-3ffc-9705-8b3049bcfb7d", + "path" : "\/Applications\/Xcode_13.3.0_fb.app\/Contents\/Developer\/Platforms\/iPhoneSimulator.platform\/Developer\/Library\/Xcode\/Agents\/xctest", + "name" : "xctest" + }, + { + "source" : "P", + "arch" : "arm64", + "base" : 4369416192, + "size" : 245760, + "uuid" : "6e6188a1-7b04-3ae8-be81-cb35b05b8358", + "path" : "\/Applications\/Xcode_13.3.0_fb.app\/Contents\/Developer\/Platforms\/iPhoneOS.platform\/Library\/Developer\/CoreSimulator\/Profiles\/Runtimes\/iOS.simruntime\/Contents\/Resources\/RuntimeRoot\/usr\/lib\/dyld_sim", + "name" : "dyld_sim" + }, + { + "source" : "P", + "arch" : "arm64e", + "base" : 4370972672, + "size" : 393216, + "uuid" : "fbb89662-e6f2-3434-b542-f75185ac5e74", + "path" : "\/usr\/lib\/dyld", + "name" : "dyld" + }, + { + "source" : "P", + "arch" : "arm64", + "base" : 7711776768, + "size" : 53248, + "uuid" : "9507407a-b251-3158-bc81-8cabbebe34de", + "path" : "\/usr\/lib\/system\/libsystem_pthread.dylib", + "name" : "libsystem_pthread.dylib" + } +], + "sharedCache" : { + "base" : 6442450944, + "size" : 2231648256, + "uuid" : "94b4e58a-7116-3dd7-90b4-0e1f4d2286c4" +}, + "vmSummary" : "ReadOnly portion of Libraries: Total=824.6M resident=0K(0%) swapped_out_or_unallocated=824.6M(100%)\nWritable regions: Total=813.2M written=0K(0%) resident=0K(0%) swapped_out=0K(0%) unallocated=813.2M(100%)\n\n VIRTUAL REGION \nREGION TYPE SIZE COUNT (non-coalesced) \n=========== ======= ======= \nKernel Alloc Once 32K 1 \nMALLOC 180.2M 19 \nMALLOC guard page 96K 4 \nMALLOC_MEDIUM (reserved) 240.0M 2 reserved VM address space (unallocated)\nMALLOC_NANO (reserved) 384.0M 1 reserved VM address space (unallocated)\nSTACK GUARD 56.0M 3 \nStack 9264K 3 \n__DATA 9.9M 302 \n__DATA_CONST 27.0M 305 \n__DATA_DIRTY 34K 8 \n__FONT_DATA 4K 1 \n__LINKEDIT 525.7M 13 \n__OBJC_RO 63.0M 1 \n__OBJC_RW 3168K 1 \n__TEXT 298.9M 312 \n__UNICODE 592K 1 \ndyld private memory 2048K 2 \nmapped file 29.2M 2 \n=========== ======= ======= \nTOTAL 1.8G 981 \nTOTAL, minus reserved VM space 1.2G 981 \n", + "legacyInfo" : { + "threadTriggered" : { + "queue" : "com.apple.main-thread" + } +}, + "trialInfo" : { + "rollouts" : [ + { + "rolloutId" : "61af99aeda72d16a4beb7756", + "factorPackIds" : { + + }, + "deploymentId" : 240000093 + }, + { + "rolloutId" : "607844aa04477260f58a8077", + "factorPackIds" : { + "SIRI_MORPHUN_ASSETS" : "6103050cbfe6dc472e1c982a" + }, + "deploymentId" : 240000066 + } + ], + "experiments" : [ + + ] +} +} diff --git a/FBControlCoreTests/Templates/FBControlCoreValueTestCase.h b/FBControlCoreTests/Templates/FBControlCoreValueTestCase.h index dadf82a5e..9a36ae0ee 100644 --- a/FBControlCoreTests/Templates/FBControlCoreValueTestCase.h +++ b/FBControlCoreTests/Templates/FBControlCoreValueTestCase.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCoreTests/Templates/FBControlCoreValueTestCase.m b/FBControlCoreTests/Templates/FBControlCoreValueTestCase.m index 0eee36665..ea8009632 100644 --- a/FBControlCoreTests/Templates/FBControlCoreValueTestCase.m +++ b/FBControlCoreTests/Templates/FBControlCoreValueTestCase.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCoreTests/Tests/Integration/FBControlCoreFrameworkLoaderTests.m b/FBControlCoreTests/Tests/Integration/FBControlCoreFrameworkLoaderTests.m new file mode 100644 index 000000000..7cc14d7e4 --- /dev/null +++ b/FBControlCoreTests/Tests/Integration/FBControlCoreFrameworkLoaderTests.m @@ -0,0 +1,56 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import + +#import + +@interface FBControlCoreFrameworkLoaderTests : XCTestCase + +@end + +@implementation FBControlCoreFrameworkLoaderTests + +- (void)assertLoadsFramework:(FBWeakFramework *)framework +{ + NSError *error = nil; + BOOL success = [framework loadWithLogger:FBControlCoreGlobalConfiguration.defaultLogger error:&error]; + XCTAssertNil(error); + XCTAssertTrue(success); +} + +- (void)testLoadsAccessibilityPlatformTranslation +{ + [self assertLoadsFramework:FBWeakFramework.AccessibilityPlatformTranslation]; +} + +- (void)testLoadsCoreSimulator +{ + [self assertLoadsFramework:FBWeakFramework.CoreSimulator]; +} + +- (void)testLoadsDTXConnectionServices +{ + [self assertLoadsFramework:FBWeakFramework.DTXConnectionServices]; +} + +- (void)testLoadsMobileDevice +{ + [self assertLoadsFramework:FBWeakFramework.MobileDevice]; +} + +- (void)testLoadsSimulatorKit +{ + [self assertLoadsFramework:FBWeakFramework.SimulatorKit]; +} + +- (void)testLoadsXCTest +{ + [self assertLoadsFramework:FBWeakFramework.XCTest]; +} + +@end diff --git a/FBControlCoreTests/Tests/Integration/FBFileReaderTests.m b/FBControlCoreTests/Tests/Integration/FBFileReaderTests.m index 09d2c862a..52d05de84 100644 --- a/FBControlCoreTests/Tests/Integration/FBFileReaderTests.m +++ b/FBControlCoreTests/Tests/Integration/FBFileReaderTests.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -76,7 +76,7 @@ - (void)testConsumesEOFAfterStoppedReading NSData *expected = [@"Foo Bar Baz" dataUsingEncoding:NSUTF8StringEncoding]; [pipe.fileHandleForWriting writeData:expected]; - // Stop reading, we may recieve the consumeEndOfFile on a different queue + // Stop reading, we may receive the consumeEndOfFile on a different queue // This is fine as this call will block until the call has happened. // Also the assignment is atomic. NSNumber *result = [[reader stopReading] await:&error]; diff --git a/FBControlCoreTests/Tests/Integration/FBFileWriterTests.m b/FBControlCoreTests/Tests/Integration/FBFileWriterTests.m index 5fdfc2485..b25593749 100644 --- a/FBControlCoreTests/Tests/Integration/FBFileWriterTests.m +++ b/FBControlCoreTests/Tests/Integration/FBFileWriterTests.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCoreTests/Tests/Integration/FBProcessFetcherTests.m b/FBControlCoreTests/Tests/Integration/FBProcessFetcherTests.m new file mode 100644 index 000000000..ee3af1ad3 --- /dev/null +++ b/FBControlCoreTests/Tests/Integration/FBProcessFetcherTests.m @@ -0,0 +1,131 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import + +#import + +@interface FBProcessFetcherTests : XCTestCase + @property(nonatomic, retain)NSTask *task; +@end + +@implementation FBProcessFetcherTests +- (void)setUp { + NSTask* task = [[NSTask alloc] init]; + task.launchPath = @"/bin/sleep"; + task.arguments = @[@"10"]; + self.task = task; + [self.task launch]; +} + +- (void)tearDown { + if (self.task.running) { + [self.task terminate]; + [self.task waitUntilExit]; + } + + self.task = nil; +} + +- (void)testIsProcessRunningRunningProcess +{ + FBProcessFetcher *fetcher = [[FBProcessFetcher alloc] init]; + NSError *error; + + BOOL output = [fetcher isProcessRunning:self.task.processIdentifier error:&error]; + + XCTAssertNil(error); + XCTAssertTrue(output); +} + +- (void)testIsProcessRunningDeadProcess +{ + FBProcessFetcher *fetcher = [[FBProcessFetcher alloc] init]; + NSError *error; + + [self.task terminate]; + [self.task waitUntilExit]; + BOOL output = [fetcher isProcessRunning:self.task.processIdentifier error:&error]; + + XCTAssertNotNil(error); + XCTAssertFalse(output); +} + +- (void)testIsProcessRunningSuspendedProcess +{ + FBProcessFetcher *fetcher = [[FBProcessFetcher alloc] init]; + NSError *error; + + [self.task suspend]; + BOOL output = [fetcher isProcessRunning:self.task.processIdentifier error:&error]; + + XCTAssertNil(error); + XCTAssertFalse(output); +} + + +- (void)testIsProcessStoppedRunningProcess +{ + FBProcessFetcher *fetcher = [[FBProcessFetcher alloc] init]; + NSError *error; + + BOOL output = [fetcher isProcessStopped:self.task.processIdentifier error:&error]; + + XCTAssertNil(error); + XCTAssertFalse(output); +} + +- (void)testIsProcessStoppedDeadProcess +{ + FBProcessFetcher *fetcher = [[FBProcessFetcher alloc] init]; + NSError *error; + + [self.task terminate]; + [self.task waitUntilExit]; + BOOL output = [fetcher isProcessStopped:self.task.processIdentifier error:&error]; + + XCTAssertNotNil(error); + XCTAssertFalse(output); +} + +- (void)testIsProcessStoppedSuspendedProcess +{ + FBProcessFetcher *fetcher = [[FBProcessFetcher alloc] init]; + NSError *error; + + [self.task suspend]; + BOOL output = [fetcher isProcessStopped:self.task.processIdentifier error:&error]; + + XCTAssertNil(error); + XCTAssertTrue(output); +} + +- (void)testIsDebuggerAttachedToDeadProcess +{ + FBProcessFetcher *fetcher = [[FBProcessFetcher alloc] init]; + NSError *error; + + [self.task terminate]; + [self.task waitUntilExit]; + BOOL output = [fetcher isDebuggerAttachedTo:self.task.processIdentifier error:&error]; + + XCTAssertNotNil(error); + XCTAssertFalse(output); +} + +- (void)testIsDebuggerAttachedToProcessNoDebugger +{ + FBProcessFetcher *fetcher = [[FBProcessFetcher alloc] init]; + NSError *error; + + BOOL output = [fetcher isDebuggerAttachedTo:self.task.processIdentifier error:&error]; + + XCTAssertNil(error); + XCTAssertFalse(output); +} + +@end diff --git a/FBControlCoreTests/Tests/Integration/FBProcessIOTests.m b/FBControlCoreTests/Tests/Integration/FBProcessIOTests.m index a02137446..45a64efab 100644 --- a/FBControlCoreTests/Tests/Integration/FBProcessIOTests.m +++ b/FBControlCoreTests/Tests/Integration/FBProcessIOTests.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCoreTests/Tests/Integration/FBProcessStreamTests.m b/FBControlCoreTests/Tests/Integration/FBProcessStreamTests.m index 2e19d9261..715a60edb 100644 --- a/FBControlCoreTests/Tests/Integration/FBProcessStreamTests.m +++ b/FBControlCoreTests/Tests/Integration/FBProcessStreamTests.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCoreTests/Tests/Integration/FBProcessTests.m b/FBControlCoreTests/Tests/Integration/FBProcessTests.m index 2526c5f55..4617ac1b2 100644 --- a/FBControlCoreTests/Tests/Integration/FBProcessTests.m +++ b/FBControlCoreTests/Tests/Integration/FBProcessTests.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -467,7 +467,7 @@ - (void)testHUPBackoffToKILL XCTAssertEqual(process.statLoc.state, FBFutureStateDone); XCTAssertEqual(process.exitCode.state, FBFutureStateFailed); XCTAssertEqual(process.signal.state, FBFutureStateDone); - XCTAssertEqual(process.signal.result, @(SIGKILL)); + XCTAssertEqual(process.signal.result.intValue, SIGKILL); success = [process.statLoc await:&error] != nil; XCTAssertEqual(process.statLoc.state, FBFutureStateDone); diff --git a/FBControlCoreTests/Tests/Unit/AXTraitsTest.m b/FBControlCoreTests/Tests/Unit/AXTraitsTest.m index 39b2994b1..b719bdb33 100644 --- a/FBControlCoreTests/Tests/Unit/AXTraitsTest.m +++ b/FBControlCoreTests/Tests/Unit/AXTraitsTest.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCoreTests/Tests/Unit/FBArchitectureProcessAdapterTests.swift b/FBControlCoreTests/Tests/Unit/FBArchitectureProcessAdapterTests.swift new file mode 100644 index 000000000..bddd9f204 --- /dev/null +++ b/FBControlCoreTests/Tests/Unit/FBArchitectureProcessAdapterTests.swift @@ -0,0 +1,74 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import XCTest + +@testable import FBControlCore + +// swiftlint:disable implicitly_unwrapped_optional +final class FBArchitectureProcessAdapterTests: XCTestCase { + + var adapter: FBArchitectureProcessAdapter! + var processConfiguration: FBProcessSpawnConfiguration! + let targetQueue = DispatchQueue(label: "test_queue", qos: .userInteractive) + var tmpDir: FBTemporaryDirectory! + + func getArchsInBinary(binary: String) throws -> String { + try FBProcessBuilder + .withLaunchPath("/usr/bin/lipo", arguments: ["-archs", binary]) + .withStdOutInMemoryAsString() + .withStdErrToDevNull() + .runUntilCompletion(withAcceptableExitCodes: [0]) + .onQueue(targetQueue, map: { p in p.stdOut ?? "" }) + .await(withTimeout: 2) as! String // swiftlint:disable:this force_cast + } + + func adaptedProcess(requested: Set, host: Set) throws -> FBProcessSpawnConfiguration { + let tmpdir = tmpDir.temporaryDirectory() + return try adapter + .adaptProcessConfiguration(processConfiguration, toAnyArchitectureIn: requested, hostArchitectures: host, queue: targetQueue, temporaryDirectory: tmpdir) + .await(withTimeout: 10) + } + + override func setUp() { + tmpDir = .init(logger: FBControlCoreLoggerFactory.systemLoggerWriting(toStderr: true, withDebugLogging: true)) + adapter = .init() + processConfiguration = .init(launchPath: TestFixtures.xctestBinary, arguments: [], environment: [:], io: FBProcessIO.outputToDevNull(), mode: .posixSpawn) + } + + override func tearDown() { + tmpDir.cleanOnExit() + } + + func testBinaryIsThinnedDownTox86_64OnArm64Host() throws { + let newConf = try adaptedProcess(requested: [.X86_64], host: [.X86_64, .arm64]) + XCTAssertNotEqual(newConf.launchPath, processConfiguration.launchPath) + XCTAssertEqual(try getArchsInBinary(binary: newConf.launchPath), "x86_64") + } + + func testBinaryIsThinnedDownTox86_64Onx86_64Host() throws { + let newConf = try adaptedProcess(requested: [.X86_64, .arm64], host: [.X86_64]) + XCTAssertNotEqual(newConf.launchPath, processConfiguration.launchPath) + XCTAssertEqual(try getArchsInBinary(binary: newConf.launchPath), "x86_64") + } + + func testArm64ArchTakesPreference() throws { + let newConf = try adaptedProcess(requested: [.X86_64, .arm64], host: [.X86_64, .arm64]) + XCTAssertNotEqual(newConf.launchPath, processConfiguration.launchPath) + XCTAssertEqual(try getArchsInBinary(binary: newConf.launchPath), "arm64") + } + + func testMismatchFails() throws { + XCTAssertThrowsError(try adaptedProcess(requested: [.arm64], host: [.X86_64])) + } + + func testDyldFrameworkPathEnvVariableInProcessInfo() throws { + let process = try adaptedProcess(requested: [.X86_64], host: [.arm64, .X86_64]) + let frameworkPath = try XCTUnwrap(process.environment["DYLD_FRAMEWORK_PATH"]) + XCTAssertFalse(frameworkPath.isEmpty) + } +} diff --git a/FBControlCoreTests/Tests/Unit/FBBinaryDescriptorTests.m b/FBControlCoreTests/Tests/Unit/FBBinaryDescriptorTests.m index f9ddd7925..47103f76e 100644 --- a/FBControlCoreTests/Tests/Unit/FBBinaryDescriptorTests.m +++ b/FBControlCoreTests/Tests/Unit/FBBinaryDescriptorTests.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCoreTests/Tests/Unit/FBConcatedJsonParserTests.swift b/FBControlCoreTests/Tests/Unit/FBConcatedJsonParserTests.swift new file mode 100644 index 000000000..b1f151423 --- /dev/null +++ b/FBControlCoreTests/Tests/Unit/FBConcatedJsonParserTests.swift @@ -0,0 +1,62 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +@testable import FBControlCore +import XCTest + +class FBConcatedJsonParserTests: XCTestCase { + + func testPlainSmallJsonParse() throws { + let json = """ + {"hello": "world"} + """ + + try XCTAssertEqual(parse(string: json), ["hello": "world"]) + } + + func testPlainDoubleJsonParse() throws { + let json = """ + {"hello": "world"} + {"second": "value"} + """ + + try XCTAssertEqual(parse(string: json), ["hello": "world", "second": "value"]) + } + + func testWithCurlyBracketsInString() throws { + let json = """ + {"hello": "wor{ld"} + {"second": "value"} + """ + + try XCTAssertEqual(parse(string: json), ["hello": "wor{ld", "second": "value"]) + } + + func testWithEscapedCharatersInString() throws { + let json = """ + {"hello": "worl\\"d"} + {"second": "value"} + """ + + try XCTAssertEqual(parse(string: json), ["hello": "worl\"d", "second": "value"]) + } + + func testThrowsIncorrectJson() throws { + let json = """ + {"hello": 1"world"1} + """ + XCTAssertThrowsError(try parse(string: json)) + } + + private func parse(string: String) throws -> [String: String] { + guard let json = try FBConcatedJsonParser.parseConcatenatedJSON(from: string) as? [String: String] else { + throw NSError(domain: "Json parsed with incorrect type", code: 0) + } + + return json + } +} diff --git a/FBControlCoreTests/Tests/Unit/FBControlCoreLoggerTests.m b/FBControlCoreTests/Tests/Unit/FBControlCoreLoggerTests.m index 456586673..185430c6f 100644 --- a/FBControlCoreTests/Tests/Unit/FBControlCoreLoggerTests.m +++ b/FBControlCoreTests/Tests/Unit/FBControlCoreLoggerTests.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -22,7 +22,7 @@ - (void)testLoggingToFileDescriptor [[NSFileManager defaultManager] createFileAtPath:temporaryFilePath contents:nil attributes:nil]; NSFileHandle *fileHandle = [NSFileHandle fileHandleForWritingAtPath:temporaryFilePath]; - id logger = [FBControlCoreLogger loggerToFileDescriptor:fileHandle.fileDescriptor closeOnEndOfFile:NO]; + id logger = [FBControlCoreLoggerFactory loggerToFileDescriptor:fileHandle.fileDescriptor closeOnEndOfFile:NO]; [logger log:@"Some content"]; [fileHandle synchronizeFile]; [fileHandle closeFile]; @@ -36,7 +36,7 @@ - (void)testLoggingToFileDescriptor - (void)testLoggingToConsumer { id consumer = FBDataBuffer.consumableBuffer; - id logger = [FBControlCoreLogger loggerToConsumer:consumer]; + id logger = [FBControlCoreLoggerFactory loggerToConsumer:consumer]; [logger log:@"HELLO"]; [logger log:@"WORLD"]; @@ -56,7 +56,7 @@ - (void)testLoggingToConsumer - (void)testThreadSafetyOfConsumableLogger { id consumer = FBDataBuffer.consumableBuffer; - id logger = [FBControlCoreLogger loggerToConsumer:consumer]; + id logger = [FBControlCoreLoggerFactory loggerToConsumer:consumer]; dispatch_group_t group = dispatch_group_create(); dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0); diff --git a/FBControlCoreTests/Tests/Unit/FBControlCoreRunLoopTests.m b/FBControlCoreTests/Tests/Unit/FBControlCoreRunLoopTests.m index 819243819..4ad23f61a 100644 --- a/FBControlCoreTests/Tests/Unit/FBControlCoreRunLoopTests.m +++ b/FBControlCoreTests/Tests/Unit/FBControlCoreRunLoopTests.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCoreTests/Tests/Unit/FBCrashLogInfoTests.m b/FBControlCoreTests/Tests/Unit/FBCrashLogInfoTests.m deleted file mode 100644 index 51886c75f..000000000 --- a/FBControlCoreTests/Tests/Unit/FBCrashLogInfoTests.m +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#import - -#import - -#import "FBControlCoreFixtures.h" - -@interface FBCrashLogInfoTests : XCTestCase - -@end - -@implementation FBCrashLogInfoTests - -+ (NSArray *)allCrashLogs -{ - return @[ - [FBCrashLogInfo fromCrashLogAtPath:FBControlCoreFixtures.assetsdCrashPathWithCustomDeviceSet error:nil], - [FBCrashLogInfo fromCrashLogAtPath:FBControlCoreFixtures.agentCrashPathWithCustomDeviceSet error:nil], - [FBCrashLogInfo fromCrashLogAtPath:FBControlCoreFixtures.appCrashPathWithDefaultDeviceSet error:nil], - [FBCrashLogInfo fromCrashLogAtPath:FBControlCoreFixtures.appCrashPathWithCustomDeviceSet error:nil], - ]; -} - -- (void)testAssetsdCustomSet -{ - FBCrashLogInfo *info = [FBCrashLogInfo fromCrashLogAtPath:FBControlCoreFixtures.assetsdCrashPathWithCustomDeviceSet error:nil]; - XCTAssertNotNil(info); - XCTAssertEqual(info.processIdentifier, 39942); - XCTAssertEqual(info.parentProcessIdentifier, 39927); - XCTAssertEqualObjects(info.identifier, @"assetsd"); - XCTAssertEqualObjects(info.processName, @"assetsd"); - XCTAssertEqualObjects(info.parentProcessName, @"launchd_sim"); - XCTAssertEqualObjects(info.executablePath, @"/Applications/xcode_7.2.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/System/Library/Frameworks/AssetsLibrary.framework/Support/assetsd"); - XCTAssertEqualWithAccuracy(info.date.timeIntervalSinceReferenceDate, 479723902, 1); - XCTAssertEqual(info.processType, FBCrashLogInfoProcessTypeSystem); -} - -- (void)testAgentCustomSet -{ - FBCrashLogInfo *info = [FBCrashLogInfo fromCrashLogAtPath:FBControlCoreFixtures.agentCrashPathWithCustomDeviceSet error:nil]; - XCTAssertNotNil(info); - XCTAssertEqual(info.processIdentifier, 39655); - XCTAssertEqual(info.parentProcessIdentifier, 39576); - XCTAssertEqualObjects(info.identifier, @"WebDriverAgent"); - XCTAssertEqualObjects(info.processName, @"WebDriverAgent"); - XCTAssertEqualObjects(info.parentProcessName, @"launchd_sim"); - XCTAssertEqualObjects(info.executablePath, @"/Users/USER/*/WebDriverAgent"); - XCTAssertEqualWithAccuracy(info.date.timeIntervalSinceReferenceDate, 479723798, 1); - XCTAssertEqual(info.processType, FBCrashLogInfoProcessTypeCustom); -} - -- (void)testAppDefaultSet -{ - FBCrashLogInfo *info = [FBCrashLogInfo fromCrashLogAtPath:FBControlCoreFixtures.appCrashPathWithDefaultDeviceSet error:nil]; - XCTAssertNotNil(info); - XCTAssertEqual(info.processIdentifier, 37083); - XCTAssertEqual(info.parentProcessIdentifier, 37007); - XCTAssertEqualObjects(info.identifier, @"TableSearch"); - XCTAssertEqualObjects(info.processName, @"TableSearch"); - XCTAssertEqualObjects(info.parentProcessName, @"launchd_sim"); - XCTAssertEqualObjects(info.executablePath, @"/Users/USER/Library/Developer/CoreSimulator/Devices/2FF8DD07-20B7-4D04-97F0-092DF61CD3C3/data/Containers/Bundle/Application/2BF2C731-1965-497D-B3E2-E347BD7BF464/TableSearch.app/TableSearch"); - XCTAssertEqualWithAccuracy(info.date.timeIntervalSinceReferenceDate, 479723201, 1); - XCTAssertEqual(info.processType, FBCrashLogInfoProcessTypeApplication); -} - -- (void)testAppCustomSet -{ - FBCrashLogInfo *info = [FBCrashLogInfo fromCrashLogAtPath:FBControlCoreFixtures.appCrashPathWithCustomDeviceSet error:nil]; - XCTAssertNotNil(info); - XCTAssertEqual(info.processIdentifier, 40119); - XCTAssertEqual(info.parentProcessIdentifier, 39927); - XCTAssertEqualObjects(info.identifier, @"TableSearch"); - XCTAssertEqualObjects(info.processName, @"TableSearch"); - XCTAssertEqualObjects(info.parentProcessName, @"launchd_sim"); - XCTAssertEqualObjects(info.executablePath, @"/private/var/folders/*/TableSearch.app/TableSearch"); - XCTAssertEqualWithAccuracy(info.date.timeIntervalSinceReferenceDate, 479723902, 1); - XCTAssertEqual(info.processType, FBCrashLogInfoProcessTypeApplication); -} - -- (void)testIdentifierPredicate -{ - NSArray *crashes = [FBCrashLogInfoTests.allCrashLogs filteredArrayUsingPredicate:[FBCrashLogInfo predicateForIdentifier:@"assetsd"]]; - XCTAssertEqual(crashes.count, 1u); -} - -- (void)testNamePredicate -{ - NSArray *crashes = [FBCrashLogInfoTests.allCrashLogs filteredArrayUsingPredicate:[FBCrashLogInfo predicateForName:@"assetsd_custom_set.crash"]]; - XCTAssertEqual(crashes.count, 1u); -} - -@end diff --git a/FBControlCoreTests/Tests/Unit/FBCrashLogInfoTests.swift b/FBControlCoreTests/Tests/Unit/FBCrashLogInfoTests.swift new file mode 100644 index 000000000..146e35891 --- /dev/null +++ b/FBControlCoreTests/Tests/Unit/FBCrashLogInfoTests.swift @@ -0,0 +1,97 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +@testable import FBControlCore + +import XCTest + +final class FBCrashLogInfoTests: XCTestCase { + + func testAssetsdCustomSet() throws { + let info = try FBCrashLogInfo.fromCrashLog(atPath: TestFixtures.assetsdCrashPathWithCustomDeviceSet) + + XCTAssertEqual(info.processIdentifier, 39942) + XCTAssertEqual(info.parentProcessIdentifier, 39927) + XCTAssertEqual(info.identifier, "assetsd") + XCTAssertEqual(info.processName, "assetsd") + XCTAssertEqual(info.parentProcessName, "launchd_sim") + XCTAssertEqual(info.executablePath, "/Applications/xcode_7.2.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/System/Library/Frameworks/AssetsLibrary.framework/Support/assetsd") + XCTAssertEqual(info.date.timeIntervalSinceReferenceDate, 479723902, accuracy: 1) + XCTAssertEqual(info.processType, .system) + } + + func testAgentCustomSet() throws { + let info = try FBCrashLogInfo.fromCrashLog(atPath: TestFixtures.agentCrashPathWithCustomDeviceSet) + + XCTAssertEqual(info.processIdentifier, 39655) + XCTAssertEqual(info.parentProcessIdentifier, 39576) + XCTAssertEqual(info.identifier, "WebDriverAgent") + XCTAssertEqual(info.processName, "WebDriverAgent") + XCTAssertEqual(info.parentProcessName, "launchd_sim") + XCTAssertEqual(info.executablePath, "/Users/USER/*/WebDriverAgent") + XCTAssertEqual(info.date.timeIntervalSinceReferenceDate, 479723798, accuracy: 1) + XCTAssertEqual(info.processType, .custom) + } + + func testAppDefaultSet() throws { + let info = try FBCrashLogInfo.fromCrashLog(atPath: TestFixtures.appCrashPathWithDefaultDeviceSet) + + XCTAssertEqual(info.processIdentifier, 37083) + XCTAssertEqual(info.parentProcessIdentifier, 37007) + XCTAssertEqual(info.identifier, "TableSearch") + XCTAssertEqual(info.processName, "TableSearch") + XCTAssertEqual(info.parentProcessName, "launchd_sim") + XCTAssertEqual(info.executablePath, "/Users/USER/Library/Developer/CoreSimulator/Devices/2FF8DD07-20B7-4D04-97F0-092DF61CD3C3/data/Containers/Bundle/Application/2BF2C731-1965-497D-B3E2-E347BD7BF464/TableSearch.app/TableSearch") + XCTAssertEqual(info.date.timeIntervalSinceReferenceDate, 479723201, accuracy: 1) + XCTAssertEqual(info.processType, .application) + } + + func testAppCustomSet() throws { + let info = try FBCrashLogInfo.fromCrashLog(atPath: TestFixtures.appCrashPathWithCustomDeviceSet) + + XCTAssertEqual(info.processIdentifier, 40119) + XCTAssertEqual(info.parentProcessIdentifier, 39927) + XCTAssertEqual(info.identifier, "TableSearch") + XCTAssertEqual(info.processName, "TableSearch") + XCTAssertEqual(info.parentProcessName, "launchd_sim") + XCTAssertEqual(info.executablePath, "/private/var/folders/*/TableSearch.app/TableSearch") + XCTAssertEqual(info.date.timeIntervalSinceReferenceDate, 479723902, accuracy: 1) + XCTAssertEqual(info.processType, .application) + } + + func testIdentifierPredicate() throws { + try XCTAssertEqual(allCrashLogs.filtered(using: FBCrashLogInfo.predicate(forIdentifier: "assetsd")).count, 1) + } + + func testNamePredicate() throws { + try XCTAssertEqual(allCrashLogs.filtered(using: FBCrashLogInfo.predicate(forName: "assetsd_custom_set.crash")).count, 1) + } + + func testJSONCrashLogFormat() throws { + let info = try FBCrashLogInfo.fromCrashLog(atPath: TestFixtures.appCrashWithJSONFormat) + + XCTAssertEqual(info.processIdentifier, 82406) + XCTAssertEqual(info.parentProcessIdentifier, 81861) + XCTAssertEqual(info.identifier, "xctest3") + XCTAssertEqual(info.processName, "xctest3") + XCTAssertEqual(info.parentProcessName, "idb") + XCTAssertEqual(info.executablePath, "/Applications/Xcode_13.3.0_fb.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/Library/Xcode/Agents/xctest") + XCTAssertEqual(info.date.timeIntervalSinceReferenceDate, 672154593, accuracy: 1) + XCTAssertEqual(info.processType, .system) + } + + private var allCrashLogs: NSArray { + get throws { + return try [ + FBCrashLogInfo.fromCrashLog(atPath: TestFixtures.assetsdCrashPathWithCustomDeviceSet), + FBCrashLogInfo.fromCrashLog(atPath: TestFixtures.agentCrashPathWithCustomDeviceSet), + FBCrashLogInfo.fromCrashLog(atPath: TestFixtures.appCrashPathWithDefaultDeviceSet), + FBCrashLogInfo.fromCrashLog(atPath: TestFixtures.appCrashPathWithCustomDeviceSet), + ] + } + } +} diff --git a/FBControlCoreTests/Tests/Unit/FBDataBufferTests.m b/FBControlCoreTests/Tests/Unit/FBDataBufferTests.m index 4b979b6a7..ad266d9cd 100644 --- a/FBControlCoreTests/Tests/Unit/FBDataBufferTests.m +++ b/FBControlCoreTests/Tests/Unit/FBDataBufferTests.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCoreTests/Tests/Unit/FBFileContainerTests.m b/FBControlCoreTests/Tests/Unit/FBFileContainerTests.m index 1fc672259..d66be1452 100644 --- a/FBControlCoreTests/Tests/Unit/FBFileContainerTests.m +++ b/FBControlCoreTests/Tests/Unit/FBFileContainerTests.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -9,52 +9,334 @@ #import +#import "FBControlCoreFixtures.h" + @interface FBFileContainerTests : XCTestCase +@property (nonatomic, copy, readonly) NSString *basePathTestBasePath; +@property (nonatomic, copy, readonly) NSString *basePathPulledFileTestBasePath; +@property (nonatomic, copy, readonly) NSString *basePathPulledDirectoryTestBasePath; +@property (nonatomic, copy, readonly) NSString *basePathTestPathMappingFoo; +@property (nonatomic, copy, readonly) NSString *basePathTestPathMappingBar; +@property (nonatomic, copy, readonly) NSString *basePathPulledFileTestPathMapping; +@property (nonatomic, copy, readonly) NSString *basePathPulledDirectoryTestPathMapping; +@property (nonatomic, copy, readonly) NSString *basePathPulledMappedDirectoryTestPathMapping; @end @implementation FBFileContainerTests -- (void)testPathMapping +- (void)setUp +{ + [super setUp]; + + _basePathTestBasePath = [NSTemporaryDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:@"%@_FBSimulatorFileCommandsTests_testBasePath", NSUUID.UUID.UUIDString]]; + _basePathPulledFileTestBasePath = [NSTemporaryDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:@"%@_FBSimulatorFileCommandsTests_testBasePath_pulled_file", NSUUID.UUID.UUIDString]]; + _basePathPulledDirectoryTestBasePath = [NSTemporaryDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:@"%@_FBSimulatorFileCommandsTests_testBasePath_pulled_directory", NSUUID.UUID.UUIDString]]; + _basePathTestPathMappingFoo =[NSTemporaryDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:@"%@_FBSimulatorFileCommandsTests_testPathMapping_foo", NSUUID.UUID.UUIDString]]; + _basePathTestPathMappingBar = [NSTemporaryDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:@"%@_FBSimulatorFileCommandsTests_testPathMapping_bar", NSUUID.UUID.UUIDString]]; + _basePathPulledFileTestPathMapping = [NSTemporaryDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:@"%@_FBSimulatorFileCommandsTests_testPathMapping_pulled_file", NSUUID.UUID.UUIDString]];; + _basePathPulledDirectoryTestPathMapping = [NSTemporaryDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:@"%@_FBSimulatorFileCommandsTests_testPathMapping_pulled_directory", NSUUID.UUID.UUIDString]]; + _basePathPulledMappedDirectoryTestPathMapping = [NSTemporaryDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:@"%@_FBSimulatorFileCommandsTests_testPathMapping_pulled_mapped_directory", NSUUID.UUID.UUIDString]]; +} + +- (void)tearDown +{ + [super tearDown]; + + [NSFileManager.defaultManager removeItemAtPath:self.basePathTestBasePath error:nil]; + [NSFileManager.defaultManager removeItemAtPath:self.basePathPulledFileTestBasePath error:nil]; + [NSFileManager.defaultManager removeItemAtPath:self.basePathPulledDirectoryTestBasePath error:nil]; + [NSFileManager.defaultManager removeItemAtPath:self.basePathTestPathMappingFoo error:nil]; + [NSFileManager.defaultManager removeItemAtPath:self.basePathTestPathMappingBar error:nil]; + [NSFileManager.defaultManager removeItemAtPath:self.basePathPulledFileTestPathMapping error:nil]; + [NSFileManager.defaultManager removeItemAtPath:self.basePathPulledDirectoryTestPathMapping error:nil]; + [NSFileManager.defaultManager removeItemAtPath:self.basePathPulledMappedDirectoryTestPathMapping error:nil]; +} + +- (NSString *)basePath +{ + return self.basePathTestBasePath; +} + +- (NSString *)fileInBasePath +{ + return [self.basePath stringByAppendingPathComponent:@"file.txt"]; +} + +- (NSString *)directoryInBasePath { - NSString *fooPath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"FBSimulatorFileCommandsTests_testPathMapping_foo"]; - NSString *fileInFoo = [fooPath stringByAppendingPathComponent:@"file.txt"]; - NSString *barPath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"FBSimulatorFileCommandsTests_testPathMapping_bar"]; - NSString *directoryInBar = [barPath stringByAppendingPathComponent:@"dir"]; - NSString *fileInDirectoryInBar = [directoryInBar stringByAppendingPathComponent:@"in_dir.txt"]; + return [self.basePath stringByAppendingPathComponent:@"dir"]; +} + +- (NSString *)fileInDirectoryInBasePath +{ + return [self.directoryInBasePath stringByAppendingPathComponent:@"some.txt"]; +} +static NSString *const FileInBasePathText = @"Some Text"; +static NSString *const FileInDirectoryInBasePathText = @"Other Text"; + +- (id)setUpBasePathContainer +{ NSError *error = nil; - XCTAssertTrue([NSFileManager.defaultManager createDirectoryAtPath:fooPath withIntermediateDirectories:YES attributes:nil error:&error]); - XCTAssertTrue([NSFileManager.defaultManager createDirectoryAtPath:barPath withIntermediateDirectories:YES attributes:nil error:&error]); - XCTAssertTrue([NSFileManager.defaultManager createDirectoryAtPath:directoryInBar withIntermediateDirectories:YES attributes:nil error:&error]); + XCTAssertTrue([NSFileManager.defaultManager createDirectoryAtPath:self.basePath withIntermediateDirectories:YES attributes:nil error:&error]); + XCTAssertTrue([NSFileManager.defaultManager createDirectoryAtPath:self.directoryInBasePath withIntermediateDirectories:YES attributes:nil error:&error]); - NSString *fileInFooText = @"Some Text"; - XCTAssertTrue([fileInFooText writeToFile:fileInFoo atomically:YES encoding:NSUTF8StringEncoding error:&error]); + XCTAssertTrue([FileInBasePathText writeToFile:self.fileInBasePath atomically:YES encoding:NSUTF8StringEncoding error:&error]); + XCTAssertTrue([FileInDirectoryInBasePathText writeToFile:self.fileInDirectoryInBasePath atomically:YES encoding:NSUTF8StringEncoding error:&error]); - NSString *fileInDirectoryInBarText = @"Other Text"; - XCTAssertTrue([fileInDirectoryInBarText writeToFile:fileInDirectoryInBar atomically:YES encoding:NSUTF8StringEncoding error:&error]); + return [FBFileContainer fileContainerForBasePath:self.basePath]; +} - NSDictionary *pathMapping = @{@"foo": fooPath, @"bar": barPath}; - id container = [FBFileContainer fileContainerForPathMapping:pathMapping]; +- (NSString *)fooPath +{ + return self.basePathTestPathMappingFoo; +} - NSSet *expectedFiles = [NSSet setWithArray:@[@"foo", @"bar"]]; +- (NSString *)fileInFoo +{ + return [self.fooPath stringByAppendingPathComponent:@"file.txt"]; +} + +- (NSString *)barPath +{ + return self.basePathTestPathMappingBar; +} + +- (NSString *)directoryInBar +{ + return [self.barPath stringByAppendingPathComponent:@"dir"]; +} + +- (NSString *)fileInDirectoryInBar +{ + return [self.directoryInBar stringByAppendingPathComponent:@"in_dir.txt"]; +} + +NSString *FileInFooText = @"Some Text"; +NSString *FileInDirectoryInBarText = @"Other Text"; + +- (id)setUpMappedPathContainer +{ + NSError *error = nil; + XCTAssertTrue([NSFileManager.defaultManager createDirectoryAtPath:self.fooPath withIntermediateDirectories:YES attributes:nil error:&error]); + XCTAssertTrue([NSFileManager.defaultManager createDirectoryAtPath:self.barPath withIntermediateDirectories:YES attributes:nil error:&error]); + XCTAssertTrue([NSFileManager.defaultManager createDirectoryAtPath:self.directoryInBar withIntermediateDirectories:YES attributes:nil error:&error]); + + XCTAssertTrue([FileInFooText writeToFile:self.fileInFoo atomically:YES encoding:NSUTF8StringEncoding error:&error]); + XCTAssertTrue([FileInDirectoryInBarText writeToFile:self.fileInDirectoryInBar atomically:YES encoding:NSUTF8StringEncoding error:&error]); + + NSDictionary *pathMapping = @{@"foo": self.fooPath, @"bar": self.barPath}; + return [FBFileContainer fileContainerForPathMapping:pathMapping]; +} + +- (void)testBasePathDirectoryListingAtRoot +{ + id container = [self setUpBasePathContainer]; + NSError *error = nil; + NSSet *expectedFiles = [NSSet setWithArray:@[@"file.txt", @"dir"]]; NSArray *actualFiles = [[container contentsOfDirectory:@"."] await:&error]; XCTAssertNotNil(actualFiles); XCTAssertNil(error); XCTAssertEqualObjects(expectedFiles, [NSSet setWithArray:actualFiles]); +} + +- (void)testBasePathDirectoryListingAtSubdirectory +{ + id container = [self setUpBasePathContainer]; + NSError *error = nil; + NSSet *expectedFiles = [NSSet setWithArray:@[@"some.txt"]]; + NSArray *actualFiles = [[container contentsOfDirectory:@"dir"] await:&error]; + XCTAssertNotNil(actualFiles); + XCTAssertNil(error); + XCTAssertEqualObjects(expectedFiles, [NSSet setWithArray:actualFiles]); + // Listing a dir that doesn't exist fails. + XCTAssertNil([[container contentsOfDirectory:@"no_dir"] await:nil]); +} + +- (void)testBasePathPullFile +{ + id container = [self setUpBasePathContainer]; + NSError *error = nil; + NSString *pulledFileDirectory = self.basePathPulledFileTestBasePath; + NSString *pulledFile = [[container copyFromContainer:@"file.txt" toHost:pulledFileDirectory] await:&error]; + pulledFile = [pulledFile stringByAppendingPathComponent:@"file.txt"]; + XCTAssertNil(error); + XCTAssertNotNil(pulledFile); + NSString *actualContent = [NSString stringWithContentsOfFile:pulledFile encoding:NSUTF8StringEncoding error:&error]; + XCTAssertNil(error); + XCTAssertNotNil(actualContent); + NSString *expectedContent = FileInBasePathText; + XCTAssertEqualObjects(actualContent, expectedContent); +} + +- (void)testBasePathPullFileFromDirectory +{ + id container = [self setUpBasePathContainer]; + NSError *error = nil; + NSString *pulledFileDirectory = self.basePathPulledFileTestBasePath; + NSString *pulledFile = [[container copyFromContainer:@"dir/some.txt" toHost:pulledFileDirectory] await:&error]; + pulledFile = [pulledFile stringByAppendingPathComponent:@"some.txt"]; + NSString *actualContent = [NSString stringWithContentsOfFile:pulledFile encoding:NSUTF8StringEncoding error:&error]; + XCTAssertNotNil(actualContent); + NSString *expectedContent = FileInDirectoryInBasePathText; + XCTAssertEqualObjects(actualContent, expectedContent); +} + +- (void)testBasePathPullEntireDirectory +{ + id container = [self setUpBasePathContainer]; + NSError *error = nil; + NSString *pulledDirectoryDirectory = self.basePathPulledDirectoryTestBasePath; + NSString *pulledDirectory = [[container copyFromContainer:@"dir" toHost:pulledDirectoryDirectory] await:&error]; + NSSet *expectedFiles = [NSSet setWithArray:@[@"some.txt"]]; + NSArray *actualFiles = [NSFileManager.defaultManager contentsOfDirectoryAtPath:pulledDirectory error:&error]; + XCTAssertNotNil(actualFiles); + XCTAssertNil(error); + XCTAssertEqualObjects(expectedFiles, [NSSet setWithArray:actualFiles]); +} + +- (void)testBasePathCreateDirectory +{ + id container = [self setUpBasePathContainer]; + NSError *error =nil; + XCTAssertNotNil([[container createDirectory:@"other"] await:&error]); + XCTAssertNil(error); + NSSet *expectedFiles = [NSSet setWithArray:@[@"file.txt", @"dir", @"other"]]; + NSArray *actualFiles = [[container contentsOfDirectory:@"."] await:&error]; + XCTAssertNotNil(actualFiles); + XCTAssertNil(error); + XCTAssertNotNil([[container createDirectory:@"other/nested/here"] await:&error]); + XCTAssertNil(error); + expectedFiles = [NSSet setWithArray:@[@"nested"]]; + actualFiles = [[container contentsOfDirectory:@"other"] await:&error]; + XCTAssertNotNil(actualFiles); + XCTAssertNil(error); + expectedFiles = [NSSet setWithArray:@[@"here"]]; + actualFiles = [[container contentsOfDirectory:@"other/nested"] await:&error]; + XCTAssertNotNil(actualFiles); + XCTAssertNil(error); +} + +- (void)testBasePathPushFile +{ + id container = [self setUpBasePathContainer]; + NSError *error = nil; + NSString *pushedFile = FBControlCoreFixtures.photo0Path; + XCTAssertNotNil([[container copyFromHost:pushedFile toContainer:@"dir"] await:&error]); + NSSet *expectedFiles = [NSSet setWithArray:@[@"some.txt", @"photo0.png"]]; + NSArray *actualFiles = [[container contentsOfDirectory:@"dir"] await:&error]; + XCTAssertNotNil(actualFiles); + XCTAssertNil(error); + XCTAssertEqualObjects(expectedFiles, [NSSet setWithArray:actualFiles]); +} + +- (void)testBasePathPushDirectory +{ + id container = [self setUpBasePathContainer]; + NSError *error = nil; + NSString *pushedDirectory = FBControlCoreFixtures.photo0Path.stringByDeletingLastPathComponent; + XCTAssertNotNil([[container copyFromHost:pushedDirectory toContainer:@"dir"] await:&error]); + NSSet *expectedFiles = [NSSet setWithArray:@[@"some.txt", @"Resources"]]; + NSArray *actualFiles = [[container contentsOfDirectory:@"dir"] await:&error]; + XCTAssertNotNil(actualFiles); + XCTAssertNil(error); + XCTAssertEqualObjects(expectedFiles, [NSSet setWithArray:actualFiles]); + expectedFiles = [NSSet setWithArray:@[ + @"xctest", + @"app_custom_set.crash", + @"tree.json", + @"app_default_set.crash", + @"assetsd_custom_set.crash", + @"xctest-concated-json-crash.ips", + @"agent_custom_set.crash", + @"photo0.png", + @"simulator_system.log", + ]]; + actualFiles = [[container contentsOfDirectory:@"dir/Resources"] await:&error]; + XCTAssertNotNil(actualFiles); + XCTAssertNil(error); + XCTAssertEqualObjects(expectedFiles, [NSSet setWithArray:actualFiles]); +} + +- (void)testBasePathMoveFile +{ + id container = [self setUpBasePathContainer]; + NSError *error = nil; + XCTAssertNotNil([[container moveFrom:@"file.txt" to:@"dir/file.txt"] await:&error]); + XCTAssertNil(error); + NSSet *expectedFiles = [NSSet setWithArray:@[@"some.txt", @"file.txt"]]; + NSArray *actualFiles = [[container contentsOfDirectory:@"dir"] await:&error]; + XCTAssertNotNil(actualFiles); + XCTAssertNil(error); + XCTAssertEqualObjects(expectedFiles, [NSSet setWithArray:actualFiles]); +} + +- (void)testBasePathMoveDirectory +{ + id container = [self setUpBasePathContainer]; + NSError *error = nil; + XCTAssertNotNil([[container moveFrom:@"dir" to:@"moved_dir"] await:&error]); + XCTAssertNil(error); + NSSet *expectedFiles = [NSSet setWithArray:@[@"some.txt"]]; + NSArray *actualFiles = [[container contentsOfDirectory:@"moved_dir"] await:&error]; + XCTAssertNotNil(actualFiles); + XCTAssertNil(error); + XCTAssertEqualObjects(expectedFiles, [NSSet setWithArray:actualFiles]); + XCTAssertNil([[container contentsOfDirectory:@"dir"] await:nil]); + // Then back again. + XCTAssertNotNil([[container moveFrom:@"moved_dir" to:@"dir"] await:&error]); + XCTAssertNil(error); + expectedFiles = [NSSet setWithArray:@[@"some.txt"]]; + actualFiles = [[container contentsOfDirectory:@"dir"] await:&error]; + XCTAssertNotNil(actualFiles); + XCTAssertNil(error); + XCTAssertEqualObjects(expectedFiles, [NSSet setWithArray:actualFiles]); + XCTAssertNil([[container contentsOfDirectory:@"moved_dir"] await:nil]); +} - expectedFiles = [NSSet setWithArray:@[@"file.txt"]]; - actualFiles = [[container contentsOfDirectory:@"foo"] await:&error]; +- (void)testBasePathDeleteFile +{ + id container = [self setUpBasePathContainer]; + NSError *error = nil; + XCTAssertNotNil([[container remove:@"dir/some.txt"] await:&error]); + XCTAssertNil(error); + NSSet *expectedFiles = [NSSet setWithArray:@[]]; + NSArray *actualFiles = [[container contentsOfDirectory:@"dir"] await:&error]; + XCTAssertNotNil(actualFiles); + XCTAssertNil(error); + XCTAssertEqualObjects(expectedFiles, [NSSet setWithArray:actualFiles]); + XCTAssertNotNil([[container remove:@"dir"] await:&error]); + XCTAssertNil(error); + actualFiles = [[container contentsOfDirectory:@"dir"] await:nil]; + XCTAssertNil(actualFiles); +} + +- (void)testMappedPathDirectoryListingAtRoot +{ + id container = [self setUpMappedPathContainer]; + NSError *error = nil; + NSSet *expectedFiles = [NSSet setWithArray:@[@"foo", @"bar"]]; + NSArray *actualFiles = [[container contentsOfDirectory:@"."] await:&error]; XCTAssertNotNil(actualFiles); XCTAssertNil(error); XCTAssertEqualObjects(expectedFiles, [NSSet setWithArray:actualFiles]); +} +- (void)testMappedPathDirectoryListingInsideMapping +{ + id container = [self setUpMappedPathContainer]; + NSError *error = nil; + NSSet *expectedFiles = [NSSet setWithArray:@[@"file.txt"]]; + NSArray *actualFiles = [[container contentsOfDirectory:@"foo"] await:&error]; + XCTAssertNotNil(actualFiles); + XCTAssertNil(error); + XCTAssertEqualObjects(expectedFiles, [NSSet setWithArray:actualFiles]); expectedFiles = [NSSet setWithArray:@[@"dir"]]; actualFiles = [[container contentsOfDirectory:@"bar"] await:&error]; XCTAssertNotNil(actualFiles); XCTAssertNil(error); XCTAssertEqualObjects(expectedFiles, [NSSet setWithArray:actualFiles]); - expectedFiles = [NSSet setWithArray:@[@"in_dir.txt"]]; actualFiles = [[container contentsOfDirectory:@"bar/dir"] await:&error]; XCTAssertNotNil(actualFiles); @@ -62,4 +344,199 @@ - (void)testPathMapping XCTAssertEqualObjects(expectedFiles, [NSSet setWithArray:actualFiles]); } +- (void)testMappedPathDirectoryListingOfNonExistentDirectory +{ + id container = [self setUpMappedPathContainer]; + XCTAssertNil([[container contentsOfDirectory:@"no_dir"] await:nil]); +} + +- (void)testMappedPathPullFile +{ + id container = [self setUpMappedPathContainer]; + NSError *error = nil; + NSString *pulledFileDirectory = self.basePathPulledFileTestPathMapping; + NSString *pulledFile = [[container copyFromContainer:@"foo/file.txt" toHost:pulledFileDirectory] await:&error]; + pulledFile = [pulledFile stringByAppendingPathComponent:@"file.txt"]; + NSString *actualContent = [NSString stringWithContentsOfFile:pulledFile encoding:NSUTF8StringEncoding error:&error]; + XCTAssertNotNil(actualContent); + NSString *expectedContent = FileInFooText; + XCTAssertEqualObjects(actualContent, expectedContent); +} + +- (void)testMappedPathPullFileInMappedDirectory +{ + id container = [self setUpMappedPathContainer]; + NSError *error = nil; + NSString *pulledFileDirectory = self.basePathPulledFileTestPathMapping; + NSString *pulledFile = [[container copyFromContainer:@"bar/dir/in_dir.txt" toHost:pulledFileDirectory] await:&error]; + pulledFile = [pulledFile stringByAppendingPathComponent:@"in_dir.txt"]; + NSString *actualContent = [NSString stringWithContentsOfFile:pulledFile encoding:NSUTF8StringEncoding error:&error]; + XCTAssertNotNil(actualContent); + NSString *expectedContent = FileInDirectoryInBarText; + XCTAssertEqualObjects(actualContent, expectedContent); +} + +- (void)testMappedPathPullDirectory +{ + id container = [self setUpMappedPathContainer]; + NSError *error = nil; + NSString *pulledDirectoryDirectory = self.basePathPulledDirectoryTestPathMapping; + NSString *pulledDirectory = [[container copyFromContainer:@"bar/dir" toHost:pulledDirectoryDirectory] await:&error]; + NSSet *expectedFiles = [NSSet setWithArray:@[@"in_dir.txt"]]; + NSArray *actualFiles = [NSFileManager.defaultManager contentsOfDirectoryAtPath:pulledDirectory error:&error]; + XCTAssertNotNil(actualFiles); + XCTAssertNil(error); + XCTAssertEqualObjects(expectedFiles, [NSSet setWithArray:actualFiles]); +} + +- (void)testMappedPathPullRootPath +{ + id container = [self setUpMappedPathContainer]; + NSError *error = nil; + NSString *pulledDirectoryDirectory = self.basePathPulledMappedDirectoryTestPathMapping; + NSString *pulledDirectory = [[container copyFromContainer:@"bar" toHost:pulledDirectoryDirectory] await:&error]; + NSSet *expectedFiles = [NSSet setWithArray:@[@"dir"]]; + NSArray *actualFiles = [NSFileManager.defaultManager contentsOfDirectoryAtPath:pulledDirectory error:&error]; + XCTAssertNotNil(actualFiles); + XCTAssertNil(error); + XCTAssertEqualObjects(expectedFiles, [NSSet setWithArray:actualFiles]); +} + +- (void)testMappedPathCreateDirectoryInContainer +{ + id container = [self setUpMappedPathContainer]; + NSError *error = nil; + XCTAssertNotNil([[container createDirectory:@"foo/other"] await:&error]); + XCTAssertNil(error); + NSSet *expectedFiles = [NSSet setWithArray:@[@"file.txt", @"dir", @"other"]]; + NSArray *actualFiles = [[container contentsOfDirectory:@"foo"] await:&error]; + XCTAssertNotNil(actualFiles); + XCTAssertNil(error); + XCTAssertNotNil([[container createDirectory:@"foo/other/nested/here"] await:&error]); + XCTAssertNil(error); + expectedFiles = [NSSet setWithArray:@[@"nested"]]; + actualFiles = [[container contentsOfDirectory:@"foo/other"] await:&error]; + XCTAssertNotNil(actualFiles); + XCTAssertNil(error); + expectedFiles = [NSSet setWithArray:@[@"here"]]; + actualFiles = [[container contentsOfDirectory:@"foo/other/nested"] await:&error]; + XCTAssertNotNil(actualFiles); + XCTAssertNil(error); +} + +- (void)testMappedPathCreateDirectoryAtRootFails +{ + id container = [self setUpMappedPathContainer]; + XCTAssertNil([[container createDirectory:@"no_create"] await:nil]); +} + +- (void)testMappedPathPushFile +{ + id container = [self setUpMappedPathContainer]; + NSError *error = nil; + NSString *pushedFile = FBControlCoreFixtures.photo0Path; + XCTAssertNotNil([[container copyFromHost:pushedFile toContainer:@"bar/dir"] await:&error]); + NSSet *expectedFiles = [NSSet setWithArray:@[@"in_dir.txt", @"photo0.png"]]; + NSArray *actualFiles = [[container contentsOfDirectory:@"bar/dir"] await:&error]; + XCTAssertNotNil(actualFiles); + XCTAssertNil(error); + XCTAssertEqualObjects(expectedFiles, [NSSet setWithArray:actualFiles]); +} + +- (void)testMappedPathPushDirectory +{ + id container = [self setUpMappedPathContainer]; + NSError *error = nil; + NSString *pushedDirectory = FBControlCoreFixtures.photo0Path.stringByDeletingLastPathComponent; + XCTAssertNotNil([[container copyFromHost:pushedDirectory toContainer:@"bar/dir"] await:&error]); + NSSet *expectedFiles = [NSSet setWithArray:@[@"in_dir.txt", @"Resources"]]; + NSArray *actualFiles = [[container contentsOfDirectory:@"bar/dir"] await:&error]; + XCTAssertNotNil(actualFiles); + XCTAssertNil(error); + XCTAssertEqualObjects(expectedFiles, [NSSet setWithArray:actualFiles]); + expectedFiles = [NSSet setWithArray:@[ + @"xctest", + @"app_custom_set.crash", + @"tree.json", + @"app_default_set.crash", + @"assetsd_custom_set.crash", + @"xctest-concated-json-crash.ips", + @"agent_custom_set.crash", + @"photo0.png", + @"simulator_system.log", + ]]; + actualFiles = [[container contentsOfDirectory:@"bar/dir/Resources"] await:&error]; + XCTAssertNotNil(actualFiles); + XCTAssertNil(error); + XCTAssertEqualObjects(expectedFiles, [NSSet setWithArray:actualFiles]); +} + +- (void)testMappedPathPushToRootFails +{ + id container = [self setUpMappedPathContainer]; + NSString *pushedFile = FBControlCoreFixtures.photo0Path; + XCTAssertNil([[container copyFromHost:pushedFile toContainer:@"."] await:nil]); +} + +- (void)testMappedPathMoveFile +{ + id container = [self setUpMappedPathContainer]; + NSError *error = nil; + XCTAssertNotNil([[container moveFrom:@"foo/file.txt" to:@"bar/dir/file.txt"] await:&error]); + XCTAssertNil(error); + NSSet *expectedFiles = [NSSet setWithArray:@[@"in_dir.txt", @"file.txt"]]; + NSArray *actualFiles = [[container contentsOfDirectory:@"bar/dir"] await:&error]; + XCTAssertNotNil(actualFiles); + XCTAssertNil(error); + XCTAssertEqualObjects(expectedFiles, [NSSet setWithArray:actualFiles]); +} + +- (void)testMappedPathMoveDirectory +{ + id container = [self setUpMappedPathContainer]; + NSError *error = nil; + XCTAssertNotNil([[container moveFrom:@"bar/dir" to:@"bar/moved_dir"] await:&error]); + XCTAssertNil(error); + NSSet *expectedFiles = [NSSet setWithArray:@[@"in_dir.txt"]]; + NSArray *actualFiles = [[container contentsOfDirectory:@"bar/moved_dir"] await:&error]; + XCTAssertNotNil(actualFiles); + XCTAssertNil(error); + XCTAssertEqualObjects(expectedFiles, [NSSet setWithArray:actualFiles]); + XCTAssertNil([[container contentsOfDirectory:@"bar/dir"] await:nil]); + // Then back again. + XCTAssertNotNil([[container moveFrom:@"bar/moved_dir" to:@"bar/dir"] await:&error]); + XCTAssertNil(error); + expectedFiles = [NSSet setWithArray:@[@"in_dir.txt",]]; + actualFiles = [[container contentsOfDirectory:@"bar/dir"] await:&error]; + XCTAssertNotNil(actualFiles); + XCTAssertNil(error); + XCTAssertEqualObjects(expectedFiles, [NSSet setWithArray:actualFiles]); + XCTAssertNil([[container contentsOfDirectory:@"bar/moved_dir"] await:nil]); +} + +- (void)testMappedPathDeleteFile +{ + id container = [self setUpMappedPathContainer]; + NSError *error = nil; + XCTAssertNotNil([[container remove:@"bar/dir/in_dir.txt"] await:&error]); + XCTAssertNil(error); + NSSet *expectedFiles = [NSSet setWithArray:@[]]; + NSArray *actualFiles = [[container contentsOfDirectory:@"bar/dir"] await:&error]; + XCTAssertNotNil(actualFiles); + XCTAssertNil(error); + XCTAssertEqualObjects(expectedFiles, [NSSet setWithArray:actualFiles]); +} + +- (void)testMappedPathDeleteDirectory +{ + id container = [self setUpMappedPathContainer]; + NSError *error = nil; + XCTAssertNotNil([[container remove:@"bar/dir"] await:&error]); + XCTAssertNil(error); + NSArray *actualFiles = [[container contentsOfDirectory:@"bar/dir"] await:nil]; + XCTAssertNil(actualFiles); + // Deleting a root fails + XCTAssertNil([[container remove:@"."] await:nil]); +} + @end diff --git a/FBControlCoreTests/Tests/Unit/FBFutureContextManagerTests.m b/FBControlCoreTests/Tests/Unit/FBFutureContextManagerTests.m index 7e379f8bd..c2cc1b83a 100644 --- a/FBControlCoreTests/Tests/Unit/FBFutureContextManagerTests.m +++ b/FBControlCoreTests/Tests/Unit/FBFutureContextManagerTests.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCoreTests/Tests/Unit/FBFutureTests.m b/FBControlCoreTests/Tests/Unit/FBFutureTests.m index 50699dddd..43addc55b 100644 --- a/FBControlCoreTests/Tests/Unit/FBFutureTests.m +++ b/FBControlCoreTests/Tests/Unit/FBFutureTests.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -496,7 +496,7 @@ - (void)testRaceFailFutures [late2Cancelled fulfill]; return FBFuture.empty; }]; - + NSError *error = [NSError errorWithDomain:@"Future with error" code:2 userInfo:nil]; FBFuture *raceFuture = [[FBFuture race:@[ @@ -969,7 +969,7 @@ - (void)testContextualTeardownOrdering }] onQueue:self.queue handleError:^(NSError *error) { // should not be called and should not affect teardowns - XCTAssertTrue(NO); + XCTFail(); return [FBFuture futureWithError:error]; }] onQueue:self.queue pop:^(id value) { diff --git a/FBControlCoreTests/Tests/Unit/FBXcodeDirectoryTests.m b/FBControlCoreTests/Tests/Unit/FBXcodeDirectoryTests.m index a0b77956c..cfa6512ff 100644 --- a/FBControlCoreTests/Tests/Unit/FBXcodeDirectoryTests.m +++ b/FBControlCoreTests/Tests/Unit/FBXcodeDirectoryTests.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCoreTests/Tests/Unit/FBiOSTargetCommandForwarderTests.m b/FBControlCoreTests/Tests/Unit/FBiOSTargetCommandForwarderTests.m index 8359916b9..bb61c600b 100644 --- a/FBControlCoreTests/Tests/Unit/FBiOSTargetCommandForwarderTests.m +++ b/FBControlCoreTests/Tests/Unit/FBiOSTargetCommandForwarderTests.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCoreTests/Tests/Unit/FBiOSTargetConfigurationTests.m b/FBControlCoreTests/Tests/Unit/FBiOSTargetConfigurationTests.m index 16df744d6..3b03543c3 100644 --- a/FBControlCoreTests/Tests/Unit/FBiOSTargetConfigurationTests.m +++ b/FBControlCoreTests/Tests/Unit/FBiOSTargetConfigurationTests.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBControlCoreTests/Tests/Unit/FBiOSTargetTests.m b/FBControlCoreTests/Tests/Unit/FBiOSTargetTests.m index 77d1de1dd..7dbebe44d 100644 --- a/FBControlCoreTests/Tests/Unit/FBiOSTargetTests.m +++ b/FBControlCoreTests/Tests/Unit/FBiOSTargetTests.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBDeviceControl/Commands/FBDeviceActivationCommands.h b/FBDeviceControl/Commands/FBDeviceActivationCommands.h index 716adc31e..33bee4a9e 100644 --- a/FBDeviceControl/Commands/FBDeviceActivationCommands.h +++ b/FBDeviceControl/Commands/FBDeviceActivationCommands.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBDeviceControl/Commands/FBDeviceActivationCommands.m b/FBDeviceControl/Commands/FBDeviceActivationCommands.m index a153ad0e1..58797618f 100644 --- a/FBDeviceControl/Commands/FBDeviceActivationCommands.m +++ b/FBDeviceControl/Commands/FBDeviceActivationCommands.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBDeviceControl/Commands/FBDeviceApplicationCommands.h b/FBDeviceControl/Commands/FBDeviceApplicationCommands.h index 2a05ba995..d3f022cc8 100644 --- a/FBDeviceControl/Commands/FBDeviceApplicationCommands.h +++ b/FBDeviceControl/Commands/FBDeviceApplicationCommands.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBDeviceControl/Commands/FBDeviceApplicationCommands.m b/FBDeviceControl/Commands/FBDeviceApplicationCommands.m index 0c253ecfd..49d4c028c 100644 --- a/FBDeviceControl/Commands/FBDeviceApplicationCommands.m +++ b/FBDeviceControl/Commands/FBDeviceApplicationCommands.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -15,15 +15,51 @@ #import "FBDeviceControlError.h" #import "FBDeviceDebuggerCommands.h" #import "FBInstrumentsClient.h" +#import -static void UninstallCallback(NSDictionary *callbackDictionary, id device) +@interface FBDeviceWorkflowStatistics : NSObject + +@property (nonatomic, copy, readonly) NSString *workflowType; +@property (nonatomic, strong, readonly) id logger; +@property (nonatomic, copy, nullable, readwrite) NSDictionary *lastEvent; + +@end + +@implementation FBDeviceWorkflowStatistics + +- (instancetype)initWithWorkflowType:(NSString *)workflowType logger:(id)logger +{ + self = [super init]; + if (!self) { + return nil; + } + + _workflowType = workflowType; + _logger = logger; + + return self; +} + +- (void)pushProgress:(NSDictionary *)event +{ + [self.logger logFormat:@"%@ Progress: %@", self.workflowType, [FBCollectionInformation oneLineDescriptionFromDictionary:event]]; + self.lastEvent = event; +} + +- (NSString *)summaryOfRecentEvents { - [device.logger logFormat:@"Uninstall Progress: %@", [FBCollectionInformation oneLineDescriptionFromDictionary:callbackDictionary]]; + NSDictionary *lastEvent = self.lastEvent; + if (!lastEvent) { + return [NSString stringWithFormat:@"No events from %@", self.lastEvent]; + } + return [NSString stringWithFormat:@"Last event %@", [FBCollectionInformation oneLineDescriptionFromDictionary:lastEvent]]; } -static void InstallCallback(NSDictionary *callbackDictionary, id device) +@end + +static void WorkflowCallback(NSDictionary *callbackDictionary, FBDeviceWorkflowStatistics *statistics) { - [device.logger logFormat:@"Install Progress: %@", [FBCollectionInformation oneLineDescriptionFromDictionary:callbackDictionary]]; + [statistics pushProgress:callbackDictionary]; } @interface FBDeviceApplicationCommands () @@ -114,21 +150,44 @@ - (instancetype)initWithDevice:(FBDevice *)device deltaUpdateDirectory:(NSURL *) return [FBFuture futureWithError:error]; } - // 'PackageType=Developer' signifies that the passed payload is a .app - // 'AMDeviceSecureInstallApplicationBundle' performs: - // 1) The transfer of the application bundle to the device. - // 2) The installation of the application after the transfer. - // 3) The performing of the relevant delta updates in the directory pointed to by 'ShadowParentKey' - // 'ShadowParentKey' must be provided in 'AMDeviceSecureInstallApplicationBundle' if 'Developer' is the 'PackageType + // Construct the options for the underlying install API. This mirrors as much of Xcode's call to the same API as is reasonable. + // `@"PreferWifi": @1` may also be passed by Xcode. However, this being preferable is highly dependent on a fast WiFi network and both host/device on the same network. Since this is harder to pick a sane default for this option, this is omitted from the options. NSURL *appURL = [NSURL fileURLWithPath:path isDirectory:YES]; NSDictionary *options = @{ - @"PackageType" : @"Developer", - @"ShadowParentKey": self.deltaUpdateDirectory, + @"CFBundleIdentifier": bundle.identifier, // Lets the installer know what the Bundle ID is of the passed in artifact. + @"CloseOnInvalidate": @1, // Standard arguments of lockdown services to ensure that the socket is closed on teardown. + @"InvalidateOnDetach": @1, // Similar to the above. + @"IsUserInitiated": @1, // Improves installation performance. This has a strong effect on time taken in "VerifyingApplication" stage of installation, which is CPU/IO bound on the attached device. + @"PackageType": @"Developer", // Signifies that the passed payload is a .app + @"ShadowParentKey": self.deltaUpdateDirectory, // Must be provided if 'Developer' is the 'PackageType'. Specifies where incremental install data and apps are persisted for faster future installs of the same bundle. }; - + // Perform the install and lookup the app after. - return [[self - secureInstallApplicationBundle:appURL options:options] + return [[[self.device + connectToDeviceWithPurpose:@"install"] + onQueue:self.device.workQueue pop:^ FBFuture * (id device) { + [self.device.logger logFormat:@"Installing Application %@", appURL]; + // 'AMDeviceSecureInstallApplicationBundle' performs: + // 1) The transfer of the application bundle to the device. + // 2) The installation of the application after the transfer. + // 3) The performing of the relevant delta updates in the directory pointed to by 'ShadowParentKey' + FBDeviceWorkflowStatistics *statistics = [[FBDeviceWorkflowStatistics alloc] initWithWorkflowType:@"Install" logger:device.logger]; + int status = device.calls.SecureInstallApplicationBundle( + device.amDeviceRef, + (__bridge CFURLRef _Nonnull)(appURL), + (__bridge CFDictionaryRef _Nonnull)(options), + (AMDeviceProgressCallback) WorkflowCallback, + (__bridge void *) (statistics) + ); + if (status != 0) { + NSString *errorMessage = CFBridgingRelease(device.calls.CopyErrorText(status)); + return [[FBDeviceControlError + describeFormat:@"Failed to install application %@ 0x%x (%@). %@", appURL.lastPathComponent, status, errorMessage, statistics.summaryOfRecentEvents] + failFuture]; + } + [self.device.logger logFormat:@"Installed Application %@", appURL]; + return FBFuture.empty; + }] onQueue:self.device.asyncQueue fmap:^(id _) { return [self installedApplicationWithBundleID:bundle.identifier]; }]; @@ -162,19 +221,20 @@ - (instancetype)initWithDevice:(FBDevice *)device deltaUpdateDirectory:(NSURL *) return [[self.device connectToDeviceWithPurpose:@"uninstall_%@", bundleID] onQueue:self.device.workQueue pop:^ FBFuture * (id device) { + FBDeviceWorkflowStatistics *statistics = [[FBDeviceWorkflowStatistics alloc] initWithWorkflowType:@"Install" logger:device.logger]; [self.device.logger logFormat:@"Uninstalling Application %@", bundleID]; int status = device.calls.SecureUninstallApplication( 0, device.amDeviceRef, (__bridge CFStringRef _Nonnull)(bundleID), 0, - (AMDeviceProgressCallback) UninstallCallback, - (__bridge void *) (device) + (AMDeviceProgressCallback) WorkflowCallback, + (__bridge void *) (statistics) ); if (status != 0) { NSString *internalMessage = CFBridgingRelease(device.calls.CopyErrorText(status)); return [[FBDeviceControlError - describeFormat:@"Failed to uninstall application '%@' with error 0x%x (%@)", bundleID, status, internalMessage] + describeFormat:@"Failed to uninstall application '%@' with error 0x%x (%@). %@", bundleID, status, internalMessage, statistics.summaryOfRecentEvents] failFuture]; } [self.device.logger logFormat:@"Uninstalled Application %@", bundleID]; @@ -300,18 +360,30 @@ - (instancetype)initWithDevice:(FBDevice *)device deltaUpdateDirectory:(NSURL *) - (FBFuture> *)launchApplicationIgnoreCurrentState:(FBApplicationLaunchConfiguration *)configuration { - return [[[self - remoteInstrumentsClient] - onQueue:self.device.asyncQueue pop:^(FBInstrumentsClient *client) { - return [client launchApplication:configuration]; - }] - onQueue:self.device.asyncQueue map:^ id (NSNumber *pid) { - return [[FBDeviceLaunchedApplication alloc] - initWithProcessIdentifier:pid.intValue - configuration:configuration - commands:self - queue:self.device.workQueue]; - }]; + if (self.device.osVersion.version.majorVersion >= 17) { + FBAppleDevicectlCommandExecutor *devicectl = [[FBAppleDevicectlCommandExecutor alloc] initWithDevice:self.device]; + return [[devicectl launchApplicationWithConfiguration:configuration] + onQueue:self.device.asyncQueue map:^ id (NSNumber* pid) { + return [[FBDeviceLaunchedApplication alloc] + initWithProcessIdentifier:pid.intValue + configuration:configuration + commands:self + queue:self.device.workQueue]; + }]; + } else { + return [[[self + remoteInstrumentsClient] + onQueue:self.device.asyncQueue pop:^(FBInstrumentsClient *client) { + return [client launchApplication:configuration]; + }] + onQueue:self.device.asyncQueue map:^ id (NSNumber *pid) { + return [[FBDeviceLaunchedApplication alloc] + initWithProcessIdentifier:pid.intValue + configuration:configuration + commands:self + queue:self.device.workQueue]; + }]; + } } - (FBFuture *)killApplicationWithProcessIdentifier:(pid_t)processIdentifier @@ -328,19 +400,23 @@ - (instancetype)initWithDevice:(FBDevice *)device deltaUpdateDirectory:(NSURL *) return [[self.device connectToDeviceWithPurpose:@"install"] onQueue:self.device.workQueue pop:^ FBFuture * (id device) { + FBDeviceWorkflowStatistics *statistics = [[FBDeviceWorkflowStatistics alloc] initWithWorkflowType:@"Install" logger:device.logger]; [self.device.logger logFormat:@"Installing Application %@", hostAppURL]; int status = device.calls.SecureInstallApplicationBundle( device.amDeviceRef, (__bridge CFURLRef _Nonnull)(hostAppURL), (__bridge CFDictionaryRef _Nonnull)(options), - (AMDeviceProgressCallback) InstallCallback, - (__bridge void *) (device) + (AMDeviceProgressCallback) WorkflowCallback, + (__bridge void *) (statistics) ); if (status != 0) { NSString *errorMessage = CFBridgingRelease(device.calls.CopyErrorText(status)); - return [[FBDeviceControlError - describeFormat:@"Failed to install application %@ 0x%x (%@)", [hostAppURL lastPathComponent], status, errorMessage] - failFuture]; + return [[FBDeviceControlError + describeFormat:@"Failed to install application %@ 0x%x (%@). %@", [hostAppURL lastPathComponent], status, errorMessage, statistics.summaryOfRecentEvents] + failFuture]; + //return [[FBDeviceControlError + // describeFormat:@"Failed to install application %@ 0x%x (%@)", [hostAppURL lastPathComponent], status, errorMessage] + // failFuture]; } [self.device.logger logFormat:@"Installed Application %@", hostAppURL]; return FBFuture.empty; @@ -352,19 +428,23 @@ - (instancetype)initWithDevice:(FBDevice *)device deltaUpdateDirectory:(NSURL *) return [[self.device connectToDeviceWithPurpose:@"install"] onQueue:self.device.workQueue pop:^ FBFuture * (id device) { + FBDeviceWorkflowStatistics *statistics = [[FBDeviceWorkflowStatistics alloc] initWithWorkflowType:@"Install" logger:device.logger]; [self.device.logger logFormat:@"Installing Application %@", appURL]; int status = device.calls.SecureInstallApplicationBundle( device.amDeviceRef, (__bridge CFURLRef _Nonnull)(appURL), (__bridge CFDictionaryRef _Nonnull)(options), - (AMDeviceProgressCallback) InstallCallback, - (__bridge void *) (device) + (AMDeviceProgressCallback) WorkflowCallback, + (__bridge void *) (statistics) ); if (status != 0) { NSString *errorMessage = CFBridgingRelease(device.calls.CopyErrorText(status)); - return [[FBDeviceControlError - describeFormat:@"Failed to install application %@ 0x%x (%@)", [appURL lastPathComponent], status, errorMessage] - failFuture]; + return [[FBDeviceControlError + describeFormat:@"Failed to install application %@ 0x%x (%@). %@", [appURL lastPathComponent], status, errorMessage, statistics.summaryOfRecentEvents] + failFuture]; + //return [[FBDeviceControlError + // describeFormat:@"Failed to install application %@ 0x%x (%@)", [appURL lastPathComponent], status, errorMessage] + // failFuture]; } [self.device.logger logFormat:@"Installed Application %@", appURL]; return FBFuture.empty; @@ -425,13 +505,13 @@ - (instancetype)initWithDevice:(FBDevice *)device deltaUpdateDirectory:(NSURL *) NSData *data = [connection receive:1 error:&error]; if (!data) { return [[FBDeviceControlError - describeFormat:@"Failed to recieve 1 byte after PidList %@", error] + describeFormat:@"Failed to receive 1 byte after PidList %@", error] failFuture]; } NSDictionary *response = [connection receiveMessageWithError:&error]; if (!response) { return [[FBDeviceControlError - describeFormat:@"Failed to recieve PidList response %@", error] + describeFormat:@"Failed to receive PidList response %@", error] failFuture]; } NSString *status = response[@"Status"]; @@ -460,15 +540,13 @@ + (FBInstalledApplication *)installedApplicationFromDictionary:(NSDictionary + +#import + +#import + +NS_ASSUME_NONNULL_BEGIN + +@class FBDevice; + +/** + The Protocol for Debug Symbol related commands. + */ +@protocol FBDeviceDebugSymbolsCommands + +/** + Obtains a listing of symbol files on a device. + + @return A future that resolves with the listing of symbol files.. + */ +- (FBFuture *> *)listSymbols; + +/** + Writes a file out to a destination + + @param fileName the file to pull + @param destinationPath the destination to write to. + @return a Future that resolves with the extract path. + */ +- (FBFuture *)pullSymbolFile:(NSString *)fileName toDestinationPath:(NSString *)destinationPath; + +/** + Pulls and extracts symbols to the provided path. + + @param destinationDirectory the destination to write to. + @return a Future that resolves with the extract path. + */ +- (FBFuture *)pullAndExtractSymbolsToDestinationDirectory:(NSString *)destinationDirectory; + +@end + +/** + An Implementation of FBDeviceDebugSymbolsCommands. + */ +@interface FBDeviceDebugSymbolsCommands : NSObject + +@end + +NS_ASSUME_NONNULL_END diff --git a/FBDeviceControl/Commands/FBDeviceDebugSymbolsCommands.m b/FBDeviceControl/Commands/FBDeviceDebugSymbolsCommands.m new file mode 100644 index 000000000..2b873ae95 --- /dev/null +++ b/FBDeviceControl/Commands/FBDeviceDebugSymbolsCommands.m @@ -0,0 +1,376 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import "FBDeviceDebugSymbolsCommands.h" + +#import + +#import "FBDevice.h" +#import "FBAMDServiceConnection.h" +#import "FBDeviceControlError.h" + +// This signature for this function is shown in the OSS release of dyld (ex: https://opensource.apple.com/source/dyld/dyld-433.5/launch-cache/dsc_extractor.cpp.auto.html) +typedef int (*SharedCacheExtractor)(const char *sharedCachePath, const char *extractionRootDirectory, void (^progressCallback)(int current, int total)); + +@interface FBDeviceDebugSymbolsCommands () + +@property (nonatomic, weak, readonly) FBDevice *device; +@property (nonatomic, copy, nullable, readwrite) NSArray *cachedFileListing; + +@end + +@implementation FBDeviceDebugSymbolsCommands + +#pragma mark Initializers + ++ (instancetype)commandsWithTarget:(FBDevice *)target +{ + return [[self alloc] initWithDevice:target]; +} + +- (instancetype)initWithDevice:(FBDevice *)device +{ + self = [super init]; + if (!self) { + return nil; + } + + _device = device; + + return self; +} + +#pragma mark FBDeviceActivationCommands Implementation + +static const uint32_t ListFilesPlistCommand = 0x30303030; +static const uint32_t ListFilesPlistAck = ListFilesPlistCommand; +static const uint32_t GetFileCommand = 0x01000000; +static const uint32_t GetFileAck = GetFileCommand; + +- (FBFuture *> *)listSymbols +{ + return [self fetchRemoteSymbolListing]; +} + +- (FBFuture *)pullSymbolFile:(NSString *)fileName toDestinationPath:(NSString *)destinationPath +{ + return [[self + indexOfSymbolFile:fileName] + onQueue:self.device.asyncQueue fmap:^(NSNumber *indexNumber) { + uint32_t index = indexNumber.unsignedIntValue; + return [self writeSymbolFileWithIndex:index toFileAtPath:destinationPath]; + }]; +} + +- (FBFuture *)pullAndExtractSymbolsToDestinationDirectory:(NSString *)destinationDirectory +{ + NSError *error = nil; + if (![NSFileManager.defaultManager createDirectoryAtPath:destinationDirectory withIntermediateDirectories:YES attributes:nil error:&error]) { + return [[FBDeviceControlError + describeFormat:@"Failed to create destination directory for symbol extraction: %@", error] + failFuture]; + } + id logger = self.device.logger; + return [[[self + indicesAndRemotePathsOfSharedCache] + onQueue:self.device.asyncQueue fmap:^(NSDictionary *indicesToRemotePaths) { + NSMutableDictionary *indicesToLocalPaths = NSMutableDictionary.dictionary; + for (NSNumber *fileIndex in indicesToRemotePaths.allKeys) { + NSString *localFileName = indicesToRemotePaths[fileIndex].lastPathComponent; + indicesToLocalPaths[fileIndex] = [destinationDirectory stringByAppendingPathComponent:localFileName]; + } + [logger logFormat:@"Extracting remote symbols %@", [FBCollectionInformation oneLineDescriptionFromArray:indicesToRemotePaths.allValues]]; + return [self extractSymbolFilesWithIndicesMap:indicesToLocalPaths extractedPaths:@[]]; + }] + onQueue:self.device.asyncQueue fmap:^(NSArray *extractedSymbolFiles) { + NSError *innerError = nil; + NSString *sharedCachePath = [FBDeviceDebugSymbolsCommands extractSharedCachePathFromPaths:extractedSymbolFiles error:&innerError]; + if (!sharedCachePath) { + return [FBFuture futureWithError:innerError]; + } + if (![FBDeviceDebugSymbolsCommands extractSharedCacheFile:sharedCachePath toDestinationDirectory:destinationDirectory logger:self.device.logger error:&innerError]) { + return [FBFuture futureWithError:innerError]; + } + for (NSString *extractedSymbolFile in extractedSymbolFiles) { + [NSFileManager.defaultManager removeItemAtPath:extractedSymbolFile error:nil]; + } + return [FBFuture futureWithResult:destinationDirectory]; + }]; +} + +#pragma mark Private + +- (FBFuture *> *)extractSymbolFilesWithIndicesMap:(NSDictionary *)indicesToName extractedPaths:(NSArray *)extractedPaths +{ + if (indicesToName.count == 0) { + return [FBFuture futureWithResult:extractedPaths]; + } + NSNumber *nextIndexNumber = [indicesToName.allKeys firstObject]; + NSString *nextPath = indicesToName[nextIndexNumber]; + NSMutableDictionary *nextIndicesToName = [indicesToName mutableCopy]; + [nextIndicesToName removeObjectForKey:nextIndexNumber]; + uint32_t nextIndex = nextIndexNumber.unsignedIntValue; + return [[self + writeSymbolFileWithIndex:nextIndex toFileAtPath:nextPath] + onQueue:self.device.asyncQueue fmap:^(NSString *extractedPath) { + NSMutableArray *nextExtractedPaths = [extractedPaths mutableCopy]; + [nextExtractedPaths addObject:extractedPath]; + return [self extractSymbolFilesWithIndicesMap:nextIndicesToName extractedPaths:nextExtractedPaths]; + }]; +} + +- (FBFuture *> *)indicesAndRemotePathsOfSharedCache +{ + return [[self + symbolServiceConnection] + onQueue:self.device.asyncQueue pop:^(FBAMDServiceConnection *connection) { + NSError *error = nil; + NSArray *files = [FBDeviceDebugSymbolsCommands obtainFileListingFromService:connection error:&error]; + if (!files) { + return [FBFuture futureWithError:error]; + } + NSArray *matchingFiles = [FBDeviceDebugSymbolsCommands matchingPathsOfSharedCache:files]; + NSDictionary *indicesToFile = [FBDeviceDebugSymbolsCommands matchFiles:matchingFiles againstFileIndices:files error:&error]; + if (!indicesToFile) { + return [FBFuture futureWithError:error]; + } + return [FBFuture futureWithResult:indicesToFile]; + }]; +} + +- (FBFuture *)indexOfSymbolFile:(NSString *)fileName +{ + return [[self + symbolServiceConnection] + onQueue:self.device.asyncQueue pop:^(FBAMDServiceConnection *connection) { + NSError *error = nil; + NSArray *files = [FBDeviceDebugSymbolsCommands obtainFileListingFromService:connection error:&error]; + if (!files) { + return [FBFuture futureWithError:error]; + } + NSUInteger index = [files indexOfObject:fileName]; + if (index == NSNotFound) { + return [[FBDeviceControlError + describeFormat:@"Could not find %@ within %@", fileName, [FBCollectionInformation oneLineDescriptionFromArray:files]] + failFuture]; + } + return [FBFuture futureWithResult:@(index)]; + }]; +} + +- (FBFuture *)writeSymbolFileWithIndex:(uint32_t)index toFileAtPath:(NSString *)destinationPath +{ + return [[self + symbolServiceConnection] + onQueue:self.device.asyncQueue pop:^(FBAMDServiceConnection *connection) { + NSError *error = nil; + if(![FBDeviceDebugSymbolsCommands getFileWithIndex:index toDestinationPath:destinationPath onConnection:connection error:&error]) { + return [FBFuture futureWithError:error]; + } + return [FBFuture futureWithResult:destinationPath]; + }]; +} + +- (FBFutureContext *)symbolServiceConnection +{ + return [[self.device + ensureDeveloperDiskImageIsMounted] + onQueue:self.device.workQueue pushTeardown:^(FBDeveloperDiskImage *image) { + return [self.device startService:@"com.apple.dt.fetchsymbols"]; + }]; +} + +- (FBFuture *> *)fetchRemoteSymbolListing +{ + return [[self + symbolServiceConnection] + onQueue:self.device.asyncQueue pop:^(FBAMDServiceConnection *connection) { + NSError *error = nil; + NSArray *files = [FBDeviceDebugSymbolsCommands obtainFileListingFromService:connection error:&error]; + if (!files) { + return [FBFuture futureWithError:error]; + } + return [FBFuture futureWithResult:files]; + }]; +} + ++ (NSArray *)obtainFileListingFromService:(FBAMDServiceConnection *)connection error:(NSError **)error +{ + if (![FBDeviceDebugSymbolsCommands sendCommand:ListFilesPlistCommand withAck:ListFilesPlistAck commandName:@"ListFilesPlist" onConnection:connection error:error]) { + return nil; + } + NSError *innerError = nil; + NSDictionary *message = [connection receiveMessageWithError:&innerError]; + if (!message) { + return [[FBDeviceControlError + describeFormat:@"Failed to recieve ListFiles plist message %@", innerError] + fail:error]; + } + NSArray *files = message[@"files"]; + if (![FBCollectionInformation isArrayHeterogeneous:files withClass:NSString.class]) { + return [[FBDeviceControlError + describeFormat:@"ListFilesPlist expected Array for 'files' but got %@", [FBCollectionInformation oneLineDescriptionFromArray:files]] + fail:error]; + } + return files; +} + ++ (BOOL)sendCommand:(uint32_t)command withAck:(uint32_t)ack commandName:(NSString *)commandName onConnection:(FBAMDServiceConnection *)connection error:(NSError **)error +{ + NSError *innerError = nil; + BOOL success = [connection sendUnsignedInt32:command error:&innerError]; + if (!success) { + return [[FBDeviceControlError + describeFormat:@"Failed to send '%@' command to symbol service %@", commandName, innerError] + failBool:error]; + } + uint32_t response = 0; + success = [connection receiveUnsignedInt32:&response error:&innerError]; + if (!success) { + return [[FBDeviceControlError + describeFormat:@"Failed to recieve '%@' response from %@", commandName, innerError] + failBool:error]; + } + if (response != ack) { + return [[FBDeviceControlError + describeFormat:@"Incorrect '%@' ack from symbol service; got %u expected %u", commandName, response, ack] + failBool:error]; + } + return YES; +} + ++ (BOOL)getFileWithIndex:(uint32_t)index toDestinationPath:(NSString *)destinationPath onConnection:(FBAMDServiceConnection *)connection error:(NSError **)error +{ + // Send the command that we want to get a file + if (![FBDeviceDebugSymbolsCommands sendCommand:GetFileCommand withAck:GetFileAck commandName:@"GetFiles" onConnection:connection error:error]) { + return NO; + } + // Send the index of the file to pull back + NSError *innerError = nil; + uint32_t indexWire = OSSwapHostToBigInt32(index); + if (![connection sendUnsignedInt32:indexWire error:&innerError]) { + return [[FBDeviceControlError + describeFormat:@"Failed to send GetFile file index %u packet %@", index, innerError] + failBool:error]; + } + uint64_t recieveLengthWire = 0; + if (![connection receiveUnsignedInt64:&recieveLengthWire error:&innerError]) { + return [[FBDeviceControlError + describeFormat:@"Failed to recieve GetFile file length %@", innerError] + failBool:error]; + } + if (recieveLengthWire == 0) { + return [[FBDeviceControlError + describe:@"Failed to get file length, recieveLength not returned or is zero."] + failBool:error]; + } + uint64_t recieveLength = OSSwapBigToHostInt64(recieveLengthWire); + if (![NSFileManager.defaultManager createFileAtPath:destinationPath contents:nil attributes:nil]) { + return [[FBDeviceControlError + describeFormat:@"Failed to create destination file at path %@", destinationPath] + failBool:error]; + } + NSFileHandle *fileHandle = [NSFileHandle fileHandleForWritingAtPath:destinationPath]; + if (!fileHandle) { + return [[FBDeviceControlError + describeFormat:@"Failed to open file for writing at %@", destinationPath] + failBool:error]; + } + if (![connection receive:recieveLength toFile:fileHandle error:error]) { + return NO; + } + return YES; +} + ++ (BOOL)extractSharedCacheFile:(NSString *)sharedCacheFile toDestinationDirectory:(NSString *)destinationDirectory logger:(id)logger error:(NSError **)error +{ + SharedCacheExtractor extractor = [self getSharedCacheExtractorWithError:error]; + if (!extractor) { + return NO; + } + [logger logFormat:@"Extracting shared cache at %@ to directory at %@", sharedCacheFile, destinationDirectory]; + int status = extractor(sharedCacheFile.UTF8String, destinationDirectory.UTF8String, ^(int completed, int total){ + [logger logFormat:@"Completed %d Total %d", completed, total]; + }); + if (status != 0) { + return [[FBDeviceControlError + describeFormat:@"Failed to get extract shared cache directory %@ to %@ with status %d", sharedCacheFile, destinationDirectory, status] + failBool:error]; + } + [logger logFormat:@"Shared cache extracted to %@", destinationDirectory]; + return YES; +} + ++ (SharedCacheExtractor)getSharedCacheExtractorWithError:(NSError **)error +{ + NSString *path = [self pathForSharedCacheExtractor:error]; + if (!path) { + return NULL; + } + void *handle = dlopen(path.UTF8String, RTLD_LAZY); + if (!handle) { + return [[FBControlCoreError + describeFormat:@"Failed to dlopen() %@", path] + failPointer:error]; + } + return FBGetSymbolFromHandle(handle, "dyld_shared_cache_extract_dylibs_progress"); +} + ++ (NSString *)pathForSharedCacheExtractor:(NSError **)error +{ + NSString *path = [FBXcodeConfiguration.developerDirectory stringByAppendingPathComponent:@"Platforms/iPhoneOS.platform/usr/lib/dsc_extractor.bundle"]; + if (![NSFileManager.defaultManager fileExistsAtPath:path]) { + return [[FBDeviceControlError + describeFormat:@"Expected dyld_shared_cache extractor library was not found at path %@", path] + fail:error]; + } + return path; +} + ++ (NSArray *)matchingPathsOfSharedCache:(NSArray *)files +{ + NSMutableArray *matchingFiles = NSMutableArray.array; + for (NSString *file in files) { + if (![file hasPrefix:@"/System/Library"]) { + continue; + } + if (![file containsString:@"shared_cache"]) { + continue; + } + [matchingFiles addObject:file]; + } + return matchingFiles; +} + ++ (NSDictionary *)matchFiles:(NSArray *)files againstFileIndices:(NSArray *)fileIndices error:(NSError **)error +{ + NSMutableDictionary *indexToFileName = NSMutableDictionary.dictionary; + for (NSString *file in files) { + NSUInteger index = [fileIndices indexOfObject:file]; + if (index == NSNotFound) { + return [[FBDeviceControlError + describeFormat:@"Could not find %@ within %@", file, [FBCollectionInformation oneLineDescriptionFromArray:fileIndices]] + fail:error]; + } + indexToFileName[@(index)] = file; + } + return indexToFileName; +} + ++ (NSString *)extractSharedCachePathFromPaths:(NSArray *)paths error:(NSError **)error +{ + for (NSString *path in paths) { + if ([path.pathExtension isEqualToString:@""]) { + return path; + } + } + return [[FBDeviceControlError + describeFormat:@"Could not find the shared cache file within %@", [FBCollectionInformation oneLineDescriptionFromArray:paths]] + fail:error]; +} + +@end diff --git a/FBDeviceControl/Commands/FBDeviceDebuggerCommands.h b/FBDeviceControl/Commands/FBDeviceDebuggerCommands.h index 9908eb6c1..480c957d7 100644 --- a/FBDeviceControl/Commands/FBDeviceDebuggerCommands.h +++ b/FBDeviceControl/Commands/FBDeviceDebuggerCommands.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBDeviceControl/Commands/FBDeviceDebuggerCommands.m b/FBDeviceControl/Commands/FBDeviceDebuggerCommands.m index 43fe45b6e..10a1c3704 100644 --- a/FBDeviceControl/Commands/FBDeviceDebuggerCommands.m +++ b/FBDeviceControl/Commands/FBDeviceDebuggerCommands.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -12,13 +12,20 @@ #import "FBDeviceControlError.h" #import "FBDeviceDebugServer.h" -// Much of the implementation here comes from: -// - DTDeviceKitBase which provides implementations of functions for calling AMDevice calls. -// - IDEiOSSupportCore that is a a client of 'DTDeviceKitBase' -// - DebuggerLLDB.ideplugin is the Xcode plugin responsible for executing the lldb commands via a C++ for launching an Application. This is linked directly by the Xcode App, but can use a remote interface. -// - This can be traced with dtrace, (e.g. `sudo dtrace -n 'objc$target:*:*HandleCommand*:entry { ustack();} ' -p XCODE_PID`) -// - Also effective tracing is to see the commands that lldb has downstream by setting in lldbinit `log enable -v -f /tmp/lldb.log lldb api` -// - DebuggerLLDB uses a combination of calls to the C++ LLDB API and executing command strings here. +/* +Much of the implementation here comes from: + - DTDeviceKitBase which provides implementations of functions for calling AMDevice calls. This is used to establish the 'debugserver' socket, which is then consumed by lldb itself. + - DVTFoundation calls out to the DebuggerLLDB.ideplugin plugin, which provides implementations of lldb debugger clients. + - DebuggerLLDB.ideplugin is the plugin/framework responsible for calling the underlying debugger, there are different objc class implementations depending on what is being debugged. + - These implementations are backed by interfaces to the SBDebugger class (https://lldb.llvm.org/python_api/lldb.SBDebugger.html) + - 'LLDBRPCDebugger' is the class responsible for debugging over an RPC interface, this is used for debugging iOS Devices, since it is running against a remote debugserver on the iOS device, forwarded over a socket on the host. This is backed by the lldb_rpc:SBDebugger class within the lldb codebase. + - DebuggerLLDB uses a combination of calls to the C++ LLDB API and executing command strings here. The bulk of the implementation is in ` -[DBGLLDBLauncher _doRegularDebugWithTarget:usingDebugServer:errTargetString:outError:]`. + - It is possible to trace (using dtrace) the commands that Xcode runs to start a debug session, by observing the 'HandleCommand:' method on the Objc class that wraps SBDebugger. + - To trace the stacks of the command strings that are executed: `sudo dtrace -n 'objc$target:*:*HandleCommand*:entry { ustack(); }' -p XCODE_PID`` + - To trace the command strings that are executed: `sudo dtrace -n 'objc$target:*:*HandleCommand*:entry { printf("HandleCommand = %s\n", copyinstr(arg2)); }' -p XCODE_PID`` + - To trace stacks of all API calls: `sudo dtrace -n 'objc$target:LLDBRPCDebugger:*:entry { ustack(); }' -p XCODE_PID` + - It is also possible to use lldb's internal logging to see the API calls that it is making. This is done by configuring lldb via adding a line in ~/.lldbinit (e.g `log enable -v -f /tmp/lldb.log lldb api`) + */ @interface FBDeviceDebuggerCommands () @@ -51,6 +58,11 @@ - (instancetype)initWithDevice:(FBDevice *)device - (FBFuture> *)launchDebugServerForHostApplication:(FBBundleDescriptor *)application port:(in_port_t)port { + if (self.device.osVersion.version.majorVersion >= 17) { + return [[FBDeviceControlError + describeFormat:@"Debugging is not supported for devices running iOS 17 and higher. Device OS version: %@", self.device.osVersion.versionString] + failFuture]; + } return [[self lldbBootstrapCommandsForApplicationAtPath:application.path port:port] onQueue:self.device.workQueue fmap:^(NSArray *commands) { @@ -95,12 +107,18 @@ - (instancetype)initWithDevice:(FBDevice *)device - (FBFuture *)platformSelectCommand { - return [[FBFuture - resolveValue:^(NSError **error) { - return [FBDeveloperDiskImage pathForDeveloperSymbols:self.device.buildVersion logger:self.device.logger error:error]; - }] - onQueue:self.device.workQueue map:^(NSString *path) { - return [NSString stringWithFormat:@"platform select remote-ios --sysroot '%@'", path]; + FBDevice *device = self.device; + id logger = self.device.logger; + return [FBFuture + onQueue:self.device.asyncQueue resolveValue:^(NSError **error) { + NSError *innerError = nil; + NSString *developerSymbolsPath = [FBDeveloperDiskImage pathForDeveloperSymbols:device.buildVersion logger:logger error:&innerError]; + NSString *platformSelectCommand = @"platform select remote-ios"; + if (!developerSymbolsPath) { + [logger logFormat:@"Failed to get developer symbols for %@, no symbolication of system libraries will occur. To fix ensure developer symbols are downloaded from the device using the 'Devices and Simulators' tool within Xcode: %@", device, innerError]; + return platformSelectCommand; + } + return [platformSelectCommand stringByAppendingFormat:@" --sysroot '%@'", developerSymbolsPath]; }]; } diff --git a/FBDeviceControl/Commands/FBDeviceDeveloperDiskImageCommands.h b/FBDeviceControl/Commands/FBDeviceDeveloperDiskImageCommands.h index 43d9d0dd4..aac3cc16f 100644 --- a/FBDeviceControl/Commands/FBDeviceDeveloperDiskImageCommands.h +++ b/FBDeviceControl/Commands/FBDeviceDeveloperDiskImageCommands.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBDeviceControl/Commands/FBDeviceDeveloperDiskImageCommands.m b/FBDeviceControl/Commands/FBDeviceDeveloperDiskImageCommands.m index 02d67fd65..37dbb15f5 100644 --- a/FBDeviceControl/Commands/FBDeviceDeveloperDiskImageCommands.m +++ b/FBDeviceControl/Commands/FBDeviceDeveloperDiskImageCommands.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -120,7 +120,7 @@ - (instancetype)initWithDevice:(FBDevice *)device FBDeveloperDiskImage *image = imagesBySignature[signature]; if (!image) { [logger logFormat:@"Could not find the location of the image mounted on the device %@", mountEntryToDiskImage]; - continue; + image = [FBDeveloperDiskImage unknownDiskImageWithSignature:signature]; } mountEntryToDiskImage[mountEntry] = image; } @@ -152,14 +152,41 @@ - (instancetype)initWithDevice:(FBDevice *)device }]; } +- (FBFuture *> *)signatureToDiskImageOfMountedDisks +{ + return [[self + mountInfoToDiskImage] + onQueue:self.device.asyncQueue map:^(NSDictionary *, FBDeveloperDiskImage *> *mountInfoToDiskImage) { + NSMutableDictionary *signatureToDiskImage = NSMutableDictionary.dictionary; + for (FBDeveloperDiskImage *image in mountInfoToDiskImage.allValues) { + signatureToDiskImage[image.signature] = image; + } + return signatureToDiskImage; + }]; +} + - (FBFuture *)mountDeveloperDiskImage:(FBDeveloperDiskImage *)diskImage imageType:(NSString *)imageType +{ + id logger = self.device.logger; + return [[self + signatureToDiskImageOfMountedDisks] + onQueue:self.device.asyncQueue fmap:^ FBFuture * (NSDictionary *signatureToDiskImage) { + if (signatureToDiskImage[diskImage.signature]) { + [logger logFormat:@"Disk Image %@ is already mounted, avoiding re-mounting it", diskImage]; + return [FBFuture futureWithResult:diskImage]; + } + return [self performDiskImageMount:diskImage imageType:imageType]; + }]; +} + +- (FBFuture *)performDiskImageMount:(FBDeveloperDiskImage *)diskImage imageType:(NSString *)imageType { return [[self.device connectToDeviceWithPurpose:@"mount_disk_image"] onQueue:self.device.asyncQueue pop:^ FBFuture *> *> * (id device) { NSDictionary *options = @{ - @"ImageSignature": diskImage.signature, - @"ImageType": imageType, + ImageSignatureKey: diskImage.signature, + ImageTypeKey: imageType, }; int status = device.calls.MountImage( device.amDeviceRef, diff --git a/FBDeviceControl/Commands/FBDeviceDiagnosticInformationCommands.h b/FBDeviceControl/Commands/FBDeviceDiagnosticInformationCommands.h index 72c992ac3..8edebc095 100644 --- a/FBDeviceControl/Commands/FBDeviceDiagnosticInformationCommands.h +++ b/FBDeviceControl/Commands/FBDeviceDiagnosticInformationCommands.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBDeviceControl/Commands/FBDeviceDiagnosticInformationCommands.m b/FBDeviceControl/Commands/FBDeviceDiagnosticInformationCommands.m index d5b6015eb..c2fb60a24 100644 --- a/FBDeviceControl/Commands/FBDeviceDiagnosticInformationCommands.m +++ b/FBDeviceControl/Commands/FBDeviceDiagnosticInformationCommands.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBDeviceControl/Commands/FBDeviceEraseCommands.h b/FBDeviceControl/Commands/FBDeviceEraseCommands.h index b150d35b7..f4c1bfc4d 100644 --- a/FBDeviceControl/Commands/FBDeviceEraseCommands.h +++ b/FBDeviceControl/Commands/FBDeviceEraseCommands.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBDeviceControl/Commands/FBDeviceEraseCommands.m b/FBDeviceControl/Commands/FBDeviceEraseCommands.m index 9b44a76df..cbb68346e 100644 --- a/FBDeviceControl/Commands/FBDeviceEraseCommands.m +++ b/FBDeviceControl/Commands/FBDeviceEraseCommands.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBDeviceControl/Commands/FBDeviceFileCommands.h b/FBDeviceControl/Commands/FBDeviceFileCommands.h index e4bff80b6..1fe603132 100644 --- a/FBDeviceControl/Commands/FBDeviceFileCommands.h +++ b/FBDeviceControl/Commands/FBDeviceFileCommands.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBDeviceControl/Commands/FBDeviceFileCommands.m b/FBDeviceControl/Commands/FBDeviceFileCommands.m index 2a2357a64..88ea63e12 100644 --- a/FBDeviceControl/Commands/FBDeviceFileCommands.m +++ b/FBDeviceControl/Commands/FBDeviceFileCommands.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -11,6 +11,7 @@ #import "FBDevice+Private.h" #import "FBDevice.h" #import "FBDeviceControlError.h" +#import "FBDeviceDebugSymbolsCommands.h" #import "FBDeviceProvisioningProfileCommands.h" #import "FBManagedConfigClient.h" #import "FBSpringboardServicesClient.h" @@ -37,7 +38,7 @@ - (instancetype)initWithAFCConnection:(FBAFCConnection *)connection queue:(dispa return self; } -- (FBFuture *)copyFromHost:(NSURL *)sourcePath toContainer:(NSString *)destinationPath +- (FBFuture *)copyFromHost:(NSString *)sourcePath toContainer:(NSString *)destinationPath { return [self handleAFCOperation:^ NSNull * (FBAFCConnection *afc, NSError **error) { BOOL success = [afc copyFromHost:sourcePath toContainerPath:destinationPath error:error]; @@ -48,14 +49,14 @@ - (instancetype)initWithAFCConnection:(FBAFCConnection *)connection queue:(dispa }]; } -- (FBFuture *)copyFromContainer:(NSString *)containerPath toHost:(NSString *)destinationPath +- (FBFuture *)copyFromContainer:(NSString *)sourcePath toHost:(NSString *)destinationPath { NSString *destination = destinationPath; if ([FBDeviceFileContainer isDirectory:destinationPath]){ - destination = [destinationPath stringByAppendingPathComponent:containerPath.lastPathComponent]; + destination = [destinationPath stringByAppendingPathComponent:sourcePath.lastPathComponent]; } return [[self - readFileFromPathInContainer:containerPath] + readFileFromPathInContainer:sourcePath] onQueue:self.queue fmap:^FBFuture *(NSData *fileData) { NSError *error; if (![fileData writeToFile:destination options:0 error:&error]) { @@ -68,7 +69,7 @@ - (instancetype)initWithAFCConnection:(FBAFCConnection *)connection queue:(dispa }]; } -- (FBFuture *> *)tail:(NSString *)containerPath toConsumer:(id)consumer +- (FBFuture *> *)tail:(NSString *)path toConsumer:(id)consumer { return [[FBControlCoreError describeFormat:@"-[%@ %@] is not implemented", NSStringFromClass(self.class), NSStringFromSelector(_cmd)] @@ -171,10 +172,10 @@ - (instancetype)initWithSpringboard:(FBSpringboardServicesClient *)springboard m return [FBFuture futureWithResult:@[FBWallpaperNameHomescreen, FBWallpaperNameLockscreen]]; } -- (FBFuture *)copyFromContainer:(NSString *)containerPath toHost:(NSString *)destinationPath +- (FBFuture *)copyFromContainer:(NSString *)sourcePath toHost:(NSString *)destinationPath { return [[self.springboard - wallpaperImageDataForKind:containerPath.lastPathComponent] + wallpaperImageDataForKind:sourcePath.lastPathComponent] onQueue:self.queue fmap:^ FBFuture * (NSData *data) { NSError *error = nil; if (![data writeToFile:destinationPath options:NSDataWritingAtomic error:&error]) { @@ -184,12 +185,12 @@ - (instancetype)initWithSpringboard:(FBSpringboardServicesClient *)springboard m }]; } -- (FBFuture *)copyFromHost:(NSURL *)sourcePath toContainer:(NSString *)destinationPath +- (FBFuture *)copyFromHost:(NSString *)sourcePath toContainer:(NSString *)destinationPath { return [FBFuture onQueue:self.queue resolve:^ FBFuture * { NSError *error = nil; - NSData *data = [NSData dataWithContentsOfURL:sourcePath options:0 error:&error]; + NSData *data = [NSData dataWithContentsOfFile:sourcePath options:0 error:&error]; if (!data) { return [FBFuture futureWithError:error]; } @@ -197,7 +198,7 @@ - (instancetype)initWithSpringboard:(FBSpringboardServicesClient *)springboard m }]; } -- (FBFuture *> *)tail:(NSString *)containerPath toConsumer:(id)consumer +- (FBFuture *> *)tail:(NSString *)path toConsumer:(id)consumer { return [[FBControlCoreError describeFormat:@"-[%@ %@] is not implemented", NSStringFromClass(self.class), NSStringFromSelector(_cmd)] @@ -256,19 +257,19 @@ - (instancetype)initWithManagedConfig:(FBManagedConfigClient *)managedConfig que return [self.managedConfig getProfileList]; } -- (FBFuture *)copyFromContainer:(NSString *)containerPath toHost:(NSString *)destinationPath +- (FBFuture *)copyFromContainer:(NSString *)sourcePath toHost:(NSString *)destinationPath { return [[FBControlCoreError describeFormat:@"%@ does not make sense for MDM Profile File Containers", NSStringFromSelector(_cmd)] failFuture]; } -- (FBFuture *)copyFromHost:(NSURL *)sourcePath toContainer:(NSString *)destinationPath +- (FBFuture *)copyFromHost:(NSString *)sourcePath toContainer:(NSString *)destinationPath { return [FBFuture onQueue:self.queue resolve:^ FBFuture * { NSError *error = nil; - NSData *data = [NSData dataWithContentsOfURL:sourcePath options:0 error:&error]; + NSData *data = [NSData dataWithContentsOfFile:sourcePath options:0 error:&error]; if (!data) { return [FBFuture futureWithError:error]; } @@ -276,7 +277,7 @@ - (instancetype)initWithManagedConfig:(FBManagedConfigClient *)managedConfig que }]; } -- (FBFuture *> *)tail:(NSString *)containerPath toConsumer:(id)consumer +- (FBFuture *> *)tail:(NSString *)path toConsumer:(id)consumer { return [[FBControlCoreError describeFormat:@"-[%@ %@] is not implemented", NSStringFromClass(self.class), NSStringFromSelector(_cmd)] @@ -328,21 +329,21 @@ - (instancetype)initWithCommands:(id)commands queu return self; } -- (FBFuture *)copyFromHost:(NSURL *)sourcePath toContainer:(NSString *)destinationPath +- (FBFuture *)copyFromHost:(NSString *)sourcePath toContainer:(NSString *)destinationPath { return [[FBControlCoreError describeFormat:@"%@ does not make sense for Disk Images", NSStringFromSelector(_cmd)] failFuture]; } -- (FBFuture *)copyFromContainer:(NSString *)containerPath toHost:(NSString *)destinationPath +- (FBFuture *)copyFromContainer:(NSString *)sourcePath toHost:(NSString *)destinationPath { return [[FBControlCoreError describeFormat:@"%@ does not make sense for Disk Images", NSStringFromSelector(_cmd)] failFuture]; } -- (FBFuture *> *)tail:(NSString *)containerPath toConsumer:(id)consumer +- (FBFuture *> *)tail:(NSString *)path toConsumer:(id)consumer { return [[FBControlCoreError describeFormat:@"-[%@ %@] is not implemented", NSStringFromClass(self.class), NSStringFromSelector(_cmd)] @@ -443,7 +444,7 @@ - (instancetype)initWithCommands:(id)commands queu onQueue:self.queue map:^(NSDictionary *mountedDiskImages) { // Construct the full list of all paths, including the mounted & available images. NSMutableArray *paths = NSMutableArray.array; - [paths addObjectsFromArray:self.mountableDiskImagesByPath.allKeys]; + [paths addObjectsFromArray:[self.mountableDiskImagesByPath keysSortedByValueUsingSelector:@selector(compare:)]]; [paths addObject:MountRootPath]; [paths addObjectsFromArray:mountedDiskImages.allKeys]; return [paths copy]; @@ -478,6 +479,85 @@ + (NSString *)filePathForImage:(FBDeveloperDiskImage *)image @end +@interface FBDeviceFileCommands_Symbols : NSObject + +@property (nonatomic, strong, readonly) id commands; +@property (nonatomic, strong, readonly) dispatch_queue_t queue; + +@end + +@implementation FBDeviceFileCommands_Symbols + +static NSString *const ExtractedSymbolsDirectory = @"Symbols"; + +- (instancetype)initWithCommands:(id)commands queue:(dispatch_queue_t)queue +{ + self = [super init]; + if (!self) { + return nil; + } + + _commands = commands; + _queue = queue; + + return self; +} + +- (FBFuture *)copyFromHost:(NSURL *)sourcePath toContainer:(NSString *)destinationPath +{ + return [[FBControlCoreError + describeFormat:@"%@ does not make sense for Symbols", NSStringFromSelector(_cmd)] + failFuture]; +} + +- (FBFuture *)copyFromContainer:(NSString *)sourcePath toHost:(NSString *)destinationPath +{ + if ([sourcePath isEqualToString:ExtractedSymbolsDirectory]) { + return [self.commands pullAndExtractSymbolsToDestinationDirectory:destinationPath]; + } + return [self.commands pullSymbolFile:sourcePath toDestinationPath:destinationPath]; +} + +- (FBFuture *> *)tail:(NSString *)path toConsumer:(id)consumer +{ + return [[FBControlCoreError + describeFormat:@"%@ does not make sense for Symbols", NSStringFromSelector(_cmd)] + failFuture]; +} + +- (FBFuture *)createDirectory:(NSString *)directoryPath +{ + return [[FBControlCoreError + describeFormat:@"%@ does not make sense for Symbols", NSStringFromSelector(_cmd)] + failFuture]; +} + +- (FBFuture *)moveFrom:(NSString *)sourcePath to:(NSString *)destinationPath +{ + return [[FBControlCoreError + describeFormat:@"%@ does not make sense for Symbols", NSStringFromSelector(_cmd)] + failFuture]; +} + +- (FBFuture *)remove:(NSString *)path +{ + return [[FBControlCoreError + describeFormat:@"%@ does not make sense for Symbols", NSStringFromSelector(_cmd)] + failFuture]; +} + +- (FBFuture *> *)contentsOfDirectory:(NSString *)path +{ + return [[self.commands + listSymbols] + onQueue:self.queue map:^(NSArray *listedSymbols) { + return [listedSymbols arrayByAddingObject:ExtractedSymbolsDirectory]; + }]; +} + +@end + + @interface FBDeviceFileCommands () @property (nonatomic, strong, readonly) FBDevice *device; @@ -601,4 +681,9 @@ - (instancetype)initWithDevice:(FBDevice *)device afcCalls:(AFCCalls)afcCalls return [FBFutureContext futureContextWithResult:[[FBDeviceFileCommands_DiskImages alloc] initWithCommands:self.device queue:self.device.asyncQueue]]; } +- (FBFutureContext> *)fileCommandsForSymbols +{ + return [FBFutureContext futureContextWithResult:[[FBDeviceFileCommands_Symbols alloc] initWithCommands:self.device queue:self.device.asyncQueue]]; +} + @end diff --git a/FBDeviceControl/Commands/FBDeviceLifecycleCommands.h b/FBDeviceControl/Commands/FBDeviceLifecycleCommands.h new file mode 100644 index 000000000..fa75fc022 --- /dev/null +++ b/FBDeviceControl/Commands/FBDeviceLifecycleCommands.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import + +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface FBDeviceLifecycleCommands : NSObject + +@end + +NS_ASSUME_NONNULL_END diff --git a/FBDeviceControl/Commands/FBDeviceLifecycleCommands.m b/FBDeviceControl/Commands/FBDeviceLifecycleCommands.m new file mode 100644 index 000000000..c14e7c528 --- /dev/null +++ b/FBDeviceControl/Commands/FBDeviceLifecycleCommands.m @@ -0,0 +1,52 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import "FBDeviceLifecycleCommands.h" + +#import "FBDevice.h" +#import "FBAMDServiceConnection.h" + +@interface FBDeviceLifecycleCommands () + +@property (nonatomic, weak, readonly) FBDevice *device; + +@end + +@implementation FBDeviceLifecycleCommands + +#pragma mark Initializers + ++ (instancetype)commandsWithTarget:(FBDevice *)target +{ + return [[self alloc] initWithDevice:target]; +} + +- (instancetype)initWithDevice:(FBDevice *)device +{ + self = [super init]; + if (!self) { + return nil; + } + + _device = device; + + return self; +} + +#pragma mark FBLifecycleCommands Implementation + +- (FBFuture *)resolveState:(FBiOSTargetState)state +{ + return FBiOSTargetResolveState(self.device, state); +} + +- (FBFuture *)resolveLeavesState:(FBiOSTargetState)state +{ + return FBiOSTargetResolveLeavesState(self.device, state); +} + +@end diff --git a/FBDeviceControl/Commands/FBDeviceLocationCommands.h b/FBDeviceControl/Commands/FBDeviceLocationCommands.h index 984e77d2d..99734765c 100644 --- a/FBDeviceControl/Commands/FBDeviceLocationCommands.h +++ b/FBDeviceControl/Commands/FBDeviceLocationCommands.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBDeviceControl/Commands/FBDeviceLocationCommands.m b/FBDeviceControl/Commands/FBDeviceLocationCommands.m index 2b66ae9c2..6e8858e72 100644 --- a/FBDeviceControl/Commands/FBDeviceLocationCommands.m +++ b/FBDeviceControl/Commands/FBDeviceLocationCommands.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBDeviceControl/Commands/FBDeviceLogCommands.h b/FBDeviceControl/Commands/FBDeviceLogCommands.h index 7f00cf9a3..b542d09a0 100644 --- a/FBDeviceControl/Commands/FBDeviceLogCommands.h +++ b/FBDeviceControl/Commands/FBDeviceLogCommands.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBDeviceControl/Commands/FBDeviceLogCommands.m b/FBDeviceControl/Commands/FBDeviceLogCommands.m index c5f9d50f6..fa16d3712 100644 --- a/FBDeviceControl/Commands/FBDeviceLogCommands.m +++ b/FBDeviceControl/Commands/FBDeviceLogCommands.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBDeviceControl/Commands/FBDevicePowerCommands.h b/FBDeviceControl/Commands/FBDevicePowerCommands.h index 1cda80665..5e77b12ee 100644 --- a/FBDeviceControl/Commands/FBDevicePowerCommands.h +++ b/FBDeviceControl/Commands/FBDevicePowerCommands.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBDeviceControl/Commands/FBDevicePowerCommands.m b/FBDeviceControl/Commands/FBDevicePowerCommands.m index a8a6ea401..8e6908b35 100644 --- a/FBDeviceControl/Commands/FBDevicePowerCommands.m +++ b/FBDeviceControl/Commands/FBDevicePowerCommands.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBDeviceControl/Commands/FBDeviceProvisioningProfileCommands.h b/FBDeviceControl/Commands/FBDeviceProvisioningProfileCommands.h index 608e4ca19..2d48377ec 100644 --- a/FBDeviceControl/Commands/FBDeviceProvisioningProfileCommands.h +++ b/FBDeviceControl/Commands/FBDeviceProvisioningProfileCommands.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBDeviceControl/Commands/FBDeviceProvisioningProfileCommands.m b/FBDeviceControl/Commands/FBDeviceProvisioningProfileCommands.m index 343546c2a..ed87852ae 100644 --- a/FBDeviceControl/Commands/FBDeviceProvisioningProfileCommands.m +++ b/FBDeviceControl/Commands/FBDeviceProvisioningProfileCommands.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBDeviceControl/Commands/FBDeviceRecoveryCommands.h b/FBDeviceControl/Commands/FBDeviceRecoveryCommands.h index c47518010..8d6f1f9db 100644 --- a/FBDeviceControl/Commands/FBDeviceRecoveryCommands.h +++ b/FBDeviceControl/Commands/FBDeviceRecoveryCommands.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBDeviceControl/Commands/FBDeviceRecoveryCommands.m b/FBDeviceControl/Commands/FBDeviceRecoveryCommands.m index da5fadfbf..2f7fa6531 100644 --- a/FBDeviceControl/Commands/FBDeviceRecoveryCommands.m +++ b/FBDeviceControl/Commands/FBDeviceRecoveryCommands.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBDeviceControl/Commands/FBDeviceScreenshotCommands.h b/FBDeviceControl/Commands/FBDeviceScreenshotCommands.h index f23b4653a..51ab7c61d 100644 --- a/FBDeviceControl/Commands/FBDeviceScreenshotCommands.h +++ b/FBDeviceControl/Commands/FBDeviceScreenshotCommands.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBDeviceControl/Commands/FBDeviceScreenshotCommands.m b/FBDeviceControl/Commands/FBDeviceScreenshotCommands.m index b29267854..97eb0df61 100644 --- a/FBDeviceControl/Commands/FBDeviceScreenshotCommands.m +++ b/FBDeviceControl/Commands/FBDeviceScreenshotCommands.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBDeviceControl/Commands/FBDeviceSocketForwardingCommands.h b/FBDeviceControl/Commands/FBDeviceSocketForwardingCommands.h index 3f13d966a..f1f1e11ef 100644 --- a/FBDeviceControl/Commands/FBDeviceSocketForwardingCommands.h +++ b/FBDeviceControl/Commands/FBDeviceSocketForwardingCommands.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBDeviceControl/Commands/FBDeviceSocketForwardingCommands.m b/FBDeviceControl/Commands/FBDeviceSocketForwardingCommands.m index 67ae2f975..fa7c10ff4 100644 --- a/FBDeviceControl/Commands/FBDeviceSocketForwardingCommands.m +++ b/FBDeviceControl/Commands/FBDeviceSocketForwardingCommands.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBDeviceControl/Commands/FBDeviceVideoRecordingCommands.h b/FBDeviceControl/Commands/FBDeviceVideoRecordingCommands.h index 7d1dd20a7..e0b342a9c 100644 --- a/FBDeviceControl/Commands/FBDeviceVideoRecordingCommands.h +++ b/FBDeviceControl/Commands/FBDeviceVideoRecordingCommands.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBDeviceControl/Commands/FBDeviceVideoRecordingCommands.m b/FBDeviceControl/Commands/FBDeviceVideoRecordingCommands.m index 7ac0869fe..9646b1f05 100644 --- a/FBDeviceControl/Commands/FBDeviceVideoRecordingCommands.m +++ b/FBDeviceControl/Commands/FBDeviceVideoRecordingCommands.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBDeviceControl/Commands/FBDeviceXCTestCommands.h b/FBDeviceControl/Commands/FBDeviceXCTestCommands.h index 7ed005799..9ec6f257f 100644 --- a/FBDeviceControl/Commands/FBDeviceXCTestCommands.h +++ b/FBDeviceControl/Commands/FBDeviceXCTestCommands.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBDeviceControl/Commands/FBDeviceXCTestCommands.m b/FBDeviceControl/Commands/FBDeviceXCTestCommands.m index f30489177..800977701 100644 --- a/FBDeviceControl/Commands/FBDeviceXCTestCommands.m +++ b/FBDeviceControl/Commands/FBDeviceXCTestCommands.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -94,9 +94,16 @@ - (instancetype)initWithDevice:(FBDevice *)device workingDirectory:(NSString *)w return [FBDeviceControlError failFutureWithError:error]; } + // This is to walk around a bug in xcodebuild. The UDID inside xcodebuild does not match + // UDID reported by device properties (the difference is missing hyphen in xcodebuild). + // This results in xcodebuild returning an error, since it cannot find a device with requested + // id (e.g. we query for 00008101-001D296A2EE8001E, while xcodebuild have + // 00008101001D296A2EE8001E). + NSString *udid = (__bridge NSString *)self.device.calls.CopyDeviceIdentifier(self.device.amDeviceRef); + // Create the Task, wrap it and store it. return [FBXcodeBuildOperation - operationWithUDID:self.device.udid + operationWithUDID:udid configuration:configuration xcodeBuildPath:xcodeBuildPath testRunFilePath:filePath diff --git a/FBDeviceControl/FBDeviceControl.h b/FBDeviceControl/FBDeviceControl.h index c158efb39..49dbeeb07 100644 --- a/FBDeviceControl/FBDeviceControl.h +++ b/FBDeviceControl/FBDeviceControl.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -19,6 +19,7 @@ #import #import #import +#import #import #import #import diff --git a/FBDeviceControl/Management/FBAFCConnection.h b/FBDeviceControl/Management/FBAFCConnection.h index 7059a322c..ece93969d 100644 --- a/FBDeviceControl/Management/FBAFCConnection.h +++ b/FBDeviceControl/Management/FBAFCConnection.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -49,12 +49,12 @@ NS_ASSUME_NONNULL_BEGIN Copies an item at the provided url into an application container. The source file can represent a file or a directory. - @param source the source file on the host. + @param hostPath the source file on the host. @param containerPath the file path relative to the application container. @param error an error out for any error that occurs. @return YES if successful, NO otherwise. */ -- (BOOL)copyFromHost:(NSURL *)source toContainerPath:(NSString *)containerPath error:(NSError **)error; +- (BOOL)copyFromHost:(NSString *)hostPath toContainerPath:(NSString *)containerPath error:(NSError **)error; /** Creates a Directory. diff --git a/FBDeviceControl/Management/FBAFCConnection.m b/FBDeviceControl/Management/FBAFCConnection.m index 28e167da6..e2d1c9fa8 100644 --- a/FBDeviceControl/Management/FBAFCConnection.m +++ b/FBDeviceControl/Management/FBAFCConnection.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -49,22 +49,10 @@ - (instancetype)initWithConnection:(AFCConnectionRef)connection calls:(AFCCalls) { return [[FBFuture onQueue:queue resolve:^{ - AFCConnectionRef afcConnection = calls.Create( - 0x0, - serviceConnection.socket, - 0x0, - AFCConnectionCallback, - 0x0 - ); - // We need to apply the Secure Context if it's present on the service connection. - AMSecureIOContext secureIOContext = serviceConnection.secureIOContext; - if (secureIOContext != NULL) { - calls.SetSecureContext(afcConnection, secureIOContext); - } - FBAFCConnection *connection = [[FBAFCConnection alloc] initWithConnection:afcConnection calls:calls logger:logger]; + FBAFCConnection *connection = [serviceConnection asAFCConnectionWithCalls:calls callback:AFCConnectionCallback logger:logger]; if (![connection connectionIsValid]) { return [[FBDeviceControlError - describeFormat:@"Created AFC Connection %@ is not valid", afcConnection] + describeFormat:@"Created AFC Connection %@ is not valid", connection] failFuture]; } return [FBFuture futureWithResult:connection]; @@ -77,21 +65,21 @@ - (instancetype)initWithConnection:(AFCConnectionRef)connection calls:(AFCCalls) #pragma mark Public Methods -- (BOOL)copyFromHost:(NSURL *)url toContainerPath:(NSString *)containerPath error:(NSError **)error +- (BOOL)copyFromHost:(NSString *)hostPath toContainerPath:(NSString *)containerPath error:(NSError **)error { - NSNumber *isDir; - if (![url getResourceValue:&isDir forKey:NSURLIsDirectoryKey error:error]) { + BOOL isDir; + if (![NSFileManager.defaultManager fileExistsAtPath:hostPath isDirectory:&isDir]) { return NO; } - if (isDir.boolValue) { - containerPath = [containerPath stringByAppendingPathComponent:url.lastPathComponent]; + if (isDir) { + containerPath = [containerPath stringByAppendingPathComponent:hostPath.lastPathComponent]; BOOL success = [self createDirectory:containerPath error:error]; if (!success) { return NO; } - return [self copyContentsOfHostDirectory:url toContainerPath:containerPath error:error]; + return [self copyContentsOfHostDirectory:hostPath toContainerPath:containerPath error:error]; } else { - return [self copyFileFromHost:url toContainerPath:[containerPath stringByAppendingPathComponent:url.lastPathComponent] error:error]; + return [self copyFileFromHost:hostPath toContainerPath:[containerPath stringByAppendingPathComponent:hostPath.lastPathComponent] error:error]; } } @@ -224,13 +212,13 @@ - (BOOL)closeWithError:(NSError **)error #pragma mark Private -- (BOOL)copyFileFromHost:(NSURL *)path toContainerPath:(NSString *)containerPath error:(NSError **)error +- (BOOL)copyFileFromHost:(NSString *)hostPath toContainerPath:(NSString *)containerPath error:(NSError **)error { - [self.logger logFormat:@"Copying %@ to %@", path, containerPath]; - NSData *data = [NSData dataWithContentsOfURL:path]; + [self.logger logFormat:@"Copying %@ to %@", hostPath, containerPath]; + NSData *data = [NSData dataWithContentsOfFile:hostPath]; if (!data) { return [[FBDeviceControlError - describeFormat:@"Could not find file on host: %@", path] + describeFormat:@"Could not find file on host: %@", hostPath] failBool:error]; } @@ -258,28 +246,28 @@ - (BOOL)copyFileFromHost:(NSURL *)path toContainerPath:(NSString *)containerPath describeFormat:@"Error when writing file %@: %@", containerPath, [self errorMessageWithCode:writeResult]] failBool:error]; } - [self.logger logFormat:@"Copied from %@ to %@", path, containerPath]; + [self.logger logFormat:@"Copied from %@ to %@", hostPath, containerPath]; return YES; } -- (BOOL)copyContentsOfHostDirectory:(NSURL *)path toContainerPath:(NSString *)containerPath error:(NSError **)error +- (BOOL)copyContentsOfHostDirectory:(NSString *)hostDirectory toContainerPath:(NSString *)containerPath error:(NSError **)error { - [self.logger logFormat:@"Copying from %@ to %@", path, containerPath]; + [self.logger logFormat:@"Copying from %@ to %@", hostDirectory, containerPath]; NSFileManager *fileManager = NSFileManager.defaultManager; NSDirectoryEnumerator *urls = [fileManager - enumeratorAtURL:path + enumeratorAtURL:[NSURL fileURLWithPath:hostDirectory] includingPropertiesForKeys:@[NSURLIsDirectoryKey] options:NSDirectoryEnumerationSkipsSubdirectoryDescendants errorHandler:NULL]; for (NSURL *url in urls) { - BOOL success = [self copyFromHost:url toContainerPath:containerPath error:error]; + BOOL success = [self copyFromHost:url.path toContainerPath:containerPath error:error]; if (!success) { - [self.logger logFormat:@"Failed to copy %@ to %@ with error %@", path, containerPath, *error]; + [self.logger logFormat:@"Failed to copy %@ to %@ with error %@", url, containerPath, *error]; return NO; } } - [self.logger logFormat:@"Copied from %@ to %@", path, containerPath]; + [self.logger logFormat:@"Copied from %@ to %@", hostDirectory, containerPath]; return YES; } diff --git a/FBDeviceControl/Management/FBAMDServiceConnection.h b/FBDeviceControl/Management/FBAMDServiceConnection.h index 1b884192b..fbc95dae8 100644 --- a/FBDeviceControl/Management/FBAMDServiceConnection.h +++ b/FBDeviceControl/Management/FBAMDServiceConnection.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -12,78 +12,14 @@ NS_ASSUME_NONNULL_BEGIN +@class FBAFCConnection; @protocol FBControlCoreLogger; -/** - Abstract protocol for defining an interaction - */ -@protocol FBAMDServiceConnectionTransfer - -#pragma mark Read/Write - -/** - Synchronously send bytes on the connection. - - @param data the data to send - @param error an error out for any error that occurs. - @return YES if the bytes were sent, NO otherwise. - */ -- (BOOL)send:(NSData *)data error:(NSError **)error; - -/** - Synchronously send bytes on the connection, prefixed with a length packet. - - @param data the data to send> - @param error an error out for any error that occurs. - @return YES if the bytes were sent, NO otherwise. - */ -- (BOOL)sendWithLengthHeader:(NSData *)data error:(NSError **)error; - -/** - Synchronously receive bytes from the connection. - - @param size the number of bytes to read. - @param error an error out for any error that occurs. - @return the data. - */ -- (NSData *)receive:(size_t)size error:(NSError **)error; - -/** - Synchronously recieve bytes into a buffer. - - @param destination the destination to write into. - @param size the number of bytes to read. - @param error an error out for any error that occurs. - @return YES if all bytes read, NO otherwise. - */ -- (BOOL)receive:(void *)destination ofSize:(size_t)size error:(NSError **)error; - -#pragma mark Streams - -/** - Reads the stream on the given queue, until exhausted. - - @param consumer the consumer to use. - @param queue the queue to consume on. - @return the FBFileReader instance, this can be used to start reading the reciever's connection. -*/ -- (id)readFromConnectionWritingToConsumer:(id)consumer onQueue:(dispatch_queue_t)queue; - -/** - Constructs a data consumer that writes to the underlying connection. - - @param queue the queue to perform writes on. - @return a consumer that writes to the reciever's connection. -*/ -- (id)writeWithConsumerWritingOnQueue:(dispatch_queue_t)queue; - -@end - /** Wraps the AMDServiceConnection. An AMDServiceConnection represents a connection to a "lockdown" service over USB. */ -@interface FBAMDServiceConnection : NSObject +@interface FBAMDServiceConnection : NSObject #pragma mark Initializers @@ -121,7 +57,7 @@ NS_ASSUME_NONNULL_BEGIN // 3) As with the write side, if there's an SSL context the data will be decrypted through this context. /** - Synchronously recieve a plist-based packet used by lockdown. + Synchronously receive a plist-based packet used by lockdown. @param message the message to send. @param error an error out for any error that occurs. @@ -130,7 +66,7 @@ NS_ASSUME_NONNULL_BEGIN - (BOOL)sendMessage:(id)message error:(NSError **)error; /** - Synchronously recieve a plist-based packet used by lockdown. + Synchronously receive a plist-based packet used by lockdown. @param error an error out for any error that occurs. @return the read plist on success, nil on error. @@ -146,6 +82,112 @@ NS_ASSUME_NONNULL_BEGIN */ - (nullable id)sendAndReceiveMessage:(id)message error:(NSError **)error; +#pragma mark Raw Bytes Read/Write +/** + Synchronously send bytes on the connection. + + @param data the data to send + @param error an error out for any error that occurs. + @return YES if the bytes were sent, NO otherwise. + */ +- (BOOL)send:(NSData *)data error:(NSError **)error; + +/** + Synchronously send bytes on the connection, prefixed with a length packet. + + @param data the data to send> + @param error an error out for any error that occurs. + @return YES if the bytes were sent, NO otherwise. + */ +- (BOOL)sendWithLengthHeader:(NSData *)data error:(NSError **)error; + +/** + Sends a uint32_t over the connection. + + @param value the value to pull. + @param error an error out for any error that occurs. + @return YES if successful, NO otherwise. + */ +- (BOOL)sendUnsignedInt32:(uint32_t)value error:(NSError **)error; + +/** + Synchronously receive bytes from the connection. + This call will block until 'size' is met. + If a read fails before the 'size' is met, this call will fail. + + @param size the number of bytes to read. + @param error an error out for any error that occurs. + @return the data. + */ +- (NSData *)receive:(size_t)size error:(NSError **)error; + +/** + Synchronously receive up to 'size' bytes in the connection + This call will return an empty NSData when end of file is reached. + + @param size the number of bytes to read up to. + @param error an error out for any error that occurs. + @return the data. + */ +- (NSData *)receiveUpTo:(size_t)size error:(NSError **)error; + +/** + Synchronously receive bytes from the connection, writing to a file handle. + + @param size the number of bytes to read. + @param fileHandle the file handle to write to. + @param error an error out for any error that occurs. + @return the data. + */ +- (BOOL)receive:(size_t)size toFile:(NSFileHandle *)fileHandle error:(NSError **)error; + +/** + Synchronously receive bytes into a buffer. + + @param destination the destination to write into. + @param size the number of bytes to read. + @param error an error out for any error that occurs. + @return YES if all bytes read, NO otherwise. + */ +- (BOOL)receive:(void *)destination ofSize:(size_t)size error:(NSError **)error; + +/** + Receives a uint32_t a from the connection. + + @param valueOut the value to pull. + @param error an error out for any error that occurs. + @return YES if successful, NO otherwise. + */ +- (BOOL)receiveUnsignedInt32:(uint32_t *)valueOut error:(NSError **)error; + +/** + Receives a uint64_t a from the connection. + + @param valueOut the value to pull. + @param error an error out for any error that occurs. + @return YES if successful, NO otherwise. + */ +- (BOOL)receiveUnsignedInt64:(uint64_t *)valueOut error:(NSError **)error; + +#pragma mark Streams + +/** + Reads the stream on the given queue, until exhausted. + + @param consumer the consumer to use. + @param queue the queue to consume on. + @return the FBFileReader instance, this can be used to start reading the receiver's connection. +*/ +- (id)readFromConnectionWritingToConsumer:(id)consumer onQueue:(dispatch_queue_t)queue; + +/** + Constructs a data consumer that writes to the underlying connection. + + @param queue the queue to perform writes on. + @return a consumer that writes to the receiver's connection. +*/ +- (id)writeWithConsumerWritingOnQueue:(dispatch_queue_t)queue; + #pragma mark Lifecycle /** @@ -157,6 +199,18 @@ NS_ASSUME_NONNULL_BEGIN */ - (BOOL)invalidateWithError:(NSError **)error; +#pragma mark AFC + +/** + Constructs an AFC Connection from the underlying connection + + @param calls calls, the calls to use. + @param callback the callback to use for progress. + @param logger the logger to use for logging. + @return a new FBAFCConnection wrapper instance. + */ +- (FBAFCConnection *)asAFCConnectionWithCalls:(AFCCalls)calls callback:(AFCNotificationCallback)callback logger:(id)logger; + #pragma mark Properties /** @@ -184,16 +238,6 @@ NS_ASSUME_NONNULL_BEGIN */ @property (nonatomic, strong, nullable, readonly) id logger; -/** - The socket for the connection. - */ -@property (nonatomic, assign, readonly) int socket; - -/** - The Secure IO Context. - */ -@property (nonatomic, assign, readonly) AMSecureIOContext secureIOContext; - /** The size of the read buffer. Public so specific services(such as syslog) can override the default. */ diff --git a/FBDeviceControl/Management/FBAMDServiceConnection.m b/FBDeviceControl/Management/FBAMDServiceConnection.m index 2ce30dbf9..fd552081b 100644 --- a/FBDeviceControl/Management/FBAMDServiceConnection.m +++ b/FBDeviceControl/Management/FBAMDServiceConnection.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -7,6 +7,7 @@ #import "FBAMDServiceConnection.h" +#import "FBAFCConnection.h" #import "FBDeviceControlError.h" typedef uint32_t HeaderIntType; @@ -18,7 +19,7 @@ @interface FBAMDServiceConnection () - (ssize_t)send:(const void *)buffer size:(size_t)size; -- (ssize_t)recieve:(void *)buffer size:(size_t)size; +- (ssize_t)receive:(void *)buffer size:(size_t)size; @end @@ -64,7 +65,7 @@ - (instancetype)initWithServiceConnection:(FBAMDServiceConnection *)connection c dispatch_async(self.queue, ^{ void *buffer = alloca(ReadBufferSize); while (self.state == FBFileReaderStateReading && self.finishedReadingMutable.state == FBFutureStateRunning) { - ssize_t readBytes = [connection recieve:buffer size:ReadBufferSize]; + ssize_t readBytes = [connection receive:buffer size:ReadBufferSize]; if (readBytes < 1) { break; } @@ -111,14 +112,6 @@ - (instancetype)initWithServiceConnection:(FBAMDServiceConnection *)connection c @end -@interface FBAMDServiceConnection_TransferRaw : FBAMDServiceConnection - -@end - -@interface FBAMDServiceConnection_TransferServiceConnection : FBAMDServiceConnection - -@end - @implementation FBAMDServiceConnection #pragma mark Initializers @@ -127,11 +120,8 @@ + (instancetype)connectionWithName:(NSString *)name connection:(AMDServiceConnec { // Use Raw transfer when there's no Secure Context, otherwise we must use the service connection wrapping. AMSecureIOContext secureIOContext = calls.ServiceConnectionGetSecureIOContext(connection); - if (secureIOContext == NULL) { - return [[FBAMDServiceConnection_TransferRaw alloc] initWithName:name connection:connection device:device calls:calls logger:logger]; - } else { - return [[FBAMDServiceConnection_TransferServiceConnection alloc] initWithName:name connection:connection device:device calls:calls logger:logger]; - } + [logger logFormat:@"Constructing service connection for %@ %@ Secure", name, secureIOContext ? @"is" : @"is not"]; + return [[FBAMDServiceConnection alloc] initWithName:name connection:connection device:device calls:calls logger:logger]; } - (instancetype)initWithName:(NSString *)name connection:(AMDServiceConnectionRef)connection device:(AMDeviceRef)device calls:(AMDCalls)calls logger:(id)logger; @@ -180,7 +170,7 @@ - (id)receiveMessageWithError:(NSError **)error if (result != 0) { NSString *errorDescription = CFBridgingRelease(self.calls.CopyErrorText(result)); return [[FBDeviceControlError - describeFormat:@"Failed to recieve message (%@): code %d", errorDescription, result] + describeFormat:@"Failed to receive message (%@): code %d", errorDescription, result] fail:error]; } return CFBridgingRelease(message); @@ -219,16 +209,23 @@ - (BOOL)invalidateWithError:(NSError **)error return YES; } -#pragma mark Properties +#pragma mark AFC -- (int)socket +- (FBAFCConnection *)asAFCConnectionWithCalls:(AFCCalls)calls callback:(AFCNotificationCallback)callback logger:(id)logger { - return self.calls.ServiceConnectionGetSocket(self.connection); -} - -- (AMSecureIOContext)secureIOContext -{ - return self.calls.ServiceConnectionGetSecureIOContext(self.connection); + AFCConnectionRef afcConnection = calls.Create( + 0x0, + self.calls.ServiceConnectionGetSocket(self.connection), + 0x0, + callback, + 0x0 + ); + // We need to apply the Secure Context if it's present on the service connection. + AMSecureIOContext secureIOContext = self.calls.ServiceConnectionGetSecureIOContext(self.connection);; + if (secureIOContext != NULL) { + calls.SetSecureContext(afcConnection, secureIOContext); + } + return [[FBAFCConnection alloc] initWithConnection:afcConnection calls:calls logger:self.logger]; } #pragma mark FBAMDServiceConnectionTransfer Implementation @@ -293,49 +290,35 @@ - (BOOL)sendWithLengthHeader:(NSData *)data error:(NSError **)error return YES; } +- (BOOL)sendUnsignedInt32:(uint32_t)value error:(NSError **)error +{ + NSData *data = [[NSData alloc] initWithBytes:&value length:sizeof(uint32_t)]; + return [self send:data error:error]; +} + - (NSData *)receive:(size_t)size error:(NSError **)error { - // Create a buffer that contains the data to return and a temp buffer for reading into. + // Create a buffer that contains the data to return and how to append it from the enumerator NSMutableData *data = NSMutableData.data; - void *buffer = alloca(ReadBufferSize); - - // Start reading in a loop, until there's no more bytes to read. - size_t bytesRemaining = size; - while (bytesRemaining > 0) { - // Don't read more bytes than are remaining. - size_t maxReadBytes = MIN(ReadBufferSize, bytesRemaining); - ssize_t result = [self recieve:buffer size:maxReadBytes]; - // End of file. - if (result == 0) { - break; - } - // A negative return indicates an error - if (result == -1) { - return [[FBDeviceControlError - describeFormat:@"Failure in receive of %zu bytes: %s", maxReadBytes, strerror(errno)] - fail:error]; - } - // Check an over-read to prevent unsigned integer overflow. - size_t readBytes = (size_t) result; - if (readBytes > bytesRemaining) { - return [[FBDeviceControlError - describeFormat:@"Failure in receive: Read %zu bytes but only %zu bytes remaining", readBytes, bytesRemaining] - fail:error]; - } - // Decrement the number of bytes to read and add it to the return buffer. - bytesRemaining -= readBytes; - [data appendBytes:buffer length:readBytes]; - } - - // Check that we've read the right number of bytes. - if (bytesRemaining != 0) { - return [[FBDeviceControlError - describeFormat:@"Failed to receive %zu bytes, %zu remaining to read", size, bytesRemaining] - fail:error]; + void(^enumerator)(NSData *) = ^(NSData *chunk){ + [data appendData:[chunk copy]]; + }; + // Start the byte recieve. + BOOL success = [self enumateReceiveOfLength:size chunkSize:ReadBufferSize enumerator:enumerator error:error]; + if (!success) { + return nil; } return data; } +- (BOOL)receive:(size_t)size toFile:(NSFileHandle *)fileHandle error:(NSError **)error +{ + void(^enumerator)(NSData *) = ^(NSData *chunk){ + [fileHandle writeData:chunk]; + }; + return [self enumateReceiveOfLength:size chunkSize:ReadBufferSize enumerator:enumerator error:error]; +} + - (BOOL)receive:(void *)destination ofSize:(size_t)size error:(NSError **)error { NSData *data = [self receive:size error:error]; @@ -346,6 +329,36 @@ - (BOOL)receive:(void *)destination ofSize:(size_t)size error:(NSError **)error return YES; } +- (NSData *)receiveUpTo:(size_t)size error:(NSError **)error +{ + // Create a buffer that contains the data + void *buffer = alloca(size); + // Read the underlying bytes. + ssize_t result = [self receive:buffer size:size]; + // End of file. + if (result == 0) { + return NSData.data; + } + // A negative return indicates an error + if (result == -1) { + return [[FBDeviceControlError + describeFormat:@"Failure in receive of up to %zu bytes: %s", size, strerror(errno)] + fail:error]; + } + size_t readBytes = (size_t) result; + return [[NSData alloc] initWithBytes:buffer length:readBytes]; +} + +- (BOOL)receiveUnsignedInt32:(uint32_t *)valueOut error:(NSError **)error +{ + return [self receive:valueOut ofSize:sizeof(uint32_t) error:error]; +} + +- (BOOL)receiveUnsignedInt64:(uint64_t *)valueOut error:(NSError **)error +{ + return [self receive:valueOut ofSize:sizeof(uint64_t) error:error]; +} + - (id)readFromConnectionWritingToConsumer:(id)consumer onQueue:(dispatch_queue_t)queue { return [[FBAMDServiceConnection_FileReader alloc] initWithServiceConnection:self consumer:consumer queue:queue]; @@ -362,42 +375,55 @@ - (BOOL)receive:(void *)destination ofSize:(size_t)size error:(NSError **)error - (ssize_t)send:(const void *)buffer size:(size_t)size { - NSAssert(NO, @"%@ is abstract", NSStringFromSelector(_cmd)); - return -1; + return self.calls.ServiceConnectionSend(self.connection, buffer, size); } -- (ssize_t)recieve:(void *)buffer size:(size_t)size +- (ssize_t)receive:(void *)buffer size:(size_t)size { - NSAssert(NO, @"%@ is abstract", NSStringFromSelector(_cmd)); - return -1; + return self.calls.ServiceConnectionReceive(self.connection, buffer, size); } -@end - -@implementation FBAMDServiceConnection_TransferRaw - -- (ssize_t)send:(const void *)buffer size:(size_t)size +- (BOOL)enumateReceiveOfLength:(size_t)size chunkSize:(size_t)chunkSize enumerator:(void(^)(NSData *))enumerator error:(NSError **)error { - return write(self.socket, buffer, size); -} + // Create a buffer that contains the incremental enumerated data. + void *buffer = alloca(chunkSize); -- (ssize_t)recieve:(void *)buffer size:(size_t)size -{ - return read(self.socket, buffer, size); -} - -@end - -@implementation FBAMDServiceConnection_TransferServiceConnection - -- (ssize_t)send:(const void *)buffer size:(size_t)size -{ - return self.calls.ServiceConnectionSend(self.connection, buffer, size); -} + // Start reading in a loop, until there's no more bytes to read. + size_t bytesRemaining = size; + while (bytesRemaining > 0) { + // Don't read more bytes than are remaining. + size_t maxReadBytes = MIN(chunkSize, bytesRemaining); + ssize_t result = [self receive:buffer size:maxReadBytes]; + // End of file. + if (result == 0) { + break; + } + // A negative return indicates an error + if (result == -1) { + return [[FBDeviceControlError + describeFormat:@"Failure in receive of %zu bytes: %s", maxReadBytes, strerror(errno)] + failBool:error]; + } + // Check an over-read to prevent unsigned integer overflow. + size_t readBytes = (size_t) result; + if (readBytes > bytesRemaining) { + return [[FBDeviceControlError + describeFormat:@"Failure in receive: Read %zu bytes but only %zu bytes remaining", readBytes, bytesRemaining] + failBool:error]; + } + // Decrement the number of bytes to read and pass it to the callback + bytesRemaining -= readBytes; + NSData *readData = [[NSData alloc] initWithBytesNoCopy:buffer length:readBytes freeWhenDone:NO]; + enumerator(readData); + } -- (ssize_t)recieve:(void *)buffer size:(size_t)size -{ - return self.calls.ServiceConnectionReceive(self.connection, buffer, size); + // Check that we've read the right number of bytes. + if (bytesRemaining != 0) { + return [[FBDeviceControlError + describeFormat:@"Failed to receive %zu bytes, %zu remaining to read and eof reached.", size, bytesRemaining] + failBool:error]; + } + return YES; } @end diff --git a/FBDeviceControl/Management/FBAMDefines.h b/FBDeviceControl/Management/FBAMDefines.h index 1b56163eb..7fb934f7c 100644 --- a/FBDeviceControl/Management/FBAMDefines.h +++ b/FBDeviceControl/Management/FBAMDefines.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBDeviceControl/Management/FBAMDevice+Private.h b/FBDeviceControl/Management/FBAMDevice+Private.h index a0b693d42..d35a202fe 100644 --- a/FBDeviceControl/Management/FBAMDevice+Private.h +++ b/FBDeviceControl/Management/FBAMDevice+Private.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBDeviceControl/Management/FBAMDevice.h b/FBDeviceControl/Management/FBAMDevice.h index e7617d930..ee2c2c994 100644 --- a/FBDeviceControl/Management/FBAMDevice.h +++ b/FBDeviceControl/Management/FBAMDevice.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBDeviceControl/Management/FBAMDevice.m b/FBDeviceControl/Management/FBAMDevice.m index 8f9f9e7c1..86aa0bb43 100644 --- a/FBDeviceControl/Management/FBAMDevice.m +++ b/FBDeviceControl/Management/FBAMDevice.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -90,9 +90,9 @@ - (NSString *)udid return self.allValues[FBDeviceKeyUniqueDeviceID]; } -- (NSString *)architecture +- (NSArray *)architectures { - return self.allValues[FBDeviceKeyCPUArchitecture]; + return @[self.allValues[FBDeviceKeyCPUArchitecture]]; } - (NSString *)buildVersion diff --git a/FBDeviceControl/Management/FBAMDeviceManager.h b/FBDeviceControl/Management/FBAMDeviceManager.h index a595c603c..5cbdb207f 100644 --- a/FBDeviceControl/Management/FBAMDeviceManager.h +++ b/FBDeviceControl/Management/FBAMDeviceManager.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBDeviceControl/Management/FBAMDeviceManager.m b/FBDeviceControl/Management/FBAMDeviceManager.m index e7804e842..9ece147e6 100644 --- a/FBDeviceControl/Management/FBAMDeviceManager.m +++ b/FBDeviceControl/Management/FBAMDeviceManager.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBDeviceControl/Management/FBAMDeviceServiceManager.h b/FBDeviceControl/Management/FBAMDeviceServiceManager.h index d29414304..3e6a6f25e 100644 --- a/FBDeviceControl/Management/FBAMDeviceServiceManager.h +++ b/FBDeviceControl/Management/FBAMDeviceServiceManager.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBDeviceControl/Management/FBAMDeviceServiceManager.m b/FBDeviceControl/Management/FBAMDeviceServiceManager.m index f9948f1c8..037a31c02 100644 --- a/FBDeviceControl/Management/FBAMDeviceServiceManager.m +++ b/FBDeviceControl/Management/FBAMDeviceServiceManager.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBDeviceControl/Management/FBAMRestorableDevice.h b/FBDeviceControl/Management/FBAMRestorableDevice.h index 1c689db8a..6a02a1b0e 100644 --- a/FBDeviceControl/Management/FBAMRestorableDevice.h +++ b/FBDeviceControl/Management/FBAMRestorableDevice.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBDeviceControl/Management/FBAMRestorableDevice.m b/FBDeviceControl/Management/FBAMRestorableDevice.m index c276b25ca..2b5244d1b 100644 --- a/FBDeviceControl/Management/FBAMRestorableDevice.m +++ b/FBDeviceControl/Management/FBAMRestorableDevice.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -74,9 +74,10 @@ - (FBDeviceType *)deviceType return [FBDeviceType genericWithName:productString]; } -- (FBArchitecture)architecture + +- (NSArray *)architectures { - return UnknownValue; + return @[UnknownValue]; } - (FBiOSTargetType)targetType diff --git a/FBDeviceControl/Management/FBAMRestorableDeviceManager.h b/FBDeviceControl/Management/FBAMRestorableDeviceManager.h index d0dfb35cd..6f38fdbd6 100644 --- a/FBDeviceControl/Management/FBAMRestorableDeviceManager.h +++ b/FBDeviceControl/Management/FBAMRestorableDeviceManager.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBDeviceControl/Management/FBAMRestorableDeviceManager.m b/FBDeviceControl/Management/FBAMRestorableDeviceManager.m index 2eea32401..cf32367d2 100644 --- a/FBDeviceControl/Management/FBAMRestorableDeviceManager.m +++ b/FBDeviceControl/Management/FBAMRestorableDeviceManager.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBDeviceControl/Management/FBAppleDevicectlCommandExecutor.swift b/FBDeviceControl/Management/FBAppleDevicectlCommandExecutor.swift new file mode 100644 index 000000000..2910886ce --- /dev/null +++ b/FBDeviceControl/Management/FBAppleDevicectlCommandExecutor.swift @@ -0,0 +1,96 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import Foundation + +public class FBAppleDevicectlCommandExecutor: NSObject { + + let logger: FBControlCoreLogger? + let device: FBDevice + + @objc public init(device: FBDevice) { + logger = device.logger?.withName("devicectl") + self.device = device + super.init() + } + + @objc public func taskBuilder(arguments: [String]) -> FBProcessBuilder { + let derivedArgs = ["devicectl"] + arguments + return FBProcessBuilder.withLaunchPath("/usr/bin/xcrun", arguments: derivedArgs) + .withStdOutInMemoryAsString() + .withStdErrInMemoryAsString() + .withTaskLifecycleLogging(to: logger) + } +} + +public extension FBAppleDevicectlCommandExecutor { + @objc func launchApplication(configuration: FBApplicationLaunchConfiguration) -> FBFuture { + do { + let tmpPath = try FileManager.default.temporaryFile(extension: "json") + let tmpPathStr: String + if #available(macOS 13.0, *) { + tmpPathStr = tmpPath.path() + } else { + tmpPathStr = tmpPath.path + } + var arguments = [ + "device", + "process", + "launch", + "--device", + device.udid, + "--terminate-existing", + "--json-output", + tmpPathStr, + ] + if !configuration.environment.isEmpty { + if let envstr = String(data: try + JSONSerialization.data(withJSONObject: configuration.environment), + encoding: .utf8) { + arguments += ["--environment-variables", envstr] + } + } + if configuration.waitForDebugger { + arguments.append("--start-stopped") + } + arguments.append(configuration.bundleID) + arguments += configuration.arguments + + let builder = taskBuilder(arguments: arguments) + + guard let future = builder.runUntilCompletion(withAcceptableExitCodes: nil) + .onQueue(device.asyncQueue, fmap: { task in + if task.exitCode.result?.intValue != 0 { + return FBControlCoreError.describe("devicectl failed with exit code \(task.exitCode.result.flatMap(String.init) ?? "")\narguments: \(FBCollectionInformation.oneLineDescription(from: arguments))\n\(task.stdOut ?? "")\n\(task.stdErr ?? "")") + .failFuture() + } + do { + let data = try Data(contentsOf: tmpPath) + let info = try JSONDecoder().decode(DevicectlProcInfo.self, from: data) + return FBFuture(result: NSNumber(value: info.result.process.processIdentifier)) + } catch { + return FBFuture(error: error) + } + }) as? FBFuture else { + assertionFailure("Failed to restore FBFuture generic paramter type after type erasure.") + } + return future + } catch { + return FBFuture(error: error) + } + } + + private struct DevicectlProcInfo: Decodable { + struct Result: Decodable { + struct Process: Decodable { + var processIdentifier: Int + } + var process: Process + } + var result: Result + } +} diff --git a/FBDeviceControl/Management/FBDevice+Private.h b/FBDeviceControl/Management/FBDevice+Private.h index 8c5a72ca7..c3573b08b 100644 --- a/FBDeviceControl/Management/FBDevice+Private.h +++ b/FBDeviceControl/Management/FBDevice+Private.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBDeviceControl/Management/FBDevice.h b/FBDeviceControl/Management/FBDevice.h index ce2b20f19..b245d171a 100644 --- a/FBDeviceControl/Management/FBDevice.h +++ b/FBDeviceControl/Management/FBDevice.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -10,6 +10,7 @@ #import #import #import +#import #import #import @@ -21,7 +22,7 @@ NS_ASSUME_NONNULL_BEGIN /** A class that represents an iOS Device. */ -@interface FBDevice : NSObject +@interface FBDevice : NSObject /** The Device Set to which the Device Belongs. diff --git a/FBDeviceControl/Management/FBDevice.m b/FBDeviceControl/Management/FBDevice.m index f2bfa1e68..8cee8420f 100644 --- a/FBDeviceControl/Management/FBDevice.m +++ b/FBDeviceControl/Management/FBDevice.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -21,6 +21,7 @@ #import "FBDeviceEraseCommands.h" #import "FBDeviceFileCommands.h" #import "FBDeviceFileCommands.h" +#import "FBDeviceLifecycleCommands.h" #import "FBDeviceLocationCommands.h" #import "FBDeviceLogCommands.h" #import "FBDevicePowerCommands.h" @@ -37,7 +38,7 @@ @implementation FBDevice @synthesize activationState = _activationState; @synthesize allValues = _allValues; @synthesize amDevice = _amDevice; -@synthesize architecture = _architecture; +@synthesize architectures = _architectures; @synthesize buildVersion = _buildVersion; @synthesize calls = _calls; @synthesize deviceType = _deviceType; @@ -195,8 +196,8 @@ - (void)cacheValuesFromInfo:(id)targetInfo overwrite: if (!_allValues || overwrite) { _allValues = targetInfo.allValues; } - if (!_architecture || overwrite) { - _architecture = targetInfo.architecture; + if (!_architectures || overwrite) { + _architectures = targetInfo.architectures; } if (!_buildVersion || overwrite) { _buildVersion = targetInfo.buildVersion; @@ -331,10 +332,12 @@ - (void)invalidateHouseArrestAFCConnectionForBundleID:(NSString *)bundleID FBDeviceApplicationCommands.class, FBDeviceCrashLogCommands.class, FBDeviceDebuggerCommands.class, + FBDeviceDebugSymbolsCommands.class, FBDeviceDeveloperDiskImageCommands.class, FBDeviceDiagnosticInformationCommands.class, FBDeviceEraseCommands.class, FBDeviceFileCommands.class, + FBDeviceLifecycleCommands.class, FBDeviceLocationCommands.class, FBDeviceLogCommands.class, FBDevicePowerCommands.class, @@ -343,8 +346,8 @@ - (void)invalidateHouseArrestAFCConnectionForBundleID:(NSString *)bundleID FBDeviceSocketForwardingCommands.class, FBDeviceVideoRecordingCommands.class, FBDeviceXCTestCommands.class, - FBXCTraceRecordCommands.class, FBInstrumentsCommands.class, + FBXCTraceRecordCommands.class, ]; }); return commandClasses; diff --git a/FBDeviceControl/Management/FBDeviceDebugServer.h b/FBDeviceControl/Management/FBDeviceDebugServer.h index 9ea73ef49..c31f7a43c 100644 --- a/FBDeviceControl/Management/FBDeviceDebugServer.h +++ b/FBDeviceControl/Management/FBDeviceDebugServer.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBDeviceControl/Management/FBDeviceDebugServer.m b/FBDeviceControl/Management/FBDeviceDebugServer.m index 269a69495..bda3a307d 100644 --- a/FBDeviceControl/Management/FBDeviceDebugServer.m +++ b/FBDeviceControl/Management/FBDeviceDebugServer.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -13,61 +13,87 @@ @interface FBDeviceDebugServer_TwistedPairFiles : NSObject -@property (nonatomic, assign, readonly) int source; -@property (nonatomic, strong, readonly) FBAMDServiceConnection *sink; -@property (nonatomic, strong, readonly) dispatch_queue_t queue; -@property (nonatomic, strong, readonly) dispatch_queue_t sinkWriteQueue; -@property (nonatomic, strong, readonly) dispatch_queue_t sinkReadQueue; - -@property (nonatomic, strong, nullable, readwrite) id sourceWriter; -@property (nonatomic, strong, nullable, readwrite) id sourceReader; -@property (nonatomic, strong, nullable, readwrite) id sinkWriter; -@property (nonatomic, strong, nullable, readwrite) id sinkReader; +@property (nonatomic, assign, readonly) int socket; +@property (nonatomic, strong, readonly) FBAMDServiceConnection *connection; +@property (nonatomic, strong, readonly) id logger; +@property (nonatomic, strong, readonly) dispatch_queue_t socketToConnectionQueue; +@property (nonatomic, strong, readonly) dispatch_queue_t connectionToSocketQueue; @end @implementation FBDeviceDebugServer_TwistedPairFiles -- (instancetype)initWithSource:(int)source sink:(FBAMDServiceConnection *)sink queue:(dispatch_queue_t)queue +- (instancetype)initWithSocket:(int)socket connection:(FBAMDServiceConnection *)connection logger:(id)logger { self = [super init]; if (!self) { return nil; } - _source = source; - _sink = sink; - _queue = queue; - _sinkWriteQueue = dispatch_queue_create("com.facebook.fbdevicecontrol.debugserver_sink_write", DISPATCH_QUEUE_SERIAL); - _sinkReadQueue = dispatch_queue_create("com.facebook.fbdevicecontrol.debugserver_sink_read", DISPATCH_QUEUE_SERIAL); + _socket = socket; + _connection = connection; + _logger = logger; + _socketToConnectionQueue = dispatch_queue_create("com.facebook.fbdevicecontrol.debugserver.socket_to_connection", DISPATCH_QUEUE_SERIAL); + _connectionToSocketQueue = dispatch_queue_create("com.facebook.fbdevicecontrol.debugserver.connection_to_socket", DISPATCH_QUEUE_SERIAL); return self; } -- (FBFuture *> *)start +static size_t const ConnectionReadSizeLimit = 1024; + +- (FBFuture *)startWithError:(NSError **)error { - NSError *error = nil; - id sourceWriter = [FBFileWriter asyncWriterWithFileDescriptor:self.source closeOnEndOfFile:NO error:&error]; - if (!sourceWriter) { - return [FBFuture futureWithError:error]; + if (@available(macOS 10.15, *)) { + id logger = self.logger; + int socket = self.socket; + NSFileHandle *socketReadHandle = [[NSFileHandle alloc] initWithFileDescriptor:socket closeOnDealloc:NO]; + NSFileHandle *socketWriteHandle = [[NSFileHandle alloc] initWithFileDescriptor:socket closeOnDealloc:NO]; + FBAMDServiceConnection *connection = self.connection; + FBMutableFuture *socketReadCompleted = FBMutableFuture.future; + FBMutableFuture *connectionReadCompleted = FBMutableFuture.future; + dispatch_async(self.socketToConnectionQueue, ^{ + while (socketReadCompleted.state == FBFutureStateRunning && connectionReadCompleted.state == FBFutureStateRunning) { + NSError *innerError = nil; + NSData *data = [socketReadHandle availableData]; + if (data.length == 0) { + [logger log:@"Socket read reached end of file"]; + break; + } + if (![connection send:data error:&innerError]) { + [logger logFormat:@"Sending data to remote debugserver failed: %@", innerError]; + break; + } + } + [logger logFormat:@"Exiting socket %d read loop", socket]; + [socketReadCompleted resolveWithResult:NSNull.null]; + }); + dispatch_async(self.connectionToSocketQueue, ^{ + while (socketReadCompleted.state == FBFutureStateRunning && connectionReadCompleted.state == FBFutureStateRunning) { + NSError *innerError = nil; + NSData *data = [connection receiveUpTo:ConnectionReadSizeLimit error:&innerError]; + if (data.length == 0) { + [logger logFormat:@"debugserver read ended: %@", innerError]; + break; + } + if (![socketWriteHandle writeData:data error:&innerError]) { + [logger logFormat:@"Socket write failed: %@", innerError]; + break; + } + } + [logger logFormat:@"Exiting connection %@ read loop", connection]; + [connectionReadCompleted resolveWithResult:NSNull.null]; + }); + return [[FBFuture + futureWithFutures:@[ + socketReadCompleted, + connectionReadCompleted, + ]] + onQueue:self.connectionToSocketQueue notifyOfCompletion:^(id _) { + [logger logFormat:@"Closing socket file descriptor %d", socket]; + close(socket); + }]; } - self.sourceWriter = sourceWriter; - self.sinkWriter = [self.sink writeWithConsumerWritingOnQueue:self.sinkWriteQueue]; - self.sourceReader = [FBFileReader readerWithFileDescriptor:self.source closeOnEndOfFile:NO consumer:self.sinkWriter logger:nil]; - self.sinkReader = [self.sink readFromConnectionWritingToConsumer:self.sourceWriter onQueue:self.sinkReadQueue]; - return [[FBFuture - futureWithFutures:@[ - [self.sourceReader startReading], - [self.sinkReader startReading], - ]] - onQueue:self.queue map:^(id _) { - return [[FBFuture - race:@[ - self.sourceReader.finishedReading, - self.sinkReader.finishedReading, - ]] - mapReplace:NSNull.null]; - }]; + return nil; } @end @@ -131,17 +157,19 @@ - (void)socketServer:(FBSocketServer *)server clientConnected:(struct in6_addr)a return; } [self.logger log:@"Client connected, connecting all file handles"]; - self.twistedPair = [[FBDeviceDebugServer_TwistedPairFiles alloc] initWithSource:fileDescriptor sink:self.serviceConnection queue:self.queue]; - [[[self.twistedPair - start] - onQueue:self.queue fmap:^(FBFuture *finished) { - [self.logger log:@"File handles connected"]; - return finished; - }] - onQueue:self.queue notifyOfCompletion:^(id _) { - [self.logger log:@"Client Disconnected"]; - self.twistedPair = nil; - }]; + FBDeviceDebugServer_TwistedPairFiles *twistedPair = [[FBDeviceDebugServer_TwistedPairFiles alloc] initWithSocket:fileDescriptor connection:self.serviceConnection logger:self.logger]; + NSError *error = nil; + FBFuture *completed = [twistedPair startWithError:&error]; + if (!completed) { + [self.logger logFormat:@"Failed to start connection %@", error]; + return; + } + [completed onQueue:self.queue notifyOfCompletion:^(id _) { + [self.logger log:@"Client Disconnected"]; + self.twistedPair = nil; + }]; + [self.teardown resolveFromFuture:completed]; + self.twistedPair = twistedPair; } #pragma mark FBiOSTargetOperation diff --git a/FBDeviceControl/Management/FBDeviceManager.h b/FBDeviceControl/Management/FBDeviceManager.h index 3308ac7bc..b1056ec68 100644 --- a/FBDeviceControl/Management/FBDeviceManager.h +++ b/FBDeviceControl/Management/FBDeviceManager.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBDeviceControl/Management/FBDeviceManager.m b/FBDeviceControl/Management/FBDeviceManager.m index f51bb1305..6c40c6fd8 100644 --- a/FBDeviceControl/Management/FBDeviceManager.m +++ b/FBDeviceControl/Management/FBDeviceManager.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBDeviceControl/Management/FBDeviceSet.h b/FBDeviceControl/Management/FBDeviceSet.h index f76d6a254..791b1fca1 100644 --- a/FBDeviceControl/Management/FBDeviceSet.h +++ b/FBDeviceControl/Management/FBDeviceSet.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBDeviceControl/Management/FBDeviceSet.m b/FBDeviceControl/Management/FBDeviceSet.m index cebb3d496..b4161881d 100644 --- a/FBDeviceControl/Management/FBDeviceSet.m +++ b/FBDeviceControl/Management/FBDeviceSet.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBDeviceControl/Management/FBDeviceStorage.h b/FBDeviceControl/Management/FBDeviceStorage.h index 147020fa7..578fd0327 100644 --- a/FBDeviceControl/Management/FBDeviceStorage.h +++ b/FBDeviceControl/Management/FBDeviceStorage.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBDeviceControl/Management/FBDeviceStorage.m b/FBDeviceControl/Management/FBDeviceStorage.m index dad0bdf4d..b0fe570d5 100644 --- a/FBDeviceControl/Management/FBDeviceStorage.m +++ b/FBDeviceControl/Management/FBDeviceStorage.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBDeviceControl/Management/FBInstrumentsClient.h b/FBDeviceControl/Management/FBInstrumentsClient.h index 45c62b084..1e9c5c819 100644 --- a/FBDeviceControl/Management/FBInstrumentsClient.h +++ b/FBDeviceControl/Management/FBInstrumentsClient.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBDeviceControl/Management/FBInstrumentsClient.m b/FBDeviceControl/Management/FBInstrumentsClient.m index d3782600b..8422b002c 100644 --- a/FBDeviceControl/Management/FBInstrumentsClient.m +++ b/FBDeviceControl/Management/FBInstrumentsClient.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -205,7 +205,7 @@ + (ResponsePayload)onConnection:(FBAMDServiceConnection *)connection requestSend if (![connection send:requestData error:error]) { return InvalidResponsePayload; } - return [self recieveMessage:connection request:request error:error]; + return [self receiveMessage:connection request:request error:error]; } static const uint32 DTXMessageHeaderMagic = 0x1F3D5B79; @@ -351,7 +351,7 @@ + (NSData *)advanceData:(NSData *)data dataOut:(NSData **)dataOut length:(size_t return [data subdataWithRange:NSMakeRange(length, data.length - length)]; } -+ (ResponsePayload)recieveMessage:(FBAMDServiceConnection *)connection request:(RequestPayload)request error:(NSError **)error ++ (ResponsePayload)receiveMessage:(FBAMDServiceConnection *)connection request:(RequestPayload)request error:(NSError **)error { // This header will start the first iteration of the loop, then is overwritten on each iteration. DTXMessageHeader messageHeader = { diff --git a/FBDeviceControl/Management/FBManagedConfigClient.h b/FBDeviceControl/Management/FBManagedConfigClient.h index 21b420baa..c22ad6e0d 100644 --- a/FBDeviceControl/Management/FBManagedConfigClient.h +++ b/FBDeviceControl/Management/FBManagedConfigClient.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBDeviceControl/Management/FBManagedConfigClient.m b/FBDeviceControl/Management/FBManagedConfigClient.m index ce85d1ccc..d020fc9ce 100644 --- a/FBDeviceControl/Management/FBManagedConfigClient.m +++ b/FBDeviceControl/Management/FBManagedConfigClient.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBDeviceControl/Management/FBSpringboardServicesClient.h b/FBDeviceControl/Management/FBSpringboardServicesClient.h index 2b6df1862..59553359d 100644 --- a/FBDeviceControl/Management/FBSpringboardServicesClient.h +++ b/FBDeviceControl/Management/FBSpringboardServicesClient.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBDeviceControl/Management/FBSpringboardServicesClient.m b/FBDeviceControl/Management/FBSpringboardServicesClient.m index 5d16861a8..74fd888ea 100644 --- a/FBDeviceControl/Management/FBSpringboardServicesClient.m +++ b/FBDeviceControl/Management/FBSpringboardServicesClient.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -57,9 +57,9 @@ - (instancetype)initWithClient:(FBSpringboardServicesClient *)client return [FBFuture futureWithResult:self.validFilenames]; } -- (FBFuture *)copyFromContainer:(NSString *)containerPath toHost:(NSString *)destinationPath +- (FBFuture *)copyFromContainer:(NSString *)sourcePath toHost:(NSString *)destinationPath { - NSString *filename = containerPath.lastPathComponent; + NSString *filename = sourcePath.lastPathComponent; return [[FBFuture onQueue:self.client.queue resolve:^ FBFuture * { if (![self.validFilenames containsObject:filename]) { @@ -95,7 +95,7 @@ - (instancetype)initWithClient:(FBSpringboardServicesClient *)client }]; } -- (FBFuture *)copyFromHost:(NSURL *)sourcePath toContainer:(NSString *)destinationPath +- (FBFuture *)copyFromHost:(NSString *)sourcePath toContainer:(NSString *)destinationPath { return [[self iconLayoutFromSourcePath:sourcePath toDestinationFile:destinationPath.lastPathComponent] @@ -104,7 +104,7 @@ - (instancetype)initWithClient:(FBSpringboardServicesClient *)client }]; } -- (FBFuture *> *)tail:(NSString *)containerPath toConsumer:(id)consumer +- (FBFuture *> *)tail:(NSString *)path toConsumer:(id)consumer { return [[FBControlCoreError describeFormat:@"-[%@ %@] is not implemented", NSStringFromClass(self.class), NSStringFromSelector(_cmd)] @@ -132,13 +132,13 @@ - (instancetype)initWithClient:(FBSpringboardServicesClient *)client failFuture]; } -- (FBFuture *)iconLayoutFromSourcePath:(NSURL *)sourcePath toDestinationFile:(NSString *)filename +- (FBFuture *)iconLayoutFromSourcePath:(NSString *)sourcePath toDestinationFile:(NSString *)filename { return [FBFuture onQueue:self.client.queue resolve:^ FBFuture * { if ([filename isEqualToString:IconJSONFile]) { NSError *error = nil; - NSData *data = [NSData dataWithContentsOfURL:sourcePath options:0 error:&error]; + NSData *data = [NSData dataWithContentsOfFile:sourcePath options:0 error:&error]; if (!data) { return [FBFuture futureWithError:error]; } @@ -150,7 +150,7 @@ - (instancetype)initWithClient:(FBSpringboardServicesClient *)client } if ([filename isEqualToString:IconPlistFile]) { NSError *error = nil; - NSData *data = [NSData dataWithContentsOfURL:sourcePath options:0 error:&error]; + NSData *data = [NSData dataWithContentsOfFile:sourcePath options:0 error:&error]; if (!data) { return [FBFuture futureWithError:error]; } @@ -267,7 +267,7 @@ - (instancetype)initWithConnection:(FBAMDServiceConnection *)connection queue:(d if (![self.connection sendMessage:@{@"command": @"setIconState", @"iconState": iconLayout} error:error]) { return nil; } - // Recieve some data to know that it reached the other side, in the event of a failure we will recive no bytes. + // Recieve some data to know that it reached the other side, in the event of a failure we will receive no bytes. NSData *data = [self.connection receive:IconLayoutSize error:error]; if (!data) { return nil; diff --git a/FBDeviceControl/Utility/FBDeviceControlError.h b/FBDeviceControl/Utility/FBDeviceControlError.h index 289116b8e..d8c45cbd4 100644 --- a/FBDeviceControl/Utility/FBDeviceControlError.h +++ b/FBDeviceControl/Utility/FBDeviceControlError.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBDeviceControl/Utility/FBDeviceControlError.m b/FBDeviceControl/Utility/FBDeviceControlError.m index 15f198d13..75e936608 100644 --- a/FBDeviceControl/Utility/FBDeviceControlError.m +++ b/FBDeviceControl/Utility/FBDeviceControlError.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBDeviceControl/Utility/FBDeviceControlFrameworkLoader.h b/FBDeviceControl/Utility/FBDeviceControlFrameworkLoader.h index 249c12c84..207c7a5a3 100644 --- a/FBDeviceControl/Utility/FBDeviceControlFrameworkLoader.h +++ b/FBDeviceControl/Utility/FBDeviceControlFrameworkLoader.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBDeviceControl/Utility/FBDeviceControlFrameworkLoader.m b/FBDeviceControl/Utility/FBDeviceControlFrameworkLoader.m index 9a49a8151..4781d533c 100644 --- a/FBDeviceControl/Utility/FBDeviceControlFrameworkLoader.m +++ b/FBDeviceControl/Utility/FBDeviceControlFrameworkLoader.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBDeviceControl/Utility/FBDeviceLinkClient.h b/FBDeviceControl/Utility/FBDeviceLinkClient.h index 82997f06b..d5cd88eb6 100644 --- a/FBDeviceControl/Utility/FBDeviceLinkClient.h +++ b/FBDeviceControl/Utility/FBDeviceLinkClient.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBDeviceControl/Utility/FBDeviceLinkClient.m b/FBDeviceControl/Utility/FBDeviceLinkClient.m index 422fab73e..19754b768 100644 --- a/FBDeviceControl/Utility/FBDeviceLinkClient.m +++ b/FBDeviceControl/Utility/FBDeviceLinkClient.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBDeviceControl/Utility/FileManager+TemporaryFile.swift b/FBDeviceControl/Utility/FileManager+TemporaryFile.swift new file mode 100644 index 000000000..e0bdece71 --- /dev/null +++ b/FBDeviceControl/Utility/FileManager+TemporaryFile.swift @@ -0,0 +1,19 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import Foundation + +extension FileManager { + func temporaryFile(extension fileExtension: String) throws -> URL { + let tmpPath = try url(for: .itemReplacementDirectory, in: .userDomainMask, appropriateFor: URL(fileURLWithPath: "/tmp"), create: true) + if #available(macOS 13.0, *) { + return tmpPath.appending(component: "\(ProcessInfo().globallyUniqueString).\(fileExtension)") + } else { + return tmpPath.appendingPathComponent("\(ProcessInfo().globallyUniqueString)", isDirectory: false) + } + } +} diff --git a/FBDeviceControl/Video/FBDeviceVideo.h b/FBDeviceControl/Video/FBDeviceVideo.h index 3fbb2d7af..02dbfa51a 100644 --- a/FBDeviceControl/Video/FBDeviceVideo.h +++ b/FBDeviceControl/Video/FBDeviceVideo.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBDeviceControl/Video/FBDeviceVideo.m b/FBDeviceControl/Video/FBDeviceVideo.m index 1dbd8dbb7..bb025ce50 100644 --- a/FBDeviceControl/Video/FBDeviceVideo.m +++ b/FBDeviceControl/Video/FBDeviceVideo.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBDeviceControl/Video/FBDeviceVideoStream.h b/FBDeviceControl/Video/FBDeviceVideoStream.h index e54d84d39..2731eb205 100644 --- a/FBDeviceControl/Video/FBDeviceVideoStream.h +++ b/FBDeviceControl/Video/FBDeviceVideoStream.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBDeviceControl/Video/FBDeviceVideoStream.m b/FBDeviceControl/Video/FBDeviceVideoStream.m index b8342b96e..dd00bed24 100644 --- a/FBDeviceControl/Video/FBDeviceVideoStream.m +++ b/FBDeviceControl/Video/FBDeviceVideoStream.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBDeviceControlTests/FBDeviceControlTests-Prefix.pch b/FBDeviceControlTests/FBDeviceControlTests-Prefix.pch deleted file mode 100644 index e507823b8..000000000 --- a/FBDeviceControlTests/FBDeviceControlTests-Prefix.pch +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -// -// Prefix header -// -// The contents of this file are implicitly included at the beginning of every source file. -// - -#ifdef __OBJC__ - #import - #import -#endif diff --git a/FBDeviceControlTests/Tests/Integration/FBDeviceControlFrameworkLoaderTests.m b/FBDeviceControlTests/Tests/Integration/FBDeviceControlFrameworkLoaderTests.m index 46913ea88..f6c1f335f 100644 --- a/FBDeviceControlTests/Tests/Integration/FBDeviceControlFrameworkLoaderTests.m +++ b/FBDeviceControlTests/Tests/Integration/FBDeviceControlFrameworkLoaderTests.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBDeviceControlTests/Tests/Unit/FBAFCConnectionTests.m b/FBDeviceControlTests/Tests/Unit/FBAFCConnectionTests.m index babdcc595..a76f0c6c8 100644 --- a/FBDeviceControlTests/Tests/Unit/FBAFCConnectionTests.m +++ b/FBDeviceControlTests/Tests/Unit/FBAFCConnectionTests.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -9,58 +9,253 @@ #import -@interface FBAFCConnectionTests : XCTestCase +static int64_t sFileOffset = 0; +static uint64_t sFileMode = 0; +static NSMutableDictionary *> *sEvents; +static NSDictionary *> *sVirtualizedFilesAndAttributes; +static NSString *const DirCreateKey = @"dirCreate"; +static NSString *const FileCloseKey = @"fileClose"; +static NSString *const FileOpenKey = @"fileRefOpen"; +static NSString *const RemovePath = @"removePath"; +static NSString *const RenamePath = @"renamePath"; +static NSString *const FileContentsKey = @"contents"; -@property (nonatomic, strong, readwrite, class) NSMutableDictionary *events; +static void appendPathToEvent(NSString *eventName, const char *path) +{ + NSMutableArray *events = sEvents[eventName]; + [events addObject:[NSString stringWithUTF8String:path]]; +} -@end +static void appendPathsToEvent(NSString *eventName, const char *first, const char *second) +{ + NSMutableArray *events = sEvents[eventName]; + [events addObject:@[[NSString stringWithUTF8String:first], [NSString stringWithUTF8String:second]]]; +} -static void appendToEvent(NSString *eventName, const char *text) { - NSMutableArray *dirs = FBAFCConnectionTests.events[eventName]; - if (!dirs) { - dirs = [NSMutableArray new]; - FBAFCConnectionTests.events[eventName] = dirs; +static NSArray *contentsOfVirtualizedDirectory(NSString *directory) +{ + NSMutableArray *contents = NSMutableArray.array; + for (NSString *path in sVirtualizedFilesAndAttributes.allKeys) { + // Don't add the listed directory to the listing. + if ([path isEqualToString:directory]) { + continue; + } + NSArray *pathComponents = path.pathComponents; + // Case for listing of the root, only list paths without nesting. + BOOL isRootDirectory = directory.length == 0 || [directory isEqualToString:@"/"]; + if (isRootDirectory && pathComponents.count == 1) { + [contents addObject:path.lastPathComponent]; + } + // Case for nested directories, just use prefix matching + if ([path hasPrefix:directory]) { + [contents addObject:path.lastPathComponent]; + } } - [dirs addObject:[NSString stringWithUTF8String:text]]; + return contents; +} + +static char *errorString(int errorCode) +{ + return "some error"; } -static int dirCreateSuccess(AFCConnectionRef connection, const char *dir) { - appendToEvent(@"dirCreate", dir); +static int directoryCreate(AFCConnectionRef connection, const char *dir) +{ + appendPathToEvent(DirCreateKey, dir); return 0; } -static int fileOpen(AFCConnectionRef connection, const char *_Nonnull path, FBAFCReadMode mode, CFTypeRef *_Nonnull ref) { - appendToEvent(@"fileOpen", path); - *ref = CFStringCreateWithCString(NULL, path, kCFStringEncodingUTF8); +static CFDictionaryRef connectionCopyLastErrorInfo(AFCConnectionRef connection) +{ + return (__bridge CFDictionaryRef) @{}; +} + +static int fileRefOpen(AFCConnectionRef connection, const char *path, FBAFCReadMode mode, CFTypeRef *fileRefOut) +{ + if (sVirtualizedFilesAndAttributes){ + NSString *filePath = [NSString stringWithCString:path encoding:NSASCIIStringEncoding]; + NSString *fileContents = sVirtualizedFilesAndAttributes[filePath][FileContentsKey]; + if (!fileContents) { + return 1; + } + } + appendPathToEvent(FileOpenKey, path); + if (fileRefOut) { + *fileRefOut = CFStringCreateWithCString(NULL, path, kCFStringEncodingUTF8); + } return 0; } -static int fileWrite(AFCConnectionRef connection, CFTypeRef ref, const void *buf, uint64_t len) { +static int fileRefSeek(AFCConnectionRef connection, CFTypeRef fileRef, int64_t offset, uint64_t mode) +{ + NSString *filePath = (__bridge NSString *)(fileRef); + NSString *fileContents = sVirtualizedFilesAndAttributes[filePath][FileContentsKey]; + if (!fileContents) { + return 1; + } + sFileOffset = offset; + sFileMode = mode; return 0; } -static int fileClose(AFCConnectionRef connection, CFTypeRef ref) { +static int fileRefTell(AFCConnectionRef connection, CFTypeRef fileRef, uint64_t *offsetOut) +{ + NSString *filePath = (__bridge NSString *)(fileRef); + NSString *fileContents = sVirtualizedFilesAndAttributes[filePath][FileContentsKey]; + if (!fileContents) { + return 1; + } + NSData *fileData = [fileContents dataUsingEncoding:NSASCIIStringEncoding]; + if (offsetOut) { + *offsetOut = fileData.length; + } + return 0; +} + +static int fileRefRead(AFCConnectionRef connection, CFTypeRef fileRef, void *buffer, uint64_t *lengthOut) +{ + NSString *filePath = (__bridge NSString *)(fileRef); + NSString *fileContents = sVirtualizedFilesAndAttributes[filePath][FileContentsKey]; + if (!fileContents) { + return 1; + } + NSData *fileData = [fileContents dataUsingEncoding:NSASCIIStringEncoding]; + memcpy(buffer, fileData.bytes, fileData.length); + return 0; +} + +static int fileWrite(AFCConnectionRef connection, CFTypeRef ref, const void *buf, uint64_t length) +{ + return 0; +} + +static int fileClose(AFCConnectionRef connection, CFTypeRef ref) +{ NSString *fileName = (__bridge NSString *)(ref); - appendToEvent(@"fileClose", fileName.UTF8String); + appendPathToEvent(FileCloseKey, fileName.UTF8String); CFRelease(ref); return 0; } -@implementation FBAFCConnectionTests +static int renamePath(AFCConnectionRef connection, const char *src, const char *dst) +{ + appendPathsToEvent(RenamePath, src, dst); + return 0; +} -static NSMutableDictionary *sEvents; +static int removePath(AFCConnectionRef connection, const char *path) +{ + appendPathToEvent(RemovePath, path); + return 0; +} -+ (NSMutableDictionary *)events +static int directoryOpen(AFCConnectionRef connection, const char *path, CFTypeRef *directoryOut) { - if (!sEvents){ - sEvents = [NSMutableDictionary dictionary]; + NSString *pathString = [NSString stringWithCString:path encoding:NSASCIIStringEncoding]; + NSMutableArray *pathsToEnumerate = [contentsOfVirtualizedDirectory(pathString) mutableCopy]; + if (pathsToEnumerate.count == 0) { + return 1; + } + if (directoryOut) { + *directoryOut = CFBridgingRetain(pathsToEnumerate); } - return sEvents; + return 0; } -+ (void)setEvents:(NSMutableDictionary *)events +static int directoryRead(AFCConnectionRef connection, CFTypeRef dir, char **directoryEntry) { - sEvents = events; + NSMutableArray *pathsToEnumerate = (__bridge NSMutableArray *)(dir); + if (pathsToEnumerate.count == 0) { + return 0; + } + NSString *next = pathsToEnumerate.firstObject; + if (directoryEntry) { + *directoryEntry = (char *) next.UTF8String; + } + [pathsToEnumerate removeObjectAtIndex:0]; + return 0; +} + +static int directoryClose(AFCConnectionRef connection, CFTypeRef dir) +{ + return 0; +} + +static AFCOperationRef operationCreateRemovePathAndContents(CFTypeRef allocator, CFStringRef path, void *unknown_callback_maybe) +{ + NSString *bridged = (__bridge NSString *)(path); + appendPathToEvent(RemovePath, bridged.UTF8String); + return CFSTR("empty"); +} + +static int connectionProcessOperation(AFCConnectionRef connection, CFTypeRef operation) +{ + return 0; +} + +static int operationGetResultStatus(CFTypeRef operation) +{ + return 0; +} + +static CFTypeRef operationGetResultObject(CFTypeRef operation) +{ + return (__bridge CFTypeRef)(@{}); +} + +@interface FBAFCConnectionTests : XCTestCase + +@property (nonatomic, copy, readonly) NSString *rootHostDirectory; +@property (nonatomic, copy, readonly) NSString *fooHostFilePath; +@property (nonatomic, copy, readonly) NSString *barHostDirectory; +@property (nonatomic, copy, readonly) NSString *bazHostFilePath; + +@end + +@implementation FBAFCConnectionTests + +- (void)setUp +{ + [super setUp]; + + sEvents = NSMutableDictionary.dictionary; + sEvents[DirCreateKey] = NSMutableArray.array; + sEvents[FileCloseKey] = NSMutableArray.array; + sEvents[FileOpenKey] = NSMutableArray.array; + sEvents[RemovePath] = NSMutableArray.array; + sEvents[RenamePath] = NSMutableArray.array; + sVirtualizedFilesAndAttributes = nil; + + _rootHostDirectory = [NSTemporaryDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:@"%@_FBAFCConnectionTests", NSUUID.UUID.UUIDString]]; + _fooHostFilePath = [self.rootHostDirectory stringByAppendingPathComponent:@"foo.txt"]; + _barHostDirectory = [self.rootHostDirectory stringByAppendingPathComponent:@"bar"]; + _bazHostFilePath = [self.barHostDirectory stringByAppendingPathComponent:@"baz.empty"]; +} + +- (void)tearDown +{ + [super tearDown]; + + [NSFileManager.defaultManager removeItemAtPath:self.bazHostFilePath error:nil]; + [NSFileManager.defaultManager removeItemAtPath:self.barHostDirectory error:nil]; + [NSFileManager.defaultManager removeItemAtPath:self.fooHostFilePath error:nil]; + [NSFileManager.defaultManager removeItemAtPath:self.rootHostDirectory error:nil]; +} + +- (NSDictionary *> *)events +{ + return [sEvents copy]; +} + +- (void)addVirtualizedRemoteFiles +{ + sVirtualizedFilesAndAttributes = @{ + @"remote_foo.txt": @{FileContentsKey: @"some foo"}, + @"remote_empty": @{FileContentsKey: @""}, + @"remote_bar": @{@"st_ifmt": @"S_IFDIR"}, + @"remote_bar/some.txt": @{FileContentsKey: @"more nested text"}, + @"remote_bar/other.txt": @{FileContentsKey: @"more other text"}, + }; } - (AFCConnectionRef)connectionRef @@ -68,45 +263,215 @@ - (AFCConnectionRef)connectionRef return NULL; } -- (void)testCopyItemsAtPath +static NSString *const FooFileContents = @"FooContents"; + +- (FBAFCConnection *)setUpConnection { AFCCalls afcCalls = { - .DirectoryCreate = dirCreateSuccess, - .FileRefOpen = fileOpen, - .FileRefWrite = fileWrite, + .ConnectionCopyLastErrorInfo = connectionCopyLastErrorInfo, + .ConnectionProcessOperation = connectionProcessOperation, + .DirectoryClose = directoryClose, + .DirectoryCreate = directoryCreate, + .DirectoryOpen = directoryOpen, + .DirectoryRead = directoryRead, + .ErrorString = errorString, .FileRefClose = fileClose, + .FileRefOpen = fileRefOpen, + .FileRefRead = fileRefRead, + .FileRefSeek = fileRefSeek, + .FileRefTell = fileRefTell, + .FileRefWrite = fileWrite, + .OperationCreateRemovePathAndContents = operationCreateRemovePathAndContents, + .OperationGetResultObject = operationGetResultObject, + .OperationGetResultStatus = operationGetResultStatus, + .RemovePath = removePath, + .RenamePath = renamePath, }; + // Structure + // ./foo.txt + // ./bar + // ./bar/baz.empty + NSError *error = nil; + XCTAssertTrue([NSFileManager.defaultManager createDirectoryAtPath:self.rootHostDirectory withIntermediateDirectories:YES attributes:nil error:&error]); + XCTAssertTrue([NSFileManager.defaultManager createDirectoryAtPath:self.barHostDirectory withIntermediateDirectories:YES attributes:nil error:&error]); + XCTAssertTrue([FooFileContents writeToFile:self.fooHostFilePath atomically:YES encoding:NSASCIIStringEncoding error:&error]); + XCTAssertTrue([NSData.data writeToFile:self.bazHostFilePath atomically:YES]); + + return [[FBAFCConnection alloc] initWithConnection:self.connectionRef calls:afcCalls logger:nil]; +} + +- (void)assertExpectedDirectoryCreate:(NSArray *)expectedDirectoryCreate +{ + XCTAssertEqualObjects(expectedDirectoryCreate, self.events[DirCreateKey]); +} + +- (void)assertExpectedFiles:(NSArray *)expectedFiles +{ + XCTAssertEqualObjects(expectedFiles, self.events[FileOpenKey]); + XCTAssertEqualObjects(expectedFiles, self.events[FileCloseKey]); +} - FBAFCConnection *connection = [[FBAFCConnection alloc] initWithConnection:self.connectionRef calls:afcCalls logger:nil]; - - /** Structure - ./{UUID} - ./{UUID}/file.empty - ./{UUID}/{UUID2}/file2.txt - */ - NSString *dir = [[NSUUID UUID] UUIDString]; - NSString *dir2 = [[NSUUID UUID] UUIDString]; - NSString *pathStr = [NSTemporaryDirectory() stringByAppendingPathComponent:dir]; - NSURL *path = [NSURL fileURLWithPath:pathStr]; - NSArray *expectedDirs = @[dir, [@[dir, dir2] componentsJoinedByString:@"/"]]; - - [[NSFileManager defaultManager] createDirectoryAtURL:[path URLByAppendingPathComponent:dir2 isDirectory:YES] withIntermediateDirectories:YES attributes:nil error:NULL]; - [[NSData data] writeToURL:[path URLByAppendingPathComponent:@"file.empty"] atomically:YES]; - [[NSData data] writeToURL:[path URLByAppendingPathComponent:[NSString pathWithComponents:@[dir2, @"file2.txt"]]] atomically:YES]; - - NSSet *files = [NSSet setWithArray:@[ - [dir stringByAppendingFormat:@"/%@", @"file.empty"], - [@[dir, dir2, @"file2.txt"] componentsJoinedByString:@"/"] +- (void)assertRenameFiles:(NSArray *> *)expectedRenameFiles +{ + XCTAssertEqualObjects(expectedRenameFiles, self.events[RenamePath]); +} + +- (void)assertRemoveFiles:(NSArray *)expectedRemoveFiles +{ + XCTAssertEqualObjects(expectedRemoveFiles, self.events[RemovePath]); +} + +- (void)testRootDirectoryList +{ + FBAFCConnection *connection = [self setUpConnection]; + [self addVirtualizedRemoteFiles]; + NSError *error = nil; + NSArray *actual = [connection contentsOfDirectory:@"" error:&error]; + NSArray *expected = @[@"remote_foo.txt", @"remote_empty", @"remote_bar"]; + XCTAssertNil(error); + XCTAssertEqualObjects(actual, expected); +} + +- (void)testNestedDirectoryList +{ + FBAFCConnection *connection = [self setUpConnection]; + [self addVirtualizedRemoteFiles]; + NSError *error = nil; + NSArray *actual = [connection contentsOfDirectory:@"remote_bar" error:&error]; + NSArray *expected = @[@"some.txt", @"other.txt"]; + XCTAssertNil(error); + XCTAssertEqualObjects(actual, expected); +} + +- (void)testMissingDirectoryFail +{ + FBAFCConnection *connection = [self setUpConnection]; + [self addVirtualizedRemoteFiles]; + NSError *error = nil; + NSArray *actual = [connection contentsOfDirectory:@"aaaaaa" error:&error]; + XCTAssertNotNil(error); + XCTAssertNil(actual); +} + +- (void)testReadsFile +{ + FBAFCConnection *connection = [self setUpConnection]; + [self addVirtualizedRemoteFiles]; + NSError *error = nil; + NSData *expected = [@"some foo" dataUsingEncoding:NSASCIIStringEncoding]; + NSData *actual = [connection contentsOfPath:@"remote_foo.txt" error:&error]; + XCTAssertNil(error); + XCTAssertEqualObjects(expected, actual); +} + +- (void)testFailsToReadDirectory +{ + FBAFCConnection *connection = [self setUpConnection]; + [self addVirtualizedRemoteFiles]; + NSError *error = nil; + NSData *actual = [connection contentsOfPath:@"remote_bar" error:&error]; + XCTAssertNil(actual); + XCTAssertNotNil(error); +} + +- (void)testFailsToReadMissingFile +{ + FBAFCConnection *connection = [self setUpConnection]; + [self addVirtualizedRemoteFiles]; + NSError *error = nil; + NSData *actual = [connection contentsOfPath:@"nope" error:&error]; + XCTAssertNil(actual); + XCTAssertNotNil(error); +} + +- (void)testCopySingleFileToRoot +{ + FBAFCConnection *connection = [self setUpConnection]; + NSError *error = nil; + BOOL success = [connection copyFromHost:self.fooHostFilePath toContainerPath:@"" error:&error]; + XCTAssertNil(error); + XCTAssertTrue(success); + + [self assertExpectedDirectoryCreate:@[]]; + [self assertExpectedFiles:@[ + @"foo.txt", + ]]; +} + +- (void)testCopyFileToContainerPath +{ + FBAFCConnection *connection = [self setUpConnection]; + NSError *error = nil; + BOOL success = [connection copyFromHost:self.fooHostFilePath toContainerPath:@"bing" error:&error]; + XCTAssertNil(error); + XCTAssertTrue(success); + + [self assertExpectedDirectoryCreate:@[]]; + [self assertExpectedFiles:@[ + @"bing/foo.txt", ]]; +} + +- (void)testCopyItemsFromHostDirectory +{ + FBAFCConnection *connection = [self setUpConnection]; + NSError *error = nil; + BOOL success = [connection copyFromHost:self.rootHostDirectory toContainerPath:@"" error:&error]; + XCTAssertNil(error); + XCTAssertTrue(success); + + [self assertExpectedDirectoryCreate:@[ + self.rootHostDirectory.lastPathComponent, + [self.rootHostDirectory.lastPathComponent stringByAppendingPathComponent:@"bar"], + ]]; + [self assertExpectedFiles:@[ + [self.rootHostDirectory.lastPathComponent stringByAppendingPathComponent:@"foo.txt"], + [self.rootHostDirectory.lastPathComponent stringByAppendingPathComponent:@"bar/baz.empty"], + ]]; +} +- (void)testCreateDirectoryAtRoot +{ + FBAFCConnection *connection = [self setUpConnection]; + NSError *error = nil; + BOOL success = [connection createDirectory:@"bing" error:&error]; + XCTAssertNil(error); + XCTAssertTrue(success); + + [self assertExpectedDirectoryCreate:@[@"bing"]]; +} + +- (void)testCreateDirectoryInsideDirectory +{ + FBAFCConnection *connection = [self setUpConnection]; + NSError *error = nil; + BOOL success = [connection createDirectory:@"bar/bing" error:&error]; + XCTAssertNil(error); + XCTAssertTrue(success); + + [self assertExpectedDirectoryCreate:@[@"bar/bing"]]; +} + +- (void)testRenamePath +{ + FBAFCConnection *connection = [self setUpConnection]; + NSError *error = nil; + BOOL success = [connection renamePath:@"foo.txt" destination:@"bar.txt" error:&error]; + XCTAssertNil(error); + XCTAssertTrue(success); + + [self assertRenameFiles:@[@[@"foo.txt", @"bar.txt"]]]; +} + +- (void)testRemovePath +{ + FBAFCConnection *connection = [self setUpConnection]; NSError *error = nil; - BOOL success = [connection copyFromHost:path toContainerPath:@"" error:&error]; + BOOL success = [connection removePath:@"foo.txt" recursively:YES error:&error]; XCTAssertNil(error); XCTAssertTrue(success); - XCTAssertEqualObjects(expectedDirs, self.class.events[@"dirCreate"]); - XCTAssertEqualObjects(files, [NSSet setWithArray:self.class.events[@"fileClose"]]); - XCTAssertEqualObjects(self.class.events[@"fileOpen"], self.class.events[@"fileClose"]); + [self assertRemoveFiles:@[@"foo.txt"]]; } @end diff --git a/FBDeviceControlTests/Tests/Unit/FBAMDeviceTests.m b/FBDeviceControlTests/Tests/Unit/FBAMDeviceTests.m index dd9136f69..5c888a677 100644 --- a/FBDeviceControlTests/Tests/Unit/FBAMDeviceTests.m +++ b/FBDeviceControlTests/Tests/Unit/FBAMDeviceTests.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBDeviceControlTests/Tests/Unit/FBDeviceXCTestCommandsTests.m b/FBDeviceControlTests/Tests/Unit/FBDeviceXCTestCommandsTests.m index d0fce0a66..95d6d1f85 100644 --- a/FBDeviceControlTests/Tests/Unit/FBDeviceXCTestCommandsTests.m +++ b/FBDeviceControlTests/Tests/Unit/FBDeviceXCTestCommandsTests.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControl.xcodeproj/project.pbxproj b/FBSimulatorControl.xcodeproj/project.pbxproj index fba1c3200..c74ddb2e7 100644 --- a/FBSimulatorControl.xcodeproj/project.pbxproj +++ b/FBSimulatorControl.xcodeproj/project.pbxproj @@ -7,7 +7,8 @@ objects = { /* Begin PBXBuildFile section */ - 0593EA101E371E5800EBD7CB /* libShimulator.dylib in Resources */ = {isa = PBXBuildFile; fileRef = AA017F4C1BD7784700F45E9D /* libShimulator.dylib */; }; + 1889EACB2AEC7B760097FE08 /* FBAppleDevicectlCommandExecutor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1889EACA2AEC7B760097FE08 /* FBAppleDevicectlCommandExecutor.swift */; }; + 18DC3ADF2AFC60C600F32F27 /* FileManager+TemporaryFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 18DC3ADE2AFC60C600F32F27 /* FileManager+TemporaryFile.swift */; }; 1C0AAAB4254B646000001D3C /* FBXCTestShimConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = 1C0AAAB2254B646000001D3C /* FBXCTestShimConfiguration.m */; }; 1C0AAAB5254B646000001D3C /* FBXCTestShimConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = 1C0AAAB3254B646000001D3C /* FBXCTestShimConfiguration.h */; settings = {ATTRIBUTES = (Public, ); }; }; 1C5091E824EDB8F600FAB67E /* FBXCTestResultBundleParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 1C5091E624EDB8F600FAB67E /* FBXCTestResultBundleParser.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -17,7 +18,6 @@ 1F34A5102512B638001A12F7 /* FBDevicePowerCommands.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F34A50E2512B638001A12F7 /* FBDevicePowerCommands.h */; settings = {ATTRIBUTES = (Public, ); }; }; 1F6F440E239B6A55001C7F72 /* FBXCTestResultToolOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 1F6F440C239B6A55001C7F72 /* FBXCTestResultToolOperation.h */; settings = {ATTRIBUTES = (Public, ); }; }; 1F6F440F239B6A55001C7F72 /* FBXCTestResultToolOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F6F440D239B6A55001C7F72 /* FBXCTestResultToolOperation.m */; }; - 1F7596B31DFF6B40006B9053 /* libShimulator.dylib in Resources */ = {isa = PBXBuildFile; fileRef = AA017F4C1BD7784700F45E9D /* libShimulator.dylib */; }; 2F8294CE1FBC571B0011E722 /* FBLogicReporterAdapter.m in Sources */ = {isa = PBXBuildFile; fileRef = 2F8294CA1FBC571B0011E722 /* FBLogicReporterAdapter.m */; }; 2F8294D01FBC5AAE0011E722 /* FBLogicReporterAdapterTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 2F8294CF1FBC5AAE0011E722 /* FBLogicReporterAdapterTests.m */; }; 2F8294D21FBC797F0011E722 /* FBLogicReporterAdapter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2F8294C91FBC571A0011E722 /* FBLogicReporterAdapter.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -39,6 +39,7 @@ 84E05F9E1F7144DD00668049 /* FBDeviceXCTestCommandsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 84E05F9D1F7144DD00668049 /* FBDeviceXCTestCommandsTests.m */; }; 877123F31BDA797800530B1E /* video0.mp4 in Resources */ = {isa = PBXBuildFile; fileRef = 877123F21BDA797800530B1E /* video0.mp4 */; }; 8BD1AF4B212DB04E001F65E1 /* FBiOSTargetSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 8BD1AF46212DACDE001F65E1 /* FBiOSTargetSet.h */; settings = {ATTRIBUTES = (Public, ); }; }; + A255670D27610C7E0052D060 /* FBProcessFetcherTests.m in Sources */ = {isa = PBXBuildFile; fileRef = A255670A27610C7E0052D060 /* FBProcessFetcherTests.m */; }; A2FD7D012739885300542291 /* FBSimulatorDapServerCommands.m in Sources */ = {isa = PBXBuildFile; fileRef = A2FD7CFD2739885200542291 /* FBSimulatorDapServerCommands.m */; }; A2FD7D022739885300542291 /* FBSimulatorDapServerCommands.h in Headers */ = {isa = PBXBuildFile; fileRef = A2FD7D002739885200542291 /* FBSimulatorDapServerCommands.h */; settings = {ATTRIBUTES = (Private, ); }; }; A2FD7D042739887200542291 /* FBDapServerCommands.h in Headers */ = {isa = PBXBuildFile; fileRef = A2FD7D032739887200542291 /* FBDapServerCommands.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -50,7 +51,6 @@ A2FD7D12273992A400542291 /* FBSimulatorNotificationCommands.m in Sources */ = {isa = PBXBuildFile; fileRef = A2FD7D10273992A400542291 /* FBSimulatorNotificationCommands.m */; }; AA0080D71DB4CCFD009A25CB /* FBProcessTerminationStrategy.h in Headers */ = {isa = PBXBuildFile; fileRef = AA0080D51DB4CCFD009A25CB /* FBProcessTerminationStrategy.h */; settings = {ATTRIBUTES = (Public, ); }; }; AA0080D81DB4CCFD009A25CB /* FBProcessTerminationStrategy.m in Sources */ = {isa = PBXBuildFile; fileRef = AA0080D61DB4CCFD009A25CB /* FBProcessTerminationStrategy.m */; }; - AA017F581BD7787300F45E9D /* libShimulator.dylib in Resources */ = {isa = PBXBuildFile; fileRef = AA017F4C1BD7784700F45E9D /* libShimulator.dylib */; }; AA07B3451D531FEA007FB614 /* FBSimulatorInflationStrategy.h in Headers */ = {isa = PBXBuildFile; fileRef = AA07B3431D531FEA007FB614 /* FBSimulatorInflationStrategy.h */; }; AA07B3461D531FEA007FB614 /* FBSimulatorInflationStrategy.m in Sources */ = {isa = PBXBuildFile; fileRef = AA07B3441D531FEA007FB614 /* FBSimulatorInflationStrategy.m */; }; AA08487B1F3F499800A4BA60 /* FBFuture.h in Headers */ = {isa = PBXBuildFile; fileRef = AA0848791F3F499800A4BA60 /* FBFuture.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -60,11 +60,9 @@ AA09736C24A38484003E4A40 /* FBSimulatorAccessibilityCommands.m in Sources */ = {isa = PBXBuildFile; fileRef = AA09736A24A38484003E4A40 /* FBSimulatorAccessibilityCommands.m */; }; AA09736D24A38484003E4A40 /* FBSimulatorAccessibilityCommands.h in Headers */ = {isa = PBXBuildFile; fileRef = AA09736B24A38484003E4A40 /* FBSimulatorAccessibilityCommands.h */; settings = {ATTRIBUTES = (Public, ); }; }; AA0CA38720643CCF00347424 /* FBCrashLogCommands.h in Headers */ = {isa = PBXBuildFile; fileRef = AA0CA38620643C6800347424 /* FBCrashLogCommands.h */; settings = {ATTRIBUTES = (Public, ); }; }; - AA0F6F2A1CA3DCF700926518 /* FBWeakFrameworkLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = AA0F6F281CA3DCF700926518 /* FBWeakFrameworkLoader.h */; settings = {ATTRIBUTES = (Public, ); }; }; - AA0F6F2B1CA3DCF700926518 /* FBWeakFrameworkLoader.m in Sources */ = {isa = PBXBuildFile; fileRef = AA0F6F291CA3DCF700926518 /* FBWeakFrameworkLoader.m */; }; AA111CCE1BBE7C5A0054AFDD /* CoreSimulatorDoubles.m in Sources */ = {isa = PBXBuildFile; fileRef = AA111CCD1BBE7C5A0054AFDD /* CoreSimulatorDoubles.m */; }; AA1174B21CEA17DB00EB699E /* FBApplicationCommands.h in Headers */ = {isa = PBXBuildFile; fileRef = AA1174B11CEA17DB00EB699E /* FBApplicationCommands.h */; settings = {ATTRIBUTES = (Public, ); }; }; - AA1174B61CEA183F00EB699E /* FBSimulatorApplicationCommands.h in Headers */ = {isa = PBXBuildFile; fileRef = AA1174B41CEA183F00EB699E /* FBSimulatorApplicationCommands.h */; settings = {ATTRIBUTES = (Public, ); }; }; + AA1174B61CEA183F00EB699E /* FBSimulatorApplicationCommands.h in Headers */ = {isa = PBXBuildFile; fileRef = AA1174B41CEA183F00EB699E /* FBSimulatorApplicationCommands.h */; }; AA1174B71CEA183F00EB699E /* FBSimulatorApplicationCommands.m in Sources */ = {isa = PBXBuildFile; fileRef = AA1174B51CEA183F00EB699E /* FBSimulatorApplicationCommands.m */; }; AA11EDF9272C44410055D6D1 /* FBFileContainerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = AA11EDF8272C44410055D6D1 /* FBFileContainerTests.m */; }; AA12D5441CE1086300CCD944 /* FBTestReporterAdapter.h in Headers */ = {isa = PBXBuildFile; fileRef = AA12D5421CE1086300CCD944 /* FBTestReporterAdapter.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -96,7 +94,6 @@ AA2076B91F0B7542001F180C /* FBProcessTests.m in Sources */ = {isa = PBXBuildFile; fileRef = AA2076A71F0B7541001F180C /* FBProcessTests.m */; }; AA2076BB1F0B7542001F180C /* FBiOSTargetConfigurationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = AA2076AA1F0B7541001F180C /* FBiOSTargetConfigurationTests.m */; }; AA2076BC1F0B7542001F180C /* FBControlCoreLoggerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = AA2076AB1F0B7541001F180C /* FBControlCoreLoggerTests.m */; }; - AA2076BD1F0B7542001F180C /* FBCrashLogInfoTests.m in Sources */ = {isa = PBXBuildFile; fileRef = AA2076AC1F0B7541001F180C /* FBCrashLogInfoTests.m */; }; AA2076C31F0B7542001F180C /* FBiOSTargetTests.m in Sources */ = {isa = PBXBuildFile; fileRef = AA2076B21F0B7541001F180C /* FBiOSTargetTests.m */; }; AA2076D01F0B76AF001F180C /* FBFileWriterTests.m in Sources */ = {isa = PBXBuildFile; fileRef = AA2076CF1F0B76AF001F180C /* FBFileWriterTests.m */; }; AA2076D21F0B779B001F180C /* FBFileReaderTests.m in Sources */ = {isa = PBXBuildFile; fileRef = AA2076D11F0B779B001F180C /* FBFileReaderTests.m */; }; @@ -114,7 +111,7 @@ AA2E38E121E629C20065C800 /* FBDebuggerCommands.h in Headers */ = {isa = PBXBuildFile; fileRef = AA2E38E021E626B10065C800 /* FBDebuggerCommands.h */; settings = {ATTRIBUTES = (Public, ); }; }; AA2F41F2252481C1002279A2 /* FBSpringboardServicesClient.h in Headers */ = {isa = PBXBuildFile; fileRef = AA2F41F0252481C1002279A2 /* FBSpringboardServicesClient.h */; }; AA2F41F3252481C1002279A2 /* FBSpringboardServicesClient.m in Sources */ = {isa = PBXBuildFile; fileRef = AA2F41F1252481C1002279A2 /* FBSpringboardServicesClient.m */; }; - AA2F45C21D6ED47B00365A2C /* FBSimulatorServiceContext.h in Headers */ = {isa = PBXBuildFile; fileRef = AA2F45C01D6ED47B00365A2C /* FBSimulatorServiceContext.h */; settings = {ATTRIBUTES = (Public, ); }; }; + AA2F45C21D6ED47B00365A2C /* FBSimulatorServiceContext.h in Headers */ = {isa = PBXBuildFile; fileRef = AA2F45C01D6ED47B00365A2C /* FBSimulatorServiceContext.h */; }; AA2F45C31D6ED47B00365A2C /* FBSimulatorServiceContext.m in Sources */ = {isa = PBXBuildFile; fileRef = AA2F45C11D6ED47B00365A2C /* FBSimulatorServiceContext.m */; }; AA3051BF2701F3A4003895E5 /* FBStorageUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = AA3051BB2701F3A4003895E5 /* FBStorageUtils.m */; }; AA3051C02701F3A4003895E5 /* FBStorageUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = AA3051BE2701F3A4003895E5 /* FBStorageUtils.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -131,7 +128,7 @@ AA3C18441D5DE47D00419EAA /* CoreImage.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AA3C18431D5DE47D00419EAA /* CoreImage.framework */; }; AA3E44401F14AE2C00F333D2 /* FBDeviceApplicationCommands.h in Headers */ = {isa = PBXBuildFile; fileRef = AA3E443E1F14AE2C00F333D2 /* FBDeviceApplicationCommands.h */; settings = {ATTRIBUTES = (Public, ); }; }; AA3E44411F14AE2C00F333D2 /* FBDeviceApplicationCommands.m in Sources */ = {isa = PBXBuildFile; fileRef = AA3E443F1F14AE2C00F333D2 /* FBDeviceApplicationCommands.m */; }; - AA3EA8531F31B20D003FBDC1 /* FBSimulatorFileCommands.h in Headers */ = {isa = PBXBuildFile; fileRef = AA3EA8511F31B20D003FBDC1 /* FBSimulatorFileCommands.h */; settings = {ATTRIBUTES = (Public, ); }; }; + AA3EA8531F31B20D003FBDC1 /* FBSimulatorFileCommands.h in Headers */ = {isa = PBXBuildFile; fileRef = AA3EA8511F31B20D003FBDC1 /* FBSimulatorFileCommands.h */; }; AA3EA8541F31B20D003FBDC1 /* FBSimulatorFileCommands.m in Sources */ = {isa = PBXBuildFile; fileRef = AA3EA8521F31B20D003FBDC1 /* FBSimulatorFileCommands.m */; }; AA3EA8561F31B494003FBDC1 /* FBSimulatorApplicationDataTests.m in Sources */ = {isa = PBXBuildFile; fileRef = AA3EA8551F31B494003FBDC1 /* FBSimulatorApplicationDataTests.m */; }; AA3FD04D1C876E4F001093CA /* FBSimulatorLaunchTests.m in Sources */ = {isa = PBXBuildFile; fileRef = AA3FD03D1C876E4F001093CA /* FBSimulatorLaunchTests.m */; }; @@ -166,9 +163,9 @@ AA56445E1E5F6ED0006C1077 /* FBSimulatorKeychainCommands.h in Headers */ = {isa = PBXBuildFile; fileRef = AA56445C1E5F6ED0006C1077 /* FBSimulatorKeychainCommands.h */; settings = {ATTRIBUTES = (Public, ); }; }; AA56445F1E5F6ED0006C1077 /* FBSimulatorKeychainCommands.m in Sources */ = {isa = PBXBuildFile; fileRef = AA56445D1E5F6ED0006C1077 /* FBSimulatorKeychainCommands.m */; }; AA56DBFC26BAA96B001896F3 /* FBProcessSpawnCommands.m in Sources */ = {isa = PBXBuildFile; fileRef = AA56DBF926BAA96B001896F3 /* FBProcessSpawnCommands.m */; }; - AA56EAF01EEFCA400062C2BC /* libMaculator.dylib in Resources */ = {isa = PBXBuildFile; fileRef = AA56EAEE1EEFCA340062C2BC /* libMaculator.dylib */; }; - AA56EAF11EEFCB1D0062C2BC /* libShimulator.dylib in Resources */ = {isa = PBXBuildFile; fileRef = AA017F4C1BD7784700F45E9D /* libShimulator.dylib */; }; AA57804526C54B7100847769 /* FBProcess.m in Sources */ = {isa = PBXBuildFile; fileRef = AA57804226C54B7100847769 /* FBProcess.m */; }; + AA57ADB72785B0C600D35D24 /* FBDeviceDebugSymbolsCommands.h in Headers */ = {isa = PBXBuildFile; fileRef = AA57ADB32785B0C600D35D24 /* FBDeviceDebugSymbolsCommands.h */; settings = {ATTRIBUTES = (Public, ); }; }; + AA57ADB82785B0C600D35D24 /* FBDeviceDebugSymbolsCommands.m in Sources */ = {isa = PBXBuildFile; fileRef = AA57ADB62785B0C600D35D24 /* FBDeviceDebugSymbolsCommands.m */; }; AA58F88C1D95917D006F8D81 /* FBBundleDescriptor.h in Headers */ = {isa = PBXBuildFile; fileRef = AA58F88A1D95917D006F8D81 /* FBBundleDescriptor.h */; settings = {ATTRIBUTES = (Public, ); }; }; AA58F88D1D95917D006F8D81 /* FBBundleDescriptor.m in Sources */ = {isa = PBXBuildFile; fileRef = AA58F88B1D95917D006F8D81 /* FBBundleDescriptor.m */; }; AA58F8921D959593006F8D81 /* FBCodesignProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = AA58F88F1D959593006F8D81 /* FBCodesignProvider.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -208,10 +205,10 @@ AA6A3B0A1CC0C96E00E016C4 /* FBCollectionOperations.m in Sources */ = {isa = PBXBuildFile; fileRef = AA6A3B081CC0C96E00E016C4 /* FBCollectionOperations.m */; }; AA6A3B3F1CC1597000E016C4 /* FBSimulatorBootStrategy.h in Headers */ = {isa = PBXBuildFile; fileRef = AA6A3B351CC1597000E016C4 /* FBSimulatorBootStrategy.h */; }; AA6A3B401CC1597000E016C4 /* FBSimulatorBootStrategy.m in Sources */ = {isa = PBXBuildFile; fileRef = AA6A3B361CC1597000E016C4 /* FBSimulatorBootStrategy.m */; }; - AA6A3B431CC1597000E016C4 /* FBSimulatorTerminationStrategy.h in Headers */ = {isa = PBXBuildFile; fileRef = AA6A3B391CC1597000E016C4 /* FBSimulatorTerminationStrategy.h */; }; - AA6A3B441CC1597000E016C4 /* FBSimulatorTerminationStrategy.m in Sources */ = {isa = PBXBuildFile; fileRef = AA6A3B3A1CC1597000E016C4 /* FBSimulatorTerminationStrategy.m */; }; AA6B1DD21FC5FCFA009DDDAE /* FBDataBufferTests.m in Sources */ = {isa = PBXBuildFile; fileRef = AA6B1DD11FC5FCFA009DDDAE /* FBDataBufferTests.m */; }; AA6C68A4267B89C100EB975D /* FBProcessIOTests.m in Sources */ = {isa = PBXBuildFile; fileRef = AA6C68A3267B89C100EB975D /* FBProcessIOTests.m */; }; + AA6F0CFF27D8ABFE00181EFC /* FBDeviceLifecycleCommands.m in Sources */ = {isa = PBXBuildFile; fileRef = AA6F0CFB27D8ABFE00181EFC /* FBDeviceLifecycleCommands.m */; }; + AA6F0D0027D8ABFE00181EFC /* FBDeviceLifecycleCommands.h in Headers */ = {isa = PBXBuildFile; fileRef = AA6F0CFE27D8ABFE00181EFC /* FBDeviceLifecycleCommands.h */; }; AA6F22441C916A31009F5CE4 /* photo0.png in Resources */ = {isa = PBXBuildFile; fileRef = AA6F22411C916A31009F5CE4 /* photo0.png */; }; AA6F22451C916A31009F5CE4 /* simulator_system.log in Resources */ = {isa = PBXBuildFile; fileRef = AA6F22421C916A31009F5CE4 /* simulator_system.log */; }; AA6F22461C916A31009F5CE4 /* tree.json in Resources */ = {isa = PBXBuildFile; fileRef = AA6F22431C916A31009F5CE4 /* tree.json */; }; @@ -234,6 +231,7 @@ AA758B4D20E3C0720064EC18 /* FBAMDeviceServiceManager.m in Sources */ = {isa = PBXBuildFile; fileRef = AA758B4B20E3C0720064EC18 /* FBAMDeviceServiceManager.m */; }; AA7728AE1E5238A6008FCF7C /* FBFileWriter.h in Headers */ = {isa = PBXBuildFile; fileRef = AA7728AC1E5238A6008FCF7C /* FBFileWriter.h */; settings = {ATTRIBUTES = (Public, ); }; }; AA7728AF1E5238A6008FCF7C /* FBFileWriter.m in Sources */ = {isa = PBXBuildFile; fileRef = AA7728AD1E5238A6008FCF7C /* FBFileWriter.m */; }; + AA777B0327A9937E00E1481F /* FBControlCoreFrameworkLoaderTests.m in Sources */ = {isa = PBXBuildFile; fileRef = AA777B0027A9937E00E1481F /* FBControlCoreFrameworkLoaderTests.m */; }; AA780714225B4A0700A6E4AF /* FBSimulatorSetTestCase.m in Sources */ = {isa = PBXBuildFile; fileRef = AA780713225B4A0700A6E4AF /* FBSimulatorSetTestCase.m */; }; AA791BA81C63668C00AE49EB /* SimulatorBridge-Protocol.h in Headers */ = {isa = PBXBuildFile; fileRef = AA791BA51C63668C00AE49EB /* SimulatorBridge-Protocol.h */; }; AA791BA91C63668C00AE49EB /* SimulatorBridge.h in Headers */ = {isa = PBXBuildFile; fileRef = AA791BA61C63668C00AE49EB /* SimulatorBridge.h */; }; @@ -260,6 +258,9 @@ AA861B721E5F920B0080C86B /* FBSimulatorLifecycleCommands.m in Sources */ = {isa = PBXBuildFile; fileRef = AA861B701E5F920B0080C86B /* FBSimulatorLifecycleCommands.m */; }; AA89546B1D5C7400006BD815 /* FBControlCoreFrameworkLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = AA8954691D5C7400006BD815 /* FBControlCoreFrameworkLoader.h */; settings = {ATTRIBUTES = (Public, ); }; }; AA89546C1D5C7400006BD815 /* FBControlCoreFrameworkLoader.m in Sources */ = {isa = PBXBuildFile; fileRef = AA89546A1D5C7400006BD815 /* FBControlCoreFrameworkLoader.m */; }; + AA89E5B227D7AF3400ECD072 /* FBiOSTargetConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = AA89E5AE27D7AF3400ECD072 /* FBiOSTargetConstants.h */; settings = {ATTRIBUTES = (Public, ); }; }; + AA89E5B327D7AF3400ECD072 /* FBiOSTargetConstants.m in Sources */ = {isa = PBXBuildFile; fileRef = AA89E5B127D7AF3400ECD072 /* FBiOSTargetConstants.m */; }; + AA89E5B527D7B08300ECD072 /* FBLifecycleCommands.h in Headers */ = {isa = PBXBuildFile; fileRef = AA89E5B427D7B08300ECD072 /* FBLifecycleCommands.h */; settings = {ATTRIBUTES = (Public, ); }; }; AA8D347224D04BD0000FAC59 /* FBDiagnosticInformationCommands.h in Headers */ = {isa = PBXBuildFile; fileRef = AA8D347124D04BD0000FAC59 /* FBDiagnosticInformationCommands.h */; settings = {ATTRIBUTES = (Public, ); }; }; AA8D347524D04C35000FAC59 /* FBDeviceDiagnosticInformationCommands.m in Sources */ = {isa = PBXBuildFile; fileRef = AA8D347324D04C34000FAC59 /* FBDeviceDiagnosticInformationCommands.m */; }; AA8D347624D04C35000FAC59 /* FBDeviceDiagnosticInformationCommands.h in Headers */ = {isa = PBXBuildFile; fileRef = AA8D347424D04C35000FAC59 /* FBDeviceDiagnosticInformationCommands.h */; }; @@ -281,7 +282,6 @@ AA9316E1248FB421004D17B3 /* FBAMRestorableDeviceManager.h in Headers */ = {isa = PBXBuildFile; fileRef = AA9316DD248FB421004D17B3 /* FBAMRestorableDeviceManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; AA9316E2248FB421004D17B3 /* FBAMRestorableDevice.h in Headers */ = {isa = PBXBuildFile; fileRef = AA9316DE248FB421004D17B3 /* FBAMRestorableDevice.h */; settings = {ATTRIBUTES = (Private, ); }; }; AA9316E3248FB421004D17B3 /* FBAMRestorableDeviceManager.m in Sources */ = {isa = PBXBuildFile; fileRef = AA9316DF248FB421004D17B3 /* FBAMRestorableDeviceManager.m */; }; - AA9319B622B78E9F00C68F65 /* FBBinaryDescriptorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = AA9319B522B78E9F00C68F65 /* FBBinaryDescriptorTests.m */; }; AA9319B822B78FB800C68F65 /* FBBinaryDescriptorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = AA9319B722B78FB800C68F65 /* FBBinaryDescriptorTests.m */; }; AA9485E42074B38C00716117 /* FBControlCoreLogger+OSLog.h in Headers */ = {isa = PBXBuildFile; fileRef = AA9485E22074B38C00716117 /* FBControlCoreLogger+OSLog.h */; }; AA9485E52074B38C00716117 /* FBControlCoreLogger+OSLog.m in Sources */ = {isa = PBXBuildFile; fileRef = AA9485E32074B38C00716117 /* FBControlCoreLogger+OSLog.m */; }; @@ -296,7 +296,7 @@ AA9517801C15F54600A89CAD /* FBSimulator.m in Sources */ = {isa = PBXBuildFile; fileRef = AA9516FF1C15F54600A89CAD /* FBSimulator.m */; }; AA9517811C15F54600A89CAD /* FBSimulatorControl+PrincipalClass.h in Headers */ = {isa = PBXBuildFile; fileRef = AA9517001C15F54600A89CAD /* FBSimulatorControl+PrincipalClass.h */; settings = {ATTRIBUTES = (Public, ); }; }; AA9517831C15F54600A89CAD /* FBSimulatorControl+PrincipalClass.m in Sources */ = {isa = PBXBuildFile; fileRef = AA9517021C15F54600A89CAD /* FBSimulatorControl+PrincipalClass.m */; }; - AA9517971C15F54600A89CAD /* FBCoreSimulatorNotifier.h in Headers */ = {isa = PBXBuildFile; fileRef = AA9517181C15F54600A89CAD /* FBCoreSimulatorNotifier.h */; settings = {ATTRIBUTES = (Public, ); }; }; + AA9517971C15F54600A89CAD /* FBCoreSimulatorNotifier.h in Headers */ = {isa = PBXBuildFile; fileRef = AA9517181C15F54600A89CAD /* FBCoreSimulatorNotifier.h */; }; AA9517981C15F54600A89CAD /* FBCoreSimulatorNotifier.m in Sources */ = {isa = PBXBuildFile; fileRef = AA9517191C15F54600A89CAD /* FBCoreSimulatorNotifier.m */; }; AA9517B81C15F54600A89CAD /* FBSimulatorError.h in Headers */ = {isa = PBXBuildFile; fileRef = AA95173E1C15F54600A89CAD /* FBSimulatorError.h */; settings = {ATTRIBUTES = (Public, ); }; }; AA9517B91C15F54600A89CAD /* FBSimulatorError.m in Sources */ = {isa = PBXBuildFile; fileRef = AA95173F1C15F54600A89CAD /* FBSimulatorError.m */; }; @@ -308,11 +308,11 @@ AA97C7FB20D90D98002B8564 /* FBAMDevice+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = AA682B231CEDA237009B6ECA /* FBAMDevice+Private.h */; settings = {ATTRIBUTES = (Public, ); }; }; AA98266724E131CA006E05A9 /* FBFileContainer.h in Headers */ = {isa = PBXBuildFile; fileRef = AA98266624E131CA006E05A9 /* FBFileContainer.h */; settings = {ATTRIBUTES = (Public, ); }; }; AA98266A24E1348C006E05A9 /* FBFileCommands.h in Headers */ = {isa = PBXBuildFile; fileRef = AA98266924E1348C006E05A9 /* FBFileCommands.h */; settings = {ATTRIBUTES = (Public, ); }; }; - AA98ECAA1D0559D000916AED /* FBControlCore.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = EEBD600E1C90628F00298A07 /* FBControlCore.framework */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; - AA98ECAC1D0559DF00916AED /* FBControlCore.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = EEBD600E1C90628F00298A07 /* FBControlCore.framework */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; - AA98ECAD1D0559E100916AED /* XCTestBootstrap.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = EE4F0D301C91B7DA00608E89 /* XCTestBootstrap.framework */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; - AA98ECAE1D0559E400916AED /* XCTestBootstrap.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = EE4F0D301C91B7DA00608E89 /* XCTestBootstrap.framework */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; - AA98ECB01D055A0000916AED /* FBControlCore.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = EEBD600E1C90628F00298A07 /* FBControlCore.framework */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; + AA98ECAA1D0559D000916AED /* FBControlCore.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = EEBD600E1C90628F00298A07 /* FBControlCore.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + AA98ECAC1D0559DF00916AED /* FBControlCore.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = EEBD600E1C90628F00298A07 /* FBControlCore.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + AA98ECAD1D0559E100916AED /* XCTestBootstrap.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = EE4F0D301C91B7DA00608E89 /* XCTestBootstrap.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + AA98ECAE1D0559E400916AED /* XCTestBootstrap.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = EE4F0D301C91B7DA00608E89 /* XCTestBootstrap.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + AA98ECB01D055A0000916AED /* FBControlCore.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = EEBD600E1C90628F00298A07 /* FBControlCore.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; AA9DB39B24DA9C1F00960765 /* FBDeviceRecoveryCommands.h in Headers */ = {isa = PBXBuildFile; fileRef = AA9DB39924DA9C1E00960765 /* FBDeviceRecoveryCommands.h */; settings = {ATTRIBUTES = (Public, ); }; }; AA9DB39C24DA9C1F00960765 /* FBDeviceRecoveryCommands.m in Sources */ = {isa = PBXBuildFile; fileRef = AA9DB39A24DA9C1F00960765 /* FBDeviceRecoveryCommands.m */; }; AAA02A4824A118AB0054F0DC /* FBDeviceCommands.h in Headers */ = {isa = PBXBuildFile; fileRef = AAA02A4724A118AB0054F0DC /* FBDeviceCommands.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -336,8 +336,6 @@ AAAB14191F46060100CE5579 /* FBXcodeBuildOperationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = AAAB14181F46060100CE5579 /* FBXcodeBuildOperationTests.m */; }; AAABD8E21E450CF400C007C2 /* FBSurfaceImageGenerator.m in Sources */ = {isa = PBXBuildFile; fileRef = AAABD8E01E450CF400C007C2 /* FBSurfaceImageGenerator.m */; }; AAABD8E31E450CF400C007C2 /* FBSurfaceImageGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = AAABD8E11E450CF400C007C2 /* FBSurfaceImageGenerator.h */; }; - AAB123821DB4B16900F20555 /* FBDispatchSourceNotifier.h in Headers */ = {isa = PBXBuildFile; fileRef = AAB123801DB4B16900F20555 /* FBDispatchSourceNotifier.h */; settings = {ATTRIBUTES = (Public, ); }; }; - AAB123831DB4B16900F20555 /* FBDispatchSourceNotifier.m in Sources */ = {isa = PBXBuildFile; fileRef = AAB123811DB4B16900F20555 /* FBDispatchSourceNotifier.m */; }; AAB1507420F5ED7600BB17A1 /* FBAMDefines.h in Headers */ = {isa = PBXBuildFile; fileRef = AAB1507320F5ED7600BB17A1 /* FBAMDefines.h */; settings = {ATTRIBUTES = (Public, ); }; }; AAB475F420C80F7D00B37634 /* FBiOSTargetCommandForwarderTests.m in Sources */ = {isa = PBXBuildFile; fileRef = AAB475F320C80F7D00B37634 /* FBiOSTargetCommandForwarderTests.m */; }; AAB475F720C8217F00B37634 /* FBSimulatorCrashLogCommands.h in Headers */ = {isa = PBXBuildFile; fileRef = AAB475F520C8217F00B37634 /* FBSimulatorCrashLogCommands.h */; }; @@ -467,6 +465,7 @@ AAFE1C131FD68A7D00ADDE66 /* FBSimulatorNotificationUpdateStrategy.m in Sources */ = {isa = PBXBuildFile; fileRef = AAFE1C111FD68A7D00ADDE66 /* FBSimulatorNotificationUpdateStrategy.m */; }; AAFE93B61CE4954500A50F76 /* FBSimulatorEraseStrategy.h in Headers */ = {isa = PBXBuildFile; fileRef = AAFE93B41CE4954500A50F76 /* FBSimulatorEraseStrategy.h */; }; AAFE93B71CE4954500A50F76 /* FBSimulatorEraseStrategy.m in Sources */ = {isa = PBXBuildFile; fileRef = AAFE93B51CE4954500A50F76 /* FBSimulatorEraseStrategy.m */; }; + B8E19B9C27D0E33A0095241C /* Accelerate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B8E19B9927D0E33A0095241C /* Accelerate.framework */; platformFilter = maccatalyst; }; C0B32FC91E4E459700A48CF4 /* FBArchitecture.h in Headers */ = {isa = PBXBuildFile; fileRef = C0B32FC71E4E459700A48CF4 /* FBArchitecture.h */; settings = {ATTRIBUTES = (Public, ); }; }; C0B32FCA1E4E459700A48CF4 /* FBArchitecture.m in Sources */ = {isa = PBXBuildFile; fileRef = C0B32FC81E4E459700A48CF4 /* FBArchitecture.m */; }; D75ACC6B264BEF82009862C4 /* FBOToolDynamicLibs.m in Sources */ = {isa = PBXBuildFile; fileRef = D75ACC69264BEF82009862C4 /* FBOToolDynamicLibs.m */; }; @@ -481,6 +480,22 @@ D7C55B30217E28D000A9BCB7 /* FBSimulatorMediaCommandsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = D7C55B2F217E28D000A9BCB7 /* FBSimulatorMediaCommandsTests.m */; }; D7E70C122440A2B40092422C /* FBAttachment.h in Headers */ = {isa = PBXBuildFile; fileRef = D7E70C102440A2B40092422C /* FBAttachment.h */; settings = {ATTRIBUTES = (Public, ); }; }; D7E70C132440A2B40092422C /* FBAttachment.m in Sources */ = {isa = PBXBuildFile; fileRef = D7E70C112440A2B40092422C /* FBAttachment.m */; }; + DB15123429E5C34C00A7C0A9 /* FBArchitectureProcessAdapterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB15123329E5C34C00A7C0A9 /* FBArchitectureProcessAdapterTests.swift */; }; + DB15123829E5C54800A7C0A9 /* xctest in Resources */ = {isa = PBXBuildFile; fileRef = DB15123729E5C54800A7C0A9 /* xctest */; }; + DB1B3C8929DD9F1F003695C4 /* FBArchitectureProcessAdapter.h in Headers */ = {isa = PBXBuildFile; fileRef = DB1B3C8629DD9D75003695C4 /* FBArchitectureProcessAdapter.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DB1B3C8B29DD9F36003695C4 /* FBArchitectureProcessAdapter.m in Sources */ = {isa = PBXBuildFile; fileRef = DB1B3C8A29DD9F36003695C4 /* FBArchitectureProcessAdapter.m */; }; + DB22F7072A8FBC7400695320 /* FBMacLaunchedApplication.h in Headers */ = {isa = PBXBuildFile; fileRef = DB22F7052A8FBC7400695320 /* FBMacLaunchedApplication.h */; }; + DB22F7082A8FBC7400695320 /* FBMacLaunchedApplication.m in Sources */ = {isa = PBXBuildFile; fileRef = DB22F7062A8FBC7400695320 /* FBMacLaunchedApplication.m */; }; + DB523BF4297199A10005D7AE /* FBExceptionInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = DB523BF0297199A10005D7AE /* FBExceptionInfo.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DB523BF5297199A10005D7AE /* FBExceptionInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = DB523BF3297199A10005D7AE /* FBExceptionInfo.m */; }; + DB5F4876281079AD000FC7C7 /* FBConcatedJsonParserTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB5F4875281079AD000FC7C7 /* FBConcatedJsonParserTests.swift */; }; + DB5F4879281079CC000FC7C7 /* FBConcatedJsonParser.m in Sources */ = {isa = PBXBuildFile; fileRef = DB5F4877281079CC000FC7C7 /* FBConcatedJsonParser.m */; }; + DB5F487A281079CC000FC7C7 /* FBConcatedJsonParser.h in Headers */ = {isa = PBXBuildFile; fileRef = DB5F4878281079CC000FC7C7 /* FBConcatedJsonParser.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DB5F487C28114D84000FC7C7 /* FBCrashLogParser.h in Headers */ = {isa = PBXBuildFile; fileRef = DB5F487B28114D84000FC7C7 /* FBCrashLogParser.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DB5F487E28114E7B000FC7C7 /* FBCrashLogParser.m in Sources */ = {isa = PBXBuildFile; fileRef = DB5F487D28114E7B000FC7C7 /* FBCrashLogParser.m */; }; + DB5F488028115683000FC7C7 /* FBCrashLogInfoTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB5F487F28115683000FC7C7 /* FBCrashLogInfoTests.swift */; }; + DB5F4882281156C4000FC7C7 /* TestFixtures.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB5F4881281156C4000FC7C7 /* TestFixtures.swift */; }; + DB5F488428115C5E000FC7C7 /* xctest-concated-json-crash.ips in Resources */ = {isa = PBXBuildFile; fileRef = DB5F488328115C5E000FC7C7 /* xctest-concated-json-crash.ips */; }; E7A30F0476B173B900000000 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DD70E2976B173B900000000 /* Cocoa.framework */; }; E7A30F04A6018C7A00000000 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DD70E29A6018C7A00000000 /* CoreGraphics.framework */; }; EE1277541C931C5E00DE52A1 /* XCTestBootstrap.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = EE4F0D301C91B7DA00608E89 /* XCTestBootstrap.framework */; }; @@ -668,6 +683,8 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 1889EACA2AEC7B760097FE08 /* FBAppleDevicectlCommandExecutor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FBAppleDevicectlCommandExecutor.swift; sourceTree = ""; }; + 18DC3ADE2AFC60C600F32F27 /* FileManager+TemporaryFile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "FileManager+TemporaryFile.swift"; sourceTree = ""; }; 1C0AAAB2254B646000001D3C /* FBXCTestShimConfiguration.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBXCTestShimConfiguration.m; sourceTree = ""; }; 1C0AAAB3254B646000001D3C /* FBXCTestShimConfiguration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBXCTestShimConfiguration.h; sourceTree = ""; }; 1C5091E624EDB8F600FAB67E /* FBXCTestResultBundleParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBXCTestResultBundleParser.h; sourceTree = ""; }; @@ -696,6 +713,48 @@ 30DF57E7266E3C6F00EC9015 /* XCTTestIdentifierSetBuilder.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = XCTTestIdentifierSetBuilder.h; sourceTree = ""; }; 713C709626F534050086D8DF /* FBCodeCoverageConfiguration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBCodeCoverageConfiguration.h; sourceTree = ""; }; 713C709726F534050086D8DF /* FBCodeCoverageConfiguration.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBCodeCoverageConfiguration.m; sourceTree = ""; }; + 717901682A960B4C000FBF19 /* XCTMessagingRole_ControlSessionInitiation-Protocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "XCTMessagingRole_ControlSessionInitiation-Protocol.h"; sourceTree = ""; }; + 717901692A960B4C000FBF19 /* XCTMessagingRole_TestReporting_Legacy-Protocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "XCTMessagingRole_TestReporting_Legacy-Protocol.h"; sourceTree = ""; }; + 7179016A2A960B4C000FBF19 /* XCTMessagingChannel_DaemonRecorderToIDE-Protocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "XCTMessagingChannel_DaemonRecorderToIDE-Protocol.h"; sourceTree = ""; }; + 7179016B2A960B4C000FBF19 /* XCTMessagingRole_DebugLogging-Protocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "XCTMessagingRole_DebugLogging-Protocol.h"; sourceTree = ""; }; + 7179016C2A960B4C000FBF19 /* XCTMessagingRole_DiagnosticsCollection-Protocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "XCTMessagingRole_DiagnosticsCollection-Protocol.h"; sourceTree = ""; }; + 7179016D2A960B4D000FBF19 /* XCTMessagingRole_CapabilityExchange-Protocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "XCTMessagingRole_CapabilityExchange-Protocol.h"; sourceTree = ""; }; + 7179016E2A960B4D000FBF19 /* XCTMessagingRole_AccessibilityNotificationReporting-Protocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "XCTMessagingRole_AccessibilityNotificationReporting-Protocol.h"; sourceTree = ""; }; + 7179016F2A960B4D000FBF19 /* XCTMessagingRole_ActivityReporting_Legacy-Protocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "XCTMessagingRole_ActivityReporting_Legacy-Protocol.h"; sourceTree = ""; }; + 717901702A960B4D000FBF19 /* XCTMessagingRole_ProcessMonitoring-Protocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "XCTMessagingRole_ProcessMonitoring-Protocol.h"; sourceTree = ""; }; + 717901712A960B4D000FBF19 /* XCTMessagingRole_SelfDiagnosisIssueReporting-Protocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "XCTMessagingRole_SelfDiagnosisIssueReporting-Protocol.h"; sourceTree = ""; }; + 717901722A960B4E000FBF19 /* XCTMessagingChannel_RunnerToIDE-Protocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "XCTMessagingChannel_RunnerToIDE-Protocol.h"; sourceTree = ""; }; + 717901732A960B4E000FBF19 /* XCTMessagingChannel_DaemonToRunner-Protocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "XCTMessagingChannel_DaemonToRunner-Protocol.h"; sourceTree = ""; }; + 717901742A960B4E000FBF19 /* _XCTMessaging_VoidProtocol-Protocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "_XCTMessaging_VoidProtocol-Protocol.h"; sourceTree = ""; }; + 717901752A960B4E000FBF19 /* XCTMessagingRole_UIApplicationStateUpdating-Protocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "XCTMessagingRole_UIApplicationStateUpdating-Protocol.h"; sourceTree = ""; }; + 717901762A960B4E000FBF19 /* XCTMessagingRole_EventSynthesis-Protocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "XCTMessagingRole_EventSynthesis-Protocol.h"; sourceTree = ""; }; + 717901772A960B4E000FBF19 /* XCTMessagingRole_UIRecordingControl-Protocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "XCTMessagingRole_UIRecordingControl-Protocol.h"; sourceTree = ""; }; + 717901782A960B4F000FBF19 /* XCTMessagingRole_MemoryTesting-Protocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "XCTMessagingRole_MemoryTesting-Protocol.h"; sourceTree = ""; }; + 717901792A960B4F000FBF19 /* XCTMessagingRole_UIAutomationProcess-Protocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "XCTMessagingRole_UIAutomationProcess-Protocol.h"; sourceTree = ""; }; + 7179017A2A960B4F000FBF19 /* XCTMessagingRole_ProtectedResourceAuthorization-Protocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "XCTMessagingRole_ProtectedResourceAuthorization-Protocol.h"; sourceTree = ""; }; + 7179017B2A960B4F000FBF19 /* XCTMessagingRole_PerformanceMeasurementReporting-Protocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "XCTMessagingRole_PerformanceMeasurementReporting-Protocol.h"; sourceTree = ""; }; + 7179017C2A960B4F000FBF19 /* XCTMessagingRole_TestExecution_Legacy-Protocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "XCTMessagingRole_TestExecution_Legacy-Protocol.h"; sourceTree = ""; }; + 7179017D2A960B4F000FBF19 /* XCTMessagingRole_UIAutomation-Protocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "XCTMessagingRole_UIAutomation-Protocol.h"; sourceTree = ""; }; + 7179017E2A960B4F000FBF19 /* XCTMessagingRole_TestReporting-Protocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "XCTMessagingRole_TestReporting-Protocol.h"; sourceTree = ""; }; + 7179017F2A960B50000FBF19 /* XCTMessagingRole_SiriAutomation-Protocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "XCTMessagingRole_SiriAutomation-Protocol.h"; sourceTree = ""; }; + 717901802A960B50000FBF19 /* XCTMessagingRole_ActivityReporting-Protocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "XCTMessagingRole_ActivityReporting-Protocol.h"; sourceTree = ""; }; + 717901812A960B50000FBF19 /* XCTMessagingRole_BundleRequesting-Protocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "XCTMessagingRole_BundleRequesting-Protocol.h"; sourceTree = ""; }; + 717901822A960B50000FBF19 /* XCTMessagingChannel_DaemonToIDE-Protocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "XCTMessagingChannel_DaemonToIDE-Protocol.h"; sourceTree = ""; }; + 717901832A960B50000FBF19 /* XCTMessagingRole_RunnerSessionInitiation-Protocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "XCTMessagingRole_RunnerSessionInitiation-Protocol.h"; sourceTree = ""; }; + 717901842A960B50000FBF19 /* XCTMessagingChannel_RunnerToUIProcess-Protocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "XCTMessagingChannel_RunnerToUIProcess-Protocol.h"; sourceTree = ""; }; + 717901852A960B50000FBF19 /* XCTMessagingRole_CrashReporting-Protocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "XCTMessagingRole_CrashReporting-Protocol.h"; sourceTree = ""; }; + 717901862A960B50000FBF19 /* XCTMessagingChannel_IDEToDaemon-Protocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "XCTMessagingChannel_IDEToDaemon-Protocol.h"; sourceTree = ""; }; + 717901872A960B50000FBF19 /* XCTMessagingRole_ForcePressureSupportQuerying-Protocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "XCTMessagingRole_ForcePressureSupportQuerying-Protocol.h"; sourceTree = ""; }; + 717901882A960B50000FBF19 /* XCTMessagingRole_PerformanceMeasurementReporting_Legacy-Protocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "XCTMessagingRole_PerformanceMeasurementReporting_Legacy-Protocol.h"; sourceTree = ""; }; + 717901892A960B50000FBF19 /* XCTMessagingRole_UIAutomationEventReporting-Protocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "XCTMessagingRole_UIAutomationEventReporting-Protocol.h"; sourceTree = ""; }; + 7179018A2A960B51000FBF19 /* XCTMessagingChannel_DaemonToIDE_All-Protocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "XCTMessagingChannel_DaemonToIDE_All-Protocol.h"; sourceTree = ""; }; + 7179018B2A960B51000FBF19 /* XCTMessagingChannel_IDEToRunner-Protocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "XCTMessagingChannel_IDEToRunner-Protocol.h"; sourceTree = ""; }; + 7179018C2A960B51000FBF19 /* XCTMessagingChannel_RunnerToDaemon-Protocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "XCTMessagingChannel_RunnerToDaemon-Protocol.h"; sourceTree = ""; }; + 7179018D2A960B51000FBF19 /* XCTMessagingRole_TestExecution-Protocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "XCTMessagingRole_TestExecution-Protocol.h"; sourceTree = ""; }; + 717901D12A963C07000FBF19 /* DTXConnection-XCTestAdditions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "DTXConnection-XCTestAdditions.h"; sourceTree = ""; }; + 717901D22A963E3E000FBF19 /* DTXProxyChannel-XCTestAdditions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "DTXProxyChannel-XCTestAdditions.h"; sourceTree = ""; }; + 718DC4CE2A9910B8003B5511 /* XCTCapabilitiesBuilder.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = XCTCapabilitiesBuilder.h; sourceTree = ""; }; + 718DC4D12A9910B8003B5511 /* XCTCapabilities.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = XCTCapabilities.h; sourceTree = ""; }; 71B9E0BB268C616200D40A91 /* Shimulator.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; path = Shimulator.xcodeproj; sourceTree = ""; }; 71C4D3172638555D00DD186B /* FBOToolOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBOToolOperation.m; sourceTree = ""; }; 71C4D3182638555D00DD186B /* FBOToolOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBOToolOperation.h; sourceTree = ""; }; @@ -708,6 +767,7 @@ 84E05F9D1F7144DD00668049 /* FBDeviceXCTestCommandsTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBDeviceXCTestCommandsTests.m; sourceTree = ""; }; 877123F21BDA797800530B1E /* video0.mp4 */ = {isa = PBXFileReference; lastKnownFileType = file; path = video0.mp4; sourceTree = ""; }; 8BD1AF46212DACDE001F65E1 /* FBiOSTargetSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBiOSTargetSet.h; sourceTree = ""; }; + A255670A27610C7E0052D060 /* FBProcessFetcherTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBProcessFetcherTests.m; sourceTree = ""; }; A2FD7CFD2739885200542291 /* FBSimulatorDapServerCommands.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBSimulatorDapServerCommands.m; sourceTree = ""; }; A2FD7D002739885200542291 /* FBSimulatorDapServerCommands.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBSimulatorDapServerCommands.h; sourceTree = ""; }; A2FD7D032739887200542291 /* FBDapServerCommands.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBDapServerCommands.h; sourceTree = ""; }; @@ -729,8 +789,6 @@ AA09736A24A38484003E4A40 /* FBSimulatorAccessibilityCommands.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBSimulatorAccessibilityCommands.m; sourceTree = ""; }; AA09736B24A38484003E4A40 /* FBSimulatorAccessibilityCommands.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBSimulatorAccessibilityCommands.h; sourceTree = ""; }; AA0CA38620643C6800347424 /* FBCrashLogCommands.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBCrashLogCommands.h; sourceTree = ""; }; - AA0F6F281CA3DCF700926518 /* FBWeakFrameworkLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBWeakFrameworkLoader.h; sourceTree = ""; }; - AA0F6F291CA3DCF700926518 /* FBWeakFrameworkLoader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBWeakFrameworkLoader.m; sourceTree = ""; }; AA111CCC1BBE7C5A0054AFDD /* CoreSimulatorDoubles.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CoreSimulatorDoubles.h; sourceTree = ""; }; AA111CCD1BBE7C5A0054AFDD /* CoreSimulatorDoubles.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CoreSimulatorDoubles.m; sourceTree = ""; }; AA1174B11CEA17DB00EB699E /* FBApplicationCommands.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBApplicationCommands.h; sourceTree = ""; }; @@ -765,7 +823,6 @@ AA2076A71F0B7541001F180C /* FBProcessTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBProcessTests.m; sourceTree = ""; }; AA2076AA1F0B7541001F180C /* FBiOSTargetConfigurationTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBiOSTargetConfigurationTests.m; sourceTree = ""; }; AA2076AB1F0B7541001F180C /* FBControlCoreLoggerTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBControlCoreLoggerTests.m; sourceTree = ""; }; - AA2076AC1F0B7541001F180C /* FBCrashLogInfoTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBCrashLogInfoTests.m; sourceTree = ""; }; AA2076B21F0B7541001F180C /* FBiOSTargetTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBiOSTargetTests.m; sourceTree = ""; }; AA2076CF1F0B76AF001F180C /* FBFileWriterTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBFileWriterTests.m; sourceTree = ""; }; AA2076D11F0B779B001F180C /* FBFileReaderTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBFileReaderTests.m; sourceTree = ""; }; @@ -944,6 +1001,8 @@ AA56EAEE1EEFCA340062C2BC /* libMaculator.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; path = libMaculator.dylib; sourceTree = ""; }; AA57804226C54B7100847769 /* FBProcess.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBProcess.m; sourceTree = ""; }; AA57AD5A1EFC238A00A5154D /* SimDeviceIO+Removed.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SimDeviceIO+Removed.h"; sourceTree = ""; }; + AA57ADB32785B0C600D35D24 /* FBDeviceDebugSymbolsCommands.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBDeviceDebugSymbolsCommands.h; sourceTree = ""; }; + AA57ADB62785B0C600D35D24 /* FBDeviceDebugSymbolsCommands.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBDeviceDebugSymbolsCommands.m; sourceTree = ""; }; AA58F88A1D95917D006F8D81 /* FBBundleDescriptor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBBundleDescriptor.h; sourceTree = ""; }; AA58F88B1D95917D006F8D81 /* FBBundleDescriptor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBBundleDescriptor.m; sourceTree = ""; }; AA58F88F1D959593006F8D81 /* FBCodesignProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBCodesignProvider.h; sourceTree = ""; }; @@ -986,10 +1045,10 @@ AA6A3B081CC0C96E00E016C4 /* FBCollectionOperations.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBCollectionOperations.m; sourceTree = ""; }; AA6A3B351CC1597000E016C4 /* FBSimulatorBootStrategy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBSimulatorBootStrategy.h; sourceTree = ""; }; AA6A3B361CC1597000E016C4 /* FBSimulatorBootStrategy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBSimulatorBootStrategy.m; sourceTree = ""; }; - AA6A3B391CC1597000E016C4 /* FBSimulatorTerminationStrategy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBSimulatorTerminationStrategy.h; sourceTree = ""; }; - AA6A3B3A1CC1597000E016C4 /* FBSimulatorTerminationStrategy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBSimulatorTerminationStrategy.m; sourceTree = ""; }; AA6B1DD11FC5FCFA009DDDAE /* FBDataBufferTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBDataBufferTests.m; sourceTree = ""; }; AA6C68A3267B89C100EB975D /* FBProcessIOTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBProcessIOTests.m; sourceTree = ""; }; + AA6F0CFB27D8ABFE00181EFC /* FBDeviceLifecycleCommands.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBDeviceLifecycleCommands.m; sourceTree = ""; }; + AA6F0CFE27D8ABFE00181EFC /* FBDeviceLifecycleCommands.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBDeviceLifecycleCommands.h; sourceTree = ""; }; AA6F22411C916A31009F5CE4 /* photo0.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = photo0.png; sourceTree = ""; }; AA6F22421C916A31009F5CE4 /* simulator_system.log */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = simulator_system.log; sourceTree = ""; }; AA6F22431C916A31009F5CE4 /* tree.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = tree.json; sourceTree = ""; }; @@ -1009,6 +1068,7 @@ AA758B4B20E3C0720064EC18 /* FBAMDeviceServiceManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBAMDeviceServiceManager.m; sourceTree = ""; }; AA7728AC1E5238A6008FCF7C /* FBFileWriter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBFileWriter.h; sourceTree = ""; }; AA7728AD1E5238A6008FCF7C /* FBFileWriter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBFileWriter.m; sourceTree = ""; }; + AA777B0027A9937E00E1481F /* FBControlCoreFrameworkLoaderTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBControlCoreFrameworkLoaderTests.m; sourceTree = ""; }; AA780712225B4A0700A6E4AF /* FBSimulatorSetTestCase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBSimulatorSetTestCase.h; sourceTree = ""; }; AA780713225B4A0700A6E4AF /* FBSimulatorSetTestCase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBSimulatorSetTestCase.m; sourceTree = ""; }; AA789C261F064A1000BC86BD /* SimDeviceLegacyClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SimDeviceLegacyClient.h; sourceTree = ""; }; @@ -1041,6 +1101,9 @@ AA861B701E5F920B0080C86B /* FBSimulatorLifecycleCommands.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBSimulatorLifecycleCommands.m; sourceTree = ""; }; AA8954691D5C7400006BD815 /* FBControlCoreFrameworkLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBControlCoreFrameworkLoader.h; sourceTree = ""; }; AA89546A1D5C7400006BD815 /* FBControlCoreFrameworkLoader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBControlCoreFrameworkLoader.m; sourceTree = ""; }; + AA89E5AE27D7AF3400ECD072 /* FBiOSTargetConstants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBiOSTargetConstants.h; sourceTree = ""; }; + AA89E5B127D7AF3400ECD072 /* FBiOSTargetConstants.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBiOSTargetConstants.m; sourceTree = ""; }; + AA89E5B427D7B08300ECD072 /* FBLifecycleCommands.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBLifecycleCommands.h; sourceTree = ""; }; AA8D347124D04BD0000FAC59 /* FBDiagnosticInformationCommands.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBDiagnosticInformationCommands.h; sourceTree = ""; }; AA8D347324D04C34000FAC59 /* FBDeviceDiagnosticInformationCommands.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBDeviceDiagnosticInformationCommands.m; sourceTree = ""; }; AA8D347424D04C35000FAC59 /* FBDeviceDiagnosticInformationCommands.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBDeviceDiagnosticInformationCommands.h; sourceTree = ""; }; @@ -1062,7 +1125,6 @@ AA9316DD248FB421004D17B3 /* FBAMRestorableDeviceManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBAMRestorableDeviceManager.h; sourceTree = ""; }; AA9316DE248FB421004D17B3 /* FBAMRestorableDevice.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBAMRestorableDevice.h; sourceTree = ""; }; AA9316DF248FB421004D17B3 /* FBAMRestorableDeviceManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBAMRestorableDeviceManager.m; sourceTree = ""; }; - AA9319B522B78E9F00C68F65 /* FBBinaryDescriptorTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBBinaryDescriptorTests.m; sourceTree = ""; }; AA9319B722B78FB800C68F65 /* FBBinaryDescriptorTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBBinaryDescriptorTests.m; sourceTree = ""; }; AA9485E22074B38C00716117 /* FBControlCoreLogger+OSLog.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "FBControlCoreLogger+OSLog.h"; sourceTree = ""; }; AA9485E32074B38C00716117 /* FBControlCoreLogger+OSLog.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "FBControlCoreLogger+OSLog.m"; sourceTree = ""; }; @@ -1093,6 +1155,7 @@ AAA02A4724A118AB0054F0DC /* FBDeviceCommands.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBDeviceCommands.h; sourceTree = ""; }; AAA1F9C21F1396FB006A4811 /* FBSimulatorLaunchCtlCommands.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBSimulatorLaunchCtlCommands.h; sourceTree = ""; }; AAA1F9C31F1396FB006A4811 /* FBSimulatorLaunchCtlCommands.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBSimulatorLaunchCtlCommands.m; sourceTree = ""; }; + AAA42D452796B0D900DED1D6 /* XCTestBootstrapTests.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = XCTestBootstrapTests.xcconfig; sourceTree = ""; }; AAA46E431C0CB92A009D6452 /* FBSimulatorControl.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = FBSimulatorControl.xcconfig; sourceTree = ""; }; AAA55F641D0088E800BC4824 /* FBControlCoreTests.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = FBControlCoreTests.xcconfig; sourceTree = ""; }; AAA5B80B24B37FBC0093DAEB /* FBDeviceStorage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBDeviceStorage.m; sourceTree = ""; }; @@ -1115,8 +1178,6 @@ AAAB14181F46060100CE5579 /* FBXcodeBuildOperationTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBXcodeBuildOperationTests.m; sourceTree = ""; }; AAABD8E01E450CF400C007C2 /* FBSurfaceImageGenerator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBSurfaceImageGenerator.m; sourceTree = ""; }; AAABD8E11E450CF400C007C2 /* FBSurfaceImageGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBSurfaceImageGenerator.h; sourceTree = ""; }; - AAB123801DB4B16900F20555 /* FBDispatchSourceNotifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBDispatchSourceNotifier.h; sourceTree = ""; }; - AAB123811DB4B16900F20555 /* FBDispatchSourceNotifier.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBDispatchSourceNotifier.m; sourceTree = ""; }; AAB1507320F5ED7600BB17A1 /* FBAMDefines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBAMDefines.h; sourceTree = ""; }; AAB475F320C80F7D00B37634 /* FBiOSTargetCommandForwarderTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBiOSTargetCommandForwarderTests.m; sourceTree = ""; }; AAB475F520C8217F00B37634 /* FBSimulatorCrashLogCommands.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBSimulatorCrashLogCommands.h; sourceTree = ""; }; @@ -1251,6 +1312,7 @@ AAFE1C111FD68A7D00ADDE66 /* FBSimulatorNotificationUpdateStrategy.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBSimulatorNotificationUpdateStrategy.m; sourceTree = ""; }; AAFE93B41CE4954500A50F76 /* FBSimulatorEraseStrategy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBSimulatorEraseStrategy.h; sourceTree = ""; }; AAFE93B51CE4954500A50F76 /* FBSimulatorEraseStrategy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBSimulatorEraseStrategy.m; sourceTree = ""; }; + B8E19B9927D0E33A0095241C /* Accelerate.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Accelerate.framework; path = System/Library/Frameworks/Accelerate.framework; sourceTree = SDKROOT; }; C0B32FC71E4E459700A48CF4 /* FBArchitecture.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBArchitecture.h; sourceTree = ""; }; C0B32FC81E4E459700A48CF4 /* FBArchitecture.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBArchitecture.m; sourceTree = ""; }; D75ACC69264BEF82009862C4 /* FBOToolDynamicLibs.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBOToolDynamicLibs.m; sourceTree = ""; }; @@ -1265,6 +1327,23 @@ D7C55B2F217E28D000A9BCB7 /* FBSimulatorMediaCommandsTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBSimulatorMediaCommandsTests.m; sourceTree = ""; }; D7E70C102440A2B40092422C /* FBAttachment.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBAttachment.h; sourceTree = ""; }; D7E70C112440A2B40092422C /* FBAttachment.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBAttachment.m; sourceTree = ""; }; + DB15123329E5C34C00A7C0A9 /* FBArchitectureProcessAdapterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FBArchitectureProcessAdapterTests.swift; sourceTree = ""; }; + DB15123729E5C54800A7C0A9 /* xctest */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.executable"; path = xctest; sourceTree = ""; }; + DB1B3C8629DD9D75003695C4 /* FBArchitectureProcessAdapter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBArchitectureProcessAdapter.h; sourceTree = ""; }; + DB1B3C8A29DD9F36003695C4 /* FBArchitectureProcessAdapter.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBArchitectureProcessAdapter.m; sourceTree = ""; }; + DB22F7052A8FBC7400695320 /* FBMacLaunchedApplication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBMacLaunchedApplication.h; sourceTree = ""; }; + DB22F7062A8FBC7400695320 /* FBMacLaunchedApplication.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBMacLaunchedApplication.m; sourceTree = ""; }; + DB523BF0297199A10005D7AE /* FBExceptionInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBExceptionInfo.h; sourceTree = ""; }; + DB523BF3297199A10005D7AE /* FBExceptionInfo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBExceptionInfo.m; sourceTree = ""; }; + DB5F4875281079AD000FC7C7 /* FBConcatedJsonParserTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FBConcatedJsonParserTests.swift; sourceTree = ""; }; + DB5F4877281079CC000FC7C7 /* FBConcatedJsonParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBConcatedJsonParser.m; sourceTree = ""; }; + DB5F4878281079CC000FC7C7 /* FBConcatedJsonParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBConcatedJsonParser.h; sourceTree = ""; }; + DB5F487B28114D84000FC7C7 /* FBCrashLogParser.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBCrashLogParser.h; sourceTree = ""; }; + DB5F487D28114E7B000FC7C7 /* FBCrashLogParser.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBCrashLogParser.m; sourceTree = ""; }; + DB5F487F28115683000FC7C7 /* FBCrashLogInfoTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FBCrashLogInfoTests.swift; sourceTree = ""; }; + DB5F4881281156C4000FC7C7 /* TestFixtures.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestFixtures.swift; sourceTree = ""; }; + DB5F488328115C5E000FC7C7 /* xctest-concated-json-crash.ips */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "xctest-concated-json-crash.ips"; sourceTree = ""; }; + DB6578002A978C72003C687B /* XCTIssue.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = XCTIssue.h; sourceTree = ""; }; EE12775C1C9338D700DE52A1 /* FBTestManagerAPIMediator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBTestManagerAPIMediator.h; sourceTree = ""; }; EE12775E1C9338D700DE52A1 /* FBTestManagerAPIMediator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBTestManagerAPIMediator.m; sourceTree = ""; }; EE2586EE1FB06D9C00E7526E /* FBMacDevice.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBMacDevice.m; sourceTree = ""; }; @@ -1315,7 +1394,6 @@ EE4F0DC01C91B85800608E89 /* DTXSharedMemoryTransport.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DTXSharedMemoryTransport.h; sourceTree = ""; }; EE4F0DC11C91B85800608E89 /* DTXSocketTransport.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DTXSocketTransport.h; sourceTree = ""; }; EE4F0DC21C91B85800608E89 /* DTXTransport.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DTXTransport.h; sourceTree = ""; }; - EE4F0DD31C91B85800608E89 /* CDStructures.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CDStructures.h; sourceTree = ""; }; EE4F0DD41C91B85800608E89 /* XCTestConfiguration.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = XCTestConfiguration.h; sourceTree = ""; }; EE4F0DD51C91B85800608E89 /* XCTestDriverInterface-Protocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "XCTestDriverInterface-Protocol.h"; sourceTree = ""; }; EE4F0DD61C91B85800608E89 /* XCTestManager_DaemonConnectionInterface-Protocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "XCTestManager_DaemonConnectionInterface-Protocol.h"; sourceTree = ""; }; @@ -1357,6 +1435,7 @@ buildActionMask = 0; files = ( AAB4AC1E1BB586930046F6A1 /* AVFoundation.framework in Frameworks */, + B8E19B9C27D0E33A0095241C /* Accelerate.framework in Frameworks */, AAC241261BB311690054570C /* ApplicationServices.framework in Frameworks */, E7A30F0476B173B900000000 /* Cocoa.framework in Frameworks */, AA3C18441D5DE47D00419EAA /* CoreImage.framework in Frameworks */, @@ -1506,23 +1585,24 @@ AAE3F7D024E3DFF50027BFB1 /* FBAccessibilityCommands.h */, AA1174B11CEA17DB00EB699E /* FBApplicationCommands.h */, AA0CA38620643C6800347424 /* FBCrashLogCommands.h */, + A2FD7D032739887200542291 /* FBDapServerCommands.h */, AA2E38E021E626B10065C800 /* FBDebuggerCommands.h */, AA685CD22550299200E2DD9D /* FBDeveloperDiskImageCommands.h */, AA8D347124D04BD0000FAC59 /* FBDiagnosticInformationCommands.h */, AA59F46424912730007C1875 /* FBEraseCommands.h */, - A2FD7D032739887200542291 /* FBDapServerCommands.h */, AA98266924E1348C006E05A9 /* FBFileCommands.h */, AA98266624E131CA006E05A9 /* FBFileContainer.h */, AAA8DE9A2508D59200964222 /* FBFileContainer.m */, AA6155DA224BB4D0007D1C22 /* FBInstrumentsCommands.h */, - A2FD7D072739891900542291 /* FBMemoryCommands.h */, - A2FD7D0927398B7900542291 /* FBNotificationCommands.h */, AA6155DC224BB60A007D1C22 /* FBInstrumentsCommands.m */, AA4424CA1F4C11A9006B5E5D /* FBiOSTargetCommandForwarder.h */, AA4424CB1F4C11A9006B5E5D /* FBiOSTargetCommandForwarder.m */, + AA89E5B427D7B08300ECD072 /* FBLifecycleCommands.h */, AA8D347724D04CCE000FAC59 /* FBLocationCommands.h */, AA805F7E1F0D0E0000AB31DE /* FBLogCommands.h */, AA2D494425DC3A2B007566C2 /* FBLogCommands.m */, + A2FD7D072739891900542291 /* FBMemoryCommands.h */, + A2FD7D0927398B7900542291 /* FBNotificationCommands.h */, 1F34A50B2512B604001A12F7 /* FBPowerCommands.h */, AA54EC7C25ED4C6200FAA59E /* FBProcessSpawnCommands.h */, AA56DBF926BAA96B001896F3 /* FBProcessSpawnCommands.m */, @@ -1601,8 +1681,10 @@ AA2076A51F0B7541001F180C /* Integration */ = { isa = PBXGroup; children = ( + AA777B0027A9937E00E1481F /* FBControlCoreFrameworkLoaderTests.m */, AA2076D11F0B779B001F180C /* FBFileReaderTests.m */, AA2076CF1F0B76AF001F180C /* FBFileWriterTests.m */, + A255670A27610C7E0052D060 /* FBProcessFetcherTests.m */, AA6C68A3267B89C100EB975D /* FBProcessIOTests.m */, AA274282204546F800CFAC3B /* FBProcessStreamTests.m */, AA2076A71F0B7541001F180C /* FBProcessTests.m */, @@ -1614,10 +1696,10 @@ isa = PBXGroup; children = ( EE87FA422008D906002716FE /* AXTraitsTest.m */, - AA9319B522B78E9F00C68F65 /* FBBinaryDescriptorTests.m */, + DB5F4875281079AD000FC7C7 /* FBConcatedJsonParserTests.swift */, AA2076AB1F0B7541001F180C /* FBControlCoreLoggerTests.m */, AA71A1161FA8E49D00BB10DA /* FBControlCoreRunLoopTests.m */, - AA2076AC1F0B7541001F180C /* FBCrashLogInfoTests.m */, + DB5F487F28115683000FC7C7 /* FBCrashLogInfoTests.swift */, AA6B1DD11FC5FCFA009DDDAE /* FBDataBufferTests.m */, AA11EDF8272C44410055D6D1 /* FBFileContainerTests.m */, AA758B4820E3BB0B0064EC18 /* FBFutureContextManagerTests.m */, @@ -1627,6 +1709,7 @@ AA2076B21F0B7541001F180C /* FBiOSTargetTests.m */, AA8F5E1C1F272AB900FAAC0F /* FBXcodeDirectoryTests.m */, AA9319B722B78FB800C68F65 /* FBBinaryDescriptorTests.m */, + DB15123329E5C34C00A7C0A9 /* FBArchitectureProcessAdapterTests.swift */, ); path = Unit; sourceTree = ""; @@ -1822,7 +1905,7 @@ AAEB58F11E2CC6F7005BC408 /* SimulatorApp */, AA791BA31C63668C00AE49EB /* SimulatorBridge */, AA2DDC221C283F40000689C6 /* SimulatorKit */, - EE4F0DD21C91B85800608E89 /* XCTest */, + EE4F0DD21C91B85800608E89 /* XCTestPrivate */, ); path = PrivateHeaders; sourceTree = ""; @@ -1848,6 +1931,8 @@ EE9E1E441D6CB2CC00860830 /* FBProcessLaunchConfiguration.h */, EE9E1E451D6CB2CC00860830 /* FBProcessLaunchConfiguration.m */, AAD99D1B25ED459A0078DAE4 /* FBProcessSpawnConfiguration.h */, + DB1B3C8629DD9D75003695C4 /* FBArchitectureProcessAdapter.h */, + DB1B3C8A29DD9F36003695C4 /* FBArchitectureProcessAdapter.m */, AAD99D1C25ED459A0078DAE4 /* FBProcessSpawnConfiguration.m */, D76F950B1F56D6700003D341 /* FBTestLaunchConfiguration.h */, D76F950C1F56D6700003D341 /* FBTestLaunchConfiguration.m */, @@ -1884,6 +1969,8 @@ children = ( AA682B2E1CEDC435009B6ECA /* FBiOSTarget.h */, AA2942801D00AB0800880984 /* FBiOSTarget.m */, + AA89E5AE27D7AF3400ECD072 /* FBiOSTargetConstants.h */, + AA89E5B127D7AF3400ECD072 /* FBiOSTargetConstants.m */, AAF9D3EA257E7D4100E6541D /* FBiOSTargetOperation.h */, AA970CC725836C7F0088B5CC /* FBiOSTargetOperation.m */, 8BD1AF46212DACDE001F65E1 /* FBiOSTargetSet.h */, @@ -1910,8 +1997,6 @@ AAFE1C111FD68A7D00ADDE66 /* FBSimulatorNotificationUpdateStrategy.m */, AAF7B0D71DDB1CD60079ED11 /* FBSimulatorShutdownStrategy.h */, AAF7B0D81DDB1CD60079ED11 /* FBSimulatorShutdownStrategy.m */, - AA6A3B391CC1597000E016C4 /* FBSimulatorTerminationStrategy.h */, - AA6A3B3A1CC1597000E016C4 /* FBSimulatorTerminationStrategy.m */, ); path = Strategies; sourceTree = ""; @@ -2165,6 +2250,7 @@ AAF2CCE42524951000C68D39 /* FBManagedConfigClient.m */, AA2F41F0252481C1002279A2 /* FBSpringboardServicesClient.h */, AA2F41F1252481C1002279A2 /* FBSpringboardServicesClient.m */, + 1889EACA2AEC7B760097FE08 /* FBAppleDevicectlCommandExecutor.swift */, ); path = Management; sourceTree = ""; @@ -2178,6 +2264,7 @@ AAC8B2501CEC51520034A865 /* FBDeviceControlFrameworkLoader.m */, AAE119642293EFB000173417 /* FBDeviceLinkClient.h */, AAE119652293EFB000173417 /* FBDeviceLinkClient.m */, + 18DC3ADE2AFC60C600F32F27 /* FileManager+TemporaryFile.swift */, ); path = Utility; sourceTree = ""; @@ -2195,6 +2282,8 @@ AABA7CF720BB45B900C1E73A /* FBDeviceCrashLogCommands.m */, AAC6084F21DFB12400280C96 /* FBDeviceDebuggerCommands.h */, AAC6085021DFB12500280C96 /* FBDeviceDebuggerCommands.m */, + AA57ADB32785B0C600D35D24 /* FBDeviceDebugSymbolsCommands.h */, + AA57ADB62785B0C600D35D24 /* FBDeviceDebugSymbolsCommands.m */, AA685CDD255029B000E2DD9D /* FBDeviceDeveloperDiskImageCommands.h */, AA685CDE255029B000E2DD9D /* FBDeviceDeveloperDiskImageCommands.m */, AA8D347424D04C35000FAC59 /* FBDeviceDiagnosticInformationCommands.h */, @@ -2203,6 +2292,8 @@ AAA8DEA02508D5E400964222 /* FBDeviceEraseCommands.m */, AABA7CF420BB450B00C1E73A /* FBDeviceFileCommands.h */, AABA7CF320BB450B00C1E73A /* FBDeviceFileCommands.m */, + AA6F0CFE27D8ABFE00181EFC /* FBDeviceLifecycleCommands.h */, + AA6F0CFB27D8ABFE00181EFC /* FBDeviceLifecycleCommands.m */, AA8D347E24D04DAE000FAC59 /* FBDeviceLocationCommands.h */, AA8D347D24D04DAE000FAC59 /* FBDeviceLocationCommands.m */, 2FB8110E1FB5C97400A848FB /* FBDeviceLogCommands.h */, @@ -2228,6 +2319,8 @@ AAE5A0831EDF90DB00A1A811 /* Reporters */ = { isa = PBXGroup; children = ( + DB523BF0297199A10005D7AE /* FBExceptionInfo.h */, + DB523BF3297199A10005D7AE /* FBExceptionInfo.m */, 2F8294C71FBC571A0011E722 /* FBJSONTestReporter.h */, AAE5A0891EDF919700A1A811 /* FBJSONTestReporter.m */, 2F8294C91FBC571A0011E722 /* FBLogicReporterAdapter.h */, @@ -2258,11 +2351,14 @@ isa = PBXGroup; children = ( AA7FDA0C1C981231009F7828 /* agent_custom_set.crash */, + DB15123729E5C54800A7C0A9 /* xctest */, AA7FDA0D1C981231009F7828 /* app_custom_set.crash */, AA7FDA0E1C981231009F7828 /* app_default_set.crash */, AA7FDA0F1C981231009F7828 /* assetsd_custom_set.crash */, + DB5F488328115C5E000FC7C7 /* xctest-concated-json-crash.ips */, AAEA3A901C90B5E4004F8409 /* FBControlCoreFixtures.h */, AAEA3A911C90B5E4004F8409 /* FBControlCoreFixtures.m */, + DB5F4881281156C4000FC7C7 /* TestFixtures.swift */, AA6F22411C916A31009F5CE4 /* photo0.png */, AA6F22421C916A31009F5CE4 /* simulator_system.log */, AA6F22431C916A31009F5CE4 /* tree.json */, @@ -2306,6 +2402,8 @@ children = ( AAF9D3B8257E76D000E6541D /* FBCrashLog.h */, AAF9D3BC257E76D000E6541D /* FBCrashLog.m */, + DB5F487B28114D84000FC7C7 /* FBCrashLogParser.h */, + DB5F487D28114E7B000FC7C7 /* FBCrashLogParser.m */, AAF9D3BB257E76D000E6541D /* FBCrashLogNotifier.h */, AAF9D3B9257E76D000E6541D /* FBCrashLogNotifier.m */, ); @@ -2315,6 +2413,7 @@ B401C97968022A5500000000 /* Frameworks */ = { isa = PBXGroup; children = ( + B8E19B9927D0E33A0095241C /* Accelerate.framework */, AAF1D44424AF777400150547 /* VideoToolbox.framework */, AAC241231BB3113F0054570C /* AppKit.framework */, AAC241251BB311690054570C /* ApplicationServices.framework */, @@ -2406,6 +2505,8 @@ EE2586F61FB0727000E7526E /* MacStrategies */ = { isa = PBXGroup; children = ( + DB22F7052A8FBC7400695320 /* FBMacLaunchedApplication.h */, + DB22F7062A8FBC7400695320 /* FBMacLaunchedApplication.m */, EE2586EF1FB06D9C00E7526E /* FBMacDevice.h */, EE2586EE1FB06D9C00E7526E /* FBMacDevice.m */, ); @@ -2431,9 +2532,10 @@ EE4F0D3D1C91B7DB00608E89 /* XCTestBootstrapTests */ = { isa = PBXGroup; children = ( + EE4F0D971C91B83300608E89 /* XCTestBootstrapTests-Info.plist */, + AAA42D452796B0D900DED1D6 /* XCTestBootstrapTests.xcconfig */, EEF4497A1CE0A22200300C9F /* Fixtures */, AAEC23BC1D5E345D0083CAB7 /* Tests */, - EE4F0D971C91B83300608E89 /* XCTestBootstrapTests-Info.plist */, ); path = XCTestBootstrapTests; sourceTree = ""; @@ -2519,21 +2621,63 @@ path = DTXConnectionServices; sourceTree = ""; }; - EE4F0DD21C91B85800608E89 /* XCTest */ = { + EE4F0DD21C91B85800608E89 /* XCTestPrivate */ = { isa = PBXGroup; children = ( + 718DC4D12A9910B8003B5511 /* XCTCapabilities.h */, + 718DC4CE2A9910B8003B5511 /* XCTCapabilitiesBuilder.h */, + 717901742A960B4E000FBF19 /* _XCTMessaging_VoidProtocol-Protocol.h */, + 7179016A2A960B4C000FBF19 /* XCTMessagingChannel_DaemonRecorderToIDE-Protocol.h */, + 7179018A2A960B51000FBF19 /* XCTMessagingChannel_DaemonToIDE_All-Protocol.h */, + 717901822A960B50000FBF19 /* XCTMessagingChannel_DaemonToIDE-Protocol.h */, + 717901732A960B4E000FBF19 /* XCTMessagingChannel_DaemonToRunner-Protocol.h */, + 717901862A960B50000FBF19 /* XCTMessagingChannel_IDEToDaemon-Protocol.h */, + 7179018B2A960B51000FBF19 /* XCTMessagingChannel_IDEToRunner-Protocol.h */, + 7179018C2A960B51000FBF19 /* XCTMessagingChannel_RunnerToDaemon-Protocol.h */, + 717901722A960B4E000FBF19 /* XCTMessagingChannel_RunnerToIDE-Protocol.h */, + 717901842A960B50000FBF19 /* XCTMessagingChannel_RunnerToUIProcess-Protocol.h */, + 7179016E2A960B4D000FBF19 /* XCTMessagingRole_AccessibilityNotificationReporting-Protocol.h */, + 7179016F2A960B4D000FBF19 /* XCTMessagingRole_ActivityReporting_Legacy-Protocol.h */, + 717901802A960B50000FBF19 /* XCTMessagingRole_ActivityReporting-Protocol.h */, + 717901812A960B50000FBF19 /* XCTMessagingRole_BundleRequesting-Protocol.h */, + 7179016D2A960B4D000FBF19 /* XCTMessagingRole_CapabilityExchange-Protocol.h */, + 717901682A960B4C000FBF19 /* XCTMessagingRole_ControlSessionInitiation-Protocol.h */, + 717901852A960B50000FBF19 /* XCTMessagingRole_CrashReporting-Protocol.h */, + 7179016B2A960B4C000FBF19 /* XCTMessagingRole_DebugLogging-Protocol.h */, + 7179016C2A960B4C000FBF19 /* XCTMessagingRole_DiagnosticsCollection-Protocol.h */, + 717901762A960B4E000FBF19 /* XCTMessagingRole_EventSynthesis-Protocol.h */, + 717901872A960B50000FBF19 /* XCTMessagingRole_ForcePressureSupportQuerying-Protocol.h */, + 717901782A960B4F000FBF19 /* XCTMessagingRole_MemoryTesting-Protocol.h */, + 717901882A960B50000FBF19 /* XCTMessagingRole_PerformanceMeasurementReporting_Legacy-Protocol.h */, + 7179017B2A960B4F000FBF19 /* XCTMessagingRole_PerformanceMeasurementReporting-Protocol.h */, + 717901702A960B4D000FBF19 /* XCTMessagingRole_ProcessMonitoring-Protocol.h */, + 7179017A2A960B4F000FBF19 /* XCTMessagingRole_ProtectedResourceAuthorization-Protocol.h */, + 717901832A960B50000FBF19 /* XCTMessagingRole_RunnerSessionInitiation-Protocol.h */, + 717901712A960B4D000FBF19 /* XCTMessagingRole_SelfDiagnosisIssueReporting-Protocol.h */, + 7179017F2A960B50000FBF19 /* XCTMessagingRole_SiriAutomation-Protocol.h */, + 7179017C2A960B4F000FBF19 /* XCTMessagingRole_TestExecution_Legacy-Protocol.h */, + 7179018D2A960B51000FBF19 /* XCTMessagingRole_TestExecution-Protocol.h */, + 717901692A960B4C000FBF19 /* XCTMessagingRole_TestReporting_Legacy-Protocol.h */, + 7179017E2A960B4F000FBF19 /* XCTMessagingRole_TestReporting-Protocol.h */, + 717901752A960B4E000FBF19 /* XCTMessagingRole_UIApplicationStateUpdating-Protocol.h */, + 7179017D2A960B4F000FBF19 /* XCTMessagingRole_UIAutomation-Protocol.h */, + 717901892A960B50000FBF19 /* XCTMessagingRole_UIAutomationEventReporting-Protocol.h */, + 717901792A960B4F000FBF19 /* XCTMessagingRole_UIAutomationProcess-Protocol.h */, + 717901772A960B4E000FBF19 /* XCTMessagingRole_UIRecordingControl-Protocol.h */, 30DF57E5266E3C6F00EC9015 /* XCTTestIdentifier.h */, 30DF57E6266E3C6F00EC9015 /* XCTTestIdentifierSet.h */, 30DF57E7266E3C6F00EC9015 /* XCTTestIdentifierSetBuilder.h */, - EE4F0DD31C91B85800608E89 /* CDStructures.h */, EE4F0DD41C91B85800608E89 /* XCTestConfiguration.h */, EE4F0DD51C91B85800608E89 /* XCTestDriverInterface-Protocol.h */, EE4F0DD61C91B85800608E89 /* XCTestManager_DaemonConnectionInterface-Protocol.h */, EE4F0DD71C91B85800608E89 /* XCTestManager_IDEInterface-Protocol.h */, EE4F0DD81C91B85800608E89 /* XCTestManager_ManagerInterface-Protocol.h */, EE4F0DD91C91B85800608E89 /* XCTestManager_TestsInterface-Protocol.h */, + 717901D12A963C07000FBF19 /* DTXConnection-XCTestAdditions.h */, + 717901D22A963E3E000FBF19 /* DTXProxyChannel-XCTestAdditions.h */, + DB6578002A978C72003C687B /* XCTIssue.h */, ); - path = XCTest; + path = XCTestPrivate; sourceTree = ""; }; EE87FA3D2008C04C002716FE /* AXRuntime */ = { @@ -2609,6 +2753,8 @@ EEBD604A1C9062E900298A07 /* Utility */ = { isa = PBXGroup; children = ( + DB5F4878281079CC000FC7C7 /* FBConcatedJsonParser.h */, + DB5F4877281079CC000FC7C7 /* FBConcatedJsonParser.m */, AADC72EF2012BF7A001060E5 /* FBAccessibilityTraits.h */, AADC72EE2012BF7A001060E5 /* FBAccessibilityTraits.m */, C0B32FC71E4E459700A48CF4 /* FBArchitecture.h */, @@ -2639,8 +2785,6 @@ AA4A7E301DD9F525001F9D8E /* FBDataConsumer.m */, AA685CB02550252100E2DD9D /* FBDeveloperDiskImage.h */, AA685CB12550252100E2DD9D /* FBDeveloperDiskImage.m */, - AAB123801DB4B16900F20555 /* FBDispatchSourceNotifier.h */, - AAB123811DB4B16900F20555 /* FBDispatchSourceNotifier.m */, AA4A7E2B1DD9F4EB001F9D8E /* FBFileReader.h */, AA4A7E2C1DD9F4EB001F9D8E /* FBFileReader.m */, AA7728AC1E5238A6008FCF7C /* FBFileWriter.h */, @@ -2665,8 +2809,6 @@ EE2EC7AB1CAC3F97009A7BB1 /* FBWeakFramework.m */, EE2EC7AE1CAC5119009A7BB1 /* FBWeakFramework+ApplePrivateFrameworks.h */, EE2EC7AF1CAC5119009A7BB1 /* FBWeakFramework+ApplePrivateFrameworks.m */, - AA0F6F281CA3DCF700926518 /* FBWeakFrameworkLoader.h */, - AA0F6F291CA3DCF700926518 /* FBWeakFrameworkLoader.m */, 7352B4D81F44BE4100B6D0EA /* FBXcodeConfiguration.h */, 7352B4D91F44BE4100B6D0EA /* FBXcodeConfiguration.m */, AA8F5E181F2727BF00FAAC0F /* FBXcodeDirectory.h */, @@ -2699,6 +2841,7 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( + AA57ADB72785B0C600D35D24 /* FBDeviceDebugSymbolsCommands.h in Headers */, AA682B201CECD49B009B6ECA /* FBAMDevice.h in Headers */, AAC6086621E344EF00280C96 /* FBDeviceDebugServer.h in Headers */, AABD72AC1E64A957004D6EBE /* FBDeviceXCTestCommands.h in Headers */, @@ -2726,6 +2869,7 @@ AA9DB39B24DA9C1F00960765 /* FBDeviceRecoveryCommands.h in Headers */, AAC8B22E1CEC51120034A865 /* FBDeviceControl.h in Headers */, AA280F4D1E714779006BB9E0 /* FBDeviceVideo.h in Headers */, + AA6F0D0027D8ABFE00181EFC /* FBDeviceLifecycleCommands.h in Headers */, AAC8B2571CEC51520034A865 /* FBDeviceControlError.h in Headers */, AAA8DE982508D57B00964222 /* FBDeviceProvisioningProfileCommands.h in Headers */, AAF2CCE52524951000C68D39 /* FBManagedConfigClient.h in Headers */, @@ -2748,7 +2892,6 @@ buildActionMask = 2147483647; files = ( AA9517971C15F54600A89CAD /* FBCoreSimulatorNotifier.h in Headers */, - AA6A3B431CC1597000E016C4 /* FBSimulatorTerminationStrategy.h in Headers */, AA15688C1F0EDBDF000743D5 /* FBSimulatorLaunchedApplication.h in Headers */, AAA1F9C41F1396FB006A4811 /* FBSimulatorLaunchCtlCommands.h in Headers */, AA44AF681E792F7500185844 /* FBSimulatorVideoStream.h in Headers */, @@ -2810,6 +2953,7 @@ buildActionMask = 2147483647; files = ( EE4F0D901C91B82700608E89 /* XCTestBootstrap.h in Headers */, + DB22F7072A8FBC7400695320 /* FBMacLaunchedApplication.h in Headers */, AA1F2C8A1CEA4176003E0BDE /* XCTestBootstrapFrameworkLoader.h in Headers */, EE48229D1FBD91C500AAA56E /* FBManagedTestRunStrategy.h in Headers */, AA7414F01CE3102F00C9641D /* FBTestBundleConnection.h in Headers */, @@ -2831,6 +2975,7 @@ EE1277621C9338D700DE52A1 /* FBTestManagerAPIMediator.h in Headers */, AA12D5441CE1086300CCD944 /* FBTestReporterAdapter.h in Headers */, 842A2B731F6AC89C00063EB1 /* FBActivityRecord.h in Headers */, + DB523BF4297199A10005D7AE /* FBExceptionInfo.h in Headers */, D7E70C122440A2B40092422C /* FBAttachment.h in Headers */, AAFD455925E54161001407CC /* FBTestConfiguration.h in Headers */, D75ACC6C264BEF82009862C4 /* FBOToolDynamicLibs.h in Headers */, @@ -2850,6 +2995,7 @@ AA84EFFE1C9FE162000CDA41 /* NSPredicate+FBControlCore.h in Headers */, AA90708E223AC97800805706 /* FBInstrumentsConfiguration.h in Headers */, EE2EC7B01CAC5119009A7BB1 /* FBWeakFramework+ApplePrivateFrameworks.h in Headers */, + DB5F487C28114D84000FC7C7 /* FBCrashLogParser.h in Headers */, AAF2FA6122396D4D00F1185C /* FBInstrumentsOperation.h in Headers */, AAF9D3C1257E76D000E6541D /* FBCrashLogNotifier.h in Headers */, AADC72F12012BF7A001060E5 /* FBAccessibilityTraits.h in Headers */, @@ -2886,7 +3032,9 @@ AA4D30741E799C1900A9FBD0 /* FBVideoStreamCommands.h in Headers */, AAD99D1D25ED459A0078DAE4 /* FBProcessSpawnConfiguration.h in Headers */, AA59F46524912730007C1875 /* FBEraseCommands.h in Headers */, + AA89E5B227D7AF3400ECD072 /* FBiOSTargetConstants.h in Headers */, AACB5E5A25E6672F00EC1FBD /* FBXCTraceRecordCommands.h in Headers */, + DB5F487A281079CC000FC7C7 /* FBConcatedJsonParser.h in Headers */, AA23F1D322424D9B00F504CC /* FBArchiveOperations.h in Headers */, AA1174B21CEA17DB00EB699E /* FBApplicationCommands.h in Headers */, EEBD60621C9062E900298A07 /* FBControlCore.h in Headers */, @@ -2898,6 +3046,7 @@ AA19D7D61F14BCED00E436CD /* FBInstalledApplication.h in Headers */, AA8F5E1A1F2727BF00FAAC0F /* FBXcodeDirectory.h in Headers */, EE87FA402008C088002716FE /* AXTraits.h in Headers */, + AA89E5B527D7B08300ECD072 /* FBLifecycleCommands.h in Headers */, AA0080D71DB4CCFD009A25CB /* FBProcessTerminationStrategy.h in Headers */, AA6155DB224BB53F007D1C22 /* FBInstrumentsCommands.h in Headers */, 8BD1AF4B212DB04E001F65E1 /* FBiOSTargetSet.h in Headers */, @@ -2909,7 +3058,6 @@ AA08487B1F3F499800A4BA60 /* FBFuture.h in Headers */, AA14B5571DF73EFF00085855 /* FBVideoRecordingCommands.h in Headers */, AAF026F01F25ED1A0091FDAB /* FBSocketServer.h in Headers */, - AA0F6F2A1CA3DCF700926518 /* FBWeakFrameworkLoader.h in Headers */, AA5D012F2003F38B005FF117 /* FBProcessStream.h in Headers */, 73E0A9741F4F361800A216AD /* FBBundleDescriptor+Application.h in Headers */, AAE93BDB22A7E503001FB8CC /* FBProcessIO.h in Headers */, @@ -2926,11 +3074,11 @@ D76F950D1F56D6700003D341 /* FBTestLaunchConfiguration.h in Headers */, AA2B266326821F1200EF31AA /* FBVideoFileWriter.h in Headers */, D76F95091F56D65C0003D341 /* FBXCTestCommands.h in Headers */, - AAB123821DB4B16900F20555 /* FBDispatchSourceNotifier.h in Headers */, D76C2AEE1F13F61E000EF13D /* FBEventReporterSubject.h in Headers */, AA685CB22550252100E2DD9D /* FBDeveloperDiskImage.h in Headers */, A2FD7D082739891900542291 /* FBMemoryCommands.h in Headers */, AA7728AE1E5238A6008FCF7C /* FBFileWriter.h in Headers */, + DB1B3C8929DD9F1F003695C4 /* FBArchitectureProcessAdapter.h in Headers */, AA58F8921D959593006F8D81 /* FBCodesignProvider.h in Headers */, 1F34A50C2512B604001A12F7 /* FBPowerCommands.h in Headers */, 1C0AAAB5254B646000001D3C /* FBXCTestShimConfiguration.h in Headers */, @@ -3107,7 +3255,7 @@ isa = PBXProject; attributes = { CLASSPREFIX = FB; - LastUpgradeCheck = 1020; + LastUpgradeCheck = 1320; ORGANIZATIONNAME = Facebook; TargetAttributes = { AA819DB11B9FB40D002F58CA = { @@ -3115,6 +3263,7 @@ }; AAC8B22A1CEC51120034A865 = { CreatedOnToolsVersion = 7.3.1; + LastSwiftMigration = 1500; }; AAC8B2331CEC51120034A865 = { CreatedOnToolsVersion = 7.3.1; @@ -3130,6 +3279,7 @@ }; EEBD60161C90628F00298A07 = { CreatedOnToolsVersion = 7.2.1; + LastSwiftMigration = 1330; }; }; }; @@ -3185,7 +3335,6 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - AA017F581BD7787300F45E9D /* libShimulator.dylib in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -3193,7 +3342,6 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 1F7596B31DFF6B40006B9053 /* libShimulator.dylib in Resources */, AA19D6FF1D61AFE300229B59 /* iOSUnitTestFixture.xctest in Resources */, 877123F31BDA797800530B1E /* video0.mp4 in Resources */, AAD305201BD4D5B10047376E /* photo1.png in Resources */, @@ -3206,7 +3354,6 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 0593EA101E371E5800EBD7CB /* libShimulator.dylib in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -3221,8 +3368,6 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - AA56EAF11EEFCB1D0062C2BC /* libShimulator.dylib in Resources */, - AA56EAF01EEFCA400062C2BC /* libMaculator.dylib in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -3250,9 +3395,11 @@ files = ( AA7FDA131C981231009F7828 /* assetsd_custom_set.crash in Resources */, AA7FDA121C981231009F7828 /* app_default_set.crash in Resources */, + DB15123829E5C54800A7C0A9 /* xctest in Resources */, AA6F22451C916A31009F5CE4 /* simulator_system.log in Resources */, AA7FDA101C981231009F7828 /* agent_custom_set.crash in Resources */, AA6F22441C916A31009F5CE4 /* photo0.png in Resources */, + DB5F488428115C5E000FC7C7 /* xctest-concated-json-crash.ips in Resources */, AA6F22461C916A31009F5CE4 /* tree.json in Resources */, AA7FDA111C981231009F7828 /* app_custom_set.crash in Resources */, ); @@ -3278,7 +3425,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "set -exu\nfunction build_shim() {\n local shim_to_build=$1 \n local shim_destination=$2 \n local build_log_mirror=$TEMP_DIR/$shim_to_build-build.log\n\n xcodebuild -project Shims/Shimulator/Shimulator.xcodeproj -scheme $shim_to_build build | tee $build_log_mirror\n \n local build_out_file=$(grep \"SHIM_DYLIB_PATH\" $build_log_mirror | cut -d \"=\" -f2-)\n\n echo cp $build_out_file $shim_destination/.\n cp $build_out_file $shim_destination/.\n}\n\n# SRCROOT refers to FBSimulatorControl project\nbuild_shim Shimulator $SRCROOT/Shims/Binaries\nif codesign -dvvv $SRCROOT/Shims/Binaries/libShimulator.dylib; then\n echo Shimulator was signed\nelse\n echo Shimulator was not signed, but it should have been\n exit 1\nfi\n\nbuild_shim Maculator $SRCROOT/Shims/Binaries\nif codesign -dvvv $SRCROOT/Shims/Binaries/libMaculator.dylib; then\n echo Maculator was signed, but it should not have been\n exit 1\nelse\n echo Maculator was not signed\nfi\n"; + shellScript = "set -exu\nfunction build_shim() {\n local shim_to_build=$1 \n local shim_destination=$2 \n local build_log_mirror=$TEMP_DIR/$shim_to_build-build.log\n\n xcodebuild -project Shims/Shimulator/Shimulator.xcodeproj -scheme $shim_to_build build | tee $build_log_mirror\n \n local build_out_file=$(grep \"SHIM_DYLIB_PATH\" $build_log_mirror | cut -d \"=\" -f2-)\n\n echo cp $build_out_file $shim_destination/.\n cp $build_out_file $shim_destination/.\n}\n\n# SRCROOT refers to FBSimulatorControl project\nbuild_shim Shimulator $SRCROOT/Shims/Binaries\nif codesign -dvvv $SRCROOT/Shims/Binaries/libShimulator.dylib; then\n echo Shimulator was signed\nelse\n echo Shimulator was not signed, but it should have been\n exit 1\nfi\n\nbuild_shim Maculator $SRCROOT/Shims/Binaries\nif codesign -dvvv $SRCROOT/Shims/Binaries/libMaculator.dylib; then\n echo Maculator was signed\nelse\n echo Maculator was not signed, but it should have been\n exit 1\nfi\n"; showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ @@ -3288,7 +3435,6 @@ isa = PBXSourcesBuildPhase; buildActionMask = 0; files = ( - AA6A3B441CC1597000E016C4 /* FBSimulatorTerminationStrategy.m in Sources */, AA3EA8541F31B20D003FBDC1 /* FBSimulatorFileCommands.m in Sources */, AAB475F820C8217F00B37634 /* FBSimulatorCrashLogCommands.m in Sources */, AAE42AA91D2D77D800DCD0EA /* FBSimulatorBridge.m in Sources */, @@ -3376,14 +3522,17 @@ AAC8B2581CEC51520034A865 /* FBDeviceControlError.m in Sources */, AABA7CF520BB450B00C1E73A /* FBDeviceFileCommands.m in Sources */, AAE248031DF8978700E0949D /* FBDeviceVideoRecordingCommands.m in Sources */, + AA57ADB82785B0C600D35D24 /* FBDeviceDebugSymbolsCommands.m in Sources */, AABD72AD1E64A957004D6EBE /* FBDeviceXCTestCommands.m in Sources */, AA682B1B1CEC9E8B009B6ECA /* FBDeviceSet.m in Sources */, AA3E44411F14AE2C00F333D2 /* FBDeviceApplicationCommands.m in Sources */, + 18DC3ADF2AFC60C600F32F27 /* FileManager+TemporaryFile.swift in Sources */, AAC8B2521CEC51520034A865 /* FBDevice.m in Sources */, AAD4B12024892F350021487B /* FBAMDeviceManager.m in Sources */, AA9316E3248FB421004D17B3 /* FBAMRestorableDeviceManager.m in Sources */, AAC6086521E344EF00280C96 /* FBDeviceDebugServer.m in Sources */, AA4D30711E79983700A9FBD0 /* FBDeviceVideoStream.m in Sources */, + AA6F0CFF27D8ABFE00181EFC /* FBDeviceLifecycleCommands.m in Sources */, AAA8DEA22508D5E400964222 /* FBDeviceEraseCommands.m in Sources */, AA280F4E1E714779006BB9E0 /* FBDeviceVideo.m in Sources */, AAD4B12424892FC30021487B /* FBDeviceManager.m in Sources */, @@ -3404,6 +3553,7 @@ AAC6085221DFB12500280C96 /* FBDeviceDebuggerCommands.m in Sources */, AAA5B80D24B37FBD0093DAEB /* FBDeviceStorage.m in Sources */, AAA8DE952508D4A100964222 /* FBDeviceCommands.m in Sources */, + 1889EACB2AEC7B760097FE08 /* FBAppleDevicectlCommandExecutor.swift in Sources */, 2FB811111FB5C97400A848FB /* FBDeviceLogCommands.m in Sources */, AABD19A61FFD1EE50043771C /* FBDeviceScreenshotCommands.m in Sources */, AA2F41F3252481C1002279A2 /* FBSpringboardServicesClient.m in Sources */, @@ -3446,10 +3596,12 @@ D75ACC6B264BEF82009862C4 /* FBOToolDynamicLibs.m in Sources */, AA12D5451CE1086300CCD944 /* FBTestReporterAdapter.m in Sources */, 1C5091E924EDB8F600FAB67E /* FBXCTestResultBundleParser.m in Sources */, + DB523BF5297199A10005D7AE /* FBExceptionInfo.m in Sources */, AAE5A0821EDF8C9C00A1A811 /* FBXCTestLogger.m in Sources */, AA6062F31EE4B59900E2EFEE /* FBLogicTestRunStrategy.m in Sources */, D7E70C132440A2B40092422C /* FBAttachment.m in Sources */, EE2586F01FB06D9C00E7526E /* FBMacDevice.m in Sources */, + DB22F7082A8FBC7400695320 /* FBMacLaunchedApplication.m in Sources */, AAFD455725E54161001407CC /* FBTestConfiguration.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -3479,6 +3631,7 @@ AABCA13C222A7C360015DBAB /* FBDataBuffer.m in Sources */, 7352B4DB1F44BE4100B6D0EA /* FBXcodeConfiguration.m in Sources */, AA34F3D020B72B3C0068420F /* FBCrashLogStore.m in Sources */, + AA89E5B327D7AF3400ECD072 /* FBiOSTargetConstants.m in Sources */, AABBF3241DAC110000E2B6AF /* FBProcessBuilder.m in Sources */, AA4424CD1F4C11A9006B5E5D /* FBiOSTargetCommandForwarder.m in Sources */, AA685CB32550252100E2DD9D /* FBDeveloperDiskImage.m in Sources */, @@ -3486,7 +3639,6 @@ AA4AF523224A9461008DDDC0 /* FBFuture+Sync.m in Sources */, AAD99D1E25ED459A0078DAE4 /* FBProcessSpawnConfiguration.m in Sources */, AA58F88D1D95917D006F8D81 /* FBBundleDescriptor.m in Sources */, - AAB123831DB4B16900F20555 /* FBDispatchSourceNotifier.m in Sources */, AA19D7D51F14BCED00E436CD /* FBInstalledApplication.m in Sources */, AAF9D3C2257E76D000E6541D /* FBCrashLog.m in Sources */, EEBD607F1C9062E900298A07 /* FBControlCoreError.m in Sources */, @@ -3506,6 +3658,7 @@ AACB5E7525E6677A00EC1FBD /* FBXCTraceOperation.m in Sources */, AACC503D1EAA230F0034A987 /* FBVideoStreamConfiguration.m in Sources */, AA6F98EC1D2B9C8E00464B0F /* FBBinaryDescriptor.m in Sources */, + DB5F4879281079CC000FC7C7 /* FBConcatedJsonParser.m in Sources */, AA70F5272701F1AA0023A36A /* FBTemporaryDirectory.m in Sources */, EE2EC7AD1CAC3F97009A7BB1 /* FBWeakFramework.m in Sources */, AA56DBFC26BAA96B001896F3 /* FBProcessSpawnCommands.m in Sources */, @@ -3523,6 +3676,8 @@ AA90708F223AC97800805706 /* FBInstrumentsConfiguration.m in Sources */, 1C0AAAB4254B646000001D3C /* FBXCTestShimConfiguration.m in Sources */, AA2B266426821F1200EF31AA /* FBVideoFileWriter.m in Sources */, + DB5F487E28114E7B000FC7C7 /* FBCrashLogParser.m in Sources */, + DB1B3C8B29DD9F36003695C4 /* FBArchitectureProcessAdapter.m in Sources */, AADBB6B525E5689600AFB15D /* FBSettingsCommands.m in Sources */, AA6A3B0A1CC0C96E00E016C4 /* FBCollectionOperations.m in Sources */, 73E0A9751F4F361800A216AD /* FBBundleDescriptor+Application.m in Sources */, @@ -3542,7 +3697,6 @@ AADC72F02012BF7A001060E5 /* FBAccessibilityTraits.m in Sources */, AA65BECC225780ED000D380B /* FBLoggingWrapper.m in Sources */, AAF2FA6222396D4D00F1185C /* FBInstrumentsOperation.m in Sources */, - AA0F6F2B1CA3DCF700926518 /* FBWeakFrameworkLoader.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -3553,7 +3707,6 @@ AA2076BC1F0B7542001F180C /* FBControlCoreLoggerTests.m in Sources */, AA2076C31F0B7542001F180C /* FBiOSTargetTests.m in Sources */, AAB84EA81D0ACEC200D6F3ED /* FBiOSTargetDouble.m in Sources */, - AA9319B622B78E9F00C68F65 /* FBBinaryDescriptorTests.m in Sources */, AA758B4920E3BB0B0064EC18 /* FBFutureContextManagerTests.m in Sources */, AAEA3A941C90B5E4004F8409 /* FBControlCoreFixtures.m in Sources */, AA2076D01F0B76AF001F180C /* FBFileWriterTests.m in Sources */, @@ -3561,17 +3714,22 @@ AAB475F420C80F7D00B37634 /* FBiOSTargetCommandForwarderTests.m in Sources */, AA71A1171FA8E49D00BB10DA /* FBControlCoreRunLoopTests.m in Sources */, AA2076BB1F0B7542001F180C /* FBiOSTargetConfigurationTests.m in Sources */, + DB15123429E5C34C00A7C0A9 /* FBArchitectureProcessAdapterTests.swift in Sources */, AA2076B91F0B7542001F180C /* FBProcessTests.m in Sources */, + DB5F4882281156C4000FC7C7 /* TestFixtures.swift in Sources */, AA9319B822B78FB800C68F65 /* FBBinaryDescriptorTests.m in Sources */, AA11EDF9272C44410055D6D1 /* FBFileContainerTests.m in Sources */, AA6C68A4267B89C100EB975D /* FBProcessIOTests.m in Sources */, - AA2076BD1F0B7542001F180C /* FBCrashLogInfoTests.m in Sources */, EE87FA432008D906002716FE /* AXTraitsTest.m in Sources */, + DB5F488028115683000FC7C7 /* FBCrashLogInfoTests.swift in Sources */, + AA777B0327A9937E00E1481F /* FBControlCoreFrameworkLoaderTests.m in Sources */, AA08487E1F3F49D600A4BA60 /* FBFutureTests.m in Sources */, AAB68D7B1C90C2F200D20416 /* FBControlCoreValueTestCase.m in Sources */, AA3B92B11DD1C716000C045B /* FBControlCoreLoggerDouble.m in Sources */, AA2076D21F0B779B001F180C /* FBFileReaderTests.m in Sources */, + A255670D27610C7E0052D060 /* FBProcessFetcherTests.m in Sources */, AA6B1DD21FC5FCFA009DDDAE /* FBDataBufferTests.m in Sources */, + DB5F4876281079AD000FC7C7 /* FBConcatedJsonParserTests.swift in Sources */, AA274283204546F800CFAC3B /* FBProcessStreamTests.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -3643,7 +3801,6 @@ 4952437303EDA63300000002 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - COMBINE_HIDPI_IMAGES = YES; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_TESTABILITY = YES; GCC_OPTIMIZATION_LEVEL = 0; @@ -3662,7 +3819,6 @@ 4952437350C7218900000002 /* Profile */ = { isa = XCBuildConfiguration; buildSettings = { - COMBINE_HIDPI_IMAGES = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; GCC_OPTIMIZATION_LEVEL = s; }; @@ -3680,7 +3836,6 @@ 49524373A439BFE700000002 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - COMBINE_HIDPI_IMAGES = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; GCC_OPTIMIZATION_LEVEL = s; }; @@ -3711,7 +3866,11 @@ isa = XCBuildConfiguration; baseConfigurationReference = AAC8B25B1CEC52540034A865 /* FBDeviceControl.xcconfig */; buildSettings = { + CLANG_ENABLE_MODULES = YES; + DEFINES_MODULE = YES; ONLY_ACTIVE_ARCH = NO; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; }; name = Debug; }; @@ -3719,7 +3878,11 @@ isa = XCBuildConfiguration; baseConfigurationReference = AAC8B25B1CEC52540034A865 /* FBDeviceControl.xcconfig */; buildSettings = { + CLANG_ENABLE_MODULES = YES; + DEFINES_MODULE = YES; ONLY_ACTIVE_ARCH = NO; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; }; name = Profile; }; @@ -3727,8 +3890,12 @@ isa = XCBuildConfiguration; baseConfigurationReference = AAC8B25B1CEC52540034A865 /* FBDeviceControl.xcconfig */; buildSettings = { + CLANG_ENABLE_MODULES = YES; + DEFINES_MODULE = YES; GCC_GENERATE_DEBUGGING_SYMBOLS = NO; ONLY_ACTIVE_ARCH = NO; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; }; name = Release; }; @@ -3736,6 +3903,7 @@ isa = XCBuildConfiguration; baseConfigurationReference = AA7E55C31CFEC5B6009209AE /* FBDeviceControlTests.xcconfig */; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; MTL_ENABLE_DEBUG_INFO = YES; }; name = Debug; @@ -3744,6 +3912,7 @@ isa = XCBuildConfiguration; baseConfigurationReference = AA7E55C31CFEC5B6009209AE /* FBDeviceControlTests.xcconfig */; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; MTL_ENABLE_DEBUG_INFO = NO; }; name = Profile; @@ -3752,6 +3921,7 @@ isa = XCBuildConfiguration; baseConfigurationReference = AA7E55C31CFEC5B6009209AE /* FBDeviceControlTests.xcconfig */; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; MTL_ENABLE_DEBUG_INFO = NO; }; name = Release; @@ -3795,18 +3965,9 @@ }; EE4F0D441C91B7DB00608E89 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = EE4F0DDA1C91B88500608E89 /* XCTestBootstrap.xcconfig */; + baseConfigurationReference = AAA42D452796B0D900DED1D6 /* XCTestBootstrapTests.xcconfig */; buildSettings = { - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Carthage/Build/Mac", - ); - INFOPLIST_FILE = "XCTestBootstrapTests/XCTestBootstrapTests-Info.plist"; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/../Frameworks", - "@loader_path/../Frameworks", - ); + HEADER_SEARCH_PATHS = "$(SRCROOT)/PrivateHeaders"; PRODUCT_BUNDLE_IDENTIFIER = com.facebook.XCTestBootstrapTests; PRODUCT_NAME = "$(TARGET_NAME)"; }; @@ -3814,18 +3975,9 @@ }; EE4F0D451C91B7DB00608E89 /* Profile */ = { isa = XCBuildConfiguration; - baseConfigurationReference = EE4F0DDA1C91B88500608E89 /* XCTestBootstrap.xcconfig */; + baseConfigurationReference = AAA42D452796B0D900DED1D6 /* XCTestBootstrapTests.xcconfig */; buildSettings = { - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Carthage/Build/Mac", - ); - INFOPLIST_FILE = "XCTestBootstrapTests/XCTestBootstrapTests-Info.plist"; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/../Frameworks", - "@loader_path/../Frameworks", - ); + HEADER_SEARCH_PATHS = "$(SRCROOT)/PrivateHeaders"; PRODUCT_BUNDLE_IDENTIFIER = com.facebook.XCTestBootstrapTests; PRODUCT_NAME = "$(TARGET_NAME)"; }; @@ -3833,18 +3985,9 @@ }; EE4F0D461C91B7DB00608E89 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = EE4F0DDA1C91B88500608E89 /* XCTestBootstrap.xcconfig */; + baseConfigurationReference = AAA42D452796B0D900DED1D6 /* XCTestBootstrapTests.xcconfig */; buildSettings = { - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Carthage/Build/Mac", - ); - INFOPLIST_FILE = "XCTestBootstrapTests/XCTestBootstrapTests-Info.plist"; - LD_RUNPATH_SEARCH_PATHS = ( - "$(inherited)", - "@executable_path/../Frameworks", - "@loader_path/../Frameworks", - ); + HEADER_SEARCH_PATHS = "$(SRCROOT)/PrivateHeaders"; PRODUCT_BUNDLE_IDENTIFIER = com.facebook.XCTestBootstrapTests; PRODUCT_NAME = "$(TARGET_NAME)"; }; @@ -3879,6 +4022,14 @@ isa = XCBuildConfiguration; baseConfigurationReference = AAA55F641D0088E800BC4824 /* FBControlCoreTests.xcconfig */; buildSettings = { + CLANG_ENABLE_MODULES = YES; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/../Frameworks", + ); + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; }; name = Debug; }; @@ -3886,6 +4037,14 @@ isa = XCBuildConfiguration; baseConfigurationReference = AAA55F641D0088E800BC4824 /* FBControlCoreTests.xcconfig */; buildSettings = { + CLANG_ENABLE_MODULES = YES; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/../Frameworks", + ); + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; }; name = Profile; }; @@ -3893,6 +4052,14 @@ isa = XCBuildConfiguration; baseConfigurationReference = AAA55F641D0088E800BC4824 /* FBControlCoreTests.xcconfig */; buildSettings = { + CLANG_ENABLE_MODULES = YES; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/../Frameworks", + ); + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; }; name = Release; }; diff --git a/FBSimulatorControl.xcodeproj/xcshareddata/xcschemes/FBControlCore.xcscheme b/FBSimulatorControl.xcodeproj/xcshareddata/xcschemes/FBControlCore.xcscheme index f21042834..d06b61598 100644 --- a/FBSimulatorControl.xcodeproj/xcshareddata/xcschemes/FBControlCore.xcscheme +++ b/FBSimulatorControl.xcodeproj/xcshareddata/xcschemes/FBControlCore.xcscheme @@ -1,6 +1,6 @@ + + + + @@ -39,17 +48,6 @@ - - - - - - - - - - - - - - - - + + + + + + - - + + + + @@ -39,17 +48,6 @@ - - - - - - - - *> *)recursiveDescriptionFromElement:(AXPMacPlatformElement *)element token:(NSString *)token nestedFormat:(BOOL)nestedFormat +{ + element.translation.bridgeDelegateToken = token; + if (nestedFormat) { + return @[[self.class nestedRecursiveDescriptionFromElement:element token:token]]; + } + return [self.class flatRecursiveDescriptionFromElement:element token:token]; +} + ++ (NSDictionary *)formattedDescriptionOfElement:(AXPMacPlatformElement *)element token:(NSString *)token nestedFormat:(BOOL)nestedFormat +{ + element.translation.bridgeDelegateToken = token; + if (nestedFormat) { + return [self.class nestedRecursiveDescriptionFromElement:element token:token]; + } + return [self.class accessibilityDictionaryForElement:element token:token]; +} + +// The values here are intended to mirror the values in the old SimulatorBridge implementation for compatibility downstream. ++ (NSDictionary *)accessibilityDictionaryForElement:(AXPMacPlatformElement *)element token:(NSString *)token +{ + // The token must always be set so that the right callback is called + element.translation.bridgeDelegateToken = token; + + NSRect frame = element.accessibilityFrame; + // The value returned in accessibilityRole is may be prefixed with "AX". + // If that's the case, then let's strip it to make it like the SimulatorBridge implementation. + NSString *role = element.accessibilityRole; + if ([role hasPrefix:AXPrefix]) { + role = [role substringFromIndex:2]; + } + NSMutableArray *customActions = [[NSMutableArray alloc] init]; + for(NSString *name in [element.accessibilityCustomActions valueForKey:@"name"]) { + [customActions addObject:ensureJSONSerializable(name)]; + } + return @{ + // These values are the "legacy" values that mirror their equivalents in SimulatorBridge + @"AXLabel": ensureJSONSerializable(element.accessibilityLabel), + @"AXFrame": NSStringFromRect(frame), + @"AXValue": ensureJSONSerializable(element.accessibilityValue), + @"AXUniqueId": ensureJSONSerializable(element.accessibilityIdentifier), + // There are additional synthetic values from the old output. + @"type": ensureJSONSerializable(role), + // These are new values in this output + @"title": ensureJSONSerializable(element.accessibilityTitle), + @"frame": @{ + @"x": @(frame.origin.x), + @"y": @(frame.origin.y), + @"width": @(frame.size.width), + @"height": @(frame.size.height), + }, + @"help": ensureJSONSerializable(element.accessibilityHelp), + @"enabled": @(element.accessibilityEnabled), + @"custom_actions": [customActions copy], + @"role": ensureJSONSerializable(element.accessibilityRole), + @"role_description": ensureJSONSerializable(element.accessibilityRoleDescription), + @"subrole": ensureJSONSerializable(element.accessibilitySubrole), + @"content_required": @(element.accessibilityRequired), + @"pid": @(element.translation.pid), + }; +} + +// This replicates the non-heirarchical system that was previously present in SimulatorBridge. +// In this case the values of frames must be relative to the root, rather than the parent frame. ++ (NSArray *> *)flatRecursiveDescriptionFromElement:(AXPMacPlatformElement *)element token:(NSString *)token +{ + NSMutableArray *> *values = NSMutableArray.array; + [values addObject:[self accessibilityDictionaryForElement:element token:token]]; + for (AXPMacPlatformElement *childElement in element.accessibilityChildren) { + childElement.translation.bridgeDelegateToken = token; + NSArray *> *childValues = [self flatRecursiveDescriptionFromElement:childElement token:token]; + [values addObjectsFromArray:childValues]; + } + return values; +} + ++ (NSDictionary *)nestedRecursiveDescriptionFromElement:(AXPMacPlatformElement *)element token:(NSString *)token +{ + NSMutableDictionary *values = [[self accessibilityDictionaryForElement:element token:token] mutableCopy]; + NSMutableArray *> *childrenValues = NSMutableArray.array; + for (AXPMacPlatformElement *childElement in element.accessibilityChildren) { + childElement.translation.bridgeDelegateToken = token; + NSDictionary *childValues = [self nestedRecursiveDescriptionFromElement:childElement token:token]; + [childrenValues addObject:childValues]; + } + values[@"children"] = childrenValues; + return values; +} + +@end + static NSString *const DummyBridgeToken = @"FBSimulatorAccessibilityCommandsDummyBridgeToken"; @interface FBSimulatorAccessibilityCommands_SimulatorBridge : NSObject @@ -99,6 +207,109 @@ - (instancetype)initWithBridge:(FBSimulatorBridge *)bridge @end +@interface FBSimulator_TranslationRequest : NSObject + +@property (nonatomic, assign, readonly) BOOL nestedFormat; +@property (nonatomic, copy, readonly) NSString *token; + +@end + +@implementation FBSimulator_TranslationRequest + +- (instancetype)initWithNestedFormat:(BOOL)nestedFormat +{ + self = [super init]; + if (!self) { + return nil; + } + + _token = NSUUID.UUID.UUIDString; + _nestedFormat = nestedFormat; + + return self; +} + +- (AXPTranslationObject *)performWithTranslator:(AXPTranslator *)translator +{ + NSAssert(NO, @"-[%@ %@] is abstract and should be overridden", NSStringFromClass(self.class), NSStringFromSelector(_cmd)); + return nil; +} + +- (id)serialize:(AXPMacPlatformElement *)element +{ + NSAssert(NO, @"-[%@ %@] is abstract and should be overridden", NSStringFromClass(self.class), NSStringFromSelector(_cmd)); + return nil; +} + +- (instancetype)cloneWithNewToken +{ + NSAssert(NO, @"-[%@ %@] is abstract and should be overridden", NSStringFromClass(self.class), NSStringFromSelector(_cmd)); + return nil; +} + +@end + +@interface FBSimulator_TranslationRequest_FrontmostApplication : FBSimulator_TranslationRequest + +@end + +@implementation FBSimulator_TranslationRequest_FrontmostApplication + +- (AXPTranslationObject *)performWithTranslator:(AXPTranslator *)translator +{ + return [translator frontmostApplicationWithDisplayId:0 bridgeDelegateToken:self.token]; +} + +- (id)serialize:(AXPMacPlatformElement *)element +{ + return [FBSimulatorAccessibilitySerializer recursiveDescriptionFromElement:element token:self.token nestedFormat:self.nestedFormat]; +} + +- (instancetype)cloneWithNewToken +{ + return [[FBSimulator_TranslationRequest_FrontmostApplication alloc] initWithNestedFormat:self.nestedFormat]; +} + +@end + +@interface FBSimulator_TranslationRequest_Point : FBSimulator_TranslationRequest + +@property (nonatomic, assign, readonly) CGPoint point; + +@end + +@implementation FBSimulator_TranslationRequest_Point + +- (instancetype)initWithNestedFormat:(BOOL)nestedFormat point:(CGPoint)point +{ + self = [super initWithNestedFormat:nestedFormat]; + if (!self) { + return nil; + } + + _point = point; + + return self; +} + +- (AXPTranslationObject *)performWithTranslator:(AXPTranslator *)translator +{ + return [translator objectAtPoint:self.point displayId:0 bridgeDelegateToken:self.token]; +} + +- (id)serialize:(AXPMacPlatformElement *)element +{ + return [FBSimulatorAccessibilitySerializer formattedDescriptionOfElement:element token:self.token nestedFormat:self.nestedFormat]; +} + +- (instancetype)cloneWithNewToken +{ + return [[FBSimulator_TranslationRequest_Point alloc] initWithNestedFormat:self.nestedFormat point:self.point]; +} + +@end + + @interface FBSimulator_TranslationDispatcher : NSObject @property (nonatomic, weak, readonly) AXPTranslator *translator; @@ -144,41 +355,32 @@ + (instancetype)sharedInstance #pragma mark Public -- (FBFuture *> *> *)frontmostApplicationForSimulator:(FBSimulator *)simulator displayId:(unsigned int)displayId nestedFormat:(BOOL)nestedFormat +- (FBFutureContext *> *)translationObjectAndMacPlatformElementForSimulator:(FBSimulator *)simulator request:(FBSimulator_TranslationRequest *)request { - return [FBFuture - onQueue:simulator.workQueue resolveValue:^(NSError **error) { - NSString *token = [self pushSimulator:simulator]; - AXPTranslationObject *translation = [self.translator frontmostApplicationWithDisplayId:displayId bridgeDelegateToken:token]; - translation.bridgeDelegateToken = token; + return [[FBFuture + onQueue:simulator.workQueue resolveValue:^ NSArray * (NSError **error){ + [self pushSimulator:simulator token:request.token]; + AXPTranslationObject *translation = [request performWithTranslator:self.translator]; + if (translation == nil) { + return [[FBSimulatorError + describeFormat:@"No translation object returned for simulator. This means you have likely specified a point onscreen that is invalid or invisible due to a fullscreen dialog"] + fail:error]; + } + translation.bridgeDelegateToken = request.token; AXPMacPlatformElement *element = [self.translator macPlatformElementFromTranslation:translation]; - element.translation.bridgeDelegateToken = token; - NSArray *> *formatted = [self.class recursiveDescriptionFromElement:element token:token nestedFormat:nestedFormat]; - [self popSimulator:token]; - return formatted; - }]; -} - -- (FBFuture *> *)objectAtPointForSimulator:(FBSimulator *)simulator displayId:(unsigned int)displayId atPoint:(CGPoint)point nestedFormat:(BOOL)nestedFormat -{ - return [FBFuture - onQueue:simulator.workQueue resolveValue:^(NSError **error) { - NSString *token = [self pushSimulator:simulator]; - AXPTranslationObject *translation = [self.translator objectAtPoint:point displayId:displayId bridgeDelegateToken:token]; - translation.bridgeDelegateToken = token; - AXPMacPlatformElement *element = [self.translator macPlatformElementFromTranslation:translation]; - element.translation.bridgeDelegateToken = token; - NSDictionary *formatted = [self.class formattedDescriptionOfElement:element token:token nestedFormat:nestedFormat]; - [self popSimulator:token]; - return formatted; + element.translation.bridgeDelegateToken = request.token; + return @[translation, element]; + }] + onQueue:simulator.workQueue contextualTeardown:^ FBFuture * (id _, FBFutureState __){ + [self popSimulator:request.token]; + return FBFuture.empty; }]; } #pragma mark Private -- (NSString *)pushSimulator:(FBSimulator *)simulator +- (NSString *)pushSimulator:(FBSimulator *)simulator token:(NSString *)token { - NSString *token = NSUUID.UUID.UUIDString; NSParameterAssert([self.tokenToSimulator objectForKey:token] == nil); [self.tokenToSimulator setObject:simulator forKey:token]; [self.logger logFormat:@"Simulator %@ backed by token %@", simulator, token]; @@ -194,10 +396,12 @@ - (FBSimulator *)popSimulator:(NSString *)token return simulator; } +#pragma mark AXPTranslationTokenDelegateHelper + // Since we're using an async callback-based function in CoreSimulator this needs to be converted to a synchronous variant for the AXTranslator callbacks. // In order to do this we have a dispatch group acting as a mutex. // This also means that the queue that this happens on should **never be the main queue**. An async global queue will suffice here. -- (AXPTranslationCallback)translationCallbackForToken:(NSString *)token +- (AXPTranslationCallback)accessibilityTranslationDelegateBridgeCallbackWithToken:(NSString *)token { FBSimulator *simulator = [self.tokenToSimulator objectForKey:token]; if (!simulator) { @@ -221,100 +425,6 @@ - (AXPTranslationCallback)translationCallbackForToken:(NSString *)token }; } -static NSString *const AXPrefix = @"AX"; - -+ (NSArray *> *)recursiveDescriptionFromElement:(AXPMacPlatformElement *)element token:(NSString *)token nestedFormat:(BOOL)nestedFormat -{ - element.translation.bridgeDelegateToken = token; - if (nestedFormat) { - return @[[self.class nestedRecursiveDescriptionFromElement:element token:token]]; - } - return [self.class flatRecursiveDescriptionFromElement:element token:token]; -} - -+ (NSDictionary *)formattedDescriptionOfElement:(AXPMacPlatformElement *)element token:(NSString *)token nestedFormat:(BOOL)nestedFormat -{ - element.translation.bridgeDelegateToken = token; - if (nestedFormat) { - return [self.class nestedRecursiveDescriptionFromElement:element token:token]; - } - return [self.class accessibilityDictionaryForElement:element token:token]; -} - -// The values here are intended to mirror the values in the old SimulatorBridge implementation for compatibility downstream. -+ (NSDictionary *)accessibilityDictionaryForElement:(AXPMacPlatformElement *)element token:(NSString *)token -{ - // The token must always be set so that the right callback is called - element.translation.bridgeDelegateToken = token; - - NSRect frame = element.accessibilityFrame; - // The value returned in accessibilityRole is may be prefixed with "AX". - // If that's the case, then let's strip it to make it like the SimulatorBridge implementation. - NSString *role = element.accessibilityRole; - if ([role hasPrefix:AXPrefix]) { - role = [role substringFromIndex:2]; - } - return @{ - // These values are the "legacy" values that mirror their equivalents in SimulatorBridge - @"AXLabel": element.accessibilityLabel ?: NSNull.null, - @"AXFrame": NSStringFromRect(frame), - @"AXValue": element.accessibilityValue ?: NSNull.null, - @"AXUniqueId": element.accessibilityIdentifier ?: NSNull.null, - // There are additional synthetic values from the old output. - @"type": role ?: NSNull.null, - // These are new values in this output - @"title": element.accessibilityTitle ?: NSNull.null, - @"frame": @{ - @"x": @(frame.origin.x), - @"y": @(frame.origin.y), - @"width": @(frame.size.width), - @"height": @(frame.size.height), - }, - @"help": element.accessibilityHelp ?: NSNull.null, - @"enabled": @(element.accessibilityEnabled), - @"custom_actions": [element.accessibilityCustomActions valueForKey:@"name"] ?: @[], - @"role": element.accessibilityRole ?: NSNull.null, - @"role_description": element.accessibilityRoleDescription ?: NSNull.null, - @"subrole": element.accessibilitySubrole ?: NSNull.null, - @"content_required": @(element.accessibilityRequired), - }; -} - -// This replicates the non-heirarchical system that was previously present in SimulatorBridge. -// In this case the values of frames must be relative to the root, rather than the parent frame. -+ (NSArray *> *)flatRecursiveDescriptionFromElement:(AXPMacPlatformElement *)element token:(NSString *)token -{ - NSMutableArray *> *values = NSMutableArray.array; - [values addObject:[self accessibilityDictionaryForElement:element token:token]]; - for (AXPMacPlatformElement *childElement in element.accessibilityChildren) { - childElement.translation.bridgeDelegateToken = token; - NSArray *> *childValues = [self flatRecursiveDescriptionFromElement:childElement token:token]; - [values addObjectsFromArray:childValues]; - } - return values; -} - -+ (NSDictionary *)nestedRecursiveDescriptionFromElement:(AXPMacPlatformElement *)element token:(NSString *)token -{ - NSMutableDictionary *values = [[self accessibilityDictionaryForElement:element token:token] mutableCopy]; - NSMutableArray *> *childrenValues = NSMutableArray.array; - for (AXPMacPlatformElement *childElement in element.accessibilityChildren) { - childElement.translation.bridgeDelegateToken = token; - NSDictionary *childValues = [self nestedRecursiveDescriptionFromElement:childElement token:token]; - [childrenValues addObject:childValues]; - } - values[@"children"] = childrenValues; - return values; -} - - -#pragma mark AXPTranslationTokenDelegateHelper - -- (AXPTranslationCallback)accessibilityTranslationDelegateBridgeCallbackWithToken:(NSString *)token -{ - return [self translationCallbackForToken:token]; -} - - (CGRect)accessibilityTranslationConvertPlatformFrameToSystem:(CGRect)rect withToken:(NSString *)token { return rect; @@ -354,14 +464,96 @@ - (instancetype)initWithSimulator:(FBSimulator *)simulator queue:(dispatch_queue #pragma mark FBSimulatorAccessibilityCommands Implementation -- (FBFuture *> *> *)accessibilityElementsWithNestedFormat:(BOOL)nestedFormat +- (FBFuture *)accessibilityElementsWithNestedFormat:(BOOL)nestedFormat { - return [FBSimulator_TranslationDispatcher.sharedInstance frontmostApplicationForSimulator:self.simulator displayId:0 nestedFormat:nestedFormat]; + FBSimulator_TranslationRequest *translationRequest = [[FBSimulator_TranslationRequest_FrontmostApplication alloc] initWithNestedFormat:nestedFormat]; + return [FBSimulatorAccessibilityCommands_CoreSimulator accessibilityElementWithTranslationRequest:translationRequest simulator:self.simulator remediationPermitted:YES]; } -- (FBFuture *> *)accessibilityElementAtPoint:(CGPoint)point nestedFormat:(BOOL)nestedFormat +- (FBFuture *)accessibilityElementAtPoint:(CGPoint)point nestedFormat:(BOOL)nestedFormat { - return [FBSimulator_TranslationDispatcher.sharedInstance objectAtPointForSimulator:self.simulator displayId:0 atPoint:point nestedFormat:nestedFormat]; + FBSimulator_TranslationRequest *translationRequest = [[FBSimulator_TranslationRequest_Point alloc] initWithNestedFormat:nestedFormat point:point]; + return [FBSimulatorAccessibilityCommands_CoreSimulator accessibilityElementWithTranslationRequest:translationRequest simulator:self.simulator remediationPermitted:NO]; +} + +#pragma mark Private + ++ (FBFuture *)accessibilityElementWithTranslationRequest:(FBSimulator_TranslationRequest *)request simulator:(FBSimulator *)simulator remediationPermitted:(BOOL)remediationPermitted +{ + return [[[[FBSimulator_TranslationDispatcher.sharedInstance + translationObjectAndMacPlatformElementForSimulator:simulator request:request] + // This next steps appends remediation information (if required). + // The remediation detection has a short circuit so that the common case (no remediation required) is fast. + onQueue:simulator.asyncQueue pend:^ FBFuture *> * (NSArray *tuple){ + AXPTranslationObject *translationObject = tuple[0]; + AXPMacPlatformElement *macPlatformElement = tuple[1]; + // Only see if remediation is needed if requested. This also ensures that the attempt *after* remediation will not infinitely recurse. + if (remediationPermitted) { + return [[FBSimulatorAccessibilityCommands_CoreSimulator + remediationRequiredForSimulator:simulator + translationObject:translationObject + macPlatformElement:macPlatformElement] + onQueue:simulator.asyncQueue map:^ NSArray * (NSNumber *remediationRequired) { + return @[translationObject, macPlatformElement, remediationRequired]; + }]; + } + return [FBFuture futureWithResult:@[translationObject, macPlatformElement, @NO]]; + }] + onQueue:simulator.workQueue pop:^ id (NSArray *tuple){ + // If remediation is required, then return an empty value, we pop the context here to finish the translation process. + BOOL remediationRequired = [tuple[2] boolValue]; + if (remediationRequired) { + return FBFuture.empty; + } + // Otherwise serialize now, when the context has popped the token is then deregistered. + AXPMacPlatformElement *element = tuple[1]; + return [FBFuture futureWithResult:[request serialize:element]]; + }] + onQueue:simulator.workQueue fmap:^ FBFuture * (id result) { + // At this point we will either have an empty result, or the result. + // In the empty (remediation) state, then we should recurse, but not allow further remediation. + if ([result isEqual:NSNull.null]) { + FBSimulator_TranslationRequest *nextRequest = [request cloneWithNewToken]; + return [[self + remediateSpringBoardForSimulator:simulator] + onQueue:simulator.workQueue fmap:^ FBFuture * (id _) { + return [self accessibilityElementWithTranslationRequest:nextRequest simulator:simulator remediationPermitted:NO]; + }]; + } + return [FBFuture futureWithResult:result]; + }]; +} + +static NSString *const CoreSimulatorBridgeServiceName = @"com.apple.CoreSimulator.bridge"; + ++ (FBFuture *)remediationRequiredForSimulator:(FBSimulator *)simulator translationObject:(AXPTranslationObject *)translationObject macPlatformElement:(AXPMacPlatformElement *)macPlatformElement +{ + // First perform a quick check, if the accessibility frame is zero, then this is indicative of the problem + if (CGRectEqualToRect(macPlatformElement.accessibilityFrame, CGRectZero) == NO) { + return [FBFuture futureWithResult:@(NO)]; + } + // Then confirm whether the pid of the translation object represents a real pid within the simulator. + // If it does not, then it likely means that we got the pid of the crashed SpringBoard. + // A crashed SpringBoard, means that there is a new one running (or else the Simulator is completely hosed). + // In this case, the remediation is to restart CoreSimulatorBridge, since the CoreSimulatorBridge needs restarting upon a crash. + // In all likelihood CoreSimulatorBridge contains a constant reference to the pid of SpringBoard and the most effective way of resolving this is to stop it. + // The Simulator's launchctl will then make sure that the SimulatorBridge is restarted (just like it does for SpringBoard itself). + pid_t processIdentifier = translationObject.pid; + return [[[simulator + serviceNameForProcessIdentifier:processIdentifier] + mapReplace:@(NO)] + onQueue:simulator.workQueue handleError:^(NSError *error) { + [simulator.logger logFormat:@"pid %d does not exist, this likely means that SpringBoard has restarted, %@ should be restarted", processIdentifier, CoreSimulatorBridgeServiceName]; + return [FBFuture futureWithResult:@(YES)]; + }]; +} + ++ (FBFuture *)remediateSpringBoardForSimulator:(FBSimulator *)simulator +{ + return [[[simulator + stopServiceWithName:CoreSimulatorBridgeServiceName] + mapReplace:NSNull.null] + rephraseFailure:@"Could not restart %@ bridge when attempting to remediate SpringBoard Crash", CoreSimulatorBridgeServiceName]; } @end @@ -422,6 +614,11 @@ - (instancetype)initWithSimulator:(FBSimulator *)simulator // The CoreSimulator API **is** backwards compatible, since it updates CoreSimulator.framework at the system level. // However, this API is only usable from CoreSimulator if Xcode 12 has been *installed at some point in the past on the host*. FBSimulator *simulator = self.simulator; + if (simulator.state != FBiOSTargetStateBooted) { + return [[FBControlCoreError + describeFormat:@"Cannot run accessibility commands against %@ as it is not booted", simulator] + failFuture]; + } SimDevice *device = simulator.device; if (nestedFormat || FBXcodeConfiguration.isXcode12OrGreater) { if (![device respondsToSelector:@selector(sendAccessibilityRequestAsync:completionQueue:completionHandler:)]) { diff --git a/FBSimulatorControl/Commands/FBSimulatorApplicationCommands.h b/FBSimulatorControl/Commands/FBSimulatorApplicationCommands.h index 935e83c5f..1898008b5 100644 --- a/FBSimulatorControl/Commands/FBSimulatorApplicationCommands.h +++ b/FBSimulatorControl/Commands/FBSimulatorApplicationCommands.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControl/Commands/FBSimulatorApplicationCommands.m b/FBSimulatorControl/Commands/FBSimulatorApplicationCommands.m index ee98daab3..8ad832add 100644 --- a/FBSimulatorControl/Commands/FBSimulatorApplicationCommands.m +++ b/FBSimulatorControl/Commands/FBSimulatorApplicationCommands.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -219,7 +219,7 @@ - (instancetype)initWithSimulator:(FBSimulator *)simulator - (FBFuture *)processIDWithBundleID:(NSString *)bundleID { NSError *error = nil; - NSString *pattern = [NSString stringWithFormat:@"UIKitApplication:%@\\[|$",[NSRegularExpression escapedPatternForString:bundleID]]; + NSString *pattern = [NSString stringWithFormat:@"UIKitApplication:%@(\\[|$)",[NSRegularExpression escapedPatternForString:bundleID]]; NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern options:0 error:&error]; if (error) { return [[FBSimulatorError @@ -454,7 +454,8 @@ + (FBInstalledApplication *)installedApplicationFromInfo:(NSDictionary *binaryArchitectures = application.binary.architectures; - NSSet *supportedArchitectures = FBiOSTargetConfiguration.baseArchToCompatibleArch[self.simulator.deviceType.simulatorArchitecture]; + NSSet *supportedArchitectures = [FBiOSTargetConfiguration baseArchsToCompatibleArch:self.simulator.architectures]; if (![binaryArchitectures intersectsSet:supportedArchitectures]) { return [[FBSimulatorError describeFormat: diff --git a/FBSimulatorControl/Commands/FBSimulatorCrashLogCommands.h b/FBSimulatorControl/Commands/FBSimulatorCrashLogCommands.h index 8024660df..8f9563044 100644 --- a/FBSimulatorControl/Commands/FBSimulatorCrashLogCommands.h +++ b/FBSimulatorControl/Commands/FBSimulatorCrashLogCommands.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControl/Commands/FBSimulatorCrashLogCommands.m b/FBSimulatorControl/Commands/FBSimulatorCrashLogCommands.m index 955da8ac8..a9ac010da 100644 --- a/FBSimulatorControl/Commands/FBSimulatorCrashLogCommands.m +++ b/FBSimulatorControl/Commands/FBSimulatorCrashLogCommands.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControl/Commands/FBSimulatorDapServerCommands.h b/FBSimulatorControl/Commands/FBSimulatorDapServerCommands.h index 2f6113882..11894be4c 100644 --- a/FBSimulatorControl/Commands/FBSimulatorDapServerCommands.h +++ b/FBSimulatorControl/Commands/FBSimulatorDapServerCommands.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControl/Commands/FBSimulatorDapServerCommands.m b/FBSimulatorControl/Commands/FBSimulatorDapServerCommands.m index 79b039c3f..2b5f28d99 100644 --- a/FBSimulatorControl/Commands/FBSimulatorDapServerCommands.m +++ b/FBSimulatorControl/Commands/FBSimulatorDapServerCommands.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControl/Commands/FBSimulatorDebuggerCommands.h b/FBSimulatorControl/Commands/FBSimulatorDebuggerCommands.h index 1b4715fee..f9ab0e6bd 100644 --- a/FBSimulatorControl/Commands/FBSimulatorDebuggerCommands.h +++ b/FBSimulatorControl/Commands/FBSimulatorDebuggerCommands.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControl/Commands/FBSimulatorDebuggerCommands.m b/FBSimulatorControl/Commands/FBSimulatorDebuggerCommands.m index 7735c6c73..a04b23d9e 100644 --- a/FBSimulatorControl/Commands/FBSimulatorDebuggerCommands.m +++ b/FBSimulatorControl/Commands/FBSimulatorDebuggerCommands.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControl/Commands/FBSimulatorFileCommands.h b/FBSimulatorControl/Commands/FBSimulatorFileCommands.h index fd393125b..b41d79ac7 100644 --- a/FBSimulatorControl/Commands/FBSimulatorFileCommands.h +++ b/FBSimulatorControl/Commands/FBSimulatorFileCommands.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControl/Commands/FBSimulatorFileCommands.m b/FBSimulatorControl/Commands/FBSimulatorFileCommands.m index c2734730c..e7384b6dd 100644 --- a/FBSimulatorControl/Commands/FBSimulatorFileCommands.m +++ b/FBSimulatorControl/Commands/FBSimulatorFileCommands.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -99,7 +99,8 @@ - (instancetype)initWithSimulator:(FBSimulator *)simulator - (FBFutureContext> *)fileCommandsForMediaDirectory { - return [FBFutureContext futureContextWithResult:[FBFileContainer fileContainerForBasePath:self.simulator.dataDirectory]]; + NSString *mediaDirectory = [self.simulator.dataDirectory stringByAppendingPathComponent:@"Media"]; + return [FBFutureContext futureContextWithResult:[FBFileContainer fileContainerForBasePath:mediaDirectory]]; } - (FBFutureContext> *)fileCommandsForMDMProfiles @@ -137,6 +138,13 @@ - (instancetype)initWithSimulator:(FBSimulator *)simulator failFutureContext]; } +- (FBFutureContext> *)fileCommandsForSymbols +{ + return [[FBControlCoreError + describeFormat:@"%@ not supported on simulators", NSStringFromSelector(_cmd)] + failFutureContext]; +} + #pragma mark Private - (FBFuture *)dataContainerForBundleID:(NSString *)bundleID diff --git a/FBSimulatorControl/Commands/FBSimulatorKeychainCommands.h b/FBSimulatorControl/Commands/FBSimulatorKeychainCommands.h index 711a3e725..5745ece11 100644 --- a/FBSimulatorControl/Commands/FBSimulatorKeychainCommands.h +++ b/FBSimulatorControl/Commands/FBSimulatorKeychainCommands.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControl/Commands/FBSimulatorKeychainCommands.m b/FBSimulatorControl/Commands/FBSimulatorKeychainCommands.m index 4d398f8bf..55cdb4367 100644 --- a/FBSimulatorControl/Commands/FBSimulatorKeychainCommands.m +++ b/FBSimulatorControl/Commands/FBSimulatorKeychainCommands.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControl/Commands/FBSimulatorLaunchCtlCommands.h b/FBSimulatorControl/Commands/FBSimulatorLaunchCtlCommands.h index 45b7084cc..35746708f 100644 --- a/FBSimulatorControl/Commands/FBSimulatorLaunchCtlCommands.h +++ b/FBSimulatorControl/Commands/FBSimulatorLaunchCtlCommands.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -21,6 +21,15 @@ NS_ASSUME_NONNULL_BEGIN #pragma mark Querying Services +/** + Finds the Service Name for a provided process identifier + Will fail if there is no process matching the Process Info found. + + @param pid the process identifier to obtain the name for. + @return A Future, wrapping the Service Name. + */ +- (FBFuture *)serviceNameForProcessIdentifier:(pid_t)pid; + /** Finds the Service Name for a provided process. Will fail if there is no process matching the Process Info found. diff --git a/FBSimulatorControl/Commands/FBSimulatorLaunchCtlCommands.m b/FBSimulatorControl/Commands/FBSimulatorLaunchCtlCommands.m index 331979ea3..8003c9cfb 100644 --- a/FBSimulatorControl/Commands/FBSimulatorLaunchCtlCommands.m +++ b/FBSimulatorControl/Commands/FBSimulatorLaunchCtlCommands.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -62,15 +62,15 @@ - (instancetype)initWithSimulator:(FBSimulator *)simulator launchctlLaunchPath:( #pragma mark Querying Services -- (FBFuture *)serviceNameForProcess:(FBProcessInfo *)process +- (FBFuture *)serviceNameForProcessIdentifier:(pid_t)pid { NSError *error = nil; - NSString *pattern = [NSString stringWithFormat:@"^%@\t", [NSRegularExpression escapedPatternForString:@(process.processIdentifier).stringValue]]; + NSString *pattern = [NSString stringWithFormat:@"^%@\t", [NSRegularExpression escapedPatternForString:@(pid).stringValue]]; NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern options:0 error:&error]; if (error) { return [[FBSimulatorError - describeFormat:@"Couldn't build search pattern for '%@'", process] - failFuture]; + describeFormat:@"Couldn't build search pattern for '%@'", @(pid)] + failFuture]; } return [[self @@ -80,6 +80,12 @@ - (instancetype)initWithSimulator:(FBSimulator *)simulator launchctlLaunchPath:( }]; } + +- (FBFuture *)serviceNameForProcess:(FBProcessInfo *)process +{ + return [self serviceNameForProcessIdentifier:process.processIdentifier]; +} + - (FBFuture *> *)serviceNamesAndProcessIdentifiersMatching:(NSRegularExpression *)regex { return [[self diff --git a/FBSimulatorControl/Commands/FBSimulatorLifecycleCommands.h b/FBSimulatorControl/Commands/FBSimulatorLifecycleCommands.h index 137f516df..ef1d517d2 100644 --- a/FBSimulatorControl/Commands/FBSimulatorLifecycleCommands.h +++ b/FBSimulatorControl/Commands/FBSimulatorLifecycleCommands.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -23,7 +23,7 @@ NS_ASSUME_NONNULL_BEGIN /** Interactions for the Lifecycle of the Simulator. */ -@protocol FBSimulatorLifecycleCommands +@protocol FBSimulatorLifecycleCommands #pragma mark Boot/Shutdown @@ -36,16 +36,6 @@ NS_ASSUME_NONNULL_BEGIN */ - (FBFuture *)boot:(FBSimulatorBootConfiguration *)configuration; -#pragma mark States - -/** - Asynchronously waits on the provided state. - - @param state the state to wait on - @return A future that resolves when it has transitioned to the given state. - */ -- (FBFuture *)resolveState:(FBiOSTargetState)state; - #pragma mark Focus /** diff --git a/FBSimulatorControl/Commands/FBSimulatorLifecycleCommands.m b/FBSimulatorControl/Commands/FBSimulatorLifecycleCommands.m index 89c965111..c0dab1b27 100644 --- a/FBSimulatorControl/Commands/FBSimulatorLifecycleCommands.m +++ b/FBSimulatorControl/Commands/FBSimulatorLifecycleCommands.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -11,6 +11,7 @@ #import +#import "FBCoreSimulatorNotifier.h" #import "FBSimulator.h" #import "FBSimulatorBootConfiguration.h" #import "FBSimulatorBootStrategy.h" @@ -21,10 +22,11 @@ #import "FBSimulatorControlConfiguration.h" #import "FBSimulatorError.h" +const int OPEN_URL_RETRIES = 2; + @interface FBSimulatorLifecycleCommands () @property (nonatomic, weak, readonly) FBSimulator *simulator; -@property (nonatomic, strong, readwrite, nullable) FBFramebuffer *framebuffer; @property (nonatomic, strong, readwrite, nullable) FBSimulatorHID *hid; @property (nonatomic, strong, readwrite, nullable) FBSimulatorBridge *bridge; @@ -62,7 +64,7 @@ - (instancetype)initWithSimulator:(FBSimulator *)simulator - (FBFuture *)shutdown { - return [[self.simulator.set killSimulator:self.simulator] mapReplace:NSNull.null]; + return [[self.simulator.set shutdown:self.simulator] mapReplace:NSNull.null]; } - (FBFuture *)reboot @@ -78,17 +80,19 @@ - (instancetype)initWithSimulator:(FBSimulator *)simulator - (FBFuture *)erase { - return [[self.simulator.set eraseSimulator:self.simulator] mapReplace:NSNull.null]; + return [[self.simulator.set erase:self.simulator] mapReplace:NSNull.null]; } #pragma mark States - (FBFuture *)resolveState:(FBiOSTargetState)state { - FBSimulator *simulator = self.simulator; - return [FBFuture onQueue:simulator.workQueue resolveWhen:^ BOOL { - return simulator.state == state; - }]; + return FBiOSTargetResolveState(self.simulator, state); +} + +- (FBFuture *)resolveLeavesState:(FBiOSTargetState)state +{ + return [FBCoreSimulatorNotifier resolveLeavesState:state forSimDevice:self.simulator.device]; } #pragma mark Focus @@ -187,7 +191,6 @@ + (NSRunningApplication *)launchSimulatorApplicationForDefaultDeviceSetWithError ]] onQueue:self.simulator.workQueue chain:^(FBFuture *_) { // Nullify - self.framebuffer = nil; self.hid = nil; self.bridge = nil; return FBFuture.empty; @@ -214,9 +217,6 @@ + (NSRunningApplication *)launchSimulatorApplicationForDefaultDeviceSetWithError - (FBFuture *)connectToFramebuffer { - if (self.framebuffer) { - return [FBFuture futureWithResult:self.framebuffer]; - } FBSimulator *simulator = self.simulator; return [FBFuture onQueue:simulator.workQueue resolveValue:^(NSError **error) { @@ -245,13 +245,20 @@ + (NSRunningApplication *)launchSimulatorApplicationForDefaultDeviceSetWithError { NSParameterAssert(url); NSError *error = nil; - if (![self.simulator.device openURL:url error:&error]) { - return [[[FBSimulatorError - describeFormat:@"Failed to open URL %@ on simulator %@", url, self.simulator] - causedBy:error] - failFuture]; - } - return [FBFuture futureWithResult:[NSNull null]]; + + int retry = 0; + do { + // Retry openURL 2 times to alleviate Rosetta startup slowness. + if ([self.simulator.device openURL:url error:&error]) { + return [FBFuture futureWithResult:[NSNull null]]; + } + retry++; + } while (retry <= OPEN_URL_RETRIES); + + return [[[FBSimulatorError + describeFormat:@"Failed to open URL %@ on simulator %@", url, self.simulator] + causedBy:error] + failFuture]; } @end diff --git a/FBSimulatorControl/Commands/FBSimulatorLocationCommands.h b/FBSimulatorControl/Commands/FBSimulatorLocationCommands.h index 34eef9d3e..39787f239 100644 --- a/FBSimulatorControl/Commands/FBSimulatorLocationCommands.h +++ b/FBSimulatorControl/Commands/FBSimulatorLocationCommands.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControl/Commands/FBSimulatorLocationCommands.m b/FBSimulatorControl/Commands/FBSimulatorLocationCommands.m index dab2a613b..69b6e7e45 100644 --- a/FBSimulatorControl/Commands/FBSimulatorLocationCommands.m +++ b/FBSimulatorControl/Commands/FBSimulatorLocationCommands.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControl/Commands/FBSimulatorLogCommands.h b/FBSimulatorControl/Commands/FBSimulatorLogCommands.h index 9ee77aa10..4c202e2e0 100644 --- a/FBSimulatorControl/Commands/FBSimulatorLogCommands.h +++ b/FBSimulatorControl/Commands/FBSimulatorLogCommands.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControl/Commands/FBSimulatorLogCommands.m b/FBSimulatorControl/Commands/FBSimulatorLogCommands.m index b0bee7200..ed46b8c86 100644 --- a/FBSimulatorControl/Commands/FBSimulatorLogCommands.m +++ b/FBSimulatorControl/Commands/FBSimulatorLogCommands.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControl/Commands/FBSimulatorMediaCommands.h b/FBSimulatorControl/Commands/FBSimulatorMediaCommands.h index 4c55604a8..bd7b44c9c 100644 --- a/FBSimulatorControl/Commands/FBSimulatorMediaCommands.h +++ b/FBSimulatorControl/Commands/FBSimulatorMediaCommands.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControl/Commands/FBSimulatorMediaCommands.m b/FBSimulatorControl/Commands/FBSimulatorMediaCommands.m index 1e5e9f2fc..5165e610d 100644 --- a/FBSimulatorControl/Commands/FBSimulatorMediaCommands.m +++ b/FBSimulatorControl/Commands/FBSimulatorMediaCommands.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControl/Commands/FBSimulatorMemoryCommands.h b/FBSimulatorControl/Commands/FBSimulatorMemoryCommands.h index a8db684df..e14675ffe 100644 --- a/FBSimulatorControl/Commands/FBSimulatorMemoryCommands.h +++ b/FBSimulatorControl/Commands/FBSimulatorMemoryCommands.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControl/Commands/FBSimulatorMemoryCommands.m b/FBSimulatorControl/Commands/FBSimulatorMemoryCommands.m index 3d6def626..6afa150e8 100644 --- a/FBSimulatorControl/Commands/FBSimulatorMemoryCommands.m +++ b/FBSimulatorControl/Commands/FBSimulatorMemoryCommands.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControl/Commands/FBSimulatorNotificationCommands.h b/FBSimulatorControl/Commands/FBSimulatorNotificationCommands.h index 3232d8953..07f34586d 100644 --- a/FBSimulatorControl/Commands/FBSimulatorNotificationCommands.h +++ b/FBSimulatorControl/Commands/FBSimulatorNotificationCommands.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControl/Commands/FBSimulatorNotificationCommands.m b/FBSimulatorControl/Commands/FBSimulatorNotificationCommands.m index b43f59873..3f5b15882 100644 --- a/FBSimulatorControl/Commands/FBSimulatorNotificationCommands.m +++ b/FBSimulatorControl/Commands/FBSimulatorNotificationCommands.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControl/Commands/FBSimulatorProcessSpawnCommands.h b/FBSimulatorControl/Commands/FBSimulatorProcessSpawnCommands.h index 874c53e74..77d346baf 100644 --- a/FBSimulatorControl/Commands/FBSimulatorProcessSpawnCommands.h +++ b/FBSimulatorControl/Commands/FBSimulatorProcessSpawnCommands.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControl/Commands/FBSimulatorProcessSpawnCommands.m b/FBSimulatorControl/Commands/FBSimulatorProcessSpawnCommands.m index c21e8d848..8b5ef3a04 100644 --- a/FBSimulatorControl/Commands/FBSimulatorProcessSpawnCommands.m +++ b/FBSimulatorControl/Commands/FBSimulatorProcessSpawnCommands.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -117,8 +117,9 @@ - (instancetype)initWithSimulator:(FBSimulator *)simulator // This would not be an issue if using simctl directly, as the stdout/stderr of the simctl process would close when the simctl process terminates. // However, using the simctl approach, we don't get the pid of the spawned process, this is merely logged internally. // Failing to close this end of the file descriptor would lead to the write-end of any pipe to not be closed and therefore it would leak. - close(attachment.stdOut.fileDescriptor); - close(attachment.stdErr.fileDescriptor); + + [attachment.stdOut close]; + [attachment.stdErr close]; } completionQueue:simulator.workQueue completionHandler:^(NSError *innerError, pid_t processIdentifier){ diff --git a/FBSimulatorControl/Commands/FBSimulatorScreenshotCommands.h b/FBSimulatorControl/Commands/FBSimulatorScreenshotCommands.h index 84af955a1..e3d260103 100644 --- a/FBSimulatorControl/Commands/FBSimulatorScreenshotCommands.h +++ b/FBSimulatorControl/Commands/FBSimulatorScreenshotCommands.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControl/Commands/FBSimulatorScreenshotCommands.m b/FBSimulatorControl/Commands/FBSimulatorScreenshotCommands.m index b0fbb7280..5b6916e7c 100644 --- a/FBSimulatorControl/Commands/FBSimulatorScreenshotCommands.m +++ b/FBSimulatorControl/Commands/FBSimulatorScreenshotCommands.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControl/Commands/FBSimulatorSettingsCommands.h b/FBSimulatorControl/Commands/FBSimulatorSettingsCommands.h index c8b95eb3c..3a13bb870 100644 --- a/FBSimulatorControl/Commands/FBSimulatorSettingsCommands.h +++ b/FBSimulatorControl/Commands/FBSimulatorSettingsCommands.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -32,10 +32,11 @@ NS_ASSUME_NONNULL_BEGIN @param name preference name @param value preference value + @param type preverence value type. If null defaults to `string`. @param domain preference domain - optional @return a Future that resolves when successful. */ -- (FBFuture *)setPreference:(NSString *)name value:(NSString *)value domain:(nullable NSString *)domain; +- (FBFuture *)setPreference:(NSString *)name value:(NSString *)value type:(nullable NSString *)type domain:(nullable NSString *)domain; /** Gets a preference value by its name and domain. If domain not specified assumed to be Apple Global Domain @@ -52,7 +53,15 @@ NS_ASSUME_NONNULL_BEGIN @param bundleIDs the bundle ids to provide access to. @return A future that resolves when the setting change is complete. */ -- (FBFuture *)grantAccess:(NSSet *)bundleIDs toServices:(NSSet *)services; +- (FBFuture *)grantAccess:(NSSet *)bundleIDs toServices:(NSSet *)services; + +/** + Revokes access to the provided services. + + @param bundleIDs the bundle ids to revoke access to. + @return A future that resolves when the setting change is complete. + */ +- (FBFuture *)revokeAccess:(NSSet *)bundleIDs toServices:(NSSet *)services; /** Grants access to the provided deeplink scheme. @@ -63,6 +72,15 @@ NS_ASSUME_NONNULL_BEGIN */ - (FBFuture *)grantAccess:(NSSet *)bundleIDs toDeeplink:(NSString*)scheme; +/** + Revokes access to the provided deeplink scheme. + + @param bundleIDs the bundle ids to revoke access to. + @param scheme the deeplink scheme + @return A future that resolves when the setting change is complete. + */ +- (FBFuture *)revokeAccess:(NSSet *)bundleIDs toDeeplink:(NSString*)scheme; + /** Updates the contacts on the target, using the provided local databases. Takes local paths to AddressBook Databases. These replace the existing databases for the Address Book. diff --git a/FBSimulatorControl/Commands/FBSimulatorSettingsCommands.m b/FBSimulatorControl/Commands/FBSimulatorSettingsCommands.m index db6e65071..994d30351 100644 --- a/FBSimulatorControl/Commands/FBSimulatorSettingsCommands.m +++ b/FBSimulatorControl/Commands/FBSimulatorSettingsCommands.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -52,11 +52,11 @@ - (instancetype)initWithSimulator:(FBSimulator *)simulator return [FBFuture onQueue:self.simulator.workQueue resolve:^ FBFuture * () { NSError *error = nil; [self.simulator.device setHardwareKeyboardEnabled:enabled keyboardType:0 error:&error]; - + return FBFuture.empty; }]; } - + return [[self.simulator connectToBridge] onQueue:self.simulator.workQueue fmap:^ FBFuture * (FBSimulatorBridge *bridge) { @@ -64,11 +64,11 @@ - (instancetype)initWithSimulator:(FBSimulator *)simulator }]; } -- (FBFuture *)setPreference:(NSString *)name value:(NSString *)value domain:(nullable NSString *)domain; +- (FBFuture *)setPreference:(NSString *)name value:(NSString *)value type:(nullable NSString *)type domain:(nullable NSString *)domain; { return [[FBPreferenceModificationStrategy strategyWithSimulator:self.simulator] - setPreference:name value:value domain:domain]; + setPreference:name value:value type: type domain:domain]; } - (FBFuture *)getCurrentPreference:(NSString *)name domain:(nullable NSString *)domain; @@ -78,7 +78,7 @@ - (instancetype)initWithSimulator:(FBSimulator *)simulator getCurrentPreference:name domain:domain]; } -- (FBFuture *)grantAccess:(NSSet *)bundleIDs toServices:(NSSet *)services +- (FBFuture *)grantAccess:(NSSet *)bundleIDs toServices:(NSSet *)services { // We need at least one approval in the input if (services.count == 0) { @@ -87,7 +87,7 @@ - (instancetype)initWithSimulator:(FBSimulator *)simulator failFuture]; } // We also need at least one bundle id in the input. - if (services.count == 0) { + if (bundleIDs.count == 0) { return [[FBSimulatorError describeFormat:@"Cannot approve %@ since no bundle ids were provided", services] failFuture]; @@ -96,30 +96,43 @@ - (instancetype)initWithSimulator:(FBSimulator *)simulator // Composing different futures due to differences in how these operate. NSMutableArray *> *futures = [NSMutableArray array]; NSMutableSet *toApprove = [NSMutableSet setWithSet:services]; + FBOSVersion *iosVer = [self.simulator osVersion]; + NSDictionary *coreSimulatorSettingMapping; + + if (iosVer.version.majorVersion >= 13) { + coreSimulatorSettingMapping = FBSimulatorSettingsCommands.coreSimulatorSettingMappingPostIos13; + } else { + coreSimulatorSettingMapping = FBSimulatorSettingsCommands.coreSimulatorSettingMappingPreIos13; + } // Go through each of the internal APIs, removing them from the pending set as we go. if ([self.simulator.device respondsToSelector:@selector(setPrivacyAccessForService:bundleID:granted:error:)]) { NSMutableSet *simDeviceServices = [toApprove mutableCopy]; - [simDeviceServices intersectSet:[NSSet setWithArray:FBSimulatorSettingsCommands.coreSimulatorSettingMapping.allKeys]]; + [simDeviceServices intersectSet:[NSSet setWithArray:coreSimulatorSettingMapping.allKeys]]; // Only approve these services, where they are serviced by the CoreSimulator API if (simDeviceServices.count > 0) { + NSMutableSet *internalServices = [NSMutableSet set]; + for (NSString *service in simDeviceServices) { + NSString *internalService = coreSimulatorSettingMapping[service]; + [internalServices addObject:internalService]; + } [toApprove minusSet:simDeviceServices]; - [futures addObject:[self coreSimulatorApproveWithBundleIDs:bundleIDs toServices:simDeviceServices]]; + [futures addObject:[self coreSimulatorApproveWithBundleIDs:bundleIDs toServices:internalServices]]; } } if (toApprove.count > 0 && [[NSSet setWithArray:FBSimulatorSettingsCommands.tccDatabaseMapping.allKeys] intersectsSet:toApprove]) { NSMutableSet *tccServices = [toApprove mutableCopy]; [tccServices intersectSet:[NSSet setWithArray:FBSimulatorSettingsCommands.tccDatabaseMapping.allKeys]]; [toApprove minusSet:tccServices]; - [futures addObject:[self modifyTCCDatabaseWithBundleIDs:bundleIDs toServices:tccServices]]; + [futures addObject:[self modifyTCCDatabaseWithBundleIDs:bundleIDs toServices:tccServices grantAccess:YES]]; } - if (toApprove.count > 0 && [toApprove containsObject:FBSettingsApprovalServiceLocation]) { + if (toApprove.count > 0 && [toApprove containsObject:FBTargetSettingsServiceLocation]) { [futures addObject:[self authorizeLocationSettings:bundleIDs.allObjects]]; - [toApprove removeObject:FBSettingsApprovalServiceLocation]; + [toApprove removeObject:FBTargetSettingsServiceLocation]; } - if (toApprove.count > 0 && [toApprove containsObject:FBSettingsApprovalServiceNotification]) { - [futures addObject:[self authorizeNotificationService:bundleIDs.allObjects]]; - [toApprove removeObject:FBSettingsApprovalServiceNotification]; + if (toApprove.count > 0 && [toApprove containsObject:FBTargetSettingsServiceNotification]) { + [futures addObject:[self updateNotificationService:bundleIDs.allObjects approve:YES]]; + [toApprove removeObject:FBTargetSettingsServiceNotification]; } // Error out if there's nothing we can do to handle a specific approval. @@ -139,6 +152,80 @@ - (instancetype)initWithSimulator:(FBSimulator *)simulator return [[FBFuture futureWithFutures:futures] mapReplace:NSNull.null]; } +- (FBFuture *)revokeAccess:(NSSet *)bundleIDs toServices:(NSSet *)services +{ + // We need at least one revoke in the input + if (services.count == 0) { + return [[FBSimulatorError + describeFormat:@"Cannot revoke any services for %@ since no services were provided", bundleIDs] + failFuture]; + } + // We also need at least one bundle id in the input. + if (bundleIDs.count == 0) { + return [[FBSimulatorError + describeFormat:@"Cannot revoke %@ since no bundle ids were provided", services] + failFuture]; + } + + // Composing different futures due to differences in how these operate. + NSMutableArray *> *futures = [NSMutableArray array]; + NSMutableSet *toRevoke = [NSMutableSet setWithSet:services]; + FBOSVersion *iosVer = [self.simulator osVersion]; + NSDictionary *coreSimulatorSettingMapping; + + if (iosVer.version.majorVersion >= 13) { + coreSimulatorSettingMapping = FBSimulatorSettingsCommands.coreSimulatorSettingMappingPostIos13; + } else { + coreSimulatorSettingMapping = FBSimulatorSettingsCommands.coreSimulatorSettingMappingPreIos13; + } + + // Go through each of the internal APIs, removing them from the pending set as we go. + if ([self.simulator.device respondsToSelector:@selector(setPrivacyAccessForService:bundleID:granted:error:)]) { + NSMutableSet *simDeviceServices = [toRevoke mutableCopy]; + [simDeviceServices intersectSet:[NSSet setWithArray:coreSimulatorSettingMapping.allKeys]]; + // Only revoke these services, where they are serviced by the CoreSimulator API + if (simDeviceServices.count > 0) { + NSMutableSet *internalServices = [NSMutableSet set]; + for (NSString *service in simDeviceServices) { + NSString *internalService = coreSimulatorSettingMapping[service]; + [internalServices addObject:internalService]; + } + [toRevoke minusSet:simDeviceServices]; + [futures addObject:[self coreSimulatorRevokeWithBundleIDs:bundleIDs toServices:internalServices]]; + } + } + if (toRevoke.count > 0 && [[NSSet setWithArray:FBSimulatorSettingsCommands.tccDatabaseMapping.allKeys] intersectsSet:toRevoke]) { + NSMutableSet *tccServices = [toRevoke mutableCopy]; + [tccServices intersectSet:[NSSet setWithArray:FBSimulatorSettingsCommands.tccDatabaseMapping.allKeys]]; + [toRevoke minusSet:tccServices]; + [futures addObject:[self modifyTCCDatabaseWithBundleIDs:bundleIDs toServices:tccServices grantAccess:NO]]; + } + if (toRevoke.count > 0 && [toRevoke containsObject:FBTargetSettingsServiceLocation]) { + [futures addObject:[self revokeLocationSettings:bundleIDs.allObjects]]; + [toRevoke removeObject:FBTargetSettingsServiceLocation]; + } + if (toRevoke.count > 0 && [toRevoke containsObject:FBTargetSettingsServiceNotification]) { + [futures addObject:[self updateNotificationService:bundleIDs.allObjects approve:NO]]; + [toRevoke removeObject:FBTargetSettingsServiceNotification]; + } + + // Error out if there's nothing we can do to handle a specific approval. + if (toRevoke.count > 0) { + return [[FBSimulatorError + describeFormat:@"Cannot approve %@ since there is no handling of it", [FBCollectionInformation oneLineDescriptionFromArray:toRevoke.allObjects]] + failFuture]; + } + // Nothing to do with zero futures. + if (futures.count == 0) { + return FBFuture.empty; + } + // Don't wrap if there's only one future. + if (futures.count == 1) { + return futures.firstObject; + } + return [[FBFuture futureWithFutures:futures] mapReplace:NSNull.null]; +} + - (FBFuture *)grantAccess:(NSSet *)bundleIDs toDeeplink:(NSString *)scheme { if ([scheme length] == 0) { @@ -166,8 +253,7 @@ - (instancetype)initWithSimulator:(FBSimulator *)simulator } } - //Add magic strings to our plist. This is necessary to skip the dialog when using `idb open` - NSString *urlKey = [NSString stringWithFormat:@"com.apple.CoreSimulator.CoreSimulatorBridge-->%@", scheme]; + NSString *urlKey = [FBSimulatorSettingsCommands magicDeeplinkKeyForScheme:scheme]; for (NSString *bundleID in bundleIDs) { schemeApprovalProperties[urlKey] = bundleID; } @@ -193,6 +279,49 @@ - (instancetype)initWithSimulator:(FBSimulator *)simulator return FBFuture.empty; } +- (FBFuture *)revokeAccess:(NSSet *)bundleIDs toDeeplink:(NSString *)scheme +{ + if ([scheme length] == 0) { + return [[FBSimulatorError + describe:@"Empty scheme provided to url revoke"] + failFuture]; + } + if ([bundleIDs count] == 0) { + return [[FBSimulatorError + describe:@"Empty bundleID set provided to url revoke"] + failFuture]; + } + + NSString *preferencesDirectory = [self.simulator.dataDirectory stringByAppendingPathComponent:@"Library/Preferences"]; + NSString *schemeApprovalPlistPath = [preferencesDirectory stringByAppendingPathComponent:@"com.apple.launchservices.schemeapproval.plist"]; + + // Read the existing file if it exists + NSMutableDictionary *schemeApprovalProperties = [NSMutableDictionary new]; + if ([NSFileManager.defaultManager fileExistsAtPath:schemeApprovalPlistPath]) { + schemeApprovalProperties = [[NSDictionary dictionaryWithContentsOfFile:schemeApprovalPlistPath] mutableCopy]; + if (schemeApprovalProperties == nil) { + return [[FBSimulatorError + describeFormat:@"Failed to read the file at %@", schemeApprovalPlistPath] + failFuture]; + } + } else { + // If the file of scheme approvals doesn't exist, then there's nothing we need to revoke + return FBFuture.empty; + } + + NSString *urlKey = [FBSimulatorSettingsCommands magicDeeplinkKeyForScheme:scheme]; + [schemeApprovalProperties removeObjectForKey:urlKey]; + + //Write the plist back + BOOL success = [schemeApprovalProperties writeToFile:schemeApprovalPlistPath atomically:YES]; + if (!success) { + return [[FBSimulatorError + describe:@"Failed to write scheme approval plist"] + failFuture]; + } + return FBFuture.empty; +} + - (FBFuture *)updateContacts:(NSString *)databaseDirectory { // Get and confirm the destination directory exists. @@ -234,7 +363,14 @@ - (instancetype)initWithSimulator:(FBSimulator *)simulator approveLocationServicesForBundleIDs:bundleIDs]; } -- (FBFuture *)authorizeNotificationService:(NSArray *)bundleIDs +- (FBFuture *)revokeLocationSettings:(NSArray *)bundleIDs +{ + return [[FBLocationServicesModificationStrategy + strategyWithSimulator:self.simulator] + revokeLocationServicesForBundleIDs:bundleIDs]; +} + +- (FBFuture *)updateNotificationService:(NSArray *)bundleIDs approve:(BOOL)approved { if ([bundleIDs count] == 0) { return [[FBSimulatorError @@ -261,21 +397,24 @@ - (instancetype)initWithSimulator:(FBSimulator *)simulator if (data == nil) { return [[FBSimulatorError describeFormat:@"No section info for %@", bundleID] failFuture]; } - - NSError *readError = nil; - NSDictionary *properties = [NSPropertyListSerialization propertyListWithData:data options:NSPropertyListMutableContainersAndLeaves format:nil error:&readError]; - if (readError != nil) { - return [FBSimulatorError failFutureWithError:readError]; - } - properties[@"$objects"][2] = bundleID; - properties[@"$objects"][3][@"allowsNotifications"] = @(YES); - - NSError *writeError = nil; - NSData *resultData = [NSPropertyListSerialization dataWithPropertyList:properties format:NSPropertyListBinaryFormat_v1_0 options:0 error:&writeError]; - if (writeError != nil) { - return [FBSimulatorError failFutureWithError:writeError]; - } - sectionInfo[@"sectionInfo"][bundleID] = resultData; + if (approved) { + NSError *readError = nil; + NSDictionary *properties = [NSPropertyListSerialization propertyListWithData:data options:NSPropertyListMutableContainersAndLeaves format:nil error:&readError]; + if (readError != nil) { + return [FBSimulatorError failFutureWithError:readError]; + } + properties[@"$objects"][2] = bundleID; + properties[@"$objects"][3][@"allowsNotifications"] = @(YES); + + NSError *writeError = nil; + NSData *resultData = [NSPropertyListSerialization dataWithPropertyList:properties format:NSPropertyListBinaryFormat_v1_0 options:0 error:&writeError]; + if (writeError != nil) { + return [FBSimulatorError failFutureWithError:writeError]; + } + sectionInfo[@"sectionInfo"][bundleID] = resultData; + } else { + [sectionInfo[@"sectionInfo"] removeObjectForKey:bundleID]; + } } BOOL result = [sectionInfo writeToFile:notificationsApprovalPlistPath atomically:YES]; @@ -292,7 +431,7 @@ - (instancetype)initWithSimulator:(FBSimulator *)simulator } } -- (FBFuture *)modifyTCCDatabaseWithBundleIDs:(NSSet *)bundleIDs toServices:(NSSet *)services +- (FBFuture *)modifyTCCDatabaseWithBundleIDs:(NSSet *)bundleIDs toServices:(NSSet *)services grantAccess:(BOOL)grantAccess { NSString *databasePath = [self.simulator.dataDirectory stringByAppendingPathComponent:@"Library/TCC/TCC.db"]; BOOL isDirectory = YES; @@ -311,32 +450,31 @@ - (instancetype)initWithSimulator:(FBSimulator *)simulator describeFormat:@"Database file at path %@ is not writable", databasePath] failFuture]; } - + id logger = [self.simulator.logger withName:@"sqlite_auth"]; dispatch_queue_t queue = self.simulator.asyncQueue; - return [[[FBSimulatorSettingsCommands - buildRowsForDatabase:databasePath bundleIDs:bundleIDs services:services queue:queue logger:logger] - onQueue:self.simulator.workQueue fmap:^(NSString *rows) { - return [FBSimulatorSettingsCommands - runSqliteCommandOnDatabase:databasePath - arguments:@[[NSString stringWithFormat:@"INSERT or REPLACE INTO access VALUES %@", rows]] - queue:queue - logger:logger]; - }] - mapReplace:NSNull.null]; + if (grantAccess) { + return [self + grantAccessInTCCDatabase:databasePath + bundleIDs:bundleIDs + services:services + queue:queue + logger:logger]; + } else { + return [self + revokeAccessInTCCDatabase:databasePath + bundleIDs:bundleIDs + services:services + queue:queue + logger:logger]; + } } -- (FBFuture *)coreSimulatorApproveWithBundleIDs:(NSSet *)bundleIDs toServices:(NSSet *)services +- (FBFuture *)coreSimulatorApproveWithBundleIDs:(NSSet *)bundleIDs toServices:(NSSet *)services { for (NSString *bundleID in bundleIDs) { - for (NSString *service in services) { - NSString *internalService = FBSimulatorSettingsCommands.coreSimulatorSettingMapping[service]; - if (!internalService) { - return [[FBSimulatorError - describeFormat:@"%@ is not a valid service for CoreSimulator", service] - failFuture]; - } + for (NSString *internalService in services) { NSError *error = nil; if (![self.simulator.device setPrivacyAccessForService:internalService bundleID:bundleID granted:YES error:&error]) { return [FBFuture futureWithError:error]; @@ -346,32 +484,57 @@ - (instancetype)initWithSimulator:(FBSimulator *)simulator return FBFuture.empty; } -+ (NSDictionary *)tccDatabaseMapping +- (FBFuture *)coreSimulatorRevokeWithBundleIDs:(NSSet *)bundleIDs toServices:(NSSet *)services +{ + for (NSString *bundleID in bundleIDs) { + for (NSString *internalService in services) { + NSError *error = nil; + if (![self.simulator.device resetPrivacyAccessForService:internalService bundleID:bundleID error:&error]) { + return [FBFuture futureWithError:error]; + } + } + } + return FBFuture.empty; +} + ++ (NSDictionary *)tccDatabaseMapping { static dispatch_once_t onceToken; - static NSDictionary *mapping; + static NSDictionary *mapping; dispatch_once(&onceToken, ^{ mapping = @{ - FBSettingsApprovalServiceContacts: @"kTCCServiceAddressBook", - FBSettingsApprovalServicePhotos: @"kTCCServicePhotos", - FBSettingsApprovalServiceCamera: @"kTCCServiceCamera", - FBSettingsApprovalServiceMicrophone: @"kTCCServiceMicrophone", + FBTargetSettingsServiceContacts: @"kTCCServiceAddressBook", + FBTargetSettingsServicePhotos: @"kTCCServicePhotos", + FBTargetSettingsServiceCamera: @"kTCCServiceCamera", + FBTargetSettingsServiceMicrophone: @"kTCCServiceMicrophone", }; }); return mapping; } -+ (NSDictionary *)coreSimulatorSettingMapping ++ (NSDictionary *)coreSimulatorSettingMappingPreIos13 { static dispatch_once_t onceToken; - static NSDictionary *mapping; + static NSDictionary *mapping; dispatch_once(&onceToken, ^{ mapping = @{ - FBSettingsApprovalServiceContacts: @"kTCCServiceContactsFull", - FBSettingsApprovalServicePhotos: @"kTCCServicePhotos", - FBSettingsApprovalServiceCamera: @"camera", - FBSettingsApprovalServiceLocation: @"__CoreLocationAlways", - FBSettingsApprovalServiceMicrophone: @"kTCCServiceMicrophone", + FBTargetSettingsServiceContacts: @"kTCCServiceContactsFull", + FBTargetSettingsServicePhotos: @"kTCCServicePhotos", + FBTargetSettingsServiceCamera: @"camera", + FBTargetSettingsServiceLocation: @"__CoreLocationAlways", + FBTargetSettingsServiceMicrophone: @"kTCCServiceMicrophone", + }; + }); + return mapping; +} + ++ (NSDictionary *)coreSimulatorSettingMappingPostIos13 +{ + static dispatch_once_t onceToken; + static NSDictionary *mapping; + dispatch_once(&onceToken, ^{ + mapping = @{ + FBTargetSettingsServiceLocation: @"__CoreLocationAlways", }; }); return mapping; @@ -394,14 +557,56 @@ - (instancetype)initWithSimulator:(FBSimulator *)simulator return filenames; } -+ (NSSet *)filteredTCCApprovals:(NSSet *)approvals ++ (NSSet *)filteredTCCApprovals:(NSSet *)approvals { - NSMutableSet *filtered = [NSMutableSet setWithSet:approvals]; + NSMutableSet *filtered = [NSMutableSet setWithSet:approvals]; [filtered intersectSet:[NSSet setWithArray:self.tccDatabaseMapping.allKeys]]; return [filtered copy]; } -+ (FBFuture *)buildRowsForDatabase:(NSString *)databasePath bundleIDs:(NSSet *)bundleIDs services:(NSSet *)services queue:(dispatch_queue_t)queue logger:(id)logger +- (FBFuture *)grantAccessInTCCDatabase:(NSString *)databasePath bundleIDs:(NSSet *)bundleIDs services:(NSSet *)services queue:(dispatch_queue_t)queue logger:(id)logger +{ + return [[[FBSimulatorSettingsCommands + buildRowsForDatabase:databasePath bundleIDs:bundleIDs services:services queue:queue logger:logger] + onQueue:self.simulator.workQueue fmap:^(NSString *rows) { + return [FBSimulatorSettingsCommands + runSqliteCommandOnDatabase:databasePath + arguments:@[[NSString stringWithFormat:@"INSERT or REPLACE INTO access VALUES %@", rows]] + queue:queue + logger:logger]; + }] + mapReplace:NSNull.null]; +} + +- (FBFuture *)revokeAccessInTCCDatabase:(NSString *)databasePath bundleIDs:(NSSet *)bundleIDs services:(NSSet *)services queue:(dispatch_queue_t)queue logger:(id)logger +{ + NSMutableArray *deletions = [NSMutableArray array]; + for (NSString *bundleID in bundleIDs) { + for (FBTargetSettingsService service in [FBSimulatorSettingsCommands filteredTCCApprovals:services]) { + [deletions addObject: + [NSString stringWithFormat:@"(service = '%@' AND client = '%@')", + [FBSimulatorSettingsCommands tccDatabaseMapping][service], + bundleID] + ]; + } + } + // Nothing to do with no modifications + if (deletions.count == 0) { + return FBFuture.empty; + } + return [ + [FBSimulatorSettingsCommands + runSqliteCommandOnDatabase:databasePath + arguments:@[ + [NSString stringWithFormat:@"DELETE FROM access WHERE %@", + [deletions componentsJoinedByString:@" OR "]] + ] + queue:queue + logger:logger] + mapReplace:NSNull.null]; +} + ++ (FBFuture *)buildRowsForDatabase:(NSString *)databasePath bundleIDs:(NSSet *)bundleIDs services:(NSSet *)services queue:(dispatch_queue_t)queue logger:(id)logger { NSParameterAssert(bundleIDs.count >= 1); NSParameterAssert(services.count >= 1); @@ -409,19 +614,23 @@ - (instancetype)initWithSimulator:(FBSimulator *)simulator return [[self runSqliteCommandOnDatabase:databasePath arguments:@[@".schema access"] queue:queue logger:logger] onQueue:queue map:^(NSString *result) { - if ([result containsString:@"last_modified"]) { + if ([result containsString:@"last_reminded"]) { + return [FBSimulatorSettingsCommands postiOS17ApprovalRowsForBundleIDs:bundleIDs services:services]; + } else if ([result containsString:@"auth_value"]) { + return [FBSimulatorSettingsCommands postiOS15ApprovalRowsForBundleIDs:bundleIDs services:services]; + } else if ([result containsString:@"last_modified"]) { return [FBSimulatorSettingsCommands postiOS12ApprovalRowsForBundleIDs:bundleIDs services:services]; } else { return [FBSimulatorSettingsCommands preiOS12ApprovalRowsForBundleIDs:bundleIDs services:services]; } - }]; + }]; } -+ (NSString *)preiOS12ApprovalRowsForBundleIDs:(NSSet *)bundleIDs services:(NSSet *)services ++ (NSString *)preiOS12ApprovalRowsForBundleIDs:(NSSet *)bundleIDs services:(NSSet *)services { NSMutableArray *tuples = [NSMutableArray array]; for (NSString *bundleID in bundleIDs) { - for (FBSettingsApprovalService service in [self filteredTCCApprovals:services]) { + for (FBTargetSettingsService service in [self filteredTCCApprovals:services]) { NSString *serviceName = self.tccDatabaseMapping[service]; [tuples addObject:[NSString stringWithFormat:@"('%@', '%@', 0, 1, 0, 0, 0)", serviceName, bundleID]]; } @@ -429,12 +638,12 @@ + (NSString *)preiOS12ApprovalRowsForBundleIDs:(NSSet *)bundleIDs se return [tuples componentsJoinedByString:@", "]; } -+ (NSString *)postiOS12ApprovalRowsForBundleIDs:(NSSet *)bundleIDs services:(NSSet *)services ++ (NSString *)postiOS12ApprovalRowsForBundleIDs:(NSSet *)bundleIDs services:(NSSet *)services { NSUInteger timestamp = (NSUInteger) NSDate.date.timeIntervalSince1970; NSMutableArray *tuples = [NSMutableArray array]; for (NSString *bundleID in bundleIDs) { - for (FBSettingsApprovalService service in [self filteredTCCApprovals:services]) { + for (FBTargetSettingsService service in [self filteredTCCApprovals:services]) { NSString *serviceName = self.tccDatabaseMapping[service]; [tuples addObject:[NSString stringWithFormat:@"('%@', '%@', 0, 1, 1, NULL, NULL, NULL, 'UNUSED', NULL, NULL, %lu)", serviceName, bundleID, timestamp]]; } @@ -442,6 +651,59 @@ + (NSString *)postiOS12ApprovalRowsForBundleIDs:(NSSet *)bundleIDs s return [tuples componentsJoinedByString:@", "]; } ++ (NSString *)postiOS15ApprovalRowsForBundleIDs:(NSSet *)bundleIDs services:(NSSet *)services +{ + NSUInteger timestamp = (NSUInteger) NSDate.date.timeIntervalSince1970; + NSMutableArray *tuples = [NSMutableArray array]; + for (NSString *bundleID in bundleIDs) { + for (FBTargetSettingsService service in [self filteredTCCApprovals:services]) { + NSString *serviceName = self.tccDatabaseMapping[service]; + // The first 2 is for auth_value, 2 corresponds to "allowed" + // The other two 2 and 2 that we set here correspond to auth_reason and auth_version + // Both has to be 2 for AVCaptureDevice.authorizationStatus(... to return something different from notDetermined + // It is also possible that in the future auth_version has to be bumped up to 3 and above with newer minor version of iOS + [tuples addObject:[NSString stringWithFormat:@"('%@', '%@', 0, 2, 2, 2, NULL, NULL, NULL, 'UNUSED', NULL, NULL, %lu)", serviceName, bundleID, timestamp]]; + } + } + return [tuples componentsJoinedByString:@", "]; +} + ++ (NSString *)postiOS17ApprovalRowsForBundleIDs:(NSSet *)bundleIDs services:(NSSet *)services +{ + NSUInteger timestamp = (NSUInteger) NSDate.date.timeIntervalSince1970; + NSMutableArray *tuples = [NSMutableArray array]; + for (NSString *bundleID in bundleIDs) { + for (FBTargetSettingsService service in [self filteredTCCApprovals:services]) { + NSString *serviceName = self.tccDatabaseMapping[service]; + // iOS 17 access table schema: + // CREATE TABLE access ( + // service TEXT NOT NULL, + // client TEXT NOT NULL, + // client_type INTEGER NOT NULL, + // auth_value INTEGER NOT NULL, + // auth_reason INTEGER NOT NULL, + // auth_version INTEGER NOT NULL, + // csreq BLOB, + // policy_id INTEGER, + // indirect_object_identifier_type INTEGER, + // indirect_object_identifier TEXT NOT NULL DEFAULT 'UNUSED', + // indirect_object_code_identity BLOB, + // flags INTEGER, + // last_modified INTEGER NOT NULL DEFAULT (CAST(strftime('%s','now') AS INTEGER)), + // pid INTEGER, + // pid_version INTEGER, + // boot_uuid TEXT NOT NULL DEFAULT 'UNUSED', + // last_reminded INTEGER NOT NULL DEFAULT (CAST(strftime('%s','now') AS INTEGER)), + // PRIMARY KEY (service, client, client_type, indirect_object_identifier), + // FOREIGN KEY (policy_id) REFERENCES policies(id) ON DELETE CASCADE ON UPDATE CASCADE + // ); + + [tuples addObject:[NSString stringWithFormat:@"('%@', '%@', 0, 2, 2, 2, NULL, NULL, NULL, 'UNUSED', NULL, NULL, %lu, NULL, NULL, 'UNUSED', %lu)", serviceName, bundleID, timestamp, timestamp]]; + } + } + return [tuples componentsJoinedByString:@", "]; +} + + (FBFuture *)runSqliteCommandOnDatabase:(NSString *)databasePath arguments:(NSArray *)arguments queue:(dispatch_queue_t)queue logger:(id)logger { arguments = [@[databasePath] arrayByAddingObjectsFromArray:arguments]; @@ -491,5 +753,9 @@ + (NSString *)postiOS12ApprovalRowsForBundleIDs:(NSSet *)bundleIDs s return [filePaths copy]; } -@end +//Add magic strings to our plist. This is necessary to skip the dialog when using `idb open` ++ (NSString *)magicDeeplinkKeyForScheme:(NSString *)scheme { + return [NSString stringWithFormat:@"com.apple.CoreSimulator.CoreSimulatorBridge-->%@", scheme]; +} +@end diff --git a/FBSimulatorControl/Commands/FBSimulatorVideoRecordingCommands.h b/FBSimulatorControl/Commands/FBSimulatorVideoRecordingCommands.h index 18f41d412..0752a41be 100644 --- a/FBSimulatorControl/Commands/FBSimulatorVideoRecordingCommands.h +++ b/FBSimulatorControl/Commands/FBSimulatorVideoRecordingCommands.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControl/Commands/FBSimulatorVideoRecordingCommands.m b/FBSimulatorControl/Commands/FBSimulatorVideoRecordingCommands.m index f2db19380..4557436c8 100644 --- a/FBSimulatorControl/Commands/FBSimulatorVideoRecordingCommands.m +++ b/FBSimulatorControl/Commands/FBSimulatorVideoRecordingCommands.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControl/Commands/FBSimulatorXCTestCommands.h b/FBSimulatorControl/Commands/FBSimulatorXCTestCommands.h index f02edc953..3ae0d8ac7 100644 --- a/FBSimulatorControl/Commands/FBSimulatorXCTestCommands.h +++ b/FBSimulatorControl/Commands/FBSimulatorXCTestCommands.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControl/Commands/FBSimulatorXCTestCommands.m b/FBSimulatorControl/Commands/FBSimulatorXCTestCommands.m index b90bf4d33..e36da5cb9 100644 --- a/FBSimulatorControl/Commands/FBSimulatorXCTestCommands.m +++ b/FBSimulatorControl/Commands/FBSimulatorXCTestCommands.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -68,7 +68,7 @@ - (instancetype)initWithSimulator:(FBSimulator *)simulator self.isRunningXcodeBuildOperation = YES; return [self _startTestWithLaunchConfiguration:testLaunchConfiguration logger:logger]; }] - onQueue:self.simulator.workQueue map:^(FBProcess *task) { + onQueue:self.simulator.workQueue fmap:^(FBProcess *task) { return [FBXcodeBuildOperation confirmExitOfXcodebuildOperation:task configuration:testLaunchConfiguration reporter:reporter target:self.simulator logger:logger]; }] onQueue:self.simulator.workQueue chain:^(FBFuture *future) { @@ -125,13 +125,20 @@ - (instancetype)initWithSimulator:(FBSimulator *)simulator - (FBFuture *> *)listTestsForBundleAtPath:(NSString *)bundlePath timeout:(NSTimeInterval)timeout withAppAtPath:(NSString *)appPath { + NSError *error = nil; + FBBundleDescriptor *bundleDescriptor = [FBBundleDescriptor bundleWithFallbackIdentifierFromPath:bundlePath error:&error]; + if (!bundleDescriptor) { + return [FBFuture futureWithError:error]; + } + FBListTestConfiguration *configuration = [FBListTestConfiguration configurationWithEnvironment:@{} workingDirectory:self.simulator.auxillaryDirectory testBundlePath:bundlePath runnerAppPath:appPath waitForDebugger:NO - timeout:timeout]; + timeout:timeout + architectures:bundleDescriptor.binary.architectures]; return [[[FBListTestStrategy alloc] initWithTarget:self.simulator configuration:configuration logger:self.simulator.logger] diff --git a/FBSimulatorControl/Configuration/FBSimulatorBootConfiguration.h b/FBSimulatorControl/Configuration/FBSimulatorBootConfiguration.h index f747ac70a..187e55292 100644 --- a/FBSimulatorControl/Configuration/FBSimulatorBootConfiguration.h +++ b/FBSimulatorControl/Configuration/FBSimulatorBootConfiguration.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControl/Configuration/FBSimulatorBootConfiguration.m b/FBSimulatorControl/Configuration/FBSimulatorBootConfiguration.m index 7367d8c93..b06f62193 100644 --- a/FBSimulatorControl/Configuration/FBSimulatorBootConfiguration.m +++ b/FBSimulatorControl/Configuration/FBSimulatorBootConfiguration.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControl/Configuration/FBSimulatorConfiguration+CoreSimulator.h b/FBSimulatorControl/Configuration/FBSimulatorConfiguration+CoreSimulator.h index 3125f6be3..d13b86a3e 100644 --- a/FBSimulatorControl/Configuration/FBSimulatorConfiguration+CoreSimulator.h +++ b/FBSimulatorControl/Configuration/FBSimulatorConfiguration+CoreSimulator.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControl/Configuration/FBSimulatorConfiguration+CoreSimulator.m b/FBSimulatorControl/Configuration/FBSimulatorConfiguration+CoreSimulator.m index d4cace36b..81656051a 100644 --- a/FBSimulatorControl/Configuration/FBSimulatorConfiguration+CoreSimulator.m +++ b/FBSimulatorControl/Configuration/FBSimulatorConfiguration+CoreSimulator.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControl/Configuration/FBSimulatorConfiguration.h b/FBSimulatorControl/Configuration/FBSimulatorConfiguration.h index 4ed557537..0e859be96 100644 --- a/FBSimulatorControl/Configuration/FBSimulatorConfiguration.h +++ b/FBSimulatorControl/Configuration/FBSimulatorConfiguration.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControl/Configuration/FBSimulatorConfiguration.m b/FBSimulatorControl/Configuration/FBSimulatorConfiguration.m index 2648bc0f7..0ffa0f2bc 100644 --- a/FBSimulatorControl/Configuration/FBSimulatorConfiguration.m +++ b/FBSimulatorControl/Configuration/FBSimulatorConfiguration.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -87,16 +87,15 @@ - (BOOL)isEqual:(FBSimulatorConfiguration *)object return [self.deviceModel isEqualToString:object.deviceModel] && [self.osVersionString isEqualToString:object.osVersionString]; - + } - (NSString *)description { return [NSString stringWithFormat: - @"Device '%@' | OS Version '%@' | Architecture '%@'", + @"Device '%@' | OS Version '%@'", self.deviceModel, - self.osVersionString, - self.architecture + self.osVersionString ]; } @@ -129,9 +128,11 @@ - (instancetype)withOS:(FBOSVersion *)os - (instancetype)withDevice:(FBDeviceType *)device { NSParameterAssert(device); - // Use the current os if compatible + // Use the current os if compatible. + // If os.families is empty, it was probably created via [FBOSVersion +genericWithName:] + // which has no information about families; in that case we assume it is compatible. FBOSVersion *os = self.os; - if ([FBSimulatorConfiguration device:device andOSPairSupported:os]) { + if (!os.families.count || [os.families containsObject:@(device.family)]) { return [[FBSimulatorConfiguration alloc] initWithNamedDevice:device os:os]; } // Attempt to find the newest OS for this device, otherwise use what we had before. @@ -141,11 +142,6 @@ - (instancetype)withDevice:(FBDeviceType *)device #pragma mark Private -+ (BOOL)device:(FBDeviceType *)device andOSPairSupported:(FBOSVersion *)os -{ - return [os.families containsObject:@(device.family)]; -} - - (FBDeviceModel)deviceModel { return self.device.model; @@ -156,9 +152,4 @@ - (FBOSVersionName)osVersionString return self.os.name; } -- (FBArchitecture)architecture -{ - return self.device.simulatorArchitecture; -} - @end diff --git a/FBSimulatorControl/Configuration/FBSimulatorControlConfiguration.h b/FBSimulatorControl/Configuration/FBSimulatorControlConfiguration.h index ca4307ebf..bc764960c 100644 --- a/FBSimulatorControl/Configuration/FBSimulatorControlConfiguration.h +++ b/FBSimulatorControl/Configuration/FBSimulatorControlConfiguration.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControl/Configuration/FBSimulatorControlConfiguration.m b/FBSimulatorControl/Configuration/FBSimulatorControlConfiguration.m index e82cba0cf..3bfb3ca2d 100644 --- a/FBSimulatorControl/Configuration/FBSimulatorControlConfiguration.m +++ b/FBSimulatorControl/Configuration/FBSimulatorControlConfiguration.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControl/FBSimulatorControl.h b/FBSimulatorControl/FBSimulatorControl.h index a46dd5ddb..53cb83e78 100644 --- a/FBSimulatorControl/FBSimulatorControl.h +++ b/FBSimulatorControl/FBSimulatorControl.h @@ -1,16 +1,14 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ -#import #import #import #import #import -#import #import #import #import @@ -18,14 +16,12 @@ #import #import #import -#import #import #import #import #import #import #import -#import #import #import #import diff --git a/FBSimulatorControl/FBSimulatorControl.xcconfig b/FBSimulatorControl/FBSimulatorControl.xcconfig index e960e692c..e9f9d8af5 100644 --- a/FBSimulatorControl/FBSimulatorControl.xcconfig +++ b/FBSimulatorControl/FBSimulatorControl.xcconfig @@ -2,9 +2,6 @@ #include "../Configuration/Shared.xcconfig" #include "../Configuration/Framework.xcconfig" -// Weak-Link Xcode Private Frameworks -OTHER_LDFLAGS = $(inherited) -weak_framework CoreSimulator -weak_framework SimulatorKit - // Target-Specific Settings INFOPLIST_FILE = $(SRCROOT)/FBSimulatorControl/FBSimulatorControl-Info.plist; PRODUCT_BUNDLE_IDENTIFIER = com.facebook.FBSimulatorControl diff --git a/FBSimulatorControl/Framebuffer/FBFramebuffer.h b/FBSimulatorControl/Framebuffer/FBFramebuffer.h index 25024089b..a75f73d44 100644 --- a/FBSimulatorControl/Framebuffer/FBFramebuffer.h +++ b/FBSimulatorControl/Framebuffer/FBFramebuffer.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControl/Framebuffer/FBFramebuffer.m b/FBSimulatorControl/Framebuffer/FBFramebuffer.m index 95c0f03d3..1191cc333 100644 --- a/FBSimulatorControl/Framebuffer/FBFramebuffer.m +++ b/FBSimulatorControl/Framebuffer/FBFramebuffer.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -166,16 +166,24 @@ - (instancetype)initWithSurface:(id)consumer uuid:(NSUUID *)uuid queue:(dispatch_queue_t)queue { - [self.surface registerCallbackWithUUID:uuid ioSurfaceChangeCallback:^(IOSurface *surface) { + void (^ioSurfaceChanged)(IOSurface *) = ^void(IOSurface *surface) { dispatch_async(queue, ^{ [consumer didChangeIOSurface:surface]; }); - }]; + }; + + [self.surface registerCallbackWithUUID:uuid ioSurfacesChangeCallback:ioSurfaceChanged]; + [self.surface registerCallbackWithUUID:uuid ioSurfaceChangeCallback:ioSurfaceChanged]; + [self.surface registerCallbackWithUUID:uuid damageRectanglesCallback:^(NSArray *frames) { dispatch_async(queue, ^{ for (NSValue *value in frames) { @@ -187,7 +195,9 @@ - (void)registerConsumer:(id)consumer uuid:(NSUUID *)uuid - (void)unregisterConsumer:(id)consumer uuid:(NSUUID *)uuid { + [self.surface unregisterIOSurfacesChangeCallbackWithUUID:uuid]; [self.surface unregisterIOSurfaceChangeCallbackWithUUID:uuid]; + [self.surface unregisterDamageRectanglesCallbackWithUUID:uuid]; } diff --git a/FBSimulatorControl/Framebuffer/FBSimulatorImage.h b/FBSimulatorControl/Framebuffer/FBSimulatorImage.h index c848a21e3..c35b4bb23 100644 --- a/FBSimulatorControl/Framebuffer/FBSimulatorImage.h +++ b/FBSimulatorControl/Framebuffer/FBSimulatorImage.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControl/Framebuffer/FBSimulatorImage.m b/FBSimulatorControl/Framebuffer/FBSimulatorImage.m index d9b8ff919..816af2c17 100644 --- a/FBSimulatorControl/Framebuffer/FBSimulatorImage.m +++ b/FBSimulatorControl/Framebuffer/FBSimulatorImage.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControl/Framebuffer/FBSimulatorVideo.h b/FBSimulatorControl/Framebuffer/FBSimulatorVideo.h index 8340caa4f..413d0e272 100644 --- a/FBSimulatorControl/Framebuffer/FBSimulatorVideo.h +++ b/FBSimulatorControl/Framebuffer/FBSimulatorVideo.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControl/Framebuffer/FBSimulatorVideo.m b/FBSimulatorControl/Framebuffer/FBSimulatorVideo.m index 4a54d9ae0..86828462b 100644 --- a/FBSimulatorControl/Framebuffer/FBSimulatorVideo.m +++ b/FBSimulatorControl/Framebuffer/FBSimulatorVideo.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControl/Framebuffer/FBSimulatorVideoStream.h b/FBSimulatorControl/Framebuffer/FBSimulatorVideoStream.h index d19870c57..3c672c2c4 100644 --- a/FBSimulatorControl/Framebuffer/FBSimulatorVideoStream.h +++ b/FBSimulatorControl/Framebuffer/FBSimulatorVideoStream.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControl/Framebuffer/FBSimulatorVideoStream.m b/FBSimulatorControl/Framebuffer/FBSimulatorVideoStream.m index 9bc604df6..471f19a78 100644 --- a/FBSimulatorControl/Framebuffer/FBSimulatorVideoStream.m +++ b/FBSimulatorControl/Framebuffer/FBSimulatorVideoStream.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -12,9 +12,21 @@ #import #import #import +#import #import "FBSimulatorError.h" +@interface FBVideoCompressorCallbackSourceFrame : NSObject + +- (instancetype)initWithPixelBuffer:(CVPixelBufferRef)pixelBuffer frameNumber:(NSUInteger)frameNumber; +- (void)dealloc; + +@property (nonatomic, readonly) NSUInteger frameNumber; +@property (nonatomic, assign, nullable, readwrite) CVPixelBufferRef pixelBuffer; + +@end + + @protocol FBSimulatorVideoStreamFramePusher - (BOOL)setupWithPixelBuffer:(CVPixelBufferRef)pixelBuffer error:(NSError **)error; @@ -25,9 +37,14 @@ - (BOOL)writeEncodedFrame:(CVPixelBufferRef)pixelBuffer frameNumber:(NSUInteger) @interface FBSimulatorVideoStreamFramePusher_Bitmap : NSObject -- (instancetype)initWithConsumer:(id)consumer; +- (instancetype)initWithConsumer:(id)consumer scaleFactor:(NSNumber *)scaleFactor; @property (nonatomic, strong, readonly) id consumer; +/** + The scale factor between 0-1. nil for no scaling. + */ +@property (nonatomic, copy, nullable, readonly) NSNumber *scaleFactor; +@property (nonatomic, assign, nullable, readwrite) CVPixelBufferPoolRef scaledPixelBufferPoolRef; @end @@ -37,6 +54,7 @@ - (instancetype)initWithConfiguration:(FBVideoStreamConfiguration *)configuratio @property (nonatomic, copy, readonly) FBVideoStreamConfiguration *configuration; @property (nonatomic, assign, nullable, readwrite) VTCompressionSessionRef compressionSession; +@property (nonatomic, assign, nullable, readwrite) CVPixelBufferPoolRef scaledPixelBufferPoolRef; @property (nonatomic, assign, readonly) CMVideoCodecType videoCodec; @property (nonatomic, assign, readonly) VTCompressionOutputCallback compressorCallback; @property (nonatomic, strong, readonly) id logger; @@ -45,14 +63,91 @@ - (instancetype)initWithConfiguration:(FBVideoStreamConfiguration *)configuratio @end +static CVPixelBufferPoolRef createScaledPixelBufferPool(CVPixelBufferRef sourceBuffer, NSNumber *scaleFactor) { + size_t sourceWidth = CVPixelBufferGetWidth(sourceBuffer); + size_t sourceHeight = CVPixelBufferGetHeight(sourceBuffer); + + size_t destinationWidth = (size_t) floor(scaleFactor.doubleValue * (double)sourceWidth); + size_t destinationHeight = (size_t) floor(scaleFactor.doubleValue * (double) sourceHeight); + + NSDictionary *pixelBufferAttributes = @{ + (NSString *) kCVPixelBufferWidthKey: @(destinationWidth), + (NSString *) kCVPixelBufferHeightKey: @(destinationHeight), + (NSString *) kCVPixelBufferPixelFormatTypeKey: @(CVPixelBufferGetPixelFormatType(sourceBuffer)), + }; + + NSDictionary *pixelBufferPoolAttributes = @{ + (NSString *) kCVPixelBufferPoolMinimumBufferCountKey: @(100), // we will have at least 100 pixel buffers in the pool + (NSString *) kCVPixelBufferPoolAllocationThresholdKey: @(250), // to guard from OOM only 250 pixel buffers are allowed + }; + + + CVPixelBufferPoolRef scaledPixelBufferPool; + CVPixelBufferPoolCreate(nil, (__bridge CFDictionaryRef) pixelBufferPoolAttributes, (__bridge CFDictionaryRef) pixelBufferAttributes, &scaledPixelBufferPool); + + return scaledPixelBufferPool; +} + +static NSDictionary *FBBitmapStreamPixelBufferAttributesFromPixelBuffer(CVPixelBufferRef pixelBuffer) +{ + size_t width = CVPixelBufferGetWidth(pixelBuffer); + size_t height = CVPixelBufferGetHeight(pixelBuffer); + size_t frameSize = CVPixelBufferGetDataSize(pixelBuffer); + size_t rowSize = CVPixelBufferGetBytesPerRow(pixelBuffer); + OSType pixelFormat = CVPixelBufferGetPixelFormatType(pixelBuffer); + NSString *pixelFormatString = (__bridge_transfer NSString *) UTCreateStringForOSType(pixelFormat); + + size_t columnLeft; + size_t columnRight; + size_t rowsTop; + size_t rowsBottom; + + CVPixelBufferGetExtendedPixels(pixelBuffer, &columnLeft, &columnRight, &rowsTop, &rowsBottom); + return @{ + @"width" : @(width), + @"height" : @(height), + @"row_size" : @(rowSize), + @"frame_size" : @(frameSize), + @"padding_column_left" : @(columnLeft), + @"padding_column_right" : @(columnRight), + @"padding_row_top" : @(rowsTop), + @"padding_row_bottom" : @(rowsBottom), + @"format" : pixelFormatString, + }; +} + +static void scaleFromSourceToDestinationBuffer(CVPixelBufferRef sourceBuffer, CVPixelBufferRef destinationBuffer) { + CVPixelBufferLockBaseAddress(sourceBuffer, kCVPixelBufferLock_ReadOnly); + CVPixelBufferLockBaseAddress(destinationBuffer, kCVPixelBufferLock_ReadOnly); + + vImage_Buffer scaleInput; + scaleInput.width = CVPixelBufferGetWidth(sourceBuffer); + scaleInput.height = CVPixelBufferGetHeight(sourceBuffer); + scaleInput.rowBytes = CVPixelBufferGetBytesPerRow(sourceBuffer); + scaleInput.data = CVPixelBufferGetBaseAddress(sourceBuffer); + + vImage_Buffer scaleOutput; + scaleOutput.width = CVPixelBufferGetWidth(destinationBuffer); + scaleOutput.height = CVPixelBufferGetHeight((destinationBuffer)); + scaleOutput.rowBytes = CVPixelBufferGetBytesPerRow(destinationBuffer); + scaleOutput.data = CVPixelBufferGetBaseAddress(destinationBuffer); + + vImageScale_ARGB8888(&scaleInput, &scaleOutput, NULL, 0); // implicitly assumes a 4-channel image, like BGRA/RGBA + + CVPixelBufferUnlockBaseAddress(sourceBuffer, kCVPixelBufferLock_ReadOnly); + CVPixelBufferUnlockBaseAddress(destinationBuffer, kCVPixelBufferLock_ReadOnly); +} + static void H264AnnexBCompressorCallback(void *outputCallbackRefCon, void *sourceFrameRefCon, OSStatus encodeStats, VTEncodeInfoFlags infoFlags, CMSampleBufferRef sampleBuffer) { + (void)(__bridge_transfer FBVideoCompressorCallbackSourceFrame *)(sourceFrameRefCon); FBSimulatorVideoStreamFramePusher_VideoToolbox *pusher = (__bridge FBSimulatorVideoStreamFramePusher_VideoToolbox *)(outputCallbackRefCon); WriteFrameToAnnexBStream(sampleBuffer, pusher.consumer, pusher.logger, nil); } static void MJPEGCompressorCallback(void *outputCallbackRefCon, void *sourceFrameRefCon, OSStatus encodeStats, VTEncodeInfoFlags infoFlags, CMSampleBufferRef sampleBuffer) { + (void)(__bridge_transfer FBVideoCompressorCallbackSourceFrame *)(sourceFrameRefCon); FBSimulatorVideoStreamFramePusher_VideoToolbox *pusher = (__bridge FBSimulatorVideoStreamFramePusher_VideoToolbox *)(outputCallbackRefCon); CMBlockBufferRef blockBufffer = CMSampleBufferGetDataBuffer(sampleBuffer); WriteJPEGDataToMJPEGStream(blockBufffer, pusher.consumer, pusher.logger, nil); @@ -60,7 +155,8 @@ static void MJPEGCompressorCallback(void *outputCallbackRefCon, void *sourceFram static void MinicapCompressorCallback(void *outputCallbackRefCon, void *sourceFrameRefCon, OSStatus encodeStats, VTEncodeInfoFlags infoFlags, CMSampleBufferRef sampleBuffer) { - NSUInteger frameNumber = (NSUInteger) sourceFrameRefCon; + FBVideoCompressorCallbackSourceFrame *sourceFrame = (__bridge_transfer FBVideoCompressorCallbackSourceFrame*) sourceFrameRefCon; + NSUInteger frameNumber = sourceFrame.frameNumber; FBSimulatorVideoStreamFramePusher_VideoToolbox *pusher = (__bridge FBSimulatorVideoStreamFramePusher_VideoToolbox *)(outputCallbackRefCon); if (frameNumber == 0) { CMFormatDescriptionRef formatDescription = CMSampleBufferGetFormatDescription(sampleBuffer); @@ -71,9 +167,32 @@ static void MinicapCompressorCallback(void *outputCallbackRefCon, void *sourceFr WriteJPEGDataToMinicapStream(blockBufffer, pusher.consumer, pusher.logger, nil); } +@implementation FBVideoCompressorCallbackSourceFrame + +- (instancetype)initWithPixelBuffer:(CVPixelBufferRef)pixelBuffer frameNumber:(NSUInteger)frameNumber +{ + self = [super init]; + if (!self) { + return nil; + } + + _pixelBuffer = pixelBuffer; + _frameNumber = frameNumber; + + return self; +} + +- (void) dealloc +{ + CVPixelBufferRelease(_pixelBuffer); +} + +@end + + @implementation FBSimulatorVideoStreamFramePusher_Bitmap -- (instancetype)initWithConsumer:(id)consumer +- (instancetype)initWithConsumer:(id)consumer scaleFactor:(NSNumber *)scaleFactor { self = [super init]; if (!self) { @@ -81,26 +200,44 @@ - (instancetype)initWithConsumer:(id)consumer } _consumer = consumer; - + _scaleFactor = scaleFactor; + return self; } - (BOOL)setupWithPixelBuffer:(CVPixelBufferRef)pixelBuffer error:(NSError **)error { + if (self.scaleFactor && [self.scaleFactor isGreaterThan:@0] && [self.scaleFactor isLessThan:@1]) { + self.scaledPixelBufferPoolRef = createScaledPixelBufferPool(pixelBuffer, self.scaleFactor); + } return YES; } - (BOOL)tearDown:(NSError **)error { + CVPixelBufferPoolRelease(self.scaledPixelBufferPoolRef); return YES; } - (BOOL)writeEncodedFrame:(CVPixelBufferRef)pixelBuffer frameNumber:(NSUInteger)frameNumber timeAtFirstFrame:(CFTimeInterval)timeAtFirstFrame error:(NSError **)error { - CVPixelBufferLockBaseAddress(pixelBuffer, kCVPixelBufferLock_ReadOnly); + CVPixelBufferRef bufferToWrite = pixelBuffer; + CVPixelBufferRef toFree = nil; + CVPixelBufferPoolRef bufferPool = self.scaledPixelBufferPoolRef; + if (bufferPool != nil) { + CVPixelBufferRef resizedBuffer; + if (kCVReturnSuccess == CVPixelBufferPoolCreatePixelBuffer(nil, bufferPool, &resizedBuffer)) { + scaleFromSourceToDestinationBuffer(pixelBuffer, resizedBuffer); + bufferToWrite = resizedBuffer; + toFree = resizedBuffer; + } + } - void *baseAddress = CVPixelBufferGetBaseAddress(pixelBuffer); - size_t size = CVPixelBufferGetDataSize(pixelBuffer); + CVPixelBufferLockBaseAddress(bufferToWrite, kCVPixelBufferLock_ReadOnly); + + void *baseAddress = CVPixelBufferGetBaseAddress(bufferToWrite); + size_t size = CVPixelBufferGetDataSize(bufferToWrite); + if ([self.consumer conformsToProtocol:@protocol(FBDataConsumerSync)]) { NSData *data = [NSData dataWithBytesNoCopy:baseAddress length:size freeWhenDone:NO]; [self.consumer consumeData:data]; @@ -109,7 +246,8 @@ - (BOOL)writeEncodedFrame:(CVPixelBufferRef)pixelBuffer frameNumber:(NSUInteger) [self.consumer consumeData:data]; } - CVPixelBufferUnlockBaseAddress(pixelBuffer, kCVPixelBufferLock_ReadOnly); + CVPixelBufferUnlockBaseAddress(bufferToWrite, kCVPixelBufferLock_ReadOnly); + CVPixelBufferRelease(toFree); return YES; } @@ -140,29 +278,37 @@ - (BOOL)setupWithPixelBuffer:(CVPixelBufferRef)pixelBuffer error:(NSError **)err NSDictionary * encoderSpecification = @{ (NSString *) kVTVideoEncoderSpecification_EnableHardwareAcceleratedVideoEncoder: @YES, }; + + if (@available(macOS 12.1, *)) { + encoderSpecification = @{ + (NSString *) kVTVideoEncoderSpecification_RequireHardwareAcceleratedVideoEncoder: @YES, + (NSString *) kVTVideoEncoderSpecification_EnableLowLatencyRateControl: @YES, + }; + } size_t sourceWidth = CVPixelBufferGetWidth(pixelBuffer); size_t sourceHeight = CVPixelBufferGetHeight(pixelBuffer); - int32_t destinationWidth = (int32_t) sourceWidth; - int32_t destinationHeight = (int32_t) sourceHeight; - NSDictionary *sourceImageBufferAttributes = @{ - (NSString *) kCVPixelBufferWidthKey: @(sourceWidth), - (NSString *) kCVPixelBufferHeightKey: @(sourceHeight), - }; + size_t destinationWidth = sourceWidth; + size_t destinationHeight = sourceHeight; NSNumber *scaleFactor = self.configuration.scaleFactor; if (scaleFactor && [scaleFactor isGreaterThan:@0] && [scaleFactor isLessThan:@1]) { - destinationWidth = (int32_t) floor(scaleFactor.doubleValue * sourceWidth); - destinationHeight = (int32_t) floor(scaleFactor.doubleValue * sourceHeight); - [self.logger.info logFormat:@"Applying %@ scale from w=%zu/h=%zu to w=%d/h=%d", scaleFactor, sourceWidth, sourceHeight, destinationWidth, destinationHeight]; + CVPixelBufferPoolRef scaledPixelBufferPool = createScaledPixelBufferPool(pixelBuffer, scaleFactor); + CFDictionaryRef bufferPoolPixelAttributes = CVPixelBufferPoolGetPixelBufferAttributes(scaledPixelBufferPool); + NSNumber *scaledBufferWidth = (NSNumber *) CFDictionaryGetValue(bufferPoolPixelAttributes, kCVPixelBufferWidthKey); + NSNumber *scaledBufferHeight = (NSNumber *) CFDictionaryGetValue(bufferPoolPixelAttributes, kCVPixelBufferHeightKey); + destinationWidth = (size_t)scaledBufferWidth.intValue; + destinationHeight = (size_t)scaledBufferHeight.intValue; + self.scaledPixelBufferPoolRef = scaledPixelBufferPool; + [self.logger.info logFormat:@"Applying %@ scale from w=%zu/h=%zu to w=%zu/h=%zu", scaleFactor, sourceWidth, sourceHeight, destinationWidth, destinationHeight]; } VTCompressionSessionRef compressionSession = NULL; OSStatus status = VTCompressionSessionCreate( nil, // Allocator - destinationWidth, - destinationHeight, + (int32_t) destinationWidth, + (int32_t) destinationHeight, self.videoCodec, (__bridge CFDictionaryRef) encoderSpecification, - (__bridge CFDictionaryRef) sourceImageBufferAttributes, + nil, nil, // Compressed Data Allocator self.compressorCallback, (__bridge void * _Nullable)(self), // Callback Ref. @@ -173,6 +319,7 @@ - (BOOL)setupWithPixelBuffer:(CVPixelBufferRef)pixelBuffer error:(NSError **)err describeFormat:@"Failed to start Compression Session %d", status] failBool:error]; } + status = VTSessionSetProperties( compressionSession, (__bridge CFDictionaryRef) self.compressionSessionProperties @@ -194,11 +341,13 @@ - (BOOL)setupWithPixelBuffer:(CVPixelBufferRef)pixelBuffer error:(NSError **)err - (BOOL)tearDown:(NSError **)error { - if (self.compressionSession) { - VTCompressionSessionCompleteFrames(self.compressionSession, kCMTimeInvalid); - VTCompressionSessionInvalidate(self.compressionSession); + VTCompressionSessionRef compression = self.compressionSession; + if (compression) { + VTCompressionSessionCompleteFrames(compression, kCMTimeInvalid); + VTCompressionSessionInvalidate(compression); self.compressionSession = nil; } + CVPixelBufferPoolRelease(self.scaledPixelBufferPoolRef); return YES; } @@ -210,16 +359,31 @@ - (BOOL)writeEncodedFrame:(CVPixelBufferRef)pixelBuffer frameNumber:(NSUInteger) describeFormat:@"No compression session"] failBool:error]; } - + + CVPixelBufferRef bufferToWrite = pixelBuffer; + FBVideoCompressorCallbackSourceFrame *sourceFrameRef = [[FBVideoCompressorCallbackSourceFrame alloc] initWithPixelBuffer:nil frameNumber:frameNumber]; + CVPixelBufferPoolRef bufferPool = self.scaledPixelBufferPoolRef; + if (bufferPool != nil) { + CVPixelBufferRef resizedBuffer; + CVReturn returnStatus = CVPixelBufferPoolCreatePixelBuffer(nil, bufferPool, &resizedBuffer); + if (returnStatus == kCVReturnSuccess) { + scaleFromSourceToDestinationBuffer(pixelBuffer, resizedBuffer); + bufferToWrite = resizedBuffer; + sourceFrameRef.pixelBuffer = resizedBuffer; + } else { + [self.logger logFormat:@"Failed to get a pixel buffer from the pool: %d", returnStatus]; + } + } + VTEncodeInfoFlags flags; CMTime time = CMTimeMakeWithSeconds(CFAbsoluteTimeGetCurrent() - timeAtFirstFrame, NSEC_PER_SEC); OSStatus status = VTCompressionSessionEncodeFrame( compressionSession, - pixelBuffer, + bufferToWrite, time, kCMTimeInvalid, // Frame duration NULL, // Frame properties - (void *) frameNumber, // Source Frame Reference for callback. + (__bridge_retained void * _Nullable)(sourceFrameRef), &flags ); if (status != 0) { @@ -247,7 +411,7 @@ - (instancetype)initWithFramebuffer:(FBFramebuffer *)framebuffer configuration:( @interface FBSimulatorVideoStream () -@property (nonatomic, weak, readonly) FBFramebuffer *framebuffer; +@property (nonatomic, strong, readonly) FBFramebuffer *framebuffer; @property (nonatomic, copy, readonly) FBVideoStreamConfiguration *configuration; @property (nonatomic, strong, readonly) dispatch_queue_t writeQueue; @property (nonatomic, strong, readonly) id logger; @@ -265,23 +429,6 @@ - (void)pushFrame; @end -static NSDictionary *FBBitmapStreamPixelBufferAttributesFromPixelBuffer(CVPixelBufferRef pixelBuffer) -{ - size_t width = CVPixelBufferGetWidth(pixelBuffer); - size_t height = CVPixelBufferGetHeight(pixelBuffer); - size_t frameSize = CVPixelBufferGetDataSize(pixelBuffer); - size_t rowSize = CVPixelBufferGetBytesPerRow(pixelBuffer); - OSType pixelFormat = CVPixelBufferGetPixelFormatType(pixelBuffer); - NSString *pixelFormatString = (__bridge_transfer NSString *) UTCreateStringForOSType(pixelFormat); - - return @{ - @"width" : @(width), - @"height" : @(height), - @"row_size" : @(rowSize), - @"frame_size" : @(frameSize), - @"format" : pixelFormatString, - }; -} @implementation FBSimulatorVideoStream @@ -413,7 +560,6 @@ - (BOOL)mountSurface:(IOSurface *)surface error:(NSError **)error if (oldBuffer) { CVPixelBufferRelease(oldBuffer); } - // Make a Buffer from the Surface CVPixelBufferRef buffer = NULL; CVReturn status = CVPixelBufferCreateWithIOSurface( @@ -434,11 +580,11 @@ - (BOOL)mountSurface:(IOSurface *)surface error:(NSError **)error describe:@"Cannot mount surface when there is no consumer"] failBool:error]; } - + // Get the Attributes NSDictionary *attributes = FBBitmapStreamPixelBufferAttributesFromPixelBuffer(buffer); [self.logger logFormat:@"Mounting Surface with Attributes: %@", attributes]; - + // Swap the pixel buffers. self.pixelBuffer = buffer; self.pixelBufferAttributes = attributes; @@ -476,7 +622,7 @@ - (void)pushFrame self.timeAtFirstFrame = CFAbsoluteTimeGetCurrent(); } CFTimeInterval timeAtFirstFrame = self.timeAtFirstFrame; - + // Push the Frame [framePusher writeEncodedFrame:pixelBufer frameNumber:frameNumber timeAtFirstFrame:timeAtFirstFrame error:nil]; @@ -486,15 +632,29 @@ - (void)pushFrame + (id)framePusherForConfiguration:(FBVideoStreamConfiguration *)configuration compressionSessionProperties:(NSDictionary *)compressionSessionProperties consumer:(id)consumer logger:(id)logger error:(NSError **)error { + NSNumber *avgBitrate = @(800 * 1024); + if (configuration.avgBitrate != nil) { + avgBitrate = configuration.avgBitrate; + } + NSNumber *maxBitrate = @(1.5 * avgBitrate.doubleValue); // Get the base compression session properties, and add the class-cluster properties to them. NSMutableDictionary *derivedCompressionSessionProperties = [NSMutableDictionary dictionaryWithDictionary:@{ (NSString *) kVTCompressionPropertyKey_RealTime: @YES, (NSString *) kVTCompressionPropertyKey_AllowFrameReordering: @NO, + (NSString *) kVTCompressionPropertyKey_AverageBitRate: avgBitrate, + (NSString *) kVTCompressionPropertyKey_DataRateLimits: @[maxBitrate, @1], }]; + [derivedCompressionSessionProperties addEntriesFromDictionary:compressionSessionProperties]; + derivedCompressionSessionProperties[(NSString *)kVTCompressionPropertyKey_MaxKeyFrameIntervalDuration] = configuration.keyFrameRate; FBVideoStreamEncoding encoding = configuration.encoding; if ([encoding isEqualToString:FBVideoStreamEncodingH264]) { - derivedCompressionSessionProperties[(NSString *) kVTCompressionPropertyKey_ProfileLevel] = (NSString *) kVTProfileLevel_H264_High_AutoLevel; + derivedCompressionSessionProperties[(NSString *) kVTCompressionPropertyKey_ProfileLevel] = (NSString *)kVTProfileLevel_H264_Baseline_AutoLevel; // ref: http://blog.mediacoderhq.com/h264-profiles-and-levels/ + derivedCompressionSessionProperties[(NSString *) kVTCompressionPropertyKey_H264EntropyMode] = (NSString *)kVTH264EntropyMode_CAVLC; + if (@available(macOS 12.1, *)) { + derivedCompressionSessionProperties[(NSString *) kVTCompressionPropertyKey_ProfileLevel] = (NSString *)kVTProfileLevel_H264_High_AutoLevel; + derivedCompressionSessionProperties[(NSString *) kVTCompressionPropertyKey_H264EntropyMode] = (NSString *)kVTH264EntropyMode_CABAC; + } return [[FBSimulatorVideoStreamFramePusher_VideoToolbox alloc] initWithConfiguration:configuration compressionSessionProperties:[derivedCompressionSessionProperties copy] @@ -524,7 +684,7 @@ - (void)pushFrame logger:logger]; } if ([encoding isEqual:FBVideoStreamEncodingBGRA]) { - return [[FBSimulatorVideoStreamFramePusher_Bitmap alloc] initWithConsumer:consumer]; + return [[FBSimulatorVideoStreamFramePusher_Bitmap alloc] initWithConsumer:consumer scaleFactor:configuration.scaleFactor]; } return [[FBControlCoreError describeFormat:@"%@ is not supported for Simulators", encoding] @@ -593,8 +753,10 @@ - (BOOL)mountSurface:(IOSurface *)surface error:(NSError **)error - (NSDictionary *)compressionSessionProperties { return @{ - (NSString *) kVTCompressionPropertyKey_ExpectedFrameRate: @(self.framesPerSecond), - (NSString *) kVTCompressionPropertyKey_MaxKeyFrameInterval: @2, + (NSString *) kVTCompressionPropertyKey_ExpectedFrameRate: @(2 * self.framesPerSecond), + (NSString *) kVTCompressionPropertyKey_MaxKeyFrameInterval: @360, + (NSString *) kVTCompressionPropertyKey_MaxKeyFrameIntervalDuration: @10, // key frame at least every 10 seconds + (NSString *) kVTCompressionPropertyKey_MaxFrameDelayCount: @0, }; } diff --git a/FBSimulatorControl/Framebuffer/FBSurfaceImageGenerator.h b/FBSimulatorControl/Framebuffer/FBSurfaceImageGenerator.h index 052883b1f..829f81270 100644 --- a/FBSimulatorControl/Framebuffer/FBSurfaceImageGenerator.h +++ b/FBSimulatorControl/Framebuffer/FBSurfaceImageGenerator.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControl/Framebuffer/FBSurfaceImageGenerator.m b/FBSimulatorControl/Framebuffer/FBSurfaceImageGenerator.m index b52394e0e..dd55531b2 100644 --- a/FBSimulatorControl/Framebuffer/FBSurfaceImageGenerator.m +++ b/FBSimulatorControl/Framebuffer/FBSurfaceImageGenerator.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControl/HID/FBSimulatorHID.h b/FBSimulatorControl/HID/FBSimulatorHID.h index 37eec01b8..d06dbda13 100644 --- a/FBSimulatorControl/HID/FBSimulatorHID.h +++ b/FBSimulatorControl/HID/FBSimulatorHID.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControl/HID/FBSimulatorHID.m b/FBSimulatorControl/HID/FBSimulatorHID.m index 7f986c753..bc6f5d489 100644 --- a/FBSimulatorControl/HID/FBSimulatorHID.m +++ b/FBSimulatorControl/HID/FBSimulatorHID.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControl/HID/FBSimulatorHIDEvent.h b/FBSimulatorControl/HID/FBSimulatorHIDEvent.h index e69e26432..5628face1 100644 --- a/FBSimulatorControl/HID/FBSimulatorHIDEvent.h +++ b/FBSimulatorControl/HID/FBSimulatorHIDEvent.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControl/HID/FBSimulatorHIDEvent.m b/FBSimulatorControl/HID/FBSimulatorHIDEvent.m index 6e4f4376b..f8beac45a 100644 --- a/FBSimulatorControl/HID/FBSimulatorHIDEvent.m +++ b/FBSimulatorControl/HID/FBSimulatorHIDEvent.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -124,10 +124,8 @@ - (instancetype)initWithDirection:(FBSimulatorHIDDirection)direction x:(double)x - (NSString *)description { return [NSString stringWithFormat: - @"Touch %@ at (%lu,%lu)", - [FBSimulatorHIDEvent directionStringFromDirection:self.direction], - (unsigned long)self.x, - (unsigned long)self.y + @"Touch %@ at ", + [FBSimulatorHIDEvent directionStringFromDirection:self.direction] ]; } @@ -272,8 +270,7 @@ - (instancetype)initWithDirection:(FBSimulatorHIDDirection)direction keyCode:(un - (NSString *)description { return [NSString stringWithFormat: - @"Keyboard Code=%d %@", - self.keyCode, + @"Keyboard Code= %@", [FBSimulatorHIDEvent directionStringFromDirection:self.direction] ]; } @@ -425,12 +422,15 @@ + (instancetype)swipe:(double)xStart yStart:(double)yStart xEnd:(double)xEnd yEn double dx = (xEnd - xStart) / steps; double dy = (yEnd - yStart) / steps; - double stepDelay = duration/(steps + 1); + double stepDelay = duration/(steps + 2); for (int i = 0 ; i <= steps ; ++i) { [events addObject:[self touchDownAtX:(xStart + dx * i) y:(yStart + dy * i)]]; [events addObject:[self delay:stepDelay]]; } + // Add an additional touch down event at the end of the swipe to avoid intertial scroll on arm simulators. + [events addObject:[self touchDownAtX:(xStart + dx * steps) y:(yStart + dy * steps)]]; + [events addObject:[self delay:stepDelay]]; [events addObject:[self touchUpAtX:xEnd y:yEnd]]; diff --git a/FBSimulatorControl/HID/FBSimulatorIndigoHID.h b/FBSimulatorControl/HID/FBSimulatorIndigoHID.h index b1c6b8121..53902903f 100644 --- a/FBSimulatorControl/HID/FBSimulatorIndigoHID.h +++ b/FBSimulatorControl/HID/FBSimulatorIndigoHID.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControl/HID/FBSimulatorIndigoHID.m b/FBSimulatorControl/HID/FBSimulatorIndigoHID.m index 13408b982..b7b30fe11 100644 --- a/FBSimulatorControl/HID/FBSimulatorIndigoHID.m +++ b/FBSimulatorControl/HID/FBSimulatorIndigoHID.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControl/Management/FBAppleSimctlCommandExecutor.h b/FBSimulatorControl/Management/FBAppleSimctlCommandExecutor.h index 2e81fec65..e377dc9e7 100644 --- a/FBSimulatorControl/Management/FBAppleSimctlCommandExecutor.h +++ b/FBSimulatorControl/Management/FBAppleSimctlCommandExecutor.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControl/Management/FBAppleSimctlCommandExecutor.m b/FBSimulatorControl/Management/FBAppleSimctlCommandExecutor.m index 826cefeb3..df4a2f753 100644 --- a/FBSimulatorControl/Management/FBAppleSimctlCommandExecutor.m +++ b/FBSimulatorControl/Management/FBAppleSimctlCommandExecutor.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControl/Management/FBSimulator+Private.h b/FBSimulatorControl/Management/FBSimulator+Private.h index be035f01f..a95a086cd 100644 --- a/FBSimulatorControl/Management/FBSimulator+Private.h +++ b/FBSimulatorControl/Management/FBSimulator+Private.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -18,8 +18,8 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, strong, readonly) id forwarder; + (instancetype)fromSimDevice:(SimDevice *)device configuration:(nullable FBSimulatorConfiguration *)configuration set:(FBSimulatorSet *)set; -- (instancetype)initWithDevice:(SimDevice *)device configuration:(FBSimulatorConfiguration *)configuration set:(FBSimulatorSet *)set auxillaryDirectory:(NSString *)auxillaryDirectory logger:(id)logger reporter:(id)reporter; - +- (instancetype)initWithDevice:(SimDevice *)device configuration:(FBSimulatorConfiguration *)configuration set:(nullable FBSimulatorSet *)set auxillaryDirectory:(NSString *)auxillaryDirectory logger:(id)logger reporter:(id)reporter; +- (instancetype)initWithDevice:(id)device logger:(id)logger reporter:(id)reporter; @end NS_ASSUME_NONNULL_END diff --git a/FBSimulatorControl/Management/FBSimulator.h b/FBSimulatorControl/Management/FBSimulator.h index 44c1195dc..167291ebc 100644 --- a/FBSimulatorControl/Management/FBSimulator.h +++ b/FBSimulatorControl/Management/FBSimulator.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -42,8 +42,10 @@ NS_ASSUME_NONNULL_BEGIN /** The Simulator Set that the Simulator belongs to. + Reference to `FBSimulatorSet` results to a strong-strong reference cycle between `FBSimulatorSet` and `FBSimulator`. + However, this cycle is explicitly broken by `FBSimulatorSet` when a `FBSimulator` is removed from the set that `FBSimulatorSet` wraps. */ -@property (nonatomic, weak, readonly, nullable) FBSimulatorSet *set; +@property (nonatomic, strong, readonly, nonnull) FBSimulatorSet *set; /** The Product Family of the Simulator. diff --git a/FBSimulatorControl/Management/FBSimulator.m b/FBSimulatorControl/Management/FBSimulator.m index d1a637c71..1031526d4 100644 --- a/FBSimulatorControl/Management/FBSimulator.m +++ b/FBSimulatorControl/Management/FBSimulator.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -67,7 +67,16 @@ + (instancetype)fromSimDevice:(SimDevice *)device configuration:(nullable FBSimu reporter:set.reporter]; } -- (instancetype)initWithDevice:(SimDevice *)device configuration:(FBSimulatorConfiguration *)configuration set:(FBSimulatorSet *)set auxillaryDirectory:(NSString *)auxillaryDirectory logger:(id)logger reporter:(id)reporter +- (instancetype)initWithDevice:(id)device logger:(id)logger reporter:(id)reporter { + return [self initWithDevice:device + configuration:[FBSimulatorConfiguration inferSimulatorConfigurationFromDeviceSynthesizingMissing:device] + set:nil + auxillaryDirectory:[FBSimulator auxillaryDirectoryFromSimDevice:device] + logger:logger + reporter:reporter]; +} + +- (instancetype)initWithDevice:(SimDevice *)device configuration:(FBSimulatorConfiguration *)configuration set:(nullable FBSimulatorSet *)set auxillaryDirectory:(NSString *)auxillaryDirectory logger:(id)logger reporter:(id)reporter { self = [super init]; if (!self) { @@ -115,9 +124,9 @@ - (FBiOSTargetType)targetType return FBiOSTargetTypeSimulator; } -- (FBArchitecture)architecture +- (NSArray *)architectures { - return self.configuration.device.simulatorArchitecture; + return [[FBArchitectureProcessAdapter hostMachineSupportedArchitectures] allObjects]; } - (FBDeviceType *)deviceType diff --git a/FBSimulatorControl/Management/FBSimulatorBridge.h b/FBSimulatorControl/Management/FBSimulatorBridge.h index 4c0da855a..4d6379b24 100644 --- a/FBSimulatorControl/Management/FBSimulatorBridge.h +++ b/FBSimulatorControl/Management/FBSimulatorBridge.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -15,7 +15,10 @@ NS_ASSUME_NONNULL_BEGIN @class FBSimulator; /** - Wraps the 'SimulatorBridge' Connection and Protocol + An interface to the "SimulatorBridge" binary, a remote process that runs inside the iOS Simulator. + This is needed for the SimulatorApp to implement some of it's functionality. + "SimulatorBridge" will wrap functionality that is present in SimulatorApp, but not present in CoreSimulator itself. + "SimulatorBridge" is distinct from "CoreSimulatorBridge", which is an internal implementation detail of the SimDevice API. */ @interface FBSimulatorBridge : NSObject diff --git a/FBSimulatorControl/Management/FBSimulatorBridge.m b/FBSimulatorControl/Management/FBSimulatorBridge.m index 0e2b1db40..f3d5b6a60 100644 --- a/FBSimulatorControl/Management/FBSimulatorBridge.m +++ b/FBSimulatorControl/Management/FBSimulatorBridge.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControl/Management/FBSimulatorControl+PrincipalClass.h b/FBSimulatorControl/Management/FBSimulatorControl+PrincipalClass.h index 215942a77..137723bec 100644 --- a/FBSimulatorControl/Management/FBSimulatorControl+PrincipalClass.h +++ b/FBSimulatorControl/Management/FBSimulatorControl+PrincipalClass.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControl/Management/FBSimulatorControl+PrincipalClass.m b/FBSimulatorControl/Management/FBSimulatorControl+PrincipalClass.m index 54c2aebc5..9702802f2 100644 --- a/FBSimulatorControl/Management/FBSimulatorControl+PrincipalClass.m +++ b/FBSimulatorControl/Management/FBSimulatorControl+PrincipalClass.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControl/Management/FBSimulatorServiceContext.h b/FBSimulatorControl/Management/FBSimulatorServiceContext.h index 5dfd8134a..ad79da1d6 100644 --- a/FBSimulatorControl/Management/FBSimulatorServiceContext.h +++ b/FBSimulatorControl/Management/FBSimulatorServiceContext.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControl/Management/FBSimulatorServiceContext.m b/FBSimulatorControl/Management/FBSimulatorServiceContext.m index 9f1254557..f39a7ad5d 100644 --- a/FBSimulatorControl/Management/FBSimulatorServiceContext.m +++ b/FBSimulatorControl/Management/FBSimulatorServiceContext.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControl/Management/FBSimulatorSet+Private.h b/FBSimulatorControl/Management/FBSimulatorSet+Private.h index 61fa21e9e..31ebf05a9 100644 --- a/FBSimulatorControl/Management/FBSimulatorSet+Private.h +++ b/FBSimulatorControl/Management/FBSimulatorSet+Private.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -14,8 +14,6 @@ - (instancetype)initWithConfiguration:(FBSimulatorControlConfiguration *)configuration deviceSet:(SimDeviceSet *)deviceSet delegate:(id)delegate logger:(id)logger reporter:(id)reporter; -@property (nonatomic, strong, readonly) dispatch_queue_t workQueue; -@property (nonatomic, strong, readonly) dispatch_queue_t asyncQueue; @property (nonatomic, strong, readonly) FBSimulatorInflationStrategy *inflationStrategy; @property (nonatomic, strong, readonly) FBSimulatorNotificationUpdateStrategy *notificationUpdateStrategy; diff --git a/FBSimulatorControl/Management/FBSimulatorSet.h b/FBSimulatorControl/Management/FBSimulatorSet.h index e64776aa4..febca8b44 100644 --- a/FBSimulatorControl/Management/FBSimulatorSet.h +++ b/FBSimulatorControl/Management/FBSimulatorSet.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -81,22 +81,22 @@ NS_ASSUME_NONNULL_BEGIN #pragma mark Desctructive Methods /** - Kills a Simulator in the Set. - The Set to which the Simulator belongs must be the receiver. + Shuts down a simulator in the set. + The Set to which the Simulator belongs must be present the receiver. - @param simulator the Simulator to delete. Must not be nil. - @return an Future that resolves when successful. + @param simulator the Simulator to shutdown. Must not be nil. + @return an Future that resolves when the operation has completed. */ -- (FBFuture *)killSimulator:(FBSimulator *)simulator; +- (FBFuture *)shutdown:(FBSimulator *)simulator; /** Erases a Simulator in the Set. The Set to which the Simulator belongs must be the receiver. @param simulator the Simulator to erase. Must not be nil. - @return A future wrapping the erased simulators udids. + @return an Future that resolves when the operation has completed. */ -- (FBFuture *)eraseSimulator:(FBSimulator *)simulator; +- (FBFuture *)erase:(FBSimulator *)simulator; /** Deletes a Simulator in the Set. @@ -105,55 +105,21 @@ NS_ASSUME_NONNULL_BEGIN @param simulator the Simulator to delete. Must not be nil. @return A future wrapping the delegate simulators. */ -- (FBFuture *)deleteSimulator:(FBSimulator *)simulator; - -/** - Kills all provided Simulators. - The Set to which the Simulators belong must be the receiver. - - @param simulators the Simulators to kill. Must not be nil. - @return an Future that resolves when successful. - */ -- (FBFuture *> *)killAll:(NSArray *)simulators; - -/** - Erases all provided Simulators. - The Set to which the Simulators belong must be the receiver. - - @param simulators the Simulators to erase. Must not be nil. - @return A future wrapping the erased simulators. - */ -- (FBFuture *> *)eraseAll:(NSArray *)simulators; - -/** - Erases all provided Simulators. - The Set to which the Simulators belong must be the receiver. - - @param simulators the Simulators to delete. Must not be nil. - @return A future wrapping the erased simulators udids. - */ -- (FBFuture *> *)deleteAll:(NSArray *)simulators; +- (FBFuture *)delete:(FBSimulator *)simulator; /** - Kills all of the Simulators that belong to the receiver. + Performs a shutdown all of the Simulators that belong to the receiver. @return an Future that resolves when successful. */ -- (FBFuture *> *)killAll; - -/** - Kills all of the Simulators that belong to the receiver. - - @return A future wrapping the erased simulators. - */ -- (FBFuture *> *)eraseAll; +- (FBFuture *)shutdownAll; /** Delete all of the Simulators that belong to the receiver. @return A future wrapping the erased simulators udids. */ -- (FBFuture *> *)deleteAll; +- (FBFuture *)deleteAll; /** The Logger to use. @@ -180,6 +146,16 @@ NS_ASSUME_NONNULL_BEGIN */ @property (nonatomic, copy, readonly) NSArray *allSimulators; +/** + The work queue that will be used by all simulators within the set. + */ +@property (nonatomic, strong, readonly) dispatch_queue_t workQueue; + +/** + The async queue that will be used by all simulators within the set. + */ +@property (nonatomic, strong, readonly) dispatch_queue_t asyncQueue; + @end NS_ASSUME_NONNULL_END diff --git a/FBSimulatorControl/Management/FBSimulatorSet.m b/FBSimulatorControl/Management/FBSimulatorSet.m index 3846ac00b..552868c0e 100644 --- a/FBSimulatorControl/Management/FBSimulatorSet.m +++ b/FBSimulatorControl/Management/FBSimulatorSet.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -27,7 +27,6 @@ #import "FBSimulatorInflationStrategy.h" #import "FBSimulatorNotificationUpdateStrategy.h" #import "FBSimulatorShutdownStrategy.h" -#import "FBSimulatorTerminationStrategy.h" @implementation FBSimulatorSet @@ -116,9 +115,8 @@ - (FBSimulator *)simulatorWithUDID:(NSString *)udid // This step ensures that the Simulator is in a known-shutdown state after creation. // This prevents racing with any 'booting' interaction that occurs immediately after allocation. - return [[[[FBSimulatorShutdownStrategy - strategyWithSimulator:simulator] - shutdown] + return [[[FBSimulatorShutdownStrategy + shutdown:simulator] rephraseFailure:@"Could not get newly-created simulator into a shutdown state"] mapReplace:simulator]; }]; @@ -144,65 +142,43 @@ - (FBSimulator *)simulatorWithUDID:(NSString *)udid #pragma mark Destructive Methods -- (FBFuture *)killSimulator:(FBSimulator *)simulator +- (FBFuture *)shutdown:(FBSimulator *)simulator { NSParameterAssert(simulator); - return [[self.simulatorTerminationStrategy - killSimulators:@[simulator]] - onQueue:self.workQueue map:^(NSArray *result) { - return [result firstObject]; - }]; + return [FBSimulatorShutdownStrategy shutdown:simulator]; } -- (FBFuture *)eraseSimulator:(FBSimulator *)simulator +- (FBFuture *)erase:(FBSimulator *)simulator { NSParameterAssert(simulator); - return [[self.eraseStrategy - eraseSimulators:@[simulator]] - onQueue:self.workQueue map:^(NSArray *result) { - return [result firstObject]; - }]; + return [FBSimulatorEraseStrategy erase:simulator]; } -- (FBFuture *)deleteSimulator:(FBSimulator *)simulator +- (FBFuture *)delete:(FBSimulator *)simulator { NSParameterAssert(simulator); - return [[self.deletionStrategy - deleteSimulators:@[simulator]] - onQueue:self.workQueue map:^(NSArray *result) { - return [result firstObject]; - }]; -} - -- (FBFuture *> *)killAll:(NSArray *)simulators -{ - NSParameterAssert(simulators); - return [self.simulatorTerminationStrategy killSimulators:simulators]; + return [FBSimulatorDeletionStrategy delete:simulator]; } -- (FBFuture *> *)eraseAll:(NSArray *)simulators +- (FBFuture *)shutdownAll:(NSArray *)simulators { NSParameterAssert(simulators); - return [self.eraseStrategy eraseSimulators:simulators]; + return [FBSimulatorShutdownStrategy shutdownAll:simulators]; } -- (FBFuture *> *)deleteAll:(NSArray *)simulators; +- (FBFuture *)deleteAll:(NSArray *)simulators; { NSParameterAssert(simulators); - return [self.deletionStrategy deleteSimulators:simulators]; -} - -- (FBFuture *> *)killAll -{ - return [self.simulatorTerminationStrategy killSimulators:self.allSimulators]; + return [FBSimulatorDeletionStrategy deleteAll:simulators]; } -- (FBFuture *> *)eraseAll +- (FBFuture *)shutdownAll { - return [self.eraseStrategy eraseSimulators:self.allSimulators]; + NSArray *simulators = self.allSimulators; + return [FBSimulatorShutdownStrategy shutdownAll:simulators]; } -- (FBFuture *> *)deleteAll +- (FBFuture *)deleteAll { return [self deleteAll:self.allSimulators]; } @@ -256,21 +232,6 @@ - (NSString *)description #pragma mark Private Properties -- (FBSimulatorTerminationStrategy *)simulatorTerminationStrategy -{ - return [FBSimulatorTerminationStrategy strategyForSet:self]; -} - -- (FBSimulatorEraseStrategy *)eraseStrategy -{ - return [FBSimulatorEraseStrategy strategyForSet:self]; -} - -- (FBSimulatorDeletionStrategy *)deletionStrategy -{ - return [FBSimulatorDeletionStrategy strategyForSet:self]; -} - + (FBFuture *)onDeviceSet:(SimDeviceSet *)deviceSet createDeviceWithType:(SimDeviceType *)deviceType runtime:(SimRuntime *)runtime name:(NSString *)name queue:(dispatch_queue_t)queue { FBMutableFuture *future = FBMutableFuture.future; diff --git a/FBSimulatorControl/Notifiers/FBCoreSimulatorNotifier.h b/FBSimulatorControl/Notifiers/FBCoreSimulatorNotifier.h index 541f20a3b..9c09b5688 100644 --- a/FBSimulatorControl/Notifiers/FBCoreSimulatorNotifier.h +++ b/FBSimulatorControl/Notifiers/FBCoreSimulatorNotifier.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -7,6 +7,8 @@ #import +#import + NS_ASSUME_NONNULL_BEGIN @class FBSimulator; @@ -21,24 +23,23 @@ NS_ASSUME_NONNULL_BEGIN #pragma mark Initializers /** - Creates and returns an FBSimDeviceNotifier for the lifecycle events that SimDevice broadcasts. + Creates and returns an FBSimDeviceNotifier for the lifecycle events that SimDeviceSet broadcasts for the provided Set. - @param simDevice the FBSimulator to relay events from. + @param set the FBSimulator to relay events from. @param queue the queue to call the block on. @param block the block to call when events are sent from the SimDevice. @return an instance of FBSimDeviceNotifier for later termination. */ -+ (instancetype)notifierForSimDevice:(SimDevice *)simDevice queue:(dispatch_queue_t)queue block:(void (^)(NSDictionary *info))block; ++ (instancetype)notifierForSet:(FBSimulatorSet *)set queue:(dispatch_queue_t)queue block:(void (^)(NSDictionary *info))block; /** - Creates and returns an FBSimDeviceNotifier for the lifecycle events that SimDeviceSet broadcasts for the provided Set. + Waits for the state to leave the state on the provided SimDevice. - @param set the FBSimulator to relay events from. - @param queue the queue to call the block on. - @param block the block to call when events are sent from the SimDevice. - @return an instance of FBSimDeviceNotifier for later termination. + @param state the state to resolve. + @param device the SimDevice to resolve state on. + @return a future that resolves when the state resolves. */ -+ (instancetype)notifierForSet:(FBSimulatorSet *)set queue:(dispatch_queue_t)queue block:(void (^)(NSDictionary *info))block; ++ (FBFuture *)resolveLeavesState:(FBiOSTargetState)state forSimDevice:(SimDevice *)device; #pragma mark Public Methods diff --git a/FBSimulatorControl/Notifiers/FBCoreSimulatorNotifier.m b/FBSimulatorControl/Notifiers/FBCoreSimulatorNotifier.m index 73b99c1ee..cac898173 100644 --- a/FBSimulatorControl/Notifiers/FBCoreSimulatorNotifier.m +++ b/FBSimulatorControl/Notifiers/FBCoreSimulatorNotifier.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -24,19 +24,52 @@ @interface FBCoreSimulatorNotifier () @implementation FBCoreSimulatorNotifier -+ (instancetype)notifierForSimDevice:(SimDevice *)simDevice queue:(dispatch_queue_t)queue block:(void (^)(NSDictionary *info))block +#pragma mark Public + ++ (instancetype)notifierForSimDevice:(SimDevice *)simDevice queue:(dispatch_queue_t)queue block:(void (^)(NSDictionary *info))block { id notifier = simDevice.notificationManager; return [[self alloc] initWithNotifier:notifier queue:queue block:block]; } -+ (instancetype)notifierForSet:(FBSimulatorSet *)set queue:(dispatch_queue_t)queue block:(void (^)(NSDictionary *info))block ++ (FBFuture *)resolveLeavesState:(FBiOSTargetState)state forSimDevice:(SimDevice *)device +{ + FBMutableFuture *future = FBMutableFuture.future; + dispatch_queue_t queue = dispatch_queue_create("com.facebook.fbsimulatorcontrol.resolve_state", DISPATCH_QUEUE_SERIAL); + FBCoreSimulatorNotifier *notifier = [self notifierForSimDevice:device queue:queue block:^(NSDictionary *info) { + if (![info[@"notification"] isEqualToString:@"device_state"]) { + return; + } + NSNumber *newStateNumber = info[@"new_state"]; + if (!newStateNumber) { + return; + } + FBiOSTargetState newState = newStateNumber.unsignedIntegerValue; + if (newState == state) { + return; + } + [future resolveWithResult:NSNull.null]; + }]; + return [future + onQueue:queue notifyOfCompletion:^(id _) { + [notifier terminate]; + }]; +} + +- (void)terminate +{ + [self.notifier unregisterNotificationHandler:self.handle error:nil]; +} + +#pragma mark Private + ++ (instancetype)notifierForSet:(FBSimulatorSet *)set queue:(dispatch_queue_t)queue block:(void (^)(NSDictionary *info))block { id notifier = set.deviceSet.notificationManager; return [[self alloc] initWithNotifier:notifier queue:queue block:block]; } -- (instancetype)initWithNotifier:(id)notifier queue:(dispatch_queue_t)queue block:(void (^)(NSDictionary *info))block +- (instancetype)initWithNotifier:(id)notifier queue:(dispatch_queue_t)queue block:(void (^)(NSDictionary *info))block { self = [super init]; if (!self) { @@ -49,12 +82,7 @@ - (instancetype)initWithNotifier:(id)notifier queue return self; } -- (void)terminate -{ - [self.notifier unregisterNotificationHandler:self.handle error:nil]; -} - -+ (NSUInteger)registerNotificationHandler:(id)notifier queue:(dispatch_queue_t)queue handler:(void (^)(NSDictionary *))handler ++ (NSUInteger)registerNotificationHandler:(id)notifier queue:(dispatch_queue_t)queue handler:(void (^)(NSDictionary *))handler { if ([notifier respondsToSelector:@selector(registerNotificationHandlerOnQueue:handler:)]) { return [notifier registerNotificationHandlerOnQueue:queue handler:handler]; diff --git a/FBSimulatorControl/Strategies/FBDefaultsModificationStrategy.h b/FBSimulatorControl/Strategies/FBDefaultsModificationStrategy.h index f92263b49..51562e433 100644 --- a/FBSimulatorControl/Strategies/FBDefaultsModificationStrategy.h +++ b/FBSimulatorControl/Strategies/FBDefaultsModificationStrategy.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -47,10 +47,11 @@ NS_ASSUME_NONNULL_BEGIN @param name preference name @param value preference value + @param type preference value type. If null defaults to `string`. @param domain preference domain - optional @return a Future that resolves when successful. */ -- (FBFuture *)setPreference:(NSString *)name value:(NSString *)value domain:(nullable NSString *)domain; +- (FBFuture *)setPreference:(NSString *)name value:(NSString *)value type:(nullable NSString *)type domain:(nullable NSString *)domain; /** Gets a preference value by its name and domain. If domain not specified assumed to be Apple Global Domain @@ -75,6 +76,14 @@ NS_ASSUME_NONNULL_BEGIN */ - (FBFuture *)approveLocationServicesForBundleIDs:(NSArray *)bundleIDs; +/** + Revokes Location Services for Applications. + + @param bundleIDs an NSArray of bundle IDs to to revoke location settings for. + @return a future that resolves when completed. + */ +- (FBFuture *)revokeLocationServicesForBundleIDs:(NSArray *)bundleIDs; + @end NS_ASSUME_NONNULL_END diff --git a/FBSimulatorControl/Strategies/FBDefaultsModificationStrategy.m b/FBSimulatorControl/Strategies/FBDefaultsModificationStrategy.m index 9f8cf3ad1..a79e4a50e 100644 --- a/FBSimulatorControl/Strategies/FBDefaultsModificationStrategy.m +++ b/FBSimulatorControl/Strategies/FBDefaultsModificationStrategy.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -76,13 +76,14 @@ - (NSString *)defaultsBinary return [[self performDefaultsCommandWithArguments:arguments] mapReplace:NSNull.null]; } -- (FBFuture *)setDefaultInDomain:(NSString *)domain key:(NSString *)key value:(NSString *)value +- (FBFuture *)setDefaultInDomain:(NSString *)domain key:(NSString *)key value:(NSString *)value type:(NSString *)type { return [[self performDefaultsCommandWithArguments:@[ @"write", domain, key, + [NSString stringWithFormat:@"-%@", type ? type : @"string"], value, ]] mapReplace:NSNull.null]; @@ -152,12 +153,12 @@ @implementation FBPreferenceModificationStrategy static NSString *const AppleGlobalDomain = @"Apple Global Domain"; -- (FBFuture *)setPreference:(NSString *)name value:(NSString *)value domain:(nullable NSString *)domain +- (FBFuture *)setPreference:(NSString *)name value:(NSString *)value type:(nullable NSString *)type domain:(nullable NSString *)domain { if (domain == nil) { domain = AppleGlobalDomain; } - return [self setDefaultInDomain:domain key:name value:value]; + return [self setDefaultInDomain:domain key:name value:value type:type]; } - (FBFuture *)getCurrentPreference:(NSString *)name domain:(nullable NSString *)domain @@ -195,4 +196,48 @@ @implementation FBLocationServicesModificationStrategy managingService:@"locationd"]; } +- (FBFuture *)revokeLocationServicesForBundleIDs:(NSArray *)bundleIDs +{ + NSParameterAssert(bundleIDs); + + FBSimulator *simulator = self.simulator; + FBiOSTargetState state = simulator.state; + if (state != FBiOSTargetStateBooted && state != FBiOSTargetStateShutdown) { + return [[FBSimulatorError + describeFormat:@"Cannot modify a plist when the Simulator state is %@, should be %@ or %@", FBiOSTargetStateStringFromState(state), FBiOSTargetStateStringShutdown, FBiOSTargetStateStringBooted] + failFuture]; + } + + NSString *serviceName = @"locationd"; + + // Stop the service, if booted. + FBFuture *stopFuture = state == FBiOSTargetStateBooted + ? [[simulator stopServiceWithName:serviceName] mapReplace:NSNull.null] + : FBFuture.empty; + + NSString *path = [self.simulator.dataDirectory + stringByAppendingPathComponent:@"Library/Caches/locationd/clients.plist"]; + NSMutableArray *> *futures = [NSMutableArray array]; + for (NSString *bundleID in bundleIDs) { + [futures addObject: + [self + performDefaultsCommandWithArguments:@[ + @"delete", + path, + bundleID, + ]]]; + } + + return [[stopFuture + onQueue:self.simulator.workQueue fmap:^FBFuture *(NSNull *_) { + return [[FBFuture futureWithFutures:futures] mapReplace:NSNull.null]; + }] + onQueue:self.simulator.workQueue fmap:^FBFuture *(NSNull *_) { + // Re-start the Service if booted. + return state == FBiOSTargetStateBooted + ? [[simulator startServiceWithName:serviceName] mapReplace:NSNull.null] + : FBFuture.empty; + }]; +} + @end diff --git a/FBSimulatorControl/Strategies/FBSimulatorBootStrategy.h b/FBSimulatorControl/Strategies/FBSimulatorBootStrategy.h index c964eb5d3..50de86763 100644 --- a/FBSimulatorControl/Strategies/FBSimulatorBootStrategy.h +++ b/FBSimulatorControl/Strategies/FBSimulatorBootStrategy.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControl/Strategies/FBSimulatorBootStrategy.m b/FBSimulatorControl/Strategies/FBSimulatorBootStrategy.m index 015fa55a9..7fae8421d 100644 --- a/FBSimulatorControl/Strategies/FBSimulatorBootStrategy.m +++ b/FBSimulatorControl/Strategies/FBSimulatorBootStrategy.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControl/Strategies/FBSimulatorBootVerificationStrategy.h b/FBSimulatorControl/Strategies/FBSimulatorBootVerificationStrategy.h index d1aa86c78..91ba3965e 100644 --- a/FBSimulatorControl/Strategies/FBSimulatorBootVerificationStrategy.h +++ b/FBSimulatorControl/Strategies/FBSimulatorBootVerificationStrategy.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControl/Strategies/FBSimulatorBootVerificationStrategy.m b/FBSimulatorControl/Strategies/FBSimulatorBootVerificationStrategy.m index bd369f6ae..480eb1bfe 100644 --- a/FBSimulatorControl/Strategies/FBSimulatorBootVerificationStrategy.m +++ b/FBSimulatorControl/Strategies/FBSimulatorBootVerificationStrategy.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControl/Strategies/FBSimulatorDeletionStrategy.h b/FBSimulatorControl/Strategies/FBSimulatorDeletionStrategy.h index 8d729b284..85f121121 100644 --- a/FBSimulatorControl/Strategies/FBSimulatorDeletionStrategy.h +++ b/FBSimulatorControl/Strategies/FBSimulatorDeletionStrategy.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -19,25 +19,23 @@ NS_ASSUME_NONNULL_BEGIN */ @interface FBSimulatorDeletionStrategy : NSObject -#pragma mark Initializers +#pragma mark Public Methods /** - Creates a FBSimulatorEraseStrategy. + Deletes a simulator. - @param set the Simulator Set to log. - @return a configured FBSimulatorDeletionStrategy instance. + @param simulator the Simulator to Delete. + @return a future wrapping the array of deleted simulator uuids. */ -+ (instancetype)strategyForSet:(FBSimulatorSet *)set; - -#pragma mark Public Methods ++ (FBFuture *)delete:(FBSimulator *)simulator; /** - Intelligently Deletes Simulators. + Batch operation for deleting multipole simulators. @param simulators the Simulators to Delete. @return a future wrapping the array of deleted simulator uuids. */ -- (FBFuture *> *)deleteSimulators:(NSArray *)simulators; ++ (FBFuture *)deleteAll:(NSArray *)simulators; @end diff --git a/FBSimulatorControl/Strategies/FBSimulatorDeletionStrategy.m b/FBSimulatorControl/Strategies/FBSimulatorDeletionStrategy.m index e2bbe3d91..9f5f26738 100644 --- a/FBSimulatorControl/Strategies/FBSimulatorDeletionStrategy.m +++ b/FBSimulatorControl/Strategies/FBSimulatorDeletionStrategy.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -14,116 +14,78 @@ #import "FBSimulator.h" #import "FBSimulatorError.h" -#import "FBSimulatorSet.h" #import "FBSimulatorSet+Private.h" - -@interface FBSimulatorDeletionStrategy () - -@property (nonatomic, weak, readonly) FBSimulatorSet *set; -@property (nonatomic, nullable, strong, readonly) id logger; - -@end +#import "FBSimulatorSet.h" +#import "FBSimulatorShutdownStrategy.h" @implementation FBSimulatorDeletionStrategy -#pragma mark Initializers - -+ (instancetype)strategyForSet:(FBSimulatorSet *)set -{ - return [[self alloc] initWithSet:set logger:set.logger]; -} - -- (instancetype)initWithSet:(FBSimulatorSet *)set logger:(id)logger -{ - self = [super init]; - if (!self) { - return nil; - } - - _set = set; - _logger = logger; - - return self; -} - #pragma mark Public Methods -- (FBFuture *> *)deleteSimulators:(NSArray *)simulators -{ - // Confirm that the Simulators belong to the set - for (FBSimulator *simulator in simulators) { - if (simulator.set != self.set) { - return [[FBSimulatorError - describeFormat:@"Simulator's set %@ is not %@, cannot delete", simulator.set, self] - failFuture]; - } - } - - // Keep the UDIDs around for confirmation. - // Start the deletion - NSSet *deletedDeviceUDIDs = [NSSet setWithArray:[simulators valueForKey:@"udid"]]; - NSMutableArray *> *futures = [NSMutableArray array]; - for (FBSimulator *simulator in simulators) { - [futures addObject:[self deleteSimulator:simulator]]; - } - - return [[FBFuture - futureWithFutures:futures] - onQueue:dispatch_get_main_queue() fmap:^(id _) { - return [FBSimulatorDeletionStrategy confirmSimulatorsAreRemovedFromSet:self.set deletedDeviceUDIDs:deletedDeviceUDIDs]; - }]; -} - -#pragma mark Private - -+ (FBFuture *> *)confirmSimulatorsAreRemovedFromSet:(FBSimulatorSet *)set deletedDeviceUDIDs:(NSSet *)deletedDeviceUDIDs -{ - // Deleting the device from the set can still leave it around for a few seconds. - // This could race with methods that may reallocate the newly-deleted device. - // So we should wait for the device to no longer be present in the underlying set. - return [[[FBFuture - onQueue:dispatch_get_main_queue() resolveWhen:^BOOL{ - NSMutableSet *remainderSet = [NSMutableSet setWithSet:deletedDeviceUDIDs]; - [remainderSet intersectSet:[NSSet setWithArray:[set.allSimulators valueForKey:@"udid"]]]; - return remainderSet.count == 0; - }] - timeout:FBControlCoreGlobalConfiguration.regularTimeout waitingFor:@"Simulator to be removed from set"] - mapReplace:deletedDeviceUDIDs.allObjects]; -} - -- (FBFuture *)deleteSimulator:(FBSimulator *)simulator ++ (FBFuture *)delete:(FBSimulator *)simulator { // Get the Log Directory ahead of time as the Simulator will dissapear on deletion. NSString *coreSimulatorLogsDirectory = simulator.coreSimulatorLogsDirectory; dispatch_queue_t workQueue = simulator.workQueue; NSString *udid = simulator.udid; + FBSimulatorSet *set = simulator.set; // Kill the Simulators before deleting them. - [self.logger logFormat:@"Killing Simulator, in preparation for deletion %@", simulator]; - return [[[self.set - killSimulator:simulator] + [simulator.logger logFormat:@"Killing Simulator, in preparation for deletion %@", simulator]; + return [[[[FBSimulatorShutdownStrategy + shutdown:simulator] onQueue:workQueue fmap:^(id _) { // Then follow through with the actual deletion of the Simulator, which will remove it from the set. - [self.logger logFormat:@"Deleting Simulator %@", simulator]; - return [FBSimulatorDeletionStrategy onDeviceSet:self.set.deviceSet performDeletionOfDevice:simulator.device onQueue:simulator.asyncQueue]; + [simulator.logger logFormat:@"Deleting Simulator %@", simulator]; + return [FBSimulatorDeletionStrategy onDeviceSet:simulator.set.deviceSet performDeletionOfDevice:simulator.device onQueue:simulator.asyncQueue]; }] - onQueue:workQueue doOnResolved:^(id _) { - [self.logger logFormat:@"Simulator %@ Deleted", udid]; + onQueue:workQueue fmap:^(id _) { + [simulator.logger logFormat:@"Simulator %@ Deleted", udid]; // The Logfiles now need disposing of. 'erasing' a Simulator will cull the logfiles, // but deleting a Simulator will not. There's no sense in letting this directory accumilate files. if ([NSFileManager.defaultManager fileExistsAtPath:coreSimulatorLogsDirectory]) { - [self.logger logFormat:@"Deleting Simulator Log Directory at %@", coreSimulatorLogsDirectory]; + [simulator.logger logFormat:@"Deleting Simulator Log Directory at %@", coreSimulatorLogsDirectory]; NSError *error = nil; if ([NSFileManager.defaultManager removeItemAtPath:coreSimulatorLogsDirectory error:&error]) { - [self.logger logFormat:@"Deleted Simulator Log Directory at %@", coreSimulatorLogsDirectory]; + [simulator.logger logFormat:@"Deleted Simulator Log Directory at %@", coreSimulatorLogsDirectory]; } else { - [self.logger.error logFormat:@"Failed to delete Simulator Log Directory %@: %@", coreSimulatorLogsDirectory, error]; + [simulator.logger.error logFormat:@"Failed to delete Simulator Log Directory %@: %@", coreSimulatorLogsDirectory, error]; } } + + [simulator.logger logFormat:@"Confirming %@ has been removed from set", udid]; + return [FBSimulatorDeletionStrategy confirmSimulatorUDID:udid isRemovedFromSet:set]; + }] + onQueue:workQueue doOnResolved:^(id _) { + [simulator.logger logFormat:@"%@ has been removed from set", udid]; }]; } ++ (FBFuture *)deleteAll:(NSArray *)simulators +{ + NSMutableArray *> *futures = [NSMutableArray array]; + for (FBSimulator *simulator in simulators) { + [futures addObject:[self delete:simulator]]; + } + return [[FBFuture futureWithFutures:futures] mapReplace:NSNull.null]; +} + +#pragma mark Private + ++ (FBFuture *)confirmSimulatorUDID:(NSString *)udid isRemovedFromSet:(FBSimulatorSet *)set +{ + // Deleting the device from the set can still leave it around for a few seconds. + // This could race with methods that may reallocate the newly-deleted device. + // So we should wait for the device to no longer be present in the underlying set. + return [[FBFuture + onQueue:set.workQueue resolveWhen:^BOOL{ + NSSet *simulatorsInSet = [NSSet setWithArray:[set.allSimulators valueForKey:@"udid"]]; + return [simulatorsInSet containsObject:udid] == NO; + }] + timeout:FBControlCoreGlobalConfiguration.regularTimeout waitingFor:@"Simulator to be removed from set"]; +} + + (FBFuture *)onDeviceSet:(SimDeviceSet *)deviceSet performDeletionOfDevice:(SimDevice *)device onQueue:(dispatch_queue_t)queue { NSString *udid = device.UDID.UUIDString; diff --git a/FBSimulatorControl/Strategies/FBSimulatorEraseStrategy.h b/FBSimulatorControl/Strategies/FBSimulatorEraseStrategy.h index 288255e4a..07b881d69 100644 --- a/FBSimulatorControl/Strategies/FBSimulatorEraseStrategy.h +++ b/FBSimulatorControl/Strategies/FBSimulatorEraseStrategy.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -19,25 +19,15 @@ NS_ASSUME_NONNULL_BEGIN */ @interface FBSimulatorEraseStrategy : NSObject -#pragma mark Initializers - -/** - Creates a FBSimulatorEraseStrategy. - - @param set the Simulator Set to create the strategy for, - @return a configured FBSimulatorEraseStrategy instance. - */ -+ (instancetype)strategyForSet:(FBSimulatorSet *)set; - #pragma mark Public /** - Erases the provided Simulators, satisfying the relevant precondition of ensuring it is shutdown. + Erases the provided Simulator, satisfying the relevant precondition of ensuring it is shutdown. - @param simulators the Simulators to Erase. - @return A future wrapping the Simulators that this were erased. + @param simulator the Simulator to Erase. + @return A future that resolves when the Simulator is erased. */ -- (FBFuture *> *)eraseSimulators:(NSArray *)simulators; ++ (FBFuture *)erase:(FBSimulator *)simulator; @end diff --git a/FBSimulatorControl/Strategies/FBSimulatorEraseStrategy.m b/FBSimulatorControl/Strategies/FBSimulatorEraseStrategy.m index 815868841..c12401cf6 100644 --- a/FBSimulatorControl/Strategies/FBSimulatorEraseStrategy.m +++ b/FBSimulatorControl/Strategies/FBSimulatorEraseStrategy.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -12,68 +12,26 @@ #import "FBSimulator.h" #import "FBSimulatorError.h" #import "FBSimulatorSet.h" -#import "FBSimulatorTerminationStrategy.h" - -@interface FBSimulatorEraseStrategy () - -@property (nonatomic, weak, readonly) FBSimulatorSet *set; -@property (nonatomic, copy, readonly) FBSimulatorControlConfiguration *configuration; -@property (nonatomic, strong, nullable, readonly) id logger; - -@end +#import "FBSimulatorShutdownStrategy.h" @implementation FBSimulatorEraseStrategy -#pragma mark Initializers - -+ (instancetype)strategyForSet:(FBSimulatorSet *)set; -{ - return [[self alloc] initWithSet:set configuration:set.configuration logger:set.logger]; -} - -- (instancetype)initWithSet:(FBSimulatorSet *)set configuration:(FBSimulatorControlConfiguration *)configuration logger:(id)logger -{ - self = [super init]; - if (!self) { - return nil; - } - - _set = set; - _configuration = configuration; - _logger = logger; - - return self; -} - #pragma mark Public -- (FBFuture *> *)eraseSimulators:(NSArray *)simulators ++ (FBFuture *)erase:(FBSimulator *)simulator { - // Confirm that the Simulators belong to the Set. - for (FBSimulator *simulator in simulators) { - if (simulator.set != self.set) { - return [[FBSimulatorError - describeFormat:@"Simulator's set %@ is not %@, cannot erase", simulator.set, self] - failFuture]; - } - } - - return [[self.terminationStrategy - killSimulators:simulators] - onQueue:dispatch_get_main_queue() fmap:^(NSArray *result) { - NSMutableArray *> *futures = [NSMutableArray array]; - for (FBSimulator *simulator in result) { - [futures addObject:[self eraseContentsAndSettings:simulator]]; - } - return [FBFuture futureWithFutures:futures]; + return [[FBSimulatorShutdownStrategy + shutdown:simulator] + onQueue:simulator.workQueue fmap:^(id _) { + return [self eraseContentsAndSettings:simulator]; }]; } #pragma mark Private -- (FBFuture *)eraseContentsAndSettings:(FBSimulator *)simulator ++ (FBFuture *)eraseContentsAndSettings:(FBSimulator *)simulator { - [self.logger logFormat:@"Erasing %@", simulator]; + [simulator.logger logFormat:@"Erasing %@", simulator]; FBMutableFuture *future = FBMutableFuture.future; [simulator.device eraseContentsAndSettingsAsyncWithCompletionQueue:simulator.workQueue @@ -81,16 +39,11 @@ - (instancetype)initWithSet:(FBSimulatorSet *)set configuration:(FBSimulatorCont if (error) { [future resolveWithError:error]; } else { - [self.logger logFormat:@"Erased %@", simulator]; + [simulator.logger logFormat:@"Erased %@", simulator]; [future resolveWithResult:simulator]; } }]; return future; } -- (FBSimulatorTerminationStrategy *)terminationStrategy -{ - return [FBSimulatorTerminationStrategy strategyForSet:self.set]; -} - @end diff --git a/FBSimulatorControl/Strategies/FBSimulatorInflationStrategy.h b/FBSimulatorControl/Strategies/FBSimulatorInflationStrategy.h index f75f3ad7b..ed1351535 100644 --- a/FBSimulatorControl/Strategies/FBSimulatorInflationStrategy.h +++ b/FBSimulatorControl/Strategies/FBSimulatorInflationStrategy.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControl/Strategies/FBSimulatorInflationStrategy.m b/FBSimulatorControl/Strategies/FBSimulatorInflationStrategy.m index 1fea80a97..1afc274be 100644 --- a/FBSimulatorControl/Strategies/FBSimulatorInflationStrategy.m +++ b/FBSimulatorControl/Strategies/FBSimulatorInflationStrategy.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControl/Strategies/FBSimulatorNotificationUpdateStrategy.h b/FBSimulatorControl/Strategies/FBSimulatorNotificationUpdateStrategy.h index 5d0e9f80e..4a894fe25 100644 --- a/FBSimulatorControl/Strategies/FBSimulatorNotificationUpdateStrategy.h +++ b/FBSimulatorControl/Strategies/FBSimulatorNotificationUpdateStrategy.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControl/Strategies/FBSimulatorNotificationUpdateStrategy.m b/FBSimulatorControl/Strategies/FBSimulatorNotificationUpdateStrategy.m index abecf063a..3ca7d2b5e 100644 --- a/FBSimulatorControl/Strategies/FBSimulatorNotificationUpdateStrategy.m +++ b/FBSimulatorControl/Strategies/FBSimulatorNotificationUpdateStrategy.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -56,7 +56,7 @@ - (void)dealloc - (void)startNotifyingOfStateChanges { __weak typeof(self) weakSelf = self; - self.notifier = [FBCoreSimulatorNotifier notifierForSet:self.set queue:dispatch_get_main_queue() block:^(NSDictionary *info) { + self.notifier = [FBCoreSimulatorNotifier notifierForSet:self.set queue:self.set.workQueue block:^(NSDictionary *info) { SimDevice *device = info[@"device"]; if (!device) { return; @@ -75,6 +75,7 @@ - (void)device:(SimDevice *)device didChangeState:(FBiOSTargetState)state if (!simulator) { return; } + [simulator disconnectWithTimeout:FBControlCoreGlobalConfiguration.regularTimeout logger:simulator.logger]; [_set.delegate targetUpdated:simulator inTargetSet:simulator.set]; } diff --git a/FBSimulatorControl/Strategies/FBSimulatorShutdownStrategy.h b/FBSimulatorControl/Strategies/FBSimulatorShutdownStrategy.h index cb558046b..a38a4aef6 100644 --- a/FBSimulatorControl/Strategies/FBSimulatorShutdownStrategy.h +++ b/FBSimulatorControl/Strategies/FBSimulatorShutdownStrategy.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -18,16 +18,6 @@ NS_ASSUME_NONNULL_BEGIN */ @interface FBSimulatorShutdownStrategy : NSObject -#pragma mark Initializers - -/** - Create a Strategy for Shutting Down a Simulator. - - @param simulator the simulator to shutdown. - @return a new Strategy. - */ -+ (instancetype)strategyWithSimulator:(FBSimulator *)simulator; - #pragma mark Public Methdos /** @@ -47,7 +37,15 @@ NS_ASSUME_NONNULL_BEGIN @return A future that resolves when successful. */ -- (FBFuture *)shutdown; ++ (FBFuture *)shutdown:(FBSimulator *)simulator; + +/** + Batch operation for shutting down multiple simulators + + @param simulators the simulators to shutdown. + @return A future that resolves when successful. + */ ++ (FBFuture *)shutdownAll:(NSArray *)simulators; @end diff --git a/FBSimulatorControl/Strategies/FBSimulatorShutdownStrategy.m b/FBSimulatorControl/Strategies/FBSimulatorShutdownStrategy.m index e894c97fb..3ce54d15b 100644 --- a/FBSimulatorControl/Strategies/FBSimulatorShutdownStrategy.m +++ b/FBSimulatorControl/Strategies/FBSimulatorShutdownStrategy.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -44,10 +44,9 @@ - (instancetype)initWithSimulator:(FBSimulator *)simulator #pragma mark Public Methdos -- (FBFuture *)shutdown ++ (FBFuture *)shutdown:(FBSimulator *)simulator { - FBSimulator *simulator = self.simulator; - id logger = self.simulator.logger; + id logger = simulator.logger; [logger.debug logFormat:@"Starting Safe Shutdown of %@", simulator.udid]; // If the device is in a strange state, we should bail now @@ -74,6 +73,17 @@ - (instancetype)initWithSimulator:(FBSimulator *)simulator return [FBSimulatorShutdownStrategy shutdownSimulator:simulator]; } ++ (FBFuture *)shutdownAll:(NSArray *)simulators +{ + NSMutableArray *> *futures = NSMutableArray.array; + for (FBSimulator *simulator in simulators) { + [futures addObject:[self shutdown:simulator]]; + } + return [[FBFuture futureWithFutures:futures] mapReplace:NSNull.null]; +} + +#pragma mark Private + + (NSInteger)errorCodeForShutdownWhenShuttingDown { if (FBXcodeConfiguration.isXcode9OrGreater) { diff --git a/FBSimulatorControl/Strategies/FBSimulatorTerminationStrategy.h b/FBSimulatorControl/Strategies/FBSimulatorTerminationStrategy.h deleted file mode 100644 index 17553463c..000000000 --- a/FBSimulatorControl/Strategies/FBSimulatorTerminationStrategy.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#import - -#import - -NS_ASSUME_NONNULL_BEGIN - -@class FBSimulator; -@class FBSimulatorSet; - -/** - A class for terminating Simulators. - */ -@interface FBSimulatorTerminationStrategy : NSObject - -#pragma mark Initializers - -/** - Creates a FBSimulatorTerminationStrategy using the provided configuration. - - @param set the Simulator Set to log. - @return a configured FBSimulatorTerminationStrategy instance. - */ -+ (instancetype)strategyForSet:(FBSimulatorSet *)set; - -#pragma mark Public Methods - -/** - Kills the provided Simulators. - This call ensures that all of the Simulators: - 1) Have any relevant Simulator.app process killed (if any applicable Simulator.app process is found). - 2) Have the appropriate SimDevice state at 'Shutdown' - - @param simulators the Simulators to Kill. - @return A future that wraps an array of the Simulators that were killed. - */ -- (FBFuture *> *)killSimulators:(NSArray *)simulators; - -@end - -NS_ASSUME_NONNULL_END diff --git a/FBSimulatorControl/Strategies/FBSimulatorTerminationStrategy.m b/FBSimulatorControl/Strategies/FBSimulatorTerminationStrategy.m deleted file mode 100644 index a762f1084..000000000 --- a/FBSimulatorControl/Strategies/FBSimulatorTerminationStrategy.m +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#import "FBSimulatorTerminationStrategy.h" - -#import -#import -#import -#import - -#import - -#import "FBCoreSimulatorNotifier.h" -#import "FBSimulator+Private.h" -#import "FBSimulatorConfiguration+CoreSimulator.h" -#import "FBSimulatorConfiguration.h" -#import "FBSimulatorControl.h" -#import "FBSimulatorControlConfiguration.h" -#import "FBSimulatorError.h" -#import "FBSimulatorShutdownStrategy.h" -#import "FBSimulatorSet.h" - -@interface FBSimulatorTerminationStrategy () - -@property (nonatomic, weak, readonly) FBSimulatorSet *set; -@property (nonatomic, copy, readonly) FBSimulatorControlConfiguration *configuration; -@property (nonatomic, strong, nullable, readonly) id logger; - -@end - -@implementation FBSimulatorTerminationStrategy - -#pragma mark Initialization - -+ (instancetype)strategyForSet:(FBSimulatorSet *)set -{ - return [[self alloc] initWithSet:set configuration:set.configuration logger:set.logger]; -} - -- (instancetype)initWithSet:(FBSimulatorSet *)set configuration:(FBSimulatorControlConfiguration *)configuration logger:(id)logger -{ - NSParameterAssert(configuration); - - self = [super init]; - if (!self) { - return nil; - } - - _set = set; - _configuration = configuration; - _logger = logger; - - return self; -} - -#pragma mark Public Methods - -- (FBFuture *> *)killSimulators:(NSArray *)simulators -{ - // Confirm that the Simulators belong to the set - for (FBSimulator *simulator in simulators) { - if (simulator.set != self.set) { - return [[FBSimulatorError - describeFormat:@"Simulator's set %@ is not %@, cannot delete", simulator.set, self] - failFuture]; - } - } - - // It looks like there is a bug with El Capitan, where terminating multiple Applications quickly - // can result in the dock getting into an inconsistent state displaying icons for terminated Applications. - // - // This happens regardless of how the Application was terminated. - // The process backing the terminated Application is definitely gone, but the dock icon isn't. - // The Application appears in the Force Quit menu, but cannot ever be quit by conventional means. - // Attempting to shutdown the Mac will result in hanging (probably because it can't terminate the App). - // - // The only remedy is to quit 'launchservicesd' followed by 'Dock.app'. - // This will clear up the stale state that must exist in the Dock/launchservicesd. - // Waiting after killing of processes by a short period of time is sufficient to mitigate this issue. - // Since `-[FBSimDeviceWrapper shutdownWithError:]` will spin the run loop until CoreSimulator confirms that the device is shutdown, - // this will give a sufficient amount of time between killing Applications. - - [self.logger.debug logFormat:@"Killing %@", [FBCollectionInformation oneLineDescriptionFromArray:simulators]]; - NSMutableArray *> *futures = [NSMutableArray array]; - for (FBSimulator *simulator in simulators) { - [futures addObject:[self killSimulator:simulator]]; - } - return [FBFuture futureWithFutures:futures]; -} - -#pragma mark Private - -- (FBFuture *)killSimulator:(FBSimulator *)simulator -{ - // Shutdown will: - // 1) Wait for the Connection to the Simulator to Disconnect. - // 2) Wait for a Simulator launched via Simulator.app to be in a consistent 'Shutdown' state. - // 3) Shutdown a SimDevice that has been launched directly via. `-[SimDevice bootWithOptions:error]`. - return [[[simulator - disconnectWithTimeout:FBControlCoreGlobalConfiguration.regularTimeout logger:self.logger] - onQueue:simulator.workQueue fmap:^(id _) { - return [[FBSimulatorShutdownStrategy - strategyWithSimulator:simulator] - shutdown]; - }] mapReplace:simulator]; -} - -@end diff --git a/FBSimulatorControl/Utility/FBSimulatorControlFrameworkLoader.h b/FBSimulatorControl/Utility/FBSimulatorControlFrameworkLoader.h index 0fabaa208..d3c5f3a1d 100644 --- a/FBSimulatorControl/Utility/FBSimulatorControlFrameworkLoader.h +++ b/FBSimulatorControl/Utility/FBSimulatorControlFrameworkLoader.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControl/Utility/FBSimulatorControlFrameworkLoader.m b/FBSimulatorControl/Utility/FBSimulatorControlFrameworkLoader.m index 5cf5f1778..b5abfa15f 100644 --- a/FBSimulatorControl/Utility/FBSimulatorControlFrameworkLoader.m +++ b/FBSimulatorControl/Utility/FBSimulatorControlFrameworkLoader.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControl/Utility/FBSimulatorError.h b/FBSimulatorControl/Utility/FBSimulatorError.h index eae8111f0..1be864728 100644 --- a/FBSimulatorControl/Utility/FBSimulatorError.h +++ b/FBSimulatorControl/Utility/FBSimulatorError.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControl/Utility/FBSimulatorError.m b/FBSimulatorControl/Utility/FBSimulatorError.m index 6a1b967ac..2de0bedc8 100644 --- a/FBSimulatorControl/Utility/FBSimulatorError.m +++ b/FBSimulatorControl/Utility/FBSimulatorError.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControl/Utility/FBSimulatorLaunchedApplication.h b/FBSimulatorControl/Utility/FBSimulatorLaunchedApplication.h index 0e83440d1..3f84930f6 100644 --- a/FBSimulatorControl/Utility/FBSimulatorLaunchedApplication.h +++ b/FBSimulatorControl/Utility/FBSimulatorLaunchedApplication.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControl/Utility/FBSimulatorLaunchedApplication.m b/FBSimulatorControl/Utility/FBSimulatorLaunchedApplication.m index 5fb0e5a54..13297f222 100644 --- a/FBSimulatorControl/Utility/FBSimulatorLaunchedApplication.m +++ b/FBSimulatorControl/Utility/FBSimulatorLaunchedApplication.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -74,7 +74,7 @@ - (NSString *)bundleID + (FBFuture *)terminationFutureForSimulator:(FBSimulator *)simulator processIdentifier:(pid_t)processIdentifier { - return [[[FBDispatchSourceNotifier + return [[[self processTerminationFutureNotifierForProcessIdentifier:processIdentifier] mapReplace:NSNull.null] onQueue:simulator.workQueue respondToCancellation:^{ @@ -84,6 +84,30 @@ - (NSString *)bundleID }]; } ++ (FBFuture *)processTerminationFutureNotifierForProcessIdentifier:(pid_t)processIdentifier +{ + dispatch_queue_t queue = dispatch_queue_create("com.facebook.fbsimulatorcontrol.application_termination_notifier", DISPATCH_QUEUE_SERIAL); + dispatch_source_t source = dispatch_source_create( + DISPATCH_SOURCE_TYPE_PROC, + (unsigned long) processIdentifier, + DISPATCH_PROC_EXIT, + queue + ); + + FBMutableFuture *future = FBMutableFuture.future; + [future onQueue:queue respondToCancellation:^ FBFuture * { + dispatch_source_cancel(source); + return FBFuture.empty; + }]; + dispatch_source_set_event_handler(source, ^(){ + [future resolveWithResult:@(processIdentifier)]; + dispatch_source_cancel(source); + }); + dispatch_resume(source); + + return future; +} + #pragma mark NSObject - (NSString *)description diff --git a/FBSimulatorControlTests/Fixtures/FBSimulatorControlFixtures.h b/FBSimulatorControlTests/Fixtures/FBSimulatorControlFixtures.h index e85ef1468..01a8e7a0c 100644 --- a/FBSimulatorControlTests/Fixtures/FBSimulatorControlFixtures.h +++ b/FBSimulatorControlTests/Fixtures/FBSimulatorControlFixtures.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControlTests/Fixtures/FBSimulatorControlFixtures.m b/FBSimulatorControlTests/Fixtures/FBSimulatorControlFixtures.m index ac49d9107..202af4491 100644 --- a/FBSimulatorControlTests/Fixtures/FBSimulatorControlFixtures.m +++ b/FBSimulatorControlTests/Fixtures/FBSimulatorControlFixtures.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -71,7 +71,9 @@ - (FBTestLaunchConfiguration *)testLaunchTableSearch resultBundlePath:nil reportActivities:NO coverageDirectoryPath:nil - logDirectoryPath:nil]; + enableContinuousCoverageCollection:NO + logDirectoryPath:nil + reportResultBundle:NO]; } - (FBTestLaunchConfiguration *)testLaunchSafari @@ -90,7 +92,9 @@ - (FBTestLaunchConfiguration *)testLaunchSafari resultBundlePath:nil reportActivities:NO coverageDirectoryPath:nil - logDirectoryPath:nil]; + enableContinuousCoverageCollection:NO + logDirectoryPath:nil + reportResultBundle:NO]; } - (FBBundleDescriptor *)tableSearchApplication @@ -154,7 +158,7 @@ - (nullable FBBundleDescriptor *)iOSUnitTestBundle NSString *bundlePath = FBSimulatorControlFixtures.iOSUnitTestBundlePath; FBBundleDescriptor * bundle = [FBBundleDescriptor bundleFromPath:bundlePath error:&error]; XCTAssert(bundle, @"Failed to load bundle at %@: %@", bundlePath, error); - + FBCodesignProvider *codesign = [FBCodesignProvider codeSignCommandWithAdHocIdentityWithLogger:nil]; if ([[codesign cdHashForBundleAtPath:bundlePath] await:nil]) { return bundle; diff --git a/FBSimulatorControlTests/Tests/Integration/FBSimulatorApplicationDataTests.m b/FBSimulatorControlTests/Tests/Integration/FBSimulatorApplicationDataTests.m index e4abe42e6..bd3fecc02 100644 --- a/FBSimulatorControlTests/Tests/Integration/FBSimulatorApplicationDataTests.m +++ b/FBSimulatorControlTests/Tests/Integration/FBSimulatorApplicationDataTests.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -28,7 +28,7 @@ - (void)testRelocatesFile BOOL success = [[[simulator fileCommandsForContainerApplication:self.safariAppLaunch.bundleID] onQueue:simulator.asyncQueue pop:^(id container) { - return [container copyFromHost:[NSURL fileURLWithPath:fixturePath] toContainer:@"Documents"]; + return [container copyFromHost:fixturePath toContainer:@"Documents"]; }] await:&error] != nil; XCTAssertNil(error); diff --git a/FBSimulatorControlTests/Tests/Integration/FBSimulatorCrashLogTests.m b/FBSimulatorControlTests/Tests/Integration/FBSimulatorCrashLogTests.m index b4afb97e1..2e7172112 100644 --- a/FBSimulatorControlTests/Tests/Integration/FBSimulatorCrashLogTests.m +++ b/FBSimulatorControlTests/Tests/Integration/FBSimulatorCrashLogTests.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControlTests/Tests/Integration/FBSimulatorFramebufferTests.m b/FBSimulatorControlTests/Tests/Integration/FBSimulatorFramebufferTests.m index 908eb4c53..c4231778b 100644 --- a/FBSimulatorControlTests/Tests/Integration/FBSimulatorFramebufferTests.m +++ b/FBSimulatorControlTests/Tests/Integration/FBSimulatorFramebufferTests.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControlTests/Tests/Integration/FBSimulatorLaunchTests.m b/FBSimulatorControlTests/Tests/Integration/FBSimulatorLaunchTests.m index 38fbf8891..0e061e187 100644 --- a/FBSimulatorControlTests/Tests/Integration/FBSimulatorLaunchTests.m +++ b/FBSimulatorControlTests/Tests/Integration/FBSimulatorLaunchTests.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControlTests/Tests/Integration/FBSimulatorMediaCommandsTests.m b/FBSimulatorControlTests/Tests/Integration/FBSimulatorMediaCommandsTests.m index de0540374..b0deeabee 100644 --- a/FBSimulatorControlTests/Tests/Integration/FBSimulatorMediaCommandsTests.m +++ b/FBSimulatorControlTests/Tests/Integration/FBSimulatorMediaCommandsTests.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControlTests/Tests/Integration/FBSimulatorSetTests.m b/FBSimulatorControlTests/Tests/Integration/FBSimulatorSetTests.m index e75fa32f8..7ff49ec89 100644 --- a/FBSimulatorControlTests/Tests/Integration/FBSimulatorSetTests.m +++ b/FBSimulatorControlTests/Tests/Integration/FBSimulatorSetTests.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControlTests/Tests/Integration/FBSimulatorTestInjectionTests.m b/FBSimulatorControlTests/Tests/Integration/FBSimulatorTestInjectionTests.m index 4af14f694..93a85831b 100644 --- a/FBSimulatorControlTests/Tests/Integration/FBSimulatorTestInjectionTests.m +++ b/FBSimulatorControlTests/Tests/Integration/FBSimulatorTestInjectionTests.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -106,7 +106,9 @@ - (void)testInjectsApplicationTestWithCustomOutputConfiguration resultBundlePath:nil reportActivities:NO coverageDirectoryPath:nil - logDirectoryPath:nil]; + enableContinuousCoverageCollection:NO + logDirectoryPath:nil + reportResultBundle:NO]; FBSimulator *simulator = [self assertObtainsBootedSimulator]; [self assertLaunchesTestWithConfiguration:testLaunch reporter:self simulator:simulator]; @@ -142,7 +144,9 @@ - (void)testInjectsApplicationTestWithTestsToRun resultBundlePath:nil reportActivities:NO coverageDirectoryPath:nil - logDirectoryPath:nil]; + enableContinuousCoverageCollection:NO + logDirectoryPath:nil + reportResultBundle:NO]; [self assertLaunchesTestWithConfiguration:testLaunch reporter:self simulator:simulator]; [self assertPassed:@[@"testIsRunningOnIOS"] @@ -166,7 +170,9 @@ - (void)testInjectsApplicationTestWithTestsToSkip resultBundlePath:nil reportActivities:NO coverageDirectoryPath:nil - logDirectoryPath:nil]; + enableContinuousCoverageCollection:NO + logDirectoryPath:nil + reportResultBundle:NO]; [self assertLaunchesTestWithConfiguration:testLaunch reporter:self simulator:simulator]; [self assertPassed:@[@"testIsRunningInIOSApp", @"testHostProcessIsMobileSafari", @"testPossibleCrashingOfHostProcess", @"testPossibleStallingOfHostProcess", @"testWillAlwaysPass"] @@ -198,11 +204,6 @@ - (void)testCaseDidFinishForTestClass:(NSString *)testClass method:(NSString *)m } } -- (void)testCaseDidFailForTestClass:(NSString *)testClass method:(NSString *)method withMessage:(NSString *)message file:(NSString *)file line:(NSUInteger)line -{ - -} - - (void)testBundleReadyWithProtocolVersion:(NSInteger)protocolVersion minimumVersion:(NSInteger)minimumVersion { @@ -256,4 +257,10 @@ - (void)testHadOutput:(NSString *)output } +- (void)testCaseDidFailForTestClass:(nonnull NSString *)testClass method:(nonnull NSString *)method exceptions:(nonnull NSArray *)exceptions +{ + +} + + @end diff --git a/FBSimulatorControlTests/Tests/Unit/FBSimulatorApplicationDescriptorTests.m b/FBSimulatorControlTests/Tests/Unit/FBSimulatorApplicationDescriptorTests.m index 8754b6d4c..99ab14b43 100644 --- a/FBSimulatorControlTests/Tests/Unit/FBSimulatorApplicationDescriptorTests.m +++ b/FBSimulatorControlTests/Tests/Unit/FBSimulatorApplicationDescriptorTests.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControlTests/Tests/Unit/FBSimulatorConfigurationTests.m b/FBSimulatorControlTests/Tests/Unit/FBSimulatorConfigurationTests.m index a74323db8..08b8b237e 100644 --- a/FBSimulatorControlTests/Tests/Unit/FBSimulatorConfigurationTests.m +++ b/FBSimulatorControlTests/Tests/Unit/FBSimulatorConfigurationTests.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControlTests/Tests/Unit/FBSimulatorControlValueTypeTests.m b/FBSimulatorControlTests/Tests/Unit/FBSimulatorControlValueTypeTests.m index 5bf9b26ed..0275d1a06 100644 --- a/FBSimulatorControlTests/Tests/Unit/FBSimulatorControlValueTypeTests.m +++ b/FBSimulatorControlTests/Tests/Unit/FBSimulatorControlValueTypeTests.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControlTests/Utilities/CoreSimulatorDoubles.h b/FBSimulatorControlTests/Utilities/CoreSimulatorDoubles.h index 2144773f1..4ee10f08b 100644 --- a/FBSimulatorControlTests/Utilities/CoreSimulatorDoubles.h +++ b/FBSimulatorControlTests/Utilities/CoreSimulatorDoubles.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -7,8 +7,7 @@ #import -#import -#import +@class SimDeviceNotificationManager; @interface FBSimulatorControlTests_SimDeviceType_Double : NSObject diff --git a/FBSimulatorControlTests/Utilities/CoreSimulatorDoubles.m b/FBSimulatorControlTests/Utilities/CoreSimulatorDoubles.m index 5870e4cc3..c260668b7 100644 --- a/FBSimulatorControlTests/Utilities/CoreSimulatorDoubles.m +++ b/FBSimulatorControlTests/Utilities/CoreSimulatorDoubles.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControlTests/Utilities/FBSimulatorControlAssertions.h b/FBSimulatorControlTests/Utilities/FBSimulatorControlAssertions.h index fdfc9c4ce..229d32127 100644 --- a/FBSimulatorControlTests/Utilities/FBSimulatorControlAssertions.h +++ b/FBSimulatorControlTests/Utilities/FBSimulatorControlAssertions.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControlTests/Utilities/FBSimulatorControlAssertions.m b/FBSimulatorControlTests/Utilities/FBSimulatorControlAssertions.m index 9dc57ae1a..4d7237026 100644 --- a/FBSimulatorControlTests/Utilities/FBSimulatorControlAssertions.m +++ b/FBSimulatorControlTests/Utilities/FBSimulatorControlAssertions.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControlTests/Utilities/FBSimulatorControlTestCase.h b/FBSimulatorControlTests/Utilities/FBSimulatorControlTestCase.h index 55eb76848..bc60a5e93 100644 --- a/FBSimulatorControlTests/Utilities/FBSimulatorControlTestCase.h +++ b/FBSimulatorControlTests/Utilities/FBSimulatorControlTestCase.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControlTests/Utilities/FBSimulatorControlTestCase.m b/FBSimulatorControlTests/Utilities/FBSimulatorControlTestCase.m index add961273..6563ae6f5 100644 --- a/FBSimulatorControlTests/Utilities/FBSimulatorControlTestCase.m +++ b/FBSimulatorControlTests/Utilities/FBSimulatorControlTestCase.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -105,14 +105,14 @@ + (FBSimulatorBootConfiguration *)defaultBootConfiguration - (void)setUp { self.continueAfterFailure = NO; - self.simulatorConfiguration = [FBSimulatorConfiguration.defaultConfiguration withDeviceModel:FBDeviceModeliPhoneSE_1stGeneration]; + self.simulatorConfiguration = [FBSimulatorConfiguration.defaultConfiguration withDeviceModel:FBDeviceModeliPhone8]; self.bootConfiguration = [[FBSimulatorBootConfiguration alloc] initWithOptions:FBSimulatorControlTestCase.bootOptions environment:@{}]; self.deviceSetPath = FBSimulatorControlTestCase.defaultDeviceSetPath; } - (void)tearDown { - [[self.control.set killAll] await:nil]; + [[self.control.set shutdownAll] await:nil]; _control = nil; } diff --git a/FBSimulatorControlTests/Utilities/FBSimulatorSetTestCase.h b/FBSimulatorControlTests/Utilities/FBSimulatorSetTestCase.h index 20b92a138..35dd589d1 100644 --- a/FBSimulatorControlTests/Utilities/FBSimulatorSetTestCase.h +++ b/FBSimulatorControlTests/Utilities/FBSimulatorSetTestCase.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/FBSimulatorControlTests/Utilities/FBSimulatorSetTestCase.m b/FBSimulatorControlTests/Utilities/FBSimulatorSetTestCase.m index 310d2df09..ef56f0cb4 100644 --- a/FBSimulatorControlTests/Utilities/FBSimulatorSetTestCase.m +++ b/FBSimulatorControlTests/Utilities/FBSimulatorSetTestCase.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/Fixtures/Source/FBTestRunnerApp/FBAppDelegate.h b/Fixtures/Source/FBTestRunnerApp/FBAppDelegate.h index fe6778d2a..efc8aa73e 100644 --- a/Fixtures/Source/FBTestRunnerApp/FBAppDelegate.h +++ b/Fixtures/Source/FBTestRunnerApp/FBAppDelegate.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/Fixtures/Source/FBTestRunnerApp/FBAppDelegate.m b/Fixtures/Source/FBTestRunnerApp/FBAppDelegate.m index 958b1bd30..4eb5f0849 100644 --- a/Fixtures/Source/FBTestRunnerApp/FBAppDelegate.m +++ b/Fixtures/Source/FBTestRunnerApp/FBAppDelegate.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/Fixtures/Source/FBTestRunnerApp/main.m b/Fixtures/Source/FBTestRunnerApp/main.m index d09ef4f5b..71a606ca0 100644 --- a/Fixtures/Source/FBTestRunnerApp/main.m +++ b/Fixtures/Source/FBTestRunnerApp/main.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/Fixtures/Source/MacCommonApp/main.m b/Fixtures/Source/MacCommonApp/main.m index 0a358452b..ffc0574f6 100644 --- a/Fixtures/Source/MacCommonApp/main.m +++ b/Fixtures/Source/MacCommonApp/main.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/Fixtures/Source/MacUITestFixture/App/AppDelegate.h b/Fixtures/Source/MacUITestFixture/App/AppDelegate.h index 87e504611..4eb6e1f39 100644 --- a/Fixtures/Source/MacUITestFixture/App/AppDelegate.h +++ b/Fixtures/Source/MacUITestFixture/App/AppDelegate.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/Fixtures/Source/MacUITestFixture/App/AppDelegate.m b/Fixtures/Source/MacUITestFixture/App/AppDelegate.m index 9cabb429a..5b713d8a5 100644 --- a/Fixtures/Source/MacUITestFixture/App/AppDelegate.m +++ b/Fixtures/Source/MacUITestFixture/App/AppDelegate.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/Fixtures/Source/MacUITestFixture/App/main.m b/Fixtures/Source/MacUITestFixture/App/main.m index 0a358452b..ffc0574f6 100644 --- a/Fixtures/Source/MacUITestFixture/App/main.m +++ b/Fixtures/Source/MacUITestFixture/App/main.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/Fixtures/Source/MacUITestFixture/Tests/MacUITestFixtureUITests.m b/Fixtures/Source/MacUITestFixture/Tests/MacUITestFixtureUITests.m index 320e7b62f..ff2db75f2 100644 --- a/Fixtures/Source/MacUITestFixture/Tests/MacUITestFixtureUITests.m +++ b/Fixtures/Source/MacUITestFixture/Tests/MacUITestFixtureUITests.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/Fixtures/Source/MacUnitTestFixture/MacUnitTestFixtureTests.m b/Fixtures/Source/MacUnitTestFixture/MacUnitTestFixtureTests.m index c8ce8a650..c089e22fc 100644 --- a/Fixtures/Source/MacUnitTestFixture/MacUnitTestFixtureTests.m +++ b/Fixtures/Source/MacUnitTestFixture/MacUnitTestFixtureTests.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/Fixtures/Source/fetch_deps.sh b/Fixtures/Source/fetch_deps.sh index 23282bee0..31dbf8ec9 100755 --- a/Fixtures/Source/fetch_deps.sh +++ b/Fixtures/Source/fetch_deps.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. diff --git a/Fixtures/Source/iOSUITestFixture/App/main.m b/Fixtures/Source/iOSUITestFixture/App/main.m index 4b2ca29fa..e2b55460e 100644 --- a/Fixtures/Source/iOSUITestFixture/App/main.m +++ b/Fixtures/Source/iOSUITestFixture/App/main.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/Fixtures/Source/iOSUITestFixture/Tests/iOSUITestFixtureUITests.m b/Fixtures/Source/iOSUITestFixture/Tests/iOSUITestFixtureUITests.m index ee272bbc1..4d1c012dc 100644 --- a/Fixtures/Source/iOSUITestFixture/Tests/iOSUITestFixtureUITests.m +++ b/Fixtures/Source/iOSUITestFixture/Tests/iOSUITestFixtureUITests.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/Fixtures/Source/iOSUITestFixture/iOSAppFixtureAppTests/iOSAppFixtureAppTests.m b/Fixtures/Source/iOSUITestFixture/iOSAppFixtureAppTests/iOSAppFixtureAppTests.m index 3f0b2399a..5a71371b1 100755 --- a/Fixtures/Source/iOSUITestFixture/iOSAppFixtureAppTests/iOSAppFixtureAppTests.m +++ b/Fixtures/Source/iOSUITestFixture/iOSAppFixtureAppTests/iOSAppFixtureAppTests.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/Fixtures/Source/iOSUnitTestFixture/iOSUnitTestFixtureTests.m b/Fixtures/Source/iOSUnitTestFixture/iOSUnitTestFixtureTests.m index 654aaf986..7efd7a039 100644 --- a/Fixtures/Source/iOSUnitTestFixture/iOSUnitTestFixtureTests.m +++ b/Fixtures/Source/iOSUnitTestFixture/iOSUnitTestFixtureTests.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/IDBCompanionUtilities/Atomic.swift b/IDBCompanionUtilities/Atomic.swift new file mode 100644 index 000000000..4b4f53aa4 --- /dev/null +++ b/IDBCompanionUtilities/Atomic.swift @@ -0,0 +1,55 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import Foundation + +@propertyWrapper +public final class Atomic: @unchecked Sendable { + + private var value: Value + private let mutex: FBMutex + + public init(wrappedValue: Value) { + self.mutex = FBMutex() + self.value = wrappedValue + } + + /// Custom setter for wrapped value is dangerous thing, because it may give false safety feeling + /// + /// For example + /// ``` + /// @Atomic var counter = 0 + /// + /// DispatchQueue.global().async { counter = 10 } + /// ``` + /// is safe operation and perfectly valid. + /// From the other side, + /// ``` + /// DispatchQueue.global().async { counter += 10 } + /// ``` + /// is unsafe, because consists of two operations: read current counter and save new value to the counter. + /// For all mutation operations please use explicit synchronisation. + public var wrappedValue: Value { + mutex.sync(execute: { value }) + } + + /// Convenience plain setter. + /// This produces exact same results: + /// ``` + /// @Atomic var counter = 0 + /// + /// $counter.set(1) + /// $counter.sync { $0 = 1 } + /// ``` + public func `set`(_ newValue: Value) { + mutex.sync(execute: { value = newValue }) + } + + public func sync(execute work: (inout Value) throws -> R) rethrows -> R { + try mutex.sync(execute: { try work(&value) }) + } +} diff --git a/IDBCompanionUtilities/CodeLocation.swift b/IDBCompanionUtilities/CodeLocation.swift new file mode 100644 index 000000000..2b19313a4 --- /dev/null +++ b/IDBCompanionUtilities/CodeLocation.swift @@ -0,0 +1,19 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import Foundation + +struct CodeLocation: CustomStringConvertible { + let function: String? + let file: String + let line: Int + let column: Int + + var description: String { + "Located at file: \(file), line: \(line), column: \(column)" + (function.map { ", function: " + $0 } ?? "") + } +} diff --git a/IDBCompanionUtilities/FBTeardownContext.swift b/IDBCompanionUtilities/FBTeardownContext.swift new file mode 100644 index 000000000..a89554cfc --- /dev/null +++ b/IDBCompanionUtilities/FBTeardownContext.swift @@ -0,0 +1,131 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import Foundation + +enum FBTeardownContextError: Error, Sendable { + case emptyContext + case cleanupAlreadyPerformed +} + +private final class FBTeardownContextImpl: @unchecked Sendable { + + @Atomic private var cleanupList: [() async throws -> Void] = [] + @Atomic var cleanupPerformed = false + + func add(cleanup: @escaping () async throws -> Void) throws { + guard !cleanupPerformed else { + throw FBTeardownContextError.cleanupAlreadyPerformed + } + _cleanupList.sync { $0.append(cleanup) } + } + + func performCleanup() async throws { + let cleanupAlreadyPerformed = _cleanupPerformed.sync { cleanupPerformed -> Bool in + defer { cleanupPerformed = true } + return cleanupPerformed + } + guard !cleanupAlreadyPerformed else { + throw FBTeardownContextError.cleanupAlreadyPerformed + } + for cleanup in cleanupList.reversed() { + try await cleanup() + } + } +} + +/// Use this class to coordinate cleanup of the tasks. +/// +/// ``` +/// +/// func automaticCleanup() async throws -> Response { +/// return FBTeardownContext.withAutocleanup { +/// doSomeStuff() +/// } +/// } +/// +/// func doSomeStuff() { +/// let tmpDir = createTemporaryDirectory() +/// FBTeardownContext.current.addCleanup { +/// FileManager.default.remove(tmpDir) +/// } +/// addFiles(to: tmpDir) +/// } +/// +/// ``` +public final class FBTeardownContext: Sendable { + + /// Current context that binded to swift concurrency Task. For more info read about `@TaskLocal` + @TaskLocal public static var current: FBTeardownContext = .init(emptyContext: ()) + + private let contextImpl: FBTeardownContextImpl? + private let codeLocation: CodeLocation + private let isAutocleanup: Bool + + private init(emptyContext: ()) { + self.contextImpl = nil + self.isAutocleanup = false + self.codeLocation = .init(function: nil, file: "", line: 0, column: 0) + } + + /// Initializer is private intentionally to restrict to `withAutocleanup` usage + private init(isAutocleanup: Bool, function: String = #function, file: String = #file, line: Int = #line, column: Int = #column) { + self.contextImpl = FBTeardownContextImpl() + self.isAutocleanup = isAutocleanup + self.codeLocation = .init(function: function, file: file, line: line, column: column) + } + + /// Creates `FBContext` and executes operation with it + /// - Parameter operation: Inside the operation you have `FBTeardownContext.current` available that will be cleaned up on scoping out + /// - Returns: Operation result + public static func withAutocleanup(function: String = #function, file: String = #file, line: Int = #line, column: Int = #column, operation: @Sendable () async throws -> T) async throws -> T { + let context = FBTeardownContext(isAutocleanup: true, function: function, file: file, line: line, column: column) + let result = try await FBTeardownContext.$current.withValue(context, operation: operation) + try await context.performCleanup() + return result + } + + /// Adds cleanup closure to the stack. All cleanup jobs will be called in LIFO order + /// - Parameter cleanup: Task with cleanup job. There is no enforcement that job *should* throw an error on failure. This is optional. + public func addCleanup(_ cleanup: @escaping () async throws -> Void) throws { + guard let contextImpl else { + throw FBTeardownContextError.emptyContext + } + try contextImpl.add(cleanup: cleanup) + } + + /// This method should be called explicitly. Relying on deinit is programmer error. + public func performCleanup() async throws { + guard let contextImpl else { + throw FBTeardownContextError.emptyContext + } + try await contextImpl.performCleanup() + } + + deinit { + if let contextImpl, contextImpl.cleanupPerformed == false { + + if !Task.isCancelled && !isAutocleanup { + // Despite that we can cleanup automatically, this should be done explicitly + + // Note: + // When current task is cancelled, we may not reach explicit cleanup. + // Then cleanup in deinit is ok, bacause task cancellation means that we exceeded client + // request timeout and error propagation is not required anymore. + // But Task.isCancelled not always correctly represents cancellation in deinit (concurrency bug?) + // so there are possibility of false-failure report. + // To reduce false failures `isAutocleanup` introduced in contexts that used within 100% safe + // env with automatic cleanup error propagation. + assertionFailure("Context was not cleaned up explicitly. \(codeLocation)") + } + + Task { + try await contextImpl.performCleanup() + } + } + } +} diff --git a/IDBCompanionUtilities/FIFOStreamWriter.swift b/IDBCompanionUtilities/FIFOStreamWriter.swift new file mode 100644 index 000000000..435662203 --- /dev/null +++ b/IDBCompanionUtilities/FIFOStreamWriter.swift @@ -0,0 +1,59 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import Foundation + +public protocol AsyncStreamWriter { + associatedtype Value: Sendable + + func send(_ value: Value) async throws +} + +/// Wraps any async stream writer and bridges it to synchronous world +/// preserving FIFO order of elements. +public final class FIFOStreamWriter: @unchecked Sendable { + + private let stream: StreamWriter + + private let semaphore = DispatchSemaphore(value: 0) + + public init(stream: StreamWriter) { + self.stream = stream + } + + // We need to please swift concurrency checker, because + // interop between semaphores and swift concurrency is not compile-time safe + private class ErrorWrapper: @unchecked Sendable { + var error: Error? + } + + /// This method should be called from GCD + /// Never ever call that from swift concurrency cooperative pool thread, because it is unsafe + /// and you will violate swift concurrency contract. Doing that may cause deadlock of whole concurrency runtime. + public func send(_ value: StreamWriter.Value) throws { + // Implementation is indentionally naive. "Clever" implementation is much harder to understand + // and gives 0.01 better results on 1000 of elements. We can live pretty happily with + // that relatively "slow" impl. + // There is one downside in current implementation - it is blocking and we consume the thread. + // So we assume that `stream.send` will not live for a long time. + + let errWrapper = ErrorWrapper() + Task { + do { + try await stream.send(value) + } catch { + errWrapper.error = error + } + semaphore.signal() + } + semaphore.wait() + + if let err = errWrapper.error { + throw err + } + } +} diff --git a/IDBCompanionUtilities/Mutex.swift b/IDBCompanionUtilities/Mutex.swift new file mode 100644 index 000000000..69aa82213 --- /dev/null +++ b/IDBCompanionUtilities/Mutex.swift @@ -0,0 +1,37 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import Darwin +import Foundation + +/// Helper wrapper around `pthread_mutex` +final class FBMutex: @unchecked Sendable { + + private var underlyingMutex = pthread_mutex_t() + + init() { + var attr = pthread_mutexattr_t() + guard pthread_mutexattr_init(&attr) == 0 else { + preconditionFailure() + } + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL) + guard pthread_mutex_init(&underlyingMutex, &attr) == 0 else { + preconditionFailure() + } + pthread_mutexattr_destroy(&attr) + } + + func sync(execute work: () throws -> R) rethrows -> R { + pthread_mutex_lock(&underlyingMutex) + defer { pthread_mutex_unlock(&underlyingMutex) } + return try work() + } + + deinit { + pthread_mutex_destroy(&underlyingMutex) + } +} diff --git a/IDBCompanionUtilities/TaskSelect.swift b/IDBCompanionUtilities/TaskSelect.swift new file mode 100644 index 000000000..0a652a355 --- /dev/null +++ b/IDBCompanionUtilities/TaskSelect.swift @@ -0,0 +1,77 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import Foundation + +struct TaskSelectState: Sendable { + var complete = false + var tasks: [Task]? = [] + + mutating func add(_ task: Task) -> Task? { + if var tasks { + tasks.append(task) + self.tasks = tasks + return nil + } else { + return task + } + } +} + +extension Task { + /// Determine the first task to complete of a sequence of tasks. + /// + /// - Parameters: + /// - tasks: The running tasks to obtain a result from + /// - Returns: The first task to complete from the running tasks + public static func select( + _ tasks: Tasks + ) async -> Task + where Tasks.Element == Task, Success: Sendable { + + let state = Atomic>(wrappedValue: .init()) + return await withTaskCancellationHandler { + await withUnsafeContinuation { continuation in + for task in tasks { + Task { + _ = await task.result + let winner = state.sync { state -> Bool in + defer { state.complete = true } + return !state.complete + } + if winner { + continuation.resume(returning: task) + } + } + state.sync { state in + state.add(task) + }?.cancel() + } + } + } onCancel: { + + let tasks = state.sync { state -> [Task] in + defer { state.tasks = nil } + return state.tasks ?? [] + } + for task in tasks { + task.cancel() + } + } + } + + /// Determine the first task to complete of a list of tasks. + /// + /// - Parameters: + /// - tasks: The running tasks to obtain a result from + /// - Returns: The first task to complete from the running tasks + public static func select( + _ tasks: Task... + ) async -> Task where Success: Sendable { + await select(tasks) + } +} diff --git a/IDBCompanionUtilities/TaskTimeout.swift b/IDBCompanionUtilities/TaskTimeout.swift new file mode 100644 index 000000000..0dfb90e16 --- /dev/null +++ b/IDBCompanionUtilities/TaskTimeout.swift @@ -0,0 +1,35 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import Foundation + +struct TaskTimeoutError: Error, LocalizedError { + let location: CodeLocation + + var errorDescription: String? { + "Received timeout for task. \(location)" + } +} + +extension Task where Failure == Error { + + /// Awaits certain amount of time for a job throwing an error on timeouts + /// - Parameters: + /// - nanoseconds: Amount of time to wait + /// - Returns: Job result + public static func timeout(nanoseconds: UInt64, function: String = #function, file: String = #file, line: Int = #line, column: Int = #column, job: @escaping @Sendable () async throws -> Success) async throws -> Success { + let jobTask = Task { try await job() } + let result = await Task.select( + jobTask, + Task { + try await Task.sleep(nanoseconds: nanoseconds) + throw TaskTimeoutError(location: .init(function: function, file: file, line: line, column: column)) + } + ) + return try await result.value + } +} diff --git a/IDBCompanionUtilitiesTests/AtomicTests.swift b/IDBCompanionUtilitiesTests/AtomicTests.swift new file mode 100644 index 000000000..b0c296a3b --- /dev/null +++ b/IDBCompanionUtilitiesTests/AtomicTests.swift @@ -0,0 +1,51 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +@testable import IDBCompanionUtilities +import XCTest + +class AtomicTests: XCTestCase { + + func testAtomicSync() throws { + @Atomic var counter = 0 + + let iterationCount = 1000 + DispatchQueue.concurrentPerform(iterations: iterationCount) { _ in + _counter.sync { + $0 += 1 + } + } + + XCTAssertEqual(counter, iterationCount, "Counters don't match. Caution: this may be flaky, because it tests possible race condition.") + } + + func testConcurrentReadNoCrash() { + @Atomic var counter = 10 + + DispatchQueue.concurrentPerform(iterations: 1000) { _ in + XCTAssertEqual(counter, 10, "This should never fail, we test for concurrent read crashes") + } + } + + func testAtomicSet() { + @Atomic var counter = 0 + @Atomic var testableCounter = 0 + + let iterationCount = 1000 + DispatchQueue.concurrentPerform(iterations: iterationCount) { _ in + + // We assume that "sync" works and use that as a reference to test "set" + let etalonCounter = _counter.sync { c -> Int in + c += 1 + return c + } + _testableCounter.set(etalonCounter) + } + + XCTAssertEqual(counter, iterationCount, "Conters not match. Caution: this maby flacky, because tests possible race condition.") + } +} diff --git a/IDBCompanionUtilitiesTests/FIFOStreamWriterTests.swift b/IDBCompanionUtilitiesTests/FIFOStreamWriterTests.swift new file mode 100644 index 000000000..faacbc007 --- /dev/null +++ b/IDBCompanionUtilitiesTests/FIFOStreamWriterTests.swift @@ -0,0 +1,34 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +@testable import IDBCompanionUtilities +import XCTest + +class FIFOStreamWriterTests: XCTestCase { + + private static let maxValue: Int = 1_000 + let sequentialValues = (0...maxValue).map({ $0 }) + private var mockWriter = MockStreamWriter(terminator: maxValue) + + override func setUp() { + mockWriter = .init(terminator: Self.maxValue) + } + + func testFIFOOrder() throws { + let expectation = expectation(description: #function) + let fifoWrapper = FIFOStreamWriter(stream: mockWriter) + mockWriter.completion = { expectation.fulfill() } + + for value in sequentialValues { + try fifoWrapper.send(value) + } + + wait(for: [expectation], timeout: 2) + + XCTAssertEqual(sequentialValues, mockWriter.storage) + } +} diff --git a/IDBCompanionUtilitiesTests/Mocks/MockStreamWriter.swift b/IDBCompanionUtilitiesTests/Mocks/MockStreamWriter.swift new file mode 100644 index 000000000..2ab937138 --- /dev/null +++ b/IDBCompanionUtilitiesTests/Mocks/MockStreamWriter.swift @@ -0,0 +1,37 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import Foundation +import IDBCompanionUtilities + +enum MockStreamError: Error { + case completionIsNil +} + +class MockStreamWriter: AsyncStreamWriter { + + let terminator: Int + + @Atomic var storage: [Int] = [] + + var completion: (() -> Void)? + + init(terminator: Int) { + self.terminator = terminator + } + + func send(_ value: Int) async throws { + _storage.sync { $0.append(value) } + + if value == terminator { + guard let completion else { + throw MockStreamError.completionIsNil + } + completion() + } + } +} diff --git a/LICENSE b/LICENSE index b96dcb048..b93be9051 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) Facebook, Inc. and its affiliates. +Copyright (c) Meta Platforms, Inc. and affiliates. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Podfile b/Podfile deleted file mode 100644 index 5faf80c45..000000000 --- a/Podfile +++ /dev/null @@ -1,15 +0,0 @@ -workspace 'idb_companion' - -platform :macos, '10.14' - -project 'idb_companion' - -target 'idb_companion' do - pod 'gRPC-C++' - pod 'gRPC-C++/Protobuf' - pod 'Protobuf-C++', :git => 'https://github.com/google/protobuf.git', :tag => 'v3.17.3' -end - -target 'idbGRPC' do - pod 'Protobuf-C++', :git => 'https://github.com/google/protobuf.git', :tag => 'v3.17.3' -end diff --git a/Podfile.lock b/Podfile.lock deleted file mode 100644 index cd070ef6b..000000000 --- a/Podfile.lock +++ /dev/null @@ -1,434 +0,0 @@ -PODS: - - abseil/algorithm/algorithm (1.20210324.0): - - abseil/base/config - - abseil/algorithm/container (1.20210324.0): - - abseil/algorithm/algorithm - - abseil/base/core_headers - - abseil/meta/type_traits - - abseil/base/atomic_hook (1.20210324.0): - - abseil/base/config - - abseil/base/core_headers - - abseil/base/base (1.20210324.0): - - abseil/base/atomic_hook - - abseil/base/base_internal - - abseil/base/config - - abseil/base/core_headers - - abseil/base/dynamic_annotations - - abseil/base/log_severity - - abseil/base/raw_logging_internal - - abseil/base/spinlock_wait - - abseil/meta/type_traits - - abseil/base/base_internal (1.20210324.0): - - abseil/base/config - - abseil/meta/type_traits - - abseil/base/config (1.20210324.0) - - abseil/base/core_headers (1.20210324.0): - - abseil/base/config - - abseil/base/dynamic_annotations (1.20210324.0): - - abseil/base/config - - abseil/base/core_headers - - abseil/base/endian (1.20210324.0): - - abseil/base/base - - abseil/base/config - - abseil/base/core_headers - - abseil/base/errno_saver (1.20210324.0): - - abseil/base/config - - abseil/base/exponential_biased (1.20210324.0): - - abseil/base/config - - abseil/base/core_headers - - abseil/base/log_severity (1.20210324.0): - - abseil/base/config - - abseil/base/core_headers - - abseil/base/malloc_internal (1.20210324.0): - - abseil/base/base - - abseil/base/base_internal - - abseil/base/config - - abseil/base/core_headers - - abseil/base/dynamic_annotations - - abseil/base/raw_logging_internal - - abseil/base/raw_logging_internal (1.20210324.0): - - abseil/base/atomic_hook - - abseil/base/config - - abseil/base/core_headers - - abseil/base/log_severity - - abseil/base/spinlock_wait (1.20210324.0): - - abseil/base/base_internal - - abseil/base/core_headers - - abseil/base/errno_saver - - abseil/base/throw_delegate (1.20210324.0): - - abseil/base/config - - abseil/base/raw_logging_internal - - abseil/container/common (1.20210324.0): - - abseil/meta/type_traits - - abseil/types/optional - - abseil/container/compressed_tuple (1.20210324.0): - - abseil/utility/utility - - abseil/container/container_memory (1.20210324.0): - - abseil/base/config - - abseil/memory/memory - - abseil/meta/type_traits - - abseil/utility/utility - - abseil/container/fixed_array (1.20210324.0): - - abseil/algorithm/algorithm - - abseil/base/config - - abseil/base/core_headers - - abseil/base/dynamic_annotations - - abseil/base/throw_delegate - - abseil/container/compressed_tuple - - abseil/memory/memory - - abseil/container/flat_hash_map (1.20210324.0): - - abseil/algorithm/container - - abseil/container/container_memory - - abseil/container/hash_function_defaults - - abseil/container/raw_hash_map - - abseil/memory/memory - - abseil/container/hash_function_defaults (1.20210324.0): - - abseil/base/config - - abseil/hash/hash - - abseil/strings/cord - - abseil/strings/strings - - abseil/container/hash_policy_traits (1.20210324.0): - - abseil/meta/type_traits - - abseil/container/hashtable_debug_hooks (1.20210324.0): - - abseil/base/config - - abseil/container/hashtablez_sampler (1.20210324.0): - - abseil/base/base - - abseil/base/core_headers - - abseil/base/exponential_biased - - abseil/container/have_sse - - abseil/debugging/stacktrace - - abseil/memory/memory - - abseil/synchronization/synchronization - - abseil/utility/utility - - abseil/container/have_sse (1.20210324.0) - - abseil/container/inlined_vector (1.20210324.0): - - abseil/algorithm/algorithm - - abseil/base/core_headers - - abseil/base/throw_delegate - - abseil/container/inlined_vector_internal - - abseil/memory/memory - - abseil/container/inlined_vector_internal (1.20210324.0): - - abseil/base/core_headers - - abseil/container/compressed_tuple - - abseil/memory/memory - - abseil/meta/type_traits - - abseil/types/span - - abseil/container/layout (1.20210324.0): - - abseil/base/config - - abseil/base/core_headers - - abseil/meta/type_traits - - abseil/strings/strings - - abseil/types/span - - abseil/utility/utility - - abseil/container/raw_hash_map (1.20210324.0): - - abseil/base/throw_delegate - - abseil/container/container_memory - - abseil/container/raw_hash_set - - abseil/container/raw_hash_set (1.20210324.0): - - abseil/base/config - - abseil/base/core_headers - - abseil/base/endian - - abseil/container/common - - abseil/container/compressed_tuple - - abseil/container/container_memory - - abseil/container/hash_policy_traits - - abseil/container/hashtable_debug_hooks - - abseil/container/hashtablez_sampler - - abseil/container/have_sse - - abseil/container/layout - - abseil/memory/memory - - abseil/meta/type_traits - - abseil/numeric/bits - - abseil/utility/utility - - abseil/debugging/debugging_internal (1.20210324.0): - - abseil/base/config - - abseil/base/core_headers - - abseil/base/dynamic_annotations - - abseil/base/errno_saver - - abseil/base/raw_logging_internal - - abseil/debugging/demangle_internal (1.20210324.0): - - abseil/base/base - - abseil/base/config - - abseil/base/core_headers - - abseil/debugging/stacktrace (1.20210324.0): - - abseil/base/config - - abseil/base/core_headers - - abseil/debugging/debugging_internal - - abseil/debugging/symbolize (1.20210324.0): - - abseil/base/base - - abseil/base/config - - abseil/base/core_headers - - abseil/base/dynamic_annotations - - abseil/base/malloc_internal - - abseil/base/raw_logging_internal - - abseil/debugging/debugging_internal - - abseil/debugging/demangle_internal - - abseil/strings/strings - - abseil/functional/bind_front (1.20210324.0): - - abseil/base/base_internal - - abseil/container/compressed_tuple - - abseil/meta/type_traits - - abseil/utility/utility - - abseil/functional/function_ref (1.20210324.0): - - abseil/base/base_internal - - abseil/meta/type_traits - - abseil/hash/city (1.20210324.0): - - abseil/base/config - - abseil/base/core_headers - - abseil/base/endian - - abseil/hash/hash (1.20210324.0): - - abseil/base/config - - abseil/base/core_headers - - abseil/base/endian - - abseil/container/fixed_array - - abseil/hash/city - - abseil/hash/wyhash - - abseil/meta/type_traits - - abseil/numeric/int128 - - abseil/strings/strings - - abseil/types/optional - - abseil/types/variant - - abseil/utility/utility - - abseil/hash/wyhash (1.20210324.0): - - abseil/base/config - - abseil/base/endian - - abseil/numeric/int128 - - abseil/memory/memory (1.20210324.0): - - abseil/base/core_headers - - abseil/meta/type_traits - - abseil/meta/type_traits (1.20210324.0): - - abseil/base/config - - abseil/numeric/bits (1.20210324.0): - - abseil/base/config - - abseil/base/core_headers - - abseil/numeric/int128 (1.20210324.0): - - abseil/base/config - - abseil/base/core_headers - - abseil/numeric/bits - - abseil/numeric/representation (1.20210324.0): - - abseil/base/config - - abseil/status/status (1.20210324.0): - - abseil/base/atomic_hook - - abseil/base/config - - abseil/base/core_headers - - abseil/base/raw_logging_internal - - abseil/container/inlined_vector - - abseil/debugging/stacktrace - - abseil/debugging/symbolize - - abseil/strings/cord - - abseil/strings/str_format - - abseil/strings/strings - - abseil/types/optional - - abseil/status/statusor (1.20210324.0): - - abseil/base/core_headers - - abseil/base/raw_logging_internal - - abseil/meta/type_traits - - abseil/status/status - - abseil/strings/strings - - abseil/types/variant - - abseil/utility/utility - - abseil/strings/cord (1.20210324.0): - - abseil/base/base - - abseil/base/core_headers - - abseil/base/endian - - abseil/base/raw_logging_internal - - abseil/container/fixed_array - - abseil/container/inlined_vector - - abseil/functional/function_ref - - abseil/meta/type_traits - - abseil/strings/cord_internal - - abseil/strings/internal - - abseil/strings/str_format - - abseil/strings/strings - - abseil/types/optional - - abseil/strings/cord_internal (1.20210324.0): - - abseil/base/base_internal - - abseil/base/config - - abseil/base/core_headers - - abseil/base/endian - - abseil/base/raw_logging_internal - - abseil/base/throw_delegate - - abseil/container/compressed_tuple - - abseil/container/inlined_vector - - abseil/container/layout - - abseil/meta/type_traits - - abseil/strings/strings - - abseil/strings/internal (1.20210324.0): - - abseil/base/config - - abseil/base/core_headers - - abseil/base/endian - - abseil/base/raw_logging_internal - - abseil/meta/type_traits - - abseil/strings/str_format (1.20210324.0): - - abseil/strings/str_format_internal - - abseil/strings/str_format_internal (1.20210324.0): - - abseil/base/config - - abseil/base/core_headers - - abseil/functional/function_ref - - abseil/meta/type_traits - - abseil/numeric/bits - - abseil/numeric/int128 - - abseil/numeric/representation - - abseil/strings/strings - - abseil/types/optional - - abseil/types/span - - abseil/strings/strings (1.20210324.0): - - abseil/base/base - - abseil/base/config - - abseil/base/core_headers - - abseil/base/endian - - abseil/base/raw_logging_internal - - abseil/base/throw_delegate - - abseil/memory/memory - - abseil/meta/type_traits - - abseil/numeric/bits - - abseil/numeric/int128 - - abseil/strings/internal - - abseil/synchronization/graphcycles_internal (1.20210324.0): - - abseil/base/base - - abseil/base/base_internal - - abseil/base/config - - abseil/base/core_headers - - abseil/base/malloc_internal - - abseil/base/raw_logging_internal - - abseil/synchronization/kernel_timeout_internal (1.20210324.0): - - abseil/base/core_headers - - abseil/base/raw_logging_internal - - abseil/time/time - - abseil/synchronization/synchronization (1.20210324.0): - - abseil/base/atomic_hook - - abseil/base/base - - abseil/base/base_internal - - abseil/base/config - - abseil/base/core_headers - - abseil/base/dynamic_annotations - - abseil/base/malloc_internal - - abseil/base/raw_logging_internal - - abseil/debugging/stacktrace - - abseil/debugging/symbolize - - abseil/synchronization/graphcycles_internal - - abseil/synchronization/kernel_timeout_internal - - abseil/time/time - - abseil/time/internal/cctz/civil_time (1.20210324.0): - - abseil/base/config - - abseil/time/internal/cctz/time_zone (1.20210324.0): - - abseil/base/config - - abseil/time/internal/cctz/civil_time - - abseil/time/time (1.20210324.0): - - abseil/base/base - - abseil/base/core_headers - - abseil/base/raw_logging_internal - - abseil/numeric/int128 - - abseil/strings/strings - - abseil/time/internal/cctz/civil_time - - abseil/time/internal/cctz/time_zone - - abseil/types/bad_optional_access (1.20210324.0): - - abseil/base/config - - abseil/base/raw_logging_internal - - abseil/types/bad_variant_access (1.20210324.0): - - abseil/base/config - - abseil/base/raw_logging_internal - - abseil/types/optional (1.20210324.0): - - abseil/base/base_internal - - abseil/base/config - - abseil/base/core_headers - - abseil/memory/memory - - abseil/meta/type_traits - - abseil/types/bad_optional_access - - abseil/utility/utility - - abseil/types/span (1.20210324.0): - - abseil/algorithm/algorithm - - abseil/base/core_headers - - abseil/base/throw_delegate - - abseil/meta/type_traits - - abseil/types/variant (1.20210324.0): - - abseil/base/base_internal - - abseil/base/config - - abseil/base/core_headers - - abseil/meta/type_traits - - abseil/types/bad_variant_access - - abseil/utility/utility - - abseil/utility/utility (1.20210324.0): - - abseil/base/base_internal - - abseil/base/config - - abseil/meta/type_traits - - BoringSSL-GRPC (0.0.19): - - BoringSSL-GRPC/Implementation (= 0.0.19) - - BoringSSL-GRPC/Interface (= 0.0.19) - - BoringSSL-GRPC/Implementation (0.0.19): - - BoringSSL-GRPC/Interface (= 0.0.19) - - BoringSSL-GRPC/Interface (0.0.19) - - "gRPC-C++ (1.39.0)": - - "gRPC-C++/Implementation (= 1.39.0)" - - "gRPC-C++/Interface (= 1.39.0)" - - "gRPC-C++/Implementation (1.39.0)": - - abseil/base/base (= 1.20210324.0) - - abseil/container/flat_hash_map (= 1.20210324.0) - - abseil/container/inlined_vector (= 1.20210324.0) - - abseil/functional/bind_front (= 1.20210324.0) - - abseil/memory/memory (= 1.20210324.0) - - abseil/status/status (= 1.20210324.0) - - abseil/status/statusor (= 1.20210324.0) - - abseil/strings/str_format (= 1.20210324.0) - - abseil/strings/strings (= 1.20210324.0) - - abseil/synchronization/synchronization (= 1.20210324.0) - - abseil/time/time (= 1.20210324.0) - - abseil/types/optional (= 1.20210324.0) - - "gRPC-C++/Interface (= 1.39.0)" - - gRPC-Core (= 1.39.0) - - "gRPC-C++/Interface (1.39.0)" - - "gRPC-C++/Protobuf (1.39.0)": - - "gRPC-C++/Interface (= 1.39.0)" - - gRPC-Core (1.39.0): - - gRPC-Core/Implementation (= 1.39.0) - - gRPC-Core/Interface (= 1.39.0) - - gRPC-Core/Implementation (1.39.0): - - abseil/base/base (= 1.20210324.0) - - abseil/container/flat_hash_map (= 1.20210324.0) - - abseil/container/inlined_vector (= 1.20210324.0) - - abseil/functional/bind_front (= 1.20210324.0) - - abseil/memory/memory (= 1.20210324.0) - - abseil/status/status (= 1.20210324.0) - - abseil/status/statusor (= 1.20210324.0) - - abseil/strings/str_format (= 1.20210324.0) - - abseil/strings/strings (= 1.20210324.0) - - abseil/synchronization/synchronization (= 1.20210324.0) - - abseil/time/time (= 1.20210324.0) - - abseil/types/optional (= 1.20210324.0) - - BoringSSL-GRPC (= 0.0.19) - - gRPC-Core/Interface (= 1.39.0) - - gRPC-Core/Interface (1.39.0) - - "Protobuf-C++ (3.17.3)" - -DEPENDENCIES: - - "gRPC-C++" - - "gRPC-C++/Protobuf" - - "Protobuf-C++ (from `https://github.com/google/protobuf.git`, tag `v3.17.3`)" - -SPEC REPOS: - trunk: - - abseil - - BoringSSL-GRPC - - "gRPC-C++" - - gRPC-Core - -EXTERNAL SOURCES: - "Protobuf-C++": - :git: https://github.com/google/protobuf.git - :tag: v3.17.3 - -CHECKOUT OPTIONS: - "Protobuf-C++": - :git: https://github.com/google/protobuf.git - :tag: v3.17.3 - -SPEC CHECKSUMS: - abseil: c12cac4b0b499c3335ac47ac46adf303f0618d13 - BoringSSL-GRPC: a1ddc6446c98c7a0766cd2bab41a0713e80fa7d0 - "gRPC-C++": eefb08df432d7dd44caba1d2bc9fdf7686e1a3ad - gRPC-Core: 36cd647e4e4f0dd3071bf3379cf159d32e1bd690 - "Protobuf-C++": 09467b43c30aeea730319291bb12048b4ae28352 - -PODFILE CHECKSUM: 9781d66d53387d429f53a652871715cd4c11474d - -COCOAPODS: 1.11.2 diff --git a/PrivateHeaders/AXRuntime/AXTraits.h b/PrivateHeaders/AXRuntime/AXTraits.h index a93b1bc71..2bf76df81 100644 --- a/PrivateHeaders/AXRuntime/AXTraits.h +++ b/PrivateHeaders/AXRuntime/AXTraits.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/AccessibilityPlatformTranslation/AXPMacPlatformElement.h b/PrivateHeaders/AccessibilityPlatformTranslation/AXPMacPlatformElement.h index 0a537dc18..bde9f50cc 100644 --- a/PrivateHeaders/AccessibilityPlatformTranslation/AXPMacPlatformElement.h +++ b/PrivateHeaders/AccessibilityPlatformTranslation/AXPMacPlatformElement.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/AccessibilityPlatformTranslation/AXPTranslationElementProtocol-Protocol.h b/PrivateHeaders/AccessibilityPlatformTranslation/AXPTranslationElementProtocol-Protocol.h index ad548221a..ef375923a 100644 --- a/PrivateHeaders/AccessibilityPlatformTranslation/AXPTranslationElementProtocol-Protocol.h +++ b/PrivateHeaders/AccessibilityPlatformTranslation/AXPTranslationElementProtocol-Protocol.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/AccessibilityPlatformTranslation/AXPTranslationObject.h b/PrivateHeaders/AccessibilityPlatformTranslation/AXPTranslationObject.h index ba61eed28..b078a5202 100644 --- a/PrivateHeaders/AccessibilityPlatformTranslation/AXPTranslationObject.h +++ b/PrivateHeaders/AccessibilityPlatformTranslation/AXPTranslationObject.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/AccessibilityPlatformTranslation/AXPTranslator.h b/PrivateHeaders/AccessibilityPlatformTranslation/AXPTranslator.h index 43bf22079..dd854df6c 100644 --- a/PrivateHeaders/AccessibilityPlatformTranslation/AXPTranslator.h +++ b/PrivateHeaders/AccessibilityPlatformTranslation/AXPTranslator.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -10,6 +10,8 @@ @class AXPTranslationObject; @class AXPTranslatorResponse; @class AXPTranslatorRequest; +@class AXPTranslator_iOS; +@class AXPTranslator_macOS; /** The return type of the translation callbacks, this will synchronously provide a response by calling out to CoreSimulator. @@ -73,8 +75,8 @@ typedef AXPTranslatorResponse * (^AXPTranslationCallback)(AXPTranslatorRequest * NSMutableDictionary *_fakeElementCache; } -+ (id)sharedmacOSInstance; -+ (id)sharediOSInstance; ++ (AXPTranslator_macOS *)sharedmacOSInstance; ++ (AXPTranslator_iOS *)sharediOSInstance; + (id)sharedInstance; @property(nonatomic) BOOL supportsDelegateTokens; // @synthesize supportsDelegateTokens=_supportsDelegateTokens; @property(retain, nonatomic) NSMutableDictionary *fakeElementCache; // @synthesize fakeElementCache=_fakeElementCache; @@ -107,7 +109,7 @@ typedef AXPTranslatorResponse * (^AXPTranslationCallback)(AXPTranslatorRequest * - (void)_resetBridgeTokensForResponse:(id)arg1 bridgeDelegateToken:(id)arg2; - (void)handleNotification:(unsigned long long)arg1 data:(id)arg2 associatedObject:(id)arg3; - (AXPTranslationObject *)frontmostApplicationWithDisplayId:(unsigned int)arg1 bridgeDelegateToken:(NSString *)arg2; -- (id)_translationApplicationObjectForPidNumber:(id)arg1; +- (id)_translationApplicationObjectForPidNumber:(NSNumber *)arg1; - (id)translationApplicationObjectForPid:(int)arg1; - (id)translationApplicationObject; - (id)init; diff --git a/PrivateHeaders/AccessibilityPlatformTranslation/AXPTranslatorRequest.h b/PrivateHeaders/AccessibilityPlatformTranslation/AXPTranslatorRequest.h index 4856da9b0..a7890c0ad 100644 --- a/PrivateHeaders/AccessibilityPlatformTranslation/AXPTranslatorRequest.h +++ b/PrivateHeaders/AccessibilityPlatformTranslation/AXPTranslatorRequest.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/AccessibilityPlatformTranslation/AXPTranslatorResponse.h b/PrivateHeaders/AccessibilityPlatformTranslation/AXPTranslatorResponse.h index 8e372af87..b4df7ab4c 100644 --- a/PrivateHeaders/AccessibilityPlatformTranslation/AXPTranslatorResponse.h +++ b/PrivateHeaders/AccessibilityPlatformTranslation/AXPTranslatorResponse.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/AccessibilityPlatformTranslation/AXPTranslator_iOS.h b/PrivateHeaders/AccessibilityPlatformTranslation/AXPTranslator_iOS.h index b80daa2ad..57155fc0a 100644 --- a/PrivateHeaders/AccessibilityPlatformTranslation/AXPTranslator_iOS.h +++ b/PrivateHeaders/AccessibilityPlatformTranslation/AXPTranslator_iOS.h @@ -1,13 +1,15 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ +#import + #import -@class AXUIElement, NSMutableDictionary, NSObject; +@class AXUIElement; @interface AXPTranslator_iOS : AXPTranslator { @@ -16,8 +18,7 @@ NSObject *_cacheQueue; struct __IOHIDEventSystemClient *_ioSystemPostBackClient; BOOL _axAppReadyFlag; - BOOL _accessibilityEnabled; - struct __AXObserver *_axEventObserver; + id _axEventObserver; AXUIElement *_systemAppElement; AXUIElement *_systemWideElement; } @@ -25,10 +26,9 @@ + (id)_iosParameterFromPlatformParameter:(id)arg1; + (id)translationObjectFromUIKitObject:(id)arg1; + (id)sharedInstance; -- (void).cxx_destruct; @property(retain, nonatomic) AXUIElement *systemWideElement; // @synthesize systemWideElement=_systemWideElement; @property(retain, nonatomic) AXUIElement *systemAppElement; // @synthesize systemAppElement=_systemAppElement; -@property(retain, nonatomic) struct __AXObserver *axEventObserver; // @synthesize axEventObserver=_axEventObserver; +@property(retain, nonatomic) id axEventObserver; // @synthesize axEventObserver=_axEventObserver; - (BOOL)accessibilityEnabled; - (id)remoteTranslationDataWithTranslation:(id)arg1 pid:(int)arg2; - (id)translationObjectFromData:(id)arg1; diff --git a/PrivateHeaders/AccessibilityPlatformTranslation/AXPTranslator_macOS.h b/PrivateHeaders/AccessibilityPlatformTranslation/AXPTranslator_macOS.h index 81808c26d..74095e834 100644 --- a/PrivateHeaders/AccessibilityPlatformTranslation/AXPTranslator_macOS.h +++ b/PrivateHeaders/AccessibilityPlatformTranslation/AXPTranslator_macOS.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/AccessibilityPlatformTranslation/AXPiOSElementData.h b/PrivateHeaders/AccessibilityPlatformTranslation/AXPiOSElementData.h index 01b7a3477..beed8d074 100644 --- a/PrivateHeaders/AccessibilityPlatformTranslation/AXPiOSElementData.h +++ b/PrivateHeaders/AccessibilityPlatformTranslation/AXPiOSElementData.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/AccessibilityPlatformTranslation/CDStructures.h b/PrivateHeaders/AccessibilityPlatformTranslation/CDStructures.h index 9eed6ad41..17c161267 100644 --- a/PrivateHeaders/AccessibilityPlatformTranslation/CDStructures.h +++ b/PrivateHeaders/AccessibilityPlatformTranslation/CDStructures.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/AccessibilityPlatformTranslation/NSAccessibilityCustomElementDataProvider-Protocol.h b/PrivateHeaders/AccessibilityPlatformTranslation/NSAccessibilityCustomElementDataProvider-Protocol.h index 789b8abfa..418f2278f 100644 --- a/PrivateHeaders/AccessibilityPlatformTranslation/NSAccessibilityCustomElementDataProvider-Protocol.h +++ b/PrivateHeaders/AccessibilityPlatformTranslation/NSAccessibilityCustomElementDataProvider-Protocol.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/AccessibilityPlatformTranslation/NSAccessibilityCustomRotor-Private.h b/PrivateHeaders/AccessibilityPlatformTranslation/NSAccessibilityCustomRotor-Private.h index 8b771d57a..5da5aa712 100644 --- a/PrivateHeaders/AccessibilityPlatformTranslation/NSAccessibilityCustomRotor-Private.h +++ b/PrivateHeaders/AccessibilityPlatformTranslation/NSAccessibilityCustomRotor-Private.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/AccessibilityPlatformTranslation/NSAccessibilityCustomRotorItemSearchDelegate-Protocol.h b/PrivateHeaders/AccessibilityPlatformTranslation/NSAccessibilityCustomRotorItemSearchDelegate-Protocol.h index 07e129770..6e31dabe3 100644 --- a/PrivateHeaders/AccessibilityPlatformTranslation/NSAccessibilityCustomRotorItemSearchDelegate-Protocol.h +++ b/PrivateHeaders/AccessibilityPlatformTranslation/NSAccessibilityCustomRotorItemSearchDelegate-Protocol.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/AccessibilityPlatformTranslation/NSAccessibilityElement-Protocol.h b/PrivateHeaders/AccessibilityPlatformTranslation/NSAccessibilityElement-Protocol.h index b5a0f4aa3..3e91c9f7d 100644 --- a/PrivateHeaders/AccessibilityPlatformTranslation/NSAccessibilityElement-Protocol.h +++ b/PrivateHeaders/AccessibilityPlatformTranslation/NSAccessibilityElement-Protocol.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/AccessibilityPlatformTranslation/NSCoding-Protocol.h b/PrivateHeaders/AccessibilityPlatformTranslation/NSCoding-Protocol.h index 2edb4ffde..6ede8a951 100644 --- a/PrivateHeaders/AccessibilityPlatformTranslation/NSCoding-Protocol.h +++ b/PrivateHeaders/AccessibilityPlatformTranslation/NSCoding-Protocol.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/AccessibilityPlatformTranslation/NSCopying-Protocol.h b/PrivateHeaders/AccessibilityPlatformTranslation/NSCopying-Protocol.h index 66cc1fc4e..f268f5386 100644 --- a/PrivateHeaders/AccessibilityPlatformTranslation/NSCopying-Protocol.h +++ b/PrivateHeaders/AccessibilityPlatformTranslation/NSCopying-Protocol.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/AccessibilityPlatformTranslation/NSObject-Protocol.h b/PrivateHeaders/AccessibilityPlatformTranslation/NSObject-Protocol.h index 7228c4e04..c0039334f 100644 --- a/PrivateHeaders/AccessibilityPlatformTranslation/NSObject-Protocol.h +++ b/PrivateHeaders/AccessibilityPlatformTranslation/NSObject-Protocol.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/AccessibilityPlatformTranslation/NSSecureCoding-Protocol.h b/PrivateHeaders/AccessibilityPlatformTranslation/NSSecureCoding-Protocol.h index 25f84cf6e..a28d64a84 100644 --- a/PrivateHeaders/AccessibilityPlatformTranslation/NSSecureCoding-Protocol.h +++ b/PrivateHeaders/AccessibilityPlatformTranslation/NSSecureCoding-Protocol.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/CoreSimulator/CDStructures.h b/PrivateHeaders/CoreSimulator/CDStructures.h index 500b12b83..ee90207ec 100644 --- a/PrivateHeaders/CoreSimulator/CDStructures.h +++ b/PrivateHeaders/CoreSimulator/CDStructures.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/CoreSimulator/CoreSimulator+BlockDefines.h b/PrivateHeaders/CoreSimulator/CoreSimulator+BlockDefines.h index e262e290d..74b24dce0 100644 --- a/PrivateHeaders/CoreSimulator/CoreSimulator+BlockDefines.h +++ b/PrivateHeaders/CoreSimulator/CoreSimulator+BlockDefines.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/CoreSimulator/DefaultDisplayDescriptorState.h b/PrivateHeaders/CoreSimulator/DefaultDisplayDescriptorState.h index 820012b3c..82a8b68f4 100644 --- a/PrivateHeaders/CoreSimulator/DefaultDisplayDescriptorState.h +++ b/PrivateHeaders/CoreSimulator/DefaultDisplayDescriptorState.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/CoreSimulator/FoundationXPCProtocolProxyable-Protocol.h b/PrivateHeaders/CoreSimulator/FoundationXPCProtocolProxyable-Protocol.h index b80be1875..d15aa409a 100644 --- a/PrivateHeaders/CoreSimulator/FoundationXPCProtocolProxyable-Protocol.h +++ b/PrivateHeaders/CoreSimulator/FoundationXPCProtocolProxyable-Protocol.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/CoreSimulator/NSArray-SimArgv.h b/PrivateHeaders/CoreSimulator/NSArray-SimArgv.h index b9c2d7503..b23739b0e 100644 --- a/PrivateHeaders/CoreSimulator/NSArray-SimArgv.h +++ b/PrivateHeaders/CoreSimulator/NSArray-SimArgv.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/CoreSimulator/NSCoding-Protocol.h b/PrivateHeaders/CoreSimulator/NSCoding-Protocol.h index 24f4a288b..257abb6b6 100644 --- a/PrivateHeaders/CoreSimulator/NSCoding-Protocol.h +++ b/PrivateHeaders/CoreSimulator/NSCoding-Protocol.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/CoreSimulator/NSDictionary-SimEnvp.h b/PrivateHeaders/CoreSimulator/NSDictionary-SimEnvp.h index ba2a8aee9..d6a5fed16 100644 --- a/PrivateHeaders/CoreSimulator/NSDictionary-SimEnvp.h +++ b/PrivateHeaders/CoreSimulator/NSDictionary-SimEnvp.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/CoreSimulator/NSDictionary-SimSaveWithError.h b/PrivateHeaders/CoreSimulator/NSDictionary-SimSaveWithError.h index e47b7785a..d2968e76a 100644 --- a/PrivateHeaders/CoreSimulator/NSDictionary-SimSaveWithError.h +++ b/PrivateHeaders/CoreSimulator/NSDictionary-SimSaveWithError.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/CoreSimulator/NSError-SimError.h b/PrivateHeaders/CoreSimulator/NSError-SimError.h index 69d20c420..9c332d730 100644 --- a/PrivateHeaders/CoreSimulator/NSError-SimError.h +++ b/PrivateHeaders/CoreSimulator/NSError-SimError.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/CoreSimulator/NSFileManager-CoreSimulator.h b/PrivateHeaders/CoreSimulator/NSFileManager-CoreSimulator.h index 5dd303a00..30da29d56 100644 --- a/PrivateHeaders/CoreSimulator/NSFileManager-CoreSimulator.h +++ b/PrivateHeaders/CoreSimulator/NSFileManager-CoreSimulator.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/CoreSimulator/NSKeyedArchiver-SimPasteboardItem.h b/PrivateHeaders/CoreSimulator/NSKeyedArchiver-SimPasteboardItem.h index 10067f7a6..842b33e72 100644 --- a/PrivateHeaders/CoreSimulator/NSKeyedArchiver-SimPasteboardItem.h +++ b/PrivateHeaders/CoreSimulator/NSKeyedArchiver-SimPasteboardItem.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/CoreSimulator/NSKeyedArchiver-SimSecurely.h b/PrivateHeaders/CoreSimulator/NSKeyedArchiver-SimSecurely.h index c3cb6d7d0..f6e256622 100644 --- a/PrivateHeaders/CoreSimulator/NSKeyedArchiver-SimSecurely.h +++ b/PrivateHeaders/CoreSimulator/NSKeyedArchiver-SimSecurely.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/CoreSimulator/NSKeyedUnarchiver-SimPasteboardItem.h b/PrivateHeaders/CoreSimulator/NSKeyedUnarchiver-SimPasteboardItem.h index 305e700f7..6471b768f 100644 --- a/PrivateHeaders/CoreSimulator/NSKeyedUnarchiver-SimPasteboardItem.h +++ b/PrivateHeaders/CoreSimulator/NSKeyedUnarchiver-SimPasteboardItem.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/CoreSimulator/NSKeyedUnarchiver-SimSecurely.h b/PrivateHeaders/CoreSimulator/NSKeyedUnarchiver-SimSecurely.h index 36de8c381..3749b1112 100644 --- a/PrivateHeaders/CoreSimulator/NSKeyedUnarchiver-SimSecurely.h +++ b/PrivateHeaders/CoreSimulator/NSKeyedUnarchiver-SimSecurely.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/CoreSimulator/NSPasteboardItem-SimPasteboardItem.h b/PrivateHeaders/CoreSimulator/NSPasteboardItem-SimPasteboardItem.h index 87b08503d..4d3ea325a 100644 --- a/PrivateHeaders/CoreSimulator/NSPasteboardItem-SimPasteboardItem.h +++ b/PrivateHeaders/CoreSimulator/NSPasteboardItem-SimPasteboardItem.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/CoreSimulator/NSPasteboardItemDataProvider-Protocol.h b/PrivateHeaders/CoreSimulator/NSPasteboardItemDataProvider-Protocol.h index 8ab06a9ad..b12a75bd2 100644 --- a/PrivateHeaders/CoreSimulator/NSPasteboardItemDataProvider-Protocol.h +++ b/PrivateHeaders/CoreSimulator/NSPasteboardItemDataProvider-Protocol.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/CoreSimulator/NSSecureCoding-Protocol.h b/PrivateHeaders/CoreSimulator/NSSecureCoding-Protocol.h index 2259425fc..2d014cb0c 100644 --- a/PrivateHeaders/CoreSimulator/NSSecureCoding-Protocol.h +++ b/PrivateHeaders/CoreSimulator/NSSecureCoding-Protocol.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/CoreSimulator/NSString-SIMCPUType.h b/PrivateHeaders/CoreSimulator/NSString-SIMCPUType.h index 197f00b5d..0355fccb9 100644 --- a/PrivateHeaders/CoreSimulator/NSString-SIMCPUType.h +++ b/PrivateHeaders/CoreSimulator/NSString-SIMCPUType.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/CoreSimulator/NSString-SIMPackedVersion.h b/PrivateHeaders/CoreSimulator/NSString-SIMPackedVersion.h index 1c1fee83b..56e2f05ee 100644 --- a/PrivateHeaders/CoreSimulator/NSString-SIMPackedVersion.h +++ b/PrivateHeaders/CoreSimulator/NSString-SIMPackedVersion.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/CoreSimulator/NSString-SimServiceContextExtras.h b/PrivateHeaders/CoreSimulator/NSString-SimServiceContextExtras.h index d140e2e2f..37b4f9b6d 100644 --- a/PrivateHeaders/CoreSimulator/NSString-SimServiceContextExtras.h +++ b/PrivateHeaders/CoreSimulator/NSString-SimServiceContextExtras.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/CoreSimulator/NSUserDefaults-SimDefaults.h b/PrivateHeaders/CoreSimulator/NSUserDefaults-SimDefaults.h index debb871a1..fef2a9f97 100644 --- a/PrivateHeaders/CoreSimulator/NSUserDefaults-SimDefaults.h +++ b/PrivateHeaders/CoreSimulator/NSUserDefaults-SimDefaults.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/CoreSimulator/SimDevice+Removed.h b/PrivateHeaders/CoreSimulator/SimDevice+Removed.h index 7d41bda0f..96a4f2111 100644 --- a/PrivateHeaders/CoreSimulator/SimDevice+Removed.h +++ b/PrivateHeaders/CoreSimulator/SimDevice+Removed.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/CoreSimulator/SimDevice.h b/PrivateHeaders/CoreSimulator/SimDevice.h index 6bf6b660e..891159953 100644 --- a/PrivateHeaders/CoreSimulator/SimDevice.h +++ b/PrivateHeaders/CoreSimulator/SimDevice.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/CoreSimulator/SimDeviceBootInfo.h b/PrivateHeaders/CoreSimulator/SimDeviceBootInfo.h index 235e49ad6..713b64722 100644 --- a/PrivateHeaders/CoreSimulator/SimDeviceBootInfo.h +++ b/PrivateHeaders/CoreSimulator/SimDeviceBootInfo.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/CoreSimulator/SimDeviceIO.h b/PrivateHeaders/CoreSimulator/SimDeviceIO.h index 7601e5eae..5010a1d83 100644 --- a/PrivateHeaders/CoreSimulator/SimDeviceIO.h +++ b/PrivateHeaders/CoreSimulator/SimDeviceIO.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/CoreSimulator/SimDeviceIOClient.h b/PrivateHeaders/CoreSimulator/SimDeviceIOClient.h index 7a666a3f1..2013b659e 100644 --- a/PrivateHeaders/CoreSimulator/SimDeviceIOClient.h +++ b/PrivateHeaders/CoreSimulator/SimDeviceIOClient.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/CoreSimulator/SimDeviceIOInterface-Protocol.h b/PrivateHeaders/CoreSimulator/SimDeviceIOInterface-Protocol.h index 33aa2992f..2f12aa02b 100644 --- a/PrivateHeaders/CoreSimulator/SimDeviceIOInterface-Protocol.h +++ b/PrivateHeaders/CoreSimulator/SimDeviceIOInterface-Protocol.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/CoreSimulator/SimDeviceIOLoadedBundle.h b/PrivateHeaders/CoreSimulator/SimDeviceIOLoadedBundle.h index 2b1681dab..60978832c 100644 --- a/PrivateHeaders/CoreSimulator/SimDeviceIOLoadedBundle.h +++ b/PrivateHeaders/CoreSimulator/SimDeviceIOLoadedBundle.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/CoreSimulator/SimDeviceIOPortConsumer-Protocol.h b/PrivateHeaders/CoreSimulator/SimDeviceIOPortConsumer-Protocol.h index 6bb383b3c..2286fc9f9 100644 --- a/PrivateHeaders/CoreSimulator/SimDeviceIOPortConsumer-Protocol.h +++ b/PrivateHeaders/CoreSimulator/SimDeviceIOPortConsumer-Protocol.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/CoreSimulator/SimDeviceIOPortDescriptorState-Protocol.h b/PrivateHeaders/CoreSimulator/SimDeviceIOPortDescriptorState-Protocol.h index b81da78ac..5052988ca 100644 --- a/PrivateHeaders/CoreSimulator/SimDeviceIOPortDescriptorState-Protocol.h +++ b/PrivateHeaders/CoreSimulator/SimDeviceIOPortDescriptorState-Protocol.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/CoreSimulator/SimDeviceIOProtocol-Protocol.h b/PrivateHeaders/CoreSimulator/SimDeviceIOProtocol-Protocol.h index ac01b63bb..222a2e292 100644 --- a/PrivateHeaders/CoreSimulator/SimDeviceIOProtocol-Protocol.h +++ b/PrivateHeaders/CoreSimulator/SimDeviceIOProtocol-Protocol.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/CoreSimulator/SimDeviceIOServer.h b/PrivateHeaders/CoreSimulator/SimDeviceIOServer.h index d3b03b88e..a3d972833 100644 --- a/PrivateHeaders/CoreSimulator/SimDeviceIOServer.h +++ b/PrivateHeaders/CoreSimulator/SimDeviceIOServer.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/CoreSimulator/SimDeviceNotificationManager.h b/PrivateHeaders/CoreSimulator/SimDeviceNotificationManager.h index f2c9447f5..2c9345be1 100644 --- a/PrivateHeaders/CoreSimulator/SimDeviceNotificationManager.h +++ b/PrivateHeaders/CoreSimulator/SimDeviceNotificationManager.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/CoreSimulator/SimDeviceNotifier-Protocol.h b/PrivateHeaders/CoreSimulator/SimDeviceNotifier-Protocol.h index b4d2af455..92952c03f 100644 --- a/PrivateHeaders/CoreSimulator/SimDeviceNotifier-Protocol.h +++ b/PrivateHeaders/CoreSimulator/SimDeviceNotifier-Protocol.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/CoreSimulator/SimDevicePair.h b/PrivateHeaders/CoreSimulator/SimDevicePair.h index 22c9c2d51..16682c498 100644 --- a/PrivateHeaders/CoreSimulator/SimDevicePair.h +++ b/PrivateHeaders/CoreSimulator/SimDevicePair.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/CoreSimulator/SimDevicePasteboard.h b/PrivateHeaders/CoreSimulator/SimDevicePasteboard.h index ad1e0d32f..f96a88c65 100644 --- a/PrivateHeaders/CoreSimulator/SimDevicePasteboard.h +++ b/PrivateHeaders/CoreSimulator/SimDevicePasteboard.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/CoreSimulator/SimDevicePasteboardConnection.h b/PrivateHeaders/CoreSimulator/SimDevicePasteboardConnection.h index 7a11e2435..dff063ddd 100644 --- a/PrivateHeaders/CoreSimulator/SimDevicePasteboardConnection.h +++ b/PrivateHeaders/CoreSimulator/SimDevicePasteboardConnection.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/CoreSimulator/SimDevicePasteboardItem.h b/PrivateHeaders/CoreSimulator/SimDevicePasteboardItem.h index 82db00ffb..446387811 100644 --- a/PrivateHeaders/CoreSimulator/SimDevicePasteboardItem.h +++ b/PrivateHeaders/CoreSimulator/SimDevicePasteboardItem.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/CoreSimulator/SimDeviceSet+Removed.h b/PrivateHeaders/CoreSimulator/SimDeviceSet+Removed.h index d6b94b817..108001ede 100644 --- a/PrivateHeaders/CoreSimulator/SimDeviceSet+Removed.h +++ b/PrivateHeaders/CoreSimulator/SimDeviceSet+Removed.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/CoreSimulator/SimDeviceSet.h b/PrivateHeaders/CoreSimulator/SimDeviceSet.h index 0c68b3564..437bef797 100644 --- a/PrivateHeaders/CoreSimulator/SimDeviceSet.h +++ b/PrivateHeaders/CoreSimulator/SimDeviceSet.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/CoreSimulator/SimDeviceType+Removed.h b/PrivateHeaders/CoreSimulator/SimDeviceType+Removed.h index 2cc1904c7..77e24e201 100644 --- a/PrivateHeaders/CoreSimulator/SimDeviceType+Removed.h +++ b/PrivateHeaders/CoreSimulator/SimDeviceType+Removed.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/CoreSimulator/SimDeviceType.h b/PrivateHeaders/CoreSimulator/SimDeviceType.h index eced03cfd..3cbcf6af6 100644 --- a/PrivateHeaders/CoreSimulator/SimDeviceType.h +++ b/PrivateHeaders/CoreSimulator/SimDeviceType.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/CoreSimulator/SimDisplayDefaultDescriptorState.h b/PrivateHeaders/CoreSimulator/SimDisplayDefaultDescriptorState.h index 8acf32b52..cad87a1a0 100644 --- a/PrivateHeaders/CoreSimulator/SimDisplayDefaultDescriptorState.h +++ b/PrivateHeaders/CoreSimulator/SimDisplayDefaultDescriptorState.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/CoreSimulator/SimDisplayDescriptorState-Protocol.h b/PrivateHeaders/CoreSimulator/SimDisplayDescriptorState-Protocol.h index 80a2a986a..addc8a7b3 100644 --- a/PrivateHeaders/CoreSimulator/SimDisplayDescriptorState-Protocol.h +++ b/PrivateHeaders/CoreSimulator/SimDisplayDescriptorState-Protocol.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/CoreSimulator/SimLocalThrowable.h b/PrivateHeaders/CoreSimulator/SimLocalThrowable.h index 993e778a5..b52f0a294 100644 --- a/PrivateHeaders/CoreSimulator/SimLocalThrowable.h +++ b/PrivateHeaders/CoreSimulator/SimLocalThrowable.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/CoreSimulator/SimMachPortServer.h b/PrivateHeaders/CoreSimulator/SimMachPortServer.h index 2128c3589..dddfb9335 100644 --- a/PrivateHeaders/CoreSimulator/SimMachPortServer.h +++ b/PrivateHeaders/CoreSimulator/SimMachPortServer.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/CoreSimulator/SimNSPasteboard.h b/PrivateHeaders/CoreSimulator/SimNSPasteboard.h index b82822f07..f6149bd8f 100644 --- a/PrivateHeaders/CoreSimulator/SimNSPasteboard.h +++ b/PrivateHeaders/CoreSimulator/SimNSPasteboard.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/CoreSimulator/SimNSPasteboardItem.h b/PrivateHeaders/CoreSimulator/SimNSPasteboardItem.h index 2212fa469..c75848e30 100644 --- a/PrivateHeaders/CoreSimulator/SimNSPasteboardItem.h +++ b/PrivateHeaders/CoreSimulator/SimNSPasteboardItem.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/CoreSimulator/SimPasteboard-Protocol.h b/PrivateHeaders/CoreSimulator/SimPasteboard-Protocol.h index 7741d4aec..6cdcab1ba 100644 --- a/PrivateHeaders/CoreSimulator/SimPasteboard-Protocol.h +++ b/PrivateHeaders/CoreSimulator/SimPasteboard-Protocol.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/CoreSimulator/SimPasteboardItem.h b/PrivateHeaders/CoreSimulator/SimPasteboardItem.h index 72be8853c..9c586edba 100644 --- a/PrivateHeaders/CoreSimulator/SimPasteboardItem.h +++ b/PrivateHeaders/CoreSimulator/SimPasteboardItem.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/CoreSimulator/SimPasteboardItemData.h b/PrivateHeaders/CoreSimulator/SimPasteboardItemData.h index 7736417ff..5152e094c 100644 --- a/PrivateHeaders/CoreSimulator/SimPasteboardItemData.h +++ b/PrivateHeaders/CoreSimulator/SimPasteboardItemData.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/CoreSimulator/SimPasteboardItemDataProvider-Protocol.h b/PrivateHeaders/CoreSimulator/SimPasteboardItemDataProvider-Protocol.h index 581ab4177..737b98b99 100644 --- a/PrivateHeaders/CoreSimulator/SimPasteboardItemDataProvider-Protocol.h +++ b/PrivateHeaders/CoreSimulator/SimPasteboardItemDataProvider-Protocol.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/CoreSimulator/SimPasteboardItemWrappedData.h b/PrivateHeaders/CoreSimulator/SimPasteboardItemWrappedData.h index e08902fbd..53fdd909b 100644 --- a/PrivateHeaders/CoreSimulator/SimPasteboardItemWrappedData.h +++ b/PrivateHeaders/CoreSimulator/SimPasteboardItemWrappedData.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/CoreSimulator/SimPasteboardPortMap.h b/PrivateHeaders/CoreSimulator/SimPasteboardPortMap.h index 98945c742..73ab8a1c4 100644 --- a/PrivateHeaders/CoreSimulator/SimPasteboardPortMap.h +++ b/PrivateHeaders/CoreSimulator/SimPasteboardPortMap.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/CoreSimulator/SimPasteboardSyncPool.h b/PrivateHeaders/CoreSimulator/SimPasteboardSyncPool.h index 97a32a7a3..ff6f5d2ce 100644 --- a/PrivateHeaders/CoreSimulator/SimPasteboardSyncPool.h +++ b/PrivateHeaders/CoreSimulator/SimPasteboardSyncPool.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/CoreSimulator/SimPasteboardSyncPoolObject.h b/PrivateHeaders/CoreSimulator/SimPasteboardSyncPoolObject.h index ae4bf6413..ffd98b128 100644 --- a/PrivateHeaders/CoreSimulator/SimPasteboardSyncPoolObject.h +++ b/PrivateHeaders/CoreSimulator/SimPasteboardSyncPoolObject.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/CoreSimulator/SimPasteboardSyncPoolProtocol-Protocol.h b/PrivateHeaders/CoreSimulator/SimPasteboardSyncPoolProtocol-Protocol.h index 11489d8b1..73f000cf1 100644 --- a/PrivateHeaders/CoreSimulator/SimPasteboardSyncPoolProtocol-Protocol.h +++ b/PrivateHeaders/CoreSimulator/SimPasteboardSyncPoolProtocol-Protocol.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/CoreSimulator/SimProfilesPathMonitor.h b/PrivateHeaders/CoreSimulator/SimProfilesPathMonitor.h index 4c3f75098..647fcd3e0 100644 --- a/PrivateHeaders/CoreSimulator/SimProfilesPathMonitor.h +++ b/PrivateHeaders/CoreSimulator/SimProfilesPathMonitor.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/CoreSimulator/SimRuntime+Removed.h b/PrivateHeaders/CoreSimulator/SimRuntime+Removed.h index aebb36927..693126e5d 100644 --- a/PrivateHeaders/CoreSimulator/SimRuntime+Removed.h +++ b/PrivateHeaders/CoreSimulator/SimRuntime+Removed.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/CoreSimulator/SimRuntime.h b/PrivateHeaders/CoreSimulator/SimRuntime.h index 7bd1e3d40..766f9bed9 100644 --- a/PrivateHeaders/CoreSimulator/SimRuntime.h +++ b/PrivateHeaders/CoreSimulator/SimRuntime.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/CoreSimulator/SimRuntimePairingReuirements.h b/PrivateHeaders/CoreSimulator/SimRuntimePairingReuirements.h index 482233d14..7b995c9c3 100644 --- a/PrivateHeaders/CoreSimulator/SimRuntimePairingReuirements.h +++ b/PrivateHeaders/CoreSimulator/SimRuntimePairingReuirements.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/CoreSimulator/SimServiceContext.h b/PrivateHeaders/CoreSimulator/SimServiceContext.h index c243fdb90..fac2f4802 100644 --- a/PrivateHeaders/CoreSimulator/SimServiceContext.h +++ b/PrivateHeaders/CoreSimulator/SimServiceContext.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/DTXConnectionServices/CDStructures.h b/PrivateHeaders/DTXConnectionServices/CDStructures.h index 0feee1ecd..11eb20680 100644 --- a/PrivateHeaders/DTXConnectionServices/CDStructures.h +++ b/PrivateHeaders/DTXConnectionServices/CDStructures.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/DTXConnectionServices/DTXAllowedRPC-Protocol.h b/PrivateHeaders/DTXConnectionServices/DTXAllowedRPC-Protocol.h index 3584c2873..5d37b1081 100644 --- a/PrivateHeaders/DTXConnectionServices/DTXAllowedRPC-Protocol.h +++ b/PrivateHeaders/DTXConnectionServices/DTXAllowedRPC-Protocol.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/DTXConnectionServices/DTXBlockCompressor-Protocol.h b/PrivateHeaders/DTXConnectionServices/DTXBlockCompressor-Protocol.h index 1f7885f2f..ed8628e8c 100644 --- a/PrivateHeaders/DTXConnectionServices/DTXBlockCompressor-Protocol.h +++ b/PrivateHeaders/DTXConnectionServices/DTXBlockCompressor-Protocol.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/DTXConnectionServices/DTXBlockCompressorFactory.h b/PrivateHeaders/DTXConnectionServices/DTXBlockCompressorFactory.h index c3b964e9c..da44ad82a 100644 --- a/PrivateHeaders/DTXConnectionServices/DTXBlockCompressorFactory.h +++ b/PrivateHeaders/DTXConnectionServices/DTXBlockCompressorFactory.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/DTXConnectionServices/DTXBlockCompressorLibCompression.h b/PrivateHeaders/DTXConnectionServices/DTXBlockCompressorLibCompression.h index ec3953760..3ed818b05 100644 --- a/PrivateHeaders/DTXConnectionServices/DTXBlockCompressorLibCompression.h +++ b/PrivateHeaders/DTXConnectionServices/DTXBlockCompressorLibCompression.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/DTXConnectionServices/DTXBlockCompressorLibFastCompression.h b/PrivateHeaders/DTXConnectionServices/DTXBlockCompressorLibFastCompression.h index c6fdaea95..df503dedc 100644 --- a/PrivateHeaders/DTXConnectionServices/DTXBlockCompressorLibFastCompression.h +++ b/PrivateHeaders/DTXConnectionServices/DTXBlockCompressorLibFastCompression.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/DTXConnectionServices/DTXChannel.h b/PrivateHeaders/DTXConnectionServices/DTXChannel.h index ecca18b65..16b2b31e4 100644 --- a/PrivateHeaders/DTXConnectionServices/DTXChannel.h +++ b/PrivateHeaders/DTXConnectionServices/DTXChannel.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/DTXConnectionServices/DTXConnection.h b/PrivateHeaders/DTXConnectionServices/DTXConnection.h index c0f59ac85..5d353e67f 100644 --- a/PrivateHeaders/DTXConnectionServices/DTXConnection.h +++ b/PrivateHeaders/DTXConnectionServices/DTXConnection.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/DTXConnectionServices/DTXConnectionRemoteReceiveQueueCalls-Protocol.h b/PrivateHeaders/DTXConnectionServices/DTXConnectionRemoteReceiveQueueCalls-Protocol.h index e5dc2cb9a..f771e86c7 100644 --- a/PrivateHeaders/DTXConnectionServices/DTXConnectionRemoteReceiveQueueCalls-Protocol.h +++ b/PrivateHeaders/DTXConnectionServices/DTXConnectionRemoteReceiveQueueCalls-Protocol.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/DTXConnectionServices/DTXDecompressionException.h b/PrivateHeaders/DTXConnectionServices/DTXDecompressionException.h index 8d8b30aa3..2a3f57045 100644 --- a/PrivateHeaders/DTXConnectionServices/DTXDecompressionException.h +++ b/PrivateHeaders/DTXConnectionServices/DTXDecompressionException.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/DTXConnectionServices/DTXFileDescriptorTransport.h b/PrivateHeaders/DTXConnectionServices/DTXFileDescriptorTransport.h index 4373ae5b6..9c49cb51c 100644 --- a/PrivateHeaders/DTXConnectionServices/DTXFileDescriptorTransport.h +++ b/PrivateHeaders/DTXConnectionServices/DTXFileDescriptorTransport.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/DTXConnectionServices/DTXFoundationURLTransport.h b/PrivateHeaders/DTXConnectionServices/DTXFoundationURLTransport.h index 27df3312d..e56163321 100644 --- a/PrivateHeaders/DTXConnectionServices/DTXFoundationURLTransport.h +++ b/PrivateHeaders/DTXConnectionServices/DTXFoundationURLTransport.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/DTXConnectionServices/DTXLegacyBufferMessage.h b/PrivateHeaders/DTXConnectionServices/DTXLegacyBufferMessage.h index 75b114cad..b48d342b8 100644 --- a/PrivateHeaders/DTXConnectionServices/DTXLegacyBufferMessage.h +++ b/PrivateHeaders/DTXConnectionServices/DTXLegacyBufferMessage.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/DTXConnectionServices/DTXLegacyCompactDictionaryAdapter.h b/PrivateHeaders/DTXConnectionServices/DTXLegacyCompactDictionaryAdapter.h index 6808910f9..054196c4b 100644 --- a/PrivateHeaders/DTXConnectionServices/DTXLegacyCompactDictionaryAdapter.h +++ b/PrivateHeaders/DTXConnectionServices/DTXLegacyCompactDictionaryAdapter.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/DTXConnectionServices/DTXLegacyDictionaryMessage.h b/PrivateHeaders/DTXConnectionServices/DTXLegacyDictionaryMessage.h index 612f16cc2..f7d370c84 100644 --- a/PrivateHeaders/DTXConnectionServices/DTXLegacyDictionaryMessage.h +++ b/PrivateHeaders/DTXConnectionServices/DTXLegacyDictionaryMessage.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/DTXConnectionServices/DTXLegacyMessageParser.h b/PrivateHeaders/DTXConnectionServices/DTXLegacyMessageParser.h index f6af5d8e7..ec15b4af0 100644 --- a/PrivateHeaders/DTXConnectionServices/DTXLegacyMessageParser.h +++ b/PrivateHeaders/DTXConnectionServices/DTXLegacyMessageParser.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/DTXConnectionServices/DTXLegacyMessageTransmitter.h b/PrivateHeaders/DTXConnectionServices/DTXLegacyMessageTransmitter.h index 510d2866a..8fab06e75 100644 --- a/PrivateHeaders/DTXConnectionServices/DTXLegacyMessageTransmitter.h +++ b/PrivateHeaders/DTXConnectionServices/DTXLegacyMessageTransmitter.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/DTXConnectionServices/DTXLegacyServiceQueueAdapter.h b/PrivateHeaders/DTXConnectionServices/DTXLegacyServiceQueueAdapter.h index f2d5dff08..525f8ed39 100644 --- a/PrivateHeaders/DTXConnectionServices/DTXLegacyServiceQueueAdapter.h +++ b/PrivateHeaders/DTXConnectionServices/DTXLegacyServiceQueueAdapter.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/DTXConnectionServices/DTXMachTransport.h b/PrivateHeaders/DTXConnectionServices/DTXMachTransport.h index 6117d246c..51354e8bc 100644 --- a/PrivateHeaders/DTXConnectionServices/DTXMachTransport.h +++ b/PrivateHeaders/DTXConnectionServices/DTXMachTransport.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/DTXConnectionServices/DTXMessage.h b/PrivateHeaders/DTXConnectionServices/DTXMessage.h index e5da996da..64f8764d0 100644 --- a/PrivateHeaders/DTXConnectionServices/DTXMessage.h +++ b/PrivateHeaders/DTXConnectionServices/DTXMessage.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/DTXConnectionServices/DTXMessageParser.h b/PrivateHeaders/DTXConnectionServices/DTXMessageParser.h index 34dad3817..40fa50c3d 100644 --- a/PrivateHeaders/DTXConnectionServices/DTXMessageParser.h +++ b/PrivateHeaders/DTXConnectionServices/DTXMessageParser.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/DTXConnectionServices/DTXMessageParsingBuffer.h b/PrivateHeaders/DTXConnectionServices/DTXMessageParsingBuffer.h index a5969a4e3..98acae2c7 100644 --- a/PrivateHeaders/DTXConnectionServices/DTXMessageParsingBuffer.h +++ b/PrivateHeaders/DTXConnectionServices/DTXMessageParsingBuffer.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/DTXConnectionServices/DTXMessageTransmitter.h b/PrivateHeaders/DTXConnectionServices/DTXMessageTransmitter.h index 02ece631d..7f2366a47 100644 --- a/PrivateHeaders/DTXConnectionServices/DTXMessageTransmitter.h +++ b/PrivateHeaders/DTXConnectionServices/DTXMessageTransmitter.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/DTXConnectionServices/DTXMessenger-Protocol.h b/PrivateHeaders/DTXConnectionServices/DTXMessenger-Protocol.h index 1c222d415..323f7397b 100644 --- a/PrivateHeaders/DTXConnectionServices/DTXMessenger-Protocol.h +++ b/PrivateHeaders/DTXConnectionServices/DTXMessenger-Protocol.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/DTXConnectionServices/DTXProxyChannel.h b/PrivateHeaders/DTXConnectionServices/DTXProxyChannel.h index 2f1a32a83..66c8d6f19 100644 --- a/PrivateHeaders/DTXConnectionServices/DTXProxyChannel.h +++ b/PrivateHeaders/DTXConnectionServices/DTXProxyChannel.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/DTXConnectionServices/DTXRateLimiter-Protocol.h b/PrivateHeaders/DTXConnectionServices/DTXRateLimiter-Protocol.h index e58921b61..237bc408b 100644 --- a/PrivateHeaders/DTXConnectionServices/DTXRateLimiter-Protocol.h +++ b/PrivateHeaders/DTXConnectionServices/DTXRateLimiter-Protocol.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/DTXConnectionServices/DTXRemoteInvocationReceipt.h b/PrivateHeaders/DTXConnectionServices/DTXRemoteInvocationReceipt.h index 2f80122b8..7b4292877 100644 --- a/PrivateHeaders/DTXConnectionServices/DTXRemoteInvocationReceipt.h +++ b/PrivateHeaders/DTXConnectionServices/DTXRemoteInvocationReceipt.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/DTXConnectionServices/DTXResourceTracker.h b/PrivateHeaders/DTXConnectionServices/DTXResourceTracker.h index 5926bc1f0..0ccf3eb4e 100644 --- a/PrivateHeaders/DTXConnectionServices/DTXResourceTracker.h +++ b/PrivateHeaders/DTXConnectionServices/DTXResourceTracker.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/DTXConnectionServices/DTXSendAndWaitRateLimiter.h b/PrivateHeaders/DTXConnectionServices/DTXSendAndWaitRateLimiter.h index 5d45431ef..f7b3bba30 100644 --- a/PrivateHeaders/DTXConnectionServices/DTXSendAndWaitRateLimiter.h +++ b/PrivateHeaders/DTXConnectionServices/DTXSendAndWaitRateLimiter.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/DTXConnectionServices/DTXSendAndWaitStats.h b/PrivateHeaders/DTXConnectionServices/DTXSendAndWaitStats.h index 0125128c2..a7d2fb440 100644 --- a/PrivateHeaders/DTXConnectionServices/DTXSendAndWaitStats.h +++ b/PrivateHeaders/DTXConnectionServices/DTXSendAndWaitStats.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/DTXConnectionServices/DTXService.h b/PrivateHeaders/DTXConnectionServices/DTXService.h index ffd6410cf..baaad616c 100644 --- a/PrivateHeaders/DTXConnectionServices/DTXService.h +++ b/PrivateHeaders/DTXConnectionServices/DTXService.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/DTXConnectionServices/DTXSharedMemoryTransport.h b/PrivateHeaders/DTXConnectionServices/DTXSharedMemoryTransport.h index 110152993..8a20cd19b 100644 --- a/PrivateHeaders/DTXConnectionServices/DTXSharedMemoryTransport.h +++ b/PrivateHeaders/DTXConnectionServices/DTXSharedMemoryTransport.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/DTXConnectionServices/DTXSocketTransport.h b/PrivateHeaders/DTXConnectionServices/DTXSocketTransport.h index ec1d3f816..584a05a28 100644 --- a/PrivateHeaders/DTXConnectionServices/DTXSocketTransport.h +++ b/PrivateHeaders/DTXConnectionServices/DTXSocketTransport.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/DTXConnectionServices/DTXTransport.h b/PrivateHeaders/DTXConnectionServices/DTXTransport.h index 390048580..e0969e4e1 100644 --- a/PrivateHeaders/DTXConnectionServices/DTXTransport.h +++ b/PrivateHeaders/DTXConnectionServices/DTXTransport.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/DTXConnectionServices/_DTXProxy.h b/PrivateHeaders/DTXConnectionServices/_DTXProxy.h index 586091782..55ed7340c 100644 --- a/PrivateHeaders/DTXConnectionServices/_DTXProxy.h +++ b/PrivateHeaders/DTXConnectionServices/_DTXProxy.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/SimulatorApp/Indigo.h b/PrivateHeaders/SimulatorApp/Indigo.h index ed70d3028..a421ef57f 100644 --- a/PrivateHeaders/SimulatorApp/Indigo.h +++ b/PrivateHeaders/SimulatorApp/Indigo.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/SimulatorApp/Mach.h b/PrivateHeaders/SimulatorApp/Mach.h index 47e334e99..2dbf7790e 100644 --- a/PrivateHeaders/SimulatorApp/Mach.h +++ b/PrivateHeaders/SimulatorApp/Mach.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/SimulatorApp/Purple.h b/PrivateHeaders/SimulatorApp/Purple.h index 616c08ce8..74654f480 100644 --- a/PrivateHeaders/SimulatorApp/Purple.h +++ b/PrivateHeaders/SimulatorApp/Purple.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/SimulatorBridge/AXPTranslationRuntimeHelper-Protocol.h b/PrivateHeaders/SimulatorBridge/AXPTranslationRuntimeHelper-Protocol.h index 0cd93032a..d0b043634 100644 --- a/PrivateHeaders/SimulatorBridge/AXPTranslationRuntimeHelper-Protocol.h +++ b/PrivateHeaders/SimulatorBridge/AXPTranslationRuntimeHelper-Protocol.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/SimulatorBridge/SimulatorBridge-Protocol.h b/PrivateHeaders/SimulatorBridge/SimulatorBridge-Protocol.h index 36f015446..a822f1c49 100644 --- a/PrivateHeaders/SimulatorBridge/SimulatorBridge-Protocol.h +++ b/PrivateHeaders/SimulatorBridge/SimulatorBridge-Protocol.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/SimulatorBridge/SimulatorBridge.h b/PrivateHeaders/SimulatorBridge/SimulatorBridge.h index 343a90242..a63f89a36 100644 --- a/PrivateHeaders/SimulatorBridge/SimulatorBridge.h +++ b/PrivateHeaders/SimulatorBridge/SimulatorBridge.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/SimulatorKit/FoundationXPCProtocolProxyable-Protocol.h b/PrivateHeaders/SimulatorKit/FoundationXPCProtocolProxyable-Protocol.h index f88bfe766..afb23468c 100644 --- a/PrivateHeaders/SimulatorKit/FoundationXPCProtocolProxyable-Protocol.h +++ b/PrivateHeaders/SimulatorKit/FoundationXPCProtocolProxyable-Protocol.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/SimulatorKit/SimDeviceBootInfo-SimulatorKit.h b/PrivateHeaders/SimulatorKit/SimDeviceBootInfo-SimulatorKit.h index 8a11ac1eb..b5f6a895b 100644 --- a/PrivateHeaders/SimulatorKit/SimDeviceBootInfo-SimulatorKit.h +++ b/PrivateHeaders/SimulatorKit/SimDeviceBootInfo-SimulatorKit.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/SimulatorKit/SimDeviceFramebufferService.h b/PrivateHeaders/SimulatorKit/SimDeviceFramebufferService.h index b19c65101..018b315e9 100644 --- a/PrivateHeaders/SimulatorKit/SimDeviceFramebufferService.h +++ b/PrivateHeaders/SimulatorKit/SimDeviceFramebufferService.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/SimulatorKit/SimDeviceIOPortConsumer-Protocol.h b/PrivateHeaders/SimulatorKit/SimDeviceIOPortConsumer-Protocol.h index 5838a8634..adecb89ad 100644 --- a/PrivateHeaders/SimulatorKit/SimDeviceIOPortConsumer-Protocol.h +++ b/PrivateHeaders/SimulatorKit/SimDeviceIOPortConsumer-Protocol.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/SimulatorKit/SimDeviceIOPortDescriptorState-Protocol.h b/PrivateHeaders/SimulatorKit/SimDeviceIOPortDescriptorState-Protocol.h index cf17b1c80..e69077ff5 100644 --- a/PrivateHeaders/SimulatorKit/SimDeviceIOPortDescriptorState-Protocol.h +++ b/PrivateHeaders/SimulatorKit/SimDeviceIOPortDescriptorState-Protocol.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/SimulatorKit/SimDeviceIOPortInterface-Protocol.h b/PrivateHeaders/SimulatorKit/SimDeviceIOPortInterface-Protocol.h index 6fc33240b..41380f16d 100644 --- a/PrivateHeaders/SimulatorKit/SimDeviceIOPortInterface-Protocol.h +++ b/PrivateHeaders/SimulatorKit/SimDeviceIOPortInterface-Protocol.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/SimulatorKit/SimDeviceIOProtocol-Protocol.h b/PrivateHeaders/SimulatorKit/SimDeviceIOProtocol-Protocol.h index 868227114..d8a15c5b5 100644 --- a/PrivateHeaders/SimulatorKit/SimDeviceIOProtocol-Protocol.h +++ b/PrivateHeaders/SimulatorKit/SimDeviceIOProtocol-Protocol.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/SimulatorKit/SimDeviceLegacyClient.h b/PrivateHeaders/SimulatorKit/SimDeviceLegacyClient.h index a2ff35644..632609bf8 100644 --- a/PrivateHeaders/SimulatorKit/SimDeviceLegacyClient.h +++ b/PrivateHeaders/SimulatorKit/SimDeviceLegacyClient.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/SimulatorKit/SimDeviceMenu.h b/PrivateHeaders/SimulatorKit/SimDeviceMenu.h index beadcd8a0..20f526618 100644 --- a/PrivateHeaders/SimulatorKit/SimDeviceMenu.h +++ b/PrivateHeaders/SimulatorKit/SimDeviceMenu.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -23,7 +23,7 @@ @property (retain, nonatomic) NSMutableDictionary *menuItemPairForDeviceUDID; @property(nonatomic, assign) unsigned long long regID; // @synthesize regID=_regID; @property (retain, nonatomic) SimDeviceSet *deviceSet; -@property (nonatomic, assign) id simDeviceMenuDelegate; +@property (nonatomic, weak) id simDeviceMenuDelegate; - (BOOL)selectDevice:(id)arg1; - (void)clearSelectedDevice; diff --git a/PrivateHeaders/SimulatorKit/SimDeviceMenuItemPair.h b/PrivateHeaders/SimulatorKit/SimDeviceMenuItemPair.h index f39341fe0..44a652213 100644 --- a/PrivateHeaders/SimulatorKit/SimDeviceMenuItemPair.h +++ b/PrivateHeaders/SimulatorKit/SimDeviceMenuItemPair.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/SimulatorKit/SimDeviceNotifier-Protocol.h b/PrivateHeaders/SimulatorKit/SimDeviceNotifier-Protocol.h index 6e4ea1752..999a5bcea 100644 --- a/PrivateHeaders/SimulatorKit/SimDeviceNotifier-Protocol.h +++ b/PrivateHeaders/SimulatorKit/SimDeviceNotifier-Protocol.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/SimulatorKit/SimDisplayConsoleDebugger.h b/PrivateHeaders/SimulatorKit/SimDisplayConsoleDebugger.h index 05d8cd0b2..987a7b472 100644 --- a/PrivateHeaders/SimulatorKit/SimDisplayConsoleDebugger.h +++ b/PrivateHeaders/SimulatorKit/SimDisplayConsoleDebugger.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/SimulatorKit/SimDisplayDamageRectangleDelegate-Protocol.h b/PrivateHeaders/SimulatorKit/SimDisplayDamageRectangleDelegate-Protocol.h index a0bb80509..911d3f795 100644 --- a/PrivateHeaders/SimulatorKit/SimDisplayDamageRectangleDelegate-Protocol.h +++ b/PrivateHeaders/SimulatorKit/SimDisplayDamageRectangleDelegate-Protocol.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/SimulatorKit/SimDisplayDescriptorState-Protocol.h b/PrivateHeaders/SimulatorKit/SimDisplayDescriptorState-Protocol.h index 8f1845be7..24b85a38c 100644 --- a/PrivateHeaders/SimulatorKit/SimDisplayDescriptorState-Protocol.h +++ b/PrivateHeaders/SimulatorKit/SimDisplayDescriptorState-Protocol.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/SimulatorKit/SimDisplayIOSurfaceRenderable-Protocol.h b/PrivateHeaders/SimulatorKit/SimDisplayIOSurfaceRenderable-Protocol.h index 8eaa05176..715ee0c8d 100644 --- a/PrivateHeaders/SimulatorKit/SimDisplayIOSurfaceRenderable-Protocol.h +++ b/PrivateHeaders/SimulatorKit/SimDisplayIOSurfaceRenderable-Protocol.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -11,6 +11,16 @@ NS_ASSUME_NONNULL_BEGIN +/** + The underlying implementation is `ROCKRemoteProxy` and requesting the objects actually + performs call to some service. The selector object may and may not exists, + so checks like `[surface respondsToSelector: @selector(ioSurface)]` may return true, because + this selector exists in proxy implementation, but underlying object may still not implement that selector + and we will receive nil result. + + To be 100% sure we calling both methods (with plural underlying implementation and not) and one of the implementation + will succeed. + */ @protocol SimDisplayIOSurfaceRenderable /** @@ -24,10 +34,25 @@ NS_ASSUME_NONNULL_BEGIN */ @property (readonly, nullable, nonatomic) id ioSurface; +/** + In Xcode 13.2 ioSurface was splitted to two surfaces. Use `framebufferSurface` as primary implementation. + */ +@property (readonly, nullable, nonatomic) id framebufferSurface; + +/** + We do not actually use this, but still worth to know that is exists. + This clips image for devices with face id so image is not square, but in the shape of iPhone with notch + */ +@property (readonly, nullable, nonatomic) id maskedFramebufferSurface; + // Added in Xcode 9 as -[SimDeviceIOClient attachConsumer:] methods have been removed. - (void)unregisterIOSurfaceChangeCallbackWithUUID:(NSUUID *)arg1; - (void)registerCallbackWithUUID:(NSUUID *)arg1 ioSurfaceChangeCallback:(void (^)(id))arg2; +// Callbacks was slightly renamed in Xcode 13.2 to address two surfaces instead of one. +- (void)unregisterIOSurfacesChangeCallbackWithUUID:(NSUUID *)arg1; +- (void)registerCallbackWithUUID:(NSUUID *)arg1 ioSurfacesChangeCallback:(void (^)(id))arg2; + @end NS_ASSUME_NONNULL_END diff --git a/PrivateHeaders/SimulatorKit/SimDisplayIOSurfaceRenderableDelegate-Protocol.h b/PrivateHeaders/SimulatorKit/SimDisplayIOSurfaceRenderableDelegate-Protocol.h index 923c4d4de..62cdd6fe6 100644 --- a/PrivateHeaders/SimulatorKit/SimDisplayIOSurfaceRenderableDelegate-Protocol.h +++ b/PrivateHeaders/SimulatorKit/SimDisplayIOSurfaceRenderableDelegate-Protocol.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/SimulatorKit/SimDisplayRenderable-Protocol.h b/PrivateHeaders/SimulatorKit/SimDisplayRenderable-Protocol.h index 142930b0a..79fba58d2 100644 --- a/PrivateHeaders/SimulatorKit/SimDisplayRenderable-Protocol.h +++ b/PrivateHeaders/SimulatorKit/SimDisplayRenderable-Protocol.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/SimulatorKit/SimDisplayResizeableRenderable-Protocol.h b/PrivateHeaders/SimulatorKit/SimDisplayResizeableRenderable-Protocol.h index 61c7927d4..2f74aab86 100644 --- a/PrivateHeaders/SimulatorKit/SimDisplayResizeableRenderable-Protocol.h +++ b/PrivateHeaders/SimulatorKit/SimDisplayResizeableRenderable-Protocol.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/SimulatorKit/SimDisplayRotationAngleDelegate-Protocol.h b/PrivateHeaders/SimulatorKit/SimDisplayRotationAngleDelegate-Protocol.h index a5ebd2bff..440f9bfc6 100644 --- a/PrivateHeaders/SimulatorKit/SimDisplayRotationAngleDelegate-Protocol.h +++ b/PrivateHeaders/SimulatorKit/SimDisplayRotationAngleDelegate-Protocol.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/SimulatorKit/SimDisplayVideoWriter+Removed.h b/PrivateHeaders/SimulatorKit/SimDisplayVideoWriter+Removed.h index 003cfb0ad..cc7b70ee9 100644 --- a/PrivateHeaders/SimulatorKit/SimDisplayVideoWriter+Removed.h +++ b/PrivateHeaders/SimulatorKit/SimDisplayVideoWriter+Removed.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/SimulatorKit/SimDisplayVideoWriter.h b/PrivateHeaders/SimulatorKit/SimDisplayVideoWriter.h index b5607e697..bc8eade5a 100644 --- a/PrivateHeaders/SimulatorKit/SimDisplayVideoWriter.h +++ b/PrivateHeaders/SimulatorKit/SimDisplayVideoWriter.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/SimulatorKit/SimVideoFile.h b/PrivateHeaders/SimulatorKit/SimVideoFile.h index bc8441f81..82b53c36f 100644 --- a/PrivateHeaders/SimulatorKit/SimVideoFile.h +++ b/PrivateHeaders/SimulatorKit/SimVideoFile.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/SimulatorKit/SimVideoFragmentedMP4File.h b/PrivateHeaders/SimulatorKit/SimVideoFragmentedMP4File.h index 68b88286b..1ad2f8ecd 100644 --- a/PrivateHeaders/SimulatorKit/SimVideoFragmentedMP4File.h +++ b/PrivateHeaders/SimulatorKit/SimVideoFragmentedMP4File.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/SimulatorKit/SimVideoH264File.h b/PrivateHeaders/SimulatorKit/SimVideoH264File.h index 6d9999a60..a9591ae69 100644 --- a/PrivateHeaders/SimulatorKit/SimVideoH264File.h +++ b/PrivateHeaders/SimulatorKit/SimVideoH264File.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/SimulatorKit/SimVideoMP4File.h b/PrivateHeaders/SimulatorKit/SimVideoMP4File.h index 16dc8b5bb..159f3c88a 100644 --- a/PrivateHeaders/SimulatorKit/SimVideoMP4File.h +++ b/PrivateHeaders/SimulatorKit/SimVideoMP4File.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/SimulatorKit/SimVideoQuicktimeFormat.h b/PrivateHeaders/SimulatorKit/SimVideoQuicktimeFormat.h index 7d63c2084..d052cb2f0 100644 --- a/PrivateHeaders/SimulatorKit/SimVideoQuicktimeFormat.h +++ b/PrivateHeaders/SimulatorKit/SimVideoQuicktimeFormat.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/XCTest/CDStructures.h b/PrivateHeaders/XCTest/CDStructures.h deleted file mode 100644 index 0feee1ecd..000000000 --- a/PrivateHeaders/XCTest/CDStructures.h +++ /dev/null @@ -1,13 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#pragma mark Blocks - -typedef void (*CDUnknownFunctionPointerType)(void); // return type and parameters are unknown - -typedef void (^CDUnknownBlockType)(void); // return type and parameters are unknown - diff --git a/PrivateHeaders/XCTestPrivate/DTXConnection-XCTestAdditions.h b/PrivateHeaders/XCTestPrivate/DTXConnection-XCTestAdditions.h new file mode 100644 index 000000000..f3e3a3af3 --- /dev/null +++ b/PrivateHeaders/XCTestPrivate/DTXConnection-XCTestAdditions.h @@ -0,0 +1,13 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import "DTXConnectionServices/DTXConnection.h" + +@interface DTXConnection (XCTestAdditions) +- (id)xct_makeProxyChannelWithRemoteInterface:(id)arg1 exportedInterface:(id)arg2; +- (void)xct_handleProxyRequestForInterface:(id)arg1 peerInterface:(id)arg2 handler:(id)arg3; +@end diff --git a/PrivateHeaders/XCTestPrivate/DTXProxyChannel-XCTestAdditions.h b/PrivateHeaders/XCTestPrivate/DTXProxyChannel-XCTestAdditions.h new file mode 100644 index 000000000..6a9476dfb --- /dev/null +++ b/PrivateHeaders/XCTestPrivate/DTXProxyChannel-XCTestAdditions.h @@ -0,0 +1,12 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import "DTXConnectionServices/DTXProxyChannel.h" + +@interface DTXProxyChannel (XCTestAdditions) +- (void)xct_setAllowedClassesForTestingProtocols; +@end diff --git a/PrivateHeaders/XCTest/XCActivityRecord.h b/PrivateHeaders/XCTestPrivate/XCActivityRecord.h similarity index 98% rename from PrivateHeaders/XCTest/XCActivityRecord.h rename to PrivateHeaders/XCTestPrivate/XCActivityRecord.h index 3cc448633..e63395064 100644 --- a/PrivateHeaders/XCTest/XCActivityRecord.h +++ b/PrivateHeaders/XCTestPrivate/XCActivityRecord.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/XCTest/XCTAttachment.h b/PrivateHeaders/XCTestPrivate/XCTAttachment.h similarity index 97% rename from PrivateHeaders/XCTest/XCTAttachment.h rename to PrivateHeaders/XCTestPrivate/XCTAttachment.h index f1a5dc7e5..b7964d49a 100644 --- a/PrivateHeaders/XCTest/XCTAttachment.h +++ b/PrivateHeaders/XCTestPrivate/XCTAttachment.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/XCTestPrivate/XCTCapabilities.h b/PrivateHeaders/XCTestPrivate/XCTCapabilities.h new file mode 100644 index 000000000..66bb891ea --- /dev/null +++ b/PrivateHeaders/XCTestPrivate/XCTCapabilities.h @@ -0,0 +1,29 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import + +@interface XCTCapabilities : NSObject +{ + NSDictionary *_capabilitiesDictionary; +} + ++ (id)emptyCapabilities; ++ (_Bool)supportsSecureCoding; + +@property(readonly, copy) NSDictionary *capabilitiesDictionary; // @synthesize capabilitiesDictionary=_capabilitiesDictionary; +- (_Bool)hasCapability:(id)arg1; +- (unsigned long long)versionForCapability:(id)arg1; +- (unsigned long long)hash; +- (_Bool)isEqual:(id)arg1; +- (id)description; +- (void)encodeWithCoder:(id)arg1; +- (id)initWithCoder:(id)arg1; +@property(readonly, copy) NSDictionary *dictionaryRepresentation; +- (id)initWithDictionary:(id)arg1; + +@end diff --git a/PrivateHeaders/XCTestPrivate/XCTCapabilitiesBuilder.h b/PrivateHeaders/XCTestPrivate/XCTCapabilitiesBuilder.h new file mode 100644 index 000000000..91ca7fb4f --- /dev/null +++ b/PrivateHeaders/XCTestPrivate/XCTCapabilitiesBuilder.h @@ -0,0 +1,27 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import + +@class XCTCapabilities; + + +@interface XCTCapabilitiesBuilder : NSObject +{ + NSMutableDictionary *_capabilitiesDictionary; +} + ++ (id)capabilitiesFromProvider:(Class)arg1; + +@property(readonly, copy) NSMutableDictionary *capabilitiesDictionary; // @synthesize capabilitiesDictionary=_capabilitiesDictionary; +@property(readonly, copy) XCTCapabilities *capabilities; +- (void)upgradeCapability:(id)arg1 toVersion:(unsigned long long)arg2; +- (void)registerCapability:(id)arg1; +- (void)registerCapability:(id)arg1 version:(unsigned long long)arg2; +- (id)init; + +@end diff --git a/PrivateHeaders/XCTestPrivate/XCTIssue.h b/PrivateHeaders/XCTestPrivate/XCTIssue.h new file mode 100644 index 000000000..70a4996cf --- /dev/null +++ b/PrivateHeaders/XCTestPrivate/XCTIssue.h @@ -0,0 +1,189 @@ + +#import + +NS_ASSUME_NONNULL_BEGIN + +/*! + * @enum XCTIssueType + * Types of failures and other issues that can be reported for tests. + */ +typedef NS_ENUM(NSInteger, XCTIssueType) { + /// Issue raised by a failed XCTAssert or related API. + XCTIssueTypeAssertionFailure = 0, + /// Issue raised by the test throwing an error in Swift. This could also occur if an Objective C test is implemented in the form `- (BOOL)testFoo:(NSError **)outError` and returns NO with a non-nil out error. + XCTIssueTypeThrownError = 1, + /// Code in the test throws and does not catch an exception, Objective C, C++, or other. + XCTIssueTypeUncaughtException = 2, + /// One of the XCTestCase(measure:) family of APIs detected a performance regression. + XCTIssueTypePerformanceRegression = 3, + /// One of the framework APIs failed internally. For example, XCUIApplication was unable to launch or terminate an app or XCUIElementQuery was unable to complete a query. + XCTIssueTypeSystem = 4, + /// Issue raised when XCTExpectFailure is used but no matching issue is recorded. + XCTIssueTypeUnmatchedExpectedFailure = 5, +}; + +@class XCTAttachment; +@class XCTSourceCodeContext; + +/*! + * @class XCTIssue + * Encapsulates all data concerning a test failure or other issue. + */ +@interface XCTIssue : NSObject + +- (instancetype)initWithType:(XCTIssueType)type + compactDescription:(NSString *)compactDescription + detailedDescription:(nullable NSString *)detailedDescription + sourceCodeContext:(XCTSourceCodeContext *)sourceCodeContext + associatedError:(nullable NSError *)associatedError + attachments:(NSArray *)attachments NS_DESIGNATED_INITIALIZER; + +- (instancetype)initWithType:(XCTIssueType)type compactDescription:(NSString *)compactDescription; + +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)new NS_UNAVAILABLE; + +/// The type of the issue. +@property (readonly) XCTIssueType type; + +/// A concise description of the issue, expected to be free of transient data and suitable for use in test run +/// summaries and for aggregation of results across multiple test runs. +@property (readonly, copy) NSString *compactDescription; + +/// A detailed description of the issue designed to help diagnose the issue. May include transient data such as +/// numbers, object identifiers, timestamps, etc. +@property (readonly, copy, nullable) NSString *detailedDescription; + +/// The source code location (file and line number) and the call stack associated with the issue. +@property (readonly, strong) XCTSourceCodeContext *sourceCodeContext; + +/// Error associated with the issue. +@property (readonly, strong, nullable) NSError *associatedError; + +/// All attachments associated with the issue. +@property (readonly, copy) NSArray *attachments; + +@end + +/*! + * @class XCTMutableIssue + * Mutable variant of XCTIssue, suitable for modifying by overrides in the reporting chain. + */ +@interface XCTMutableIssue : XCTIssue + +@property (readwrite) XCTIssueType type; +@property (readwrite, copy) NSString *compactDescription; +@property (readwrite, copy, nullable) NSString *detailedDescription; +@property (readwrite, strong) XCTSourceCodeContext *sourceCodeContext; +@property (readwrite, strong, nullable) NSError *associatedError; +@property (readwrite, copy) NSArray *attachments; + +/// Add an attachment to this issue. +- (void)addAttachment:(XCTAttachment *)attachment; + +@end + +NS_ASSUME_NONNULL_END + + +#import + +NS_ASSUME_NONNULL_BEGIN + +/*! + * @class XCTSourceCodeLocation + * Contains a file URL and line number representing a distinct location in source code related to a run of a test. + */ +__attribute__((objc_subclassing_restricted)) +@interface XCTSourceCodeLocation : NSObject + +- (instancetype)initWithFileURL:(NSURL *)fileURL lineNumber:(NSInteger)lineNumber NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithFilePath:(NSString *)filePath lineNumber:(NSInteger)lineNumber; + +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)new NS_UNAVAILABLE; + +@property (readonly) NSURL *fileURL; +@property (readonly) NSInteger lineNumber; + +@end + +/*! + * @class XCTSourceCodeSymbolInfo + * Contains symbolication information for a given frame in a call stack. + */ +__attribute__((objc_subclassing_restricted)) +@interface XCTSourceCodeSymbolInfo : NSObject + +- (instancetype)initWithImageName:(NSString *)imageName + symbolName:(NSString *)symbolName + location:(nullable XCTSourceCodeLocation *)location NS_DESIGNATED_INITIALIZER; + +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)new NS_UNAVAILABLE; + +@property (readonly, copy) NSString *imageName; +@property (readonly, copy) NSString *symbolName; +@property (readonly, nullable) XCTSourceCodeLocation *location; + +@end + +/*! + * @class XCTSourceCodeFrame + * Represents a single frame in a call stack and supports retrieval of symbol information for the address. + */ +__attribute__((objc_subclassing_restricted)) +@interface XCTSourceCodeFrame : NSObject + +- (instancetype)initWithAddress:(uint64_t)address symbolInfo:(nullable XCTSourceCodeSymbolInfo *)symbolInfo NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithAddress:(uint64_t)address; + +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype)new NS_UNAVAILABLE; + +@property (readonly) uint64_t address; + +@property (readonly, nullable) XCTSourceCodeSymbolInfo *symbolInfo; + +/// Error previously returned for symbolication attempt. This is not serialized when the frame is encoded. +@property (readonly, nullable) NSError *symbolicationError; + +/*! + * method -symbolInfoWithError: + * Attempts to get symbol information for the address. This can fail if required symbol data is not available. Only + * one attempt will be made and the error will be stored and returned for future requests. + */ +- (nullable XCTSourceCodeSymbolInfo *)symbolInfoWithError:(NSError **)outError; + +@end + +/*! + * @class XCTSourceCodeContext + * Call stack and optional specific location - which may or may not be also included in the call stack + * providing context around a point of execution in a test. + */ +__attribute__((objc_subclassing_restricted)) +@interface XCTSourceCodeContext : NSObject + +- (instancetype)initWithCallStack:(NSArray *)callStack + location:(nullable XCTSourceCodeLocation *)location NS_DESIGNATED_INITIALIZER; + +/// The call stack addresses could be those from NSThread.callStackReturnAddresses, +/// NSException.callStackReturnAddresses, or another source. +- (instancetype)initWithCallStackAddresses:(NSArray *)callStackAddresses + location:(nullable XCTSourceCodeLocation *)location; + +/// Initializes a new instance with call stack derived from NSThread.callStackReturnAddresses and the specified location. +- (instancetype)initWithLocation:(nullable XCTSourceCodeLocation *)location; + +/// Initializes a new instance with call stack derived from NSThread.callStackReturnAddresses and a nil location. +- (instancetype)init; + +@property (readonly, copy) NSArray *callStack; +@property (readonly, nullable) XCTSourceCodeLocation *location; + +@end + +NS_ASSUME_NONNULL_END + + diff --git a/PrivateHeaders/XCTestPrivate/XCTMessagingChannel_DaemonRecorderToIDE-Protocol.h b/PrivateHeaders/XCTestPrivate/XCTMessagingChannel_DaemonRecorderToIDE-Protocol.h new file mode 100644 index 000000000..bc94eafd5 --- /dev/null +++ b/PrivateHeaders/XCTestPrivate/XCTMessagingChannel_DaemonRecorderToIDE-Protocol.h @@ -0,0 +1,16 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import +#import + +@protocol XCTMessagingChannel_DaemonRecorderToIDE + +@optional +- (void)__dummy_method_to_work_around_68987191; +@end + diff --git a/PrivateHeaders/XCTestPrivate/XCTMessagingChannel_DaemonToIDE-Protocol.h b/PrivateHeaders/XCTestPrivate/XCTMessagingChannel_DaemonToIDE-Protocol.h new file mode 100644 index 000000000..9872b804a --- /dev/null +++ b/PrivateHeaders/XCTestPrivate/XCTMessagingChannel_DaemonToIDE-Protocol.h @@ -0,0 +1,18 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import "XCTMessagingRole_CrashReporting-Protocol.h" +#import "XCTMessagingRole_DebugLogging-Protocol.h" +#import "XCTMessagingRole_SelfDiagnosisIssueReporting-Protocol.h" +#import "_XCTMessaging_VoidProtocol-Protocol.h" + +@protocol XCTMessagingChannel_DaemonToIDE + +@optional +- (void)__dummy_method_to_work_around_68987191; +@end + diff --git a/PrivateHeaders/XCTestPrivate/XCTMessagingChannel_DaemonToIDE_All-Protocol.h b/PrivateHeaders/XCTestPrivate/XCTMessagingChannel_DaemonToIDE_All-Protocol.h new file mode 100644 index 000000000..01f90ee52 --- /dev/null +++ b/PrivateHeaders/XCTestPrivate/XCTMessagingChannel_DaemonToIDE_All-Protocol.h @@ -0,0 +1,17 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import +#import +#import + +@protocol XCTMessagingChannel_DaemonToIDE_All + +@optional +- (void)__dummy_method_to_work_around_68987191; +@end + diff --git a/PrivateHeaders/XCTestPrivate/XCTMessagingChannel_DaemonToRunner-Protocol.h b/PrivateHeaders/XCTestPrivate/XCTMessagingChannel_DaemonToRunner-Protocol.h new file mode 100644 index 000000000..d9a5f4dd7 --- /dev/null +++ b/PrivateHeaders/XCTestPrivate/XCTMessagingChannel_DaemonToRunner-Protocol.h @@ -0,0 +1,17 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import +#import +#import + +@protocol XCTMessagingChannel_DaemonToRunner + +@optional +- (void)__dummy_method_to_work_around_68987191; +@end + diff --git a/PrivateHeaders/XCTestPrivate/XCTMessagingChannel_IDEToDaemon-Protocol.h b/PrivateHeaders/XCTestPrivate/XCTMessagingChannel_IDEToDaemon-Protocol.h new file mode 100644 index 000000000..e44131dad --- /dev/null +++ b/PrivateHeaders/XCTestPrivate/XCTMessagingChannel_IDEToDaemon-Protocol.h @@ -0,0 +1,12 @@ +#import "XCTMessagingRole_ControlSessionInitiation-Protocol.h" +#import "XCTMessagingRole_DiagnosticsCollection-Protocol.h" +#import "XCTMessagingRole_RunnerSessionInitiation-Protocol.h" +#import "XCTMessagingRole_UIRecordingControl-Protocol.h" +#import "_XCTMessaging_VoidProtocol-Protocol.h" + +@protocol XCTMessagingChannel_IDEToDaemon + +@optional +- (void)__dummy_method_to_work_around_68987191; +@end + diff --git a/PrivateHeaders/XCTestPrivate/XCTMessagingChannel_IDEToRunner-Protocol.h b/PrivateHeaders/XCTestPrivate/XCTMessagingChannel_IDEToRunner-Protocol.h new file mode 100644 index 000000000..360c39e09 --- /dev/null +++ b/PrivateHeaders/XCTestPrivate/XCTMessagingChannel_IDEToRunner-Protocol.h @@ -0,0 +1,11 @@ +#import "XCTMessagingRole_ProcessMonitoring-Protocol.h" +#import "XCTMessagingRole_TestExecution-Protocol.h" +#import "XCTMessagingRole_TestExecution_Legacy-Protocol.h" +#import "_XCTMessaging_VoidProtocol-Protocol.h" + +@protocol XCTMessagingChannel_IDEToRunner + +@optional +- (void)__dummy_method_to_work_around_68987191; +@end + diff --git a/PrivateHeaders/XCTestPrivate/XCTMessagingChannel_RunnerToDaemon-Protocol.h b/PrivateHeaders/XCTestPrivate/XCTMessagingChannel_RunnerToDaemon-Protocol.h new file mode 100644 index 000000000..5972fb15a --- /dev/null +++ b/PrivateHeaders/XCTestPrivate/XCTMessagingChannel_RunnerToDaemon-Protocol.h @@ -0,0 +1,22 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import +#import +#import +#import +#import +#import +#import +#import + +@protocol XCTMessagingChannel_RunnerToDaemon + +@optional +- (void)__dummy_method_to_work_around_68987191; +@end + diff --git a/PrivateHeaders/XCTestPrivate/XCTMessagingChannel_RunnerToIDE-Protocol.h b/PrivateHeaders/XCTestPrivate/XCTMessagingChannel_RunnerToIDE-Protocol.h new file mode 100644 index 000000000..3574cb735 --- /dev/null +++ b/PrivateHeaders/XCTestPrivate/XCTMessagingChannel_RunnerToIDE-Protocol.h @@ -0,0 +1,24 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import "XCTMessagingRole_ActivityReporting-Protocol.h" +#import "XCTMessagingRole_ActivityReporting_Legacy-Protocol.h" +#import "XCTMessagingRole_DebugLogging-Protocol.h" +#import "XCTMessagingRole_PerformanceMeasurementReporting-Protocol.h" +#import "XCTMessagingRole_PerformanceMeasurementReporting_Legacy-Protocol.h" +#import "XCTMessagingRole_SelfDiagnosisIssueReporting-Protocol.h" +#import "XCTMessagingRole_TestReporting-Protocol.h" +#import "XCTMessagingRole_TestReporting_Legacy-Protocol.h" +#import "XCTMessagingRole_UIAutomation-Protocol.h" +#import "_XCTMessaging_VoidProtocol-Protocol.h" + +@protocol XCTMessagingChannel_RunnerToIDE + +@optional +- (void)__dummy_method_to_work_around_68987191; +@end + diff --git a/PrivateHeaders/XCTestPrivate/XCTMessagingChannel_RunnerToUIProcess-Protocol.h b/PrivateHeaders/XCTestPrivate/XCTMessagingChannel_RunnerToUIProcess-Protocol.h new file mode 100644 index 000000000..5215509ca --- /dev/null +++ b/PrivateHeaders/XCTestPrivate/XCTMessagingChannel_RunnerToUIProcess-Protocol.h @@ -0,0 +1,16 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import +#import + +@protocol XCTMessagingChannel_RunnerToUIProcess + +@optional +- (void)__dummy_method_to_work_around_68987191; +@end + diff --git a/PrivateHeaders/XCTestPrivate/XCTMessagingRole_AccessibilityNotificationReporting-Protocol.h b/PrivateHeaders/XCTestPrivate/XCTMessagingRole_AccessibilityNotificationReporting-Protocol.h new file mode 100644 index 000000000..361b34909 --- /dev/null +++ b/PrivateHeaders/XCTestPrivate/XCTMessagingRole_AccessibilityNotificationReporting-Protocol.h @@ -0,0 +1,14 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +@class NSData, XCAccessibilityElement; + +@protocol XCTMessagingRole_AccessibilityNotificationReporting +- (void)_XCT_receivedAccessibilityNotification:(int)arg1 fromElement:(XCAccessibilityElement *)arg2 payload:(NSData *)arg3; +- (void)_XCT_receivedAccessibilityNotification:(int)arg1 withPayload:(NSData *)arg2; +@end + diff --git a/PrivateHeaders/XCTestPrivate/XCTMessagingRole_ActivityReporting-Protocol.h b/PrivateHeaders/XCTestPrivate/XCTMessagingRole_ActivityReporting-Protocol.h new file mode 100644 index 000000000..18da00341 --- /dev/null +++ b/PrivateHeaders/XCTestPrivate/XCTMessagingRole_ActivityReporting-Protocol.h @@ -0,0 +1,14 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +@class XCActivityRecord, XCTTestIdentifier; + +@protocol XCTMessagingRole_ActivityReporting +- (id)_XCT_testCaseWithIdentifier:(XCTTestIdentifier *)arg1 didFinishActivity:(XCActivityRecord *)arg2; +- (id)_XCT_testCaseWithIdentifier:(XCTTestIdentifier *)arg1 willStartActivity:(XCActivityRecord *)arg2; +@end + diff --git a/PrivateHeaders/XCTestPrivate/XCTMessagingRole_ActivityReporting_Legacy-Protocol.h b/PrivateHeaders/XCTestPrivate/XCTMessagingRole_ActivityReporting_Legacy-Protocol.h new file mode 100644 index 000000000..fff0d0973 --- /dev/null +++ b/PrivateHeaders/XCTestPrivate/XCTMessagingRole_ActivityReporting_Legacy-Protocol.h @@ -0,0 +1,14 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +@class NSString, XCActivityRecord; + +@protocol XCTMessagingRole_ActivityReporting_Legacy +- (id)_XCT_testCase:(NSString *)arg1 method:(NSString *)arg2 didFinishActivity:(XCActivityRecord *)arg3; +- (id)_XCT_testCase:(NSString *)arg1 method:(NSString *)arg2 willStartActivity:(XCActivityRecord *)arg3; +@end + diff --git a/PrivateHeaders/XCTestPrivate/XCTMessagingRole_BundleRequesting-Protocol.h b/PrivateHeaders/XCTestPrivate/XCTMessagingRole_BundleRequesting-Protocol.h new file mode 100644 index 000000000..050a4c784 --- /dev/null +++ b/PrivateHeaders/XCTestPrivate/XCTMessagingRole_BundleRequesting-Protocol.h @@ -0,0 +1,11 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +@protocol XCTMessagingRole_BundleRequesting +- (void)_XCT_requestBundleIDForPID:(int)arg1 reply:(void (^)(NSString *, NSError *))arg2; +@end + diff --git a/PrivateHeaders/XCTestPrivate/XCTMessagingRole_CapabilityExchange-Protocol.h b/PrivateHeaders/XCTestPrivate/XCTMessagingRole_CapabilityExchange-Protocol.h new file mode 100644 index 000000000..2b6765fae --- /dev/null +++ b/PrivateHeaders/XCTestPrivate/XCTMessagingRole_CapabilityExchange-Protocol.h @@ -0,0 +1,39 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +@class NSArray, NSDictionary, NSNumber, NSString, NSUUID, XCAccessibilityElement, XCTCapabilities, XCTScreenshotRequest, XCTSpindumpRequestSpecification; + +@protocol XCTMessagingRole_CapabilityExchange +- (void)_XCT_requestElementAtPoint:(struct CGPoint)arg1 reply:(void (^)(XCAccessibilityElement *, NSError *))arg2; +- (void)_XCT_fetchParameterizedAttribute:(NSString *)arg1 forElement:(XCAccessibilityElement *)arg2 parameter:(id)arg3 reply:(void (^)(id, NSError *))arg4; +- (void)_XCT_fetchParameterizedAttributeForElement:(XCAccessibilityElement *)arg1 attributes:(NSNumber *)arg2 parameter:(id)arg3 reply:(void (^)(id, NSError *))arg4; +- (void)_XCT_setAttribute:(NSNumber *)arg1 value:(id)arg2 element:(XCAccessibilityElement *)arg3 reply:(void (^)(_Bool, NSError *))arg4; +- (void)_XCT_fetchAttributes:(NSArray *)arg1 forElement:(XCAccessibilityElement *)arg2 reply:(void (^)(NSDictionary *, NSError *))arg3; +- (void)_XCT_fetchAttributesForElement:(XCAccessibilityElement *)arg1 attributes:(NSArray *)arg2 reply:(void (^)(NSDictionary *, NSError *))arg3; +- (void)_XCT_fetchSnapshotForElement:(XCAccessibilityElement *)arg1 attributes:(NSArray *)arg2 parameters:(NSDictionary *)arg3 reply:(void (^)(XCUIElementSnapshotRequestResult *, NSError *))arg4; +- (void)_XCT_requestSnapshotForElement:(XCAccessibilityElement *)arg1 attributes:(NSArray *)arg2 parameters:(NSDictionary *)arg3 reply:(void (^)(XCElementSnapshot *, NSError *))arg4; +- (void)_XCT_snapshotForElement:(XCAccessibilityElement *)arg1 attributes:(NSArray *)arg2 parameters:(NSDictionary *)arg3 reply:(void (^)(XCElementSnapshot *, NSError *))arg4; +- (void)_XCT_terminateApplicationWithBundleID:(NSString *)arg1 completion:(void (^)(NSError *))arg2; +- (void)_XCT_performAccessibilityAction:(int)arg1 onElement:(XCAccessibilityElement *)arg2 withValue:(id)arg3 reply:(void (^)(NSError *))arg4; +- (void)_XCT_unregisterForAccessibilityNotification:(int)arg1 withRegistrationToken:(NSNumber *)arg2 reply:(void (^)(NSError *))arg3; +- (void)_XCT_registerForAccessibilityNotification:(int)arg1 reply:(void (^)(NSNumber *, NSError *))arg2; +- (void)_XCT_launchApplicationWithBundleID:(NSString *)arg1 arguments:(NSArray *)arg2 environment:(NSDictionary *)arg3 completion:(void (^)(NSError *))arg4; +- (void)_XCT_startMonitoringApplicationWithBundleID:(NSString *)arg1; +- (void)_XCT_requestBackgroundAssertionWithReply:(void (^)(void))arg1; +- (void)_XCT_requestBackgroundAssertionForPID:(int)arg1 reply:(void (^)(_Bool))arg2; +- (void)_XCT_requestScreenshotWithReply:(void (^)(NSData *, NSError *))arg1; +- (void)_XCT_requestScreenshotOfScreenWithID:(unsigned int)arg1 withRect:(struct CGRect)arg2 uti:(NSString *)arg3 compressionQuality:(double)arg4 withReply:(void (^)(NSData *, NSError *))arg5; +- (void)_XCT_requestScreenshot:(XCTScreenshotRequest *)arg1 withReply:(void (^)(XCTImage *, NSError *))arg2; +- (void)_XCT_requestSpindumpWithSpecification:(XCTSpindumpRequestSpecification *)arg1 completion:(void (^)(NSData *, NSError *))arg2; +- (void)_XCT_requestUnsupportedBundleIdentifiersForAutomationSessions:(void (^)(NSSet *, NSError *))arg1; +- (void)_XCT_requestEndpointForTestTargetWithPID:(int)arg1 preferredBackendPath:(NSString *)arg2 reply:(void (^)(NSXPCListenerEndpoint *, NSError *))arg3; +- (void)_XCT_requestSerializedTransportWrapperForIDESessionWithIdentifier:(NSUUID *)arg1 reply:(void (^)(XCTSerializedTransportWrapper *))arg2; +- (void)_XCT_requestSocketForSessionIdentifier:(NSUUID *)arg1 reply:(void (^)(NSFileHandle *))arg2; +- (void)_XCT_exchangeCapabilities:(XCTCapabilities *)arg1 reply:(void (^)(XCTCapabilities *))arg2; +- (void)_XCT_exchangeProtocolVersion:(unsigned long long)arg1 reply:(void (^)(unsigned long long))arg2; +@end + diff --git a/PrivateHeaders/XCTestPrivate/XCTMessagingRole_ControlSessionInitiation-Protocol.h b/PrivateHeaders/XCTestPrivate/XCTMessagingRole_ControlSessionInitiation-Protocol.h new file mode 100644 index 000000000..c80b2e523 --- /dev/null +++ b/PrivateHeaders/XCTestPrivate/XCTMessagingRole_ControlSessionInitiation-Protocol.h @@ -0,0 +1,17 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +@class NSNumber, XCTCapabilities; + +@protocol XCTMessagingRole_ControlSessionInitiation +- (id)_IDE_authorizeTestSessionWithProcessID:(NSNumber *)arg1; +- (id)_IDE_initiateControlSessionWithCapabilities:(XCTCapabilities *)arg1; +- (id)_IDE_initiateControlSessionWithProtocolVersion:(NSNumber *)arg1; +- (id)_IDE_initiateControlSessionForTestProcessID:(NSNumber *)arg1 protocolVersion:(NSNumber *)arg2; +- (id)_IDE_initiateControlSessionForTestProcessID:(NSNumber *)arg1; +@end + diff --git a/PrivateHeaders/XCTestPrivate/XCTMessagingRole_CrashReporting-Protocol.h b/PrivateHeaders/XCTestPrivate/XCTMessagingRole_CrashReporting-Protocol.h new file mode 100644 index 000000000..475d05033 --- /dev/null +++ b/PrivateHeaders/XCTestPrivate/XCTMessagingRole_CrashReporting-Protocol.h @@ -0,0 +1,13 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +@class NSData, NSString; + +@protocol XCTMessagingRole_CrashReporting +- (id)_XCT_handleCrashReportData:(NSData *)arg1 fromFileWithName:(NSString *)arg2; +@end + diff --git a/PrivateHeaders/XCTestPrivate/XCTMessagingRole_DebugLogging-Protocol.h b/PrivateHeaders/XCTestPrivate/XCTMessagingRole_DebugLogging-Protocol.h new file mode 100644 index 000000000..4fb7588ec --- /dev/null +++ b/PrivateHeaders/XCTestPrivate/XCTMessagingRole_DebugLogging-Protocol.h @@ -0,0 +1,13 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +@class NSString; + +@protocol XCTMessagingRole_DebugLogging +- (id)_XCT_logDebugMessage:(NSString *)arg1; +@end + diff --git a/PrivateHeaders/XCTestPrivate/XCTMessagingRole_DiagnosticsCollection-Protocol.h b/PrivateHeaders/XCTestPrivate/XCTMessagingRole_DiagnosticsCollection-Protocol.h new file mode 100644 index 000000000..bcb56fbfc --- /dev/null +++ b/PrivateHeaders/XCTestPrivate/XCTMessagingRole_DiagnosticsCollection-Protocol.h @@ -0,0 +1,16 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +@class NSArray, NSDate, XCTSpindumpRequestSpecification; + +@protocol XCTMessagingRole_DiagnosticsCollection +- (id)_IDE_requestSpindumpWithSpecification:(XCTSpindumpRequestSpecification *)arg1; +- (id)_IDE_requestSpindump; +- (id)_IDE_requestLogArchiveWithStartDate:(NSDate *)arg1; +- (id)_IDE_collectNewCrashReportsInDirectories:(NSArray *)arg1 matchingProcessNames:(NSArray *)arg2; +@end + diff --git a/PrivateHeaders/XCTestPrivate/XCTMessagingRole_EventSynthesis-Protocol.h b/PrivateHeaders/XCTestPrivate/XCTMessagingRole_EventSynthesis-Protocol.h new file mode 100644 index 000000000..4b7c2667c --- /dev/null +++ b/PrivateHeaders/XCTestPrivate/XCTMessagingRole_EventSynthesis-Protocol.h @@ -0,0 +1,23 @@ +// +// Generated by class-dump 3.5 (64 bit) (Debug version compiled Jun 1 2021 15:19:06). +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +@class NSString, XCDeviceEvent, XCSynthesizedEventRecord; + +@protocol XCTMessagingRole_EventSynthesis +- (void)_XCT_enableFauxCollectionViewCells:(void (^)(_Bool, NSError *))arg1; +- (void)_XCT_setLocalizableStringsDataGatheringEnabled:(_Bool)arg1 reply:(void (^)(_Bool, NSError *))arg2; +- (void)_XCT_loadAccessibilityWithTimeout:(double)arg1 reply:(void (^)(_Bool, NSError *))arg2; +- (void)_XCT_setAXTimeout:(double)arg1 reply:(void (^)(int))arg2; +- (void)_XCT_sendString:(NSString *)arg1 maximumFrequency:(unsigned long long)arg2 completion:(void (^)(NSError *))arg3; +- (void)_XCT_getDeviceOrientationWithCompletion:(void (^)(NSNumber *, NSError *))arg1; +- (void)_XCT_updateDeviceOrientation:(long long)arg1 completion:(void (^)(NSError *))arg2; +- (void)_XCT_performDeviceEvent:(XCDeviceEvent *)arg1 completion:(void (^)(NSError *))arg2; +- (void)_XCT_synthesizeEvent:(XCSynthesizedEventRecord *)arg1 completion:(void (^)(NSError *))arg2; +@end + diff --git a/PrivateHeaders/XCTestPrivate/XCTMessagingRole_ForcePressureSupportQuerying-Protocol.h b/PrivateHeaders/XCTestPrivate/XCTMessagingRole_ForcePressureSupportQuerying-Protocol.h new file mode 100644 index 000000000..a0c4c8127 --- /dev/null +++ b/PrivateHeaders/XCTestPrivate/XCTMessagingRole_ForcePressureSupportQuerying-Protocol.h @@ -0,0 +1,15 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +@class NSData, XCSynthesizedEventRecord; + +@protocol XCTMessagingRole_ForcePressureSupportQuerying +- (void)_XCT_synthesizeEvent:(XCSynthesizedEventRecord *)arg1 implicitConfirmationInterval:(double)arg2 completion:(void (^)(NSError *))arg3; +- (void)_XCT_postTelemetryData:(NSData *)arg1 reply:(void (^)(NSError *))arg2; +- (void)_XCT_requestPressureEventsSupported:(void (^)(_Bool, NSError *))arg1; +@end + diff --git a/PrivateHeaders/XCTestPrivate/XCTMessagingRole_MemoryTesting-Protocol.h b/PrivateHeaders/XCTestPrivate/XCTMessagingRole_MemoryTesting-Protocol.h new file mode 100644 index 000000000..634dd92f0 --- /dev/null +++ b/PrivateHeaders/XCTestPrivate/XCTMessagingRole_MemoryTesting-Protocol.h @@ -0,0 +1,10 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +@protocol XCTMessagingRole_MemoryTesting +@end + diff --git a/PrivateHeaders/XCTestPrivate/XCTMessagingRole_PerformanceMeasurementReporting-Protocol.h b/PrivateHeaders/XCTestPrivate/XCTMessagingRole_PerformanceMeasurementReporting-Protocol.h new file mode 100644 index 000000000..4a62a59f1 --- /dev/null +++ b/PrivateHeaders/XCTestPrivate/XCTMessagingRole_PerformanceMeasurementReporting-Protocol.h @@ -0,0 +1,13 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +@class NSDictionary, NSNumber, NSString, XCTTestIdentifier; + +@protocol XCTMessagingRole_PerformanceMeasurementReporting +- (id)_XCT_testCaseWithIdentifier:(XCTTestIdentifier *)arg1 didMeasureMetric:(NSDictionary *)arg2 file:(NSString *)arg3 line:(NSNumber *)arg4; +@end + diff --git a/PrivateHeaders/XCTestPrivate/XCTMessagingRole_PerformanceMeasurementReporting_Legacy-Protocol.h b/PrivateHeaders/XCTestPrivate/XCTMessagingRole_PerformanceMeasurementReporting_Legacy-Protocol.h new file mode 100644 index 000000000..fc2efbe63 --- /dev/null +++ b/PrivateHeaders/XCTestPrivate/XCTMessagingRole_PerformanceMeasurementReporting_Legacy-Protocol.h @@ -0,0 +1,13 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +@class NSDictionary, NSNumber, NSString; + +@protocol XCTMessagingRole_PerformanceMeasurementReporting_Legacy +- (id)_XCT_testMethod:(NSString *)arg1 ofClass:(NSString *)arg2 didMeasureMetric:(NSDictionary *)arg3 file:(NSString *)arg4 line:(NSNumber *)arg5; +@end + diff --git a/PrivateHeaders/XCTestPrivate/XCTMessagingRole_ProcessMonitoring-Protocol.h b/PrivateHeaders/XCTestPrivate/XCTMessagingRole_ProcessMonitoring-Protocol.h new file mode 100644 index 000000000..fa6b4d490 --- /dev/null +++ b/PrivateHeaders/XCTestPrivate/XCTMessagingRole_ProcessMonitoring-Protocol.h @@ -0,0 +1,15 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +@class NSNumber, NSString; + +@protocol XCTMessagingRole_ProcessMonitoring +- (id)_IDE_processWithToken:(NSNumber *)arg1 exitedWithStatus:(NSNumber *)arg2; +- (id)_IDE_stopTrackingProcessWithToken:(NSNumber *)arg1; +- (id)_IDE_processWithBundleID:(NSString *)arg1 path:(NSString *)arg2 pid:(NSNumber *)arg3 crashedUnderSymbol:(NSString *)arg4; +@end + diff --git a/PrivateHeaders/XCTestPrivate/XCTMessagingRole_ProtectedResourceAuthorization-Protocol.h b/PrivateHeaders/XCTestPrivate/XCTMessagingRole_ProtectedResourceAuthorization-Protocol.h new file mode 100644 index 000000000..696ae671c --- /dev/null +++ b/PrivateHeaders/XCTestPrivate/XCTMessagingRole_ProtectedResourceAuthorization-Protocol.h @@ -0,0 +1,13 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +@class NSString; + +@protocol XCTMessagingRole_ProtectedResourceAuthorization +- (void)_XCT_resetAuthorizationStatusForBundleIdentifier:(NSString *)arg1 resourceIdentifier:(NSString *)arg2 reply:(void (^)(_Bool, NSError *))arg3; +@end + diff --git a/PrivateHeaders/XCTestPrivate/XCTMessagingRole_RunnerSessionInitiation-Protocol.h b/PrivateHeaders/XCTestPrivate/XCTMessagingRole_RunnerSessionInitiation-Protocol.h new file mode 100644 index 000000000..3d485176c --- /dev/null +++ b/PrivateHeaders/XCTestPrivate/XCTMessagingRole_RunnerSessionInitiation-Protocol.h @@ -0,0 +1,14 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +@class NSNumber, NSString, NSUUID, XCTCapabilities; + +@protocol XCTMessagingRole_RunnerSessionInitiation +- (id)_IDE_initiateSessionWithIdentifier:(NSUUID *)arg1 forClient:(NSString *)arg2 atPath:(NSString *)arg3 protocolVersion:(NSNumber *)arg4; +- (id)_IDE_initiateSessionWithIdentifier:(NSUUID *)arg1 capabilities:(XCTCapabilities *)arg2; +@end + diff --git a/PrivateHeaders/XCTestPrivate/XCTMessagingRole_SelfDiagnosisIssueReporting-Protocol.h b/PrivateHeaders/XCTestPrivate/XCTMessagingRole_SelfDiagnosisIssueReporting-Protocol.h new file mode 100644 index 000000000..323bf0dde --- /dev/null +++ b/PrivateHeaders/XCTestPrivate/XCTMessagingRole_SelfDiagnosisIssueReporting-Protocol.h @@ -0,0 +1,13 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +@class NSString; + +@protocol XCTMessagingRole_SelfDiagnosisIssueReporting +- (id)_XCT_reportSelfDiagnosisIssue:(NSString *)arg1 description:(NSString *)arg2; +@end + diff --git a/PrivateHeaders/XCTestPrivate/XCTMessagingRole_SiriAutomation-Protocol.h b/PrivateHeaders/XCTestPrivate/XCTMessagingRole_SiriAutomation-Protocol.h new file mode 100644 index 000000000..00bf00fca --- /dev/null +++ b/PrivateHeaders/XCTestPrivate/XCTMessagingRole_SiriAutomation-Protocol.h @@ -0,0 +1,17 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +@class NSArray, NSString, NSURL; + +@protocol XCTMessagingRole_SiriAutomation +- (void)_XCT_injectVoiceRecognitionAudioInputPaths:(NSArray *)arg1 completion:(void (^)(_Bool, NSError *))arg2; +- (void)_XCT_injectAssistantRecognitionStrings:(NSArray *)arg1 completion:(void (^)(_Bool, NSError *))arg2; +- (void)_XCT_startSiriUIRequestWithAudioFileURL:(NSURL *)arg1 completion:(void (^)(_Bool, NSError *))arg2; +- (void)_XCT_startSiriUIRequestWithText:(NSString *)arg1 completion:(void (^)(_Bool, NSError *))arg2; +- (void)_XCT_requestSiriEnabledStatus:(void (^)(_Bool, NSError *))arg1; +@end + diff --git a/PrivateHeaders/XCTestPrivate/XCTMessagingRole_TestExecution-Protocol.h b/PrivateHeaders/XCTestPrivate/XCTMessagingRole_TestExecution-Protocol.h new file mode 100644 index 000000000..1c7762755 --- /dev/null +++ b/PrivateHeaders/XCTestPrivate/XCTMessagingRole_TestExecution-Protocol.h @@ -0,0 +1,16 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +@class NSNumber, XCTTestIdentifierSet; + +@protocol XCTMessagingRole_TestExecution +- (id)_IDE_shutdown; +- (id)_IDE_executeTestsWithIdentifiersToRun:(XCTTestIdentifierSet *)arg1 identifiersToSkip:(XCTTestIdentifierSet *)arg2; +- (id)_IDE_fetchParallelizableTestIdentifiers; +- (id)_IDE_startExecutingTestPlanWithProtocolVersion:(NSNumber *)arg1; +@end + diff --git a/PrivateHeaders/XCTestPrivate/XCTMessagingRole_TestExecution_Legacy-Protocol.h b/PrivateHeaders/XCTestPrivate/XCTMessagingRole_TestExecution_Legacy-Protocol.h new file mode 100644 index 000000000..65aca6a1c --- /dev/null +++ b/PrivateHeaders/XCTestPrivate/XCTMessagingRole_TestExecution_Legacy-Protocol.h @@ -0,0 +1,14 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +@class NSSet; + +@protocol XCTMessagingRole_TestExecution_Legacy +- (id)_IDE_executeTestIdentifiers:(NSSet *)arg1 skippingTestIdentifiers:(NSSet *)arg2; +- (id)_IDE_fetchDiscoveredTestClasses; +@end + diff --git a/PrivateHeaders/XCTestPrivate/XCTMessagingRole_TestReporting-Protocol.h b/PrivateHeaders/XCTestPrivate/XCTMessagingRole_TestReporting-Protocol.h new file mode 100644 index 000000000..42232a1ca --- /dev/null +++ b/PrivateHeaders/XCTestPrivate/XCTMessagingRole_TestReporting-Protocol.h @@ -0,0 +1,28 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +@class NSError, NSNumber, NSString, XCTCapabilities, XCTExpectedFailure, XCTIssue, XCTSourceCodeContext, XCTTestIdentifier, XCTestCaseRunConfiguration; + +@protocol XCTMessagingRole_TestReporting +- (id)_XCT_testCaseWithIdentifier:(XCTTestIdentifier *)arg1 didStallOnMainThreadInFile:(NSString *)arg2 line:(NSNumber *)arg3; +- (id)_XCT_testCaseWithIdentifier:(XCTTestIdentifier *)arg1 didFinishWithStatus:(NSString *)arg2 duration:(NSNumber *)arg3; +- (id)_XCT_testCaseWithIdentifier:(XCTTestIdentifier *)arg1 didRecordExpectedFailure:(XCTExpectedFailure *)arg2; +- (id)_XCT_testCaseWithIdentifier:(XCTTestIdentifier *)arg1 didRecordIssue:(XCTIssue *)arg2; +- (id)_XCT_testCaseWithIdentifier:(XCTTestIdentifier *)arg1 wasSkippedWithMessage:(NSString *)arg2 sourceCodeContext:(XCTSourceCodeContext *)arg3; +- (id)_XCT_testCaseDidStartWithIdentifier:(XCTTestIdentifier *)arg1 iteration:(NSNumber *)arg2; +- (id)_XCT_testCaseDidStartWithIdentifier:(XCTTestIdentifier *)arg1; +- (id)_XCT_testCaseDidStartWithIdentifier:(XCTTestIdentifier *)arg1 testCaseRunConfiguration:(XCTestCaseRunConfiguration *)arg2; +- (id)_XCT_testSuiteWithIdentifier:(XCTTestIdentifier *)arg1 didFinishAt:(NSString *)arg2 runCount:(NSNumber *)arg3 skipCount:(NSNumber *)arg4 failureCount:(NSNumber *)arg5 expectedFailureCount:(NSNumber *)arg6 uncaughtExceptionCount:(NSNumber *)arg7 testDuration:(NSNumber *)arg8 totalDuration:(NSNumber *)arg9; +- (id)_XCT_testSuiteWithIdentifier:(XCTTestIdentifier *)arg1 didRecordIssue:(XCTIssue *)arg2; +- (id)_XCT_testSuiteWithIdentifier:(XCTTestIdentifier *)arg1 didStartAt:(NSString *)arg2; +- (id)_XCT_didFinishExecutingTestPlan; +- (id)_XCT_didBeginExecutingTestPlan; +- (id)_XCT_testBundleReadyWithProtocolVersion:(NSNumber *)arg1 minimumVersion:(NSNumber *)arg2; +- (id)_XCT_testRunnerReadyWithCapabilities:(XCTCapabilities *)arg1; +- (id)_XCT_reportTestWithIdentifier:(XCTTestIdentifier *)arg1 didExceedExecutionTimeAllowance:(NSNumber *)arg2; +- (id)_XCT_didFailToBootstrapWithError:(NSError *)arg1; +@end diff --git a/PrivateHeaders/XCTestPrivate/XCTMessagingRole_TestReporting_Legacy-Protocol.h b/PrivateHeaders/XCTestPrivate/XCTMessagingRole_TestReporting_Legacy-Protocol.h new file mode 100644 index 000000000..7c0692aa7 --- /dev/null +++ b/PrivateHeaders/XCTestPrivate/XCTMessagingRole_TestReporting_Legacy-Protocol.h @@ -0,0 +1,21 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +@class NSNumber, NSString; + +@protocol XCTMessagingRole_TestReporting_Legacy +- (id)_XCT_testCase:(NSString *)arg1 method:(NSString *)arg2 didStallOnMainThreadInFile:(NSString *)arg3 line:(NSNumber *)arg4; +- (id)_XCT_testCaseDidFinishForTestClass:(NSString *)arg1 method:(NSString *)arg2 withStatus:(NSString *)arg3 duration:(NSNumber *)arg4; +- (id)_XCT_testCaseDidFailForTestClass:(NSString *)arg1 method:(NSString *)arg2 withMessage:(NSString *)arg3 file:(NSString *)arg4 line:(NSNumber *)arg5; +- (id)_XCT_testCaseWasSkippedForTestClass:(NSString *)arg1 method:(NSString *)arg2 withMessage:(NSString *)arg3 file:(NSString *)arg4 line:(NSNumber *)arg5; +- (id)_XCT_testCaseDidStartForTestClass:(NSString *)arg1 method:(NSString *)arg2; +- (id)_XCT_testSuite:(NSString *)arg1 didFinishAt:(NSString *)arg2 runCount:(NSNumber *)arg3 skipCount:(NSNumber *)arg4 failureCount:(NSNumber *)arg5 expectedFailureCount:(NSNumber *)arg6 uncaughtExceptionCount:(NSNumber *)arg7 testDuration:(NSNumber *)arg8 totalDuration:(NSNumber *)arg9; +- (id)_XCT_testSuite:(NSString *)arg1 didFinishAt:(NSString *)arg2 runCount:(NSNumber *)arg3 skipCount:(NSNumber *)arg4 failureCount:(NSNumber *)arg5 unexpectedFailureCount:(NSNumber *)arg6 testDuration:(NSNumber *)arg7 totalDuration:(NSNumber *)arg8; +- (id)_XCT_testSuite:(NSString *)arg1 didFinishAt:(NSString *)arg2 runCount:(NSNumber *)arg3 withFailures:(NSNumber *)arg4 unexpected:(NSNumber *)arg5 testDuration:(NSNumber *)arg6 totalDuration:(NSNumber *)arg7; +- (id)_XCT_testSuite:(NSString *)arg1 didStartAt:(NSString *)arg2; +@end + diff --git a/PrivateHeaders/XCTestPrivate/XCTMessagingRole_UIApplicationStateUpdating-Protocol.h b/PrivateHeaders/XCTestPrivate/XCTMessagingRole_UIApplicationStateUpdating-Protocol.h new file mode 100644 index 000000000..b68f0049d --- /dev/null +++ b/PrivateHeaders/XCTestPrivate/XCTMessagingRole_UIApplicationStateUpdating-Protocol.h @@ -0,0 +1,13 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +@class NSString; + +@protocol XCTMessagingRole_UIApplicationStateUpdating +- (void)_XCT_applicationWithBundleID:(NSString *)arg1 didUpdatePID:(int)arg2 andState:(unsigned long long)arg3; +@end + diff --git a/PrivateHeaders/XCTestPrivate/XCTMessagingRole_UIAutomation-Protocol.h b/PrivateHeaders/XCTestPrivate/XCTMessagingRole_UIAutomation-Protocol.h new file mode 100644 index 000000000..dc00fb6e8 --- /dev/null +++ b/PrivateHeaders/XCTestPrivate/XCTMessagingRole_UIAutomation-Protocol.h @@ -0,0 +1,17 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +@class NSArray, NSDictionary, NSError, NSString; + +@protocol XCTMessagingRole_UIAutomation +- (id)_XCT_getProgressForLaunch:(id)arg1; +- (id)_XCT_terminateProcess:(id)arg1; +- (id)_XCT_launchProcessWithPath:(NSString *)arg1 bundleID:(NSString *)arg2 arguments:(NSArray *)arg3 environmentVariables:(NSDictionary *)arg4; +- (id)_XCT_initializationForUITestingDidFailWithError:(NSError *)arg1; +- (id)_XCT_didBeginInitializingForUITesting; +@end + diff --git a/PrivateHeaders/XCTestPrivate/XCTMessagingRole_UIAutomationEventReporting-Protocol.h b/PrivateHeaders/XCTestPrivate/XCTMessagingRole_UIAutomationEventReporting-Protocol.h new file mode 100644 index 000000000..da95a124e --- /dev/null +++ b/PrivateHeaders/XCTestPrivate/XCTMessagingRole_UIAutomationEventReporting-Protocol.h @@ -0,0 +1,17 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +@class NSArray, NSDictionary, NSNumber, NSString, XCElementSnapshot; + +@protocol XCTMessagingRole_UIAutomationEventReporting +- (id)_XCT_nativeFocusItemDidChangeAtTime:(NSNumber *)arg1 parameterSnapshot:(XCElementSnapshot *)arg2 applicationSnapshot:(XCElementSnapshot *)arg3; +- (id)_XCT_recordedEventNames:(NSArray *)arg1 timestamp:(NSNumber *)arg2 duration:(NSNumber *)arg3 startLocation:(NSDictionary *)arg4 startElementSnapshot:(XCElementSnapshot *)arg5 startApplicationSnapshot:(XCElementSnapshot *)arg6 endLocation:(NSDictionary *)arg7 endElementSnapshot:(XCElementSnapshot *)arg8 endApplicationSnapshot:(XCElementSnapshot *)arg9; +- (id)_XCT_recordedOrientationChange:(NSString *)arg1; +- (id)_XCT_recordedKeyEventsWithApplicationSnapshot:(XCElementSnapshot *)arg1 characters:(NSString *)arg2 charactersIgnoringModifiers:(NSString *)arg3 modifierFlags:(NSNumber *)arg4; +- (id)_XCT_recordedFirstResponderChangedWithApplicationSnapshot:(XCElementSnapshot *)arg1; +@end + diff --git a/PrivateHeaders/XCTestPrivate/XCTMessagingRole_UIAutomationProcess-Protocol.h b/PrivateHeaders/XCTestPrivate/XCTMessagingRole_UIAutomationProcess-Protocol.h new file mode 100644 index 000000000..04e5a92e0 --- /dev/null +++ b/PrivateHeaders/XCTestPrivate/XCTMessagingRole_UIAutomationProcess-Protocol.h @@ -0,0 +1,19 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +@class NSArray, XCAccessibilityElement, XCTCapabilities, XCTElementQuery, XCTSerializedTransportWrapper2; + +@protocol XCTMessagingRole_UIAutomationProcess +- (void)listenForRemoteConnectionViaSerializedTransportWrapper:(XCTSerializedTransportWrapper2 *)arg1 completion:(void (^)(void))arg2; +- (void)notifyWhenAnimationsAreIdle:(void (^)(NSError *))arg1; +- (void)notifyWhenMainRunLoopIsIdle:(void (^)(NSError *))arg1; +- (void)attributesForElement:(XCAccessibilityElement *)arg1 attributes:(NSArray *)arg2 reply:(void (^)(NSDictionary *, NSError *))arg3; +- (void)fetchMatchesForQuery:(XCTElementQuery *)arg1 reply:(void (^)(XCTElementQueryResults *, NSError *))arg2; +- (void)exchangeCapabilities:(XCTCapabilities *)arg1 reply:(void (^)(XCTCapabilities *))arg2; +- (void)requestHostAppExecutableNameWithReply:(void (^)(NSString *))arg1; +@end + diff --git a/PrivateHeaders/XCTestPrivate/XCTMessagingRole_UIRecordingControl-Protocol.h b/PrivateHeaders/XCTestPrivate/XCTMessagingRole_UIRecordingControl-Protocol.h new file mode 100644 index 000000000..d2b66e049 --- /dev/null +++ b/PrivateHeaders/XCTestPrivate/XCTMessagingRole_UIRecordingControl-Protocol.h @@ -0,0 +1,14 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +@class NSArray, NSDictionary, NSNumber; + +@protocol XCTMessagingRole_UIRecordingControl +- (id)_IDE_stopRecording; +- (id)_IDE_startRecordingProcessPID:(NSNumber *)arg1 applicationSnapshotAttributes:(NSArray *)arg2 applicationSnapshotParameters:(NSDictionary *)arg3 elementSnapshotAttributes:(NSArray *)arg4 elementSnapshotParameters:(NSDictionary *)arg5 simpleTargetGestureNames:(NSArray *)arg6; +@end + diff --git a/PrivateHeaders/XCTest/XCTTestIdentifier.h b/PrivateHeaders/XCTestPrivate/XCTTestIdentifier.h similarity index 97% rename from PrivateHeaders/XCTest/XCTTestIdentifier.h rename to PrivateHeaders/XCTestPrivate/XCTTestIdentifier.h index 6a3d1bf40..b217cec0f 100644 --- a/PrivateHeaders/XCTest/XCTTestIdentifier.h +++ b/PrivateHeaders/XCTestPrivate/XCTTestIdentifier.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/XCTest/XCTTestIdentifierSet.h b/PrivateHeaders/XCTestPrivate/XCTTestIdentifierSet.h similarity index 95% rename from PrivateHeaders/XCTest/XCTTestIdentifierSet.h rename to PrivateHeaders/XCTestPrivate/XCTTestIdentifierSet.h index fce96f241..b1eb9d18f 100644 --- a/PrivateHeaders/XCTest/XCTTestIdentifierSet.h +++ b/PrivateHeaders/XCTestPrivate/XCTTestIdentifierSet.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/XCTest/XCTTestIdentifierSetBuilder.h b/PrivateHeaders/XCTestPrivate/XCTTestIdentifierSetBuilder.h similarity index 94% rename from PrivateHeaders/XCTest/XCTTestIdentifierSetBuilder.h rename to PrivateHeaders/XCTestPrivate/XCTTestIdentifierSetBuilder.h index 8b8a65468..db564993d 100644 --- a/PrivateHeaders/XCTest/XCTTestIdentifierSetBuilder.h +++ b/PrivateHeaders/XCTestPrivate/XCTTestIdentifierSetBuilder.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/XCTest/XCTestConfiguration.h b/PrivateHeaders/XCTestPrivate/XCTestConfiguration.h similarity index 95% rename from PrivateHeaders/XCTest/XCTestConfiguration.h rename to PrivateHeaders/XCTestPrivate/XCTestConfiguration.h index 1ab1afbc3..b229ac9e3 100644 --- a/PrivateHeaders/XCTest/XCTestConfiguration.h +++ b/PrivateHeaders/XCTestPrivate/XCTestConfiguration.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -7,7 +7,7 @@ #import -@class NSArray, NSDictionary, NSNumber, NSString, NSURL, NSUUID, XCTAggregateSuiteRunStatistics; +@class NSArray, NSDictionary, NSNumber, NSString, NSURL, NSUUID, XCTAggregateSuiteRunStatistics, XCTCapabilities; @interface XCTestConfiguration : NSObject { @@ -40,12 +40,14 @@ long long _userAttachmentLifetime; long long _testExecutionOrdering; NSNumber *_randomExecutionOrderingSeed; + XCTCapabilities *_IDECapabilities; } + (id)configurationWithContentsOfFile:(id)arg1; + (id)activeTestConfiguration; + (void)setActiveTestConfiguration:(id)arg1; + (_Bool)supportsSecureCoding; +@property(retain) XCTCapabilities *IDECapabilities; // @synthesize IDECapabilities=_IDECapabilities; @property(retain) NSNumber *randomExecutionOrderingSeed; // @synthesize randomExecutionOrderingSeed=_randomExecutionOrderingSeed; @property long long testExecutionOrdering; // @synthesize testExecutionOrdering=_testExecutionOrdering; @property long long userAttachmentLifetime; // @synthesize userAttachmentLifetime=_userAttachmentLifetime; diff --git a/PrivateHeaders/XCTest/XCTestDriverInterface-Protocol.h b/PrivateHeaders/XCTestPrivate/XCTestDriverInterface-Protocol.h similarity index 91% rename from PrivateHeaders/XCTest/XCTestDriverInterface-Protocol.h rename to PrivateHeaders/XCTestPrivate/XCTestDriverInterface-Protocol.h index ac9c6b59b..a97f36ceb 100644 --- a/PrivateHeaders/XCTest/XCTestDriverInterface-Protocol.h +++ b/PrivateHeaders/XCTestPrivate/XCTestDriverInterface-Protocol.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/XCTest/XCTestManager_DaemonConnectionInterface-Protocol.h b/PrivateHeaders/XCTestPrivate/XCTestManager_DaemonConnectionInterface-Protocol.h similarity index 96% rename from PrivateHeaders/XCTest/XCTestManager_DaemonConnectionInterface-Protocol.h rename to PrivateHeaders/XCTestPrivate/XCTestManager_DaemonConnectionInterface-Protocol.h index 0b5b5ea92..2c4a6c120 100644 --- a/PrivateHeaders/XCTest/XCTestManager_DaemonConnectionInterface-Protocol.h +++ b/PrivateHeaders/XCTestPrivate/XCTestManager_DaemonConnectionInterface-Protocol.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/XCTest/XCTestManager_IDEInterface-Protocol.h b/PrivateHeaders/XCTestPrivate/XCTestManager_IDEInterface-Protocol.h similarity index 98% rename from PrivateHeaders/XCTest/XCTestManager_IDEInterface-Protocol.h rename to PrivateHeaders/XCTestPrivate/XCTestManager_IDEInterface-Protocol.h index 2bdd6f6d0..52c6051c8 100644 --- a/PrivateHeaders/XCTest/XCTestManager_IDEInterface-Protocol.h +++ b/PrivateHeaders/XCTestPrivate/XCTestManager_IDEInterface-Protocol.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/XCTest/XCTestManager_ManagerInterface-Protocol.h b/PrivateHeaders/XCTestPrivate/XCTestManager_ManagerInterface-Protocol.h similarity index 97% rename from PrivateHeaders/XCTest/XCTestManager_ManagerInterface-Protocol.h rename to PrivateHeaders/XCTestPrivate/XCTestManager_ManagerInterface-Protocol.h index 9f88cbdd5..e1abae346 100644 --- a/PrivateHeaders/XCTest/XCTestManager_ManagerInterface-Protocol.h +++ b/PrivateHeaders/XCTestPrivate/XCTestManager_ManagerInterface-Protocol.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/XCTest/XCTestManager_TestsInterface-Protocol.h b/PrivateHeaders/XCTestPrivate/XCTestManager_TestsInterface-Protocol.h similarity index 88% rename from PrivateHeaders/XCTest/XCTestManager_TestsInterface-Protocol.h rename to PrivateHeaders/XCTestPrivate/XCTestManager_TestsInterface-Protocol.h index 010e2019e..c468e7a38 100644 --- a/PrivateHeaders/XCTest/XCTestManager_TestsInterface-Protocol.h +++ b/PrivateHeaders/XCTestPrivate/XCTestManager_TestsInterface-Protocol.h @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/PrivateHeaders/XCTestPrivate/_XCTMessaging_VoidProtocol-Protocol.h b/PrivateHeaders/XCTestPrivate/_XCTMessaging_VoidProtocol-Protocol.h new file mode 100644 index 000000000..62c361726 --- /dev/null +++ b/PrivateHeaders/XCTestPrivate/_XCTMessaging_VoidProtocol-Protocol.h @@ -0,0 +1,10 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +@protocol _XCTMessaging_VoidProtocol +@end + diff --git a/README.md b/README.md index 250072aa9..fd161eb1e 100644 --- a/README.md +++ b/README.md @@ -2,11 +2,11 @@ [![Discord](https://img.shields.io/discord/770978552698896394?style=flat-square)](https://discord.gg/SF26Yqw) -The "iOS Development Bridge" or `idb`, is a command line interface for automating iOS Simulators and Devices. It has three main priniciples: +The "iOS Development Bridge" or `idb`, is a command line interface for automating iOS Simulators and Devices. It has three main principles: * *Remote Automation*: `idb` is composed of a "companion" that runs on macOS and a python client that can run anywhere. This enables scenarios such as a "Device Lab" within a Data Center or fanning out shards of test executions to a large pool of iOS Simulators. -* *Simple Primitives*: `idb` exposes granular commands so that sophisticated workflows can be sequenced on top of them. This means you can use `idb` from an IDE or build an automated testing scenario that isn't feasible with default tooling. All of these primitives aim to be consistent across iOS versions and between iOS Simulators and iOS Devices. All the primitives are exposed over a cli, so that it easy to use for both humans and automation. -* *Exposing missing functionality*: Xcode has a number of features that aren't available outside it's user interface. `idb` leverages many of Private Frameworks that are used by Xcode, so that these features can be in GUI-less automated scenarios. +* *Simple Primitives*: `idb` exposes granular commands so that sophisticated workflows can be sequenced on top of them. This means you can use `idb` from an IDE or build an automated testing scenario that isn't feasible with default tooling. All of these primitives aim to be consistent across iOS versions and between iOS Simulators and iOS Devices. All the primitives are exposed over a cli, so that it's easy to use for both humans and automation. +* *Exposing missing functionality*: Xcode has a number of features that aren't available outside its user interface. `idb` leverages many of Private Frameworks that are used by Xcode, so that these features can be in GUI-less automated scenarios. `idb` is built on top the `FBSimulatorControl` and `FBDeviceControl` macOS Frameworks, contained within this repository. These Frameworks can be used independently of `idb`, however `idb` is likely to provide the simplest install and the most sensible defaults for most users. diff --git a/Shims/Binaries/libMaculator.dylib b/Shims/Binaries/libMaculator.dylib index 49a3ad084..2ea637903 100755 Binary files a/Shims/Binaries/libMaculator.dylib and b/Shims/Binaries/libMaculator.dylib differ diff --git a/Shims/Binaries/libShimulator.dylib b/Shims/Binaries/libShimulator.dylib index 78a758f96..31d4f0462 100755 Binary files a/Shims/Binaries/libShimulator.dylib and b/Shims/Binaries/libShimulator.dylib differ diff --git a/Shims/Shimulator/Configs/Maculator.xcconfig b/Shims/Shimulator/Configs/Maculator.xcconfig index 2466507e6..8cccb5355 100644 --- a/Shims/Shimulator/Configs/Maculator.xcconfig +++ b/Shims/Shimulator/Configs/Maculator.xcconfig @@ -8,3 +8,4 @@ EXECUTABLE_PREFIX = lib SDKROOT = macosx MACOSX_DEPLOYMENT_TARGET = 10.13 COPY_PHASE_STRIP = NO +CODE_SIGN_IDENTITY = - // Maculator Shims must be CodeSigned, to work for injection. diff --git a/Shims/Shimulator/Configs/Shimulator.xcconfig b/Shims/Shimulator/Configs/Shimulator.xcconfig index 33ac6162d..442e69fea 100644 --- a/Shims/Shimulator/Configs/Shimulator.xcconfig +++ b/Shims/Shimulator/Configs/Shimulator.xcconfig @@ -6,7 +6,6 @@ DYLIB_COMPATIBILITY_VERSION = 1 PRODUCT_NAME = Shimulator EXECUTABLE_PREFIX = lib SDKROOT = iphonesimulator -IPHONEOS_DEPLOYMENT_TARGET = 10.0 +IPHONEOS_DEPLOYMENT_TARGET = 11.0 COPY_PHASE_STRIP = NO -ARCHS = x86_64 CODE_SIGN_IDENTITY = - // Simulator Shims must be CodeSigned, to work for injection. diff --git a/Shims/Shimulator/Shimulator.xcodeproj/project.pbxproj b/Shims/Shimulator/Shimulator.xcodeproj/project.pbxproj index f0d3cb701..e48d335f3 100644 --- a/Shims/Shimulator/Shimulator.xcodeproj/project.pbxproj +++ b/Shims/Shimulator/Shimulator.xcodeproj/project.pbxproj @@ -7,6 +7,14 @@ objects = { /* Begin PBXBuildFile section */ + 7197B82C2A9E39CC00234737 /* XTSwizzle.h in Headers */ = {isa = PBXBuildFile; fileRef = 7197B82A2A9E39CC00234737 /* XTSwizzle.h */; }; + 7197B82D2A9E39CC00234737 /* XTSwizzle.h in Headers */ = {isa = PBXBuildFile; fileRef = 7197B82A2A9E39CC00234737 /* XTSwizzle.h */; }; + 7197B82E2A9E39CC00234737 /* XTSwizzle.m in Sources */ = {isa = PBXBuildFile; fileRef = 7197B82B2A9E39CC00234737 /* XTSwizzle.m */; }; + 7197B82F2A9E39CC00234737 /* XTSwizzle.m in Sources */ = {isa = PBXBuildFile; fileRef = 7197B82B2A9E39CC00234737 /* XTSwizzle.m */; }; + 7197B8382A9E3FD500234737 /* XCTestCaseHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = 7197B8362A9E3FD500234737 /* XCTestCaseHelpers.h */; }; + 7197B8392A9E3FD500234737 /* XCTestCaseHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = 7197B8362A9E3FD500234737 /* XCTestCaseHelpers.h */; }; + 7197B83A2A9E3FD500234737 /* XCTestCaseHelpers.m in Sources */ = {isa = PBXBuildFile; fileRef = 7197B8372A9E3FD500234737 /* XCTestCaseHelpers.m */; }; + 7197B83B2A9E3FD500234737 /* XCTestCaseHelpers.m in Sources */ = {isa = PBXBuildFile; fileRef = 7197B8372A9E3FD500234737 /* XCTestCaseHelpers.m */; }; 71B9E0D9268C61B800D40A91 /* TestCrashShim.m in Sources */ = {isa = PBXBuildFile; fileRef = EED62EE620D1224C006E86E5 /* TestCrashShim.m */; }; EED62EDE20D12217006E86E5 /* XCTestPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = EED62EDB20D12217006E86E5 /* XCTestPrivate.h */; }; EED62EDF20D12217006E86E5 /* XCTestPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = EED62EDB20D12217006E86E5 /* XCTestPrivate.h */; }; @@ -30,6 +38,10 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + 7197B82A2A9E39CC00234737 /* XTSwizzle.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = XTSwizzle.h; sourceTree = ""; }; + 7197B82B2A9E39CC00234737 /* XTSwizzle.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = XTSwizzle.m; sourceTree = ""; }; + 7197B8362A9E3FD500234737 /* XCTestCaseHelpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = XCTestCaseHelpers.h; sourceTree = ""; }; + 7197B8372A9E3FD500234737 /* XCTestCaseHelpers.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = XCTestCaseHelpers.m; sourceTree = ""; }; AA017F411BD7776B00F45E9D /* libShimulator.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libShimulator.dylib; sourceTree = BUILT_PRODUCTS_DIR; }; AA56EAE21EEF08720062C2BC /* libMaculator.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libMaculator.dylib; sourceTree = BUILT_PRODUCTS_DIR; }; EED62ED820D12209006E86E5 /* Maculator.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Maculator.xcconfig; sourceTree = ""; }; @@ -102,6 +114,10 @@ EED62EEA20D12431006E86E5 /* FBRuntimeTools.h */, EED62EE920D12431006E86E5 /* FBRuntimeTools.m */, EED62EDB20D12217006E86E5 /* XCTestPrivate.h */, + 7197B82A2A9E39CC00234737 /* XTSwizzle.h */, + 7197B82B2A9E39CC00234737 /* XTSwizzle.m */, + 7197B8362A9E3FD500234737 /* XCTestCaseHelpers.h */, + 7197B8372A9E3FD500234737 /* XCTestCaseHelpers.m */, ); path = Tools; sourceTree = ""; @@ -142,6 +158,8 @@ EED62EF720D1243E006E86E5 /* FBXCTestMain.h in Headers */, EED62EF120D12432006E86E5 /* FBDebugLog.h in Headers */, EED62EE220D12242006E86E5 /* FBXCTestConstants.h in Headers */, + 7197B82C2A9E39CC00234737 /* XTSwizzle.h in Headers */, + 7197B8382A9E3FD500234737 /* XCTestCaseHelpers.h in Headers */, EED62EDE20D12217006E86E5 /* XCTestPrivate.h in Headers */, EED62EEF20D12432006E86E5 /* FBRuntimeTools.h in Headers */, ); @@ -154,6 +172,8 @@ EED62EF820D1243E006E86E5 /* FBXCTestMain.h in Headers */, EED62EF220D12432006E86E5 /* FBDebugLog.h in Headers */, EED62EE320D12242006E86E5 /* FBXCTestConstants.h in Headers */, + 7197B82D2A9E39CC00234737 /* XTSwizzle.h in Headers */, + 7197B8392A9E3FD500234737 /* XCTestCaseHelpers.h in Headers */, EED62EDF20D12217006E86E5 /* XCTestPrivate.h in Headers */, EED62EF020D12432006E86E5 /* FBRuntimeTools.h in Headers */, ); @@ -166,7 +186,6 @@ isa = PBXNativeTarget; buildConfigurationList = AA017F451BD7776B00F45E9D /* Build configuration list for PBXNativeTarget "Shimulator" */; buildPhases = ( - 2F430FD31FD829C200B2B8B6 /* Don't allow ARM binaries */, AA017F3D1BD7776B00F45E9D /* Sources */, AA017F3E1BD7776B00F45E9D /* Frameworks */, AA017F3F1BD7776B00F45E9D /* Headers */, @@ -236,20 +255,6 @@ /* End PBXProject section */ /* Begin PBXShellScriptBuildPhase section */ - 2F430FD31FD829C200B2B8B6 /* Don't allow ARM binaries */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 12; - files = ( - ); - inputPaths = ( - ); - name = "Don't allow ARM binaries"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "if [[ \"${ARCHS}\" == *\"arm\"* ]];then\necho \"error: This will build an ARM binary, you (probably) don't want this (${ARCHS})\"\necho \"error: Tip: Perform a Run with Release configuration and use the resulting binary\"\nexit 1\nfi\n"; - }; 71B9E0DB268C792900D40A91 /* Print Shim Path */ = { isa = PBXShellScriptBuildPhase; alwaysOutOfDate = 1; @@ -297,10 +302,12 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 7197B82E2A9E39CC00234737 /* XTSwizzle.m in Sources */, EED62EF920D1243E006E86E5 /* FBXCTestMain.m in Sources */, EED62EF320D12432006E86E5 /* FBDebugLog.m in Sources */, EED62EE720D1224C006E86E5 /* TestCrashShim.m in Sources */, EED62EED20D12432006E86E5 /* FBRuntimeTools.m in Sources */, + 7197B83A2A9E3FD500234737 /* XCTestCaseHelpers.m in Sources */, EED62EE420D12242006E86E5 /* XCTestReporterShim.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -309,10 +316,12 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 7197B82F2A9E39CC00234737 /* XTSwizzle.m in Sources */, EED62EEE20D12432006E86E5 /* FBRuntimeTools.m in Sources */, EED62EFA20D1243E006E86E5 /* FBXCTestMain.m in Sources */, EED62EF420D12432006E86E5 /* FBDebugLog.m in Sources */, 71B9E0D9268C61B800D40A91 /* TestCrashShim.m in Sources */, + 7197B83B2A9E3FD500234737 /* XCTestCaseHelpers.m in Sources */, EED62EE520D12242006E86E5 /* XCTestReporterShim.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -354,7 +363,6 @@ isa = XCBuildConfiguration; baseConfigurationReference = EED62ED820D12209006E86E5 /* Maculator.xcconfig */; buildSettings = { - CODE_SIGN_IDENTITY = ""; }; name = Debug; }; @@ -362,7 +370,6 @@ isa = XCBuildConfiguration; baseConfigurationReference = EED62ED820D12209006E86E5 /* Maculator.xcconfig */; buildSettings = { - CODE_SIGN_IDENTITY = ""; }; name = Release; }; diff --git a/Shims/Shimulator/TestCrashShim/TestCrashShim.m b/Shims/Shimulator/TestCrashShim/TestCrashShim.m index a149c1367..ac1c19307 100644 --- a/Shims/Shimulator/TestCrashShim/TestCrashShim.m +++ b/Shims/Shimulator/TestCrashShim/TestCrashShim.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -7,6 +7,7 @@ #import +#import "FBDebugLog.h" static NSString *const ShimulatorCrashAfter = @"SHIMULATOR_CRASH_AFTER"; @@ -20,10 +21,25 @@ static void PerformCrashAfter(void) [NSFileManager.defaultManager performSelector:@selector(stringWithFormat:) withObject:@"NOPE" afterDelay:timeInterval]; } +static NSString *ArchName(void) +{ +#if TARGET_CPU_ARM64 + return @"arm64"; +#elif TARGET_CPU_X86_64 + return @"x86_64"; +#else + return @"not supported"); +#endif +} + static void PrintProcessInfo(void) { + FBDebugLog(@"Architecture %@",ArchName()); + NSProcessInfo *processInfo = NSProcessInfo.processInfo; NSLog(@"Arguments [%@]", [processInfo.arguments componentsJoinedByString:@" "]); + + FBDebugLog(@"Environment %@", processInfo.environment); } __attribute__((constructor)) static void EntryPoint() diff --git a/Shims/Shimulator/TestLoadingShim/FBXCTestMain.h b/Shims/Shimulator/TestLoadingShim/FBXCTestMain.h index 8cfc084bd..d78207643 100644 --- a/Shims/Shimulator/TestLoadingShim/FBXCTestMain.h +++ b/Shims/Shimulator/TestLoadingShim/FBXCTestMain.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/Shims/Shimulator/TestLoadingShim/FBXCTestMain.m b/Shims/Shimulator/TestLoadingShim/FBXCTestMain.m index 93aad04d5..1d3b76f47 100644 --- a/Shims/Shimulator/TestLoadingShim/FBXCTestMain.m +++ b/Shims/Shimulator/TestLoadingShim/FBXCTestMain.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -8,12 +8,15 @@ #import "FBXCTestMain.h" #import +#import #import #import "FBDebugLog.h" #import "FBRuntimeTools.h" #import "FBXCTestConstants.h" +#import "XCTestCaseHelpers.h" #import "XCTestPrivate.h" +#import "XTSwizzle.h" #include "TargetConditionals.h" @@ -66,7 +69,7 @@ BOOL FBLoadXCTestIfNeeded() for(NSString *frameworkDir in fallbackFrameworkDirs) { NSString *possibleLocation = [frameworkDir stringByAppendingPathComponent:@"XCTest.framework/XCTest"]; - if ([NSFileManager.defaultManager fileExistsAtPath:possibleLocation isDirectory:NO]) { + if ([NSFileManager.defaultManager fileExistsAtPath:possibleLocation isDirectory:nil]) { if (dlopen([possibleLocation cStringUsingEncoding:NSUTF8StringEncoding], RTLD_LAZY)) { FBDebugLog(@"[XCTestMainEntryPoint] Found and loaded XCTest from %@", possibleLocation); return YES; @@ -96,11 +99,32 @@ void FBDeployBlockWhenAppLoads(void(^mainBlock)()) { }]; } +/// Construct an XCTTestIdentifier using the same logic used to list the tests. +/// The identifier will contain the swift module prefix for tests written in swift, +/// as they used to in Xcode versions prior to 15.0 +static id XCTestCase__xctTestIdentifier(id self, SEL sel) +{ + NSString *classNameOut = nil; + NSString *methodNameOut = nil; + NSString *testKeyOut = nil; + parseXCTestCase(self, &classNameOut, &methodNameOut, &testKeyOut); + + Class XCTTestIdentifier_class = objc_lookUpClass("XCTTestIdentifier"); + return [[XCTTestIdentifier_class alloc] initWithStringRepresentation:[NSString stringWithFormat:@"%@/%@", classNameOut, methodNameOut] preserveModulePrefix:YES]; +} + BOOL FBXCTestMain() { if (!FBLoadXCTestIfNeeded()) { exit(TestShimExitCodeXCTestFailedLoading); } + + XTSwizzleSelectorForFunction( + objc_getClass("XCTestCase"), + @selector(_xctTestIdentifier), + (IMP)XCTestCase__xctTestIdentifier + ); + NSString *configurationPath = NSProcessInfo.processInfo.environment[@"XCTestConfigurationFilePath"]; if (!configurationPath) { NSLog(@"Failed to load XCTest as XCTestConfigurationFilePath environment variable is empty"); @@ -116,7 +140,7 @@ BOOL FBXCTestMain() if([NSKeyedUnarchiver respondsToSelector:@selector(xct_unarchivedObjectOfClass:fromData:)]){ configuration = (XCTestConfiguration *)[NSKeyedUnarchiver xct_unarchivedObjectOfClass:NSClassFromString(@"XCTestConfiguration") fromData:data]; } else { - configuration = [NSKeyedUnarchiver unarchiveObjectWithData:data]; + configuration = [NSKeyedUnarchiver unarchivedObjectOfClass:[NSString class] fromData:data error:&error]; } if (!configuration) { NSLog(@"Loaded XCTestConfiguration is nil"); diff --git a/Shims/Shimulator/TestReporterShim/XCTestReporterShim.m b/Shims/Shimulator/TestReporterShim/XCTestReporterShim.m index 5090b88d9..ca9d5eb49 100644 --- a/Shims/Shimulator/TestReporterShim/XCTestReporterShim.m +++ b/Shims/Shimulator/TestReporterShim/XCTestReporterShim.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -12,7 +12,9 @@ #import #import "FBXCTestConstants.h" +#import "XCTestCaseHelpers.h" #import "XCTestPrivate.h" +#import "XTSwizzle.h" #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wundeclared-selector" @@ -28,48 +30,6 @@ static NSMutableArray *> *__testExceptions = nil; static int __testSuiteDepth = 0; -static void parseXCTestCase(XCTestCase *testCase, NSString **classNameOut, NSString **methodNameOut, NSString **testKeyOut) -{ - NSString *className = NSStringFromClass(testCase.class); - NSString *methodName; - if ([testCase respondsToSelector:@selector(languageAgnosticTestMethodName)]) { - methodName = [testCase languageAgnosticTestMethodName]; - } else { - methodName = NSStringFromSelector([testCase.invocation selector]); - } - NSString *testKey = [NSString stringWithFormat:@"-[%@ %@]", className, methodName]; - if (classNameOut) { - *classNameOut = className; - } - if (methodNameOut) { - *methodNameOut = methodName; - } - if (testKeyOut) { - *testKeyOut = testKey; - } -} - -static NSString *parseXCTestSuiteKey(XCTestSuite *suite) -{ - NSString *testKey = nil; - for (id test in suite.tests) { - if (![test isKindOfClass:NSClassFromString(@"XCTestCase")]) { - return [suite name]; - } - XCTestCase *testCase = test; - NSString *innerTestKey = nil; - parseXCTestCase(testCase, &innerTestKey, nil, nil); - if (!testKey) { - testKey = innerTestKey; - continue; - } - if (![innerTestKey isEqualToString:testKey]) { - return [suite name]; - } - } - return testKey ?: [suite name]; -} - NSDictionary *EventDictionaryWithNameAndContent(NSString *name, NSDictionary *content) { NSMutableDictionary *eventJSON = [NSMutableDictionary dictionaryWithDictionary:@{ @@ -80,43 +40,6 @@ static void parseXCTestCase(XCTestCase *testCase, NSString **classNameOut, NSStr return eventJSON; } -void XTSwizzleClassSelectorForFunction(Class cls, SEL sel, IMP newImp) __attribute__((no_sanitize("nullability-arg"))) -{ - Class clscls = object_getClass((id)cls); - Method originalMethod = class_getClassMethod(cls, sel); - - NSString *selectorName = [[NSString alloc] initWithFormat: - @"__%s_%s", - class_getName(cls), - sel_getName(sel)]; - SEL newSelector = sel_registerName([selectorName UTF8String]); - - class_addMethod(clscls, newSelector, newImp, method_getTypeEncoding(originalMethod)); - Method replacedMethod = class_getClassMethod(cls, newSelector); - method_exchangeImplementations(originalMethod, replacedMethod); -} - -void XTSwizzleSelectorForFunction(Class cls, SEL sel, IMP newImp) -{ - Method originalMethod = class_getInstanceMethod(cls, sel); - const char *typeEncoding = method_getTypeEncoding(originalMethod); - - NSString *selectorName = [[NSString alloc] initWithFormat: - @"__%s_%s", - class_getName(cls), - sel_getName(sel)]; - SEL newSelector = sel_registerName([selectorName UTF8String]); - - class_addMethod(cls, newSelector, newImp, typeEncoding); - - Method newMethod = class_getInstanceMethod(cls, newSelector); - // @lint-ignore FBOBJCDISCOURAGEDFUNCTION - if (class_addMethod(cls, sel, newImp, typeEncoding)) { - class_replaceMethod(cls, newSelector, method_getImplementation(originalMethod), typeEncoding); - } else { - method_exchangeImplementations(originalMethod, newMethod); - } -} NSArray *TestsFromSuite(id testSuite) { diff --git a/Shims/Shimulator/Tools/FBDebugLog.h b/Shims/Shimulator/Tools/FBDebugLog.h index f19cec80e..c6f175fd5 100644 --- a/Shims/Shimulator/Tools/FBDebugLog.h +++ b/Shims/Shimulator/Tools/FBDebugLog.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/Shims/Shimulator/Tools/FBDebugLog.m b/Shims/Shimulator/Tools/FBDebugLog.m index ac84ae93a..05fd88f1b 100644 --- a/Shims/Shimulator/Tools/FBDebugLog.m +++ b/Shims/Shimulator/Tools/FBDebugLog.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/Shims/Shimulator/Tools/FBRuntimeTools.h b/Shims/Shimulator/Tools/FBRuntimeTools.h index a64477540..272869494 100644 --- a/Shims/Shimulator/Tools/FBRuntimeTools.h +++ b/Shims/Shimulator/Tools/FBRuntimeTools.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/Shims/Shimulator/Tools/FBRuntimeTools.m b/Shims/Shimulator/Tools/FBRuntimeTools.m index 32f3c986a..b1ae37137 100644 --- a/Shims/Shimulator/Tools/FBRuntimeTools.m +++ b/Shims/Shimulator/Tools/FBRuntimeTools.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/Shims/Shimulator/Tools/FBXCTestConstants.h b/Shims/Shimulator/Tools/FBXCTestConstants.h index a4f2f3e21..aaf90aa7a 100644 --- a/Shims/Shimulator/Tools/FBXCTestConstants.h +++ b/Shims/Shimulator/Tools/FBXCTestConstants.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/Shims/Shimulator/Tools/XCTestCaseHelpers.h b/Shims/Shimulator/Tools/XCTestCaseHelpers.h new file mode 100644 index 000000000..770b8ce1a --- /dev/null +++ b/Shims/Shimulator/Tools/XCTestCaseHelpers.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +@class XCTestCase, XCTestSuite, NSString; + +void parseXCTestCase(XCTestCase *testCase, NSString **classNameOut, NSString **methodNameOut, NSString **testKeyOut); + +NSString *parseXCTestSuiteKey(XCTestSuite *suite); diff --git a/Shims/Shimulator/Tools/XCTestCaseHelpers.m b/Shims/Shimulator/Tools/XCTestCaseHelpers.m new file mode 100644 index 000000000..9b795dfd6 --- /dev/null +++ b/Shims/Shimulator/Tools/XCTestCaseHelpers.m @@ -0,0 +1,55 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + + +#import "XCTestCaseHelpers.h" + +#import + +#import "XCTestPrivate.h" + +void parseXCTestCase(XCTestCase *testCase, NSString **classNameOut, NSString **methodNameOut, NSString **testKeyOut) +{ + NSString *className = NSStringFromClass(testCase.class); + NSString *methodName; + if ([testCase respondsToSelector:@selector(languageAgnosticTestMethodName)]) { + methodName = [testCase languageAgnosticTestMethodName]; + } else { + methodName = NSStringFromSelector([testCase.invocation selector]); + } + NSString *testKey = [NSString stringWithFormat:@"-[%@ %@]", className, methodName]; + if (classNameOut) { + *classNameOut = className; + } + if (methodNameOut) { + *methodNameOut = methodName; + } + if (testKeyOut) { + *testKeyOut = testKey; + } +} + +NSString *parseXCTestSuiteKey(XCTestSuite *suite) +{ + NSString *testKey = nil; + for (id test in suite.tests) { + if (![test isKindOfClass:NSClassFromString(@"XCTestCase")]) { + return [suite name]; + } + XCTestCase *testCase = test; + NSString *innerTestKey = nil; + parseXCTestCase(testCase, &innerTestKey, nil, nil); + if (!testKey) { + testKey = innerTestKey; + continue; + } + if (![innerTestKey isEqualToString:testKey]) { + return [suite name]; + } + } + return testKey ?: [suite name]; +} diff --git a/Shims/Shimulator/Tools/XCTestPrivate.h b/Shims/Shimulator/Tools/XCTestPrivate.h index fdd150f56..680e17615 100644 --- a/Shims/Shimulator/Tools/XCTestPrivate.h +++ b/Shims/Shimulator/Tools/XCTestPrivate.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -185,6 +185,54 @@ struct __va_list_tag { - (instancetype)initWithSelector:(SEL)arg1; - (instancetype)initWithInvocation:(id)arg1; - (instancetype)init; +- (id)_xctTestIdentifier; + +@end + +@interface XCTTestIdentifier : NSObject +{ +} + ++ (_Bool)supportsSecureCoding; ++ (id)allocWithZone:(struct _NSZone *)arg1; ++ (id)bundleIdentifier; ++ (id)identifierForClass:(Class)arg1; ++ (id)leafIdentifierWithComponents:(id)arg1; ++ (id)containerIdentifierWithComponents:(id)arg1; ++ (id)containerIdentifierWithComponent:(id)arg1; +- (Class)classForCoder; +- (void)encodeWithCoder:(id)arg1; +- (id)initWithCoder:(id)arg1; +@property(readonly) unsigned long long options; +- (id)componentAtIndex:(unsigned long long)arg1; +@property(readonly) unsigned long long componentCount; +@property(readonly) NSArray *components; +- (id)initWithComponents:(id)arg1 options:(unsigned long long)arg2; +- (id)initWithStringRepresentation:(id)arg1 preserveModulePrefix:(_Bool)arg2; +- (id)initWithStringRepresentation:(id)arg1; +- (id)initWithClassName:(id)arg1; +- (id)initWithClassName:(id)arg1 methodName:(id)arg2; +- (id)initWithClassAndMethodComponents:(id)arg1; +- (id)initWithComponents:(id)arg1 isContainer:(_Bool)arg2; +- (id)copyWithZone:(struct _NSZone *)arg1; +@property(readonly) XCTTestIdentifier *swiftMethodCounterpart; +@property(readonly) XCTTestIdentifier *firstComponentIdentifier; +@property(readonly) XCTTestIdentifier *parentIdentifier; +- (id)_identifierString; +@property(readonly) NSString *identifierString; +@property(readonly) NSString *displayName; +@property(readonly) NSString *lastComponentDisplayName; +@property(readonly) NSString *lastComponent; +@property(readonly) NSString *firstComponent; +@property(readonly) _Bool representsBundle; +@property(readonly) _Bool isLeaf; +@property(readonly) _Bool isContainer; +- (unsigned long long)hash; +- (_Bool)isEqual:(id)arg1; +- (id)debugDescription; +- (id)description; +@property(readonly) _Bool isSwiftMethod; +@property(readonly) _Bool usesClassAndMethodSemantics; @end diff --git a/Shims/Shimulator/Tools/XTSwizzle.h b/Shims/Shimulator/Tools/XTSwizzle.h new file mode 100644 index 000000000..0349cfab5 --- /dev/null +++ b/Shims/Shimulator/Tools/XTSwizzle.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import + +void XTSwizzleClassSelectorForFunction(Class cls, SEL sel, IMP newImp) __attribute__((no_sanitize("nullability-arg"))); + +void XTSwizzleSelectorForFunction(Class cls, SEL sel, IMP newImp); diff --git a/Shims/Shimulator/Tools/XTSwizzle.m b/Shims/Shimulator/Tools/XTSwizzle.m new file mode 100644 index 000000000..bf6f02478 --- /dev/null +++ b/Shims/Shimulator/Tools/XTSwizzle.m @@ -0,0 +1,49 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import "XTSwizzle.h" + +#import + +void XTSwizzleClassSelectorForFunction(Class cls, SEL sel, IMP newImp) __attribute__((no_sanitize("nullability-arg"))) +{ + Class clscls = object_getClass((id)cls); + Method originalMethod = class_getClassMethod(cls, sel); + + NSString *selectorName = [[NSString alloc] initWithFormat: + @"__%s_%s", + class_getName(cls), + sel_getName(sel)]; + SEL newSelector = sel_registerName([selectorName UTF8String]); + + class_addMethod(clscls, newSelector, newImp, method_getTypeEncoding(originalMethod)); + Method replacedMethod = class_getClassMethod(cls, newSelector); + method_exchangeImplementations(originalMethod, replacedMethod); +} + +void XTSwizzleSelectorForFunction(Class cls, SEL sel, IMP newImp) +{ + Method originalMethod = class_getInstanceMethod(cls, sel); + const char *typeEncoding = method_getTypeEncoding(originalMethod); + + NSString *selectorName = [[NSString alloc] initWithFormat: + @"__%s_%s", + class_getName(cls), + sel_getName(sel)]; + SEL newSelector = sel_registerName([selectorName UTF8String]); + + class_addMethod(cls, newSelector, newImp, typeEncoding); + + Method newMethod = class_getInstanceMethod(cls, newSelector); + // @lint-ignore FBOBJCDISCOURAGEDFUNCTION + if (class_addMethod(cls, sel, newImp, typeEncoding)) { + class_replaceMethod(cls, newSelector, method_getImplementation(originalMethod), typeEncoding); + } else { + method_exchangeImplementations(originalMethod, newMethod); + } +} + diff --git a/XCTestBootstrap/Configuration/FBCodeCoverageConfiguration.h b/XCTestBootstrap/Configuration/FBCodeCoverageConfiguration.h index efe3887ef..ea47c8789 100644 --- a/XCTestBootstrap/Configuration/FBCodeCoverageConfiguration.h +++ b/XCTestBootstrap/Configuration/FBCodeCoverageConfiguration.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -29,7 +29,12 @@ typedef NS_ENUM(NSUInteger, FBCodeCoverageFormat) { */ @property (nonatomic, assign, readonly) FBCodeCoverageFormat format; -- (instancetype)initWithDirectory:(NSString *)coverageDirectory format:(FBCodeCoverageFormat)format; +/** + Determines whether should enable continuous coverage collection + */ +@property (nonatomic, assign, readonly) BOOL shouldEnableContinuousCoverageCollection; + +- (instancetype)initWithDirectory:(NSString *)coverageDirectory format:(FBCodeCoverageFormat)format enableContinuousCoverageCollection:(BOOL)enableContinuousCoverageCollection; @end diff --git a/XCTestBootstrap/Configuration/FBCodeCoverageConfiguration.m b/XCTestBootstrap/Configuration/FBCodeCoverageConfiguration.m index 65bf63f10..283762cf4 100644 --- a/XCTestBootstrap/Configuration/FBCodeCoverageConfiguration.m +++ b/XCTestBootstrap/Configuration/FBCodeCoverageConfiguration.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -10,22 +10,23 @@ @implementation FBCodeCoverageConfiguration --(instancetype) initWithDirectory:(NSString *)coverageDirectory format:(FBCodeCoverageFormat)format +-(instancetype) initWithDirectory:(NSString *)coverageDirectory format:(FBCodeCoverageFormat)format enableContinuousCoverageCollection:(BOOL)enableContinuousCoverageCollection { self = [super init]; if (!self) { return nil; } - + _coverageDirectory = coverageDirectory; _format = format; + _shouldEnableContinuousCoverageCollection = enableContinuousCoverageCollection; return self; } - (NSString *)description { - return [NSString stringWithFormat:@"Coverage Directory %@ | Format %lu", self.coverageDirectory, (unsigned long)self.format]; + return [NSString stringWithFormat:@"Coverage Directory %@ | Format %lu | Enable Continuous Coverage Collection %d", self.coverageDirectory, (unsigned long)self.format, self.shouldEnableContinuousCoverageCollection]; } diff --git a/XCTestBootstrap/Configuration/FBTestConfiguration.h b/XCTestBootstrap/Configuration/FBTestConfiguration.h index 88ce618d7..2881eb5d6 100644 --- a/XCTestBootstrap/Configuration/FBTestConfiguration.h +++ b/XCTestBootstrap/Configuration/FBTestConfiguration.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -7,6 +7,8 @@ #import +@class XCTestConfiguration; + NS_ASSUME_NONNULL_BEGIN /** @@ -40,8 +42,9 @@ NS_ASSUME_NONNULL_BEGIN @param moduleName name the test module name. @param testBundlePath the absolute path to the test bundle. @param uiTesting YES if to initialize the Test Configuraiton for UI Testing, NO otherwise. + @param xcTestConfiguration underlying XCTestConfiguration object */ -+ (instancetype)configurationWithSessionIdentifier:(NSUUID *)sessionIdentifier moduleName:(NSString *)moduleName testBundlePath:(NSString *)testBundlePath path:(NSString *)path uiTesting:(BOOL)uiTesting; ++ (instancetype)configurationWithSessionIdentifier:(NSUUID *)sessionIdentifier moduleName:(NSString *)moduleName testBundlePath:(NSString *)testBundlePath path:(NSString *)path uiTesting:(BOOL)uiTesting xcTestConfiguration:(XCTestConfiguration *)xcTestConfiguration; /** The session identifier @@ -73,6 +76,8 @@ NS_ASSUME_NONNULL_BEGIN */ @property (nonatomic, assign, readonly) BOOL shouldInitializeForUITesting; +@property (nonatomic, strong, readonly) XCTestConfiguration *xcTestConfiguration; + @end NS_ASSUME_NONNULL_END diff --git a/XCTestBootstrap/Configuration/FBTestConfiguration.m b/XCTestBootstrap/Configuration/FBTestConfiguration.m index 94dc80f7d..37ae09064 100644 --- a/XCTestBootstrap/Configuration/FBTestConfiguration.m +++ b/XCTestBootstrap/Configuration/FBTestConfiguration.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -9,10 +9,11 @@ #import -#import -#import -#import -#import +#import +#import +#import +#import +#import #import @@ -39,16 +40,21 @@ + (nullable instancetype)configurationByWritingToFileWithSessionIdentifier:(NSUU testConfiguration.reportActivities = reportActivities; testConfiguration.testsDrivenByIDE = NO; testConfiguration.testApplicationDependencies = testApplicationDependencies; - - NSData *data = [NSKeyedArchiver archivedDataWithRootObject:testConfiguration]; + XCTCapabilitiesBuilder *capabilitiesBuilder = [objc_lookUpClass("XCTCapabilitiesBuilder") new]; + [capabilitiesBuilder registerCapability:@"XCTIssue capability"]; + [capabilitiesBuilder registerCapability:@"ubiquitous test identifiers"]; + testConfiguration.IDECapabilities = [capabilitiesBuilder capabilities]; + + NSData *data = [NSKeyedArchiver archivedDataWithRootObject:testConfiguration requiringSecureCoding:NO error:nil]; // Write it to file. - NSString *savePath = [testBundlePath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@-%@.xctestconfiguration", moduleName, sessionIdentifier.UUIDString]]; - if (![data writeToFile:savePath options:NSDataWritingAtomic error:error]) { + NSString *testBundleContainerPath = testBundlePath.stringByDeletingLastPathComponent; + NSString *testConfigPath = [testBundleContainerPath stringByAppendingPathComponent:[NSString stringWithFormat:@"%@-%@.xctestconfiguration", moduleName, sessionIdentifier.UUIDString]]; + if (![data writeToFile:testConfigPath options:NSDataWritingAtomic error:error]) { return nil; } - return [self configurationWithSessionIdentifier:sessionIdentifier moduleName:moduleName testBundlePath:testBundlePath path:savePath uiTesting:uiTesting]; + return [self configurationWithSessionIdentifier:sessionIdentifier moduleName:moduleName testBundlePath:testBundlePath path:testConfigPath uiTesting:uiTesting xcTestConfiguration:testConfiguration]; } + (void) setTestsToRun: (NSSet *) toRun andTestsToSkip: (NSSet *) toSkip to: (XCTestConfiguration *) configuration @@ -67,28 +73,30 @@ + (nullable XCTTestIdentifierSet *)xctestIdentifierSetFromSetOfStrings:(nullable if (tests == nil) { return nil; } - + Class XCTTestIdentifierSetBuilder_class = objc_lookUpClass("XCTTestIdentifierSetBuilder"); XCTTestIdentifierSetBuilder *b = [[XCTTestIdentifierSetBuilder_class alloc] init]; Class XCTTestIdentifier_class = objc_lookUpClass("XCTTestIdentifier");; for (NSString *test in tests) { - [b addTestIdentifier: [[XCTTestIdentifier_class alloc] initWithStringRepresentation: test]]; + XCTTestIdentifier *identifier = [[XCTTestIdentifier_class alloc] initWithStringRepresentation: test preserveModulePrefix:YES]; + [b addTestIdentifier: identifier]; } - + return b.testIdentifierSet; } -+ (instancetype)configurationWithSessionIdentifier:(NSUUID *)sessionIdentifier moduleName:(NSString *)moduleName testBundlePath:(NSString *)testBundlePath path:(NSString *)path uiTesting:(BOOL)uiTesting ++ (instancetype)configurationWithSessionIdentifier:(NSUUID *)sessionIdentifier moduleName:(NSString *)moduleName testBundlePath:(NSString *)testBundlePath path:(NSString *)path uiTesting:(BOOL)uiTesting xcTestConfiguration:(XCTestConfiguration *)xcTestConfiguration { return [[self alloc] initWithSessionIdentifier:sessionIdentifier moduleName:moduleName testBundlePath:testBundlePath path:path - uiTesting:uiTesting]; + uiTesting:uiTesting + xcTestConfiguration:xcTestConfiguration]; } -- (instancetype)initWithSessionIdentifier:(NSUUID *)sessionIdentifier moduleName:(NSString *)moduleName testBundlePath:(NSString *)testBundlePath path:(NSString *)path uiTesting:(BOOL)uiTesting +- (instancetype)initWithSessionIdentifier:(NSUUID *)sessionIdentifier moduleName:(NSString *)moduleName testBundlePath:(NSString *)testBundlePath path:(NSString *)path uiTesting:(BOOL)uiTesting xcTestConfiguration:(XCTestConfiguration *)xcTestConfiguration { self = [super init]; if (!self) { @@ -100,6 +108,7 @@ - (instancetype)initWithSessionIdentifier:(NSUUID *)sessionIdentifier moduleName _testBundlePath = testBundlePath; _path = path; _shouldInitializeForUITesting = uiTesting; + _xcTestConfiguration=xcTestConfiguration; return self; } diff --git a/XCTestBootstrap/Configuration/FBTestRunnerConfiguration.h b/XCTestBootstrap/Configuration/FBTestRunnerConfiguration.h index 3724ad4da..2a9188075 100644 --- a/XCTestBootstrap/Configuration/FBTestRunnerConfiguration.h +++ b/XCTestBootstrap/Configuration/FBTestRunnerConfiguration.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -43,7 +43,7 @@ NS_ASSUME_NONNULL_BEGIN @param hostApplication the application bundle. @param hostApplicationAdditionalEnvironment additional environment variables that are passed into the runner app. @param testBundle the test bundle. - @param testConfigurationPath the path on disk of the test configuration used. + @param testConfigurationPath FBTestConfiguration object. @param frameworkSearchPaths the list of search paths to add in the launch. @return a new environment dictionary. */ @@ -76,6 +76,8 @@ NS_ASSUME_NONNULL_BEGIN */ @property (nonatomic, copy, readonly) NSDictionary *testedApplicationAdditionalEnvironment; +@property (nonatomic, strong, readonly) FBTestConfiguration *testConfiguration; + @end NS_ASSUME_NONNULL_END diff --git a/XCTestBootstrap/Configuration/FBTestRunnerConfiguration.m b/XCTestBootstrap/Configuration/FBTestRunnerConfiguration.m index 5edb306df..dc4baa765 100644 --- a/XCTestBootstrap/Configuration/FBTestRunnerConfiguration.m +++ b/XCTestBootstrap/Configuration/FBTestRunnerConfiguration.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -15,7 +15,7 @@ @implementation FBTestRunnerConfiguration #pragma mark Initializers -- (instancetype)initWithSessionIdentifier:(NSUUID *)sessionIdentifier testRunner:(FBBundleDescriptor *)testRunner launchEnvironment:(NSDictionary *)launchEnvironment testedApplicationAdditionalEnvironment:(NSDictionary *)testedApplicationAdditionalEnvironment +- (instancetype)initWithSessionIdentifier:(NSUUID *)sessionIdentifier testRunner:(FBBundleDescriptor *)testRunner launchEnvironment:(NSDictionary *)launchEnvironment testedApplicationAdditionalEnvironment:(NSDictionary *)testedApplicationAdditionalEnvironment testConfiguration:(FBTestConfiguration *)testConfiguration { self = [super init]; if (!self) { @@ -26,6 +26,7 @@ - (instancetype)initWithSessionIdentifier:(NSUUID *)sessionIdentifier testRunner _testRunner = testRunner; _launchEnvironment = launchEnvironment; _testedApplicationAdditionalEnvironment = testedApplicationAdditionalEnvironment; + _testConfiguration = testConfiguration; return self; } @@ -159,7 +160,7 @@ - (instancetype)copyWithZone:(NSZone *)zone automationFrameworkPath:automationFrameworkPath reportActivities:testLaunchConfiguration.reportActivities error:&error]; - if (!testBundle) { + if (!testConfiguration) { return [[[XCTestBootstrapError describe:@"Failed to prepare test configuration"] causedBy:error] @@ -179,12 +180,13 @@ - (instancetype)copyWithZone:(NSZone *)zone hostApplicationAdditionalEnvironment[@"DYLD_INSERT_LIBRARIES"] = shimPath; hostApplicationAdditionalEnvironment[kEnv_WaitForDebugger] = testLaunchConfiguration.applicationLaunchConfiguration.waitForDebugger ? @"YES" : @"NO"; if (testLaunchConfiguration.coverageDirectoryPath) { - NSString *hostCoverageFile = [NSString stringWithFormat:@"coverage_%@.profraw", hostApplication.bundle.identifier]; + NSString *continuousCoverageCollectionMode = testLaunchConfiguration.shouldEnableContinuousCoverageCollection ? @"%c" : @""; + NSString *hostCoverageFile = [NSString stringWithFormat:@"coverage_%@%@.profraw", hostApplication.bundle.identifier, continuousCoverageCollectionMode]; NSString *hostCoveragePath = [testLaunchConfiguration.coverageDirectoryPath stringByAppendingPathComponent:hostCoverageFile]; hostApplicationAdditionalEnvironment[kEnv_LLVMProfileFile] = hostCoveragePath; if (testLaunchConfiguration.targetApplicationBundle != nil) { - NSString *targetCoverageFile = [NSString stringWithFormat:@"coverage_%@.profraw", testLaunchConfiguration.targetApplicationBundle.identifier]; + NSString *targetCoverageFile = [NSString stringWithFormat:@"coverage_%@%@.profraw", testLaunchConfiguration.targetApplicationBundle.identifier, continuousCoverageCollectionMode]; NSString *targetAppCoveragePath = [testLaunchConfiguration.coverageDirectoryPath stringByAppendingPathComponent:targetCoverageFile]; testedApplicationAdditionalEnvironment[kEnv_LLVMProfileFile] = targetAppCoveragePath; } @@ -211,7 +213,8 @@ - (instancetype)copyWithZone:(NSZone *)zone initWithSessionIdentifier:sessionIdentifier testRunner:hostApplication.bundle launchEnvironment:launchEnvironment - testedApplicationAdditionalEnvironment:[testedApplicationAdditionalEnvironment copy]]; + testedApplicationAdditionalEnvironment:[testedApplicationAdditionalEnvironment copy] + testConfiguration:testConfiguration]; }]; } diff --git a/XCTestBootstrap/Configuration/FBXCTestConfiguration.h b/XCTestBootstrap/Configuration/FBXCTestConfiguration.h index 3ec72a175..e0a9561da 100644 --- a/XCTestBootstrap/Configuration/FBXCTestConfiguration.h +++ b/XCTestBootstrap/Configuration/FBXCTestConfiguration.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -100,10 +100,15 @@ extern FBXCTestType const FBXCTestTypeListTest; */ @interface FBListTestConfiguration : FBXCTestConfiguration +/** + The supported architectures of the test bundle. + */ +@property (nonatomic, strong, readonly, nonnull) NSSet *architectures; + /** The Designated Initializer. */ -+ (instancetype)configurationWithEnvironment:(NSDictionary *)environment workingDirectory:(NSString *)workingDirectory testBundlePath:(NSString *)testBundlePath runnerAppPath:(nullable NSString *)runnerAppPath waitForDebugger:(BOOL)waitForDebugger timeout:(NSTimeInterval)timeout; ++ (instancetype)configurationWithEnvironment:(NSDictionary *)environment workingDirectory:(NSString *)workingDirectory testBundlePath:(NSString *)testBundlePath runnerAppPath:(nullable NSString *)runnerAppPath waitForDebugger:(BOOL)waitForDebugger timeout:(NSTimeInterval)timeout architectures:(nonnull NSSet *)architectures; @property (nonatomic, copy, readonly) NSString *runnerAppPath; @@ -195,10 +200,15 @@ typedef NS_OPTIONS(NSUInteger, FBLogicTestMirrorLogs) { */ @property (nonatomic, nullable, copy, readonly) NSString *logDirectoryPath; +/** + The supported architectures of the test bundle. + */ +@property (nonatomic, strong, readonly) NSSet *architectures; + /** The Designated Initializer. */ -+ (instancetype)configurationWithEnvironment:(NSDictionary *)environment workingDirectory:(NSString *)workingDirectory testBundlePath:(NSString *)testBundlePath waitForDebugger:(BOOL)waitForDebugger timeout:(NSTimeInterval)timeout testFilter:(nullable NSString *)testFilter mirroring:(FBLogicTestMirrorLogs)mirroring coverageConfiguration:(nullable FBCodeCoverageConfiguration *)coverageConfiguration binaryPath:(nullable NSString *)binaryPath logDirectoryPath:(nullable NSString *)logDirectoryPath; ++ (instancetype)configurationWithEnvironment:(NSDictionary *)environment workingDirectory:(NSString *)workingDirectory testBundlePath:(NSString *)testBundlePath waitForDebugger:(BOOL)waitForDebugger timeout:(NSTimeInterval)timeout testFilter:(nullable NSString *)testFilter mirroring:(FBLogicTestMirrorLogs)mirroring coverageConfiguration:(nullable FBCodeCoverageConfiguration *)coverageConfiguration binaryPath:(nullable NSString *)binaryPath logDirectoryPath:(nullable NSString *)logDirectoryPath architectures:(nonnull NSSet *)architectures; @end diff --git a/XCTestBootstrap/Configuration/FBXCTestConfiguration.m b/XCTestBootstrap/Configuration/FBXCTestConfiguration.m index 34c20401f..cb6d05120 100644 --- a/XCTestBootstrap/Configuration/FBXCTestConfiguration.m +++ b/XCTestBootstrap/Configuration/FBXCTestConfiguration.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -157,12 +157,12 @@ @implementation FBListTestConfiguration #pragma mark Initializers -+ (instancetype)configurationWithEnvironment:(NSDictionary *)environment workingDirectory:(NSString *)workingDirectory testBundlePath:(NSString *)testBundlePath runnerAppPath:(nullable NSString *)runnerAppPath waitForDebugger:(BOOL)waitForDebugger timeout:(NSTimeInterval)timeout ++ (instancetype)configurationWithEnvironment:(NSDictionary *)environment workingDirectory:(NSString *)workingDirectory testBundlePath:(NSString *)testBundlePath runnerAppPath:(nullable NSString *)runnerAppPath waitForDebugger:(BOOL)waitForDebugger timeout:(NSTimeInterval)timeout architectures:(nonnull NSSet *)architectures { - return [[FBListTestConfiguration alloc] initWithEnvironment:environment workingDirectory:workingDirectory testBundlePath:testBundlePath runnerAppPath:runnerAppPath waitForDebugger:waitForDebugger timeout:timeout]; + return [[FBListTestConfiguration alloc] initWithEnvironment:environment workingDirectory:workingDirectory testBundlePath:testBundlePath runnerAppPath:runnerAppPath waitForDebugger:waitForDebugger timeout:timeout architectures:architectures]; } -- (instancetype)initWithEnvironment:(NSDictionary *)environment workingDirectory:(NSString *)workingDirectory testBundlePath:(NSString *)testBundlePath runnerAppPath:(nullable NSString *)runnerAppPath waitForDebugger:(BOOL)waitForDebugger timeout:(NSTimeInterval)timeout +- (instancetype)initWithEnvironment:(NSDictionary *)environment workingDirectory:(NSString *)workingDirectory testBundlePath:(NSString *)testBundlePath runnerAppPath:(nullable NSString *)runnerAppPath waitForDebugger:(BOOL)waitForDebugger timeout:(NSTimeInterval)timeout architectures:(nonnull NSSet *)architectures { self = [super initWithEnvironment:environment workingDirectory:workingDirectory testBundlePath:testBundlePath waitForDebugger:waitForDebugger timeout:timeout]; if (!self) { @@ -170,6 +170,7 @@ - (instancetype)initWithEnvironment:(NSDictionary *)envi } _runnerAppPath = runnerAppPath; + _architectures = architectures; return self; } @@ -246,12 +247,12 @@ @implementation FBLogicTestConfiguration #pragma mark Initializers -+ (instancetype)configurationWithEnvironment:(NSDictionary *)environment workingDirectory:(NSString *)workingDirectory testBundlePath:(NSString *)testBundlePath waitForDebugger:(BOOL)waitForDebugger timeout:(NSTimeInterval)timeout testFilter:(NSString *)testFilter mirroring:(FBLogicTestMirrorLogs)mirroring coverageConfiguration:(nullable FBCodeCoverageConfiguration *)coverageConfiguration binaryPath:(nullable NSString *)binaryPath logDirectoryPath:(NSString *)logDirectoryPath ++ (instancetype)configurationWithEnvironment:(NSDictionary *)environment workingDirectory:(NSString *)workingDirectory testBundlePath:(NSString *)testBundlePath waitForDebugger:(BOOL)waitForDebugger timeout:(NSTimeInterval)timeout testFilter:(NSString *)testFilter mirroring:(FBLogicTestMirrorLogs)mirroring coverageConfiguration:(nullable FBCodeCoverageConfiguration *)coverageConfiguration binaryPath:(nullable NSString *)binaryPath logDirectoryPath:(NSString *)logDirectoryPath architectures:(nonnull NSSet *)architectures { - return [[FBLogicTestConfiguration alloc] initWithEnvironment:environment workingDirectory:workingDirectory testBundlePath:testBundlePath waitForDebugger:waitForDebugger timeout:timeout testFilter:testFilter mirroring:mirroring coverageConfiguration:coverageConfiguration binaryPath:binaryPath logDirectoryPath:logDirectoryPath]; + return [[FBLogicTestConfiguration alloc] initWithEnvironment:environment workingDirectory:workingDirectory testBundlePath:testBundlePath waitForDebugger:waitForDebugger timeout:timeout testFilter:testFilter mirroring:mirroring coverageConfiguration:coverageConfiguration binaryPath:binaryPath logDirectoryPath:logDirectoryPath architectures:architectures]; } -- (instancetype)initWithEnvironment:(NSDictionary *)environment workingDirectory:(NSString *)workingDirectory testBundlePath:(NSString *)testBundlePath waitForDebugger:(BOOL)waitForDebugger timeout:(NSTimeInterval)timeout testFilter:(NSString *)testFilter mirroring:(FBLogicTestMirrorLogs)mirroring coverageConfiguration:(nullable FBCodeCoverageConfiguration *)coverageConfiguration binaryPath:(nullable NSString *)binaryPath logDirectoryPath:(NSString *)logDirectoryPath +- (instancetype)initWithEnvironment:(NSDictionary *)environment workingDirectory:(NSString *)workingDirectory testBundlePath:(NSString *)testBundlePath waitForDebugger:(BOOL)waitForDebugger timeout:(NSTimeInterval)timeout testFilter:(NSString *)testFilter mirroring:(FBLogicTestMirrorLogs)mirroring coverageConfiguration:(nullable FBCodeCoverageConfiguration *)coverageConfiguration binaryPath:(nullable NSString *)binaryPath logDirectoryPath:(NSString *)logDirectoryPath architectures:(nonnull NSSet *)architectures { self = [super initWithEnvironment:environment workingDirectory:workingDirectory testBundlePath:testBundlePath waitForDebugger:waitForDebugger timeout:timeout]; if (!self) { @@ -263,6 +264,7 @@ - (instancetype)initWithEnvironment:(NSDictionary *)envi _coverageConfiguration = coverageConfiguration; _binaryPath = binaryPath; _logDirectoryPath = logDirectoryPath; + _architectures = architectures; return self; } diff --git a/XCTestBootstrap/MacStrategies/FBMacDevice.h b/XCTestBootstrap/MacStrategies/FBMacDevice.h index f948113ec..fc5b7f4a5 100644 --- a/XCTestBootstrap/MacStrategies/FBMacDevice.h +++ b/XCTestBootstrap/MacStrategies/FBMacDevice.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/XCTestBootstrap/MacStrategies/FBMacDevice.m b/XCTestBootstrap/MacStrategies/FBMacDevice.m index 08e168064..57ed0f6f7 100644 --- a/XCTestBootstrap/MacStrategies/FBMacDevice.m +++ b/XCTestBootstrap/MacStrategies/FBMacDevice.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -15,6 +15,7 @@ #import "XCTestBootstrapError.h" #import "FBListTestStrategy.h" #import "FBXCTestConfiguration.h" +#import "FBMacLaunchedApplication.h" @protocol XCTestManager_XPCControl - (void)_XCT_requestConnectedSocketForTransport:(void (^)(NSFileHandle *, NSError *))arg1; @@ -38,7 +39,9 @@ + (NSString *)applicationInstallDirectory static dispatch_once_t onceToken; static NSString *_value; dispatch_once(&onceToken, ^{ - _value = NSSearchPathForDirectoriesInDomains(NSApplicationDirectory, NSUserDomainMask, YES).lastObject; + NSString *uuid = [[NSUUID UUID] UUIDString]; + NSString *parentDir = NSSearchPathForDirectoriesInDomains(NSApplicationDirectory, NSUserDomainMask, YES).lastObject; + _value = [parentDir stringByAppendingPathComponent:uuid]; }); return _value; } @@ -65,9 +68,15 @@ - (instancetype)init { self = [super init]; if (self) { - _architecture = FBArchitectureX86_64; + + _architectures = [[FBArchitectureProcessAdapter hostMachineSupportedArchitectures] allObjects]; _asyncQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0); - _auxillaryDirectory = [NSTemporaryDirectory() stringByAppendingPathComponent:NSProcessInfo.processInfo.globallyUniqueString]; + NSString *explicitTmpDirectory = NSProcessInfo.processInfo.environment[@"IDB_MAC_AUXILLIARY_DIR"]; + if (explicitTmpDirectory) { + _auxillaryDirectory = [[explicitTmpDirectory stringByAppendingPathComponent:@"idb-mac-aux"] stringByAppendingPathComponent:NSProcessInfo.processInfo.globallyUniqueString]; + } else { + _auxillaryDirectory = [[NSTemporaryDirectory() stringByAppendingPathComponent:@"idb-mac-cwd"] stringByAppendingPathComponent:NSProcessInfo.processInfo.globallyUniqueString]; + } _bundleIDToProductMap = [FBMacDevice fetchInstalledApplications]; _bundleIDToRunningTask = @{}.mutableCopy; _udid = [FBMacDevice resolveDeviceUDID]; @@ -78,6 +87,7 @@ - (instancetype)init _workingDirectory = [NSTemporaryDirectory() stringByAppendingPathComponent:NSProcessInfo.processInfo.globallyUniqueString]; _screenInfo = nil; _osVersion = [FBOSVersion genericWithName:FBOSVersionNamemac]; + _name = [[NSHost currentHost] localizedName]; } return self; } @@ -226,7 +236,7 @@ - (nonnull NSString *)consoleString #pragma mark - FBiOSTarget -@synthesize architecture = _architecture; +@synthesize architectures = _architectures; @synthesize asyncQueue = _asyncQueue; @synthesize auxillaryDirectory = _auxillaryDirectory; @synthesize name = _name; @@ -253,25 +263,9 @@ + (nonnull instancetype)commandsWithTarget:(nonnull id)target - (FBFuture *)installApplicationWithPath:(NSString *)path { NSError *error; - NSFileManager *fm = [NSFileManager defaultManager]; - if (![fm fileExistsAtPath:FBMacDevice.applicationInstallDirectory]) { - if (![fm createDirectoryAtPath:FBMacDevice.applicationInstallDirectory withIntermediateDirectories:YES attributes:nil error:&error]) { - return [FBFuture futureWithResult:error]; - } - } - - NSString *dest = [FBMacDevice.applicationInstallDirectory stringByAppendingPathComponent:path.lastPathComponent]; - if ([fm fileExistsAtPath:dest]) { - if (![fm removeItemAtPath:dest error:&error]) { - return [FBFuture futureWithResult:error]; - } - } - if (![fm copyItemAtPath:path toPath:dest error:&error]) { - return [FBFuture futureWithResult:error]; - } - FBBundleDescriptor *bundle = [FBBundleDescriptor bundleFromPath:dest error:&error]; + FBBundleDescriptor *bundle = [FBBundleDescriptor bundleFromPath:path error:&error]; if (error) { - return [FBFuture futureWithResult:error]; + return [FBFuture futureWithError:error]; } self.bundleIDToProductMap[bundle.identifier] = bundle; return [FBFuture futureWithResult:[FBInstalledApplication installedApplicationWithBundle:bundle installType:FBApplicationInstallTypeUnknown dataContainer:nil]]; @@ -285,9 +279,14 @@ + (nonnull instancetype)commandsWithTarget:(nonnull id)target describeFormat:@"Application with bundleID (%@) was not installed by XCTestBootstrap", bundleID] failFuture]; } + + if (![[NSFileManager defaultManager] fileExistsAtPath:bundle.path]) { + return [FBFuture futureWithResult:[NSNull null]]; + } + NSError *error; if (![[NSFileManager defaultManager] removeItemAtPath:bundle.path error:&error]) { - return [FBFuture futureWithResult:error]; + return [FBFuture futureWithError:error]; } [self.bundleIDToProductMap removeObjectForKey:bundleID]; return [FBFuture futureWithResult:[NSNull null]]; @@ -332,7 +331,7 @@ + (nonnull instancetype)commandsWithTarget:(nonnull id)target return [FBFuture futureWithResult:[NSNull null]]; } -- (FBFuture *)launchApplication:(FBApplicationLaunchConfiguration *)configuration +- (FBFuture *)launchApplication:(FBApplicationLaunchConfiguration *)configuration { FBBundleDescriptor *bundle = self.bundleIDToProductMap[configuration.bundleID]; if (!bundle) { @@ -345,10 +344,14 @@ + (nonnull instancetype)commandsWithTarget:(nonnull id)target withArguments:configuration.arguments] withEnvironment:configuration.environment] start] - onQueue:self.workQueue map:^ FBProcess * (FBProcess *task) { + onQueue:self.workQueue map:^ FBMacLaunchedApplication* (FBProcess *task) { self.bundleIDToRunningTask[bundle.identifier] = task; - return task; - }]; + return [[FBMacLaunchedApplication alloc] + initWithBundleID:bundle.identifier + processIdentifier:task.processIdentifier + device:self + queue:self.workQueue]; + }]; } - (nonnull FBFuture *> *)runningApplications @@ -393,6 +396,16 @@ - (NSString *)customDeviceSetPath return nil; } +- (FBFuture *)resolveState:(FBiOSTargetState)state +{ + return FBiOSTargetResolveState(self, state); +} + +- (FBFuture *)resolveLeavesState:(FBiOSTargetState)state +{ + return FBiOSTargetResolveLeavesState(self, state); +} + - (NSDictionary *)replacementMapping { return NSDictionary.dictionary; @@ -423,13 +436,20 @@ - (NSString *)customDeviceSetPath - (FBFuture *> *)listTestsForBundleAtPath:(NSString *)bundlePath timeout:(NSTimeInterval)timeout withAppAtPath:(NSString *)appPath { + NSError *error = nil; + FBBundleDescriptor *bundleDescriptor = [FBBundleDescriptor bundleWithFallbackIdentifierFromPath:bundlePath error:&error]; + if (!bundleDescriptor) { + return [FBFuture futureWithError:error]; + } + FBListTestConfiguration *configuration = [FBListTestConfiguration configurationWithEnvironment:@{} workingDirectory:self.auxillaryDirectory testBundlePath:bundlePath runnerAppPath:appPath waitForDebugger:NO - timeout:timeout]; + timeout:timeout + architectures:bundleDescriptor.binary.architectures]; return [[[FBListTestStrategy alloc] initWithTarget:self diff --git a/XCTestBootstrap/MacStrategies/FBMacLaunchedApplication.h b/XCTestBootstrap/MacStrategies/FBMacLaunchedApplication.h new file mode 100644 index 000000000..9e530bb8d --- /dev/null +++ b/XCTestBootstrap/MacStrategies/FBMacLaunchedApplication.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import + +#import + +NS_ASSUME_NONNULL_BEGIN + +@class FBMacDevice; + +@interface FBMacLaunchedApplication : NSObject + +- (instancetype)initWithBundleID:(NSString *)bundleID + processIdentifier:(pid_t)processIdentifier + device:(FBMacDevice *)device + queue:(dispatch_queue_t)queue; +@end + +NS_ASSUME_NONNULL_END diff --git a/XCTestBootstrap/MacStrategies/FBMacLaunchedApplication.m b/XCTestBootstrap/MacStrategies/FBMacLaunchedApplication.m new file mode 100644 index 000000000..b048168ff --- /dev/null +++ b/XCTestBootstrap/MacStrategies/FBMacLaunchedApplication.m @@ -0,0 +1,46 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import "FBMacLaunchedApplication.h" + +#import "FBMacDevice.h" + +@interface FBMacLaunchedApplication() +@property (nonatomic, strong) FBProcess *process; +@property (nonatomic, weak) FBMacDevice *device; +@property (nonatomic, assign) dispatch_queue_t queue; +@end + +@implementation FBMacLaunchedApplication +@synthesize bundleID = _bundleID; +@synthesize processIdentifier = _processIdentifier; + +- (instancetype)initWithBundleID:(NSString *)bundleID + processIdentifier:(pid_t)processIdentifier + device:(FBMacDevice *)device + queue:(dispatch_queue_t)queue +{ + if (self = [super init]) { + _bundleID = bundleID; + _processIdentifier = processIdentifier; + _device = device; + _queue = queue; + } + return self; +} + +- (FBFuture *)applicationTerminated +{ + NSString *bundleID = self.bundleID; + FBMacDevice *device = self.device; + return [FBMutableFuture.future + onQueue:self.queue respondToCancellation:^ FBFuture *{ + return [device killApplicationWithBundleID:bundleID]; + }]; +} + +@end diff --git a/XCTestBootstrap/Reporters/FBExceptionInfo.h b/XCTestBootstrap/Reporters/FBExceptionInfo.h new file mode 100644 index 000000000..923371648 --- /dev/null +++ b/XCTestBootstrap/Reporters/FBExceptionInfo.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import + +/** + A summary of an exception. + */ +@interface FBExceptionInfo : NSObject + +@property (nonnull, nonatomic, copy, readonly) NSString *message; +@property (nullable, nonatomic, copy, readonly) NSString *file; +@property (nonatomic, assign, readonly) NSUInteger line; + +- (instancetype _Nonnull)initWithMessage:(nonnull NSString *)message file:(nullable NSString *)file line:(NSUInteger)line; + +- (instancetype _Nonnull)initWithMessage:(nonnull NSString *)message; + +@end diff --git a/XCTestBootstrap/Reporters/FBExceptionInfo.m b/XCTestBootstrap/Reporters/FBExceptionInfo.m new file mode 100644 index 000000000..f5e3d2ea3 --- /dev/null +++ b/XCTestBootstrap/Reporters/FBExceptionInfo.m @@ -0,0 +1,49 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + + + +#import "FBExceptionInfo.h" + +@implementation FBExceptionInfo + +- (instancetype)initWithMessage:(NSString *)message file:(NSString *)file line:(NSUInteger)line +{ + self = [super init]; + + if (!self) { + return nil; + } + + _message = message; + _file = file; + _line = line; + + return self; +} + +- (instancetype)initWithMessage:(NSString *)message +{ + self = [super init]; + + if (!self) { + return nil; + } + + _message = message; + _file = nil; + _line = 0; + + return self; +} + +- (NSString *)description +{ + return [NSString stringWithFormat:@"Message %@ | File %@ | Line %lu", self.message, self.file, self.line]; +} + +@end diff --git a/XCTestBootstrap/Reporters/FBJSONTestReporter.h b/XCTestBootstrap/Reporters/FBJSONTestReporter.h index 2bbcfdb0a..916996234 100644 --- a/XCTestBootstrap/Reporters/FBJSONTestReporter.h +++ b/XCTestBootstrap/Reporters/FBJSONTestReporter.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/XCTestBootstrap/Reporters/FBJSONTestReporter.m b/XCTestBootstrap/Reporters/FBJSONTestReporter.m index 61c2d00b8..7d7f7b5ac 100644 --- a/XCTestBootstrap/Reporters/FBJSONTestReporter.m +++ b/XCTestBootstrap/Reporters/FBJSONTestReporter.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -111,10 +111,14 @@ - (void)testCaseDidStartForTestClass:(NSString *)testClass method:(NSString *)me [self printEvent:[FBJSONTestReporter beginTestCaseEvent:testClass testMethod:method]]; } -- (void)testCaseDidFailForTestClass:(NSString *)testClass method:(NSString *)method withMessage:(NSString *)message file:(NSString *)file line:(NSUInteger)line +- (void)testCaseDidFailForTestClass:(NSString *)testClass method:(NSString *)method exceptions:(nonnull NSArray *)exceptions { NSString *xctestName = FBFullyFormattedXCTestName(testClass, method); - [self.xctestNameExceptionsMapping[xctestName] addObject:[FBJSONTestReporter exceptionEvent:message file:file line:line]]; + for (FBExceptionInfo *exception in exceptions) { + [self.xctestNameExceptionsMapping[xctestName] addObject:[FBJSONTestReporter exceptionEvent:exception.message + file:exception.file + line:exception.line]]; + } } - (void)testCaseDidFinishForTestClass:(NSString *)testClass method:(NSString *)method withStatus:(FBTestReportStatus)status duration:(NSTimeInterval)duration logs:(NSArray *)logs diff --git a/XCTestBootstrap/Reporters/FBLogicReporterAdapter.h b/XCTestBootstrap/Reporters/FBLogicReporterAdapter.h index 015990fd2..5c46d3fac 100644 --- a/XCTestBootstrap/Reporters/FBLogicReporterAdapter.h +++ b/XCTestBootstrap/Reporters/FBLogicReporterAdapter.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/XCTestBootstrap/Reporters/FBLogicReporterAdapter.m b/XCTestBootstrap/Reporters/FBLogicReporterAdapter.m index a74b229df..f0a7d2a11 100644 --- a/XCTestBootstrap/Reporters/FBLogicReporterAdapter.m +++ b/XCTestBootstrap/Reporters/FBLogicReporterAdapter.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -71,8 +71,15 @@ - (void)handleEventJSONData:(NSData *)data id reporter = self.reporter; if ([eventName isEqualToString:kReporter_Events_BeginTestSuite]) { NSString *suiteName = JSONEvent[kReporter_BeginTestSuite_SuiteKey]; - NSString *startTime = JSONEvent[kReporter_TimestampKey]; - [reporter testSuite:suiteName didStartAt:startTime]; + id startTime = JSONEvent[kReporter_TimestampKey]; + if ([startTime isKindOfClass:NSNumber.class]) { + [reporter testSuite:suiteName didStartAt:((NSNumber *)startTime).stringValue]; + } else if ([startTime isKindOfClass:NSString.class]) { + [reporter testSuite:suiteName didStartAt:((NSString *)startTime)]; + } else { + NSAssert(NO, @"Unknown type of obj. This will likely cause crash in runtime because of swift signature mismatch"); + } + } else if ([eventName isEqualToString:kReporter_Events_BeginTest]) { NSString *className = JSONEvent[kReporter_BeginTest_ClassNameKey]; NSString *methodName = JSONEvent[kReporter_BeginTest_MethodNameKey]; @@ -121,11 +128,18 @@ - (void)handleEndTest:(NSDictionary *)JSONEvent data:(NSData *)d - (void)reportTestFailureForTestClass:(NSString *)testClass testName:(NSString *)testName endTestEvent:(NSDictionary *)JSONEvent { - NSDictionary *exception = [JSONEvent[kReporter_EndTest_ExceptionsKey] lastObject]; - NSString *message = exception[kReporter_EndTest_Exception_ReasonKey]; - NSString *file = exception[kReporter_EndTest_Exception_FilePathInProjectKey]; - NSUInteger line = [exception[kReporter_EndTest_Exception_LineNumberKey] unsignedIntegerValue]; - [self.reporter testCaseDidFailForTestClass:testClass method:testName withMessage:message file:file line:line]; + NSArray *exceptionDicts = JSONEvent[kReporter_EndTest_ExceptionsKey]; + NSMutableArray *parsedExceptions = [NSMutableArray new]; + + for (NSDictionary *exceptionDict in exceptionDicts) { + NSString *message = exceptionDict[kReporter_EndTest_Exception_ReasonKey]; + NSString *file = exceptionDict[kReporter_EndTest_Exception_FilePathInProjectKey]; + NSUInteger line = [exceptionDict[kReporter_EndTest_Exception_LineNumberKey] unsignedIntegerValue]; + FBExceptionInfo *exception = [[FBExceptionInfo alloc]initWithMessage:message file:file line:line]; + [parsedExceptions addObject:exception]; + } + + [self.reporter testCaseDidFailForTestClass:testClass method:testName exceptions:[parsedExceptions copy]]; } - (void)didCrashDuringTest:(NSError *)error @@ -133,6 +147,7 @@ - (void)didCrashDuringTest:(NSError *)error if ([self.reporter respondsToSelector:@selector(didCrashDuringTest:)]) { [self.reporter didCrashDuringTest:error]; } + [self.reporter processUnderTestDidExit]; } @end diff --git a/XCTestBootstrap/Reporters/FBLogicXCTestReporter.h b/XCTestBootstrap/Reporters/FBLogicXCTestReporter.h index 9b390fb82..4795d9aec 100644 --- a/XCTestBootstrap/Reporters/FBLogicXCTestReporter.h +++ b/XCTestBootstrap/Reporters/FBLogicXCTestReporter.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/XCTestBootstrap/Reporters/FBXCTestReporter.h b/XCTestBootstrap/Reporters/FBXCTestReporter.h index 126b9766f..4e4d7e8fc 100644 --- a/XCTestBootstrap/Reporters/FBXCTestReporter.h +++ b/XCTestBootstrap/Reporters/FBXCTestReporter.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -10,6 +10,8 @@ #import #import #import +#import + NS_ASSUME_NONNULL_BEGIN @@ -66,11 +68,9 @@ NS_ASSUME_NONNULL_BEGIN @param testClass the test class that has failed. @param method the test method that has failed. - @param message the failure message. - @param file the failing file. - @param line the failing line number. + @param exceptions an array of the exceptions that caused the failure. */ -- (void)testCaseDidFailForTestClass:(NSString *)testClass method:(NSString *)method withMessage:(NSString *)message file:(nullable NSString *)file line:(NSUInteger)line; +- (void)testCaseDidFailForTestClass:(NSString *)testClass method:(NSString *)method exceptions:(NSArray *)exceptions; /** Called when a test case has started @@ -102,7 +102,7 @@ NS_ASSUME_NONNULL_BEGIN - (void)handleExternalEvent:(NSString *)event; /** - Called when the results of the test should be written to the output. + Called when the results of the test should be written to the output. Warning! This method is bridged to swift incorrectly and loses bool return type. Adapt and use with extra care @param error an error for an error that occurs. */ diff --git a/XCTestBootstrap/Strategies/FBListTestStrategy.h b/XCTestBootstrap/Strategies/FBListTestStrategy.h index 13447989b..a2f799826 100644 --- a/XCTestBootstrap/Strategies/FBListTestStrategy.h +++ b/XCTestBootstrap/Strategies/FBListTestStrategy.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/XCTestBootstrap/Strategies/FBListTestStrategy.m b/XCTestBootstrap/Strategies/FBListTestStrategy.m index 67b90fedc..cb0fe55a2 100644 --- a/XCTestBootstrap/Strategies/FBListTestStrategy.m +++ b/XCTestBootstrap/Strategies/FBListTestStrategy.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -112,29 +112,33 @@ - (instancetype)initWithTarget:(id * (NSArray *libraries){ + return [[[FBTemporaryDirectory temporaryDirectoryWithLogger:self.logger] withTemporaryDirectory] + onQueue:self.target.workQueue pop:^FBFuture *(NSURL *temporaryDirectory) { + return [[FBOToolDynamicLibs + findFullPathForSanitiserDyldInBundle:self.configuration.testBundlePath onQueue:self.target.workQueue] + onQueue:self.target.workQueue fmap:^FBFuture * (NSArray *libraries){ NSDictionary *environment = [FBListTestStrategy setupEnvironmentWithDylibs:libraries shimPath:shimPath shimOutputFilePath:shimOutput.filePath bundlePath:self.configuration.testBundlePath]; - + return [[FBListTestStrategy - listTestProcessWithTarget:self.target - configuration:self.configuration - xctestPath:self.target.xctestPath - environment:environment - stdOutConsumer:stdOutConsumer - stdErrConsumer:stdErrConsumer - logger:self.logger] - onQueue:self.target.workQueue fmap:^(FBFuture *exitCode) { - return [FBListTestStrategy - launchedProcessWithExitCode:exitCode - shimOutput:shimOutput - shimBuffer:shimBuffer - stdOutBuffer:stdOutBuffer - stdErrBuffer:stdErrBuffer - queue:self.target.workQueue]; - }]; + listTestProcessWithTarget:self.target + configuration:self.configuration + xctestPath:self.target.xctestPath + environment:environment + stdOutConsumer:stdOutConsumer + stdErrConsumer:stdErrConsumer + logger:self.logger + temporaryDirectory:temporaryDirectory] + onQueue:self.target.workQueue fmap:^(FBFuture *exitCode) { + return [FBListTestStrategy + launchedProcessWithExitCode:exitCode + shimOutput:shimOutput + shimBuffer:shimBuffer + stdOutBuffer:stdOutBuffer + stdErrBuffer:stdErrBuffer + queue:self.target.workQueue]; + }]; }]; + }]; } + (NSDictionary *)setupEnvironmentWithDylibs:(NSArray *)libraries shimPath:(NSString *)shimPath shimOutputFilePath:(NSString *)shimOutputFilePath bundlePath:(NSString *)bundlePath @@ -202,11 +206,13 @@ - (instancetype)initWithTarget:(id *> *)listTestProcessWithTarget:(id)target configuration:(FBListTestConfiguration *)configuration xctestPath:(NSString *)xctestPath environment:(NSDictionary *)environment stdOutConsumer:(id)stdOutConsumer stdErrConsumer:(id)stdErrConsumer logger:(id)logger ++ (FBFuture *> *)listTestProcessWithTarget:(id)target configuration:(FBListTestConfiguration *)configuration xctestPath:(NSString *)xctestPath environment:(NSDictionary *)environment stdOutConsumer:(id)stdOutConsumer stdErrConsumer:(id)stdErrConsumer logger:(id)logger temporaryDirectory: (NSURL *)temporaryDirectory { NSString *launchPath = xctestPath; NSTimeInterval timeout = configuration.testTimeout; + + FBProcessIO *io = [[FBProcessIO alloc] initWithStdIn:nil stdOut:[FBProcessOutput outputForDataConsumer:stdOutConsumer] stdErr:[FBProcessOutput outputForDataConsumer:stdErrConsumer]]; // List test for app test bundle, so we use app binary instead of xctest to load test bundle. if ([FBBundleDescriptor isApplicationAtPath:configuration.runnerAppPath]) { // Since we're loading the test bundle in app binary's process without booting a simulator, @@ -232,16 +238,27 @@ - (instancetype)initWithTarget:(id *> *)listTestProcessWithSpawnConfiguration:(FBProcessSpawnConfiguration *)spawnConfiguration onTarget:(id)target timeout:(NSTimeInterval )timeout logger:(id)logger +{ + return [[target launchProcess:spawnConfiguration] onQueue:target.workQueue map:^id _Nonnull(FBProcess * _Nonnull process) { + return [FBXCTestProcess ensureProcess:process completesWithin:timeout crashLogCommands:nil queue:target.workQueue logger:logger]; + }]; } - (id)wrapInReporter:(id)reporter diff --git a/XCTestBootstrap/Strategies/FBLogicTestRunStrategy.h b/XCTestBootstrap/Strategies/FBLogicTestRunStrategy.h index ab5408d1b..d17f10369 100644 --- a/XCTestBootstrap/Strategies/FBLogicTestRunStrategy.h +++ b/XCTestBootstrap/Strategies/FBLogicTestRunStrategy.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/XCTestBootstrap/Strategies/FBLogicTestRunStrategy.m b/XCTestBootstrap/Strategies/FBLogicTestRunStrategy.m index fb5d80e6c..14728bff8 100644 --- a/XCTestBootstrap/Strategies/FBLogicTestRunStrategy.m +++ b/XCTestBootstrap/Strategies/FBLogicTestRunStrategy.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -112,28 +112,30 @@ - (instancetype)initWithTarget:(id *arguments = @[@"-XCTest", testSpecifier, self.configuration.testBundlePath]; - return [[FBOToolDynamicLibs - findFullPathForSanitiserDyldInBundle:self.configuration.testBundlePath onQueue:self.target.workQueue] - onQueue:self.target.workQueue fmap:^FBFuture * (NSArray *libraries) { + return [[[FBTemporaryDirectory temporaryDirectoryWithLogger:self.logger] withTemporaryDirectory] + onQueue:self.target.workQueue pop:^FBFuture *(NSURL *temporaryDirectory) { + return [[FBOToolDynamicLibs + findFullPathForSanitiserDyldInBundle:self.configuration.testBundlePath onQueue:self.target.workQueue] + onQueue:self.target.workQueue fmap:^FBFuture * (NSArray *libraries) { NSDictionary *environment = [FBLogicTestRunStrategy - setupEnvironmentWithDylibs:self.configuration.processUnderTestEnvironment - withLibraries:libraries - shimOutputFilePath:outputs.shimOutput.filePath - shimPath:shimPath - bundlePath:self.configuration.testBundlePath - coverageDirectoryPath:self.configuration.coverageConfiguration.coverageDirectory - logDirectoryPath:self.configuration.logDirectoryPath - waitForDebugger:self.configuration.waitForDebugger]; - + setupEnvironmentWithDylibs:self.configuration.processUnderTestEnvironment + withLibraries:libraries + shimOutputFilePath:outputs.shimOutput.filePath + shimPath:shimPath + bundlePath:self.configuration.testBundlePath + coverageConfiguration:self.configuration.coverageConfiguration + logDirectoryPath:self.configuration.logDirectoryPath + waitForDebugger:self.configuration.waitForDebugger]; return [[self - startTestProcessWithLaunchPath:launchPath arguments:arguments environment:environment outputs:outputs] - onQueue:self.target.workQueue fmap:^(FBFuture *exitCode) { - return [self completeLaunchedProcess:exitCode outputs:outputs]; - }]; + startTestProcessWithLaunchPath:launchPath arguments:arguments environment:environment outputs:outputs temporaryDirectory:temporaryDirectory] + onQueue:self.target.workQueue fmap:^(FBFuture *exitCode) { + return [self completeLaunchedProcess:exitCode outputs:outputs]; + }]; }]; + }]; } -+ (NSDictionary *)setupEnvironmentWithDylibs:(NSDictionary *)environment withLibraries:(NSArray *)libraries shimOutputFilePath:(NSString *)shimOutputFilePath shimPath:(NSString *)shimPath bundlePath:(NSString *)bundlePath coverageDirectoryPath:(nullable NSString *)coverageDirectoryPath logDirectoryPath:(nullable NSString *)logDirectoryPath waitForDebugger:(BOOL)waitForDebugger ++ (NSDictionary *)setupEnvironmentWithDylibs:(NSDictionary *)environment withLibraries:(NSArray *)libraries shimOutputFilePath:(NSString *)shimOutputFilePath shimPath:(NSString *)shimPath bundlePath:(NSString *)bundlePath coverageConfiguration:(nullable FBCodeCoverageConfiguration *)coverageConfiguration logDirectoryPath:(nullable NSString *)logDirectoryPath waitForDebugger:(BOOL)waitForDebugger { NSMutableArray *librariesWithShim = [NSMutableArray arrayWithObject:shimPath]; [librariesWithShim addObjectsFromArray:libraries]; @@ -144,9 +146,10 @@ - (instancetype)initWithTarget:(id *(){ - siginfo_t sig_info; - if (waitid(P_PID, (id_t)processIdentifier, &sig_info, WSTOPPED) != 0) { - return [[XCTestBootstrapError - describeFormat:@"Failed to wait test process (pid %d) to receive a SIGSTOP: '%s'", processIdentifier, strerror(errno)] - failFuture]; - } - [reporter processWaitingForDebuggerWithProcessIdentifier:processIdentifier]; - return FBFuture.empty; - }]; + + return [[FBProcessFetcher waitStopSignalForProcess:processIdentifier] onQueue:waitQueue chain:^FBFuture *(FBFuture *future) { + if (future.error){ + return [[XCTestBootstrapError + describeFormat:@"Failed to wait test process (pid %d) to receive a SIGSTOP: '%@'", processIdentifier, future.error.localizedDescription] + failFuture]; + } + [reporter processWaitingForDebuggerWithProcessIdentifier:processIdentifier]; + return FBFuture.empty; + }]; } - (FBFuture *)buildOutputsForUUID:(NSUUID *)udid @@ -286,9 +286,9 @@ - (instancetype)initWithTarget:(id> *shimFuture = [FBFuture futureWithResult:shimConsumer]; if (mirrorToFiles) { FBXCTestLogger *mirrorLogger = self.configuration.logDirectoryPath ? [FBXCTestLogger defaultLoggerInDirectory:self.configuration.logDirectoryPath] : [FBXCTestLogger defaultLoggerInDefaultDirectory]; - stdOutFuture = [mirrorLogger logConsumptionToFile:stdOutConsumer outputKind:@"out" udid:udid logger:logger]; - stdErrFuture = [mirrorLogger logConsumptionToFile:stdErrConsumer outputKind:@"err" udid:udid logger:logger]; - shimFuture = [mirrorLogger logConsumptionToFile:shimConsumer outputKind:@"shim" udid:udid logger:logger]; + stdOutFuture = [mirrorLogger logConsumptionOf:stdOutConsumer toFileNamed:@"test_process_stdout.out" logger:logger]; + stdErrFuture = [mirrorLogger logConsumptionOf:stdErrConsumer toFileNamed:@"test_process_stderr.err" logger:logger]; + shimFuture = [mirrorLogger logConsumptionOf:shimConsumer toFileNamed:@"shimulator_logs.shim" logger:logger]; } return [[FBFuture futureWithFutures:@[ @@ -304,7 +304,7 @@ - (instancetype)initWithTarget:(id *> *)startTestProcessWithLaunchPath:(NSString *)launchPath arguments:(NSArray *)arguments environment:(NSDictionary *)environment outputs:(FBLogicTestRunOutputs *)outputs +- (FBFuture *> *)startTestProcessWithLaunchPath:(NSString *)launchPath arguments:(NSArray *)arguments environment:(NSDictionary *)environment outputs:(FBLogicTestRunOutputs *)outputs temporaryDirectory:(NSURL *)temporaryDirectory { dispatch_queue_t queue = self.target.workQueue; id logger = self.logger; @@ -317,17 +317,20 @@ - (instancetype)initWithTarget:(id * (FBProcess *process) { - return [[FBLogicTestRunStrategy - fromQueue:queue reportWaitForDebugger:self.configuration.waitForDebugger forProcessIdentifier:process.processIdentifier reporter:reporter] - onQueue:queue fmap:^(id _) { - return [FBXCTestProcess ensureProcess:process completesWithin:timeout crashLogCommands:self.target queue:queue logger:logger]; - }]; + FBProcessSpawnConfiguration *configuration = [[FBProcessSpawnConfiguration alloc] initWithLaunchPath:launchPath arguments:arguments environment:environment io:io mode:FBProcessSpawnModePosixSpawn]; + FBArchitectureProcessAdapter *adapter = [[FBArchitectureProcessAdapter alloc] init]; + + // Note process adapter may change process configuration launch binary path if it decided to isolate desired arch. + // For more information look at `FBArchitectureProcessAdapter` docs. + return [[[adapter adaptProcessConfiguration:configuration toAnyArchitectureIn:self.configuration.architectures queue:queue temporaryDirectory:temporaryDirectory] + onQueue:queue fmap:^FBFuture *(FBProcessSpawnConfiguration *mappedConfiguration) { + return [self.target launchProcess:mappedConfiguration]; + }] + onQueue:queue map:^ FBFuture * (FBProcess *process) { + return [[FBLogicTestRunStrategy fromQueue:queue reportWaitForDebugger:self.configuration.waitForDebugger forProcessIdentifier:process.processIdentifier reporter:reporter] onQueue:queue fmap:^(id _) { + return [FBXCTestProcess ensureProcess:process completesWithin:timeout crashLogCommands:self.target queue:queue logger:logger]; }]; + }]; } @end diff --git a/XCTestBootstrap/Strategies/FBManagedTestRunStrategy.h b/XCTestBootstrap/Strategies/FBManagedTestRunStrategy.h index e88465fa0..6c4e3f044 100644 --- a/XCTestBootstrap/Strategies/FBManagedTestRunStrategy.h +++ b/XCTestBootstrap/Strategies/FBManagedTestRunStrategy.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/XCTestBootstrap/Strategies/FBManagedTestRunStrategy.m b/XCTestBootstrap/Strategies/FBManagedTestRunStrategy.m index a4dc409ec..322e9fced 100644 --- a/XCTestBootstrap/Strategies/FBManagedTestRunStrategy.m +++ b/XCTestBootstrap/Strategies/FBManagedTestRunStrategy.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -43,7 +43,8 @@ @implementation FBManagedTestRunStrategy initWithSessionIdentifier:runnerConfiguration.sessionIdentifier timeout:configuration.timeout testHostLaunchConfiguration:testHostLaunchConfiguration - testedApplicationAdditionalEnvironment:runnerConfiguration.testedApplicationAdditionalEnvironment]; + testedApplicationAdditionalEnvironment:runnerConfiguration.testedApplicationAdditionalEnvironment + testConfiguration:runnerConfiguration.testConfiguration]; // Construct and run the mediator, the core of the test execution. return [FBTestManagerAPIMediator diff --git a/XCTestBootstrap/Strategies/FBXCTestProcess.h b/XCTestBootstrap/Strategies/FBXCTestProcess.h index 52e8a3cb9..014242a00 100644 --- a/XCTestBootstrap/Strategies/FBXCTestProcess.h +++ b/XCTestBootstrap/Strategies/FBXCTestProcess.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -43,18 +43,6 @@ NS_ASSUME_NONNULL_BEGIN */ + (nullable NSString *)describeFailingExitCode:(int)exitCode; -/** - Performs a stackshot on the provided process id. - Does not terminate the process after performing the stackshot. - Returns a future in the error state, with the stackshot in the error message. - - @param processIdentifier the process identifier of the process to stackshot. - @param timeout the original timeout that prompted this call. - @param queue the queue to use. - @param logger the logger to use. - */ -+ (FBFuture *)performSampleStackshotOnProcessIdentifier:(pid_t)processIdentifier forTimeout:(NSTimeInterval)timeout queue:(dispatch_queue_t)queue logger:(id)logger; - @end NS_ASSUME_NONNULL_END diff --git a/XCTestBootstrap/Strategies/FBXCTestProcess.m b/XCTestBootstrap/Strategies/FBXCTestProcess.m index 327e1a74c..dc25b1a04 100644 --- a/XCTestBootstrap/Strategies/FBXCTestProcess.m +++ b/XCTestBootstrap/Strategies/FBXCTestProcess.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -16,7 +16,6 @@ static NSTimeInterval const CrashLogStartDateFuzz = -20; static NSTimeInterval const CrashLogWaitTime = 180; // In case resources are pegged, just wait -static NSTimeInterval const SampleDuration = 1; static NSTimeInterval const KillBackoffTimeout = 1; @implementation FBXCTestProcess @@ -73,32 +72,17 @@ + (nullable NSString *)describeFailingExitCode:(int)exitCode } } -+ (FBFuture *)performSampleStackshotOnProcessIdentifier:(pid_t)processIdentifier forTimeout:(NSTimeInterval)timeout queue:(dispatch_queue_t)queue logger:(id)logger -{ - [logger logFormat:@"Performing stackshot on process %d as it has not exited after %f seconds", processIdentifier, timeout]; - return [[[[FBProcessBuilder - withLaunchPath:@"/usr/bin/sample" arguments:@[@(processIdentifier).stringValue, @(SampleDuration).stringValue]] - runUntilCompletionWithAcceptableExitCodes:nil] - onQueue:queue handleError:^(NSError *error) { - return [[[FBXCTestError - describeFormat:@"Failed to obtain a stack sample of stalled xctest process %d", processIdentifier] - causedBy:error] - failFuture]; - }] - onQueue:queue fmap:^(FBProcess *task) { - [logger logFormat:@"Stackshot completed of process %d", processIdentifier]; - return [[FBXCTestError - describeFormat:@"Waited %f seconds for process %d to terminate, but the xctest process stalled: %@", timeout, processIdentifier, task.stdOut] - failFuture]; - }]; -} - #pragma mark Private + (FBFuture *)performSampleStackshotOnProcess:(FBProcess *)process forTimeout:(NSTimeInterval)timeout queue:(dispatch_queue_t)queue logger:(id)logger { - return [[self - performSampleStackshotOnProcessIdentifier:process.processIdentifier forTimeout:timeout queue:queue logger:logger] + return [[[FBProcessFetcher + performSampleStackshotForProcessIdentifier:process.processIdentifier queue:queue] + onQueue:queue fmap:^FBFuture *(NSString *stackshot) { + return [[FBXCTestError + describeFormat:@"Waited %f seconds for process %d to terminate, but the xctest process stalled: %@", timeout, process.processIdentifier, stackshot] + failFuture]; + }] onQueue:queue notifyOfCompletion:^(FBFuture *_) { [logger logFormat:@"Terminating stalled xctest process %@", process]; [[process @@ -116,9 +100,8 @@ + (nullable NSString *)describeFailingExitCode:(int)exitCode crashLogsForTerminationOfProcess:process since:startDate crashLogCommands:crashLogCommands crashLogWaitTime:crashLogWaitTime queue:queue] rephraseFailure:@"xctest process (%d) exited abnormally with no crash log, to check for yourself look in ~/Library/Logs/DiagnosticReports", process.processIdentifier] onQueue:queue fmap:^(FBCrashLogInfo *crashInfo) { - NSString *crashString = [NSString stringWithContentsOfFile:crashInfo.crashPath encoding:NSUTF8StringEncoding error:nil]; return [[FBXCTestError - describeFormat:@"xctest process crashed\n %@", crashString] + describeFormat:@"xctest process crashed\n%@\n\nRaw Crash File Contents\n%@", crashInfo, [crashInfo loadRawCrashLogStringWithError:nil]] failFuture]; }]; } diff --git a/XCTestBootstrap/TestManager/FBActivityRecord.h b/XCTestBootstrap/TestManager/FBActivityRecord.h index 899b84987..d70fa62d8 100644 --- a/XCTestBootstrap/TestManager/FBActivityRecord.h +++ b/XCTestBootstrap/TestManager/FBActivityRecord.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/XCTestBootstrap/TestManager/FBActivityRecord.m b/XCTestBootstrap/TestManager/FBActivityRecord.m index 78133b862..884437a06 100644 --- a/XCTestBootstrap/TestManager/FBActivityRecord.m +++ b/XCTestBootstrap/TestManager/FBActivityRecord.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -7,7 +7,7 @@ #import "FBActivityRecord.h" #import "FBAttachment.h" -#import +#import @implementation FBActivityRecord diff --git a/XCTestBootstrap/TestManager/FBAttachment.h b/XCTestBootstrap/TestManager/FBAttachment.h index c8328a6d0..00be39863 100644 --- a/XCTestBootstrap/TestManager/FBAttachment.h +++ b/XCTestBootstrap/TestManager/FBAttachment.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -17,6 +17,7 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, copy, readonly) NSDate *timestamp; @property (nonatomic, copy, readonly) NSString *name; @property (nonatomic, copy, readonly) NSString *uniformTypeIdentifier; +@property (nonatomic, copy, readonly, nullable) NSDictionary *userInfo; /** Constructs a attachment from a XCTAttachment diff --git a/XCTestBootstrap/TestManager/FBAttachment.m b/XCTestBootstrap/TestManager/FBAttachment.m index 8105efae7..99bea194e 100644 --- a/XCTestBootstrap/TestManager/FBAttachment.m +++ b/XCTestBootstrap/TestManager/FBAttachment.m @@ -1,12 +1,12 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #import "FBAttachment.h" -#import +#import @implementation FBAttachment @@ -27,6 +27,7 @@ - (instancetype)initFromAttachment:(XCTAttachment *)attachment _timestamp = attachment.timestamp; _name = attachment.name; _uniformTypeIdentifier = attachment.uniformTypeIdentifier; + _userInfo = attachment.userInfo; return self; } diff --git a/XCTestBootstrap/TestManager/FBTestBundleConnection.h b/XCTestBootstrap/TestManager/FBTestBundleConnection.h index 4d116a9d6..5b836d3b6 100644 --- a/XCTestBootstrap/TestManager/FBTestBundleConnection.h +++ b/XCTestBootstrap/TestManager/FBTestBundleConnection.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -14,6 +14,7 @@ NS_ASSUME_NONNULL_BEGIN @class FBTestManagerContext; @protocol XCTestManager_IDEInterface; +@protocol XCTMessagingChannel_RunnerToIDE; /** A Strategy for Connecting. @@ -33,7 +34,7 @@ NS_ASSUME_NONNULL_BEGIN @param logger the Logger to Log to. @return a Future that resolves successfully when the test plan has completed. */ -+ (FBFuture *)connectAndRunBundleToCompletionWithContext:(FBTestManagerContext *)context target:(id)target interface:(id)interface testHostApplication:(id)testHostApplication requestQueue:(dispatch_queue_t)requestQueue logger:(nullable id)logger; ++ (FBFuture *)connectAndRunBundleToCompletionWithContext:(FBTestManagerContext *)context target:(id)target interface:(id)interface testHostApplication:(id)testHostApplication requestQueue:(dispatch_queue_t)requestQueue logger:(nullable id)logger; @end diff --git a/XCTestBootstrap/TestManager/FBTestBundleConnection.m b/XCTestBootstrap/TestManager/FBTestBundleConnection.m index f7cdc9b80..647d9a59c 100644 --- a/XCTestBootstrap/TestManager/FBTestBundleConnection.m +++ b/XCTestBootstrap/TestManager/FBTestBundleConnection.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -7,9 +7,18 @@ #import "FBTestBundleConnection.h" -#import -#import -#import +#import +#import +#import + +// Protocol for RPC with testmanagerd daemon +#import +#import + +// Protocol for RPC with XCTest runner (within the host app process) +#import +#import + #import #import @@ -17,6 +26,9 @@ #import #import +#import +#import + #import #import @@ -24,21 +36,25 @@ #import "XCTestBootstrapError.h" #import "FBTestManagerContext.h" #import "FBTestManagerAPIMediator.h" +#import "FBTestConfiguration.h" + +static const NSInteger FBProtocolVersion = 36; +static const NSInteger FBProtocolMinimumVersion = 0x8; -static NSTimeInterval BundleReadyTimeout = 20; // Time for `_XCT_testBundleReadyWithProtocolVersion` to be called after the 'connect'. -static NSTimeInterval IDEInterfaceReadyTimeout = 10; // Time for `XCTestManager_IDEInterface` to be returned. -static NSTimeInterval DaemonSessionReadyTimeout = 10; // Time for `_IDE_initiateSessionWithIdentifier` to be returned. -static NSTimeInterval CrashCheckWaitLimit = 30; // Time to wait for crash report to be generated. +static NSTimeInterval BundleReadyTimeout = 60; // Time for `_XCT_testBundleReadyWithProtocolVersion` to be called after the 'connect'. +static NSTimeInterval IDEInterfaceReadyTimeout = 60; // Time for `XCTestManager_IDEInterface` to be returned. +static NSTimeInterval DaemonSessionReadyTimeout = 60; // Time for `_IDE_initiateSessionWithIdentifier` to be returned. +static NSTimeInterval CrashCheckWaitLimit = 120; // Time to wait for crash report to be generated. #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wprotocol" #pragma clang diagnostic ignored "-Wincomplete-implementation" -@interface FBTestBundleConnection () +@interface FBTestBundleConnection () @property (nonatomic, strong, readonly) FBTestManagerContext *context; @property (nonatomic, strong, readonly) id target; -@property (nonatomic, strong, readonly) id interface; +@property (nonatomic, strong, readonly) id interface; @property (nonatomic, strong, readonly) id testHostApplication; @property (nonatomic, strong, readonly) dispatch_queue_t requestQueue; @property (nonatomic, strong, nullable, readonly) id logger; @@ -75,7 +91,7 @@ + (NSString *)clientProcessDisplayPath return _clientProcessDisplayPath; } -- (instancetype)initWithWithContext:(FBTestManagerContext *)context target:(id)target interface:(id)interface testHostApplication:(id)testHostApplication requestQueue:(dispatch_queue_t)requestQueue logger:(nullable id)logger +- (instancetype)initWithWithContext:(FBTestManagerContext *)context target:(id)target interface:(id)interface testHostApplication:(id)testHostApplication requestQueue:(dispatch_queue_t)requestQueue logger:(nullable id)logger { self = [super init]; if (!self) { @@ -119,7 +135,7 @@ - (void)forwardInvocation:(NSInvocation *)invocation #pragma mark Public -+ (FBFuture *)connectAndRunBundleToCompletionWithContext:(FBTestManagerContext *)context target:(id)target interface:(id)interface testHostApplication:(id)testHostApplication requestQueue:(dispatch_queue_t)requestQueue logger:(nullable id)logger ++ (FBFuture *)connectAndRunBundleToCompletionWithContext:(FBTestManagerContext *)context target:(id)target interface:(id)interface testHostApplication:(id)testHostApplication requestQueue:(dispatch_queue_t)requestQueue logger:(nullable id)logger { FBTestBundleConnection *connection = [[self alloc] initWithWithContext:context target:target interface:interface testHostApplication:testHostApplication requestQueue:requestQueue logger:logger]; return [connection connectAndRunToCompletion]; @@ -138,10 +154,10 @@ - (void)forwardInvocation:(NSInvocation *)invocation processIDWithBundleID:self.context.testHostLaunchConfiguration.bundleID] onQueue:self.requestQueue handleError:^FBFuture *(NSError *pidLookupError) { NSString *msg = @"Error while establishing connection to test bundle: " - @"Could not find process for test host application. " - @"The host application is likely to have crashed during startup."; + @"The host application is likely to have crashed during startup, " + @"but could not find a crash log."; // In this case the application lived long enough to avoid a relaunch (see bellow), but crashed before idb could connect to it. - return [[[FBXCTestError describe:msg] causedBy:pidLookupError] failFuture]; + return [self failedFutureWithCrashLogOrNotFoundErrorDescription:msg]; }] onQueue:self.requestQueue fmap:^FBFuture *(NSNumber *runningPid) { if (self.testHostApplication.processIdentifier != runningPid.intValue) { @@ -153,8 +169,21 @@ - (void)forwardInvocation:(NSInvocation *)invocation // idb can't work with this 'vanilla' app process, resulting in errors connecting to the bundle (there won't be a bundle to connect to). return [[[FBXCTestError describe:msg] causedBy:error] failFuture]; } - // No obvious issue with the process, returning the original error - return [FBFuture futureWithError:error]; + + // Application process still running. + // Try to sample process stack. + return [[[FBProcessFetcher + performSampleStackshotForProcessIdentifier:self.testHostApplication.processIdentifier + queue:self.target.workQueue] + onQueue:self.requestQueue handleError:^FBFuture *(NSError *_) { + // Could not sample stack, returning original error + return [FBFuture futureWithError:error]; + }] + onQueue:self.requestQueue fmap:^FBFuture *(NSString *stackshot) { + return [[FBXCTestError + describeFormat:@"Could not connect to test bundle, but host application process %d is still alive and busy/stalled: %@", self.testHostApplication.processIdentifier, stackshot] + failFuture]; + }]; }]; } @@ -183,13 +212,13 @@ - (void)forwardInvocation:(NSInvocation *)invocation testBundleProxy = results[0]; return [self.bundleReadyFuture timeout:BundleReadyTimeout waitingFor:@"Bundle Ready to be called"]; }] + onQueue:self.requestQueue handleError:^(NSError *error) { + return [self performDiagnosisOnBundleConnectionError:error]; + }] onQueue:self.requestQueue pop:^(id result) { [self.logger logFormat:@"Starting Execution of the test plan w/ version %ld", FBProtocolVersion]; [testBundleProxy _IDE_startExecutingTestPlanWithProtocolVersion:@(FBProtocolVersion)]; return self.bundleDisconnectedSuccessfully; - }] - onQueue:self.requestQueue handleError:^(NSError *error) { - return [self performDiagnosisOnBundleConnectionError:error]; }]; } @@ -233,8 +262,8 @@ - (void)forwardInvocation:(NSInvocation *)invocation [self.logger logFormat:@"Listening for proxy connection request from the test bundle (all platforms)"]; [connection - handleProxyRequestForInterface:@protocol(XCTestManager_IDEInterface) - peerInterface:@protocol(XCTestDriverInterface) + xct_handleProxyRequestForInterface:@protocol(XCTMessagingChannel_RunnerToIDE) + peerInterface:@protocol(XCTMessagingChannel_IDEToRunner) handler:^(DTXProxyChannel *channel){ [self.logger logFormat:@"Got proxy channel request from test bundle"]; [channel setExportedObject:self queue:self.target.workQueue]; @@ -251,8 +280,9 @@ - (void)forwardInvocation:(NSInvocation *)invocation { [self.logger log:@"Checking test manager availability..."]; DTXProxyChannel *proxyChannel = [connection - makeProxyChannelWithRemoteInterface:@protocol(XCTestManager_DaemonConnectionInterface) - exportedInterface:@protocol(XCTestManager_IDEInterface)]; + xct_makeProxyChannelWithRemoteInterface:@protocol(XCTMessagingChannel_IDEToDaemon) + exportedInterface:@protocol(XCTMessagingChannel_DaemonToIDE)]; + [proxyChannel xct_setAllowedClassesForTestingProtocols]; [proxyChannel setExportedObject:self queue:self.target.workQueue]; id remoteProxy = (id) proxyChannel.remoteObjectProxy; @@ -272,9 +302,10 @@ - (void)forwardInvocation:(NSInvocation *)invocation if (error) { [self.logger logFormat:@"testmanagerd did %@ failed: %@", sessionStartMethod, error]; [future resolveWithError:error]; + return; } + [self.logger logFormat:@"testmanagerd handled session request using protocol version requested=%ld received=%ld", FBProtocolVersion, version.longValue]; [future resolveWithResult:version]; - [self.logger logFormat:@"testmanagerd handled session request using protcol version %ld.", (long)FBProtocolVersion]; }]; return [future timeout:DaemonSessionReadyTimeout waitingFor:@"%@ to be resolved", sessionStartMethod]; @@ -290,23 +321,29 @@ - (void)forwardInvocation:(NSInvocation *)invocation return FBFuture.empty; } [self.logger logFormat:@"Bundle disconnected, but test plan has not completed. This could mean a crash has occured"]; - return [[self - findCrashedProcessLog] - onQueue:self.target.workQueue chain:^ FBFuture * (FBFuture *future) { - FBCrashLog *crashLog = future.result; - if (!crashLog) { - return [[[XCTestBootstrapError - describeFormat:@"Lost connection to test process, but could not find a crash log"] - code:XCTestBootstrapErrorCodeLostConnection] - failFuture]; - } - return [[XCTestBootstrapError - describeFormat:@"Test Bundle Crashed: %@", crashLog] - failFuture]; - }]; + return [self + failedFutureWithCrashLogOrNotFoundErrorDescription:@"Lost connection to test process, but could not find a crash log"]; }]; } +- (FBFuture *)failedFutureWithCrashLogOrNotFoundErrorDescription:(NSString *)notFoundErrorDescription +{ + return [[[self + findCrashedProcessLog] + onQueue:self.target.workQueue chain:^ FBFuture * (FBFuture *future) { + FBCrashLog *crashLog = future.result; + if (!crashLog) { + return [[[FBXCTestError + describe:notFoundErrorDescription] + code:XCTestBootstrapErrorCodeLostConnection] + failFuture]; + } + return [[FBXCTestError + describeFormat:@"Test Bundle/HostApp Crashed: %@", crashLog] + failFuture]; + }] mapReplace:NSNull.null]; +} + - (FBFuture *)findCrashedProcessLog { id testHostApplication = self.testHostApplication; @@ -401,11 +438,20 @@ - (id)_XCT_initializationForUITestingDidFailWithError:(NSError *)error return nil; } +/// Method called to notify us (the "IDE") that XCTest "runner" has been +/// loaded into the host app process and is ready. +/// +/// Return value must be an XCTestConfiguration object that specifies which +/// tests should run alongside other options for the test execution. - (id)_XCT_testRunnerReadyWithCapabilities:(XCTCapabilities *)arg1 { [self.logger logFormat:@"Test Bundle is Ready"]; + + DTXRemoteInvocationReceipt *receipt = [[objc_lookUpClass("DTXRemoteInvocationReceipt") alloc] init]; + [receipt invokeCompletionWithReturnValue:self.context.testConfiguration.xcTestConfiguration error:nil]; + [self.bundleReadyFuture resolveWithResult:NSNull.null]; - return nil; + return receipt; } @end diff --git a/XCTestBootstrap/TestManager/FBTestManagerAPIMediator.h b/XCTestBootstrap/TestManager/FBTestManagerAPIMediator.h index 95eca0d7c..27e61d1e5 100644 --- a/XCTestBootstrap/TestManager/FBTestManagerAPIMediator.h +++ b/XCTestBootstrap/TestManager/FBTestManagerAPIMediator.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -18,8 +18,6 @@ NS_ASSUME_NONNULL_BEGIN @protocol FBXCTestExtendedCommands; @protocol FBXCTestReporter; -extern const NSInteger FBProtocolVersion; -extern const NSInteger FBProtocolMinimumVersion; /** This is a simplified re-implementation of Apple's _IDETestManagerAPIMediator class. diff --git a/XCTestBootstrap/TestManager/FBTestManagerAPIMediator.m b/XCTestBootstrap/TestManager/FBTestManagerAPIMediator.m index 20a0f0894..aff2f2b29 100644 --- a/XCTestBootstrap/TestManager/FBTestManagerAPIMediator.m +++ b/XCTestBootstrap/TestManager/FBTestManagerAPIMediator.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -7,9 +7,14 @@ #import "FBTestManagerAPIMediator.h" -#import -#import -#import +#import +#import +#import + +#import + +#import +#import #import #import @@ -31,10 +36,7 @@ #import "FBXCTestReporter.h" -const NSInteger FBProtocolVersion = 0x16; -const NSInteger FBProtocolMinimumVersion = 0x8; - -@interface FBTestManagerAPIMediator () +@interface FBTestManagerAPIMediator () @property (nonatomic, strong, readonly) FBTestManagerContext *context; @property (nonatomic, strong, readonly) id target; @@ -148,23 +150,26 @@ - (NSString *)description return [[[FBTestBundleConnection connectAndRunBundleToCompletionWithContext:self.context target:self.target - interface:(id)self + interface:self testHostApplication:launchedApplication requestQueue:self.requestQueue logger:logger] onQueue:queue fmap:^(NSNull *_) { // The bundle has disconnected at this point, but we also need to terminate any processes // spawned through `_XCT_launchProcessWithPath`and wait for the host application to terminate - return [[self terminateSpawnedProcesses] chainReplace:launchedApplication.applicationTerminated]; + return [[[self terminateSpawnedProcesses] chainReplace:launchedApplication.applicationTerminated] cancel]; }] onQueue:queue timeout:timeout handler:^{ // The timeout is applied to the lifecycle of the entire application. [logger logFormat:@"Timed out after %f, attempting stack sample", timeout]; - return [[FBXCTestProcess - performSampleStackshotOnProcessIdentifier:launchedApplication.processIdentifier - forTimeout:timeout - queue:queue - logger:logger] + return [[[FBProcessFetcher + performSampleStackshotForProcessIdentifier:launchedApplication.processIdentifier + queue:queue] + onQueue:queue fmap:^FBFuture *(NSString *stackshot) { + return [[FBXCTestError + describeFormat:@"Waited %f seconds for process %d to terminate, but the host application process stalled: %@", timeout, launchedApplication.processIdentifier, stackshot] + failFuture]; + }] onQueue:queue chain:^FBFuture *(FBFuture *future) { return [[self terminateSpawnedProcesses] chainReplace:future]; }]; @@ -228,8 +233,11 @@ - (NSString *)description #pragma mark - XCTestManager_IDEInterface protocol -#pragma mark Process Launch Delegation +#pragma mark Process Launch Delegation (UI Tests) +/// This callback is called when the UI tests call `-[XCUIApplication launch]` to launch the target app +/// It should return an NSNumber containing an unique identifier to this process, the `token` +/// This `token` will be used later on for further requests ralated to this process - (id)_XCT_launchProcessWithPath:(NSString *)path bundleID:(NSString *)bundleID arguments:(NSArray *)arguments environmentVariables:(NSDictionary *)environment { [self.logger logFormat:@"Test process requested process launch with bundleID %@", bundleID]; @@ -268,6 +276,14 @@ - (id)_XCT_launchProcessWithPath:(NSString *)path bundleID:(NSString *)bundleID return receipt; } +/// After _XCT_launchProcessWithPath:bundleID:arguments:environmentVariables: is called, +/// this method will be called to check on wherer the process has already been launched or not +/// return should be 0 or 1. +/// +/// If 0 is returned, `_XCT_getProgressForLaunch:` will be called again until 1 is returned +/// +/// Since we only invoke `_XCT_launchProcessWithPath:bundleID:arguments:environmentVariables:`'s receipt +/// completion after the process is launched, we just return 1 (because the process is already launched) - (id)_XCT_getProgressForLaunch:(id)token { [self.logger logFormat:@"Test process requested launch process status with token %@", token]; @@ -276,6 +292,13 @@ - (id)_XCT_getProgressForLaunch:(id)token return receipt; } +/// Called whenever the target process needs to be killed, for instance when `-[XCUIApplication launch]` +/// is called to launch the target app for the next test. +/// +/// `token` identifies which process should be terminated. It contains the value that +/// `_XCT_launchProcessWithPath:bundleID:arguments:environmentVariables:` defined +/// +/// This method doesn't seem to be called when all the tests finish execution. - (id)_XCT_terminateProcess:(id)token { [self.logger logFormat:@"Test process requested process termination with token %@", token]; @@ -305,8 +328,6 @@ - (id)_XCT_terminateProcess:(id)token return receipt; } -#pragma mark iOS 10.x - - (id)_XCT_didBeginInitializingForUITesting { [self.logger log:@"Started initilizing for UI testing."]; @@ -342,6 +363,12 @@ - (id)_XCT_testSuite:(NSString *)testSuite didStartAt:(NSString *)time return nil; } +- (id)_XCT_testSuiteWithIdentifier:(XCTTestIdentifier *)suiteIdentifier didStartAt:(NSString *)time { + [self _XCT_testSuite:[suiteIdentifier _identifierString] didStartAt:time]; // for some reason the property accessor (-[XCTTestIdentifier identifierString]) crashes + return nil; +} + + - (id)_XCT_didBeginExecutingTestPlan { [self.logger logFormat:@"Test Plan Started"]; @@ -368,6 +395,21 @@ - (id)_XCT_testCaseDidStartForTestClass:(NSString *)testClass method:(NSString * return nil; } +- (id)_XCT_testCaseDidStartWithIdentifier:(XCTTestIdentifier *)arg1 testCaseRunConfiguration:(XCTestCaseRunConfiguration *)arg2 +{ + [self.logger logFormat:@"Test Case %@/%@ did start", arg1.firstComponent, arg1.lastComponent]; + [self.reporterAdapter _XCT_testCaseDidStartForTestClass:arg1.firstComponent method:arg1.lastComponent]; + return nil; +} + +- (id)_XCT_testCaseWithIdentifier:(XCTTestIdentifier *)arg1 didRecordIssue:(XCTIssue *)arg2 { + [self.logger logFormat:@"Test Case %@/%@ did fail: %@", arg1.firstComponent, arg1.lastComponent, arg2.detailedDescription ?: arg2.compactDescription]; + return [self.reporterAdapter _XCT_testCaseDidFailForTestClass:arg1.firstComponent method:arg1.lastComponent + withMessage:arg2.compactDescription + file:arg2.sourceCodeContext.location.fileURL.absoluteString + line:@(arg2.sourceCodeContext.location.lineNumber)]; +} + - (id)_XCT_testCaseDidFailForTestClass:(NSString *)testClass method:(NSString *)method withMessage:(NSString *)message file:(NSString *)file line:(NSNumber *)line { [self.logger logFormat:@"Test Case %@/%@ did fail: %@", testClass, method, message]; @@ -383,6 +425,7 @@ - (id)_XCT_logDebugMessage:(NSString *)debugMessage - (id)_XCT_logMessage:(NSString *)message { + [self.logger logFormat:@"_XCT_logMessage: %@", message]; return nil; } @@ -393,13 +436,25 @@ - (id)_XCT_testCaseDidFinishForTestClass:(NSString *)testClass method:(NSString return nil; } +- (id)_XCT_testCaseWithIdentifier:(XCTTestIdentifier *)identifier didFinishWithStatus:(NSString *)statusString duration:(NSNumber *)duration { + return [self _XCT_testCaseDidFinishForTestClass:identifier.firstComponent method:identifier.lastComponent withStatus:statusString duration:duration]; +} + + - (id)_XCT_testSuite:(NSString *)testSuite didFinishAt:(NSString *)time runCount:(NSNumber *)runCount withFailures:(NSNumber *)failures unexpected:(NSNumber *)unexpected testDuration:(NSNumber *)testDuration totalDuration:(NSNumber *)totalDuration { [self.logger logFormat:@"Test Suite Did Finish %@", testSuite]; - [self. reporterAdapter _XCT_testSuite:testSuite didFinishAt:time runCount:runCount withFailures:failures unexpected:unexpected testDuration:testDuration totalDuration:totalDuration]; + [self.reporterAdapter _XCT_testSuite:testSuite didFinishAt:time runCount:runCount withFailures:failures unexpected:unexpected testDuration:testDuration totalDuration:totalDuration]; + return nil; +} + +- (id)_XCT_testSuiteWithIdentifier:(XCTTestIdentifier *)arg1 didFinishAt:(NSString *)arg2 runCount:(NSNumber *)arg3 skipCount:(NSNumber *)arg4 failureCount:(NSNumber *)arg5 expectedFailureCount:(NSNumber *)arg6 uncaughtExceptionCount:(NSNumber *)arg7 testDuration:(NSNumber *)arg8 totalDuration:(NSNumber *)arg9 { + // do nothing as the values reported by the legacy method _XCT_testSuite:didFinishAt:runCount:withFailures:unexpected:testDuration: + // are ignored on IDBXCTestReporter return nil; } + - (id)_XCT_testCase:(NSString *)testCase method:(NSString *)method didFinishActivity:(XCActivityRecord *)activity { [self.reporterAdapter _XCT_testCase:testCase method:method didFinishActivity:activity]; @@ -412,6 +467,16 @@ - (id)_XCT_testCase:(NSString *)testCase method:(NSString *)method willStartActi return nil; } +- (id)_XCT_testCaseWithIdentifier:(XCTTestIdentifier *)arg1 didFinishActivity:(XCActivityRecord *)arg2 { + [self.reporterAdapter _XCT_testCase:arg1.firstComponent method:arg1.lastComponent didFinishActivity:arg2]; + return nil; +} + +- (id)_XCT_testCaseWithIdentifier:(XCTTestIdentifier *)arg1 willStartActivity:(XCActivityRecord *)arg2 { + [self.reporterAdapter _XCT_testCase:arg1.firstComponent method:arg1.lastComponent willStartActivity:arg2]; + return nil; +} + #pragma mark - Unimplemented - (id)_XCT_nativeFocusItemDidChangeAtTime:(NSNumber *)arg1 parameterSnapshot:(XCElementSnapshot *)arg2 applicationSnapshot:(XCElementSnapshot *)arg3 @@ -479,6 +544,21 @@ - (id)_XCT_testCase:(NSString *)arg1 method:(NSString *)arg2 didStallOnMainThrea return [self handleUnimplementedXCTRequest:_cmd]; } +- (id)_XCT_testCaseWasSkippedForTestClass:(NSString *)arg1 method:(NSString *)arg2 withMessage:(NSString *)arg3 file:(NSString *)arg4 line:(NSNumber *)arg5 { + return [self handleUnimplementedXCTRequest:_cmd]; +} + + +- (id)_XCT_testSuite:(NSString *)arg1 didFinishAt:(NSString *)arg2 runCount:(NSNumber *)arg3 skipCount:(NSNumber *)arg4 failureCount:(NSNumber *)arg5 expectedFailureCount:(NSNumber *)arg6 uncaughtExceptionCount:(NSNumber *)arg7 testDuration:(NSNumber *)arg8 totalDuration:(NSNumber *)arg9 { + return [self handleUnimplementedXCTRequest:_cmd]; +} + + +- (id)_XCT_testSuite:(NSString *)arg1 didFinishAt:(NSString *)arg2 runCount:(NSNumber *)arg3 skipCount:(NSNumber *)arg4 failureCount:(NSNumber *)arg5 unexpectedFailureCount:(NSNumber *)arg6 testDuration:(NSNumber *)arg7 totalDuration:(NSNumber *)arg8 { + return [self handleUnimplementedXCTRequest:_cmd]; +} + + - (id)_XCT_testMethod:(NSString *)arg1 ofClass:(NSString *)arg2 didMeasureValues:(NSArray *)arg3 forPerformanceMetricID:(NSString *)arg4 name:(NSString *)arg5 withUnits:(NSString *)arg6 baselineName:(NSString *)arg7 baselineAverage:(NSNumber *)arg8 maxPercentRegression:(NSNumber *)arg9 maxPercentRelativeStandardDeviation:(NSNumber *)arg10 file:(NSString *)arg11 line:(NSNumber *)arg12 { return [self handleUnimplementedXCTRequest:_cmd]; @@ -494,6 +574,45 @@ - (id)_XCT_testRunnerReadyWithCapabilities:(XCTCapabilities *)arg1 return [self handleUnimplementedXCTRequest:_cmd]; } +- (id)_XCT_didFailToBootstrapWithError:(NSError *)arg1 { + return [self handleUnimplementedXCTRequest:_cmd]; +} + + +- (id)_XCT_reportTestWithIdentifier:(XCTTestIdentifier *)arg1 didExceedExecutionTimeAllowance:(NSNumber *)arg2 { + return [self handleUnimplementedXCTRequest:_cmd]; +} + + +- (id)_XCT_testCaseDidStartWithIdentifier:(XCTTestIdentifier *)arg1 { + return [self handleUnimplementedXCTRequest:_cmd]; +} + + +- (id)_XCT_testCaseDidStartWithIdentifier:(XCTTestIdentifier *)arg1 iteration:(NSNumber *)arg2 { + return [self handleUnimplementedXCTRequest:_cmd]; +} + + +- (id)_XCT_testCaseWithIdentifier:(XCTTestIdentifier *)arg1 didRecordExpectedFailure:(XCTExpectedFailure *)arg2 { + return [self handleUnimplementedXCTRequest:_cmd]; +} + +- (id)_XCT_testCaseWithIdentifier:(XCTTestIdentifier *)arg1 didStallOnMainThreadInFile:(NSString *)arg2 line:(NSNumber *)arg3 { + return [self handleUnimplementedXCTRequest:_cmd]; +} + + +- (id)_XCT_testCaseWithIdentifier:(XCTTestIdentifier *)arg1 wasSkippedWithMessage:(NSString *)arg2 sourceCodeContext:(XCTSourceCodeContext *)arg3 { + return [self handleUnimplementedXCTRequest:_cmd]; +} + + +- (id)_XCT_testSuiteWithIdentifier:(XCTTestIdentifier *)arg1 didRecordIssue:(XCTIssue *)arg2 { + return [self handleUnimplementedXCTRequest:_cmd]; +} + + - (NSString *)unknownMessageForSelector:(SEL)aSelector { return [NSString stringWithFormat:@"Received call for unhandled method (%@). Probably you should have a look at _IDETestManagerAPIMediator in IDEFoundation.framework and implement it. Good luck!", NSStringFromSelector(aSelector)]; @@ -507,4 +626,12 @@ - (id)handleUnimplementedXCTRequest:(SEL)aSelector return nil; } +- (id)_XCT_reportSelfDiagnosisIssue:(NSString *)arg1 description:(NSString *)arg2 { + return [self handleUnimplementedXCTRequest:_cmd]; +} + +- (id)_XCT_testCaseWithIdentifier:(XCTTestIdentifier *)arg1 didMeasureMetric:(NSDictionary *)arg2 file:(NSString *)arg3 line:(NSNumber *)arg4 { + return [self handleUnimplementedXCTRequest:_cmd]; +} + @end diff --git a/XCTestBootstrap/TestManager/FBTestManagerContext.h b/XCTestBootstrap/TestManager/FBTestManagerContext.h index 34610e8ac..5c999245b 100644 --- a/XCTestBootstrap/TestManager/FBTestManagerContext.h +++ b/XCTestBootstrap/TestManager/FBTestManagerContext.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -9,6 +9,8 @@ #import +@class FBTestConfiguration; + NS_ASSUME_NONNULL_BEGIN /** @@ -25,7 +27,7 @@ NS_ASSUME_NONNULL_BEGIN @param testedApplicationAdditionalEnvironment Additional environment for the app-under-test. @return a new FBTestManagerContext instance. */ -- (instancetype)initWithSessionIdentifier:(NSUUID *)sessionIdentifier timeout:(NSTimeInterval)timeout testHostLaunchConfiguration:(FBApplicationLaunchConfiguration *)testHostLaunchConfiguration testedApplicationAdditionalEnvironment:(nullable NSDictionary *)testedApplicationAdditionalEnvironment; +- (instancetype)initWithSessionIdentifier:(NSUUID *)sessionIdentifier timeout:(NSTimeInterval)timeout testHostLaunchConfiguration:(FBApplicationLaunchConfiguration *)testHostLaunchConfiguration testedApplicationAdditionalEnvironment:(nullable NSDictionary *)testedApplicationAdditionalEnvironment testConfiguration:(FBTestConfiguration *)testConfiguration; /** A session identifier of test that should be started @@ -46,6 +48,8 @@ NS_ASSUME_NONNULL_BEGIN */ @property (nonatomic, copy, readonly, nullable) NSDictionary *testedApplicationAdditionalEnvironment; +@property (nonatomic, strong, readonly) FBTestConfiguration *testConfiguration; + @end NS_ASSUME_NONNULL_END diff --git a/XCTestBootstrap/TestManager/FBTestManagerContext.m b/XCTestBootstrap/TestManager/FBTestManagerContext.m index a75934636..7ece0341a 100644 --- a/XCTestBootstrap/TestManager/FBTestManagerContext.m +++ b/XCTestBootstrap/TestManager/FBTestManagerContext.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -9,7 +9,7 @@ @implementation FBTestManagerContext -- (instancetype)initWithSessionIdentifier:(NSUUID *)sessionIdentifier timeout:(NSTimeInterval)timeout testHostLaunchConfiguration:(FBApplicationLaunchConfiguration *)testHostLaunchConfiguration testedApplicationAdditionalEnvironment:(nullable NSDictionary *)testedApplicationAdditionalEnvironment +- (instancetype)initWithSessionIdentifier:(NSUUID *)sessionIdentifier timeout:(NSTimeInterval)timeout testHostLaunchConfiguration:(FBApplicationLaunchConfiguration *)testHostLaunchConfiguration testedApplicationAdditionalEnvironment:(nullable NSDictionary *)testedApplicationAdditionalEnvironment testConfiguration:(FBTestConfiguration *)testConfiguration { self = [super init]; if (!self) { @@ -20,6 +20,7 @@ - (instancetype)initWithSessionIdentifier:(NSUUID *)sessionIdentifier timeout:(N _timeout = timeout; _testHostLaunchConfiguration = testHostLaunchConfiguration; _testedApplicationAdditionalEnvironment = testedApplicationAdditionalEnvironment; + _testConfiguration = testConfiguration; return self; } diff --git a/XCTestBootstrap/TestManager/FBTestManagerResultSummary.h b/XCTestBootstrap/TestManager/FBTestManagerResultSummary.h index 2d7d7b759..723955bfe 100644 --- a/XCTestBootstrap/TestManager/FBTestManagerResultSummary.h +++ b/XCTestBootstrap/TestManager/FBTestManagerResultSummary.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/XCTestBootstrap/TestManager/FBTestManagerResultSummary.m b/XCTestBootstrap/TestManager/FBTestManagerResultSummary.m index 0632c3a8b..82d0960ba 100644 --- a/XCTestBootstrap/TestManager/FBTestManagerResultSummary.m +++ b/XCTestBootstrap/TestManager/FBTestManagerResultSummary.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/XCTestBootstrap/TestManager/FBTestReporterAdapter.h b/XCTestBootstrap/TestManager/FBTestReporterAdapter.h index 3ea7825e7..6b3b84e09 100644 --- a/XCTestBootstrap/TestManager/FBTestReporterAdapter.h +++ b/XCTestBootstrap/TestManager/FBTestReporterAdapter.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -7,7 +7,7 @@ #import -#import +#import @protocol FBXCTestReporter; diff --git a/XCTestBootstrap/TestManager/FBTestReporterAdapter.m b/XCTestBootstrap/TestManager/FBTestReporterAdapter.m index 19d01335b..5e675d404 100644 --- a/XCTestBootstrap/TestManager/FBTestReporterAdapter.m +++ b/XCTestBootstrap/TestManager/FBTestReporterAdapter.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -7,8 +7,8 @@ #import "FBTestReporterAdapter.h" -#import -#import +#import +#import #import "FBActivityRecord.h" #import "FBTestManagerAPIMediator.h" @@ -67,7 +67,9 @@ - (id)_XCT_testCaseDidStartForTestClass:(NSString *)testClass method:(NSString * - (id)_XCT_testCaseDidFailForTestClass:(NSString *)testClass method:(NSString *)method withMessage:(NSString *)message file:(NSString *)file line:(NSNumber *)line { - [self.reporter testCaseDidFailForTestClass:testClass method:method withMessage:message file:file line:line.unsignedIntegerValue]; + [self.reporter testCaseDidFailForTestClass:testClass method:method exceptions:@[ + [[FBExceptionInfo alloc]initWithMessage:message file:file line:line.unsignedIntegerValue + ]]]; return nil; } diff --git a/XCTestBootstrap/Utility/FBOToolDynamicLibs.h b/XCTestBootstrap/Utility/FBOToolDynamicLibs.h index 88a110e35..2629fb526 100644 --- a/XCTestBootstrap/Utility/FBOToolDynamicLibs.h +++ b/XCTestBootstrap/Utility/FBOToolDynamicLibs.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/XCTestBootstrap/Utility/FBOToolDynamicLibs.m b/XCTestBootstrap/Utility/FBOToolDynamicLibs.m index e02595cfb..88d7b4ca9 100644 --- a/XCTestBootstrap/Utility/FBOToolDynamicLibs.m +++ b/XCTestBootstrap/Utility/FBOToolDynamicLibs.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/XCTestBootstrap/Utility/FBOToolOperation.h b/XCTestBootstrap/Utility/FBOToolOperation.h index 636a9d6ee..7be5c9431 100644 --- a/XCTestBootstrap/Utility/FBOToolOperation.h +++ b/XCTestBootstrap/Utility/FBOToolOperation.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/XCTestBootstrap/Utility/FBOToolOperation.m b/XCTestBootstrap/Utility/FBOToolOperation.m index a7a347ad5..e97e2a6d4 100644 --- a/XCTestBootstrap/Utility/FBOToolOperation.m +++ b/XCTestBootstrap/Utility/FBOToolOperation.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/XCTestBootstrap/Utility/FBXCTestLogger.h b/XCTestBootstrap/Utility/FBXCTestLogger.h index feff6c20c..85542ec8f 100644 --- a/XCTestBootstrap/Utility/FBXCTestLogger.h +++ b/XCTestBootstrap/Utility/FBXCTestLogger.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -52,12 +52,11 @@ NS_ASSUME_NONNULL_BEGIN Logs the Consumption of the consumer to a file @param consumer the consumer to wrap. - @param outputKind kind of output that is written. - @param uuid a UUID to identify the current invocation. + @param fileName file to be written. @param logger the logger to log the mirrored path to. @return a Future that resolves with the new consumer. */ -- (FBFuture> *)logConsumptionToFile:(id)consumer outputKind:(NSString *)outputKind udid:(NSUUID *)uuid logger:(id)logger; +- (FBFuture> *)logConsumptionOf:(id)consumer toFileNamed:(NSString *)fileName logger:(id)logger; @end diff --git a/XCTestBootstrap/Utility/FBXCTestLogger.m b/XCTestBootstrap/Utility/FBXCTestLogger.m index ba2dd9cd7..06ce8a03e 100644 --- a/XCTestBootstrap/Utility/FBXCTestLogger.m +++ b/XCTestBootstrap/Utility/FBXCTestLogger.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -67,14 +67,14 @@ + (instancetype)loggerInDirectory:(NSString *)directory name:(NSString *)name // Create an empty file so that it can be appeneded to. NSString *path = [directory stringByAppendingPathComponent:name]; - success = [NSFileManager.defaultManager createFileAtPath:path contents:nil attributes:nil]; - NSAssert(success, @"Expected to create file at path %@, but could not", path); + success = [[NSData new] writeToFile:path options:0 error:&error]; + NSAssert(success, @"Expected to create file at path %@, but could not: %@", path, error); NSFileHandle *fileHandle = [NSFileHandle fileHandleForWritingAtPath:path]; NSAssert(fileHandle, @"Could not create a writable file handle for file at path %@", fileHandle); - id baseLogger = [FBControlCoreLogger compositeLoggerWithLoggers:@[ - [[FBControlCoreLogger systemLoggerWritingToStderr:YES withDebugLogging:YES] withDateFormatEnabled:YES], - [[FBControlCoreLogger loggerToFileDescriptor:fileHandle.fileDescriptor closeOnEndOfFile:NO] withDateFormatEnabled:YES], + id baseLogger = [FBControlCoreLoggerFactory compositeLoggerWithLoggers:@[ + [[FBControlCoreLoggerFactory systemLoggerWritingToStderr:YES withDebugLogging:YES] withDateFormatEnabled:YES], + [[FBControlCoreLoggerFactory loggerToFileDescriptor:fileHandle.fileDescriptor closeOnEndOfFile:NO] withDateFormatEnabled:YES], ]]; return [[self alloc] initWithBaseLogger:baseLogger logDirectory:directory]; @@ -156,10 +156,9 @@ - (FBControlCoreLogLevel)level return self.baseLogger.level; } -- (FBFuture> *)logConsumptionToFile:(id)consumer outputKind:(NSString *)outputKind udid:(NSUUID *)uuid logger:(id)logger +- (FBFuture> *)logConsumptionOf:(id)consumer toFileNamed:(NSString *)fileName logger:(id)logger { dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0); - NSString *fileName = [NSString stringWithFormat:@"%@.%@", uuid.UUIDString, outputKind]; NSString *filePath = [self.logDirectory stringByAppendingPathComponent:fileName]; return [[FBFileWriter diff --git a/XCTestBootstrap/Utility/FBXCTestResultBundleParser.h b/XCTestBootstrap/Utility/FBXCTestResultBundleParser.h index 8a3833803..f0f44150c 100644 --- a/XCTestBootstrap/Utility/FBXCTestResultBundleParser.h +++ b/XCTestBootstrap/Utility/FBXCTestResultBundleParser.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -17,7 +17,7 @@ NS_ASSUME_NONNULL_BEGIN @interface FBXCTestResultBundleParser : NSObject -+ (FBFuture *)parse:(NSString *)resultBundlePath target:(id)target reporter:(id)reporter logger:(id)logger; ++ (FBFuture *)parse:(NSString *)resultBundlePath target:(id)target reporter:(id)reporter logger:(id)logger extractScreenshots:(BOOL)extractScreenshots; @end diff --git a/XCTestBootstrap/Utility/FBXCTestResultBundleParser.m b/XCTestBootstrap/Utility/FBXCTestResultBundleParser.m index 538343c85..5d9c6086f 100644 --- a/XCTestBootstrap/Utility/FBXCTestResultBundleParser.m +++ b/XCTestBootstrap/Utility/FBXCTestResultBundleParser.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -105,7 +105,7 @@ @implementation FBXCTestResultBundleParser #pragma mark PUBLIC -+ (FBFuture *)parse:(NSString *)resultBundlePath target:(id)target reporter:(id)reporter logger:(id)logger ++ (FBFuture *)parse:(NSString *)resultBundlePath target:(id)target reporter:(id)reporter logger:(id)logger extractScreenshots:(BOOL)extractScreenshots { [logger logFormat:@"Parsing the result bundle %@", resultBundlePath]; @@ -136,7 +136,7 @@ @implementation FBXCTestResultBundleParser onQueue:target.workQueue doOnResolved:^void (NSDictionary *> *xcresults) { [logger logFormat:@"Parsing summaries for id %@", bundleObjectId]; NSArray *summaries = accessAndUnwrapValues(xcresults, @"summaries", logger); - [self reportSummaries:summaries reporter:reporter queue:target.asyncQueue resultBundlePath:resultBundlePath logger:logger]; + [self reportSummaries:summaries reporter:reporter queue:target.asyncQueue resultBundlePath:resultBundlePath logger:logger extractScreenshots:extractScreenshots]; [logger logFormat:@"Done parsing summaries for id %@", bundleObjectId]; }]; [operations addObject:operation]; @@ -276,7 +276,9 @@ + (void)reportTestMethod:(NSDictionary *)testMethod test [reporter testCaseDidStartForTestClass:testClassName method:testMethodName]; if (status == FBTestReportStatusFailed) { NSArray *failureSummaries = readArrayFromDict(testMethod, @"FailureSummaries"); - [reporter testCaseDidFailForTestClass:testClassName method:testMethodName withMessage:[self buildErrorMessageLegacy:failureSummaries] file:nil line:0]; + [reporter testCaseDidFailForTestClass:testClassName method:testMethodName exceptions:@[ + [[FBExceptionInfo alloc]initWithMessage:[self buildErrorMessageLegacy:failureSummaries] + ]]]; } [reporter testCaseDidFinishForTestClass:testClassName method:testMethodName withStatus:status duration:[duration doubleValue] logs:[logs copy]]; @@ -390,12 +392,13 @@ + (void)reportSummaries:(NSArray *)summaries queue:(dispatch_queue_t)queue resultBundlePath:(NSString *)resultBundlePath logger:(id)logger + extractScreenshots:(BOOL)extractScreenshots { NSAssert(summaries, @"Test summaries have no value"); NSAssert([summaries isKindOfClass:NSArray.class], @"Test summary values not a NSArray"); for (NSDictionary *summary in summaries) { - [self reportResults:summary reporter:reporter queue:queue resultBundlePath:resultBundlePath logger:logger]; + [self reportResults:summary reporter:reporter queue:queue resultBundlePath:resultBundlePath logger:logger extractScreenshots:extractScreenshots]; } } @@ -404,11 +407,12 @@ + (void)reportResults:(NSDictionary *)results queue:(dispatch_queue_t)queue resultBundlePath:(NSString *)resultBundlePath logger:(id)logger + extractScreenshots:(BOOL)extractScreenshots { NSAssert([results isKindOfClass:NSDictionary.class], @"Test results not a NSDictionary"); NSArray *testTargets = accessAndUnwrapValues(results, @"testableSummaries", logger); - [self reportTargetTests:testTargets reporter:reporter queue:queue resultBundlePath:resultBundlePath logger:logger]; + [self reportTargetTests:testTargets reporter:reporter queue:queue resultBundlePath:resultBundlePath logger:logger extractScreenshots:extractScreenshots]; } + (void)reportTargetTests:(NSArray *)targetTests @@ -416,12 +420,13 @@ + (void)reportTargetTests:(NSArray *)targetTests queue:(dispatch_queue_t)queue resultBundlePath:(NSString *)resultBundlePath logger:(id)logger + extractScreenshots:(BOOL)extractScreenshots { NSAssert(targetTests, @"targetTests is nil"); NSAssert([targetTests isKindOfClass:NSArray.class], @"targetTests not a NSArray"); for (NSDictionary *targetTest in targetTests) { - [self reportTargetTest:targetTest reporter:reporter queue:queue resultBundlePath:resultBundlePath logger:logger]; + [self reportTargetTest:targetTest reporter:reporter queue:queue resultBundlePath:resultBundlePath logger:logger extractScreenshots:extractScreenshots]; } } @@ -430,6 +435,7 @@ + (void)reportTargetTest:(NSDictionary *)targetTest queue:(dispatch_queue_t)queue resultBundlePath:(NSString *)resultBundlePath logger:(id)logger + extractScreenshots:(BOOL)extractScreenshots { NSAssert(targetTest, @"targetTest is nil"); NSAssert([targetTest isKindOfClass:NSDictionary.class], @"targetTest not a NSDictionary"); @@ -437,12 +443,16 @@ + (void)reportTargetTest:(NSDictionary *)targetTest NSArray *selectedTests = accessAndUnwrapValues(targetTest, @"tests", logger); if (selectedTests != nil) { - [self reportSelectedTests:selectedTests testBundleName:testBundleName reporter:reporter queue:queue resultBundlePath:resultBundlePath logger:logger]; + [self reportSelectedTests:selectedTests testBundleName:testBundleName reporter:reporter queue:queue resultBundlePath:resultBundlePath logger:logger extractScreenshots:extractScreenshots]; } else { [logger log:@"Test failed and no test results found in the bundle"]; NSArray *failureSummaries = accessAndUnwrapValues(targetTest, @"failureSummaries", logger); - [reporter testCaseDidFailForTestClass:@"" method:@"" withMessage:[self buildErrorMessage:failureSummaries logger:logger] file:nil line:0]; + + [reporter testCaseDidFailForTestClass:@"" method:@"" exceptions:@[ + [[FBExceptionInfo alloc]initWithMessage:[self buildErrorMessage:failureSummaries logger:logger] + ]]]; + } } @@ -452,12 +462,13 @@ + (void)reportSelectedTests:(NSArray *)selectedTests queue:(dispatch_queue_t)queue resultBundlePath:(NSString *)resultBundlePath logger:(id)logger + extractScreenshots:(BOOL)extractScreenshots { NSAssert(selectedTests, @"selectedTests is nil"); NSAssert([selectedTests isKindOfClass:NSArray.class], @"selectedTests not a NSArray"); for (NSDictionary *selectedTest in selectedTests) { - [self reportSelectedTest:selectedTest testBundleName:testBundleName reporter:reporter queue:queue resultBundlePath:resultBundlePath logger:logger]; + [self reportSelectedTest:selectedTest testBundleName:testBundleName reporter:reporter queue:queue resultBundlePath:resultBundlePath logger:logger extractScreenshots:extractScreenshots]; } } @@ -467,17 +478,20 @@ + (void)reportSelectedTest:(NSDictionary *)selectedT queue:(dispatch_queue_t)queue resultBundlePath:(NSString *)resultBundlePath logger:(id)logger + extractScreenshots:(BOOL)extractScreenshots { NSAssert(selectedTest, @"selectedTest is nil"); NSAssert([selectedTest isKindOfClass:NSDictionary.class], @"selectedTest not a NSDictionary"); NSArray *testTargetXctests = accessAndUnwrapValues(selectedTest, @"subtests", logger); if (testTargetXctests != nil) { - [self reportTestTargetXctests:testTargetXctests testBundleName:testBundleName reporter:reporter queue:queue resultBundlePath:resultBundlePath logger:logger]; + [self reportTestTargetXctests:testTargetXctests testBundleName:testBundleName reporter:reporter queue:queue resultBundlePath:resultBundlePath logger:logger extractScreenshots:extractScreenshots]; } else { [logger log:@"Test failed and no target test results found in the bundle"]; - [reporter testCaseDidFailForTestClass:@"" method:@"" withMessage:@"" file:nil line:0]; + [reporter testCaseDidFailForTestClass:@"" method:@"" exceptions:@[ + [[FBExceptionInfo alloc]initWithMessage:@"" + ]]]; } } @@ -487,12 +501,13 @@ + (void)reportTestTargetXctests:(NSArray *)testTargetXctests queue:(dispatch_queue_t)queue resultBundlePath:(NSString *)resultBundlePath logger:(id)logger + extractScreenshots:(BOOL)extractScreenshots { NSAssert(testTargetXctests, @"testTargetXctests is nil"); NSAssert([testTargetXctests isKindOfClass:NSArray.class], @"testTargetXctests not a NSArray"); for (NSDictionary *testTargetXctest in testTargetXctests) { - [self reportTestTargetXctest:testTargetXctest testBundleName:testBundleName reporter:reporter queue:queue resultBundlePath:resultBundlePath logger:logger]; + [self reportTestTargetXctest:testTargetXctest testBundleName:testBundleName reporter:reporter queue:queue resultBundlePath:resultBundlePath logger:logger extractScreenshots:extractScreenshots]; } } @@ -502,17 +517,21 @@ + (void)reportTestTargetXctest:(NSDictionary *)testT queue:(dispatch_queue_t)queue resultBundlePath:(NSString *)resultBundlePath logger:(id)logger + extractScreenshots:(BOOL)extractScreenshots { NSAssert(testTargetXctest, @"selectedTest is nil"); NSAssert([testTargetXctest isKindOfClass:NSDictionary.class], @"testTargetXctest not a NSDictionary"); NSArray *testClasses = accessAndUnwrapValues(testTargetXctest, @"subtests", logger); if (testClasses != nil) { - [self reportTestClasses:testClasses testBundleName:testBundleName reporter:reporter queue:queue resultBundlePath:resultBundlePath logger:logger]; + [self reportTestClasses:testClasses testBundleName:testBundleName reporter:reporter queue:queue resultBundlePath:resultBundlePath logger:logger extractScreenshots:extractScreenshots]; } else { [logger log:@"Test failed and no test class results found in the bundle"]; - [reporter testCaseDidFailForTestClass:@"" method:@"" withMessage:@"" file:nil line:0]; + [reporter testCaseDidFailForTestClass:@"" method:@"" exceptions:@[ + [[FBExceptionInfo alloc]initWithMessage:@"" + ]]]; + } } @@ -522,12 +541,13 @@ + (void)reportTestClasses:(NSArray *)testClasses queue:(dispatch_queue_t)queue resultBundlePath:(NSString *)resultBundlePath logger:(id)logger + extractScreenshots:(BOOL)extractScreenshots { NSAssert(testClasses, @"selectedTest is nil"); NSAssert([testClasses isKindOfClass:NSArray.class], @"testClasses not a NSArray"); for (NSDictionary *testClass in testClasses) { - [self reportTestClass:testClass testBundleName:testBundleName reporter:reporter queue:queue resultBundlePath:resultBundlePath logger:logger]; + [self reportTestClass:testClass testBundleName:testBundleName reporter:reporter queue:queue resultBundlePath:resultBundlePath logger:logger extractScreenshots:extractScreenshots]; } } @@ -537,6 +557,7 @@ + (void)reportTestClass:(NSDictionary *)testClass queue:(dispatch_queue_t)queue resultBundlePath:(NSString *)resultBundlePath logger:(id)logger + extractScreenshots:(BOOL)extractScreenshots { NSAssert(testClass, @"selectedTest is nil"); NSAssert([testClass isKindOfClass:NSDictionary.class], @"testClass not a NSDictionary"); @@ -544,11 +565,13 @@ + (void)reportTestClass:(NSDictionary *)testClass NSString *testClassName = (NSString *)accessAndUnwrapValue(testClass, @"identifier", logger); NSArray *testMethods = accessAndUnwrapValues(testClass, @"subtests", logger); if (testMethods != nil) { - [self reportTestMethods:testMethods testBundleName:testBundleName testClassName:testClassName reporter:reporter queue:queue resultBundlePath:resultBundlePath logger:logger]; + [self reportTestMethods:testMethods testBundleName:testBundleName testClassName:testClassName reporter:reporter queue:queue resultBundlePath:resultBundlePath logger:logger extractScreenshots:extractScreenshots]; } else { [logger logFormat:@"Test failed for %@ and no test method results found", testClassName]; - [reporter testCaseDidFailForTestClass:testClassName method:@"" withMessage:@"" file:nil line:0]; + [reporter testCaseDidFailForTestClass:@"" method:@"" exceptions:@[ + [[FBExceptionInfo alloc]initWithMessage:@"" + ]]]; } } @@ -559,12 +582,13 @@ + (void)reportTestMethods:(NSArray *)testMethods queue:(dispatch_queue_t)queue resultBundlePath:(NSString *)resultBundlePath logger:(id)logger + extractScreenshots:(BOOL)extractScreenshots { NSAssert(testMethods, @"testMethods is nil"); NSAssert([testMethods isKindOfClass:NSArray.class], @"testMethods not a NSArray"); for (NSDictionary *testMethod in testMethods) { - [self reportTestMethod:testMethod testBundleName:testBundleName testClassName:testClassName reporter:reporter queue:queue resultBundlePath:resultBundlePath logger:logger]; + [self reportTestMethod:testMethod testBundleName:testBundleName testClassName:testClassName reporter:reporter queue:queue resultBundlePath:resultBundlePath logger:logger extractScreenshots:extractScreenshots]; } } @@ -575,6 +599,7 @@ + (void)reportTestMethod:(NSDictionary *)testMethod queue:(dispatch_queue_t)queue resultBundlePath:(NSString *)resultBundlePath logger:(id)logger + extractScreenshots:(BOOL)extractScreenshots { NSAssert(testMethod, @"testMethod is nil"); NSAssert([testMethod isKindOfClass:NSDictionary.class], @"testMethod not a NSDictionary"); @@ -603,7 +628,9 @@ + (void)reportTestMethod:(NSDictionary *)testMethod onQueue:queue doOnResolved:^(NSDictionary *> *actionTestSummary) { if (status == FBTestReportStatusFailed) { NSArray *failureSummaries = accessAndUnwrapValues(actionTestSummary, @"failureSummaries", logger); - [reporter testCaseDidFailForTestClass:testClassName method:testMethodIdentifier withMessage:[self buildErrorMessage:failureSummaries logger:logger] file:nil line:0]; + [reporter testCaseDidFailForTestClass:testClassName method:testMethodIdentifier exceptions:@[ + [[FBExceptionInfo alloc]initWithMessage:[self buildErrorMessage:failureSummaries logger:logger]] + ]]; } NSArray *performanceMetrics = accessAndUnwrapValues(actionTestSummary, @"performanceMetrics", logger); @@ -617,7 +644,9 @@ + (void)reportTestMethod:(NSDictionary *)testMethod } NSArray *activitySummaries = accessAndUnwrapValues(actionTestSummary, @"activitySummaries", logger); - [self extractScreenshotsFromActivities:activitySummaries queue:queue resultBundlePath:resultBundlePath logger:logger]; + if (extractScreenshots) { + [self extractScreenshotsFromActivities:activitySummaries queue:queue resultBundlePath:resultBundlePath logger:logger]; + } NSMutableArray *logs = [self buildTestLog:activitySummaries diff --git a/XCTestBootstrap/Utility/FBXCTestResultToolOperation.h b/XCTestBootstrap/Utility/FBXCTestResultToolOperation.h index fda883151..4a80b4698 100644 --- a/XCTestBootstrap/Utility/FBXCTestResultToolOperation.h +++ b/XCTestBootstrap/Utility/FBXCTestResultToolOperation.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/XCTestBootstrap/Utility/FBXCTestResultToolOperation.m b/XCTestBootstrap/Utility/FBXCTestResultToolOperation.m index e8f4f1280..229c8f655 100644 --- a/XCTestBootstrap/Utility/FBXCTestResultToolOperation.m +++ b/XCTestBootstrap/Utility/FBXCTestResultToolOperation.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/XCTestBootstrap/Utility/FBXCTestRunner.h b/XCTestBootstrap/Utility/FBXCTestRunner.h index ed9bfecec..da6395fff 100644 --- a/XCTestBootstrap/Utility/FBXCTestRunner.h +++ b/XCTestBootstrap/Utility/FBXCTestRunner.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/XCTestBootstrap/Utility/FBXcodeBuildOperation.h b/XCTestBootstrap/Utility/FBXcodeBuildOperation.h index 3272846b5..0bae3e2a4 100644 --- a/XCTestBootstrap/Utility/FBXcodeBuildOperation.h +++ b/XCTestBootstrap/Utility/FBXcodeBuildOperation.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/XCTestBootstrap/Utility/FBXcodeBuildOperation.m b/XCTestBootstrap/Utility/FBXcodeBuildOperation.m index d270de25c..b0492f5ef 100644 --- a/XCTestBootstrap/Utility/FBXcodeBuildOperation.m +++ b/XCTestBootstrap/Utility/FBXcodeBuildOperation.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -47,7 +47,7 @@ @implementation FBXcodeBuildOperation NSMutableDictionary *environment = [NSProcessInfo.processInfo.environment mutableCopy]; environment[XcodebuildEnvironmentTargetUDID] = udid; - + // Add environments for xcodebuild method swizzling if a simulator device set is provided if (simDeviceSetPath) { if (!macOSTestShimPath) { @@ -173,7 +173,8 @@ + (NSString *)xcodeBuildPathWithError:(NSError **)error // This will execute only if the operation completes successfully. [logger logFormat:@"xcodebuild operation completed successfully %@", task]; if (configuration.resultBundlePath) { - return [FBXCTestResultBundleParser parse:configuration.resultBundlePath target:target reporter:reporter logger:logger]; + // If we don't want to return result bundle in payload, there is no need to do expensive screenshot extraction + return [FBXCTestResultBundleParser parse:configuration.resultBundlePath target:target reporter:reporter logger:logger extractScreenshots:configuration.reportResultBundle]; } [logger log:@"No result bundle to parse"]; return FBFuture.empty; diff --git a/XCTestBootstrap/Utility/XCTestBootstrapError.h b/XCTestBootstrap/Utility/XCTestBootstrapError.h index b81a5713f..227ab885b 100644 --- a/XCTestBootstrap/Utility/XCTestBootstrapError.h +++ b/XCTestBootstrap/Utility/XCTestBootstrapError.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/XCTestBootstrap/Utility/XCTestBootstrapError.m b/XCTestBootstrap/Utility/XCTestBootstrapError.m index 62e1bc1b2..be7f3e79a 100644 --- a/XCTestBootstrap/Utility/XCTestBootstrapError.m +++ b/XCTestBootstrap/Utility/XCTestBootstrapError.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/XCTestBootstrap/Utility/XCTestBootstrapFrameworkLoader.h b/XCTestBootstrap/Utility/XCTestBootstrapFrameworkLoader.h index 92f6150b7..a65df6d45 100644 --- a/XCTestBootstrap/Utility/XCTestBootstrapFrameworkLoader.h +++ b/XCTestBootstrap/Utility/XCTestBootstrapFrameworkLoader.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/XCTestBootstrap/Utility/XCTestBootstrapFrameworkLoader.m b/XCTestBootstrap/Utility/XCTestBootstrapFrameworkLoader.m index 5e7a233c6..95e93becd 100644 --- a/XCTestBootstrap/Utility/XCTestBootstrapFrameworkLoader.m +++ b/XCTestBootstrap/Utility/XCTestBootstrapFrameworkLoader.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/XCTestBootstrap/XCTestBootstrap.h b/XCTestBootstrap/XCTestBootstrap.h index ce138d413..e5abc8dc1 100644 --- a/XCTestBootstrap/XCTestBootstrap.h +++ b/XCTestBootstrap/XCTestBootstrap.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/XCTestBootstrapTests/Fixtures/FBXCTestBootstrapFixtures.h b/XCTestBootstrapTests/Fixtures/FBXCTestBootstrapFixtures.h index f69bffa8a..ebf5ba0e8 100644 --- a/XCTestBootstrapTests/Fixtures/FBXCTestBootstrapFixtures.h +++ b/XCTestBootstrapTests/Fixtures/FBXCTestBootstrapFixtures.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -8,6 +8,8 @@ #import #import +@class FBBundleDescriptor; + /** Fetching Fixtures, causing test failures if they cannot be obtained. */ @@ -23,4 +25,9 @@ */ + (NSBundle *)macUnitTestBundleFixture; +/** + An macOS dummy application + */ ++ (FBBundleDescriptor *)macCommonApplicationWithError:(NSError **)error; + @end diff --git a/XCTestBootstrapTests/Fixtures/FBXCTestBootstrapFixtures.m b/XCTestBootstrapTests/Fixtures/FBXCTestBootstrapFixtures.m index aa4dab266..5579b89bc 100644 --- a/XCTestBootstrapTests/Fixtures/FBXCTestBootstrapFixtures.m +++ b/XCTestBootstrapTests/Fixtures/FBXCTestBootstrapFixtures.m @@ -1,11 +1,12 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #import "FBXCTestBootstrapFixtures.h" +#import @implementation XCTestCase (FBXCTestBootstrapFixtures) @@ -21,4 +22,10 @@ + (NSBundle *)macUnitTestBundleFixture return [NSBundle bundleWithPath:fixturePath]; } ++ (FBBundleDescriptor *)macCommonApplicationWithError:(NSError **)error +{ + NSString *path = [[NSBundle bundleForClass:self] pathForResource:@"MacCommonApp" ofType:@"app"]; + return [FBBundleDescriptor bundleFromPath:path error:error]; +} + @end diff --git a/XCTestBootstrapTests/Fixtures/FBXCTestReporterDouble.h b/XCTestBootstrapTests/Fixtures/FBXCTestReporterDouble.h index fd604320f..acee2538e 100644 --- a/XCTestBootstrapTests/Fixtures/FBXCTestReporterDouble.h +++ b/XCTestBootstrapTests/Fixtures/FBXCTestReporterDouble.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -52,7 +52,7 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, nullable, copy) NSString *logDirectoryPath; /** - Get events by name that were recieved from `-[FBXCTestReporter handleExternalEvent:]` + Get events by name that were received from `-[FBXCTestReporter handleExternalEvent:]` */ - (NSArray *)eventsWithName:(NSString *)name; diff --git a/XCTestBootstrapTests/Fixtures/FBXCTestReporterDouble.m b/XCTestBootstrapTests/Fixtures/FBXCTestReporterDouble.m index f78b80a17..6157afefa 100644 --- a/XCTestBootstrapTests/Fixtures/FBXCTestReporterDouble.m +++ b/XCTestBootstrapTests/Fixtures/FBXCTestReporterDouble.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -75,11 +75,6 @@ - (void)testSuite:(NSString *)testSuite didStartAt:(NSString *)startTime [self.mutableStartedSuites addObject:testSuite]; } -- (void)testCaseDidFailForTestClass:(NSString *)testClass method:(NSString *)method withMessage:(NSString *)message file:(NSString *)file line:(NSUInteger)line -{ - -} - - (void)finishedWithSummary:(FBTestManagerResultSummary *)summary { [self.mutableEndedSuites addObject:summary.testSuite]; @@ -141,6 +136,11 @@ - (void)didCrashDuringTest:(NSError *)error } +- (void)testCaseDidFailForTestClass:(nonnull NSString *)testClass method:(nonnull NSString *)method exceptions:(nonnull NSArray *)exceptions { + +} + + #pragma mark Accessors - (NSArray *)startedSuites diff --git a/XCTestBootstrapTests/Tests/FBJSONTestReporterTests.m b/XCTestBootstrapTests/Tests/FBJSONTestReporterTests.m index 25b15f34a..87ea11fa0 100644 --- a/XCTestBootstrapTests/Tests/FBJSONTestReporterTests.m +++ b/XCTestBootstrapTests/Tests/FBJSONTestReporterTests.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -147,7 +147,8 @@ - (void)testReportTestFailure { [self.reporter didBeginExecutingTestPlan]; [self.reporter testCaseDidStartForTestClass:@"FooTest" method:@"BarCase"]; - [self.reporter testCaseDidFailForTestClass:@"FooTest" method:@"BarCase" withMessage:@"BadBar" file:@"BadFile" line:42]; + [self.reporter testCaseDidFailForTestClass:@"FooTest" method:@"BarCase" exceptions:@[[[FBExceptionInfo alloc] initWithMessage:@"BadBar" file:@"BadFile" line:42 + ]]]; [self.reporter testCaseDidFinishForTestClass:@"FooTest" method:@"BarCase" withStatus:FBTestReportStatusFailed duration:1 logs:nil]; [self.reporter didFinishExecutingTestPlan]; NSError *error = nil; diff --git a/XCTestBootstrapTests/Tests/FBLogicReporterAdapterTests.m b/XCTestBootstrapTests/Tests/FBLogicReporterAdapterTests.m index 9ad677ccc..a80a20ee6 100644 --- a/XCTestBootstrapTests/Tests/FBLogicReporterAdapterTests.m +++ b/XCTestBootstrapTests/Tests/FBLogicReporterAdapterTests.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -18,7 +18,7 @@ @interface FBLogicReporterAdapterTests : XCTestCase @end -static NSDictionary *beginTestSuiteDict() { +static NSDictionary *beginTestSuiteDict(void) { return @{ @"event": @"begin-test-suite", @"suite": @"NARANJA", @@ -26,7 +26,7 @@ @interface FBLogicReporterAdapterTests : XCTestCase }; } -static NSDictionary *testEventDict() { +static NSDictionary *testEventDict(void) { return @{ @"className": @"OmniClass", @"methodName": @"theMethod:toRule:themAll:", diff --git a/XCTestBootstrapTests/Tests/FBMacDeviceTests.m b/XCTestBootstrapTests/Tests/FBMacDeviceTests.m new file mode 100644 index 000000000..855b5b233 --- /dev/null +++ b/XCTestBootstrapTests/Tests/FBMacDeviceTests.m @@ -0,0 +1,154 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import + +#import +#import "FBXCTestBootstrapFixtures.h" + +@interface FBMacDeviceTests : XCTestCase +@property (nonatomic, strong, nullable, readwrite) FBMacDevice *device; +@end + +@implementation FBMacDeviceTests + +- (void)setUp +{ + [super setUp]; + self.device = [[FBMacDevice alloc] init]; +} + +- (BOOL)tearDownWithError:(NSError *__autoreleasing _Nullable *)error +{ + + NSError *err = nil; + [[self.device restorePrimaryDeviceState] awaitWithTimeout:5 error:&err]; + if (err) { + NSLog(@"Failed to tearDown test gracefully %@. Further tests may be affected", err.description); + } + *error = err; + return err == nil; +} + +- (void)testMacComparsion +{ + FBMacDevice *anotherDevice = [[FBMacDevice alloc] init]; + NSComparisonResult comparsionResult = [self.device compare:anotherDevice]; + + XCTAssertEqual(comparsionResult, NSOrderedSame, + @"We should have only one exemplar of FBMacDevice, so this is same"); +} + +- (void)testMacStateRestorationWithEmptyTasks +{ + XCTAssertNotNil([[self.device restorePrimaryDeviceState] result], + @"State restoration without launched task should complete immidiately"); +} + +-(void)testInstallNotExistedApplicationAtPath +{ + __auto_type installTask = [self.device installApplicationWithPath:@"/not/existed/path"]; + XCTAssertNotNil(installTask.error, + @"Installing not existed app should fail immidiately"); +} + +-(void)testInstallExistedApplicationAtPath +{ + NSError *err = nil; + __auto_type res = [self installDummyApplicationWithError:&err]; + XCTAssertNil(err, @"Failed to install application"); + + XCTAssertTrue([res.bundle.identifier isEqualToString: @"com.facebook.MacCommonApp"], + @"Dummy application should install properly"); +} + +-(void)testUninstallApplicationByIncorrectBundleID +{ + XCTAssertNotNil([self.device uninstallApplicationWithBundleID:@"not.existed"].error); +} + +-(void)testUninstallApplicationByIncorrectAppPath +{ + NSError *err = nil; + __auto_type app = [self installDummyApplicationWithError:&err]; + XCTAssertNil(err, + @"Precondition failure"); + + __auto_type rightPath = app.bundle.path; + + // Substitute path of bundle to simulate corruption of path to app + [app.bundle setValue:@"incorrect/path" forKey:@"_path"]; + + XCTAssertNil([self.device uninstallApplicationWithBundleID:app.bundle.identifier].error, + @"Error should not be thrown when bundle path is incorrect"); + + // Restore correct path to make tearDown behave properly + [app.bundle setValue:rightPath forKey:@"_path"]; +} + +-(void)testUninstallApplicationByApp +{ + NSError *err = nil; + __auto_type app = [self installDummyApplicationWithError:&err]; + XCTAssertNil(err, + @"Precondition failure"); + + __auto_type uninstalled = [self.device uninstallApplicationWithBundleID:app.bundle.identifier]; + XCTAssertNotNil(uninstalled, + @"Failed to remove installed application"); +} + +-(void)testLaunchingNotInstalledAppByBuntleID +{ + FBApplicationLaunchConfiguration *config = [[FBApplicationLaunchConfiguration alloc] initWithBundleID:@"not.existed" + bundleName:@"not.existed" + arguments:@[] + environment:@{} + waitForDebugger:NO + io:FBProcessIO.outputToDevNull + launchMode:FBApplicationLaunchModeRelaunchIfRunning]; + __auto_type launchAppFuture = [self.device launchApplication:config]; + + XCTAssertNotNil([launchAppFuture error], + @"Launhing not existed app should fail immidiately"); +} + +-(void)testLaunchingExistedApp +{ + NSError *err = nil; + __auto_type installResult = [self installDummyApplicationWithError:&err]; + XCTAssertNil(err, + @"Precondition failure"); + + FBApplicationLaunchConfiguration *config = [[FBApplicationLaunchConfiguration alloc] initWithBundleID:installResult.bundle.identifier + bundleName:installResult.bundle.name + arguments:@[] + environment:@{} + waitForDebugger:NO + io:FBProcessIO.outputToDevNull + launchMode:FBApplicationLaunchModeRelaunchIfRunning]; + + [[self.device launchApplication:config] awaitWithTimeout:5 error:&err]; + + XCTAssertNil(err, + @"Failed to launch installed application"); +} + +-(FBInstalledApplication *)installDummyApplicationWithError:(NSError **)error +{ + NSError *err = nil; + __auto_type descriptor = [FBMacDeviceTests macCommonApplicationWithError:&err]; + if (err) { + *error = err; + return nil; + } + __auto_type installTask = [self.device installApplicationWithPath: descriptor.path]; + return [installTask awaitWithTimeout:5 error:error]; +} + + +@end diff --git a/XCTestBootstrapTests/Tests/FBTestConfigurationTests.m b/XCTestBootstrapTests/Tests/FBTestConfigurationTests.m index af02e34f9..a04fcce91 100644 --- a/XCTestBootstrapTests/Tests/FBTestConfigurationTests.m +++ b/XCTestBootstrapTests/Tests/FBTestConfigurationTests.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -7,7 +7,11 @@ #import +#import + #import +#import +#import @interface FBTestConfigurationTests : XCTestCase @@ -17,13 +21,15 @@ @implementation FBTestConfigurationTests - (void)testSimpleConstructor { + XCTestConfiguration * xcTestConfig = [objc_lookUpClass("XCTestConfiguration") new]; NSUUID *sessionIdentifier = [[NSUUID alloc] initWithUUIDString:@"E621E1F8-C36C-495A-93FC-0C247A3E6E5F"]; FBTestConfiguration *testConfiguration = [FBTestConfiguration configurationWithSessionIdentifier:sessionIdentifier moduleName:@"Franek" testBundlePath:@"BundlePath" path:@"ConfigPath" - uiTesting:YES]; + uiTesting:YES + xcTestConfiguration:xcTestConfig]; XCTAssertTrue([testConfiguration isKindOfClass:FBTestConfiguration.class]); XCTAssertEqual(testConfiguration.sessionIdentifier, sessionIdentifier); @@ -31,17 +37,20 @@ - (void)testSimpleConstructor XCTAssertEqual(testConfiguration.testBundlePath, @"BundlePath"); XCTAssertEqual(testConfiguration.path, @"ConfigPath"); XCTAssertTrue(testConfiguration.shouldInitializeForUITesting); + XCTAssertEqual(testConfiguration.xcTestConfiguration, xcTestConfig); + } - (void)testSaveAs { NSError *error; NSUUID *sessionIdentifier = NSUUID.UUID; + NSString *someRandomPath = NSTemporaryDirectory(); FBTestConfiguration *testConfiguration = [FBTestConfiguration configurationByWritingToFileWithSessionIdentifier:sessionIdentifier moduleName:@"ModuleName" - testBundlePath:NSTemporaryDirectory() + testBundlePath:someRandomPath uiTesting:YES testsToRun:[NSSet set] testsToSkip:[NSSet set] @@ -55,6 +64,20 @@ - (void)testSaveAs XCTAssertNil(error); XCTAssertNotNil(testConfiguration); XCTAssertTrue([NSFileManager.defaultManager fileExistsAtPath:testConfiguration.path]); + + XCTestConfiguration *xcTestConfig = testConfiguration.xcTestConfiguration; + + XCTAssertNotNil(xcTestConfig); + XCTAssertEqual(xcTestConfig.productModuleName, @"ModuleName"); + XCTAssertEqualObjects(xcTestConfig.testBundleURL, [NSURL fileURLWithPath:someRandomPath]); + XCTAssertEqual(xcTestConfig.initializeForUITesting, YES); + XCTAssertEqual(xcTestConfig.targetApplicationPath, @"targetAppPath"); + XCTAssertEqual(xcTestConfig.targetApplicationBundleID, @"targetBundleID"); + XCTAssertEqual(xcTestConfig.reportActivities, NO); + XCTAssertEqual(xcTestConfig.reportResultsToIDE, YES); + + NSDictionary *capabilities = @{@"XCTIssue capability": @1, @"ubiquitous test identifiers": @1}; + XCTAssertEqualObjects(xcTestConfig.IDECapabilities.capabilitiesDictionary, capabilities); } @end diff --git a/XCTestBootstrapTests/Tests/FBTestRunnerConfigurationTests.m b/XCTestBootstrapTests/Tests/FBTestRunnerConfigurationTests.m index 3735690e4..c704a7fe1 100644 --- a/XCTestBootstrapTests/Tests/FBTestRunnerConfigurationTests.m +++ b/XCTestBootstrapTests/Tests/FBTestRunnerConfigurationTests.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/XCTestBootstrapTests/Tests/FBXcodeBuildOperationTests.m b/XCTestBootstrapTests/Tests/FBXcodeBuildOperationTests.m index 82be0b2a8..d38f774c9 100644 --- a/XCTestBootstrapTests/Tests/FBXcodeBuildOperationTests.m +++ b/XCTestBootstrapTests/Tests/FBXcodeBuildOperationTests.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -46,7 +46,9 @@ - (void)testUITestConfiguration resultBundlePath:nil reportActivities:NO coverageDirectoryPath:nil - logDirectoryPath:nil]; + enableContinuousCoverageCollection:NO + logDirectoryPath:nil + reportResultBundle:NO]; NSDictionary *properties = [FBXcodeBuildOperation xctestRunProperties:configuration]; NSDictionary *stubBundleProperties = properties[@"StubBundleId"]; diff --git a/XCTestBootstrapTests/XCTestBootstrapTests.xcconfig b/XCTestBootstrapTests/XCTestBootstrapTests.xcconfig new file mode 100644 index 000000000..40d3f32c9 --- /dev/null +++ b/XCTestBootstrapTests/XCTestBootstrapTests.xcconfig @@ -0,0 +1,8 @@ +// Import Shared Configuration +#include "../Configuration/Shared.xcconfig" + +// Target-Specific Settings +INFOPLIST_FILE = $(SRCROOT)/XCTestBootstrapTests/XCTestBootstrapTests-Info.plist; +LD_RUNPATH_SEARCH_PATHS = $(inherited) @executable_path/../Frameworks @loader_path/../Frameworks +PRODUCT_BUNDLE_IDENTIFIER = com.facebook.XCTestBootstrapTests +PRODUCT_NAME = XCTestBootstrapTests diff --git a/build.sh b/build.sh index 0a29dd128..3a1347b46 100755 --- a/build.sh +++ b/build.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. diff --git a/fbxctest/FBXCTestKit/Configuration/FBXCTestCommandLine.h b/fbxctest/FBXCTestKit/Configuration/FBXCTestCommandLine.h index 7700ca141..d0a5ecc98 100644 --- a/fbxctest/FBXCTestKit/Configuration/FBXCTestCommandLine.h +++ b/fbxctest/FBXCTestKit/Configuration/FBXCTestCommandLine.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/fbxctest/FBXCTestKit/Configuration/FBXCTestCommandLine.m b/fbxctest/FBXCTestKit/Configuration/FBXCTestCommandLine.m index 4941d0cd0..826158060 100644 --- a/fbxctest/FBXCTestKit/Configuration/FBXCTestCommandLine.m +++ b/fbxctest/FBXCTestKit/Configuration/FBXCTestCommandLine.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -67,7 +67,8 @@ + (nullable instancetype)commandLineFromArguments:(NSArray *)argumen testBundlePath:testBundlePath runnerAppPath:runnerAppPath waitForDebugger:waitForDebugger - timeout:timeout]; + timeout:timeout + architectures: [NSSet setWithArray:@[@"arm64", @"x86_64"]]]; } else if ([argumentSet containsObject:@"-logicTest"]) { configuration = [FBLogicTestConfiguration configurationWithEnvironment:environment @@ -79,7 +80,8 @@ + (nullable instancetype)commandLineFromArguments:(NSArray *)argumen mirroring:FBLogicTestMirrorFileLogs coverageConfiguration:nil binaryPath:nil - logDirectoryPath:nil]; + logDirectoryPath:nil + architectures:[NSSet setWithArray:@[@"arm64", @"x86_64"]]]; } else if ([argumentSet containsObject:@"-appTest"]) { NSMutableDictionary *allEnvironment = [NSProcessInfo.processInfo.environment mutableCopy]; [allEnvironment addEntriesFromDictionary:environment]; diff --git a/fbxctest/FBXCTestKit/Configuration/FBXCTestContext.h b/fbxctest/FBXCTestKit/Configuration/FBXCTestContext.h index 88a4338b5..abba3c5a7 100644 --- a/fbxctest/FBXCTestKit/Configuration/FBXCTestContext.h +++ b/fbxctest/FBXCTestKit/Configuration/FBXCTestContext.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/fbxctest/FBXCTestKit/Configuration/FBXCTestContext.m b/fbxctest/FBXCTestKit/Configuration/FBXCTestContext.m index 8cd2adef8..3388b72a3 100644 --- a/fbxctest/FBXCTestKit/Configuration/FBXCTestContext.m +++ b/fbxctest/FBXCTestKit/Configuration/FBXCTestContext.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/fbxctest/FBXCTestKit/Configuration/FBXCTestDestination.h b/fbxctest/FBXCTestKit/Configuration/FBXCTestDestination.h index 162f608d0..82dcf722e 100644 --- a/fbxctest/FBXCTestKit/Configuration/FBXCTestDestination.h +++ b/fbxctest/FBXCTestKit/Configuration/FBXCTestDestination.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/fbxctest/FBXCTestKit/Configuration/FBXCTestDestination.m b/fbxctest/FBXCTestKit/Configuration/FBXCTestDestination.m index f25b2f5db..cc7626e6a 100644 --- a/fbxctest/FBXCTestKit/Configuration/FBXCTestDestination.m +++ b/fbxctest/FBXCTestKit/Configuration/FBXCTestDestination.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/fbxctest/FBXCTestKit/FBXCTestKit.h b/fbxctest/FBXCTestKit/FBXCTestKit.h index 095bede5c..c626ecd38 100644 --- a/fbxctest/FBXCTestKit/FBXCTestKit.h +++ b/fbxctest/FBXCTestKit/FBXCTestKit.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/fbxctest/FBXCTestKit/Runners/FBTestRunStrategy.h b/fbxctest/FBXCTestKit/Runners/FBTestRunStrategy.h index 4e33d7798..d47d1b3a4 100644 --- a/fbxctest/FBXCTestKit/Runners/FBTestRunStrategy.h +++ b/fbxctest/FBXCTestKit/Runners/FBTestRunStrategy.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/fbxctest/FBXCTestKit/Runners/FBTestRunStrategy.m b/fbxctest/FBXCTestKit/Runners/FBTestRunStrategy.m index 69011a82c..b7f9b18d5 100644 --- a/fbxctest/FBXCTestKit/Runners/FBTestRunStrategy.m +++ b/fbxctest/FBXCTestKit/Runners/FBTestRunStrategy.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -102,7 +102,9 @@ - (instancetype)initWithTarget:(id)target resultBundlePath:nil reportActivities:NO coverageDirectoryPath:nil - logDirectoryPath:nil]; + enableContinuousCoverageCollection:NO + logDirectoryPath:nil + reportResultBundle:NO]; __block id tailLogOperation = nil; FBFuture *executionFinished = [FBManagedTestRunStrategy diff --git a/fbxctest/FBXCTestKit/Runners/FBXCTestBaseRunner.h b/fbxctest/FBXCTestKit/Runners/FBXCTestBaseRunner.h index ad2a55c86..da8995388 100644 --- a/fbxctest/FBXCTestKit/Runners/FBXCTestBaseRunner.h +++ b/fbxctest/FBXCTestKit/Runners/FBXCTestBaseRunner.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/fbxctest/FBXCTestKit/Runners/FBXCTestBaseRunner.m b/fbxctest/FBXCTestKit/Runners/FBXCTestBaseRunner.m index 442d4a11f..daf9dacb9 100644 --- a/fbxctest/FBXCTestKit/Runners/FBXCTestBaseRunner.m +++ b/fbxctest/FBXCTestKit/Runners/FBXCTestBaseRunner.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/fbxctest/FBXCTestKit/Runners/FBXCTestSimulatorFetcher.h b/fbxctest/FBXCTestKit/Runners/FBXCTestSimulatorFetcher.h index b79161a24..b1714e25c 100644 --- a/fbxctest/FBXCTestKit/Runners/FBXCTestSimulatorFetcher.h +++ b/fbxctest/FBXCTestKit/Runners/FBXCTestSimulatorFetcher.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/fbxctest/FBXCTestKit/Runners/FBXCTestSimulatorFetcher.m b/fbxctest/FBXCTestKit/Runners/FBXCTestSimulatorFetcher.m index 3cd7ce135..3ecd862eb 100644 --- a/fbxctest/FBXCTestKit/Runners/FBXCTestSimulatorFetcher.m +++ b/fbxctest/FBXCTestKit/Runners/FBXCTestSimulatorFetcher.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -114,7 +114,7 @@ - (instancetype)initWithSimulatorControl:(FBSimulatorControl *)simulatorControl - (FBFuture *)returnSimulator:(FBSimulator *)simulator { - return [[self.simulatorControl.set deleteSimulator:simulator] mapReplace:NSNull.null]; + return [[self.simulatorControl.set delete:simulator] mapReplace:NSNull.null]; } #pragma mark Private diff --git a/fbxctest/FBXCTestKitTests/Fixtures/FBXCTestKitFixtures.h b/fbxctest/FBXCTestKitTests/Fixtures/FBXCTestKitFixtures.h index 35fc01b19..c808cc392 100644 --- a/fbxctest/FBXCTestKitTests/Fixtures/FBXCTestKitFixtures.h +++ b/fbxctest/FBXCTestKitTests/Fixtures/FBXCTestKitFixtures.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/fbxctest/FBXCTestKitTests/Fixtures/FBXCTestKitFixtures.m b/fbxctest/FBXCTestKitTests/Fixtures/FBXCTestKitFixtures.m index 71d72d6a8..16d151906 100644 --- a/fbxctest/FBXCTestKitTests/Fixtures/FBXCTestKitFixtures.m +++ b/fbxctest/FBXCTestKitTests/Fixtures/FBXCTestKitFixtures.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/fbxctest/FBXCTestKitTests/Tests/Integration/FBXCTestKitIntegrationTests.m b/fbxctest/FBXCTestKitTests/Tests/Integration/FBXCTestKitIntegrationTests.m index a3b90ec9c..df31da9b8 100644 --- a/fbxctest/FBXCTestKitTests/Tests/Integration/FBXCTestKitIntegrationTests.m +++ b/fbxctest/FBXCTestKitTests/Tests/Integration/FBXCTestKitIntegrationTests.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/fbxctest/FBXCTestKitTests/Tests/Unit/FBOSXLogicTestConfigurationTests.m b/fbxctest/FBXCTestKitTests/Tests/Unit/FBOSXLogicTestConfigurationTests.m index db9e2a0fd..86ff589c1 100644 --- a/fbxctest/FBXCTestKitTests/Tests/Unit/FBOSXLogicTestConfigurationTests.m +++ b/fbxctest/FBXCTestKitTests/Tests/Unit/FBOSXLogicTestConfigurationTests.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/fbxctest/FBXCTestKitTests/Tests/Unit/FBOSXUITestConfigurationTests.m b/fbxctest/FBXCTestKitTests/Tests/Unit/FBOSXUITestConfigurationTests.m index 72e82f33d..083ad6437 100644 --- a/fbxctest/FBXCTestKitTests/Tests/Unit/FBOSXUITestConfigurationTests.m +++ b/fbxctest/FBXCTestKitTests/Tests/Unit/FBOSXUITestConfigurationTests.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/fbxctest/FBXCTestKitTests/Tests/Unit/FBiOSApplicationTestConfigurationTests.m b/fbxctest/FBXCTestKitTests/Tests/Unit/FBiOSApplicationTestConfigurationTests.m index fc663e1f8..404e23b3b 100644 --- a/fbxctest/FBXCTestKitTests/Tests/Unit/FBiOSApplicationTestConfigurationTests.m +++ b/fbxctest/FBXCTestKitTests/Tests/Unit/FBiOSApplicationTestConfigurationTests.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/fbxctest/FBXCTestKitTests/Tests/Unit/FBiOSLogicTestConfigurationTests.m b/fbxctest/FBXCTestKitTests/Tests/Unit/FBiOSLogicTestConfigurationTests.m index cc6ef3ee1..42c2e7130 100644 --- a/fbxctest/FBXCTestKitTests/Tests/Unit/FBiOSLogicTestConfigurationTests.m +++ b/fbxctest/FBXCTestKitTests/Tests/Unit/FBiOSLogicTestConfigurationTests.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/fbxctest/FBXCTestKitTests/Tests/Unit/FBiOSUITestConfigurationTests.m b/fbxctest/FBXCTestKitTests/Tests/Unit/FBiOSUITestConfigurationTests.m index f88587b39..d1b856019 100644 --- a/fbxctest/FBXCTestKitTests/Tests/Unit/FBiOSUITestConfigurationTests.m +++ b/fbxctest/FBXCTestKitTests/Tests/Unit/FBiOSUITestConfigurationTests.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/fbxctest/FBXCTestKitTests/Utilities/XCTestCase+FBXCTestKitTests.h b/fbxctest/FBXCTestKitTests/Utilities/XCTestCase+FBXCTestKitTests.h index 9e6dd5d0b..c4a3f041f 100644 --- a/fbxctest/FBXCTestKitTests/Utilities/XCTestCase+FBXCTestKitTests.h +++ b/fbxctest/FBXCTestKitTests/Utilities/XCTestCase+FBXCTestKitTests.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/fbxctest/FBXCTestKitTests/Utilities/XCTestCase+FBXCTestKitTests.m b/fbxctest/FBXCTestKitTests/Utilities/XCTestCase+FBXCTestKitTests.m index 1d46220e8..47821cf40 100644 --- a/fbxctest/FBXCTestKitTests/Utilities/XCTestCase+FBXCTestKitTests.m +++ b/fbxctest/FBXCTestKitTests/Utilities/XCTestCase+FBXCTestKitTests.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/fbxctest/fbxctest/FBXCTestBootstrapper.h b/fbxctest/fbxctest/FBXCTestBootstrapper.h index 8563cb403..ae4508159 100644 --- a/fbxctest/fbxctest/FBXCTestBootstrapper.h +++ b/fbxctest/fbxctest/FBXCTestBootstrapper.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/fbxctest/fbxctest/FBXCTestBootstrapper.m b/fbxctest/fbxctest/FBXCTestBootstrapper.m index fac6eb789..519cba492 100644 --- a/fbxctest/fbxctest/FBXCTestBootstrapper.m +++ b/fbxctest/fbxctest/FBXCTestBootstrapper.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/fbxctest/fbxctest/main.m b/fbxctest/fbxctest/main.m index eb0bde26a..8ff43f6d5 100644 --- a/fbxctest/fbxctest/main.m +++ b/fbxctest/fbxctest/main.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/idb/cli/__init__.py b/idb/cli/__init__.py index f8ae6a556..e509a8eae 100644 --- a/idb/cli/__init__.py +++ b/idb/cli/__init__.py @@ -1,9 +1,11 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + import json import logging import os diff --git a/idb/cli/commands/accessibility.py b/idb/cli/commands/accessibility.py index ce8df5b68..11fdbf400 100644 --- a/idb/cli/commands/accessibility.py +++ b/idb/cli/commands/accessibility.py @@ -1,9 +1,11 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + from argparse import ArgumentParser, Namespace from idb.cli import ClientCommand diff --git a/idb/cli/commands/app.py b/idb/cli/commands/app.py index 7d952790e..bf2ef4515 100644 --- a/idb/cli/commands/app.py +++ b/idb/cli/commands/app.py @@ -1,9 +1,11 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + import json from argparse import ArgumentParser, Namespace from typing import Optional @@ -13,7 +15,7 @@ human_format_installed_app_info, json_format_installed_app_info, ) -from idb.common.types import Client, InstalledArtifact, Compression +from idb.common.types import Client, Compression, InstalledArtifact from idb.utils.typing import none_throws @@ -34,6 +36,13 @@ def add_parser_arguments(self, parser: ArgumentParser) -> None: default=None, required=False, ) + parser.add_argument( + "--override-mtime", + help="If set, idb will disregard the mtime of files contained in an .ipa file. Current timestamp will be used as modification time. Use this flag to ensure app updates work properly when your build system normalises the timestamps of contents of archives.", + action="store_true", + default=None, + required=False, + ) parser.add_argument( "bundle_path", help="Path to the .app/.ipa to install. Note that .app bundles will usually be faster to install than .ipa files.", @@ -50,6 +59,7 @@ async def run_with_client(self, args: Namespace, client: Client) -> None: bundle=args.bundle_path, make_debuggable=args.make_debuggable, compression=compression, + override_modification_time=args.override_mtime, ): artifact = info progress = info.progress diff --git a/idb/cli/commands/approve.py b/idb/cli/commands/approve.py index 74608e4c4..582c80874 100644 --- a/idb/cli/commands/approve.py +++ b/idb/cli/commands/approve.py @@ -1,9 +1,11 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + from argparse import ArgumentParser, Namespace from typing import Dict diff --git a/idb/cli/commands/contacts.py b/idb/cli/commands/contacts.py index 7b3eba852..2a1f84ba5 100644 --- a/idb/cli/commands/contacts.py +++ b/idb/cli/commands/contacts.py @@ -1,9 +1,11 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + from argparse import ArgumentParser, Namespace from idb.cli import ClientCommand diff --git a/idb/cli/commands/crash.py b/idb/cli/commands/crash.py index 634d39a4c..0121f53a0 100644 --- a/idb/cli/commands/crash.py +++ b/idb/cli/commands/crash.py @@ -1,9 +1,11 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + import dataclasses import json from argparse import ArgumentParser, Namespace diff --git a/idb/cli/commands/daemon.py b/idb/cli/commands/daemon.py index 481c9a3b3..fec96a18e 100644 --- a/idb/cli/commands/daemon.py +++ b/idb/cli/commands/daemon.py @@ -1,12 +1,14 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + import json import os -from argparse import SUPPRESS, ArgumentParser, Namespace +from argparse import ArgumentParser, Namespace, SUPPRESS from typing import Dict, Optional from idb.cli import BaseCommand diff --git a/idb/cli/commands/dap.py b/idb/cli/commands/dap.py index 51ccdeef0..125500182 100644 --- a/idb/cli/commands/dap.py +++ b/idb/cli/commands/dap.py @@ -1,13 +1,15 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + import asyncio import sys from argparse import ArgumentParser, Namespace -from asyncio import StreamWriter, StreamReader +from asyncio import StreamReader, StreamWriter from dataclasses import dataclass from idb.cli import ClientCommand diff --git a/idb/cli/commands/debugserver.py b/idb/cli/commands/debugserver.py index 0ba216fc5..dfea67461 100644 --- a/idb/cli/commands/debugserver.py +++ b/idb/cli/commands/debugserver.py @@ -1,9 +1,11 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + from argparse import ArgumentParser, Namespace from idb.cli import ClientCommand diff --git a/idb/cli/commands/dsym.py b/idb/cli/commands/dsym.py index 0e409a808..1899855fc 100644 --- a/idb/cli/commands/dsym.py +++ b/idb/cli/commands/dsym.py @@ -1,14 +1,16 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + import json from argparse import ArgumentParser, Namespace from idb.cli import ClientCommand -from idb.common.types import Client +from idb.common.types import Client, Compression, FileContainerType class DsymInstallCommand(ClientCommand): @@ -32,8 +34,16 @@ def add_parser_arguments(self, parser: ArgumentParser) -> None: super().add_parser_arguments(parser) async def run_with_client(self, args: Namespace, client: Client) -> None: + compression = ( + Compression[args.compression] if args.compression is not None else None + ) + + bundle_type = FileContainerType.APPLICATION if args.bundle_id else None async for install_response in client.install_dsym( - args.dsym_path, args.bundle_id + args.dsym_path, + args.bundle_id, + compression, + bundle_type, ): if install_response.progress != 0.0 and not args.json: print("Installed {install_response.progress}%") diff --git a/idb/cli/commands/dylib.py b/idb/cli/commands/dylib.py index 08a04d656..8a294e6bd 100644 --- a/idb/cli/commands/dylib.py +++ b/idb/cli/commands/dylib.py @@ -1,9 +1,11 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + import json from argparse import ArgumentParser, Namespace diff --git a/idb/cli/commands/file.py b/idb/cli/commands/file.py index e74c1af6f..3804957fe 100644 --- a/idb/cli/commands/file.py +++ b/idb/cli/commands/file.py @@ -1,21 +1,37 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + import json import os import sys import tempfile from abc import abstractmethod -from argparse import ArgumentParser, Namespace -from typing import List +from argparse import _MutuallyExclusiveGroup, ArgumentParser, Namespace +from typing import List, Tuple import aiofiles from idb.cli import ClientCommand from idb.common.signal import signal_handler_event -from idb.common.types import Client, FileContainer, FileContainerType, Compression +from idb.common.types import Client, Compression, FileContainer, FileContainerType + + +def _add_container_types_to_group( + group: _MutuallyExclusiveGroup, containers: List[Tuple[FileContainerType, str]] +) -> None: + for container_type, help_text in containers: + argument_name = container_type.value.replace("_", "-") + group.add_argument( + f"--{argument_name}", + action="store_const", + dest="container_type", + const=container_type, + help=help_text, + ) class FSCommand(ClientCommand): @@ -28,82 +44,50 @@ def add_parser_arguments(self, parser: ArgumentParser) -> None: required=False, default=None, ) - group.add_argument( - "--application", - action="store_const", - dest="container_type", - const=FileContainerType.APPLICATION, - help="Use the container of application containers. Applications containers are presented, by bundle-id in the root.", - ) - group.add_argument( - "--auxillary", - action="store_const", - dest="container_type", - const=FileContainerType.AUXILLARY, - help="Use the auxillary container. This is where idb will store intermediate files.", - ) - group.add_argument( - "--group", - action="store_const", - dest="container_type", - const=FileContainerType.GROUP, - help="Use the group containers. Group containers are shared directories between applications and are prefixed with reverse-domain identifiers (e.g 'group.com.apple.safari')", - ) - group.add_argument( - "--root", - action="store_const", - dest="container_type", - const=FileContainerType.ROOT, - help="Use the root file container", - ) - group.add_argument( - "--media", - action="store_const", - dest="container_type", - const=FileContainerType.MEDIA, - help="Use the media container", - ) - group.add_argument( - "--crashes", - action="store_const", - dest="container_type", - const=FileContainerType.CRASHES, - help="Use the crashes container", - ) - group.add_argument( - "--disk-images", - action="store_const", - dest="container_type", - const=FileContainerType.DISK_IMAGES, - help="Use the disk images", - ) - group.add_argument( - "--provisioning-profiles", - action="store_const", - dest="container_type", - const=FileContainerType.PROVISIONING_PROFILES, - help="Use the provisioning profiles container", - ) - group.add_argument( - "--mdm-profiles", - action="store_const", - dest="container_type", - const=FileContainerType.MDM_PROFILES, - help="Use the mdm profiles container", - ) - group.add_argument( - "--springboard-icons", - action="store_const", - dest="container_type", - const=FileContainerType.SPRINGBOARD_ICONS, - help="Use the springboard icons container", - ) - group.add_argument( - "--wallpaper", - action="store_const", - dest="container_type", - const=FileContainerType.WALLPAPER, - help="Use the wallpaper container", + _add_container_types_to_group( + group, + [ + ( + FileContainerType.APPLICATION, + "Use the container of application containers. Applications containers are presented, by bundle-id in the root.", + ), + ( + FileContainerType.AUXILLARY, + "Use the auxillary container. This is where idb will store intermediate files.", + ), + ( + FileContainerType.GROUP, + "Use the group containers. Group containers are shared directories between applications and are prefixed with reverse-domain identifiers (e.g 'group.com.apple.safari')", + ), + (FileContainerType.ROOT, "Use the root file container"), + (FileContainerType.MEDIA, "Use the media container"), + (FileContainerType.CRASHES, "Use the crashes container"), + (FileContainerType.DISK_IMAGES, "Use the disk images"), + ( + FileContainerType.PROVISIONING_PROFILES, + "Use the provisioning profiles container", + ), + (FileContainerType.MDM_PROFILES, "Use the mdm profiles container"), + ( + FileContainerType.SPRINGBOARD_ICONS, + "Use the springboard icons container", + ), + (FileContainerType.WALLPAPER, "Use the wallpaper container"), + ( + FileContainerType.XCTEST, + "Use the container of installed xctest bundles", + ), + (FileContainerType.DYLIB, "Use the container of installed dylibs"), + (FileContainerType.DSYM, "Use the container of installed dsyms"), + ( + FileContainerType.FRAMEWORK, + "Use the container of installed frameworks", + ), + ( + FileContainerType.SYMBOLS, + "Use the container of target-provided symbols/dyld cache", + ), + ], ) super().add_parser_arguments(parser) diff --git a/idb/cli/commands/focus.py b/idb/cli/commands/focus.py index e8d08dfb5..7c2075f4a 100644 --- a/idb/cli/commands/focus.py +++ b/idb/cli/commands/focus.py @@ -1,9 +1,11 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + from argparse import Namespace from idb.cli import ClientCommand diff --git a/idb/cli/commands/framework.py b/idb/cli/commands/framework.py index 008ab1cbe..f89de6310 100644 --- a/idb/cli/commands/framework.py +++ b/idb/cli/commands/framework.py @@ -1,9 +1,11 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + import json from argparse import ArgumentParser, Namespace diff --git a/idb/cli/commands/hid.py b/idb/cli/commands/hid.py index 743db5b4b..f3df9dc82 100644 --- a/idb/cli/commands/hid.py +++ b/idb/cli/commands/hid.py @@ -1,9 +1,11 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + from argparse import ArgumentParser, Namespace from idb.cli import ClientCommand diff --git a/idb/cli/commands/instruments.py b/idb/cli/commands/instruments.py index 60bc05c26..3b4fe26d5 100644 --- a/idb/cli/commands/instruments.py +++ b/idb/cli/commands/instruments.py @@ -1,14 +1,16 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + import os from argparse import ArgumentParser, Namespace from idb.cli import ClientCommand -from idb.common.args import KeyValueDictAppendAction, find_next_file_prefix +from idb.common.args import find_next_file_prefix, KeyValueDictAppendAction from idb.common.misc import get_env_with_idb_prefix from idb.common.signal import signal_handler_event from idb.common.types import Client, InstrumentsTimings diff --git a/idb/cli/commands/keychain.py b/idb/cli/commands/keychain.py index 0584d46a2..6d9bec001 100644 --- a/idb/cli/commands/keychain.py +++ b/idb/cli/commands/keychain.py @@ -1,9 +1,11 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + from argparse import Namespace from idb.cli import ClientCommand diff --git a/idb/cli/commands/kill.py b/idb/cli/commands/kill.py index b76681125..d19da0f20 100644 --- a/idb/cli/commands/kill.py +++ b/idb/cli/commands/kill.py @@ -1,9 +1,11 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + from argparse import Namespace from idb.cli import ManagementCommand diff --git a/idb/cli/commands/launch.py b/idb/cli/commands/launch.py index d41c78b59..4bd68e20e 100644 --- a/idb/cli/commands/launch.py +++ b/idb/cli/commands/launch.py @@ -1,10 +1,12 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. -from argparse import REMAINDER, ArgumentParser, Namespace +# pyre-strict + +from argparse import ArgumentParser, Namespace, REMAINDER from idb.cli import ClientCommand from idb.common.misc import get_env_with_idb_prefix @@ -52,6 +54,12 @@ def add_parser_arguments(self, parser: ArgumentParser) -> None: help="Wait for the process to exit, tailing all output from the app", action="store_true", ) + parser.add_argument( + "-p", + "--pid-file", + help="launched app pid will be written into the specified file", + type=str, + ) super().add_parser_arguments(parser) async def run_with_client(self, args: Namespace, client: Client) -> None: @@ -62,4 +70,5 @@ async def run_with_client(self, args: Namespace, client: Client) -> None: foreground_if_running=args.foreground_if_running, wait_for_debugger=args.wait_for_debugger, stop=signal_handler_event("launch") if args.wait_for else None, + pid_file=args.pid_file, ) diff --git a/idb/cli/commands/location.py b/idb/cli/commands/location.py index d20ebe591..f6eb517f3 100644 --- a/idb/cli/commands/location.py +++ b/idb/cli/commands/location.py @@ -1,9 +1,11 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + from argparse import ArgumentParser, Namespace from idb.cli import ClientCommand diff --git a/idb/cli/commands/log.py b/idb/cli/commands/log.py index dae946f0c..24b6d6bf1 100644 --- a/idb/cli/commands/log.py +++ b/idb/cli/commands/log.py @@ -1,10 +1,12 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. -from argparse import REMAINDER, ArgumentParser, Namespace +# pyre-strict + +from argparse import ArgumentParser, Namespace, REMAINDER from typing import List, Optional from idb.cli import ClientCommand diff --git a/idb/cli/commands/media.py b/idb/cli/commands/media.py index be386ac34..0a1041f99 100644 --- a/idb/cli/commands/media.py +++ b/idb/cli/commands/media.py @@ -1,9 +1,11 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + from argparse import ArgumentParser, Namespace from idb.cli import ClientCommand diff --git a/idb/cli/commands/memory.py b/idb/cli/commands/memory.py index 09ee2b654..f985e8878 100644 --- a/idb/cli/commands/memory.py +++ b/idb/cli/commands/memory.py @@ -1,9 +1,11 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + from argparse import Namespace from idb.cli import ClientCommand diff --git a/idb/cli/commands/notification.py b/idb/cli/commands/notification.py index e537e1e0b..3f59a1688 100644 --- a/idb/cli/commands/notification.py +++ b/idb/cli/commands/notification.py @@ -1,9 +1,11 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + from argparse import ArgumentParser, Namespace from idb.cli import ClientCommand diff --git a/idb/cli/commands/revoke.py b/idb/cli/commands/revoke.py new file mode 100644 index 000000000..cbe03b730 --- /dev/null +++ b/idb/cli/commands/revoke.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python3 +# Copyright (c) Meta Platforms, Inc. and affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +# pyre-strict + +from argparse import ArgumentParser, Namespace +from typing import Dict + +from idb.cli import ClientCommand +from idb.common.types import Client, Permission + + +_ARG_TO_ENUM: Dict[str, Permission] = { + key.lower(): value for (key, value) in Permission.__members__.items() +} + + +class RevokeCommand(ClientCommand): + @property + def description(self) -> str: + return "Revoke permissions for an app" + + @property + def name(self) -> str: + return "revoke" + + def add_parser_arguments(self, parser: ArgumentParser) -> None: + parser.add_argument("bundle_id", help="App's bundle id", type=str) + parser.add_argument( + "permissions", + nargs="+", + help="Permissions to revoke", + choices=_ARG_TO_ENUM.keys(), + ) + parser.add_argument( + "--scheme", help="Url scheme registered by the app to revoke", type=str + ) + super().add_parser_arguments(parser) + + async def run_with_client(self, args: Namespace, client: Client) -> None: + if "url" in args.permissions and not args.scheme: + print("You need to specify --scheme when revoking url permissions") + exit(1) + await client.revoke( + bundle_id=args.bundle_id, + permissions={ + _ARG_TO_ENUM[permission_name] for permission_name in args.permissions + }, + scheme=args.scheme, + ) diff --git a/idb/cli/commands/screenshot.py b/idb/cli/commands/screenshot.py index 457337d88..0495f2451 100644 --- a/idb/cli/commands/screenshot.py +++ b/idb/cli/commands/screenshot.py @@ -1,9 +1,11 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + import sys from argparse import ArgumentParser, Namespace from contextlib import contextmanager diff --git a/idb/cli/commands/settings.py b/idb/cli/commands/settings.py index c5b4f357f..3b49a9c7b 100644 --- a/idb/cli/commands/settings.py +++ b/idb/cli/commands/settings.py @@ -1,16 +1,17 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + from argparse import ArgumentParser, Namespace from idb.cli import ClientCommand from idb.common.command import CommandGroup from idb.common.types import Client - _ENABLE = "enable" _DISABLE = "disable" @@ -36,6 +37,13 @@ def add_parser_arguments(self, parser: ArgumentParser) -> None: help="Preference name", type=str, ) + parser.add_argument( + "--type", + help="Specifies the type of the value to be set, for supported types see 'defaults get help' defaults to string. " + "Example of usage: idb set --domain com.apple.suggestions.plist SuggestionsAppLibraryEnabled --type bool true", + type=str, + default="string", + ) parser.add_argument( "value", help="Preference value", @@ -58,7 +66,10 @@ async def run_with_client(self, args: Namespace, client: Client) -> None: await client.set_hardware_keyboard(args.value == _ENABLE) else: await client.set_preference( - name=args.name, value=args.value, domain=args.domain + name=args.name, + value=args.value, + value_type=args.type, + domain=args.domain, ) diff --git a/idb/cli/commands/shell.py b/idb/cli/commands/shell.py index 8b6f5566f..0b7705b07 100644 --- a/idb/cli/commands/shell.py +++ b/idb/cli/commands/shell.py @@ -1,9 +1,11 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + import shlex import sys from argparse import ArgumentParser, Namespace @@ -11,8 +13,7 @@ from idb.cli import ClientCommand from idb.common.command import CommandGroup -from idb.common.types import Client -from idb.common.types import IdbException +from idb.common.types import Client, IdbException from idb.utils.typing import none_throws @@ -24,7 +25,7 @@ def __init__(self, parser: ArgumentParser) -> None: @property def description(self) -> str: - return "Interactive shell" + return "Interactive shell which allows you to chain multiple IDB commands (doesn't open a shell on the simulator)" @property def name(self) -> str: diff --git a/idb/cli/commands/target.py b/idb/cli/commands/target.py index d7f9ee268..85b4bdc14 100644 --- a/idb/cli/commands/target.py +++ b/idb/cli/commands/target.py @@ -1,19 +1,27 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + import json -from argparse import SUPPRESS, ArgumentParser, Namespace -from typing import Union, Mapping +from argparse import ArgumentParser, Namespace, SUPPRESS +from typing import Mapping, Union import idb.common.plugin as plugin from idb.cli import ClientCommand, CompanionCommand, ManagementCommand from idb.common.format import human_format_target_info, json_format_target_info from idb.common.signal import signal_handler_event -from idb.common.types import Client, ClientManager, Companion, IdbException, TCPAddress -from idb.common.types import TargetType +from idb.common.types import ( + Client, + ClientManager, + Companion, + IdbException, + TargetType, + TCPAddress, +) from idb.common.udid import is_udid @@ -291,7 +299,7 @@ async def run_with_companion(self, args: Namespace, companion: Companion) -> Non class TargetCloneCommand(UDIDTargetedCompanionCommand): @property def description(self) -> str: - return "Erases the simulator (only works on mac)" + return "Clones the simulator (only works on mac)" @property def name(self) -> str: diff --git a/idb/cli/commands/url.py b/idb/cli/commands/url.py index 690a44f72..89d976a28 100644 --- a/idb/cli/commands/url.py +++ b/idb/cli/commands/url.py @@ -1,9 +1,11 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + from argparse import ArgumentParser, Namespace from idb.cli import ClientCommand diff --git a/idb/cli/commands/video.py b/idb/cli/commands/video.py index 612504c34..894ad6b23 100644 --- a/idb/cli/commands/video.py +++ b/idb/cli/commands/video.py @@ -1,9 +1,11 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + import sys from argparse import ArgumentParser, Namespace from typing import Dict, List diff --git a/idb/cli/commands/xctest.py b/idb/cli/commands/xctest.py index 97404e6c0..9032996ac 100644 --- a/idb/cli/commands/xctest.py +++ b/idb/cli/commands/xctest.py @@ -1,11 +1,15 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + import json -from argparse import REMAINDER, ArgumentParser, Namespace +import os.path +import sys +from argparse import ArgumentParser, Namespace, REMAINDER from pathlib import Path from typing import Optional, Set @@ -18,7 +22,9 @@ json_format_test_info, ) from idb.common.misc import get_env_with_idb_prefix -from idb.common.types import Client, CodeCoverageFormat, ExitWithCodeException +from idb.common.types import Client, CodeCoverageFormat, FileContainerType, IdbException + +NO_SPECIFIED_PATH = "NO_SPECIFIED_PATH" class XctestInstallCommand(ClientCommand): @@ -34,10 +40,19 @@ def add_parser_arguments(self, parser: ArgumentParser) -> None: parser.add_argument( "test_bundle_path", help="Bundle path of the test bundle", type=str ) + parser.add_argument( + "--skip-signing-bundles", + help="idb will skip signing the test and/or apps bundles", + action="store_true", + default=None, + required=False, + ) super().add_parser_arguments(parser) async def run_with_client(self, args: Namespace, client: Client) -> None: - async for install_response in client.install_xctest(args.test_bundle_path): + async for install_response in client.install_xctest( + args.test_bundle_path, args.skip_signing_bundles + ): if install_response.progress != 0.0 and not args.json: print("Installed {install_response.progress}%") elif args.json: @@ -166,6 +181,11 @@ def add_parser_arguments(self, parser: ArgumentParser) -> None: "--coverage-output-path", help="Outputs code coverage information. See --coverage-format option.", ) + parser.add_argument( + "--enable-continuous-coverage-collection", + action="store_true", + help="Enable continuous coverage collection mode in llvm", + ) parser.add_argument( "--coverage-format", choices=[str(key) for (key, _) in CodeCoverageFormat.__members__.items()], @@ -191,31 +211,59 @@ def add_parser_arguments(self, parser: ArgumentParser) -> None: "to be paths instead. They are installed before running.", action="store_true", ) + parser.add_argument( + "--install-dsym-test-bundle", + default=None, + type=str, + nargs="?", + const=NO_SPECIFIED_PATH, + help="Install debug symbols together with bundle. Specify path for debug symbols; otherwise, we'll try to infer it. (requires --install)", + ) + parser.add_argument( + "--skip-signing-bundles", + help="idb will skip signing the test and/or apps bundles", + action="store_true", + default=None, + required=False, + ) super().add_parser_arguments(parser) async def run_with_client(self, args: Namespace, client: Client) -> None: await super().run_with_client(args, client) + + is_ui = args.run == "ui" + is_logic = args.run == "logic" + is_app = args.run == "app" + if args.install: + # Note for --install specified, test_bundle_id is a path initially, but + # `install_bundles` will override it. + test_bundle_location = args.test_bundle_id + await self.install_bundles(args, client) + if args.install_dsym_test_bundle: + if is_ui or is_app: + print( + "--install-dsym-test-bundle is experimental for ui and app tests; this flag is only supported for logic tests.", + file=sys.stderr, + ) + await self.install_dsym_test_bundle(args, client, test_bundle_location) + tests_to_run = self.get_tests_to_run(args) tests_to_skip = self.get_tests_to_skip(args) - app_bundle_id = args.app_bundle_id if hasattr(args, "app_bundle_id") else None + app_bundle_id = getattr(args, "app_bundle_id", None) test_host_app_bundle_id = ( args.test_host_app_bundle_id if hasattr(args, "test_host_app_bundle_id") else None ) arguments = getattr(args, "test_arguments", []) - is_ui = args.run == "ui" - is_logic = args.run == "logic" - if args.wait_for_debugger and is_ui: print( "--wait_for_debugger flag is NOT supported for ui tests. It will default to False" ) formatter = json_format_test_info if args.json else human_format_test_info - crashed_outside_test_case = False coverage_format = CodeCoverageFormat[args.coverage_format] async for test_result in client.run_xctest( @@ -234,21 +282,44 @@ async def run_with_client(self, args: Namespace, client: Client) -> None: report_attachments=args.report_attachments, activities_output_path=args.activities_output_path, coverage_output_path=args.coverage_output_path, + enable_continuous_coverage_collection=args.enable_continuous_coverage_collection, coverage_format=coverage_format, log_directory_path=args.log_directory_path, wait_for_debugger=args.wait_for_debugger, ): print(formatter(test_result)) - crashed_outside_test_case = ( - crashed_outside_test_case or test_result.crashed_outside_test_case - ) - if crashed_outside_test_case: - raise ExitWithCodeException(3) async def install_bundles(self, args: Namespace, client: Client) -> None: - async for test in client.install_xctest(args.test_bundle_id): + async for test in client.install_xctest( + args.test_bundle_id, args.skip_signing_bundles + ): args.test_bundle_id = test.name + async def install_dsym_test_bundle( + self, args: Namespace, client: Client, test_bundle_location: str + ) -> Optional[str]: + dsym_name = None + dsym_path_location = args.install_dsym_test_bundle + if args.install_dsym_test_bundle == NO_SPECIFIED_PATH: + dsym_path_location = test_bundle_location + ".dSYM" + + if not os.path.exists(dsym_path_location): + raise IdbException( + "XCTest run failed! Error: --install-dsym flag was used but there is no file at location {}.".format( + dsym_path_location + ) + ) + + async for install_response in client.install_dsym( + dsym=dsym_path_location, + bundle_id=args.test_bundle_id, + bundle_type=FileContainerType.XCTEST, + compression=None, + ): + if install_response.progress == 0.0: + dsym_name = install_response.name + return dsym_name + def get_tests_to_run(self, args: Namespace) -> Optional[Set[str]]: return None diff --git a/idb/cli/commands/xctrace.py b/idb/cli/commands/xctrace.py index 4fa0eea8b..33ac28010 100644 --- a/idb/cli/commands/xctrace.py +++ b/idb/cli/commands/xctrace.py @@ -1,14 +1,16 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + import os from argparse import ArgumentParser, Namespace from idb.cli import ClientCommand -from idb.common.args import KeyValueDictAppendAction, find_next_file_prefix +from idb.common.args import find_next_file_prefix, KeyValueDictAppendAction from idb.common.misc import get_env_with_idb_prefix from idb.common.signal import signal_handler_event from idb.common.types import Client diff --git a/idb/cli/main.py b/idb/cli/main.py index 6aa639147..60b844284 100644 --- a/idb/cli/main.py +++ b/idb/cli/main.py @@ -1,9 +1,11 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + import argparse import asyncio import concurrent.futures @@ -11,7 +13,7 @@ import os import shutil import sys -from typing import List, Optional, Set +from typing import List, Optional, Set, Union import idb.common.plugin as plugin from idb.cli.commands.accessibility import ( @@ -41,15 +43,15 @@ from idb.cli.commands.dsym import DsymInstallCommand from idb.cli.commands.dylib import DylibInstallCommand from idb.cli.commands.file import ( + FBSReadCommand, FSListCommand, FSMkdirCommand, FSMoveCommand, FSPullCommand, FSPushCommand, - FSWriteCommand, FSRemoveCommand, FSTailCommand, - FBSReadCommand, + FSWriteCommand, ) from idb.cli.commands.focus import FocusCommand from idb.cli.commands.framework import FrameworkInstallCommand @@ -70,11 +72,12 @@ from idb.cli.commands.media import MediaAddCommand from idb.cli.commands.memory import SimulateMemoryWarningCommand from idb.cli.commands.notification import SendNotificationCommand +from idb.cli.commands.revoke import RevokeCommand from idb.cli.commands.screenshot import ScreenshotCommand from idb.cli.commands.settings import ( - SetPreferenceCommand, GetPreferenceCommand, ListCommand, + SetPreferenceCommand, ) from idb.cli.commands.shell import ShellCommand from idb.cli.commands.target import ( @@ -101,7 +104,7 @@ ) from idb.cli.commands.xctrace import XctraceRecordCommand from idb.common.command import Command, CommandGroup -from idb.common.types import IdbException, ExitWithCodeException, Compression +from idb.common.types import Compression, IdbException COROUTINE_DRAIN_TIMEOUT = 2 @@ -120,7 +123,10 @@ def get_default_companion_path() -> Optional[str]: return shutil.which("idb_companion") or "/usr/local/bin/idb_companion" -async def gen_main(cmd_input: Optional[List[str]] = None) -> int: +SysExitArg = Union[int, str, None] + + +async def gen_main(cmd_input: Optional[List[str]] = None) -> SysExitArg: # Make sure all files are created with global rw permissions os.umask(0o000) # Setup parser @@ -145,6 +151,7 @@ async def gen_main(cmd_input: Optional[List[str]] = None) -> int: "Compressor should be available at this host. " "Decompressor should be available at the destination site (where IDB companion is hosted)", ) + parser.add_argument( "--companion", type=str, @@ -223,6 +230,7 @@ async def gen_main(cmd_input: Optional[List[str]] = None) -> int: SimulateMemoryWarningCommand(), SendNotificationCommand(), ApproveCommand(), + RevokeCommand(), TargetConnectCommand(), TargetDisconnectCommand(), TargetListCommand(), @@ -318,8 +326,6 @@ async def gen_main(cmd_input: Optional[List[str]] = None) -> int: except IdbException as e: print(e.args[0], file=sys.stderr) return 1 - except ExitWithCodeException as e: - return e.exit_code except SystemExit as e: return e.code except Exception: @@ -349,7 +355,7 @@ async def drain_coroutines(pending: Set[asyncio.Task]) -> None: pass -def main(cmd_input: Optional[List[str]] = None) -> int: +def main(cmd_input: Optional[List[str]] = None) -> SysExitArg: loop = asyncio.get_event_loop() try: return loop.run_until_complete(gen_main(cmd_input)) @@ -357,5 +363,9 @@ def main(cmd_input: Optional[List[str]] = None) -> int: loop.close() -if __name__ == "__main__": +def main_2() -> None: sys.exit(main()) + + +if __name__ == "__main__": + main_2() diff --git a/idb/cli/tests/connect_tests.py b/idb/cli/tests/connect_tests.py index f347fa8af..b8983245d 100644 --- a/idb/cli/tests/connect_tests.py +++ b/idb/cli/tests/connect_tests.py @@ -1,14 +1,16 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + from argparse import Namespace from idb.cli.commands.target import get_destination from idb.common.types import TCPAddress -from idb.utils.testing import TestCase, ignoreTaskLeaks +from idb.utils.testing import ignoreTaskLeaks, TestCase @ignoreTaskLeaks diff --git a/idb/cli/tests/parser_tests.py b/idb/cli/tests/parser_tests.py index 56453c2cc..bf3072d55 100644 --- a/idb/cli/tests/parser_tests.py +++ b/idb/cli/tests/parser_tests.py @@ -1,9 +1,11 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + import asyncio import os import sys @@ -11,6 +13,7 @@ from typing import Any, Optional, Tuple, TypeVar from unittest.mock import ANY, MagicMock, patch +from idb.cli.commands.xctest import NO_SPECIFIED_PATH from idb.cli.main import gen_main as cli_main from idb.common.types import ( Compression, @@ -91,6 +94,25 @@ async def test_launch_with_udid(self) -> None: foreground_if_running=False, wait_for_debugger=False, stop=None, + pid_file=None, + ) + + async def test_launch_with_pid_file(self) -> None: + bundle_id = "com.foo.app" + udid = "my udid" + pid_file = "/tmp/fifo-file" + self.client_mock.launch = AsyncMock(return_value=bundle_id) + await cli_main( + cmd_input=["launch", "--pid-file", pid_file, "--udid", udid, bundle_id] + ) + self.client_mock.launch.assert_called_once_with( + bundle_id=bundle_id, + env={}, + args=[], + foreground_if_running=False, + wait_for_debugger=False, + stop=None, + pid_file=pid_file, ) async def test_create(self) -> None: @@ -151,7 +173,22 @@ async def test_install(self) -> None: compression = None await cli_main(cmd_input=["install", app_path]) self.client_mock.install.assert_called_once_with( - bundle=app_path, make_debuggable=None, compression=compression + bundle=app_path, + make_debuggable=None, + compression=compression, + override_modification_time=None, + ) + + async def test_install_with_mtime_override(self) -> None: + self.client_mock.install = MagicMock(return_value=AsyncGeneratorMock()) + app_path = "testApp.ipa" + compression = None + await cli_main(cmd_input=["install", "--override-mtime", app_path]) + self.client_mock.install.assert_called_once_with( + bundle=app_path, + make_debuggable=None, + compression=compression, + override_modification_time=True, ) async def test_install_with_bad_compression(self) -> None: @@ -168,7 +205,10 @@ async def test_install_with_compression(self) -> None: app_path = "testApp.app" await cli_main(cmd_input=["--compression", "ZSTD", "install", app_path]) self.client_mock.install.assert_called_once_with( - bundle=app_path, make_debuggable=None, compression=Compression.ZSTD + bundle=app_path, + make_debuggable=None, + compression=Compression.ZSTD, + override_modification_time=None, ) async def test_uninstall(self) -> None: @@ -423,7 +463,7 @@ async def test_xctest_install(self) -> None: self.client_mock.install_xctest = MagicMock(return_value=AsyncGeneratorMock()) test_bundle_path = "testBundle.xctest" await cli_main(cmd_input=["xctest", "install", test_bundle_path]) - self.client_mock.install_xctest.assert_called_once_with(test_bundle_path) + self.client_mock.install_xctest.assert_called_once_with(test_bundle_path, None) def xctest_run_namespace(self, command: str, test_bundle_id: str) -> Namespace: namespace = Namespace() @@ -451,11 +491,14 @@ def xctest_run_namespace(self, command: str, test_bundle_id: str) -> Namespace: namespace.report_attachments = False namespace.activities_output_path = None namespace.coverage_output_path = None + namespace.enable_continuous_coverage_collection = False namespace.coverage_format = "EXPORTED" namespace.log_directory_path = None namespace.wait_for_debugger = False namespace.install = False namespace.companion_tls = False + namespace.install_dsym_test_bundle = None + namespace.skip_signing_bundles = None return namespace async def test_xctest_run_app(self) -> None: @@ -524,6 +567,69 @@ async def test_xctest_list_bundles(self) -> None: test_bundle_id=bundle_id, app_path=None ) + async def test_xctest_run_logic_with_install(self) -> None: + mock = AsyncMock() + mock.return_value = [] + with patch( + "idb.cli.commands.xctest.CommonRunXcTestCommand.run", new=mock, create=True + ): + test_bundle_path = "/bundle/path" + await cli_main( + cmd_input=["xctest", "run", "logic", "--install", test_bundle_path] + ) + namespace = self.xctest_run_namespace("logic", test_bundle_path) + namespace.install = True + namespace.timeout = None + mock.assert_called_once_with(namespace) + + async def test_xctest_run_logic_with_install_dsym_test_bundle(self) -> None: + mock = AsyncMock() + mock.return_value = [] + with patch( + "idb.cli.commands.xctest.CommonRunXcTestCommand.run", new=mock, create=True + ): + test_bundle_path = "/bundle/path" + test_dsym_path = "/dsym/path" + await cli_main( + cmd_input=[ + "xctest", + "run", + "logic", + "--install-dsym", + test_dsym_path, + "--install", + test_bundle_path, + ] + ) + namespace = self.xctest_run_namespace("logic", test_bundle_path) + namespace.install_dsym_test_bundle = test_dsym_path + namespace.install = True + namespace.timeout = None + mock.assert_called_once_with(namespace) + + async def test_xctest_run_logic_with_install_dsym_no_path(self) -> None: + mock = AsyncMock() + mock.return_value = [] + with patch( + "idb.cli.commands.xctest.CommonRunXcTestCommand.run", new=mock, create=True + ): + test_bundle_path = "/bundle/path" + await cli_main( + cmd_input=[ + "xctest", + "run", + "logic", + "--install-dsym", + "--install", + test_bundle_path, + ] + ) + namespace = self.xctest_run_namespace("logic", test_bundle_path) + namespace.install_dsym_test_bundle = NO_SPECIFIED_PATH + namespace.install = True + namespace.timeout = None + mock.assert_called_once_with(namespace) + async def test_daemon(self) -> None: mock = AsyncMock() with patch( @@ -626,6 +732,22 @@ async def test_approve_url(self) -> None: bundle_id=bundle_id, permissions={Permission.URL}, scheme="fb" ) + async def test_revoke(self) -> None: + self.client_mock.revoke = AsyncMock(return_value=[]) + bundle_id = "com.fb.myApp" + await cli_main(cmd_input=["revoke", bundle_id, "photos"]) + self.client_mock.revoke.assert_called_once_with( + bundle_id=bundle_id, permissions={Permission.PHOTOS}, scheme=None + ) + + async def test_revoke_url(self) -> None: + self.client_mock.revoke = AsyncMock(return_value=[]) + bundle_id = "com.fb.myApp" + await cli_main(cmd_input=["revoke", bundle_id, "url", "--scheme", "fb"]) + self.client_mock.revoke.assert_called_once_with( + bundle_id=bundle_id, permissions={Permission.URL}, scheme="fb" + ) + async def test_video_record(self) -> None: mock = AsyncMock() with patch( @@ -753,7 +875,7 @@ async def test_accessibility_info_at_point(self) -> None: point=(10, 20), nested=False ) - async def test_accessibility_info_at_point(self) -> None: + async def test_accessibility_info_at_point_nested(self) -> None: self.client_mock.accessibility_info = AsyncMock() await cli_main(cmd_input=["ui", "describe-point", "--nested", "10", "20"]) self.client_mock.accessibility_info.assert_called_once_with( diff --git a/idb/common/args.py b/idb/common/args.py index ef615cac9..751415055 100644 --- a/idb/common/args.py +++ b/idb/common/args.py @@ -1,9 +1,11 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + import argparse import os from typing import List, Optional diff --git a/idb/common/command.py b/idb/common/command.py index 1d8e2ebfe..cd92de424 100644 --- a/idb/common/command.py +++ b/idb/common/command.py @@ -1,9 +1,11 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + from abc import ABCMeta, abstractmethod from argparse import ArgumentParser, Namespace from typing import Dict, List, Optional @@ -20,21 +22,17 @@ def allow_unknown_args(self) -> bool: @property @abstractmethod - def description(self) -> str: - ... + def description(self) -> str: ... @property @abstractmethod - def name(self) -> str: - ... + def name(self) -> str: ... @abstractmethod - def add_parser_arguments(self, parser: ArgumentParser) -> None: - ... + def add_parser_arguments(self, parser: ArgumentParser) -> None: ... @abstractmethod - async def run(self, args: Namespace) -> None: - ... + async def run(self, args: Namespace) -> None: ... def resolve_command_from_args(self, args: Namespace) -> "Command": return self diff --git a/idb/common/companion.py b/idb/common/companion.py index e60b19152..de2454753 100644 --- a/idb/common/companion.py +++ b/idb/common/companion.py @@ -1,9 +1,11 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + import asyncio import json import logging @@ -11,8 +13,8 @@ import subprocess from dataclasses import dataclass from datetime import timedelta -from logging import Logger, DEBUG as LOG_LEVEL_DEBUG -from typing import AsyncGenerator, Dict, List, Optional, Sequence, Union, Tuple +from logging import DEBUG as LOG_LEVEL_DEBUG, Logger +from typing import AsyncGenerator, Dict, List, Optional, Sequence, Tuple, Union from idb.common.constants import IDB_LOGS_PATH from idb.common.file import get_last_n_lines @@ -22,6 +24,7 @@ ) from idb.common.logging import log_call from idb.common.types import ( + Architecture, Companion as CompanionBase, ECIDFilter, IdbException, @@ -38,6 +41,9 @@ DEFAULT_COMPANION_TEARDOWN_TIMEOUT = timedelta(seconds=30) +CompanionReport = Dict[str, Union[int, str]] + + class IdbJsonException(Exception): pass @@ -84,26 +90,60 @@ def parse_json_line(line: bytes) -> Dict[str, Union[int, str]]: async def _extract_companion_report_from_spawned_companion( - stream: asyncio.StreamReader, -) -> Dict[str, Union[int, str]]: - # The first line of stdout should contain launch info, - # otherwise something bad has happened - line = await stream.readline() - logging.debug(f"Read line from companion: {line}") - update = parse_json_line(line) - logging.debug(f"Got update from companion: {update}") - return update - - -async def _extract_port_from_spawned_companion(stream: asyncio.StreamReader) -> int: - update = await _extract_companion_report_from_spawned_companion(stream=stream) - return int(update["grpc_port"]) + stream: asyncio.StreamReader, log_file_path: str +) -> CompanionReport: + try: + # The first line of stdout should contain launch info, + # otherwise something bad has happened + line = await stream.readline() + logging.debug(f"Read line from companion: {line}") + update = parse_json_line(line) + logging.debug(f"Got update from companion: {update}") + return update + except Exception as e: + raise CompanionSpawnerException( + f"Failed to spawn companion, couldn't read report " + f"stderr: {get_last_n_lines(log_file_path, 30)}" + ) from e + + +async def _verify_port_from_spawned_companion( + report: CompanionReport, + port_name: str, + log_file_path: str, + expected_port: Optional[int], +) -> int: + try: + extracted_port = int(report[port_name]) + except Exception as e: + raise CompanionSpawnerException( + f"Failed to spawn companion, couldn't read {port_name} output " + f"stderr: {get_last_n_lines(log_file_path, 30)}" + ) from e + if extracted_port == 0: + raise CompanionSpawnerException( + f"Failed to spawn companion, {port_name} zero is invalid " + f"stderr: {get_last_n_lines(log_file_path, 30)}" + ) + if ( + expected_port is not None + and expected_port != 0 + and extracted_port != expected_port + ): + raise CompanionSpawnerException( + f"Failed to spawn companion, invalid {port_name} " + f"(expected {expected_port} got {extracted_port})" + f"stderr: {get_last_n_lines(log_file_path, 30)}" + ) + return extracted_port async def _extract_domain_sock_from_spawned_companion( - stream: asyncio.StreamReader, + stream: asyncio.StreamReader, log_file_path: str ) -> str: - update = await _extract_companion_report_from_spawned_companion(stream=stream) + update = await _extract_companion_report_from_spawned_companion( + stream=stream, log_file_path=log_file_path + ) return str(update["grpc_path"]) @@ -119,20 +159,32 @@ class CompanionServerConfig: class Companion(CompanionBase): def __init__( - self, companion_path: str, device_set_path: Optional[str], logger: Logger + self, + companion_path: str, + device_set_path: Optional[str], + logger: Logger, + architecture: Architecture = Architecture.ANY, + only: Optional[OnlyFilter] = None, ) -> None: self._companion_path = companion_path self._device_set_path = device_set_path self._logger = logger + self._architecture = architecture + self._only = only @asynccontextmanager async def _start_companion_command( self, arguments: List[str] ) -> AsyncGenerator[asyncio.subprocess.Process, None]: - cmd: List[str] = [self._companion_path] + cmd: List[str] = [] + if self._architecture != Architecture.ANY: + cmd = ["arch", "-" + self._architecture.value] + cmd += [self._companion_path] device_set_path = self._device_set_path if device_set_path is not None: cmd.extend(["--device-set-path", device_set_path]) + if self._only is not None: + cmd.extend(_only_arg_from_filter(only=self._only)) cmd.extend(arguments) process = await asyncio.create_subprocess_exec( *cmd, @@ -143,7 +195,7 @@ async def _start_companion_command( else subprocess.DEVNULL ), ) - logger = self._logger.getChild(f"{process.pid}:{' '.join(arguments)}") + logger = self._logger.getChild(f"{process.pid}:{' '.join(cmd)}") logger.info("Launched process") try: yield process @@ -164,7 +216,9 @@ async def _run_companion_command( process.communicate(), timeout=timeout.total_seconds() ) if process.returncode != 0: - raise IdbException(f"Failed to run {arguments}") + message = f"Failed to run {arguments}" + self._logger.error(f"{message}. Output: [[{output}]]") + raise IdbException(message) self._logger.info(f"Ran {arguments} successfully.") return output.decode() except asyncio.TimeoutError: @@ -193,6 +247,7 @@ def _log_file_path(self, target_udid: str) -> str: async def _spawn_server( self, config: CompanionServerConfig, + port_env_variables: Dict[str, str], bind_arguments: List[str], ) -> Tuple[asyncio.subprocess.Process, str]: if os.getuid() == 0: @@ -201,7 +256,10 @@ async def _spawn_server( "Listing available targets on this host and spawning " "companions will not work" ) - arguments: List[str] = ( + arguments: List[str] = [] + if self._architecture != Architecture.ANY: + arguments = ["arch", "-" + self._architecture.value] + arguments += ( [ self._companion_path, "--udid", @@ -220,6 +278,8 @@ async def _spawn_server( env = dict(os.environ) if config.tmp_path: env["TMPDIR"] = config.tmp_path + if port_env_variables: + env.update(port_env_variables) with open(log_file_path, "a") as log_file: process = await asyncio.create_subprocess_exec( @@ -238,59 +298,72 @@ async def spawn_tcp_server( self, config: CompanionServerConfig, port: Optional[int], + swift_port: Optional[int] = None, tls_cert_path: Optional[str] = None, - ) -> Tuple[asyncio.subprocess.Process, int]: + ) -> Tuple[asyncio.subprocess.Process, int, Optional[int]]: + port_env_variables: Dict[str, str] = {} + if swift_port is not None: + port_env_variables["IDB_SWIFT_COMPANION_PORT"] = str(swift_port) + bind_arguments = ["--grpc-port", str(port) if port is not None else "0"] if tls_cert_path is not None: bind_arguments.extend(["--tls-cert-path", tls_cert_path]) (process, log_file_path) = await self._spawn_server( config=config, + port_env_variables=port_env_variables, bind_arguments=bind_arguments, ) stdout = none_throws(process.stdout) - try: - extracted_port = await _extract_port_from_spawned_companion(stdout) - except Exception as e: - raise CompanionSpawnerException( - f"Failed to spawn companion, couldn't read port output " - f"stderr: {get_last_n_lines(log_file_path, 30)}" - ) from e - if extracted_port == 0: - raise CompanionSpawnerException( - f"Failed to spawn companion, port zero is invalid " - f"stderr: {get_last_n_lines(log_file_path, 30)}" - ) - if port is not None and extracted_port != port: - raise CompanionSpawnerException( - "Failed to spawn companion, invalid port " - f"(expected {port} got {extracted_port})" - f"stderr: {get_last_n_lines(log_file_path, 30)}" - ) - return (process, extracted_port) + companion_report = await _extract_companion_report_from_spawned_companion( + stream=stdout, log_file_path=log_file_path + ) + extracted_port = await _verify_port_from_spawned_companion( + companion_report, "grpc_port", log_file_path, port + ) + + extracted_swift_port: Optional[int] = None + if swift_port: + try: + extracted_swift_port = await _verify_port_from_spawned_companion( + companion_report, + "grpc_swift_port", + log_file_path, + swift_port, + ) + except Exception: + self._logger.exception("Failed to verify SWIFT GRPC port") + else: + self._logger.info("Swift server not requested, skipping verification") + + return (process, extracted_port, extracted_swift_port) async def spawn_domain_sock_server( self, config: CompanionServerConfig, path: str ) -> asyncio.subprocess.Process: (process, log_file_path) = await self._spawn_server( - config=config, bind_arguments=["--grpc-domain-sock", path] + config=config, + port_env_variables={}, + bind_arguments=["--grpc-domain-sock", path], ) stdout = none_throws(process.stdout) try: - extracted_path = await _extract_domain_sock_from_spawned_companion(stdout) + extracted_path = await _extract_domain_sock_from_spawned_companion( + stream=stdout, log_file_path=log_file_path + ) except Exception as e: raise CompanionSpawnerException( - f"Failed to spawn companion, couldn't read port " + f"Failed to spawn companion, couldn't read domain socket path " f"stderr: {get_last_n_lines(log_file_path, 30)}" ) from e if not extracted_path: raise CompanionSpawnerException( - f"Failed to spawn companion, no extracted path" + f"Failed to spawn companion, no extracted domain socket path " f"stderr: {get_last_n_lines(log_file_path, 30)}" ) if extracted_path != path: raise CompanionSpawnerException( - "Failed to spawn companion, extracted path is not correct " - f"(expected {path} got {extracted_path})" + "Failed to spawn companion, extracted domain socket path " + f"is not correct (expected {path} got {extracted_path})" f"stderr: {get_last_n_lines(log_file_path, 30)}" ) return process @@ -426,6 +499,4 @@ async def unix_domain_server( if grpc_path is None: raise IdbException(f"No grpc_path in {line}") self._logger.info(f"Started domain sock server on {grpc_path}") - # pyre-fixme[7]: Expected `AsyncGenerator[str, None]` but got - # `AsyncGenerator[Union[int, str], None]`. - yield grpc_path + yield grpc_path if isinstance(grpc_path, str) else str(grpc_path) diff --git a/idb/common/companion_set.py b/idb/common/companion_set.py index 3568516be..7ed1a8d84 100644 --- a/idb/common/companion_set.py +++ b/idb/common/companion_set.py @@ -1,9 +1,11 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + import asyncio import json import logging @@ -144,7 +146,8 @@ async def remove_companion( and companion.address.path == destination.path ) ] + else: + to_remove = [] for companion in to_remove: companions.remove(companion) - # pyre-fixme[61]: `to_remove` may not be initialized here. return to_remove diff --git a/idb/common/constants.py b/idb/common/constants.py index 1f24b7c03..6fb20bbd6 100644 --- a/idb/common/constants.py +++ b/idb/common/constants.py @@ -1,9 +1,11 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + from datetime import timedelta from typing import Any, Dict diff --git a/idb/common/file.py b/idb/common/file.py index 65c23a0f9..7caecc5e2 100644 --- a/idb/common/file.py +++ b/idb/common/file.py @@ -1,9 +1,11 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + from typing import AsyncIterator import aiofiles diff --git a/idb/common/format.py b/idb/common/format.py index 4b66222e0..4439d6642 100644 --- a/idb/common/format.py +++ b/idb/common/format.py @@ -1,9 +1,11 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + import base64 import json from textwrap import indent @@ -11,18 +13,18 @@ from uuid import uuid4 from idb.common.types import ( - IdbException, AppProcessState, CompanionInfo, DebuggerInfo, DomainSocketAddress, + IdbException, InstalledAppInfo, InstalledTestInfo, TargetDescription, + TargetType, TCPAddress, TestActivity, TestRunInfo, - TargetType, ) from treelib import Tree @@ -33,6 +35,8 @@ def target_type_from_string(output: str) -> TargetType: return TargetType.SIMULATOR if "dev" in normalized: return TargetType.DEVICE + if "mac" in normalized: + return TargetType.MAC raise IdbException(f"Could not interpret target type from {output}") @@ -72,9 +76,8 @@ def human_format_test_info(test: TestRunInfo) -> str: def human_format_activities(activities: List[TestActivity]) -> str: tree: Tree = Tree() - start = activities[0].start + start: float = activities[0].start - # pyre-fixme[53]: Captured variable `start` is not annotated. def process_activity(activity: TestActivity, parent: Optional[str] = None) -> None: tree.create_node( f"{activity.name} ({activity.finish - start:.2f}s)", @@ -140,6 +143,11 @@ def json_format_activity(activity: TestActivity) -> Dict[str, Any]: "timestap": attachment.timestamp, "name": attachment.name, "uniform_type_identifier": attachment.uniform_type_identifier, + "user_info": ( + json.loads(attachment.user_info_json.decode("utf-8")) + if len(attachment.user_info_json) + else {} + ), } for attachment in activity.attachments ], diff --git a/idb/common/gzip.py b/idb/common/gzip.py index 65fe58cbc..3b9f64953 100644 --- a/idb/common/gzip.py +++ b/idb/common/gzip.py @@ -1,9 +1,11 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + import asyncio import sys diff --git a/idb/common/hid.py b/idb/common/hid.py index da80ddd4b..23dd4f72e 100644 --- a/idb/common/hid.py +++ b/idb/common/hid.py @@ -1,9 +1,11 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + from typing import AsyncIterator, Dict, Iterable, List, Optional, Tuple from idb.common.types import ( diff --git a/idb/common/logging.py b/idb/common/logging.py index 3e601e51f..b06fdefaa 100644 --- a/idb/common/logging.py +++ b/idb/common/logging.py @@ -1,16 +1,18 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + import functools import inspect import logging import time from concurrent.futures import CancelledError from types import TracebackType -from typing import Any, AsyncContextManager, Collection, Optional, Tuple, Type +from typing import Any, AsyncContextManager, Optional, Sequence, Tuple, Type from uuid import uuid4 import idb.common.plugin as plugin @@ -22,11 +24,10 @@ def _initial_info( - args: Collection[Any], metadata: Optional[LoggingMetadata] # pyre-ignore + args: Sequence[object], metadata: Optional[LoggingMetadata] ) -> Tuple[LoggingMetadata, int]: _metadata: LoggingMetadata = metadata or {} if len(args): - # pyre-fixme[16]: `Collection` has no attribute `__getitem__`. self_meta: Optional[LoggingMetadata] = getattr(args[0], "metadata", None) if self_meta: _metadata.update(self_meta) @@ -49,14 +50,10 @@ async def __aenter__(self) -> None: self.start = int(time.time()) await plugin.before_invocation(name=name, metadata=self.metadata) - # pyre-fixme[14]: `__aexit__` overrides method defined in `AsyncContextManager` - # inconsistently. - # pyre-fixme[14]: `__aexit__` overrides method defined in `AsyncContextManager` - # inconsistently. async def __aexit__( self, - exc_type: Optional[Type[Exception]], - exception: Optional[Exception], + exc_type: Optional[Type[BaseException]], + exception: Optional[BaseException], traceback: Optional[TracebackType], ) -> bool: name = none_throws(self.name) diff --git a/idb/common/misc.py b/idb/common/misc.py index dbe3b6c1f..433fa9f2c 100644 --- a/idb/common/misc.py +++ b/idb/common/misc.py @@ -1,9 +1,11 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + import os from typing import Dict diff --git a/idb/common/networking.py b/idb/common/networking.py index d1bdef369..a64490fad 100644 --- a/idb/common/networking.py +++ b/idb/common/networking.py @@ -1,9 +1,11 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + import asyncio import json diff --git a/idb/common/plugin.py b/idb/common/plugin.py index e9dd6f457..fbf036b96 100644 --- a/idb/common/plugin.py +++ b/idb/common/plugin.py @@ -1,9 +1,13 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + +from __future__ import annotations + import asyncio import importlib import logging @@ -13,10 +17,11 @@ from functools import wraps from logging import Logger from types import ModuleType -from typing import Dict, List, Optional +from typing import Any, Awaitable, Callable, Dict, List, Optional, overload, TypeVar from idb.common.command import Command from idb.common.types import LoggingMetadata +from pyre_extensions import ParameterSpecification def package_exists(package_name: str) -> bool: @@ -40,12 +45,27 @@ def package_exists(package_name: str) -> bool: logger: logging.Logger = logging.getLogger(__name__) -# pyre-ignore -def swallow_exceptions(f): +P = ParameterSpecification("P") +T = TypeVar("T") + + +@overload +def swallow_exceptions( + f: Callable[P, Awaitable[T]] +) -> Callable[P, Awaitable[T | None]]: ... + + +@overload +def swallow_exceptions(f: Callable[P, T]) -> Callable[P, T | None]: ... + + +def swallow_exceptions( + f: Callable[P, T] | Callable[P, Awaitable[T]] +) -> Callable[P, T | None] | Callable[P, Awaitable[T | None]]: if asyncio.iscoroutinefunction(f): @wraps(f) - async def inner(*args, **kwargs) -> None: + async def inner(*args: P.args, **kwargs: P.kwargs) -> T | None: try: return await f(*args, **kwargs) except Exception: @@ -54,10 +74,12 @@ async def inner(*args, **kwargs) -> None: else: @wraps(f) - def inner(*args, **kwargs) -> None: # pyre-ignore + def inner(*args: P.args, **kwargs: P.kwargs) -> T | None: try: + # pyre-ignore[7] return f(*args, **kwargs) except Exception: + # pyre-ignore[16] logger.exception(f"{f.__name__} plugin failed, swallowing exception") return inner @@ -75,11 +97,7 @@ def on_launch(logger: Logger) -> None: @swallow_exceptions async def on_close(logger: Logger) -> None: await asyncio.gather( - *[ - plugin.on_close(logger) # pyre-ignore - for plugin in PLUGINS - if hasattr(plugin, "on_close") - ], + *[plugin.on_close(logger) for plugin in PLUGINS if hasattr(plugin, "on_close")], ) @@ -87,7 +105,7 @@ async def on_close(logger: Logger) -> None: async def before_invocation(name: str, metadata: LoggingMetadata) -> None: await asyncio.gather( *[ - plugin.before_invocation(name=name, metadata=metadata) # pyre-ignore + plugin.before_invocation(name=name, metadata=metadata) for plugin in PLUGINS if hasattr(plugin, "before_invocation") ] @@ -98,9 +116,7 @@ async def before_invocation(name: str, metadata: LoggingMetadata) -> None: async def after_invocation(name: str, duration: int, metadata: LoggingMetadata) -> None: await asyncio.gather( *[ - plugin.after_invocation( # pyre-ignore - name=name, duration=duration, metadata=metadata - ) + plugin.after_invocation(name=name, duration=duration, metadata=metadata) for plugin in PLUGINS if hasattr(plugin, "after_invocation") ] @@ -113,7 +129,7 @@ async def failed_invocation( ) -> None: await asyncio.gather( *[ - plugin.failed_invocation( # pyre-ignore + plugin.failed_invocation( name=name, duration=duration, exception=exception, metadata=metadata ) for plugin in PLUGINS diff --git a/idb/common/signal.py b/idb/common/signal.py index 7d11a076a..2910e14bb 100644 --- a/idb/common/signal.py +++ b/idb/common/signal.py @@ -1,9 +1,11 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + import asyncio import signal from logging import Logger diff --git a/idb/common/socket.py b/idb/common/socket.py index 35d6511da..58948b34d 100644 --- a/idb/common/socket.py +++ b/idb/common/socket.py @@ -1,10 +1,12 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. -from socket import AF_INET, AF_INET6, AddressFamily, socket +# pyre-strict + +from socket import AddressFamily, AF_INET, AF_INET6, socket from typing import List, Optional, Tuple diff --git a/idb/common/stream.py b/idb/common/stream.py index 257299f77..9f310bcfb 100644 --- a/idb/common/stream.py +++ b/idb/common/stream.py @@ -1,9 +1,11 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + from typing import AsyncIterator, Callable, TypeVar diff --git a/idb/common/tar.py b/idb/common/tar.py index eeb1e9b44..e22cbc435 100644 --- a/idb/common/tar.py +++ b/idb/common/tar.py @@ -1,9 +1,11 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + import asyncio import os import sys diff --git a/idb/common/tests/companion_set_tests.py b/idb/common/tests/companion_set_tests.py index 87bca13c8..6398fc9fa 100644 --- a/idb/common/tests/companion_set_tests.py +++ b/idb/common/tests/companion_set_tests.py @@ -1,21 +1,19 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + import tempfile from pathlib import Path from typing import AsyncGenerator from unittest import mock from idb.common.companion_set import CompanionSet -from idb.common.types import ( - CompanionInfo, - DomainSocketAddress, - TCPAddress, -) -from idb.utils.testing import TestCase, ignoreTaskLeaks +from idb.common.types import CompanionInfo, DomainSocketAddress, TCPAddress +from idb.utils.testing import ignoreTaskLeaks, TestCase @ignoreTaskLeaks diff --git a/idb/common/tests/companion_tests.py b/idb/common/tests/companion_tests.py index f0eaaf306..91af727e0 100644 --- a/idb/common/tests/companion_tests.py +++ b/idb/common/tests/companion_tests.py @@ -1,61 +1,221 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + import json import os +from contextlib import asynccontextmanager +from typing import AsyncIterator from unittest import mock -from idb.common.companion import Companion, CompanionServerConfig +from idb.common.companion import ( + Companion, + CompanionReport, + CompanionServerConfig, + CompanionSpawnerException, +) from idb.common.types import TargetType -from idb.utils.testing import AsyncMock, TestCase, ignoreTaskLeaks +from idb.utils.testing import AsyncMock, ignoreTaskLeaks, TestCase @ignoreTaskLeaks class CompanionTests(TestCase): - async def test_spawn_tcp_server(self) -> None: - spawner = Companion( + def setUp(self) -> None: + self.udid = "someUdid" + self.spawner = Companion( companion_path="idb_path", device_set_path=None, logger=mock.Mock() ) - spawner._log_file_path = mock.Mock() - udid = "someUdid" + self.spawner._log_file_path = mock.Mock() + self.companion_server_config = CompanionServerConfig( + udid=self.udid, + only=TargetType.SIMULATOR, + log_file_path=None, + cwd=None, + tmp_path=None, + reparent=True, + ) + self.exec_mock_common_args = { + "stdout": mock.ANY, + "stderr": mock.ANY, + "stdin": mock.ANY, + "cwd": None, + "preexec_fn": os.setpgrp, + } + + @asynccontextmanager + async def _mock_all_the_things( + self, report: CompanionReport + ) -> AsyncIterator[AsyncMock]: with mock.patch( "idb.common.companion.asyncio.create_subprocess_exec", new=AsyncMock(), - ) as exec_mock, mock.patch("idb.common.companion.open"): + ) as exec_mock, mock.patch("idb.common.companion.open"), mock.patch( + "idb.common.companion.get_last_n_lines" + ): process_mock = mock.Mock() process_mock.stdout.readline = AsyncMock( - return_value=json.dumps( - {"hostname": "myHost", "grpc_port": 1234} - ).encode("utf-8") + return_value=json.dumps(report).encode("utf-8") ) exec_mock.return_value = process_mock - (_, port) = await spawner.spawn_tcp_server( - config=CompanionServerConfig( - udid=udid, - only=TargetType.SIMULATOR, - log_file_path=None, - cwd=None, - tmp_path=None, - reparent=True, - ), + yield exec_mock + + async def test_spawn_tcp_server(self) -> None: + async with self._mock_all_the_things( + {"hostname": "myHost", "grpc_port": 1234} + ) as exec_mock: + (_, port, swift_port) = await self.spawner.spawn_tcp_server( + config=self.companion_server_config, + port=1234, + ) + exec_mock.assert_called_once_with( + "idb_path", + "--udid", + self.udid, + "--grpc-port", + "1234", + "--only", + "simulator", + env=os.environ, + **self.exec_mock_common_args, + ) + self.assertEqual(port, 1234) + self.assertIsNone(swift_port) + + async def test_spawn_tcp_server_auto_bind(self) -> None: + async with self._mock_all_the_things( + {"hostname": "myHost", "grpc_port": 1234} + ) as exec_mock: + (_, port, swift_port) = await self.spawner.spawn_tcp_server( + config=self.companion_server_config, port=None, ) exec_mock.assert_called_once_with( "idb_path", "--udid", - "someUdid", + self.udid, "--grpc-port", "0", "--only", "simulator", - stdout=mock.ANY, - stderr=mock.ANY, - stdin=mock.ANY, - cwd=None, env=os.environ, - preexec_fn=os.setpgrp, + **self.exec_mock_common_args, + ) + self.assertEqual(port, 1234) + self.assertIsNone(swift_port) + + async def test_spawn_tcp_server_broken_report(self) -> None: + async with self._mock_all_the_things({"hostname": "myHost"}) as exec_mock: + with self.assertRaisesRegex( + CompanionSpawnerException, r".*couldn\'t read.*" + ): + await self.spawner.spawn_tcp_server( + config=self.companion_server_config, + port=1234, + ) + exec_mock.assert_called_once_with( + "idb_path", + "--udid", + self.udid, + "--grpc-port", + "1234", + "--only", + "simulator", + env=os.environ, + **self.exec_mock_common_args, + ) + + async def test_spawn_tcp_server_port_mismatch(self) -> None: + async with self._mock_all_the_things( + {"hostname": "myHost", "grpc_port": 0} + ) as exec_mock: + with self.assertRaisesRegex( + CompanionSpawnerException, r".*zero is invalid.*" + ): + await self.spawner.spawn_tcp_server( + config=self.companion_server_config, + port=1234, + ) + exec_mock.assert_called_once_with( + "idb_path", + "--udid", + self.udid, + "--grpc-port", + "1234", + "--only", + "simulator", + env=os.environ, + **self.exec_mock_common_args, + ) + + async def test_spawn_tcp_server_with_swift(self) -> None: + async with self._mock_all_the_things( + {"hostname": "myHost", "grpc_port": 1234, "grpc_swift_port": 1235} + ) as exec_mock: + (_, port, swift_port) = await self.spawner.spawn_tcp_server( + config=self.companion_server_config, + port=1234, + swift_port=1235, + ) + exec_mock.assert_called_once_with( + "idb_path", + "--udid", + self.udid, + "--grpc-port", + "1234", + "--only", + "simulator", + env={**os.environ, "IDB_SWIFT_COMPANION_PORT": "1235"}, + **self.exec_mock_common_args, + ) + self.assertEqual(port, 1234) + self.assertEqual(swift_port, 1235) + + async def test_spawn_tcp_server_with_swift_missing_from_report(self) -> None: + async with self._mock_all_the_things( + {"hostname": "myHost", "grpc_port": 1234} + ) as exec_mock: + (_, port, swift_port) = await self.spawner.spawn_tcp_server( + config=self.companion_server_config, + port=1234, + swift_port=1235, + ) + exec_mock.assert_called_once_with( + "idb_path", + "--udid", + self.udid, + "--grpc-port", + "1234", + "--only", + "simulator", + env={**os.environ, "IDB_SWIFT_COMPANION_PORT": "1235"}, + **self.exec_mock_common_args, + ) + self.assertEqual(port, 1234) + self.assertIsNone(swift_port) + + async def test_spawn_tcp_server_with_swift_port_mismatch(self) -> None: + async with self._mock_all_the_things( + {"hostname": "myHost", "grpc_port": 1234, "grpc_swift_port": 42} + ) as exec_mock: + (_, port, swift_port) = await self.spawner.spawn_tcp_server( + config=self.companion_server_config, + port=1234, + swift_port=1235, + ) + exec_mock.assert_called_once_with( + "idb_path", + "--udid", + self.udid, + "--grpc-port", + "1234", + "--only", + "simulator", + env={**os.environ, "IDB_SWIFT_COMPANION_PORT": "1235"}, + **self.exec_mock_common_args, ) self.assertEqual(port, 1234) + self.assertIsNone(swift_port) diff --git a/idb/common/tests/format_tests.py b/idb/common/tests/format_tests.py index fd5da2a70..2d278c6f0 100644 --- a/idb/common/tests/format_tests.py +++ b/idb/common/tests/format_tests.py @@ -1,9 +1,11 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + from idb.common.format import ( json_data_companions, json_format_target_info, @@ -16,9 +18,9 @@ InstalledAppInfo, InstalledTestInfo, TargetDescription, + TargetType, TCPAddress, TestActivity, - TargetType, TestRunFailureInfo, TestRunInfo, ) diff --git a/idb/common/tests/networking_tests.py b/idb/common/tests/networking_tests.py index 18f60c88b..edeb440c9 100644 --- a/idb/common/tests/networking_tests.py +++ b/idb/common/tests/networking_tests.py @@ -1,11 +1,13 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + from idb.common.networking import _get_ports -from idb.utils.testing import TestCase, ignoreTaskLeaks +from idb.utils.testing import ignoreTaskLeaks, TestCase @ignoreTaskLeaks diff --git a/idb/common/tests/tar_tests.py b/idb/common/tests/tar_tests.py index 9f2af392e..dc95dcb4a 100644 --- a/idb/common/tests/tar_tests.py +++ b/idb/common/tests/tar_tests.py @@ -1,9 +1,11 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + from idb.common.tar import _create_untar_command from idb.utils.testing import TestCase diff --git a/idb/common/tests/udid_tests.py b/idb/common/tests/udid_tests.py index 6f103e824..7e35572ea 100644 --- a/idb/common/tests/udid_tests.py +++ b/idb/common/tests/udid_tests.py @@ -1,9 +1,11 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + from idb.common.udid import is_udid from idb.utils.testing import TestCase diff --git a/idb/common/types.py b/idb/common/types.py index 46f542914..f7f3b9ecd 100644 --- a/idb/common/types.py +++ b/idb/common/types.py @@ -1,24 +1,26 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + import asyncio import json from abc import ABC, abstractmethod, abstractproperty -from asyncio import StreamWriter, StreamReader +from asyncio import StreamReader, StreamWriter +from contextlib import asynccontextmanager from dataclasses import asdict, dataclass, field from datetime import timedelta from enum import Enum from io import StringIO from typing import ( - IO, - AsyncContextManager, AsyncGenerator, AsyncIterable, AsyncIterator, Dict, + IO, List, Mapping, Optional, @@ -39,11 +41,6 @@ class IdbConnectionException(Exception): pass -@dataclass(frozen=True) -class ExitWithCodeException(Exception): - exit_code: int - - class Permission(Enum): PHOTOS = 0 CAMERA = 1 @@ -51,6 +48,7 @@ class Permission(Enum): URL = 3 LOCATION = 4 NOTIFICATION = 5 + MICROPHONE = 6 class TargetType(str, Enum): @@ -67,6 +65,12 @@ class ECIDFilter: OnlyFilter = Union[TargetType, ECIDFilter] +class Architecture(Enum): + ANY = "any" + X86 = "x86_64" + ARM64 = "arm64" + + class VideoFormat(Enum): H264 = "h264" RBGA = "rbga" @@ -220,6 +224,7 @@ class TestAttachment: timestamp: float name: str uniform_type_identifier: str + user_info_json: bytes @dataclass(frozen=True) @@ -327,13 +332,18 @@ class FileContainerType(Enum): AUXILLARY = "auxillary" CRASHES = "crashes" DISK_IMAGES = "disk_images" + DSYM = "dsym" + DYLIB = "dylib" + FRAMEWORK = "framework" GROUP = "group" MDM_PROFILES = "mdm_profiles" MEDIA = "media" PROVISIONING_PROFILES = "provisioning_profiles" ROOT = "root" SPRINGBOARD_ICONS = "springboard_icons" + SYMBOLS = "symbols" WALLPAPER = "wallpaper" + XCTEST = "xctest" FileContainer = Optional[Union[str, FileContainerType]] @@ -363,9 +373,10 @@ async def boot( pass @abstractmethod - async def boot_headless( # pyre-fixme + @asynccontextmanager + async def boot_headless( self, udid: str, verify: bool = True, timeout: Optional[timedelta] = None - ) -> AsyncContextManager[None]: + ) -> AsyncGenerator[None, None]: yield @abstractmethod @@ -417,9 +428,10 @@ async def target_description( pass @abstractmethod - async def unix_domain_server( # pyre-fixme + @asynccontextmanager + async def unix_domain_server( self, udid: str, path: str, only: Optional[OnlyFilter] = None - ) -> AsyncContextManager[str]: + ) -> AsyncGenerator[str, None]: yield @@ -440,6 +452,7 @@ async def launch( foreground_if_running: bool = False, wait_for_debugger: bool = False, stop: Optional[asyncio.Event] = None, + pid_file: Optional[str] = None, ) -> None: pass @@ -463,6 +476,7 @@ async def run_xctest( report_attachments: bool = False, activities_output_path: Optional[str] = None, coverage_output_path: Optional[str] = None, + enable_continuous_coverage_collection: bool = False, coverage_format: CodeCoverageFormat = CodeCoverageFormat.EXPORTED, log_directory_path: Optional[str] = None, wait_for_debugger: bool = False, @@ -475,6 +489,7 @@ async def install( bundle: Union[str, IO[bytes]], compression: Optional[Compression] = None, make_debuggable: Optional[bool] = None, + override_modification_time: Optional[bool] = None, ) -> AsyncIterator[InstalledArtifact]: yield @@ -489,12 +504,14 @@ async def install_dsym( self, dsym: Union[str, IO[bytes]], bundle_id: Optional[str], + compression: Optional[Compression], + bundle_type: Optional[FileContainerType] = None, ) -> AsyncIterator[InstalledArtifact]: yield @abstractmethod async def install_xctest( - self, xctest: Union[str, IO[bytes]] + self, xctest: Union[str, IO[bytes]], skip_signing_bundles: Optional[bool] = None ) -> AsyncIterator[InstalledArtifact]: yield @@ -544,7 +561,7 @@ async def set_locale(self, locale_identifier: str) -> None: @abstractmethod async def set_preference( - self, name: str, value: str, domain: Optional[str] + self, name: str, value: str, value_type: str, domain: Optional[str] ) -> None: pass @@ -582,6 +599,12 @@ async def approve( ) -> None: pass + @abstractmethod + async def revoke( + self, bundle_id: str, permissions: Set[Permission], scheme: Optional[str] = None + ) -> None: + pass + @abstractmethod async def record_video(self, stop: asyncio.Event, output_file: str) -> None: pass diff --git a/idb/common/udid.py b/idb/common/udid.py index 37f170c36..b386c49c1 100644 --- a/idb/common/udid.py +++ b/idb/common/udid.py @@ -1,16 +1,18 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + import re SIMULATOR_UDID = r"^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$" OLD_DEVICE_UDID = r"^[0-9a-f]{40}$" NEW_DEVICE_UDID = r"^[0-9]{8}-[0-9A-F]{16}$" -UDID = fr"({SIMULATOR_UDID}|{OLD_DEVICE_UDID}|{NEW_DEVICE_UDID})" +UDID = rf"({SIMULATOR_UDID}|{OLD_DEVICE_UDID}|{NEW_DEVICE_UDID})" def is_udid(udid: str) -> bool: diff --git a/idb/grpc/client.py b/idb/grpc/client.py index d458f266d..3ae701a9f 100644 --- a/idb/grpc/client.py +++ b/idb/grpc/client.py @@ -1,18 +1,21 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + import asyncio import functools import inspect import logging import os import shutil +import sys import tempfile import urllib.parse -from asyncio import StreamWriter, StreamReader +from asyncio import StreamReader, StreamWriter from io import StringIO from pathlib import Path from typing import ( @@ -33,6 +36,7 @@ from grpclib.exceptions import GRPCError, ProtocolError, StreamTerminatedError from idb.common.constants import TESTS_POLL_INTERVAL from idb.common.file import drain_to_file +from idb.common.format import json_format_debugger_info from idb.common.gzip import drain_gzip_decompress, gunzip from idb.common.hid import ( button_press_to_events, @@ -46,7 +50,6 @@ from idb.common.stream import stream_map from idb.common.tar import create_tar, drain_untar, generate_tar from idb.common.types import ( - FileContainerType, AccessibilityInfo, Address, AppProcessState, @@ -60,6 +63,7 @@ CrashLogQuery, DomainSocketAddress, FileContainer, + FileContainerType, FileEntryInfo, FileListing, HIDButtonType, @@ -70,6 +74,7 @@ InstalledArtifact, InstalledTestInfo, InstrumentsTimings, + LoggingMetadata, OnlyFilter, Permission, TargetDescription, @@ -89,6 +94,7 @@ from idb.grpc.idb_pb2 import ( AccessibilityInfoRequest, AddMediaRequest, + ANY as AnySetting, ApproveRequest, ClearKeychainRequest, ConnectRequest, @@ -97,20 +103,16 @@ DebugServerRequest, DebugServerResponse, FocusRequest, + GetSettingRequest, InstallRequest, InstrumentsRunRequest, LaunchRequest, - TailRequest, ListAppsRequest, + ListSettingRequest, + LOCALE as LocaleSetting, Location, LogRequest, - SimulateMemoryWarningRequest, - SendNotificationRequest, LsRequest, - GetSettingRequest, - LOCALE as LocaleSetting, - ANY as AnySetting, - ListSettingRequest, MkdirRequest, MvRequest, OpenUrlRequest, @@ -119,18 +121,22 @@ PullRequest, PushRequest, RecordRequest, + RevokeRequest, RmRequest, ScreenshotRequest, + SendNotificationRequest, SetLocationRequest, SettingRequest, + SimulateMemoryWarningRequest, + TailRequest, TargetDescriptionRequest, TerminateRequest, UninstallRequest, VideoStreamRequest, XctestListBundlesRequest, XctestListTestsRequest, - XctraceRecordRequest, XctestRunResponse, + XctraceRecordRequest, ) from idb.grpc.install import ( Bundle, @@ -160,10 +166,7 @@ untar_into_path, ) from idb.grpc.xctest_log_parser import XCTestLogParser -from idb.grpc.xctrace import ( - xctrace_drain_until_running, - xctrace_generate_bytes, -) +from idb.grpc.xctrace import xctrace_drain_until_running, xctrace_generate_bytes from idb.utils.contextlib import asynccontextmanager @@ -174,6 +177,17 @@ Permission.URL: ApproveRequest.URL, Permission.LOCATION: ApproveRequest.LOCATION, Permission.NOTIFICATION: ApproveRequest.NOTIFICATION, + Permission.MICROPHONE: ApproveRequest.MICROPHONE, +} + +REVOKE_MAP: Dict[Permission, "RevokeRequest.Permission"] = { + Permission.PHOTOS: RevokeRequest.PHOTOS, + Permission.CAMERA: RevokeRequest.CAMERA, + Permission.CONTACTS: RevokeRequest.CONTACTS, + Permission.URL: RevokeRequest.URL, + Permission.LOCATION: RevokeRequest.LOCATION, + Permission.NOTIFICATION: RevokeRequest.NOTIFICATION, + Permission.MICROPHONE: RevokeRequest.MICROPHONE, } VIDEO_FORMAT_MAP: Dict[VideoFormat, "VideoStreamRequest.Format"] = { @@ -189,38 +203,43 @@ } -def log_and_handle_exceptions(func): # pyre-ignore - @functools.wraps(func) - @log_call(name=func.__name__) - async def func_wrapper(*args: Any, **kwargs: Any) -> Any: # pyre-ignore - try: - return await func(*args, **kwargs) - except GRPCError as e: - raise IdbException(e.message) from e # noqa B306 - except (ProtocolError, StreamTerminatedError) as e: - raise IdbException(e.args) from e - except OSError as e: - raise IdbConnectionException(e.strerror) - - @functools.wraps(func) - @log_call(name=func.__name__) - # pyre-fixme[53]: Captured variable `func` is not annotated. - # pyre-fixme[3]: Return annotation cannot be `Any`. - async def func_wrapper_gen(*args: Any, **kwargs: Any) -> Any: - try: - async for item in func(*args, **kwargs): - yield item - except GRPCError as e: - raise IdbException(e.message) from e # noqa B306 - except (ProtocolError, StreamTerminatedError) as e: - raise IdbException(e.args) from e - except OSError as e: - raise IdbConnectionException(e.strerror) - - if inspect.isasyncgenfunction(func): - return func_wrapper_gen - else: - return func_wrapper +def log_and_handle_exceptions(grpc_method_name: str): # pyre-ignore + metadata: LoggingMetadata = { + "grpc_method_name": grpc_method_name, + } + + def decorating(func) -> Any: # pyre-ignore: + @functools.wraps(func) + @log_call(name=func.__name__, metadata=metadata) + async def func_wrapper(*args: Any, **kwargs: Any) -> Any: # pyre-ignore + try: + return await func(*args, **kwargs) + except GRPCError as e: + raise IdbException(e.message) from e # noqa B306 + except (ProtocolError, StreamTerminatedError) as e: + raise IdbException(e.args) from e + except OSError as e: + raise IdbConnectionException(e.strerror) + + @functools.wraps(func) + @log_call(name=func.__name__, metadata=metadata) + async def func_wrapper_gen(*args: Any, **kwargs: Any) -> Any: # pyre-ignore + try: + async for item in func(*args, **kwargs): + yield item + except GRPCError as e: + raise IdbException(e.message) from e # noqa B306 + except (ProtocolError, StreamTerminatedError) as e: + raise IdbException(e.args) from e + except OSError as e: + raise IdbConnectionException(e.strerror) + + if inspect.isasyncgenfunction(func): + return func_wrapper_gen + else: + return func_wrapper + + return decorating class Client(ClientBase): @@ -344,6 +363,9 @@ async def _install_to_destination( compression: Optional[Compression], make_debuggable: Optional[bool], bundle_id: Optional[str], + bundle_type: Optional[FileContainerType], + override_modification_time: Optional[bool] = None, + skip_signing_bundles: Optional[bool] = None, ) -> AsyncIterator[InstalledArtifact]: async with self.stub.install.open() as stream: generator = None @@ -386,6 +408,16 @@ async def _install_to_destination( await stream.send_message( InstallRequest(make_debuggable=make_debuggable) ) + if override_modification_time is not None: + await stream.send_message( + InstallRequest( + override_modification_time=override_modification_time + ) + ) + if skip_signing_bundles is not None: + await stream.send_message( + InstallRequest(skip_signing_bundles=skip_signing_bundles) + ) if compression is not None: await stream.send_message( InstallRequest( @@ -393,7 +425,20 @@ async def _install_to_destination( ) ) if bundle_id is not None: - await stream.send_message(InstallRequest(bundle_id=bundle_id)) + link_to_bundle_type = None + if bundle_type == FileContainerType.APPLICATION: + link_to_bundle_type = InstallRequest.LinkDsymToBundle.APP + elif bundle_type == FileContainerType.XCTEST: + link_to_bundle_type = InstallRequest.LinkDsymToBundle.XCTEST + else: + raise IdbException( + f"Unexpected bundle_type. Bundle_type {bundle_type} specified for {bundle_id}" + ) + message = InstallRequest.LinkDsymToBundle( + bundle_id=bundle_id, bundle_type=link_to_bundle_type + ) + await stream.send_message(InstallRequest(link_dsym_to_bundle=message)) + async for message in generator: await stream.send_message(message) self.logger.debug("Finished sending install payload to companion") @@ -410,7 +455,7 @@ def _is_verbose(self) -> bool: def _log_from_companion(self, data: str) -> None: self.logger.info(data.strip()) - @log_and_handle_exceptions + @log_and_handle_exceptions("list_apps") async def list_apps( self, fetch_process_state: bool = True ) -> List[InstalledAppInfo]: @@ -430,7 +475,7 @@ async def list_apps( for app in response.apps ] - @log_and_handle_exceptions + @log_and_handle_exceptions("accessibility_info") async def accessibility_info( self, point: Optional[Tuple[int, int]], nested: bool ) -> AccessibilityInfo: @@ -447,7 +492,7 @@ async def accessibility_info( ) return AccessibilityInfo(json=response.json) - @log_and_handle_exceptions + @log_and_handle_exceptions("add_media") async def add_media(self, file_paths: List[str]) -> None: async with self.stub.add_media.open() as stream: if self.is_local: @@ -471,35 +516,55 @@ async def add_media(self, file_paths: List[str]) -> None: stream=stream, generator=generator, logger=self.logger ) - @log_and_handle_exceptions + @log_and_handle_exceptions("approve") async def approve( - self, bundle_id: str, permissions: Set[Permission], scheme: Optional[str] = None + self, + bundle_id: str, + permissions: Set[Permission], + scheme: Optional[str] = None, ) -> None: await self.stub.approve( ApproveRequest( bundle_id=bundle_id, permissions=[APPROVE_MAP[permission] for permission in permissions], + # pyre-ignore + scheme=scheme, + ) + ) + + @log_and_handle_exceptions("revoke") + async def revoke( + self, + bundle_id: str, + permissions: Set[Permission], + scheme: Optional[str] = None, + ) -> None: + await self.stub.revoke( + RevokeRequest( + bundle_id=bundle_id, + permissions=[REVOKE_MAP[permission] for permission in permissions], + # pyre-ignore scheme=scheme, ) ) - @log_and_handle_exceptions + @log_and_handle_exceptions("clear_keychain") async def clear_keychain(self) -> None: await self.stub.clear_keychain(ClearKeychainRequest()) - @log_and_handle_exceptions + @log_and_handle_exceptions("contacts_update") async def contacts_update(self, contacts_path: str) -> None: data = await create_tar([contacts_path]) await self.stub.contacts_update( ContactsUpdateRequest(payload=Payload(data=data)) ) - @log_and_handle_exceptions + @log_and_handle_exceptions("screenshot") async def screenshot(self) -> bytes: response = await self.stub.screenshot(ScreenshotRequest()) return response.image_data - @log_and_handle_exceptions + @log_and_handle_exceptions("set_location") async def set_location(self, latitude: float, longitude: float) -> None: await self.stub.set_location( SetLocationRequest( @@ -507,11 +572,11 @@ async def set_location(self, latitude: float, longitude: float) -> None: ) ) - @log_and_handle_exceptions + @log_and_handle_exceptions("simulate_memory_warning") async def simulate_memory_warning(self) -> None: await self.stub.simulate_memory_warning(SimulateMemoryWarningRequest()) - @log_and_handle_exceptions + @log_and_handle_exceptions("send_notification") async def send_notification(self, bundle_id: str, json_payload: str) -> None: await self.stub.send_notification( SendNotificationRequest( @@ -520,11 +585,11 @@ async def send_notification(self, bundle_id: str, json_payload: str) -> None: ) ) - @log_and_handle_exceptions + @log_and_handle_exceptions("terminate") async def terminate(self, bundle_id: str) -> None: await self.stub.terminate(TerminateRequest(bundle_id=bundle_id)) - @log_and_handle_exceptions + @log_and_handle_exceptions("describe") async def describe(self, fetch_diagnostics: bool = False) -> TargetDescription: response = await self.stub.describe( TargetDescriptionRequest(fetch_diagnostics=fetch_diagnostics) @@ -543,25 +608,25 @@ async def describe(self, fetch_diagnostics: bool = False) -> TargetDescription: metadata=response.companion.metadata, ) - @log_and_handle_exceptions + @log_and_handle_exceptions("focus") async def focus(self) -> None: await self.stub.focus(FocusRequest()) - @log_and_handle_exceptions + @log_and_handle_exceptions("open_url") async def open_url(self, url: str) -> None: await self.stub.open_url(OpenUrlRequest(url=url)) - @log_and_handle_exceptions + @log_and_handle_exceptions("uninstall") async def uninstall(self, bundle_id: str) -> None: await self.stub.uninstall(UninstallRequest(bundle_id=bundle_id)) - @log_and_handle_exceptions + @log_and_handle_exceptions("rm") async def rm(self, container: FileContainer, paths: List[str]) -> None: await self.stub.rm( RmRequest(paths=paths, container=file_container_to_grpc(container)) ) - @log_and_handle_exceptions + @log_and_handle_exceptions("mv") async def mv( self, container: FileContainer, src_paths: List[str], dest_path: str ) -> None: @@ -573,7 +638,7 @@ async def mv( ) ) - @log_and_handle_exceptions + @log_and_handle_exceptions("ls") async def ls_single( self, container: FileContainer, path: str ) -> List[FileEntryInfo]: @@ -582,7 +647,7 @@ async def ls_single( ) return [FileEntryInfo(path=file.path) for file in response.files] - @log_and_handle_exceptions + @log_and_handle_exceptions("ls") async def ls(self, container: FileContainer, paths: List[str]) -> List[FileListing]: response = await self.stub.ls( LsRequest(paths=paths, container=file_container_to_grpc(container)) @@ -595,33 +660,34 @@ async def ls(self, container: FileContainer, paths: List[str]) -> List[FileListi for listing in response.listings ] - @log_and_handle_exceptions + @log_and_handle_exceptions("mkdir") async def mkdir(self, container: FileContainer, path: str) -> None: await self.stub.mkdir( MkdirRequest(path=path, container=file_container_to_grpc(container)) ) - @log_and_handle_exceptions + @log_and_handle_exceptions("crash_delete") async def crash_delete(self, query: CrashLogQuery) -> List[CrashLogInfo]: response = await self.stub.crash_delete(_to_crash_log_query_proto(query)) return _to_crash_log_info_list(response) - @log_and_handle_exceptions + @log_and_handle_exceptions("crash_list") async def crash_list(self, query: CrashLogQuery) -> List[CrashLogInfo]: response = await self.stub.crash_list(_to_crash_log_query_proto(query)) return _to_crash_log_info_list(response) - @log_and_handle_exceptions + @log_and_handle_exceptions("crash_show") async def crash_show(self, name: str) -> CrashLog: response = await self.stub.crash_show(CrashShowRequest(name=name)) return _to_crash_log(response) - @log_and_handle_exceptions + @log_and_handle_exceptions("install") async def install( self, bundle: Bundle, compression: Optional[Compression] = None, make_debuggable: Optional[bool] = None, + override_modification_time: Optional[bool] = None, ) -> AsyncIterator[InstalledArtifact]: async for response in self._install_to_destination( bundle=bundle, @@ -629,21 +695,29 @@ async def install( compression=compression, make_debuggable=make_debuggable, bundle_id=None, + bundle_type=None, + override_modification_time=override_modification_time, ): yield response - @log_and_handle_exceptions - async def install_xctest(self, xctest: Bundle) -> AsyncIterator[InstalledArtifact]: + @log_and_handle_exceptions("install") + async def install_xctest( + self, + xctest: Bundle, + skip_signing_bundles: Optional[bool] = None, + ) -> AsyncIterator[InstalledArtifact]: async for response in self._install_to_destination( bundle=xctest, destination=InstallRequest.XCTEST, compression=None, make_debuggable=None, bundle_id=None, + bundle_type=None, + skip_signing_bundles=skip_signing_bundles, ): yield response - @log_and_handle_exceptions + @log_and_handle_exceptions("install") async def install_dylib(self, dylib: Bundle) -> AsyncIterator[InstalledArtifact]: async for response in self._install_to_destination( bundle=dylib, @@ -651,23 +725,29 @@ async def install_dylib(self, dylib: Bundle) -> AsyncIterator[InstalledArtifact] compression=None, make_debuggable=None, bundle_id=None, + bundle_type=None, ): yield response - @log_and_handle_exceptions + @log_and_handle_exceptions("install") async def install_dsym( - self, dsym: Bundle, bundle_id: Optional[str] + self, + dsym: Bundle, + bundle_id: Optional[str], + compression: Optional[Compression], + bundle_type: Optional[FileContainerType] = None, ) -> AsyncIterator[InstalledArtifact]: async for response in self._install_to_destination( bundle=dsym, destination=InstallRequest.DSYM, - compression=None, + compression=compression, make_debuggable=None, bundle_id=bundle_id, + bundle_type=bundle_type, ): yield response - @log_and_handle_exceptions + @log_and_handle_exceptions("install") async def install_framework( self, framework_path: Bundle ) -> AsyncIterator[InstalledArtifact]: @@ -677,10 +757,11 @@ async def install_framework( compression=None, make_debuggable=None, bundle_id=None, + bundle_type=None, ): yield response - @log_and_handle_exceptions + @log_and_handle_exceptions("push") async def push( self, src_paths: List[str], @@ -724,7 +805,7 @@ async def push( logger=self.logger, ) - @log_and_handle_exceptions + @log_and_handle_exceptions("pull") async def pull( self, container: FileContainer, src_path: str, dest_path: str ) -> None: @@ -733,6 +814,7 @@ async def pull( src_path=src_path, # not sending the destination to remote companion # so it streams the file back + # pyre-ignore dst_path=dest_path if self.is_local else None, container=file_container_to_grpc(container), ) @@ -744,7 +826,7 @@ async def pull( await drain_untar(generate_bytes(stream), output_path=dest_path) self.logger.info(f"pulled file to {dest_path}") - @log_and_handle_exceptions + @log_and_handle_exceptions("tail") async def tail( self, stop: asyncio.Event, container: FileContainer, path: str ) -> AsyncIterator[bytes]: @@ -760,14 +842,14 @@ async def tail( yield response.data await stream.send_message(TailRequest(stop=TailRequest.Stop())) - @log_and_handle_exceptions + @log_and_handle_exceptions("xctest_list_tests") async def list_test_bundle(self, test_bundle_id: str, app_path: str) -> List[str]: response = await self.stub.xctest_list_tests( XctestListTestsRequest(bundle_name=test_bundle_id, app_path=app_path) ) return list(response.names) - @log_and_handle_exceptions + @log_and_handle_exceptions("xctest_list_bundles") async def list_xctests(self) -> List[InstalledTestInfo]: response = await self.stub.xctest_list_bundles(XctestListBundlesRequest()) return [ @@ -779,29 +861,29 @@ async def list_xctests(self) -> List[InstalledTestInfo]: for bundle in response.bundles ] - @log_and_handle_exceptions + @log_and_handle_exceptions("hid") async def send_events(self, events: Iterable[HIDEvent]) -> None: await self.hid(iterator_to_async_iterator(events)) - @log_and_handle_exceptions + @log_and_handle_exceptions("hid") async def tap(self, x: float, y: float, duration: Optional[float] = None) -> None: await self.send_events(tap_to_events(x, y, duration)) - @log_and_handle_exceptions + @log_and_handle_exceptions("hid") async def button( self, button_type: HIDButtonType, duration: Optional[float] = None ) -> None: await self.send_events(button_press_to_events(button_type, duration)) - @log_and_handle_exceptions + @log_and_handle_exceptions("hid") async def key(self, keycode: int, duration: Optional[float] = None) -> None: await self.send_events(key_press_to_events(keycode, duration)) - @log_and_handle_exceptions + @log_and_handle_exceptions("hid") async def text(self, text: str) -> None: await self.send_events(text_to_events(text)) - @log_and_handle_exceptions + @log_and_handle_exceptions("hid") async def swipe( self, p_start: Tuple[int, int], @@ -811,14 +893,14 @@ async def swipe( ) -> None: await self.send_events(swipe_to_events(p_start, p_end, duration, delta)) - @log_and_handle_exceptions + @log_and_handle_exceptions("hid") async def key_sequence(self, key_sequence: List[int]) -> None: events: List[HIDEvent] = [] for key in key_sequence: events.extend(key_press_to_events(key)) await self.send_events(events) - @log_and_handle_exceptions + @log_and_handle_exceptions("hid") async def hid(self, event_iterator: AsyncIterable[HIDEvent]) -> None: async with self.stub.hid.open() as stream: grpc_event_iterator = ( @@ -826,22 +908,19 @@ async def hid(self, event_iterator: AsyncIterable[HIDEvent]) -> None: ) await drain_to_stream( stream=stream, - # pyre-fixme[6]: Expected - # `AsyncIterator[Variable[idb.grpc.stream._TSend]]` for 2nd param but - # got `Generator[typing.Any, None, None]`. generator=grpc_event_iterator, logger=self.logger, ) await stream.recv_message() - @log_and_handle_exceptions + @log_and_handle_exceptions("debugserver") async def debug_server(self, request: DebugServerRequest) -> DebugServerResponse: async with self.stub.debugserver.open() as stream: await stream.send_message(request) await stream.end() return await stream.recv_message() - @log_and_handle_exceptions + @log_and_handle_exceptions("debugserver") async def debugserver_start(self, bundle_id: str) -> List[str]: response = await self.debug_server( request=DebugServerRequest( @@ -850,13 +929,13 @@ async def debugserver_start(self, bundle_id: str) -> List[str]: ) return response.status.lldb_bootstrap_commands - @log_and_handle_exceptions + @log_and_handle_exceptions("debugserver") async def debugserver_stop(self) -> None: await self.debug_server( request=DebugServerRequest(stop=DebugServerRequest.Stop()) ) - @log_and_handle_exceptions + @log_and_handle_exceptions("debugserver") async def debugserver_status(self) -> Optional[List[str]]: response = await self.debug_server( request=DebugServerRequest(status=DebugServerRequest.Status()) @@ -864,7 +943,7 @@ async def debugserver_status(self) -> Optional[List[str]]: commands = response.status.lldb_bootstrap_commands return commands if commands else None - @log_and_handle_exceptions + @log_and_handle_exceptions("instruments_run") async def run_instruments( self, stop: asyncio.Event, @@ -945,7 +1024,7 @@ async def run_instruments( return result - @log_and_handle_exceptions + @log_and_handle_exceptions("launch") async def launch( self, bundle_id: str, @@ -954,6 +1033,7 @@ async def launch( foreground_if_running: bool = False, wait_for_debugger: bool = False, stop: Optional[asyncio.Event] = None, + pid_file: Optional[str] = None, ) -> None: async with self.stub.launch.open() as stream: request = LaunchRequest( @@ -969,13 +1049,14 @@ async def launch( await stream.send_message(request) if stop: await asyncio.gather( - drain_launch_stream(stream), end_launch_stream(stream, stop) + drain_launch_stream(stream, pid_file), + end_launch_stream(stream, stop), ) else: await stream.end() - await drain_launch_stream(stream) + await drain_launch_stream(stream, pid_file) - @log_and_handle_exceptions + @log_and_handle_exceptions("record") async def record_video(self, stop: asyncio.Event, output_file: str) -> None: self.logger.info("Starting connection to backend") async with self.stub.record.open() as stream: @@ -989,6 +1070,7 @@ async def record_video(self, stop: asyncio.Event, output_file: str) -> None: else: self.logger.info("Starting video recording with response data") await stream.send_message( + # pyre-ignore RecordRequest(start=RecordRequest.Start(file_path=None)) ) await stop.wait() @@ -1005,6 +1087,7 @@ async def record_video(self, stop: asyncio.Event, output_file: str) -> None: ) self.logger.info(f"Finished decompression to {output_file}") + @log_and_handle_exceptions("video_stream") async def stream_video( self, output_file: Optional[str], @@ -1023,6 +1106,7 @@ async def stream_video( VideoStreamRequest( start=VideoStreamRequest.Start( file_path=output_file, + # pyre-ignore fps=fps, format=VIDEO_FORMAT_MAP[format], compression_quality=compression_quality, @@ -1035,7 +1119,9 @@ async def stream_video( await stream.send_message( VideoStreamRequest( start=VideoStreamRequest.Start( + # pyre-ignore file_path=None, + # pyre-ignore fps=fps, format=VIDEO_FORMAT_MAP[format], compression_quality=compression_quality, @@ -1090,7 +1176,7 @@ async def _handle_code_coverage_in_response( with open(coverage_output_path, "w") as f: f.write(response.coverage_json) - @log_and_handle_exceptions + @log_and_handle_exceptions("xctest_run") async def run_xctest( self, test_bundle_id: str, @@ -1110,6 +1196,7 @@ async def run_xctest( report_attachments: bool = False, activities_output_path: Optional[str] = None, coverage_output_path: Optional[str] = None, + enable_continuous_coverage_collection: bool = False, coverage_format: CodeCoverageFormat = CodeCoverageFormat.EXPORTED, log_directory_path: Optional[str] = None, wait_for_debugger: bool = False, @@ -1134,9 +1221,11 @@ async def run_xctest( ), report_attachments=report_attachments, collect_coverage=coverage_output_path is not None, + enable_continuous_coverage_collection=enable_continuous_coverage_collection, coverage_format=coverage_format, collect_logs=log_directory_path is not None, wait_for_debugger=wait_for_debugger, + collect_result_bundle=result_bundle_path is not None, ) log_parser = XCTestLogParser() await stream.send_message(request) @@ -1174,8 +1263,11 @@ async def run_xctest( ) if wait_for_debugger and response.debugger.pid: - print("Tests waiting for debugger. To debug run:") - print(f"lldb -p {response.debugger.pid}") + sys.stdout.buffer.write( + json_format_debugger_info(response.debugger).encode() + ) + sys.stdout.buffer.write(os.linesep.encode()) + sys.stdout.buffer.flush() for result in make_results(response, log_parser): if activities_output_path: @@ -1185,7 +1277,7 @@ async def run_xctest( ) yield result - @log_and_handle_exceptions + @log_and_handle_exceptions("log") async def tail_logs( self, stop: asyncio.Event, arguments: Optional[List[str]] = None ) -> AsyncIterator[str]: @@ -1194,14 +1286,14 @@ async def tail_logs( ): yield message - @log_and_handle_exceptions + @log_and_handle_exceptions("log") async def tail_companion_logs(self, stop: asyncio.Event) -> AsyncIterator[str]: async for message in self._tail_specific_logs( source=LogRequest.COMPANION, stop=stop, arguments=None ): yield message - @log_and_handle_exceptions + @log_and_handle_exceptions("setting") async def set_hardware_keyboard(self, enabled: bool) -> None: await self.stub.setting( SettingRequest( @@ -1209,7 +1301,7 @@ async def set_hardware_keyboard(self, enabled: bool) -> None: ) ) - @log_and_handle_exceptions + @log_and_handle_exceptions("setting") async def set_locale(self, locale_identifier: str) -> None: await self.stub.setting( SettingRequest( @@ -1219,31 +1311,37 @@ async def set_locale(self, locale_identifier: str) -> None: ) ) - @log_and_handle_exceptions + @log_and_handle_exceptions("setting") async def set_preference( - self, name: str, value: str, domain: Optional[str] + self, name: str, value: str, value_type: str, domain: Optional[str] ) -> None: await self.stub.setting( SettingRequest( stringSetting=SettingRequest.StringSetting( - setting=AnySetting, value=value, name=name, domain=domain + setting=AnySetting, + value=value, + name=name, + value_type=value_type, + # pyre-ignore + domain=domain, ) ) ) - @log_and_handle_exceptions + @log_and_handle_exceptions("get_setting") async def get_locale(self) -> str: response = await self.stub.get_setting(GetSettingRequest(setting=LocaleSetting)) return response.value - @log_and_handle_exceptions + @log_and_handle_exceptions("get_setting") async def get_preference(self, name: str, domain: Optional[str]) -> str: response = await self.stub.get_setting( + # pyre-ignore GetSettingRequest(setting=AnySetting, name=name, domain=domain) ) return response.value - @log_and_handle_exceptions + @log_and_handle_exceptions("list_settings") async def list_locale_identifiers(self) -> List[str]: response = await self.stub.list_settings( ListSettingRequest( @@ -1252,7 +1350,7 @@ async def list_locale_identifiers(self) -> List[str]: ) return list(response.values) - @log_and_handle_exceptions + @log_and_handle_exceptions("xctrace_record") async def xctrace_record( self, stop: asyncio.Event, @@ -1287,9 +1385,12 @@ async def xctrace_record( else: target = XctraceRecordRequest.Target( launch_process=XctraceRecordRequest.LauchProcess( + # pyre-ignore process_to_launch=process_to_launch, launch_args=launch_args, + # pyre-ignore target_stdin=target_stdin, + # pyre-ignore target_stdout=target_stdout, process_env=process_env, ) @@ -1298,7 +1399,9 @@ async def xctrace_record( XctraceRecordRequest( start=XctraceRecordRequest.Start( template_name=template_name, + # pyre-ignore time_limit=time_limit, + # pyre-ignore package=package, target=target, ) @@ -1317,6 +1420,7 @@ async def xctrace_record( await stream.send_message( XctraceRecordRequest( stop=XctraceRecordRequest.Stop( + # pyre-ignore timeout=stop_timeout, args=post_args, ) @@ -1353,7 +1457,7 @@ async def xctrace_record( return result - @log_and_handle_exceptions + @log_and_handle_exceptions("dap") async def dap( self, dap_path: str, diff --git a/idb/grpc/crash.py b/idb/grpc/crash.py index 4c2382867..ab96e31e0 100644 --- a/idb/grpc/crash.py +++ b/idb/grpc/crash.py @@ -1,9 +1,11 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + from typing import List from idb.common.types import CrashLog, CrashLogInfo, CrashLogQuery @@ -37,8 +39,12 @@ def _to_crash_log(proto: CrashShowResponse) -> CrashLog: def _to_crash_log_query_proto(query: CrashLogQuery) -> CrashLogQueryProto: return CrashLogQueryProto( + # pyre-ignore before=query.before, + # pyre-ignore since=query.since, + # pyre-ignore bundle_id=query.bundle_id, + # pyre-ignore name=query.name, ) diff --git a/idb/grpc/dap.py b/idb/grpc/dap.py index bb29cc210..0d2957101 100644 --- a/idb/grpc/dap.py +++ b/idb/grpc/dap.py @@ -1,20 +1,19 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + import asyncio import logging -from asyncio import StreamWriter, StreamReader -from typing import Optional, AsyncGenerator +from asyncio import StreamReader, StreamWriter +from typing import AsyncGenerator, Optional from idb.common.types import IdbException from idb.grpc.idb_grpc import CompanionServiceStub -from idb.grpc.idb_pb2 import ( - DapResponse, - DapRequest, -) +from idb.grpc.idb_pb2 import DapRequest, DapResponse from idb.grpc.stream import Stream from idb.utils.contextlib import asynccontextmanager from idb.utils.typing import none_throws diff --git a/idb/grpc/file.py b/idb/grpc/file.py index 0c0312e56..d5fb75ef4 100644 --- a/idb/grpc/file.py +++ b/idb/grpc/file.py @@ -1,9 +1,11 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + from idb.common.types import FileContainer, FileContainerType from idb.grpc.idb_pb2 import FileContainer as GrpcFileContainer @@ -35,4 +37,14 @@ def container_to_grpc(container: FileContainer) -> GrpcFileContainer: return GrpcFileContainer(kind=GrpcFileContainer.APPLICATION_CONTAINER) if container == FileContainerType.AUXILLARY: return GrpcFileContainer(kind=GrpcFileContainer.AUXILLARY) + if container == FileContainerType.XCTEST: + return GrpcFileContainer(kind=GrpcFileContainer.XCTEST) + if container == FileContainerType.DYLIB: + return GrpcFileContainer(kind=GrpcFileContainer.DYLIB) + if container == FileContainerType.DSYM: + return GrpcFileContainer(kind=GrpcFileContainer.DSYM) + if container == FileContainerType.FRAMEWORK: + return GrpcFileContainer(kind=GrpcFileContainer.FRAMEWORK) + if container == FileContainerType.SYMBOLS: + return GrpcFileContainer(kind=GrpcFileContainer.SYMBOLS) return GrpcFileContainer(kind=GrpcFileContainer.NONE) diff --git a/idb/grpc/hid.py b/idb/grpc/hid.py index 1ee85fba9..168a41adc 100644 --- a/idb/grpc/hid.py +++ b/idb/grpc/hid.py @@ -1,9 +1,11 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + from typing import List, Tuple, TypeVar from idb.common.types import ( @@ -100,7 +102,9 @@ def swipe_to_grpc(swipe: HIDSwipe) -> GrpcHIDSwipe: return GrpcHIDSwipe( start=point_to_grpc(swipe.start), end=point_to_grpc(swipe.end), + # pyre-ignore delta=swipe.delta, + # pyre-ignore duration=swipe.duration, ) diff --git a/idb/grpc/install.py b/idb/grpc/install.py index 708b08f12..73149b787 100644 --- a/idb/grpc/install.py +++ b/idb/grpc/install.py @@ -1,12 +1,14 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + import os from logging import Logger -from typing import IO, AsyncIterator, List, Union, Optional +from typing import AsyncIterator, IO, List, Optional, Union import aiofiles import idb.common.gzip as gzip @@ -65,10 +67,10 @@ async def _generate_dylib_chunks( async def _generate_dsym_chunks( - path: str, logger: Logger + path: str, compression: Compression, logger: Logger ) -> AsyncIterator[InstallRequest]: logger.debug(f"Generating chunks for {path}") - async for chunk in tar.generate_tar([path]): + async for chunk in tar.generate_tar([path], compression): yield InstallRequest(payload=Payload(data=chunk)) logger.debug(f"Finished generating chunks {path}") @@ -122,7 +124,9 @@ def generate_binary_chunks( elif destination == InstallRequest.DYLIB: return _generate_dylib_chunks(path=path, logger=logger) elif destination == InstallRequest.DSYM: - return _generate_dsym_chunks(path=path, logger=logger) + return _generate_dsym_chunks( + path=path, compression=compression or Compression.GZIP, logger=logger + ) elif destination == InstallRequest.FRAMEWORK: return _generate_framework_chunks(path=path, logger=logger) raise GRPCError( diff --git a/idb/grpc/instruments.py b/idb/grpc/instruments.py index cfb58b1d4..122544f7d 100644 --- a/idb/grpc/instruments.py +++ b/idb/grpc/instruments.py @@ -1,9 +1,11 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + import asyncio from logging import Logger @@ -69,9 +71,13 @@ def translate_instruments_timings( ) -> Optional[InstrumentsRunRequest.InstrumentsTimings]: return ( InstrumentsRunRequest.InstrumentsTimings( + # pyre-ignore terminate_timeout=timings.terminate_timeout, + # pyre-ignore launch_retry_timeout=timings.launch_retry_timeout, + # pyre-ignore launch_error_timeout=timings.launch_error_timeout, + # pyre-ignore operation_duration=timings.operation_duration, ) if timings diff --git a/idb/grpc/launch.py b/idb/grpc/launch.py index 959788519..8d9b7ffe2 100644 --- a/idb/grpc/launch.py +++ b/idb/grpc/launch.py @@ -1,11 +1,14 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + import asyncio import sys +from typing import Optional from idb.common.format import json_format_debugger_info from idb.common.types import DebuggerInfo @@ -13,7 +16,9 @@ from idb.grpc.stream import Stream -async def drain_launch_stream(stream: Stream[LaunchRequest, LaunchResponse]) -> None: +async def drain_launch_stream( + stream: Stream[LaunchRequest, LaunchResponse], pid_file: Optional[str] +) -> None: async for message in stream: output = message.output data = output.data @@ -29,8 +34,13 @@ async def drain_launch_stream(stream: Stream[LaunchRequest, LaunchResponse]) -> debugger_pid = debugger_info.pid if debugger_pid is not None and debugger_pid != 0: info = DebuggerInfo(pid=debugger_info.pid) - sys.stdout.buffer.write(json_format_debugger_info(info).encode()) - sys.stdout.buffer.flush() + if pid_file is None: + sys.stdout.buffer.write(json_format_debugger_info(info).encode()) + sys.stdout.buffer.flush() + else: + with open(pid_file, "wb") as f: + f.write(json_format_debugger_info(info).encode()) + f.flush() async def end_launch_stream( diff --git a/idb/grpc/management.py b/idb/grpc/management.py index 3a7cfb7a1..92453b600 100644 --- a/idb/grpc/management.py +++ b/idb/grpc/management.py @@ -1,9 +1,11 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + import asyncio import logging import os @@ -17,12 +19,12 @@ from idb.common.types import ( ClientManager as ClientManagerBase, CompanionInfo, - OnlyFilter, ConnectionDestination, DomainSocketAddress, IdbException, - TargetType, + OnlyFilter, TargetDescription, + TargetType, TCPAddress, ) from idb.grpc.client import Client diff --git a/idb/grpc/stream.py b/idb/grpc/stream.py index 13fcfa1b7..2ce8097e7 100644 --- a/idb/grpc/stream.py +++ b/idb/grpc/stream.py @@ -1,9 +1,11 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + import asyncio from logging import Logger from typing import AsyncIterator, Dict, Generic, Optional, TypeVar @@ -18,17 +20,13 @@ class Stream(Generic[_TSend, _TRecv], AsyncIterator[_TRecv]): metadata: Dict[str, str] = {} - async def recv_message(self) -> Optional[_TRecv]: - ... + async def recv_message(self) -> Optional[_TRecv]: ... - async def send_message(self, message: _TSend) -> None: - ... + async def send_message(self, message: _TSend) -> None: ... - async def end(self) -> None: - ... + async def end(self) -> None: ... - async def cancel(self) -> None: - ... + async def cancel(self) -> None: ... async def drain_to_stream( @@ -41,7 +39,6 @@ async def drain_to_stream( logger.debug("Streamed all chunks to companion, waiting for completion") response = none_throws(await stream.recv_message()) logger.debug("Companion completed") - # pyre-fixme[7]: Expected `_TRecv` but got `object`. return response diff --git a/idb/grpc/target.py b/idb/grpc/target.py index 0079263a9..c16901f7d 100644 --- a/idb/grpc/target.py +++ b/idb/grpc/target.py @@ -1,9 +1,11 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + import json from typing import List, Sequence @@ -55,8 +57,11 @@ def screen_dimensions_to_grpc(dimensions: ScreenDimensions) -> GrpcScreenDimensi return GrpcScreenDimensions( width=dimensions.width, height=dimensions.height, + # pyre-ignore density=dimensions.density, + # pyre-ignore width_points=dimensions.width_points, + # pyre-ignore height_points=dimensions.height_points, ) diff --git a/idb/grpc/tests/hid_tests.py b/idb/grpc/tests/hid_tests.py index 7834d2994..1a4e2f164 100644 --- a/idb/grpc/tests/hid_tests.py +++ b/idb/grpc/tests/hid_tests.py @@ -1,10 +1,13 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + from idb.grpc.hid import ( + event_to_grpc, GrpcHIDButton, GrpcHIDDelay, GrpcHIDEvent, @@ -23,7 +26,6 @@ HIDSwipe, HIDTouch, Point, - event_to_grpc, ) from idb.utils.testing import TestCase @@ -64,6 +66,7 @@ def test_swipe(self) -> None: swipe=GrpcHIDSwipe( start=GrpcPoint(x=1, y=2), end=GrpcPoint(x=3, y=4), + # pyre-ignore delta=delta, duration=0.5, ) diff --git a/idb/grpc/tests/target_tests.py b/idb/grpc/tests/target_tests.py index 41723df96..add8cf542 100644 --- a/idb/grpc/tests/target_tests.py +++ b/idb/grpc/tests/target_tests.py @@ -1,12 +1,14 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + from unittest import TestCase -from idb.common.types import CompanionInfo, TargetDescription, TCPAddress, TargetType +from idb.common.types import CompanionInfo, TargetDescription, TargetType, TCPAddress from idb.grpc.target import merge_connected_targets diff --git a/idb/grpc/tests/xctest_log_parser.py b/idb/grpc/tests/xctest_log_parser.py index 6842ac576..97bb9249b 100644 --- a/idb/grpc/tests/xctest_log_parser.py +++ b/idb/grpc/tests/xctest_log_parser.py @@ -1,9 +1,11 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + import json from unittest import TestCase diff --git a/idb/grpc/tests/xctest_tests.py b/idb/grpc/tests/xctest_tests.py index 78cbfd138..9ac66ba7e 100644 --- a/idb/grpc/tests/xctest_tests.py +++ b/idb/grpc/tests/xctest_tests.py @@ -1,21 +1,27 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + import os.path import plistlib import tempfile -from unittest import TestCase +from unittest import IsolatedAsyncioTestCase from idb.grpc.xctest import extract_paths_from_xctestrun -class XCTestsTestCase(TestCase): +class XCTestsTestCase(IsolatedAsyncioTestCase): async def test_extract_paths_from_xctestrun(self) -> None: with tempfile.TemporaryDirectory() as tmp_dir: file_path = os.path.join(tmp_dir, "test.plist") + with open(os.path.join(tmp_dir, "rest1"), "w") as rest1: + rest1.write("rest1") + with open(os.path.join(tmp_dir, "rest2"), "w") as rest2: + rest2.write("rest2") with open(file_path, "wb+") as f: plistlib.dump( { diff --git a/idb/grpc/video.py b/idb/grpc/video.py index 50b77b312..5d500d516 100644 --- a/idb/grpc/video.py +++ b/idb/grpc/video.py @@ -1,9 +1,11 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + from typing import AsyncIterator from idb.grpc.idb_pb2 import RecordResponse diff --git a/idb/grpc/xctest.py b/idb/grpc/xctest.py index 548596d2b..8bbabd0e4 100644 --- a/idb/grpc/xctest.py +++ b/idb/grpc/xctest.py @@ -1,9 +1,11 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + import os import plistlib from enum import Enum @@ -12,13 +14,13 @@ from idb.common.tar import untar from idb.common.types import ( + CodeCoverageFormat, TestActivity, TestAttachment, TestRunFailureInfo, TestRunInfo, - CodeCoverageFormat, ) -from idb.grpc.idb_pb2 import XctestRunRequest, XctestRunResponse, Payload +from idb.grpc.idb_pb2 import Payload, XctestRunRequest, XctestRunResponse from idb.grpc.xctest_log_parser import XCTestLogParser @@ -111,9 +113,11 @@ def make_request( report_activities: bool, report_attachments: bool, collect_coverage: bool, + enable_continuous_coverage_collection: bool, coverage_format: CodeCoverageFormat, collect_logs: bool, wait_for_debugger: bool, + collect_result_bundle: bool, ) -> XctestRunRequest: if is_logic_test: mode = Mode(logic=Logic()) @@ -121,6 +125,7 @@ def make_request( mode = Mode( ui=UI( app_bundle_id=app_bundle_id, + # pyre-ignore test_host_app_bundle_id=test_host_app_bundle_id, ) ) @@ -132,6 +137,7 @@ def make_request( coverage_object = XctestRunRequest.CodeCoverage( collect=True, + enable_continuous_coverage_collection=enable_continuous_coverage_collection, format=CODE_COVERAGE_FORMAT_MAP[coverage_format], ) @@ -149,6 +155,7 @@ def make_request( collect_logs=collect_logs, wait_for_debugger=wait_for_debugger, code_coverage=coverage_object, + collect_result_bundle=collect_result_bundle, ) @@ -179,15 +186,7 @@ def make_results( ), duration=result.duration, passed=result.status == XctestRunResponse.TestRunInfo.PASSED, - failure_info=( - TestRunFailureInfo( - message=result.failure_info.failure_message, - file=result.failure_info.file, - line=result.failure_info.line, - ) - if result.failure_info - else None - ), + failure_info=(make_failure_info(result) if result.failure_info else None), activityLogs=[ translate_activity(activity) for activity in result.activityLogs or [] ], @@ -197,6 +196,35 @@ def make_results( ] +def make_failure_info(result: XctestRunResponse.TestRunInfo) -> TestRunFailureInfo: + if result.other_failures is None or len(result.other_failures) == 0: + return TestRunFailureInfo( + message=result.failure_info.failure_message, + file=result.failure_info.file, + line=result.failure_info.line, + ) + else: + message = ( + "line:" + + str(result.failure_info.line) + + " " + + result.failure_info.failure_message + ) + for other_failure in result.other_failures: + message = ( + message + + ", line:" + + str(other_failure.line) + + " " + + other_failure.failure_message + ) + return TestRunFailureInfo( + message=message, + file=result.failure_info.file, + line=result.failure_info.line, + ) + + def translate_activity( activity: XctestRunResponse.TestRunInfo.TestActivity, ) -> TestActivity: @@ -214,6 +242,7 @@ def translate_activity( timestamp=attachment.timestamp, name=attachment.name, uniform_type_identifier=attachment.uniform_type_identifier, + user_info_json=attachment.user_info_json, ) for attachment in activity.attachments or [] ], diff --git a/idb/grpc/xctest_log_parser.py b/idb/grpc/xctest_log_parser.py index 1f793987a..4f74191ba 100644 --- a/idb/grpc/xctest_log_parser.py +++ b/idb/grpc/xctest_log_parser.py @@ -1,11 +1,13 @@ -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + import json from collections import defaultdict -from typing import Optional, Dict, List, NamedTuple +from typing import Dict, List, NamedTuple, Optional class XCTestLogParserKey(NamedTuple): diff --git a/idb/grpc/xctrace.py b/idb/grpc/xctrace.py index 8a42cae8e..64e2419e7 100644 --- a/idb/grpc/xctrace.py +++ b/idb/grpc/xctrace.py @@ -1,19 +1,18 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + import asyncio import re from logging import Logger from typing import AsyncIterator, Optional -from idb.grpc.idb_pb2 import ( - XctraceRecordRequest, - XctraceRecordResponse, -) +from idb.grpc.idb_pb2 import XctraceRecordRequest, XctraceRecordResponse from idb.grpc.stream import Stream from idb.utils.typing import none_throws diff --git a/idb/utils/contextlib.py b/idb/utils/contextlib.py index 1f54bef16..a44ffe038 100644 --- a/idb/utils/contextlib.py +++ b/idb/utils/contextlib.py @@ -1,9 +1,11 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-ignore-all-errors + import abc import sys @@ -29,7 +31,6 @@ def _check_methods(C, *methods): class AbstractContextManager(abc.ABC): - """An abstract base class for context managers.""" def __enter__(self): @@ -49,7 +50,6 @@ def __subclasshook__(cls, C): class AbstractAsyncContextManager(abc.ABC): - """An abstract base class for asynchronous context managers.""" async def __aenter__(self): @@ -68,7 +68,7 @@ def __subclasshook__(cls, C): return NotImplemented -class ContextDecorator(object): +class ContextDecorator: "A base class or mixin that enables context managers to work as decorators." def _recreate_cm(self): diff --git a/idb/utils/testing.py b/idb/utils/testing.py index 8429eee2c..55631bfdc 100644 --- a/idb/utils/testing.py +++ b/idb/utils/testing.py @@ -1,9 +1,11 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-ignore-all-errors + import asyncio import functools import inspect @@ -11,7 +13,7 @@ import unittest import unittest.mock as _mock import warnings -from typing import Awaitable, Callable, TypeVar, cast +from typing import Awaitable, Callable, cast, TypeVar # pyre-ignore from unittest.case import _Outcome @@ -265,7 +267,7 @@ async def test_1(self): return_value=AsyncContextManagerMock(return_value=m) ): r = await target() - self.assertEquals(r, 'fff') + self.assertEqual(r, 'fff') """ def __init__(self, *args, **kwargs): diff --git a/idb/utils/typing.py b/idb/utils/typing.py index 4d773e939..f8fef3675 100644 --- a/idb/utils/typing.py +++ b/idb/utils/typing.py @@ -1,9 +1,11 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. +# pyre-strict + from typing import Optional, TypeVar diff --git a/idb_build.sh b/idb_build.sh index 5cf4cda47..a762e67d5 100755 --- a/idb_build.sh +++ b/idb_build.sh @@ -1,5 +1,5 @@ #!/bin/bash -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. @@ -80,28 +80,25 @@ function all_frameworks_build() { } function strip_framework() { - local FRAMEWORK_PATH="$BUILD_DIRECTORY/Build/Products/Debug/$1" + local FRAMEWORK_PATH="$BUILD_DIRECTORY/Build/Products/Release/$1" if [ -d "$FRAMEWORK_PATH" ]; then echo "Stripping Framework $FRAMEWORK_PATH" rm -r "$FRAMEWORK_PATH" fi } -function strip_idb_grpc() { - echo "Stripping idbGRPC from $BUILD_DIRECTORY" - rm -rf $BUILD_DIRECTORY/Build/Products/Debug/*idbGRPC* -} - function cli_build() { local name=$1 local output_directory=$2 local script_directory=$1/Scripts invoke_xcodebuild \ + ONLY_ACTIVE_ARCH=NO \ -workspace $name.xcworkspace \ -scheme $name \ -sdk macosx \ -derivedDataPath $BUILD_DIRECTORY \ + -configuration Release \ build strip_framework "FBSimulatorControl.framework/Versions/Current/Frameworks/XCTestBootstrap.framework" @@ -118,8 +115,8 @@ function cli_build() { function cli_install() { local output_directory=$1 local script_directory=$2 - local cli_artifact="$BUILD_DIRECTORY/Build/Products/Debug/idb_companion" - local framework_artifact="$BUILD_DIRECTORY/Build/Products/Debug/*.framework" + local cli_artifact="$BUILD_DIRECTORY/Build/Products/Release/idb_companion" + local framework_artifact="$BUILD_DIRECTORY/Build/Products/Release/*.framework" local output_directory_cli="$output_directory/bin" local output_directory_framework="$output_directory/Frameworks" diff --git a/idb_companion.xcodeproj/project.pbxproj b/idb_companion.xcodeproj/project.pbxproj index 740fd3274..5ae468f7f 100644 --- a/idb_companion.xcodeproj/project.pbxproj +++ b/idb_companion.xcodeproj/project.pbxproj @@ -3,82 +3,193 @@ archiveVersion = 1; classes = { }; - objectVersion = 51; + objectVersion = 54; objects = { /* Begin PBXBuildFile section */ - 1CF77457F352C3C1079A442C /* libPods-idbGRPC.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CEFAE887E28B2550E73E65C6 /* libPods-idbGRPC.a */; }; - 623D9F0D22E40DCB00D9129C /* FBIDBLogger.h in Headers */ = {isa = PBXBuildFile; fileRef = 623D9F0B22E40DCB00D9129C /* FBIDBLogger.h */; }; - 623D9F0E22E40DCB00D9129C /* FBIDBLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = 623D9F0C22E40DCB00D9129C /* FBIDBLogger.m */; }; - 713C709426F52F970086D8DF /* FBCodeCoverageRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 713C709226F52F970086D8DF /* FBCodeCoverageRequest.h */; }; - 713C709526F52F970086D8DF /* FBCodeCoverageRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 713C709326F52F970086D8DF /* FBCodeCoverageRequest.m */; }; - 713C70A126F53BC80086D8DF /* FBXCTestRunRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 713C709F26F53BC80086D8DF /* FBXCTestRunRequest.h */; }; - 713C70A226F53BC80086D8DF /* FBXCTestRunRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 713C70A026F53BC80086D8DF /* FBXCTestRunRequest.m */; }; - 713C70AD26F8D0700086D8DF /* FBIDBAppHostedTestConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = 713C70AB26F8D0700086D8DF /* FBIDBAppHostedTestConfiguration.h */; }; - 713C70AE26F8D0700086D8DF /* FBIDBAppHostedTestConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = 713C70AC26F8D0700086D8DF /* FBIDBAppHostedTestConfiguration.m */; }; - 7E30A85F7039E2EB464C03DE /* libPods-idb_companion.a in Frameworks */ = {isa = PBXBuildFile; fileRef = BEC79D15EF2190287C8A0D82 /* libPods-idb_companion.a */; }; - AA0DB07D23CF0D9800E8CDEE /* FBIDBTestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = AA0DB07B23CF0D9800E8CDEE /* FBIDBTestOperation.m */; }; - AA0DB07E23CF0D9800E8CDEE /* FBIDBTestOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = AA0DB07C23CF0D9800E8CDEE /* FBIDBTestOperation.h */; }; - AA0DB08123CF0DCB00E8CDEE /* FBIDBXCTestReporter.mm in Sources */ = {isa = PBXBuildFile; fileRef = AA0DB07F23CF0DCA00E8CDEE /* FBIDBXCTestReporter.mm */; }; + 710FD8182811AFE1000832EA /* AccessibilityInfoMethodHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 710FD8172811AFE1000832EA /* AccessibilityInfoMethodHandler.swift */; }; + 712F098927E8B3FC005EFD42 /* DescribeMethodHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 712F098827E8B3FC005EFD42 /* DescribeMethodHandler.swift */; }; + 7135AF3A2A8C1C0300D8B882 /* FBIDBCommandExecutor.h in Headers */ = {isa = PBXBuildFile; fileRef = 7135AF0F2A8C1B6100D8B882 /* FBIDBCommandExecutor.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 7135AF3B2A8C1C0B00D8B882 /* FBIDBCommandExecutor.m in Sources */ = {isa = PBXBuildFile; fileRef = 7135AF102A8C1B6100D8B882 /* FBIDBCommandExecutor.m */; }; + 7135AF3C2A8C1C2500D8B882 /* FBIDBLogger.h in Headers */ = {isa = PBXBuildFile; fileRef = 7135AF1E2A8C1B6100D8B882 /* FBIDBLogger.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 7135AF3D2A8C1C2500D8B882 /* FBDataDownloadInput.h in Headers */ = {isa = PBXBuildFile; fileRef = 7135AF1C2A8C1B6100D8B882 /* FBDataDownloadInput.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 7135AF3E2A8C1C2500D8B882 /* FBXCTestRunFileReader.h in Headers */ = {isa = PBXBuildFile; fileRef = 7135AF2A2A8C1B6100D8B882 /* FBXCTestRunFileReader.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 7135AF3F2A8C1C2500D8B882 /* FBXCTestRunFileReader.m in Sources */ = {isa = PBXBuildFile; fileRef = 7135AF2B2A8C1B6100D8B882 /* FBXCTestRunFileReader.m */; }; + 7135AF402A8C1C2500D8B882 /* FBIDBStorageManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 7135AF212A8C1B6100D8B882 /* FBIDBStorageManager.m */; }; + 7135AF412A8C1C2500D8B882 /* FBDataDownloadInput.m in Sources */ = {isa = PBXBuildFile; fileRef = 7135AF1D2A8C1B6100D8B882 /* FBDataDownloadInput.m */; }; + 7135AF422A8C1C2500D8B882 /* FBIDBTestOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 7135AF232A8C1B6100D8B882 /* FBIDBTestOperation.m */; }; + 7135AF432A8C1C2500D8B882 /* FBXCTestDescriptor.h in Headers */ = {isa = PBXBuildFile; fileRef = 7135AF262A8C1B6100D8B882 /* FBXCTestDescriptor.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 7135AF442A8C1C2500D8B882 /* FBXCTestDescriptor.m in Sources */ = {isa = PBXBuildFile; fileRef = 7135AF272A8C1B6100D8B882 /* FBXCTestDescriptor.m */; }; + 7135AF452A8C1C2500D8B882 /* FBXCTestReporterConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = 7135AF292A8C1B6100D8B882 /* FBXCTestReporterConfiguration.m */; }; + 7135AF462A8C1C2500D8B882 /* FBIDBLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = 7135AF1F2A8C1B6100D8B882 /* FBIDBLogger.m */; }; + 7135AF472A8C1C2500D8B882 /* FBIDBStorageManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 7135AF202A8C1B6100D8B882 /* FBIDBStorageManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 7135AF482A8C1C2500D8B882 /* FBXCTestReporterConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = 7135AF282A8C1B6100D8B882 /* FBXCTestReporterConfiguration.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 7135AF492A8C1C2500D8B882 /* FBTestApplicationsPair.h in Headers */ = {isa = PBXBuildFile; fileRef = 7135AF242A8C1B6100D8B882 /* FBTestApplicationsPair.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 7135AF4A2A8C1C2500D8B882 /* FBTestApplicationsPair.m in Sources */ = {isa = PBXBuildFile; fileRef = 7135AF252A8C1B6100D8B882 /* FBTestApplicationsPair.m */; }; + 7135AF4B2A8C1C2500D8B882 /* FBIDBTestOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 7135AF222A8C1B6100D8B882 /* FBIDBTestOperation.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 7135AF4C2A8C1C4100D8B882 /* FBDsymInstallLinkToBundle.m in Sources */ = {isa = PBXBuildFile; fileRef = 7135AF182A8C1B6100D8B882 /* FBDsymInstallLinkToBundle.m */; }; + 7135AF4D2A8C1C4100D8B882 /* FBXCTestRunRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 7135AF1A2A8C1B6100D8B882 /* FBXCTestRunRequest.m */; }; + 7135AF4E2A8C1C4100D8B882 /* FBCodeCoverageRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 7135AF162A8C1B6100D8B882 /* FBCodeCoverageRequest.m */; }; + 7135AF4F2A8C1C4100D8B882 /* FBXCTestRunRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 7135AF192A8C1B6100D8B882 /* FBXCTestRunRequest.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 7135AF502A8C1C4100D8B882 /* FBCodeCoverageRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 7135AF152A8C1B6100D8B882 /* FBCodeCoverageRequest.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 7135AF512A8C1C4100D8B882 /* FBDsymInstallLinkToBundle.h in Headers */ = {isa = PBXBuildFile; fileRef = 7135AF172A8C1B6100D8B882 /* FBDsymInstallLinkToBundle.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 7135AF522A8C1C5100D8B882 /* FBIDBError.m in Sources */ = {isa = PBXBuildFile; fileRef = 7135AF132A8C1B6100D8B882 /* FBIDBError.m */; }; + 7135AF532A8C1C5500D8B882 /* FBIDBError.h in Headers */ = {isa = PBXBuildFile; fileRef = 7135AF122A8C1B6100D8B882 /* FBIDBError.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 7135AF592A8C2A1100D8B882 /* EmptyEventReporter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7135AF582A8C2A1100D8B882 /* EmptyEventReporter.swift */; }; + 7135AF5C2A8C2C6A00D8B882 /* FBiOSTargetProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = 7135AF5A2A8C2C6A00D8B882 /* FBiOSTargetProvider.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 7135AF5D2A8C2C6A00D8B882 /* FBiOSTargetProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = 7135AF5B2A8C2C6A00D8B882 /* FBiOSTargetProvider.m */; }; + 7135AF692A8CC19600D8B882 /* FBIDBAppHostedTestConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = 7135AF0D2A8C1B6100D8B882 /* FBIDBAppHostedTestConfiguration.h */; }; + 7135AF6A2A8CC19900D8B882 /* FBIDBAppHostedTestConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = 7135AF0E2A8C1B6100D8B882 /* FBIDBAppHostedTestConfiguration.m */; }; + 7135AF6B2A8CC25500D8B882 /* IDBConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBB72C84283B957F0065DDB3 /* IDBConfiguration.swift */; }; + 7135AF6C2A8CC28E00D8B882 /* FBControlCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D7D6DF882265DE4E00B01F14 /* FBControlCore.framework */; }; + 7135AF6F2A8CC2B000D8B882 /* FBDeviceControl.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D7D6DF8A2265DE4E00B01F14 /* FBDeviceControl.framework */; }; + 7135AF722A8CC2EC00D8B882 /* XCTestBootstrap.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D7D6DF8E2265DE4E00B01F14 /* XCTestBootstrap.framework */; }; + 7135AF762A8CC3B800D8B882 /* FBSimulatorControl.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7135AF752A8CC3B800D8B882 /* FBSimulatorControl.framework */; }; + 7135AF792A8CC51200D8B882 /* CompanionLib.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7135AF312A8C1BBA00D8B882 /* CompanionLib.framework */; }; + 7135AF7F2A8CC5FC00D8B882 /* CompanionLib.h in Headers */ = {isa = PBXBuildFile; fileRef = 7135AF7E2A8CC5FC00D8B882 /* CompanionLib.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 717AFB7328326638009714AB /* XCTestListTestsMethodHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 717AFB7228326638009714AB /* XCTestListTestsMethodHandler.swift */; }; + 717AFB7528328C11009714AB /* XCTestListBundlesMethodHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 717AFB7428328C11009714AB /* XCTestListBundlesMethodHandler.swift */; }; + 7185380C2B22884200D2C033 /* BridgeFuture.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7185380A2B22884200D2C033 /* BridgeFuture.swift */; }; + 7185380D2B22884200D2C033 /* BridgeQueues.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7185380B2B22884200D2C033 /* BridgeQueues.swift */; }; AA0DB08223CF0DCB00E8CDEE /* FBIDBXCTestReporter.h in Headers */ = {isa = PBXBuildFile; fileRef = AA0DB08023CF0DCB00E8CDEE /* FBIDBXCTestReporter.h */; }; - AA34E73C228EBF1B0085F93F /* FBIDBStorageManager.m in Sources */ = {isa = PBXBuildFile; fileRef = AA34E73A228EBF1B0085F93F /* FBIDBStorageManager.m */; }; - AA34E73D228EBF1B0085F93F /* FBIDBStorageManager.h in Headers */ = {isa = PBXBuildFile; fileRef = AA34E73B228EBF1B0085F93F /* FBIDBStorageManager.h */; }; - AA37EEF326A1B000007FA6F0 /* FBXCTestRunFileReader.h in Headers */ = {isa = PBXBuildFile; fileRef = AA37EEF126A1B000007FA6F0 /* FBXCTestRunFileReader.h */; }; - AA37EEF426A1B000007FA6F0 /* FBXCTestRunFileReader.m in Sources */ = {isa = PBXBuildFile; fileRef = AA37EEF226A1B000007FA6F0 /* FBXCTestRunFileReader.m */; }; - AA37EEF726A1B096007FA6F0 /* FBXCTestReporterConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = AA37EEF526A1B096007FA6F0 /* FBXCTestReporterConfiguration.m */; }; - AA37EEF826A1B096007FA6F0 /* FBXCTestReporterConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = AA37EEF626A1B096007FA6F0 /* FBXCTestReporterConfiguration.h */; }; AA8F751F249116B700F3BF18 /* FBiOSTargetDescription.h in Headers */ = {isa = PBXBuildFile; fileRef = AA8F751D249116B700F3BF18 /* FBiOSTargetDescription.h */; }; AA8F7520249116B700F3BF18 /* FBiOSTargetDescription.m in Sources */ = {isa = PBXBuildFile; fileRef = AA8F751E249116B700F3BF18 /* FBiOSTargetDescription.m */; }; - D7107CF822E708C00007FF32 /* FBIDBCompanionServer.mm in Sources */ = {isa = PBXBuildFile; fileRef = D7107CF722E708BF0007FF32 /* FBIDBCompanionServer.mm */; }; - D72CB1C52277837000265160 /* FBDataDownloadInput.h in Headers */ = {isa = PBXBuildFile; fileRef = D72CB1C32277837000265160 /* FBDataDownloadInput.h */; }; - D72CB1C62277837000265160 /* FBDataDownloadInput.m in Sources */ = {isa = PBXBuildFile; fileRef = D72CB1C42277837000265160 /* FBDataDownloadInput.m */; }; D7D6DF892265DE4E00B01F14 /* FBControlCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D7D6DF882265DE4E00B01F14 /* FBControlCore.framework */; }; D7D6DF8B2265DE4E00B01F14 /* FBDeviceControl.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D7D6DF8A2265DE4E00B01F14 /* FBDeviceControl.framework */; }; D7D6DF8D2265DE4E00B01F14 /* FBSimulatorControl.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D7D6DF8C2265DE4E00B01F14 /* FBSimulatorControl.framework */; }; D7D6DF8F2265DE4E00B01F14 /* XCTestBootstrap.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D7D6DF8E2265DE4E00B01F14 /* XCTestBootstrap.framework */; }; D7D6DF9A2265DF2B00B01F14 /* idb.proto in Sources */ = {isa = PBXBuildFile; fileRef = D7D6DF992265DF2B00B01F14 /* idb.proto */; }; - D7D6DF9D2265E04800B01F14 /* libidbGRPC.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D7D6DF942265DF2200B01F14 /* libidbGRPC.a */; }; - D7D6E0052265F0DF00B01F14 /* FBIDBError.h in Headers */ = {isa = PBXBuildFile; fileRef = D7D6DFBB2265F0DF00B01F14 /* FBIDBError.h */; }; - D7D6E0062265F0DF00B01F14 /* FBIDBError.m in Sources */ = {isa = PBXBuildFile; fileRef = D7D6DFBC2265F0DF00B01F14 /* FBIDBError.m */; }; - D7D6E0072265F0DF00B01F14 /* FBIDBPortsConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = D7D6DFBE2265F0DF00B01F14 /* FBIDBPortsConfiguration.h */; }; - D7D6E0082265F0DF00B01F14 /* FBIDBConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = D7D6DFBF2265F0DF00B01F14 /* FBIDBConfiguration.m */; }; - D7D6E00B2265F0DF00B01F14 /* FBIDBConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = D7D6DFC32265F0DF00B01F14 /* FBIDBConfiguration.h */; }; - D7D6E00C2265F0DF00B01F14 /* FBIDBPortsConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = D7D6DFC42265F0DF00B01F14 /* FBIDBPortsConfiguration.m */; }; - D7D6E00D2265F0DF00B01F14 /* FBIDBServiceHandler.mm in Sources */ = {isa = PBXBuildFile; fileRef = D7D6DFC62265F0DF00B01F14 /* FBIDBServiceHandler.mm */; }; - D7D6E00E2265F0DF00B01F14 /* FBIDBCompanionServer.h in Headers */ = {isa = PBXBuildFile; fileRef = D7D6DFC72265F0DF00B01F14 /* FBIDBCompanionServer.h */; }; - D7D6E00F2265F0DF00B01F14 /* FBIDBCommandExecutor.m in Sources */ = {isa = PBXBuildFile; fileRef = D7D6DFC82265F0DF00B01F14 /* FBIDBCommandExecutor.m */; }; - D7D6E0122265F0DF00B01F14 /* FBIDBCommandExecutor.h in Headers */ = {isa = PBXBuildFile; fileRef = D7D6DFCB2265F0DF00B01F14 /* FBIDBCommandExecutor.h */; }; - D7D6E0142265F0DF00B01F14 /* FBIDBServiceHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = D7D6DFCD2265F0DF00B01F14 /* FBIDBServiceHandler.h */; }; D7D6E0282265F0DF00B01F14 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = D7D6DFE32265F0DF00B01F14 /* main.m */; }; - D7D6E02A2265F0DF00B01F14 /* FBXCTestDescriptor.m in Sources */ = {isa = PBXBuildFile; fileRef = D7D6DFE92265F0DF00B01F14 /* FBXCTestDescriptor.m */; }; - D7D6E02C2265F0DF00B01F14 /* FBiOSTargetProvider.m in Sources */ = {isa = PBXBuildFile; fileRef = D7D6DFEB2265F0DF00B01F14 /* FBiOSTargetProvider.m */; }; - D7D6E02E2265F0DF00B01F14 /* FBTestApplicationsPair.h in Headers */ = {isa = PBXBuildFile; fileRef = D7D6DFED2265F0DF00B01F14 /* FBTestApplicationsPair.h */; }; D7D6E02F2265F0DF00B01F14 /* FBiOSTargetStateChangeNotifier.h in Headers */ = {isa = PBXBuildFile; fileRef = D7D6DFEE2265F0DF00B01F14 /* FBiOSTargetStateChangeNotifier.h */; }; - D7D6E0312265F0DF00B01F14 /* FBXCTestDescriptor.h in Headers */ = {isa = PBXBuildFile; fileRef = D7D6DFF02265F0DF00B01F14 /* FBXCTestDescriptor.h */; }; - D7D6E0332265F0DF00B01F14 /* FBiOSTargetProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = D7D6DFF22265F0DF00B01F14 /* FBiOSTargetProvider.h */; }; - D7D6E0352265F0DF00B01F14 /* FBTestApplicationsPair.m in Sources */ = {isa = PBXBuildFile; fileRef = D7D6DFF42265F0DF00B01F14 /* FBTestApplicationsPair.m */; }; D7D6E0362265F0DF00B01F14 /* FBiOSTargetStateChangeNotifier.m in Sources */ = {isa = PBXBuildFile; fileRef = D7D6DFF52265F0DF00B01F14 /* FBiOSTargetStateChangeNotifier.m */; }; + DB0AEE8A27C3822C005048F0 /* GRPCSwiftServerErrorDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB0AEE8927C3822C005048F0 /* GRPCSwiftServerErrorDelegate.swift */; }; + DB15C401283645AF0074D326 /* DebugserverMethodHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB15C400283645AF0074D326 /* DebugserverMethodHandler.swift */; }; + DB15C403283647120074D326 /* AddMediaMethodHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB15C402283647120074D326 /* AddMediaMethodHandler.swift */; }; + DB1FCCFA284F6C8B00EAFB20 /* TaskFBFuture.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB1FCCF9284F6C8B00EAFB20 /* TaskFBFuture.swift */; }; + DB1FCCFC284F6ECA00EAFB20 /* IDBKillswitchBridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB1FCCFB284F6ECA00EAFB20 /* IDBKillswitchBridge.swift */; }; + DB29DC7A283633D000D267BF /* DapMethodHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB29DC79283633D000D267BF /* DapMethodHandler.swift */; }; + DB36C9F828324A6100105C7D /* XctraceRecordMethodHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB36C9F728324A6100105C7D /* XctraceRecordMethodHandler.swift */; }; + DB36C9FA28329B7500105C7D /* CrashLogInfoValueTransformer.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB36C9F928329B7500105C7D /* CrashLogInfoValueTransformer.swift */; }; + DB36C9FD28339B9D00105C7D /* LoggingInterceptor.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB36C9FC28339B9D00105C7D /* LoggingInterceptor.swift */; }; + DB440A92287F01E700D01423 /* FIFOStreamWriter.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB440A90287F01E700D01423 /* FIFOStreamWriter.swift */; }; + DB440A97287F0A7100D01423 /* FIFOStreamWriterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB440A96287F0A7100D01423 /* FIFOStreamWriterTests.swift */; }; + DB440A9A287F12E400D01423 /* MockStreamWriter.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB440A99287F12E400D01423 /* MockStreamWriter.swift */; }; + DB440A9C2880152C00D01423 /* GRPCAsyncResponseStreamWriter+AsyncStreamWriter.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB440A9B2880152C00D01423 /* GRPCAsyncResponseStreamWriter+AsyncStreamWriter.swift */; }; + DB4585BA2808532D004065A2 /* ListAppsMethodHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB4585B92808532B004065A2 /* ListAppsMethodHandler.swift */; }; + DB4585BD280862F7004065A2 /* FileContainerValueTransformer.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB4585BC280862F7004065A2 /* FileContainerValueTransformer.swift */; }; + DB4585BF280863FE004065A2 /* FileDrainWriter.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB4585BE280863FE004065A2 /* FileDrainWriter.swift */; }; + DB4585C32808661B004065A2 /* PullMethodHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB4585C22808661B004065A2 /* PullMethodHandler.swift */; }; + DB465CCC279567AB00FD4583 /* idb_companion-Bridging-Header.h in Headers */ = {isa = PBXBuildFile; fileRef = DB465CCA279567AB00FD4583 /* idb_companion-Bridging-Header.h */; }; + DB4B33CA282D18230080EDEF /* ContactsUpdateMethodHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB4B33C9282D18230080EDEF /* ContactsUpdateMethodHandler.swift */; }; + DB4B33CC282D1A100080EDEF /* GetSettingMethodHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB4B33CB282D1A100080EDEF /* GetSettingMethodHandler.swift */; }; + DB561283287EE17600D28A07 /* Atomic.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBA2ED1C27BBA96100926054 /* Atomic.swift */; }; + DB561284287EE18700D28A07 /* IDBCompanionUtilities.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DB561277287EE0EF00D28A07 /* IDBCompanionUtilities.framework */; }; + DB561289287EE1A800D28A07 /* TaskTimeout.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBB72C86283BACE10065DDB3 /* TaskTimeout.swift */; }; + DB56128A287EE1AD00D28A07 /* TaskSelect.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBE60F3E282A98180043EB57 /* TaskSelect.swift */; }; + DB56128B287EE1BE00D28A07 /* Mutex.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBA2ED1A27BBA96000926054 /* Mutex.swift */; }; + DB56128C287EE1C900D28A07 /* FBTeardownContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB6177CD2819540C00C33A0A /* FBTeardownContext.swift */; }; + DB56128D287EE1CE00D28A07 /* CodeLocation.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBB72C88283BADA00065DDB3 /* CodeLocation.swift */; }; + DB561295287EE21900D28A07 /* AtomicTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB561294287EE21900D28A07 /* AtomicTests.swift */; }; + DB561296287EE21900D28A07 /* IDBCompanionUtilities.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DB561277287EE0EF00D28A07 /* IDBCompanionUtilities.framework */; }; + DB5C38E227B54FCA00401F91 /* GRPCSwiftServer.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB5C38E127B54FCA00401F91 /* GRPCSwiftServer.swift */; }; + DB5C38E527B5512D00401F91 /* MethodPathSetterInterceptor.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB5C38E427B5512D00401F91 /* MethodPathSetterInterceptor.swift */; }; + DB5C38E727B5514500401F91 /* CompanionServiceInterceptors.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB5C38E627B5514500401F91 /* CompanionServiceInterceptors.swift */; }; + DB6177B32817EA7200C33A0A /* ListSettingsMethodHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB6177B22817EA7200C33A0A /* ListSettingsMethodHandler.swift */; }; + DB6177B52817EBE500C33A0A /* ScreenshotMethodHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB6177B42817EBE500C33A0A /* ScreenshotMethodHandler.swift */; }; + DB6177B72817ED3400C33A0A /* TerminateMethodHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB6177B62817ED3400C33A0A /* TerminateMethodHandler.swift */; }; + DB6177B92817EF0100C33A0A /* ApproveMethodHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB6177B82817EF0100C33A0A /* ApproveMethodHandler.swift */; }; + DB6177BB2817FFC300C33A0A /* SettingMethodHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB6177BA2817FFC300C33A0A /* SettingMethodHandler.swift */; }; + DB6177BD281808B200C33A0A /* ClearKeychainMethodHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB6177BC281808B200C33A0A /* ClearKeychainMethodHandler.swift */; }; + DB6177BF28182C1B00C33A0A /* LogMethodHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB6177BE28182C1B00C33A0A /* LogMethodHandler.swift */; }; + DB6177C1281837A100C33A0A /* RecordMethodHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB6177C0281837A100C33A0A /* RecordMethodHandler.swift */; }; + DB6177C928194EDF00C33A0A /* RmMethodHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB6177C828194EDF00C33A0A /* RmMethodHandler.swift */; }; + DB6177CB2819501E00C33A0A /* MvMethodHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB6177CA2819501E00C33A0A /* MvMethodHandler.swift */; }; + DB6177D4281A956600C33A0A /* HidMethodHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB6177D3281A956600C33A0A /* HidMethodHandler.swift */; }; + DB67676627EB2BAD002BBE32 /* GRPC in Frameworks */ = {isa = PBXBuildFile; productRef = DB67676527EB2BAD002BBE32 /* GRPC */; }; + DB67DD31283D16EF003EF139 /* IDBKillswitch.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB67DD30283D16EF003EF139 /* IDBKillswitch.swift */; }; + DB6BBBA32816ABE2003D3894 /* LsMethodHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB6BBBA22816ABE2003D3894 /* LsMethodHandler.swift */; }; + DB6E6C452824152600144D97 /* TailMethodHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB6E6C442824152600144D97 /* TailMethodHandler.swift */; }; + DB7BCC1A28212A80001C1C8D /* IDBPortsConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB7BCC1928212A80001C1C8D /* IDBPortsConfiguration.swift */; }; + DB9722D627CCCCCC00E37D78 /* ConnectMethodHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB9722D527CCCCCC00E37D78 /* ConnectMethodHandler.swift */; }; + DB9722DA27CCCE4600E37D78 /* InstallMethodHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB9722D927CCCE4600E37D78 /* InstallMethodHandler.swift */; }; + DB9722DC27CCCF3A00E37D78 /* XCTestRunMethodHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB9722DB27CCCF3A00E37D78 /* XCTestRunMethodHandler.swift */; }; + DB9B0730281A985700F2C119 /* OpenUrlMethodHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB9B072F281A985700F2C119 /* OpenUrlMethodHandler.swift */; }; + DBA2ED1827BBA95900926054 /* IDBXCTestReporter.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBA2ED1727BBA95900926054 /* IDBXCTestReporter.swift */; }; + DBA2ED1D27BBA96100926054 /* FBControlCoreError+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBA2ED1927BBA96000926054 /* FBControlCoreError+Extension.swift */; }; + DBA31DD127BE72EF0032091C /* AsyncSequence+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBA31DD027BE72EF0032091C /* AsyncSequence+Extension.swift */; }; + DBB3278727F5D157001A8E3A /* LaunchMethodHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBB3278627F5D157001A8E3A /* LaunchMethodHandler.swift */; }; + DBCAE6A82816B6AE00C15D07 /* MkdirMethodHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBCAE6A72816B6AE00C15D07 /* MkdirMethodHandler.swift */; }; + DBCAE6AB2816C8F700C15D07 /* PushMethodHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBCAE6AA2816C8F700C15D07 /* PushMethodHandler.swift */; }; + DBCAE6B22816E72E00C15D07 /* MultisourceFileReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBCAE6B12816E72E00C15D07 /* MultisourceFileReader.swift */; }; + DBCD82DB27D60FF300293F77 /* GrpcDataMappings.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBCD82DA27D60FF300293F77 /* GrpcDataMappings.swift */; }; + DBD20681289939F600145AE5 /* RevokeMethodHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBD20680289939F600145AE5 /* RevokeMethodHandler.swift */; }; + DBE60F3D282A95D10043EB57 /* VideoStreamMethodHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBE60F3C282A95D10043EB57 /* VideoStreamMethodHandler.swift */; }; + DBF5D5CB278EF97500633753 /* IDBGRPCSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DBF5D5C4278EF96E00633753 /* IDBGRPCSwift.framework */; }; + DBF5D5D6278EFA9C00633753 /* CompanionServiceProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBF5D5D5278EFA9C00633753 /* CompanionServiceProvider.swift */; }; + DBF88BBC282900D1003B1494 /* UninstallMethodHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBF88BBB282900D1003B1494 /* UninstallMethodHandler.swift */; }; + DBF88BBE2829032A003B1494 /* FocusMethodHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBF88BBD2829032A003B1494 /* FocusMethodHandler.swift */; }; + DBF88BC02829046A003B1494 /* SimulateMemoryWarningMethodHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBF88BBF2829046A003B1494 /* SimulateMemoryWarningMethodHandler.swift */; }; + DBF88BC22829057F003B1494 /* SendNotificationMethodHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBF88BC12829057F003B1494 /* SendNotificationMethodHandler.swift */; }; + DBF88BC42829152A003B1494 /* SetLocationMethodHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBF88BC32829152A003B1494 /* SetLocationMethodHandler.swift */; }; + DBF88BC628291C9A003B1494 /* InstrumentsRunMethodHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBF88BC528291C9A003B1494 /* InstrumentsRunMethodHandler.swift */; }; + DBF88BCD28294572003B1494 /* CrashListMethodHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBF88BCC28294572003B1494 /* CrashListMethodHandler.swift */; }; + DBF88BCF282945D4003B1494 /* CrashLogQueryValueTransformer.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBF88BCE282945D4003B1494 /* CrashLogQueryValueTransformer.swift */; }; + DBF88BD128294A7B003B1494 /* CrashShowMethodHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBF88BD028294A7B003B1494 /* CrashShowMethodHandler.swift */; }; + DBF88BD328294B5E003B1494 /* CrashDeleteMethodHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBF88BD228294B5E003B1494 /* CrashDeleteMethodHandler.swift */; }; /* End PBXBuildFile section */ /* Begin PBXBuildRule section */ - D7D6DF9C2265DF4E00B01F14 /* PBXBuildRule */ = { + DBF5D5D2278EF9F000633753 /* PBXBuildRule */ = { isa = PBXBuildRule; compilerSpec = com.apple.compilers.proxy.script; filePatterns = "*.proto"; fileType = pattern.proxy; inputFiles = ( + "$(BUILD_DIR)/../../SourcePackages/checkouts/grpc-swift/.build/release/protoc-gen-grpc-swift", + "$(BUILD_DIR)/../../SourcePackages/checkouts/grpc-swift/.build/release/protoc-gen-swift", ); isEditable = 1; + name = "Files '*.proto' using Script"; outputFiles = ( - "$(DERIVED_FILE_DIR)/$(INPUT_FILE_BASE).pb.h", - "$(DERIVED_FILE_DIR)/$(INPUT_FILE_BASE).pb.cc", - "$(DERIVED_FILE_DIR)/$(INPUT_FILE_BASE).grpc.pb.h", - "$(DERIVED_FILE_DIR)/$(INPUT_FILE_BASE).grpc.pb.cc", + "$(DERIVED_FILE_DIR)/$(INPUT_FILE_BASE).pb.swift", + "$(DERIVED_FILE_DIR)/$(INPUT_FILE_BASE).grpc.swift", ); - script = "# Generate grpc code from .proto\nPATH=$PATH:/opt/homebrew/bin/:/usr/local/bin\n\nprotoc --proto_path=$INPUT_FILE_DIR --cpp_out=$DERIVED_FILE_DIR --grpc_out=$DERIVED_FILE_DIR --plugin=protoc-gen-grpc=$(brew --prefix)/bin/grpc_cpp_plugin $INPUT_FILE_PATH\n\n# Copy headers\nmkdir -p ${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}\ncp -a ${DERIVED_FILES_DIR}/*.h ${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}\n"; + runOncePerArchitecture = 0; + script = "# Generate grpc code from .proto\nPATH=$PATH:/opt/homebrew/bin/:/usr/local/bin:$HOME/homebrew/bin/\n\nGRPC_PACKAGE_DIR=${BUILD_DIR%Build/*}SourcePackages/checkouts/grpc-swift\n\nprotoc \\\n --proto_path=$INPUT_FILE_DIR \\\n --swift_out=$DERIVED_FILE_DIR \\\n --grpc-swift_out=$DERIVED_FILE_DIR \\\n --grpc-swift_opt=Visibility=Public \\\n --swift_opt=Visibility=Public \\\n --plugin=protoc-gen-grpc-swift=$GRPC_PACKAGE_DIR/.build/release/protoc-gen-grpc-swift \\\n --plugin=protoc-gen-swift=$GRPC_PACKAGE_DIR/.build/release/protoc-gen-swift \\\n $INPUT_FILE_PATH\n"; }; /* End PBXBuildRule section */ +/* Begin PBXContainerItemProxy section */ + 7135AF7B2A8CC51200D8B882 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D7D6DF0A2265DDEC00B01F14 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 7135AF302A8C1BBA00D8B882; + remoteInfo = CompanionLib; + }; + DB561286287EE18700D28A07 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D7D6DF0A2265DDEC00B01F14 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DB561276287EE0EF00D28A07; + remoteInfo = IDBCompanionUtilities; + }; + DB561297287EE21900D28A07 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D7D6DF0A2265DDEC00B01F14 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DB561276287EE0EF00D28A07; + remoteInfo = IDBCompanionUtilities; + }; + DBF5D5CD278EF97500633753 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = D7D6DF0A2265DDEC00B01F14 /* Project object */; + proxyType = 1; + remoteGlobalIDString = DBF5D5C3278EF96E00633753; + remoteInfo = idbGRPCSwift; + }; +/* End PBXContainerItemProxy section */ + /* Begin PBXCopyFilesBuildPhase section */ D7D6DF102265DDEC00B01F14 /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; @@ -92,116 +203,282 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ - 1665EB692F9D40164D398C85 /* Pods-idb_companion-idbGRPC.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-idb_companion-idbGRPC.debug.xcconfig"; path = "Target Support Files/Pods-idb_companion-idbGRPC/Pods-idb_companion-idbGRPC.debug.xcconfig"; sourceTree = ""; }; - 2F9F718F1D3B7619BFEB9E4E /* Pods-idb_companion-idbGRPC.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-idb_companion-idbGRPC.release.xcconfig"; path = "Target Support Files/Pods-idb_companion-idbGRPC/Pods-idb_companion-idbGRPC.release.xcconfig"; sourceTree = ""; }; - 409D3E336E3BC34257F5C8D8 /* Pods-idbGRPC.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-idbGRPC.debug.xcconfig"; path = "Target Support Files/Pods-idbGRPC/Pods-idbGRPC.debug.xcconfig"; sourceTree = ""; }; - 5821D9A6984DF4BCB878A87A /* Pods-idbGRPC.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-idbGRPC.release.xcconfig"; path = "Target Support Files/Pods-idbGRPC/Pods-idbGRPC.release.xcconfig"; sourceTree = ""; }; - 623D9F0B22E40DCB00D9129C /* FBIDBLogger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBIDBLogger.h; sourceTree = ""; }; - 623D9F0C22E40DCB00D9129C /* FBIDBLogger.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBIDBLogger.m; sourceTree = ""; }; - 713C709226F52F970086D8DF /* FBCodeCoverageRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBCodeCoverageRequest.h; sourceTree = ""; }; - 713C709326F52F970086D8DF /* FBCodeCoverageRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBCodeCoverageRequest.m; sourceTree = ""; }; - 713C709F26F53BC80086D8DF /* FBXCTestRunRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBXCTestRunRequest.h; sourceTree = ""; }; - 713C70A026F53BC80086D8DF /* FBXCTestRunRequest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBXCTestRunRequest.m; sourceTree = ""; }; - 713C70AB26F8D0700086D8DF /* FBIDBAppHostedTestConfiguration.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBIDBAppHostedTestConfiguration.h; sourceTree = ""; }; - 713C70AC26F8D0700086D8DF /* FBIDBAppHostedTestConfiguration.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBIDBAppHostedTestConfiguration.m; sourceTree = ""; }; + 710FD8172811AFE1000832EA /* AccessibilityInfoMethodHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccessibilityInfoMethodHandler.swift; sourceTree = ""; }; + 712F098827E8B3FC005EFD42 /* DescribeMethodHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DescribeMethodHandler.swift; sourceTree = ""; }; + 7135AF0D2A8C1B6100D8B882 /* FBIDBAppHostedTestConfiguration.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBIDBAppHostedTestConfiguration.h; sourceTree = ""; }; + 7135AF0E2A8C1B6100D8B882 /* FBIDBAppHostedTestConfiguration.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBIDBAppHostedTestConfiguration.m; sourceTree = ""; }; + 7135AF0F2A8C1B6100D8B882 /* FBIDBCommandExecutor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBIDBCommandExecutor.h; sourceTree = ""; }; + 7135AF102A8C1B6100D8B882 /* FBIDBCommandExecutor.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBIDBCommandExecutor.m; sourceTree = ""; }; + 7135AF122A8C1B6100D8B882 /* FBIDBError.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBIDBError.h; sourceTree = ""; }; + 7135AF132A8C1B6100D8B882 /* FBIDBError.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBIDBError.m; sourceTree = ""; }; + 7135AF152A8C1B6100D8B882 /* FBCodeCoverageRequest.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBCodeCoverageRequest.h; sourceTree = ""; }; + 7135AF162A8C1B6100D8B882 /* FBCodeCoverageRequest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBCodeCoverageRequest.m; sourceTree = ""; }; + 7135AF172A8C1B6100D8B882 /* FBDsymInstallLinkToBundle.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBDsymInstallLinkToBundle.h; sourceTree = ""; }; + 7135AF182A8C1B6100D8B882 /* FBDsymInstallLinkToBundle.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBDsymInstallLinkToBundle.m; sourceTree = ""; }; + 7135AF192A8C1B6100D8B882 /* FBXCTestRunRequest.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBXCTestRunRequest.h; sourceTree = ""; }; + 7135AF1A2A8C1B6100D8B882 /* FBXCTestRunRequest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBXCTestRunRequest.m; sourceTree = ""; }; + 7135AF1C2A8C1B6100D8B882 /* FBDataDownloadInput.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBDataDownloadInput.h; sourceTree = ""; }; + 7135AF1D2A8C1B6100D8B882 /* FBDataDownloadInput.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBDataDownloadInput.m; sourceTree = ""; }; + 7135AF1E2A8C1B6100D8B882 /* FBIDBLogger.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBIDBLogger.h; sourceTree = ""; }; + 7135AF1F2A8C1B6100D8B882 /* FBIDBLogger.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBIDBLogger.m; sourceTree = ""; }; + 7135AF202A8C1B6100D8B882 /* FBIDBStorageManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBIDBStorageManager.h; sourceTree = ""; }; + 7135AF212A8C1B6100D8B882 /* FBIDBStorageManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBIDBStorageManager.m; sourceTree = ""; }; + 7135AF222A8C1B6100D8B882 /* FBIDBTestOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBIDBTestOperation.h; sourceTree = ""; }; + 7135AF232A8C1B6100D8B882 /* FBIDBTestOperation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBIDBTestOperation.m; sourceTree = ""; }; + 7135AF242A8C1B6100D8B882 /* FBTestApplicationsPair.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBTestApplicationsPair.h; sourceTree = ""; }; + 7135AF252A8C1B6100D8B882 /* FBTestApplicationsPair.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBTestApplicationsPair.m; sourceTree = ""; }; + 7135AF262A8C1B6100D8B882 /* FBXCTestDescriptor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBXCTestDescriptor.h; sourceTree = ""; }; + 7135AF272A8C1B6100D8B882 /* FBXCTestDescriptor.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBXCTestDescriptor.m; sourceTree = ""; }; + 7135AF282A8C1B6100D8B882 /* FBXCTestReporterConfiguration.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBXCTestReporterConfiguration.h; sourceTree = ""; }; + 7135AF292A8C1B6100D8B882 /* FBXCTestReporterConfiguration.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBXCTestReporterConfiguration.m; sourceTree = ""; }; + 7135AF2A2A8C1B6100D8B882 /* FBXCTestRunFileReader.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FBXCTestRunFileReader.h; sourceTree = ""; }; + 7135AF2B2A8C1B6100D8B882 /* FBXCTestRunFileReader.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = FBXCTestRunFileReader.m; sourceTree = ""; }; + 7135AF312A8C1BBA00D8B882 /* CompanionLib.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = CompanionLib.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 7135AF582A8C2A1100D8B882 /* EmptyEventReporter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EmptyEventReporter.swift; sourceTree = ""; }; + 7135AF5A2A8C2C6A00D8B882 /* FBiOSTargetProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBiOSTargetProvider.h; sourceTree = ""; }; + 7135AF5B2A8C2C6A00D8B882 /* FBiOSTargetProvider.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBiOSTargetProvider.m; sourceTree = ""; }; + 7135AF752A8CC3B800D8B882 /* FBSimulatorControl.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = FBSimulatorControl.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 7135AF7E2A8CC5FC00D8B882 /* CompanionLib.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CompanionLib.h; sourceTree = ""; }; 716E3C1E26210B5C00D7DA42 /* libgrpc++.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = "libgrpc++.dylib"; path = "/usr/local/lib/libgrpc++.dylib"; sourceTree = ""; }; 716E3C2126210B9B00D7DA42 /* libgrpc.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libgrpc.dylib; path = /usr/local/lib/libgrpc.dylib; sourceTree = ""; }; 716E3C782625D7AE00D7DA42 /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; }; - 79B8968AB3BFDB9737B0FF9E /* Pods-idb_companion.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-idb_companion.debug.xcconfig"; path = "Target Support Files/Pods-idb_companion/Pods-idb_companion.debug.xcconfig"; sourceTree = ""; }; - AA0DB07B23CF0D9800E8CDEE /* FBIDBTestOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBIDBTestOperation.m; sourceTree = ""; }; - AA0DB07C23CF0D9800E8CDEE /* FBIDBTestOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBIDBTestOperation.h; sourceTree = ""; }; - AA0DB07F23CF0DCA00E8CDEE /* FBIDBXCTestReporter.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = FBIDBXCTestReporter.mm; sourceTree = ""; }; + 717AFB7228326638009714AB /* XCTestListTestsMethodHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XCTestListTestsMethodHandler.swift; sourceTree = ""; }; + 717AFB7428328C11009714AB /* XCTestListBundlesMethodHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XCTestListBundlesMethodHandler.swift; sourceTree = ""; }; + 7185380A2B22884200D2C033 /* BridgeFuture.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BridgeFuture.swift; sourceTree = ""; }; + 7185380B2B22884200D2C033 /* BridgeQueues.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BridgeQueues.swift; sourceTree = ""; }; AA0DB08023CF0DCB00E8CDEE /* FBIDBXCTestReporter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBIDBXCTestReporter.h; sourceTree = ""; }; - AA34E73A228EBF1B0085F93F /* FBIDBStorageManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBIDBStorageManager.m; sourceTree = ""; }; - AA34E73B228EBF1B0085F93F /* FBIDBStorageManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBIDBStorageManager.h; sourceTree = ""; }; - AA37EEF126A1B000007FA6F0 /* FBXCTestRunFileReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBXCTestRunFileReader.h; sourceTree = ""; }; - AA37EEF226A1B000007FA6F0 /* FBXCTestRunFileReader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBXCTestRunFileReader.m; sourceTree = ""; }; - AA37EEF526A1B096007FA6F0 /* FBXCTestReporterConfiguration.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBXCTestReporterConfiguration.m; sourceTree = ""; }; - AA37EEF626A1B096007FA6F0 /* FBXCTestReporterConfiguration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBXCTestReporterConfiguration.h; sourceTree = ""; }; AA8F751D249116B700F3BF18 /* FBiOSTargetDescription.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBiOSTargetDescription.h; sourceTree = ""; }; AA8F751E249116B700F3BF18 /* FBiOSTargetDescription.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBiOSTargetDescription.m; sourceTree = ""; }; - BEC79D15EF2190287C8A0D82 /* libPods-idb_companion.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-idb_companion.a"; sourceTree = BUILT_PRODUCTS_DIR; }; - CEFAE887E28B2550E73E65C6 /* libPods-idbGRPC.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-idbGRPC.a"; sourceTree = BUILT_PRODUCTS_DIR; }; - D5D2CAAA6E490662111C69F6 /* Pods-idb_companion.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-idb_companion.release.xcconfig"; path = "Target Support Files/Pods-idb_companion/Pods-idb_companion.release.xcconfig"; sourceTree = ""; }; - D7107CF722E708BF0007FF32 /* FBIDBCompanionServer.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = FBIDBCompanionServer.mm; sourceTree = ""; }; D720AE7323CE1D6E0040F01B /* libcares.2.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libcares.2.dylib; path = /usr/local/lib/libcares.2.dylib; sourceTree = ""; }; - D72CB1C32277837000265160 /* FBDataDownloadInput.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBDataDownloadInput.h; sourceTree = ""; }; - D72CB1C42277837000265160 /* FBDataDownloadInput.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBDataDownloadInput.m; sourceTree = ""; }; D7D6DF122265DDEC00B01F14 /* idb_companion */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = idb_companion; sourceTree = BUILT_PRODUCTS_DIR; }; D7D6DF882265DE4E00B01F14 /* FBControlCore.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = FBControlCore.framework; sourceTree = BUILT_PRODUCTS_DIR; }; D7D6DF8A2265DE4E00B01F14 /* FBDeviceControl.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = FBDeviceControl.framework; sourceTree = BUILT_PRODUCTS_DIR; }; D7D6DF8C2265DE4E00B01F14 /* FBSimulatorControl.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = FBSimulatorControl.framework; sourceTree = BUILT_PRODUCTS_DIR; }; D7D6DF8E2265DE4E00B01F14 /* XCTestBootstrap.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = XCTestBootstrap.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - D7D6DF942265DF2200B01F14 /* libidbGRPC.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libidbGRPC.a; sourceTree = BUILT_PRODUCTS_DIR; }; D7D6DF992265DF2B00B01F14 /* idb.proto */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.protobuf; path = idb.proto; sourceTree = ""; }; D7D6DFA32265E76200B01F14 /* libprotobuf.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libprotobuf.a; path = /usr/local/lib/libprotobuf.a; sourceTree = ""; }; - D7D6DFBB2265F0DF00B01F14 /* FBIDBError.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBIDBError.h; sourceTree = ""; }; - D7D6DFBC2265F0DF00B01F14 /* FBIDBError.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBIDBError.m; sourceTree = ""; }; - D7D6DFBE2265F0DF00B01F14 /* FBIDBPortsConfiguration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBIDBPortsConfiguration.h; sourceTree = ""; }; - D7D6DFBF2265F0DF00B01F14 /* FBIDBConfiguration.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBIDBConfiguration.m; sourceTree = ""; }; - D7D6DFC32265F0DF00B01F14 /* FBIDBConfiguration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBIDBConfiguration.h; sourceTree = ""; }; - D7D6DFC42265F0DF00B01F14 /* FBIDBPortsConfiguration.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBIDBPortsConfiguration.m; sourceTree = ""; }; - D7D6DFC62265F0DF00B01F14 /* FBIDBServiceHandler.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = FBIDBServiceHandler.mm; sourceTree = ""; }; - D7D6DFC72265F0DF00B01F14 /* FBIDBCompanionServer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBIDBCompanionServer.h; sourceTree = ""; }; - D7D6DFC82265F0DF00B01F14 /* FBIDBCommandExecutor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBIDBCommandExecutor.m; sourceTree = ""; }; - D7D6DFCB2265F0DF00B01F14 /* FBIDBCommandExecutor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBIDBCommandExecutor.h; sourceTree = ""; }; - D7D6DFCD2265F0DF00B01F14 /* FBIDBServiceHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBIDBServiceHandler.h; sourceTree = ""; }; D7D6DFE32265F0DF00B01F14 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; D7D6DFE62265F0DF00B01F14 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - D7D6DFE92265F0DF00B01F14 /* FBXCTestDescriptor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBXCTestDescriptor.m; sourceTree = ""; }; - D7D6DFEB2265F0DF00B01F14 /* FBiOSTargetProvider.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBiOSTargetProvider.m; sourceTree = ""; }; - D7D6DFED2265F0DF00B01F14 /* FBTestApplicationsPair.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBTestApplicationsPair.h; sourceTree = ""; }; D7D6DFEE2265F0DF00B01F14 /* FBiOSTargetStateChangeNotifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBiOSTargetStateChangeNotifier.h; sourceTree = ""; }; - D7D6DFF02265F0DF00B01F14 /* FBXCTestDescriptor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBXCTestDescriptor.h; sourceTree = ""; }; - D7D6DFF22265F0DF00B01F14 /* FBiOSTargetProvider.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FBiOSTargetProvider.h; sourceTree = ""; }; - D7D6DFF42265F0DF00B01F14 /* FBTestApplicationsPair.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBTestApplicationsPair.m; sourceTree = ""; }; D7D6DFF52265F0DF00B01F14 /* FBiOSTargetStateChangeNotifier.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FBiOSTargetStateChangeNotifier.m; sourceTree = ""; }; + DB0AEE8927C3822C005048F0 /* GRPCSwiftServerErrorDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GRPCSwiftServerErrorDelegate.swift; sourceTree = ""; }; + DB15C400283645AF0074D326 /* DebugserverMethodHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DebugserverMethodHandler.swift; sourceTree = ""; }; + DB15C402283647120074D326 /* AddMediaMethodHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddMediaMethodHandler.swift; sourceTree = ""; }; + DB1FCCF9284F6C8B00EAFB20 /* TaskFBFuture.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TaskFBFuture.swift; sourceTree = ""; }; + DB1FCCFB284F6ECA00EAFB20 /* IDBKillswitchBridge.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IDBKillswitchBridge.swift; sourceTree = ""; }; + DB29DC79283633D000D267BF /* DapMethodHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DapMethodHandler.swift; sourceTree = ""; }; + DB36C9F728324A6100105C7D /* XctraceRecordMethodHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XctraceRecordMethodHandler.swift; sourceTree = ""; }; + DB36C9F928329B7500105C7D /* CrashLogInfoValueTransformer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CrashLogInfoValueTransformer.swift; sourceTree = ""; }; + DB36C9FC28339B9D00105C7D /* LoggingInterceptor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoggingInterceptor.swift; sourceTree = ""; }; + DB440A90287F01E700D01423 /* FIFOStreamWriter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FIFOStreamWriter.swift; sourceTree = ""; }; + DB440A96287F0A7100D01423 /* FIFOStreamWriterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FIFOStreamWriterTests.swift; sourceTree = ""; }; + DB440A99287F12E400D01423 /* MockStreamWriter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockStreamWriter.swift; sourceTree = ""; }; + DB440A9B2880152C00D01423 /* GRPCAsyncResponseStreamWriter+AsyncStreamWriter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "GRPCAsyncResponseStreamWriter+AsyncStreamWriter.swift"; sourceTree = ""; }; + DB4585B92808532B004065A2 /* ListAppsMethodHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ListAppsMethodHandler.swift; sourceTree = ""; }; + DB4585BC280862F7004065A2 /* FileContainerValueTransformer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileContainerValueTransformer.swift; sourceTree = ""; }; + DB4585BE280863FE004065A2 /* FileDrainWriter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileDrainWriter.swift; sourceTree = ""; }; + DB4585C22808661B004065A2 /* PullMethodHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PullMethodHandler.swift; sourceTree = ""; }; + DB465CCA279567AB00FD4583 /* idb_companion-Bridging-Header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "idb_companion-Bridging-Header.h"; sourceTree = ""; }; + DB4B33C9282D18230080EDEF /* ContactsUpdateMethodHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactsUpdateMethodHandler.swift; sourceTree = ""; }; + DB4B33CB282D1A100080EDEF /* GetSettingMethodHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GetSettingMethodHandler.swift; sourceTree = ""; }; + DB561277287EE0EF00D28A07 /* IDBCompanionUtilities.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = IDBCompanionUtilities.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + DB561292287EE21900D28A07 /* IDBCompanionUtilitiesTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = IDBCompanionUtilitiesTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + DB561294287EE21900D28A07 /* AtomicTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AtomicTests.swift; sourceTree = ""; }; + DB5C38E127B54FCA00401F91 /* GRPCSwiftServer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GRPCSwiftServer.swift; sourceTree = ""; }; + DB5C38E427B5512D00401F91 /* MethodPathSetterInterceptor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MethodPathSetterInterceptor.swift; sourceTree = ""; }; + DB5C38E627B5514500401F91 /* CompanionServiceInterceptors.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompanionServiceInterceptors.swift; sourceTree = ""; }; + DB6177B22817EA7200C33A0A /* ListSettingsMethodHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListSettingsMethodHandler.swift; sourceTree = ""; }; + DB6177B42817EBE500C33A0A /* ScreenshotMethodHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScreenshotMethodHandler.swift; sourceTree = ""; }; + DB6177B62817ED3400C33A0A /* TerminateMethodHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TerminateMethodHandler.swift; sourceTree = ""; }; + DB6177B82817EF0100C33A0A /* ApproveMethodHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApproveMethodHandler.swift; sourceTree = ""; }; + DB6177BA2817FFC300C33A0A /* SettingMethodHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingMethodHandler.swift; sourceTree = ""; }; + DB6177BC281808B200C33A0A /* ClearKeychainMethodHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClearKeychainMethodHandler.swift; sourceTree = ""; }; + DB6177BE28182C1B00C33A0A /* LogMethodHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LogMethodHandler.swift; sourceTree = ""; }; + DB6177C0281837A100C33A0A /* RecordMethodHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecordMethodHandler.swift; sourceTree = ""; }; + DB6177C828194EDF00C33A0A /* RmMethodHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RmMethodHandler.swift; sourceTree = ""; }; + DB6177CA2819501E00C33A0A /* MvMethodHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MvMethodHandler.swift; sourceTree = ""; }; + DB6177CD2819540C00C33A0A /* FBTeardownContext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FBTeardownContext.swift; sourceTree = ""; }; + DB6177D3281A956600C33A0A /* HidMethodHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HidMethodHandler.swift; sourceTree = ""; }; + DB67DD30283D16EF003EF139 /* IDBKillswitch.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IDBKillswitch.swift; sourceTree = ""; }; + DB6BBBA22816ABE2003D3894 /* LsMethodHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LsMethodHandler.swift; sourceTree = ""; }; + DB6E6C442824152600144D97 /* TailMethodHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TailMethodHandler.swift; sourceTree = ""; }; + DB7BCC1928212A80001C1C8D /* IDBPortsConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IDBPortsConfiguration.swift; sourceTree = ""; }; + DB9722D527CCCCCC00E37D78 /* ConnectMethodHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConnectMethodHandler.swift; sourceTree = ""; }; + DB9722D927CCCE4600E37D78 /* InstallMethodHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstallMethodHandler.swift; sourceTree = ""; }; + DB9722DB27CCCF3A00E37D78 /* XCTestRunMethodHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XCTestRunMethodHandler.swift; sourceTree = ""; }; + DB9B072F281A985700F2C119 /* OpenUrlMethodHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OpenUrlMethodHandler.swift; sourceTree = ""; }; + DBA2ED1727BBA95900926054 /* IDBXCTestReporter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IDBXCTestReporter.swift; sourceTree = ""; }; + DBA2ED1927BBA96000926054 /* FBControlCoreError+Extension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "FBControlCoreError+Extension.swift"; sourceTree = ""; }; + DBA2ED1A27BBA96000926054 /* Mutex.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Mutex.swift; sourceTree = ""; }; + DBA2ED1C27BBA96100926054 /* Atomic.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Atomic.swift; sourceTree = ""; }; + DBA31DD027BE72EF0032091C /* AsyncSequence+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AsyncSequence+Extension.swift"; sourceTree = ""; }; + DBB3278627F5D157001A8E3A /* LaunchMethodHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LaunchMethodHandler.swift; sourceTree = ""; }; + DBB72C84283B957F0065DDB3 /* IDBConfiguration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IDBConfiguration.swift; sourceTree = ""; }; + DBB72C86283BACE10065DDB3 /* TaskTimeout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TaskTimeout.swift; sourceTree = ""; }; + DBB72C88283BADA00065DDB3 /* CodeLocation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CodeLocation.swift; sourceTree = ""; }; + DBCAE6A72816B6AE00C15D07 /* MkdirMethodHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MkdirMethodHandler.swift; sourceTree = ""; }; + DBCAE6AA2816C8F700C15D07 /* PushMethodHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PushMethodHandler.swift; sourceTree = ""; }; + DBCAE6B12816E72E00C15D07 /* MultisourceFileReader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultisourceFileReader.swift; sourceTree = ""; }; + DBCD82DA27D60FF300293F77 /* GrpcDataMappings.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GrpcDataMappings.swift; sourceTree = ""; }; + DBD20680289939F600145AE5 /* RevokeMethodHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RevokeMethodHandler.swift; sourceTree = ""; }; + DBE60F3C282A95D10043EB57 /* VideoStreamMethodHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VideoStreamMethodHandler.swift; sourceTree = ""; }; + DBE60F3E282A98180043EB57 /* TaskSelect.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TaskSelect.swift; sourceTree = ""; }; + DBF5D5C4278EF96E00633753 /* IDBGRPCSwift.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = IDBGRPCSwift.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + DBF5D5D5278EFA9C00633753 /* CompanionServiceProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CompanionServiceProvider.swift; sourceTree = ""; }; + DBF88BBB282900D1003B1494 /* UninstallMethodHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UninstallMethodHandler.swift; sourceTree = ""; }; + DBF88BBD2829032A003B1494 /* FocusMethodHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FocusMethodHandler.swift; sourceTree = ""; }; + DBF88BBF2829046A003B1494 /* SimulateMemoryWarningMethodHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimulateMemoryWarningMethodHandler.swift; sourceTree = ""; }; + DBF88BC12829057F003B1494 /* SendNotificationMethodHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SendNotificationMethodHandler.swift; sourceTree = ""; }; + DBF88BC32829152A003B1494 /* SetLocationMethodHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SetLocationMethodHandler.swift; sourceTree = ""; }; + DBF88BC528291C9A003B1494 /* InstrumentsRunMethodHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstrumentsRunMethodHandler.swift; sourceTree = ""; }; + DBF88BCC28294572003B1494 /* CrashListMethodHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CrashListMethodHandler.swift; sourceTree = ""; }; + DBF88BCE282945D4003B1494 /* CrashLogQueryValueTransformer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CrashLogQueryValueTransformer.swift; sourceTree = ""; }; + DBF88BD028294A7B003B1494 /* CrashShowMethodHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CrashShowMethodHandler.swift; sourceTree = ""; }; + DBF88BD228294B5E003B1494 /* CrashDeleteMethodHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CrashDeleteMethodHandler.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ + 7135AF2E2A8C1BBA00D8B882 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 7135AF6F2A8CC2B000D8B882 /* FBDeviceControl.framework in Frameworks */, + 7135AF762A8CC3B800D8B882 /* FBSimulatorControl.framework in Frameworks */, + 7135AF722A8CC2EC00D8B882 /* XCTestBootstrap.framework in Frameworks */, + 7135AF6C2A8CC28E00D8B882 /* FBControlCore.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; D7D6DF0F2265DDEC00B01F14 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( D7D6DF892265DE4E00B01F14 /* FBControlCore.framework in Frameworks */, D7D6DF8B2265DE4E00B01F14 /* FBDeviceControl.framework in Frameworks */, + DB561284287EE18700D28A07 /* IDBCompanionUtilities.framework in Frameworks */, D7D6DF8D2265DE4E00B01F14 /* FBSimulatorControl.framework in Frameworks */, - D7D6DF9D2265E04800B01F14 /* libidbGRPC.a in Frameworks */, D7D6DF8F2265DE4E00B01F14 /* XCTestBootstrap.framework in Frameworks */, - 7E30A85F7039E2EB464C03DE /* libPods-idb_companion.a in Frameworks */, + DBF5D5CB278EF97500633753 /* IDBGRPCSwift.framework in Frameworks */, + 7135AF792A8CC51200D8B882 /* CompanionLib.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DB561274287EE0EF00D28A07 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( ); runOnlyForDeploymentPostprocessing = 0; }; - D7D6DF922265DF2200B01F14 /* Frameworks */ = { + DB56128F287EE21900D28A07 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 1CF77457F352C3C1079A442C /* libPods-idbGRPC.a in Frameworks */, + DB561296287EE21900D28A07 /* IDBCompanionUtilities.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DBF5D5C1278EF96E00633753 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + DB67676627EB2BAD002BBE32 /* GRPC in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - 713C709126F52F970086D8DF /* Request */ = { + 7135AF0B2A8C1B6100D8B882 /* CompanionLib */ = { + isa = PBXGroup; + children = ( + 718538092B22884200D2C033 /* BridgeFuture */, + 7135AF0C2A8C1B6100D8B882 /* Configuration */, + 7135AF0F2A8C1B6100D8B882 /* FBIDBCommandExecutor.h */, + 7135AF102A8C1B6100D8B882 /* FBIDBCommandExecutor.m */, + 7135AF112A8C1B6100D8B882 /* Reporting */, + 7135AF142A8C1B6100D8B882 /* Request */, + 7135AF1B2A8C1B6100D8B882 /* Utility */, + 7135AF7E2A8CC5FC00D8B882 /* CompanionLib.h */, + ); + path = CompanionLib; + sourceTree = ""; + }; + 7135AF0C2A8C1B6100D8B882 /* Configuration */ = { + isa = PBXGroup; + children = ( + 7135AF0D2A8C1B6100D8B882 /* FBIDBAppHostedTestConfiguration.h */, + 7135AF0E2A8C1B6100D8B882 /* FBIDBAppHostedTestConfiguration.m */, + ); + path = Configuration; + sourceTree = ""; + }; + 7135AF112A8C1B6100D8B882 /* Reporting */ = { isa = PBXGroup; children = ( - 713C709F26F53BC80086D8DF /* FBXCTestRunRequest.h */, - 713C70A026F53BC80086D8DF /* FBXCTestRunRequest.m */, - 713C709226F52F970086D8DF /* FBCodeCoverageRequest.h */, - 713C709326F52F970086D8DF /* FBCodeCoverageRequest.m */, + 7135AF122A8C1B6100D8B882 /* FBIDBError.h */, + 7135AF132A8C1B6100D8B882 /* FBIDBError.m */, + ); + path = Reporting; + sourceTree = ""; + }; + 7135AF142A8C1B6100D8B882 /* Request */ = { + isa = PBXGroup; + children = ( + 7135AF152A8C1B6100D8B882 /* FBCodeCoverageRequest.h */, + 7135AF162A8C1B6100D8B882 /* FBCodeCoverageRequest.m */, + 7135AF172A8C1B6100D8B882 /* FBDsymInstallLinkToBundle.h */, + 7135AF182A8C1B6100D8B882 /* FBDsymInstallLinkToBundle.m */, + 7135AF192A8C1B6100D8B882 /* FBXCTestRunRequest.h */, + 7135AF1A2A8C1B6100D8B882 /* FBXCTestRunRequest.m */, ); path = Request; sourceTree = ""; }; + 7135AF1B2A8C1B6100D8B882 /* Utility */ = { + isa = PBXGroup; + children = ( + 7135AF5A2A8C2C6A00D8B882 /* FBiOSTargetProvider.h */, + 7135AF5B2A8C2C6A00D8B882 /* FBiOSTargetProvider.m */, + 7135AF1C2A8C1B6100D8B882 /* FBDataDownloadInput.h */, + 7135AF1D2A8C1B6100D8B882 /* FBDataDownloadInput.m */, + 7135AF1E2A8C1B6100D8B882 /* FBIDBLogger.h */, + 7135AF1F2A8C1B6100D8B882 /* FBIDBLogger.m */, + 7135AF202A8C1B6100D8B882 /* FBIDBStorageManager.h */, + 7135AF212A8C1B6100D8B882 /* FBIDBStorageManager.m */, + 7135AF222A8C1B6100D8B882 /* FBIDBTestOperation.h */, + 7135AF232A8C1B6100D8B882 /* FBIDBTestOperation.m */, + 7135AF242A8C1B6100D8B882 /* FBTestApplicationsPair.h */, + 7135AF252A8C1B6100D8B882 /* FBTestApplicationsPair.m */, + 7135AF262A8C1B6100D8B882 /* FBXCTestDescriptor.h */, + 7135AF272A8C1B6100D8B882 /* FBXCTestDescriptor.m */, + 7135AF282A8C1B6100D8B882 /* FBXCTestReporterConfiguration.h */, + 7135AF292A8C1B6100D8B882 /* FBXCTestReporterConfiguration.m */, + 7135AF2A2A8C1B6100D8B882 /* FBXCTestRunFileReader.h */, + 7135AF2B2A8C1B6100D8B882 /* FBXCTestRunFileReader.m */, + ); + path = Utility; + sourceTree = ""; + }; + 718538092B22884200D2C033 /* BridgeFuture */ = { + isa = PBXGroup; + children = ( + 7185380A2B22884200D2C033 /* BridgeFuture.swift */, + 7185380B2B22884200D2C033 /* BridgeQueues.swift */, + ); + path = BridgeFuture; + sourceTree = ""; + }; D7D6DF092265DDEC00B01F14 = { isa = PBXGroup; children = ( + 7135AF0B2A8C1B6100D8B882 /* CompanionLib */, D7D6DFA82265F0DF00B01F14 /* idb_companion */, D7D6DF982265DF2B00B01F14 /* proto */, + DB561278287EE0F000D28A07 /* IDBCompanionUtilities */, + DB561293287EE21900D28A07 /* IDBCompanionUtilitiesTests */, D7D6DF132265DDEC00B01F14 /* Products */, D7D6DF872265DE4E00B01F14 /* Frameworks */, - E47FF620763B1FAD507E99B9 /* Pods */, ); sourceTree = ""; }; @@ -209,7 +486,10 @@ isa = PBXGroup; children = ( D7D6DF122265DDEC00B01F14 /* idb_companion */, - D7D6DF942265DF2200B01F14 /* libidbGRPC.a */, + DBF5D5C4278EF96E00633753 /* IDBGRPCSwift.framework */, + DB561277287EE0EF00D28A07 /* IDBCompanionUtilities.framework */, + DB561292287EE21900D28A07 /* IDBCompanionUtilitiesTests.xctest */, + 7135AF312A8C1BBA00D8B882 /* CompanionLib.framework */, ); name = Products; sourceTree = ""; @@ -217,6 +497,7 @@ D7D6DF872265DE4E00B01F14 /* Frameworks */ = { isa = PBXGroup; children = ( + 7135AF752A8CC3B800D8B882 /* FBSimulatorControl.framework */, 716E3C782625D7AE00D7DA42 /* libz.tbd */, 716E3C2126210B9B00D7DA42 /* libgrpc.dylib */, 716E3C1E26210B5C00D7DA42 /* libgrpc++.dylib */, @@ -226,8 +507,6 @@ D7D6DF8C2265DE4E00B01F14 /* FBSimulatorControl.framework */, D7D6DFA32265E76200B01F14 /* libprotobuf.a */, D7D6DF8E2265DE4E00B01F14 /* XCTestBootstrap.framework */, - BEC79D15EF2190287C8A0D82 /* libPods-idb_companion.a */, - CEFAE887E28B2550E73E65C6 /* libPods-idbGRPC.a */, ); name = Frameworks; sourceTree = ""; @@ -243,10 +522,10 @@ D7D6DFA82265F0DF00B01F14 /* idb_companion */ = { isa = PBXGroup; children = ( + DB465CC7279567AB00FD4583 /* Bridging */, + DBF5D5D3278EFA7900633753 /* SwiftServer */, D7D6DFBD2265F0DF00B01F14 /* Configuration */, D7D6DFB52265F0DF00B01F14 /* Reporting */, - 713C709126F52F970086D8DF /* Request */, - D7D6DFC52265F0DF00B01F14 /* Server */, D7D6DFE72265F0DF00B01F14 /* Utility */, D7D6DFE62265F0DF00B01F14 /* Info.plist */, D7D6DFE32265F0DF00B01F14 /* main.m */, @@ -257,8 +536,6 @@ D7D6DFB52265F0DF00B01F14 /* Reporting */ = { isa = PBXGroup; children = ( - D7D6DFBB2265F0DF00B01F14 /* FBIDBError.h */, - D7D6DFBC2265F0DF00B01F14 /* FBIDBError.m */, AA8F751D249116B700F3BF18 /* FBiOSTargetDescription.h */, AA8F751E249116B700F3BF18 /* FBiOSTargetDescription.m */, ); @@ -268,78 +545,187 @@ D7D6DFBD2265F0DF00B01F14 /* Configuration */ = { isa = PBXGroup; children = ( - D7D6DFC32265F0DF00B01F14 /* FBIDBConfiguration.h */, - D7D6DFBF2265F0DF00B01F14 /* FBIDBConfiguration.m */, - D7D6DFBE2265F0DF00B01F14 /* FBIDBPortsConfiguration.h */, - D7D6DFC42265F0DF00B01F14 /* FBIDBPortsConfiguration.m */, - 713C70AB26F8D0700086D8DF /* FBIDBAppHostedTestConfiguration.h */, - 713C70AC26F8D0700086D8DF /* FBIDBAppHostedTestConfiguration.m */, + 7135AF582A8C2A1100D8B882 /* EmptyEventReporter.swift */, + DBB72C84283B957F0065DDB3 /* IDBConfiguration.swift */, + DB7BCC1928212A80001C1C8D /* IDBPortsConfiguration.swift */, + DB67DD30283D16EF003EF139 /* IDBKillswitch.swift */, + DB1FCCFB284F6ECA00EAFB20 /* IDBKillswitchBridge.swift */, ); path = Configuration; sourceTree = ""; }; - D7D6DFC52265F0DF00B01F14 /* Server */ = { - isa = PBXGroup; - children = ( - D7D6DFCB2265F0DF00B01F14 /* FBIDBCommandExecutor.h */, - D7D6DFC82265F0DF00B01F14 /* FBIDBCommandExecutor.m */, - D7D6DFC72265F0DF00B01F14 /* FBIDBCompanionServer.h */, - D7107CF722E708BF0007FF32 /* FBIDBCompanionServer.mm */, - D7D6DFCD2265F0DF00B01F14 /* FBIDBServiceHandler.h */, - D7D6DFC62265F0DF00B01F14 /* FBIDBServiceHandler.mm */, - ); - path = Server; - sourceTree = ""; - }; D7D6DFE72265F0DF00B01F14 /* Utility */ = { isa = PBXGroup; children = ( - D72CB1C32277837000265160 /* FBDataDownloadInput.h */, - D72CB1C42277837000265160 /* FBDataDownloadInput.m */, - 623D9F0B22E40DCB00D9129C /* FBIDBLogger.h */, - 623D9F0C22E40DCB00D9129C /* FBIDBLogger.m */, - AA34E73B228EBF1B0085F93F /* FBIDBStorageManager.h */, - AA34E73A228EBF1B0085F93F /* FBIDBStorageManager.m */, - AA0DB07C23CF0D9800E8CDEE /* FBIDBTestOperation.h */, - AA0DB07B23CF0D9800E8CDEE /* FBIDBTestOperation.m */, + DBA31DD027BE72EF0032091C /* AsyncSequence+Extension.swift */, + DBA2ED1927BBA96000926054 /* FBControlCoreError+Extension.swift */, + DB4585BE280863FE004065A2 /* FileDrainWriter.swift */, + DB440A9B2880152C00D01423 /* GRPCAsyncResponseStreamWriter+AsyncStreamWriter.swift */, + DBCAE6B12816E72E00C15D07 /* MultisourceFileReader.swift */, + DB1FCCF9284F6C8B00EAFB20 /* TaskFBFuture.swift */, + DBF4764527B69294001E39C2 /* IDBXCTestReporter */, AA0DB08023CF0DCB00E8CDEE /* FBIDBXCTestReporter.h */, - AA0DB07F23CF0DCA00E8CDEE /* FBIDBXCTestReporter.mm */, - D7D6DFF22265F0DF00B01F14 /* FBiOSTargetProvider.h */, - D7D6DFEB2265F0DF00B01F14 /* FBiOSTargetProvider.m */, D7D6DFEE2265F0DF00B01F14 /* FBiOSTargetStateChangeNotifier.h */, D7D6DFF52265F0DF00B01F14 /* FBiOSTargetStateChangeNotifier.m */, - D7D6DFED2265F0DF00B01F14 /* FBTestApplicationsPair.h */, - D7D6DFF42265F0DF00B01F14 /* FBTestApplicationsPair.m */, - D7D6DFF02265F0DF00B01F14 /* FBXCTestDescriptor.h */, - D7D6DFE92265F0DF00B01F14 /* FBXCTestDescriptor.m */, - AA37EEF626A1B096007FA6F0 /* FBXCTestReporterConfiguration.h */, - AA37EEF526A1B096007FA6F0 /* FBXCTestReporterConfiguration.m */, - AA37EEF126A1B000007FA6F0 /* FBXCTestRunFileReader.h */, - AA37EEF226A1B000007FA6F0 /* FBXCTestRunFileReader.m */, ); path = Utility; sourceTree = ""; }; - E47FF620763B1FAD507E99B9 /* Pods */ = { + DB440A98287F12D900D01423 /* Mocks */ = { isa = PBXGroup; children = ( - 79B8968AB3BFDB9737B0FF9E /* Pods-idb_companion.debug.xcconfig */, - D5D2CAAA6E490662111C69F6 /* Pods-idb_companion.release.xcconfig */, - 409D3E336E3BC34257F5C8D8 /* Pods-idbGRPC.debug.xcconfig */, - 5821D9A6984DF4BCB878A87A /* Pods-idbGRPC.release.xcconfig */, - 1665EB692F9D40164D398C85 /* Pods-idb_companion-idbGRPC.debug.xcconfig */, - 2F9F718F1D3B7619BFEB9E4E /* Pods-idb_companion-idbGRPC.release.xcconfig */, - ); - path = Pods; + DB440A99287F12E400D01423 /* MockStreamWriter.swift */, + ); + path = Mocks; + sourceTree = ""; + }; + DB465CC7279567AB00FD4583 /* Bridging */ = { + isa = PBXGroup; + children = ( + DB465CCA279567AB00FD4583 /* idb_companion-Bridging-Header.h */, + ); + path = Bridging; + sourceTree = ""; + }; + DB561278287EE0F000D28A07 /* IDBCompanionUtilities */ = { + isa = PBXGroup; + children = ( + DBB72C88283BADA00065DDB3 /* CodeLocation.swift */, + DB6177CD2819540C00C33A0A /* FBTeardownContext.swift */, + DBA2ED1A27BBA96000926054 /* Mutex.swift */, + DBE60F3E282A98180043EB57 /* TaskSelect.swift */, + DBB72C86283BACE10065DDB3 /* TaskTimeout.swift */, + DBA2ED1C27BBA96100926054 /* Atomic.swift */, + DB440A90287F01E700D01423 /* FIFOStreamWriter.swift */, + ); + path = IDBCompanionUtilities; + sourceTree = ""; + }; + DB561293287EE21900D28A07 /* IDBCompanionUtilitiesTests */ = { + isa = PBXGroup; + children = ( + DB440A98287F12D900D01423 /* Mocks */, + DB561294287EE21900D28A07 /* AtomicTests.swift */, + DB440A96287F0A7100D01423 /* FIFOStreamWriterTests.swift */, + ); + path = IDBCompanionUtilitiesTests; + sourceTree = ""; + }; + DB5C38E327B5511F00401F91 /* Interceptors */ = { + isa = PBXGroup; + children = ( + DB5C38E427B5512D00401F91 /* MethodPathSetterInterceptor.swift */, + DB36C9FC28339B9D00105C7D /* LoggingInterceptor.swift */, + DB5C38E627B5514500401F91 /* CompanionServiceInterceptors.swift */, + ); + path = Interceptors; + sourceTree = ""; + }; + DB9722D427CCCCA200E37D78 /* MethodHandlers */ = { + isa = PBXGroup; + children = ( + DBD20680289939F600145AE5 /* RevokeMethodHandler.swift */, + 710FD8172811AFE1000832EA /* AccessibilityInfoMethodHandler.swift */, + DB9722D527CCCCCC00E37D78 /* ConnectMethodHandler.swift */, + DB9722DB27CCCF3A00E37D78 /* XCTestRunMethodHandler.swift */, + 717AFB7228326638009714AB /* XCTestListTestsMethodHandler.swift */, + DB9722D927CCCE4600E37D78 /* InstallMethodHandler.swift */, + DB4585B92808532B004065A2 /* ListAppsMethodHandler.swift */, + 712F098827E8B3FC005EFD42 /* DescribeMethodHandler.swift */, + DBB3278627F5D157001A8E3A /* LaunchMethodHandler.swift */, + DB4585C22808661B004065A2 /* PullMethodHandler.swift */, + DB6BBBA22816ABE2003D3894 /* LsMethodHandler.swift */, + DBCAE6A72816B6AE00C15D07 /* MkdirMethodHandler.swift */, + DB6177B22817EA7200C33A0A /* ListSettingsMethodHandler.swift */, + DB6177B42817EBE500C33A0A /* ScreenshotMethodHandler.swift */, + DB6177B62817ED3400C33A0A /* TerminateMethodHandler.swift */, + DB6177B82817EF0100C33A0A /* ApproveMethodHandler.swift */, + DB6177BA2817FFC300C33A0A /* SettingMethodHandler.swift */, + DB6177BC281808B200C33A0A /* ClearKeychainMethodHandler.swift */, + DB6177BE28182C1B00C33A0A /* LogMethodHandler.swift */, + DB6177C0281837A100C33A0A /* RecordMethodHandler.swift */, + DB6177C828194EDF00C33A0A /* RmMethodHandler.swift */, + DB6177CA2819501E00C33A0A /* MvMethodHandler.swift */, + DB6177D3281A956600C33A0A /* HidMethodHandler.swift */, + DB9B072F281A985700F2C119 /* OpenUrlMethodHandler.swift */, + DBCAE6AA2816C8F700C15D07 /* PushMethodHandler.swift */, + DB6E6C442824152600144D97 /* TailMethodHandler.swift */, + DBF88BBB282900D1003B1494 /* UninstallMethodHandler.swift */, + DBF88BBD2829032A003B1494 /* FocusMethodHandler.swift */, + DBF88BBF2829046A003B1494 /* SimulateMemoryWarningMethodHandler.swift */, + DBF88BC12829057F003B1494 /* SendNotificationMethodHandler.swift */, + DBF88BC32829152A003B1494 /* SetLocationMethodHandler.swift */, + DBF88BCC28294572003B1494 /* CrashListMethodHandler.swift */, + DBF88BD028294A7B003B1494 /* CrashShowMethodHandler.swift */, + DBF88BD228294B5E003B1494 /* CrashDeleteMethodHandler.swift */, + DB4B33C9282D18230080EDEF /* ContactsUpdateMethodHandler.swift */, + DB4B33CB282D1A100080EDEF /* GetSettingMethodHandler.swift */, + DBE60F3C282A95D10043EB57 /* VideoStreamMethodHandler.swift */, + 717AFB7428328C11009714AB /* XCTestListBundlesMethodHandler.swift */, + DBF88BC528291C9A003B1494 /* InstrumentsRunMethodHandler.swift */, + DB36C9F728324A6100105C7D /* XctraceRecordMethodHandler.swift */, + DB29DC79283633D000D267BF /* DapMethodHandler.swift */, + DB15C400283645AF0074D326 /* DebugserverMethodHandler.swift */, + DB15C402283647120074D326 /* AddMediaMethodHandler.swift */, + ); + path = MethodHandlers; + sourceTree = ""; + }; + DBCD82D927D60FF300293F77 /* ValueTransformers */ = { + isa = PBXGroup; + children = ( + DBCD82DA27D60FF300293F77 /* GrpcDataMappings.swift */, + DB4585BC280862F7004065A2 /* FileContainerValueTransformer.swift */, + DBF88BCE282945D4003B1494 /* CrashLogQueryValueTransformer.swift */, + DB36C9F928329B7500105C7D /* CrashLogInfoValueTransformer.swift */, + ); + path = ValueTransformers; + sourceTree = ""; + }; + DBF4764527B69294001E39C2 /* IDBXCTestReporter */ = { + isa = PBXGroup; + children = ( + DBA2ED1727BBA95900926054 /* IDBXCTestReporter.swift */, + ); + path = IDBXCTestReporter; + sourceTree = ""; + }; + DBF5D5D3278EFA7900633753 /* SwiftServer */ = { + isa = PBXGroup; + children = ( + DBCD82D927D60FF300293F77 /* ValueTransformers */, + DB9722D427CCCCA200E37D78 /* MethodHandlers */, + DB5C38E327B5511F00401F91 /* Interceptors */, + DB5C38E127B54FCA00401F91 /* GRPCSwiftServer.swift */, + DB0AEE8927C3822C005048F0 /* GRPCSwiftServerErrorDelegate.swift */, + DBF5D5D5278EFA9C00633753 /* CompanionServiceProvider.swift */, + ); + path = SwiftServer; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ - D7D6DF902265DF2200B01F14 /* Headers */ = { + 7135AF2C2A8C1BBA00D8B882 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( + 7135AF3E2A8C1C2500D8B882 /* FBXCTestRunFileReader.h in Headers */, + 7135AF492A8C1C2500D8B882 /* FBTestApplicationsPair.h in Headers */, + 7135AF3C2A8C1C2500D8B882 /* FBIDBLogger.h in Headers */, + 7135AF692A8CC19600D8B882 /* FBIDBAppHostedTestConfiguration.h in Headers */, + 7135AF3A2A8C1C0300D8B882 /* FBIDBCommandExecutor.h in Headers */, + 7135AF3D2A8C1C2500D8B882 /* FBDataDownloadInput.h in Headers */, + 7135AF472A8C1C2500D8B882 /* FBIDBStorageManager.h in Headers */, + 7135AF482A8C1C2500D8B882 /* FBXCTestReporterConfiguration.h in Headers */, + 7135AF502A8C1C4100D8B882 /* FBCodeCoverageRequest.h in Headers */, + 7135AF512A8C1C4100D8B882 /* FBDsymInstallLinkToBundle.h in Headers */, + 7135AF4F2A8C1C4100D8B882 /* FBXCTestRunRequest.h in Headers */, + 7135AF5C2A8C2C6A00D8B882 /* FBiOSTargetProvider.h in Headers */, + 7135AF532A8C1C5500D8B882 /* FBIDBError.h in Headers */, + 7135AF4B2A8C1C2500D8B882 /* FBIDBTestOperation.h in Headers */, + 7135AF432A8C1C2500D8B882 /* FBXCTestDescriptor.h in Headers */, + 7135AF7F2A8CC5FC00D8B882 /* CompanionLib.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -347,72 +733,127 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - D72CB1C52277837000265160 /* FBDataDownloadInput.h in Headers */, - D7D6E0122265F0DF00B01F14 /* FBIDBCommandExecutor.h in Headers */, - D7D6E00E2265F0DF00B01F14 /* FBIDBCompanionServer.h in Headers */, - 713C70A126F53BC80086D8DF /* FBXCTestRunRequest.h in Headers */, - AA37EEF326A1B000007FA6F0 /* FBXCTestRunFileReader.h in Headers */, AA0DB08223CF0DCB00E8CDEE /* FBIDBXCTestReporter.h in Headers */, - D7D6E00B2265F0DF00B01F14 /* FBIDBConfiguration.h in Headers */, - D7D6E0052265F0DF00B01F14 /* FBIDBError.h in Headers */, - D7D6E0072265F0DF00B01F14 /* FBIDBPortsConfiguration.h in Headers */, - 623D9F0D22E40DCB00D9129C /* FBIDBLogger.h in Headers */, - 713C709426F52F970086D8DF /* FBCodeCoverageRequest.h in Headers */, - D7D6E0142265F0DF00B01F14 /* FBIDBServiceHandler.h in Headers */, - D7D6E0332265F0DF00B01F14 /* FBiOSTargetProvider.h in Headers */, - AA37EEF826A1B096007FA6F0 /* FBXCTestReporterConfiguration.h in Headers */, D7D6E02F2265F0DF00B01F14 /* FBiOSTargetStateChangeNotifier.h in Headers */, AA8F751F249116B700F3BF18 /* FBiOSTargetDescription.h in Headers */, - 713C70AD26F8D0700086D8DF /* FBIDBAppHostedTestConfiguration.h in Headers */, - AA0DB07E23CF0D9800E8CDEE /* FBIDBTestOperation.h in Headers */, - D7D6E02E2265F0DF00B01F14 /* FBTestApplicationsPair.h in Headers */, - AA34E73D228EBF1B0085F93F /* FBIDBStorageManager.h in Headers */, - D7D6E0312265F0DF00B01F14 /* FBXCTestDescriptor.h in Headers */, + DB465CCC279567AB00FD4583 /* idb_companion-Bridging-Header.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DB561272287EE0EF00D28A07 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DBF5D5BF278EF96E00633753 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ + 7135AF302A8C1BBA00D8B882 /* CompanionLib */ = { + isa = PBXNativeTarget; + buildConfigurationList = 7135AF372A8C1BBA00D8B882 /* Build configuration list for PBXNativeTarget "CompanionLib" */; + buildPhases = ( + 7135AF2C2A8C1BBA00D8B882 /* Headers */, + 7135AF2D2A8C1BBA00D8B882 /* Sources */, + 7135AF2E2A8C1BBA00D8B882 /* Frameworks */, + 7135AF2F2A8C1BBA00D8B882 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = CompanionLib; + productName = CompanionLib; + productReference = 7135AF312A8C1BBA00D8B882 /* CompanionLib.framework */; + productType = "com.apple.product-type.framework"; + }; D7D6DF112265DDEC00B01F14 /* idb_companion */ = { isa = PBXNativeTarget; buildConfigurationList = D7D6DF192265DDEC00B01F14 /* Build configuration list for PBXNativeTarget "idb_companion" */; buildPhases = ( - 4AC0E3B025661EF33E389D53 /* [CP] Check Pods Manifest.lock */, D7D6DF0E2265DDEC00B01F14 /* Sources */, D7D6DF9E2265E35300B01F14 /* Headers */, D7D6DF0F2265DDEC00B01F14 /* Frameworks */, D7D6DF102265DDEC00B01F14 /* CopyFiles */, - 273B5E1B76569E02D4F3E178 /* [CP] Copy Pods Resources */, ); buildRules = ( ); dependencies = ( + DBF5D5CE278EF97500633753 /* PBXTargetDependency */, + DB561287287EE18700D28A07 /* PBXTargetDependency */, + 7135AF7C2A8CC51200D8B882 /* PBXTargetDependency */, ); name = idb_companion; productName = idb_companion; productReference = D7D6DF122265DDEC00B01F14 /* idb_companion */; productType = "com.apple.product-type.tool"; }; - D7D6DF932265DF2200B01F14 /* idbGRPC */ = { + DB561276287EE0EF00D28A07 /* IDBCompanionUtilities */ = { isa = PBXNativeTarget; - buildConfigurationList = D7D6DF952265DF2300B01F14 /* Build configuration list for PBXNativeTarget "idbGRPC" */; + buildConfigurationList = DB56127B287EE0F000D28A07 /* Build configuration list for PBXNativeTarget "IDBCompanionUtilities" */; buildPhases = ( - 8D0D65049282F70481EC4EDD /* [CP] Check Pods Manifest.lock */, - D7D6DF912265DF2200B01F14 /* Sources */, - D7D6DF902265DF2200B01F14 /* Headers */, - D7D6DF922265DF2200B01F14 /* Frameworks */, - D7D6DF9B2265DF3900B01F14 /* ShellScript */, + DB561272287EE0EF00D28A07 /* Headers */, + DB561273287EE0EF00D28A07 /* Sources */, + DB561274287EE0EF00D28A07 /* Frameworks */, + DB561275287EE0EF00D28A07 /* Resources */, ); buildRules = ( - D7D6DF9C2265DF4E00B01F14 /* PBXBuildRule */, ); dependencies = ( ); - name = idbGRPC; - productName = idbGRPC; - productReference = D7D6DF942265DF2200B01F14 /* libidbGRPC.a */; - productType = "com.apple.product-type.library.static"; + name = IDBCompanionUtilities; + productName = IDBCompanionUtilities; + productReference = DB561277287EE0EF00D28A07 /* IDBCompanionUtilities.framework */; + productType = "com.apple.product-type.framework"; + }; + DB561291287EE21900D28A07 /* IDBCompanionUtilitiesTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = DB561299287EE21900D28A07 /* Build configuration list for PBXNativeTarget "IDBCompanionUtilitiesTests" */; + buildPhases = ( + DB56128E287EE21900D28A07 /* Sources */, + DB56128F287EE21900D28A07 /* Frameworks */, + DB561290287EE21900D28A07 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + DB561298287EE21900D28A07 /* PBXTargetDependency */, + ); + name = IDBCompanionUtilitiesTests; + productName = IDBCompanionUtilitiesTests; + productReference = DB561292287EE21900D28A07 /* IDBCompanionUtilitiesTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + DBF5D5C3278EF96E00633753 /* IDBGRPCSwift */ = { + isa = PBXNativeTarget; + buildConfigurationList = DBF5D5C8278EF96E00633753 /* Build configuration list for PBXNativeTarget "IDBGRPCSwift" */; + buildPhases = ( + DBF5D5D1278EF9BD00633753 /* Build protoc plugin */, + DBF5D5BF278EF96E00633753 /* Headers */, + DBF5D5C0278EF96E00633753 /* Sources */, + DBF5D5C1278EF96E00633753 /* Frameworks */, + DBF5D5C2278EF96E00633753 /* Resources */, + ); + buildRules = ( + DBF5D5D2278EF9F000633753 /* PBXBuildRule */, + ); + dependencies = ( + ); + name = IDBGRPCSwift; + packageProductDependencies = ( + DB67676527EB2BAD002BBE32 /* GRPC */, + ); + productName = idbGRPCSwift; + productReference = DBF5D5C4278EF96E00633753 /* IDBGRPCSwift.framework */; + productType = "com.apple.product-type.framework"; }; /* End PBXNativeTarget section */ @@ -420,14 +861,26 @@ D7D6DF0A2265DDEC00B01F14 /* Project object */ = { isa = PBXProject; attributes = { + LastSwiftUpdateCheck = 1340; LastUpgradeCheck = 1020; ORGANIZATIONNAME = Facebook; TargetAttributes = { + 7135AF302A8C1BBA00D8B882 = { + CreatedOnToolsVersion = 14.3; + LastSwiftMigration = 1430; + }; D7D6DF112265DDEC00B01F14 = { CreatedOnToolsVersion = 10.2; + LastSwiftMigration = 1320; }; - D7D6DF932265DF2200B01F14 = { - CreatedOnToolsVersion = 10.2; + DB561276287EE0EF00D28A07 = { + CreatedOnToolsVersion = 13.4; + }; + DB561291287EE21900D28A07 = { + CreatedOnToolsVersion = 13.4; + }; + DBF5D5C3278EF96E00633753 = { + CreatedOnToolsVersion = 13.2; }; }; }; @@ -440,79 +893,55 @@ Base, ); mainGroup = D7D6DF092265DDEC00B01F14; + packageReferences = ( + DB67676427EB2BAD002BBE32 /* XCRemoteSwiftPackageReference "grpc-swift" */, + ); productRefGroup = D7D6DF132265DDEC00B01F14 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( D7D6DF112265DDEC00B01F14 /* idb_companion */, - D7D6DF932265DF2200B01F14 /* idbGRPC */, + DBF5D5C3278EF96E00633753 /* IDBGRPCSwift */, + DB561276287EE0EF00D28A07 /* IDBCompanionUtilities */, + DB561291287EE21900D28A07 /* IDBCompanionUtilitiesTests */, + 7135AF302A8C1BBA00D8B882 /* CompanionLib */, ); }; /* End PBXProject section */ -/* Begin PBXShellScriptBuildPhase section */ - 273B5E1B76569E02D4F3E178 /* [CP] Copy Pods Resources */ = { - isa = PBXShellScriptBuildPhase; +/* Begin PBXResourcesBuildPhase section */ + 7135AF2F2A8C1BBA00D8B882 /* Resources */ = { + isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-idb_companion/Pods-idb_companion-resources-${CONFIGURATION}-input-files.xcfilelist", - ); - name = "[CP] Copy Pods Resources"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-idb_companion/Pods-idb_companion-resources-${CONFIGURATION}-output-files.xcfilelist", - ); runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-idb_companion/Pods-idb_companion-resources.sh\"\n"; - showEnvVarsInLog = 0; }; - 4AC0E3B025661EF33E389D53 /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; + DB561275287EE0EF00D28A07 /* Resources */ = { + isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-idb_companion-checkManifestLockResult.txt", - ); runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; }; - 8D0D65049282F70481EC4EDD /* [CP] Check Pods Manifest.lock */ = { - isa = PBXShellScriptBuildPhase; + DB561290287EE21900D28A07 /* Resources */ = { + isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); - inputFileListPaths = ( - ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; - outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-idbGRPC-checkManifestLockResult.txt", + runOnlyForDeploymentPostprocessing = 0; + }; + DBF5D5C2278EF96E00633753 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( ); runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; - showEnvVarsInLog = 0; }; - D7D6DF9B2265DF3900B01F14 /* ShellScript */ = { +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + DBF5D5D1278EF9BD00633753 /* Build protoc plugin */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -521,47 +950,144 @@ ); inputPaths = ( ); + name = "Build protoc plugin"; outputFileListPaths = ( ); outputPaths = ( + "$(BUILD_DIR)/../../SourcePackages/checkouts/grpc-swift/.build/release/protoc-gen-grpc-swift", + "$(BUILD_DIR)/../../SourcePackages/checkouts/grpc-swift/.build/release/protoc-gen-swift", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "# Type a script or drag a script file from your workspace to insert its path.\n"; + shellScript = "cd ${BUILD_DIR}\npwd\ncd ${BUILD_DIR%Build/*}SourcePackages/checkouts/grpc-swift\nmake plugins\npwd\n"; }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ + 7135AF2D2A8C1BBA00D8B882 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 7135AF3B2A8C1C0B00D8B882 /* FBIDBCommandExecutor.m in Sources */, + 7135AF402A8C1C2500D8B882 /* FBIDBStorageManager.m in Sources */, + 7135AF4D2A8C1C4100D8B882 /* FBXCTestRunRequest.m in Sources */, + 7135AF6A2A8CC19900D8B882 /* FBIDBAppHostedTestConfiguration.m in Sources */, + 7135AF412A8C1C2500D8B882 /* FBDataDownloadInput.m in Sources */, + 7185380C2B22884200D2C033 /* BridgeFuture.swift in Sources */, + 7135AF442A8C1C2500D8B882 /* FBXCTestDescriptor.m in Sources */, + 7135AF3F2A8C1C2500D8B882 /* FBXCTestRunFileReader.m in Sources */, + 7135AF4E2A8C1C4100D8B882 /* FBCodeCoverageRequest.m in Sources */, + 7135AF522A8C1C5100D8B882 /* FBIDBError.m in Sources */, + 7185380D2B22884200D2C033 /* BridgeQueues.swift in Sources */, + 7135AF422A8C1C2500D8B882 /* FBIDBTestOperation.m in Sources */, + 7135AF4A2A8C1C2500D8B882 /* FBTestApplicationsPair.m in Sources */, + 7135AF452A8C1C2500D8B882 /* FBXCTestReporterConfiguration.m in Sources */, + 7135AF462A8C1C2500D8B882 /* FBIDBLogger.m in Sources */, + 7135AF4C2A8C1C4100D8B882 /* FBDsymInstallLinkToBundle.m in Sources */, + 7135AF5D2A8C2C6A00D8B882 /* FBiOSTargetProvider.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; D7D6DF0E2265DDEC00B01F14 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - D7107CF822E708C00007FF32 /* FBIDBCompanionServer.mm in Sources */, - AA0DB07D23CF0D9800E8CDEE /* FBIDBTestOperation.m in Sources */, + DB5C38E227B54FCA00401F91 /* GRPCSwiftServer.swift in Sources */, + DBF88BC22829057F003B1494 /* SendNotificationMethodHandler.swift in Sources */, + DBF88BBE2829032A003B1494 /* FocusMethodHandler.swift in Sources */, + DB4585C32808661B004065A2 /* PullMethodHandler.swift in Sources */, + DBCAE6B22816E72E00C15D07 /* MultisourceFileReader.swift in Sources */, + DB4585BF280863FE004065A2 /* FileDrainWriter.swift in Sources */, + DBF88BBC282900D1003B1494 /* UninstallMethodHandler.swift in Sources */, AA8F7520249116B700F3BF18 /* FBiOSTargetDescription.m in Sources */, - D7D6E00F2265F0DF00B01F14 /* FBIDBCommandExecutor.m in Sources */, - AA34E73C228EBF1B0085F93F /* FBIDBStorageManager.m in Sources */, - AA37EEF426A1B000007FA6F0 /* FBXCTestRunFileReader.m in Sources */, - AA37EEF726A1B096007FA6F0 /* FBXCTestReporterConfiguration.m in Sources */, - D72CB1C62277837000265160 /* FBDataDownloadInput.m in Sources */, - 713C709526F52F970086D8DF /* FBCodeCoverageRequest.m in Sources */, - 713C70AE26F8D0700086D8DF /* FBIDBAppHostedTestConfiguration.m in Sources */, - D7D6E0082265F0DF00B01F14 /* FBIDBConfiguration.m in Sources */, - D7D6E0062265F0DF00B01F14 /* FBIDBError.m in Sources */, - D7D6E00C2265F0DF00B01F14 /* FBIDBPortsConfiguration.m in Sources */, - D7D6E00D2265F0DF00B01F14 /* FBIDBServiceHandler.mm in Sources */, - D7D6E02C2265F0DF00B01F14 /* FBiOSTargetProvider.m in Sources */, + DB15C403283647120074D326 /* AddMediaMethodHandler.swift in Sources */, + 717AFB7528328C11009714AB /* XCTestListBundlesMethodHandler.swift in Sources */, + DB6E6C452824152600144D97 /* TailMethodHandler.swift in Sources */, + DB6177CB2819501E00C33A0A /* MvMethodHandler.swift in Sources */, + DBA31DD127BE72EF0032091C /* AsyncSequence+Extension.swift in Sources */, + DBD20681289939F600145AE5 /* RevokeMethodHandler.swift in Sources */, + 710FD8182811AFE1000832EA /* AccessibilityInfoMethodHandler.swift in Sources */, + DBF88BC42829152A003B1494 /* SetLocationMethodHandler.swift in Sources */, + DBCAE6A82816B6AE00C15D07 /* MkdirMethodHandler.swift in Sources */, + DBA2ED1827BBA95900926054 /* IDBXCTestReporter.swift in Sources */, + DBB3278727F5D157001A8E3A /* LaunchMethodHandler.swift in Sources */, + DB4B33CC282D1A100080EDEF /* GetSettingMethodHandler.swift in Sources */, + DB6177BB2817FFC300C33A0A /* SettingMethodHandler.swift in Sources */, + DB6177B72817ED3400C33A0A /* TerminateMethodHandler.swift in Sources */, + DB9B0730281A985700F2C119 /* OpenUrlMethodHandler.swift in Sources */, + DBF88BCD28294572003B1494 /* CrashListMethodHandler.swift in Sources */, + DB9722DA27CCCE4600E37D78 /* InstallMethodHandler.swift in Sources */, + DB36C9F828324A6100105C7D /* XctraceRecordMethodHandler.swift in Sources */, + DB6177B52817EBE500C33A0A /* ScreenshotMethodHandler.swift in Sources */, + DB5C38E527B5512D00401F91 /* MethodPathSetterInterceptor.swift in Sources */, + DB440A9C2880152C00D01423 /* GRPCAsyncResponseStreamWriter+AsyncStreamWriter.swift in Sources */, + DBA2ED1D27BBA96100926054 /* FBControlCoreError+Extension.swift in Sources */, + DB36C9FA28329B7500105C7D /* CrashLogInfoValueTransformer.swift in Sources */, + DBF88BD328294B5E003B1494 /* CrashDeleteMethodHandler.swift in Sources */, + DB15C401283645AF0074D326 /* DebugserverMethodHandler.swift in Sources */, + 7135AF592A8C2A1100D8B882 /* EmptyEventReporter.swift in Sources */, + DBF88BD128294A7B003B1494 /* CrashShowMethodHandler.swift in Sources */, + DBCD82DB27D60FF300293F77 /* GrpcDataMappings.swift in Sources */, + DB6177D4281A956600C33A0A /* HidMethodHandler.swift in Sources */, + DB5C38E727B5514500401F91 /* CompanionServiceInterceptors.swift in Sources */, + DB7BCC1A28212A80001C1C8D /* IDBPortsConfiguration.swift in Sources */, + DB9722DC27CCCF3A00E37D78 /* XCTestRunMethodHandler.swift in Sources */, + DB6177B32817EA7200C33A0A /* ListSettingsMethodHandler.swift in Sources */, + DBE60F3D282A95D10043EB57 /* VideoStreamMethodHandler.swift in Sources */, + DB6177C928194EDF00C33A0A /* RmMethodHandler.swift in Sources */, + DB6177B92817EF0100C33A0A /* ApproveMethodHandler.swift in Sources */, + DBF88BC628291C9A003B1494 /* InstrumentsRunMethodHandler.swift in Sources */, + DB1FCCFA284F6C8B00EAFB20 /* TaskFBFuture.swift in Sources */, + DB4585BA2808532D004065A2 /* ListAppsMethodHandler.swift in Sources */, + DBF88BCF282945D4003B1494 /* CrashLogQueryValueTransformer.swift in Sources */, + DB4585BD280862F7004065A2 /* FileContainerValueTransformer.swift in Sources */, + DB6177C1281837A100C33A0A /* RecordMethodHandler.swift in Sources */, D7D6E0362265F0DF00B01F14 /* FBiOSTargetStateChangeNotifier.m in Sources */, - D7D6E0352265F0DF00B01F14 /* FBTestApplicationsPair.m in Sources */, - D7D6E02A2265F0DF00B01F14 /* FBXCTestDescriptor.m in Sources */, + DB6177BD281808B200C33A0A /* ClearKeychainMethodHandler.swift in Sources */, + 7135AF6B2A8CC25500D8B882 /* IDBConfiguration.swift in Sources */, + DB36C9FD28339B9D00105C7D /* LoggingInterceptor.swift in Sources */, + DBF5D5D6278EFA9C00633753 /* CompanionServiceProvider.swift in Sources */, + DB1FCCFC284F6ECA00EAFB20 /* IDBKillswitchBridge.swift in Sources */, + DB4B33CA282D18230080EDEF /* ContactsUpdateMethodHandler.swift in Sources */, + DBCAE6AB2816C8F700C15D07 /* PushMethodHandler.swift in Sources */, + DB29DC7A283633D000D267BF /* DapMethodHandler.swift in Sources */, + 712F098927E8B3FC005EFD42 /* DescribeMethodHandler.swift in Sources */, + DB6BBBA32816ABE2003D3894 /* LsMethodHandler.swift in Sources */, + 717AFB7328326638009714AB /* XCTestListTestsMethodHandler.swift in Sources */, + DB0AEE8A27C3822C005048F0 /* GRPCSwiftServerErrorDelegate.swift in Sources */, D7D6E0282265F0DF00B01F14 /* main.m in Sources */, - 623D9F0E22E40DCB00D9129C /* FBIDBLogger.m in Sources */, - AA0DB08123CF0DCB00E8CDEE /* FBIDBXCTestReporter.mm in Sources */, - 713C70A226F53BC80086D8DF /* FBXCTestRunRequest.m in Sources */, + DBF88BC02829046A003B1494 /* SimulateMemoryWarningMethodHandler.swift in Sources */, + DB6177BF28182C1B00C33A0A /* LogMethodHandler.swift in Sources */, + DB9722D627CCCCCC00E37D78 /* ConnectMethodHandler.swift in Sources */, + DB67DD31283D16EF003EF139 /* IDBKillswitch.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DB561273287EE0EF00D28A07 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DB56128D287EE1CE00D28A07 /* CodeLocation.swift in Sources */, + DB56128C287EE1C900D28A07 /* FBTeardownContext.swift in Sources */, + DB561283287EE17600D28A07 /* Atomic.swift in Sources */, + DB561289287EE1A800D28A07 /* TaskTimeout.swift in Sources */, + DB440A92287F01E700D01423 /* FIFOStreamWriter.swift in Sources */, + DB56128A287EE1AD00D28A07 /* TaskSelect.swift in Sources */, + DB56128B287EE1BE00D28A07 /* Mutex.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + DB56128E287EE21900D28A07 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + DB440A9A287F12E400D01423 /* MockStreamWriter.swift in Sources */, + DB440A97287F0A7100D01423 /* FIFOStreamWriterTests.swift in Sources */, + DB561295287EE21900D28A07 /* AtomicTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - D7D6DF912265DF2200B01F14 /* Sources */ = { + DBF5D5C0278EF96E00633753 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( @@ -571,7 +1097,103 @@ }; /* End PBXSourcesBuildPhase section */ +/* Begin PBXTargetDependency section */ + 7135AF7C2A8CC51200D8B882 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 7135AF302A8C1BBA00D8B882 /* CompanionLib */; + targetProxy = 7135AF7B2A8CC51200D8B882 /* PBXContainerItemProxy */; + }; + DB561287287EE18700D28A07 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DB561276287EE0EF00D28A07 /* IDBCompanionUtilities */; + targetProxy = DB561286287EE18700D28A07 /* PBXContainerItemProxy */; + }; + DB561298287EE21900D28A07 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DB561276287EE0EF00D28A07 /* IDBCompanionUtilities */; + targetProxy = DB561297287EE21900D28A07 /* PBXContainerItemProxy */; + }; + DBF5D5CE278EF97500633753 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = DBF5D5C3278EF96E00633753 /* IDBGRPCSwift */; + targetProxy = DBF5D5CD278EF97500633753 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + /* Begin XCBuildConfiguration section */ + 7135AF382A8C1BBA00D8B882 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2023 Facebook. All rights reserved."; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 11.0; + MARKETING_VERSION = 1.0; + MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu11 gnu++20"; + PRODUCT_BUNDLE_IDENTIFIER = com.facebook.CompanionLib; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SKIP_INSTALL = YES; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 7135AF392A8C1BBA00D8B882 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_MODULE_VERIFIER = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2023 Facebook. All rights reserved."; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 11.0; + MARKETING_VERSION = 1.0; + MODULE_VERIFIER_SUPPORTED_LANGUAGES = "objective-c objective-c++"; + MODULE_VERIFIER_SUPPORTED_LANGUAGE_STANDARDS = "gnu11 gnu++20"; + PRODUCT_BUNDLE_IDENTIFIER = com.facebook.CompanionLib; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SKIP_INSTALL = YES; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; D7D6DF172265DDEC00B01F14 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -623,11 +1245,12 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.14; + MACOSX_DEPLOYMENT_TARGET = 11.0; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; + SWIFT_OBJC_INTERFACE_HEADER_NAME = "idb-Swift.h"; }; name = Debug; }; @@ -676,17 +1299,18 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.14; + MACOSX_DEPLOYMENT_TARGET = 11.0; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; SDKROOT = macosx; + SWIFT_OBJC_INTERFACE_HEADER_NAME = "idb-Swift.h"; }; name = Release; }; D7D6DF1A2265DDEC00B01F14 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 79B8968AB3BFDB9737B0FF9E /* Pods-idb_companion.debug.xcconfig */; buildSettings = { + CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Manual; DEVELOPMENT_TEAM = ""; HEADER_SEARCH_PATHS = ( @@ -695,15 +1319,20 @@ ); INFOPLIST_FILE = "$(SRCROOT)/idb_companion/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "@executable_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 11.0; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OBJC_BRIDGING_HEADER = "idb_companion/Bridging/idb_companion-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_STRICT_CONCURRENCY = complete; + SWIFT_VERSION = 5.0; }; name = Debug; }; D7D6DF1B2265DDEC00B01F14 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = D5D2CAAA6E490662111C69F6 /* Pods-idb_companion.release.xcconfig */; buildSettings = { + CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Manual; DEVELOPMENT_TEAM = ""; HEADER_SEARCH_PATHS = ( @@ -712,36 +1341,201 @@ ); INFOPLIST_FILE = "$(SRCROOT)/idb_companion/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "@executable_path/../Frameworks"; + MACOSX_DEPLOYMENT_TARGET = 11.0; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OBJC_BRIDGING_HEADER = "idb_companion/Bridging/idb_companion-Bridging-Header.h"; + SWIFT_STRICT_CONCURRENCY = complete; + SWIFT_VERSION = 5.0; }; name = Release; }; - D7D6DF962265DF2300B01F14 /* Debug */ = { + DB56127C287EE0F000D28A07 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 409D3E336E3BC34257F5C8D8 /* Pods-idbGRPC.debug.xcconfig */; buildSettings = { - CODE_SIGN_STYLE = Manual; - EXECUTABLE_PREFIX = lib; - PRODUCT_NAME = "$(TARGET_NAME)"; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2022 Facebook. All rights reserved."; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 11.0; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = local.IDBCompanionUtilities; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; }; name = Debug; }; - D7D6DF972265DF2300B01F14 /* Release */ = { + DB56127D287EE0F000D28A07 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 5821D9A6984DF4BCB878A87A /* Pods-idbGRPC.release.xcconfig */; buildSettings = { - CODE_SIGN_STYLE = Manual; - EXECUTABLE_PREFIX = lib; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2022 Facebook. All rights reserved."; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 11.0; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = local.IDBCompanionUtilities; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SKIP_INSTALL = YES; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + DB56129A287EE21900D28A07 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MACOSX_DEPLOYMENT_TARGET = 12.3; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = local.IDBCompanionUtilitiesTests; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + DB56129B287EE21900D28A07 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MACOSX_DEPLOYMENT_TARGET = 12.3; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = local.IDBCompanionUtilitiesTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; + DBF5D5C9278EF96E00633753 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2022 Facebook. All rights reserved."; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 11.0; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = local.IDBGRPCSwift; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + DBF5D5CA278EF96E00633753 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2022 Facebook. All rights reserved."; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/Frameworks", + ); + MACOSX_DEPLOYMENT_TARGET = 11.0; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = local.IDBGRPCSwift; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; + SKIP_INSTALL = YES; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ + 7135AF372A8C1BBA00D8B882 /* Build configuration list for PBXNativeTarget "CompanionLib" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7135AF382A8C1BBA00D8B882 /* Debug */, + 7135AF392A8C1BBA00D8B882 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; D7D6DF0D2265DDEC00B01F14 /* Build configuration list for PBXProject "idb_companion" */ = { isa = XCConfigurationList; buildConfigurations = ( @@ -760,16 +1554,53 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - D7D6DF952265DF2300B01F14 /* Build configuration list for PBXNativeTarget "idbGRPC" */ = { + DB56127B287EE0F000D28A07 /* Build configuration list for PBXNativeTarget "IDBCompanionUtilities" */ = { isa = XCConfigurationList; buildConfigurations = ( - D7D6DF962265DF2300B01F14 /* Debug */, - D7D6DF972265DF2300B01F14 /* Release */, + DB56127C287EE0F000D28A07 /* Debug */, + DB56127D287EE0F000D28A07 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DB561299287EE21900D28A07 /* Build configuration list for PBXNativeTarget "IDBCompanionUtilitiesTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DB56129A287EE21900D28A07 /* Debug */, + DB56129B287EE21900D28A07 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + DBF5D5C8278EF96E00633753 /* Build configuration list for PBXNativeTarget "IDBGRPCSwift" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + DBF5D5C9278EF96E00633753 /* Debug */, + DBF5D5CA278EF96E00633753 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ + +/* Begin XCRemoteSwiftPackageReference section */ + DB67676427EB2BAD002BBE32 /* XCRemoteSwiftPackageReference "grpc-swift" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/grpc/grpc-swift.git"; + requirement = { + kind = exactVersion; + version = 1.10.0; + }; + }; +/* End XCRemoteSwiftPackageReference section */ + +/* Begin XCSwiftPackageProductDependency section */ + DB67676527EB2BAD002BBE32 /* GRPC */ = { + isa = XCSwiftPackageProductDependency; + package = DB67676427EB2BAD002BBE32 /* XCRemoteSwiftPackageReference "grpc-swift" */; + productName = GRPC; + }; +/* End XCSwiftPackageProductDependency section */ }; rootObject = D7D6DF0A2265DDEC00B01F14 /* Project object */; } diff --git a/idb_companion.xcworkspace/contents.xcworkspacedata b/idb_companion.xcworkspace/contents.xcworkspacedata index ee35bbba9..b462d7c43 100644 --- a/idb_companion.xcworkspace/contents.xcworkspacedata +++ b/idb_companion.xcworkspace/contents.xcworkspacedata @@ -7,7 +7,4 @@ - - diff --git a/idb_companion/Bridging/idb_companion-Bridging-Header.h b/idb_companion/Bridging/idb_companion-Bridging-Header.h new file mode 100644 index 000000000..22a776156 --- /dev/null +++ b/idb_companion/Bridging/idb_companion-Bridging-Header.h @@ -0,0 +1,6 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ diff --git a/idb_companion/Configuration/DefaultConfiguration.swift b/idb_companion/Configuration/DefaultConfiguration.swift new file mode 100644 index 000000000..e5f582da8 --- /dev/null +++ b/idb_companion/Configuration/DefaultConfiguration.swift @@ -0,0 +1,17 @@ +// (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary. + +import Foundation + +public enum DefaultConfiguration { + + public static let cacheInvalidationInterval: TimeInterval = 120 // 2 mins + + public static let baseURL = "https://interngraph.intern.facebook.com/" + + public static let urlSessionConfiguration: URLSessionConfiguration = { + let configuration = URLSessionConfiguration.default + let fifteenSeconds: TimeInterval = 15 + configuration.timeoutIntervalForRequest = fifteenSeconds + return configuration + }() +} diff --git a/idb_companion/Configuration/EmptyEventReporter.swift b/idb_companion/Configuration/EmptyEventReporter.swift new file mode 100644 index 000000000..4d461dac7 --- /dev/null +++ b/idb_companion/Configuration/EmptyEventReporter.swift @@ -0,0 +1,20 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import FBSimulatorControl +import Foundation + +/// Mock class for OSS implementation. It is easier to have mock than to use optional everywhere. +@objc final class EmptyEventReporter: NSObject, FBEventReporter { + + @objc static let shared = EmptyEventReporter() + + var metadata: [String: String] = [:] + + func report(_ subject: FBEventReporterSubject) {} + func addMetadata(_ metadata: [String: String]) {} +} diff --git a/idb_companion/Configuration/FBIDBConfiguration.h b/idb_companion/Configuration/FBIDBConfiguration.h deleted file mode 100644 index b22e70c4f..000000000 --- a/idb_companion/Configuration/FBIDBConfiguration.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#import - -NS_ASSUME_NONNULL_BEGIN - -@protocol FBEventReporter; - -/** - Configuration object for idb. - */ -@interface FBIDBConfiguration : NSObject - -/** - The event reporter to use. - */ -@property (nonatomic, strong, readwrite, class) id eventReporter; - -@end - -NS_ASSUME_NONNULL_END diff --git a/idb_companion/Configuration/FBIDBConfiguration.m b/idb_companion/Configuration/FBIDBConfiguration.m deleted file mode 100644 index fd86d9f66..000000000 --- a/idb_companion/Configuration/FBIDBConfiguration.m +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#import "FBIDBConfiguration.h" - -@implementation FBIDBConfiguration - -static id reporter = nil; - -+ (id)eventReporter -{ - return reporter; -} - -+ (void)setEventReporter:(id)eventReporter -{ - reporter = eventReporter; -} - -@end diff --git a/idb_companion/Configuration/FBIDBPortsConfiguration.h b/idb_companion/Configuration/FBIDBPortsConfiguration.h deleted file mode 100644 index 5b30a6735..000000000 --- a/idb_companion/Configuration/FBIDBPortsConfiguration.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#import - -NS_ASSUME_NONNULL_BEGIN - -/** - A wrapper for TCP Ports - */ -@interface FBIDBPortsConfiguration : NSObject - -#pragma mark Initializers - -/** - Construct a ports object. - - @param userDefaults the user defaults - @return a new ports object - */ -+ (instancetype)portsWithArguments:(NSUserDefaults *)userDefaults; - -/** - The GRPC Unix Domain Socket Path. nil if not set. - */ -@property (nonatomic, nullable, copy, readonly) NSString *grpcDomainSocket; - -/** - The GRPC TCP Port. - */ -@property (nonatomic, assign, readonly) in_port_t grpcPort; - -/** - The debugserver port - */ -@property (nonatomic, assign, readonly) in_port_t debugserverPort; - -/** - The TLS server cert path. If not specified grpcPort will be listening on unencrypted socket - */ -@property (nonatomic, assign, readonly) NSString *tlsCertPath; - -@end - -NS_ASSUME_NONNULL_END diff --git a/idb_companion/Configuration/FBIDBPortsConfiguration.m b/idb_companion/Configuration/FBIDBPortsConfiguration.m deleted file mode 100644 index 39db4d011..000000000 --- a/idb_companion/Configuration/FBIDBPortsConfiguration.m +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#import "FBIDBPortsConfiguration.h" - -static NSString *const GrpcPortKey = @"-grpc-port"; - -@implementation FBIDBPortsConfiguration - -#pragma mark Initializers - -+ (instancetype)portsWithArguments:(NSUserDefaults *)userDefaults -{ - return [[self alloc] initWithUserDefaults:userDefaults]; -} - -- (instancetype)initWithUserDefaults:(NSUserDefaults *)userDefaults -{ - self = [super init]; - if (!self) { - return nil; - } - - _debugserverPort = [userDefaults integerForKey:@"-debug-port"] ?: 10881; - _grpcPort = [userDefaults stringForKey:GrpcPortKey] ? [userDefaults integerForKey:GrpcPortKey] : 10882; - _grpcDomainSocket = [userDefaults stringForKey:@"-grpc-domain-sock"]; - _tlsCertPath = [userDefaults stringForKey:@"-tls-cert-path"]; - - return self; -} - -@end diff --git a/idb_companion/Configuration/FBInternGraphError.swift b/idb_companion/Configuration/FBInternGraphError.swift new file mode 100644 index 000000000..71547c29e --- /dev/null +++ b/idb_companion/Configuration/FBInternGraphError.swift @@ -0,0 +1,37 @@ +// (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary. + +import Foundation + +/// Possible errors of incorrect library implementation or usage. This should be explicitly handled by client and fixed. +public enum FBInternGraphError: Error, LocalizedError { + case failToFormURLRequest + case inconsistentSitevarTypes + + public var errorDescription: String? { + switch self { + case .failToFormURLRequest: + return "\(FBInternGraphError.self): failed to form URL request. Most likely you provide incorrect baseURL" + case .inconsistentSitevarTypes: + return "\(FBInternGraphError.self): received request, found cached response, but types mismatched. Usage of different types for same entity name is not supported" + } + } +} + +/// Internal library error that should not be propagated to user directly. +/// The cause is unobvious so we will just user `defaultValue` of request. Most likely some configuration or netwokring problems +enum FBInternGraphInternalError: Error, CustomStringConvertible { + case sitevarNotFoundInResult + case notReceiveErrorOrData + case inacceptableStatusCode(String) + + var description: String { + switch self { + case .notReceiveErrorOrData: + return "\(FBInternGraphInternalError.self): not received error or data from request. This is internal library error that should never happen" + case .sitevarNotFoundInResult: + return "\(FBInternGraphInternalError.self): sitevar not found in result. Most likely you provide incorrect input parameters" + case .inacceptableStatusCode(let output): + return "\(FBInternGraphInternalError.self): received inacceptable status code from server. Most likely appID or token is incorrect. Output: \(output)" + } + } +} diff --git a/idb_companion/Configuration/GatekeeperReader.swift b/idb_companion/Configuration/GatekeeperReader.swift new file mode 100644 index 000000000..57edadde3 --- /dev/null +++ b/idb_companion/Configuration/GatekeeperReader.swift @@ -0,0 +1,49 @@ +// (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary. + +import Foundation + +/// Reads gatekeeper value from interngraph via http request. +/// Batch gatekeeper request is not implemented. +/// To use that reader you should create and FB application using https://www.internalfb.com/intern/wiki/XcontrollerGuide/XInternGraphController/#creating-an-app-id-and-t +@available(macOSApplicationExtension 10.15, *) +public final class GatekeeperReader { + + private let reader: InternGraphCachableReader + private let decoder: JSONDecoder + + /// Provide appID and token from FB application. To obtain follow [this insctructions](https://www.internalfb.com/intern/wiki/XcontrollerGuide/XInternGraphController/#creating-an-app-id-and-t) + /// - Parameters: + /// - appID: FB application identifier + /// - token: Generated token + /// - cacheInvalidationInterval: Sets cache lifetime + /// - sessionConfiguration: Controls setup for network calls. Default one sets request timeout to 15 seconds + public init(appID: String, token: String, + baseURL: String = DefaultConfiguration.baseURL, + cacheInvalidationInterval: TimeInterval = DefaultConfiguration.cacheInvalidationInterval, + sessionConfiguration: URLSessionConfiguration = DefaultConfiguration.urlSessionConfiguration) { + + let session = URLSession(configuration: sessionConfiguration) + self.reader = .init(cacheInvalidationInterval: cacheInvalidationInterval, + internGraphRequestor: FBApplicationBasedGatekeeperRequestor(appID: appID, token: token, baseURL: baseURL, urlSession: session)) + self.decoder = JSONDecoder() + } + + /// Reads and caches gatekeeper value. + /// + /// - Parameters: + /// - sitevarName: Your fancy name of the gatekeeper + /// - default: value to use on network error + /// - Returns: Sitevar value + /// - Throws: FBInternGraphError on incorrect library usage or implementation. Network/server errors do *not* throw an error but uses `defaultValue` + public func read(name: String, unixname: String, `default` defaultValue: Bool) async throws -> Bool { + do { + let request = GatekeeperRequest(unixname: unixname, gatekeeperName: name) + return try await reader.readWithCache(request: request, decoder: decoder, defaultValue: defaultValue) + } catch is DecodingError { + assertionFailure("We should not receive DecodingError in that reader, because it is library-internal and not configured by user. Check server implemenation. Most likely simething changed") + return defaultValue + } catch { + throw error + } + } +} diff --git a/idb_companion/Configuration/IDBConfiguration.swift b/idb_companion/Configuration/IDBConfiguration.swift new file mode 100644 index 000000000..2f509f2f7 --- /dev/null +++ b/idb_companion/Configuration/IDBConfiguration.swift @@ -0,0 +1,21 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import FBControlCore +import Foundation + +class IDBConfiguration: NSObject { + + @objc static var eventReporter: FBEventReporter = EmptyEventReporter.shared + @objc static var swiftEventReporter: FBEventReporter = EmptyEventReporter.shared + + static var idbKillswitch: IDBKillswitch = EmptyIDBKillswitch() + + @objc static func getIDBKillswitch() -> IDBKillswitchBridge { + return idbKillswitch.objcBridged + } +} diff --git a/idb_companion/Configuration/IDBKillswitch.swift b/idb_companion/Configuration/IDBKillswitch.swift new file mode 100644 index 000000000..f82762517 --- /dev/null +++ b/idb_companion/Configuration/IDBKillswitch.swift @@ -0,0 +1,26 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import Foundation + +enum IDBFeature { + case grpcEndpoint +} + +protocol IDBKillswitch { + func disabled(_ killswitch: IDBFeature) async -> Bool +} + +extension IDBKillswitch { + var objcBridged: IDBKillswitchBridge { + .init(idbKillswitch: self) + } +} + +final class EmptyIDBKillswitch: IDBKillswitch { + func disabled(_ killswitch: IDBFeature) async -> Bool { true } +} diff --git a/idb_companion/Configuration/IDBKillswitchBridge.swift b/idb_companion/Configuration/IDBKillswitchBridge.swift new file mode 100644 index 000000000..bf4e373d5 --- /dev/null +++ b/idb_companion/Configuration/IDBKillswitchBridge.swift @@ -0,0 +1,37 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import FBSimulatorControl +import Foundation + +/// Bridge for killswitch from objc world. Should be subset of `IDBFeature`. Use from objc +@objc(FBIDBFeatureKey) enum IDBFeatureBridge: Int { + case grpcEndpoint + + fileprivate var nativeValue: IDBFeature { + switch self { + case .grpcEndpoint: + return .grpcEndpoint + } + } +} + +@objc(FBIDBKillswitch) class IDBKillswitchBridge: NSObject { + + private let idbKillswitch: IDBKillswitch + + init(idbKillswitch: IDBKillswitch) { + self.idbKillswitch = idbKillswitch + } + + /// - Returns: NSNumber initialized with boolean value + @objc func disabledWith(_ feature: IDBFeatureBridge) -> FBFuture { + return Task.fbFuture { + await NSNumber(value: self.idbKillswitch.disabled(feature.nativeValue)) + } + } +} diff --git a/idb_companion/Configuration/IDBPortsConfiguration.swift b/idb_companion/Configuration/IDBPortsConfiguration.swift new file mode 100644 index 000000000..9f13c0fbb --- /dev/null +++ b/idb_companion/Configuration/IDBPortsConfiguration.swift @@ -0,0 +1,106 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import Foundation +import GRPC +import NIO + +enum GRPCConnectionTarget: CustomStringConvertible { + enum ExtractionError: Error { + case socketAddressIsEmpty + case failedToExtractAssociatedInfo + } + + case tcpPort(port: Int) + case unixDomainSocket(String) + + var grpcConnection: ConnectionTarget { + switch self { + case let .tcpPort(port): + return .hostAndPort("::", port) + + case let .unixDomainSocket(path): + return .unixDomainSocket(path) + } + } + + func outputDescription(for socketAddress: SocketAddress?) throws -> [String: Any] { + guard let socketAddress else { + throw ExtractionError.socketAddressIsEmpty + } + switch self { + case .tcpPort: + guard let port = socketAddress.port else { + throw ExtractionError.failedToExtractAssociatedInfo + } + return ["grpc_swift_port": port, + "grpc_port": port] + + case .unixDomainSocket: + guard let path = socketAddress.pathname else { + throw ExtractionError.failedToExtractAssociatedInfo + } + return ["grpc_path": path] + } + } + + var description: String { + switch self { + case let .tcpPort(port): + return "tcp port \(port)" + case let .unixDomainSocket(path): + return "unix socket \(path)" + } + } + + var supportsTLSCert: Bool { + switch self { + case .unixDomainSocket: + return false + case .tcpPort: + return true + } + } +} + +@objc final class IDBPortsConfiguration: NSObject { + + private enum Key { + static let debugPort = "-debug-port" + static let grpcDomainSock = "-grpc-domain-sock" + static let tlsCertPath = "-tls-cert-path" + static let grpcPort = "-grpc-port" + } + + /// The GRPC Unix Domain Socket Path + private let grpcDomainSocket: String? + + /// The GRPC TCP Port. + private let grpcPort: Int + + /// The debugserver port + @objc let debugserverPort: Int + + /// The TLS server cert path. If not specified grpcPort will be listening on unencrypted socket + let tlsCertPath: String? + + var swiftServerTarget: GRPCConnectionTarget { + if let grpcDomainSocket, !grpcDomainSocket.isEmpty { + return .unixDomainSocket(grpcDomainSocket) + } else { + return .tcpPort(port: grpcPort) + } + } + + /// Construct a ports object. + @objc init(arguments: UserDefaults) { + self.debugserverPort = arguments.string(forKey: Key.debugPort).flatMap(Int.init) ?? 10881 + self.grpcPort = arguments.string(forKey: Key.grpcPort).flatMap(Int.init) ?? 10882 + self.grpcDomainSocket = arguments.string(forKey: Key.grpcDomainSock) + self.tlsCertPath = arguments.string(forKey: Key.tlsCertPath) + } +} diff --git a/idb_companion/Configuration/Private/FBApplicationBasedGatekeeperRequestor.swift b/idb_companion/Configuration/Private/FBApplicationBasedGatekeeperRequestor.swift new file mode 100644 index 000000000..3f51efcd1 --- /dev/null +++ b/idb_companion/Configuration/Private/FBApplicationBasedGatekeeperRequestor.swift @@ -0,0 +1,73 @@ +// (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary. + +import Foundation + +struct GatekeeperRequest: Hashable { + let unixname: String + let gatekeeperName: String +} + +/// Fetches values from `XInternGraphEmployeeGKController.php` +@available(macOSApplicationExtension 10.15, *) +final class FBApplicationBasedGatekeeperRequestor: InternGraphRequestor { + + private let appID: String + private let token: String + private let baseURL: String + private let urlSession: URLSession + + init(appID: String, token: String, baseURL: String, urlSession: URLSession) { + self.appID = appID + self.token = token + self.baseURL = baseURL + self.urlSession = urlSession + } + + func read(request: GatekeeperRequest, decoder: JSONDecoder) async throws -> FetchResult { + let data = try await withCheckedThrowingContinuation { continuation in + performRequest(request: request) { result in + continuation.resume(with: result) + } + } + let gkBatch = try decoder.decode([String: FetchResult].self, from: data) + guard let gkResult = gkBatch[request.gatekeeperName] else { + throw FBInternGraphInternalError.sitevarNotFoundInResult + } + return gkResult + } + + private func performRequest(request: GatekeeperRequest, handler: @escaping @Sendable (Result) -> Void) { + let queryItems = [ + URLQueryItem(name: "app", value: appID), + URLQueryItem(name: "token", value: token), + URLQueryItem(name: "unixname", value: request.unixname), + URLQueryItem(name: "gk[]", value: request.gatekeeperName), + ] + + guard var urlComps = URLComponents(string: "\(baseURL)/gk/check") else { + assertionFailure("Incorrect URL components, should never happen") + handler(.failure(FBInternGraphError.failToFormURLRequest)) + return + } + urlComps.queryItems = queryItems + guard let sitevarURL = urlComps.url else { + assertionFailure("Fail to formURL, should never happen") + handler(.failure(FBInternGraphError.failToFormURLRequest)) + return + } + + URLSession.shared.dataTask(with: .init(url: sitevarURL), completionHandler: { data, response, error in + if let error { + handler(.failure(error)) + } else if let response = response as? HTTPURLResponse, !(200...299).contains(response.statusCode) { + let output = data.flatMap { String(data: $0, encoding: .utf8) } ?? "Empty" + handler(.failure(FBInternGraphInternalError.inacceptableStatusCode(output))) + } else if let data { + handler(.success(data)) + } else { + handler(.failure(FBInternGraphInternalError.notReceiveErrorOrData)) + } + }) + .resume() + } +} diff --git a/idb_companion/Configuration/Private/FBApplicationBasedSitevarRequestor.swift b/idb_companion/Configuration/Private/FBApplicationBasedSitevarRequestor.swift new file mode 100644 index 000000000..66c0d5797 --- /dev/null +++ b/idb_companion/Configuration/Private/FBApplicationBasedSitevarRequestor.swift @@ -0,0 +1,65 @@ +// (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary. + +import Foundation + +/// Fetches values from `XInternGraphSVController.php` +@available(macOSApplicationExtension 10.15, *) +final class FBApplicationBasedSitevarRequestor: InternGraphRequestor { + private let appID: String + private let token: String + private let baseURL: String + private let urlSession: URLSession + + init(appID: String, token: String, baseURL: String, urlSession: URLSession) { + self.appID = appID + self.token = token + self.baseURL = baseURL + self.urlSession = urlSession + } + + func read(request name: String, decoder: JSONDecoder) async throws -> FetchResult { + let data = try await withCheckedThrowingContinuation { continuation in + performRequest(sitevarList: [name]) { result in + continuation.resume(with: result) + } + } + let sitevarBatch = try decoder.decode([String: FetchResult].self, from: data) + guard let sitevar = sitevarBatch[name] else { + throw FBInternGraphInternalError.sitevarNotFoundInResult + } + return sitevar + } + + private func performRequest(sitevarList: [String], handler: @escaping @Sendable (Result) -> Void) { + let queryItems = [ + URLQueryItem(name: "app", value: appID), + URLQueryItem(name: "token", value: token) + ] + sitevarList.map { URLQueryItem(name: "sv[]", value: $0) } + + guard var urlComps = URLComponents(string: "\(baseURL)/sv/get/") else { + assertionFailure("Incorrect URL components, should never happen") + handler(.failure(FBInternGraphError.failToFormURLRequest)) + return + } + urlComps.queryItems = queryItems + guard let sitevarURL = urlComps.url else { + assertionFailure("Fail to formURL, should never happen") + handler(.failure(FBInternGraphError.failToFormURLRequest)) + return + } + + urlSession.dataTask(with: .init(url: sitevarURL), completionHandler: { data, response, error in + if let error { + handler(.failure(error)) + } else if let response = response as? HTTPURLResponse, !(200...299).contains(response.statusCode) { + let output = data.flatMap { String(data: $0, encoding: .utf8) } ?? "Empty" + handler(.failure(FBInternGraphInternalError.inacceptableStatusCode(output))) + } else if let data { + handler(.success(data)) + } else { + handler(.failure(FBInternGraphInternalError.notReceiveErrorOrData)) + } + }) + .resume() + } +} diff --git a/idb_companion/Configuration/Private/InternGraphCachableReader.swift b/idb_companion/Configuration/Private/InternGraphCachableReader.swift new file mode 100644 index 000000000..f10216c6e --- /dev/null +++ b/idb_companion/Configuration/Private/InternGraphCachableReader.swift @@ -0,0 +1,57 @@ +// (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary. + +import Foundation + +@available(macOSApplicationExtension 10.15, *) +actor InternGraphCachableReader { + + private let internGraphRequestor: Requestor + + private var ongoingTasks: [Requestor.Request: Task] = [:] + private var cachedValues: [Requestor.Request: (lastSyncDate: Date, value: any Sendable)] = [:] + + private let cacheInvalidationInterval: TimeInterval + + init(cacheInvalidationInterval: TimeInterval, internGraphRequestor: Requestor) { + self.cacheInvalidationInterval = cacheInvalidationInterval + self.internGraphRequestor = internGraphRequestor + } + + func readWithCache(request: Requestor.Request, decoder: JSONDecoder, defaultValue: FetchResult) async throws -> FetchResult { + if let ongoingFetchTask = ongoingTasks[request] { + let taskResult = try await ongoingFetchTask.value + guard let typedResult = taskResult as? FetchResult else { + throw FBInternGraphError.inconsistentSitevarTypes + } + return typedResult + } + if let cachedResult = cachedValues[request], Date().timeIntervalSince(cachedResult.lastSyncDate) < cacheInvalidationInterval { + guard let typedResult = cachedResult.value as? FetchResult else { + throw FBInternGraphError.inconsistentSitevarTypes + } + return typedResult + } + return try await fetchConfig(request: request, decoder: decoder, defaultValue: defaultValue) + } + + // swiftlint:disable force_cast + private func fetchConfig(request: Requestor.Request, decoder: JSONDecoder, defaultValue: FetchResult) async throws -> FetchResult { + let getInterngraphValueTask = Task { + defer { ongoingTasks.removeValue(forKey: request) } + + do { + let fetchResult: FetchResult = try await internGraphRequestor.read(request: request, decoder: decoder) + cachedValues[request] = (lastSyncDate: Date(), value: fetchResult) + + return fetchResult + } catch let error as FBInternGraphError { + throw error + } catch { + return defaultValue + } + } + ongoingTasks[request] = getInterngraphValueTask + + return try await getInterngraphValueTask.value as! FetchResult + } +} diff --git a/idb_companion/Configuration/Private/InternGraphRequestor.swift b/idb_companion/Configuration/Private/InternGraphRequestor.swift new file mode 100644 index 000000000..0bb9ad838 --- /dev/null +++ b/idb_companion/Configuration/Private/InternGraphRequestor.swift @@ -0,0 +1,9 @@ +// (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary. + +import Foundation + +protocol InternGraphRequestor { + associatedtype Request: Hashable & Sendable + + func read(request: Request, decoder: JSONDecoder) async throws -> FetchResult +} diff --git a/idb_companion/Configuration/SitevarReader.swift b/idb_companion/Configuration/SitevarReader.swift new file mode 100644 index 000000000..39361dea9 --- /dev/null +++ b/idb_companion/Configuration/SitevarReader.swift @@ -0,0 +1,40 @@ +// (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary. + +import Foundation + +/// Reads sitevar value from interngraph via http request. +/// Batch sitevar request is not implemented. +/// To use that reader you should create and FB application using https://www.internalfb.com/intern/wiki/XcontrollerGuide/XInternGraphController/#creating-an-app-id-and-t +@available(macOSApplicationExtension 10.15, *) +public final class SitevarReader { + + private let reader: InternGraphCachableReader + + /// Provide appID and token from FB application. To obtain follow [this insctructions](https://www.internalfb.com/intern/wiki/XcontrollerGuide/XInternGraphController/#creating-an-app-id-and-t) + /// - Parameters: + /// - appID: FB application identifier + /// - token: Generated token + /// - cacheInvalidationInterval: Sets cache lifetime + /// - sessionConfiguration: Controls setup for network calls. Default one sets request timeout to 15 seconds + public init(appID: String, token: String, + baseURL: String = DefaultConfiguration.baseURL, + cacheInvalidationInterval: TimeInterval = DefaultConfiguration.cacheInvalidationInterval, + sessionConfiguration: URLSessionConfiguration = DefaultConfiguration.urlSessionConfiguration) { + + let session = URLSession(configuration: sessionConfiguration) + self.reader = .init(cacheInvalidationInterval: cacheInvalidationInterval, + internGraphRequestor: FBApplicationBasedSitevarRequestor(appID: appID, token: token, baseURL: baseURL, urlSession: session)) + } + + /// Reads and caches sitevar value. + /// + /// - Parameters: + /// - sitevarName: Your fancy name of the sitevar + /// - decoder: Decoder to use to unmap server response + /// - default: value to use on network error + /// - Returns: Sitevar value + /// - Throws: FBInternGraphError on incorrect library usage or implementation or DecodingError. Network/server errors do *not* throw an error but uses `defaultValue` + public func read(name sitevarName: String, decoder: JSONDecoder, `default` defaultValue: Sitevar) async throws -> Sitevar { + try await reader.readWithCache(request: sitevarName, decoder: decoder, defaultValue: defaultValue) + } +} diff --git a/idb_companion/Reporting/FBiOSTargetDescription.h b/idb_companion/Reporting/FBiOSTargetDescription.h index c9e93d4b5..3e7ec1850 100644 --- a/idb_companion/Reporting/FBiOSTargetDescription.h +++ b/idb_companion/Reporting/FBiOSTargetDescription.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/idb_companion/Reporting/FBiOSTargetDescription.m b/idb_companion/Reporting/FBiOSTargetDescription.m index f03020b05..ef6d22780 100644 --- a/idb_companion/Reporting/FBiOSTargetDescription.m +++ b/idb_companion/Reporting/FBiOSTargetDescription.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -14,7 +14,6 @@ @interface FBiOSTargetDescription () @implementation FBiOSTargetDescription -@synthesize architecture = _architecture; @synthesize deviceType = _deviceType; @synthesize extendedInformation = _extendedInformation; @synthesize name = _name; @@ -23,18 +22,7 @@ @implementation FBiOSTargetDescription @synthesize targetType = _targetType; @synthesize udid = _udid; @synthesize uniqueIdentifier = _uniqueIdentifier; - -static NSString *FBiOSTargetTypeStringFromTargetType(FBiOSTargetType targetType) -{ - if ((targetType & FBiOSTargetTypeDevice) == FBiOSTargetTypeDevice) { - return @"device"; - } else if ((targetType & FBiOSTargetTypeSimulator) == FBiOSTargetTypeSimulator) { - return @"simulator"; - } else if ((targetType & FBiOSTargetTypeLocalMac) == FBiOSTargetTypeLocalMac) { - return @"mac"; - } - return nil; -} +@synthesize architectures = _architectures; - (instancetype)initWithTarget:(id)target { @@ -43,7 +31,6 @@ - (instancetype)initWithTarget:(id)target return nil; } - _architecture = target.architecture; _extendedInformation = target.extendedInformation; _model = target.deviceType.model; _name = target.name; @@ -72,7 +59,6 @@ - (id)copyWithZone:(NSZone *)zone - (NSDictionary *)asJSON { NSMutableDictionary *representation = [NSMutableDictionary dictionaryWithDictionary:@{ - KeyArchitecture : self.architecture ?: NSNull.null, KeyModel : self.model ?: NSNull.null, KeyName : self.name ?: NSNull.null, KeyOSVersion : self.osVersion.name ?: NSNull.null, diff --git a/idb_companion/Server/FBIDBCompanionServer.h b/idb_companion/Server/FBIDBCompanionServer.h deleted file mode 100644 index 16cc62d25..000000000 --- a/idb_companion/Server/FBIDBCompanionServer.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#import -#import - -NS_ASSUME_NONNULL_BEGIN - -@class FBIDBCommandExecutor; -@class FBIDBLogger; -@class FBIDBPortsConfiguration; -@class FBTemporaryDirectory; - -@protocol FBEventReporter; - - -/** - The IDB Companion. - */ -@interface FBIDBCompanionServer : NSObject - -#pragma mark Initializers - -/** - The Designated Initializer - - @param target the target to serve up - @param temporaryDirectory the temporaryDirectory to use. - @param ports the ports to use. - @param eventReporter the event reporter to report to. - @param logger the logger to us. - @param error an error out for any error that occurs in initialization - @return a server on success, nil otherwise. - */ -+ (nullable instancetype)companionForTarget:(id)target temporaryDirectory:(FBTemporaryDirectory *)temporaryDirectory ports:(FBIDBPortsConfiguration *)ports eventReporter:(id)eventReporter logger:(id)logger error:(NSError **)error; - -#pragma mark Methods - -/** - Starts the server. - - @return a Future that resolves with a dictionary describing the bound server. - */ -- (FBFuture *> *)start; - -#pragma mark Properties - -/** - Resolves when the server has stopped serving. - */ -@property (nonatomic, strong, readonly) FBFuture *completed; - -@end - -NS_ASSUME_NONNULL_END diff --git a/idb_companion/Server/FBIDBCompanionServer.mm b/idb_companion/Server/FBIDBCompanionServer.mm deleted file mode 100644 index 8f1c418f9..000000000 --- a/idb_companion/Server/FBIDBCompanionServer.mm +++ /dev/null @@ -1,153 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#import "FBIDBCompanionServer.h" - -#import -#import -#import - -#import "FBIDBStorageManager.h" -#import "FBIDBCommandExecutor.h" -#import "FBIDBError.h" -#import "FBIDBPortsConfiguration.h" -#import "FBIDBLogger.h" -#import "FBIDBServiceHandler.h" - -@interface FBIDBCompanionServer () - -@property (nonatomic, strong, readonly) FBIDBPortsConfiguration *ports; -@property (nonatomic, strong, readonly) FBIDBCommandExecutor *commandExecutor; -@property (nonatomic, strong, readonly) id target; -@property (nonatomic, strong, readonly) id logger; -@property (nonatomic, strong, readonly) id eventReporter; -@property (nonatomic, strong, readonly) FBMutableFuture *serverTerminated; - -@property (nonatomic, assign, readwrite) in_port_t selectedPort; - -@end - -using grpc::Server; -using grpc::ServerBuilder; -using grpc::ServerContext; -using grpc::Status; -using grpc::ResourceQuota; -using namespace std; - -@implementation FBIDBCompanionServer - -#pragma mark Initializers - -+ (instancetype)companionForTarget:(id)target temporaryDirectory:(FBTemporaryDirectory *)temporaryDirectory ports:(FBIDBPortsConfiguration *)ports eventReporter:(id)eventReporter logger:(FBIDBLogger *)logger error:(NSError **)error -{ - FBIDBStorageManager *storageManager = [FBIDBStorageManager managerForTarget:target logger:logger error:error]; - if (!storageManager) { - return nil; - } - // Command Executor - FBIDBCommandExecutor *commandExecutor = [FBIDBCommandExecutor - commandExecutorForTarget:target - storageManager:storageManager - temporaryDirectory:temporaryDirectory - ports:ports - logger:logger]; - commandExecutor = [FBLoggingWrapper wrap:commandExecutor simplifiedNaming:YES eventReporter:eventReporter logger:logger]; - - return [[self alloc] initWithPorts:ports target:target commandExecutor:commandExecutor eventReporter:eventReporter logger:logger]; -} - - -- (instancetype)initWithPorts:(FBIDBPortsConfiguration *)ports target:(id)target commandExecutor:(FBIDBCommandExecutor *)commandExecutor eventReporter:(id)eventReporter logger:(id)logger -{ - self = [super init]; - if (!self) { - return nil; - } - - _ports = ports; - _target = target; - _commandExecutor = commandExecutor; - _eventReporter = eventReporter; - _logger = logger; - _serverTerminated = FBMutableFuture.future; - - return self; -} - - -#pragma mark FBIDBCompanionServer - -- (FBFuture *> *)start -{ - dispatch_queue_t queue = dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); - FBMutableFuture *> *serverStarted = FBMutableFuture.future; - dispatch_async(queue, ^(void){ - NSString *domainSocket = self.ports.grpcDomainSocket; - NSString *tlsCertPath = self.ports.tlsCertPath; - std::string server_address("0.0.0.0:" + std::to_string(self.ports.grpcPort)); - if (domainSocket) { - server_address = "unix:" + std::string(self.ports.grpcDomainSocket.UTF8String); - [self.logger logFormat:@"Starting GRPC server at path %@", domainSocket]; - } else { - [self.logger logFormat:@"Starting GRPC server on port %u", self.ports.grpcPort]; - if (tlsCertPath) { - [self.logger logFormat:@"Starting GRPC server with TLS path %@", tlsCertPath]; - } - } - FBIDBServiceHandler service = FBIDBServiceHandler(self.commandExecutor, self.target, self.eventReporter); - int selectedPort = 0; - std::shared_ptr server_cred = grpc::InsecureServerCredentials(); - if (tlsCertPath && !domainSocket) { - grpc::SslServerCredentialsOptions sslOpts; - NSData *rawCertData = [NSData dataWithContentsOfFile:tlsCertPath]; - NSString *certAsString = [[NSString alloc] initWithData:rawCertData encoding:NSUTF8StringEncoding]; - std::string key = [certAsString UTF8String]; - std::string cert = [certAsString UTF8String]; - sslOpts.pem_key_cert_pairs.push_back({key, cert}); - server_cred = grpc::SslServerCredentials(sslOpts); - } - unique_ptr server(ServerBuilder() - .AddListeningPort(server_address, server_cred, &selectedPort) - .RegisterService(&service) - .SetResourceQuota(ResourceQuota("idb_resource.quota").SetMaxThreads(10)) - .SetMaxReceiveMessageSize(16777216) // 16MB (16 * 1024 * 1024). Default is 4MB (4 * 1024 * 1024) - .AddChannelArgument(GRPC_ARG_ALLOW_REUSEPORT, 0) - .BuildAndStart() - ); - // AddListeningPort will either set this to 0 or not modify it. - // For 0 TCP input that binds: The selectedPort is whatever port that the server has bound on - // For PORT TCP input that binds: The selectedPort is PORT. - // For a Unix Domain Socket: The selectedPort is 1. - if (selectedPort == 0) { - [serverStarted resolveWithError:[[FBIDBError describeFormat:@"Failed to start GRPC Server"] build]]; - return; - } - if (domainSocket) { - [self.logger.info logFormat:@"Started GRPC server at path %@", domainSocket]; - [serverStarted resolveWithResult:@{@"grpc_path": domainSocket}]; - } else { - [self.logger.info logFormat:@"Started GRPC server on port %u", selectedPort]; - [serverStarted resolveWithResult:@{@"grpc_port": @(selectedPort)}]; - } - server->Wait(); - [self.logger.info logFormat:@"GRPC server is no longer running on port %u", selectedPort]; - [self.serverTerminated resolveWithResult:NSNull.null]; - }); - return serverStarted; -} - -- (FBFuture *)completed -{ - return self.serverTerminated; -} - -- (NSString *)operationType -{ - return @"grpc_server"; -} - -@end diff --git a/idb_companion/Server/FBIDBServiceHandler.h b/idb_companion/Server/FBIDBServiceHandler.h deleted file mode 100644 index d335b73a2..000000000 --- a/idb_companion/Server/FBIDBServiceHandler.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#import - -@class FBIDBCommandExecutor; -@class FBIDBPortsConfiguration; - -using idb::CompanionService; -using grpc::Status; -using grpc::ServerContext; - -#pragma once - -class FBIDBServiceHandler final : public CompanionService::Service { -private: - FBIDBCommandExecutor *_commandExecutor; - id _target; - id _eventReporter; - FBFuture *install_future(const idb::InstallRequest_Destination destination, grpc::ServerReaderWriter *stream); - -public: - FBIDBPortsConfiguration *portsConfig; - // Constructors - FBIDBServiceHandler(FBIDBCommandExecutor *commandExecutor, id target, id eventReporter); - FBIDBServiceHandler(const FBIDBServiceHandler &c); - - // Handled Methods - Status accessibility_info(ServerContext *context, const idb::AccessibilityInfoRequest *request, idb::AccessibilityInfoResponse *response); - Status add_media(ServerContext *context,grpc::ServerReader *reader, idb::AddMediaResponse *response); - Status approve(ServerContext *context, const idb::ApproveRequest *request, idb::ApproveResponse *response); - Status clear_keychain(ServerContext *context, const idb::ClearKeychainRequest *request, idb::ClearKeychainResponse *response); - Status connect(ServerContext *context, const idb::ConnectRequest *request, idb::ConnectResponse *response); - Status contacts_update(ServerContext *context, const idb::ContactsUpdateRequest *request, idb::ContactsUpdateResponse *response); - Status crash_delete(ServerContext *context, const idb::CrashLogQuery *request, idb::CrashLogResponse *response); - Status crash_list(ServerContext *context, const idb::CrashLogQuery *request, idb::CrashLogResponse *response); - Status crash_show(ServerContext *context, const idb::CrashShowRequest *request, idb::CrashShowResponse *response); - Status debugserver(ServerContext *context,grpc::ServerReaderWriter *stream); - Status describe(ServerContext *context, const idb::TargetDescriptionRequest *request, idb::TargetDescriptionResponse *response); - Status focus(ServerContext *context, const idb::FocusRequest *request, idb::FocusResponse *response); - Status get_setting(ServerContext* context, const idb::GetSettingRequest* request, idb::GetSettingResponse* response); - Status hid(ServerContext *context, grpc::ServerReader *reader, idb::HIDResponse *response); - Status install(ServerContext *context, grpc::ServerReaderWriter *stream); - Status instruments_run(ServerContext *context, grpc::ServerReaderWriter *stream); - Status launch(ServerContext *context,grpc::ServerReaderWriter *stream); - Status list_apps(ServerContext *context, const idb::ListAppsRequest *request, idb::ListAppsResponse *response); - Status list_settings(ServerContext* context, const idb::ListSettingRequest* request, idb::ListSettingResponse* response); - Status log(ServerContext *context, const idb::LogRequest *request, grpc::ServerWriter *response); - Status ls(ServerContext *context, const idb::LsRequest *request, idb::LsResponse *response); - Status mkdir(ServerContext *context, const idb::MkdirRequest *request, idb::MkdirResponse *response); - Status mv(ServerContext *context, const idb::MvRequest *request, idb::MvResponse *response); - Status open_url(ServerContext *context, const idb::OpenUrlRequest *request, idb::OpenUrlRequest *response); - Status pull(ServerContext *context, const idb::PullRequest *request, grpc::ServerWriter<::idb::PullResponse> *writer); - Status push(ServerContext *context,grpc::ServerReader *reader, idb::PushResponse *response); - Status record(ServerContext *context,grpc::ServerReaderWriter *stream); - Status rm(ServerContext *context, const idb::RmRequest *request, idb::RmResponse *response); - Status screenshot(ServerContext *context, const idb::ScreenshotRequest *request, idb::ScreenshotResponse *response); - Status set_location(ServerContext *context, const idb::SetLocationRequest *request, idb::SetLocationResponse *response); - Status setting(ServerContext* context, const idb::SettingRequest* request, idb::SettingResponse* response); - Status tail(ServerContext* context, grpc::ServerReaderWriter* stream); - Status terminate(ServerContext *context, const idb::TerminateRequest *request, idb::TerminateResponse *response); - Status uninstall(ServerContext *context, const idb::UninstallRequest *request, idb::UninstallResponse *response); - Status video_stream(ServerContext* context, grpc::ServerReaderWriter* stream); - Status xctest_list_bundles(ServerContext *context, const idb::XctestListBundlesRequest *request, idb::XctestListBundlesResponse *response); - Status xctest_list_tests(ServerContext *context, const idb::XctestListTestsRequest *request, idb::XctestListTestsResponse *response); - Status xctest_run(ServerContext *context, const idb::XctestRunRequest *request, grpc::ServerWriter *response); - Status xctrace_record(ServerContext *context, grpc::ServerReaderWriter *stream); - Status send_notification(ServerContext *context, const idb::SendNotificationRequest *request, idb::SendNotificationResponse *response); - Status dap(ServerContext *context,grpc::ServerReaderWriter *stream); - Status simulate_memory_warning(ServerContext *context, const idb::SimulateMemoryWarningRequest *request, idb::SimulateMemoryWarningResponse *response); -}; diff --git a/idb_companion/Server/FBIDBServiceHandler.mm b/idb_companion/Server/FBIDBServiceHandler.mm deleted file mode 100644 index 339abf5a7..000000000 --- a/idb_companion/Server/FBIDBServiceHandler.mm +++ /dev/null @@ -1,1690 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#import - -#import -#import -#import -#import - -#import "FBCodeCoverageRequest.h" -#import "FBDataDownloadInput.h" -#import "FBIDBCommandExecutor.h" -#import "FBIDBError.h" -#import "FBIDBPortsConfiguration.h" -#import "FBIDBServiceHandler.h" -#import "FBIDBStorageManager.h" -#import "FBIDBTestOperation.h" -#import "FBIDBXCTestReporter.h" -#import "FBXCTestRunRequest.h" -#import - -using grpc::Server; -using grpc::ServerBuilder; -using grpc::ServerContext; -using grpc::Status; - -#pragma mark Private Functions - -static NSString *nsstring_from_c_string(const ::std::string& string) -{ - return [NSString stringWithUTF8String:string.c_str()]; -} - -static int BufferOutputSize = 16384; // # 16Kb - -static FBCompressionFormat read_compression_format(const idb::Payload_Compression comp) -{ - switch (comp) { - case idb::Payload_Compression::Payload_Compression_GZIP: - return FBCompressionFormatGZIP; - case idb::Payload_Compression::Payload_Compression_ZSTD: - return FBCompressionFormatZSTD; - default: - return FBCompressionFormatGZIP; - } -} - -template -static FBFuture * resolve_next_read(grpc::internal::ReaderInterface *reader) -{ - FBMutableFuture *future = FBMutableFuture.future; - dispatch_queue_t queue = dispatch_queue_create("com.facebook.idb.grpc.reader_wait", DISPATCH_QUEUE_SERIAL); - dispatch_async(queue, ^{ - T stop; - reader->Read(&stop); - [future resolveWithResult:NSNull.null]; - }); - return future; -} - -template -static id drain_consumer(grpc::internal::WriterInterface *writer, FBFuture *done) -{ - return [FBBlockDataConsumer asynchronousDataConsumerWithBlock:^(NSData *data) { - if (done.hasCompleted) { - return; - } - T response; - idb::Payload *payload = response.mutable_payload(); - payload->set_data(data.bytes, data.length); - writer->Write(response); - }]; -} - -template -static id consumer_from_request(grpc::ServerReaderWriter *stream, Read& request, FBFuture *done, NSError **error) -{ - Read initial; - stream->Read(&initial); - request = initial; - const std::string requestedFilePath = initial.start().file_path(); - if (requestedFilePath.length() > 0) { - return [FBFileWriter syncWriterForFilePath:nsstring_from_c_string(requestedFilePath.c_str()) error:error]; - } - return drain_consumer(stream, done); -} - -template -static Status drain_writer(FBFuture *> *taskFuture, grpc::internal::WriterInterface *stream) -{ - NSError *error = nil; - FBProcess *task = [taskFuture block:&error]; - if (!task) { - return Status(grpc::StatusCode::INTERNAL, error.localizedDescription.UTF8String); - } - NSInputStream *inputStream = task.stdOut; - [inputStream open]; - while (true) { - uintptr_t buffer[BufferOutputSize]; - NSInteger size = [inputStream read:(uint8_t *)buffer maxLength:BufferOutputSize]; - if (size == 0) { - break; - } - if (size < 0) { - return Status::OK; - } - T response; - idb::Payload *payload = response.mutable_payload(); - payload->set_data(reinterpret_cast(buffer), size); - stream->Write(response); - } - [inputStream close]; - NSNumber *exitCode = [task.exitCode block:&error]; - if (exitCode.integerValue != 0) { - NSString *errorString = [NSString stringWithFormat:@"Draining operation failed with exit code %ld", (long)exitCode.integerValue]; - return Status(grpc::StatusCode::INTERNAL, errorString.UTF8String); - } - return Status::OK; -} - -template -static Status respond_file_path(NSURL *source, NSString *destination, grpc::internal::WriterInterface *stream) -{ - if (source) { - NSError *error = nil; - if (![NSFileManager.defaultManager moveItemAtPath:source.path toPath:destination error:&error]) { - return Status(grpc::StatusCode::INTERNAL, error.localizedDescription.UTF8String); - } - } - T response; - idb::Payload payload = response.payload(); - payload.set_file_path(destination.UTF8String); - stream->Write(response); - return Status::OK; -} - -template -static FBProcessInput *pipe_to_input(const idb::Payload initial, grpc::ServerReader *reader) -{ - const std::string initialData = initial.data(); - FBProcessInput *input = [FBProcessInput inputFromStream]; - NSOutputStream *stream = input.contents; - dispatch_queue_t queue = dispatch_queue_create("com.facebook.idb.processinput", DISPATCH_QUEUE_SERIAL); - dispatch_async(queue, ^{ - T request; - [stream open]; - [stream write:(const uint8_t *)initialData.c_str() maxLength:initialData.length()]; - while (reader->Read(&request)) { - const auto tarData = request.payload().data(); - [stream write:(const uint8_t *)tarData.c_str() maxLength:tarData.length()]; - } - [stream close]; - }); - return input; -} - -static FBProcessInput *pipe_to_input_output(const idb::Payload initial, grpc::ServerReaderWriter *stream) -{ - const std::string initialData = initial.data(); - FBProcessInput *input = [FBProcessInput inputFromStream]; - NSOutputStream *appStream = input.contents; - dispatch_queue_t queue = dispatch_queue_create("com.facebook.idb.processinput", DISPATCH_QUEUE_SERIAL); - dispatch_async(queue, ^{ - idb::InstallRequest request; - [appStream open]; - [appStream write:(const uint8_t *)initialData.c_str() maxLength:initialData.length()]; - while (stream->Read(&request)) { - const auto tarData = request.payload().data(); - [appStream write:(const uint8_t *)tarData.c_str() maxLength:tarData.length()]; - } - [appStream close]; - }); -return input; -} - -static id pipe_output(const idb::ProcessOutput_Interface interface, dispatch_queue_t queue, grpc::ServerReaderWriter *stream) -{ - id consumer = [FBBlockDataConsumer asynchronousDataConsumerOnQueue:queue consumer:^(NSData *data) { - idb::LaunchResponse response; - idb::ProcessOutput *output = response.mutable_output(); - output->set_data(data.bytes, data.length); - output->set_interface(interface); - stream->Write(response); - }]; - return consumer; -} - -template -static FBFuture *> *filepaths_from_stream(const idb::Payload initial, grpc::ServerReader *reader) -{ - NSMutableArray *filePaths = NSMutableArray.array; - FBMutableFuture *> *future = FBMutableFuture.future; - dispatch_queue_t queue = dispatch_queue_create("com.facebook.idb.processinput", DISPATCH_QUEUE_SERIAL); - dispatch_async(queue, ^{ - T request; - [filePaths addObject:[NSURL fileURLWithPath:nsstring_from_c_string(initial.file_path())]]; - while (reader->Read(&request)) { - [filePaths addObject:[NSURL fileURLWithPath:nsstring_from_c_string(request.payload().file_path())]]; - } - [future resolveWithResult:filePaths]; - }); - return future; -} - -static FBFutureContext *> *filepaths_from_tar(FBTemporaryDirectory *temporaryDirectory, FBProcessInput *input, bool extract_from_subdir, FBCompressionFormat compression, id logger) -{ - dispatch_queue_t queue = dispatch_queue_create("com.facebook.idb.processinput", DISPATCH_QUEUE_SERIAL); - FBFutureContext *tarContext = [temporaryDirectory withArchiveExtractedFromStream:input compression:compression]; - if (extract_from_subdir) { - // Extract from subdirectories - return [temporaryDirectory filesFromSubdirs:tarContext]; - } else { - // Extract from the top level - return [tarContext onQueue:queue pend:^FBFuture *> *(NSURL *extractionDir) { - NSError *error; - NSArray *paths = [NSFileManager.defaultManager contentsOfDirectoryAtURL:extractionDir includingPropertiesForKeys:@[NSURLIsDirectoryKey] options:0 error:&error]; - if (!paths) { - return [FBFuture futureWithError:error]; - } - return [FBFuture futureWithResult:paths]; - }]; - } -} - -template -static FBFutureContext *> *filepaths_from_reader(FBTemporaryDirectory *temporaryDirectory, grpc::ServerReader *reader, bool extract_from_subdir, id logger) -{ - T request; - reader->Read(&request); - idb::Payload firstPayload = request.payload(); - - // The first item in the payload stream may be the compression format, if it's not assume the default. - FBCompressionFormat compression = FBCompressionFormatGZIP; - if (firstPayload.source_case() == idb::Payload::kCompression) { - compression = read_compression_format(firstPayload.compression()); - reader->Read(&request); - firstPayload = request.payload(); - } - - switch (firstPayload.source_case()) { - case idb::Payload::kData: { - FBProcessInput *input = pipe_to_input(firstPayload, reader); - return filepaths_from_tar(temporaryDirectory, input, extract_from_subdir, compression, logger); - } - case idb::Payload::kFilePath: { - return [FBFutureContext futureContextWithFuture:filepaths_from_stream(firstPayload, reader)]; - } - default: { - return [FBFutureContext futureContextWithError:[FBControlCoreError errorForFormat:@"Unrecognised initial payload type %u", firstPayload.source_case()]]; - } - } -} - -static NSDictionary *extract_str_dict(const ::google::protobuf::Map<::std::string, ::std::string >& iterator) -{ - NSMutableDictionary *environment = NSMutableDictionary.dictionary; - for (auto item : iterator) { - environment[nsstring_from_c_string(item.first)] = nsstring_from_c_string(item.second); - } - return environment; -} - -template -static NSArray *extract_string_array(T &input) -{ - NSMutableArray *arguments = NSMutableArray.array; - for (auto value : input) { - [arguments addObject:nsstring_from_c_string(value)]; - } - return arguments; -} - -static FBCodeCoverageRequest *extract_code_coverage(const idb::XctestRunRequest *request) { - if (request->has_code_coverage()) { - const idb::XctestRunRequest::CodeCoverage codeCoverage = request->code_coverage(); - FBCodeCoverageFormat format = FBCodeCoverageExported; - switch (codeCoverage.format()) { - case idb::XctestRunRequest_CodeCoverage_Format::XctestRunRequest_CodeCoverage_Format_RAW: - format = FBCodeCoverageRaw; - break; - case idb::XctestRunRequest_CodeCoverage_Format::XctestRunRequest_CodeCoverage_Format_EXPORTED: - default: - format = FBCodeCoverageExported; - break; - } - return [[FBCodeCoverageRequest alloc] initWithCollect:codeCoverage.collect() format:format]; - } else { - // fallback to deprecated request field for backwards compatibility - return [[FBCodeCoverageRequest alloc] initWithCollect:request->collect_coverage() format:FBCodeCoverageExported]; - } -} - -static FBXCTestRunRequest *convert_xctest_request(const idb::XctestRunRequest *request) -{ - NSNumber *testTimeout = @(request->timeout()); - NSArray *arguments = extract_string_array(request->arguments()); - NSDictionary *environment = extract_str_dict(request->environment()); - NSMutableSet *testsToRun = nil; - NSMutableSet *testsToSkip = NSMutableSet.set; - NSString *testBundleID = nsstring_from_c_string(request->test_bundle_id()); - BOOL reportActivities = request->report_activities(); - BOOL collectLogs = request->collect_logs(); - BOOL waitForDebugger = request->wait_for_debugger(); - BOOL reportAttachments = request->report_attachments(); - FBCodeCoverageRequest *coverage = extract_code_coverage(request); - - if (request->tests_to_run_size() > 0) { - testsToRun = NSMutableSet.set; - for (int i = 0; i < request->tests_to_run_size(); i++) { - const std::string value = request->tests_to_run(i); - [testsToRun addObject:nsstring_from_c_string(value)]; - } - } - for (int i = 0; i < request->tests_to_skip_size(); i++) { - const std::string value = request->tests_to_skip(i); - [testsToSkip addObject:nsstring_from_c_string(value)]; - } - - - switch (request->mode().mode_case()) { - case idb::XctestRunRequest_Mode::kLogic: { - return [FBXCTestRunRequest logicTestWithTestBundleID:testBundleID environment:environment arguments:arguments testsToRun:testsToRun testsToSkip:testsToSkip testTimeout:testTimeout reportActivities:reportActivities reportAttachments:reportAttachments coverageRequest:coverage collectLogs:collectLogs waitForDebugger:waitForDebugger]; - } - case idb::XctestRunRequest_Mode::kApplication: { - const idb::XctestRunRequest::Application application = request->mode().application(); - NSString *appBundleID = nsstring_from_c_string(application.app_bundle_id()); - return [FBXCTestRunRequest applicationTestWithTestBundleID:testBundleID appBundleID:appBundleID environment:environment arguments:arguments testsToRun:testsToRun testsToSkip:testsToSkip testTimeout:testTimeout reportActivities:reportActivities reportAttachments:reportAttachments coverageRequest:coverage collectLogs:collectLogs waitForDebugger:waitForDebugger]; - } - case idb::XctestRunRequest_Mode::kUi: { - const idb::XctestRunRequest::UI ui = request->mode().ui(); - NSString *appBundleID = nsstring_from_c_string(ui.app_bundle_id()); - NSString *testHostAppBundleID = nsstring_from_c_string(ui.test_host_app_bundle_id()); - return [FBXCTestRunRequest uiTestWithTestBundleID:testBundleID appBundleID:appBundleID testHostAppBundleID:testHostAppBundleID environment:environment arguments:arguments testsToRun:testsToRun testsToSkip:testsToSkip testTimeout:testTimeout reportActivities:reportActivities reportAttachments:reportAttachments coverageRequest:coverage collectLogs:collectLogs]; - } - default: - return nil; - } -} - -static NSPredicate *nspredicate_from_crash_log_query(const idb::CrashLogQuery *request) -{ - NSMutableArray *subpredicates = [NSMutableArray array]; - if (request->since()) { - [subpredicates addObject:[FBCrashLogInfo predicateNewerThanDate:[NSDate dateWithTimeIntervalSince1970:request->since()]]]; - } - if (request->before()) { - [subpredicates addObject:[FBCrashLogInfo predicateOlderThanDate:[NSDate dateWithTimeIntervalSince1970:request->before()]]]; - } - NSString *bundle_id = nsstring_from_c_string(request->bundle_id()); - if (bundle_id.length) { - [subpredicates addObject:[FBCrashLogInfo predicateForIdentifier:bundle_id]]; - } - NSString *name = nsstring_from_c_string(request->name()); - if (name.length) { - [subpredicates addObject:[FBCrashLogInfo predicateForName:name]]; - } - if (subpredicates.count == 0) { - return [NSPredicate predicateWithValue:YES]; - } - return [NSCompoundPredicate andPredicateWithSubpredicates:subpredicates]; -} - -static void fill_crash_log_info(idb::CrashLogInfo *info, const FBCrashLogInfo *crash) -{ - info->set_name(crash.name.UTF8String); - info->set_process_name(crash.processName.UTF8String); - info->set_parent_process_name(crash.parentProcessName.UTF8String); - info->set_process_identifier(crash.processIdentifier); - info->set_parent_process_identifier(crash.parentProcessIdentifier); - info->set_timestamp(crash.date.timeIntervalSince1970); -} - -static void fill_crash_log_response(idb::CrashLogResponse *response, const NSArray *crashes) -{ - for (FBCrashLogInfo *crash in crashes) { - idb::CrashLogInfo *info = response->add_list(); - fill_crash_log_info(info, crash); - } -} - -static FBSimulatorHIDEvent *translate_event(idb::HIDEvent &event, NSError **error) -{ - if (event.has_press()) { - idb::HIDEvent_HIDDirection direction = event.press().direction(); - idb::HIDEvent_HIDPressAction action = event.press().action(); - if (action.has_key()) { - int keycode = (int)action.key().keycode(); - if (direction == idb::HIDEvent_HIDDirection_DOWN) { - return [FBSimulatorHIDEvent keyDown:keycode]; - } else if (direction == idb::HIDEvent_HIDDirection_UP) { - return [FBSimulatorHIDEvent keyUp:keycode]; - } - } else if (action.has_button()) { - // Need to convert between the objc enum that starts at 1 and the grpc enum that starts at 0 - FBSimulatorHIDButton button = (FBSimulatorHIDButton)(action.button().button() + 1); - if (direction == idb::HIDEvent_HIDDirection_DOWN) { - return [FBSimulatorHIDEvent buttonDown:button]; - } else if (direction == idb::HIDEvent_HIDDirection_UP) { - return [FBSimulatorHIDEvent buttonUp:button]; - } - } else if (action.has_touch()) { - int x = action.touch().point().x(); - int y = action.touch().point().y(); - if (direction == idb::HIDEvent_HIDDirection_DOWN) { - return [FBSimulatorHIDEvent touchDownAtX:x y:y]; - } else if (direction == idb::HIDEvent_HIDDirection_UP) { - return [FBSimulatorHIDEvent touchUpAtX:x y:y]; - } - } - } else if (event.has_swipe()) { - return [FBSimulatorHIDEvent swipe:event.swipe().start().x() yStart:event.swipe().start().y() xEnd:event.swipe().end().x() yEnd:event.swipe().end().y() delta:event.swipe().delta() duration:event.swipe().duration()]; - } else if (event.has_delay()) { - return [FBSimulatorHIDEvent delay:event.delay().duration()]; - } - if (error) { - *error = [FBControlCoreError errorForDescription:@"Can't decode event"]; - } - return nil; -} - -static FBInstrumentsConfiguration *translate_instruments_configuration(idb::InstrumentsRunRequest_Start request, FBIDBStorageManager *storageManager) -{ - return [FBInstrumentsConfiguration - configurationWithTemplateName:nsstring_from_c_string(request.template_name()) - targetApplication:nsstring_from_c_string(request.app_bundle_id()) - appEnvironment:extract_str_dict(request.environment()) - appArguments:extract_string_array(request.arguments()) - toolArguments:[storageManager interpolateArgumentReplacements:extract_string_array(request.tool_arguments())] - timings:[FBInstrumentsTimings - timingsWithTerminateTimeout:request.timings().terminate_timeout() ?: DefaultInstrumentsTerminateTimeout - launchRetryTimeout:request.timings().launch_retry_timeout() ?: DefaultInstrumentsLaunchRetryTimeout - launchErrorTimeout:request.timings().launch_error_timeout() ?: DefaultInstrumentsLaunchErrorTimeout - operationDuration:request.timings().operation_duration() ?: DefaultInstrumentsOperationDuration - ] - ]; -} - -static FBXCTraceRecordConfiguration *translate_xctrace_record_configuration(idb::XctraceRecordRequest_Start request) -{ - return [FBXCTraceRecordConfiguration - RecordWithTemplateName:nsstring_from_c_string(request.template_name()) - timeLimit:request.time_limit() ?: DefaultXCTraceRecordOperationTimeLimit - package:nsstring_from_c_string(request.package()) - allProcesses:request.target().all_processes() - processToAttach:nsstring_from_c_string(request.target().process_to_attach()) - processToLaunch:nsstring_from_c_string(request.target().launch_process().process_to_launch()) - launchArgs:extract_string_array(request.target().launch_process().launch_args()) - targetStdin:nsstring_from_c_string(request.target().launch_process().target_stdin()) - targetStdout:nsstring_from_c_string(request.target().launch_process().target_stdout()) - processEnv:extract_str_dict(request.target().launch_process().process_env()) - shim:nil - ]; -} - -static idb::DebugServerResponse translate_debugserver_status(id debugServer) -{ - idb::DebugServerResponse response; - idb::DebugServerResponse::Status *status = response.mutable_status(); - if (debugServer) { - for (NSString *command in debugServer.lldbBootstrapCommands) { - status->add_lldb_bootstrap_commands(command.UTF8String); - } - } - return response; -} - -static NSString *file_container(idb::FileContainer container) -{ - switch (container.kind()) { - case idb::FileContainer_Kind_ROOT: - return FBFileContainerKindRoot; - case idb::FileContainer_Kind_MEDIA: - return FBFileContainerKindMedia; - case idb::FileContainer_Kind_CRASHES: - return FBFileContainerKindCrashes; - case idb::FileContainer_Kind_PROVISIONING_PROFILES: - return FBFileContainerKindProvisioningProfiles; - case idb::FileContainer_Kind_MDM_PROFILES: - return FBFileContainerKindMDMProfiles; - case idb::FileContainer_Kind_SPRINGBOARD_ICONS: - return FBFileContainerKindSpringboardIcons; - case idb::FileContainer_Kind_WALLPAPER: - return FBFileContainerKindWallpaper; - case idb::FileContainer_Kind_DISK_IMAGES: - return FBFileContainerKindDiskImages; - case idb::FileContainer_Kind_GROUP_CONTAINER: - return FBFileContainerKindGroup; - case idb::FileContainer_Kind_APPLICATION_CONTAINER: - return FBFileContainerKindApplication; - case idb::FileContainer_Kind_AUXILLARY: - return FBFileContainerKindAuxillary; - case idb::FileContainer_Kind_APPLICATION: - default: - return nsstring_from_c_string(container.bundle_id()); - } -} - -static void populate_companion_info(idb::CompanionInfo *info, id reporter, id target) -{ - info->set_udid(target.udid.UTF8String); - NSDictionary *metadata = reporter.metadata ?: @{}; - NSError *error = nil; - NSData *data = [NSJSONSerialization dataWithJSONObject:metadata options:0 error:&error]; - if (data) { - info->set_metadata(data.bytes, data.length); - } -} - -#pragma mark Constructors - -FBIDBServiceHandler::FBIDBServiceHandler(FBIDBCommandExecutor *commandExecutor, id target, id eventReporter) -{ - _commandExecutor = commandExecutor; - _target = target; - _eventReporter = eventReporter; -} - -FBIDBServiceHandler::FBIDBServiceHandler(const FBIDBServiceHandler &c) -{ - _commandExecutor = c._commandExecutor; - _target = c._target; - _eventReporter = c._eventReporter; -} - -#pragma mark Handled Methods - -FBFuture *FBIDBServiceHandler::install_future(const idb::InstallRequest_Destination destination, grpc::ServerReaderWriter *stream) -{@autoreleasepool{ - // Read the initial request - idb::InstallRequest request; - stream->Read(&request); - - // The name hint may be provided, if it is not then default to some UUID, then advance the stream. - NSString *name = NSUUID.UUID.UUIDString; - if (request.value_case() == idb::InstallRequest::ValueCase::kNameHint) { - name = nsstring_from_c_string(request.name_hint()); - stream->Read(&request); - } - - // A debuggable flag may be provided, if it is, then obtain that value, then advance that stream. - BOOL makeDebuggable = NO; - if (request.value_case() == idb::InstallRequest::ValueCase::kMakeDebuggable) { - makeDebuggable = (request.make_debuggable() == true); - stream->Read(&request); - } - // A bundle id might be provided, if it is, then obtain the installed app if exists, then advance that stream. - // It can be used to determine where debug symbols should be linked - NSString *bundleID = nil; - if (request.value_case() == idb::InstallRequest::ValueCase::kBundleId) { - bundleID = nsstring_from_c_string(request.bundle_id()); - stream->Read(&request); - } - - // Now that we've read the header, the next item in the stream must be the payload. - if (request.value_case() != idb::InstallRequest::ValueCase::kPayload) { - return [[FBIDBError - describeFormat:@"Expected the next item in the stream to be a payload"] - failFuture]; - } - - // The first item in the payload stream may be the compression format, if it's not assume the default. - FBCompressionFormat compression = FBCompressionFormatGZIP; - idb::Payload payload = request.payload(); - if (payload.source_case() == idb::Payload::kCompression) { - compression = read_compression_format(payload.compression()); - stream->Read(&request); - payload = request.payload(); - } - - switch (payload.source_case()) { - case idb::Payload::kData: { - FBProcessInput *dataStream = pipe_to_input_output(payload, stream); - switch (destination) { - case idb::InstallRequest_Destination::InstallRequest_Destination_APP: - return [_commandExecutor install_app_stream:dataStream compression:compression make_debuggable:makeDebuggable]; - case idb::InstallRequest_Destination::InstallRequest_Destination_XCTEST: - return [_commandExecutor install_xctest_app_stream:dataStream]; - case idb::InstallRequest_Destination::InstallRequest_Destination_DSYM: - return [_commandExecutor install_dsym_stream:dataStream linkToApp:bundleID]; - case idb::InstallRequest_Destination::InstallRequest_Destination_DYLIB: - return [_commandExecutor install_dylib_stream:dataStream name:name]; - case idb::InstallRequest_Destination::InstallRequest_Destination_FRAMEWORK: - return [_commandExecutor install_framework_stream:dataStream]; - default: - return nil; - } - } - case idb::Payload::kUrl: { - NSURL *url = [NSURL URLWithString:[NSString stringWithCString:payload.url().c_str() encoding:NSUTF8StringEncoding]]; - FBDataDownloadInput *download = [FBDataDownloadInput dataDownloadWithURL:url logger:_target.logger]; - switch (destination) { - case idb::InstallRequest_Destination::InstallRequest_Destination_APP: - return [_commandExecutor install_app_stream:download.input compression:compression make_debuggable:makeDebuggable]; - case idb::InstallRequest_Destination::InstallRequest_Destination_XCTEST: - return [_commandExecutor install_xctest_app_stream:download.input]; - case idb::InstallRequest_Destination::InstallRequest_Destination_DSYM: - return [_commandExecutor install_dsym_stream:download.input linkToApp:bundleID]; - case idb::InstallRequest_Destination::InstallRequest_Destination_DYLIB: - return [_commandExecutor install_dylib_stream:download.input name:name]; - case idb::InstallRequest_Destination::InstallRequest_Destination_FRAMEWORK: - return [_commandExecutor install_framework_stream:download.input]; - default: - return nil; - } - } - case idb::Payload::kFilePath: { - NSString *filePath = nsstring_from_c_string(payload.file_path()); - switch (destination) { - case idb::InstallRequest_Destination::InstallRequest_Destination_APP: - return [_commandExecutor install_app_file_path:filePath make_debuggable:makeDebuggable]; - case idb::InstallRequest_Destination::InstallRequest_Destination_XCTEST: - return [_commandExecutor install_xctest_app_file_path:filePath]; - case idb::InstallRequest_Destination::InstallRequest_Destination_DSYM: - return [_commandExecutor install_dsym_file_path:filePath linkToApp:bundleID]; - case idb::InstallRequest_Destination::InstallRequest_Destination_DYLIB: - return [_commandExecutor install_dylib_file_path:filePath]; - case idb::InstallRequest_Destination::InstallRequest_Destination_FRAMEWORK: - return [_commandExecutor install_framework_file_path:filePath]; - default: - return nil; - } - } - default: - return nil; - } -}} - -Status FBIDBServiceHandler::list_apps(ServerContext *context, const idb::ListAppsRequest *request, idb::ListAppsResponse *response) -{@autoreleasepool{ - NSError *error = nil; - NSSet *persistedBundleIDs = _commandExecutor.storageManager.application.persistedBundleIDs; - BOOL fetchAppProcessState = request->suppress_process_state() == false; - NSDictionary *apps = [[_commandExecutor list_apps:fetchAppProcessState] block:&error]; - for (FBInstalledApplication *app in apps.allKeys) { - idb::InstalledAppInfo *appInfo = response->add_apps(); - appInfo->set_bundle_id(app.bundle.identifier.UTF8String ?: ""); - appInfo->set_name(app.bundle.name.UTF8String ?: ""); - appInfo->set_install_type([FBInstalledApplication stringFromApplicationInstallType:app.installType].UTF8String); - for (NSString *architecture in app.bundle.binary.architectures) { - appInfo->add_architectures(architecture.UTF8String); - } - id processState = apps[app]; - if ([processState isKindOfClass:NSNumber.class]) { - appInfo->set_process_state(idb::InstalledAppInfo_AppProcessState_RUNNING); - appInfo->set_process_identifier([processState unsignedIntegerValue]); - } else { - appInfo->set_process_state(idb::InstalledAppInfo_AppProcessState_UNKNOWN); - } - appInfo->set_debuggable(app.installType == FBApplicationInstallTypeUserDevelopment && [persistedBundleIDs containsObject:app.bundle.identifier]); - } - if (error) { - return Status(grpc::StatusCode::INTERNAL, error.localizedDescription.UTF8String); - } - return Status::OK; -}} - -Status FBIDBServiceHandler::open_url(ServerContext *context, const idb::OpenUrlRequest *request, idb::OpenUrlRequest *response) -{@autoreleasepool{ - NSError *error = nil; - [[_commandExecutor open_url:nsstring_from_c_string(request->url())] block:&error]; - if (error) { - return Status(grpc::StatusCode::INTERNAL, [error.localizedDescription UTF8String]); - } - return Status::OK; -}} - -Status FBIDBServiceHandler::install(ServerContext *context, grpc::ServerReaderWriter *stream) -{@autoreleasepool{ - idb::InstallRequest request; - stream->Read(&request); - idb::InstallRequest_Destination destination = request.destination(); - - NSError *error = nil; - FBInstalledArtifact *artifact = [install_future(destination, stream) block:&error]; - if (!artifact) { - return Status(grpc::StatusCode::INTERNAL, error.localizedDescription.UTF8String ?: "An internal error occured when installing"); - } - idb::InstallResponse response; - response.set_name(artifact.name.UTF8String); - response.set_uuid(artifact.uuid.UUIDString.UTF8String ?: ""); - stream->Write(response); - return Status::OK; -}} - -Status FBIDBServiceHandler::screenshot(ServerContext *context, const idb::ScreenshotRequest *request, idb::ScreenshotResponse *response) -{@autoreleasepool{ - NSError *error = nil; - NSData *screenshot = [[_commandExecutor take_screenshot:FBScreenshotFormatPNG] block:&error]; - if (error) { - return Status(grpc::StatusCode::INTERNAL, error.localizedDescription.UTF8String); - } - response->set_image_data(screenshot.bytes, screenshot.length); - return Status::OK; -}} - -Status FBIDBServiceHandler::focus(ServerContext *context, const idb::FocusRequest *request, idb::FocusResponse *response) -{@autoreleasepool{ - NSError *error = nil; - [[_commandExecutor focus] block:&error]; - if (error) { - return Status(grpc::StatusCode::INTERNAL, [error.localizedDescription UTF8String]); - } - return Status::OK; -}} - -Status FBIDBServiceHandler::accessibility_info(ServerContext *context, const idb::AccessibilityInfoRequest *request, idb::AccessibilityInfoResponse *response) -{@autoreleasepool{ - NSError *error = nil; - NSValue *point = nil; - if (request->has_point()) { - point = [NSValue valueWithPoint:CGPointMake(request->point().x(), request->point().y())]; - } - BOOL nestedFormat = request->format() == idb::AccessibilityInfoRequest_Format::AccessibilityInfoRequest_Format_NESTED; - NSArray *> *info = [[_commandExecutor accessibility_info_at_point:point nestedFormat:nestedFormat] block:&error]; - - if (!info) { - return Status(grpc::StatusCode::INTERNAL, [error.localizedDescription UTF8String]); - } - - NSData *data = [NSJSONSerialization dataWithJSONObject:info options:0 error:&error]; - if (!data) { - return Status(grpc::StatusCode::INTERNAL, [error.localizedDescription UTF8String]); - } - - NSString *json = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; - response->set_json([json UTF8String]); - return Status::OK; -}} - -Status FBIDBServiceHandler::uninstall(ServerContext *context, const idb::UninstallRequest *request, idb::UninstallResponse *response) -{@autoreleasepool{ - NSError *error = nil; - [[_commandExecutor uninstall_application:nsstring_from_c_string(request->bundle_id())] block:&error]; - if (error) { - return Status(grpc::StatusCode::INTERNAL, [error.localizedDescription UTF8String]); - } - return Status::OK; -}} - -Status FBIDBServiceHandler::mkdir(grpc::ServerContext *context, const idb::MkdirRequest *request, idb::MkdirResponse *response) -{@autoreleasepool{ - NSError *error = nil; - [[_commandExecutor create_directory:nsstring_from_c_string(request->path()) containerType:file_container(request->container())] block:&error]; - if (error) { - return Status(grpc::StatusCode::INTERNAL, error.localizedDescription.UTF8String); - } - return Status::OK; -}} - -Status FBIDBServiceHandler::mv(grpc::ServerContext *context, const idb::MvRequest *request, idb::MvResponse *response) -{@autoreleasepool{ - NSError *error = nil; - NSMutableArray *originalPaths = NSMutableArray.array; - for (int j = 0; j < request->src_paths_size(); j++) { - [originalPaths addObject:nsstring_from_c_string(request->src_paths(j))]; - } - [[_commandExecutor move_paths:originalPaths to_path:nsstring_from_c_string(request->dst_path()) containerType:file_container(request->container())] block:&error]; - if (error) { - return Status(grpc::StatusCode::INTERNAL, error.localizedDescription.UTF8String); - } - return Status::OK; -}} - -Status FBIDBServiceHandler::rm(grpc::ServerContext *context, const idb::RmRequest *request, idb::RmResponse *response) -{@autoreleasepool{ - NSError *error = nil; - NSMutableArray *paths = NSMutableArray.array; - for (int j = 0; j < request->paths_size(); j++) { - [paths addObject:nsstring_from_c_string(request->paths(j))]; - } - [[_commandExecutor remove_paths:paths containerType:file_container(request->container())] block:&error]; - if (error) { - return Status(grpc::StatusCode::INTERNAL, error.localizedDescription.UTF8String); - } - return Status::OK; -}} - -Status FBIDBServiceHandler::ls(grpc::ServerContext *context, const idb::LsRequest *request, idb::LsResponse *response) -{@autoreleasepool{ - NSError *error = nil; - if (request->paths_size() > 0) { - NSArray *inputPaths = extract_string_array(request->paths()); - NSDictionary *> *pathsToPaths = [[_commandExecutor list_paths:inputPaths containerType:file_container(request->container())] block:&error]; - if (error) { - return Status(grpc::StatusCode::INTERNAL, error.localizedDescription.UTF8String); - } - - for (NSString *containerPath in pathsToPaths.allKeys) { - NSArray *paths = pathsToPaths[containerPath]; - idb::FileListing *listing = response->add_listings(); - idb::FileInfo *parent = listing->mutable_parent(); - parent->set_path(containerPath.UTF8String); - for (NSString *path in paths) { - idb::FileInfo *info = listing->add_files(); - info->set_path(path.UTF8String); - } - } - } else { - // Back-compat with single paths - NSArray *paths = [[_commandExecutor list_path:nsstring_from_c_string(request->path()) containerType:file_container(request->container())] block:&error]; - if (error) { - return Status(grpc::StatusCode::INTERNAL, error.localizedDescription.UTF8String); - } - - for (NSString *path in paths) { - idb::FileInfo *info = response->add_files(); - info->set_path(path.UTF8String); - } - } - - return Status::OK; -}} - -Status FBIDBServiceHandler::approve(ServerContext *context, const idb::ApproveRequest *request, idb::ApproveResponse *response) -{@autoreleasepool{ - NSError *error = nil; - NSDictionary *mapping = @{ - @((int)idb::ApproveRequest_Permission::ApproveRequest_Permission_PHOTOS): FBSettingsApprovalServicePhotos, - @((int)idb::ApproveRequest_Permission::ApproveRequest_Permission_CAMERA): FBSettingsApprovalServiceCamera, - @((int)idb::ApproveRequest_Permission::ApproveRequest_Permission_CONTACTS): FBSettingsApprovalServiceContacts, - @((int)idb::ApproveRequest_Permission::ApproveRequest_Permission_URL): FBSettingsApprovalServiceUrl, - @((int)idb::ApproveRequest_Permission::ApproveRequest_Permission_LOCATION): FBSettingsApprovalServiceLocation, - @((int)idb::ApproveRequest_Permission::ApproveRequest_Permission_NOTIFICATION): FBSettingsApprovalServiceNotification, - }; - NSMutableSet *services = NSMutableSet.set; - for (int j = 0; j < request->permissions_size(); j++) { - idb::ApproveRequest_Permission permission = request->permissions(j); - [services addObject:mapping[@(permission)]]; - } - if ([services containsObject:FBSettingsApprovalServiceUrl]) { - [services removeObject:FBSettingsApprovalServiceUrl]; - [[_commandExecutor approve_deeplink:nsstring_from_c_string(request->scheme()) - for_application:nsstring_from_c_string(request->bundle_id())] block:&error]; - } - if ([services count] > 0 && !error) { - [[_commandExecutor approve:services for_application:nsstring_from_c_string(request->bundle_id())] block:&error]; - } - if (error) { - return Status(grpc::StatusCode::INTERNAL, error.localizedDescription.UTF8String); - } - return Status::OK; -}} - -Status FBIDBServiceHandler::clear_keychain(ServerContext *context, const idb::ClearKeychainRequest *request, idb::ClearKeychainResponse *response) -{@autoreleasepool{ - NSError *error = nil; - [[_commandExecutor clear_keychain] block:&error]; - if (error) { - return Status(grpc::StatusCode::INTERNAL, [error.localizedDescription UTF8String]); - } - return Status::OK; -}} - -Status FBIDBServiceHandler::terminate(ServerContext *context, const idb::TerminateRequest *request, idb::TerminateResponse *response) -{@autoreleasepool{ - NSError *error = nil; - [[_commandExecutor kill_application:nsstring_from_c_string(request->bundle_id())] block:&error]; - if (error) { - return Status(grpc::StatusCode::INTERNAL, error.localizedDescription.UTF8String); - } - return Status::OK; -}} - -Status FBIDBServiceHandler::hid(grpc::ServerContext *context, grpc::ServerReader *reader, idb::HIDResponse *response) -{@autoreleasepool{ - NSError *error = nil; - idb::HIDEvent grpcEvent; - while (reader->Read(&grpcEvent)) { - FBSimulatorHIDEvent *event = translate_event(grpcEvent, &error); - if (error) { - return Status(grpc::StatusCode::INTERNAL, error.localizedDescription.UTF8String); - } - [[_commandExecutor hid:event] block:&error]; - if (error) { - return Status(grpc::StatusCode::INTERNAL, error.localizedDescription.UTF8String); - } - } - return Status::OK; -}} - -Status FBIDBServiceHandler::set_location(ServerContext *context, const idb::SetLocationRequest *request, idb::SetLocationResponse *response) -{@autoreleasepool{ - NSError *error = nil; - [[_commandExecutor set_location:request->location().latitude() longitude:request->location().longitude()] block:&error]; - if (error) { - return Status(grpc::StatusCode::INTERNAL, [error.localizedDescription UTF8String]); - } - return Status::OK; -}} - -Status FBIDBServiceHandler::setting(ServerContext* context, const idb::SettingRequest* request, idb::SettingResponse* response) -{@autoreleasepool{ - switch (request->setting_case()) { - case idb::SettingRequest::SettingCase::kHardwareKeyboard: { - NSError *error = nil; - NSNull *result = [[_commandExecutor set_hardware_keyboard_enabled:request->hardwarekeyboard().enabled()] await:&error]; - if (!result) { - return Status(grpc::StatusCode::INTERNAL, error.localizedDescription.UTF8String); - } - return Status::OK; - } - case idb::SettingRequest::SettingCase::kStringSetting: { - idb::SettingRequest::StringSetting stringSetting = request->stringsetting(); - switch (stringSetting.setting()) { - case idb::Setting::LOCALE: { - NSError *error = nil; - NSNull *result = [[_commandExecutor set_locale_with_identifier:nsstring_from_c_string(stringSetting.value().c_str())] await:&error]; - if (!result) { - return Status(grpc::StatusCode::INTERNAL, error.localizedDescription.UTF8String); - } - return Status::OK; - } - case idb::Setting::ANY: { - NSError *error = nil; - NSString *name = nsstring_from_c_string(stringSetting.name().c_str()); - NSString *value = nsstring_from_c_string(stringSetting.value().c_str()); - NSString *domain = nil; - if (stringSetting.domain().length() > 0) { - domain = nsstring_from_c_string(stringSetting.domain().c_str()); - } - NSNull *result = [[_commandExecutor set_preference:name value:value domain:domain] await:&error]; - if (!result) { - return Status(grpc::StatusCode::INTERNAL, error.localizedDescription.UTF8String); - } - return Status::OK; - } - default: - return Status(grpc::StatusCode::INTERNAL, "Unknown setting case"); - } - } - default: - return Status(grpc::StatusCode::INTERNAL, "Unknown setting case"); - } -}} - -Status FBIDBServiceHandler::get_setting(ServerContext* context, const idb::GetSettingRequest* request, idb::GetSettingResponse* response) -{@autoreleasepool{ - switch (request->setting()) { - case idb::Setting::LOCALE: { - NSError *error = nil; - NSString *localeIdentifier = [[_commandExecutor get_current_locale_identifier] await:&error]; - if (error) { - return Status(grpc::StatusCode::INTERNAL, error.localizedDescription.UTF8String); - } - response->set_value(localeIdentifier.UTF8String); - return Status::OK; - } - case idb::Setting::ANY: { - NSError *error = nil; - NSString *name = nsstring_from_c_string(request->name().c_str()); - NSString *domain = nil; - if (request->domain().length() > 0) { - domain = nsstring_from_c_string(request->domain().c_str()); - } - NSString *value = [[_commandExecutor get_preference:name domain:domain] await:&error]; - if (error) { - return Status(grpc::StatusCode::INTERNAL, error.localizedDescription.UTF8String); - } - response->set_value(value.UTF8String); - return Status::OK; - } - default: - return Status(grpc::StatusCode::INTERNAL, "Unknown setting case"); - } -}} - -Status FBIDBServiceHandler::list_settings(ServerContext* context, const idb::ListSettingRequest* request, idb::ListSettingResponse* response) -{@autoreleasepool{ - switch (request->setting()) { - case idb::Setting::LOCALE: { - NSArray *localeIdentifiers = _commandExecutor.list_locale_identifiers; - auto values = response->mutable_values(); - for (NSString *localeIdentifier in localeIdentifiers) { - values->Add(localeIdentifier.UTF8String); - } - return Status::OK; - } - default: - return Status(grpc::StatusCode::INTERNAL, "Unknown setting case"); - } -}} - -Status FBIDBServiceHandler::contacts_update(ServerContext *context, const idb::ContactsUpdateRequest *request, idb::ContactsUpdateResponse *response) -{@autoreleasepool{ - NSError *error = nil; - std::string data = request->payload().data(); - [[_commandExecutor update_contacts:[NSData dataWithBytes:data.c_str() length:data.length()]] block:&error]; - if (error) { - return Status(grpc::StatusCode::INTERNAL, [error.localizedDescription UTF8String]); - } - return Status::OK; -}} - -Status FBIDBServiceHandler::launch(grpc::ServerContext *context, grpc::ServerReaderWriter *stream) -{@autoreleasepool{ - idb::LaunchRequest request; - stream->Read(&request); - idb::LaunchRequest_Start start = request.start(); - NSError *error = nil; - FBProcessOutput *stdOut = FBProcessOutput.outputForNullDevice; - FBProcessOutput *stdErr = FBProcessOutput.outputForNullDevice; - NSMutableArray *completions = NSMutableArray.array; - if (start.wait_for()) { - dispatch_queue_t writeQueue = dispatch_queue_create("com.facebook.idb.launch.write", DISPATCH_QUEUE_SERIAL); - id consumer = pipe_output(idb::ProcessOutput_Interface_STDOUT, writeQueue, stream); - [completions addObject:consumer.finishedConsuming]; - stdOut = [FBProcessOutput outputForDataConsumer:consumer]; - consumer = pipe_output(idb::ProcessOutput_Interface_STDERR, writeQueue, stream); - [completions addObject:consumer.finishedConsuming]; - stdErr = [FBProcessOutput outputForDataConsumer:consumer]; - } - FBProcessIO *io = [[FBProcessIO alloc] - initWithStdIn:nil - stdOut:stdOut - stdErr:stdErr]; - FBApplicationLaunchConfiguration *configuration = [[FBApplicationLaunchConfiguration alloc] - initWithBundleID:nsstring_from_c_string(start.bundle_id()) - bundleName:nil - arguments:extract_string_array(start.app_args()) - environment:extract_str_dict(start.env()) - waitForDebugger:(start.wait_for_debugger() ? YES : NO) - io:io - launchMode:start.foreground_if_running() ? FBApplicationLaunchModeForegroundIfRunning : FBApplicationLaunchModeFailIfRunning]; - id launchedApp = [[_commandExecutor launch_app:configuration] block:&error]; - if (!launchedApp) { - if (error.code != 0) { - return Status(grpc::StatusCode::INTERNAL, error.localizedDescription.UTF8String); - } else { - return Status(grpc::StatusCode::FAILED_PRECONDITION, error.localizedDescription.UTF8String); - } - } - // Respond with the pid of the launched process - idb::LaunchResponse response; - idb::DebuggerInfo *debugger_info = response.mutable_debugger(); - debugger_info->set_pid(launchedApp.processIdentifier); - stream->Write(response); - // Return early if not waiting for output - if (!start.wait_for()) { - return Status::OK; - } - // Otherwise wait for the client to hang up. - stream->Read(&request); - [[launchedApp.applicationTerminated cancel] block:nil]; - [[FBFuture futureWithFutures:completions] block:nil]; - return Status::OK; -}} - -Status FBIDBServiceHandler::crash_list(ServerContext *context, const idb::CrashLogQuery *request, idb::CrashLogResponse *response) -{@autoreleasepool{ - NSError *error = nil; - NSPredicate *predicate = nspredicate_from_crash_log_query(request); - NSArray *crashes = [[_commandExecutor crash_list:predicate] block:&error]; - if (error) { - return Status(grpc::StatusCode::INTERNAL, error.localizedDescription.UTF8String); - } - fill_crash_log_response(response, crashes); - return Status::OK; -}} - -Status FBIDBServiceHandler::crash_show(ServerContext *context, const idb::CrashShowRequest *request, idb::CrashShowResponse *response) -{@autoreleasepool{ - NSError *error = nil; - NSString *name = nsstring_from_c_string(request->name()); - if (!name){ - return Status(grpc::StatusCode::INTERNAL, @"Missing crash name".UTF8String); - } - NSPredicate *predicate = [FBCrashLogInfo predicateForName:name]; - FBCrashLog *crash = [[_commandExecutor crash_show:predicate] block:&error]; - if (error) { - return Status(grpc::StatusCode::INTERNAL, error.localizedDescription.UTF8String); - } - idb::CrashLogInfo *info = response->mutable_info(); - fill_crash_log_info(info, crash.info); - response->set_contents(crash.contents.UTF8String); - return Status::OK; -}} - -Status FBIDBServiceHandler::crash_delete(ServerContext *context, const idb::CrashLogQuery *request, idb::CrashLogResponse *response) -{@autoreleasepool{ - NSError *error = nil; - NSPredicate *predicate = nspredicate_from_crash_log_query(request); - NSArray *crashes = [[_commandExecutor crash_delete:predicate] block:&error]; - if (error) { - return Status(grpc::StatusCode::INTERNAL, error.localizedDescription.UTF8String); - } - fill_crash_log_response(response, crashes); - return Status::OK; -}} - -Status FBIDBServiceHandler::xctest_list_bundles(ServerContext *context, const idb::XctestListBundlesRequest *request, idb::XctestListBundlesResponse *response) -{@autoreleasepool{ - NSError *error = nil; - NSSet> *descriptors = [[_commandExecutor list_test_bundles] block:&error]; - if (!descriptors) { - return Status(grpc::StatusCode::INTERNAL, error.localizedDescription.UTF8String); - } - for (id descriptor in descriptors) { - idb::XctestListBundlesResponse_Bundles *bundle = response->add_bundles(); - bundle->set_name(descriptor.name.UTF8String ?: ""); - bundle->set_bundle_id(descriptor.testBundleID.UTF8String ?: ""); - for (NSString *architecture in descriptor.architectures) { - bundle->add_architectures(architecture.UTF8String); - } - } - return Status::OK; -}} - -Status FBIDBServiceHandler::xctest_list_tests(ServerContext *context, const idb::XctestListTestsRequest *request, idb::XctestListTestsResponse *response) -{@autoreleasepool{ - NSError *error = nil; - NSArray *tests = [[_commandExecutor list_tests_in_bundle:nsstring_from_c_string(request->bundle_name()) with_app:nsstring_from_c_string(request->app_path())] block:&error]; - if (!tests) { - return Status(grpc::StatusCode::INTERNAL, error.localizedDescription.UTF8String); - } - for (NSString *test in tests) { - response->add_names(test.UTF8String); - } - return Status::OK; -}} - -Status FBIDBServiceHandler::xctest_run(ServerContext *context, const idb::XctestRunRequest *request, grpc::ServerWriter *response) -{@autoreleasepool{ - FBXCTestRunRequest *xctestRunRequest = convert_xctest_request(request); - if (xctestRunRequest == nil) { - return Status(grpc::StatusCode::INTERNAL, "Failed to convert xctest request"); - } - // Once the reporter is created, only it will perform writing to the writer. - NSError *error = nil; - FBIDBXCTestReporter *reporter = [[FBIDBXCTestReporter alloc] initWithResponseWriter:response queue:_target.workQueue logger:_target.logger]; - FBIDBTestOperation *operation = [[_commandExecutor xctest_run:xctestRunRequest reporter:reporter logger:[FBControlCoreLogger loggerToConsumer:reporter]] block:&error]; - if (!operation) { - return Status(grpc::StatusCode::INTERNAL, error.localizedDescription.UTF8String); - } - reporter.configuration = operation.reporterConfiguration; - - // First wait for the test operation to finish - [operation.completed block:&error]; - // Then make sure we've reported everything, otherwise we could write in the background (use-after-free) - [reporter.reportingTerminated block:&error]; - return Status::OK; -}} - -Status FBIDBServiceHandler::log(ServerContext *context, const idb::LogRequest *request, grpc::ServerWriter *response) -{@autoreleasepool{ - // In the background, write out the log data. Prevent future writes if the client write fails. - // This will happen asynchronously with the server thread. - FBMutableFuture *writingDone = FBMutableFuture.future; - id consumer = [FBBlockDataConsumer synchronousDataConsumerWithBlock:^(NSData *data) { - idb::LogResponse item; - item.set_output(data.bytes, data.length); - if (writingDone.hasCompleted) { - return; - } - bool success = response->Write(item); - if (success) { - return; - } - // The client write failed, the client has gone so don't write again. - [writingDone resolveWithResult:NSNull.null]; - }]; - - // Setup the log operation. - NSError *error = nil; - BOOL logFromCompanion = request->source() == idb::LogRequest::Source::LogRequest_Source_COMPANION; - NSArray *arguments = extract_string_array(request->arguments()); - id operation = [(logFromCompanion ? [_commandExecutor tail_companion_logs:consumer] : [_target tailLog:arguments consumer:consumer]) block:&error]; - if (!operation) { - return Status(grpc::StatusCode::INTERNAL, error.localizedDescription.UTF8String); - } - - // Poll on completion (logging happens asynchronously). This occurs when the stream is cancelled, the log operation is done, or the last write failed. - FBFuture *completed = [FBFuture race:@[writingDone, operation.completed]]; - while (completed.hasCompleted == NO && context->IsCancelled() == false) { - // Sleep for 200ms before polling again. - usleep(1000 * 200); - } - - // Signal that we're done writing due to the operation completion or the client going away. - // This will also prevent the polling of the ClientContext. - [writingDone resolveWithResult:NSNull.null]; - - // Teardown the log operation now that we're done with it - FBFuture *teardown = [operation.completed cancel]; - [teardown block:nil]; - - return Status::OK; -}} - -Status FBIDBServiceHandler::record(grpc::ServerContext *context, grpc::ServerReaderWriter *stream) -{@autoreleasepool{ - idb::RecordRequest initial; - stream->Read(&initial); - NSError *error = nil; - const std::string requestedFilePath = initial.start().file_path(); - NSString *filePath = requestedFilePath.length() > 0 ? nsstring_from_c_string(requestedFilePath.c_str()) : [[_target.auxillaryDirectory stringByAppendingPathComponent:@"idb_encode"] stringByAppendingPathExtension:@"mp4"]; - id operation = [[_target startRecordingToFile:filePath] block:&error]; - if (!operation) { - return Status(grpc::StatusCode::INTERNAL, error.localizedDescription.UTF8String); - } - idb::RecordRequest stop; - stream->Read(&stop); - if (![[_target stopRecording] succeeds:&error]) { - return Status(grpc::StatusCode::INTERNAL, error.localizedDescription.UTF8String); - } - if (requestedFilePath.length() > 0) { - return respond_file_path(nil, filePath, stream); - } else { - return drain_writer([FBArchiveOperations createGzipForPath:filePath queue:dispatch_queue_create("com.facebook.idb.record", DISPATCH_QUEUE_SERIAL) logger:_target.logger], stream); - } -}} - -Status FBIDBServiceHandler::video_stream(ServerContext* context, grpc::ServerReaderWriter* stream) -{@autoreleasepool{ - NSError *error = nil; - idb::VideoStreamRequest request; - FBMutableFuture *done = FBMutableFuture.future; - id consumer = consumer_from_request(stream, request, done, &error); - if (!consumer) { - return Status(grpc::StatusCode::INTERNAL, error.localizedDescription.UTF8String); - } - idb::VideoStreamRequest_Start start = request.start(); - NSNumber *framesPerSecond = start.fps() > 0 ? @(start.fps()) : nil; - FBVideoStreamEncoding encoding = @""; - switch (start.format()) { - case idb::VideoStreamRequest_Format_RBGA: - encoding = FBVideoStreamEncodingBGRA; - break; - case idb::VideoStreamRequest_Format_H264: - encoding = FBVideoStreamEncodingH264; - break; - case idb::VideoStreamRequest_Format_MJPEG: - encoding = FBVideoStreamEncodingMJPEG; - break; - case idb::VideoStreamRequest_Format_MINICAP: - encoding = FBVideoStreamEncodingMinicap; - break; - default: - return Status(grpc::StatusCode::INTERNAL, "Invalid Video format provided"); - } - NSNumber *compressionQuality = @(start.compression_quality()); - NSNumber *scaleFactor = @(start.scale_factor()); - FBVideoStreamConfiguration *configuration = [[FBVideoStreamConfiguration alloc] initWithEncoding:encoding framesPerSecond:framesPerSecond compressionQuality:compressionQuality scaleFactor:scaleFactor]; - id videoStream = [[_target createStreamWithConfiguration:configuration] block:&error]; - if (!stream) { - return Status(grpc::StatusCode::INTERNAL, error.localizedDescription.UTF8String); - } - BOOL success = [[videoStream startStreaming:consumer] block:&error] != nil; - if (success == NO) { - return Status(grpc::StatusCode::INTERNAL, error.localizedDescription.UTF8String); - } - - // Wait for the client to hangup or stream to stop - FBFuture *clientStopped = resolve_next_read(stream); - [[FBFuture race:@[clientStopped, videoStream.completed]] block:nil]; - - // Signal that we're done so we don't write to a dangling pointer. - [done resolveWithResult:NSNull.null]; - // Stop the streaming for real. It may have stopped already in which case this returns instantly. - success = [[videoStream stopStreaming] block:&error] != nil; - [_target.logger logFormat:@"The video stream is terminated"]; - if (success == NO) { - return Status(grpc::StatusCode::INTERNAL, error.localizedDescription.UTF8String); - } - return Status::OK; -}} - -Status FBIDBServiceHandler::push(grpc::ServerContext *context, grpc::ServerReader *reader, idb::PushResponse *response) -{@autoreleasepool{ - NSError *error = nil; - idb::PushRequest request; - reader->Read(&request); - if (request.value_case() != idb::PushRequest::kInner) { - return Status(grpc::StatusCode::INTERNAL, "First message must contain the commands information"); - } - const idb::PushRequest_Inner inner = request.inner(); - - [[filepaths_from_reader(_commandExecutor.temporaryDirectory, reader, false, _target.logger) onQueue:_target.asyncQueue pop:^FBFuture *(NSArray *files) { - return [_commandExecutor push_files:files to_path:nsstring_from_c_string(inner.dst_path()) containerType:file_container(inner.container())]; - }] block:&error]; - if (error) { - return Status(grpc::StatusCode::INTERNAL, error.localizedDescription.UTF8String); - } - return Status::OK; -}} - -Status FBIDBServiceHandler::pull(ServerContext *context, const ::idb::PullRequest *request, grpc::ServerWriter<::idb::PullResponse> *stream) -{@autoreleasepool{ - NSString *path = nsstring_from_c_string(request->src_path()); - NSError *error = nil; - if (request->dst_path().length() > 0) { - NSString *filePath = [[_commandExecutor pull_file_path:path destination_path:nsstring_from_c_string(request->dst_path()) containerType:file_container(request->container())] block:&error]; - if (error) { - return Status(grpc::StatusCode::INTERNAL, error.localizedDescription.UTF8String); - } - return respond_file_path(nil, filePath, stream); - } else { - NSURL *url = [_commandExecutor.temporaryDirectory temporaryDirectory]; - NSString *tempPath = [url.path stringByAppendingPathComponent:path.lastPathComponent]; - NSString *filePath = [[_commandExecutor pull_file_path:path destination_path:tempPath containerType:file_container(request->container())] block:&error]; - if (error) { - return Status(grpc::StatusCode::INTERNAL, error.localizedDescription.UTF8String); - } - return drain_writer([FBArchiveOperations - createGzippedTarForPath:filePath - queue:dispatch_queue_create("com.facebook.idb.pull", DISPATCH_QUEUE_SERIAL) - logger:_target.logger], - stream); - } -}} - -Status FBIDBServiceHandler::tail(ServerContext* context, grpc::ServerReaderWriter* stream) -{@autoreleasepool{ - idb::TailRequest request; - stream->Read(&request); - idb::TailRequest_Start start = request.start(); - NSString *path = nsstring_from_c_string(start.path()); - NSString *container = file_container(start.container()); - - FBMutableFuture *finished = FBMutableFuture.future; - id consumer = [FBBlockDataConsumer synchronousDataConsumerWithBlock:^(NSData *data) { - if (finished.hasCompleted) { - return; - } - idb::TailResponse response; - response.set_data(data.bytes, data.length); - stream->Write(response); - }]; - - NSError *error = nil; - FBFuture *tailOperation = [[_commandExecutor tail:path to_consumer:consumer in_container:container] block:&error]; - if (!tailOperation) { - return Status(grpc::StatusCode::INTERNAL, error.localizedDescription.UTF8String); - } - - stream->Read(&request); - [[tailOperation cancel] block:nil]; - [finished resolveWithResult:NSNull.null]; - - return Status::OK; -}} - -Status FBIDBServiceHandler::describe(ServerContext *context, const idb::TargetDescriptionRequest *request, idb::TargetDescriptionResponse *response) -{@autoreleasepool{ - // Populate the default values - idb::TargetDescription *description = response->mutable_target_description(); - FBiOSTargetScreenInfo *screenInfo = _target.screenInfo; - if (screenInfo) { - idb::ScreenDimensions *dimensions = description->mutable_screen_dimensions(); - dimensions->set_width(screenInfo.widthPixels); - dimensions->set_height(screenInfo.heightPixels); - dimensions->set_height_points(screenInfo.heightPixels/screenInfo.scale); - dimensions->set_width_points(screenInfo.widthPixels/screenInfo.scale); - dimensions->set_density(screenInfo.scale); - } - description->set_udid(_target.udid.UTF8String); - description->set_name(_target.name.UTF8String); - description->set_state(FBiOSTargetStateStringFromState(_target.state).UTF8String); - description->set_target_type(FBiOSTargetTypeStringsFromTargetType(_target.targetType).firstObject.lowercaseString.UTF8String); - description->set_os_version(_target.osVersion.name.UTF8String); - description->set_architecture(_target.architecture.UTF8String); - - // Add extended information - NSDictionary *extendedInformation = _target.extendedInformation; - NSError *error = nil; - NSData *data = [NSJSONSerialization dataWithJSONObject:extendedInformation options:0 error:&error]; - if (!data) { - return Status(grpc::StatusCode::INTERNAL, error.localizedDescription.UTF8String); - } - description->set_extended(data.bytes, data.length); - - // Also attach the companion metadata - populate_companion_info(response->mutable_companion(), _eventReporter, _target); - - // Only fetch diagnostic information when requested. - if (!request->fetch_diagnostics()) { - return Status::OK; - } - NSDictionary *diagnosticInformation = [[_commandExecutor diagnostic_information] block:&error]; - if (!diagnosticInformation) { - return Status(grpc::StatusCode::INTERNAL, error.localizedDescription.UTF8String); - } - data = [NSJSONSerialization dataWithJSONObject:diagnosticInformation options:0 error:&error]; - if (!data) { - return Status(grpc::StatusCode::INTERNAL, error.localizedDescription.UTF8String); - } - description->set_diagnostics(data.bytes, data.length); - - return Status::OK; -}} - -Status FBIDBServiceHandler::add_media(grpc::ServerContext *context, grpc::ServerReader *reader, idb::AddMediaResponse *response) -{@autoreleasepool{ - NSError *error = nil; - [[filepaths_from_reader(_commandExecutor.temporaryDirectory, reader, true, _target.logger) - onQueue:_target.asyncQueue pop:^(NSArray *files) { - return [_commandExecutor add_media:files]; - }] - block:&error]; - if (error) { - return Status(grpc::StatusCode::INTERNAL, error.localizedDescription.UTF8String); - } - return Status::OK; -}} - -Status FBIDBServiceHandler::instruments_run(grpc::ServerContext *context, grpc::ServerReaderWriter *stream) -{@autoreleasepool{ - __block idb::InstrumentsRunRequest startRunRequest; - __block pthread_mutex_t mutex; - pthread_mutex_init(&mutex, NULL); - __block bool finished_writing = NO; - dispatch_queue_t queue = dispatch_queue_create("com.facebook.idb.instruments.server", DISPATCH_QUEUE_SERIAL); - dispatch_sync(queue, ^{ - idb::InstrumentsRunRequest request; - stream->Read(&request); - startRunRequest = request; - }); - - FBInstrumentsConfiguration *configuration = translate_instruments_configuration(startRunRequest.start(), _commandExecutor.storageManager); - - NSError *error = nil; - id consumer = [FBBlockDataConsumer asynchronousDataConsumerOnQueue:queue consumer:^(NSData *data) { - idb::InstrumentsRunResponse response; - response.set_log_output(data.bytes, data.length); - pthread_mutex_lock(&mutex); - if (!finished_writing) { - stream->Write(response); - } - pthread_mutex_unlock(&mutex); - - }]; - id logger = [FBControlCoreLogger compositeLoggerWithLoggers:@[ - [FBControlCoreLogger loggerToConsumer:consumer], - _target.logger, - ]]; - FBInstrumentsOperation *operation = [[_target startInstruments:configuration logger:logger] block:&error]; - if (!operation) { - pthread_mutex_lock(&mutex); - finished_writing = YES; - pthread_mutex_unlock(&mutex); - return Status(grpc::StatusCode::INTERNAL, error.localizedDescription.UTF8String); - } - __block idb::InstrumentsRunRequest stopRunRequest; - dispatch_sync(queue, ^{ - idb::InstrumentsRunResponse response; - response.set_state(idb::InstrumentsRunResponse::State::InstrumentsRunResponse_State_RUNNING_INSTRUMENTS); - stream->Write(response); - idb::InstrumentsRunRequest request; - stream->Read(&request); - stopRunRequest = request; - }); - if (![operation.stop succeeds:&error]) { - pthread_mutex_lock(&mutex); - finished_writing = YES; - pthread_mutex_unlock(&mutex); - return Status(grpc::StatusCode::INTERNAL, error.localizedDescription.UTF8String); - } - NSArray *postProcessArguments = [_commandExecutor.storageManager interpolateArgumentReplacements:extract_string_array(stopRunRequest.stop().post_process_arguments())]; - dispatch_sync(queue, ^{ - idb::InstrumentsRunResponse response; - response.set_state(idb::InstrumentsRunResponse::State::InstrumentsRunResponse_State_POST_PROCESSING); - stream->Write(response); - }); - NSURL *processed = [[FBInstrumentsOperation postProcess:postProcessArguments traceDir:operation.traceDir queue:queue logger:logger] block:&error]; - pthread_mutex_lock(&mutex); - finished_writing = YES; - pthread_mutex_unlock(&mutex); - if (!processed) { - return Status(grpc::StatusCode::INTERNAL, error.localizedDescription.UTF8String); - } - return drain_writer([FBArchiveOperations createGzippedTarForPath:processed.path queue:queue logger:_target.logger], stream); -}} - -Status FBIDBServiceHandler::debugserver(grpc::ServerContext *context, grpc::ServerReaderWriter *stream) -{@autoreleasepool{ - idb::DebugServerRequest request; - stream->Read(&request); - - NSError *error = nil; - switch (request.control_case()) { - case idb::DebugServerRequest::ControlCase::kStart: { - idb::DebugServerRequest::Start start = request.start(); - id debugServer = [[_commandExecutor debugserver_start:nsstring_from_c_string(start.bundle_id())] block:&error]; - if (!debugServer) { - return Status(grpc::StatusCode::INTERNAL, error.localizedDescription.UTF8String); - } - stream->Write(translate_debugserver_status(debugServer)); - return Status::OK; - } - case idb::DebugServerRequest::ControlCase::kStatus: { - id debugServer = [[_commandExecutor debugserver_status] block:&error]; - stream->Write(translate_debugserver_status(debugServer)); - return Status::OK; - } - case idb::DebugServerRequest::ControlCase::kStop: { - id debugServer = [[_commandExecutor debugserver_status] block:&error]; - if (!debugServer) { - return Status(grpc::StatusCode::INTERNAL, error.localizedDescription.UTF8String); - } - stream->Write(translate_debugserver_status(debugServer)); - return Status::OK; - } - default: { - return Status(grpc::StatusCode::UNIMPLEMENTED, NULL); - } - } -}} - -Status FBIDBServiceHandler::dap(grpc::ServerContext *context, grpc::ServerReaderWriter *stream) -{@autoreleasepool{ - idb::DapRequest initial_request; - stream->Read(&initial_request); - if (initial_request.control_case() != idb::DapRequest::ControlCase::kStart) { - return Status(grpc::StatusCode::FAILED_PRECONDITION, "Dap command expected a Start messaged in the beginning of the Stream"); - } - idb::DapRequest_Start start = initial_request.start(); - NSString *pkg_id = nsstring_from_c_string(start.debugger_pkg_id()); - NSString *lldb_vscode = [@"dap" stringByAppendingPathComponent:[pkg_id stringByAppendingPathComponent: @"usr/bin/lldb-vscode"]]; - - id reader = [FBBlockDataConsumer synchronousDataConsumerWithBlock:^(NSData *data) { - idb::DapResponse response; - idb::DapResponse_Pipe *stdout = response.mutable_stdout(); - stdout->set_data(data.bytes, data.length); - stream->Write(response); - [_target.logger.debug logFormat:@"Dap server stdout consumer: sent %lu bytes.", data.length]; - }]; - - - [_target.logger.debug logFormat:@"Starting dap server with path %@", lldb_vscode]; - NSError *error = nil; - FBProcessInput> *writer = [FBProcessInput inputFromConsumer]; - FBProcess *process = [[_commandExecutor dapServerWithPath:lldb_vscode stdIn:writer stdOut:reader] awaitWithTimeout:600 error:&error]; - if (error){ - NSString *errorMsg = [NSString stringWithFormat:@"Failed to spaw DAP server. Error: %@", error.localizedDescription]; - return Status(grpc::StatusCode::INTERNAL, errorMsg.UTF8String); - } - [_target.logger.debug logFormat:@"Dap server spawn with PID: %d", process.processIdentifier]; - idb::DapResponse response; - response.mutable_started(); - stream->Write(response); - - dispatch_queue_t write_queue = dispatch_queue_create("com.facebook.idb.dap.write", DISPATCH_QUEUE_SERIAL); - auto writeFuture = [FBFuture onQueue:write_queue resolveWhen:^BOOL { - idb::DapRequest request; - stream->Read(&request); - if (request.control_case() == idb::DapRequest::ControlCase::kStop){ - [_target.logger.debug logFormat:@"Received stop from Dap Request"]; - [_target.logger.debug logFormat:@"Dap server with pid %d. Stderr: %@", process.processIdentifier, process.stdErr]; - return YES; - } - - idb::DapRequest_Pipe pipe = request.pipe(); - auto raw_data = pipe.data(); - NSData *data = [NSData dataWithBytes:raw_data.c_str() length:raw_data.length()]; - if (data.length == 0) { - [_target.logger.debug logFormat:@"Dap Request. Receiving empty messages. Transmission finished."]; - return YES; - } - [_target.logger.debug logFormat:@"Dap Request. Received %lu bytes from client", data.length]; - [writer.contents consumeData:data]; - return NO; - }]; - - // Debug session shouln't be longer than 10hours - [writeFuture awaitWithTimeout:36000 error:&error]; - if (error){ - NSString *errorMsg = [NSString stringWithFormat:@"Error in writting to dap server stdout: %@", error.localizedDescription]; - return Status(grpc::StatusCode::INTERNAL, errorMsg.UTF8String); - } - - idb::DapResponse_Event *stopped = response.mutable_stopped(); - stopped->set_desc(@"Dap server stopped.".UTF8String); - stream->Write(response); - - return Status::OK; -}} - - - - -Status FBIDBServiceHandler::connect(grpc::ServerContext *context, const idb::ConnectRequest *request, idb::ConnectResponse *response) -{@autoreleasepool{ - // Add Meta to Reporter - [_eventReporter addMetadata:extract_str_dict(request->metadata())]; - - // Get the local state - BOOL isLocal = [NSFileManager.defaultManager fileExistsAtPath:nsstring_from_c_string(request->local_file_path())]; - idb::CompanionInfo *info = response->mutable_companion(); - info->set_is_local(isLocal); - - // Populate the other values. - populate_companion_info(info, _eventReporter, _target); - - return Status::OK; -}} - -Status FBIDBServiceHandler::xctrace_record(ServerContext *context,grpc::ServerReaderWriter *stream) -{@autoreleasepool{ - __block idb::XctraceRecordRequest recordRequest; - __block pthread_mutex_t mutex; - pthread_mutex_init(&mutex, NULL); - __block bool finished_writing = NO; - dispatch_queue_t queue = dispatch_queue_create("com.facebook.idb.xctrace.record", DISPATCH_QUEUE_SERIAL); - // @lint-ignore FBOBJCDISCOURAGEDFUNCTION - dispatch_sync(queue, ^{ - idb::XctraceRecordRequest request; - stream->Read(&request); - recordRequest = request; - }); - - FBXCTraceRecordConfiguration *configuration = translate_xctrace_record_configuration(recordRequest.start()); - - NSError *error = nil; - id consumer = [FBBlockDataConsumer asynchronousDataConsumerOnQueue:queue consumer:^(NSData *data) { - idb::XctraceRecordResponse response; - response.set_log(data.bytes, data.length); - pthread_mutex_lock(&mutex); - if (!finished_writing) { - stream->Write(response); - } - pthread_mutex_unlock(&mutex); - }]; - id logger = [FBControlCoreLogger compositeLoggerWithLoggers:@[ - [FBControlCoreLogger loggerToConsumer:consumer], - _target.logger, - ]]; - - FBXCTraceRecordOperation *operation = [[_target startXctraceRecord:configuration logger:logger] block:&error]; - if (!operation) { - pthread_mutex_lock(&mutex); - finished_writing = YES; - pthread_mutex_unlock(&mutex); - return Status(grpc::StatusCode::INTERNAL, error.localizedDescription.UTF8String); - } - // @lint-ignore FBOBJCDISCOURAGEDFUNCTION - dispatch_sync(queue, ^{ - idb::XctraceRecordResponse response; - response.set_state(idb::XctraceRecordResponse::State::XctraceRecordResponse_State_RUNNING); - stream->Write(response); - idb::XctraceRecordRequest request; - stream->Read(&request); - recordRequest = request; - }); - NSTimeInterval stopTimeout = recordRequest.stop().timeout() ?: DefaultXCTraceRecordStopTimeout; - if (![[operation stopWithTimeout:stopTimeout] succeeds:&error]) { - pthread_mutex_lock(&mutex); - finished_writing = YES; - pthread_mutex_unlock(&mutex); - return Status(grpc::StatusCode::INTERNAL, error.localizedDescription.UTF8String); - } - NSArray *postProcessArgs = extract_string_array(recordRequest.stop().args()); - // @lint-ignore FBOBJCDISCOURAGEDFUNCTION - dispatch_sync(queue, ^{ - idb::XctraceRecordResponse response; - response.set_state(idb::XctraceRecordResponse::State::XctraceRecordResponse_State_PROCESSING); - stream->Write(response); - }); - NSURL *processed = [[FBInstrumentsOperation postProcess:postProcessArgs traceDir:operation.traceDir queue:queue logger:logger] block:&error]; - pthread_mutex_lock(&mutex); - finished_writing = YES; - pthread_mutex_unlock(&mutex); - if (!processed) { - return Status(grpc::StatusCode::INTERNAL, error.localizedDescription.UTF8String); - } - return drain_writer([FBArchiveOperations createGzippedTarForPath:processed.path queue:queue logger:_target.logger], stream); -}} - -Status FBIDBServiceHandler::send_notification(grpc::ServerContext *context, const idb::SendNotificationRequest *request, idb::SendNotificationResponse *response) -{@autoreleasepool{ - NSError *error = nil; - [[_commandExecutor sendPushNotificationForBundleID:nsstring_from_c_string(request->bundle_id()) jsonPayload:nsstring_from_c_string(request->json_payload())] block:&error]; - if (error) { - return Status(grpc::StatusCode::INTERNAL, [error.localizedDescription UTF8String]); - } - return Status::OK; -}} - -Status FBIDBServiceHandler::simulate_memory_warning(grpc::ServerContext *context, const idb::SimulateMemoryWarningRequest *request, idb::SimulateMemoryWarningResponse *response) -{@autoreleasepool{ - NSError *error = nil; - [[_commandExecutor simulateMemoryWarning] block:&error]; - if (error) { - return Status(grpc::StatusCode::INTERNAL, [error.localizedDescription UTF8String]); - } - return Status::OK; -}} diff --git a/idb_companion/SwiftServer/CompanionServiceProvider.swift b/idb_companion/SwiftServer/CompanionServiceProvider.swift new file mode 100644 index 000000000..6a0ed6d66 --- /dev/null +++ b/idb_companion/SwiftServer/CompanionServiceProvider.swift @@ -0,0 +1,348 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import CompanionLib +import Foundation +import GRPC +import IDBCompanionUtilities +import IDBGRPCSwift +import NIOHPACK +import SwiftProtobuf +import XCTestBootstrap + +final class CompanionServiceProvider: Idb_CompanionServiceAsyncProvider { + + private let target: FBiOSTarget + private let commandExecutor: FBIDBCommandExecutor + private let reporter: FBEventReporter + private let logger: FBIDBLogger + private let interceptorFactory: Idb_CompanionServiceServerInterceptorFactoryProtocol + + init(target: FBiOSTarget, + commandExecutor: FBIDBCommandExecutor, + reporter: FBEventReporter, + logger: FBIDBLogger, + interceptors: Idb_CompanionServiceServerInterceptorFactoryProtocol) { + self.target = target + self.commandExecutor = commandExecutor + self.reporter = reporter + self.logger = logger + self.interceptorFactory = interceptors + } + + var interceptors: Idb_CompanionServiceServerInterceptorFactoryProtocol? { interceptorFactory } + + private var targetLogger: FBControlCoreLogger { + get throws { + guard let logger = target.logger else { + throw GRPCStatus(code: .internalError, message: "Target logger not configured") + } + return logger + } + } + + func connect(request: Idb_ConnectRequest, context: GRPCAsyncServerCallContext) async throws -> Idb_ConnectResponse { + return try await FBTeardownContext.withAutocleanup { + try await ConnectMethodHandler(reporter: reporter, logger: logger, target: target) + .handle(request: request, context: context) + } + } + + func debugserver(requestStream: GRPCAsyncRequestStream, responseStream: GRPCAsyncResponseStreamWriter, context: GRPCAsyncServerCallContext) async throws { + return try await FBTeardownContext.withAutocleanup { + try await DebugserverMethodHandler(commandExecutor: commandExecutor) + .handle(requestStream: requestStream, responseStream: responseStream, context: context) + } + } + + func dap(requestStream: GRPCAsyncRequestStream, responseStream: GRPCAsyncResponseStreamWriter, context: GRPCAsyncServerCallContext) async throws { + return try await FBTeardownContext.withAutocleanup { + try await DapMethodHandler(commandExecutor: commandExecutor, targetLogger: targetLogger) + .handle(requestStream: requestStream, responseStream: responseStream, context: context) + } + } + + func describe(request: Idb_TargetDescriptionRequest, context: GRPCAsyncServerCallContext) async throws -> Idb_TargetDescriptionResponse { + return try await FBTeardownContext.withAutocleanup { + try await DescribeMethodHandler(reporter: reporter, logger: logger, target: target, commandExecutor: commandExecutor) + .handle(request: request, context: context) + } + } + + func install(requestStream: GRPCAsyncRequestStream, responseStream: GRPCAsyncResponseStreamWriter, context: GRPCAsyncServerCallContext) async throws { + return try await FBTeardownContext.withAutocleanup { + try await InstallMethodHandler(commandExecutor: commandExecutor, targetLogger: targetLogger) + .handle(requestStream: requestStream, responseStream: responseStream, context: context) + } + } + + func instruments_run(requestStream: GRPCAsyncRequestStream, responseStream: GRPCAsyncResponseStreamWriter, context: GRPCAsyncServerCallContext) async throws { + return try await FBTeardownContext.withAutocleanup { + try await InstrumentsRunMethodHandler(target: target, targetLogger: targetLogger, commandExecutor: commandExecutor, logger: logger) + .handle(requestStream: requestStream, responseStream: responseStream, context: context) + } + } + + func log(request: Idb_LogRequest, responseStream: GRPCAsyncResponseStreamWriter, context: GRPCAsyncServerCallContext) async throws { + return try await FBTeardownContext.withAutocleanup { + try await LogMethodHandler(target: target, commandExecutor: commandExecutor) + .handle(request: request, responseStream: responseStream, context: context) + } + } + + func xctrace_record(requestStream: GRPCAsyncRequestStream, responseStream: GRPCAsyncResponseStreamWriter, context: GRPCAsyncServerCallContext) async throws { + return try await FBTeardownContext.withAutocleanup { + try await XctraceRecordMethodHandler(logger: logger, targetLogger: targetLogger, target: target) + .handle(requestStream: requestStream, responseStream: responseStream, context: context) + } + } + + func accessibility_info(request: Idb_AccessibilityInfoRequest, context: GRPCAsyncServerCallContext) async throws -> Idb_AccessibilityInfoResponse { + return try await FBTeardownContext.withAutocleanup { + try await AccessibilityInfoMethodHandler(commandExecutor: commandExecutor) + .handle(request: request, context: context) + } + } + + func focus(request: Idb_FocusRequest, context: GRPCAsyncServerCallContext) async throws -> Idb_FocusResponse { + return try await FBTeardownContext.withAutocleanup { + try await FocusMethodHandler(commandExecutor: commandExecutor) + .handle(request: request, context: context) + } + } + + func hid(requestStream: GRPCAsyncRequestStream, context: GRPCAsyncServerCallContext) async throws -> Idb_HIDResponse { + return try await FBTeardownContext.withAutocleanup { + try await HidMethodHandler(commandExecutor: commandExecutor) + .handle(requestStream: requestStream, context: context) + } + } + + func open_url(request: Idb_OpenUrlRequest, context: GRPCAsyncServerCallContext) async throws -> Idb_OpenUrlRequest { + return try await FBTeardownContext.withAutocleanup { + try await OpenUrlMethodHandler(commandExecutor: commandExecutor) + .handle(request: request, context: context) + } + } + + func set_location(request: Idb_SetLocationRequest, context: GRPCAsyncServerCallContext) async throws -> Idb_SetLocationResponse { + return try await FBTeardownContext.withAutocleanup { + try await SetLocationMethodHandler(commandExecutor: commandExecutor) + .handle(request: request, context: context) + } + } + + func send_notification(request: Idb_SendNotificationRequest, context: GRPCAsyncServerCallContext) async throws -> Idb_SendNotificationResponse { + return try await FBTeardownContext.withAutocleanup { + try await SendNotificationMethodHandler(commandExecutor: commandExecutor) + .handle(request: request, context: context) + } + } + + func simulate_memory_warning(request: Idb_SimulateMemoryWarningRequest, context: GRPCAsyncServerCallContext) async throws -> Idb_SimulateMemoryWarningResponse { + return try await FBTeardownContext.withAutocleanup { + try await SimulateMemoryWarningMethodHandler(commandExecutor: commandExecutor) + .handle(request: request, context: context) + } + } + + func approve(request: Idb_ApproveRequest, context: GRPCAsyncServerCallContext) async throws -> Idb_ApproveResponse { + return try await FBTeardownContext.withAutocleanup { + try await ApproveMethodHandler(commandExecutor: commandExecutor) + .handle(request: request, context: context) + } + } + + func revoke(request: Idb_RevokeRequest, context: GRPCAsyncServerCallContext) async throws -> Idb_RevokeResponse { + return try await FBTeardownContext.withAutocleanup { + try await RevokeMethodHandler(commandExecutor: commandExecutor) + .handle(request: request, context: context) + } + } + + func clear_keychain(request: Idb_ClearKeychainRequest, context: GRPCAsyncServerCallContext) async throws -> Idb_ClearKeychainResponse { + return try await FBTeardownContext.withAutocleanup { + try await ClearKeychainMethodHandler(commandExecutor: commandExecutor) + .handle(request: request, context: context) + } + } + + func contacts_update(request: Idb_ContactsUpdateRequest, context: GRPCAsyncServerCallContext) async throws -> Idb_ContactsUpdateResponse { + return try await FBTeardownContext.withAutocleanup { + try await ContactsUpdateMethodHandler(commandExecutor: commandExecutor) + .handle(request: request, context: context) + } + } + + func setting(request: Idb_SettingRequest, context: GRPCAsyncServerCallContext) async throws -> Idb_SettingResponse { + return try await FBTeardownContext.withAutocleanup { + try await SettingMethodHandler(commandExecutor: commandExecutor) + .handle(request: request, context: context) + } + } + + func get_setting(request: Idb_GetSettingRequest, context: GRPCAsyncServerCallContext) async throws -> Idb_GetSettingResponse { + return try await FBTeardownContext.withAutocleanup { + try await GetSettingMethodHandler(commandExecutor: commandExecutor) + .handle(request: request, context: context) + } + } + + func list_settings(request: Idb_ListSettingRequest, context: GRPCAsyncServerCallContext) async throws -> Idb_ListSettingResponse { + return try await FBTeardownContext.withAutocleanup { + try await ListSettingsMethodHandler(commandExecutor: commandExecutor) + .handle(request: request, context: context) + } + } + + func launch(requestStream: GRPCAsyncRequestStream, responseStream: GRPCAsyncResponseStreamWriter, context: GRPCAsyncServerCallContext) async throws { + return try await FBTeardownContext.withAutocleanup { + try await LaunchMethodHandler(commandExecutor: commandExecutor) + .handle(requestStream: requestStream, responseStream: responseStream, context: context) + } + } + + func list_apps(request: Idb_ListAppsRequest, context: GRPCAsyncServerCallContext) async throws -> Idb_ListAppsResponse { + return try await FBTeardownContext.withAutocleanup { + try await ListAppsMethodHandler(commandExecutor: commandExecutor) + .handle(request: request, context: context) + } + } + + func terminate(request: Idb_TerminateRequest, context: GRPCAsyncServerCallContext) async throws -> Idb_TerminateResponse { + return try await FBTeardownContext.withAutocleanup { + try await TerminateMethodHandler(commandExecutor: commandExecutor) + .handle(request: request, context: context) + } + } + + func uninstall(request: Idb_UninstallRequest, context: GRPCAsyncServerCallContext) async throws -> Idb_UninstallResponse { + return try await FBTeardownContext.withAutocleanup { + try await UninstallMethodHandler(commandExecutor: commandExecutor) + .handle(request: request, context: context) + } + } + + func add_media(requestStream: GRPCAsyncRequestStream, context: GRPCAsyncServerCallContext) async throws -> Idb_AddMediaResponse { + return try await FBTeardownContext.withAutocleanup { + try await AddMediaMethodHandler(commandExecutor: commandExecutor) + .handle(requestStream: requestStream, context: context) + } + } + + func record(requestStream: GRPCAsyncRequestStream, responseStream: GRPCAsyncResponseStreamWriter, context: GRPCAsyncServerCallContext) async throws { + return try await FBTeardownContext.withAutocleanup { + try await RecordMethodHandler(target: target, targetLogger: targetLogger) + .handle(requestStream: requestStream, responseStream: responseStream, context: context) + } + } + + func screenshot(request: Idb_ScreenshotRequest, context: GRPCAsyncServerCallContext) async throws -> Idb_ScreenshotResponse { + return try await FBTeardownContext.withAutocleanup { + try await ScreenshotMethodHandler(commandExecutor: commandExecutor) + .handle(request: request, context: context) + } + } + + func video_stream(requestStream: GRPCAsyncRequestStream, responseStream: GRPCAsyncResponseStreamWriter, context: GRPCAsyncServerCallContext) async throws { + return try await FBTeardownContext.withAutocleanup { + try await VideoStreamMethodHandler(target: target, targetLogger: targetLogger, commandExecutor: commandExecutor) + .handle(requestStream: requestStream, responseStream: responseStream, context: context) + } + } + + func crash_delete(request: Idb_CrashLogQuery, context: GRPCAsyncServerCallContext) async throws -> Idb_CrashLogResponse { + return try await FBTeardownContext.withAutocleanup { + try await CrashDeleteMethodHandler(commandExecutor: commandExecutor) + .handle(request: request, context: context) + } + } + + func crash_list(request: Idb_CrashLogQuery, context: GRPCAsyncServerCallContext) async throws -> Idb_CrashLogResponse { + return try await FBTeardownContext.withAutocleanup { + try await CrashListMethodHandler(commandExecutor: commandExecutor) + .handle(request: request, context: context) + } + } + + func crash_show(request: Idb_CrashShowRequest, context: GRPCAsyncServerCallContext) async throws -> Idb_CrashShowResponse { + return try await FBTeardownContext.withAutocleanup { + try await CrashShowMethodHandler(commandExecutor: commandExecutor) + .handle(request: request, context: context) + } + } + + func xctest_list_bundles(request: Idb_XctestListBundlesRequest, context: GRPCAsyncServerCallContext) async throws -> Idb_XctestListBundlesResponse { + return try await FBTeardownContext.withAutocleanup { + try await XCTestListBundlesMethodHandler(commandExecutor: commandExecutor) + .handle(request: request, context: context) + } + } + + func xctest_list_tests(request: Idb_XctestListTestsRequest, context: GRPCAsyncServerCallContext) async throws -> Idb_XctestListTestsResponse { + return try await FBTeardownContext.withAutocleanup { + try await XCTestListTestsMethodHandler(commandExecutor: commandExecutor) + .handle(request: request, context: context) + } + } + + func xctest_run(request: Idb_XctestRunRequest, responseStream: GRPCAsyncResponseStreamWriter, context: GRPCAsyncServerCallContext) async throws { + return try await FBTeardownContext.withAutocleanup { + try await XCTestRunMethodHandler(target: target, commandExecutor: commandExecutor, reporter: reporter, targetLogger: targetLogger, logger: logger) + .handle(request: request, responseStream: responseStream, context: context) + } + } + + func ls(request: Idb_LsRequest, context: GRPCAsyncServerCallContext) async throws -> Idb_LsResponse { + return try await FBTeardownContext.withAutocleanup { + try await LsMethodHandler(commandExecutor: commandExecutor) + .handle(request: request, context: context) + } + } + + func mkdir(request: Idb_MkdirRequest, context: GRPCAsyncServerCallContext) async throws -> Idb_MkdirResponse { + return try await FBTeardownContext.withAutocleanup { + try await MkdirMethodHandler(commandExecutor: commandExecutor) + .handle(request: request, context: context) + } + } + + func mv(request: Idb_MvRequest, context: GRPCAsyncServerCallContext) async throws -> Idb_MvResponse { + return try await FBTeardownContext.withAutocleanup { + try await MvMethodHandler(commandExecutor: commandExecutor) + .handle(request: request, context: context) + } + } + + func rm(request: Idb_RmRequest, context: GRPCAsyncServerCallContext) async throws -> Idb_RmResponse { + return try await FBTeardownContext.withAutocleanup { + try await RmMethodHandler(commandExecutor: commandExecutor) + .handle(request: request, context: context) + } + } + + func pull(request: Idb_PullRequest, responseStream: GRPCAsyncResponseStreamWriter, context: GRPCAsyncServerCallContext) async throws { + return try await FBTeardownContext.withAutocleanup { + try await PullMethodHandler(target: target, commandExecutor: commandExecutor) + .handle(request: request, responseStream: responseStream, context: context) + } + } + + func push(requestStream: GRPCAsyncRequestStream, context: GRPCAsyncServerCallContext) async throws -> Idb_PushResponse { + return try await FBTeardownContext.withAutocleanup { + try await PushMethodHandler(target: target, commandExecutor: commandExecutor) + .handle(requestStream: requestStream, context: context) + } + } + + func tail(requestStream: GRPCAsyncRequestStream, responseStream: GRPCAsyncResponseStreamWriter, context: GRPCAsyncServerCallContext) async throws { + return try await FBTeardownContext.withAutocleanup { + try await TailMethodHandler(commandExecutor: commandExecutor) + .handle(requestStream: requestStream, responseStream: responseStream, context: context) + } + } +} diff --git a/idb_companion/SwiftServer/GRPCSwiftServer.swift b/idb_companion/SwiftServer/GRPCSwiftServer.swift new file mode 100644 index 000000000..29dccbe67 --- /dev/null +++ b/idb_companion/SwiftServer/GRPCSwiftServer.swift @@ -0,0 +1,192 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import CompanionLib +import FBControlCore +import Foundation +import GRPC +import IDBGRPCSwift +import NIOCore +import NIOPosix +import NIOSSL + +struct IDBUnixDomainSocketPathWrongType: Error {} + +@objc +final class GRPCSwiftServer: NSObject { + + private struct TLSCertificates { + let certificates: [NIOSSLCertificateSource] + let privateKey: NIOSSLPrivateKeySource + } + + private var server: EventLoopFuture? + private let provider: CallHandlerProvider + private let logger: FBIDBLogger + + private let serverConfig: Server.Configuration + private let ports: IDBPortsConfiguration + + @objc + let completed: FBMutableFuture + + @objc + init(target: FBiOSTarget, + commandExecutor: FBIDBCommandExecutor, + reporter: FBEventReporter, + logger: FBIDBLogger, + ports: IDBPortsConfiguration) throws { + + let group = MultiThreadedEventLoopGroup(numberOfThreads: 4) + let tlsCerts = Self.loadCertificates(tlsCertPath: ports.tlsCertPath, logger: logger) + + let interceptors = CompanionServiceInterceptors(logger: logger, reporter: reporter) + + self.provider = CompanionServiceProvider(target: target, + commandExecutor: commandExecutor, + reporter: reporter, + logger: logger, + interceptors: interceptors) + + var serverConfiguration = Server.Configuration.default(target: ports.swiftServerTarget.grpcConnection, + eventLoopGroup: group, + serviceProviders: [provider]) + serverConfiguration.maximumReceiveMessageLength = 16777216 + + if ports.swiftServerTarget.supportsTLSCert { + serverConfiguration.tlsConfiguration = tlsCerts.map { + GRPCTLSConfiguration.makeServerConfigurationBackedByNIOSSL(certificateChain: $0.certificates, privateKey: $0.privateKey) + } + } + + serverConfiguration.errorDelegate = GRPCSwiftServerErrorDelegate() + self.serverConfig = serverConfiguration + self.ports = ports + + self.completed = FBMutableFuture() + self.logger = logger + + super.init() + } + + @objc func start() -> FBMutableFuture { + // Start the server and print its address once it has started. + let future = FBMutableFuture() + + if case .unixDomainSocket(let path) = ports.swiftServerTarget { + do { + try cleanupUnixDomainSocket(path: path) + } catch { + self.logger.error().log("\(error)") + future.resolveWithError(error) + return future + } + } + + let server = Server.start(configuration: serverConfig) + self.server = server + + logger.info().log("Starting swift server on \(ports.swiftServerTarget)") + if let tlsPath = ports.tlsCertPath, !tlsPath.isEmpty { + logger.info().log("Starting swift server with TLS path \(tlsPath)") + } + + server.map(\.channel.localAddress).whenComplete { [weak self, ports] result in + do { + let address = try result.get() + self?.logServerStartup(address: address) + try future.resolve(withResult: ports.swiftServerTarget.outputDescription(for: address) as NSDictionary) + } catch { + self?.logger.error().log("\(error)") + future.resolveWithError(error) + } + } + + server.flatMap(\.onClose).whenCompleteBlocking(onto: .main) { [completed] _ in + self.logger.info().log("Server closed") + completed.resolve(withResult: NSNull()) + } + + return future + } + + private func cleanupUnixDomainSocket(path: String) throws { + do { + self.logger.info().log("Cleaning up UDS if exists") + var sb: stat = stat() + try withUnsafeMutablePointer(to: &sb) { sbPtr in + try syscall { + stat(path, sbPtr) + } + } + + // Only unlink the existing file if it is a socket + if sb.st_mode & S_IFSOCK == S_IFSOCK { + self.logger.info().log("Existed UDS socket found, unlinking") + try syscall { + unlink(path) + } + self.logger.info().log("UDS socket cleaned up") + } else { + throw IDBUnixDomainSocketPathWrongType() + } + } catch let err as IOError { + // If the filepath did not exist, we consider it cleaned up + if err.errnoCode == ENOENT { + return + } + throw err + } + } + + private func syscall(function: String = #function, _ body: () throws -> Int32) throws { + while true { + let res = try body() + if res == -1 { + let err = errno + switch err { + case EINTR: + continue + default: + throw IOError(errnoCode: err, reason: function) + } + } + return + } + } + + private func logServerStartup(address: SocketAddress?) { + let message = "Swift server started on " + if let address { + logger.info().log(message + address.description) + } else { + logger.error().log(message + " unknown address") + } + } + + private static func loadCertificates(tlsCertPath: String?, logger: FBIDBLogger) -> TLSCertificates? { + guard let tlsPath = tlsCertPath, + !tlsPath.isEmpty + else { return nil } + + let tlsURL = URL(fileURLWithPath: tlsPath) + do { + let rawCert = try Data(contentsOf: tlsURL) + + let certificate = try NIOSSLCertificateSource.certificate(.init(bytes: [UInt8](rawCert), format: .pem)) + let privateKey = try NIOSSLPrivateKeySource.privateKey(.init(bytes: [UInt8](rawCert), format: .pem)) + + return TLSCertificates( + certificates: [certificate], + privateKey: privateKey + ) + } catch { + logger.error().log("Unable to load tls certificate. Error: \(error)") + fatalError("Unable to load tls certificate. Error: \(error)") + } + } +} diff --git a/idb_companion/SwiftServer/GRPCSwiftServerErrorDelegate.swift b/idb_companion/SwiftServer/GRPCSwiftServerErrorDelegate.swift new file mode 100644 index 000000000..f9aa83e0b --- /dev/null +++ b/idb_companion/SwiftServer/GRPCSwiftServerErrorDelegate.swift @@ -0,0 +1,45 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import CompanionLib +import Foundation +import GRPC +import NIOHPACK + +final class GRPCSwiftServerErrorDelegate: ServerErrorDelegate { + + func transformRequestHandlerError(_ error: Error, headers: HPACKHeaders) -> GRPCStatusAndTrailers? { + if error is GRPCStatus || error is GRPCStatusTransformable { + // Use default error propagation transformation + return nil + } + + var message = error.localizedDescription + if type(of: error) == NSError.self { + // Legacy NSError from objc, we should unwrap it for more expressive error handling. + // Don't use `is NSError` check because all swift errors bridges to NSError successfully and this check passed + + message = extractMessage(fromLegacyNSError: error as NSError) + } + return GRPCStatusAndTrailers(status: GRPCStatus(code: .internalError, message: message)) + } + + private func extractMessage(fromLegacyNSError error: NSError) -> String { + var userInfo = error.userInfo + + var message: String + if let localizedDescription = userInfo.removeValue(forKey: NSLocalizedDescriptionKey) as? String { + message = localizedDescription + } else { + message = error.description + } + if !userInfo.isEmpty { + message += "\nInfo: \(userInfo)" + } + return message + } +} diff --git a/idb_companion/SwiftServer/Interceptors/CompanionServiceInterceptors.swift b/idb_companion/SwiftServer/Interceptors/CompanionServiceInterceptors.swift new file mode 100644 index 000000000..2bafb49c0 --- /dev/null +++ b/idb_companion/SwiftServer/Interceptors/CompanionServiceInterceptors.swift @@ -0,0 +1,202 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import CompanionLib +import Foundation +import GRPC +import IDBGRPCSwift + +// By design in grpc-swift we should provide interceptor for each method separately. +// This gives us ability to precicely control which interceptors will be used for concrete method from one side, +// but make it too explicit from other side. +final class CompanionServiceInterceptors: Idb_CompanionServiceServerInterceptorFactoryProtocol { + + private let logger: FBIDBLogger + private let reporter: FBEventReporter + + init(logger: FBIDBLogger, reporter: FBEventReporter) { + self.logger = logger + self.reporter = reporter + } + + private func commonInterceptors() -> [ServerInterceptor] { + [MethodInfoSetterInterceptor(), + LoggingInterceptor(logger: logger, reporter: reporter)] + } + + func makeconnectInterceptors() -> [ServerInterceptor] { + commonInterceptors() + } + + func makedebugserverInterceptors() -> [ServerInterceptor] { + commonInterceptors() + } + + func makedapInterceptors() -> [ServerInterceptor] { + commonInterceptors() + } + + func makedescribeInterceptors() -> [ServerInterceptor] { + commonInterceptors() + } + + func makeinstallInterceptors() -> [ServerInterceptor] { + commonInterceptors() + } + + func makeinstruments_runInterceptors() -> [ServerInterceptor] { + commonInterceptors() + } + + func makelogInterceptors() -> [ServerInterceptor] { + commonInterceptors() + } + + func makexctrace_recordInterceptors() -> [ServerInterceptor] { + commonInterceptors() + } + + func makeaccessibility_infoInterceptors() -> [ServerInterceptor] { + commonInterceptors() + } + + func makefocusInterceptors() -> [ServerInterceptor] { + commonInterceptors() + } + + func makehidInterceptors() -> [ServerInterceptor] { + commonInterceptors() + } + + func makeopen_urlInterceptors() -> [ServerInterceptor] { + commonInterceptors() + } + + func makeset_locationInterceptors() -> [ServerInterceptor] { + commonInterceptors() + } + + func makesend_notificationInterceptors() -> [ServerInterceptor] { + commonInterceptors() + } + + func makesimulate_memory_warningInterceptors() -> [ServerInterceptor] { + commonInterceptors() + } + + func makeapproveInterceptors() -> [ServerInterceptor] { + commonInterceptors() + } + + func makerevokeInterceptors() -> [ServerInterceptor] { + commonInterceptors() + } + + func makeclear_keychainInterceptors() -> [ServerInterceptor] { + commonInterceptors() + } + + func makecontacts_updateInterceptors() -> [ServerInterceptor] { + commonInterceptors() + } + + func makesettingInterceptors() -> [ServerInterceptor] { + commonInterceptors() + } + + func makeget_settingInterceptors() -> [ServerInterceptor] { + commonInterceptors() + } + + func makelist_settingsInterceptors() -> [ServerInterceptor] { + commonInterceptors() + } + + func makelaunchInterceptors() -> [ServerInterceptor] { + commonInterceptors() + } + + func makelist_appsInterceptors() -> [ServerInterceptor] { + commonInterceptors() + } + + func maketerminateInterceptors() -> [ServerInterceptor] { + commonInterceptors() + } + + func makeuninstallInterceptors() -> [ServerInterceptor] { + commonInterceptors() + } + + func makeadd_mediaInterceptors() -> [ServerInterceptor] { + commonInterceptors() + } + + func makerecordInterceptors() -> [ServerInterceptor] { + commonInterceptors() + } + + func makescreenshotInterceptors() -> [ServerInterceptor] { + commonInterceptors() + } + + func makevideo_streamInterceptors() -> [ServerInterceptor] { + commonInterceptors() + } + + func makecrash_deleteInterceptors() -> [ServerInterceptor] { + commonInterceptors() + } + + func makecrash_listInterceptors() -> [ServerInterceptor] { + commonInterceptors() + } + + func makecrash_showInterceptors() -> [ServerInterceptor] { + commonInterceptors() + } + + func makexctest_list_bundlesInterceptors() -> [ServerInterceptor] { + commonInterceptors() + } + + func makexctest_list_testsInterceptors() -> [ServerInterceptor] { + commonInterceptors() + } + + func makexctest_runInterceptors() -> [ServerInterceptor] { + commonInterceptors() + } + + func makelsInterceptors() -> [ServerInterceptor] { + commonInterceptors() + } + + func makemkdirInterceptors() -> [ServerInterceptor] { + commonInterceptors() + } + + func makemvInterceptors() -> [ServerInterceptor] { + commonInterceptors() + } + + func makermInterceptors() -> [ServerInterceptor] { + commonInterceptors() + } + + func makepullInterceptors() -> [ServerInterceptor] { + commonInterceptors() + } + + func makepushInterceptors() -> [ServerInterceptor] { + commonInterceptors() + } + + func maketailInterceptors() -> [ServerInterceptor] { + commonInterceptors() + } +} diff --git a/idb_companion/SwiftServer/Interceptors/LoggingInterceptor.swift b/idb_companion/SwiftServer/Interceptors/LoggingInterceptor.swift new file mode 100644 index 000000000..322ed5c06 --- /dev/null +++ b/idb_companion/SwiftServer/Interceptors/LoggingInterceptor.swift @@ -0,0 +1,105 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import CompanionLib +import GRPC +import NIO + +private enum MethodStartKey: UserInfo.Key { + typealias Value = Date +} + +final class LoggingInterceptor: ServerInterceptor { + + private let logger: FBIDBLogger + private let reporter: FBEventReporter + + init(logger: FBIDBLogger, reporter: FBEventReporter) { + self.logger = logger + self.reporter = reporter + } + + // MARK: Request start + incoming frames + + override func receive(_ part: GRPCServerRequestPart, context: ServerInterceptorContext) { + guard let methodInfo = context.userInfo[MethodInfoKey.self] else { + assertionFailure("MethodInfoKey is empty, you have incorrect interceptor order") + super.receive(part, context: context) + return + } + + switch part { + case .metadata: + saveStartDate(in: context) + reportMethodStart(methodName: methodInfo.name, in: context) + + case .message where methodInfo.callType == .clientStreaming || methodInfo.callType == .bidirectionalStreaming: + logger.debug().log("Receive frame of \(methodInfo.name)") + + case .end where methodInfo.callType == .clientStreaming || methodInfo.callType == .bidirectionalStreaming: + logger.debug().log("Close client stream of \(methodInfo.name)") + + default: + break + } + + super.receive(part, context: context) + } + + private func saveStartDate(in context: ServerInterceptorContext) { + context.userInfo[MethodStartKey.self] = Date() + } + + private func reportMethodStart(methodName: String, in context: ServerInterceptorContext) { + logger.info().log("Start of \(methodName)") + let subject = FBEventReporterSubject(forStartedCall: methodName, arguments: [], reportNativeSwiftMethodCall: true) + reporter.report(subject) + } + + // MARK: Request end + outgoing frames + + override func send(_ part: GRPCServerResponsePart, promise: EventLoopPromise?, context: ServerInterceptorContext) { + guard let methodInfo = context.userInfo[MethodInfoKey.self] else { + assertionFailure("MethodInfoKey is empty, you have incorrect interceptor order") + super.send(part, promise: promise, context: context) + return + } + + switch part { + case let .end(status, _): + reportMethodEnd(methodName: methodInfo.name, status: status, context: context) + + default: + break + } + + super.send(part, promise: promise, context: context) + } + + private func reportMethodEnd(methodName: String, status: GRPCStatus, context: ServerInterceptorContext) { + let duration = getMethodDuration(context: context) + + let subject: FBEventReporterSubject + if status.isOk { + logger.debug().log("Success of \(methodName)") + subject = FBEventReporterSubject(forSuccessfulCall: methodName, duration: duration, size: nil, arguments: [], reportNativeSwiftMethodCall: true) + } else { + logger.info().log("Failure of \(methodName), \(status)") + subject = FBEventReporterSubject(forFailingCall: methodName, duration: duration, message: status.message ?? "Unknown error with code \(status.code)", size: nil, arguments: [], reportNativeSwiftMethodCall: true) + } + + reporter.report(subject) + } + + private func getMethodDuration(context: ServerInterceptorContext) -> TimeInterval { + guard let methodStartDate = context.userInfo[MethodStartKey.self] else { + assertionFailure("\(MethodStartKey.self) is not configured on request start") + return 0 + } + return Date().timeIntervalSince(methodStartDate) + } +} diff --git a/idb_companion/SwiftServer/Interceptors/MethodPathSetterInterceptor.swift b/idb_companion/SwiftServer/Interceptors/MethodPathSetterInterceptor.swift new file mode 100644 index 000000000..c28f98633 --- /dev/null +++ b/idb_companion/SwiftServer/Interceptors/MethodPathSetterInterceptor.swift @@ -0,0 +1,60 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import CompanionLib +import Foundation +import GRPC +import IDBCompanionUtilities +import IDBGRPCSwift + +enum MethodInfoKey: UserInfo.Key { + typealias Value = GRPCMethodInfo +} + +struct GRPCMethodInfo { + let name: String + let path: String + let callType: GRPCCallType +} + +final class MethodInfoSetterInterceptor: ServerInterceptor { + + @Atomic var methodDescriptors: [String: GRPCMethodDescriptor] = Idb_CompanionServiceServerMetadata + .serviceDescriptor + .methods + .reduce(into: [:]) { $0[$1.path] = $1 } + + override func receive(_ part: GRPCServerRequestPart, context: ServerInterceptorContext) { + switch part { + case .metadata: + let methodInfo: GRPCMethodInfo + if let methodDescriptor = methodDescriptors[context.path] { + methodInfo = GRPCMethodInfo(name: methodDescriptor.name, + path: methodDescriptor.path, + callType: methodDescriptor.type) + } else { + assertionFailure("Method not found in descriptors list. If this is client and companion version mismatch, ignore that error") + // context.callType is not reported correctly in ServerInterceptorContext and always return .bidirectionalStreaming + methodInfo = GRPCMethodInfo(name: String(extractMethodName(path: context.path)), + path: context.path, + callType: context.type) + } + context.userInfo[MethodInfoKey.self] = methodInfo + + default: + break + } + + super.receive(part, context: context) + } + + private func extractMethodName(path: String) -> Substring { + path + .suffix(from: path.lastIndex(of: "/")!) + .dropFirst() + } +} diff --git a/idb_companion/SwiftServer/MethodHandlers/AccessibilityInfoMethodHandler.swift b/idb_companion/SwiftServer/MethodHandlers/AccessibilityInfoMethodHandler.swift new file mode 100644 index 000000000..48b9100ee --- /dev/null +++ b/idb_companion/SwiftServer/MethodHandlers/AccessibilityInfoMethodHandler.swift @@ -0,0 +1,30 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import CompanionLib +import FBControlCore +import Foundation +import GRPC +import IDBGRPCSwift + +struct AccessibilityInfoMethodHandler { + + let commandExecutor: FBIDBCommandExecutor + + func handle(request: Idb_AccessibilityInfoRequest, context: GRPCAsyncServerCallContext) async throws -> Idb_AccessibilityInfoResponse { + var point: NSValue? + if request.hasPoint { + point = NSValue(point: .init(x: request.point.x, y: request.point.y)) + } + let nested = request.format == .nested + let info = try await BridgeFuture.value(commandExecutor.accessibility_info_(at_point: point, nestedFormat: nested)) + let jsonData = try JSONSerialization.data(withJSONObject: info) + return .with { + $0.json = String(data: jsonData, encoding: .utf8) ?? "" + } + } +} diff --git a/idb_companion/SwiftServer/MethodHandlers/AddMediaMethodHandler.swift b/idb_companion/SwiftServer/MethodHandlers/AddMediaMethodHandler.swift new file mode 100644 index 000000000..2b7b1eab9 --- /dev/null +++ b/idb_companion/SwiftServer/MethodHandlers/AddMediaMethodHandler.swift @@ -0,0 +1,23 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import CompanionLib +import GRPC +import IDBGRPCSwift + +struct AddMediaMethodHandler { + + let commandExecutor: FBIDBCommandExecutor + + func handle(requestStream: GRPCAsyncRequestStream, context: GRPCAsyncServerCallContext) async throws -> Idb_AddMediaResponse { + let extractedFileURLs = try await MultisourceFileReader + .filePathURLs(from: requestStream, temporaryDirectory: commandExecutor.temporaryDirectory, extractFromSubdir: true) + + try await BridgeFuture.await(commandExecutor.add_media(extractedFileURLs)) + return .init() + } +} diff --git a/idb_companion/SwiftServer/MethodHandlers/ApproveMethodHandler.swift b/idb_companion/SwiftServer/MethodHandlers/ApproveMethodHandler.swift new file mode 100644 index 000000000..c4870f442 --- /dev/null +++ b/idb_companion/SwiftServer/MethodHandlers/ApproveMethodHandler.swift @@ -0,0 +1,50 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import CompanionLib +import GRPC +import IDBGRPCSwift + +struct ApproveMethodHandler { + + let commandExecutor: FBIDBCommandExecutor + + func handle(request: Idb_ApproveRequest, context: GRPCAsyncServerCallContext) async throws -> Idb_ApproveResponse { + + // Swift implements custom bridging logic for NSNotificationName and this causes ALL string enums ended with "Notification" + // suffix translates in this special way + let notificationApprovalService = FBTargetSettingsService.FBTargetSettingsService + + let mapping: [Idb_ApproveRequest.Permission: FBTargetSettingsService] = [ + .microphone: .microphone, + .photos: .photos, + .camera: .camera, + .contacts: .contacts, + .url: .url, + .location: .location, + .notification: notificationApprovalService, + ] + + var services = try Set( + request.permissions.map { permission -> FBTargetSettingsService in + guard let service = mapping[permission] else { + throw GRPCStatus(code: .invalidArgument, message: "Unrecognized permission \(permission)") + } + return service + } + ) + if services.contains(.url) { + services.remove(.url) + try await BridgeFuture.await(commandExecutor.approve_deeplink(request.scheme, for_application: request.bundleID)) + } + + if !services.isEmpty { + try await BridgeFuture.await(commandExecutor.approve(services, for_application: request.bundleID)) + } + return .init() + } +} diff --git a/idb_companion/SwiftServer/MethodHandlers/ClearKeychainMethodHandler.swift b/idb_companion/SwiftServer/MethodHandlers/ClearKeychainMethodHandler.swift new file mode 100644 index 000000000..c07e88747 --- /dev/null +++ b/idb_companion/SwiftServer/MethodHandlers/ClearKeychainMethodHandler.swift @@ -0,0 +1,20 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import CompanionLib +import GRPC +import IDBGRPCSwift + +struct ClearKeychainMethodHandler { + + let commandExecutor: FBIDBCommandExecutor + + func handle(request: Idb_ClearKeychainRequest, context: GRPCAsyncServerCallContext) async throws -> Idb_ClearKeychainResponse { + try await BridgeFuture.await(commandExecutor.clear_keychain()) + return .init() + } +} diff --git a/idb_companion/SwiftServer/MethodHandlers/ConnectMethodHandler.swift b/idb_companion/SwiftServer/MethodHandlers/ConnectMethodHandler.swift new file mode 100644 index 000000000..dde894597 --- /dev/null +++ b/idb_companion/SwiftServer/MethodHandlers/ConnectMethodHandler.swift @@ -0,0 +1,36 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import CompanionLib +import Foundation +import GRPC +import IDBGRPCSwift + +struct ConnectMethodHandler { + + let reporter: FBEventReporter + let logger: FBIDBLogger + let target: FBiOSTarget + + func handle(request: Idb_ConnectRequest, context: GRPCAsyncServerCallContext) async throws -> Idb_ConnectResponse { + self.reporter.addMetadata(request.metadata) + let isLocal = FileManager.default.fileExists(atPath: request.localFilePath) + + return Idb_ConnectResponse.with { + $0.companion = .with { + $0.udid = target.udid + $0.isLocal = isLocal + + do { + $0.metadata = try JSONSerialization.data(withJSONObject: reporter.metadata, options: []) + } catch { + logger.error().log("Error while serializing metadata \(error.localizedDescription)") + } + } + } + } +} diff --git a/idb_companion/SwiftServer/MethodHandlers/ContactsUpdateMethodHandler.swift b/idb_companion/SwiftServer/MethodHandlers/ContactsUpdateMethodHandler.swift new file mode 100644 index 000000000..90f907290 --- /dev/null +++ b/idb_companion/SwiftServer/MethodHandlers/ContactsUpdateMethodHandler.swift @@ -0,0 +1,20 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import CompanionLib +import GRPC +import IDBGRPCSwift + +struct ContactsUpdateMethodHandler { + + let commandExecutor: FBIDBCommandExecutor + + func handle(request: Idb_ContactsUpdateRequest, context: GRPCAsyncServerCallContext) async throws -> Idb_ContactsUpdateResponse { + try await BridgeFuture.await(commandExecutor.update_contacts(request.payload.data)) + return .init() + } +} diff --git a/idb_companion/SwiftServer/MethodHandlers/CrashDeleteMethodHandler.swift b/idb_companion/SwiftServer/MethodHandlers/CrashDeleteMethodHandler.swift new file mode 100644 index 000000000..0879801cf --- /dev/null +++ b/idb_companion/SwiftServer/MethodHandlers/CrashDeleteMethodHandler.swift @@ -0,0 +1,23 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import CompanionLib +import GRPC +import IDBGRPCSwift + +struct CrashDeleteMethodHandler { + + let commandExecutor: FBIDBCommandExecutor + + func handle(request: Idb_CrashLogQuery, context: GRPCAsyncServerCallContext) async throws -> Idb_CrashLogResponse { + let predicate = CrashLogQueryValueTransformer.predicate(from: request) + let crashes: [FBCrashLogInfo] = try await BridgeFuture.value(commandExecutor.crash_delete(predicate)) + return .with { + $0.list = crashes.map(CrashLogInfoValueTransformer.responseCrashLogInfo(from:)) + } + } +} diff --git a/idb_companion/SwiftServer/MethodHandlers/CrashListMethodHandler.swift b/idb_companion/SwiftServer/MethodHandlers/CrashListMethodHandler.swift new file mode 100644 index 000000000..a0b99c5cd --- /dev/null +++ b/idb_companion/SwiftServer/MethodHandlers/CrashListMethodHandler.swift @@ -0,0 +1,23 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import CompanionLib +import GRPC +import IDBGRPCSwift + +struct CrashListMethodHandler { + + let commandExecutor: FBIDBCommandExecutor + + func handle(request: Idb_CrashLogQuery, context: GRPCAsyncServerCallContext) async throws -> Idb_CrashLogResponse { + let predicate = CrashLogQueryValueTransformer.predicate(from: request) + let crashes: [FBCrashLogInfo] = try await BridgeFuture.value(commandExecutor.crash_list(predicate)) + return Idb_CrashLogResponse.with { + $0.list = crashes.map(CrashLogInfoValueTransformer.responseCrashLogInfo(from:)) + } + } +} diff --git a/idb_companion/SwiftServer/MethodHandlers/CrashShowMethodHandler.swift b/idb_companion/SwiftServer/MethodHandlers/CrashShowMethodHandler.swift new file mode 100644 index 000000000..52f838ec8 --- /dev/null +++ b/idb_companion/SwiftServer/MethodHandlers/CrashShowMethodHandler.swift @@ -0,0 +1,28 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import CompanionLib +import GRPC +import IDBGRPCSwift + +struct CrashShowMethodHandler { + + let commandExecutor: FBIDBCommandExecutor + + func handle(request: Idb_CrashShowRequest, context: GRPCAsyncServerCallContext) async throws -> Idb_CrashShowResponse { + guard !request.name.isEmpty else { + throw GRPCStatus(code: .invalidArgument, message: "Missing crash name") + } + + let predicate = FBCrashLogInfo.predicate(forName: request.name) + let crash = try await BridgeFuture.value(commandExecutor.crash_show(predicate)) + return .with { + $0.info = CrashLogInfoValueTransformer.responseCrashLogInfo(from: crash.info) + $0.contents = crash.contents + } + } +} diff --git a/idb_companion/SwiftServer/MethodHandlers/DapMethodHandler.swift b/idb_companion/SwiftServer/MethodHandlers/DapMethodHandler.swift new file mode 100644 index 000000000..a8fdc6bb6 --- /dev/null +++ b/idb_companion/SwiftServer/MethodHandlers/DapMethodHandler.swift @@ -0,0 +1,103 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import CompanionLib +import FBControlCore +import FBSimulatorControl +import GRPC +import IDBCompanionUtilities +import IDBGRPCSwift + +struct DapMethodHandler { + + let commandExecutor: FBIDBCommandExecutor + let targetLogger: FBControlCoreLogger + + func handle(requestStream: GRPCAsyncRequestStream, responseStream: GRPCAsyncResponseStreamWriter, context: GRPCAsyncServerCallContext) async throws { + guard case let .start(start) = try await requestStream.requiredNext.control + else { throw GRPCStatus(code: .failedPrecondition, message: "Dap command expected a Start messaged in the beginning of the Stream") } + + let writer = FBProcessInput.fromConsumer() as! FBProcessInput + let dapProcess = try await startDapServer(startRequest: start, processInput: writer, responseStream: responseStream) + + let tenHours: UInt64 = 36000 * 1000000000 + try await Task.timeout(nanoseconds: tenHours) { + try await consumeElements(from: requestStream, to: writer, dapProcess: dapProcess) + } + + let stoppedResponse = Idb_DapResponse.with { + $0.event = .stopped( + .with { $0.desc = "Dap server stopped" } + ) + } + try await responseStream.send(stoppedResponse) + } + + private func startDapServer(startRequest: Idb_DapRequest.Start, processInput: FBProcessInput, responseStream: GRPCAsyncResponseStreamWriter) async throws -> FBProcess { + + let lldbVSCode = "dap/\(startRequest.debuggerPkgID)/usr/bin/lldb-vscode" + + let stdOutConsumer = createDataConsumer(to: responseStream) + targetLogger.debug().log("Starting dap server with path \(lldbVSCode)") + + let tenMinutes: UInt64 = 600 * 1000000000 + let process = try await Task.timeout(nanoseconds: tenMinutes) { + try await BridgeFuture.value(commandExecutor.dapServer(withPath: lldbVSCode, stdIn: processInput, stdOut: stdOutConsumer)) + } + + targetLogger.debug().log("Dap server spawn with PID: \(process.processIdentifier)") + let serverStartedResponse = Idb_DapResponse.with { + $0.event = .started(.init()) + } + try await responseStream.send(serverStartedResponse) + + return process + } + + private func consumeElements(from requestStream: GRPCAsyncRequestStream, to writer: FBProcessInput, dapProcess: FBProcess) async throws { + for try await request in requestStream { + switch request.control { + case .start: + throw GRPCStatus(code: .failedPrecondition, message: "DAP server already started") + + case .none: + throw GRPCStatus(code: .invalidArgument, message: "Empty control in request") + + case let .pipe(pipe): + guard !pipe.data.isEmpty else { + targetLogger.debug().log("Dap request received empty message. Transmission finished") + return + } + targetLogger.debug().log("Dap Request. Received \(pipe.data.count) bytes from client") + writer.contents.consumeData(pipe.data) + + case .stop: + targetLogger.debug().log("Received stop from Dap Request") + targetLogger.debug().log("Stopping dap server with pid \(dapProcess.processIdentifier). Stderr: \(dapProcess.stdErr ?? "Empty")") + return + } + } + } + + private func createDataConsumer(to responseStream: GRPCAsyncResponseStreamWriter) -> FBDataConsumer { + let responseWriter = FIFOStreamWriter(stream: responseStream) + + return FBBlockDataConsumer.synchronousDataConsumer { data in + let response = Idb_DapResponse.with { + $0.event = .stdout( + .with { $0.data = data } + ) + } + do { + try responseWriter.send(response) + targetLogger.debug().log("Dap server stdout consumer: sent \(data.count) bytes.") + } catch { + targetLogger.debug().log("Dap server stdout consumer: error \(error) when tried to send bytes.") + } + } + } +} diff --git a/idb_companion/SwiftServer/MethodHandlers/DebugserverMethodHandler.swift b/idb_companion/SwiftServer/MethodHandlers/DebugserverMethodHandler.swift new file mode 100644 index 000000000..4b4c1da85 --- /dev/null +++ b/idb_companion/SwiftServer/MethodHandlers/DebugserverMethodHandler.swift @@ -0,0 +1,56 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import CompanionLib +import FBControlCore +import GRPC +import IDBGRPCSwift + +struct DebugserverMethodHandler { + + let commandExecutor: FBIDBCommandExecutor + + func handle(requestStream: GRPCAsyncRequestStream, responseStream: GRPCAsyncResponseStreamWriter, context: GRPCAsyncServerCallContext) async throws { + + for try await request in requestStream { + switch request.control { + case let .start(start): + let debugServer = try await BridgeFuture.value(commandExecutor.debugserver_start(start.bundleID)) + try await responseStream.send(debugserverStatusToProto(debugServer: debugServer)) + return + + case .status: + // Replicates old cpp server behaviour. We should return `0` exit code if server not started + if let debugServer = try? await BridgeFuture.value(commandExecutor.debugserver_status()) { + try await responseStream.send(debugserverStatusToProto(debugServer: debugServer)) + } else { + try await responseStream.send(.init()) + } + return + + case .stop: + let debugServer = try await BridgeFuture.value(commandExecutor.debugserver_stop()) + try await responseStream.send(debugserverStatusToProto(debugServer: debugServer)) + return + + case .pipe: + throw GRPCStatus(code: .unimplemented) + + case .none: + throw GRPCStatus(code: .invalidArgument, message: "Received empty control") + } + } + } + + private func debugserverStatusToProto(debugServer: FBDebugServer) -> Idb_DebugServerResponse { + return .with { + $0.status = .with { + $0.lldbBootstrapCommands = debugServer.lldbBootstrapCommands + } + } + } +} diff --git a/idb_companion/SwiftServer/MethodHandlers/DescribeMethodHandler.swift b/idb_companion/SwiftServer/MethodHandlers/DescribeMethodHandler.swift new file mode 100644 index 000000000..c16bd8116 --- /dev/null +++ b/idb_companion/SwiftServer/MethodHandlers/DescribeMethodHandler.swift @@ -0,0 +1,66 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import CompanionLib +import FBControlCore +import Foundation +import GRPC +import IDBGRPCSwift + +struct DescribeMethodHandler { + + let reporter: FBEventReporter + let logger: FBIDBLogger + let target: FBiOSTarget + let commandExecutor: FBIDBCommandExecutor + + func handle(request: Idb_TargetDescriptionRequest, context: GRPCAsyncServerCallContext) async throws -> Idb_TargetDescriptionResponse { + var response = Idb_TargetDescriptionResponse.with { + $0.targetDescription = .with { + $0.udid = target.udid + $0.name = target.name + $0.state = FBiOSTargetStateStringFromState(target.state).rawValue + $0.targetType = FBiOSTargetTypeStringFromTargetType(target.targetType).lowercased() + $0.osVersion = target.osVersion.name.rawValue + if let screenInfo = target.screenInfo { + $0.screenDimensions = .with { + $0.width = UInt64(screenInfo.widthPixels) + $0.widthPoints = $0.width / UInt64(screenInfo.scale) + $0.height = UInt64(screenInfo.heightPixels) + $0.heightPoints = $0.height / UInt64(screenInfo.scale) + $0.density = Double(screenInfo.scale) + } + } + if let extData = try? JSONSerialization.data(withJSONObject: target.extendedInformation) { + $0.extended = extData + } + } + $0.companion = Idb_CompanionInfo.with { + $0.udid = target.udid + if let metadata = try? JSONSerialization.data(withJSONObject: reporter.metadata) { + $0.metadata = metadata + } + } + } + + guard request.fetchDiagnostics else { + return response + } + + let diagnosticInformation = try await BridgeFuture.value(commandExecutor.diagnostic_information()) + let diagnosticInfoData = try JSONSerialization.data(withJSONObject: diagnosticInformation) + response.targetDescription.diagnostics = diagnosticInfoData + + return response + } + + private func populateCompanionInfo(info: inout Idb_CompanionInfo) throws { + info.udid = target.udid + let data = try JSONSerialization.data(withJSONObject: reporter.metadata, options: []) + info.metadata = data + } +} diff --git a/idb_companion/SwiftServer/MethodHandlers/FocusMethodHandler.swift b/idb_companion/SwiftServer/MethodHandlers/FocusMethodHandler.swift new file mode 100644 index 000000000..e94bf3d45 --- /dev/null +++ b/idb_companion/SwiftServer/MethodHandlers/FocusMethodHandler.swift @@ -0,0 +1,20 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import CompanionLib +import GRPC +import IDBGRPCSwift + +struct FocusMethodHandler { + + let commandExecutor: FBIDBCommandExecutor + + func handle(request: Idb_FocusRequest, context: GRPCAsyncServerCallContext) async throws -> Idb_FocusResponse { + try await BridgeFuture.await(commandExecutor.focus()) + return .init() + } +} diff --git a/idb_companion/SwiftServer/MethodHandlers/GetSettingMethodHandler.swift b/idb_companion/SwiftServer/MethodHandlers/GetSettingMethodHandler.swift new file mode 100644 index 000000000..19c82cf85 --- /dev/null +++ b/idb_companion/SwiftServer/MethodHandlers/GetSettingMethodHandler.swift @@ -0,0 +1,33 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import CompanionLib +import GRPC +import IDBGRPCSwift + +struct GetSettingMethodHandler { + + let commandExecutor: FBIDBCommandExecutor + + func handle(request: Idb_GetSettingRequest, context: GRPCAsyncServerCallContext) async throws -> Idb_GetSettingResponse { + switch request.setting { + case .locale: + let localeIdentifier = try await BridgeFuture.value(commandExecutor.get_current_locale_identifier()) + return .with { + $0.value = localeIdentifier as String + } + case .any: + let domain = request.domain.isEmpty ? nil : request.domain + let value = try await BridgeFuture.value(commandExecutor.get_preference(request.name, domain: domain)) + return .with { + $0.value = value as String + } + case .UNRECOGNIZED: + throw GRPCStatus(code: .invalidArgument, message: "Unknown setting case") + } + } +} diff --git a/idb_companion/SwiftServer/MethodHandlers/HidMethodHandler.swift b/idb_companion/SwiftServer/MethodHandlers/HidMethodHandler.swift new file mode 100644 index 000000000..411a9c7e5 --- /dev/null +++ b/idb_companion/SwiftServer/MethodHandlers/HidMethodHandler.swift @@ -0,0 +1,98 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import CompanionLib +import FBSimulatorControl +import GRPC +import IDBGRPCSwift + +struct HidMethodHandler { + + let commandExecutor: FBIDBCommandExecutor + + func handle(requestStream: GRPCAsyncRequestStream, context: GRPCAsyncServerCallContext) async throws -> Idb_HIDResponse { + for try await request in requestStream { + let event = try fbSimulatorHIDEvent(from: request) + try await BridgeFuture.await(commandExecutor.hid(event)) + } + return .init() + } + + private func fbSimulatorHIDEvent(from request: Idb_HIDEvent) throws -> FBSimulatorHIDEvent { + switch request.event { + case let .press(press): + switch press.action.action { + case let .key(key): + switch press.direction { + case .up: + return .keyUp(UInt32(key.keycode)) + case .down: + return .keyDown(UInt32(key.keycode)) + case .UNRECOGNIZED: + throw GRPCStatus(code: .invalidArgument, message: "Unrecognized press.direction") + } + + case let .button(button): + guard let hidButton = fbSimulatorHIDButton(from: button.button) else { + throw GRPCStatus(code: .invalidArgument, message: "Unrecognized hid button type") + } + switch press.direction { + case .up: + return .buttonUp(hidButton) + case .down: + return .buttonDown(hidButton) + case .UNRECOGNIZED: + throw GRPCStatus(code: .invalidArgument, message: "Unrecognized press.direction") + } + + case let .touch(touch): + switch press.direction { + case .up: + return .touchUpAt(x: touch.point.x, y: touch.point.y) + case .down: + return .touchDownAt(x: touch.point.x, y: touch.point.y) + case .UNRECOGNIZED: + throw GRPCStatus(code: .invalidArgument, message: "Unrecognized press.direction") + } + + case .none: + throw GRPCStatus(code: .invalidArgument, message: "Unrecognized press.action") + } + + case let .swipe(swipe): + return .swipe(swipe.start.x, + yStart: swipe.start.y, + xEnd: swipe.end.x, + yEnd: swipe.end.y, + delta: swipe.delta, + duration: swipe.duration) + + case let .delay(delay): + return .delay(delay.duration) + + case .none: + throw GRPCStatus(code: .invalidArgument, message: "Unrecognized request.event") + } + } + + private func fbSimulatorHIDButton(from request: Idb_HIDEvent.HIDButtonType) -> FBSimulatorHIDButton? { + switch request { + case .applePay: + return .applePay + case .home: + return .homeButton + case .lock: + return .lock + case .sideButton: + return .sideButton + case .siri: + return .siri + case .UNRECOGNIZED: + return nil + } + } +} diff --git a/idb_companion/SwiftServer/MethodHandlers/InstallMethodHandler.swift b/idb_companion/SwiftServer/MethodHandlers/InstallMethodHandler.swift new file mode 100644 index 000000000..aa6da9bf7 --- /dev/null +++ b/idb_companion/SwiftServer/MethodHandlers/InstallMethodHandler.swift @@ -0,0 +1,231 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import CompanionLib +import FBControlCore +import Foundation +import GRPC +import IDBGRPCSwift + +struct InstallMethodHandler { + + let commandExecutor: FBIDBCommandExecutor + let targetLogger: FBControlCoreLogger + + func handle(requestStream: GRPCAsyncRequestStream, responseStream: GRPCAsyncResponseStreamWriter, context: GRPCAsyncServerCallContext) async throws { + + let artifact = try await install(requestStream: requestStream, responseStream: responseStream) + + let response = Idb_InstallResponse.with { + $0.name = artifact.name + $0.uuid = artifact.uuid?.uuidString ?? "" + } + try await responseStream.send(response) + } + + private func install(requestStream: GRPCAsyncRequestStream, responseStream: GRPCAsyncResponseStreamWriter) async throws -> FBInstalledArtifact { + + func extractPayloadFromRequest() throws -> Idb_Payload { + guard let payload = request.extractPayload() else { + throw GRPCStatus(code: .invalidArgument, message: "Expected the next item in the stream to be a payload") + } + return payload + } + + var request = try await requestStream.requiredNext + + guard case let .destination(destination) = request.value else { + throw GRPCStatus(code: .failedPrecondition, message: "Expected destination as first request in stream") + } + request = try await requestStream.requiredNext + + var name = UUID().uuidString + if case let .nameHint(nameHint) = request.value { + name = nameHint + request = try await requestStream.requiredNext + } + + var makeDebuggable = false + if case let .makeDebuggable(debuggable) = request.value { + makeDebuggable = debuggable + request = try await requestStream.requiredNext + } + var overrideModificationTime = false + if case let .overrideModificationTime(omtime) = request.value { + overrideModificationTime = omtime + request = try await requestStream.requiredNext + } + + var skipSigningBundles = false + if case let .skipSigningBundles(skip) = request.value { + skipSigningBundles = skip + request = try await requestStream.requiredNext + } + + var linkToBundle: FBDsymInstallLinkToBundle? + + // (2022-03-02) REMOVE! Keeping only for retrocompatibility + if case let .bundleID(id) = request.value { + linkToBundle = .init(id, bundle_type: .app) + request = try await requestStream.requiredNext + } + + if case let .linkDsymToBundle(link) = request.value { + linkToBundle = readLinkBundleToDsym(from: link) + request = try await requestStream.requiredNext + } + + var payload = try extractPayloadFromRequest() + + var compression = FBCompressionFormat.GZIP + if case let .compression(format) = payload.source { + compression = readCompressionFormat(from: format) + request = try await requestStream.requiredNext + payload = try extractPayloadFromRequest() + } + + return try await installData(from: payload.source, + to: destination, + requestStream: requestStream, + name: name, + makeDebuggable: makeDebuggable, + linkToBundle: linkToBundle, + compression: compression, + overrideModificationTime: overrideModificationTime, + skipSigningBundles: skipSigningBundles) + } + + private func installData(from source: Idb_Payload.OneOf_Source?, + to destination: Idb_InstallRequest.Destination, + requestStream: GRPCAsyncRequestStream, + name: String, + makeDebuggable: Bool, + linkToBundle: FBDsymInstallLinkToBundle?, + compression: FBCompressionFormat, + overrideModificationTime: Bool, + skipSigningBundles: Bool) async throws -> FBInstalledArtifact { + + func installSource(dataStream: FBProcessInput, skipSigningBundles: Bool) async throws -> FBInstalledArtifact { + switch destination { + case .app: + return try await BridgeFuture.value( + commandExecutor.install_app_stream(dataStream, compression: compression, make_debuggable: makeDebuggable, override_modification_time: overrideModificationTime) + ) + case .xctest: + return try await BridgeFuture.value( + commandExecutor.install_xctest_app_stream(dataStream, skipSigningBundles: skipSigningBundles) + ) + case .dsym: + return try await BridgeFuture.value( + commandExecutor.install_dsym_stream(dataStream, compression: compression, linkTo: linkToBundle) + ) + case .dylib: + return try await BridgeFuture.value( + commandExecutor.install_dylib_stream(dataStream, name: name) + ) + case .framework: + return try await BridgeFuture.value( + commandExecutor.install_framework_stream(dataStream) + ) + case .UNRECOGNIZED: + throw GRPCStatus(code: .invalidArgument, message: "Unrecognized destination") + } + } + + switch source { + case let .data(data): + let dataStream = pipeToInputOutput(initial: data, requestStream: requestStream) as! FBProcessInput + return try await installSource(dataStream: dataStream, skipSigningBundles: skipSigningBundles) + + case let .url(urlString): + guard let url = URL(string: urlString) else { + throw GRPCStatus(code: .invalidArgument, message: "Invalid url source") + } + let download = FBDataDownloadInput.dataDownload(with: url, logger: targetLogger) + let input = download.input as! FBProcessInput + + return try await installSource(dataStream: input, skipSigningBundles: skipSigningBundles) + + case let .filePath(filePath): + switch destination { + case .app: + return try await BridgeFuture.value( + commandExecutor.install_app_file_path(filePath, make_debuggable: makeDebuggable, override_modification_time: overrideModificationTime) + ) + case .xctest: + return try await BridgeFuture.value( + commandExecutor.install_xctest_app_file_path(filePath, skipSigningBundles: skipSigningBundles) + ) + case .dsym: + return try await BridgeFuture.value( + commandExecutor.install_dsym_file_path(filePath, linkTo: linkToBundle) + ) + case .dylib: + return try await BridgeFuture.value( + commandExecutor.install_dylib_file_path(filePath) + ) + case .framework: + return try await BridgeFuture.value( + commandExecutor.install_framework_file_path(filePath) + ) + case .UNRECOGNIZED: + throw GRPCStatus(code: .invalidArgument, message: "Unrecognized destination") + } + + default: + throw GRPCStatus(code: .invalidArgument, message: "Incorrect payload source") + } + } + + private func pipeToInputOutput(initial: Data, requestStream: GRPCAsyncRequestStream) -> FBProcessInput { + let input = FBProcessInput.fromStream() + let appStream = input.contents + Task { + appStream.open() + defer { appStream.close() } + + var buffer = [UInt8](initial) + appStream.write(&buffer, maxLength: buffer.count) + + for try await request in requestStream { + guard let data = request.extractDataFrame() else { + continue + } + + var buffer = [UInt8](data) + appStream.write(&buffer, maxLength: buffer.count) + } + } + + return input + } + + private func readLinkBundleToDsym(from link: Idb_InstallRequest.LinkDsymToBundle) -> FBDsymInstallLinkToBundle { + return .init(link.bundleID, + bundle_type: readDsymBundleType(from: link.bundleType)) + } + + private func readDsymBundleType(from bundleType: Idb_InstallRequest.LinkDsymToBundle.BundleType) -> FBDsymBundleType { + switch bundleType { + case .app: + return .app + case .xctest: + return .xcTest + case .UNRECOGNIZED: + return .app + } + } + + private func readCompressionFormat(from compression: Idb_Payload.Compression) -> FBCompressionFormat { + switch compression { + case .gzip, .UNRECOGNIZED: + return .GZIP + case .zstd: + return .ZSTD + } + } +} diff --git a/idb_companion/SwiftServer/MethodHandlers/InstrumentsRunMethodHandler.swift b/idb_companion/SwiftServer/MethodHandlers/InstrumentsRunMethodHandler.swift new file mode 100644 index 000000000..e3374173f --- /dev/null +++ b/idb_companion/SwiftServer/MethodHandlers/InstrumentsRunMethodHandler.swift @@ -0,0 +1,109 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import CompanionLib +import FBSimulatorControl +import GRPC +import IDBCompanionUtilities +import IDBGRPCSwift + +struct InstrumentsRunMethodHandler { + + let target: FBiOSTarget + let targetLogger: FBControlCoreLogger + let commandExecutor: FBIDBCommandExecutor + let logger: FBControlCoreLogger + + func handle(requestStream: GRPCAsyncRequestStream, responseStream: GRPCAsyncResponseStreamWriter, context: GRPCAsyncServerCallContext) async throws { + @Atomic var finishedWriting = false + + guard case let .start(start) = try await requestStream.requiredNext.control + else { throw GRPCStatus(code: .failedPrecondition, message: "Expected start control") } + + let operation = try await startInstrumentsOperation(request: start, responseStream: responseStream, finishedWriting: _finishedWriting) + + guard case let .stop(stop) = try await requestStream.requiredNext.control + else { throw GRPCStatus(code: .failedPrecondition, message: "Expected end control") } + + try await stopInstruments(operation: operation, request: stop, responseStream: responseStream, finishedWriting: _finishedWriting) + } + + private func startInstrumentsOperation(request: Idb_InstrumentsRunRequest.Start, responseStream: GRPCAsyncResponseStreamWriter, finishedWriting: Atomic) async throws -> FBInstrumentsOperation { + let configuration = instrumentsConfiguration(from: request, storageManager: commandExecutor.storageManager) + + let responseWriter = FIFOStreamWriter(stream: responseStream) + let consumer = FBBlockDataConsumer.asynchronousDataConsumer { data in + guard !finishedWriting.wrappedValue else { return } + + do { + let response = Idb_InstrumentsRunResponse.with { + $0.logOutput = data + } + try responseWriter.send(response) + } catch { + finishedWriting.set(true) + } + } + let logger = FBControlCoreLoggerFactory.compositeLogger(with: [ + FBControlCoreLoggerFactory.logger(to: consumer), + targetLogger, + ].compactMap { $0 }) + + let operation = try await BridgeFuture.value(target.startInstruments(configuration, logger: logger)) + + let runningStateResponse = Idb_InstrumentsRunResponse.with { + $0.output = .state(.runningInstruments) + } + try await responseStream.send(runningStateResponse) + + return operation + } + + private func stopInstruments(operation: FBInstrumentsOperation, request: Idb_InstrumentsRunRequest.Stop, responseStream: GRPCAsyncResponseStreamWriter, finishedWriting: Atomic) async throws { + _ = try await BridgeFuture.value(operation.stop()) + let response = Idb_InstrumentsRunResponse.with { + $0.state = .postProcessing + } + try await responseStream.send(response) + + let postProcessArguments = commandExecutor.storageManager.interpolateArgumentReplacements(request.postProcessArguments) + let processed = try await BridgeFuture.value(FBInstrumentsOperation.postProcess(postProcessArguments, + traceDir: operation.traceDir, + queue: BridgeQueues.futureSerialFullfillmentQueue, + logger: logger)) + guard let processedPath = processed.path else { + throw GRPCStatus(code: .internalError, message: "Unable to get post process file path") + } + finishedWriting.set(true) + + let archiveOperation = FBArchiveOperations.createGzippedTar(forPath: processedPath, logger: logger) + + try await FileDrainWriter.performDrain(taskFuture: archiveOperation) { data in + let response = Idb_InstrumentsRunResponse.with { + $0.payload = .with { + $0.data = data + } + } + try await responseStream.send(response) + } + } + + private func instrumentsConfiguration(from request: Idb_InstrumentsRunRequest.Start, storageManager: FBIDBStorageManager) -> FBInstrumentsConfiguration { + func withDefaultTimeout(_ initial: Double, _ default: Double) -> Double { + initial != 0 ? initial : `default` + } + return .init(templateName: request.templateName, + targetApplication: request.appBundleID, + appEnvironment: request.environment, + appArguments: request.arguments, + toolArguments: storageManager.interpolateArgumentReplacements(request.toolArguments) ?? [], + timings: .init(terminateTimeout: withDefaultTimeout(request.timings.terminateTimeout, DefaultInstrumentsTerminateTimeout), + launchRetryTimeout: withDefaultTimeout(request.timings.launchRetryTimeout, DefaultInstrumentsLaunchRetryTimeout), + launchErrorTimeout: withDefaultTimeout(request.timings.launchErrorTimeout, DefaultInstrumentsLaunchErrorTimeout), + operationDuration: withDefaultTimeout(request.timings.operationDuration, DefaultInstrumentsOperationDuration))) + } +} diff --git a/idb_companion/SwiftServer/MethodHandlers/LaunchMethodHandler.swift b/idb_companion/SwiftServer/MethodHandlers/LaunchMethodHandler.swift new file mode 100644 index 000000000..3f31c37e7 --- /dev/null +++ b/idb_companion/SwiftServer/MethodHandlers/LaunchMethodHandler.swift @@ -0,0 +1,77 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import CompanionLib +import Foundation +import GRPC +import IDBCompanionUtilities +import IDBGRPCSwift + +struct LaunchMethodHandler { + + let commandExecutor: FBIDBCommandExecutor + + func handle(requestStream: GRPCAsyncRequestStream, responseStream: GRPCAsyncResponseStreamWriter, context: GRPCAsyncServerCallContext) async throws { + var completions: [FBFuture] = [] + + var request = try await requestStream.requiredNext + guard case let .start(start) = request.control else { + throw GRPCStatus(code: .failedPrecondition, message: "Application not started yet") + } + var stdOut = processOutputForNullDevice() + var stdErr = processOutputForNullDevice() + + let responseWriter = FIFOStreamWriter(stream: responseStream) + if start.waitFor { + let stdOutConsumer = pipeOutput(interface: .stdout, responseWriter: responseWriter) + completions.append(stdOutConsumer.finishedConsuming) + stdOut = FBProcessOutput(for: stdOutConsumer) + + let stdErrConsumer = pipeOutput(interface: .stderr, responseWriter: responseWriter) + completions.append(stdErrConsumer.finishedConsuming) + stdErr = FBProcessOutput(for: stdErrConsumer) + } + let io = FBProcessIO(stdIn: nil, stdOut: stdOut, stdErr: stdErr) + let config = FBApplicationLaunchConfiguration(bundleID: start.bundleID, + bundleName: nil, + arguments: start.appArgs, + environment: start.env, + waitForDebugger: start.waitForDebugger, + io: io, + launchMode: start.foregroundIfRunning ? .foregroundIfRunning : .failIfRunning) + let launchedApp = try await BridgeFuture.value(commandExecutor.launch_app(config)) + let response = Idb_LaunchResponse.with { + $0.debugger.pid = UInt64(launchedApp.processIdentifier) + } + try await responseStream.send(response) + + guard start.waitFor else { return } + + request = try await requestStream.requiredNext + guard case .stop = request.control else { + throw GRPCStatus(code: .failedPrecondition, message: "Application has already started") + } + + try await BridgeFuture.await(launchedApp.applicationTerminated.cancel()) + + _ = try await BridgeFuture.values(completions) + } + + private func processOutputForNullDevice() -> FBProcessOutput { + return FBProcessOutput.forNullDevice() as! FBProcessOutput + } + + private func pipeOutput(interface: Idb_ProcessOutput.Interface, responseWriter: FIFOStreamWriter>) -> (FBDataConsumer & FBDataConsumerLifecycle) { + return FBBlockDataConsumer.asynchronousDataConsumer { data in + let response = Idb_LaunchResponse.with { + $0.output.data = data + $0.output.interface = interface + } + try? responseWriter.send(response) + } + } +} diff --git a/idb_companion/SwiftServer/MethodHandlers/ListAppsMethodHandler.swift b/idb_companion/SwiftServer/MethodHandlers/ListAppsMethodHandler.swift new file mode 100644 index 000000000..b1b12e85f --- /dev/null +++ b/idb_companion/SwiftServer/MethodHandlers/ListAppsMethodHandler.swift @@ -0,0 +1,41 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import CompanionLib +import FBControlCore +import Foundation +import GRPC +import IDBGRPCSwift + +struct ListAppsMethodHandler { + + let commandExecutor: FBIDBCommandExecutor + + func handle(request: Idb_ListAppsRequest, context: GRPCAsyncServerCallContext) async throws -> Idb_ListAppsResponse { + let persistedBundleIDs = commandExecutor.storageManager.application.persistedBundleIDs + let fetchAppProcessState = !request.suppressProcessState + let apps: [FBInstalledApplication: Any] = try await BridgeFuture.value(commandExecutor.list_apps(fetchAppProcessState)) + + return .with { + $0.apps = apps.map { app, processState in + .with { + $0.bundleID = app.bundle.identifier + $0.name = app.bundle.name + $0.installType = app.installTypeString + $0.architectures = app.bundle.binary?.architectures.map(\.rawValue) ?? [] + if let processID = processState as? NSNumber { + $0.processState = .running + $0.processIdentifier = processID.uint64Value + } else { + $0.processState = .unknown + } + $0.debuggable = app.installType == .userDevelopment && persistedBundleIDs.contains(app.bundle.identifier) + } + } + } + } +} diff --git a/idb_companion/SwiftServer/MethodHandlers/ListSettingsMethodHandler.swift b/idb_companion/SwiftServer/MethodHandlers/ListSettingsMethodHandler.swift new file mode 100644 index 000000000..9955d17a0 --- /dev/null +++ b/idb_companion/SwiftServer/MethodHandlers/ListSettingsMethodHandler.swift @@ -0,0 +1,26 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import CompanionLib +import GRPC +import IDBGRPCSwift + +struct ListSettingsMethodHandler { + + let commandExecutor: FBIDBCommandExecutor + + func handle(request: Idb_ListSettingRequest, context: GRPCAsyncServerCallContext) async throws -> Idb_ListSettingResponse { + switch request.setting { + case .locale: + return .with { + $0.values = commandExecutor.list_locale_identifiers() + } + case .any, .UNRECOGNIZED: + throw GRPCStatus(code: .invalidArgument, message: "Unknown setting case") + } + } +} diff --git a/idb_companion/SwiftServer/MethodHandlers/LogMethodHandler.swift b/idb_companion/SwiftServer/MethodHandlers/LogMethodHandler.swift new file mode 100644 index 000000000..2dc3c17cc --- /dev/null +++ b/idb_companion/SwiftServer/MethodHandlers/LogMethodHandler.swift @@ -0,0 +1,50 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import CompanionLib +import FBSimulatorControl +import GRPC +import IDBCompanionUtilities +import IDBGRPCSwift + +struct LogMethodHandler { + + let target: FBiOSTarget + let commandExecutor: FBIDBCommandExecutor + + func handle(request: Idb_LogRequest, responseStream: GRPCAsyncResponseStreamWriter, context: GRPCAsyncServerCallContext) async throws { + let writingDone = FBMutableFuture(name: nil) + let streamWriter = FIFOStreamWriter(stream: responseStream) + + let consumer = FBBlockDataConsumer.synchronousDataConsumer { data in + if writingDone.hasCompleted { + return + } + let response = Idb_LogResponse.with { + $0.output = data + } + do { + try streamWriter.send(response) + } catch { + writingDone.resolveWithError(error) + } + } + + let operationFuture = request.source == .companion + ? commandExecutor.tail_companion_logs(consumer) + : target.tailLog(request.arguments, consumer: consumer) + + let operation = try await BridgeFuture.value(operationFuture) + + let completed = FBFuture(race: [BridgeFuture.convertToFuture(writingDone), operation.completed]) + + try await BridgeFuture.await(completed) + writingDone.resolve(withResult: NSNull()) + + try await BridgeFuture.await(operation.completed.cancel()) + } +} diff --git a/idb_companion/SwiftServer/MethodHandlers/LsMethodHandler.swift b/idb_companion/SwiftServer/MethodHandlers/LsMethodHandler.swift new file mode 100644 index 000000000..23e8611ad --- /dev/null +++ b/idb_companion/SwiftServer/MethodHandlers/LsMethodHandler.swift @@ -0,0 +1,53 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import CompanionLib +import Foundation +import GRPC +import IDBGRPCSwift + +struct LsMethodHandler { + + let commandExecutor: FBIDBCommandExecutor + + func handle(request: Idb_LsRequest, context: GRPCAsyncServerCallContext) async throws -> Idb_LsResponse { + let fileContainer = FileContainerValueTransformer.rawFileContainer(from: request.container) + + if request.paths.isEmpty { + return try await list(path: request.path, fileContainer: fileContainer) + } else { + return try await list(pathList: request.paths, fileContainer: fileContainer) + } + } + + private func list(path: String, fileContainer: String) async throws -> Idb_LsResponse { + let paths: [String] = try await BridgeFuture.value(commandExecutor.list_path(path, containerType: fileContainer)) + + return .with { + $0.files = paths.map(toFileInfo) + } + } + + private func list(pathList: [String], fileContainer: String) async throws -> Idb_LsResponse { + let pathsToPaths: [String: [String]] = try await BridgeFuture.value(commandExecutor.list_paths(pathList, containerType: fileContainer)) + + return .with { + $0.listings = pathsToPaths.map { containerPath, paths in + .with { + $0.parent = .with { + $0.path = containerPath + } + $0.files = paths.map(toFileInfo) + } + } + } + } + + private func toFileInfo(path: String) -> Idb_FileInfo { + .with { $0.path = path } + } +} diff --git a/idb_companion/SwiftServer/MethodHandlers/MkdirMethodHandler.swift b/idb_companion/SwiftServer/MethodHandlers/MkdirMethodHandler.swift new file mode 100644 index 000000000..014bee69b --- /dev/null +++ b/idb_companion/SwiftServer/MethodHandlers/MkdirMethodHandler.swift @@ -0,0 +1,21 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import CompanionLib +import GRPC +import IDBGRPCSwift + +struct MkdirMethodHandler { + + let commandExecutor: FBIDBCommandExecutor + + func handle(request: Idb_MkdirRequest, context: GRPCAsyncServerCallContext) async throws -> Idb_MkdirResponse { + let fileContainer = FileContainerValueTransformer.rawFileContainer(from: request.container) + try await BridgeFuture.await(commandExecutor.create_directory(request.path, containerType: fileContainer)) + return .init() + } +} diff --git a/idb_companion/SwiftServer/MethodHandlers/MvMethodHandler.swift b/idb_companion/SwiftServer/MethodHandlers/MvMethodHandler.swift new file mode 100644 index 000000000..3bb34820f --- /dev/null +++ b/idb_companion/SwiftServer/MethodHandlers/MvMethodHandler.swift @@ -0,0 +1,21 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import CompanionLib +import GRPC +import IDBGRPCSwift + +struct MvMethodHandler { + + let commandExecutor: FBIDBCommandExecutor + + func handle(request: Idb_MvRequest, context: GRPCAsyncServerCallContext) async throws -> Idb_MvResponse { + let fileContainer = FileContainerValueTransformer.rawFileContainer(from: request.container) + try await BridgeFuture.await(commandExecutor.move_paths(request.srcPaths, to_path: request.dstPath, containerType: fileContainer)) + return .init() + } +} diff --git a/idb_companion/SwiftServer/MethodHandlers/OpenUrlMethodHandler.swift b/idb_companion/SwiftServer/MethodHandlers/OpenUrlMethodHandler.swift new file mode 100644 index 000000000..7ffc4698a --- /dev/null +++ b/idb_companion/SwiftServer/MethodHandlers/OpenUrlMethodHandler.swift @@ -0,0 +1,20 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import CompanionLib +import GRPC +import IDBGRPCSwift + +struct OpenUrlMethodHandler { + + let commandExecutor: FBIDBCommandExecutor + + func handle(request: Idb_OpenUrlRequest, context: GRPCAsyncServerCallContext) async throws -> Idb_OpenUrlRequest { + try await BridgeFuture.await(commandExecutor.open_url(request.url)) + return .init() + } +} diff --git a/idb_companion/SwiftServer/MethodHandlers/PullMethodHandler.swift b/idb_companion/SwiftServer/MethodHandlers/PullMethodHandler.swift new file mode 100644 index 000000000..fd53cdd54 --- /dev/null +++ b/idb_companion/SwiftServer/MethodHandlers/PullMethodHandler.swift @@ -0,0 +1,63 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import CompanionLib +import FBSimulatorControl +import Foundation +import GRPC +import IDBGRPCSwift + +struct PullMethodHandler { + + let target: FBiOSTarget + let commandExecutor: FBIDBCommandExecutor + + func handle(request: Idb_PullRequest, responseStream: GRPCAsyncResponseStreamWriter, context: GRPCAsyncServerCallContext) async throws { + if request.dstPath.isEmpty { + try await sendRawData(request: request, responseStream: responseStream) + } else { + try await sendFilePath(request: request, responseStream: responseStream) + } + } + + private func sendRawData(request: Idb_PullRequest, responseStream: GRPCAsyncResponseStreamWriter) async throws { + guard let logger = target.logger else { + throw GRPCStatus(code: .internalError, message: "Internal logger not configured") + } + let path = request.srcPath as NSString + let fileContainer = FileContainerValueTransformer.rawFileContainer(from: request.container) + let url = commandExecutor.temporaryDirectory.temporaryDirectory() + let tempPath = url.appendingPathComponent(path.lastPathComponent).path + + let filePath = try await BridgeFuture.value( + commandExecutor.pull_file_path(request.srcPath, + destination_path: tempPath, + containerType: fileContainer) + ) + + let archiveFuture = FBArchiveOperations.createGzippedTar(forPath: filePath as String, logger: logger) + + try await FileDrainWriter.performDrain(taskFuture: archiveFuture) { data in + let response = Idb_PullResponse.with { $0.payload.data = data } + try await responseStream.send(response) + } + } + + private func sendFilePath(request: Idb_PullRequest, responseStream: GRPCAsyncResponseStreamWriter) async throws { + let fileContainer = FileContainerValueTransformer.rawFileContainer(from: request.container) + + let filePath = try await BridgeFuture.value( + commandExecutor.pull_file_path(request.srcPath, + destination_path: request.dstPath, + containerType: fileContainer) + ) as String + let response = Idb_PullResponse.with { + $0.payload = .with { $0.source = .filePath(filePath) } + } + try await responseStream.send(response) + } +} diff --git a/idb_companion/SwiftServer/MethodHandlers/PushMethodHandler.swift b/idb_companion/SwiftServer/MethodHandlers/PushMethodHandler.swift new file mode 100644 index 000000000..d4736faea --- /dev/null +++ b/idb_companion/SwiftServer/MethodHandlers/PushMethodHandler.swift @@ -0,0 +1,34 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import CompanionLib +import FBControlCore +import GRPC +import IDBGRPCSwift + +struct PushMethodHandler { + + let target: FBiOSTarget + let commandExecutor: FBIDBCommandExecutor + + func handle(requestStream: GRPCAsyncRequestStream, context: GRPCAsyncServerCallContext) async throws -> Idb_PushResponse { + let request = try await requestStream.requiredNext + + guard case let .inner(inner) = request.value + else { throw GRPCStatus(code: .invalidArgument, message: "Expected inner as first request in stream") } + + let extractedFileURLs = try await MultisourceFileReader + .filePathURLs(from: requestStream, temporaryDirectory: commandExecutor.temporaryDirectory, extractFromSubdir: false) + + let fileContainer = FileContainerValueTransformer.rawFileContainer(from: inner.container) + try await BridgeFuture.await( + commandExecutor.push_files(extractedFileURLs, to_path: inner.dstPath, containerType: fileContainer) + ) + + return .init() + } +} diff --git a/idb_companion/SwiftServer/MethodHandlers/RecordMethodHandler.swift b/idb_companion/SwiftServer/MethodHandlers/RecordMethodHandler.swift new file mode 100644 index 000000000..91dd956d0 --- /dev/null +++ b/idb_companion/SwiftServer/MethodHandlers/RecordMethodHandler.swift @@ -0,0 +1,49 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import CompanionLib +import GRPC +import IDBGRPCSwift + +struct RecordMethodHandler { + + let target: FBiOSTarget + let targetLogger: FBControlCoreLogger + + func handle(requestStream: GRPCAsyncRequestStream, responseStream: GRPCAsyncResponseStreamWriter, context: GRPCAsyncServerCallContext) async throws { + + let request = try await requestStream.requiredNext + guard case let .start(start) = request.control + else { throw GRPCStatus(code: .failedPrecondition, message: "Expect start as initial request frame") } + + let filePath = + start.filePath.isEmpty + ? URL(fileURLWithPath: target.auxillaryDirectory).appendingPathComponent("idb_encode").appendingPathExtension("mp4").path + : start.filePath + + _ = try await BridgeFuture.value(target.startRecording(toFile: filePath)) + + _ = try await requestStream.requiredNext + try await BridgeFuture.await(target.stopRecording()) + + if start.filePath.isEmpty { + let gzipTask = FBArchiveOperations.createGzip(forPath: filePath, + queue: BridgeQueues.miscEventReaderQueue, + logger: targetLogger) + + try await FileDrainWriter.performDrain(taskFuture: gzipTask) { data in + let response = Idb_RecordResponse.with { $0.payload.data = data } + try await responseStream.send(response) + } + } else { + let response = Idb_RecordResponse.with { + $0.output = .payload(.with { $0.source = .filePath(start.filePath) }) + } + try await responseStream.send(response) + } + } +} diff --git a/idb_companion/SwiftServer/MethodHandlers/RevokeMethodHandler.swift b/idb_companion/SwiftServer/MethodHandlers/RevokeMethodHandler.swift new file mode 100644 index 000000000..f9a07f9ff --- /dev/null +++ b/idb_companion/SwiftServer/MethodHandlers/RevokeMethodHandler.swift @@ -0,0 +1,50 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import CompanionLib +import GRPC +import IDBGRPCSwift + +struct RevokeMethodHandler { + + let commandExecutor: FBIDBCommandExecutor + + func handle(request: Idb_RevokeRequest, context: GRPCAsyncServerCallContext) async throws -> Idb_RevokeResponse { + + // Swift implements custom bridging logic for NSNotificationName and this causes ALL string enums ended with "Notification" + // suffix translates in this special way + let notificationApprovalService = FBTargetSettingsService.FBTargetSettingsService + + let mapping: [Idb_RevokeRequest.Permission: FBTargetSettingsService] = [ + .microphone: .microphone, + .photos: .photos, + .camera: .camera, + .contacts: .contacts, + .url: .url, + .location: .location, + .notification: notificationApprovalService, + ] + + var services = try Set( + request.permissions.map { permission -> FBTargetSettingsService in + guard let service = mapping[permission] else { + throw GRPCStatus(code: .invalidArgument, message: "Unrecognized permission \(permission)") + } + return service + } + ) + if services.contains(.url) { + services.remove(.url) + try await BridgeFuture.await(commandExecutor.revoke_deeplink(request.scheme, for_application: request.bundleID)) + } + + if !services.isEmpty { + try await BridgeFuture.await(commandExecutor.revoke(services, for_application: request.bundleID)) + } + return .init() + } +} diff --git a/idb_companion/SwiftServer/MethodHandlers/RmMethodHandler.swift b/idb_companion/SwiftServer/MethodHandlers/RmMethodHandler.swift new file mode 100644 index 000000000..5660ff244 --- /dev/null +++ b/idb_companion/SwiftServer/MethodHandlers/RmMethodHandler.swift @@ -0,0 +1,21 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import CompanionLib +import GRPC +import IDBGRPCSwift + +struct RmMethodHandler { + + let commandExecutor: FBIDBCommandExecutor + + func handle(request: Idb_RmRequest, context: GRPCAsyncServerCallContext) async throws -> Idb_RmResponse { + let fileContainer = FileContainerValueTransformer.rawFileContainer(from: request.container) + try await BridgeFuture.await(commandExecutor.remove_paths(request.paths, containerType: fileContainer)) + return .init() + } +} diff --git a/idb_companion/SwiftServer/MethodHandlers/ScreenshotMethodHandler.swift b/idb_companion/SwiftServer/MethodHandlers/ScreenshotMethodHandler.swift new file mode 100644 index 000000000..c54e55720 --- /dev/null +++ b/idb_companion/SwiftServer/MethodHandlers/ScreenshotMethodHandler.swift @@ -0,0 +1,22 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import CompanionLib +import GRPC +import IDBGRPCSwift + +struct ScreenshotMethodHandler { + + let commandExecutor: FBIDBCommandExecutor + + func handle(request: Idb_ScreenshotRequest, context: GRPCAsyncServerCallContext) async throws -> Idb_ScreenshotResponse { + let screenshot = try await BridgeFuture.value(commandExecutor.take_screenshot(.PNG)) + return .with { + $0.imageData = screenshot as Data + } + } +} diff --git a/idb_companion/SwiftServer/MethodHandlers/SendNotificationMethodHandler.swift b/idb_companion/SwiftServer/MethodHandlers/SendNotificationMethodHandler.swift new file mode 100644 index 000000000..5bc53da10 --- /dev/null +++ b/idb_companion/SwiftServer/MethodHandlers/SendNotificationMethodHandler.swift @@ -0,0 +1,20 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import CompanionLib +import GRPC +import IDBGRPCSwift + +struct SendNotificationMethodHandler { + + let commandExecutor: FBIDBCommandExecutor + + func handle(request: Idb_SendNotificationRequest, context: GRPCAsyncServerCallContext) async throws -> Idb_SendNotificationResponse { + try await BridgeFuture.await(commandExecutor.sendPushNotification(forBundleID: request.bundleID, jsonPayload: request.jsonPayload)) + return .init() + } +} diff --git a/idb_companion/SwiftServer/MethodHandlers/SetLocationMethodHandler.swift b/idb_companion/SwiftServer/MethodHandlers/SetLocationMethodHandler.swift new file mode 100644 index 000000000..a34d3b901 --- /dev/null +++ b/idb_companion/SwiftServer/MethodHandlers/SetLocationMethodHandler.swift @@ -0,0 +1,20 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import CompanionLib +import GRPC +import IDBGRPCSwift + +struct SetLocationMethodHandler { + + let commandExecutor: FBIDBCommandExecutor + + func handle(request: Idb_SetLocationRequest, context: GRPCAsyncServerCallContext) async throws -> Idb_SetLocationResponse { + try await BridgeFuture.await(commandExecutor.set_location(request.location.latitude, longitude: request.location.longitude)) + return .init() + } +} diff --git a/idb_companion/SwiftServer/MethodHandlers/SettingMethodHandler.swift b/idb_companion/SwiftServer/MethodHandlers/SettingMethodHandler.swift new file mode 100644 index 000000000..bbd300e5d --- /dev/null +++ b/idb_companion/SwiftServer/MethodHandlers/SettingMethodHandler.swift @@ -0,0 +1,40 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import CompanionLib +import GRPC +import IDBGRPCSwift + +struct SettingMethodHandler { + + let commandExecutor: FBIDBCommandExecutor + + func handle(request: Idb_SettingRequest, context: GRPCAsyncServerCallContext) async throws -> Idb_SettingResponse { + switch request.setting { + case let .hardwareKeyboard(hardwareKeyboard): + try await BridgeFuture.await(commandExecutor.set_hardware_keyboard_enabled(hardwareKeyboard.enabled)) + + case let .stringSetting(stringSetting): + switch stringSetting.setting { + case .locale: + try await BridgeFuture.await(commandExecutor.set_locale_with_identifier(stringSetting.value)) + + case .any: + let domain = stringSetting.domain.isEmpty ? nil : stringSetting.domain + let type = stringSetting.valueType.isEmpty ? nil : stringSetting.valueType + try await BridgeFuture.await(commandExecutor.set_preference(stringSetting.name, value: stringSetting.value, type: type, domain: domain)) + + case .UNRECOGNIZED: + throw GRPCStatus(code: .invalidArgument, message: "Unknown setting case") + } + case .none: + throw GRPCStatus(code: .invalidArgument, message: "Unknown setting case") + } + + return .init() + } +} diff --git a/idb_companion/SwiftServer/MethodHandlers/SimulateMemoryWarningMethodHandler.swift b/idb_companion/SwiftServer/MethodHandlers/SimulateMemoryWarningMethodHandler.swift new file mode 100644 index 000000000..91adc49fe --- /dev/null +++ b/idb_companion/SwiftServer/MethodHandlers/SimulateMemoryWarningMethodHandler.swift @@ -0,0 +1,20 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import CompanionLib +import GRPC +import IDBGRPCSwift + +struct SimulateMemoryWarningMethodHandler { + + let commandExecutor: FBIDBCommandExecutor + + func handle(request: Idb_SimulateMemoryWarningRequest, context: GRPCAsyncServerCallContext) async throws -> Idb_SimulateMemoryWarningResponse { + try await BridgeFuture.await(commandExecutor.simulateMemoryWarning()) + return .init() + } +} diff --git a/idb_companion/SwiftServer/MethodHandlers/TailMethodHandler.swift b/idb_companion/SwiftServer/MethodHandlers/TailMethodHandler.swift new file mode 100644 index 000000000..687ce2340 --- /dev/null +++ b/idb_companion/SwiftServer/MethodHandlers/TailMethodHandler.swift @@ -0,0 +1,46 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import CompanionLib +import FBSimulatorControl +import GRPC +import IDBCompanionUtilities +import IDBGRPCSwift + +struct TailMethodHandler { + + let commandExecutor: FBIDBCommandExecutor + + func handle(requestStream: GRPCAsyncRequestStream, responseStream: GRPCAsyncResponseStreamWriter, context: GRPCAsyncServerCallContext) async throws { + @Atomic var finished = false + + guard case let .start(start) = try await requestStream.requiredNext.control + else { throw GRPCStatus(code: .failedPrecondition, message: "Expected start control") } + + let responseWriter = FIFOStreamWriter(stream: responseStream) + let consumer = FBBlockDataConsumer.asynchronousDataConsumer { data in + guard !finished else { return } + let response = Idb_TailResponse.with { + $0.data = data + } + do { + try responseWriter.send(response) + } catch { + _finished.set(true) + } + } + + let fileContainer = FileContainerValueTransformer.rawFileContainer(from: start.container) + let tail = try await BridgeFuture.value(commandExecutor.tail(start.path, to_consumer: consumer, in_container: fileContainer)) + + guard case .stop = try await requestStream.requiredNext.control + else { throw GRPCStatus(code: .failedPrecondition, message: "Expected end control") } + + try await BridgeFuture.await(tail.cancel()) + _finished.set(true) + } +} diff --git a/idb_companion/SwiftServer/MethodHandlers/TerminateMethodHandler.swift b/idb_companion/SwiftServer/MethodHandlers/TerminateMethodHandler.swift new file mode 100644 index 000000000..6986d354e --- /dev/null +++ b/idb_companion/SwiftServer/MethodHandlers/TerminateMethodHandler.swift @@ -0,0 +1,20 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import CompanionLib +import GRPC +import IDBGRPCSwift + +struct TerminateMethodHandler { + + let commandExecutor: FBIDBCommandExecutor + + func handle(request: Idb_TerminateRequest, context: GRPCAsyncServerCallContext) async throws -> Idb_TerminateResponse { + try await BridgeFuture.await(commandExecutor.kill_application(request.bundleID)) + return .init() + } +} diff --git a/idb_companion/SwiftServer/MethodHandlers/UninstallMethodHandler.swift b/idb_companion/SwiftServer/MethodHandlers/UninstallMethodHandler.swift new file mode 100644 index 000000000..f0ba98f11 --- /dev/null +++ b/idb_companion/SwiftServer/MethodHandlers/UninstallMethodHandler.swift @@ -0,0 +1,20 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import CompanionLib +import GRPC +import IDBGRPCSwift + +struct UninstallMethodHandler { + + let commandExecutor: FBIDBCommandExecutor + + func handle(request: Idb_UninstallRequest, context: GRPCAsyncServerCallContext) async throws -> Idb_UninstallResponse { + try await BridgeFuture.await(commandExecutor.uninstall_application(request.bundleID)) + return .init() + } +} diff --git a/idb_companion/SwiftServer/MethodHandlers/VideoStreamMethodHandler.swift b/idb_companion/SwiftServer/MethodHandlers/VideoStreamMethodHandler.swift new file mode 100644 index 000000000..55ed73b13 --- /dev/null +++ b/idb_companion/SwiftServer/MethodHandlers/VideoStreamMethodHandler.swift @@ -0,0 +1,105 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import CompanionLib +import FBSimulatorControl +import GRPC +import IDBCompanionUtilities +import IDBGRPCSwift + +struct VideoStreamMethodHandler { + + let target: FBiOSTarget + let targetLogger: FBControlCoreLogger + let commandExecutor: FBIDBCommandExecutor + + func handle(requestStream: GRPCAsyncRequestStream, responseStream: GRPCAsyncResponseStreamWriter, context: GRPCAsyncServerCallContext) async throws { + @Atomic var finished = false + + guard case let .start(start) = try await requestStream.requiredNext.control + else { throw GRPCStatus(code: .failedPrecondition, message: "Expected start control") } + + let videoStream = try await startVideoStream(request: start, + responseStream: responseStream, + finished: _finished) + + let observeClientCancelStreaming = Task { + for try await request in requestStream { + switch request.control { + case .start: + throw GRPCStatus(code: .failedPrecondition, message: "Video streaming already started") + case .stop: + return + case .none: + throw GRPCStatus(code: .invalidArgument, message: "Client should not close request stream explicitly, send `stop` frame first") + } + } + } + + let observeVideoStreamStop = Task { + try await BridgeFuture.await(videoStream.completed) + } + + try await Task.select(observeClientCancelStreaming, observeVideoStreamStop).value + + try await BridgeFuture.await(videoStream.stopStreaming()) + targetLogger.log("The video stream is terminated") + } + + private func startVideoStream(request start: Idb_VideoStreamRequest.Start, responseStream: GRPCAsyncResponseStreamWriter, finished: Atomic) async throws -> FBVideoStream { + let consumer: FBDataConsumer + + if start.filePath.isEmpty { + let responseWriter = FIFOStreamWriter(stream: responseStream) + + consumer = FBBlockDataConsumer.asynchronousDataConsumer { data in + guard !finished.wrappedValue else { return } + let response = Idb_VideoStreamResponse.with { + $0.payload.data = data + } + do { + try responseWriter.send(response) + } catch { + finished.set(true) + } + } + } else { + consumer = try FBFileWriter.syncWriter(forFilePath: start.filePath) + } + + let framesPerSecond = start.fps > 0 ? NSNumber(value: start.fps) : nil + let avgBitrate = start.avgBitrate > 0 ? NSNumber(value: start.avgBitrate) : nil + let encoding = try streamEncoding(from: start.format) + let config = FBVideoStreamConfiguration(encoding: encoding, + framesPerSecond: framesPerSecond, + compressionQuality: .init(value: start.compressionQuality), + scaleFactor: .init(value: start.scaleFactor), + avgBitrate: avgBitrate, + keyFrameRate: .init(value: start.keyFrameRate)) + + let videoStream = try await BridgeFuture.value(target.createStream(with: config)) + + try await BridgeFuture.await(videoStream.startStreaming(consumer)) + + return videoStream + } + + private func streamEncoding(from requestFormat: Idb_VideoStreamRequest.Format) throws -> FBVideoStreamEncoding { + switch requestFormat { + case .h264: + return .H264 + case .rbga: + return .BGRA + case .mjpeg: + return .MJPEG + case .minicap: + return .minicap + case .i420, .UNRECOGNIZED: + throw GRPCStatus(code: .invalidArgument, message: "Unrecognized video format") + } + } +} diff --git a/idb_companion/SwiftServer/MethodHandlers/XCTestListBundlesMethodHandler.swift b/idb_companion/SwiftServer/MethodHandlers/XCTestListBundlesMethodHandler.swift new file mode 100644 index 000000000..1a4f07db2 --- /dev/null +++ b/idb_companion/SwiftServer/MethodHandlers/XCTestListBundlesMethodHandler.swift @@ -0,0 +1,34 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import CompanionLib +import FBSimulatorControl +import Foundation +import GRPC +import IDBGRPCSwift +import XCTestBootstrap + +struct XCTestListBundlesMethodHandler { + + let commandExecutor: FBIDBCommandExecutor + + func handle(request: Idb_XctestListBundlesRequest, context: GRPCAsyncServerCallContext) async throws -> Idb_XctestListBundlesResponse { + let descriptors: [FBXCTestDescriptor] = try await BridgeFuture.value( + commandExecutor.list_test_bundles() + ) + return .with { + $0.bundles = descriptors.map(toBundle(descriptor:)) + } + } + private func toBundle(descriptor: FBXCTestDescriptor) -> Idb_XctestListBundlesResponse.Bundles { + return .with { + $0.name = descriptor.name + $0.bundleID = descriptor.testBundleID + $0.architectures = Array(descriptor.architectures) + } + } +} diff --git a/idb_companion/SwiftServer/MethodHandlers/XCTestListTestsMethodHandler.swift b/idb_companion/SwiftServer/MethodHandlers/XCTestListTestsMethodHandler.swift new file mode 100644 index 000000000..d1372af63 --- /dev/null +++ b/idb_companion/SwiftServer/MethodHandlers/XCTestListTestsMethodHandler.swift @@ -0,0 +1,26 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import CompanionLib +import FBSimulatorControl +import Foundation +import GRPC +import IDBGRPCSwift + +struct XCTestListTestsMethodHandler { + + let commandExecutor: FBIDBCommandExecutor + + func handle(request: Idb_XctestListTestsRequest, context: GRPCAsyncServerCallContext) async throws -> Idb_XctestListTestsResponse { + let tests: [String] = try await BridgeFuture.value( + commandExecutor.list_tests_(in_bundle: request.bundleName, with_app: request.appPath) + ) + return .with { + $0.names = tests + } + } +} diff --git a/idb_companion/SwiftServer/MethodHandlers/XCTestRunMethodHandler.swift b/idb_companion/SwiftServer/MethodHandlers/XCTestRunMethodHandler.swift new file mode 100644 index 000000000..4cac09078 --- /dev/null +++ b/idb_companion/SwiftServer/MethodHandlers/XCTestRunMethodHandler.swift @@ -0,0 +1,108 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import CompanionLib +import FBSimulatorControl +import Foundation +import GRPC +import IDBGRPCSwift + +struct XCTestRunMethodHandler { + + let target: FBiOSTarget + let commandExecutor: FBIDBCommandExecutor + let reporter: FBEventReporter + let targetLogger: FBControlCoreLogger + let logger: FBIDBLogger + + func handle(request: Idb_XctestRunRequest, responseStream: GRPCAsyncResponseStreamWriter, context: GRPCAsyncServerCallContext) async throws { + guard let request = transform(value: request) else { + throw GRPCStatus(code: .invalidArgument, message: "failed to create FBXCTestRunRequest") + } + + let reporter = IDBXCTestReporter(responseStream: responseStream, queue: target.workQueue, logger: logger) + + let operationFuture = commandExecutor.xctest_run(request, + reporter: reporter, + logger: FBControlCoreLoggerFactory.logger(to: reporter)) + let operation = try await BridgeFuture.value(operationFuture) + reporter.configuration = .init(legacy: operation.reporterConfiguration) + + do { + try await BridgeFuture.await(operation.completed) + } catch let error as NSError { + // We should ignore errors that came from test binary. Like when exception is throwed or binary crashed. + if error.domain != FBTestErrorDomain { + throw error + } + } + + _ = try await BridgeFuture.value(reporter.reportingTerminated) + } + + func transform(value request: Idb_XctestRunRequest) -> FBXCTestRunRequest? { + let testsToRun = request.testsToRun.isEmpty ? nil : Set(request.testsToRun) + switch request.mode.mode { + case .logic: + return FBXCTestRunRequest.logicTest(withTestBundleID: request.testBundleID, + environment: request.environment, + arguments: request.arguments, + testsToRun: testsToRun, + testsToSkip: Set(request.testsToSkip), + testTimeout: request.timeout as NSNumber, + reportActivities: request.reportActivities, + reportAttachments: request.reportAttachments, + coverageRequest: extractCodeCoverage(from: request), + collectLogs: request.collectLogs, + waitForDebugger: request.waitForDebugger, + collectResultBundle: request.collectResultBundle) + case let .application(app): + return FBXCTestRunRequest.applicationTest(withTestBundleID: request.testBundleID, + testHostAppBundleID: app.appBundleID, + environment: request.environment, + arguments: request.arguments, + testsToRun: testsToRun, + testsToSkip: Set(request.testsToSkip), + testTimeout: request.timeout as NSNumber, + reportActivities: request.reportActivities, + reportAttachments: request.reportAttachments, + coverageRequest: extractCodeCoverage(from: request), + collectLogs: request.collectLogs, + waitForDebugger: request.waitForDebugger, + collectResultBundle: request.collectResultBundle) + case let .ui(ui): + return FBXCTestRunRequest.uiTest(withTestBundleID: request.testBundleID, + testHostAppBundleID: ui.testHostAppBundleID, + testTargetAppBundleID: ui.appBundleID, + environment: request.environment, + arguments: request.arguments, + testsToRun: testsToRun, + testsToSkip: Set(request.testsToSkip), + testTimeout: request.timeout as NSNumber, + reportActivities: request.reportActivities, + reportAttachments: request.reportAttachments, + coverageRequest: extractCodeCoverage(from: request), + collectLogs: request.collectLogs, + collectResultBundle: request.collectResultBundle) + case .none: + return nil + } + } + + private func extractCodeCoverage(from request: Idb_XctestRunRequest) -> FBCodeCoverageRequest { + if request.hasCodeCoverage { + switch request.codeCoverage.format { + case .raw: + return FBCodeCoverageRequest(collect: request.codeCoverage.collect, format: .raw, enableContinuousCoverageCollection: request.codeCoverage.enableContinuousCoverageCollection) + case .exported, .UNRECOGNIZED: + return FBCodeCoverageRequest(collect: request.codeCoverage.collect, format: .exported, enableContinuousCoverageCollection: request.codeCoverage.enableContinuousCoverageCollection) + } + } + // fallback to deprecated request field for backwards compatibility + return FBCodeCoverageRequest(collect: request.collectCoverage, format: .exported, enableContinuousCoverageCollection: request.codeCoverage.enableContinuousCoverageCollection) + } +} diff --git a/idb_companion/SwiftServer/MethodHandlers/XctraceRecordMethodHandler.swift b/idb_companion/SwiftServer/MethodHandlers/XctraceRecordMethodHandler.swift new file mode 100644 index 000000000..dea5d1a4f --- /dev/null +++ b/idb_companion/SwiftServer/MethodHandlers/XctraceRecordMethodHandler.swift @@ -0,0 +1,116 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import CompanionLib +import FBSimulatorControl +import GRPC +import IDBCompanionUtilities +import IDBGRPCSwift + +struct XctraceRecordMethodHandler { + + let logger: FBControlCoreLogger + let targetLogger: FBControlCoreLogger + let target: FBiOSTarget + + func handle(requestStream: GRPCAsyncRequestStream, responseStream: GRPCAsyncResponseStreamWriter, context: GRPCAsyncServerCallContext) async throws { + + @Atomic var finishedWriting = false + defer { _finishedWriting.set(true) } + + guard case let .start(start) = try await requestStream.requiredNext.control + else { throw GRPCStatus(code: .failedPrecondition, message: "Expected start control") } + let operation = try await startXCTraceOperation(request: start, responseStream: responseStream, finishedWriting: _finishedWriting) + + guard case let .stop(stop) = try await requestStream.requiredNext.control + else { throw GRPCStatus(code: .failedPrecondition, message: "Expected end control") } + + try await stopXCTrace(operation: operation, request: stop, responseStream: responseStream, finishedWriting: _finishedWriting) + } + + private func startXCTraceOperation(request start: Idb_XctraceRecordRequest.Start, responseStream: GRPCAsyncResponseStreamWriter, finishedWriting: Atomic) async throws -> FBXCTraceRecordOperation { + let config = xcTraceRecordConfiguration(from: start) + + let responseWriter = FIFOStreamWriter(stream: responseStream) + let consumer = FBBlockDataConsumer.asynchronousDataConsumer { data in + guard !finishedWriting.wrappedValue else { return } + + let response = Idb_XctraceRecordResponse.with { + $0.log = data + } + do { + try responseWriter.send(response) + } catch { + finishedWriting.set(true) + } + } + + let logger = FBControlCoreLoggerFactory.compositeLogger(with: [ + FBControlCoreLoggerFactory.logger(to: consumer), + targetLogger, + ].compactMap({ $0 })) + + let operation = try await BridgeFuture.value(target.startXctraceRecord(config, logger: logger)) + let response = Idb_XctraceRecordResponse.with { + $0.state = .running + } + try await responseStream.send(response) + + return operation + } + + private func stopXCTrace(operation: FBXCTraceRecordOperation, request stop: Idb_XctraceRecordRequest.Stop, responseStream: GRPCAsyncResponseStreamWriter, finishedWriting: Atomic) async throws { + let stopTimeout = stop.timeout != 0 ? stop.timeout : DefaultXCTraceRecordStopTimeout + _ = try await BridgeFuture.value(operation.stop(withTimeout: stopTimeout)) + let response = Idb_XctraceRecordResponse.with { + $0.state = .processing + } + try await responseStream.send(response) + + let processed = try await BridgeFuture.value( + FBInstrumentsOperation.postProcess(stop.args, + traceDir: operation.traceDir, + queue: BridgeQueues.miscEventReaderQueue, + logger: logger) + ) + finishedWriting.set(true) + + guard let path = processed.path else { + throw GRPCStatus(code: .internalError, message: "Unable to get post process file path") + } + + let data = try await BridgeFuture.value(FBArchiveOperations.createGzippedTarData(forPath: path, queue: BridgeQueues.futureSerialFullfillmentQueue, logger: targetLogger)) + let resp = Idb_XctraceRecordResponse.with { + $0.payload = .with { $0.data = data as Data } + } + try await responseStream.send(resp) + + let createTarOperation = FBArchiveOperations.createGzippedTar(forPath: path, logger: logger) + try await FileDrainWriter.performDrain(taskFuture: createTarOperation) { data in + let response = Idb_XctraceRecordResponse.with { + $0.payload = .with { $0.data = data } + } + try await responseStream.send(response) + } + } + + private func xcTraceRecordConfiguration(from request: Idb_XctraceRecordRequest.Start) -> FBXCTraceRecordConfiguration { + let timeLimit = request.timeLimit != 0 ? request.timeLimit : DefaultXCTraceRecordOperationTimeLimit + + return .init(templateName: request.templateName, + timeLimit: timeLimit, + package: request.package, + allProcesses: request.target.allProcesses, + processToAttach: request.target.processToAttach, + processToLaunch: request.target.launchProcess.processToLaunch, + launchArgs: request.target.launchProcess.launchArgs, + targetStdin: request.target.launchProcess.targetStdin, + targetStdout: request.target.launchProcess.targetStdout, + processEnv: request.target.launchProcess.processEnv, + shim: nil) + } +} diff --git a/idb_companion/SwiftServer/ValueTransformers/CrashLogInfoValueTransformer.swift b/idb_companion/SwiftServer/ValueTransformers/CrashLogInfoValueTransformer.swift new file mode 100644 index 000000000..2a689524b --- /dev/null +++ b/idb_companion/SwiftServer/ValueTransformers/CrashLogInfoValueTransformer.swift @@ -0,0 +1,23 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import FBSimulatorControl +import IDBGRPCSwift + +enum CrashLogInfoValueTransformer { + + static func responseCrashLogInfo(from crash: FBCrashLogInfo) -> Idb_CrashLogInfo { + return .with { + $0.name = crash.name + $0.processName = crash.processName + $0.parentProcessName = crash.parentProcessName + $0.processIdentifier = UInt64(crash.processIdentifier) + $0.parentProcessIdentifier = UInt64(crash.parentProcessIdentifier) + $0.timestamp = UInt64(crash.date.timeIntervalSince1970) + } + } +} diff --git a/idb_companion/SwiftServer/ValueTransformers/CrashLogQueryValueTransformer.swift b/idb_companion/SwiftServer/ValueTransformers/CrashLogQueryValueTransformer.swift new file mode 100644 index 000000000..159938e22 --- /dev/null +++ b/idb_companion/SwiftServer/ValueTransformers/CrashLogQueryValueTransformer.swift @@ -0,0 +1,32 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import FBControlCore +import IDBGRPCSwift + +enum CrashLogQueryValueTransformer { + + static func predicate(from request: Idb_CrashLogQuery) -> NSPredicate { + var subpredicates: [NSPredicate] = [] + if request.since != 0 { + subpredicates.append(FBCrashLogInfo.predicateNewerThanDate(Date(timeIntervalSince1970: TimeInterval(request.since)))) + } + if request.before != 0 { + subpredicates.append(FBCrashLogInfo.predicateOlderThanDate(Date(timeIntervalSince1970: TimeInterval(request.before)))) + } + if !request.bundleID.isEmpty { + subpredicates.append(FBCrashLogInfo.predicate(forIdentifier: request.bundleID)) + } + if !request.name.isEmpty { + subpredicates.append(FBCrashLogInfo.predicate(forName: request.name)) + } + if subpredicates.isEmpty { + return NSPredicate(value: true) + } + return NSCompoundPredicate(andPredicateWithSubpredicates: subpredicates) + } +} diff --git a/idb_companion/SwiftServer/ValueTransformers/FileContainerValueTransformer.swift b/idb_companion/SwiftServer/ValueTransformers/FileContainerValueTransformer.swift new file mode 100644 index 000000000..c6fe61e86 --- /dev/null +++ b/idb_companion/SwiftServer/ValueTransformers/FileContainerValueTransformer.swift @@ -0,0 +1,56 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import FBControlCore +import Foundation +import IDBGRPCSwift + +struct FileContainerValueTransformer { + + static func rawFileContainer(from proto: Idb_FileContainer) -> String { + return fileContainer(from: proto.kind)?.rawValue ?? proto.bundleID + } + + static func fileContainer(from proto: Idb_FileContainer.Kind) -> FBFileContainerKind? { + switch proto { + case .root: + return .root + case .media: + return .media + case .crashes: + return .crashes + case .provisioningProfiles: + return .provisioningProfiles + case .mdmProfiles: + return .mdmProfiles + case .springboardIcons: + return .springboardIcons + case .wallpaper: + return .wallpaper + case .diskImages: + return .diskImages + case .groupContainer: + return .group + case .applicationContainer: + return .application + case .auxillary: + return .auxillary + case .xctest: + return .xctest + case .dylib: + return .dylib + case .dsym: + return .dsym + case .framework: + return .framework + case .symbols: + return .symbols + case .application, .none, .UNRECOGNIZED: + return nil + } + } +} diff --git a/idb_companion/SwiftServer/ValueTransformers/GrpcDataMappings.swift b/idb_companion/SwiftServer/ValueTransformers/GrpcDataMappings.swift new file mode 100644 index 000000000..0417d2ec5 --- /dev/null +++ b/idb_companion/SwiftServer/ValueTransformers/GrpcDataMappings.swift @@ -0,0 +1,67 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import Foundation +import IDBGRPCSwift + +// Convenient extractions of items from certain requests + +protocol DataExtractable { + func extractDataFrame() -> Data? +} + +protocol PayloadExtractable: DataExtractable { + func extractPayload() -> Idb_Payload? +} + +extension Idb_InstallRequest: PayloadExtractable { + func extractPayload() -> Idb_Payload? { + switch value { + case .payload(let payload): + return payload + default: + return nil + } + } +} + +extension Idb_PushRequest: PayloadExtractable { + func extractPayload() -> Idb_Payload? { + switch value { + case .payload(let payload): + return payload + default: + return nil + } + } +} + +extension Idb_AddMediaRequest: PayloadExtractable { + func extractPayload() -> Idb_Payload? { + if hasPayload { + return payload + } + return nil + } +} + +extension PayloadExtractable { + func extractDataFrame() -> Data? { + extractPayload()?.extractDataFrame() + } +} + +extension Idb_Payload: DataExtractable { + func extractDataFrame() -> Data? { + switch source { + case let .data(data): + return data + default: + return nil + } + } +} diff --git a/idb_companion/Utility/AsyncSequence+Extension.swift b/idb_companion/Utility/AsyncSequence+Extension.swift new file mode 100644 index 000000000..5051d98c9 --- /dev/null +++ b/idb_companion/Utility/AsyncSequence+Extension.swift @@ -0,0 +1,34 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import Foundation +import GRPC + +enum StreamReadError: Error, GRPCStatusTransformable { + case nextElementNotProduced + + func makeGRPCStatus() -> GRPCStatus { + switch self { + case .nextElementNotProduced: + return GRPCStatus(code: .failedPrecondition, message: "Expected next element of type \(Element.self)") + } + } +} + +extension AsyncSequence { + + /// We have quite a lot of grpc request streams where we read request N constant number of times and do not need foreach loop. But pure next produces optinal by design. + /// This small tweak just saves us from lots of boilerplate of unwrapping the optionals everywhere + var requiredNext: Element { + get async throws { + guard let next = try await first(where: { _ in true }) else { + throw StreamReadError.nextElementNotProduced + } + return next + } + } +} diff --git a/idb_companion/Utility/FBControlCoreError+Extension.swift b/idb_companion/Utility/FBControlCoreError+Extension.swift new file mode 100644 index 000000000..c426b0cf2 --- /dev/null +++ b/idb_companion/Utility/FBControlCoreError+Extension.swift @@ -0,0 +1,11 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import FBSimulatorControl + +extension FBControlCoreError: Error { +} diff --git a/idb_companion/Utility/FBIDBXCTestReporter.h b/idb_companion/Utility/FBIDBXCTestReporter.h index a7a36627b..81d73a5d7 100644 --- a/idb_companion/Utility/FBIDBXCTestReporter.h +++ b/idb_companion/Utility/FBIDBXCTestReporter.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -34,7 +34,7 @@ NS_ASSUME_NONNULL_BEGIN @param queue the queue to serialize work on. @param logger the logger to log to. */ -- (instancetype)initWithResponseWriter:(grpc::ServerWriter *)writer queue:(dispatch_queue_t)queue logger:(id)logger; +- (instancetype)initWithResponseWriter:(grpc::ServerWriter *)writer queue:(dispatch_queue_t)queue logger:(id)logger reportResultBundle:(BOOL)reportResultBundle; #pragma mark Properties diff --git a/idb_companion/Utility/FBIDBXCTestReporter.mm b/idb_companion/Utility/FBIDBXCTestReporter.mm deleted file mode 100644 index e062b0ebb..000000000 --- a/idb_companion/Utility/FBIDBXCTestReporter.mm +++ /dev/null @@ -1,558 +0,0 @@ -/* - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#import "FBIDBXCTestReporter.h" - -#import "FBXCTestReporterConfiguration.h" - -#import - -@interface FBIDBXCTestReporter () - -@property (nonatomic, assign, readwrite) grpc::ServerWriter *writer; -@property (nonatomic, strong, readonly) dispatch_queue_t queue; -@property (nonatomic, strong, readonly) id logger; -@property (nonatomic, strong, readonly) FBMutableFuture *reportingTerminatedMutable; -@property (nonatomic, strong, readonly) FBMutableFuture *processUnderTestExitedMutable; - -@property (nonatomic, nullable, copy, readwrite) NSString *currentBundleName; -@property (nonatomic, nullable, copy, readwrite) NSString *currentTestClass; -@property (nonatomic, nullable, copy, readwrite) NSString *currentTestMethod; - -@property (nonatomic, strong, readonly) NSMutableArray *currentActivityRecords; -@property (nonatomic, assign, readwrite) idb::XctestRunResponse_TestRunInfo_TestRunFailureInfo failureInfo; - -@end - -@interface CodeCoverageResponseData : NSObject - -@property(nonatomic, copy, nullable, readonly) NSString *jsonString; - -@property(nonatomic, copy, nullable, readonly) NSData *data; - -- (instancetype)initWithData:(nullable NSData *)data jsonString:(nullable NSString *)jsonString; - -@end - -@implementation CodeCoverageResponseData - -- (instancetype)initWithData:(nullable NSData *)data jsonString:(nullable NSString *)jsonString -{ - self = [super init]; - if (self) { - _data = data; - _jsonString = jsonString; - } - return self; -} - -@end - - - -@implementation FBIDBXCTestReporter - -#pragma mark Initializer - -- (instancetype)initWithResponseWriter:(grpc::ServerWriter *)writer queue:(dispatch_queue_t)queue logger:(id)logger -{ - self = [super init]; - if (!self) { - return nil; - } - - _writer = writer; - _queue = queue; - _logger = logger; - - _configuration = [[FBXCTestReporterConfiguration alloc] initWithResultBundlePath:nil coverageConfiguration:nil logDirectoryPath:nil binariesPaths:nil reportAttachments:NO]; - _currentActivityRecords = NSMutableArray.array; - _reportingTerminatedMutable = FBMutableFuture.future; - _processUnderTestExitedMutable = FBMutableFuture.future; - - return self; -} - -#pragma mark Properties - -- (FBFuture *)reportingTerminated -{ - return self.reportingTerminatedMutable; -} - -#pragma mark FBXCTestReporter - -- (void)testCaseDidStartForTestClass:(NSString *)testClass method:(NSString *)method -{ - self.currentTestClass = testClass; - self.currentTestMethod = method; -} - -- (void)testPlanDidFailWithMessage:(NSString *)message -{ - const idb::XctestRunResponse response = [self responseForCrashMessage:message]; - [self writeResponse:response]; -} - -- (void)testCaseDidFailForTestClass:(NSString *)testClass method:(NSString *)method withMessage:(NSString *)message file:(NSString *)file line:(NSUInteger)line -{ - // testCaseDidFinishForTestClass will be called immediately after this call, this makes sure we attach the failure info to it. - if (([testClass isEqualToString:self.currentTestClass] && [method isEqualToString:self.currentTestMethod]) == NO) { - [self.logger logFormat:@"Got failure info for %@/%@ but the current known executing test is %@/%@. Ignoring it", testClass, method, self.currentTestClass, self.currentTestMethod]; - return; - } - self.failureInfo = [self failureInfoWithMessage:message file:file line:line]; -} - -- (void)testCaseDidFinishForTestClass:(NSString *)testClass method:(NSString *)method withStatus:(FBTestReportStatus)status duration:(NSTimeInterval)duration logs:(NSArray *)logs -{ - const idb::XctestRunResponse_TestRunInfo info = [self runInfoForTestClass:testClass method:method withStatus:status duration:duration logs:logs]; - [self writeTestRunInfo:info]; -} - -- (void)testCase:(NSString *)testClass method:(NSString *)method didFinishActivity:(FBActivityRecord *)activity -{ - [self.currentActivityRecords addObject:activity]; -} - -- (void)testSuite:(NSString *)testSuite didStartAt:(NSString *)startTime -{ - @synchronized (self) { - self.currentBundleName = testSuite; - } -} - -- (void)didCrashDuringTest:(NSError *)error -{ - const idb::XctestRunResponse response = [self responseForCrashMessage:error.localizedDescription]; - [self writeResponse:response]; -} - -- (void)testHadOutput:(NSString *)output -{ - const idb::XctestRunResponse response = [self responseForLogOutput:@[output]]; - [self writeResponse:response]; -} - -- (void)handleExternalEvent:(NSString *)event -{ - const idb::XctestRunResponse response = [self responseForLogOutput:@[event]]; - [self writeResponse:response]; -} - -- (void)didFinishExecutingTestPlan -{ - const idb::XctestRunResponse response = [self responseForNormalTestTermination]; - [self writeResponse:response]; -} - -- (void)processUnderTestDidExit { - [self.processUnderTestExitedMutable resolveWithResult:NSNull.null]; -} - -#pragma mark FBXCTestReporter (Unused) - -- (BOOL)printReportWithError:(NSError **)error -{ - return NO; -} - -- (void)processWaitingForDebuggerWithProcessIdentifier:(pid_t)pid -{ - [self.logger.info logFormat:@"Tests waiting for debugger. To debug run: lldb -p %d", pid]; - idb::XctestRunResponse response; - response.set_status(idb::XctestRunResponse_Status_RUNNING); - - idb::DebuggerInfo *debugger_info = response.mutable_debugger(); - debugger_info->set_pid(pid); - - [self writeResponse:response]; -} - -- (void)didBeginExecutingTestPlan -{ -} - -- (void)finishedWithSummary:(FBTestManagerResultSummary *)summary -{ - // didFinishExecutingTestPlan should be used to signify completion instead -} - -#pragma mark FBDataConsumer - -- (void)consumeData:(NSData *)data -{ - idb::XctestRunResponse response = [self responseForLogData:data]; - [self writeResponse:response]; -} - -- (void)consumeEndOfFile -{ - -} - -#pragma mark Private - -- (const idb::XctestRunResponse_TestRunInfo)runInfoForTestClass:(NSString *)testClass method:(NSString *)method withStatus:(FBTestReportStatus)status duration:(NSTimeInterval)duration logs:(NSArray *)logs -{ - idb::XctestRunResponse_TestRunInfo info; - info.set_bundle_name(self.currentBundleName.UTF8String ?: ""); - info.set_class_name(testClass.UTF8String ?: ""); - info.set_method_name(method.UTF8String ?: ""); - info.set_duration(duration); - info.mutable_failure_info()->CopyFrom(self.failureInfo); - switch (status) { - case FBTestReportStatusPassed: - info.set_status(idb::XctestRunResponse_TestRunInfo_Status_PASSED); - break; - case FBTestReportStatusFailed: - info.set_status(idb::XctestRunResponse_TestRunInfo_Status_FAILED); - break; - default: - break; - } - for (NSString *log in logs) { - info.add_logs(log.UTF8String ?: ""); - } - NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"start" ascending:YES]; - [self.currentActivityRecords sortUsingDescriptors:@[sortDescriptor]]; - NSMutableArray *stackedActivities = [NSMutableArray array]; - while (self.currentActivityRecords.count) { - FBActivityRecord *activity = self.currentActivityRecords[0]; - [self.currentActivityRecords removeObjectAtIndex:0]; - [self populateSubactivities:activity remaining:self.currentActivityRecords]; - [stackedActivities addObject:activity]; - } - for (FBActivityRecord *activity in stackedActivities) { - [self translateActivity:activity activityOut:info.add_activitylogs()]; - } - [self resetCurrentTestState]; - return info; -} - -- (void)populateSubactivities:(FBActivityRecord *)root remaining:(NSMutableArray *)remaining { - while (remaining.count && root.start.timeIntervalSince1970 <= remaining[0].start.timeIntervalSince1970 && root.finish.timeIntervalSince1970 >= remaining[0].finish.timeIntervalSince1970) { - FBActivityRecord *sub = remaining[0]; - [remaining removeObjectAtIndex:0]; - [self populateSubactivities:sub remaining:remaining]; - [root.subactivities addObject:sub]; - } -} - -- (void)translateActivity:(FBActivityRecord *)activity activityOut:(idb::XctestRunResponse_TestRunInfo_TestActivity *)activityOut -{ - activityOut->set_title(activity.title.UTF8String ?: ""); - activityOut->set_duration(activity.duration); - activityOut->set_uuid(activity.uuid.UUIDString.UTF8String ?: ""); - activityOut->set_activity_type(activity.activityType.UTF8String ?: ""); - activityOut->set_start(activity.start.timeIntervalSince1970); - activityOut->set_finish(activity.finish.timeIntervalSince1970); - activityOut->set_name(activity.name.UTF8String ?: ""); - if (self.configuration.reportAttachments) { - for (FBAttachment *attachment in activity.attachments) { - idb::XctestRunResponse_TestRunInfo_TestAttachment *attachmentOut = activityOut->add_attachments(); - attachmentOut->set_payload(attachment.payload.bytes, attachment.payload.length); - attachmentOut->set_name(attachment.name.UTF8String ?: ""); - attachmentOut->set_timestamp(attachment.timestamp.timeIntervalSince1970); - attachmentOut->set_uniform_type_identifier(attachment.uniformTypeIdentifier.UTF8String ?: ""); - } - } - for (FBActivityRecord *subActitvity in activity.subactivities) { - idb::XctestRunResponse_TestRunInfo_TestActivity *subactivityOut = activityOut->add_sub_activities(); - [self translateActivity:subActitvity activityOut:subactivityOut]; - } -} - -- (const idb::XctestRunResponse_TestRunInfo_TestRunFailureInfo)failureInfoWithMessage:(NSString *)message file:(NSString *)file line:(NSUInteger)line -{ - idb::XctestRunResponse_TestRunInfo_TestRunFailureInfo failureInfo; - failureInfo.set_failure_message(message.UTF8String ?: ""); - failureInfo.set_file(file.UTF8String ?: ""); - failureInfo.set_line(line); - return failureInfo; -} - -- (const idb::XctestRunResponse)responseForLogOutput:(NSArray *)logOutput -{ - idb::XctestRunResponse response; - response.set_status(idb::XctestRunResponse_Status_RUNNING); - for (NSString *log in logOutput) { - NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"Assertion failed: (.*), function (.*), file (.*), line (\\d+)." options:NSRegularExpressionCaseInsensitive error:nil]; - NSTextCheckingResult *result = [regex firstMatchInString:log options:0 range:NSMakeRange(0, [log length])]; - if (result) { - self.failureInfo = [self failureInfoWithMessage:[log substringWithRange:[result rangeAtIndex:1]] file:[log substringWithRange:[result rangeAtIndex:3]] line:[[log substringWithRange:[result rangeAtIndex:4]] integerValue]]; - } - response.add_log_output(log.UTF8String ?: ""); - } - return response; -} - -- (const idb::XctestRunResponse)responseForLogData:(NSData *)data -{ - idb::XctestRunResponse response; - response.set_status(idb::XctestRunResponse_Status_RUNNING); - response.add_log_output((char *) data.bytes, data.length); - return response; -} - -- (const idb::XctestRunResponse)responseForCrashMessage:(NSString *)message -{ - idb::XctestRunResponse response; - response.set_status(idb::XctestRunResponse_Status_TERMINATED_ABNORMALLY); - idb::XctestRunResponse_TestRunInfo *info = response.add_results(); - info->set_bundle_name(self.currentBundleName.UTF8String ?: ""); - info->set_class_name(self.currentTestClass.UTF8String ?: ""); - info->set_method_name(self.currentTestMethod.UTF8String ?: ""); - info->mutable_failure_info()->CopyFrom(self.failureInfo); - info->mutable_failure_info()->set_failure_message(message.UTF8String); - info->set_status(idb::XctestRunResponse_TestRunInfo_Status_CRASHED); - [self resetCurrentTestState]; - return response; -} - -- (const idb::XctestRunResponse)responseForNormalTestTermination -{ - idb::XctestRunResponse response; - response.set_status(idb::XctestRunResponse_Status_TERMINATED_NORMALLY); - return response; -} - -- (void)resetCurrentTestState -{ - [self.currentActivityRecords removeAllObjects]; - self.failureInfo = idb::XctestRunResponse_TestRunInfo_TestRunFailureInfo(); - self.currentTestMethod = nil; - self.currentTestClass = nil; -} - -- (void)writeTestRunInfo:(const idb::XctestRunResponse_TestRunInfo &)info -{ - idb::XctestRunResponse response; - response.set_status(idb::XctestRunResponse_Status_RUNNING); - response.add_results()->CopyFrom(info); - [self writeResponse:response]; -} - -- (void)writeResponse:(const idb::XctestRunResponse &)response -{ - // If there's a result bundle and this is the last message, then append the result bundle. - switch (response.status()) { - case idb::XctestRunResponse_Status_TERMINATED_NORMALLY: - case idb::XctestRunResponse_Status_TERMINATED_ABNORMALLY: - [self insertFinalDataThenWriteResponse:response]; - return; - default: - break; - } - - [self writeResponseFinal:response]; -} - -- (void)insertFinalDataThenWriteResponse:(const idb::XctestRunResponse &)response -{ - // This method can make changes to the response object, however the reference is `const` so - // it's necessary to make a copy of the object and use the copy throughout this method. - // As the changes to the request (copy) will effectivelly happen inside blocks the reference to the copy - // needs to be declared as __block otherwise the (reference to the) copy object will be destroyed - // (together with the stack frame) before the blocks try to change it, causing memory access errors. - - __block idb::XctestRunResponse responseCopy; - responseCopy.CopyFrom(response); - - NSMutableArray *> *futures = [NSMutableArray array]; - if (self.configuration.resultBundlePath) { - [futures addObject:[[self getResultsBundle] onQueue:self.queue chain:^FBFuture *(FBFuture *future) { - NSData *data = future.result; - if (data) { - idb::Payload *payload = responseCopy.mutable_result_bundle(); - payload->set_data(data.bytes, data.length); - } else { - [self.logger.info logFormat:@"Failed to create result bundle %@", future]; - } - return [FBFuture futureWithResult:NSNull.null]; - }]]; - } - if (self.configuration.coverageConfiguration.coverageDirectory) { - [futures addObject:[[[self getCoverageResponseData] - onQueue:self.queue map:^NSNull *(CodeCoverageResponseData *coverageResponseData) { - NSData *data = coverageResponseData.data; - if (data) { - idb::Payload *payload = responseCopy.mutable_code_coverage_data(); - payload->set_data(data.bytes, data.length); - } - NSString *jsonString = coverageResponseData.jsonString; - if (jsonString) { - // for backwards compatibility - responseCopy.set_coverage_json(jsonString.UTF8String ?: ""); - } - return NSNull.null; - }] - onQueue:self.queue handleError:^FBFuture *(NSError *error) { - [self.logger.info logFormat:@"Failed to get coverage data: %@", error.localizedDescription]; - return FBFuture.empty; - }]]; - } - if (self.configuration.logDirectoryPath) { - [futures addObject:[[self getLogDirectoryData] onQueue:self.queue chain:^FBFuture *(FBFuture *future) { - NSData *data = future.result; - if (data) { - idb::Payload *payload = responseCopy.mutable_log_directory(); - payload->set_data(data.bytes, data.length); - } else { - [self.logger.info logFormat:@"Failed to get log drectory: %@", future.error.localizedDescription]; - } - return [FBFuture futureWithResult:NSNull.null]; - }]]; - - } - if (futures.count == 0) { - [self writeResponseFinal:responseCopy]; - return; - } - [[FBFuture futureWithFutures:futures] onQueue:self.queue map:^NSNull *(id _) { - [self writeResponseFinal:responseCopy]; - return NSNull.null; - }]; -} - -- (void)writeResponseFinal:(const idb::XctestRunResponse &)response -{ - @synchronized (self) - { - // Break out if the terminating condition happens twice. - if (self.reportingTerminated.hasCompleted || self.writer == nil) { - [self.logger.error log:@"writeResponse called, but the last response has already been written!!"]; - return; - } - - self.writer->Write(response); - - // Update the terminal future to signify that reporting is done. - switch (response.status()) { - case idb::XctestRunResponse_Status_TERMINATED_NORMALLY: - case idb::XctestRunResponse_Status_TERMINATED_ABNORMALLY: - [self.logger logFormat:@"Test Reporting has finished with status %d", response.status()]; - [self.reportingTerminatedMutable resolveWithResult:@(response.status())]; - self.writer = nil; - break; - default: - break; - } - } -} - -- (FBFuture *)getResultsBundle -{ - return [FBArchiveOperations createGzippedTarDataForPath:self.configuration.resultBundlePath queue:self.queue logger:self.logger]; -} - -- (FBFuture *)getLogDirectoryData -{ - return [FBArchiveOperations createGzippedTarDataForPath:self.configuration.logDirectoryPath queue:self.queue logger:self.logger]; -} - -#pragma mark Code Coverage - -- (FBFuture *)getCoverageResponseData -{ - return [self.processUnderTestExitedMutable - onQueue:self.queue fmap:^FBFuture *(id _) { - - switch (self.configuration.coverageConfiguration.format) { - case FBCodeCoverageExported: - return [[self getCoverageDataExported] - onQueue:self.queue fmap:^FBFuture *(NSData *coverageData) { - return [[FBArchiveOperations createGzipDataFromData:coverageData logger:self.logger] - onQueue:self.queue map:^CodeCoverageResponseData *(FBProcess *task) { - return [[CodeCoverageResponseData alloc] - initWithData:task.stdOut - jsonString:[[NSString alloc] initWithData:coverageData encoding:NSUTF8StringEncoding] - ]; - }]; - }]; - case FBCodeCoverageRaw: - return [[self getCoverageDataDirectory] - onQueue:self.queue map:^CodeCoverageResponseData *(NSData *coverageTarball) { - return [[CodeCoverageResponseData alloc] initWithData:coverageTarball jsonString:nil]; - }]; - default: - return [[FBControlCoreError - describeFormat:@"Unsupported code coverage format"] - failFuture]; - } - }]; -} - - -- (FBFuture *)getCoverageDataDirectory -{ - return [FBArchiveOperations - createGzippedTarDataForPath:self.configuration.coverageConfiguration.coverageDirectory - queue:self.queue - logger:self.logger]; -} - -- (FBFuture *)getCoverageDataExported -{ - FBFuture *> * (^checkXcrunError)(FBProcess *) = - ^FBFuture *> * (FBProcess *task) { - NSNumber *exitCode = task.exitCode.result; - if ([exitCode isEqual:@0]) { - return [FBFuture futureWithResult:task]; - } else { - return [[FBControlCoreError - describeFormat:@"xcrun failed to export code coverage data %@, %@", exitCode, task.stdErr] - failFuture]; - } - }; - - NSString *coverageDirectoryPath = self.configuration.coverageConfiguration.coverageDirectory; - NSString *profdataPath = [coverageDirectoryPath stringByAppendingPathComponent:@"coverage.profdata"]; - - NSError *error = nil; - NSArray *profraws = [NSFileManager.defaultManager contentsOfDirectoryAtPath:coverageDirectoryPath error:&error]; - if (profraws == nil) { - return [[FBControlCoreError - describeFormat:@"Couldn't find code coverage raw data: %@", error] - failFuture]; - } - profraws = [profraws filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(NSString *evaluatedObject, NSDictionary *_) { - return [[evaluatedObject pathExtension] isEqualToString:@"profraw"]; - }]]; - - NSMutableArray *mergeArgs = @[@"llvm-profdata", @"merge", @"-o", profdataPath].mutableCopy; - for (NSString *profraw in profraws) { - [mergeArgs addObject:[coverageDirectoryPath stringByAppendingPathComponent:profraw]]; - } - - FBFuture *mergeFuture = [[[[FBProcessBuilder - withLaunchPath:@"/usr/bin/xcrun" arguments:mergeArgs.copy] - withStdOutInMemoryAsData] - withStdErrInMemoryAsString] - runUntilCompletionWithAcceptableExitCodes:nil]; - - return [[[[mergeFuture onQueue:self.queue fmap:[checkXcrunError copy]] - onQueue:self.queue fmap:^FBFuture *> *(id _) { - NSMutableArray *exportArgs = @[@"llvm-cov", @"export", @"-instr-profile", profdataPath].mutableCopy; - for (NSString *binary in self.configuration.binariesPaths) { - [exportArgs addObject:@"-object"]; - [exportArgs addObject:binary]; - } - return [[[[FBProcessBuilder - withLaunchPath:@"/usr/bin/xcrun" arguments:exportArgs.copy] - withStdOutInMemoryAsData] - withStdErrInMemoryAsString] - runUntilCompletionWithAcceptableExitCodes:nil]; - }] - onQueue:self.queue fmap:[checkXcrunError copy]] - onQueue:self.queue map:^NSData *(FBProcess *task) { - return task.stdOut; - }]; -} - - -@end diff --git a/idb_companion/Utility/FBiOSTargetStateChangeNotifier.h b/idb_companion/Utility/FBiOSTargetStateChangeNotifier.h index bb37a9842..73eb04902 100644 --- a/idb_companion/Utility/FBiOSTargetStateChangeNotifier.h +++ b/idb_companion/Utility/FBiOSTargetStateChangeNotifier.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/idb_companion/Utility/FBiOSTargetStateChangeNotifier.m b/idb_companion/Utility/FBiOSTargetStateChangeNotifier.m index 499172f80..27ab43c8b 100644 --- a/idb_companion/Utility/FBiOSTargetStateChangeNotifier.m +++ b/idb_companion/Utility/FBiOSTargetStateChangeNotifier.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -8,7 +8,7 @@ #import "FBiOSTargetStateChangeNotifier.h" #import "FBiOSTargetDescription.h" -#import "FBIDBError.h" +#import @interface FBiOSTargetStateChangeNotifier () diff --git a/idb_companion/Utility/FileDrainWriter.swift b/idb_companion/Utility/FileDrainWriter.swift new file mode 100644 index 000000000..9009d34b6 --- /dev/null +++ b/idb_companion/Utility/FileDrainWriter.swift @@ -0,0 +1,46 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import CompanionLib +import FBSimulatorControl +import GRPC + +struct FileDrainWriter { + + static func performDrain(taskFuture: FBFuture>, sendResponse: (Data) async throws -> Void) async throws { + let task = try await BridgeFuture.value(taskFuture) + guard let inputStream = task.stdOut else { + throw GRPCStatus(code: .internalError, message: "Unable to get stdOut to write") + } + + inputStream.open() + defer { inputStream.close() } + + // inputStream.hasBytesAvailable is unavailable due to custom implementation of NSInputStream + while true { + let sixteenKilobytes = 16384 + var buffer = [UInt8](repeating: 0, count: sixteenKilobytes) + let readBytes = inputStream.read(&buffer, maxLength: sixteenKilobytes) + + guard readBytes >= 0 else { + let message = "Draining operation failed with stream error: \(inputStream.streamError?.localizedDescription ?? "Unknown")" + throw GRPCStatus(code: .internalError, message: message) + } + if readBytes == 0 { + break + } + + let data = Data(bytes: &buffer, count: readBytes) + try await sendResponse(data) + } + + let exitCode = try await BridgeFuture.value(task.exitCode).intValue + if exitCode != 0 { + throw GRPCStatus(code: .internalError, message: "Draining operation failed with exit code \(exitCode)") + } + } +} diff --git a/idb_companion/Utility/GRPCAsyncResponseStreamWriter+AsyncStreamWriter.swift b/idb_companion/Utility/GRPCAsyncResponseStreamWriter+AsyncStreamWriter.swift new file mode 100644 index 000000000..84c79dadc --- /dev/null +++ b/idb_companion/Utility/GRPCAsyncResponseStreamWriter+AsyncStreamWriter.swift @@ -0,0 +1,18 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import GRPC +import IDBCompanionUtilities + +extension GRPCAsyncResponseStreamWriter: AsyncStreamWriter { + public typealias Value = Response + + @inlinable + public func send(_ value: Value) async throws { + try await send(value, compression: .deferToCallDefault) + } +} diff --git a/idb_companion/Utility/IDBXCTestReporter/IDBXCTestReporter.swift b/idb_companion/Utility/IDBXCTestReporter/IDBXCTestReporter.swift new file mode 100644 index 000000000..e2791114c --- /dev/null +++ b/idb_companion/Utility/IDBXCTestReporter/IDBXCTestReporter.swift @@ -0,0 +1,523 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import CompanionLib +import FBSimulatorControl +import Foundation +import GRPC +import IDBCompanionUtilities +import IDBGRPCSwift +import XCTestBootstrap + +extension IDBXCTestReporter { + + struct Configuration { + + let resultBundlePath: String + + let coverageConfiguration: FBCodeCoverageConfiguration? + + let logDirectoryPath: String? + + let binariesPath: [String] + + let reportAttachments: Bool + + let reportResultBundle: Bool + + init(legacy: FBXCTestReporterConfiguration) { + self.resultBundlePath = legacy.resultBundlePath ?? "" + self.coverageConfiguration = legacy.coverageConfiguration + self.logDirectoryPath = legacy.logDirectoryPath + self.binariesPath = legacy.binariesPaths ?? [] + self.reportAttachments = legacy.reportAttachments + self.reportResultBundle = legacy.reportResultBundle + } + } + + struct CurrentTestInfo { + var bundleName = "" + var testClass = "" + var testMethod = "" + var activityRecords: [FBActivityRecord] = [] + var failureInfo: Idb_XctestRunResponse.TestRunInfo.TestRunFailureInfo? + var otherFailures: [Idb_XctestRunResponse.TestRunInfo.TestRunFailureInfo] = [] + } +} + +@objc final class IDBXCTestReporter: NSObject, FBXCTestReporter, FBDataConsumer { + + let reportingTerminated = FBMutableFuture() + var configuration: Configuration! + + @Atomic private var responseStream: GRPCAsyncResponseStreamWriter? + + private let queue: DispatchQueue + private let logger: FBControlCoreLogger + + private let processUnderTestExitedMutable = FBMutableFuture() + + @Atomic private var currentInfo = CurrentTestInfo() + + init(responseStream: GRPCAsyncResponseStreamWriter, queue: DispatchQueue, logger: FBControlCoreLogger) { + self._responseStream = .init(wrappedValue: responseStream) + self.queue = queue + self.logger = logger + } + + // MARK: - FBDataConsumer implementation + + @objc func consumeData(_ data: Data) { + let logOutput = String(data: data, encoding: .utf8) ?? "" + let response = createResponse(logOutput: logOutput) + write(response: response) + } + + @objc func consumeEndOfFile() { + // Implementation not required + } + + // MARK: - FBXCTestReporter implementation + + @objc func processWaitingForDebugger(withProcessIdentifier pid: pid_t) { + logger.info().log("Tests waiting for debugger. To debug run: lldb -p \(pid)") + let response = Idb_XctestRunResponse.with { + $0.status = .running + $0.debugger = .with { + $0.pid = UInt64(pid) + } + } + + write(response: response) + } + + @objc func didBeginExecutingTestPlan() { + // Implementation not required + } + + @objc func didFinishExecutingTestPlan() { + let response = Idb_XctestRunResponse.with { + $0.status = .terminatedNormally + } + write(response: response) + } + + @objc func processUnderTestDidExit() { + processUnderTestExitedMutable.resolve(withResult: NSNull()) + } + + @objc func testSuite(_ testSuite: String, didStartAt startTime: String) { + _currentInfo.sync { $0.bundleName = testSuite } + } + + @objc func testCaseDidFinish(forTestClass testClass: String, method: String, with status: FBTestReportStatus, duration: TimeInterval, logs: [String]?) { + do { + let info = try createRunInfo(testClass: testClass, method: method, status: status, duration: duration, logs: logs ?? []) + write(testRunInfo: info) + } catch { + _responseStream.sync { $0 = nil } + reportingTerminated.resolveWithError(error) + } + } + + @objc func testCaseDidFail(forTestClass testClass: String, method: String, exceptions: [FBExceptionInfo]) { + let currentInfo = self.currentInfo + if testClass == currentInfo.testClass && method != currentInfo.testMethod { + logger.log("Got failure info for \(testClass)/\(method) but the current known executing test is \(currentInfo.testClass)\(currentInfo.testMethod). Ignoring it") + return + } + self._currentInfo.sync { + if let firstExceptionInfo = exceptions.first { + $0.failureInfo = createFailureInfo(exceptionInfo: firstExceptionInfo) + $0.otherFailures = exceptions.dropFirst().map { createFailureInfo(exceptionInfo: $0) } + } else { + logger.log("No exceptions were returned in the failure. This shouldn't happen.") + } + } + } + + @objc func testCaseDidStart(forTestClass testClass: String, method: String) { + _currentInfo.sync { + $0.testClass = testClass + $0.testMethod = method + } + } + + @objc func testPlanDidFail(withMessage message: String) { + let response = responseFor(crashMessage: message) + write(response: response) + } + + @objc func testCase(_ testClass: String, method: String, didFinishActivity activity: FBActivityRecord) { + _currentInfo.sync { + $0.activityRecords.append(activity) + } + } + + @objc func finished(with summary: FBTestManagerResultSummary) { + // didFinishExecutingTestPlan should be used to signify completion instead + } + + @objc func testHadOutput(_ output: String) { + let response = createResponseExtractingFailureInfo(from: output) + write(response: response) + } + + @objc func handleExternalEvent(_ event: String) { + let response = createResponseExtractingFailureInfo(from: event) + write(response: response) + } + + @objc func printReport() throws { + // Warning! This method is bridged to swift incorrectly and loses bool return type. Adapt and use with extra care + } + + @objc func didCrashDuringTest(_ error: Error) { + let response = responseFor(crashMessage: error.localizedDescription) + write(response: response) + } + + // MARK: - Privates + + private func createRunInfo(testClass: String, method: String, status: FBTestReportStatus, duration: TimeInterval, logs: [String]) throws -> Idb_XctestRunResponse.TestRunInfo { + + defer { resetCurrentTestState() } + + return try _currentInfo.sync { currentInfo in + + var stackedActivities: [FBActivityRecord] = [] + currentInfo.activityRecords.sort(by: { $0.start < $1.start }) + + while let activity = currentInfo.activityRecords.first { + currentInfo.activityRecords.remove(at: 0) + populateSubactivities(root: activity, remaining: ¤tInfo.activityRecords) + stackedActivities.append(activity) + } + + return try Idb_XctestRunResponse.TestRunInfo.with { + $0.bundleName = currentInfo.bundleName + $0.className = testClass + $0.methodName = method + $0.status = status == .failed ? .failed : .passed + $0.duration = duration + if let failureInfo = currentInfo.failureInfo { + $0.failureInfo = failureInfo + } + $0.logs = logs + $0.activityLogs = try stackedActivities.map(translate(activity:)) + $0.otherFailures = currentInfo.otherFailures + } + } + } + + private func translate(activity: FBActivityRecord) throws -> Idb_XctestRunResponse.TestRunInfo.TestActivity { + let subactivities = activity.subactivities as! [FBActivityRecord] + return try Idb_XctestRunResponse.TestRunInfo.TestActivity.with { + $0.title = activity.title + $0.duration = activity.duration + $0.uuid = activity.uuid.uuidString + $0.activityType = activity.activityType + $0.start = activity.start.timeIntervalSince1970 + $0.finish = activity.finish.timeIntervalSince1970 + $0.name = activity.name + if configuration.reportAttachments { + $0.attachments = try activity.attachments.map { attachment in + try .with { + $0.payload = attachment.payload ?? Data() + $0.name = attachment.name + $0.timestamp = attachment.timestamp.timeIntervalSince1970 + $0.uniformTypeIdentifier = attachment.uniformTypeIdentifier + if let userInfo = attachment.userInfo { + $0.userInfoJson = try translate(attachmentUserInfo: userInfo) + } + } + } + } + $0.subActivities = try subactivities.map(translate(activity:)) + } + } + + private func translate(attachmentUserInfo userInfo: [AnyHashable: Any]) throws -> Data { + try JSONSerialization.data(withJSONObject: userInfo, options: []) + } + + private func resetCurrentTestState() { + _currentInfo.sync { + $0.activityRecords.removeAll() + $0.failureInfo = nil + $0.testClass = "" + $0.testMethod = "" + $0.otherFailures.removeAll() + } + } + + private func populateSubactivities(root: FBActivityRecord, remaining: inout [FBActivityRecord]) { + while let firstRemaining = remaining.first, root.start <= firstRemaining.start && firstRemaining.finish <= root.finish { + remaining.remove(at: 0) + populateSubactivities(root: firstRemaining, remaining: &remaining) + root.subactivities.add(firstRemaining) + } + } + + private func write(testRunInfo: Idb_XctestRunResponse.TestRunInfo) { + let response = Idb_XctestRunResponse.with { + $0.status = .running + $0.results = [testRunInfo] + } + write(response: response) + } + + private func write(response: Idb_XctestRunResponse) { + Task { + do { + switch response.status { + case .terminatedNormally, .terminatedAbnormally: + try await insertFinalDataThenWriteResponse(response: response) + + default: + try await writeResponseFinal(response: response) + } + } catch { + logger.log("Failed to write xctest run response \(error.localizedDescription)") + } + } + } + + // TODO: Parallelism of execution was lost after rewriting this method to swift. Make this work in parallel again + private func insertFinalDataThenWriteResponse(response: Idb_XctestRunResponse) async throws { + var response = response + + if !configuration.resultBundlePath.isEmpty && configuration.reportResultBundle { + do { + let resultBundle = try await gzipFolder(at: configuration.resultBundlePath) + response.resultBundle = .with { + $0.data = resultBundle + } + } catch { + logger.info().log("Failed to create result bundle \(error.localizedDescription)") + } + } + + if let coverageConfig = configuration.coverageConfiguration, !coverageConfig.coverageDirectory.isEmpty { + do { + let coverageData = try await getCoverageResponseData(config: coverageConfig) + response.codeCoverageData = .with { + $0.data = coverageData + } + } catch { + logger.info().log("Failed to get coverage data: \(error.localizedDescription)") + } + } + + if let logDirectoryPath = configuration.logDirectoryPath { + let data = try await gzipFolder(at: logDirectoryPath) + response.logDirectory = .with { + $0.data = data + } + } + + try await writeResponseFinal(response: response) + } + + private func writeResponseFinal(response: Idb_XctestRunResponse) async throws { + let shouldCloseStream = isLastMessage(responseStatus: response.status) + + let stream: GRPCAsyncResponseStreamWriter? = _responseStream.sync { storedStream in + guard let responseStream = storedStream else { return nil } + if shouldCloseStream { + storedStream = nil + } + return responseStream + } + + guard let responseStream = stream else { + logger.error().log("writeResponse called, but the last response has already been written!") + return + } + + try await responseStream.send(response) + + if shouldCloseStream { + logger.log("Test Reporting has finished with status \(response.status)") + reportingTerminated.resolve(withResult: .init(value: response.status.rawValue)) + } + } + + private func isLastMessage(responseStatus: Idb_XctestRunResponse.Status) -> Bool { + return responseStatus == .terminatedNormally || responseStatus == .terminatedAbnormally + } + + private func gzipFolder(at path: String) async throws -> Data { + let task = FBArchiveOperations.createGzippedTarData(forPath: path, + queue: queue, + logger: logger) + return try await BridgeFuture.value(task) as Data + } + + private func getCoverageResponseData(config: FBCodeCoverageConfiguration) async throws -> Data { + try await BridgeFuture.await(processUnderTestExitedMutable) + switch config.format { + case .exported: + let data = try await getCoverageDataExported(config: config) + return data as Data + + case .raw: + return try await gzipFolder(at: config.coverageDirectory) + + default: + throw FBControlCoreError.describe("Unsupported code coverage format") + } + } + + private func getCoverageDataExported(config: FBCodeCoverageConfiguration) async throws -> Data { + let coverageDirectory = URL(fileURLWithPath: config.coverageDirectory) + let profdataPath = coverageDirectory.appendingPathComponent("coverage.profdata") + + try await mergeRawCoverage(coverageDirectory: coverageDirectory, profdataPath: profdataPath) + return try await exportCoverage(profdataPath: profdataPath, binariesPath: configuration.binariesPath) + } + + private func mergeRawCoverage(coverageDirectory: URL, profdataPath: URL) async throws { + let profraws = try FileManager.default + .contentsOfDirectory(at: coverageDirectory, includingPropertiesForKeys: nil, options: []) + .filter { $0.pathExtension == "profraw" } + + let mergeArgs: [String] = ["llvm-profdata", "merge", "-o", profdataPath.path] + + profraws.map(\.path) + + let mergeProcessFuture = FBProcessBuilder + .withLaunchPath("/usr/bin/xcrun", arguments: mergeArgs) + .withStdOutInMemoryAsData() + .withStdErrInMemoryAsString() + .runUntilCompletion(withAcceptableExitCodes: nil) + + let mergeProcess = try await BridgeFuture.value(mergeProcessFuture) + let exitCode = try await BridgeFuture.value(mergeProcess.exitCode) + if exitCode != 0 { + throw FBControlCoreError.describe("xcrun failed to export code coverage data \(exitCode.intValue) \(mergeProcess.stdErr ?? "")") + } + } + + private func exportCoverage(profdataPath: URL, binariesPath: [String]) async throws -> Data { + let exportArgs: [String] = ["llvm-cov", "export", "-instr-profile", profdataPath.path] + + binariesPath.reduce(into: []) { + $0 += ["-object", $1] + } + let exportProcess = try await BridgeFuture.value( + FBProcessBuilder + .withLaunchPath("/usr/bin/xcrun", arguments: exportArgs) + .withStdOutToInputStream() + .withStdErrInMemoryAsString() + .start() + ) + + let gzipProcessInput = FBProcessInput.fromStream() + let archiveFuture = FBArchiveOperations.createGzipData(from: gzipProcessInput as! FBProcessInput, logger: self.logger) + + let oneMega = 1024 * 1024 + let buffer = UnsafeMutablePointer.allocate(capacity: oneMega) + defer { + buffer.deallocate() + } + + guard let exportOutputStream = exportProcess.stdOut + else { + throw FBControlCoreError.describe("xcrun llvm-cov export misconfigured. stdOut stream is nil") + } + exportOutputStream.open() + + let gzipInputStream = gzipProcessInput.contents + gzipInputStream.open() + while case let bytesRead = exportOutputStream.read(buffer, maxLength: oneMega), bytesRead > 0 { + gzipInputStream.write(buffer, maxLength: bytesRead) + } + exportOutputStream.close() + gzipInputStream.close() + + let exitCode = try await BridgeFuture.value(exportProcess.exitCode) + if exitCode != 0 { + throw FBControlCoreError.describe("xcrun failed to export code coverage data \(exitCode.intValue) \(exportProcess.stdErr ?? "")") + } + + let archiveProcess = try await BridgeFuture.value(archiveFuture) + let stdOut = archiveProcess.stdOut ?? NSData() + return stdOut as Data + } + + private func createFailureInfo(message: String, file: String?, line: UInt) -> Idb_XctestRunResponse.TestRunInfo.TestRunFailureInfo { + return Idb_XctestRunResponse.TestRunInfo.TestRunFailureInfo.with { + $0.failureMessage = message + $0.file = file ?? "" + $0.line = UInt64(line) + } + } + + private func createFailureInfo(exceptionInfo: FBExceptionInfo) -> Idb_XctestRunResponse.TestRunInfo.TestRunFailureInfo { + return Idb_XctestRunResponse.TestRunInfo.TestRunFailureInfo.with { + $0.failureMessage = exceptionInfo.message + $0.file = exceptionInfo.file ?? "" + $0.line = UInt64(exceptionInfo.line) + } + } + + private func responseFor(crashMessage: String) -> Idb_XctestRunResponse { + defer { resetCurrentTestState() } + + let currentInfo = self.currentInfo + let info = Idb_XctestRunResponse.TestRunInfo.with { + $0.bundleName = currentInfo.bundleName + $0.className = currentInfo.testClass + $0.methodName = currentInfo.testMethod + $0.failureInfo = currentInfo.failureInfo ?? .init() + $0.failureInfo.failureMessage = crashMessage + $0.status = .crashed + $0.otherFailures = currentInfo.otherFailures + } + + return Idb_XctestRunResponse.with { + $0.status = .terminatedAbnormally + $0.results = [info] + } + } + + private func createResponseExtractingFailureInfo(from logOutput: String) -> Idb_XctestRunResponse { + extractFailureInfo(from: logOutput) + return createResponse(logOutput: logOutput) + } + + private func extractFailureInfo(from logOutput: String) { + do { + let regexp = try NSRegularExpression(pattern: "Assertion failed: (.*), function (.*), file (.*), line (\\d+).", options: .caseInsensitive) + let log = logOutput as NSString + if let result = regexp.firstMatch(in: logOutput, options: [], range: .init(location: 0, length: log.length)) { + _currentInfo.sync { + $0.failureInfo = failureInfoWith(message: log.substring(with: result.range(at: 1)), + file: log.substring(with: result.range(at: 3)), + line: UInt(log.substring(with: result.range(at: 4))) ?? 0) + } + } + } catch { + assertionFailure(error.localizedDescription) + logger.error().log("Incorrect regexp \(error.localizedDescription)") + } + } + + private func createResponse(logOutput: String) -> Idb_XctestRunResponse { + return Idb_XctestRunResponse.with { + $0.status = .running + $0.logOutput = [logOutput] + } + } + + private func failureInfoWith(message: String, file: String, line: UInt) -> Idb_XctestRunResponse.TestRunInfo.TestRunFailureInfo { + return .with { + $0.failureMessage = message + $0.file = file + $0.line = UInt64(line) + } + } +} diff --git a/idb_companion/Utility/MultisourceFileReader.swift b/idb_companion/Utility/MultisourceFileReader.swift new file mode 100644 index 000000000..7d6e9a424 --- /dev/null +++ b/idb_companion/Utility/MultisourceFileReader.swift @@ -0,0 +1,115 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import CompanionLib +import FBControlCore +import Foundation +import GRPC +import IDBGRPCSwift + +enum MultisourceFileReader { + + static func filePathURLs(from requestStream: GRPCAsyncRequestStream, temporaryDirectory: FBTemporaryDirectory, extractFromSubdir: Bool) async throws -> [URL] { + func readNextPayload() async throws -> Idb_Payload { + guard let p = try await requestStream.requiredNext.extractPayload() + else { throw GRPCStatus(code: .failedPrecondition, message: "Incorrect request. Expected payload") } + return p + } + + var payload = try await readNextPayload() + + var compression = FBCompressionFormat.GZIP + + if case let .compression(payloadCompression) = payload.source { + compression = compressionFormat(from: payloadCompression) + payload = try await readNextPayload() + } + + switch payload.source { + case let .data(data): + let (readTaskFromStreamTask, input) = pipeToInput(initialData: data, requestStream: requestStream) + + let result = try await filepathsFromTar(temporaryDirectory: temporaryDirectory, input: input, extractFromSubdir: extractFromSubdir, compression: compression) + + // We just check that read from request stream did not produce any errors + _ = try await readTaskFromStreamTask.value + + return result + + case let .filePath(filePath): + return try await filepathsFromStream(initial: .init(fileURLWithPath: filePath), requestStream: requestStream) + + case .url, .compression, .none: + throw GRPCStatus(code: .invalidArgument, message: "Unrecogized initial payload type \(payload.source as Any)") + } + } + + private static func compressionFormat(from request: Idb_Payload.Compression) -> FBCompressionFormat { + switch request { + case .gzip: + return .GZIP + case .zstd: + return .ZSTD + case .UNRECOGNIZED: + return .GZIP + } + } + + private static func filepathsFromStream(initial: URL, requestStream: GRPCAsyncRequestStream) async throws -> [URL] { + var filePaths = [initial] + + for try await request in requestStream { + guard let payload = request.extractPayload() + else { throw GRPCStatus(code: .invalidArgument, message: "Unrecogized buffer frame. Expect payload, got \(request)") } + + guard case .filePath(let filePath) = payload.source + else { throw GRPCStatus(code: .invalidArgument, message: "Unrecogized buffer frame. Expect file path, got \(payload.source as Any)") } + + filePaths.append(URL(fileURLWithPath: filePath)) + } + + return filePaths + } + + private static func filepathsFromTar(temporaryDirectory: FBTemporaryDirectory, input: FBProcessInput, extractFromSubdir: Bool, compression: FBCompressionFormat) async throws -> [URL] { + let mappedInput = input as! FBProcessInput + let tarContext = temporaryDirectory.withArchiveExtracted(fromStream: mappedInput, compression: compression) + if extractFromSubdir { + return try await BridgeFuture.values(temporaryDirectory.files(fromSubdirs: tarContext)) + } else { + let extractionDir = try await BridgeFuture.value(tarContext) + return try FileManager.default.contentsOfDirectory(at: extractionDir as URL, includingPropertiesForKeys: [.isDirectoryKey], options: []) + } + } + + // TODO: Do we really need multithreading here? Isnt we just fill the stream sequentially while read is blocked and only then read starts? + private static func pipeToInput(initialData: Data, requestStream: GRPCAsyncRequestStream) -> (Task, FBProcessInput) { + let input = FBProcessInput.fromStream() + let stream = input.contents + + let readFromStreamTask = Task { + stream.open() + defer { stream.close() } + + var buffer = [UInt8](initialData) + stream.write(&buffer, maxLength: buffer.count) + + for try await request in requestStream { + guard let payload = request.extractPayload() + else { throw GRPCStatus(code: .invalidArgument, message: "Unrecogized buffer frame. Expect payload, got \(request)") } + + guard case .data(let data) = payload.source + else { throw GRPCStatus(code: .invalidArgument, message: "Unrecogized buffer frame. Expect file path, got \(payload.source as Any)") } + + var buffer = [UInt8](data) + stream.write(&buffer, maxLength: buffer.count) + } + } + + return (readFromStreamTask, input) + } +} diff --git a/idb_companion/Utility/TaskFBFuture.swift b/idb_companion/Utility/TaskFBFuture.swift new file mode 100644 index 000000000..3c664532a --- /dev/null +++ b/idb_companion/Utility/TaskFBFuture.swift @@ -0,0 +1,39 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import CompanionLib +import FBControlCore +import Foundation + +extension Task where Failure == Error, Success: AnyObject & Sendable { + + /// Bridges swift concurrency back to FBFuture world. + /// - Parameters: + /// - job: Asynchronous task + /// - Returns: Job result + /// - Note: Job starts its execution instantly and do not wait for FBFuture observation. + /// - Note: FBFuture cancellation propagates to task. + static func fbFuture(job: @escaping @Sendable () async throws -> Success) -> FBFuture { + let mutableFuture = FBMutableFuture() + + let task = Task { + do { + let result = try await job() + mutableFuture.resolve(withResult: result) + } catch { + mutableFuture.resolveWithError(error) + } + } + + mutableFuture.onQueue(BridgeQueues.miscEventReaderQueue) { + task.cancel() + return FBFuture.empty() + } + + return mutableFuture as! FBFuture + } +} diff --git a/idb_companion/main.m b/idb_companion/main.m index e64ee6f40..2c01621d2 100644 --- a/idb_companion/main.m +++ b/idb_companion/main.m @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -12,16 +12,15 @@ #import #import -#import "FBIDBCompanionServer.h" -#import "FBIDBConfiguration.h" -#import "FBIDBError.h" -#import "FBIDBLogger.h" -#import "FBIDBPortsConfiguration.h" -#import "FBiOSTargetProvider.h" +#import +#import +#import #import "FBiOSTargetStateChangeNotifier.h" #import "FBiOSTargetDescription.h" -#import "FBIDBStorageManager.h" -#import "FBIDBCommandExecutor.h" +#import +#import + +#import "idb-Swift.h" const char *kUsageHelpMessage = "\ Usage: \n \ @@ -189,14 +188,11 @@ static void WriteTargetToStdOut(id target) static FBFuture *TargetOfflineFuture(id target, id logger) { - return [FBFuture - onQueue:target.workQueue resolveWhen:^ BOOL { - if (target.state != FBiOSTargetStateBooted) { - [logger.error logFormat:@"Target with udid %@ is no longer booted, it is in state %@", target.udid, FBiOSTargetStateStringFromState(target.state)]; - return YES; - } - return NO; - }]; + return [[target + resolveLeavesState:FBiOSTargetStateBooted] + onQueue:target.workQueue doOnResolved:^(id _){ + [target.logger log:@"Target is no longer booted, companion going offline"]; + }]; } static FBFuture *> *BootFuture(NSString *udid, NSUserDefaults *userDefaults, id logger, id reporter) @@ -300,7 +296,7 @@ static void WriteTargetToStdOut(id target) describeFormat:@"Could not find a simulator with udid %@", udidOrAll] failFuture]; } - return [set deleteSimulator:simulator]; + return [set delete:simulator]; }] mapReplace:NSNull.null]; } @@ -386,55 +382,86 @@ static void WriteTargetToStdOut(id target) static FBFuture *CleanFuture(NSString *udid, NSUserDefaults *userDefaults, BOOL xcodeAvailable, id logger, id reporter) { return [TargetForUDID(udid, userDefaults, xcodeAvailable, YES, logger, reporter) - onQueue:dispatch_get_main_queue() fmap:^FBFuture *(id target) { - NSError *error = nil; - FBIDBStorageManager *storageManager = [FBIDBStorageManager managerForTarget:target logger:logger error:&error]; - if (!storageManager) { - return [FBFuture futureWithError:error]; - } - FBIDBCommandExecutor *commandExecutor = [FBIDBCommandExecutor - commandExecutorForTarget:target - storageManager:storageManager - temporaryDirectory:[FBTemporaryDirectory temporaryDirectoryWithLogger:logger] - ports:[FBIDBPortsConfiguration portsWithArguments:userDefaults] - logger:logger]; - return [commandExecutor clean]; - }]; + onQueue:dispatch_get_main_queue() fmap:^FBFuture *(id target) { + NSError *error = nil; + FBIDBStorageManager *storageManager = [FBIDBStorageManager managerForTarget:target logger:logger error:&error]; + if (!storageManager) { + return [FBFuture futureWithError:error]; + } + FBIDBCommandExecutor *commandExecutor = [FBIDBCommandExecutor + commandExecutorForTarget:target + storageManager:storageManager + temporaryDirectory:[FBTemporaryDirectory temporaryDirectoryWithLogger:logger] + debugserverPort:[[IDBPortsConfiguration alloc] initWithArguments:userDefaults].debugserverPort + logger:logger]; + return [commandExecutor clean]; + }]; } static FBFuture *> *CompanionServerFuture(NSString *udid, NSUserDefaults *userDefaults, BOOL xcodeAvailable, id logger, id reporter) { BOOL terminateOffline = [userDefaults boolForKey:@"-terminate-offline"]; + return [TargetForUDID(udid, userDefaults, xcodeAvailable, YES, logger, reporter) onQueue:dispatch_get_main_queue() fmap:^(id target) { - [reporter addMetadata:@{@"udid": udid}]; + [reporter addMetadata:@{ + @"udid": udid, + @"target_type": FBiOSTargetTypeStringFromTargetType(target.targetType).lowercaseString, + }]; [reporter report:[FBEventReporterSubject subjectForEvent:@"launched"]]; - // Start up the companion - FBIDBPortsConfiguration *ports = [FBIDBPortsConfiguration portsWithArguments:userDefaults]; + FBTemporaryDirectory *temporaryDirectory = [FBTemporaryDirectory temporaryDirectoryWithLogger:logger]; NSError *error = nil; - FBIDBCompanionServer *server = [FBIDBCompanionServer companionForTarget:target temporaryDirectory:temporaryDirectory ports:ports eventReporter:reporter logger:logger error:&error]; - if (!server) { + + FBIDBStorageManager *storageManager = [FBIDBStorageManager managerForTarget:target logger:logger error:&error]; + if (!storageManager) { return [FBFuture futureWithError:error]; } - return [[server - start] - onQueue:target.workQueue map:^ FBFuture * (NSDictionary *serverDescription) { - WriteJSONToStdOut(serverDescription); - FBFuture *completed = server.completed; - if (terminateOffline) { - [logger.info logFormat:@"Companion will terminate when target goes offline"]; - completed = [FBFuture race:@[completed, TargetOfflineFuture(target, logger)]]; - } else { - [logger.info logFormat:@"Companion will stay alive if target goes offline"]; - } - return [completed - onQueue:target.workQueue chain:^(FBFuture *future) { - [temporaryDirectory cleanOnExit]; - return future; - }]; + NSError *err = nil; + + // Start up the companion + IDBPortsConfiguration *ports = [[IDBPortsConfiguration alloc] initWithArguments:userDefaults]; + + // Command Executor + FBIDBCommandExecutor *commandExecutor = [FBIDBCommandExecutor + commandExecutorForTarget:target + storageManager:storageManager + temporaryDirectory:temporaryDirectory + debugserverPort:ports.debugserverPort + logger:logger]; + + FBIDBCommandExecutor *loggingCommandExecutor = [FBLoggingWrapper wrap:commandExecutor simplifiedNaming:YES eventReporter:IDBConfiguration.swiftEventReporter logger:logger]; + + GRPCSwiftServer *swiftServer = [[GRPCSwiftServer alloc] + initWithTarget:target + commandExecutor:loggingCommandExecutor + reporter:IDBConfiguration.swiftEventReporter + logger:logger + ports:ports + error:&err]; + if (!swiftServer) { + return [FBFuture futureWithError:err]; + } + + return [[swiftServer start] onQueue:target.workQueue map:^ FBFuture * (NSDictionary *serverDescription) { + WriteJSONToStdOut(serverDescription); + NSMutableArray *> *futures = [[NSMutableArray alloc] initWithArray: @[swiftServer.completed]]; + + if (terminateOffline) { + [logger.info logFormat:@"Companion will terminate when target goes offline"]; + [futures addObject:TargetOfflineFuture(target, logger)]; + } else { + [logger.info logFormat:@"Companion will stay alive if target goes offline"]; + } + + FBFuture *completed = [FBFuture race: futures]; + return [completed + onQueue:target.workQueue chain:^(FBFuture *future) { + [temporaryDirectory cleanOnExit]; + return future; }]; - }]; + }]; + }]; } static FBFuture *> *NotiferFuture(NSString *notify, NSUserDefaults *userDefaults, BOOL xcodeAvailable, id logger, id reporter) @@ -500,7 +527,7 @@ static void WriteTargetToStdOut(id target) NSString *clean = [userDefaults stringForKey:@"-clean"]; NSString *forward = [userDefaults stringForKey:@"-forward"]; - id reporter = FBIDBConfiguration.eventReporter; + id reporter = IDBConfiguration.eventReporter; if (udid) { return CompanionServerFuture(udid, userDefaults, xcodeAvailable, logger, reporter); } else if (list) { @@ -570,11 +597,29 @@ static void WriteTargetToStdOut(id target) }]; } -static NSString *EnvDescription() +static NSString *EnvDescription(void) { return [FBCollectionInformation oneLineDescriptionFromDictionary:FBControlCoreGlobalConfiguration.safeSubprocessEnvironment]; } +static NSString *ArchName(void) +{ +#if TARGET_CPU_ARM64 + return @"arm64"; +#elif TARGET_CPU_X86_64 + return @"x86_64"; +#else + return @"not supported"); +#endif +} + +static void logStartupInfo(FBIDBLogger *logger) +{ + [logger.info logFormat:@"IDB Companion Built at %s %s", __DATE__, __TIME__]; + [logger.info logFormat:@"IDB Companion architecture %@", ArchName()]; + [logger.info logFormat:@"Invoked with args=%@ env=%@", [FBCollectionInformation oneLineDescriptionFromArray:NSProcessInfo.processInfo.arguments], EnvDescription()]; +} + int main(int argc, const char *argv[]) { @autoreleasepool { @@ -590,8 +635,8 @@ int main(int argc, const char *argv[]) { NSUserDefaults *userDefaults = NSUserDefaults.standardUserDefaults; FBIDBLogger *logger = [FBIDBLogger loggerWithUserDefaults:userDefaults]; - [logger.info logFormat:@"IDB Companion Built at %s %s", __DATE__, __TIME__]; - [logger.info logFormat:@"Invoked with args=%@ env=%@", [FBCollectionInformation oneLineDescriptionFromArray:NSProcessInfo.processInfo.arguments], EnvDescription()]; + logStartupInfo(logger); + NSError *error = nil; // Check that xcode-select returns a valid path, throw a big diff --git a/idb_companion_oss_release.py b/idb_companion_oss_release.py new file mode 100644 index 000000000..36e984d7d --- /dev/null +++ b/idb_companion_oss_release.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python3 +# Copyright (c) Meta Platforms, Inc. and affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import hashlib +import os +import subprocess +import tempfile + + +class bcolors: + HEADER = "\033[95m" + OKGREEN = "\033[92m" + ENDC = "\033[0m" + + +release = os.getenv("NEW") +if not release: + raise Exception("set release via `export NEW=`") + +dirpath = tempfile.mkdtemp() + + +print( + bcolors.HEADER + + "Preparing new OSS build. This script assumes that you already created new release on github. To create a release do:" + + bcolors.ENDC +) +print(' gh release create v$NEW -t "" -d --repo facebook/idb\n') + +print(bcolors.OKGREEN + "Step 1. " + bcolors.ENDC + "Building to", dirpath) +subprocess.run(["./idb_build.sh", "idb_companion", "build", dirpath], check=True) + +print(bcolors.OKGREEN + "Step 2. " + bcolors.ENDC + "Compressing the build") + +subprocess.run( + ["tar", "-cjf", "idb-companion.universal.tar.gz", "-C", dirpath, "."], check=True +) + + +print(bcolors.OKGREEN + "Step 3. " + bcolors.ENDC + "Calculating shasum") +with open("idb-companion.universal.tar.gz", "rb") as f: + bytes = f.read() # read entire file as bytes + readable_hash = hashlib.sha256(bytes).hexdigest() + +print(readable_hash) + +print( + bcolors.OKGREEN + "Step 4. " + bcolors.ENDC + "Uploading the binary to gh release" +) +subprocess.run( + [ + "gh", + "release", + "upload", + "v" + release, + "idb-companion.universal.tar.gz", + "--repo", + "facebook/idb", + ] +) + +binary_url = f"https://github.com/facebook/idb/releases/download/v{release}/idb-companion.universal.tar.gz" +print("New binary uploaded. It should be available by", binary_url) + +subprocess.run(["brew", "tap", "facebook/fb"]) + +proc = subprocess.Popen(["brew", "--repo", "facebook/fb"], stdout=subprocess.PIPE) + +homebrew_fb_repo_path = proc.stdout.read()[:-1].decode() + +idb_companion_homebrew_config = homebrew_fb_repo_path + "/idb-companion.rb" +print( + bcolors.OKGREEN + "Step 5. " + bcolors.ENDC + "Modifying", + idb_companion_homebrew_config, +) + +subprocess.run( + [ + "sed", + "-i", + "", + 's/url ".*"/url "https://github.com/facebook/idb/releases/download/v{}/idb-companion.universal.tar.gz"/g'.format( + release + ), + "idb-companion.rb", + ], + cwd=homebrew_fb_repo_path, + check=True, +) +subprocess.run( + [ + "sed", + "-i", + "", + f's/sha256 "[a-zA-Z0-9]*"/sha256 "{readable_hash}"/g', + "idb-companion.rb", + ], + cwd=homebrew_fb_repo_path, + check=True, +) + +print( + bcolors.OKGREEN + "Step 6. " + bcolors.ENDC + "Printing changes of idb-companion.rb" +) +subprocess.run(["git", "--no-pager", "diff"], cwd=homebrew_fb_repo_path, check=True) + +print( + bcolors.HEADER + + f"Please check {idb_companion_homebrew_config} contents and push the file manually. This script won't do that." + + bcolors.ENDC +) +print("Yayy, we almost done!") + +print("Steps:") +print("1. Review git diff") +print("2. git add idb-companion.rb") +print(f'3. git commit -m "idb v{release}" && git push') diff --git a/proto/idb.proto b/proto/idb.proto index f5c27b4d9..dcafa5ee9 100644 --- a/proto/idb.proto +++ b/proto/idb.proto @@ -1,5 +1,5 @@ /* - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -36,6 +36,7 @@ service CompanionService { returns (SimulateMemoryWarningResponse) {} // Settings rpc approve(ApproveRequest) returns (ApproveResponse) {} + rpc revoke(RevokeRequest) returns (RevokeResponse) {} rpc clear_keychain(ClearKeychainRequest) returns (ClearKeychainResponse) {} rpc contacts_update(ContactsUpdateRequest) returns (ContactsUpdateResponse) {} rpc setting(SettingRequest) returns (SettingResponse) {} // Sets settings @@ -116,6 +117,22 @@ message SettingRequest { string value = 2; string name = 3; // iff setting == ANY string domain = 4; // assumed "Apple Global Domain" if empty + /* + * Currently supported value_types and corresponding values are: + * string + * data + * int[eger] + * float + * bool[ean] (true | false | yes | no) + * date + * array ... + * array-add ... + * dict ... + * dict-add ... + * + * Check defaults set help for more details. + */ + string value_type = 5; } oneof setting { HardwareKeyboard hardwareKeyboard = 1; @@ -174,12 +191,24 @@ message InstallRequest { DSYM = 3; FRAMEWORK = 4; } + message LinkDsymToBundle { + enum BundleType { + APP = 0; + XCTEST = 1; + } + BundleType bundle_type = 1; + string bundle_id = 2; + } oneof value { Destination destination = 1; Payload payload = 2; string name_hint = 3; bool make_debuggable = 4; - string bundle_id = 5; // dSYM for app + string bundle_id = 5; //(2022-03-02) REMOVE, For back compatibility only. + // Link dSYM to app bundle_id + LinkDsymToBundle link_dsym_to_bundle = 6; + bool override_modification_time = 7; + bool skip_signing_bundles = 8; } } @@ -226,6 +255,7 @@ message ApproveRequest { URL = 3; LOCATION = 4; NOTIFICATION = 5; + MICROPHONE = 6; } string bundle_id = 1; repeated Permission permissions = 2; @@ -234,6 +264,23 @@ message ApproveRequest { message ApproveResponse {} +message RevokeRequest { + enum Permission { + PHOTOS = 0; + CAMERA = 1; + CONTACTS = 2; + URL = 3; + LOCATION = 4; + NOTIFICATION = 5; + MICROPHONE = 6; + } + string bundle_id = 1; + repeated Permission permissions = 2; + string scheme = 3; +} + +message RevokeResponse {} + message ClearKeychainRequest {} message ClearKeychainResponse {} @@ -407,6 +454,7 @@ message VideoStreamRequest { RBGA = 1; MJPEG = 2; MINICAP = 3; + I420 = 4; } message Start { string file_path = 1; @@ -414,6 +462,8 @@ message VideoStreamRequest { Format format = 3; double compression_quality = 4; double scale_factor = 5; + double avg_bitrate = 6; + double key_frame_rate = 7; } message Stop {} oneof control { @@ -644,6 +694,7 @@ message XctestRunRequest { } bool collect = 1; Format format = 2; + bool enable_continuous_coverage_collection = 3; } Mode mode = 1; string test_bundle_id = 2; @@ -658,6 +709,7 @@ message XctestRunRequest { bool collect_logs = 11; bool wait_for_debugger = 12; CodeCoverage code_coverage = 13; + bool collect_result_bundle = 14; } message XctestRunResponse { @@ -672,6 +724,7 @@ message XctestRunResponse { double timestamp = 2; string name = 3; string uniform_type_identifier = 4; + bytes user_info_json = 5; } message TestActivity { string title = 1; @@ -697,6 +750,7 @@ message XctestRunResponse { TestRunFailureInfo failure_info = 6; repeated string logs = 7; repeated TestActivity activityLogs = 8; + repeated TestRunFailureInfo other_failures = 9; } enum Status { RUNNING = 0; @@ -730,6 +784,11 @@ message FileContainer { GROUP_CONTAINER = 10; APPLICATION_CONTAINER = 11; AUXILLARY = 12; + XCTEST = 13; + DYLIB = 14; + DSYM = 15; + FRAMEWORK = 16; + SYMBOLS = 17; } Kind kind = 1; string bundle_id = 2; diff --git a/setup.py b/setup.py index 7c40f82c3..f77ff91e1 100644 --- a/setup.py +++ b/setup.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. +# Copyright (c) Meta Platforms, Inc. and affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. diff --git a/website/docs/architecture.mdx b/website/docs/architecture.mdx index 453ffaeb0..4598551f2 100644 --- a/website/docs/architecture.mdx +++ b/website/docs/architecture.mdx @@ -29,7 +29,7 @@ Additionally, the `idb_companion` has some commands that are deliberately unavai The `idb` cli will, by default operate in one of two modes: -- If the `idb` cli is running on macOS, then it will automatically start and stop companions for all targets that are attached to your Mac. This means that you can run commands against any iOS Simulators that you have, as well as any devies that you have connected. +- If the `idb` cli is running on macOS, then it will automatically start and stop companions for all targets that are attached to your Mac. This means that you can run commands against any iOS Simulators that you have, as well as any devices that you have connected. - If the `idb` cli is running on any other OS, it will not manage companions for you. In this case you can either "attach" companions via `idb connect` or explictly on every call using the `IDB_COMPANION=hostname:port` environment variable. This allows you to perform `idb` commands against companions running on other hosts. These facilities for companion discovery work on macOS also. ## Differences between Devices, Simulators & Emulators @@ -43,7 +43,7 @@ iOS Devices and Simulators behave in substantially different ways, as well as Si - As Simulators run natively, they have similar performance characteristics to that of the host. In a sense Simulator Applications perform in a similar way to a macOS application running on macOS. This usually means that Simulators are substantially more performant than emulators, even when an emulator has access to a hypervisor and is running the same ISA. - iOS Simulators have the concept of a "root" directory, which can be thought of as the Simulator's Filesystem. Applications running inside the Simulator still have access to files outside of this root (there is no [`chroot`'ing](https://en.wikipedia.org/wiki/Chroot) inside of the Simulator), so are able to manipulate files that are outside of this root. Applications are also able to manipulate files outside of their own "Application Sandbox" which is not the case on iOS Devices. - This lack of isolation in iOS Simulators is a double edged sword. It can make certain automation cases more convenient to implement, but it is not easy to ensure that a Simulator has access to a limited amount of system resources. For example, emulators typically allow setting an upper limit on the number of cores or memory that can be consumed by the "guest" OS, where iOS Simulators can access the same resources that any application on the host can. This makes it harder to isolate multiple iOS Simulators running on the same host from each other. For instance, an iOS Simulator Application that consumes extreme amounts of system resources will exhaust these resources for other applications, processes or Simulators running on the same host. -- iOS Devices are very strict about isolating processes from each other as well as the host to which it is attached. Interaction between the host and attached iOS Device is only possible through purpose-built APIs that exposes functionality for existing host-device behaviours. For instance, iOS App launching is implemented on iOS Devices through APIs that are used by the "Instruments" Application. This functionality is typically provided over a socket transport, with varying different protocol implementations depending on the domain. Access to these services is arbitrated via a `lockdown` service running on the iOS Device. +- iOS Devices are very strict about isolating processes from each other as well as the host to which it is attached. Interaction between the host and attached iOS Device is only possible through purpose-built APIs that expose functionality for existing host-device behaviours. For instance, iOS App launching is implemented on iOS Devices through APIs that are used by the "Instruments" Application. This functionality is typically provided over a socket transport, with varying different protocol implementations depending on the domain. Access to these services is arbitrated via a `lockdown` service running on the iOS Device. - As such, the implementations for functionality across iOS Simulators & Devices are drastically different, even within Xcode's own Frameworks. ## Framework Concepts diff --git a/website/docs/fbdevicecontrol.mdx b/website/docs/fbdevicecontrol.mdx index 8cb287ba0..128d05764 100644 --- a/website/docs/fbdevicecontrol.mdx +++ b/website/docs/fbdevicecontrol.mdx @@ -45,7 +45,7 @@ There are a number of function calls relevant to this type, dealing with sending It is important to stress that this types is just a "Transport" rather than a "Protocol". Each "lockdown service" may have it's own very different binary protocol for sending and recieving data. In the simple case of `com.apple.syslog_relay`, the service just repeatedly sends text over the connection. Other protocols, for instance those used by Instruments are far more complicated. There is no single Protocol that is used by all lockdown services. -There is one exception to this, the ["Plist Protocol"](https://github.com/facebook/idb/blob/main/FBDeviceControl/Management/FBAMDServiceConnection.h#L83). This is implemented in `AMDServiceConnection(Send|Recieve)Message` calls. This is common across a range of services, such as the screenshot service and SpringBoard service. It's essentially wiring a length header followed by a binary plist, this is used on both the send and recieve sides. +There is one exception to this, the ["Plist Protocol"](https://github.com/facebook/idb/blob/main/FBDeviceControl/Management/FBAMDServiceConnection.h#L83). This is implemented in `AMDServiceConnection(Send|Recieve)Message` calls. This is common across a range of services, such as the screenshot service and SpringBoard service. It's essentially wiring a length header followed by a binary plist, this is used on both the send and receive sides. ## `AFC`: "Apple File Connection" @@ -126,6 +126,79 @@ The client-side implementation of this protocol is provided via `DTXConnectionSe One of the key features of `FBDeviceControl` is the ability to stream the iPhone's screen to the host over USB. You might be familiar with this within QuickTime's "Screen Recording" feature, where you can record video from a connected iOS Device to an `.mp4` file on your Mac. -Access to this [is provided via `AVFoundation`](https://github.com/facebook/idb/blob/main/FBDeviceControl/Video/FBDeviceVideo.m#L38) as a "Capture Device". Usage of "Capture Devices" on macOS also requires that the hosting process (The process using `FBDeviceControl`) has system-level permissions for this on more recent versions of macOS. With a Capture Device for the iOS Device screen, it is then possible to create a "Capture Session" with the device. A "Capture Session" can thent be established, with relevant configuration so that frames are recieved in the most optimal format for the consumer. `FBDeviceControl` recieves frame samples from the device and these samples are either re-encoded or not before being passed on to a stream of data. +Access to this [is provided via `AVFoundation`](https://github.com/facebook/idb/blob/main/FBDeviceControl/Video/FBDeviceVideo.m#L38) as a "Capture Device". Usage of "Capture Devices" on macOS also requires that the hosting process (The process using `FBDeviceControl`) has system-level permissions for this on more recent versions of macOS. With a Capture Device for the iOS Device screen, it is then possible to create a "Capture Session" with the device. A "Capture Session" can thent be established, with relevant configuration so that frames are received in the most optimal format for the consumer. `FBDeviceControl` receives frame samples from the device and these samples are either re-encoded or not before being passed on to a stream of data. `FBDeviceControl` supports writing to an `mp4` video file or as a stream of encoded data. For streams of data, these can be passed to other Applications for cases like webRTC or HTTP Live-Streaming. + +## Debugging Applications + +`idb` (via `FBDeviceControl`) has support for launching a `debugserver` on an iOS Device. This enables debugging Apps on iOS Devices, without having to run via Xcode. There are some important considerations in terms of what is possible: + +- Only `lldb` may be used as the debugger client. +- Only "Developer Signed" Applications may be debugged. Debugging Enterprise signed or App Store Apps is not supported or allowed by iOS. +- Attaching to an already-launched Application is not supported or allowed by iOS. Debugged Applications must be launched by the debugger. + +Debugging an app on an iOS Device isn't quite as simple as an `lldb` one-liner. However, the only process that changes is how to start a debugging session. The process for a device is as follows: + +1. The Application to debug is installed on the iOS Device. A copy of the Application is also present/saved on the host attached to the device. The copy of the App is required on the host as this is needed for `lldb` to be able to symbolicate symbols within the debugged app. +2. [A Developer Disk Image](#developer-disk-images) for the current device is mounted. This is required as the `debugserver` lockdown service is contained within the Developer Disk Image. +3. The [`debugserver` service is started via lockdown](https://github.com/facebook/idb/blob/main/FBDeviceControl/Commands/FBDeviceDebuggerCommands.m#L76). This results in a bi-directional socket stream that `lldb` can talk to. This is a [remote debugging server, using the gdb protocol](https://lldb.llvm.org/use/remote.html). +4. The `debugserver` service must be made accessible to `lldb`. This is done by wrapping the `debugserver` connection within a socket, so that it can be connected to outside of the process that obtained the `debugserver` socket. +5. `lldb` is started and then connects to the `debugserver` via the exposed socket. A series of commands are sent to `lldb` so that it understands how to connect to the remote debugserver and how to talk to it. +6. `lldb` can now launch and debug the application. + +### A "debuggable app" + +Aside from the previously-mentioned requirement that an App is only debuggable if it is "Developer Signed", there is an additional contraint around App debuggability; a copy of the Application must be persisted on the host attached to the device. This is required so that `lldb` has a local copy of the Application available to it for the purpose of symbolication. + +`idb` can do this via the `--make-debuggable` flag upon an `idb install`: + +``` +# Install an app, also persisting it to disk so that idb can later find it when launching a debugserver +$ idb install --make-debuggable /path/to/SomeApp.app +``` + +You can also confirm whether an app is debuggable or not in the output of `idb list-apps`: + +``` +$ idb list-apps | grep SomeApp +com.foo.SomeApp | SomeApp | user_development | no archs available | Unknown | Debuggable | pid=None +``` + +If the application is listed as "Debuggable" then a `debugserver` can be started against it. + +### Starting a `debugserver` + +A `debugserver` can then be started for any "Debuggable" App. This is done with the `idb debugserver` command. + +``` +# Start the debugserver, a list of bootstrapping commands are returned on stdout +$ idb debugserver start com.foo.SomeApp +platform select remote-ios --sysroot '/Users/Someone/Library/Developer/Xcode/iOS DeviceSupport/15.2.1 (19C63) arm64e/Symbols' +target create '/private/tmp/idb-applications/com.foo.SomeApp/SomeApp.app' +script lldb.target.modules[0].SetPlatformFileSpec(lldb.SBFileSpec("/private/var/containers/Bundle/Application/64B4DDB3-1049-458C-AA0B-F56AF4DCF0E0/SomeApp.app")) +process connect connect://localhost:10881 +``` + +The bootstrapping commands returned can then be used to initialize a debug session via `lldb`. + +### Bootstrapping via `lldb` + +``` +# Start lldb and pass the bootrapping commands from above +$ lldb +(lldb) platform select remote-ios --sysroot '/Users/Someone/Library/Developer/Xcode/iOS DeviceSupport/15.2.1 (19C63) arm64e/Symbols' + Platform: remote-ios + Connected: no + SDK Path: "/Users/Someone/Library/Developer/Xcode/iOS DeviceSupport/15.2.1 (19C63) arm64e/Symbols" +(lldb) target create '/private/tmp/idb-applications/com.foo.SomeApp/SomeApp.app' +script lldb.target.modules[0].SetPlatformFileSpec(lldb.SBFileSpec("/private/var/containers/Bundle/Application/64B4DDB3-1049-458C-AA0B-F56AF4DCF0E0/SomeApp.app"))Current executable set to '/private/tmp/idb-applications/com.foo.SomeApp/SomeApp.app' (arm64). +(lldb) script lldb.target.modules[0].SetPlatformFileSpec(lldb.SBFileSpec("/private/var/containers/Bundle/Application/64B4DDB3-1049-458C-AA0B-F56AF4DCF0E0/SomeApp.app")) +True +(lldb) process connect connect://localhost:10881 +(lldb) r +Process 10416 launched: '/private/tmp/idb-applications/com.foo.SomeApp/SomeApp.app/SomeApp' (arm64) +``` + +Upon `process connect` completing, the `lldb` will then be attached to the remote `debugserver`. The app will in a ready state, but not launched, this can be done with the `run` command in `lldb` that will launch the app. +At this point `lldb` can be used as a regular debugger, there's some [good documentation about how to use `lldb` via it's command prompt in `lldb`'s documenation](https://lldb.llvm.org/use/map.html). One important note is that you can only have one debug session with a launched debugserver. To start a new debug session after `process connect`, the debugserver needs to be re-started via `idb debugserver stop` and subsequently running `idb debugserver start` again. diff --git a/website/docs/installation.mdx b/website/docs/installation.mdx index 3bc5e2bb3..44f275390 100644 --- a/website/docs/installation.mdx +++ b/website/docs/installation.mdx @@ -30,6 +30,6 @@ pip3.6 install fb-idb Note: The idb client requires python 3.6 or greater to be installed. -Note: Instructions on how to install pip can be found [here](https://pip.pypa.io/en/stable/installing/) +Note: Instructions on how to install pip can be found [here](https://pip.pypa.io/en/stable/installation/) Make sure both parts of idb are installed successfully and then you're good to go! Head over to the [guided tour](guided-tour.mdx) to try idb out. diff --git a/website/docs/overview.mdx b/website/docs/overview.mdx index 259438c50..f4e4c5fc8 100644 --- a/website/docs/overview.mdx +++ b/website/docs/overview.mdx @@ -3,4 +3,4 @@ id: overview title: Overview --- -iOS Debug Bridge (idb) is a versatile tool for automating iOS Simulators & Devices. It exposes a lot of functionality that is spread over Apple's tools in a consistent and human-friendly interface. +iOS Development Bridge (idb) is a versatile tool for automating iOS Simulators & Devices. It exposes a lot of functionality that is spread over Apple's tools in a consistent and human-friendly interface. diff --git a/website/docusaurus.config.js b/website/docusaurus.config.js index 52b39d8fe..260461dd9 100644 --- a/website/docusaurus.config.js +++ b/website/docusaurus.config.js @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -14,6 +14,14 @@ module.exports = { organizationName: 'facebook', projectName: 'idb', themeConfig: { + announcementBar: { + id: 'support_ukraine', + content: + 'Support Ukraine 🇺🇦 Help Provide Humanitarian Aid to Ukraine.', + backgroundColor: '#20232a', + textColor: '#fff', + isCloseable: false, + }, navbar: { title: 'idb', items: [ diff --git a/website/package.json b/website/package.json index bcf23cdbd..d7ed7335d 100644 --- a/website/package.json +++ b/website/package.json @@ -7,19 +7,26 @@ }, "license": "MIT", "dependencies": { - "@docusaurus/core": "^2.0.0-beta.9", - "@docusaurus/preset-classic": "^2.0.0-beta.9", - "browserslist": ">4.16.5", + "@docusaurus/core": "^2.0.0-beta", + "@docusaurus/preset-classic": "^2.0.0-beta", "classnames": "^2.3.1", - "css-what": "^5.0.1", - "glob-parent": ">5.1.2", - "react": "^17.0.2", - "react-dom": "^17.0.2" + "react": "^17", + "react-dom": "^17", + "yarn": "^1.22", + "follow-redirects": "^1.14", + "node-forge": "^1.3", + "minimist": "^1.2", + "async": "^2.6" }, "resolutions": { "browserslist": ">4.16.5", "trim": "^1.0.1", - "css-what": "^5.0.1", - "glob-parent": ">5.1.2" + "css-what": ">5.0.1", + "follow-redirects": ">=1.14.9", + "node-forge": ">=1.3.0", + "minimist": ">=1.2.6", + "async": ">=2.6.4", + "got": ">=11.8.5", + "semver": ">=7.5.2" } } diff --git a/website/sidebars.js b/website/sidebars.js index 85aeaca3f..d3da67df8 100644 --- a/website/sidebars.js +++ b/website/sidebars.js @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/website/src/pages/index.js b/website/src/pages/index.js index b36030a69..6a35a6c73 100644 --- a/website/src/pages/index.js +++ b/website/src/pages/index.js @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. diff --git a/website/src/pages/styles.module.css b/website/src/pages/styles.module.css index 441c548af..b7fd9e714 100644 --- a/website/src/pages/styles.module.css +++ b/website/src/pages/styles.module.css @@ -1,5 +1,5 @@ /** - * Copyright (c) Facebook, Inc. and its affiliates. + * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. @@ -40,3 +40,40 @@ height: 200px; width: 200px; } + +/* Announcement banner */ + +:root { + --docusaurus-announcement-bar-height: auto !important; +} + +div[class^="announcementBarContent"] { + line-height: 40px; + font-size: 20px; + font-weight: bold; + padding: 8px 30px; +} + +div[class^="announcementBarContent"] a { + text-decoration: underline; + display: inline-block; + color: var(--ifm-color-primary-lightest) !important; +} + +div[class^="announcementBarContent"] a:hover { + color: var(--brand) !important; +} + +@media only screen and (max-width: 768px) { + .announcement { + font-size: 18px; + } +} + +@media only screen and (max-width: 500px) { + .announcement { + font-size: 15px; + line-height: 22px; + padding: 6px 30px; + } +} diff --git a/website/yarn.lock b/website/yarn.lock index ac73bbe5f..60f32c355 100644 --- a/website/yarn.lock +++ b/website/yarn.lock @@ -2,140 +2,153 @@ # yarn lockfile v1 -"@algolia/autocomplete-core@1.2.2": - version "1.2.2" - resolved "https://registry.yarnpkg.com/@algolia/autocomplete-core/-/autocomplete-core-1.2.2.tgz#c121e70c78fd0175c989a219918124ad7758e48b" - integrity sha512-JOQaURze45qVa8OOFDh+ozj2a/ObSRsVyz6Zd0aiBeej+RSTqrr1hDVpGNbbXYLW26G5ujuc9QIdH+rBHn95nw== - dependencies: - "@algolia/autocomplete-shared" "1.2.2" - -"@algolia/autocomplete-preset-algolia@1.2.2": - version "1.2.2" - resolved "https://registry.yarnpkg.com/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.2.2.tgz#da734ef9e42a5f64cdad2dfc81c4e9fbf805d976" - integrity sha512-AZkh+bAMaJDzMZTelFOXJTJqkp5VPGH8W3n0B+Ggce7DdozlMRsDLguKTCQAkZ0dJ1EbBPyFL5ztL/JImB137Q== - dependencies: - "@algolia/autocomplete-shared" "1.2.2" - -"@algolia/autocomplete-shared@1.2.2": - version "1.2.2" - resolved "https://registry.yarnpkg.com/@algolia/autocomplete-shared/-/autocomplete-shared-1.2.2.tgz#ff25dc308f2a296b2b9b325f1e3b57498eea3e0c" - integrity sha512-mLTl7d2C1xVVazHt/bqh9EE/u2lbp5YOxLDdcjILXmUqOs5HH1D4SuySblXaQG1uf28FhTqMGp35qE5wJQnqAw== - -"@algolia/cache-browser-local-storage@4.11.0": - version "4.11.0" - resolved "https://registry.yarnpkg.com/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.11.0.tgz#1c168add00b398a860db6c86039e33b2843a9425" - integrity sha512-4sr9vHIG1fVA9dONagdzhsI/6M5mjs/qOe2xUP0yBmwsTsuwiZq3+Xu6D3dsxsuFetcJgC6ydQoCW8b7fDJHYQ== - dependencies: - "@algolia/cache-common" "4.11.0" - -"@algolia/cache-common@4.11.0": - version "4.11.0" - resolved "https://registry.yarnpkg.com/@algolia/cache-common/-/cache-common-4.11.0.tgz#066fe6d58b18e4b028dbef9bb8de07c5e22a3594" - integrity sha512-lODcJRuPXqf+6mp0h6bOxPMlbNoyn3VfjBVcQh70EDP0/xExZbkpecgHyyZK4kWg+evu+mmgvTK3GVHnet/xKw== - -"@algolia/cache-in-memory@4.11.0": - version "4.11.0" - resolved "https://registry.yarnpkg.com/@algolia/cache-in-memory/-/cache-in-memory-4.11.0.tgz#763c8cb655e6fd2261588e04214fca0959ac07c1" - integrity sha512-aBz+stMSTBOBaBEQ43zJXz2DnwS7fL6dR0e2myehAgtfAWlWwLDHruc/98VOy1ZAcBk1blE2LCU02bT5HekGxQ== +"@algolia/autocomplete-core@1.7.2": + version "1.7.2" + resolved "https://registry.yarnpkg.com/@algolia/autocomplete-core/-/autocomplete-core-1.7.2.tgz#8abbed88082f611997538760dffcb43b33b1fd1d" + integrity sha512-eclwUDC6qfApNnEfu1uWcL/rudQsn59tjEoUYZYE2JSXZrHLRjBUGMxiCoknobU2Pva8ejb0eRxpIYDtVVqdsw== dependencies: - "@algolia/cache-common" "4.11.0" + "@algolia/autocomplete-shared" "1.7.2" -"@algolia/client-account@4.11.0": - version "4.11.0" - resolved "https://registry.yarnpkg.com/@algolia/client-account/-/client-account-4.11.0.tgz#67fadd3b0802b013ebaaa4b47bb7babae892374e" - integrity sha512-jwmFBoUSzoMwMqgD3PmzFJV/d19p1RJXB6C1ADz4ju4mU7rkaQLtqyZroQpheLoU5s5Tilmn/T8/0U2XLoJCRQ== +"@algolia/autocomplete-preset-algolia@1.7.2": + version "1.7.2" + resolved "https://registry.yarnpkg.com/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.7.2.tgz#9cd4f64b3d64399657ee2dc2b7e0a939e0713a26" + integrity sha512-+RYEG6B0QiGGfRb2G3MtPfyrl0dALF3cQNTWBzBX6p5o01vCCGTTinAm2UKG3tfc2CnOMAtnPLkzNZyJUpnVJw== dependencies: - "@algolia/client-common" "4.11.0" - "@algolia/client-search" "4.11.0" - "@algolia/transporter" "4.11.0" + "@algolia/autocomplete-shared" "1.7.2" -"@algolia/client-analytics@4.11.0": - version "4.11.0" - resolved "https://registry.yarnpkg.com/@algolia/client-analytics/-/client-analytics-4.11.0.tgz#cbdc8128205e2da749cafc79e54708d14c413974" - integrity sha512-v5U9585aeEdYml7JqggHAj3E5CQ+jPwGVztPVhakBk8H/cmLyPS2g8wvmIbaEZCHmWn4TqFj3EBHVYxAl36fSA== - dependencies: - "@algolia/client-common" "4.11.0" - "@algolia/client-search" "4.11.0" - "@algolia/requester-common" "4.11.0" - "@algolia/transporter" "4.11.0" +"@algolia/autocomplete-shared@1.7.2": + version "1.7.2" + resolved "https://registry.yarnpkg.com/@algolia/autocomplete-shared/-/autocomplete-shared-1.7.2.tgz#daa23280e78d3b42ae9564d12470ae034db51a89" + integrity sha512-QCckjiC7xXHIUaIL3ektBtjJ0w7tTA3iqKcAE/Hjn1lZ5omp7i3Y4e09rAr9ZybqirL7AbxCLLq0Ra5DDPKeug== + +"@algolia/cache-browser-local-storage@4.14.2": + version "4.14.2" + resolved "https://registry.yarnpkg.com/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.14.2.tgz#d5b1b90130ca87c6321de876e167df9ec6524936" + integrity sha512-FRweBkK/ywO+GKYfAWbrepewQsPTIEirhi1BdykX9mxvBPtGNKccYAxvGdDCumU1jL4r3cayio4psfzKMejBlA== + dependencies: + "@algolia/cache-common" "4.14.2" + +"@algolia/cache-common@4.14.2": + version "4.14.2" + resolved "https://registry.yarnpkg.com/@algolia/cache-common/-/cache-common-4.14.2.tgz#b946b6103c922f0c06006fb6929163ed2c67d598" + integrity sha512-SbvAlG9VqNanCErr44q6lEKD2qoK4XtFNx9Qn8FK26ePCI8I9yU7pYB+eM/cZdS9SzQCRJBbHUumVr4bsQ4uxg== + +"@algolia/cache-in-memory@4.14.2": + version "4.14.2" + resolved "https://registry.yarnpkg.com/@algolia/cache-in-memory/-/cache-in-memory-4.14.2.tgz#88e4a21474f9ac05331c2fa3ceb929684a395a24" + integrity sha512-HrOukWoop9XB/VFojPv1R5SVXowgI56T9pmezd/djh2JnVN/vXswhXV51RKy4nCpqxyHt/aGFSq2qkDvj6KiuQ== + dependencies: + "@algolia/cache-common" "4.14.2" + +"@algolia/client-account@4.14.2": + version "4.14.2" + resolved "https://registry.yarnpkg.com/@algolia/client-account/-/client-account-4.14.2.tgz#b76ac1ba9ea71e8c3f77a1805b48350dc0728a16" + integrity sha512-WHtriQqGyibbb/Rx71YY43T0cXqyelEU0lB2QMBRXvD2X0iyeGl4qMxocgEIcbHyK7uqE7hKgjT8aBrHqhgc1w== + dependencies: + "@algolia/client-common" "4.14.2" + "@algolia/client-search" "4.14.2" + "@algolia/transporter" "4.14.2" + +"@algolia/client-analytics@4.14.2": + version "4.14.2" + resolved "https://registry.yarnpkg.com/@algolia/client-analytics/-/client-analytics-4.14.2.tgz#ca04dcaf9a78ee5c92c5cb5e9c74cf031eb2f1fb" + integrity sha512-yBvBv2mw+HX5a+aeR0dkvUbFZsiC4FKSnfqk9rrfX+QrlNOKEhCG0tJzjiOggRW4EcNqRmaTULIYvIzQVL2KYQ== + dependencies: + "@algolia/client-common" "4.14.2" + "@algolia/client-search" "4.14.2" + "@algolia/requester-common" "4.14.2" + "@algolia/transporter" "4.14.2" + +"@algolia/client-common@4.14.2": + version "4.14.2" + resolved "https://registry.yarnpkg.com/@algolia/client-common/-/client-common-4.14.2.tgz#e1324e167ffa8af60f3e8bcd122110fd0bfd1300" + integrity sha512-43o4fslNLcktgtDMVaT5XwlzsDPzlqvqesRi4MjQz2x4/Sxm7zYg5LRYFol1BIhG6EwxKvSUq8HcC/KxJu3J0Q== + dependencies: + "@algolia/requester-common" "4.14.2" + "@algolia/transporter" "4.14.2" + +"@algolia/client-personalization@4.14.2": + version "4.14.2" + resolved "https://registry.yarnpkg.com/@algolia/client-personalization/-/client-personalization-4.14.2.tgz#656bbb6157a3dd1a4be7de65e457fda136c404ec" + integrity sha512-ACCoLi0cL8CBZ1W/2juehSltrw2iqsQBnfiu/Rbl9W2yE6o2ZUb97+sqN/jBqYNQBS+o0ekTMKNkQjHHAcEXNw== + dependencies: + "@algolia/client-common" "4.14.2" + "@algolia/requester-common" "4.14.2" + "@algolia/transporter" "4.14.2" + +"@algolia/client-search@4.14.2": + version "4.14.2" + resolved "https://registry.yarnpkg.com/@algolia/client-search/-/client-search-4.14.2.tgz#357bdb7e640163f0e33bad231dfcc21f67dc2e92" + integrity sha512-L5zScdOmcZ6NGiVbLKTvP02UbxZ0njd5Vq9nJAmPFtjffUSOGEp11BmD2oMJ5QvARgx2XbX4KzTTNS5ECYIMWw== + dependencies: + "@algolia/client-common" "4.14.2" + "@algolia/requester-common" "4.14.2" + "@algolia/transporter" "4.14.2" + +"@algolia/events@^4.0.1": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@algolia/events/-/events-4.0.1.tgz#fd39e7477e7bc703d7f893b556f676c032af3950" + integrity sha512-FQzvOCgoFXAbf5Y6mYozw2aj5KCJoA3m4heImceldzPSMbdyS4atVjJzXKMsfX3wnZTFYwkkt8/z8UesLHlSBQ== -"@algolia/client-common@4.11.0": - version "4.11.0" - resolved "https://registry.yarnpkg.com/@algolia/client-common/-/client-common-4.11.0.tgz#9a2d1f6f8eaad25ba5d6d4ce307ba5bd84e6f999" - integrity sha512-Qy+F+TZq12kc7tgfC+FM3RvYH/Ati7sUiUv/LkvlxFwNwNPwWGoZO81AzVSareXT/ksDDrabD4mHbdTbBPTRmQ== - dependencies: - "@algolia/requester-common" "4.11.0" - "@algolia/transporter" "4.11.0" +"@algolia/logger-common@4.14.2": + version "4.14.2" + resolved "https://registry.yarnpkg.com/@algolia/logger-common/-/logger-common-4.14.2.tgz#b74b3a92431f92665519d95942c246793ec390ee" + integrity sha512-/JGlYvdV++IcMHBnVFsqEisTiOeEr6cUJtpjz8zc0A9c31JrtLm318Njc72p14Pnkw3A/5lHHh+QxpJ6WFTmsA== -"@algolia/client-personalization@4.11.0": - version "4.11.0" - resolved "https://registry.yarnpkg.com/@algolia/client-personalization/-/client-personalization-4.11.0.tgz#d3bf0e760f85df876b4baf5b81996f0aa3a59940" - integrity sha512-mI+X5IKiijHAzf9fy8VSl/GTT67dzFDnJ0QAM8D9cMPevnfX4U72HRln3Mjd0xEaYUOGve8TK/fMg7d3Z5yG6g== +"@algolia/logger-console@4.14.2": + version "4.14.2" + resolved "https://registry.yarnpkg.com/@algolia/logger-console/-/logger-console-4.14.2.tgz#ec49cb47408f5811d4792598683923a800abce7b" + integrity sha512-8S2PlpdshbkwlLCSAB5f8c91xyc84VM9Ar9EdfE9UmX+NrKNYnWR1maXXVDQQoto07G1Ol/tYFnFVhUZq0xV/g== dependencies: - "@algolia/client-common" "4.11.0" - "@algolia/requester-common" "4.11.0" - "@algolia/transporter" "4.11.0" + "@algolia/logger-common" "4.14.2" -"@algolia/client-search@4.11.0": - version "4.11.0" - resolved "https://registry.yarnpkg.com/@algolia/client-search/-/client-search-4.11.0.tgz#c1105d715a2a04ba27231eca86f5d6620f68f4ae" - integrity sha512-iovPLc5YgiXBdw2qMhU65sINgo9umWbHFzInxoNErWnYoTQWfXsW6P54/NlKx5uscoLVjSf+5RUWwFu5BX+lpw== +"@algolia/requester-browser-xhr@4.14.2": + version "4.14.2" + resolved "https://registry.yarnpkg.com/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.14.2.tgz#a2cd4d9d8d90d53109cc7f3682dc6ebf20f798f2" + integrity sha512-CEh//xYz/WfxHFh7pcMjQNWgpl4wFB85lUMRyVwaDPibNzQRVcV33YS+63fShFWc2+42YEipFGH2iPzlpszmDw== dependencies: - "@algolia/client-common" "4.11.0" - "@algolia/requester-common" "4.11.0" - "@algolia/transporter" "4.11.0" + "@algolia/requester-common" "4.14.2" -"@algolia/logger-common@4.11.0": - version "4.11.0" - resolved "https://registry.yarnpkg.com/@algolia/logger-common/-/logger-common-4.11.0.tgz#bac1c2d59d29dee378b57412c8edd435b97de663" - integrity sha512-pRMJFeOY8hoWKIxWuGHIrqnEKN/kqKh7UilDffG/+PeEGxBuku+Wq5CfdTFG0C9ewUvn8mAJn5BhYA5k8y0Jqg== +"@algolia/requester-common@4.14.2": + version "4.14.2" + resolved "https://registry.yarnpkg.com/@algolia/requester-common/-/requester-common-4.14.2.tgz#bc4e9e5ee16c953c0ecacbfb334a33c30c28b1a1" + integrity sha512-73YQsBOKa5fvVV3My7iZHu1sUqmjjfs9TteFWwPwDmnad7T0VTCopttcsM3OjLxZFtBnX61Xxl2T2gmG2O4ehg== -"@algolia/logger-console@4.11.0": - version "4.11.0" - resolved "https://registry.yarnpkg.com/@algolia/logger-console/-/logger-console-4.11.0.tgz#ced19e3abb22eb782ed5268d51efb5aa9ef109ef" - integrity sha512-wXztMk0a3VbNmYP8Kpc+F7ekuvaqZmozM2eTLok0XIshpAeZ/NJDHDffXK2Pw+NF0wmHqurptLYwKoikjBYvhQ== +"@algolia/requester-node-http@4.14.2": + version "4.14.2" + resolved "https://registry.yarnpkg.com/@algolia/requester-node-http/-/requester-node-http-4.14.2.tgz#7c1223a1785decaab1def64c83dade6bea45e115" + integrity sha512-oDbb02kd1o5GTEld4pETlPZLY0e+gOSWjWMJHWTgDXbv9rm/o2cF7japO6Vj1ENnrqWvLBmW1OzV9g6FUFhFXg== dependencies: - "@algolia/logger-common" "4.11.0" + "@algolia/requester-common" "4.14.2" -"@algolia/requester-browser-xhr@4.11.0": - version "4.11.0" - resolved "https://registry.yarnpkg.com/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.11.0.tgz#f9e1ad56f185432aa8dde8cad53ae271fd5d6181" - integrity sha512-Fp3SfDihAAFR8bllg8P5ouWi3+qpEVN5e7hrtVIYldKBOuI/qFv80Zv/3/AMKNJQRYglS4zWyPuqrXm58nz6KA== +"@algolia/transporter@4.14.2": + version "4.14.2" + resolved "https://registry.yarnpkg.com/@algolia/transporter/-/transporter-4.14.2.tgz#77c069047fb1a4359ee6a51f51829508e44a1e3d" + integrity sha512-t89dfQb2T9MFQHidjHcfhh6iGMNwvuKUvojAj+JsrHAGbuSy7yE4BylhLX6R0Q1xYRoC4Vvv+O5qIw/LdnQfsQ== dependencies: - "@algolia/requester-common" "4.11.0" - -"@algolia/requester-common@4.11.0": - version "4.11.0" - resolved "https://registry.yarnpkg.com/@algolia/requester-common/-/requester-common-4.11.0.tgz#d16de98d3ff72434bac39e4d915eab08035946a9" - integrity sha512-+cZGe/9fuYgGuxjaBC+xTGBkK7OIYdfapxhfvEf03dviLMPmhmVYFJtJlzAjQ2YmGDJpHrGgAYj3i/fbs8yhiA== + "@algolia/cache-common" "4.14.2" + "@algolia/logger-common" "4.14.2" + "@algolia/requester-common" "4.14.2" -"@algolia/requester-node-http@4.11.0": - version "4.11.0" - resolved "https://registry.yarnpkg.com/@algolia/requester-node-http/-/requester-node-http-4.11.0.tgz#beb2b6b68d5f4ce15aec80ede623f0ac96991368" - integrity sha512-qJIk9SHRFkKDi6dMT9hba8X1J1z92T5AZIgl+tsApjTGIRQXJLTIm+0q4yOefokfu4CoxYwRZ9QAq+ouGwfeOg== +"@ampproject/remapping@^2.1.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.0.tgz#56c133824780de3174aed5ab6834f3026790154d" + integrity sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w== dependencies: - "@algolia/requester-common" "4.11.0" + "@jridgewell/gen-mapping" "^0.1.0" + "@jridgewell/trace-mapping" "^0.3.9" -"@algolia/transporter@4.11.0": - version "4.11.0" - resolved "https://registry.yarnpkg.com/@algolia/transporter/-/transporter-4.11.0.tgz#a8de3c173093ceceb02b26b577395ce3b3d4b96f" - integrity sha512-k4dyxiaEfYpw4UqybK9q7lrFzehygo6KV3OCYJMMdX0IMWV0m4DXdU27c1zYRYtthaFYaBzGF4Kjcl8p8vxCKw== +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.16.0", "@babel/code-frame@^7.18.6", "@babel/code-frame@^7.8.3": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.18.6.tgz#3b25d38c89600baa2dcc219edfa88a74eb2c427a" + integrity sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q== dependencies: - "@algolia/cache-common" "4.11.0" - "@algolia/logger-common" "4.11.0" - "@algolia/requester-common" "4.11.0" - -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.16.0", "@babel/code-frame@^7.8.3": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.16.0.tgz#0dfc80309beec8411e65e706461c408b0bb9b431" - integrity sha512-IF4EOMEV+bfYwOmNxGzSnjR2EmQod7f1UXOpZM3l4i4o4QNwzjtJAu/HxdjHq0aYBvdqMuQEY1eg0nqW9ZPORA== - dependencies: - "@babel/highlight" "^7.16.0" + "@babel/highlight" "^7.18.6" -"@babel/compat-data@^7.13.11", "@babel/compat-data@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.16.0.tgz#ea269d7f78deb3a7826c39a4048eecda541ebdaa" - integrity sha512-DGjt2QZse5SGd9nfOSqO4WLJ8NN/oHkijbXbPrxuoJO3oIPJL3TciZs9FX+cOHNiY9E9l0opL8g7BmLe3T+9ew== +"@babel/compat-data@^7.17.7", "@babel/compat-data@^7.20.0", "@babel/compat-data@^7.20.1": + version "7.20.1" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.20.1.tgz#f2e6ef7790d8c8dbf03d379502dcc246dcce0b30" + integrity sha512-EWZ4mE2diW3QALKvDMiXnbZpRvlj+nayZ112nK93SnhqOtpdsbVD4W+2tEoT3YNBAG9RBR0ISY758ZkOgsn6pQ== "@babel/core@7.12.9": version "7.12.9" @@ -159,341 +172,345 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/core@^7.12.16", "@babel/core@^7.12.3": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.16.0.tgz#c4ff44046f5fe310525cc9eb4ef5147f0c5374d4" - integrity sha512-mYZEvshBRHGsIAiyH5PzCFTCfbWfoYbO/jcSdXQSUQu1/pW0xDZAUP7KEc32heqWTAfAHhV9j1vH8Sav7l+JNQ== - dependencies: - "@babel/code-frame" "^7.16.0" - "@babel/generator" "^7.16.0" - "@babel/helper-compilation-targets" "^7.16.0" - "@babel/helper-module-transforms" "^7.16.0" - "@babel/helpers" "^7.16.0" - "@babel/parser" "^7.16.0" - "@babel/template" "^7.16.0" - "@babel/traverse" "^7.16.0" - "@babel/types" "^7.16.0" +"@babel/core@^7.18.6", "@babel/core@^7.19.6": + version "7.20.2" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.20.2.tgz#8dc9b1620a673f92d3624bd926dc49a52cf25b92" + integrity sha512-w7DbG8DtMrJcFOi4VrLm+8QM4az8Mo+PuLBKLp2zrYRCow8W/f9xiXm5sN53C8HksCyDQwCKha9JiDoIyPjT2g== + dependencies: + "@ampproject/remapping" "^2.1.0" + "@babel/code-frame" "^7.18.6" + "@babel/generator" "^7.20.2" + "@babel/helper-compilation-targets" "^7.20.0" + "@babel/helper-module-transforms" "^7.20.2" + "@babel/helpers" "^7.20.1" + "@babel/parser" "^7.20.2" + "@babel/template" "^7.18.10" + "@babel/traverse" "^7.20.1" + "@babel/types" "^7.20.2" convert-source-map "^1.7.0" debug "^4.1.0" gensync "^1.0.0-beta.2" - json5 "^2.1.2" + json5 "^2.2.1" semver "^6.3.0" - source-map "^0.5.0" -"@babel/generator@^7.12.15", "@babel/generator@^7.12.5", "@babel/generator@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.16.0.tgz#d40f3d1d5075e62d3500bccb67f3daa8a95265b2" - integrity sha512-RR8hUCfRQn9j9RPKEVXo9LiwoxLPYn6hNZlvUOR8tSnaxlD0p0+la00ZP9/SnRt6HchKr+X0fO2r8vrETiJGew== +"@babel/generator@^7.12.5", "@babel/generator@^7.18.7", "@babel/generator@^7.20.1", "@babel/generator@^7.20.2": + version "7.20.4" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.20.4.tgz#4d9f8f0c30be75fd90a0562099a26e5839602ab8" + integrity sha512-luCf7yk/cm7yab6CAW1aiFnmEfBJplb/JojV56MYEK7ziWfGmFlTfmL9Ehwfy4gFhbjBfWO1wj7/TuSbVNEEtA== dependencies: - "@babel/types" "^7.16.0" + "@babel/types" "^7.20.2" + "@jridgewell/gen-mapping" "^0.3.2" jsesc "^2.5.1" - source-map "^0.5.0" -"@babel/helper-annotate-as-pure@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.0.tgz#9a1f0ebcda53d9a2d00108c4ceace6a5d5f1f08d" - integrity sha512-ItmYF9vR4zA8cByDocY05o0LGUkp1zhbTQOH1NFyl5xXEqlTJQCEJjieriw+aFpxo16swMxUnUiKS7a/r4vtHg== +"@babel/helper-annotate-as-pure@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz#eaa49f6f80d5a33f9a5dd2276e6d6e451be0a6bb" + integrity sha512-duORpUiYrEpzKIop6iNbjnwKLAKnJ47csTyRACyEmWj0QdUrm5aqNJGHSSEQSUAvNW0ojX0dOmK9dZduvkfeXA== dependencies: - "@babel/types" "^7.16.0" + "@babel/types" "^7.18.6" -"@babel/helper-builder-binary-assignment-operator-visitor@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.16.0.tgz#f1a686b92da794020c26582eb852e9accd0d7882" - integrity sha512-9KuleLT0e77wFUku6TUkqZzCEymBdtuQQ27MhEKzf9UOOJu3cYj98kyaDAzxpC7lV6DGiZFuC8XqDsq8/Kl6aQ== +"@babel/helper-builder-binary-assignment-operator-visitor@^7.18.6": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.18.9.tgz#acd4edfd7a566d1d51ea975dff38fd52906981bb" + integrity sha512-yFQ0YCHoIqarl8BCRwBL8ulYUaZpz3bNsA7oFepAzee+8/+ImtADXNOmO5vJvsPff3qi+hvpkY/NYBTrBQgdNw== dependencies: - "@babel/helper-explode-assignable-expression" "^7.16.0" - "@babel/types" "^7.16.0" + "@babel/helper-explode-assignable-expression" "^7.18.6" + "@babel/types" "^7.18.9" -"@babel/helper-compilation-targets@^7.13.0", "@babel/helper-compilation-targets@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.16.0.tgz#01d615762e796c17952c29e3ede9d6de07d235a8" - integrity sha512-S7iaOT1SYlqK0sQaCi21RX4+13hmdmnxIEAnQUB/eh7GeAnRjOUgTYpLkUOiRXzD+yog1JxP0qyAQZ7ZxVxLVg== +"@babel/helper-compilation-targets@^7.17.7", "@babel/helper-compilation-targets@^7.18.9", "@babel/helper-compilation-targets@^7.20.0": + version "7.20.0" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.0.tgz#6bf5374d424e1b3922822f1d9bdaa43b1a139d0a" + integrity sha512-0jp//vDGp9e8hZzBc6N/KwA5ZK3Wsm/pfm4CrY7vzegkVxc65SgSn6wYOnwHe9Js9HRQ1YTCKLGPzDtaS3RoLQ== dependencies: - "@babel/compat-data" "^7.16.0" - "@babel/helper-validator-option" "^7.14.5" - browserslist "^4.16.6" + "@babel/compat-data" "^7.20.0" + "@babel/helper-validator-option" "^7.18.6" + browserslist "^4.21.3" semver "^6.3.0" -"@babel/helper-create-class-features-plugin@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.16.0.tgz#090d4d166b342a03a9fec37ef4fd5aeb9c7c6a4b" - integrity sha512-XLwWvqEaq19zFlF5PTgOod4bUA+XbkR4WLQBct1bkzmxJGB0ZEJaoKF4c8cgH9oBtCDuYJ8BP5NB9uFiEgO5QA== - dependencies: - "@babel/helper-annotate-as-pure" "^7.16.0" - "@babel/helper-function-name" "^7.16.0" - "@babel/helper-member-expression-to-functions" "^7.16.0" - "@babel/helper-optimise-call-expression" "^7.16.0" - "@babel/helper-replace-supers" "^7.16.0" - "@babel/helper-split-export-declaration" "^7.16.0" - -"@babel/helper-create-regexp-features-plugin@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.16.0.tgz#06b2348ce37fccc4f5e18dcd8d75053f2a7c44ff" - integrity sha512-3DyG0zAFAZKcOp7aVr33ddwkxJ0Z0Jr5V99y3I690eYLpukJsJvAbzTy1ewoCqsML8SbIrjH14Jc/nSQ4TvNPA== - dependencies: - "@babel/helper-annotate-as-pure" "^7.16.0" - regexpu-core "^4.7.1" - -"@babel/helper-define-polyfill-provider@^0.2.4": - version "0.2.4" - resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.2.4.tgz#8867aed79d3ea6cade40f801efb7ac5c66916b10" - integrity sha512-OrpPZ97s+aPi6h2n1OXzdhVis1SGSsMU2aMHgLcOKfsp4/v1NWpx3CWT3lBj5eeBq9cDkPkh+YCfdF7O12uNDQ== - dependencies: - "@babel/helper-compilation-targets" "^7.13.0" - "@babel/helper-module-imports" "^7.12.13" - "@babel/helper-plugin-utils" "^7.13.0" - "@babel/traverse" "^7.13.0" +"@babel/helper-create-class-features-plugin@^7.18.6", "@babel/helper-create-class-features-plugin@^7.20.2": + version "7.20.2" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.20.2.tgz#3c08a5b5417c7f07b5cf3dfb6dc79cbec682e8c2" + integrity sha512-k22GoYRAHPYr9I+Gvy2ZQlAe5mGy8BqWst2wRt8cwIufWTxrsVshhIBvYNqC80N0GSFWTsqRVexOtfzlgOEDvA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.18.6" + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-function-name" "^7.19.0" + "@babel/helper-member-expression-to-functions" "^7.18.9" + "@babel/helper-optimise-call-expression" "^7.18.6" + "@babel/helper-replace-supers" "^7.19.1" + "@babel/helper-split-export-declaration" "^7.18.6" + +"@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.19.0": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.19.0.tgz#7976aca61c0984202baca73d84e2337a5424a41b" + integrity sha512-htnV+mHX32DF81amCDrwIDr8nrp1PTm+3wfBN9/v8QJOLEioOCOG7qNyq0nHeFiWbT3Eb7gsPwEmV64UCQ1jzw== + dependencies: + "@babel/helper-annotate-as-pure" "^7.18.6" + regexpu-core "^5.1.0" + +"@babel/helper-define-polyfill-provider@^0.3.3": + version "0.3.3" + resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.3.tgz#8612e55be5d51f0cd1f36b4a5a83924e89884b7a" + integrity sha512-z5aQKU4IzbqCC1XH0nAqfsFLMVSo22SBKUc0BxGrLkolTdPTructy0ToNnlO2zA4j9Q/7pjMZf0DSY+DSTYzww== + dependencies: + "@babel/helper-compilation-targets" "^7.17.7" + "@babel/helper-plugin-utils" "^7.16.7" debug "^4.1.1" lodash.debounce "^4.0.8" resolve "^1.14.2" semver "^6.1.2" -"@babel/helper-explode-assignable-expression@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.16.0.tgz#753017337a15f46f9c09f674cff10cee9b9d7778" - integrity sha512-Hk2SLxC9ZbcOhLpg/yMznzJ11W++lg5GMbxt1ev6TXUiJB0N42KPC+7w8a+eWGuqDnUYuwStJoZHM7RgmIOaGQ== - dependencies: - "@babel/types" "^7.16.0" +"@babel/helper-environment-visitor@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz#0c0cee9b35d2ca190478756865bb3528422f51be" + integrity sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg== -"@babel/helper-function-name@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.16.0.tgz#b7dd0797d00bbfee4f07e9c4ea5b0e30c8bb1481" - integrity sha512-BZh4mEk1xi2h4HFjWUXRQX5AEx4rvaZxHgax9gcjdLWdkjsY7MKt5p0otjsg5noXw+pB+clMCjw+aEVYADMjog== +"@babel/helper-explode-assignable-expression@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz#41f8228ef0a6f1a036b8dfdfec7ce94f9a6bc096" + integrity sha512-eyAYAsQmB80jNfg4baAtLeWAQHfHFiR483rzFK+BhETlGZaQC9bsfrugfXDCbRHLQbIA7U5NxhhOxN7p/dWIcg== dependencies: - "@babel/helper-get-function-arity" "^7.16.0" - "@babel/template" "^7.16.0" - "@babel/types" "^7.16.0" + "@babel/types" "^7.18.6" -"@babel/helper-get-function-arity@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.16.0.tgz#0088c7486b29a9cb5d948b1a1de46db66e089cfa" - integrity sha512-ASCquNcywC1NkYh/z7Cgp3w31YW8aojjYIlNg4VeJiHkqyP4AzIvr4qx7pYDb4/s8YcsZWqqOSxgkvjUz1kpDQ== +"@babel/helper-function-name@^7.18.9", "@babel/helper-function-name@^7.19.0": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz#941574ed5390682e872e52d3f38ce9d1bef4648c" + integrity sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w== dependencies: - "@babel/types" "^7.16.0" + "@babel/template" "^7.18.10" + "@babel/types" "^7.19.0" -"@babel/helper-hoist-variables@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.16.0.tgz#4c9023c2f1def7e28ff46fc1dbcd36a39beaa81a" - integrity sha512-1AZlpazjUR0EQZQv3sgRNfM9mEVWPK3M6vlalczA+EECcPz3XPh6VplbErL5UoMpChhSck5wAJHthlj1bYpcmg== +"@babel/helper-hoist-variables@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz#d4d2c8fb4baeaa5c68b99cc8245c56554f926678" + integrity sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q== dependencies: - "@babel/types" "^7.16.0" + "@babel/types" "^7.18.6" -"@babel/helper-member-expression-to-functions@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.16.0.tgz#29287040efd197c77636ef75188e81da8bccd5a4" - integrity sha512-bsjlBFPuWT6IWhl28EdrQ+gTvSvj5tqVP5Xeftp07SEuz5pLnsXZuDkDD3Rfcxy0IsHmbZ+7B2/9SHzxO0T+sQ== +"@babel/helper-member-expression-to-functions@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.18.9.tgz#1531661e8375af843ad37ac692c132841e2fd815" + integrity sha512-RxifAh2ZoVU67PyKIO4AMi1wTenGfMR/O/ae0CCRqwgBAt5v7xjdtRw7UoSbsreKrQn5t7r89eruK/9JjYHuDg== dependencies: - "@babel/types" "^7.16.0" + "@babel/types" "^7.18.9" -"@babel/helper-module-imports@^7.12.13", "@babel/helper-module-imports@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.16.0.tgz#90538e60b672ecf1b448f5f4f5433d37e79a3ec3" - integrity sha512-kkH7sWzKPq0xt3H1n+ghb4xEMP8k0U7XV3kkB+ZGy69kDk2ySFW1qPi06sjKzFY3t1j6XbJSqr4mF9L7CYVyhg== +"@babel/helper-module-imports@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz#1e3ebdbbd08aad1437b428c50204db13c5a3ca6e" + integrity sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA== dependencies: - "@babel/types" "^7.16.0" + "@babel/types" "^7.18.6" -"@babel/helper-module-transforms@^7.12.1", "@babel/helper-module-transforms@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.16.0.tgz#1c82a8dd4cb34577502ebd2909699b194c3e9bb5" - integrity sha512-My4cr9ATcaBbmaEa8M0dZNA74cfI6gitvUAskgDtAFmAqyFKDSHQo5YstxPbN+lzHl2D9l/YOEFqb2mtUh4gfA== +"@babel/helper-module-transforms@^7.12.1", "@babel/helper-module-transforms@^7.18.6", "@babel/helper-module-transforms@^7.19.6", "@babel/helper-module-transforms@^7.20.2": + version "7.20.2" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.20.2.tgz#ac53da669501edd37e658602a21ba14c08748712" + integrity sha512-zvBKyJXRbmK07XhMuujYoJ48B5yvvmM6+wcpv6Ivj4Yg6qO7NOZOSnvZN9CRl1zz1Z4cKf8YejmCMh8clOoOeA== dependencies: - "@babel/helper-module-imports" "^7.16.0" - "@babel/helper-replace-supers" "^7.16.0" - "@babel/helper-simple-access" "^7.16.0" - "@babel/helper-split-export-declaration" "^7.16.0" - "@babel/helper-validator-identifier" "^7.15.7" - "@babel/template" "^7.16.0" - "@babel/traverse" "^7.16.0" - "@babel/types" "^7.16.0" + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-module-imports" "^7.18.6" + "@babel/helper-simple-access" "^7.20.2" + "@babel/helper-split-export-declaration" "^7.18.6" + "@babel/helper-validator-identifier" "^7.19.1" + "@babel/template" "^7.18.10" + "@babel/traverse" "^7.20.1" + "@babel/types" "^7.20.2" -"@babel/helper-optimise-call-expression@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.16.0.tgz#cecdb145d70c54096b1564f8e9f10cd7d193b338" - integrity sha512-SuI467Gi2V8fkofm2JPnZzB/SUuXoJA5zXe/xzyPP2M04686RzFKFHPK6HDVN6JvWBIEW8tt9hPR7fXdn2Lgpw== +"@babel/helper-optimise-call-expression@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.18.6.tgz#9369aa943ee7da47edab2cb4e838acf09d290ffe" + integrity sha512-HP59oD9/fEHQkdcbgFCnbmgH5vIQTJbxh2yf+CdM89/glUNnuzr87Q8GIjGEnOktTROemO0Pe0iPAYbqZuOUiA== dependencies: - "@babel/types" "^7.16.0" + "@babel/types" "^7.18.6" "@babel/helper-plugin-utils@7.10.4": version "7.10.4" resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz#2f75a831269d4f677de49986dff59927533cf375" integrity sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg== -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.13.0", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.14.5.tgz#5ac822ce97eec46741ab70a517971e443a70c5a9" - integrity sha512-/37qQCE3K0vvZKwoK4XU/irIJQdIfCJuhU5eKnNxpFDsOkgFaUAwbv+RYw6eYgsC0E4hS7r5KqGULUogqui0fQ== - -"@babel/helper-remap-async-to-generator@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.16.0.tgz#d5aa3b086e13a5fe05238ff40c3a5a0c2dab3ead" - integrity sha512-MLM1IOMe9aQBqMWxcRw8dcb9jlM86NIw7KA0Wri91Xkfied+dE0QuBFSBjMNvqzmS0OSIDsMNC24dBEkPUi7ew== - dependencies: - "@babel/helper-annotate-as-pure" "^7.16.0" - "@babel/helper-wrap-function" "^7.16.0" - "@babel/types" "^7.16.0" - -"@babel/helper-replace-supers@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.16.0.tgz#73055e8d3cf9bcba8ddb55cad93fedc860f68f17" - integrity sha512-TQxuQfSCdoha7cpRNJvfaYxxxzmbxXw/+6cS7V02eeDYyhxderSoMVALvwupA54/pZcOTtVeJ0xccp1nGWladA== - dependencies: - "@babel/helper-member-expression-to-functions" "^7.16.0" - "@babel/helper-optimise-call-expression" "^7.16.0" - "@babel/traverse" "^7.16.0" - "@babel/types" "^7.16.0" - -"@babel/helper-simple-access@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.16.0.tgz#21d6a27620e383e37534cf6c10bba019a6f90517" - integrity sha512-o1rjBT/gppAqKsYfUdfHq5Rk03lMQrkPHG1OWzHWpLgVXRH4HnMM9Et9CVdIqwkCQlobnGHEJMsgWP/jE1zUiw== - dependencies: - "@babel/types" "^7.16.0" - -"@babel/helper-skip-transparent-expression-wrappers@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.16.0.tgz#0ee3388070147c3ae051e487eca3ebb0e2e8bb09" - integrity sha512-+il1gTy0oHwUsBQZyJvukbB4vPMdcYBrFHa0Uc4AizLxbq6BOYC51Rv4tWocX9BLBDLZ4kc6qUFpQ6HRgL+3zw== - dependencies: - "@babel/types" "^7.16.0" - -"@babel/helper-split-export-declaration@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.16.0.tgz#29672f43663e936df370aaeb22beddb3baec7438" - integrity sha512-0YMMRpuDFNGTHNRiiqJX19GjNXA4H0E8jZ2ibccfSxaCogbm3am5WN/2nQNj0YnQwGWM1J06GOcQ2qnh3+0paw== - dependencies: - "@babel/types" "^7.16.0" - -"@babel/helper-validator-identifier@^7.15.7": - version "7.15.7" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.15.7.tgz#220df993bfe904a4a6b02ab4f3385a5ebf6e2389" - integrity sha512-K4JvCtQqad9OY2+yTU8w+E82ywk/fe+ELNlt1G8z3bVGlZfn/hOcQQsUhGhW/N+tb3fxK800wLtKOE/aM0m72w== - -"@babel/helper-validator-option@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.14.5.tgz#6e72a1fff18d5dfcb878e1e62f1a021c4b72d5a3" - integrity sha512-OX8D5eeX4XwcroVW45NMvoYaIuFI+GQpA2a8Gi+X/U/cDUIRsV37qQfF905F0htTRCREQIB4KqPeaveRJUl3Ow== - -"@babel/helper-wrap-function@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.16.0.tgz#b3cf318afce774dfe75b86767cd6d68f3482e57c" - integrity sha512-VVMGzYY3vkWgCJML+qVLvGIam902mJW0FvT7Avj1zEe0Gn7D93aWdLblYARTxEw+6DhZmtzhBM2zv0ekE5zg1g== - dependencies: - "@babel/helper-function-name" "^7.16.0" - "@babel/template" "^7.16.0" - "@babel/traverse" "^7.16.0" - "@babel/types" "^7.16.0" - -"@babel/helpers@^7.12.5", "@babel/helpers@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.16.0.tgz#875519c979c232f41adfbd43a3b0398c2e388183" - integrity sha512-dVRM0StFMdKlkt7cVcGgwD8UMaBfWJHl3A83Yfs8GQ3MO0LHIIIMvK7Fa0RGOGUQ10qikLaX6D7o5htcQWgTMQ== - dependencies: - "@babel/template" "^7.16.0" - "@babel/traverse" "^7.16.0" - "@babel/types" "^7.16.0" - -"@babel/highlight@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.16.0.tgz#6ceb32b2ca4b8f5f361fb7fd821e3fddf4a1725a" - integrity sha512-t8MH41kUQylBtu2+4IQA3atqevA2lRgqA2wyVB/YiWmsDSuylZZuXOUy9ric30hfzauEFfdsuk/eXTRrGrfd0g== - dependencies: - "@babel/helper-validator-identifier" "^7.15.7" +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.16.7", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.18.9", "@babel/helper-plugin-utils@^7.19.0", "@babel/helper-plugin-utils@^7.20.2", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": + version "7.20.2" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz#d1b9000752b18d0877cff85a5c376ce5c3121629" + integrity sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ== + +"@babel/helper-remap-async-to-generator@^7.18.6", "@babel/helper-remap-async-to-generator@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.18.9.tgz#997458a0e3357080e54e1d79ec347f8a8cd28519" + integrity sha512-dI7q50YKd8BAv3VEfgg7PS7yD3Rtbi2J1XMXaalXO0W0164hYLnh8zpjRS0mte9MfVp/tltvr/cfdXPvJr1opA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.18.6" + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-wrap-function" "^7.18.9" + "@babel/types" "^7.18.9" + +"@babel/helper-replace-supers@^7.18.6", "@babel/helper-replace-supers@^7.19.1": + version "7.19.1" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.19.1.tgz#e1592a9b4b368aa6bdb8784a711e0bcbf0612b78" + integrity sha512-T7ahH7wV0Hfs46SFh5Jz3s0B6+o8g3c+7TMxu7xKfmHikg7EAZ3I2Qk9LFhjxXq8sL7UkP5JflezNwoZa8WvWw== + dependencies: + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-member-expression-to-functions" "^7.18.9" + "@babel/helper-optimise-call-expression" "^7.18.6" + "@babel/traverse" "^7.19.1" + "@babel/types" "^7.19.0" + +"@babel/helper-simple-access@^7.19.4", "@babel/helper-simple-access@^7.20.2": + version "7.20.2" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz#0ab452687fe0c2cfb1e2b9e0015de07fc2d62dd9" + integrity sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA== + dependencies: + "@babel/types" "^7.20.2" + +"@babel/helper-skip-transparent-expression-wrappers@^7.18.9": + version "7.20.0" + resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.20.0.tgz#fbe4c52f60518cab8140d77101f0e63a8a230684" + integrity sha512-5y1JYeNKfvnT8sZcK9DVRtpTbGiomYIHviSP3OQWmDPU3DeH4a1ZlT/N2lyQ5P8egjcRaT/Y9aNqUxK0WsnIIg== + dependencies: + "@babel/types" "^7.20.0" + +"@babel/helper-split-export-declaration@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz#7367949bc75b20c6d5a5d4a97bba2824ae8ef075" + integrity sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA== + dependencies: + "@babel/types" "^7.18.6" + +"@babel/helper-string-parser@^7.19.4": + version "7.19.4" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz#38d3acb654b4701a9b77fb0615a96f775c3a9e63" + integrity sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw== + +"@babel/helper-validator-identifier@^7.18.6", "@babel/helper-validator-identifier@^7.19.1": + version "7.19.1" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz#7eea834cf32901ffdc1a7ee555e2f9c27e249ca2" + integrity sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w== + +"@babel/helper-validator-option@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz#bf0d2b5a509b1f336099e4ff36e1a63aa5db4db8" + integrity sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw== + +"@babel/helper-wrap-function@^7.18.9": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.19.0.tgz#89f18335cff1152373222f76a4b37799636ae8b1" + integrity sha512-txX8aN8CZyYGTwcLhlk87KRqncAzhh5TpQamZUa0/u3an36NtDpUP6bQgBCBcLeBs09R/OwQu3OjK0k/HwfNDg== + dependencies: + "@babel/helper-function-name" "^7.19.0" + "@babel/template" "^7.18.10" + "@babel/traverse" "^7.19.0" + "@babel/types" "^7.19.0" + +"@babel/helpers@^7.12.5", "@babel/helpers@^7.20.1": + version "7.20.1" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.20.1.tgz#2ab7a0fcb0a03b5bf76629196ed63c2d7311f4c9" + integrity sha512-J77mUVaDTUJFZ5BpP6mMn6OIl3rEWymk2ZxDBQJUG3P+PbmyMcF3bYWvz0ma69Af1oobDqT/iAsvzhB58xhQUg== + dependencies: + "@babel/template" "^7.18.10" + "@babel/traverse" "^7.20.1" + "@babel/types" "^7.20.0" + +"@babel/highlight@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.18.6.tgz#81158601e93e2563795adcbfbdf5d64be3f2ecdf" + integrity sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g== + dependencies: + "@babel/helper-validator-identifier" "^7.18.6" chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.12.16", "@babel/parser@^7.12.7", "@babel/parser@^7.16.0": - version "7.16.2" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.16.2.tgz#3723cd5c8d8773eef96ce57ea1d9b7faaccd12ac" - integrity sha512-RUVpT0G2h6rOZwqLDTrKk7ksNv7YpAilTnYe1/Q+eDjxEceRMKVWbCsX7t8h6C1qCFi/1Y8WZjcEPBAFG27GPw== +"@babel/parser@^7.12.7", "@babel/parser@^7.18.10", "@babel/parser@^7.18.8", "@babel/parser@^7.20.1", "@babel/parser@^7.20.2": + version "7.20.3" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.20.3.tgz#5358cf62e380cf69efcb87a7bb922ff88bfac6e2" + integrity sha512-OP/s5a94frIPXwjzEcv5S/tpQfc6XhxYUnmWpgdqMWGgYCuErA3SzozaRAMQgSZWKeTJxht9aWAkUY+0UzvOFg== -"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.16.0": - version "7.16.2" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.16.2.tgz#2977fca9b212db153c195674e57cfab807733183" - integrity sha512-h37CvpLSf8gb2lIJ2CgC3t+EjFbi0t8qS7LCS1xcJIlEXE4czlofwaW7W1HA8zpgOCzI9C1nmoqNR1zWkk0pQg== +"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.18.6.tgz#da5b8f9a580acdfbe53494dba45ea389fb09a4d2" + integrity sha512-Dgxsyg54Fx1d4Nge8UnvTrED63vrwOdPmyvPzlNN/boaliRP54pm3pGzZD1SJUwrBA+Cs/xdG8kXX6Mn/RfISQ== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.16.0.tgz#358972eaab006f5eb0826183b0c93cbcaf13e1e2" - integrity sha512-4tcFwwicpWTrpl9qjf7UsoosaArgImF85AxqCRZlgc3IQDvkUHjJpruXAL58Wmj+T6fypWTC/BakfEkwIL/pwA== +"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.18.9.tgz#a11af19aa373d68d561f08e0a57242350ed0ec50" + integrity sha512-AHrP9jadvH7qlOj6PINbgSuphjQUAK7AOT7DPjBo9EHoLhQTnnK5u45e1Hd4DbSQEO9nqPWtQ89r+XEOWFScKg== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0" - "@babel/plugin-proposal-optional-chaining" "^7.16.0" + "@babel/helper-plugin-utils" "^7.18.9" + "@babel/helper-skip-transparent-expression-wrappers" "^7.18.9" + "@babel/plugin-proposal-optional-chaining" "^7.18.9" -"@babel/plugin-proposal-async-generator-functions@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.16.0.tgz#11425d47a60364352f668ad5fbc1d6596b2c5caf" - integrity sha512-nyYmIo7ZqKsY6P4lnVmBlxp9B3a96CscbLotlsNuktMHahkDwoPYEjXrZHU0Tj844Z9f1IthVxQln57mhkcExw== +"@babel/plugin-proposal-async-generator-functions@^7.20.1": + version "7.20.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.20.1.tgz#352f02baa5d69f4e7529bdac39aaa02d41146af9" + integrity sha512-Gh5rchzSwE4kC+o/6T8waD0WHEQIsDmjltY8WnWRXHUdH8axZhuH86Ov9M72YhJfDrZseQwuuWaaIT/TmePp3g== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-remap-async-to-generator" "^7.16.0" + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-plugin-utils" "^7.19.0" + "@babel/helper-remap-async-to-generator" "^7.18.9" "@babel/plugin-syntax-async-generators" "^7.8.4" -"@babel/plugin-proposal-class-properties@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.16.0.tgz#c029618267ddebc7280fa286e0f8ca2a278a2d1a" - integrity sha512-mCF3HcuZSY9Fcx56Lbn+CGdT44ioBMMvjNVldpKtj8tpniETdLjnxdHI1+sDWXIM1nNt+EanJOZ3IG9lzVjs7A== +"@babel/plugin-proposal-class-properties@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz#b110f59741895f7ec21a6fff696ec46265c446a3" + integrity sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ== dependencies: - "@babel/helper-create-class-features-plugin" "^7.16.0" - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-create-class-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-proposal-class-static-block@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.16.0.tgz#5296942c564d8144c83eea347d0aa8a0b89170e7" - integrity sha512-mAy3sdcY9sKAkf3lQbDiv3olOfiLqI51c9DR9b19uMoR2Z6r5pmGl7dfNFqEvqOyqbf1ta4lknK4gc5PJn3mfA== +"@babel/plugin-proposal-class-static-block@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.18.6.tgz#8aa81d403ab72d3962fc06c26e222dacfc9b9020" + integrity sha512-+I3oIiNxrCpup3Gi8n5IGMwj0gOCAjcJUSQEcotNnCCPMEnixawOQ+KeJPlgfjzx+FKQ1QSyZOWe7wmoJp7vhw== dependencies: - "@babel/helper-create-class-features-plugin" "^7.16.0" - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-create-class-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-syntax-class-static-block" "^7.14.5" -"@babel/plugin-proposal-dynamic-import@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.16.0.tgz#783eca61d50526202f9b296095453977e88659f1" - integrity sha512-QGSA6ExWk95jFQgwz5GQ2Dr95cf7eI7TKutIXXTb7B1gCLTCz5hTjFTQGfLFBBiC5WSNi7udNwWsqbbMh1c4yQ== +"@babel/plugin-proposal-dynamic-import@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.18.6.tgz#72bcf8d408799f547d759298c3c27c7e7faa4d94" + integrity sha512-1auuwmK+Rz13SJj36R+jqFPMJWyKEDd7lLSdOj4oJK0UTgGueSAtkrCvz9ewmgyU/P941Rv2fQwZJN8s6QruXw== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-syntax-dynamic-import" "^7.8.3" -"@babel/plugin-proposal-export-namespace-from@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.16.0.tgz#9c01dee40b9d6b847b656aaf4a3976a71740f222" - integrity sha512-CjI4nxM/D+5wCnhD11MHB1AwRSAYeDT+h8gCdcVJZ/OK7+wRzFsf7PFPWVpVpNRkHMmMkQWAHpTq+15IXQ1diA== +"@babel/plugin-proposal-export-namespace-from@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.18.9.tgz#5f7313ab348cdb19d590145f9247540e94761203" + integrity sha512-k1NtHyOMvlDDFeb9G5PhUXuGj8m/wiwojgQVEhJ/fsVsMCpLyOP4h0uGEjYJKrRI+EVPlb5Jk+Gt9P97lOGwtA== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.18.9" "@babel/plugin-syntax-export-namespace-from" "^7.8.3" -"@babel/plugin-proposal-json-strings@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.16.0.tgz#cae35a95ed1d2a7fa29c4dc41540b84a72e9ab25" - integrity sha512-kouIPuiv8mSi5JkEhzApg5Gn6hFyKPnlkO0a9YSzqRurH8wYzSlf6RJdzluAsbqecdW5pBvDJDfyDIUR/vLxvg== +"@babel/plugin-proposal-json-strings@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.18.6.tgz#7e8788c1811c393aff762817e7dbf1ebd0c05f0b" + integrity sha512-lr1peyn9kOdbYc0xr0OdHTZ5FMqS6Di+H0Fz2I/JwMzGmzJETNeOFq2pBySw6X/KFL5EWDjlJuMsUGRFb8fQgQ== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-syntax-json-strings" "^7.8.3" -"@babel/plugin-proposal-logical-assignment-operators@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.16.0.tgz#a711b8ceb3ffddd3ef88d3a49e86dbd3cc7db3fd" - integrity sha512-pbW0fE30sVTYXXm9lpVQQ/Vc+iTeQKiXlaNRZPPN2A2VdlWyAtsUrsQ3xydSlDW00TFMK7a8m3cDTkBF5WnV3Q== +"@babel/plugin-proposal-logical-assignment-operators@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.18.9.tgz#8148cbb350483bf6220af06fa6db3690e14b2e23" + integrity sha512-128YbMpjCrP35IOExw2Fq+x55LMP42DzhOhX2aNNIdI9avSWl2PI0yuBWarr3RYpZBSPtabfadkH2yeRiMD61Q== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.18.9" "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" -"@babel/plugin-proposal-nullish-coalescing-operator@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.16.0.tgz#44e1cce08fe2427482cf446a91bb451528ed0596" - integrity sha512-3bnHA8CAFm7cG93v8loghDYyQ8r97Qydf63BeYiGgYbjKKB/XP53W15wfRC7dvKfoiJ34f6Rbyyx2btExc8XsQ== +"@babel/plugin-proposal-nullish-coalescing-operator@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz#fdd940a99a740e577d6c753ab6fbb43fdb9467e1" + integrity sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" -"@babel/plugin-proposal-numeric-separator@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.16.0.tgz#5d418e4fbbf8b9b7d03125d3a52730433a373734" - integrity sha512-FAhE2I6mjispy+vwwd6xWPyEx3NYFS13pikDBWUAFGZvq6POGs5eNchw8+1CYoEgBl9n11I3NkzD7ghn25PQ9Q== +"@babel/plugin-proposal-numeric-separator@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz#899b14fbafe87f053d2c5ff05b36029c62e13c75" + integrity sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-syntax-numeric-separator" "^7.10.4" "@babel/plugin-proposal-object-rest-spread@7.12.1": @@ -505,59 +522,59 @@ "@babel/plugin-syntax-object-rest-spread" "^7.8.0" "@babel/plugin-transform-parameters" "^7.12.1" -"@babel/plugin-proposal-object-rest-spread@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.16.0.tgz#5fb32f6d924d6e6712810362a60e12a2609872e6" - integrity sha512-LU/+jp89efe5HuWJLmMmFG0+xbz+I2rSI7iLc1AlaeSMDMOGzWlc5yJrMN1d04osXN4sSfpo4O+azkBNBes0jg== +"@babel/plugin-proposal-object-rest-spread@^7.20.2": + version "7.20.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.20.2.tgz#a556f59d555f06961df1e572bb5eca864c84022d" + integrity sha512-Ks6uej9WFK+fvIMesSqbAto5dD8Dz4VuuFvGJFKgIGSkJuRGcrwGECPA1fDgQK3/DbExBJpEkTeYeB8geIFCSQ== dependencies: - "@babel/compat-data" "^7.16.0" - "@babel/helper-compilation-targets" "^7.16.0" - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/compat-data" "^7.20.1" + "@babel/helper-compilation-targets" "^7.20.0" + "@babel/helper-plugin-utils" "^7.20.2" "@babel/plugin-syntax-object-rest-spread" "^7.8.3" - "@babel/plugin-transform-parameters" "^7.16.0" + "@babel/plugin-transform-parameters" "^7.20.1" -"@babel/plugin-proposal-optional-catch-binding@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.16.0.tgz#5910085811ab4c28b00d6ebffa4ab0274d1e5f16" - integrity sha512-kicDo0A/5J0nrsCPbn89mTG3Bm4XgYi0CZtvex9Oyw7gGZE3HXGD0zpQNH+mo+tEfbo8wbmMvJftOwpmPy7aVw== +"@babel/plugin-proposal-optional-catch-binding@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.18.6.tgz#f9400d0e6a3ea93ba9ef70b09e72dd6da638a2cb" + integrity sha512-Q40HEhs9DJQyaZfUjjn6vE8Cv4GmMHCYuMGIWUnlxH6400VGxOuwWsPt4FxXxJkC/5eOzgn0z21M9gMT4MOhbw== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" -"@babel/plugin-proposal-optional-chaining@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.16.0.tgz#56dbc3970825683608e9efb55ea82c2a2d6c8dc0" - integrity sha512-Y4rFpkZODfHrVo70Uaj6cC1JJOt3Pp0MdWSwIKtb8z1/lsjl9AmnB7ErRFV+QNGIfcY1Eruc2UMx5KaRnXjMyg== +"@babel/plugin-proposal-optional-chaining@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.18.9.tgz#e8e8fe0723f2563960e4bf5e9690933691915993" + integrity sha512-v5nwt4IqBXihxGsW2QmCWMDS3B3bzGIk/EQVZz2ei7f3NJl8NzAJVvUmpDW5q1CRNY+Beb/k58UAH1Km1N411w== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0" + "@babel/helper-plugin-utils" "^7.18.9" + "@babel/helper-skip-transparent-expression-wrappers" "^7.18.9" "@babel/plugin-syntax-optional-chaining" "^7.8.3" -"@babel/plugin-proposal-private-methods@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.16.0.tgz#b4dafb9c717e4301c5776b30d080d6383c89aff6" - integrity sha512-IvHmcTHDFztQGnn6aWq4t12QaBXTKr1whF/dgp9kz84X6GUcwq9utj7z2wFCUfeOup/QKnOlt2k0zxkGFx9ubg== +"@babel/plugin-proposal-private-methods@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.18.6.tgz#5209de7d213457548a98436fa2882f52f4be6bea" + integrity sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA== dependencies: - "@babel/helper-create-class-features-plugin" "^7.16.0" - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-create-class-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-proposal-private-property-in-object@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.16.0.tgz#69e935b2c5c79d2488112d886f0c4e2790fee76f" - integrity sha512-3jQUr/HBbMVZmi72LpjQwlZ55i1queL8KcDTQEkAHihttJnAPrcvG9ZNXIfsd2ugpizZo595egYV6xy+pv4Ofw== +"@babel/plugin-proposal-private-property-in-object@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.18.6.tgz#a64137b232f0aca3733a67eb1a144c192389c503" + integrity sha512-9Rysx7FOctvT5ouj5JODjAFAkgGoudQuLPamZb0v1TGLpapdNaftzifU8NTWQm0IRjqoYypdrSmyWgkocDQ8Dw== dependencies: - "@babel/helper-annotate-as-pure" "^7.16.0" - "@babel/helper-create-class-features-plugin" "^7.16.0" - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-annotate-as-pure" "^7.18.6" + "@babel/helper-create-class-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-syntax-private-property-in-object" "^7.14.5" -"@babel/plugin-proposal-unicode-property-regex@^7.16.0", "@babel/plugin-proposal-unicode-property-regex@^7.4.4": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.16.0.tgz#890482dfc5ea378e42e19a71e709728cabf18612" - integrity sha512-ti7IdM54NXv29cA4+bNNKEMS4jLMCbJgl+Drv+FgYy0erJLAxNAIXcNjNjrRZEcWq0xJHsNVwQezskMFpF8N9g== +"@babel/plugin-proposal-unicode-property-regex@^7.18.6", "@babel/plugin-proposal-unicode-property-regex@^7.4.4": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz#af613d2cd5e643643b65cded64207b15c85cb78e" + integrity sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.16.0" - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-create-regexp-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-syntax-async-generators@^7.8.4": version "7.8.4" @@ -594,6 +611,13 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.3" +"@babel/plugin-syntax-import-assertions@^7.20.0": + version "7.20.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.20.0.tgz#bb50e0d4bea0957235390641209394e87bdb9cc4" + integrity sha512-IUh1vakzNoWalR8ch/areW7qFopR2AEw03JlG7BbrDqmQ4X3q9uuipQwSGrUn7oGiemKjtSLDhNtQHzMHr1JdQ== + dependencies: + "@babel/helper-plugin-utils" "^7.19.0" + "@babel/plugin-syntax-json-strings@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" @@ -608,12 +632,12 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-syntax-jsx@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.16.0.tgz#f9624394317365a9a88c82358d3f8471154698f1" - integrity sha512-8zv2+xiPHwly31RK4RmnEYY5zziuF3O7W2kIDW+07ewWDh6Oi0dRq8kwvulRkFgt6DB97RlKs5c1y068iPlCUg== +"@babel/plugin-syntax-jsx@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz#a8feef63b010150abd97f1649ec296e849943ca0" + integrity sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-syntax-logical-assignment-operators@^7.10.4": version "7.10.4" @@ -671,353 +695,356 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-syntax-typescript@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.16.0.tgz#2feeb13d9334cc582ea9111d3506f773174179bb" - integrity sha512-Xv6mEXqVdaqCBfJFyeab0fH2DnUoMsDmhamxsSi4j8nLd4Vtw213WMJr55xxqipC/YVWyPY3K0blJncPYji+dQ== +"@babel/plugin-syntax-typescript@^7.20.0": + version "7.20.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.20.0.tgz#4e9a0cfc769c85689b77a2e642d24e9f697fc8c7" + integrity sha512-rd9TkG+u1CExzS4SM1BlMEhMXwFLKVjOAFFCDx9PbX5ycJWDoWMcwdJH9RhkPu1dOgn5TrxLot/Gx6lWFuAUNQ== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.19.0" -"@babel/plugin-transform-arrow-functions@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.16.0.tgz#951706f8b449c834ed07bd474c0924c944b95a8e" - integrity sha512-vIFb5250Rbh7roWARvCLvIJ/PtAU5Lhv7BtZ1u24COwpI9Ypjsh+bZcKk6rlIyalK+r0jOc1XQ8I4ovNxNrWrA== +"@babel/plugin-transform-arrow-functions@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.18.6.tgz#19063fcf8771ec7b31d742339dac62433d0611fe" + integrity sha512-9S9X9RUefzrsHZmKMbDXxweEH+YlE8JJEuat9FdvW9Qh1cw7W64jELCtWNkPBPX5En45uy28KGvA/AySqUh8CQ== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-transform-async-to-generator@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.16.0.tgz#df12637f9630ddfa0ef9d7a11bc414d629d38604" - integrity sha512-PbIr7G9kR8tdH6g8Wouir5uVjklETk91GMVSUq+VaOgiinbCkBP6Q7NN/suM/QutZkMJMvcyAriogcYAdhg8Gw== +"@babel/plugin-transform-async-to-generator@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.18.6.tgz#ccda3d1ab9d5ced5265fdb13f1882d5476c71615" + integrity sha512-ARE5wZLKnTgPW7/1ftQmSi1CmkqqHo2DNmtztFhvgtOWSDfq0Cq9/9L+KnZNYSNrydBekhW3rwShduf59RoXag== dependencies: - "@babel/helper-module-imports" "^7.16.0" - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-remap-async-to-generator" "^7.16.0" + "@babel/helper-module-imports" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-remap-async-to-generator" "^7.18.6" -"@babel/plugin-transform-block-scoped-functions@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.16.0.tgz#c618763233ad02847805abcac4c345ce9de7145d" - integrity sha512-V14As3haUOP4ZWrLJ3VVx5rCnrYhMSHN/jX7z6FAt5hjRkLsb0snPCmJwSOML5oxkKO4FNoNv7V5hw/y2bjuvg== +"@babel/plugin-transform-block-scoped-functions@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.18.6.tgz#9187bf4ba302635b9d70d986ad70f038726216a8" + integrity sha512-ExUcOqpPWnliRcPqves5HJcJOvHvIIWfuS4sroBUenPuMdmW+SMHDakmtS7qOo13sVppmUijqeTv7qqGsvURpQ== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-transform-block-scoping@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.16.0.tgz#bcf433fb482fe8c3d3b4e8a66b1c4a8e77d37c16" - integrity sha512-27n3l67/R3UrXfizlvHGuTwsRIFyce3D/6a37GRxn28iyTPvNXaW4XvznexRh1zUNLPjbLL22Id0XQElV94ruw== +"@babel/plugin-transform-block-scoping@^7.20.2": + version "7.20.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.20.2.tgz#f59b1767e6385c663fd0bce655db6ca9c8b236ed" + integrity sha512-y5V15+04ry69OV2wULmwhEA6jwSWXO1TwAtIwiPXcvHcoOQUqpyMVd2bDsQJMW8AurjulIyUV8kDqtjSwHy1uQ== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.20.2" -"@babel/plugin-transform-classes@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.16.0.tgz#54cf5ff0b2242c6573d753cd4bfc7077a8b282f5" - integrity sha512-HUxMvy6GtAdd+GKBNYDWCIA776byUQH8zjnfjxwT1P1ARv/wFu8eBDpmXQcLS/IwRtrxIReGiplOwMeyO7nsDQ== +"@babel/plugin-transform-classes@^7.20.2": + version "7.20.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.20.2.tgz#c0033cf1916ccf78202d04be4281d161f6709bb2" + integrity sha512-9rbPp0lCVVoagvtEyQKSo5L8oo0nQS/iif+lwlAz29MccX2642vWDlSZK+2T2buxbopotId2ld7zZAzRfz9j1g== dependencies: - "@babel/helper-annotate-as-pure" "^7.16.0" - "@babel/helper-function-name" "^7.16.0" - "@babel/helper-optimise-call-expression" "^7.16.0" - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-replace-supers" "^7.16.0" - "@babel/helper-split-export-declaration" "^7.16.0" + "@babel/helper-annotate-as-pure" "^7.18.6" + "@babel/helper-compilation-targets" "^7.20.0" + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-function-name" "^7.19.0" + "@babel/helper-optimise-call-expression" "^7.18.6" + "@babel/helper-plugin-utils" "^7.20.2" + "@babel/helper-replace-supers" "^7.19.1" + "@babel/helper-split-export-declaration" "^7.18.6" globals "^11.1.0" -"@babel/plugin-transform-computed-properties@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.16.0.tgz#e0c385507d21e1b0b076d66bed6d5231b85110b7" - integrity sha512-63l1dRXday6S8V3WFY5mXJwcRAnPYxvFfTlt67bwV1rTyVTM5zrp0DBBb13Kl7+ehkCVwIZPumPpFP/4u70+Tw== +"@babel/plugin-transform-computed-properties@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.18.9.tgz#2357a8224d402dad623caf6259b611e56aec746e" + integrity sha512-+i0ZU1bCDymKakLxn5srGHrsAPRELC2WIbzwjLhHW9SIE1cPYkLCL0NlnXMZaM1vhfgA2+M7hySk42VBvrkBRw== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.18.9" -"@babel/plugin-transform-destructuring@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.16.0.tgz#ad3d7e74584ad5ea4eadb1e6642146c590dee33c" - integrity sha512-Q7tBUwjxLTsHEoqktemHBMtb3NYwyJPTJdM+wDwb0g8PZ3kQUIzNvwD5lPaqW/p54TXBc/MXZu9Jr7tbUEUM8Q== +"@babel/plugin-transform-destructuring@^7.20.2": + version "7.20.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.20.2.tgz#c23741cfa44ddd35f5e53896e88c75331b8b2792" + integrity sha512-mENM+ZHrvEgxLTBXUiQ621rRXZes3KWUv6NdQlrnr1TkWVw+hUjQBZuP2X32qKlrlG2BzgR95gkuCRSkJl8vIw== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.20.2" -"@babel/plugin-transform-dotall-regex@^7.16.0", "@babel/plugin-transform-dotall-regex@^7.4.4": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.16.0.tgz#50bab00c1084b6162d0a58a818031cf57798e06f" - integrity sha512-FXlDZfQeLILfJlC6I1qyEwcHK5UpRCFkaoVyA1nk9A1L1Yu583YO4un2KsLBsu3IJb4CUbctZks8tD9xPQubLw== +"@babel/plugin-transform-dotall-regex@^7.18.6", "@babel/plugin-transform-dotall-regex@^7.4.4": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.18.6.tgz#b286b3e7aae6c7b861e45bed0a2fafd6b1a4fef8" + integrity sha512-6S3jpun1eEbAxq7TdjLotAsl4WpQI9DxfkycRcKrjhQYzU87qpXdknpBg/e+TdcMehqGnLFi7tnFUBR02Vq6wg== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.16.0" - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-create-regexp-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-transform-duplicate-keys@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.16.0.tgz#8bc2e21813e3e89e5e5bf3b60aa5fc458575a176" - integrity sha512-LIe2kcHKAZOJDNxujvmp6z3mfN6V9lJxubU4fJIGoQCkKe3Ec2OcbdlYP+vW++4MpxwG0d1wSDOJtQW5kLnkZQ== +"@babel/plugin-transform-duplicate-keys@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.18.9.tgz#687f15ee3cdad6d85191eb2a372c4528eaa0ae0e" + integrity sha512-d2bmXCtZXYc59/0SanQKbiWINadaJXqtvIQIzd4+hNwkWBgyCd5F/2t1kXoUdvPMrxzPvhK6EMQRROxsue+mfw== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.18.9" -"@babel/plugin-transform-exponentiation-operator@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.16.0.tgz#a180cd2881e3533cef9d3901e48dad0fbeff4be4" - integrity sha512-OwYEvzFI38hXklsrbNivzpO3fh87skzx8Pnqi4LoSYeav0xHlueSoCJrSgTPfnbyzopo5b3YVAJkFIcUpK2wsw== +"@babel/plugin-transform-exponentiation-operator@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.18.6.tgz#421c705f4521888c65e91fdd1af951bfefd4dacd" + integrity sha512-wzEtc0+2c88FVR34aQmiz56dxEkxr2g8DQb/KfaFa1JYXOFVsbhvAonFN6PwVWj++fKmku8NP80plJ5Et4wqHw== dependencies: - "@babel/helper-builder-binary-assignment-operator-visitor" "^7.16.0" - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-builder-binary-assignment-operator-visitor" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-transform-for-of@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.16.0.tgz#f7abaced155260e2461359bbc7c7248aca5e6bd2" - integrity sha512-5QKUw2kO+GVmKr2wMYSATCTTnHyscl6sxFRAY+rvN7h7WB0lcG0o4NoV6ZQU32OZGVsYUsfLGgPQpDFdkfjlJQ== +"@babel/plugin-transform-for-of@^7.18.8": + version "7.18.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.18.8.tgz#6ef8a50b244eb6a0bdbad0c7c61877e4e30097c1" + integrity sha512-yEfTRnjuskWYo0k1mHUqrVWaZwrdq8AYbfrpqULOJOaucGSp4mNMVps+YtA8byoevxS/urwU75vyhQIxcCgiBQ== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-transform-function-name@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.16.0.tgz#02e3699c284c6262236599f751065c5d5f1f400e" - integrity sha512-lBzMle9jcOXtSOXUpc7tvvTpENu/NuekNJVova5lCCWCV9/U1ho2HH2y0p6mBg8fPm/syEAbfaaemYGOHCY3mg== +"@babel/plugin-transform-function-name@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.18.9.tgz#cc354f8234e62968946c61a46d6365440fc764e0" + integrity sha512-WvIBoRPaJQ5yVHzcnJFor7oS5Ls0PYixlTYE63lCj2RtdQEl15M68FXQlxnG6wdraJIXRdR7KI+hQ7q/9QjrCQ== dependencies: - "@babel/helper-function-name" "^7.16.0" - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-compilation-targets" "^7.18.9" + "@babel/helper-function-name" "^7.18.9" + "@babel/helper-plugin-utils" "^7.18.9" -"@babel/plugin-transform-literals@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.16.0.tgz#79711e670ffceb31bd298229d50f3621f7980cac" - integrity sha512-gQDlsSF1iv9RU04clgXqRjrPyyoJMTclFt3K1cjLmTKikc0s/6vE3hlDeEVC71wLTRu72Fq7650kABrdTc2wMQ== +"@babel/plugin-transform-literals@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.18.9.tgz#72796fdbef80e56fba3c6a699d54f0de557444bc" + integrity sha512-IFQDSRoTPnrAIrI5zoZv73IFeZu2dhu6irxQjY9rNjTT53VmKg9fenjvoiOWOkJ6mm4jKVPtdMzBY98Fp4Z4cg== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.18.9" -"@babel/plugin-transform-member-expression-literals@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.16.0.tgz#5251b4cce01eaf8314403d21aedb269d79f5e64b" - integrity sha512-WRpw5HL4Jhnxw8QARzRvwojp9MIE7Tdk3ez6vRyUk1MwgjJN0aNpRoXainLR5SgxmoXx/vsXGZ6OthP6t/RbUg== +"@babel/plugin-transform-member-expression-literals@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.18.6.tgz#ac9fdc1a118620ac49b7e7a5d2dc177a1bfee88e" + integrity sha512-qSF1ihLGO3q+/g48k85tUjD033C29TNTVB2paCwZPVmOsjn9pClvYYrM2VeJpBY2bcNkuny0YUyTNRyRxJ54KA== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-transform-modules-amd@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.16.0.tgz#09abd41e18dcf4fd479c598c1cef7bd39eb1337e" - integrity sha512-rWFhWbCJ9Wdmzln1NmSCqn7P0RAD+ogXG/bd9Kg5c7PKWkJtkiXmYsMBeXjDlzHpVTJ4I/hnjs45zX4dEv81xw== +"@babel/plugin-transform-modules-amd@^7.19.6": + version "7.19.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.19.6.tgz#aca391801ae55d19c4d8d2ebfeaa33df5f2a2cbd" + integrity sha512-uG3od2mXvAtIFQIh0xrpLH6r5fpSQN04gIVovl+ODLdUMANokxQLZnPBHcjmv3GxRjnqwLuHvppjjcelqUFZvg== dependencies: - "@babel/helper-module-transforms" "^7.16.0" - "@babel/helper-plugin-utils" "^7.14.5" - babel-plugin-dynamic-import-node "^2.3.3" + "@babel/helper-module-transforms" "^7.19.6" + "@babel/helper-plugin-utils" "^7.19.0" -"@babel/plugin-transform-modules-commonjs@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.16.0.tgz#add58e638c8ddc4875bd9a9ecb5c594613f6c922" - integrity sha512-Dzi+NWqyEotgzk/sb7kgQPJQf7AJkQBWsVp1N6JWc1lBVo0vkElUnGdr1PzUBmfsCCN5OOFya3RtpeHk15oLKQ== +"@babel/plugin-transform-modules-commonjs@^7.19.6": + version "7.19.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.19.6.tgz#25b32feef24df8038fc1ec56038917eacb0b730c" + integrity sha512-8PIa1ym4XRTKuSsOUXqDG0YaOlEuTVvHMe5JCfgBMOtHvJKw/4NGovEGN33viISshG/rZNVrACiBmPQLvWN8xQ== dependencies: - "@babel/helper-module-transforms" "^7.16.0" - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-simple-access" "^7.16.0" - babel-plugin-dynamic-import-node "^2.3.3" + "@babel/helper-module-transforms" "^7.19.6" + "@babel/helper-plugin-utils" "^7.19.0" + "@babel/helper-simple-access" "^7.19.4" -"@babel/plugin-transform-modules-systemjs@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.16.0.tgz#a92cf240afeb605f4ca16670453024425e421ea4" - integrity sha512-yuGBaHS3lF1m/5R+6fjIke64ii5luRUg97N2wr+z1sF0V+sNSXPxXDdEEL/iYLszsN5VKxVB1IPfEqhzVpiqvg== +"@babel/plugin-transform-modules-systemjs@^7.19.6": + version "7.19.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.19.6.tgz#59e2a84064b5736a4471b1aa7b13d4431d327e0d" + integrity sha512-fqGLBepcc3kErfR9R3DnVpURmckXP7gj7bAlrTQyBxrigFqszZCkFkcoxzCp2v32XmwXLvbw+8Yq9/b+QqksjQ== dependencies: - "@babel/helper-hoist-variables" "^7.16.0" - "@babel/helper-module-transforms" "^7.16.0" - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-validator-identifier" "^7.15.7" - babel-plugin-dynamic-import-node "^2.3.3" + "@babel/helper-hoist-variables" "^7.18.6" + "@babel/helper-module-transforms" "^7.19.6" + "@babel/helper-plugin-utils" "^7.19.0" + "@babel/helper-validator-identifier" "^7.19.1" -"@babel/plugin-transform-modules-umd@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.16.0.tgz#195f26c2ad6d6a391b70880effce18ce625e06a7" - integrity sha512-nx4f6no57himWiHhxDM5pjwhae5vLpTK2zCnDH8+wNLJy0TVER/LJRHl2bkt6w9Aad2sPD5iNNoUpY3X9sTGDg== +"@babel/plugin-transform-modules-umd@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.18.6.tgz#81d3832d6034b75b54e62821ba58f28ed0aab4b9" + integrity sha512-dcegErExVeXcRqNtkRU/z8WlBLnvD4MRnHgNs3MytRO1Mn1sHRyhbcpYbVMGclAqOjdW+9cfkdZno9dFdfKLfQ== dependencies: - "@babel/helper-module-transforms" "^7.16.0" - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-module-transforms" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-transform-named-capturing-groups-regex@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.16.0.tgz#d3db61cc5d5b97986559967cd5ea83e5c32096ca" - integrity sha512-LogN88uO+7EhxWc8WZuQ8vxdSyVGxhkh8WTC3tzlT8LccMuQdA81e9SGV6zY7kY2LjDhhDOFdQVxdGwPyBCnvg== +"@babel/plugin-transform-named-capturing-groups-regex@^7.19.1": + version "7.19.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.19.1.tgz#ec7455bab6cd8fb05c525a94876f435a48128888" + integrity sha512-oWk9l9WItWBQYS4FgXD4Uyy5kq898lvkXpXQxoJEY1RnvPk4R/Dvu2ebXU9q8lP+rlMwUQTFf2Ok6d78ODa0kw== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.16.0" + "@babel/helper-create-regexp-features-plugin" "^7.19.0" + "@babel/helper-plugin-utils" "^7.19.0" -"@babel/plugin-transform-new-target@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.16.0.tgz#af823ab576f752215a49937779a41ca65825ab35" - integrity sha512-fhjrDEYv2DBsGN/P6rlqakwRwIp7rBGLPbrKxwh7oVt5NNkIhZVOY2GRV+ULLsQri1bDqwDWnU3vhlmx5B2aCw== +"@babel/plugin-transform-new-target@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.18.6.tgz#d128f376ae200477f37c4ddfcc722a8a1b3246a8" + integrity sha512-DjwFA/9Iu3Z+vrAn+8pBUGcjhxKguSMlsFqeCKbhb9BAV756v0krzVK04CRDi/4aqmk8BsHb4a/gFcaA5joXRw== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-transform-object-super@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.16.0.tgz#fb20d5806dc6491a06296ac14ea8e8d6fedda72b" - integrity sha512-fds+puedQHn4cPLshoHcR1DTMN0q1V9ou0mUjm8whx9pGcNvDrVVrgw+KJzzCaiTdaYhldtrUps8DWVMgrSEyg== +"@babel/plugin-transform-object-super@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.18.6.tgz#fb3c6ccdd15939b6ff7939944b51971ddc35912c" + integrity sha512-uvGz6zk+pZoS1aTZrOvrbj6Pp/kK2mp45t2B+bTDre2UgsZZ8EZLSJtUg7m/no0zOJUWgFONpB7Zv9W2tSaFlA== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-replace-supers" "^7.16.0" + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-replace-supers" "^7.18.6" -"@babel/plugin-transform-parameters@^7.12.1", "@babel/plugin-transform-parameters@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.16.0.tgz#1b50765fc421c229819dc4c7cdb8911660b3c2d7" - integrity sha512-XgnQEm1CevKROPx+udOi/8f8TiGhrUWiHiaUCIp47tE0tpFDjzXNTZc9E5CmCwxNjXTWEVqvRfWZYOTFvMa/ZQ== +"@babel/plugin-transform-parameters@^7.12.1", "@babel/plugin-transform-parameters@^7.20.1": + version "7.20.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.20.3.tgz#7b3468d70c3c5b62e46be0a47b6045d8590fb748" + integrity sha512-oZg/Fpx0YDrj13KsLyO8I/CX3Zdw7z0O9qOd95SqcoIzuqy/WTGWvePeHAnZCN54SfdyjHcb1S30gc8zlzlHcA== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.20.2" -"@babel/plugin-transform-property-literals@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.16.0.tgz#a95c552189a96a00059f6776dc4e00e3690c78d1" - integrity sha512-XLldD4V8+pOqX2hwfWhgwXzGdnDOThxaNTgqagOcpBgIxbUvpgU2FMvo5E1RyHbk756WYgdbS0T8y0Cj9FKkWQ== +"@babel/plugin-transform-property-literals@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.18.6.tgz#e22498903a483448e94e032e9bbb9c5ccbfc93a3" + integrity sha512-cYcs6qlgafTud3PAzrrRNbQtfpQ8+y/+M5tKmksS9+M1ckbH6kzY8MrexEM9mcA6JDsukE19iIRvAyYl463sMg== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-transform-react-constant-elements@^7.12.1": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.16.0.tgz#1483b894b8e6ef0709d260532fbd4db9fc27a0e6" - integrity sha512-OgtklS+p9t1X37eWA4XdvvbZG/3gqzX569gqmo3q4/Ui6qjfTQmOs5UTSrfdD9nVByHhX6Gbm/Pyc4KbwUXGWA== +"@babel/plugin-transform-react-constant-elements@^7.18.12": + version "7.20.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.20.2.tgz#3f02c784e0b711970d7d8ccc96c4359d64e27ac7" + integrity sha512-KS/G8YI8uwMGKErLFOHS/ekhqdHhpEloxs43NecQHVgo2QuQSyJhGIY1fL8UGl9wy5ItVwwoUL4YxVqsplGq2g== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.20.2" -"@babel/plugin-transform-react-display-name@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.16.0.tgz#9a0ad8aa8e8790883a7bd2736f66229a58125676" - integrity sha512-FJFdJAqaCpndL+pIf0aeD/qlQwT7QXOvR6Cc8JPvNhKJBi2zc/DPc4g05Y3fbD/0iWAMQFGij4+Xw+4L/BMpTg== +"@babel/plugin-transform-react-display-name@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.18.6.tgz#8b1125f919ef36ebdfff061d664e266c666b9415" + integrity sha512-TV4sQ+T013n61uMoygyMRm+xf04Bd5oqFpv2jAEQwSZ8NwQA7zeRPg1LMVg2PWi3zWBz+CLKD+v5bcpZ/BS0aA== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-transform-react-jsx-development@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.16.0.tgz#1cb52874678d23ab11d0d16488d54730807303ef" - integrity sha512-qq65iSqBRq0Hr3wq57YG2AmW0H6wgTnIzpffTphrUWUgLCOK+zf1f7G0vuOiXrp7dU1qq+fQBoqZ3wCDAkhFzw== +"@babel/plugin-transform-react-jsx-development@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.18.6.tgz#dbe5c972811e49c7405b630e4d0d2e1380c0ddc5" + integrity sha512-SA6HEjwYFKF7WDjWcMcMGUimmw/nhNRDWxr+KaLSCrkD/LMDBvWRmHAYgE1HDeF8KUuI8OAu+RT6EOtKxSW2qA== dependencies: - "@babel/plugin-transform-react-jsx" "^7.16.0" + "@babel/plugin-transform-react-jsx" "^7.18.6" -"@babel/plugin-transform-react-jsx@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.16.0.tgz#55b797d4960c3de04e07ad1c0476e2bc6a4889f1" - integrity sha512-rqDgIbukZ44pqq7NIRPGPGNklshPkvlmvqjdx3OZcGPk4zGIenYkxDTvl3LsSL8gqcc3ZzGmXPE6hR/u/voNOw== +"@babel/plugin-transform-react-jsx@^7.18.6": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.19.0.tgz#b3cbb7c3a00b92ec8ae1027910e331ba5c500eb9" + integrity sha512-UVEvX3tXie3Szm3emi1+G63jyw1w5IcMY0FSKM+CRnKRI5Mr1YbCNgsSTwoTwKphQEG9P+QqmuRFneJPZuHNhg== dependencies: - "@babel/helper-annotate-as-pure" "^7.16.0" - "@babel/helper-module-imports" "^7.16.0" - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/plugin-syntax-jsx" "^7.16.0" - "@babel/types" "^7.16.0" + "@babel/helper-annotate-as-pure" "^7.18.6" + "@babel/helper-module-imports" "^7.18.6" + "@babel/helper-plugin-utils" "^7.19.0" + "@babel/plugin-syntax-jsx" "^7.18.6" + "@babel/types" "^7.19.0" -"@babel/plugin-transform-react-pure-annotations@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.16.0.tgz#23db6ddf558d8abde41b8ad9d59f48ad5532ccab" - integrity sha512-NC/Bj2MG+t8Ef5Pdpo34Ay74X4Rt804h5y81PwOpfPtmAK3i6CizmQqwyBQzIepz1Yt8wNr2Z2L7Lu3qBMfZMA== - dependencies: - "@babel/helper-annotate-as-pure" "^7.16.0" - "@babel/helper-plugin-utils" "^7.14.5" +"@babel/plugin-transform-react-pure-annotations@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.18.6.tgz#561af267f19f3e5d59291f9950fd7b9663d0d844" + integrity sha512-I8VfEPg9r2TRDdvnHgPepTKvuRomzA8+u+nhY7qSI1fR2hRNebasZEETLyM5mAUr0Ku56OkXJ0I7NHJnO6cJiQ== + dependencies: + "@babel/helper-annotate-as-pure" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-transform-regenerator@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.16.0.tgz#eaee422c84b0232d03aea7db99c97deeaf6125a4" - integrity sha512-JAvGxgKuwS2PihiSFaDrp94XOzzTUeDeOQlcKzVAyaPap7BnZXK/lvMDiubkPTdotPKOIZq9xWXWnggUMYiExg== +"@babel/plugin-transform-regenerator@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.18.6.tgz#585c66cb84d4b4bf72519a34cfce761b8676ca73" + integrity sha512-poqRI2+qiSdeldcz4wTSTXBRryoq3Gc70ye7m7UD5Ww0nE29IXqMl6r7Nd15WBgRd74vloEMlShtH6CKxVzfmQ== dependencies: - regenerator-transform "^0.14.2" + "@babel/helper-plugin-utils" "^7.18.6" + regenerator-transform "^0.15.0" -"@babel/plugin-transform-reserved-words@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.16.0.tgz#fff4b9dcb19e12619394bda172d14f2d04c0379c" - integrity sha512-Dgs8NNCehHSvXdhEhln8u/TtJxfVwGYCgP2OOr5Z3Ar+B+zXicEOKNTyc+eca2cuEOMtjW6m9P9ijOt8QdqWkg== +"@babel/plugin-transform-reserved-words@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.18.6.tgz#b1abd8ebf8edaa5f7fe6bbb8d2133d23b6a6f76a" + integrity sha512-oX/4MyMoypzHjFrT1CdivfKZ+XvIPMFXwwxHp/r0Ddy2Vuomt4HDFGmft1TAY2yiTKiNSsh3kjBAzcM8kSdsjA== dependencies: - "@babel/helper-plugin-utils" "^7.14.5" + "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-transform-runtime@^7.15.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.16.0.tgz#3fe0da36c2f0834bef7c4d3e7f2b2db0ee0c8909" - integrity sha512-zlPf1/XFn5+vWdve3AAhf+Sxl+MVa5VlwTwWgnLx23u4GlatSRQJ3Eoo9vllf0a9il3woQsT4SK+5Z7c06h8ag== +"@babel/plugin-transform-runtime@^7.18.6": + version "7.19.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.19.6.tgz#9d2a9dbf4e12644d6f46e5e75bfbf02b5d6e9194" + integrity sha512-PRH37lz4JU156lYFW1p8OxE5i7d6Sl/zV58ooyr+q1J1lnQPyg5tIiXlIwNVhJaY4W3TmOtdc8jqdXQcB1v5Yw== dependencies: - "@babel/helper-module-imports" "^7.16.0" - "@babel/helper-plugin-utils" "^7.14.5" - babel-plugin-polyfill-corejs2 "^0.2.3" - babel-plugin-polyfill-corejs3 "^0.3.0" - babel-plugin-polyfill-regenerator "^0.2.3" + "@babel/helper-module-imports" "^7.18.6" + "@babel/helper-plugin-utils" "^7.19.0" + babel-plugin-polyfill-corejs2 "^0.3.3" + babel-plugin-polyfill-corejs3 "^0.6.0" + babel-plugin-polyfill-regenerator "^0.4.1" semver "^6.3.0" -"@babel/plugin-transform-shorthand-properties@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.16.0.tgz#090372e3141f7cc324ed70b3daf5379df2fa384d" - integrity sha512-iVb1mTcD8fuhSv3k99+5tlXu5N0v8/DPm2mO3WACLG6al1CGZH7v09HJyUb1TtYl/Z+KrM6pHSIJdZxP5A+xow== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/plugin-transform-spread@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.16.0.tgz#d21ca099bbd53ab307a8621e019a7bd0f40cdcfb" - integrity sha512-Ao4MSYRaLAQczZVp9/7E7QHsCuK92yHRrmVNRe/SlEJjhzivq0BSn8mEraimL8wizHZ3fuaHxKH0iwzI13GyGg== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-skip-transparent-expression-wrappers" "^7.16.0" - -"@babel/plugin-transform-sticky-regex@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.16.0.tgz#c35ea31a02d86be485f6aa510184b677a91738fd" - integrity sha512-/ntT2NljR9foobKk4E/YyOSwcGUXtYWv5tinMK/3RkypyNBNdhHUaq6Orw5DWq9ZcNlS03BIlEALFeQgeVAo4Q== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/plugin-transform-template-literals@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.16.0.tgz#a8eced3a8e7b8e2d40ec4ec4548a45912630d302" - integrity sha512-Rd4Ic89hA/f7xUSJQk5PnC+4so50vBoBfxjdQAdvngwidM8jYIBVxBZ/sARxD4e0yMXRbJVDrYf7dyRtIIKT6Q== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/plugin-transform-typeof-symbol@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.16.0.tgz#8b19a244c6f8c9d668dca6a6f754ad6ead1128f2" - integrity sha512-++V2L8Bdf4vcaHi2raILnptTBjGEFxn5315YU+e8+EqXIucA+q349qWngCLpUYqqv233suJ6NOienIVUpS9cqg== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/plugin-transform-typescript@^7.16.0": - version "7.16.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.16.1.tgz#cc0670b2822b0338355bc1b3d2246a42b8166409" - integrity sha512-NO4XoryBng06jjw/qWEU2LhcLJr1tWkhpMam/H4eas/CDKMX/b2/Ylb6EI256Y7+FVPCawwSM1rrJNOpDiz+Lg== - dependencies: - "@babel/helper-create-class-features-plugin" "^7.16.0" - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/plugin-syntax-typescript" "^7.16.0" - -"@babel/plugin-transform-unicode-escapes@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.16.0.tgz#1a354064b4c45663a32334f46fa0cf6100b5b1f3" - integrity sha512-VFi4dhgJM7Bpk8lRc5CMaRGlKZ29W9C3geZjt9beuzSUrlJxsNwX7ReLwaL6WEvsOf2EQkyIJEPtF8EXjB/g2A== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/plugin-transform-unicode-regex@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.16.0.tgz#293b80950177c8c85aede87cef280259fb995402" - integrity sha512-jHLK4LxhHjvCeZDWyA9c+P9XH1sOxRd1RO9xMtDVRAOND/PczPqizEtVdx4TQF/wyPaewqpT+tgQFYMnN/P94A== - dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.16.0" - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/preset-env@^7.12.1", "@babel/preset-env@^7.15.6": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.16.0.tgz#97228393d217560d6a1c6c56f0adb9d12bca67f5" - integrity sha512-cdTu/W0IrviamtnZiTfixPfIncr2M1VqRrkjzZWlr1B4TVYimCFK5jkyOdP4qw2MrlKHi+b3ORj6x8GoCew8Dg== - dependencies: - "@babel/compat-data" "^7.16.0" - "@babel/helper-compilation-targets" "^7.16.0" - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-validator-option" "^7.14.5" - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.16.0" - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.16.0" - "@babel/plugin-proposal-async-generator-functions" "^7.16.0" - "@babel/plugin-proposal-class-properties" "^7.16.0" - "@babel/plugin-proposal-class-static-block" "^7.16.0" - "@babel/plugin-proposal-dynamic-import" "^7.16.0" - "@babel/plugin-proposal-export-namespace-from" "^7.16.0" - "@babel/plugin-proposal-json-strings" "^7.16.0" - "@babel/plugin-proposal-logical-assignment-operators" "^7.16.0" - "@babel/plugin-proposal-nullish-coalescing-operator" "^7.16.0" - "@babel/plugin-proposal-numeric-separator" "^7.16.0" - "@babel/plugin-proposal-object-rest-spread" "^7.16.0" - "@babel/plugin-proposal-optional-catch-binding" "^7.16.0" - "@babel/plugin-proposal-optional-chaining" "^7.16.0" - "@babel/plugin-proposal-private-methods" "^7.16.0" - "@babel/plugin-proposal-private-property-in-object" "^7.16.0" - "@babel/plugin-proposal-unicode-property-regex" "^7.16.0" +"@babel/plugin-transform-shorthand-properties@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.18.6.tgz#6d6df7983d67b195289be24909e3f12a8f664dc9" + integrity sha512-eCLXXJqv8okzg86ywZJbRn19YJHU4XUa55oz2wbHhaQVn/MM+XhukiT7SYqp/7o00dg52Rj51Ny+Ecw4oyoygw== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-spread@^7.19.0": + version "7.19.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.19.0.tgz#dd60b4620c2fec806d60cfaae364ec2188d593b6" + integrity sha512-RsuMk7j6n+r752EtzyScnWkQyuJdli6LdO5Klv8Yx0OfPVTcQkIUfS8clx5e9yHXzlnhOZF3CbQ8C2uP5j074w== + dependencies: + "@babel/helper-plugin-utils" "^7.19.0" + "@babel/helper-skip-transparent-expression-wrappers" "^7.18.9" + +"@babel/plugin-transform-sticky-regex@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.18.6.tgz#c6706eb2b1524028e317720339583ad0f444adcc" + integrity sha512-kfiDrDQ+PBsQDO85yj1icueWMfGfJFKN1KCkndygtu/C9+XUfydLC8Iv5UYJqRwy4zk8EcplRxEOeLyjq1gm6Q== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/plugin-transform-template-literals@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.18.9.tgz#04ec6f10acdaa81846689d63fae117dd9c243a5e" + integrity sha512-S8cOWfT82gTezpYOiVaGHrCbhlHgKhQt8XH5ES46P2XWmX92yisoZywf5km75wv5sYcXDUCLMmMxOLCtthDgMA== + dependencies: + "@babel/helper-plugin-utils" "^7.18.9" + +"@babel/plugin-transform-typeof-symbol@^7.18.9": + version "7.18.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.18.9.tgz#c8cea68263e45addcd6afc9091429f80925762c0" + integrity sha512-SRfwTtF11G2aemAZWivL7PD+C9z52v9EvMqH9BuYbabyPuKUvSWks3oCg6041pT925L4zVFqaVBeECwsmlguEw== + dependencies: + "@babel/helper-plugin-utils" "^7.18.9" + +"@babel/plugin-transform-typescript@^7.18.6": + version "7.20.2" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.20.2.tgz#91515527b376fc122ba83b13d70b01af8fe98f3f" + integrity sha512-jvS+ngBfrnTUBfOQq8NfGnSbF9BrqlR6hjJ2yVxMkmO5nL/cdifNbI30EfjRlN4g5wYWNnMPyj5Sa6R1pbLeag== + dependencies: + "@babel/helper-create-class-features-plugin" "^7.20.2" + "@babel/helper-plugin-utils" "^7.20.2" + "@babel/plugin-syntax-typescript" "^7.20.0" + +"@babel/plugin-transform-unicode-escapes@^7.18.10": + version "7.18.10" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.18.10.tgz#1ecfb0eda83d09bbcb77c09970c2dd55832aa246" + integrity sha512-kKAdAI+YzPgGY/ftStBFXTI1LZFju38rYThnfMykS+IXy8BVx+res7s2fxf1l8I35DV2T97ezo6+SGrXz6B3iQ== + dependencies: + "@babel/helper-plugin-utils" "^7.18.9" + +"@babel/plugin-transform-unicode-regex@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.18.6.tgz#194317225d8c201bbae103364ffe9e2cea36cdca" + integrity sha512-gE7A6Lt7YLnNOL3Pb9BNeZvi+d8l7tcRrG4+pwJjK9hD2xX4mEvjlQW60G9EEmfXVYRPv9VRQcyegIVHCql/AA== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.18.6" + "@babel/helper-plugin-utils" "^7.18.6" + +"@babel/preset-env@^7.18.6", "@babel/preset-env@^7.19.4": + version "7.20.2" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.20.2.tgz#9b1642aa47bb9f43a86f9630011780dab7f86506" + integrity sha512-1G0efQEWR1EHkKvKHqbG+IN/QdgwfByUpM5V5QroDzGV2t3S/WXNQd693cHiHTlCFMpr9B6FkPFXDA2lQcKoDg== + dependencies: + "@babel/compat-data" "^7.20.1" + "@babel/helper-compilation-targets" "^7.20.0" + "@babel/helper-plugin-utils" "^7.20.2" + "@babel/helper-validator-option" "^7.18.6" + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.18.6" + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.18.9" + "@babel/plugin-proposal-async-generator-functions" "^7.20.1" + "@babel/plugin-proposal-class-properties" "^7.18.6" + "@babel/plugin-proposal-class-static-block" "^7.18.6" + "@babel/plugin-proposal-dynamic-import" "^7.18.6" + "@babel/plugin-proposal-export-namespace-from" "^7.18.9" + "@babel/plugin-proposal-json-strings" "^7.18.6" + "@babel/plugin-proposal-logical-assignment-operators" "^7.18.9" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.18.6" + "@babel/plugin-proposal-numeric-separator" "^7.18.6" + "@babel/plugin-proposal-object-rest-spread" "^7.20.2" + "@babel/plugin-proposal-optional-catch-binding" "^7.18.6" + "@babel/plugin-proposal-optional-chaining" "^7.18.9" + "@babel/plugin-proposal-private-methods" "^7.18.6" + "@babel/plugin-proposal-private-property-in-object" "^7.18.6" + "@babel/plugin-proposal-unicode-property-regex" "^7.18.6" "@babel/plugin-syntax-async-generators" "^7.8.4" "@babel/plugin-syntax-class-properties" "^7.12.13" "@babel/plugin-syntax-class-static-block" "^7.14.5" "@babel/plugin-syntax-dynamic-import" "^7.8.3" "@babel/plugin-syntax-export-namespace-from" "^7.8.3" + "@babel/plugin-syntax-import-assertions" "^7.20.0" "@babel/plugin-syntax-json-strings" "^7.8.3" "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" @@ -1027,44 +1054,44 @@ "@babel/plugin-syntax-optional-chaining" "^7.8.3" "@babel/plugin-syntax-private-property-in-object" "^7.14.5" "@babel/plugin-syntax-top-level-await" "^7.14.5" - "@babel/plugin-transform-arrow-functions" "^7.16.0" - "@babel/plugin-transform-async-to-generator" "^7.16.0" - "@babel/plugin-transform-block-scoped-functions" "^7.16.0" - "@babel/plugin-transform-block-scoping" "^7.16.0" - "@babel/plugin-transform-classes" "^7.16.0" - "@babel/plugin-transform-computed-properties" "^7.16.0" - "@babel/plugin-transform-destructuring" "^7.16.0" - "@babel/plugin-transform-dotall-regex" "^7.16.0" - "@babel/plugin-transform-duplicate-keys" "^7.16.0" - "@babel/plugin-transform-exponentiation-operator" "^7.16.0" - "@babel/plugin-transform-for-of" "^7.16.0" - "@babel/plugin-transform-function-name" "^7.16.0" - "@babel/plugin-transform-literals" "^7.16.0" - "@babel/plugin-transform-member-expression-literals" "^7.16.0" - "@babel/plugin-transform-modules-amd" "^7.16.0" - "@babel/plugin-transform-modules-commonjs" "^7.16.0" - "@babel/plugin-transform-modules-systemjs" "^7.16.0" - "@babel/plugin-transform-modules-umd" "^7.16.0" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.16.0" - "@babel/plugin-transform-new-target" "^7.16.0" - "@babel/plugin-transform-object-super" "^7.16.0" - "@babel/plugin-transform-parameters" "^7.16.0" - "@babel/plugin-transform-property-literals" "^7.16.0" - "@babel/plugin-transform-regenerator" "^7.16.0" - "@babel/plugin-transform-reserved-words" "^7.16.0" - "@babel/plugin-transform-shorthand-properties" "^7.16.0" - "@babel/plugin-transform-spread" "^7.16.0" - "@babel/plugin-transform-sticky-regex" "^7.16.0" - "@babel/plugin-transform-template-literals" "^7.16.0" - "@babel/plugin-transform-typeof-symbol" "^7.16.0" - "@babel/plugin-transform-unicode-escapes" "^7.16.0" - "@babel/plugin-transform-unicode-regex" "^7.16.0" + "@babel/plugin-transform-arrow-functions" "^7.18.6" + "@babel/plugin-transform-async-to-generator" "^7.18.6" + "@babel/plugin-transform-block-scoped-functions" "^7.18.6" + "@babel/plugin-transform-block-scoping" "^7.20.2" + "@babel/plugin-transform-classes" "^7.20.2" + "@babel/plugin-transform-computed-properties" "^7.18.9" + "@babel/plugin-transform-destructuring" "^7.20.2" + "@babel/plugin-transform-dotall-regex" "^7.18.6" + "@babel/plugin-transform-duplicate-keys" "^7.18.9" + "@babel/plugin-transform-exponentiation-operator" "^7.18.6" + "@babel/plugin-transform-for-of" "^7.18.8" + "@babel/plugin-transform-function-name" "^7.18.9" + "@babel/plugin-transform-literals" "^7.18.9" + "@babel/plugin-transform-member-expression-literals" "^7.18.6" + "@babel/plugin-transform-modules-amd" "^7.19.6" + "@babel/plugin-transform-modules-commonjs" "^7.19.6" + "@babel/plugin-transform-modules-systemjs" "^7.19.6" + "@babel/plugin-transform-modules-umd" "^7.18.6" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.19.1" + "@babel/plugin-transform-new-target" "^7.18.6" + "@babel/plugin-transform-object-super" "^7.18.6" + "@babel/plugin-transform-parameters" "^7.20.1" + "@babel/plugin-transform-property-literals" "^7.18.6" + "@babel/plugin-transform-regenerator" "^7.18.6" + "@babel/plugin-transform-reserved-words" "^7.18.6" + "@babel/plugin-transform-shorthand-properties" "^7.18.6" + "@babel/plugin-transform-spread" "^7.19.0" + "@babel/plugin-transform-sticky-regex" "^7.18.6" + "@babel/plugin-transform-template-literals" "^7.18.9" + "@babel/plugin-transform-typeof-symbol" "^7.18.9" + "@babel/plugin-transform-unicode-escapes" "^7.18.10" + "@babel/plugin-transform-unicode-regex" "^7.18.6" "@babel/preset-modules" "^0.1.5" - "@babel/types" "^7.16.0" - babel-plugin-polyfill-corejs2 "^0.2.3" - babel-plugin-polyfill-corejs3 "^0.3.0" - babel-plugin-polyfill-regenerator "^0.2.3" - core-js-compat "^3.19.0" + "@babel/types" "^7.20.2" + babel-plugin-polyfill-corejs2 "^0.3.3" + babel-plugin-polyfill-corejs3 "^0.6.0" + babel-plugin-polyfill-regenerator "^0.4.1" + core-js-compat "^3.25.1" semver "^6.3.0" "@babel/preset-modules@^0.1.5": @@ -1078,326 +1105,350 @@ "@babel/types" "^7.4.4" esutils "^2.0.2" -"@babel/preset-react@^7.12.13", "@babel/preset-react@^7.12.5": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.16.0.tgz#f71d3e8dff5218478011df037fad52660ee6d82a" - integrity sha512-d31IFW2bLRB28uL1WoElyro8RH5l6531XfxMtCeCmp6RVAF1uTfxxUA0LH1tXl+psZdwfmIbwoG4U5VwgbhtLw== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-validator-option" "^7.14.5" - "@babel/plugin-transform-react-display-name" "^7.16.0" - "@babel/plugin-transform-react-jsx" "^7.16.0" - "@babel/plugin-transform-react-jsx-development" "^7.16.0" - "@babel/plugin-transform-react-pure-annotations" "^7.16.0" - -"@babel/preset-typescript@^7.12.16": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.16.0.tgz#b0b4f105b855fb3d631ec036cdc9d1ffd1fa5eac" - integrity sha512-txegdrZYgO9DlPbv+9QOVpMnKbOtezsLHWsnsRF4AjbSIsVaujrq1qg8HK0mxQpWv0jnejt0yEoW1uWpvbrDTg== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/helper-validator-option" "^7.14.5" - "@babel/plugin-transform-typescript" "^7.16.0" - -"@babel/runtime-corejs3@^7.15.4": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.16.0.tgz#58a7fb00e6948508f12f53a303993e8b6e2f6c70" - integrity sha512-Oi2qwQ21X7/d9gn3WiwkDTJmq3TQtYNz89lRnoFy8VeZpWlsyXvzSwiRrRZ8cXluvSwqKxqHJ6dBd9Rv+p0ZGQ== - dependencies: - core-js-pure "^3.19.0" - regenerator-runtime "^0.13.4" - -"@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.3", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.13", "@babel/runtime@^7.15.4", "@babel/runtime@^7.8.4": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.16.0.tgz#e27b977f2e2088ba24748bf99b5e1dece64e4f0b" - integrity sha512-Nht8L0O8YCktmsDV6FqFue7vQLRx3Hb0B37lS5y0jDRqRxlBG4wIJHnf9/bgSE2UyipKFA01YtS+npRdTWBUyw== - dependencies: - regenerator-runtime "^0.13.4" - -"@babel/template@^7.12.7", "@babel/template@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.16.0.tgz#d16a35ebf4cd74e202083356fab21dd89363ddd6" - integrity sha512-MnZdpFD/ZdYhXwiunMqqgyZyucaYsbL0IrjoGjaVhGilz+x8YB++kRfygSOIj1yOtWKPlx7NBp+9I1RQSgsd5A== - dependencies: - "@babel/code-frame" "^7.16.0" - "@babel/parser" "^7.16.0" - "@babel/types" "^7.16.0" - -"@babel/traverse@^7.12.13", "@babel/traverse@^7.12.9", "@babel/traverse@^7.13.0", "@babel/traverse@^7.16.0": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.16.0.tgz#965df6c6bfc0a958c1e739284d3c9fa4a6e3c45b" - integrity sha512-qQ84jIs1aRQxaGaxSysII9TuDaguZ5yVrEuC0BN2vcPlalwfLovVmCjbFDPECPXcYM/wLvNFfp8uDOliLxIoUQ== - dependencies: - "@babel/code-frame" "^7.16.0" - "@babel/generator" "^7.16.0" - "@babel/helper-function-name" "^7.16.0" - "@babel/helper-hoist-variables" "^7.16.0" - "@babel/helper-split-export-declaration" "^7.16.0" - "@babel/parser" "^7.16.0" - "@babel/types" "^7.16.0" +"@babel/preset-react@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.18.6.tgz#979f76d6277048dc19094c217b507f3ad517dd2d" + integrity sha512-zXr6atUmyYdiWRVLOZahakYmOBHtWc2WGCkP8PYTgZi0iJXDY2CN180TdrIW4OGOAdLc7TifzDIvtx6izaRIzg== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-validator-option" "^7.18.6" + "@babel/plugin-transform-react-display-name" "^7.18.6" + "@babel/plugin-transform-react-jsx" "^7.18.6" + "@babel/plugin-transform-react-jsx-development" "^7.18.6" + "@babel/plugin-transform-react-pure-annotations" "^7.18.6" + +"@babel/preset-typescript@^7.18.6": + version "7.18.6" + resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.18.6.tgz#ce64be3e63eddc44240c6358daefac17b3186399" + integrity sha512-s9ik86kXBAnD760aybBucdpnLsAt0jK1xqJn2juOn9lkOvSHV60os5hxoVJsPzMQxvnUJFAlkont2DvvaYEBtQ== + dependencies: + "@babel/helper-plugin-utils" "^7.18.6" + "@babel/helper-validator-option" "^7.18.6" + "@babel/plugin-transform-typescript" "^7.18.6" + +"@babel/runtime-corejs3@^7.18.6": + version "7.20.1" + resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.20.1.tgz#d0775a49bb5fba77e42cbb7276c9955c7b05af8d" + integrity sha512-CGulbEDcg/ND1Im7fUNRZdGXmX2MTWVVZacQi/6DiKE5HNwZ3aVTm5PV4lO8HHz0B2h8WQyvKKjbX5XgTtydsg== + dependencies: + core-js-pure "^3.25.1" + regenerator-runtime "^0.13.10" + +"@babel/runtime@^7.1.2", "@babel/runtime@^7.10.2", "@babel/runtime@^7.10.3", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.18.6", "@babel/runtime@^7.8.4": + version "7.20.1" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.20.1.tgz#1148bb33ab252b165a06698fde7576092a78b4a9" + integrity sha512-mrzLkl6U9YLF8qpqI7TB82PESyEGjm/0Ly91jG575eVxMMlb8fYfOXFZIJ8XfLrJZQbm7dlKry2bJmXBUEkdFg== + dependencies: + regenerator-runtime "^0.13.10" + +"@babel/template@^7.12.7", "@babel/template@^7.18.10": + version "7.18.10" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.18.10.tgz#6f9134835970d1dbf0835c0d100c9f38de0c5e71" + integrity sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA== + dependencies: + "@babel/code-frame" "^7.18.6" + "@babel/parser" "^7.18.10" + "@babel/types" "^7.18.10" + +"@babel/traverse@^7.12.9", "@babel/traverse@^7.18.8", "@babel/traverse@^7.19.0", "@babel/traverse@^7.19.1", "@babel/traverse@^7.20.1": + version "7.20.1" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.20.1.tgz#9b15ccbf882f6d107eeeecf263fbcdd208777ec8" + integrity sha512-d3tN8fkVJwFLkHkBN479SOsw4DMZnz8cdbL/gvuDuzy3TS6Nfw80HuQqhw1pITbIruHyh7d1fMA47kWzmcUEGA== + dependencies: + "@babel/code-frame" "^7.18.6" + "@babel/generator" "^7.20.1" + "@babel/helper-environment-visitor" "^7.18.9" + "@babel/helper-function-name" "^7.19.0" + "@babel/helper-hoist-variables" "^7.18.6" + "@babel/helper-split-export-declaration" "^7.18.6" + "@babel/parser" "^7.20.1" + "@babel/types" "^7.20.0" debug "^4.1.0" globals "^11.1.0" -"@babel/types@^7.12.6", "@babel/types@^7.12.7", "@babel/types@^7.16.0", "@babel/types@^7.4.4": - version "7.16.0" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.16.0.tgz#db3b313804f96aadd0b776c4823e127ad67289ba" - integrity sha512-PJgg/k3SdLsGb3hhisFvtLOw5ts113klrpLuIPtCJIU+BB24fqq6lf8RWqKJEjzqXR9AEH1rIb5XTqwBHB+kQg== +"@babel/types@^7.12.7", "@babel/types@^7.18.10", "@babel/types@^7.18.6", "@babel/types@^7.18.9", "@babel/types@^7.19.0", "@babel/types@^7.20.0", "@babel/types@^7.20.2", "@babel/types@^7.4.4": + version "7.20.2" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.20.2.tgz#67ac09266606190f496322dbaff360fdaa5e7842" + integrity sha512-FnnvsNWgZCr232sqtXggapvlkk/tuwR/qhGzcmxI0GXLCjmPYQPzio2FbdlWuY6y1sHFfQKk+rRbUZ9VStQMog== dependencies: - "@babel/helper-validator-identifier" "^7.15.7" + "@babel/helper-string-parser" "^7.19.4" + "@babel/helper-validator-identifier" "^7.19.1" to-fast-properties "^2.0.0" -"@docsearch/css@3.0.0-alpha.41": - version "3.0.0-alpha.41" - resolved "https://registry.yarnpkg.com/@docsearch/css/-/css-3.0.0-alpha.41.tgz#c5c8e803541bd157ad86e764c2c1e9f1b5a68592" - integrity sha512-AP1jqcF/9jCrm4s0lcES3QAtHueyipKjd14L/pguk0CZYK7uI7hC0FWodmRmrgK3/HST9jiHa1waUMR6ZYedlQ== +"@colors/colors@1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" + integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ== -"@docsearch/react@^3.0.0-alpha.39": - version "3.0.0-alpha.41" - resolved "https://registry.yarnpkg.com/@docsearch/react/-/react-3.0.0-alpha.41.tgz#07e85a664e85f251ce3d13153abce65a4d5997ab" - integrity sha512-UL0Gdter/NUea04lGuBGH0GzQ2/2q/hBfn7Rjo71rRKbjtfkQCM92leJ9tZ+9j9sFLoyuHb9XMm/B8vCjWwTEg== +"@docsearch/css@3.3.0": + version "3.3.0" + resolved "https://registry.yarnpkg.com/@docsearch/css/-/css-3.3.0.tgz#d698e48302d12240d7c2f7452ccb2d2239a8cd80" + integrity sha512-rODCdDtGyudLj+Va8b6w6Y85KE85bXRsps/R4Yjwt5vueXKXZQKYw0aA9knxLBT6a/bI/GMrAcmCR75KYOM6hg== + +"@docsearch/react@^3.1.1": + version "3.3.0" + resolved "https://registry.yarnpkg.com/@docsearch/react/-/react-3.3.0.tgz#b8ac8e7f49b9bf2f96d34c24bc1cfd097ec0eead" + integrity sha512-fhS5adZkae2SSdMYEMVg6pxI5a/cE+tW16ki1V0/ur4Fdok3hBRkmN/H8VvlXnxzggkQIIRIVvYPn00JPjen3A== dependencies: - "@algolia/autocomplete-core" "1.2.2" - "@algolia/autocomplete-preset-algolia" "1.2.2" - "@docsearch/css" "3.0.0-alpha.41" + "@algolia/autocomplete-core" "1.7.2" + "@algolia/autocomplete-preset-algolia" "1.7.2" + "@docsearch/css" "3.3.0" algoliasearch "^4.0.0" -"@docusaurus/core@2.0.0-beta.9", "@docusaurus/core@^2.0.0-beta.9": - version "2.0.0-beta.9" - resolved "https://registry.yarnpkg.com/@docusaurus/core/-/core-2.0.0-beta.9.tgz#59b57c5e60fe83ef9e3c6aa7000d470eb0c52656" - integrity sha512-Bf9c6+yftZfAJk2h4HyaDvzBp5TLhqYtfnfWKKNi0Gdw9vRLXhi7IaiGaLWIuNAIJLTi++Ql0BAn+C0OO8EsWA== +"@docusaurus/core@2.2.0", "@docusaurus/core@^2.0.0-beta": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@docusaurus/core/-/core-2.2.0.tgz#64c9ee31502c23b93c869f8188f73afaf5fd4867" + integrity sha512-Vd6XOluKQqzG12fEs9prJgDtyn6DPok9vmUWDR2E6/nV5Fl9SVkhEQOBxwObjk3kQh7OY7vguFaLh0jqdApWsA== dependencies: - "@babel/core" "^7.12.16" - "@babel/generator" "^7.12.15" + "@babel/core" "^7.18.6" + "@babel/generator" "^7.18.7" "@babel/plugin-syntax-dynamic-import" "^7.8.3" - "@babel/plugin-transform-runtime" "^7.15.0" - "@babel/preset-env" "^7.15.6" - "@babel/preset-react" "^7.12.13" - "@babel/preset-typescript" "^7.12.16" - "@babel/runtime" "^7.15.4" - "@babel/runtime-corejs3" "^7.15.4" - "@babel/traverse" "^7.12.13" - "@docusaurus/cssnano-preset" "2.0.0-beta.9" + "@babel/plugin-transform-runtime" "^7.18.6" + "@babel/preset-env" "^7.18.6" + "@babel/preset-react" "^7.18.6" + "@babel/preset-typescript" "^7.18.6" + "@babel/runtime" "^7.18.6" + "@babel/runtime-corejs3" "^7.18.6" + "@babel/traverse" "^7.18.8" + "@docusaurus/cssnano-preset" "2.2.0" + "@docusaurus/logger" "2.2.0" + "@docusaurus/mdx-loader" "2.2.0" "@docusaurus/react-loadable" "5.5.2" - "@docusaurus/types" "2.0.0-beta.9" - "@docusaurus/utils" "2.0.0-beta.9" - "@docusaurus/utils-common" "2.0.0-beta.9" - "@docusaurus/utils-validation" "2.0.0-beta.9" - "@slorber/static-site-generator-webpack-plugin" "^4.0.0" - "@svgr/webpack" "^5.5.0" - autoprefixer "^10.3.5" - babel-loader "^8.2.2" - babel-plugin-dynamic-import-node "2.3.0" - boxen "^5.0.1" + "@docusaurus/utils" "2.2.0" + "@docusaurus/utils-common" "2.2.0" + "@docusaurus/utils-validation" "2.2.0" + "@slorber/static-site-generator-webpack-plugin" "^4.0.7" + "@svgr/webpack" "^6.2.1" + autoprefixer "^10.4.7" + babel-loader "^8.2.5" + babel-plugin-dynamic-import-node "^2.3.3" + boxen "^6.2.1" chalk "^4.1.2" - chokidar "^3.5.2" - clean-css "^5.1.5" + chokidar "^3.5.3" + clean-css "^5.3.0" + cli-table3 "^0.6.2" + combine-promises "^1.1.0" commander "^5.1.0" - copy-webpack-plugin "^9.0.1" - core-js "^3.18.0" - css-loader "^5.1.1" - css-minimizer-webpack-plugin "^3.0.2" - cssnano "^5.0.8" - del "^6.0.0" + copy-webpack-plugin "^11.0.0" + core-js "^3.23.3" + css-loader "^6.7.1" + css-minimizer-webpack-plugin "^4.0.0" + cssnano "^5.1.12" + del "^6.1.1" detect-port "^1.3.0" escape-html "^1.0.3" eta "^1.12.3" file-loader "^6.2.0" - fs-extra "^10.0.0" - github-slugger "^1.4.0" - globby "^11.0.2" - html-minifier-terser "^6.0.2" - html-tags "^3.1.0" - html-webpack-plugin "^5.4.0" + fs-extra "^10.1.0" + html-minifier-terser "^6.1.0" + html-tags "^3.2.0" + html-webpack-plugin "^5.5.0" import-fresh "^3.3.0" - is-root "^2.1.0" leven "^3.1.0" - lodash "^4.17.20" - mini-css-extract-plugin "^1.6.0" - nprogress "^0.2.0" - postcss "^8.3.7" - postcss-loader "^6.1.1" - prompts "^2.4.1" - react-dev-utils "12.0.0-next.47" - react-error-overlay "^6.0.9" - react-helmet "^6.1.0" + lodash "^4.17.21" + mini-css-extract-plugin "^2.6.1" + postcss "^8.4.14" + postcss-loader "^7.0.0" + prompts "^2.4.2" + react-dev-utils "^12.0.1" + react-helmet-async "^1.3.0" react-loadable "npm:@docusaurus/react-loadable@5.5.2" react-loadable-ssr-addon-v5-slorber "^1.0.1" - react-router "^5.2.0" + react-router "^5.3.3" react-router-config "^5.1.1" - react-router-dom "^5.2.0" - remark-admonitions "^1.2.1" - resolve-pathname "^3.0.0" + react-router-dom "^5.3.3" rtl-detect "^1.0.4" - semver "^7.3.4" + semver "^7.3.7" serve-handler "^6.1.3" - shelljs "^0.8.4" - std-env "^2.2.1" - strip-ansi "^6.0.0" - terser-webpack-plugin "^5.2.4" - tslib "^2.3.1" + shelljs "^0.8.5" + terser-webpack-plugin "^5.3.3" + tslib "^2.4.0" update-notifier "^5.1.0" url-loader "^4.1.1" - wait-on "^6.0.0" - webpack "^5.61.0" - webpack-bundle-analyzer "^4.4.2" - webpack-dev-server "^4.4.0" + wait-on "^6.0.1" + webpack "^5.73.0" + webpack-bundle-analyzer "^4.5.0" + webpack-dev-server "^4.9.3" webpack-merge "^5.8.0" - webpackbar "^5.0.0-3" - -"@docusaurus/cssnano-preset@2.0.0-beta.9": - version "2.0.0-beta.9" - resolved "https://registry.yarnpkg.com/@docusaurus/cssnano-preset/-/cssnano-preset-2.0.0-beta.9.tgz#4ad9079c68b79744c08be6e48e51d2c12907f71f" - integrity sha512-oIdoiZ/i4LXRxmuLN2ZmvGpMqtwba+ck9TlaQDWC7wvHx+EA9mvvcewKWgc7e4dxPA00+777cQvrDctAreAqLw== - dependencies: - cssnano-preset-advanced "^5.1.4" - postcss "^8.3.7" - postcss-sort-media-queries "^4.1.0" - -"@docusaurus/mdx-loader@2.0.0-beta.9": - version "2.0.0-beta.9" - resolved "https://registry.yarnpkg.com/@docusaurus/mdx-loader/-/mdx-loader-2.0.0-beta.9.tgz#e87a1ff22fdabcb6bea59beae8b2d999dfb6eb81" - integrity sha512-qb+/Ew69kaAIiot+1lJ13ozsyCY+7/VryzopDTgr60BDCsLUvuDzjNKreBqo1xdC4JxYD/hJMV7UAHkZ8rWB8Q== - dependencies: - "@babel/parser" "^7.12.16" - "@babel/traverse" "^7.12.13" - "@docusaurus/core" "2.0.0-beta.9" - "@docusaurus/utils" "2.0.0-beta.9" - "@mdx-js/mdx" "^1.6.21" - "@mdx-js/react" "^1.6.21" + webpackbar "^5.0.2" + +"@docusaurus/cssnano-preset@2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@docusaurus/cssnano-preset/-/cssnano-preset-2.2.0.tgz#fc05044659051ae74ab4482afcf4a9936e81d523" + integrity sha512-mAAwCo4n66TMWBH1kXnHVZsakW9VAXJzTO4yZukuL3ro4F+JtkMwKfh42EG75K/J/YIFQG5I/Bzy0UH/hFxaTg== + dependencies: + cssnano-preset-advanced "^5.3.8" + postcss "^8.4.14" + postcss-sort-media-queries "^4.2.1" + tslib "^2.4.0" + +"@docusaurus/logger@2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@docusaurus/logger/-/logger-2.2.0.tgz#ea2f7feda7b8675485933b87f06d9c976d17423f" + integrity sha512-DF3j1cA5y2nNsu/vk8AG7xwpZu6f5MKkPPMaaIbgXLnWGfm6+wkOeW7kNrxnM95YOhKUkJUophX69nGUnLsm0A== + dependencies: chalk "^4.1.2" + tslib "^2.4.0" + +"@docusaurus/mdx-loader@2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@docusaurus/mdx-loader/-/mdx-loader-2.2.0.tgz#fd558f429e5d9403d284bd4214e54d9768b041a0" + integrity sha512-X2bzo3T0jW0VhUU+XdQofcEeozXOTmKQMvc8tUnWRdTnCvj4XEcBVdC3g+/jftceluiwSTNRAX4VBOJdNt18jA== + dependencies: + "@babel/parser" "^7.18.8" + "@babel/traverse" "^7.18.8" + "@docusaurus/logger" "2.2.0" + "@docusaurus/utils" "2.2.0" + "@mdx-js/mdx" "^1.6.22" escape-html "^1.0.3" file-loader "^6.2.0" - fs-extra "^10.0.0" - github-slugger "^1.4.0" - gray-matter "^4.0.3" + fs-extra "^10.1.0" + image-size "^1.0.1" mdast-util-to-string "^2.0.0" - remark-emoji "^2.1.0" + remark-emoji "^2.2.0" stringify-object "^3.3.0" - unist-util-visit "^2.0.2" + tslib "^2.4.0" + unified "^9.2.2" + unist-util-visit "^2.0.3" url-loader "^4.1.1" - webpack "^5.61.0" - -"@docusaurus/plugin-content-blog@2.0.0-beta.9": - version "2.0.0-beta.9" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-blog/-/plugin-content-blog-2.0.0-beta.9.tgz#d72a32013232610552cbc45509ba2ddaea653690" - integrity sha512-KZ6UmUa/P4SSX8/xnZpwSt7krnAfRg3S/ghZ7zeIzcp12iumSZBmLNi5rIIXcsFVH0IPOnIofEoWEaEIwaNerg== - dependencies: - "@docusaurus/core" "2.0.0-beta.9" - "@docusaurus/mdx-loader" "2.0.0-beta.9" - "@docusaurus/types" "2.0.0-beta.9" - "@docusaurus/utils" "2.0.0-beta.9" - "@docusaurus/utils-validation" "2.0.0-beta.9" - chalk "^4.1.2" - escape-string-regexp "^4.0.0" + webpack "^5.73.0" + +"@docusaurus/module-type-aliases@2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@docusaurus/module-type-aliases/-/module-type-aliases-2.2.0.tgz#1e23e54a1bbb6fde1961e4fa395b1b69f4803ba5" + integrity sha512-wDGW4IHKoOr9YuJgy7uYuKWrDrSpsUSDHLZnWQYM9fN7D5EpSmYHjFruUpKWVyxLpD/Wh0rW8hYZwdjJIQUQCQ== + dependencies: + "@docusaurus/react-loadable" "5.5.2" + "@docusaurus/types" "2.2.0" + "@types/history" "^4.7.11" + "@types/react" "*" + "@types/react-router-config" "*" + "@types/react-router-dom" "*" + react-helmet-async "*" + react-loadable "npm:@docusaurus/react-loadable@5.5.2" + +"@docusaurus/plugin-content-blog@2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-blog/-/plugin-content-blog-2.2.0.tgz#dc55982e76771f4e678ac10e26d10e1da2011dc1" + integrity sha512-0mWBinEh0a5J2+8ZJXJXbrCk1tSTNf7Nm4tYAl5h2/xx+PvH/Bnu0V+7mMljYm/1QlDYALNIIaT/JcoZQFUN3w== + dependencies: + "@docusaurus/core" "2.2.0" + "@docusaurus/logger" "2.2.0" + "@docusaurus/mdx-loader" "2.2.0" + "@docusaurus/types" "2.2.0" + "@docusaurus/utils" "2.2.0" + "@docusaurus/utils-common" "2.2.0" + "@docusaurus/utils-validation" "2.2.0" + cheerio "^1.0.0-rc.12" feed "^4.2.2" - fs-extra "^10.0.0" - globby "^11.0.2" - js-yaml "^4.0.0" - loader-utils "^2.0.0" - lodash "^4.17.20" + fs-extra "^10.1.0" + lodash "^4.17.21" reading-time "^1.5.0" - remark-admonitions "^1.2.1" - tslib "^2.3.1" + tslib "^2.4.0" + unist-util-visit "^2.0.3" utility-types "^3.10.0" - webpack "^5.61.0" - -"@docusaurus/plugin-content-docs@2.0.0-beta.9": - version "2.0.0-beta.9" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-docs/-/plugin-content-docs-2.0.0-beta.9.tgz#53ac2b43beb0f183c8a9b8fab6201e5e8f444a67" - integrity sha512-GC+CvqKuravPpK5fqlYJVmj9hc6nkd/c/rM2ONueFCqw2wyuH7esWL8RpMqgS0JM1qwwuRpi0Dd3R/zdOptHIQ== - dependencies: - "@docusaurus/core" "2.0.0-beta.9" - "@docusaurus/mdx-loader" "2.0.0-beta.9" - "@docusaurus/types" "2.0.0-beta.9" - "@docusaurus/utils" "2.0.0-beta.9" - "@docusaurus/utils-validation" "2.0.0-beta.9" - chalk "^4.1.2" + webpack "^5.73.0" + +"@docusaurus/plugin-content-docs@2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-docs/-/plugin-content-docs-2.2.0.tgz#0fcb85226fcdb80dc1e2d4a36ef442a650dcc84d" + integrity sha512-BOazBR0XjzsHE+2K1wpNxz5QZmrJgmm3+0Re0EVPYFGW8qndCWGNtXW/0lGKhecVPML8yyFeAmnUCIs7xM2wPw== + dependencies: + "@docusaurus/core" "2.2.0" + "@docusaurus/logger" "2.2.0" + "@docusaurus/mdx-loader" "2.2.0" + "@docusaurus/module-type-aliases" "2.2.0" + "@docusaurus/types" "2.2.0" + "@docusaurus/utils" "2.2.0" + "@docusaurus/utils-validation" "2.2.0" + "@types/react-router-config" "^5.0.6" combine-promises "^1.1.0" - escape-string-regexp "^4.0.0" - execa "^5.0.0" - fs-extra "^10.0.0" - globby "^11.0.2" - import-fresh "^3.2.2" - js-yaml "^4.0.0" - loader-utils "^2.0.0" - lodash "^4.17.20" - remark-admonitions "^1.2.1" - shelljs "^0.8.4" - tslib "^2.3.1" + fs-extra "^10.1.0" + import-fresh "^3.3.0" + js-yaml "^4.1.0" + lodash "^4.17.21" + tslib "^2.4.0" utility-types "^3.10.0" - webpack "^5.61.0" - -"@docusaurus/plugin-content-pages@2.0.0-beta.9": - version "2.0.0-beta.9" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-pages/-/plugin-content-pages-2.0.0-beta.9.tgz#115309f03bae2864bb9e4cd8fae646ea2e1f31dc" - integrity sha512-27nFHhPpZEWra6izyWgY+EkBspr3OAUUHojRXzMUKplYLZ5gIciM224PXbwLyECjpn51eaf8/2Ay+/H9BdTCBw== - dependencies: - "@docusaurus/core" "2.0.0-beta.9" - "@docusaurus/mdx-loader" "2.0.0-beta.9" - "@docusaurus/types" "2.0.0-beta.9" - "@docusaurus/utils" "2.0.0-beta.9" - "@docusaurus/utils-validation" "2.0.0-beta.9" - globby "^11.0.2" - lodash "^4.17.20" - remark-admonitions "^1.2.1" - tslib "^2.3.1" - webpack "^5.61.0" - -"@docusaurus/plugin-debug@2.0.0-beta.9": - version "2.0.0-beta.9" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-debug/-/plugin-debug-2.0.0-beta.9.tgz#97920e6ba333f99537bd72ae97a8999beeb39a3b" - integrity sha512-uVnLfNE7YBMCWVcfoy6NgAxbqfG3bXfrLozM2RMafPmsCitaw+wrTdnba/irM364wPFFursF9lDrNLwSrYiRbw== - dependencies: - "@docusaurus/core" "2.0.0-beta.9" - "@docusaurus/types" "2.0.0-beta.9" - "@docusaurus/utils" "2.0.0-beta.9" - fs-extra "^10.0.0" + webpack "^5.73.0" + +"@docusaurus/plugin-content-pages@2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-pages/-/plugin-content-pages-2.2.0.tgz#e3f40408787bbe229545dd50595f87e1393bc3ae" + integrity sha512-+OTK3FQHk5WMvdelz8v19PbEbx+CNT6VSpx7nVOvMNs5yJCKvmqBJBQ2ZSxROxhVDYn+CZOlmyrC56NSXzHf6g== + dependencies: + "@docusaurus/core" "2.2.0" + "@docusaurus/mdx-loader" "2.2.0" + "@docusaurus/types" "2.2.0" + "@docusaurus/utils" "2.2.0" + "@docusaurus/utils-validation" "2.2.0" + fs-extra "^10.1.0" + tslib "^2.4.0" + webpack "^5.73.0" + +"@docusaurus/plugin-debug@2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-debug/-/plugin-debug-2.2.0.tgz#b38741d2c492f405fee01ee0ef2e0029cedb689a" + integrity sha512-p9vOep8+7OVl6r/NREEYxf4HMAjV8JMYJ7Bos5fCFO0Wyi9AZEo0sCTliRd7R8+dlJXZEgcngSdxAUo/Q+CJow== + dependencies: + "@docusaurus/core" "2.2.0" + "@docusaurus/types" "2.2.0" + "@docusaurus/utils" "2.2.0" + fs-extra "^10.1.0" react-json-view "^1.21.3" - tslib "^2.3.1" - -"@docusaurus/plugin-google-analytics@2.0.0-beta.9": - version "2.0.0-beta.9" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-2.0.0-beta.9.tgz#5584d20b2e64cc3f84978d42cb0edeeabaf49123" - integrity sha512-fYnunrefFko2jF/M973FONZjn9QHzNnt7+uMokR4frK/BX/zEyW2Yw6vh7dC0oo+ml5625Pv5OfwwlOJ9DRmHw== - dependencies: - "@docusaurus/core" "2.0.0-beta.9" - -"@docusaurus/plugin-google-gtag@2.0.0-beta.9": - version "2.0.0-beta.9" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-2.0.0-beta.9.tgz#70de97bb5a25bc10969941ec257d694db0abed79" - integrity sha512-AlVhbjN0OEiM8r8BncdiP82B9I7Dw3fN4cj2pPLtcOmvcRPQM2BfdzxbXPBUHgyT50Rd6hxS+R2Fl/s2RpUAHA== - dependencies: - "@docusaurus/core" "2.0.0-beta.9" - -"@docusaurus/plugin-sitemap@2.0.0-beta.9": - version "2.0.0-beta.9" - resolved "https://registry.yarnpkg.com/@docusaurus/plugin-sitemap/-/plugin-sitemap-2.0.0-beta.9.tgz#4c944b6fc4e8fa4625a6fd985ec21d6455c31647" - integrity sha512-p6Qc1vo/yb1v767/u0E72inkGKayx77HDKsDOGrNj2IH0db0cMsskBLeKYcDfVz5+dtmFrR+lubINp7TyofkvA== - dependencies: - "@docusaurus/core" "2.0.0-beta.9" - "@docusaurus/types" "2.0.0-beta.9" - "@docusaurus/utils" "2.0.0-beta.9" - "@docusaurus/utils-common" "2.0.0-beta.9" - "@docusaurus/utils-validation" "2.0.0-beta.9" - fs-extra "^10.0.0" - sitemap "^7.0.0" - tslib "^2.3.1" - -"@docusaurus/preset-classic@^2.0.0-beta.9": - version "2.0.0-beta.9" - resolved "https://registry.yarnpkg.com/@docusaurus/preset-classic/-/preset-classic-2.0.0-beta.9.tgz#853e6fa376eb389a2f06c0c85f2bc823b26b3010" - integrity sha512-wm4x+jOKYaBL+7ckJwskyiITayNm3127e42kz4CtvmjjccpZu68JCfjehqkpnoPDTByBYnaeOKyga4azeAQLSA== - dependencies: - "@docusaurus/core" "2.0.0-beta.9" - "@docusaurus/plugin-content-blog" "2.0.0-beta.9" - "@docusaurus/plugin-content-docs" "2.0.0-beta.9" - "@docusaurus/plugin-content-pages" "2.0.0-beta.9" - "@docusaurus/plugin-debug" "2.0.0-beta.9" - "@docusaurus/plugin-google-analytics" "2.0.0-beta.9" - "@docusaurus/plugin-google-gtag" "2.0.0-beta.9" - "@docusaurus/plugin-sitemap" "2.0.0-beta.9" - "@docusaurus/theme-classic" "2.0.0-beta.9" - "@docusaurus/theme-search-algolia" "2.0.0-beta.9" + tslib "^2.4.0" + +"@docusaurus/plugin-google-analytics@2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-2.2.0.tgz#63c7137eff5a1208d2059fea04b5207c037d7954" + integrity sha512-+eZVVxVeEnV5nVQJdey9ZsfyEVMls6VyWTIj8SmX0k5EbqGvnIfET+J2pYEuKQnDIHxy+syRMoRM6AHXdHYGIg== + dependencies: + "@docusaurus/core" "2.2.0" + "@docusaurus/types" "2.2.0" + "@docusaurus/utils-validation" "2.2.0" + tslib "^2.4.0" + +"@docusaurus/plugin-google-gtag@2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-2.2.0.tgz#7b086d169ac5fe9a88aca10ab0fd2bf00c6c6b12" + integrity sha512-6SOgczP/dYdkqUMGTRqgxAS1eTp6MnJDAQMy8VCF1QKbWZmlkx4agHDexihqmYyCujTYHqDAhm1hV26EET54NQ== + dependencies: + "@docusaurus/core" "2.2.0" + "@docusaurus/types" "2.2.0" + "@docusaurus/utils-validation" "2.2.0" + tslib "^2.4.0" + +"@docusaurus/plugin-sitemap@2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-sitemap/-/plugin-sitemap-2.2.0.tgz#876da60937886032d63143253d420db6a4b34773" + integrity sha512-0jAmyRDN/aI265CbWZNZuQpFqiZuo+5otk2MylU9iVrz/4J7gSc+ZJ9cy4EHrEsW7PV8s1w18hIEsmcA1YgkKg== + dependencies: + "@docusaurus/core" "2.2.0" + "@docusaurus/logger" "2.2.0" + "@docusaurus/types" "2.2.0" + "@docusaurus/utils" "2.2.0" + "@docusaurus/utils-common" "2.2.0" + "@docusaurus/utils-validation" "2.2.0" + fs-extra "^10.1.0" + sitemap "^7.1.1" + tslib "^2.4.0" + +"@docusaurus/preset-classic@^2.0.0-beta": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@docusaurus/preset-classic/-/preset-classic-2.2.0.tgz#bece5a043eeb74430f7c6c7510000b9c43669eb7" + integrity sha512-yKIWPGNx7BT8v2wjFIWvYrS+nvN04W+UameSFf8lEiJk6pss0kL6SG2MRvyULiI3BDxH+tj6qe02ncpSPGwumg== + dependencies: + "@docusaurus/core" "2.2.0" + "@docusaurus/plugin-content-blog" "2.2.0" + "@docusaurus/plugin-content-docs" "2.2.0" + "@docusaurus/plugin-content-pages" "2.2.0" + "@docusaurus/plugin-debug" "2.2.0" + "@docusaurus/plugin-google-analytics" "2.2.0" + "@docusaurus/plugin-google-gtag" "2.2.0" + "@docusaurus/plugin-sitemap" "2.2.0" + "@docusaurus/theme-classic" "2.2.0" + "@docusaurus/theme-common" "2.2.0" + "@docusaurus/theme-search-algolia" "2.2.0" + "@docusaurus/types" "2.2.0" "@docusaurus/react-loadable@5.5.2", "react-loadable@npm:@docusaurus/react-loadable@5.5.2": version "5.5.2" @@ -1407,122 +1458,144 @@ "@types/react" "*" prop-types "^15.6.2" -"@docusaurus/theme-classic@2.0.0-beta.9": - version "2.0.0-beta.9" - resolved "https://registry.yarnpkg.com/@docusaurus/theme-classic/-/theme-classic-2.0.0-beta.9.tgz#d4d246c295e91938bb4ae9745104e352bc5dfe94" - integrity sha512-vTijCGrkFkaqzpOu7w1AaXOBFOo6wirkNEN0+TMkx3oTu95Yj7h98rt/9Z60f6L9HVjOFQ18h3fU6cWloNG+Bg== - dependencies: - "@docusaurus/core" "2.0.0-beta.9" - "@docusaurus/plugin-content-blog" "2.0.0-beta.9" - "@docusaurus/plugin-content-docs" "2.0.0-beta.9" - "@docusaurus/plugin-content-pages" "2.0.0-beta.9" - "@docusaurus/theme-common" "2.0.0-beta.9" - "@docusaurus/types" "2.0.0-beta.9" - "@docusaurus/utils" "2.0.0-beta.9" - "@docusaurus/utils-common" "2.0.0-beta.9" - "@docusaurus/utils-validation" "2.0.0-beta.9" - "@mdx-js/mdx" "^1.6.21" - "@mdx-js/react" "^1.6.21" - chalk "^4.1.2" - clsx "^1.1.1" +"@docusaurus/theme-classic@2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@docusaurus/theme-classic/-/theme-classic-2.2.0.tgz#a048bb1bc077dee74b28bec25f4b84b481863742" + integrity sha512-kjbg/qJPwZ6H1CU/i9d4l/LcFgnuzeiGgMQlt6yPqKo0SOJIBMPuz7Rnu3r/WWbZFPi//o8acclacOzmXdUUEg== + dependencies: + "@docusaurus/core" "2.2.0" + "@docusaurus/mdx-loader" "2.2.0" + "@docusaurus/module-type-aliases" "2.2.0" + "@docusaurus/plugin-content-blog" "2.2.0" + "@docusaurus/plugin-content-docs" "2.2.0" + "@docusaurus/plugin-content-pages" "2.2.0" + "@docusaurus/theme-common" "2.2.0" + "@docusaurus/theme-translations" "2.2.0" + "@docusaurus/types" "2.2.0" + "@docusaurus/utils" "2.2.0" + "@docusaurus/utils-common" "2.2.0" + "@docusaurus/utils-validation" "2.2.0" + "@mdx-js/react" "^1.6.22" + clsx "^1.2.1" copy-text-to-clipboard "^3.0.1" - fs-extra "^10.0.0" - globby "^11.0.2" - infima "0.2.0-alpha.34" - lodash "^4.17.20" + infima "0.2.0-alpha.42" + lodash "^4.17.21" + nprogress "^0.2.0" + postcss "^8.4.14" + prism-react-renderer "^1.3.5" + prismjs "^1.28.0" + react-router-dom "^5.3.3" + rtlcss "^3.5.0" + tslib "^2.4.0" + utility-types "^3.10.0" + +"@docusaurus/theme-common@2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@docusaurus/theme-common/-/theme-common-2.2.0.tgz#2303498d80448aafdd588b597ce9d6f4cfa930e4" + integrity sha512-R8BnDjYoN90DCL75gP7qYQfSjyitXuP9TdzgsKDmSFPNyrdE3twtPNa2dIN+h+p/pr+PagfxwWbd6dn722A1Dw== + dependencies: + "@docusaurus/mdx-loader" "2.2.0" + "@docusaurus/module-type-aliases" "2.2.0" + "@docusaurus/plugin-content-blog" "2.2.0" + "@docusaurus/plugin-content-docs" "2.2.0" + "@docusaurus/plugin-content-pages" "2.2.0" + "@docusaurus/utils" "2.2.0" + "@types/history" "^4.7.11" + "@types/react" "*" + "@types/react-router-config" "*" + clsx "^1.2.1" parse-numeric-range "^1.3.0" - postcss "^8.3.7" - prism-react-renderer "^1.2.1" - prismjs "^1.23.0" - prop-types "^15.7.2" - react-router-dom "^5.2.0" - rtlcss "^3.3.0" - -"@docusaurus/theme-common@2.0.0-beta.9": - version "2.0.0-beta.9" - resolved "https://registry.yarnpkg.com/@docusaurus/theme-common/-/theme-common-2.0.0-beta.9.tgz#a2bd5eb242baa38b110a191126f9054740267925" - integrity sha512-ZsFP+wH1CY6SBqkBGAdj9kHZHkV/7Y77Jw0rnEVbVU4zX2Jh6apWRCOJVaPrroDES8/9D6WWKQgQifeoJ2EeIA== - dependencies: - "@docusaurus/core" "2.0.0-beta.9" - "@docusaurus/plugin-content-blog" "2.0.0-beta.9" - "@docusaurus/plugin-content-docs" "2.0.0-beta.9" - "@docusaurus/plugin-content-pages" "2.0.0-beta.9" - "@docusaurus/types" "2.0.0-beta.9" - clsx "^1.1.1" - fs-extra "^10.0.0" - tslib "^2.3.1" + prism-react-renderer "^1.3.5" + tslib "^2.4.0" utility-types "^3.10.0" -"@docusaurus/theme-search-algolia@2.0.0-beta.9": - version "2.0.0-beta.9" - resolved "https://registry.yarnpkg.com/@docusaurus/theme-search-algolia/-/theme-search-algolia-2.0.0-beta.9.tgz#ccece22535b91e83757c21d895817c5f577fcc36" - integrity sha512-pbpA18kqr5H7A7snmHf4dzMYV+3nsTDYMhV9f2Tms7yP9cxW7ZMHJwaEKXh1myE58Nbkv84AF734TR1UgYrziw== - dependencies: - "@docsearch/react" "^3.0.0-alpha.39" - "@docusaurus/core" "2.0.0-beta.9" - "@docusaurus/theme-common" "2.0.0-beta.9" - "@docusaurus/utils" "2.0.0-beta.9" - "@docusaurus/utils-validation" "2.0.0-beta.9" - algoliasearch "^4.10.5" - algoliasearch-helper "^3.5.5" - clsx "^1.1.1" +"@docusaurus/theme-search-algolia@2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@docusaurus/theme-search-algolia/-/theme-search-algolia-2.2.0.tgz#77fd9f7a600917e6024fe3ac7fb6cfdf2ce84737" + integrity sha512-2h38B0tqlxgR2FZ9LpAkGrpDWVdXZ7vltfmTdX+4RsDs3A7khiNsmZB+x/x6sA4+G2V2CvrsPMlsYBy5X+cY1w== + dependencies: + "@docsearch/react" "^3.1.1" + "@docusaurus/core" "2.2.0" + "@docusaurus/logger" "2.2.0" + "@docusaurus/plugin-content-docs" "2.2.0" + "@docusaurus/theme-common" "2.2.0" + "@docusaurus/theme-translations" "2.2.0" + "@docusaurus/utils" "2.2.0" + "@docusaurus/utils-validation" "2.2.0" + algoliasearch "^4.13.1" + algoliasearch-helper "^3.10.0" + clsx "^1.2.1" eta "^1.12.3" - lodash "^4.17.20" + fs-extra "^10.1.0" + lodash "^4.17.21" + tslib "^2.4.0" + utility-types "^3.10.0" + +"@docusaurus/theme-translations@2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@docusaurus/theme-translations/-/theme-translations-2.2.0.tgz#5fbd4693679806f80c26eeae1381e1f2c23d83e7" + integrity sha512-3T140AG11OjJrtKlY4pMZ5BzbGRDjNs2co5hJ6uYJG1bVWlhcaFGqkaZ5lCgKflaNHD7UHBHU9Ec5f69jTdd6w== + dependencies: + fs-extra "^10.1.0" + tslib "^2.4.0" -"@docusaurus/types@2.0.0-beta.9": - version "2.0.0-beta.9" - resolved "https://registry.yarnpkg.com/@docusaurus/types/-/types-2.0.0-beta.9.tgz#3561a0e3ce9bcb0892d02a025161bb854a189d10" - integrity sha512-7qK7PCwRImHzv9RMi5HJ7RoHKQ8r7oqZK79UucmzBXl5nyfZridBC7JQ+LG7GBqYVaIjfOHUflOOLIVn+gK2/g== +"@docusaurus/types@2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@docusaurus/types/-/types-2.2.0.tgz#02c577a4041ab7d058a3c214ccb13647e21a9857" + integrity sha512-b6xxyoexfbRNRI8gjblzVOnLr4peCJhGbYGPpJ3LFqpi5nsFfoK4mmDLvWdeah0B7gmJeXabN7nQkFoqeSdmOw== dependencies: + "@types/history" "^4.7.11" + "@types/react" "*" commander "^5.1.0" - joi "^17.4.2" - querystring "0.2.0" + joi "^17.6.0" + react-helmet-async "^1.3.0" utility-types "^3.10.0" - webpack "^5.61.0" + webpack "^5.73.0" webpack-merge "^5.8.0" -"@docusaurus/utils-common@2.0.0-beta.9": - version "2.0.0-beta.9" - resolved "https://registry.yarnpkg.com/@docusaurus/utils-common/-/utils-common-2.0.0-beta.9.tgz#3c61db4dd87b4644266e9c240024049cd991f338" - integrity sha512-ftVRifnVXW9eQjwOSuTzhEb9P55KSVfqEbQHgUlMm8KYXHC4NNdn4V+9sHmdJ8rDWNU+PA/+FMjGxWLVejMkxg== +"@docusaurus/utils-common@2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@docusaurus/utils-common/-/utils-common-2.2.0.tgz#a401c1b93a8697dd566baf6ac64f0fdff1641a78" + integrity sha512-qebnerHp+cyovdUseDQyYFvMW1n1nv61zGe5JJfoNQUnjKuApch3IVsz+/lZ9a38pId8kqehC1Ao2bW/s0ntDA== dependencies: - "@docusaurus/types" "2.0.0-beta.9" - tslib "^2.3.1" + tslib "^2.4.0" -"@docusaurus/utils-validation@2.0.0-beta.9": - version "2.0.0-beta.9" - resolved "https://registry.yarnpkg.com/@docusaurus/utils-validation/-/utils-validation-2.0.0-beta.9.tgz#7a4e4ab29627b618a784e8b59fbe4b4bab736594" - integrity sha512-8XZ2wdg+HPSVqgFzhfvntPLwX0+sCypvODatXR8A3YUraZYqQU0NK7SLqD1epLpmHjT/bztSq5DydoGoFRJdIA== +"@docusaurus/utils-validation@2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@docusaurus/utils-validation/-/utils-validation-2.2.0.tgz#04d4d103137ad0145883971d3aa497f4a1315f25" + integrity sha512-I1hcsG3yoCkasOL5qQAYAfnmVoLei7apugT6m4crQjmDGxq+UkiRrq55UqmDDyZlac/6ax/JC0p+usZ6W4nVyg== dependencies: - "@docusaurus/utils" "2.0.0-beta.9" - chalk "^4.1.2" - joi "^17.4.2" - tslib "^2.3.1" + "@docusaurus/logger" "2.2.0" + "@docusaurus/utils" "2.2.0" + joi "^17.6.0" + js-yaml "^4.1.0" + tslib "^2.4.0" -"@docusaurus/utils@2.0.0-beta.9": - version "2.0.0-beta.9" - resolved "https://registry.yarnpkg.com/@docusaurus/utils/-/utils-2.0.0-beta.9.tgz#b9d2b5e2baaed94b5041288fa759438e0164c408" - integrity sha512-f5TUY72Qux0wv1tjxsvjFDjfRnsWtQjsjR5Q/gJ5V021H9lycC9YCk0cEReg3bI3+IVL2iGvQqNnH3R1G7NcRw== +"@docusaurus/utils@2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@docusaurus/utils/-/utils-2.2.0.tgz#3d6f9b7a69168d5c92d371bf21c556a4f50d1da6" + integrity sha512-oNk3cjvx7Tt1Lgh/aeZAmFpGV2pDr5nHKrBVx6hTkzGhrnMuQqLt6UPlQjdYQ3QHXwyF/ZtZMO1D5Pfi0lu7SA== dependencies: - "@docusaurus/types" "2.0.0-beta.9" - "@mdx-js/runtime" "^1.6.22" - "@types/github-slugger" "^1.3.0" - chalk "^4.1.2" - escape-string-regexp "^4.0.0" - fs-extra "^10.0.0" - globby "^11.0.4" + "@docusaurus/logger" "2.2.0" + "@svgr/webpack" "^6.2.1" + file-loader "^6.2.0" + fs-extra "^10.1.0" + github-slugger "^1.4.0" + globby "^11.1.0" gray-matter "^4.0.3" - lodash "^4.17.20" - micromatch "^4.0.4" - remark-mdx-remove-exports "^1.6.22" - remark-mdx-remove-imports "^1.6.22" + js-yaml "^4.1.0" + lodash "^4.17.21" + micromatch "^4.0.5" resolve-pathname "^3.0.0" - tslib "^2.3.1" + shelljs "^0.8.5" + tslib "^2.4.0" + url-loader "^4.1.1" + webpack "^5.73.0" "@hapi/hoek@^9.0.0": - version "9.2.1" - resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.2.1.tgz#9551142a1980503752536b5050fd99f4a7f13b17" - integrity sha512-gfta+H8aziZsm8pZa0vj04KO6biEiisppNgA1kbJvFrrWu9Vm7eaUEy76DIxsuTaWvti5fkJVhllWc6ZTE+Mdw== + version "9.3.0" + resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-9.3.0.tgz#8368869dcb735be2e7f5cb7647de78e167a251fb" + integrity sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ== "@hapi/topo@^5.0.0": version "5.1.0" @@ -1531,7 +1604,79 @@ dependencies: "@hapi/hoek" "^9.0.0" -"@mdx-js/mdx@1.6.22", "@mdx-js/mdx@^1.6.21": +"@jest/schemas@^29.0.0": + version "29.0.0" + resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.0.0.tgz#5f47f5994dd4ef067fb7b4188ceac45f77fe952a" + integrity sha512-3Ab5HgYIIAnS0HjqJHQYZS+zXc4tUmTmBH3z83ajI6afXp8X3ZtdLX+nXx+I7LNkJD7uN9LAVhgnjDgZa2z0kA== + dependencies: + "@sinclair/typebox" "^0.24.1" + +"@jest/types@^29.3.1": + version "29.3.1" + resolved "https://registry.yarnpkg.com/@jest/types/-/types-29.3.1.tgz#7c5a80777cb13e703aeec6788d044150341147e3" + integrity sha512-d0S0jmmTpjnhCmNpApgX3jrUZgZ22ivKJRvL2lli5hpCRoNnp1f85r2/wpKfXuYu8E7Jjh1hGfhPyup1NM5AmA== + dependencies: + "@jest/schemas" "^29.0.0" + "@types/istanbul-lib-coverage" "^2.0.0" + "@types/istanbul-reports" "^3.0.0" + "@types/node" "*" + "@types/yargs" "^17.0.8" + chalk "^4.0.0" + +"@jridgewell/gen-mapping@^0.1.0": + version "0.1.1" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz#e5d2e450306a9491e3bd77e323e38d7aff315996" + integrity sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w== + dependencies: + "@jridgewell/set-array" "^1.0.0" + "@jridgewell/sourcemap-codec" "^1.4.10" + +"@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2": + version "0.3.2" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9" + integrity sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A== + dependencies: + "@jridgewell/set-array" "^1.0.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.9" + +"@jridgewell/resolve-uri@3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" + integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== + +"@jridgewell/set-array@^1.0.0", "@jridgewell/set-array@^1.0.1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" + integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== + +"@jridgewell/source-map@^0.3.2": + version "0.3.2" + resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.2.tgz#f45351aaed4527a298512ec72f81040c998580fb" + integrity sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw== + dependencies: + "@jridgewell/gen-mapping" "^0.3.0" + "@jridgewell/trace-mapping" "^0.3.9" + +"@jridgewell/sourcemap-codec@1.4.14", "@jridgewell/sourcemap-codec@^1.4.10": + version "1.4.14" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" + integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== + +"@jridgewell/trace-mapping@^0.3.14", "@jridgewell/trace-mapping@^0.3.9": + version "0.3.17" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz#793041277af9073b0951a7fe0f0d8c4c98c36985" + integrity sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g== + dependencies: + "@jridgewell/resolve-uri" "3.1.0" + "@jridgewell/sourcemap-codec" "1.4.14" + +"@leichtgewicht/ip-codec@^2.0.1": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz#b2ac626d6cb9c8718ab459166d4bb405b8ffa78b" + integrity sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A== + +"@mdx-js/mdx@^1.6.22": version "1.6.22" resolved "https://registry.yarnpkg.com/@mdx-js/mdx/-/mdx-1.6.22.tgz#8a723157bf90e78f17dc0f27995398e6c731f1ba" integrity sha512-AMxuLxPz2j5/6TpF/XSdKpQP1NlG0z11dFOlq+2IP/lSgl11GY8ji6S/rgsViN/L0BDvHvUMruRb7ub+24LUYA== @@ -1556,20 +1701,11 @@ unist-builder "2.0.3" unist-util-visit "2.0.3" -"@mdx-js/react@1.6.22", "@mdx-js/react@^1.6.21": +"@mdx-js/react@^1.6.22": version "1.6.22" resolved "https://registry.yarnpkg.com/@mdx-js/react/-/react-1.6.22.tgz#ae09b4744fddc74714ee9f9d6f17a66e77c43573" integrity sha512-TDoPum4SHdfPiGSAaRBw7ECyI8VaHpK8GJugbJIJuqyh6kzw9ZLJZW3HGL3NNrJGxcAixUvqROm+YuQOo5eXtg== -"@mdx-js/runtime@^1.6.22": - version "1.6.22" - resolved "https://registry.yarnpkg.com/@mdx-js/runtime/-/runtime-1.6.22.tgz#3edd388bf68a519ffa1aaf9c446b548165102345" - integrity sha512-p17spaO2+55VLCuxXA3LVHC4phRx60NR2XMdZ+qgVU1lKvEX4y88dmFNOzGDCPLJ03IZyKrJ/rPWWRiBrd9JrQ== - dependencies: - "@mdx-js/mdx" "1.6.22" - "@mdx-js/react" "1.6.22" - buble-jsx-only "^0.19.8" - "@mdx-js/util@1.6.22": version "1.6.22" resolved "https://registry.yarnpkg.com/@mdx-js/util/-/util-1.6.22.tgz#219dfd89ae5b97a8801f015323ffa4b62f45718b" @@ -1601,10 +1737,10 @@ resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.21.tgz#5de5a2385a35309427f6011992b544514d559aa1" integrity sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g== -"@sideway/address@^4.1.0": - version "4.1.2" - resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.2.tgz#811b84333a335739d3969cfc434736268170cad1" - integrity sha512-idTz8ibqWFrPU8kMirL0CoPH/A29XOzzAzpyN3zQ4kAWnzmNfFmRaoMNN6VI8ske5M73HZyhIaW4OuSFIdM4oA== +"@sideway/address@^4.1.3": + version "4.1.4" + resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.4.tgz#03dccebc6ea47fdc226f7d3d1ad512955d4783f0" + integrity sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw== dependencies: "@hapi/hoek" "^9.0.0" @@ -1618,162 +1754,217 @@ resolved "https://registry.yarnpkg.com/@sideway/pinpoint/-/pinpoint-2.0.0.tgz#cff8ffadc372ad29fd3f78277aeb29e632cc70df" integrity sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ== -"@sindresorhus/is@^0.14.0": - version "0.14.0" - resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" - integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ== - -"@slorber/static-site-generator-webpack-plugin@^4.0.0": - version "4.0.1" - resolved "https://registry.yarnpkg.com/@slorber/static-site-generator-webpack-plugin/-/static-site-generator-webpack-plugin-4.0.1.tgz#0c8852146441aaa683693deaa5aee2f991d94841" - integrity sha512-PSv4RIVO1Y3kvHxjvqeVisk3E9XFoO04uwYBDWe217MFqKspplYswTuKLiJu0aLORQWzuQjfVsSlLPojwfYsLw== - dependencies: - bluebird "^3.7.1" - cheerio "^0.22.0" - eval "^0.1.4" - url "^0.11.0" - webpack-sources "^1.4.3" - -"@svgr/babel-plugin-add-jsx-attribute@^5.4.0": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-5.4.0.tgz#81ef61947bb268eb9d50523446f9c638fb355906" - integrity sha512-ZFf2gs/8/6B8PnSofI0inYXr2SDNTDScPXhN7k5EqD4aZ3gi6u+rbmZHVB8IM3wDyx8ntKACZbtXSm7oZGRqVg== - -"@svgr/babel-plugin-remove-jsx-attribute@^5.4.0": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-5.4.0.tgz#6b2c770c95c874654fd5e1d5ef475b78a0a962ef" - integrity sha512-yaS4o2PgUtwLFGTKbsiAy6D0o3ugcUhWK0Z45umJ66EPWunAz9fuFw2gJuje6wqQvQWOTJvIahUwndOXb7QCPg== - -"@svgr/babel-plugin-remove-jsx-empty-expression@^5.0.1": - version "5.0.1" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-5.0.1.tgz#25621a8915ed7ad70da6cea3d0a6dbc2ea933efd" - integrity sha512-LA72+88A11ND/yFIMzyuLRSMJ+tRKeYKeQ+mR3DcAZ5I4h5CPWN9AHyUzJbWSYp/u2u0xhmgOe0+E41+GjEueA== +"@sinclair/typebox@^0.24.1": + version "0.24.51" + resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.24.51.tgz#645f33fe4e02defe26f2f5c0410e1c094eac7f5f" + integrity sha512-1P1OROm/rdubP5aFDSZQILU0vrLCJ4fvHt6EoqHEM+2D/G5MK3bIaymUKLit8Js9gbns5UyJnkP/TZROLw4tUA== -"@svgr/babel-plugin-replace-jsx-attribute-value@^5.0.1": - version "5.0.1" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-5.0.1.tgz#0b221fc57f9fcd10e91fe219e2cd0dd03145a897" - integrity sha512-PoiE6ZD2Eiy5mK+fjHqwGOS+IXX0wq/YDtNyIgOrc6ejFnxN4b13pRpiIPbtPwHEc+NT2KCjteAcq33/F1Y9KQ== - -"@svgr/babel-plugin-svg-dynamic-title@^5.4.0": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-5.4.0.tgz#139b546dd0c3186b6e5db4fefc26cb0baea729d7" - integrity sha512-zSOZH8PdZOpuG1ZVx/cLVePB2ibo3WPpqo7gFIjLV9a0QsuQAzJiwwqmuEdTaW2pegyBE17Uu15mOgOcgabQZg== +"@sindresorhus/is@^5.2.0": + version "5.3.0" + resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-5.3.0.tgz#0ec9264cf54a527671d990eb874e030b55b70dcc" + integrity sha512-CX6t4SYQ37lzxicAqsBtxA3OseeoVrh9cSJ5PFYam0GksYlupRfy1A+Q4aYD3zvcfECLc0zO2u+ZnR2UYKvCrw== -"@svgr/babel-plugin-svg-em-dimensions@^5.4.0": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-5.4.0.tgz#6543f69526632a133ce5cabab965deeaea2234a0" - integrity sha512-cPzDbDA5oT/sPXDCUYoVXEmm3VIoAWAPT6mSPTJNbQaBNUuEKVKyGH93oDY4e42PYHRW67N5alJx/eEol20abw== +"@slorber/static-site-generator-webpack-plugin@^4.0.7": + version "4.0.7" + resolved "https://registry.yarnpkg.com/@slorber/static-site-generator-webpack-plugin/-/static-site-generator-webpack-plugin-4.0.7.tgz#fc1678bddefab014e2145cbe25b3ce4e1cfc36f3" + integrity sha512-Ug7x6z5lwrz0WqdnNFOMYrDQNTPAprvHLSh6+/fmml3qUiz6l5eq+2MzLKWtn/q5K5NpSiFsZTP/fck/3vjSxA== + dependencies: + eval "^0.1.8" + p-map "^4.0.0" + webpack-sources "^3.2.2" -"@svgr/babel-plugin-transform-react-native-svg@^5.4.0": - version "5.4.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-5.4.0.tgz#00bf9a7a73f1cad3948cdab1f8dfb774750f8c80" - integrity sha512-3eYP/SaopZ41GHwXma7Rmxcv9uRslRDTY1estspeB1w1ueZWd/tPlMfEOoccYpEMZU3jD4OU7YitnXcF5hLW2Q== +"@svgr/babel-plugin-add-jsx-attribute@^6.5.1": + version "6.5.1" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-6.5.1.tgz#74a5d648bd0347bda99d82409d87b8ca80b9a1ba" + integrity sha512-9PYGcXrAxitycIjRmZB+Q0JaN07GZIWaTBIGQzfaZv+qr1n8X1XUEJ5rZ/vx6OVD9RRYlrNnXWExQXcmZeD/BQ== -"@svgr/babel-plugin-transform-svg-component@^5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-5.5.0.tgz#583a5e2a193e214da2f3afeb0b9e8d3250126b4a" - integrity sha512-q4jSH1UUvbrsOtlo/tKcgSeiCHRSBdXoIoqX1pgcKK/aU3JD27wmMKwGtpB8qRYUYoyXvfGxUVKchLuR5pB3rQ== +"@svgr/babel-plugin-remove-jsx-attribute@*": + version "6.5.0" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-6.5.0.tgz#652bfd4ed0a0699843585cda96faeb09d6e1306e" + integrity sha512-8zYdkym7qNyfXpWvu4yq46k41pyNM9SOstoWhKlm+IfdCE1DdnRKeMUPsWIEO/DEkaWxJ8T9esNdG3QwQ93jBA== -"@svgr/babel-preset@^5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-preset/-/babel-preset-5.5.0.tgz#8af54f3e0a8add7b1e2b0fcd5a882c55393df327" - integrity sha512-4FiXBjvQ+z2j7yASeGPEi8VD/5rrGQk4Xrq3EdJmoZgz/tpqChpo5hgXDvmEauwtvOc52q8ghhZK4Oy7qph4ig== - dependencies: - "@svgr/babel-plugin-add-jsx-attribute" "^5.4.0" - "@svgr/babel-plugin-remove-jsx-attribute" "^5.4.0" - "@svgr/babel-plugin-remove-jsx-empty-expression" "^5.0.1" - "@svgr/babel-plugin-replace-jsx-attribute-value" "^5.0.1" - "@svgr/babel-plugin-svg-dynamic-title" "^5.4.0" - "@svgr/babel-plugin-svg-em-dimensions" "^5.4.0" - "@svgr/babel-plugin-transform-react-native-svg" "^5.4.0" - "@svgr/babel-plugin-transform-svg-component" "^5.5.0" - -"@svgr/core@^5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@svgr/core/-/core-5.5.0.tgz#82e826b8715d71083120fe8f2492ec7d7874a579" - integrity sha512-q52VOcsJPvV3jO1wkPtzTuKlvX7Y3xIcWRpCMtBF3MrteZJtBfQw/+u0B1BHy5ColpQc1/YVTrPEtSYIMNZlrQ== - dependencies: - "@svgr/plugin-jsx" "^5.5.0" +"@svgr/babel-plugin-remove-jsx-empty-expression@*": + version "6.5.0" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-6.5.0.tgz#4b78994ab7d39032c729903fc2dd5c0fa4565cb8" + integrity sha512-NFdxMq3xA42Kb1UbzCVxplUc0iqSyM9X8kopImvFnB+uSDdzIHOdbs1op8ofAvVRtbg4oZiyRl3fTYeKcOe9Iw== + +"@svgr/babel-plugin-replace-jsx-attribute-value@^6.5.1": + version "6.5.1" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-6.5.1.tgz#fb9d22ea26d2bc5e0a44b763d4c46d5d3f596c60" + integrity sha512-8DPaVVE3fd5JKuIC29dqyMB54sA6mfgki2H2+swh+zNJoynC8pMPzOkidqHOSc6Wj032fhl8Z0TVn1GiPpAiJg== + +"@svgr/babel-plugin-svg-dynamic-title@^6.5.1": + version "6.5.1" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-6.5.1.tgz#01b2024a2b53ffaa5efceaa0bf3e1d5a4c520ce4" + integrity sha512-FwOEi0Il72iAzlkaHrlemVurgSQRDFbk0OC8dSvD5fSBPHltNh7JtLsxmZUhjYBZo2PpcU/RJvvi6Q0l7O7ogw== + +"@svgr/babel-plugin-svg-em-dimensions@^6.5.1": + version "6.5.1" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-6.5.1.tgz#dd3fa9f5b24eb4f93bcf121c3d40ff5facecb217" + integrity sha512-gWGsiwjb4tw+ITOJ86ndY/DZZ6cuXMNE/SjcDRg+HLuCmwpcjOktwRF9WgAiycTqJD/QXqL2f8IzE2Rzh7aVXA== + +"@svgr/babel-plugin-transform-react-native-svg@^6.5.1": + version "6.5.1" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-6.5.1.tgz#1d8e945a03df65b601551097d8f5e34351d3d305" + integrity sha512-2jT3nTayyYP7kI6aGutkyfJ7UMGtuguD72OjeGLwVNyfPRBD8zQthlvL+fAbAKk5n9ZNcvFkp/b1lZ7VsYqVJg== + +"@svgr/babel-plugin-transform-svg-component@^6.5.1": + version "6.5.1" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-6.5.1.tgz#48620b9e590e25ff95a80f811544218d27f8a250" + integrity sha512-a1p6LF5Jt33O3rZoVRBqdxL350oge54iZWHNI6LJB5tQ7EelvD/Mb1mfBiZNAan0dt4i3VArkFRjA4iObuNykQ== + +"@svgr/babel-preset@^6.5.1": + version "6.5.1" + resolved "https://registry.yarnpkg.com/@svgr/babel-preset/-/babel-preset-6.5.1.tgz#b90de7979c8843c5c580c7e2ec71f024b49eb828" + integrity sha512-6127fvO/FF2oi5EzSQOAjo1LE3OtNVh11R+/8FXa+mHx1ptAaS4cknIjnUA7e6j6fwGGJ17NzaTJFUwOV2zwCw== + dependencies: + "@svgr/babel-plugin-add-jsx-attribute" "^6.5.1" + "@svgr/babel-plugin-remove-jsx-attribute" "*" + "@svgr/babel-plugin-remove-jsx-empty-expression" "*" + "@svgr/babel-plugin-replace-jsx-attribute-value" "^6.5.1" + "@svgr/babel-plugin-svg-dynamic-title" "^6.5.1" + "@svgr/babel-plugin-svg-em-dimensions" "^6.5.1" + "@svgr/babel-plugin-transform-react-native-svg" "^6.5.1" + "@svgr/babel-plugin-transform-svg-component" "^6.5.1" + +"@svgr/core@^6.5.1": + version "6.5.1" + resolved "https://registry.yarnpkg.com/@svgr/core/-/core-6.5.1.tgz#d3e8aa9dbe3fbd747f9ee4282c1c77a27410488a" + integrity sha512-/xdLSWxK5QkqG524ONSjvg3V/FkNyCv538OIBdQqPNaAta3AsXj/Bd2FbvR87yMbXO2hFSWiAe/Q6IkVPDw+mw== + dependencies: + "@babel/core" "^7.19.6" + "@svgr/babel-preset" "^6.5.1" + "@svgr/plugin-jsx" "^6.5.1" camelcase "^6.2.0" - cosmiconfig "^7.0.0" + cosmiconfig "^7.0.1" -"@svgr/hast-util-to-babel-ast@^5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-5.5.0.tgz#5ee52a9c2533f73e63f8f22b779f93cd432a5461" - integrity sha512-cAaR/CAiZRB8GP32N+1jocovUtvlj0+e65TB50/6Lcime+EA49m/8l+P2ko+XPJ4dw3xaPS3jOL4F2X4KWxoeQ== +"@svgr/hast-util-to-babel-ast@^6.5.1": + version "6.5.1" + resolved "https://registry.yarnpkg.com/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-6.5.1.tgz#81800bd09b5bcdb968bf6ee7c863d2288fdb80d2" + integrity sha512-1hnUxxjd83EAxbL4a0JDJoD3Dao3hmjvyvyEV8PzWmLK3B9m9NPlW7GKjFyoWE8nM7HnXzPcmmSyOW8yOddSXw== dependencies: - "@babel/types" "^7.12.6" + "@babel/types" "^7.20.0" + entities "^4.4.0" -"@svgr/plugin-jsx@^5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@svgr/plugin-jsx/-/plugin-jsx-5.5.0.tgz#1aa8cd798a1db7173ac043466d7b52236b369000" - integrity sha512-V/wVh33j12hGh05IDg8GpIUXbjAPnTdPTKuP4VNLggnwaHMPNQNae2pRnyTAILWCQdz5GyMqtO488g7CKM8CBA== +"@svgr/plugin-jsx@^6.5.1": + version "6.5.1" + resolved "https://registry.yarnpkg.com/@svgr/plugin-jsx/-/plugin-jsx-6.5.1.tgz#0e30d1878e771ca753c94e69581c7971542a7072" + integrity sha512-+UdQxI3jgtSjCykNSlEMuy1jSRQlGC7pqBCPvkG/2dATdWo082zHTTK3uhnAju2/6XpE6B5mZ3z4Z8Ns01S8Gw== dependencies: - "@babel/core" "^7.12.3" - "@svgr/babel-preset" "^5.5.0" - "@svgr/hast-util-to-babel-ast" "^5.5.0" - svg-parser "^2.0.2" + "@babel/core" "^7.19.6" + "@svgr/babel-preset" "^6.5.1" + "@svgr/hast-util-to-babel-ast" "^6.5.1" + svg-parser "^2.0.4" -"@svgr/plugin-svgo@^5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@svgr/plugin-svgo/-/plugin-svgo-5.5.0.tgz#02da55d85320549324e201c7b2e53bf431fcc246" - integrity sha512-r5swKk46GuQl4RrVejVwpeeJaydoxkdwkM1mBKOgJLBUJPGaLci6ylg/IjhrRsREKDkr4kbMWdgOtbXEh0fyLQ== +"@svgr/plugin-svgo@^6.5.1": + version "6.5.1" + resolved "https://registry.yarnpkg.com/@svgr/plugin-svgo/-/plugin-svgo-6.5.1.tgz#0f91910e988fc0b842f88e0960c2862e022abe84" + integrity sha512-omvZKf8ixP9z6GWgwbtmP9qQMPX4ODXi+wzbVZgomNFsUIlHA1sf4fThdwTWSsZGgvGAG6yE+b/F5gWUkcZ/iQ== dependencies: - cosmiconfig "^7.0.0" + cosmiconfig "^7.0.1" deepmerge "^4.2.2" - svgo "^1.2.2" - -"@svgr/webpack@^5.5.0": - version "5.5.0" - resolved "https://registry.yarnpkg.com/@svgr/webpack/-/webpack-5.5.0.tgz#aae858ee579f5fa8ce6c3166ef56c6a1b381b640" - integrity sha512-DOBOK255wfQxguUta2INKkzPj6AIS6iafZYiYmHn6W3pHlycSRRlvWKCfLDG10fXfLWqE3DJHgRUOyJYmARa7g== - dependencies: - "@babel/core" "^7.12.3" - "@babel/plugin-transform-react-constant-elements" "^7.12.1" - "@babel/preset-env" "^7.12.1" - "@babel/preset-react" "^7.12.5" - "@svgr/core" "^5.5.0" - "@svgr/plugin-jsx" "^5.5.0" - "@svgr/plugin-svgo" "^5.5.0" - loader-utils "^2.0.0" - -"@szmarczak/http-timer@^1.1.2": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421" - integrity sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA== + svgo "^2.8.0" + +"@svgr/webpack@^6.2.1": + version "6.5.1" + resolved "https://registry.yarnpkg.com/@svgr/webpack/-/webpack-6.5.1.tgz#ecf027814fc1cb2decc29dc92f39c3cf691e40e8" + integrity sha512-cQ/AsnBkXPkEK8cLbv4Dm7JGXq2XrumKnL1dRpJD9rIO2fTIlJI9a1uCciYG1F2aUsox/hJQyNGbt3soDxSRkA== + dependencies: + "@babel/core" "^7.19.6" + "@babel/plugin-transform-react-constant-elements" "^7.18.12" + "@babel/preset-env" "^7.19.4" + "@babel/preset-react" "^7.18.6" + "@babel/preset-typescript" "^7.18.6" + "@svgr/core" "^6.5.1" + "@svgr/plugin-jsx" "^6.5.1" + "@svgr/plugin-svgo" "^6.5.1" + +"@szmarczak/http-timer@^5.0.1": + version "5.0.1" + resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-5.0.1.tgz#c7c1bf1141cdd4751b0399c8fc7b8b664cd5be3a" + integrity sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw== dependencies: - defer-to-connect "^1.0.1" + defer-to-connect "^2.0.1" "@trysound/sax@0.2.0": version "0.2.0" resolved "https://registry.yarnpkg.com/@trysound/sax/-/sax-0.2.0.tgz#cccaab758af56761eb7bf37af6f03f326dd798ad" integrity sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA== -"@types/eslint-scope@^3.7.0": - version "3.7.1" - resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.1.tgz#8dc390a7b4f9dd9f1284629efce982e41612116e" - integrity sha512-SCFeogqiptms4Fg29WpOTk5nHIzfpKCemSN63ksBQYKTcXoJEmJagV+DhVmbapZzY4/5YaOV1nZwrsU79fFm1g== +"@types/body-parser@*": + version "1.19.2" + resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.2.tgz#aea2059e28b7658639081347ac4fab3de166e6f0" + integrity sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g== + dependencies: + "@types/connect" "*" + "@types/node" "*" + +"@types/bonjour@^3.5.9": + version "3.5.10" + resolved "https://registry.yarnpkg.com/@types/bonjour/-/bonjour-3.5.10.tgz#0f6aadfe00ea414edc86f5d106357cda9701e275" + integrity sha512-p7ienRMiS41Nu2/igbJxxLDWrSZ0WxM8UQgCeO9KhoVF7cOVFkrKsiDr1EsJIla8vV3oEEjGcz11jc5yimhzZw== + dependencies: + "@types/node" "*" + +"@types/connect-history-api-fallback@^1.3.5": + version "1.3.5" + resolved "https://registry.yarnpkg.com/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.3.5.tgz#d1f7a8a09d0ed5a57aee5ae9c18ab9b803205dae" + integrity sha512-h8QJa8xSb1WD4fpKBDcATDNGXghFj6/3GRWG6dhmRcu0RX1Ubasur2Uvx5aeEwlf0MwblEC2bMzzMQntxnw/Cw== + dependencies: + "@types/express-serve-static-core" "*" + "@types/node" "*" + +"@types/connect@*": + version "3.4.35" + resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.35.tgz#5fcf6ae445e4021d1fc2219a4873cc73a3bb2ad1" + integrity sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ== + dependencies: + "@types/node" "*" + +"@types/eslint-scope@^3.7.3": + version "3.7.4" + resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.4.tgz#37fc1223f0786c39627068a12e94d6e6fc61de16" + integrity sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA== dependencies: "@types/eslint" "*" "@types/estree" "*" "@types/eslint@*": - version "7.28.2" - resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-7.28.2.tgz#0ff2947cdd305897c52d5372294e8c76f351db68" - integrity sha512-KubbADPkfoU75KgKeKLsFHXnU4ipH7wYg0TRT33NK3N3yiu7jlFAAoygIWBV+KbuHx/G+AvuGX6DllnK35gfJA== + version "8.4.10" + resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.4.10.tgz#19731b9685c19ed1552da7052b6f668ed7eb64bb" + integrity sha512-Sl/HOqN8NKPmhWo2VBEPm0nvHnu2LL3v9vKo8MEq0EtbJ4eVzGPl41VNPvn5E1i5poMk4/XD8UriLHpJvEP/Nw== dependencies: "@types/estree" "*" "@types/json-schema" "*" -"@types/estree@*", "@types/estree@^0.0.50": - version "0.0.50" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.50.tgz#1e0caa9364d3fccd2931c3ed96fdbeaa5d4cca83" - integrity sha512-C6N5s2ZFtuZRj54k2/zyRhNDjJwwcViAM3Nbm8zjBpbqAdZ00mr0CFxvSKeO8Y/e03WVFLpQMdHYVfUd6SB+Hw== +"@types/estree@*": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.0.tgz#5fb2e536c1ae9bf35366eed879e827fa59ca41c2" + integrity sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ== -"@types/github-slugger@^1.3.0": - version "1.3.0" - resolved "https://registry.yarnpkg.com/@types/github-slugger/-/github-slugger-1.3.0.tgz#16ab393b30d8ae2a111ac748a015ac05a1fc5524" - integrity sha512-J/rMZa7RqiH/rT29TEVZO4nBoDP9XJOjnbbIofg7GQKs4JIduEO3WLpte+6WeUz/TcrXKlY+bM7FYrp8yFB+3g== +"@types/estree@^0.0.51": + version "0.0.51" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.51.tgz#cfd70924a25a3fd32b218e5e420e6897e1ac4f40" + integrity sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ== + +"@types/express-serve-static-core@*", "@types/express-serve-static-core@^4.17.18": + version "4.17.31" + resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.31.tgz#a1139efeab4e7323834bb0226e62ac019f474b2f" + integrity sha512-DxMhY+NAsTwMMFHBTtJFNp5qiHKJ7TeqOo23zVEM9alT1Ml27Q3xcTH0xwxn7Q0BbMcVEJOs/7aQtUWupUQN3Q== + dependencies: + "@types/node" "*" + "@types/qs" "*" + "@types/range-parser" "*" + +"@types/express@*", "@types/express@^4.17.13": + version "4.17.14" + resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.14.tgz#143ea0557249bc1b3b54f15db4c81c3d4eb3569c" + integrity sha512-TEbt+vaPFQ+xpxFLFssxUDXj5cWCxZJjIcB7Yg0k0GMHGtgtQgpvx/MUQUeAkNbA9AAGrwkAsoeItdTgS7FMyg== + dependencies: + "@types/body-parser" "*" + "@types/express-serve-static-core" "^4.17.18" + "@types/qs" "*" + "@types/serve-static" "*" "@types/hast@^2.0.0": version "2.3.4" @@ -1782,22 +1973,51 @@ dependencies: "@types/unist" "*" +"@types/history@^4.7.11": + version "4.7.11" + resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.11.tgz#56588b17ae8f50c53983a524fc3cc47437969d64" + integrity sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA== + "@types/html-minifier-terser@^6.0.0": - version "6.0.0" - resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-6.0.0.tgz#563c1c6c132cd204e71512f9c0b394ff90d3fae7" - integrity sha512-NZwaaynfs1oIoLAV1vg18e7QMVDvw+6SQrdJc8w3BwUaoroVSf6EBj/Sk4PBWGxsq0dzhA2drbsuMC1/6C6KgQ== + version "6.1.0" + resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz#4fc33a00c1d0c16987b1a20cf92d20614c55ac35" + integrity sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg== -"@types/http-proxy@^1.17.5": - version "1.17.7" - resolved "https://registry.yarnpkg.com/@types/http-proxy/-/http-proxy-1.17.7.tgz#30ea85cc2c868368352a37f0d0d3581e24834c6f" - integrity sha512-9hdj6iXH64tHSLTY+Vt2eYOGzSogC+JQ2H7bdPWkuh7KXP5qLllWx++t+K9Wk556c3dkDdPws/SpMRi0sdCT1w== +"@types/http-cache-semantics@^4.0.1": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@types/http-cache-semantics/-/http-cache-semantics-4.0.1.tgz#0ea7b61496902b95890dc4c3a116b60cb8dae812" + integrity sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ== + +"@types/http-proxy@^1.17.8": + version "1.17.9" + resolved "https://registry.yarnpkg.com/@types/http-proxy/-/http-proxy-1.17.9.tgz#7f0e7931343761efde1e2bf48c40f02f3f75705a" + integrity sha512-QsbSjA/fSk7xB+UXlCT3wHBy5ai9wOcNDWwZAtud+jXhwOM3l+EYZh8Lng4+/6n8uar0J7xILzqftJdJ/Wdfkw== dependencies: "@types/node" "*" -"@types/json-schema@*", "@types/json-schema@^7.0.4", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8": - version "7.0.9" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d" - integrity sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ== +"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz#8467d4b3c087805d63580480890791277ce35c44" + integrity sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g== + +"@types/istanbul-lib-report@*": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#c14c24f18ea8190c118ee7562b7ff99a36552686" + integrity sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg== + dependencies: + "@types/istanbul-lib-coverage" "*" + +"@types/istanbul-reports@^3.0.0": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz#9153fe98bba2bd565a63add9436d6f0d7f8468ff" + integrity sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw== + dependencies: + "@types/istanbul-lib-report" "*" + +"@types/json-schema@*", "@types/json-schema@^7.0.4", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": + version "7.0.11" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" + integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ== "@types/mdast@^3.0.0": version "3.0.10" @@ -1806,15 +2026,20 @@ dependencies: "@types/unist" "*" +"@types/mime@*": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@types/mime/-/mime-3.0.1.tgz#5f8f2bca0a5863cb69bc0b0acd88c96cb1d4ae10" + integrity sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA== + "@types/node@*": - version "16.11.6" - resolved "https://registry.yarnpkg.com/@types/node/-/node-16.11.6.tgz#6bef7a2a0ad684cf6e90fcfe31cecabd9ce0a3ae" - integrity sha512-ua7PgUoeQFjmWPcoo9khiPum3Pd60k4/2ZGXt18sm2Slk0W0xZTqt5Y0Ny1NyBiN1EVQ/+FaF9NcY4Qe6rwk5w== + version "18.11.9" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.9.tgz#02d013de7058cea16d36168ef2fc653464cfbad4" + integrity sha512-CRpX21/kGdzjOpFsZSkcrXMGIBWMGNIHXXBVFSH+ggkftxg+XYP20TESbh+zFvFj3EQOl5byk0HTRn1IL6hbqg== -"@types/node@^15.0.1": - version "15.14.9" - resolved "https://registry.yarnpkg.com/@types/node/-/node-15.14.9.tgz#bc43c990c3c9be7281868bbc7b8fdd6e2b57adfa" - integrity sha512-qjd88DrCxupx/kJD5yQgZdcYKZKSIGBVDIBE1/LTGcNm3d2Np/jxojkdePDdfnBHJc5W7vSMpbJ1aB7p/Py69A== +"@types/node@^17.0.5": + version "17.0.45" + resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.45.tgz#2c0fafd78705e7a18b7906b5201a522719dc5190" + integrity sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw== "@types/parse-json@^4.0.0": version "4.0.0" @@ -1827,33 +2052,64 @@ integrity sha512-kUNnecmtkunAoQ3CnjmMkzNU/gtxG8guhi+Fk2U/kOpIKjIMKnXGp4IJCgQJrXSgMsWYimYG4TGjz/UzbGEBTw== "@types/prop-types@*": - version "15.7.4" - resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.4.tgz#fcf7205c25dff795ee79af1e30da2c9790808f11" - integrity sha512-rZ5drC/jWjrArrS8BR6SIr4cWpW09RNTYt9AMZo3Jwwif+iacXAqgVjm0B0Bv/S1jhDXKHqRVNCbACkJ89RAnQ== + version "15.7.5" + resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.5.tgz#5f19d2b85a98e9558036f6a3cacc8819420f05cf" + integrity sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w== -"@types/q@^1.5.1": - version "1.5.5" - resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.5.tgz#75a2a8e7d8ab4b230414505d92335d1dcb53a6df" - integrity sha512-L28j2FcJfSZOnL1WBjDYp2vUHCeIFlyYI/53EwD/rKUBQ7MtUUfbQWiyKJGpcnv4/WgrhWsFKrcPstcAt/J0tQ== +"@types/qs@*": + version "6.9.7" + resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb" + integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw== + +"@types/range-parser@*": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.4.tgz#cd667bcfdd025213aafb7ca5915a932590acdcdc" + integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw== + +"@types/react-router-config@*", "@types/react-router-config@^5.0.6": + version "5.0.6" + resolved "https://registry.yarnpkg.com/@types/react-router-config/-/react-router-config-5.0.6.tgz#87c5c57e72d241db900d9734512c50ccec062451" + integrity sha512-db1mx37a1EJDf1XeX8jJN7R3PZABmJQXR8r28yUjVMFSjkmnQo6X6pOEEmNl+Tp2gYQOGPdYbFIipBtdElZ3Yg== + dependencies: + "@types/history" "^4.7.11" + "@types/react" "*" + "@types/react-router" "*" + +"@types/react-router-dom@*": + version "5.3.3" + resolved "https://registry.yarnpkg.com/@types/react-router-dom/-/react-router-dom-5.3.3.tgz#e9d6b4a66fcdbd651a5f106c2656a30088cc1e83" + integrity sha512-kpqnYK4wcdm5UaWI3fLcELopqLrHgLqNsdpHauzlQktfkHL3npOSwtj1Uz9oKBAzs7lFtVkV8j83voAz2D8fhw== + dependencies: + "@types/history" "^4.7.11" + "@types/react" "*" + "@types/react-router" "*" + +"@types/react-router@*": + version "5.1.19" + resolved "https://registry.yarnpkg.com/@types/react-router/-/react-router-5.1.19.tgz#9b404246fba7f91474d7008a3d48c17b6e075ad6" + integrity sha512-Fv/5kb2STAEMT3wHzdKQK2z8xKq38EDIGVrutYLmQVVLe+4orDFquU52hQrULnEHinMKv9FSA6lf9+uNT1ITtA== + dependencies: + "@types/history" "^4.7.11" + "@types/react" "*" "@types/react@*": - version "17.0.34" - resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.34.tgz#797b66d359b692e3f19991b6b07e4b0c706c0102" - integrity sha512-46FEGrMjc2+8XhHXILr+3+/sTe3OfzSPU9YGKILLrUYbQ1CLQC9Daqo1KzENGXAWwrFwiY0l4ZbF20gRvgpWTg== + version "18.0.25" + resolved "https://registry.yarnpkg.com/@types/react/-/react-18.0.25.tgz#8b1dcd7e56fe7315535a4af25435e0bb55c8ae44" + integrity sha512-xD6c0KDT4m7n9uD4ZHi02lzskaiqcBxf4zi+tXZY98a04wvc0hi/TcCPC2FOESZi51Nd7tlUeOJY8RofL799/g== dependencies: "@types/prop-types" "*" "@types/scheduler" "*" csstype "^3.0.2" -"@types/retry@^0.12.0": - version "0.12.1" - resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.1.tgz#d8f1c0d0dc23afad6dc16a9e993a0865774b4065" - integrity sha512-xoDlM2S4ortawSWORYqsdU+2rxdh4LRW9ytc3zmT37RIKQh6IHyKwwtKhKis9ah8ol07DCkZxPt8BBvPjC6v4g== +"@types/retry@0.12.0": + version "0.12.0" + resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.0.tgz#2b35eccfcee7d38cd72ad99232fbd58bffb3c84d" + integrity sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA== "@types/sax@^1.2.1": - version "1.2.3" - resolved "https://registry.yarnpkg.com/@types/sax/-/sax-1.2.3.tgz#b630ac1403ebd7812e0bf9a10de9bf5077afb348" - integrity sha512-+QSw6Tqvs/KQpZX8DvIl3hZSjNFLW/OqE5nlyHXtTwODaJvioN2rOWpBNEWZp2HZUFhOh+VohmJku/WxEXU2XA== + version "1.2.4" + resolved "https://registry.yarnpkg.com/@types/sax/-/sax-1.2.4.tgz#8221affa7f4f3cb21abd22f244cfabfa63e6a69e" + integrity sha512-pSAff4IAxJjfAXUG6tFkO7dsSbTmf8CtUpfhhZ5VhkRpC4628tJhh3+V6H1E+/Gs9piSzYKT5yzHO5M4GG9jkw== dependencies: "@types/node" "*" @@ -1862,11 +2118,52 @@ resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.2.tgz#1a62f89525723dde24ba1b01b092bf5df8ad4d39" integrity sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew== +"@types/serve-index@^1.9.1": + version "1.9.1" + resolved "https://registry.yarnpkg.com/@types/serve-index/-/serve-index-1.9.1.tgz#1b5e85370a192c01ec6cec4735cf2917337a6278" + integrity sha512-d/Hs3nWDxNL2xAczmOVZNj92YZCS6RGxfBPjKzuu/XirCgXdpKEb88dYNbrYGint6IVWLNP+yonwVAuRC0T2Dg== + dependencies: + "@types/express" "*" + +"@types/serve-static@*", "@types/serve-static@^1.13.10": + version "1.15.0" + resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.15.0.tgz#c7930ff61afb334e121a9da780aac0d9b8f34155" + integrity sha512-z5xyF6uh8CbjAu9760KDKsH2FcDxZ2tFCsA4HIMWE6IkiYMXfVoa+4f9KX+FN0ZLsaMw1WNG2ETLA6N+/YA+cg== + dependencies: + "@types/mime" "*" + "@types/node" "*" + +"@types/sockjs@^0.3.33": + version "0.3.33" + resolved "https://registry.yarnpkg.com/@types/sockjs/-/sockjs-0.3.33.tgz#570d3a0b99ac995360e3136fd6045113b1bd236f" + integrity sha512-f0KEEe05NvUnat+boPTZ0dgaLZ4SfSouXUgv5noUiefG2ajgKjmETo9ZJyuqsl7dfl2aHlLJUiki6B4ZYldiiw== + dependencies: + "@types/node" "*" + "@types/unist@*", "@types/unist@^2.0.0", "@types/unist@^2.0.2", "@types/unist@^2.0.3": version "2.0.6" resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.6.tgz#250a7b16c3b91f672a24552ec64678eeb1d3a08d" integrity sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ== +"@types/ws@^8.5.1": + version "8.5.3" + resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.3.tgz#7d25a1ffbecd3c4f2d35068d0b283c037003274d" + integrity sha512-6YOoWjruKj1uLf3INHH7D3qTXwFfEsg1kf3c0uDdSBJwfa/llkwIjrAGV7j7mVgGNbzTQ3HiHKKDXl6bJPD97w== + dependencies: + "@types/node" "*" + +"@types/yargs-parser@*": + version "21.0.0" + resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.0.tgz#0c60e537fa790f5f9472ed2776c2b71ec117351b" + integrity sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA== + +"@types/yargs@^17.0.8": + version "17.0.14" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.14.tgz#0943473052c24bd8cf2d1de25f1a710259327237" + integrity sha512-9Pj7abXoW1RSTcZaL2Hk6G2XyLMlp5ECdVC/Zf2p/KBjC3srijLGgRAXOBjtFrJoIrvxdTKyKDA14bEcbxBaWw== + dependencies: + "@types/yargs-parser" "*" + "@webassemblyjs/ast@1.11.1": version "1.11.1" resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.1.tgz#2bfd767eae1a6996f432ff7e8d7fc75679c0b6a7" @@ -1998,48 +2295,33 @@ resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== -accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.7: - version "1.3.7" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" - integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA== - dependencies: - mime-types "~2.1.24" - negotiator "0.6.2" - -acorn-dynamic-import@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/acorn-dynamic-import/-/acorn-dynamic-import-4.0.0.tgz#482210140582a36b83c3e342e1cfebcaa9240948" - integrity sha512-d3OEjQV4ROpoflsnUA8HozoIR504TFxNivYEUi6uwz0IYhBkTDXGuWlNdMtybRt3nqVx/L6XqMt0FxkXuWKZhw== +accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8: + version "1.3.8" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" + integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw== + dependencies: + mime-types "~2.1.34" + negotiator "0.6.3" acorn-import-assertions@^1.7.6: version "1.8.0" resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz#ba2b5939ce62c238db6d93d81c9b111b29b855e9" integrity sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw== -acorn-jsx@^5.0.1: - version "5.3.2" - resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" - integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== - acorn-walk@^8.0.0: version "8.2.0" resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== -acorn@^6.1.1: - version "6.4.2" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.2.tgz#35866fd710528e92de10cf06016498e47e39e1e6" - integrity sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ== - -acorn@^8.0.4, acorn@^8.4.1: - version "8.5.0" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.5.0.tgz#4512ccb99b3698c752591e9bb4472e38ad43cee2" - integrity sha512-yXbYeFy+jUuYd3/CDcg2NkIYE991XYX/bje7LmjJigUciaeO1JR4XxXgCIV1/Zc/dRuFEyw1L0pbA+qynJkW5Q== +acorn@^8.0.4, acorn@^8.5.0, acorn@^8.7.1: + version "8.8.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.1.tgz#0a3f9cbecc4ec3bea6f0a80b66ae8dd2da250b73" + integrity sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA== address@^1.0.1, address@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/address/-/address-1.1.2.tgz#bf1116c9c758c51b7a933d296b72c221ed9428b6" - integrity sha512-aT6camzM4xEA54YVJYSqxz1kv4IHnQZRtThJJHhUMRExaU5spC7jX5ugSwTaTgJliIgs4VhZOk7htClvQ/LmRA== + version "1.2.1" + resolved "https://registry.yarnpkg.com/address/-/address-1.2.1.tgz#25bb61095b7522d65b357baa11bc05492d4c8acd" + integrity sha512-B+6bi5D34+fDYENiH5qOlA0cV2rAGKuWZ9LeyUUehbXy8e0VS9e498yO0Jeeh+iM+6KbfudHTFjXw2MmJD4QRA== aggregate-error@^3.0.0: version "3.1.0" @@ -2049,11 +2331,25 @@ aggregate-error@^3.0.0: clean-stack "^2.0.0" indent-string "^4.0.0" +ajv-formats@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520" + integrity sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA== + dependencies: + ajv "^8.0.0" + ajv-keywords@^3.4.1, ajv-keywords@^3.5.2: version "3.5.2" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== +ajv-keywords@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-5.1.0.tgz#69d4d385a4733cdbeab44964a1170a88f87f0e16" + integrity sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw== + dependencies: + fast-deep-equal "^3.1.3" + ajv@^6.12.2, ajv@^6.12.4, ajv@^6.12.5: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" @@ -2064,39 +2360,44 @@ ajv@^6.12.2, ajv@^6.12.4, ajv@^6.12.5: json-schema-traverse "^0.4.1" uri-js "^4.2.2" -algoliasearch-helper@^3.5.5: - version "3.6.2" - resolved "https://registry.yarnpkg.com/algoliasearch-helper/-/algoliasearch-helper-3.6.2.tgz#45e19b12589cfa0c611b573287f65266ea2cc14a" - integrity sha512-Xx0NOA6k4ySn+R2l3UMSONAaMkyfmrZ3AP1geEMo32MxDJQJesZABZYsldO9fa6FKQxH91afhi4hO1G0Zc2opg== - dependencies: - events "^1.1.1" - -algoliasearch@^4.0.0, algoliasearch@^4.10.5: - version "4.11.0" - resolved "https://registry.yarnpkg.com/algoliasearch/-/algoliasearch-4.11.0.tgz#234befb3ac355c094077f0edf3777240b1ee013c" - integrity sha512-IXRj8kAP2WrMmj+eoPqPc6P7Ncq1yZkFiyDrjTBObV1ADNL8Z/KdZ+dWC5MmYcBLAbcB/mMCpak5N/D1UIZvsA== - dependencies: - "@algolia/cache-browser-local-storage" "4.11.0" - "@algolia/cache-common" "4.11.0" - "@algolia/cache-in-memory" "4.11.0" - "@algolia/client-account" "4.11.0" - "@algolia/client-analytics" "4.11.0" - "@algolia/client-common" "4.11.0" - "@algolia/client-personalization" "4.11.0" - "@algolia/client-search" "4.11.0" - "@algolia/logger-common" "4.11.0" - "@algolia/logger-console" "4.11.0" - "@algolia/requester-browser-xhr" "4.11.0" - "@algolia/requester-common" "4.11.0" - "@algolia/requester-node-http" "4.11.0" - "@algolia/transporter" "4.11.0" - -alphanum-sort@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3" - integrity sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM= +ajv@^8.0.0, ajv@^8.8.0: + version "8.11.2" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.11.2.tgz#aecb20b50607acf2569b6382167b65a96008bb78" + integrity sha512-E4bfmKAhGiSTvMfL1Myyycaub+cUEU2/IvpylXkUu7CHBkBj1f/ikdzbD7YQ6FKUbixDxeYvB/xY4fvyroDlQg== + dependencies: + fast-deep-equal "^3.1.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + uri-js "^4.2.2" -ansi-align@^3.0.0: +algoliasearch-helper@^3.10.0: + version "3.11.1" + resolved "https://registry.yarnpkg.com/algoliasearch-helper/-/algoliasearch-helper-3.11.1.tgz#d83ab7f1a2a374440686ef7a144b3c288b01188a" + integrity sha512-mvsPN3eK4E0bZG0/WlWJjeqe/bUD2KOEVOl0GyL/TGXn6wcpZU8NOuztGHCUKXkyg5gq6YzUakVTmnmSSO5Yiw== + dependencies: + "@algolia/events" "^4.0.1" + +algoliasearch@^4.0.0, algoliasearch@^4.13.1: + version "4.14.2" + resolved "https://registry.yarnpkg.com/algoliasearch/-/algoliasearch-4.14.2.tgz#63f142583bfc3a9bd3cd4a1b098bf6fe58e56f6c" + integrity sha512-ngbEQonGEmf8dyEh5f+uOIihv4176dgbuOZspiuhmTTBRBuzWu3KCGHre6uHj5YyuC7pNvQGzB6ZNJyZi0z+Sg== + dependencies: + "@algolia/cache-browser-local-storage" "4.14.2" + "@algolia/cache-common" "4.14.2" + "@algolia/cache-in-memory" "4.14.2" + "@algolia/client-account" "4.14.2" + "@algolia/client-analytics" "4.14.2" + "@algolia/client-common" "4.14.2" + "@algolia/client-personalization" "4.14.2" + "@algolia/client-search" "4.14.2" + "@algolia/logger-common" "4.14.2" + "@algolia/logger-console" "4.14.2" + "@algolia/requester-browser-xhr" "4.14.2" + "@algolia/requester-common" "4.14.2" + "@algolia/requester-node-http" "4.14.2" + "@algolia/transporter" "4.14.2" + +ansi-align@^3.0.0, ansi-align@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-3.0.1.tgz#0cdf12e111ace773a86e9a1fad1225c43cb19a59" integrity sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w== @@ -2132,18 +2433,23 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0: dependencies: color-convert "^2.0.1" +ansi-styles@^6.1.0: + version "6.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" + integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== + anymatch@~3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" - integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== dependencies: normalize-path "^3.0.0" picomatch "^2.0.4" arg@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.1.tgz#eb0c9a8f77786cad2af8ff2b862899842d7b6adb" - integrity sha512-e0hDa9H2Z9AwFkk2qDlwhoMYE4eToKarchkQHovNdLTCYMHZHeRjI71crOh+dio4K6u1IcwubQqo79Ga4CyAQA== + version "5.0.2" + resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.2.tgz#c81433cc427c92c4dcf4865142dbca6f15acd59c" + integrity sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg== argparse@^1.0.7: version "1.0.10" @@ -2160,9 +2466,9 @@ argparse@^2.0.1: array-flatten@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" - integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= + integrity sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg== -array-flatten@^2.1.0: +array-flatten@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.1.2.tgz#24ef80a28c1a893617e2149b0c6d0d788293b099" integrity sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ== @@ -2175,12 +2481,17 @@ array-union@^2.1.0: asap@~2.0.3: version "2.0.6" resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" - integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY= + integrity sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA== + +async@>=2.6.4: + version "3.2.4" + resolved "https://registry.yarnpkg.com/async/-/async-3.2.4.tgz#2d22e00f8cddeb5fde5dd33522b56d1cf569a81c" + integrity sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ== -async@^2.6.2: - version "2.6.3" - resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff" - integrity sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg== +async@^2.6: + version "2.6.4" + resolved "https://registry.yarnpkg.com/async/-/async-2.6.4.tgz#706b7ff6084664cd7eae713f6f965433b5504221" + integrity sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA== dependencies: lodash "^4.17.14" @@ -2189,32 +2500,32 @@ at-least-node@^1.0.0: resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== -autoprefixer@^10.3.5, autoprefixer@^10.3.7: - version "10.4.0" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.0.tgz#c3577eb32a1079a440ec253e404eaf1eb21388c8" - integrity sha512-7FdJ1ONtwzV1G43GDD0kpVMn/qbiNqyOPMFTX5nRffI+7vgWoFEc6DcXOxHJxrWNDXrZh18eDsZjvZGUljSRGA== +autoprefixer@^10.4.12, autoprefixer@^10.4.7: + version "10.4.13" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.13.tgz#b5136b59930209a321e9fa3dca2e7c4d223e83a8" + integrity sha512-49vKpMqcZYsJjwotvt4+h/BCjJVnhGwcLpDt5xkcaOG3eLrG/HUYLagrihYsQ+qrIBgIzX1Rw7a6L8I/ZA1Atg== dependencies: - browserslist "^4.17.5" - caniuse-lite "^1.0.30001272" - fraction.js "^4.1.1" + browserslist "^4.21.4" + caniuse-lite "^1.0.30001426" + fraction.js "^4.2.0" normalize-range "^0.1.2" picocolors "^1.0.0" - postcss-value-parser "^4.1.0" + postcss-value-parser "^4.2.0" -axios@^0.21.1: - version "0.21.4" - resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.4.tgz#c67b90dc0568e5c1cf2b0b858c43ba28e2eda575" - integrity sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg== +axios@^0.25.0: + version "0.25.0" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.25.0.tgz#349cfbb31331a9b4453190791760a8d35b093e0a" + integrity sha512-cD8FOb0tRH3uuEe6+evtAbgJtfxr7ly3fQjYcMcuPlgkwVS9xboaVIpcDV+cYQe+yGykgwZCs1pzjntcGa6l5g== dependencies: - follow-redirects "^1.14.0" + follow-redirects "^1.14.7" -babel-loader@^8.2.2: - version "8.2.3" - resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.2.3.tgz#8986b40f1a64cacfcb4b8429320085ef68b1342d" - integrity sha512-n4Zeta8NC3QAsuyiizu0GkmRcQ6clkV9WFUnUf1iXP//IeSKbWjofW3UHyZVwlOB4y039YQKefawyTn64Zwbuw== +babel-loader@^8.2.5: + version "8.3.0" + resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.3.0.tgz#124936e841ba4fe8176786d6ff28add1f134d6a8" + integrity sha512-H8SvsMF+m9t15HNLMipppzkC+Y2Yq+v3SonZyU70RBL/h1gxPkH08Ot8pEE9Z4Kd+czyWJClmFS8qzIP9OZ04Q== dependencies: find-cache-dir "^3.3.1" - loader-utils "^1.4.0" + loader-utils "^2.0.0" make-dir "^3.1.0" schema-utils "^2.6.5" @@ -2226,13 +2537,6 @@ babel-plugin-apply-mdx-type-prop@1.6.22: "@babel/helper-plugin-utils" "7.10.4" "@mdx-js/util" "1.6.22" -babel-plugin-dynamic-import-node@2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz#f00f507bdaa3c3e3ff6e7e5e98d90a7acab96f7f" - integrity sha512-o6qFkpeQEBxcqt0XYlWzAVxNCSCZdUgcR8IRlhD/8DylxjjO4foPcvTW0GGKa/cVt3rvxZ7o5ippJ+/0nvLhlQ== - dependencies: - object.assign "^4.1.0" - babel-plugin-dynamic-import-node@^2.3.3: version "2.3.3" resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz#84fda19c976ec5c6defef57f9427b3def66e17a3" @@ -2247,29 +2551,29 @@ babel-plugin-extract-import-names@1.6.22: dependencies: "@babel/helper-plugin-utils" "7.10.4" -babel-plugin-polyfill-corejs2@^0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.2.3.tgz#6ed8e30981b062f8fe6aca8873a37ebcc8cc1c0f" - integrity sha512-NDZ0auNRzmAfE1oDDPW2JhzIMXUk+FFe2ICejmt5T4ocKgiQx3e0VCRx9NCAidcMtL2RUZaWtXnmjTCkx0tcbA== +babel-plugin-polyfill-corejs2@^0.3.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.3.tgz#5d1bd3836d0a19e1b84bbf2d9640ccb6f951c122" + integrity sha512-8hOdmFYFSZhqg2C/JgLUQ+t52o5nirNwaWM2B9LWteozwIvM14VSwdsCAUET10qT+kmySAlseadmfeeSWFCy+Q== dependencies: - "@babel/compat-data" "^7.13.11" - "@babel/helper-define-polyfill-provider" "^0.2.4" + "@babel/compat-data" "^7.17.7" + "@babel/helper-define-polyfill-provider" "^0.3.3" semver "^6.1.1" -babel-plugin-polyfill-corejs3@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.3.0.tgz#fa7ca3d1ee9ddc6193600ffb632c9785d54918af" - integrity sha512-JLwi9vloVdXLjzACL80j24bG6/T1gYxwowG44dg6HN/7aTPdyPbJJidf6ajoA3RPHHtW0j9KMrSOLpIZpAnPpg== +babel-plugin-polyfill-corejs3@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.6.0.tgz#56ad88237137eade485a71b52f72dbed57c6230a" + integrity sha512-+eHqR6OPcBhJOGgsIar7xoAB1GcSwVUA3XjAd7HJNzOXT4wv6/H7KIdA/Nc60cvUlDbKApmqNvD1B1bzOt4nyA== dependencies: - "@babel/helper-define-polyfill-provider" "^0.2.4" - core-js-compat "^3.18.0" + "@babel/helper-define-polyfill-provider" "^0.3.3" + core-js-compat "^3.25.1" -babel-plugin-polyfill-regenerator@^0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.2.3.tgz#2e9808f5027c4336c994992b48a4262580cb8d6d" - integrity sha512-JVE78oRZPKFIeUqFGrSORNzQnrDwZR16oiWeGM8ZyjBn2XAT5OjP+wXx5ESuo33nUsFUEJYjtklnsKbxW5L+7g== +babel-plugin-polyfill-regenerator@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.4.1.tgz#390f91c38d90473592ed43351e801a9d3e0fd747" + integrity sha512-NtQGmyQDXjQqQ+IzRkBVwEOz9lQ4zxAQZgoAYEtU9dJjnl1Oc98qnN7jcp+bE7O7aYzVpavXE3/VKXNzUbh7aw== dependencies: - "@babel/helper-define-polyfill-provider" "^0.2.4" + "@babel/helper-define-polyfill-provider" "^0.3.3" bail@^1.0.0: version "1.0.5" @@ -2284,12 +2588,12 @@ balanced-match@^1.0.0: base16@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/base16/-/base16-1.0.0.tgz#e297f60d7ec1014a7a971a39ebc8a98c0b681e70" - integrity sha1-4pf2DX7BAUp6lxo568ipjAtoHnA= + integrity sha512-pNdYkNPiJUnEhnfXV56+sQy8+AaPcG3POZAUnwr4EeqCUZFz4u2PePbo3e5Gj4ziYPCWGUZT9RHisvJKnwFuBQ== batch@0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16" - integrity sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY= + integrity sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw== big.js@^5.2.2: version "5.2.2" @@ -2301,45 +2605,40 @@ binary-extensions@^2.0.0: resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== -bluebird@^3.7.1: - version "3.7.2" - resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" - integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== - -body-parser@1.19.0: - version "1.19.0" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a" - integrity sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw== +body-parser@1.20.1: + version "1.20.1" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.1.tgz#b1812a8912c195cd371a3ee5e66faa2338a5c668" + integrity sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw== dependencies: - bytes "3.1.0" + bytes "3.1.2" content-type "~1.0.4" debug "2.6.9" - depd "~1.1.2" - http-errors "1.7.2" + depd "2.0.0" + destroy "1.2.0" + http-errors "2.0.0" iconv-lite "0.4.24" - on-finished "~2.3.0" - qs "6.7.0" - raw-body "2.4.0" - type-is "~1.6.17" + on-finished "2.4.1" + qs "6.11.0" + raw-body "2.5.1" + type-is "~1.6.18" + unpipe "1.0.0" -bonjour@^3.5.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/bonjour/-/bonjour-3.5.0.tgz#8e890a183d8ee9a2393b3844c691a42bcf7bc9f5" - integrity sha1-jokKGD2O6aI5OzhExpGkK897yfU= +bonjour-service@^1.0.11: + version "1.0.14" + resolved "https://registry.yarnpkg.com/bonjour-service/-/bonjour-service-1.0.14.tgz#c346f5bc84e87802d08f8d5a60b93f758e514ee7" + integrity sha512-HIMbgLnk1Vqvs6B4Wq5ep7mxvj9sGz5d1JJyDNSGNIdA/w2MCz6GTjWTdjqOJV1bEPj+6IkxDvWNFKEBxNt4kQ== dependencies: - array-flatten "^2.1.0" - deep-equal "^1.0.1" + array-flatten "^2.1.2" dns-equal "^1.0.0" - dns-txt "^2.0.2" - multicast-dns "^6.0.1" - multicast-dns-service-types "^1.1.0" + fast-deep-equal "^3.1.3" + multicast-dns "^7.2.5" -boolbase@^1.0.0, boolbase@~1.0.0: +boolbase@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" - integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24= + integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww== -boxen@^5.0.0, boxen@^5.0.1: +boxen@^5.0.0: version "5.1.2" resolved "https://registry.yarnpkg.com/boxen/-/boxen-5.1.2.tgz#788cb686fc83c1f486dfa8a40c68fc2b831d2b50" integrity sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ== @@ -2353,6 +2652,20 @@ boxen@^5.0.0, boxen@^5.0.1: widest-line "^3.1.0" wrap-ansi "^7.0.0" +boxen@^6.2.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/boxen/-/boxen-6.2.1.tgz#b098a2278b2cd2845deef2dff2efc38d329b434d" + integrity sha512-H4PEsJXfFI/Pt8sjDWbHlQPx4zL/bvSQjcilJmaulGt5mLDorHOHpmdXAJcBcmru7PhYSp/cDMWRko4ZUMFkSw== + dependencies: + ansi-align "^3.0.1" + camelcase "^6.2.0" + chalk "^4.1.2" + cli-boxes "^3.0.0" + string-width "^5.0.1" + type-fest "^2.5.0" + widest-line "^4.0.1" + wrap-ansi "^8.0.1" + brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -2361,69 +2674,55 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" -braces@^3.0.1, braces@~3.0.2: +braces@^3.0.2, braces@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== dependencies: fill-range "^7.0.1" -browserslist@>4.16.5, browserslist@^4.0.0, browserslist@^4.14.5, browserslist@^4.16.0, browserslist@^4.16.5, browserslist@^4.16.6, browserslist@^4.17.5, browserslist@^4.17.6: - version "4.17.6" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.17.6.tgz#c76be33e7786b497f66cad25a73756c8b938985d" - integrity sha512-uPgz3vyRTlEiCv4ee9KlsKgo2V6qPk7Jsn0KAn2OBqbqKo3iNcPEC1Ti6J4dwnz+aIRfEEEuOzC9IBk8tXUomw== - dependencies: - caniuse-lite "^1.0.30001274" - electron-to-chromium "^1.3.886" - escalade "^3.1.1" - node-releases "^2.0.1" - picocolors "^1.0.0" - -buble-jsx-only@^0.19.8: - version "0.19.8" - resolved "https://registry.yarnpkg.com/buble-jsx-only/-/buble-jsx-only-0.19.8.tgz#6e3524aa0f1c523de32496ac9aceb9cc2b493867" - integrity sha512-7AW19pf7PrKFnGTEDzs6u9+JZqQwM1VnLS19OlqYDhXomtFFknnoQJAPHeg84RMFWAvOhYrG7harizJNwUKJsA== +browserslist@>4.16.5, browserslist@^4.0.0, browserslist@^4.14.5, browserslist@^4.16.6, browserslist@^4.18.1, browserslist@^4.21.3, browserslist@^4.21.4: + version "4.21.4" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.4.tgz#e7496bbc67b9e39dd0f98565feccdcb0d4ff6987" + integrity sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw== dependencies: - acorn "^6.1.1" - acorn-dynamic-import "^4.0.0" - acorn-jsx "^5.0.1" - chalk "^2.4.2" - magic-string "^0.25.3" - minimist "^1.2.0" - regexpu-core "^4.5.4" + caniuse-lite "^1.0.30001400" + electron-to-chromium "^1.4.251" + node-releases "^2.0.6" + update-browserslist-db "^1.0.9" buffer-from@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== -buffer-indexof@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/buffer-indexof/-/buffer-indexof-1.1.1.tgz#52fabcc6a606d1a00302802648ef68f639da268c" - integrity sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g== - bytes@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" - integrity sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg= + integrity sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw== -bytes@3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" - integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== +bytes@3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" + integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== -cacheable-request@^6.0.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-6.1.0.tgz#20ffb8bd162ba4be11e9567d823db651052ca912" - integrity sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg== - dependencies: - clone-response "^1.0.2" - get-stream "^5.1.0" - http-cache-semantics "^4.0.0" - keyv "^3.0.0" - lowercase-keys "^2.0.0" - normalize-url "^4.1.0" - responselike "^1.0.2" +cacheable-lookup@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/cacheable-lookup/-/cacheable-lookup-7.0.0.tgz#3476a8215d046e5a3202a9209dd13fec1f933a27" + integrity sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w== + +cacheable-request@^10.2.1: + version "10.2.3" + resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-10.2.3.tgz#25277efe121308ab722c28b4164e51382b4adeb1" + integrity sha512-6BehRBOs7iurNjAYN9iPazTwFDaMQavJO8W1MEm3s2pH8q/tkPTtLDRUZaweWK87WFGf2Y5wLAlaCJlR5kOz3w== + dependencies: + "@types/http-cache-semantics" "^4.0.1" + get-stream "^6.0.1" + http-cache-semantics "^4.1.0" + keyv "^4.5.2" + mimic-response "^4.0.0" + normalize-url "^8.0.0" + responselike "^3.0.0" call-bind@^1.0.0, call-bind@^1.0.2: version "1.0.2" @@ -2452,9 +2751,9 @@ camelcase-css@2.0.1: integrity sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA== camelcase@^6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.2.0.tgz#924af881c9d525ac9d87f40d964e5cea982a1809" - integrity sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg== + version "6.3.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" + integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== caniuse-api@^3.0.0: version "3.0.0" @@ -2466,17 +2765,17 @@ caniuse-api@^3.0.0: lodash.memoize "^4.1.2" lodash.uniq "^4.5.0" -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001272, caniuse-lite@^1.0.30001274: - version "1.0.30001278" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001278.tgz#51cafc858df77d966b17f59b5839250b24417fff" - integrity sha512-mpF9KeH8u5cMoEmIic/cr7PNS+F5LWBk0t2ekGT60lFf0Wq+n9LspAj0g3P+o7DQhD3sUdlMln4YFAWhFYn9jg== +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001400, caniuse-lite@^1.0.30001426: + version "1.0.30001434" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001434.tgz#ec1ec1cfb0a93a34a0600d37903853030520a4e5" + integrity sha512-aOBHrLmTQw//WFa2rcF1If9fa3ypkC1wzqqiKHgfdrXTWcU8C4gKVZT77eQAPWN1APys3+uQ0Df07rKauXGEYA== -ccount@^1.0.0, ccount@^1.0.3: +ccount@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/ccount/-/ccount-1.1.0.tgz#246687debb6014735131be8abab2d93898f8d043" integrity sha512-vlNK021QdI7PNeiUh/lKkC/mNHHfV0m/Ad5JoI0TYtlBnJAslM/JIkm/tGC88bkLIwO6OQ5uV6ztS6kVAtCDlg== -chalk@^2.0.0, chalk@^2.4.1, chalk@^2.4.2: +chalk@^2.0.0: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -2485,7 +2784,7 @@ chalk@^2.0.0, chalk@^2.4.1, chalk@^2.4.2: escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chalk@^4.1.0, chalk@^4.1.2: +chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== @@ -2508,32 +2807,35 @@ character-reference-invalid@^1.0.0: resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz#083329cda0eae272ab3dbbf37e9a382c13af1560" integrity sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg== -cheerio@^0.22.0: - version "0.22.0" - resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-0.22.0.tgz#a9baa860a3f9b595a6b81b1a86873121ed3a269e" - integrity sha1-qbqoYKP5tZWmuBsahocxIe06Jp4= - dependencies: - css-select "~1.2.0" - dom-serializer "~0.1.0" - entities "~1.1.1" - htmlparser2 "^3.9.1" - lodash.assignin "^4.0.9" - lodash.bind "^4.1.4" - lodash.defaults "^4.0.1" - lodash.filter "^4.4.0" - lodash.flatten "^4.2.0" - lodash.foreach "^4.3.0" - lodash.map "^4.4.0" - lodash.merge "^4.4.0" - lodash.pick "^4.2.1" - lodash.reduce "^4.4.0" - lodash.reject "^4.4.0" - lodash.some "^4.4.0" - -chokidar@^3.4.2, chokidar@^3.5.2: - version "3.5.2" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.2.tgz#dba3976fcadb016f66fd365021d91600d01c1e75" - integrity sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ== +cheerio-select@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cheerio-select/-/cheerio-select-2.1.0.tgz#4d8673286b8126ca2a8e42740d5e3c4884ae21b4" + integrity sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g== + dependencies: + boolbase "^1.0.0" + css-select "^5.1.0" + css-what "^6.1.0" + domelementtype "^2.3.0" + domhandler "^5.0.3" + domutils "^3.0.1" + +cheerio@^1.0.0-rc.12: + version "1.0.0-rc.12" + resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-1.0.0-rc.12.tgz#788bf7466506b1c6bf5fae51d24a2c4d62e47683" + integrity sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q== + dependencies: + cheerio-select "^2.1.0" + dom-serializer "^2.0.0" + domhandler "^5.0.3" + domutils "^3.0.1" + htmlparser2 "^8.0.1" + parse5 "^7.0.0" + parse5-htmlparser2-tree-adapter "^7.0.0" + +chokidar@^3.4.2, chokidar@^3.5.3: + version "3.5.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" + integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== dependencies: anymatch "~3.1.2" braces "~3.0.2" @@ -2555,20 +2857,20 @@ ci-info@^2.0.0: resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46" integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ== -ci-info@^3.1.1: - version "3.2.0" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.2.0.tgz#2876cb948a498797b5236f0095bc057d0dca38b6" - integrity sha512-dVqRX7fLUm8J6FgHJ418XuIgDLZDkYcDFTeL6TA2gt5WlIZUQrrH6EZrNClwT/H0FateUsZkGIOPRrLbP+PR9A== +ci-info@^3.2.0: + version "3.7.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.7.0.tgz#6d01b3696c59915b6ce057e4aa4adfc2fa25f5ef" + integrity sha512-2CpRNYmImPx+RXKLq6jko/L07phmS9I02TyqkcNU20GCF/GgaWvc58hPtjxDX8lPpkdwc9sNh72V9k00S7ezog== classnames@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.3.1.tgz#dfcfa3891e306ec1dad105d0e88f4417b8535e8e" - integrity sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA== + version "2.3.2" + resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.3.2.tgz#351d813bf0137fcc6a76a16b88208d2560a0d924" + integrity sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw== -clean-css@^5.1.5: - version "5.2.2" - resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-5.2.2.tgz#d3a7c6ee2511011e051719838bdcf8314dc4548d" - integrity sha512-/eR8ru5zyxKzpBLv9YZvMXgTSSQn7AdkMItMYynsFgGwTveCRVam9IUPFloE85B4vAIj05IuKmmEoV7/AQjT0w== +clean-css@^5.2.2, clean-css@^5.3.0: + version "5.3.1" + resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-5.3.1.tgz#d0610b0b90d125196a2894d35366f734e5d7aa32" + integrity sha512-lCr8OHhiWCTw4v8POJovCoh4T7I9U11yVsPjMWWnnMmp9ZowCxyad1Pathle/9HjaDp+fdQKjO9fQydE6RHTZg== dependencies: source-map "~0.6.0" @@ -2582,6 +2884,20 @@ cli-boxes@^2.2.1: resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.1.tgz#ddd5035d25094fce220e9cab40a45840a440318f" integrity sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw== +cli-boxes@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-3.0.0.tgz#71a10c716feeba005e4504f36329ef0b17cf3145" + integrity sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g== + +cli-table3@^0.6.2: + version "0.6.3" + resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.3.tgz#61ab765aac156b52f222954ffc607a6f01dbeeb2" + integrity sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg== + dependencies: + string-width "^4.2.0" + optionalDependencies: + "@colors/colors" "1.5.0" + clone-deep@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387" @@ -2591,26 +2907,10 @@ clone-deep@^4.0.1: kind-of "^6.0.2" shallow-clone "^3.0.0" -clone-response@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b" - integrity sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws= - dependencies: - mimic-response "^1.0.0" - -clsx@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.1.1.tgz#98b3134f9abbdf23b2663491ace13c5c03a73188" - integrity sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA== - -coa@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/coa/-/coa-2.0.2.tgz#43f6c21151b4ef2bf57187db0d73de229e3e7ec3" - integrity sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA== - dependencies: - "@types/q" "^1.5.1" - chalk "^2.4.1" - q "^1.1.2" +clsx@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.2.1.tgz#0ddc4a20a549b59c93a4116bb26f5294ca17dc12" + integrity sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg== collapse-white-space@^1.0.2: version "1.0.6" @@ -2634,7 +2934,7 @@ color-convert@^2.0.1: color-name@1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= + integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== color-name@~1.1.4: version "1.1.4" @@ -2642,14 +2942,14 @@ color-name@~1.1.4: integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== colord@^2.9.1: - version "2.9.1" - resolved "https://registry.yarnpkg.com/colord/-/colord-2.9.1.tgz#c961ea0efeb57c9f0f4834458f26cb9cc4a3f90e" - integrity sha512-4LBMSt09vR0uLnPVkOUBnmxgoaeN4ewRbx801wY/bXcltXfpR/G46OdWn96XpYmCWuYvO46aBZP4NgX8HpNAcw== + version "2.9.3" + resolved "https://registry.yarnpkg.com/colord/-/colord-2.9.3.tgz#4f8ce919de456f1d5c1c368c307fe20f3e59fb43" + integrity sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw== colorette@^2.0.10: - version "2.0.16" - resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.16.tgz#713b9af84fdb000139f04546bd4a93f62a5085da" - integrity sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g== + version "2.0.19" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.19.tgz#cdf044f47ad41a0f4b56b3a0d5b4e6e1a2d5a798" + integrity sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ== combine-promises@^1.1.0: version "1.1.0" @@ -2676,7 +2976,7 @@ commander@^7.2.0: resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== -commander@^8.1.0: +commander@^8.3.0: version "8.3.0" resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww== @@ -2684,7 +2984,7 @@ commander@^8.1.0: commondir@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" - integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= + integrity sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg== compressible@~2.0.16: version "2.0.18" @@ -2709,7 +3009,7 @@ compression@^1.7.4: concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== configstore@^5.0.1: version "5.0.1" @@ -2723,10 +3023,10 @@ configstore@^5.0.1: write-file-atomic "^3.0.0" xdg-basedir "^4.0.0" -connect-history-api-fallback@^1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz#8b32089359308d111115d81cad3fceab888f97bc" - integrity sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg== +connect-history-api-fallback@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz#647264845251a0daf25b97ce87834cace0f5f1c8" + integrity sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA== consola@^2.15.3: version "2.15.3" @@ -2736,14 +3036,14 @@ consola@^2.15.3: content-disposition@0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4" - integrity sha1-DPaLud318r55YcOoUXjLhdunjLQ= + integrity sha512-kRGRZw3bLlFISDBgwTSA1TMBFN6J6GWDeubmDE3AF+3+yXL8hTWv8r5rkLbqYXY4RjPk/EzHnClI3zQf1cFmHA== -content-disposition@0.5.3: - version "0.5.3" - resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd" - integrity sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g== +content-disposition@0.5.4: + version "0.5.4" + resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.4.tgz#8b82b4efac82512a02bb0b1dcec9d2c5e8eb5bfe" + integrity sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ== dependencies: - safe-buffer "5.1.2" + safe-buffer "5.2.1" content-type@~1.0.4: version "1.0.4" @@ -2751,57 +3051,53 @@ content-type@~1.0.4: integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== convert-source-map@^1.7.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.8.0.tgz#f3373c32d21b4d780dd8004514684fb791ca4369" - integrity sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA== - dependencies: - safe-buffer "~5.1.1" + version "1.9.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f" + integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A== cookie-signature@1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" - integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= + integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== -cookie@0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba" - integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg== +cookie@0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b" + integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== copy-text-to-clipboard@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/copy-text-to-clipboard/-/copy-text-to-clipboard-3.0.1.tgz#8cbf8f90e0a47f12e4a24743736265d157bce69c" integrity sha512-rvVsHrpFcL4F2P8ihsoLdFHmd404+CMg71S756oRSeQgqk51U3kicGdnvfkrxva0xXH92SjGS62B0XIJsbh+9Q== -copy-webpack-plugin@^9.0.1: - version "9.0.1" - resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-9.0.1.tgz#b71d21991599f61a4ee00ba79087b8ba279bbb59" - integrity sha512-14gHKKdYIxF84jCEgPgYXCPpldbwpxxLbCmA7LReY7gvbaT555DgeBWBgBZM116tv/fO6RRJrsivBqRyRlukhw== +copy-webpack-plugin@^11.0.0: + version "11.0.0" + resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-11.0.0.tgz#96d4dbdb5f73d02dd72d0528d1958721ab72e04a" + integrity sha512-fX2MWpamkW0hZxMEg0+mYnA40LTosOSa5TqZ9GYIBzyJa9C3QUaMPSE2xAi/buNr8u89SfD9wHSQVBzrRa/SOQ== dependencies: - fast-glob "^3.2.5" - glob-parent "^6.0.0" - globby "^11.0.3" + fast-glob "^3.2.11" + glob-parent "^6.0.1" + globby "^13.1.1" normalize-path "^3.0.0" - p-limit "^3.1.0" - schema-utils "^3.0.0" + schema-utils "^4.0.0" serialize-javascript "^6.0.0" -core-js-compat@^3.18.0, core-js-compat@^3.19.0: - version "3.19.1" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.19.1.tgz#fe598f1a9bf37310d77c3813968e9f7c7bb99476" - integrity sha512-Q/VJ7jAF/y68+aUsQJ/afPOewdsGkDtcMb40J8MbuWKlK3Y+wtHq8bTHKPj2WKWLIqmS5JhHs4CzHtz6pT2W6g== +core-js-compat@^3.25.1: + version "3.26.1" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.26.1.tgz#0e710b09ebf689d719545ac36e49041850f943df" + integrity sha512-622/KzTudvXCDLRw70iHW4KKs1aGpcRcowGWyYJr2DEBfRrd6hNJybxSWJFuZYD4ma86xhrwDDHxmDaIq4EA8A== dependencies: - browserslist "^4.17.6" - semver "7.0.0" + browserslist "^4.21.4" -core-js-pure@^3.19.0: - version "3.19.1" - resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.19.1.tgz#edffc1fc7634000a55ba05e95b3f0fe9587a5aa4" - integrity sha512-Q0Knr8Es84vtv62ei6/6jXH/7izKmOrtrxH9WJTHLCMAVeU+8TF8z8Nr08CsH4Ot0oJKzBzJJL9SJBYIv7WlfQ== +core-js-pure@^3.25.1: + version "3.26.1" + resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.26.1.tgz#653f4d7130c427820dcecd3168b594e8bb095a33" + integrity sha512-VVXcDpp/xJ21KdULRq/lXdLzQAtX7+37LzpyfFM973il0tWSsDEoyzG38G14AjTpK9VTfiNM9jnFauq/CpaWGQ== -core-js@^3.18.0: - version "3.19.1" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.19.1.tgz#f6f173cae23e73a7d88fa23b6e9da329276c6641" - integrity sha512-Tnc7E9iKd/b/ff7GFbhwPVzJzPztGrChB8X8GLqoYGdEOG8IpLnK1xPyo3ZoO3HsK6TodJS58VGPOxA+hLHQMg== +core-js@^3.23.3: + version "3.26.1" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.26.1.tgz#7a9816dabd9ee846c1c0fe0e8fcad68f3709134e" + integrity sha512-21491RRQVzUn0GGM9Z1Jrpr6PNPxPi+Za8OM9q4tksTSnlbXXGKK1nXNg/QvwFYettXvSX6zWKCtHHfjN4puyA== core-util-is@~1.0.0: version "1.0.3" @@ -2819,10 +3115,10 @@ cosmiconfig@^6.0.0: path-type "^4.0.0" yaml "^1.7.2" -cosmiconfig@^7.0.0: - version "7.0.1" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.0.1.tgz#714d756522cace867867ccb4474c5d01bbae5d6d" - integrity sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ== +cosmiconfig@^7.0.0, cosmiconfig@^7.0.1: + version "7.1.0" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.1.0.tgz#1443b9afa596b670082ea46cbd8f6a62b84635f6" + integrity sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA== dependencies: "@types/parse-json" "^4.0.0" import-fresh "^3.2.1" @@ -2830,12 +3126,12 @@ cosmiconfig@^7.0.0: path-type "^4.0.0" yaml "^1.10.0" -cross-fetch@^3.0.4: - version "3.1.4" - resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.4.tgz#9723f3a3a247bf8b89039f3a380a9244e8fa2f39" - integrity sha512-1eAtFWdIubi6T4XPy6ei9iUFoKpUkIF971QLN8lIvvvwueI65+Nw5haMNKUwfJxabqlIIDODJKGrQ66gxC0PbQ== +cross-fetch@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.5.tgz#e1389f44d9e7ba767907f7af8454787952ab534f" + integrity sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw== dependencies: - node-fetch "2.6.1" + node-fetch "2.6.7" cross-spawn@^7.0.3: version "7.0.3" @@ -2851,90 +3147,58 @@ crypto-random-string@^2.0.0: resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5" integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA== -css-color-names@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-1.0.1.tgz#6ff7ee81a823ad46e020fa2fd6ab40a887e2ba67" - integrity sha512-/loXYOch1qU1biStIFsHH8SxTmOseh1IJqFvy8IujXOm1h+QjUdDhkzOrR5HG8K8mlxREj0yfi8ewCHx0eMxzA== - -css-declaration-sorter@^6.0.3: - version "6.1.3" - resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-6.1.3.tgz#e9852e4cf940ba79f509d9425b137d1f94438dc2" - integrity sha512-SvjQjNRZgh4ULK1LDJ2AduPKUKxIqmtU7ZAyi47BTV+M90Qvxr9AB6lKlLbDUfXqI9IQeYA8LbAsCZPpJEV3aA== - dependencies: - timsort "^0.3.0" +css-declaration-sorter@^6.3.1: + version "6.3.1" + resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-6.3.1.tgz#be5e1d71b7a992433fb1c542c7a1b835e45682ec" + integrity sha512-fBffmak0bPAnyqc/HO8C3n2sHrp9wcqQz6ES9koRF2/mLOVAx9zIQ3Y7R29sYCteTPqMCwns4WYQoCX91Xl3+w== -css-loader@^5.1.1: - version "5.2.7" - resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-5.2.7.tgz#9b9f111edf6fb2be5dc62525644cbc9c232064ae" - integrity sha512-Q7mOvpBNBG7YrVGMxRxcBJZFL75o+cH2abNASdibkj/fffYD8qWbInZrD0S9ccI6vZclF3DsHE7njGlLtaHbhg== +css-loader@^6.7.1: + version "6.7.2" + resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-6.7.2.tgz#26bc22401b5921686a10fbeba75d124228302304" + integrity sha512-oqGbbVcBJkm8QwmnNzrFrWTnudnRZC+1eXikLJl0n4ljcfotgRifpg2a1lKy8jTrc4/d9A/ap1GFq1jDKG7J+Q== dependencies: icss-utils "^5.1.0" - loader-utils "^2.0.0" - postcss "^8.2.15" + postcss "^8.4.18" postcss-modules-extract-imports "^3.0.0" postcss-modules-local-by-default "^4.0.0" postcss-modules-scope "^3.0.0" postcss-modules-values "^4.0.0" - postcss-value-parser "^4.1.0" - schema-utils "^3.0.0" - semver "^7.3.5" + postcss-value-parser "^4.2.0" + semver "^7.3.8" -css-minimizer-webpack-plugin@^3.0.2: - version "3.1.1" - resolved "https://registry.yarnpkg.com/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-3.1.1.tgz#27bafa3b75054713565b2266c64b0228acd18634" - integrity sha512-KlB8l5uoNcf9F7i5kXnkxoqJGd2BXH4f0+Lj2vSWSmuvMLYO1kNsJ1KHSzeDW8e45/whgSOPcKVT/3JopkT8dg== +css-minimizer-webpack-plugin@^4.0.0: + version "4.2.2" + resolved "https://registry.yarnpkg.com/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-4.2.2.tgz#79f6199eb5adf1ff7ba57f105e3752d15211eb35" + integrity sha512-s3Of/4jKfw1Hj9CxEO1E5oXhQAxlayuHO2y/ML+C6I9sQ7FdzfEV6QgMLN3vI+qFsjJGIAFLKtQK7t8BOXAIyA== dependencies: - cssnano "^5.0.6" - jest-worker "^27.0.2" - p-limit "^3.0.2" - postcss "^8.3.5" - schema-utils "^3.1.0" + cssnano "^5.1.8" + jest-worker "^29.1.2" + postcss "^8.4.17" + schema-utils "^4.0.0" serialize-javascript "^6.0.0" source-map "^0.6.1" -css-select-base-adapter@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz#3b2ff4972cc362ab88561507a95408a1432135d7" - integrity sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w== - -css-select@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/css-select/-/css-select-2.1.0.tgz#6a34653356635934a81baca68d0255432105dbef" - integrity sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ== - dependencies: - boolbase "^1.0.0" - css-what "^3.2.1" - domutils "^1.7.0" - nth-check "^1.0.2" - css-select@^4.1.3: - version "4.1.3" - resolved "https://registry.yarnpkg.com/css-select/-/css-select-4.1.3.tgz#a70440f70317f2669118ad74ff105e65849c7067" - integrity sha512-gT3wBNd9Nj49rAbmtFHj1cljIAOLYSX1nZ8CB7TBO3INYckygm5B7LISU/szY//YmdiSLbJvDLOx9VnMVpMBxA== + version "4.3.0" + resolved "https://registry.yarnpkg.com/css-select/-/css-select-4.3.0.tgz#db7129b2846662fd8628cfc496abb2b59e41529b" + integrity sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ== dependencies: boolbase "^1.0.0" - css-what "^5.0.0" - domhandler "^4.2.0" - domutils "^2.6.0" - nth-check "^2.0.0" - -css-select@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/css-select/-/css-select-1.2.0.tgz#2b3a110539c5355f1cd8d314623e870b121ec858" - integrity sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg= - dependencies: - boolbase "~1.0.0" - css-what "2.1" - domutils "1.5.1" - nth-check "~1.0.1" + css-what "^6.0.1" + domhandler "^4.3.1" + domutils "^2.8.0" + nth-check "^2.0.1" -css-tree@1.0.0-alpha.37: - version "1.0.0-alpha.37" - resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.37.tgz#98bebd62c4c1d9f960ec340cf9f7522e30709a22" - integrity sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg== +css-select@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/css-select/-/css-select-5.1.0.tgz#b8ebd6554c3637ccc76688804ad3f6a6fdaea8a6" + integrity sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg== dependencies: - mdn-data "2.0.4" - source-map "^0.6.1" + boolbase "^1.0.0" + css-what "^6.1.0" + domhandler "^5.0.2" + domutils "^3.0.1" + nth-check "^2.0.1" css-tree@^1.1.2, css-tree@^1.1.3: version "1.1.3" @@ -2944,79 +3208,78 @@ css-tree@^1.1.2, css-tree@^1.1.3: mdn-data "2.0.14" source-map "^0.6.1" -css-what@2.1, css-what@^3.2.1, css-what@^5.0.0, css-what@^5.0.1: - version "5.1.0" - resolved "https://registry.yarnpkg.com/css-what/-/css-what-5.1.0.tgz#3f7b707aadf633baf62c2ceb8579b545bb40f7fe" - integrity sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw== +css-what@>5.0.1, css-what@^6.0.1, css-what@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/css-what/-/css-what-6.1.0.tgz#fb5effcf76f1ddea2c81bdfaa4de44e79bac70f4" + integrity sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw== cssesc@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== -cssnano-preset-advanced@^5.1.4: - version "5.1.6" - resolved "https://registry.yarnpkg.com/cssnano-preset-advanced/-/cssnano-preset-advanced-5.1.6.tgz#182fdeb69fde30efdc9961365461f79a751bdcfe" - integrity sha512-rkuQ16aS/0zNaTNbJIw/IOhwboqWfBfsmUnchP1qR54ml5lP2qSu8s3Ux7khNBHAi08FTMQq1819/RpDgawXNQ== - dependencies: - autoprefixer "^10.3.7" - cssnano-preset-default "^5.1.6" - postcss-discard-unused "^5.0.1" - postcss-merge-idents "^5.0.1" - postcss-reduce-idents "^5.0.1" - postcss-zindex "^5.0.1" - -cssnano-preset-default@^5.1.6: - version "5.1.6" - resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-5.1.6.tgz#1bdb83be6a6b1fee6dc5e9ec2e61286bcadcc7a6" - integrity sha512-X2nDeNGBXc0486oHjT2vSj+TdeyVsxRvJUxaOH50hOM6vSDLkKd0+59YXpSZRInJ4sNtBOykS4KsPfhdrU/35w== - dependencies: - css-declaration-sorter "^6.0.3" - cssnano-utils "^2.0.1" - postcss-calc "^8.0.0" - postcss-colormin "^5.2.1" - postcss-convert-values "^5.0.2" - postcss-discard-comments "^5.0.1" - postcss-discard-duplicates "^5.0.1" - postcss-discard-empty "^5.0.1" - postcss-discard-overridden "^5.0.1" - postcss-merge-longhand "^5.0.3" - postcss-merge-rules "^5.0.2" - postcss-minify-font-values "^5.0.1" - postcss-minify-gradients "^5.0.3" - postcss-minify-params "^5.0.1" - postcss-minify-selectors "^5.1.0" - postcss-normalize-charset "^5.0.1" - postcss-normalize-display-values "^5.0.1" - postcss-normalize-positions "^5.0.1" - postcss-normalize-repeat-style "^5.0.1" - postcss-normalize-string "^5.0.1" - postcss-normalize-timing-functions "^5.0.1" - postcss-normalize-unicode "^5.0.1" - postcss-normalize-url "^5.0.2" - postcss-normalize-whitespace "^5.0.1" - postcss-ordered-values "^5.0.2" - postcss-reduce-initial "^5.0.1" - postcss-reduce-transforms "^5.0.1" - postcss-svgo "^5.0.3" - postcss-unique-selectors "^5.0.1" - -cssnano-utils@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/cssnano-utils/-/cssnano-utils-2.0.1.tgz#8660aa2b37ed869d2e2f22918196a9a8b6498ce2" - integrity sha512-i8vLRZTnEH9ubIyfdZCAdIdgnHAUeQeByEeQ2I7oTilvP9oHO6RScpeq3GsFUVqeB8uZgOQ9pw8utofNn32hhQ== +cssnano-preset-advanced@^5.3.8: + version "5.3.9" + resolved "https://registry.yarnpkg.com/cssnano-preset-advanced/-/cssnano-preset-advanced-5.3.9.tgz#99e1cdf81a467a5e6c366cfc6d874a166c4d9a67" + integrity sha512-njnh4pp1xCsibJcEHnWZb4EEzni0ePMqPuPNyuWT4Z+YeXmsgqNuTPIljXFEXhxGsWs9183JkXgHxc1TcsahIg== + dependencies: + autoprefixer "^10.4.12" + cssnano-preset-default "^5.2.13" + postcss-discard-unused "^5.1.0" + postcss-merge-idents "^5.1.1" + postcss-reduce-idents "^5.2.0" + postcss-zindex "^5.1.0" + +cssnano-preset-default@^5.2.13: + version "5.2.13" + resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-5.2.13.tgz#e7353b0c57975d1bdd97ac96e68e5c1b8c68e990" + integrity sha512-PX7sQ4Pb+UtOWuz8A1d+Rbi+WimBIxJTRyBdgGp1J75VU0r/HFQeLnMYgHiCAp6AR4rqrc7Y4R+1Rjk3KJz6DQ== + dependencies: + css-declaration-sorter "^6.3.1" + cssnano-utils "^3.1.0" + postcss-calc "^8.2.3" + postcss-colormin "^5.3.0" + postcss-convert-values "^5.1.3" + postcss-discard-comments "^5.1.2" + postcss-discard-duplicates "^5.1.0" + postcss-discard-empty "^5.1.1" + postcss-discard-overridden "^5.1.0" + postcss-merge-longhand "^5.1.7" + postcss-merge-rules "^5.1.3" + postcss-minify-font-values "^5.1.0" + postcss-minify-gradients "^5.1.1" + postcss-minify-params "^5.1.4" + postcss-minify-selectors "^5.2.1" + postcss-normalize-charset "^5.1.0" + postcss-normalize-display-values "^5.1.0" + postcss-normalize-positions "^5.1.1" + postcss-normalize-repeat-style "^5.1.1" + postcss-normalize-string "^5.1.0" + postcss-normalize-timing-functions "^5.1.0" + postcss-normalize-unicode "^5.1.1" + postcss-normalize-url "^5.1.0" + postcss-normalize-whitespace "^5.1.1" + postcss-ordered-values "^5.1.3" + postcss-reduce-initial "^5.1.1" + postcss-reduce-transforms "^5.1.0" + postcss-svgo "^5.1.0" + postcss-unique-selectors "^5.1.1" + +cssnano-utils@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/cssnano-utils/-/cssnano-utils-3.1.0.tgz#95684d08c91511edfc70d2636338ca37ef3a6861" + integrity sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA== -cssnano@^5.0.6, cssnano@^5.0.8: - version "5.0.10" - resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-5.0.10.tgz#92207eb7c9c6dc08d318050726f9fad0adf7220b" - integrity sha512-YfNhVJJ04imffOpbPbXP2zjIoByf0m8E2c/s/HnvSvjXgzXMfgopVjAEGvxYOjkOpWuRQDg/OZFjO7WW94Ri8w== +cssnano@^5.1.12, cssnano@^5.1.8: + version "5.1.14" + resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-5.1.14.tgz#07b0af6da73641276fe5a6d45757702ebae2eb05" + integrity sha512-Oou7ihiTocbKqi0J1bB+TRJIQX5RMR3JghA8hcWSw9mjBLQ5Y3RWqEDoYG3sRNlAbCIXpqMoZGbq5KDR3vdzgw== dependencies: - cssnano-preset-default "^5.1.6" - is-resolvable "^1.1.0" + cssnano-preset-default "^5.2.13" lilconfig "^2.0.3" yaml "^1.10.2" -csso@^4.0.2, csso@^4.2.0: +csso@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/csso/-/csso-4.2.0.tgz#ea3a561346e8dc9f546d6febedd50187cf389529" integrity sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA== @@ -3024,9 +3287,9 @@ csso@^4.0.2, csso@^4.2.0: css-tree "^1.1.2" csstype@^3.0.2: - version "3.0.9" - resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.0.9.tgz#6410af31b26bd0520933d02cbc64fce9ce3fbf0b" - integrity sha512-rpw6JPxK6Rfg1zLOYCSwle2GFOOsnjmDYDaBwEcwoOg4qlsIVCN789VkBZDJAGi4T07gI4YSutR43t9Zz4Lzuw== + version "3.1.1" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.1.tgz#841b532c45c758ee546a11d5bd7b7b473c8c30b9" + integrity sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw== debug@2.6.9, debug@^2.6.0: version "2.6.9" @@ -3035,38 +3298,19 @@ debug@2.6.9, debug@^2.6.0: dependencies: ms "2.0.0" -debug@^3.1.1: - version "3.2.7" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" - integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== - dependencies: - ms "^2.1.1" - -debug@^4.1.0, debug@^4.1.1: - version "4.3.2" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.2.tgz#f0a49c18ac8779e31d4a0c6029dfb76873c7428b" - integrity sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw== +debug@4, debug@^4.1.0, debug@^4.1.1: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== dependencies: ms "2.1.2" -decompress-response@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" - integrity sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M= - dependencies: - mimic-response "^1.0.0" - -deep-equal@^1.0.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.1.1.tgz#b5c98c942ceffaf7cb051e24e1434a25a2e6076a" - integrity sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g== +decompress-response@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc" + integrity sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ== dependencies: - is-arguments "^1.0.4" - is-date-object "^1.0.1" - is-regex "^1.0.4" - object-is "^1.0.1" - object-keys "^1.1.1" - regexp.prototype.flags "^1.2.0" + mimic-response "^3.1.0" deep-extend@^0.6.0: version "0.6.0" @@ -3078,34 +3322,35 @@ deepmerge@^4.2.2: resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.2.2.tgz#44d2ea3679b8f4d4ffba33f03d865fc1e7bf4955" integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== -default-gateway@^6.0.0: +default-gateway@^6.0.3: version "6.0.3" resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-6.0.3.tgz#819494c888053bdb743edbf343d6cdf7f2943a71" integrity sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg== dependencies: execa "^5.0.0" -defer-to-connect@^1.0.1: - version "1.1.3" - resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591" - integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ== +defer-to-connect@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-2.0.1.tgz#8016bdb4143e4632b77a3449c6236277de520587" + integrity sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg== define-lazy-prop@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og== -define-properties@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" - integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== +define-properties@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.4.tgz#0b14d7bd7fbeb2f3572c3a7eda80ea5d57fb05b1" + integrity sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA== dependencies: - object-keys "^1.0.12" + has-property-descriptors "^1.0.0" + object-keys "^1.1.1" -del@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/del/-/del-6.0.0.tgz#0b40d0332cea743f1614f818be4feb717714c952" - integrity sha512-1shh9DQ23L16oXSZKB2JxpL7iMy2E0S9d517ptA1P8iw0alkPtQcrKH7ru31rYtKwF499HkTu+DRzq3TCKDFRQ== +del@^6.1.1: + version "6.1.1" + resolved "https://registry.yarnpkg.com/del/-/del-6.1.1.tgz#3b70314f1ec0aa325c6b14eb36b95786671edb7a" + integrity sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg== dependencies: globby "^11.0.1" graceful-fs "^4.2.4" @@ -3116,15 +3361,20 @@ del@^6.0.0: rimraf "^3.0.2" slash "^3.0.0" +depd@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" + integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw== + depd@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" - integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= + integrity sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ== -destroy@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" - integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= +destroy@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" + integrity sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg== detab@2.0.4: version "2.0.4" @@ -3147,12 +3397,12 @@ detect-port-alt@^1.1.6: debug "^2.6.0" detect-port@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/detect-port/-/detect-port-1.3.0.tgz#d9c40e9accadd4df5cac6a782aefd014d573d1f1" - integrity sha512-E+B1gzkl2gqxt1IhUzwjrxBKRqx1UzC3WLONHinn8S3T6lwV/agVCyitiFOsGJ/eYuEUBvD71MZHy3Pv1G9doQ== + version "1.5.1" + resolved "https://registry.yarnpkg.com/detect-port/-/detect-port-1.5.1.tgz#451ca9b6eaf20451acb0799b8ab40dff7718727b" + integrity sha512-aBzdj76lueB6uUst5iAs7+0H/oOjqI5D16XUWxlWMIMROhcM0rfsNVk93zTngq1dDNpoXRr++Sus7ETAExppAQ== dependencies: address "^1.0.1" - debug "^2.6.0" + debug "4" dir-glob@^3.0.1: version "3.0.1" @@ -3164,22 +3414,14 @@ dir-glob@^3.0.1: dns-equal@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/dns-equal/-/dns-equal-1.0.0.tgz#b39e7f1da6eb0a75ba9c17324b34753c47e0654d" - integrity sha1-s55/HabrCnW6nBcySzR1PEfgZU0= - -dns-packet@^1.3.1: - version "1.3.4" - resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-1.3.4.tgz#e3455065824a2507ba886c55a89963bb107dec6f" - integrity sha512-BQ6F4vycLXBvdrJZ6S3gZewt6rcrks9KBgM9vrhW+knGRqc8uEdT7fuCwloc7nny5xNoMJ17HGH0R/6fpo8ECA== - dependencies: - ip "^1.1.0" - safe-buffer "^5.0.1" + integrity sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg== -dns-txt@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/dns-txt/-/dns-txt-2.0.2.tgz#b91d806f5d27188e4ab3e7d107d881a1cc4642b6" - integrity sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY= +dns-packet@^5.2.2: + version "5.4.0" + resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-5.4.0.tgz#1f88477cf9f27e78a213fb6d118ae38e759a879b" + integrity sha512-EgqGeaBB8hLiHLZtp/IbaDQTL8pZ0+IvwzSHA6d7VyMDM+B9hgddEMa9xjK5oYnw0ci0JQ6g2XCD7/f6cafU6g== dependencies: - buffer-indexof "^1.0.0" + "@leichtgewicht/ip-codec" "^2.0.1" dom-converter@^0.2.0: version "0.2.0" @@ -3188,72 +3430,44 @@ dom-converter@^0.2.0: dependencies: utila "~0.4" -dom-serializer@0: - version "0.2.2" - resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.2.2.tgz#1afb81f533717175d478655debc5e332d9f9bb51" - integrity sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g== - dependencies: - domelementtype "^2.0.1" - entities "^2.0.0" - dom-serializer@^1.0.1: - version "1.3.2" - resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.3.2.tgz#6206437d32ceefaec7161803230c7a20bc1b4d91" - integrity sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig== + version "1.4.1" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.4.1.tgz#de5d41b1aea290215dc45a6dae8adcf1d32e2d30" + integrity sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag== dependencies: domelementtype "^2.0.1" domhandler "^4.2.0" entities "^2.0.0" -dom-serializer@~0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.1.tgz#1ec4059e284babed36eec2941d4a970a189ce7c0" - integrity sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA== +dom-serializer@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-2.0.0.tgz#e41b802e1eedf9f6cae183ce5e622d789d7d8e53" + integrity sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg== dependencies: - domelementtype "^1.3.0" - entities "^1.1.1" - -domelementtype@1, domelementtype@^1.3.0, domelementtype@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f" - integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w== + domelementtype "^2.3.0" + domhandler "^5.0.2" + entities "^4.2.0" -domelementtype@^2.0.1, domelementtype@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.2.0.tgz#9a0b6c2782ed6a1c7323d42267183df9bd8b1d57" - integrity sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A== - -domhandler@^2.3.0: - version "2.4.2" - resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.2.tgz#8805097e933d65e85546f726d60f5eb88b44f803" - integrity sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA== - dependencies: - domelementtype "1" +domelementtype@^2.0.1, domelementtype@^2.2.0, domelementtype@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d" + integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw== -domhandler@^4.0.0, domhandler@^4.2.0: - version "4.2.2" - resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.2.2.tgz#e825d721d19a86b8c201a35264e226c678ee755f" - integrity sha512-PzE9aBMsdZO8TK4BnuJwH0QT41wgMbRzuZrHUcpYncEjmQazq8QEaBWgLG7ZyC/DAZKEgglpIA6j4Qn/HmxS3w== +domhandler@^4.0.0, domhandler@^4.2.0, domhandler@^4.3.1: + version "4.3.1" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.3.1.tgz#8d792033416f59d68bc03a5aa7b018c1ca89279c" + integrity sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ== dependencies: domelementtype "^2.2.0" -domutils@1.5.1: - version "1.5.1" - resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf" - integrity sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8= - dependencies: - dom-serializer "0" - domelementtype "1" - -domutils@^1.5.1, domutils@^1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a" - integrity sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg== +domhandler@^5.0.1, domhandler@^5.0.2, domhandler@^5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-5.0.3.tgz#cc385f7f751f1d1fc650c21374804254538c7d31" + integrity sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w== dependencies: - dom-serializer "0" - domelementtype "1" + domelementtype "^2.3.0" -domutils@^2.5.2, domutils@^2.6.0: +domutils@^2.5.2, domutils@^2.8.0: version "2.8.0" resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.8.0.tgz#4437def5db6e2d1f5d6ee859bd95ca7d02048135" integrity sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A== @@ -3262,6 +3476,15 @@ domutils@^2.5.2, domutils@^2.6.0: domelementtype "^2.2.0" domhandler "^4.2.0" +domutils@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-3.0.1.tgz#696b3875238338cb186b6c0612bd4901c89a4f1c" + integrity sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q== + dependencies: + dom-serializer "^2.0.0" + domelementtype "^2.3.0" + domhandler "^5.0.1" + dot-case@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-3.0.4.tgz#9b2b670d00a431667a8a75ba29cd1b98809ce751" @@ -3277,31 +3500,36 @@ dot-prop@^5.2.0: dependencies: is-obj "^2.0.0" -duplexer3@^0.1.4: - version "0.1.4" - resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" - integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI= - -duplexer@^0.1.1, duplexer@^0.1.2: +duplexer@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6" integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg== +eastasianwidth@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" + integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== + ee-first@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" - integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= + integrity sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow== -electron-to-chromium@^1.3.886: - version "1.3.890" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.890.tgz#e7143b659f73dc4d0512d1ae4baeb0fb9e7bc835" - integrity sha512-VWlVXSkv0cA/OOehrEyqjUTHwV8YXCPTfPvbtoeU2aHR21vI4Ejh5aC4AxUwOmbLbBgb6Gd3URZahoCxtBqCYQ== +electron-to-chromium@^1.4.251: + version "1.4.284" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz#61046d1e4cab3a25238f6bf7413795270f125592" + integrity sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA== emoji-regex@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== +emoji-regex@^9.2.2: + version "9.2.2" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" + integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== + emojis-list@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" @@ -3315,33 +3543,26 @@ emoticon@^3.2.0: encodeurl@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" - integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= - -end-of-stream@^1.1.0: - version "1.4.4" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" - integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== - dependencies: - once "^1.4.0" + integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w== -enhanced-resolve@^5.8.3: - version "5.8.3" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.8.3.tgz#6d552d465cce0423f5b3d718511ea53826a7b2f0" - integrity sha512-EGAbGvH7j7Xt2nc0E7D99La1OiEs8LnyimkRgwExpUMScN6O+3x9tIWs7PLQZVNx4YD+00skHXPXi1yQHpAmZA== +enhanced-resolve@^5.10.0: + version "5.12.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz#300e1c90228f5b570c4d35babf263f6da7155634" + integrity sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ== dependencies: graceful-fs "^4.2.4" tapable "^2.2.0" -entities@^1.1.1, entities@~1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56" - integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w== - entities@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== +entities@^4.2.0, entities@^4.3.0, entities@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-4.4.0.tgz#97bdaba170339446495e653cfd2db78962900174" + integrity sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA== + error-ex@^1.3.1: version "1.3.2" resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" @@ -3349,46 +3570,11 @@ error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" -es-abstract@^1.17.2, es-abstract@^1.19.1: - version "1.19.1" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.19.1.tgz#d4885796876916959de78edaa0df456627115ec3" - integrity sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w== - dependencies: - call-bind "^1.0.2" - es-to-primitive "^1.2.1" - function-bind "^1.1.1" - get-intrinsic "^1.1.1" - get-symbol-description "^1.0.0" - has "^1.0.3" - has-symbols "^1.0.2" - internal-slot "^1.0.3" - is-callable "^1.2.4" - is-negative-zero "^2.0.1" - is-regex "^1.1.4" - is-shared-array-buffer "^1.0.1" - is-string "^1.0.7" - is-weakref "^1.0.1" - object-inspect "^1.11.0" - object-keys "^1.1.1" - object.assign "^4.1.2" - string.prototype.trimend "^1.0.4" - string.prototype.trimstart "^1.0.4" - unbox-primitive "^1.0.1" - es-module-lexer@^0.9.0: version "0.9.3" resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.9.3.tgz#6f13db00cc38417137daf74366f535c8eb438f19" integrity sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ== -es-to-primitive@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" - integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== - dependencies: - is-callable "^1.1.4" - is-date-object "^1.0.1" - is-symbol "^1.0.2" - escalade@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" @@ -3402,17 +3588,12 @@ escape-goat@^2.0.0: escape-html@^1.0.3, escape-html@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" - integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= + integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= - -escape-string-regexp@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" - integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== + integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== escape-string-regexp@^4.0.0: version "4.0.0" @@ -3462,13 +3643,14 @@ eta@^1.12.3: etag@~1.8.1: version "1.8.1" resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" - integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= + integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== -eval@^0.1.4: - version "0.1.6" - resolved "https://registry.yarnpkg.com/eval/-/eval-0.1.6.tgz#9620d7d8c85515e97e6b47c5814f46ae381cb3cc" - integrity sha512-o0XUw+5OGkXw4pJZzQoXUk+H87DHuC+7ZE//oSrRGtatTmr12oTnLfg6QOq9DyTt0c/p4TwzgmkKrBzWTSizyQ== +eval@^0.1.8: + version "0.1.8" + resolved "https://registry.yarnpkg.com/eval/-/eval-0.1.8.tgz#2b903473b8cc1d1989b83a1e7923f883eb357f85" + integrity sha512-EzV94NYKoO09GLXGjXj9JIlXijVck4ONSr5wiCWDvhsvj5jxSrzTmRU/9C1DyB6uToszLs8aifA6NQ7lEQdvFw== dependencies: + "@types/node" "*" require-like ">= 0.1.1" eventemitter3@^4.0.0: @@ -3476,11 +3658,6 @@ eventemitter3@^4.0.0: resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== -events@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924" - integrity sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ= - events@^3.2.0: version "3.3.0" resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" @@ -3501,38 +3678,39 @@ execa@^5.0.0: signal-exit "^3.0.3" strip-final-newline "^2.0.0" -express@^4.17.1: - version "4.17.1" - resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134" - integrity sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g== +express@^4.17.3: + version "4.18.2" + resolved "https://registry.yarnpkg.com/express/-/express-4.18.2.tgz#3fabe08296e930c796c19e3c516979386ba9fd59" + integrity sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ== dependencies: - accepts "~1.3.7" + accepts "~1.3.8" array-flatten "1.1.1" - body-parser "1.19.0" - content-disposition "0.5.3" + body-parser "1.20.1" + content-disposition "0.5.4" content-type "~1.0.4" - cookie "0.4.0" + cookie "0.5.0" cookie-signature "1.0.6" debug "2.6.9" - depd "~1.1.2" + depd "2.0.0" encodeurl "~1.0.2" escape-html "~1.0.3" etag "~1.8.1" - finalhandler "~1.1.2" + finalhandler "1.2.0" fresh "0.5.2" + http-errors "2.0.0" merge-descriptors "1.0.1" methods "~1.1.2" - on-finished "~2.3.0" + on-finished "2.4.1" parseurl "~1.3.3" path-to-regexp "0.1.7" - proxy-addr "~2.0.5" - qs "6.7.0" + proxy-addr "~2.0.7" + qs "6.11.0" range-parser "~1.2.1" - safe-buffer "5.1.2" - send "0.17.1" - serve-static "1.14.1" - setprototypeof "1.1.1" - statuses "~1.5.0" + safe-buffer "5.2.1" + send "0.18.0" + serve-static "1.15.0" + setprototypeof "1.2.0" + statuses "2.0.1" type-is "~1.6.18" utils-merge "1.0.1" vary "~1.1.2" @@ -3540,7 +3718,7 @@ express@^4.17.1: extend-shallow@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" - integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= + integrity sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug== dependencies: is-extendable "^0.1.0" @@ -3549,15 +3727,15 @@ extend@^3.0.0: resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== -fast-deep-equal@^3.1.1: +fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== -fast-glob@^3.1.1, fast-glob@^3.2.5: - version "3.2.7" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.7.tgz#fd6cb7a2d7e9aa7a7846111e85a196d6b2f766a1" - integrity sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q== +fast-glob@^3.2.11, fast-glob@^3.2.9: + version "3.2.12" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80" + integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w== dependencies: "@nodelib/fs.stat" "^2.0.2" "@nodelib/fs.walk" "^1.2.3" @@ -3573,7 +3751,7 @@ fast-json-stable-stringify@^2.0.0: fast-url-parser@1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/fast-url-parser/-/fast-url-parser-1.1.3.tgz#f4af3ea9f34d8a271cf58ad2b3759f431f0b318d" - integrity sha1-9K8+qfNNiicc9YrSs3WfQx8LMY0= + integrity sha512-5jOCVXADYNuRkKFzNJ0dCCewsZiYo0dz8QNYljkOpFC6r2U4OBmKtvm/Tsuh4w1YYdDqDb31a8TVhBJ2OJKdqQ== dependencies: punycode "^1.3.2" @@ -3603,12 +3781,12 @@ fbjs-css-vars@^1.0.0: resolved "https://registry.yarnpkg.com/fbjs-css-vars/-/fbjs-css-vars-1.0.2.tgz#216551136ae02fe255932c3ec8775f18e2c078b8" integrity sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ== -fbjs@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-3.0.1.tgz#70a053d34a96c2b513b559eaea124daed49ace64" - integrity sha512-8+vkGyT4lNDRKHQNPp0yh/6E7FfkLg89XqQbOYnvntRh+8RiSD43yrh9E5ejp1muCizTL4nDVG+y8W4e+LROHg== +fbjs@^3.0.0, fbjs@^3.0.1: + version "3.0.4" + resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-3.0.4.tgz#e1871c6bd3083bac71ff2da868ad5067d37716c6" + integrity sha512-ucV0tDODnGV3JCnnkmoszb5lf4bNpzjv80K41wd4k798Etq+UYD0y0TIfalLjZoKgjive6/adkRnszwapiDgBQ== dependencies: - cross-fetch "^3.0.4" + cross-fetch "^3.1.5" fbjs-css-vars "^1.0.0" loose-envify "^1.0.0" object-assign "^4.1.0" @@ -3631,10 +3809,10 @@ file-loader@^6.2.0: loader-utils "^2.0.0" schema-utils "^3.0.0" -filesize@^6.1.0: - version "6.4.0" - resolved "https://registry.yarnpkg.com/filesize/-/filesize-6.4.0.tgz#914f50471dd66fdca3cefe628bd0cde4ef769bcd" - integrity sha512-mjFIpOHC4jbfcTfoh4rkWpI31mF7viw9ikj/JyLoKzqlwG/YsefKfvYlYhdYdg/9mtK2z1AzgN/0LvVQ3zdlSQ== +filesize@^8.0.6: + version "8.0.7" + resolved "https://registry.yarnpkg.com/filesize/-/filesize-8.0.7.tgz#695e70d80f4e47012c132d57a059e80c6b580bd8" + integrity sha512-pjmC+bkIF8XI7fWaH8KxHcZL3DPybs1roSKP4rKDvy20tAWwIObE4+JIseG2byfGKhud5ZnM4YSGKBz7Sh0ndQ== fill-range@^7.0.1: version "7.0.1" @@ -3643,17 +3821,17 @@ fill-range@^7.0.1: dependencies: to-regex-range "^5.0.1" -finalhandler@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" - integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== +finalhandler@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32" + integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg== dependencies: debug "2.6.9" encodeurl "~1.0.2" escape-html "~1.0.3" - on-finished "~2.3.0" + on-finished "2.4.1" parseurl "~1.3.3" - statuses "~1.5.0" + statuses "2.0.1" unpipe "~1.0.0" find-cache-dir@^3.3.1: @@ -3672,7 +3850,7 @@ find-up@^3.0.0: dependencies: locate-path "^3.0.0" -find-up@^4.0.0, find-up@^4.1.0: +find-up@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== @@ -3689,22 +3867,22 @@ find-up@^5.0.0: path-exists "^4.0.0" flux@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/flux/-/flux-4.0.2.tgz#d71dcaf6cb51ca059f303f3d964d6f325d444952" - integrity sha512-u/ucO5ezm3nBvdaSGkWpDlzCePoV+a9x3KHmy13TV/5MzOaCZDN8Mfd94jmf0nOi8ZZay+nOKbBUkOe2VNaupQ== + version "4.0.3" + resolved "https://registry.yarnpkg.com/flux/-/flux-4.0.3.tgz#573b504a24982c4768fdfb59d8d2ea5637d72ee7" + integrity sha512-yKAbrp7JhZhj6uiT1FTuVMlIAT1J4jqEyBpFApi1kxpGZCvacMVc/t1pMQyotqHhAgvoE3bNvAykhCo2CLjnYw== dependencies: fbemitter "^3.0.0" - fbjs "^3.0.0" + fbjs "^3.0.1" -follow-redirects@^1.0.0, follow-redirects@^1.14.0: - version "1.14.5" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.5.tgz#f09a5848981d3c772b5392309778523f8d85c381" - integrity sha512-wtphSXy7d4/OR+MvIFbCVBDzZ5520qV8XfPklSN5QtxuMUJZ+b0Wnst1e1lCDocfzuCkHqj8k0FpZqO+UIaKNA== +follow-redirects@>=1.14.9, follow-redirects@^1.0.0, follow-redirects@^1.14, follow-redirects@^1.14.7: + version "1.15.2" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" + integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== -fork-ts-checker-webpack-plugin@^6.0.5: - version "6.4.0" - resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.4.0.tgz#057e477cf1d8b013b2ed2669437f818680289c4c" - integrity sha512-3I3wFkc4DbzaUDPWEi96wdYGu4EKtxBafhZYm0o4mX51d9bphAY4P3mBl8K5mFXFJqVzHfmdbm9kLGnm7vwwBg== +fork-ts-checker-webpack-plugin@^6.5.0: + version "6.5.2" + resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.2.tgz#4f67183f2f9eb8ba7df7177ce3cf3e75cdafb340" + integrity sha512-m5cUmF30xkZ7h4tWUgTAcEaKmUW7tfyUyTqNNOz7OxWJ0v1VWKTcOvH8FWHUwSjlW/356Ijc9vi3XfcPstpQKA== dependencies: "@babel/code-frame" "^7.8.3" "@types/json-schema" "^7.0.5" @@ -3720,25 +3898,30 @@ fork-ts-checker-webpack-plugin@^6.0.5: semver "^7.3.2" tapable "^1.0.0" +form-data-encoder@^2.1.2: + version "2.1.4" + resolved "https://registry.yarnpkg.com/form-data-encoder/-/form-data-encoder-2.1.4.tgz#261ea35d2a70d48d30ec7a9603130fa5515e9cd5" + integrity sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw== + forwarded@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811" integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow== -fraction.js@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.1.1.tgz#ac4e520473dae67012d618aab91eda09bcb400ff" - integrity sha512-MHOhvvxHTfRFpF1geTK9czMIZ6xclsEor2wkIGYYq+PxcQqT7vStJqjhe6S1TenZrMZzo+wlqOufBDVepUEgPg== +fraction.js@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.2.0.tgz#448e5109a313a3527f5a3ab2119ec4cf0e0e2950" + integrity sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA== fresh@0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" - integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= + integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== -fs-extra@^10.0.0: - version "10.0.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.0.0.tgz#9ff61b655dde53fb34a82df84bb214ce802e17c1" - integrity sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ== +fs-extra@^10.1.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf" + integrity sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ== dependencies: graceful-fs "^4.2.0" jsonfile "^6.0.1" @@ -3754,7 +3937,7 @@ fs-extra@^9.0.0: jsonfile "^6.0.1" universalify "^2.0.0" -fs-monkey@1.0.3: +fs-monkey@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/fs-monkey/-/fs-monkey-1.0.3.tgz#ae3ac92d53bb328efe0e9a1d9541f6ad8d48e2d3" integrity sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q== @@ -3762,7 +3945,7 @@ fs-monkey@1.0.3: fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== fsevents@~2.3.2: version "2.3.2" @@ -3779,53 +3962,38 @@ gensync@^1.0.0-beta.1, gensync@^1.0.0-beta.2: resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== -get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.1.tgz#15f59f376f855c446963948f0d24cd3637b4abc6" - integrity sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q== +get-intrinsic@^1.0.2, get-intrinsic@^1.1.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.3.tgz#063c84329ad93e83893c7f4f243ef63ffa351385" + integrity sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A== dependencies: function-bind "^1.1.1" has "^1.0.3" - has-symbols "^1.0.1" + has-symbols "^1.0.3" get-own-enumerable-property-symbols@^3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz#b5fde77f22cbe35f390b4e089922c50bce6ef664" integrity sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g== -get-stream@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" - integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== - dependencies: - pump "^3.0.0" - -get-stream@^5.1.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" - integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA== - dependencies: - pump "^3.0.0" - -get-stream@^6.0.0: +get-stream@^6.0.0, get-stream@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== -get-symbol-description@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6" - integrity sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw== - dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.1.1" - github-slugger@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/github-slugger/-/github-slugger-1.4.0.tgz#206eb96cdb22ee56fdc53a28d5a302338463444e" - integrity sha512-w0dzqw/nt51xMVmlaV1+JRzN+oCa1KfcgGEWhxUG16wbdA+Xnt/yoFO8Z8x/V82ZcZ0wy6ln9QDup5avbhiDhQ== + version "1.5.0" + resolved "https://registry.yarnpkg.com/github-slugger/-/github-slugger-1.5.0.tgz#17891bbc73232051474d68bd867a34625c955f7d" + integrity sha512-wIh+gKBI9Nshz2o46B0B3f5k/W+WI9ZAv6y5Dn5WJ5SK1t0TnDimB4WE5rmTD05ZAIn8HALCZVmCsvj0w0v0lw== + +glob-parent@^5.1.2, glob-parent@~5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" -glob-parent@>5.1.2, glob-parent@^5.1.2, glob-parent@^6.0.0, glob-parent@~5.1.2: +glob-parent@^6.0.1: version "6.0.2" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== @@ -3838,21 +4006,21 @@ glob-to-regexp@^0.4.1: integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== glob@^7.0.0, glob@^7.1.3, glob@^7.1.6: - version "7.2.0" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" - integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== + version "7.2.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== dependencies: fs.realpath "^1.0.0" inflight "^1.0.4" inherits "2" - minimatch "^3.0.4" + minimatch "^3.1.1" once "^1.3.0" path-is-absolute "^1.0.0" global-dirs@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-3.0.0.tgz#70a76fe84ea315ab37b1f5576cbde7d48ef72686" - integrity sha512-v8ho2DS5RiCjftj1nD9NmnfaOzTdud7RRnVd9kFNOjqZbISlx5DQ+OrTkywgd0dIt7oFCvKetZSHoHcP3sDdiA== + version "3.0.1" + resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-3.0.1.tgz#0c488971f066baceda21447aecb1a8b911d22485" + integrity sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA== dependencies: ini "2.0.0" @@ -3877,39 +4045,50 @@ globals@^11.1.0: resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== -globby@^11.0.1, globby@^11.0.2, globby@^11.0.3, globby@^11.0.4: - version "11.0.4" - resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.4.tgz#2cbaff77c2f2a62e71e9b2813a67b97a3a3001a5" - integrity sha512-9O4MVG9ioZJ08ffbcyVYyLOJLk5JQ688pJ4eMGLpdWLHq/Wr1D9BlriLQyL0E+jbkuePVZXYFj47QM/v093wHg== +globby@^11.0.1, globby@^11.0.4, globby@^11.1.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" + integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== dependencies: array-union "^2.1.0" dir-glob "^3.0.1" - fast-glob "^3.1.1" - ignore "^5.1.4" - merge2 "^1.3.0" + fast-glob "^3.2.9" + ignore "^5.2.0" + merge2 "^1.4.1" slash "^3.0.0" -got@^9.6.0: - version "9.6.0" - resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85" - integrity sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q== - dependencies: - "@sindresorhus/is" "^0.14.0" - "@szmarczak/http-timer" "^1.1.2" - cacheable-request "^6.0.0" - decompress-response "^3.3.0" - duplexer3 "^0.1.4" - get-stream "^4.1.0" - lowercase-keys "^1.0.1" - mimic-response "^1.0.1" - p-cancelable "^1.0.0" - to-readable-stream "^1.0.0" - url-parse-lax "^3.0.0" - -graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.6: - version "4.2.8" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.8.tgz#e412b8d33f5e006593cbd3cee6df9f2cebbe802a" - integrity sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg== +globby@^13.1.1: + version "13.1.2" + resolved "https://registry.yarnpkg.com/globby/-/globby-13.1.2.tgz#29047105582427ab6eca4f905200667b056da515" + integrity sha512-LKSDZXToac40u8Q1PQtZihbNdTYSNMuWe+K5l+oa6KgDzSvVrHXlJy40hUP522RjAIoNLJYBJi7ow+rbFpIhHQ== + dependencies: + dir-glob "^3.0.1" + fast-glob "^3.2.11" + ignore "^5.2.0" + merge2 "^1.4.1" + slash "^4.0.0" + +got@>=11.8.5, got@^9.6.0: + version "12.5.3" + resolved "https://registry.yarnpkg.com/got/-/got-12.5.3.tgz#82bdca2dd61258a02e24d668ea6e7abb70ac3598" + integrity sha512-8wKnb9MGU8IPGRIo+/ukTy9XLJBwDiCpIf5TVzQ9Cpol50eMTpBq2GAuDsuDIz7hTYmZgMgC1e9ydr6kSDWs3w== + dependencies: + "@sindresorhus/is" "^5.2.0" + "@szmarczak/http-timer" "^5.0.1" + cacheable-lookup "^7.0.0" + cacheable-request "^10.2.1" + decompress-response "^6.0.0" + form-data-encoder "^2.1.2" + get-stream "^6.0.1" + http2-wrapper "^2.1.10" + lowercase-keys "^3.0.0" + p-cancelable "^3.0.0" + responselike "^3.0.0" + +graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9: + version "4.2.10" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" + integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== gray-matter@^4.0.3: version "4.0.3" @@ -3921,14 +4100,6 @@ gray-matter@^4.0.3: section-matter "^1.0.0" strip-bom-string "^1.0.0" -gzip-size@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-5.1.1.tgz#cb9bee692f87c0612b232840a873904e4c135274" - integrity sha512-FNHi6mmoHvs1mxZAds4PpdCS6QG8B4C1krxJsMutgxl5t3+GlRTzzI3NEkifXx2pVsOvJdOGSmIgDhQ55FwdPA== - dependencies: - duplexer "^0.1.1" - pify "^4.0.1" - gzip-size@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-6.0.0.tgz#065367fd50c239c0671cbcbad5be3e2eeb10e462" @@ -3941,32 +4112,27 @@ handle-thing@^2.0.0: resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.1.tgz#857f79ce359580c340d43081cc648970d0bb234e" integrity sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg== -has-bigints@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.1.tgz#64fe6acb020673e3b78db035a5af69aa9d07b113" - integrity sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA== - has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= + integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== has-flag@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== -has-symbols@^1.0.1, has-symbols@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423" - integrity sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw== - -has-tostringtag@^1.0.0: +has-property-descriptors@^1.0.0: version "1.0.0" - resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" - integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz#610708600606d36961ed04c196193b6a607fa861" + integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ== dependencies: - has-symbols "^1.0.2" + get-intrinsic "^1.1.1" + +has-symbols@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" + integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== has-yarn@^2.1.0: version "2.1.0" @@ -3993,17 +4159,6 @@ hast-to-hyperscript@^9.0.0: unist-util-is "^4.0.0" web-namespaces "^1.0.0" -hast-util-from-parse5@^5.0.0: - version "5.0.3" - resolved "https://registry.yarnpkg.com/hast-util-from-parse5/-/hast-util-from-parse5-5.0.3.tgz#3089dc0ee2ccf6ec8bc416919b51a54a589e097c" - integrity sha512-gOc8UB99F6eWVWFtM9jUikjN7QkWxB3nY0df5Z0Zq1/Nkwl5V4hAAsl0tmwlgWl/1shlTF8DnNYLO8X6wRV9pA== - dependencies: - ccount "^1.0.3" - hastscript "^5.0.0" - property-information "^5.0.0" - web-namespaces "^1.1.2" - xtend "^4.0.1" - hast-util-from-parse5@^6.0.0: version "6.0.1" resolved "https://registry.yarnpkg.com/hast-util-from-parse5/-/hast-util-from-parse5-6.0.1.tgz#554e34abdeea25ac76f5bd950a1f0180e0b3bc2a" @@ -4041,22 +4196,12 @@ hast-util-to-parse5@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/hast-util-to-parse5/-/hast-util-to-parse5-6.0.0.tgz#1ec44650b631d72952066cea9b1445df699f8479" integrity sha512-Lu5m6Lgm/fWuz8eWnrKezHtVY83JeRGaNQ2kn9aJgqaxvVkFCZQBEhgodZUDUvoodgyROHDb3r5IxAEdl6suJQ== - dependencies: - hast-to-hyperscript "^9.0.0" - property-information "^5.0.0" - web-namespaces "^1.0.0" - xtend "^4.0.0" - zwitch "^1.0.0" - -hastscript@^5.0.0: - version "5.1.2" - resolved "https://registry.yarnpkg.com/hastscript/-/hastscript-5.1.2.tgz#bde2c2e56d04c62dd24e8c5df288d050a355fb8a" - integrity sha512-WlztFuK+Lrvi3EggsqOkQ52rKbxkXL3RwB6t5lwoa8QLMemoWfBuL43eDrwOamJyR7uKQKdmKYaBH1NZBiIRrQ== - dependencies: - comma-separated-tokens "^1.0.0" - hast-util-parse-selector "^2.0.0" + dependencies: + hast-to-hyperscript "^9.0.0" property-information "^5.0.0" - space-separated-tokens "^1.0.0" + web-namespaces "^1.0.0" + xtend "^4.0.0" + zwitch "^1.0.0" hastscript@^6.0.0: version "6.0.0" @@ -4096,7 +4241,7 @@ hoist-non-react-statics@^3.1.0: hpack.js@^2.1.6: version "2.1.6" resolved "https://registry.yarnpkg.com/hpack.js/-/hpack.js-2.1.6.tgz#87774c0949e513f42e84575b3c45681fade2a0b2" - integrity sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI= + integrity sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ== dependencies: inherits "^2.0.1" obuf "^1.0.0" @@ -4104,34 +4249,34 @@ hpack.js@^2.1.6: wbuf "^1.1.0" html-entities@^2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.3.2.tgz#760b404685cb1d794e4f4b744332e3b00dcfe488" - integrity sha512-c3Ab/url5ksaT0WyleslpBEthOzWhrjQbg75y7XUsfSzi3Dgzt0l8w5e7DylRn15MTlMMD58dTfzddNS2kcAjQ== + version "2.3.3" + resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.3.3.tgz#117d7626bece327fc8baace8868fa6f5ef856e46" + integrity sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA== -html-minifier-terser@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/html-minifier-terser/-/html-minifier-terser-6.0.2.tgz#14059ad64b69bf9f8b8a33f25b53411d8321e75d" - integrity sha512-AgYO3UGhMYQx2S/FBJT3EM0ZYcKmH6m9XL9c1v77BeK/tYJxGPxT1/AtsdUi4FcP8kZGmqqnItCcjFPcX9hk6A== +html-minifier-terser@^6.0.2, html-minifier-terser@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz#bfc818934cc07918f6b3669f5774ecdfd48f32ab" + integrity sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw== dependencies: camel-case "^4.1.2" - clean-css "^5.1.5" - commander "^8.1.0" + clean-css "^5.2.2" + commander "^8.3.0" he "^1.2.0" param-case "^3.0.4" relateurl "^0.2.7" - terser "^5.7.2" + terser "^5.10.0" -html-tags@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-3.1.0.tgz#7b5e6f7e665e9fb41f30007ed9e0d41e97fb2140" - integrity sha512-1qYz89hW3lFDEazhjW0yVAV87lw8lVkrJocr72XmBkMKsoSVJCQx3W8BXsC7hO2qAt8BoVjYjtAcZ9perqGnNg== +html-tags@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-3.2.0.tgz#dbb3518d20b726524e4dd43de397eb0a95726961" + integrity sha512-vy7ClnArOZwCnqZgvv+ddgHgJiAFXe3Ge9ML5/mBctVJoUoYPCdxVucOywjDARn6CVoh3dRSFdPHy2sX80L0Wg== html-void-elements@^1.0.0: version "1.0.5" resolved "https://registry.yarnpkg.com/html-void-elements/-/html-void-elements-1.0.5.tgz#ce9159494e86d95e45795b166c2021c2cfca4483" integrity sha512-uE/TxKuyNIcx44cIWnjr/rfIATDH7ZaOMmstu0CwhFG1Dunhlp4OC6/NMbhiwoq5BpW0ubi303qnEk/PZj614w== -html-webpack-plugin@^5.4.0: +html-webpack-plugin@^5.5.0: version "5.5.0" resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-5.5.0.tgz#c3911936f57681c1f9f4d8b68c158cd9dfe52f50" integrity sha512-sy88PC2cRTVxvETRgUHFrL4No3UxvcH8G1NepGhqaTT+GXN2kTamqasot0inS5hXeg1cMbFDt27zzo9p35lZVw== @@ -4142,18 +4287,6 @@ html-webpack-plugin@^5.4.0: pretty-error "^4.0.0" tapable "^2.0.0" -htmlparser2@^3.9.1: - version "3.10.1" - resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.10.1.tgz#bd679dc3f59897b6a34bb10749c855bb53a9392f" - integrity sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ== - dependencies: - domelementtype "^1.3.1" - domhandler "^2.3.0" - domutils "^1.5.1" - entities "^1.1.1" - inherits "^2.0.1" - readable-stream "^3.1.1" - htmlparser2@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-6.1.0.tgz#c4d762b6c3371a05dbe65e94ae43a9f845fb8fb7" @@ -4164,7 +4297,17 @@ htmlparser2@^6.1.0: domutils "^2.5.2" entities "^2.0.0" -http-cache-semantics@^4.0.0: +htmlparser2@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-8.0.1.tgz#abaa985474fcefe269bc761a779b544d7196d010" + integrity sha512-4lVbmc1diZC7GUJQtRQ5yBAeUCL1exyMwmForWkRLnwyzWBFxN633SALPMGYaWZvKe9j1pRZJpauvmxENSp/EA== + dependencies: + domelementtype "^2.3.0" + domhandler "^5.0.2" + domutils "^3.0.1" + entities "^4.3.0" + +http-cache-semantics@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390" integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ== @@ -4172,51 +4315,40 @@ http-cache-semantics@^4.0.0: http-deceiver@^1.2.7: version "1.2.7" resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87" - integrity sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc= + integrity sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw== -http-errors@1.7.2: - version "1.7.2" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f" - integrity sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg== +http-errors@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3" + integrity sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ== dependencies: - depd "~1.1.2" - inherits "2.0.3" - setprototypeof "1.1.1" - statuses ">= 1.5.0 < 2" - toidentifier "1.0.0" + depd "2.0.0" + inherits "2.0.4" + setprototypeof "1.2.0" + statuses "2.0.1" + toidentifier "1.0.1" http-errors@~1.6.2: version "1.6.3" resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" - integrity sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0= + integrity sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A== dependencies: depd "~1.1.2" inherits "2.0.3" setprototypeof "1.1.0" statuses ">= 1.4.0 < 2" -http-errors@~1.7.2: - version "1.7.3" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06" - integrity sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw== - dependencies: - depd "~1.1.2" - inherits "2.0.4" - setprototypeof "1.1.1" - statuses ">= 1.5.0 < 2" - toidentifier "1.0.0" - http-parser-js@>=0.5.1: - version "0.5.3" - resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.3.tgz#01d2709c79d41698bb01d4decc5e9da4e4a033d9" - integrity sha512-t7hjvef/5HEK7RWTdUzVUhl8zkEu+LlaE0IYzdMuvbSDipxBRpOn4Uhw8ZyECEa808iVT8XCjzo6xmYt4CiLZg== + version "0.5.8" + resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.8.tgz#af23090d9ac4e24573de6f6aecc9d84a48bf20e3" + integrity sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q== -http-proxy-middleware@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-2.0.1.tgz#7ef3417a479fb7666a571e09966c66a39bd2c15f" - integrity sha512-cfaXRVoZxSed/BmkA7SwBVNI9Kj7HFltaE5rqYOub5kWzWZ+gofV2koVN1j2rMW7pEfSSlCHGJ31xmuyFyfLOg== +http-proxy-middleware@^2.0.3: + version "2.0.6" + resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-2.0.6.tgz#e1a4dd6979572c7ab5a4e4b55095d1f32a74963f" + integrity sha512-ya/UeJ6HVBYxrgYotAZo1KvPWlgB48kUJLDePFeneHsVujFaW5WNj2NgWCAE//B1Dl02BIfYlpNgBy8Kf8Rjmw== dependencies: - "@types/http-proxy" "^1.17.5" + "@types/http-proxy" "^1.17.8" http-proxy "^1.18.1" is-glob "^4.0.1" is-plain-obj "^3.0.0" @@ -4231,6 +4363,14 @@ http-proxy@^1.18.1: follow-redirects "^1.0.0" requires-port "^1.0.0" +http2-wrapper@^2.1.10: + version "2.2.0" + resolved "https://registry.yarnpkg.com/http2-wrapper/-/http2-wrapper-2.2.0.tgz#b80ad199d216b7d3680195077bd7b9060fa9d7f3" + integrity sha512-kZB0wxMo0sh1PehyjJUWRFEd99KC5TLjZ2cULC4f9iqJBAmKQQXEICjxl5iPJRwP40dpeHFqqhm7tYCvODpqpQ== + dependencies: + quick-lru "^5.1.1" + resolve-alpn "^1.2.0" + human-signals@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" @@ -4248,17 +4388,24 @@ icss-utils@^5.0.0, icss-utils@^5.1.0: resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-5.1.0.tgz#c6be6858abd013d768e98366ae47e25d5887b1ae" integrity sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA== -ignore@^5.1.4: - version "5.1.9" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.9.tgz#9ec1a5cbe8e1446ec60d4420060d43aa6e7382fb" - integrity sha512-2zeMQpbKz5dhZ9IwL0gbxSW5w0NK/MSAMtNuhgIHEPmaU3vPdKPL0UdvUCXs5SS4JAwsBxysK5sFMW8ocFiVjQ== +ignore@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" + integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== + +image-size@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/image-size/-/image-size-1.0.2.tgz#d778b6d0ab75b2737c1556dd631652eb963bc486" + integrity sha512-xfOoWjceHntRb3qFCrh5ZFORYH8XCdYpASltMhZ/Q0KZiOwjdE/Yl2QCiWdwD+lygV5bMCvauzgu5PxBX/Yerg== + dependencies: + queue "6.0.2" -immer@^9.0.6: - version "9.0.6" - resolved "https://registry.yarnpkg.com/immer/-/immer-9.0.6.tgz#7a96bf2674d06c8143e327cbf73539388ddf1a73" - integrity sha512-G95ivKpy+EvVAnAab4fVa4YGYn24J1SpEktnJX7JJ45Bd7xqME/SCplFzYFmTbrkwZbQ4xJK1xMTUYBkN6pWsQ== +immer@^9.0.7: + version "9.0.16" + resolved "https://registry.yarnpkg.com/immer/-/immer-9.0.16.tgz#8e7caab80118c2b54b37ad43e05758cdefad0198" + integrity sha512-qenGE7CstVm1NrHQbMh8YaSzTZTFNP3zPqr3YU0S0UY441j4bJTg4A2Hh5KAhwgaiU6ZZ1Ar6y/2f4TblnMReQ== -import-fresh@^3.1.0, import-fresh@^3.2.1, import-fresh@^3.2.2, import-fresh@^3.3.0: +import-fresh@^3.1.0, import-fresh@^3.2.1, import-fresh@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== @@ -4269,27 +4416,27 @@ import-fresh@^3.1.0, import-fresh@^3.2.1, import-fresh@^3.2.2, import-fresh@^3.3 import-lazy@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43" - integrity sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM= + integrity sha512-m7ZEHgtw69qOGw+jwxXkHlrlIPdTGkyh66zXZ1ajZbxkDBNjSY/LGbmjc7h0s2ELsUDTAhFr55TrPSSqJGPG0A== imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" - integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= + integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== indent-string@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== -infima@0.2.0-alpha.34: - version "0.2.0-alpha.34" - resolved "https://registry.yarnpkg.com/infima/-/infima-0.2.0-alpha.34.tgz#14a900d79a4de2013e025ac95749a4592f16ef6e" - integrity sha512-Na6A2Tl56i1p9dzu7VOAT1Kmu3f5buz63Wvd+D9ZZWL6siQ47L7wkEZUICVKFgc5gERFZVZ/PoPB57Kl++h37Q== +infima@0.2.0-alpha.42: + version "0.2.0-alpha.42" + resolved "https://registry.yarnpkg.com/infima/-/infima-0.2.0-alpha.42.tgz#f6e86a655ad40877c6b4d11b2ede681eb5470aa5" + integrity sha512-ift8OXNbQQwtbIt6z16KnSWP7uJ/SysSMFI4F87MNRTicypfl4Pv3E2OGVv6N3nSZFJvA8imYulCBS64iyHYww== inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== dependencies: once "^1.3.0" wrappy "1" @@ -4302,7 +4449,7 @@ inherits@2, inherits@2.0.4, inherits@^2.0.0, inherits@^2.0.1, inherits@^2.0.3, i inherits@2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" - integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= + integrity sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw== ini@2.0.0: version "2.0.0" @@ -4319,41 +4466,19 @@ inline-style-parser@0.1.1: resolved "https://registry.yarnpkg.com/inline-style-parser/-/inline-style-parser-0.1.1.tgz#ec8a3b429274e9c0a1f1c4ffa9453a7fef72cea1" integrity sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q== -internal-ip@^6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/internal-ip/-/internal-ip-6.2.0.tgz#d5541e79716e406b74ac6b07b856ef18dc1621c1" - integrity sha512-D8WGsR6yDt8uq7vDMu7mjcR+yRMm3dW8yufyChmszWRjcSHuxLBkR3GdS2HZAjodsaGuCvXeEJpueisXJULghg== - dependencies: - default-gateway "^6.0.0" - ipaddr.js "^1.9.1" - is-ip "^3.1.0" - p-event "^4.2.0" - -internal-slot@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c" - integrity sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA== - dependencies: - get-intrinsic "^1.1.0" - has "^1.0.3" - side-channel "^1.0.4" - interpret@^1.0.0: version "1.4.0" resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e" integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA== -ip-regex@^4.0.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-4.3.0.tgz#687275ab0f57fa76978ff8f4dddc8a23d5990db5" - integrity sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q== - -ip@^1.1.0: - version "1.1.5" - resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" - integrity sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo= +invariant@^2.2.4: + version "2.2.4" + resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" + integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== + dependencies: + loose-envify "^1.0.0" -ipaddr.js@1.9.1, ipaddr.js@^1.9.1: +ipaddr.js@1.9.1: version "1.9.1" resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== @@ -4363,11 +4488,6 @@ ipaddr.js@^2.0.1: resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.0.1.tgz#eca256a7a877e917aeb368b0a7497ddf42ef81c0" integrity sha512-1qTgH9NG+IIJ4yfKs2e6Pp1bZg8wbDbKHT21HrLIeYBTRLgMYKnMTPAuI3Lcs61nfx5h1xlXnbJtH1kX5/d/ng== -is-absolute-url@^3.0.3: - version "3.0.3" - resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-3.0.3.tgz#96c6a22b6a23929b11ea0afb1836c36ad4a5d698" - integrity sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q== - is-alphabetical@1.0.4, is-alphabetical@^1.0.0: version "1.0.4" resolved "https://registry.yarnpkg.com/is-alphabetical/-/is-alphabetical-1.0.4.tgz#9e7d6b94916be22153745d184c298cbf986a686d" @@ -4381,25 +4501,10 @@ is-alphanumerical@^1.0.0: is-alphabetical "^1.0.0" is-decimal "^1.0.0" -is-arguments@^1.0.4: - version "1.1.1" - resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" - integrity sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - is-arrayish@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= - -is-bigint@^1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" - integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg== - dependencies: - has-bigints "^1.0.1" + integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== is-binary-path@~2.1.0: version "2.1.0" @@ -4408,24 +4513,11 @@ is-binary-path@~2.1.0: dependencies: binary-extensions "^2.0.0" -is-boolean-object@^1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" - integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - is-buffer@^2.0.0: version "2.0.5" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ== -is-callable@^1.1.4, is-callable@^1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.4.tgz#47301d58dd0259407865547853df6d61fe471945" - integrity sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w== - is-ci@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-2.0.0.tgz#6bc6334181810e04b5c22b3d589fdca55026404c" @@ -4433,20 +4525,13 @@ is-ci@^2.0.0: dependencies: ci-info "^2.0.0" -is-core-module@^2.2.0: - version "2.8.0" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.8.0.tgz#0321336c3d0925e497fd97f5d95cb114a5ccd548" - integrity sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw== +is-core-module@^2.9.0: + version "2.11.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.11.0.tgz#ad4cb3e3863e814523c96f3f58d26cc570ff0144" + integrity sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw== dependencies: has "^1.0.3" -is-date-object@^1.0.1: - version "1.0.5" - resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" - integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== - dependencies: - has-tostringtag "^1.0.0" - is-decimal@^1.0.0: version "1.0.4" resolved "https://registry.yarnpkg.com/is-decimal/-/is-decimal-1.0.4.tgz#65a3a5958a1c5b63a706e1b333d7cd9f630d3fa5" @@ -4460,12 +4545,12 @@ is-docker@^2.0.0, is-docker@^2.1.1: is-extendable@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" - integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= + integrity sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw== is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" - integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== is-fullwidth-code-point@^3.0.0: version "3.0.0" @@ -4492,30 +4577,11 @@ is-installed-globally@^0.4.0: global-dirs "^3.0.0" is-path-inside "^3.0.2" -is-ip@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/is-ip/-/is-ip-3.1.0.tgz#2ae5ddfafaf05cb8008a62093cf29734f657c5d8" - integrity sha512-35vd5necO7IitFPjd/YBeqwWnyDWbuLH9ZXQdMfDA8TEo7pv5X8yfrvVO3xbJbLUlERCMvf6X0hTUamQxCYJ9Q== - dependencies: - ip-regex "^4.0.0" - -is-negative-zero@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.1.tgz#3de746c18dda2319241a53675908d8f766f11c24" - integrity sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w== - is-npm@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-5.0.0.tgz#43e8d65cc56e1b67f8d47262cf667099193f45a8" integrity sha512-WW/rQLOazUq+ST/bCAVBp/2oMERWLsR7OrKyt052dNDk4DHcDE0/7QSXITlmi+VBcV13DfIbysG3tZJm5RfdBA== -is-number-object@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.6.tgz#6a7aaf838c7f0686a50b4553f7e54a96494e89f0" - integrity sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g== - dependencies: - has-tostringtag "^1.0.0" - is-number@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" @@ -4524,7 +4590,7 @@ is-number@^7.0.0: is-obj@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" - integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= + integrity sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg== is-obj@^2.0.0: version "2.0.0" @@ -4558,64 +4624,25 @@ is-plain-object@^2.0.4: dependencies: isobject "^3.0.1" -is-regex@^1.0.4, is-regex@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" - integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== - dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" - is-regexp@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069" - integrity sha1-/S2INUXEa6xaYz57mgnof6LLUGk= - -is-resolvable@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" - integrity sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg== + integrity sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA== is-root@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-root/-/is-root-2.1.0.tgz#809e18129cf1129644302a4f8544035d51984a9c" integrity sha512-AGOriNp96vNBd3HtU+RzFEc75FfR5ymiYv8E553I71SCeXBiMsVDUtdio1OEFvrPyLIQ9tVR5RxXIFe5PUFjMg== -is-shared-array-buffer@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz#97b0c85fbdacb59c9c446fe653b82cf2b5b7cfe6" - integrity sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA== - is-stream@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== -is-string@^1.0.5, is-string@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" - integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg== - dependencies: - has-tostringtag "^1.0.0" - -is-symbol@^1.0.2, is-symbol@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c" - integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg== - dependencies: - has-symbols "^1.0.2" - is-typedarray@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" - integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= - -is-weakref@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.1.tgz#842dba4ec17fa9ac9850df2d6efbc1737274f2a2" - integrity sha512-b2jKc2pQZjaeFYWEf7ScFj+Be1I+PXmlu572Q8coTXZ+LD/QQZ7ShPMst8h16riVgyXTQwUsFEl74mDvc/3MHQ== - dependencies: - call-bind "^1.0.0" + integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA== is-whitespace-character@^1.0.0: version "1.0.4" @@ -4627,7 +4654,7 @@ is-word-character@^1.0.0: resolved "https://registry.yarnpkg.com/is-word-character/-/is-word-character-1.0.4.tgz#ce0e73216f98599060592f62ff31354ddbeb0230" integrity sha512-5SMO8RVennx3nZrqtKwCGyyetPE9VDba5ugvKLaD4KopPG5kR4mQ7tNt/r7feL5yt5h3lpuBbIUmCOG2eSzXHA== -is-wsl@^2.1.1, is-wsl@^2.2.0: +is-wsl@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== @@ -4642,40 +4669,62 @@ is-yarn-global@^0.3.0: isarray@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" - integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= + integrity sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ== isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= + integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" - integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== isobject@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" - integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= + integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== + +jest-util@^29.3.1: + version "29.3.1" + resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.3.1.tgz#1dda51e378bbcb7e3bc9d8ab651445591ed373e1" + integrity sha512-7YOVZaiX7RJLv76ZfHt4nbNEzzTRiMW/IiOG7ZOKmTXmoGBxUDefgMAxQubu6WPVqP5zSzAdZG0FfLcC7HOIFQ== + dependencies: + "@jest/types" "^29.3.1" + "@types/node" "*" + chalk "^4.0.0" + ci-info "^3.2.0" + graceful-fs "^4.2.9" + picomatch "^2.2.3" + +jest-worker@^27.4.5: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0" + integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg== + dependencies: + "@types/node" "*" + merge-stream "^2.0.0" + supports-color "^8.0.0" -jest-worker@^27.0.2, jest-worker@^27.0.6: - version "27.3.1" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.3.1.tgz#0def7feae5b8042be38479799aeb7b5facac24b2" - integrity sha512-ks3WCzsiZaOPJl/oMsDjaf0TRiSv7ctNgs0FqRr2nARsovz6AWWy4oLElwcquGSz692DzgZQrCLScPNs5YlC4g== +jest-worker@^29.1.2: + version "29.3.1" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-29.3.1.tgz#e9462161017a9bb176380d721cab022661da3d6b" + integrity sha512-lY4AnnmsEWeiXirAIA0c9SDPbuCBq8IYuDVL8PMm0MZ2PEs2yPvRA/J64QBXuZp7CYKrDM/rmNrc9/i3KJQncw== dependencies: "@types/node" "*" + jest-util "^29.3.1" merge-stream "^2.0.0" supports-color "^8.0.0" -joi@^17.4.0, joi@^17.4.2: - version "17.4.2" - resolved "https://registry.yarnpkg.com/joi/-/joi-17.4.2.tgz#02f4eb5cf88e515e614830239379dcbbe28ce7f7" - integrity sha512-Lm56PP+n0+Z2A2rfRvsfWVDXGEWjXxatPopkQ8qQ5mxCEhwHG+Ettgg5o98FFaxilOxozoa14cFhrE/hOzh/Nw== +joi@^17.6.0: + version "17.7.0" + resolved "https://registry.yarnpkg.com/joi/-/joi-17.7.0.tgz#591a33b1fe1aca2bc27f290bcad9b9c1c570a6b3" + integrity sha512-1/ugc8djfn93rTE3WRKdCzGGt/EtiYKxITMO4Wiv6q5JL1gl9ePt4kBsl1S499nbosspfctIQTpYIhSmHA3WAg== dependencies: "@hapi/hoek" "^9.0.0" "@hapi/topo" "^5.0.0" - "@sideway/address" "^4.1.0" + "@sideway/address" "^4.1.3" "@sideway/formula" "^3.0.0" "@sideway/pinpoint" "^2.0.0" @@ -4692,7 +4741,7 @@ js-yaml@^3.13.1: argparse "^1.0.7" esprima "^4.0.0" -js-yaml@^4.0.0: +js-yaml@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== @@ -4707,19 +4756,14 @@ jsesc@^2.5.1: jsesc@~0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" - integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= - -json-buffer@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898" - integrity sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg= + integrity sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA== -json-parse-better-errors@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" - integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== +json-buffer@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13" + integrity sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ== -json-parse-even-better-errors@^2.3.0: +json-parse-even-better-errors@^2.3.0, json-parse-even-better-errors@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== @@ -4729,19 +4773,15 @@ json-schema-traverse@^0.4.1: resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== -json5@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" - integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== - dependencies: - minimist "^1.2.0" +json-schema-traverse@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" + integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== -json5@^2.1.2: - version "2.2.0" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.0.tgz#2dfefe720c6ba525d9ebd909950f0515316c89a3" - integrity sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA== - dependencies: - minimist "^1.2.5" +json5@^2.1.2, json5@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.1.tgz#655d50ed1e6f95ad1a3caababd2b0efda10b395c" + integrity sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA== jsonfile@^6.0.1: version "6.1.0" @@ -4752,12 +4792,12 @@ jsonfile@^6.0.1: optionalDependencies: graceful-fs "^4.1.6" -keyv@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.1.0.tgz#ecc228486f69991e49e9476485a5be1e8fc5c4d9" - integrity sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA== +keyv@^4.5.2: + version "4.5.2" + resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.2.tgz#0e310ce73bf7851ec702f2eaf46ec4e3805cce56" + integrity sha512-5MHbFaKn8cNSmVW7BYnijeAVlE4cYA/SVkifVgrh7yotnfhKmjuXpDKjrABLnT0SfHWV21P8ow07OGfRrNDg8g== dependencies: - json-buffer "3.0.0" + json-buffer "3.0.1" kind-of@^6.0.0, kind-of@^6.0.2: version "6.0.3" @@ -4769,7 +4809,7 @@ kleur@^3.0.3: resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== -klona@^2.0.4: +klona@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.5.tgz#d166574d90076395d9963aa7a928fabb8d76afbc" integrity sha512-pJiBpiXMbt7dkzXe8Ghj/u4FfXOOa98fPW+bihOJ4SjnoijweJrNThJfd3ifXpXhREjpoF2mZVH1GfS9LV3kHQ== @@ -4787,38 +4827,34 @@ leven@^3.1.0: integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== lilconfig@^2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.0.4.tgz#f4507d043d7058b380b6a8f5cb7bcd4b34cee082" - integrity sha512-bfTIN7lEsiooCocSISTWXkiWJkRqtL9wYtYy+8EK3Y41qh3mpwPU0ycTOgjdY9ErwXCc8QyrQp82bdL0Xkm9yA== + version "2.0.6" + resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.0.6.tgz#32a384558bd58af3d4c6e077dd1ad1d397bc69d4" + integrity sha512-9JROoBW7pobfsx+Sq2JsASvCo6Pfo6WWoUW79HuB1BCoBXD4PLWJPqDF6fNj67pqBYTbAHkE57M1kS/+L1neOg== lines-and-columns@^1.1.6: - version "1.1.6" - resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.1.6.tgz#1c00c743b433cd0a4e80758f7b64a57440d9ff00" - integrity sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA= + version "1.2.4" + resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" + integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== loader-runner@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.2.0.tgz#d7022380d66d14c5fb1d496b89864ebcfd478384" - integrity sha512-92+huvxMvYlMzMt0iIOukcwYBFpkYJdpl2xsZ7LrlayO7E8SOv+JJUEK17B/dJIHAOLMfh2dZZ/Y18WgmGtYNw== - -loader-utils@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.4.0.tgz#c579b5e34cb34b1a74edc6c1fb36bfa371d5a613" - integrity sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA== - dependencies: - big.js "^5.2.2" - emojis-list "^3.0.0" - json5 "^1.0.1" + version "4.3.0" + resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.3.0.tgz#c1b4a163b99f614830353b16755e7149ac2314e1" + integrity sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg== loader-utils@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.2.tgz#d6e3b4fb81870721ae4e0868ab11dd638368c129" - integrity sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A== + version "2.0.4" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.4.tgz#8b5cb38b5c34a9a018ee1fc0e6a066d1dfcc528c" + integrity sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw== dependencies: big.js "^5.2.2" emojis-list "^3.0.0" json5 "^2.1.2" +loader-utils@^3.2.0: + version "3.2.1" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-3.2.1.tgz#4fb104b599daafd82ef3e1a41fb9265f87e1f576" + integrity sha512-ZvFw1KWS3GVyYBYb7qkmRM/WwL2TQQBxgCK62rlvm4WpVQ23Nb4tYjApUlfjrEGvOs7KHEsmyUn75OHZrJMWPw== + locate-path@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" @@ -4841,90 +4877,30 @@ locate-path@^6.0.0: dependencies: p-locate "^5.0.0" -lodash.assignin@^4.0.9: - version "4.2.0" - resolved "https://registry.yarnpkg.com/lodash.assignin/-/lodash.assignin-4.2.0.tgz#ba8df5fb841eb0a3e8044232b0e263a8dc6a28a2" - integrity sha1-uo31+4QesKPoBEIysOJjqNxqKKI= - -lodash.bind@^4.1.4: - version "4.2.1" - resolved "https://registry.yarnpkg.com/lodash.bind/-/lodash.bind-4.2.1.tgz#7ae3017e939622ac31b7d7d7dcb1b34db1690d35" - integrity sha1-euMBfpOWIqwxt9fX3LGzTbFpDTU= - lodash.curry@^4.0.1: version "4.1.1" resolved "https://registry.yarnpkg.com/lodash.curry/-/lodash.curry-4.1.1.tgz#248e36072ede906501d75966200a86dab8b23170" - integrity sha1-JI42By7ekGUB11lmIAqG2riyMXA= + integrity sha512-/u14pXGviLaweY5JI0IUzgzF2J6Ne8INyzAZjImcryjgkZ+ebruBxy2/JaOOkTqScddcYtakjhSaeemV8lR0tA== lodash.debounce@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" - integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168= - -lodash.defaults@^4.0.1: - version "4.2.0" - resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c" - integrity sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw= - -lodash.filter@^4.4.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/lodash.filter/-/lodash.filter-4.6.0.tgz#668b1d4981603ae1cc5a6fa760143e480b4c4ace" - integrity sha1-ZosdSYFgOuHMWm+nYBQ+SAtMSs4= - -lodash.flatten@^4.2.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f" - integrity sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8= + integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow== lodash.flow@^3.3.0: version "3.5.0" resolved "https://registry.yarnpkg.com/lodash.flow/-/lodash.flow-3.5.0.tgz#87bf40292b8cf83e4e8ce1a3ae4209e20071675a" - integrity sha1-h79AKSuM+D5OjOGjrkIJ4gBxZ1o= - -lodash.foreach@^4.3.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.foreach/-/lodash.foreach-4.5.0.tgz#1a6a35eace401280c7f06dddec35165ab27e3e53" - integrity sha1-Gmo16s5AEoDH8G3d7DUWWrJ+PlM= - -lodash.map@^4.4.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/lodash.map/-/lodash.map-4.6.0.tgz#771ec7839e3473d9c4cde28b19394c3562f4f6d3" - integrity sha1-dx7Hg540c9nEzeKLGTlMNWL09tM= + integrity sha512-ff3BX/tSioo+XojX4MOsOMhJw0nZoUEF011LX8g8d3gvjVbxd89cCio4BCXronjxcTUIJUoqKEUA+n4CqvvRPw== lodash.memoize@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" - integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4= - -lodash.merge@^4.4.0: - version "4.6.2" - resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" - integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== - -lodash.pick@^4.2.1: - version "4.4.0" - resolved "https://registry.yarnpkg.com/lodash.pick/-/lodash.pick-4.4.0.tgz#52f05610fff9ded422611441ed1fc123a03001b3" - integrity sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM= - -lodash.reduce@^4.4.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/lodash.reduce/-/lodash.reduce-4.6.0.tgz#f1ab6b839299ad48f784abbf476596f03b914d3b" - integrity sha1-8atrg5KZrUj3hKu/R2WW8DuRTTs= - -lodash.reject@^4.4.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/lodash.reject/-/lodash.reject-4.6.0.tgz#80d6492dc1470864bbf583533b651f42a9f52415" - integrity sha1-gNZJLcFHCGS79YNTO2UfQqn1JBU= - -lodash.some@^4.4.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/lodash.some/-/lodash.some-4.6.0.tgz#1bb9f314ef6b8baded13b549169b2a945eb68e4d" - integrity sha1-G7nzFO9ri63tE7VJFpsqlF62jk0= + integrity sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag== lodash.uniq@4.5.0, lodash.uniq@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" - integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= + integrity sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ== lodash@^4.17.14, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21: version "4.17.21" @@ -4945,15 +4921,10 @@ lower-case@^2.0.2: dependencies: tslib "^2.0.3" -lowercase-keys@^1.0.0, lowercase-keys@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" - integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== - -lowercase-keys@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479" - integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== +lowercase-keys@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-3.0.0.tgz#c5e7d442e37ead247ae9db117a9d0a467c89d4f2" + integrity sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ== lru-cache@^6.0.0: version "6.0.0" @@ -4962,13 +4933,6 @@ lru-cache@^6.0.0: dependencies: yallist "^4.0.0" -magic-string@^0.25.3: - version "0.25.7" - resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.7.tgz#3f497d6fd34c669c6798dcb821f2ef31f5445051" - integrity sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA== - dependencies: - sourcemap-codec "^1.4.4" - make-dir@^3.0.0, make-dir@^3.0.2, make-dir@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" @@ -5019,39 +4983,34 @@ mdn-data@2.0.14: resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.14.tgz#7113fc4281917d63ce29b43446f701e68c25ba50" integrity sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow== -mdn-data@2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.4.tgz#699b3c38ac6f1d728091a64650b65d388502fd5b" - integrity sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA== - mdurl@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e" - integrity sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4= + integrity sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g== media-typer@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" - integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= + integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== -memfs@^3.1.2, memfs@^3.2.2: - version "3.3.0" - resolved "https://registry.yarnpkg.com/memfs/-/memfs-3.3.0.tgz#4da2d1fc40a04b170a56622c7164c6be2c4cbef2" - integrity sha512-BEE62uMfKOavX3iG7GYX43QJ+hAeeWnwIAuJ/R6q96jaMtiLzhsxHJC8B1L7fK7Pt/vXDRwb3SG/yBpNGDPqzg== +memfs@^3.1.2, memfs@^3.4.3: + version "3.4.12" + resolved "https://registry.yarnpkg.com/memfs/-/memfs-3.4.12.tgz#d00f8ad8dab132dc277c659dc85bfd14b07d03bd" + integrity sha512-BcjuQn6vfqP+k100e0E9m61Hyqa//Brp+I3f0OBmN0ATHlFA8vx3Lt8z57R3u2bPqe3WGDBC+nF72fTH7isyEw== dependencies: - fs-monkey "1.0.3" + fs-monkey "^1.0.3" merge-descriptors@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" - integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= + integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w== merge-stream@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== -merge2@^1.3.0: +merge2@^1.3.0, merge2@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== @@ -5059,20 +5018,20 @@ merge2@^1.3.0: methods@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" - integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= + integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== -micromatch@^4.0.2, micromatch@^4.0.4: - version "4.0.4" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.4.tgz#896d519dfe9db25fce94ceb7a500919bf881ebf9" - integrity sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg== +micromatch@^4.0.2, micromatch@^4.0.4, micromatch@^4.0.5: + version "4.0.5" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" + integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== dependencies: - braces "^3.0.1" - picomatch "^2.2.3" + braces "^3.0.2" + picomatch "^2.3.1" -mime-db@1.50.0, "mime-db@>= 1.43.0 < 2": - version "1.50.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.50.0.tgz#abd4ac94e98d3c0e185016c67ab45d5fde40c11f" - integrity sha512-9tMZCDlYHqeERXEHO9f/hKfNXhre5dK2eE/krIvUjZbS2KPcqGDfNShIWS1uW9XOTKQKqK6qbeOci18rbfW77A== +mime-db@1.52.0, "mime-db@>= 1.43.0 < 2": + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== mime-db@~1.33.0: version "1.33.0" @@ -5086,116 +5045,94 @@ mime-types@2.1.18: dependencies: mime-db "~1.33.0" -mime-types@^2.1.27, mime-types@^2.1.31, mime-types@~2.1.17, mime-types@~2.1.24: - version "2.1.33" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.33.tgz#1fa12a904472fafd068e48d9e8401f74d3f70edb" - integrity sha512-plLElXp7pRDd0bNZHw+nMd52vRYjLwQjygaNg7ddJ2uJtTlmnTCjWuPKxVu6//AdaRuME84SvLW91sIkBqGT0g== +mime-types@^2.1.27, mime-types@^2.1.31, mime-types@~2.1.17, mime-types@~2.1.24, mime-types@~2.1.34: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== dependencies: - mime-db "1.50.0" + mime-db "1.52.0" mime@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== -mime@^2.3.1: - version "2.6.0" - resolved "https://registry.yarnpkg.com/mime/-/mime-2.6.0.tgz#a2a682a95cd4d0cb1d6257e28f83da7e35800367" - integrity sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg== - mimic-fn@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== -mimic-response@^1.0.0, mimic-response@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b" - integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ== +mimic-response@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9" + integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ== -mini-create-react-context@^0.4.0: - version "0.4.1" - resolved "https://registry.yarnpkg.com/mini-create-react-context/-/mini-create-react-context-0.4.1.tgz#072171561bfdc922da08a60c2197a497cc2d1d5e" - integrity sha512-YWCYEmd5CQeHGSAKrYvXgmzzkrvssZcuuQDDeqkT+PziKGMgE+0MCCtcKbROzocGBG1meBLl2FotlRwf4gAzbQ== - dependencies: - "@babel/runtime" "^7.12.1" - tiny-warning "^1.0.3" +mimic-response@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-4.0.0.tgz#35468b19e7c75d10f5165ea25e75a5ceea7cf70f" + integrity sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg== -mini-css-extract-plugin@^1.6.0: - version "1.6.2" - resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-1.6.2.tgz#83172b4fd812f8fc4a09d6f6d16f924f53990ca8" - integrity sha512-WhDvO3SjGm40oV5y26GjMJYjd2UMqrLAGKy5YS2/3QKJy2F7jgynuHTir/tgUUOiNQu5saXHdc8reo7YuhhT4Q== +mini-css-extract-plugin@^2.6.1: + version "2.7.0" + resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-2.7.0.tgz#d7d9ba0c5b596d155e36e2b174082fc7f010dd64" + integrity sha512-auqtVo8KhTScMsba7MbijqZTfibbXiBNlPAQbsVt7enQfcDYLdgG57eGxMqwVU3mfeWANY4F1wUg+rMF+ycZgw== dependencies: - loader-utils "^2.0.0" - schema-utils "^3.0.0" - webpack-sources "^1.1.0" + schema-utils "^4.0.0" minimalistic-assert@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== -minimatch@3.0.4, minimatch@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" - integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== +minimatch@3.1.2, minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1: + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== dependencies: brace-expansion "^1.1.7" -minimist@^1.2.0, minimist@^1.2.5: - version "1.2.5" - resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" - integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== +minimist@>=1.2.6, minimist@^1.2, minimist@^1.2.0, minimist@^1.2.5: + version "1.2.7" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.7.tgz#daa1c4d91f507390437c6a8bc01078e7000c4d18" + integrity sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g== -mkdirp@^0.5.5, mkdirp@~0.5.1: - version "0.5.5" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" - integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== - dependencies: - minimist "^1.2.5" +mrmime@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/mrmime/-/mrmime-1.0.1.tgz#5f90c825fad4bdd41dc914eff5d1a8cfdaf24f27" + integrity sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw== ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= - -ms@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" - integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== + integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== ms@2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -ms@^2.1.1: +ms@2.1.3: version "2.1.3" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== -multicast-dns-service-types@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz#899f11d9686e5e05cb91b35d5f0e63b773cfc901" - integrity sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE= - -multicast-dns@^6.0.1: - version "6.2.3" - resolved "https://registry.yarnpkg.com/multicast-dns/-/multicast-dns-6.2.3.tgz#a0ec7bd9055c4282f790c3c82f4e28db3b31b229" - integrity sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g== +multicast-dns@^7.2.5: + version "7.2.5" + resolved "https://registry.yarnpkg.com/multicast-dns/-/multicast-dns-7.2.5.tgz#77eb46057f4d7adbd16d9290fa7299f6fa64cced" + integrity sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg== dependencies: - dns-packet "^1.3.1" + dns-packet "^5.2.2" thunky "^1.0.2" -nanoid@^3.1.30: - version "3.1.30" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.30.tgz#63f93cc548d2a113dc5dfbc63bfa09e2b9b64362" - integrity sha512-zJpuPDwOv8D2zq2WRoMe1HsfZthVewpel9CAvTfc/2mBD1uUT/agc5f7GHGWXlYkFvi1mVxe4IjvP2HNrop7nQ== +nanoid@^3.3.4: + version "3.3.4" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab" + integrity sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw== -negotiator@0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" - integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== +negotiator@0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" + integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg== neo-async@^2.6.2: version "2.6.2" @@ -5217,20 +5154,22 @@ node-emoji@^1.10.0: dependencies: lodash "^4.17.21" -node-fetch@2.6.1: - version "2.6.1" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" - integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== +node-fetch@2.6.7: + version "2.6.7" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" + integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== + dependencies: + whatwg-url "^5.0.0" -node-forge@^0.10.0: - version "0.10.0" - resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.10.0.tgz#32dea2afb3e9926f02ee5ce8794902691a676bf3" - integrity sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA== +node-forge@>=1.3.0, node-forge@^1, node-forge@^1.3: + version "1.3.1" + resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" + integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA== -node-releases@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.1.tgz#3d1d395f204f1f2f29a54358b9fb678765ad2fc5" - integrity sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA== +node-releases@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.6.tgz#8a7088c63a55e493845683ebf3c828d8c51c5503" + integrity sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg== normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" @@ -5240,18 +5179,18 @@ normalize-path@^3.0.0, normalize-path@~3.0.0: normalize-range@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" - integrity sha1-LRDAa9/TEuqXd2laTShDlFa3WUI= - -normalize-url@^4.1.0: - version "4.5.1" - resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.1.tgz#0dd90cf1288ee1d1313b87081c9a5932ee48518a" - integrity sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA== + integrity sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA== normalize-url@^6.0.1: version "6.1.0" resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-6.1.0.tgz#40d0885b535deffe3f3147bec877d05fe4c5668a" integrity sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A== +normalize-url@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-8.0.0.tgz#593dbd284f743e8dcf6a5ddf8fadff149c82701a" + integrity sha512-uVFpKhj5MheNBJRTiMZ9pE/7hD1QTeEvugSJW/OmLzAp78PB5O6adfMNTvmfKhXBkvCzC+rqifWcVYpGFwTjnw== + npm-run-path@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" @@ -5262,82 +5201,49 @@ npm-run-path@^4.0.1: nprogress@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/nprogress/-/nprogress-0.2.0.tgz#cb8f34c53213d895723fcbab907e9422adbcafb1" - integrity sha1-y480xTIT2JVyP8urkH6UIq28r7E= - -nth-check@^1.0.2, nth-check@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.2.tgz#b2bd295c37e3dd58a3bf0700376663ba4d9cf05c" - integrity sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg== - dependencies: - boolbase "~1.0.0" + integrity sha512-I19aIingLgR1fmhftnbWWO3dXc0hSxqHQHQb3H8m+K3TnEn/iSeTZZOyvKXWqQESMwuUVnatlCnZdLBZZt2VSA== -nth-check@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.0.1.tgz#2efe162f5c3da06a28959fbd3db75dbeea9f0fc2" - integrity sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w== +nth-check@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.1.1.tgz#c9eab428effce36cd6b92c924bdb000ef1f1ed1d" + integrity sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w== dependencies: boolbase "^1.0.0" object-assign@^4.1.0, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= + integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== -object-inspect@^1.11.0, object-inspect@^1.9.0: - version "1.11.0" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.11.0.tgz#9dceb146cedd4148a0d9e51ab88d34cf509922b1" - integrity sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg== - -object-is@^1.0.1: - version "1.1.5" - resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac" - integrity sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" +object-inspect@^1.9.0: + version "1.12.2" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea" + integrity sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ== -object-keys@^1.0.12, object-keys@^1.1.1: +object-keys@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== -object.assign@^4.1.0, object.assign@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.2.tgz#0ed54a342eceb37b38ff76eb831a0e788cb63940" - integrity sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ== - dependencies: - call-bind "^1.0.0" - define-properties "^1.1.3" - has-symbols "^1.0.1" - object-keys "^1.1.1" - -object.getownpropertydescriptors@^2.1.0: - version "2.1.3" - resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.3.tgz#b223cf38e17fefb97a63c10c91df72ccb386df9e" - integrity sha512-VdDoCwvJI4QdC6ndjpqFmoL3/+HxffFBbcJzKi5hwLLqqx3mdbedRpfZDdK0SrOSauj8X4GzBvnDZl4vTN7dOw== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.19.1" - -object.values@^1.1.0: - version "1.1.5" - resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.5.tgz#959f63e3ce9ef108720333082131e4a459b716ac" - integrity sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg== +object.assign@^4.1.0: + version "4.1.4" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.4.tgz#9673c7c7c351ab8c4d0b516f4343ebf4dfb7799f" + integrity sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ== dependencies: call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.19.1" + define-properties "^1.1.4" + has-symbols "^1.0.3" + object-keys "^1.1.1" obuf@^1.0.0, obuf@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e" integrity sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg== -on-finished@~2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" - integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= +on-finished@2.4.1: + version "2.4.1" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f" + integrity sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg== dependencies: ee-first "1.1.1" @@ -5346,10 +5252,10 @@ on-headers@~1.0.2: resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f" integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA== -once@^1.3.0, once@^1.3.1, once@^1.4.0: +once@^1.3.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== dependencies: wrappy "1" @@ -5360,15 +5266,7 @@ onetime@^5.1.2: dependencies: mimic-fn "^2.1.0" -open@^7.0.2: - version "7.4.2" - resolved "https://registry.yarnpkg.com/open/-/open-7.4.2.tgz#b8147e26dcf3e426316c730089fd71edd29c2321" - integrity sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q== - dependencies: - is-docker "^2.0.0" - is-wsl "^2.1.1" - -open@^8.0.9: +open@^8.0.9, open@^8.4.0: version "8.4.0" resolved "https://registry.yarnpkg.com/open/-/open-8.4.0.tgz#345321ae18f8138f82565a910fdc6b39e8c244f8" integrity sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q== @@ -5382,22 +5280,10 @@ opener@^1.5.2: resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.2.tgz#5d37e1f35077b9dcac4301372271afdeb2a13598" integrity sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A== -p-cancelable@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc" - integrity sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw== - -p-event@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/p-event/-/p-event-4.2.0.tgz#af4b049c8acd91ae81083ebd1e6f5cae2044c1b5" - integrity sha512-KXatOjCRXXkSePPb1Nbi0p0m+gQAwdlbhi4wQKJPI1HsMQS9g+Sqp2o+QHziPr7eYJyOZet836KoHEVM1mwOrQ== - dependencies: - p-timeout "^3.1.0" - -p-finally@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" - integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= +p-cancelable@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-3.0.0.tgz#63826694b54d61ca1c20ebcb6d3ecf5e14cd8050" + integrity sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw== p-limit@^2.0.0, p-limit@^2.2.0: version "2.3.0" @@ -5406,7 +5292,7 @@ p-limit@^2.0.0, p-limit@^2.2.0: dependencies: p-try "^2.0.0" -p-limit@^3.0.2, p-limit@^3.1.0: +p-limit@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== @@ -5442,20 +5328,13 @@ p-map@^4.0.0: aggregate-error "^3.0.0" p-retry@^4.5.0: - version "4.6.1" - resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-4.6.1.tgz#8fcddd5cdf7a67a0911a9cf2ef0e5df7f602316c" - integrity sha512-e2xXGNhZOZ0lfgR9kL34iGlU8N/KO0xZnQxVEwdeOvpqNDQfdnxIYizvWtK8RglUa3bGqI8g0R/BdfzLMxRkiA== + version "4.6.2" + resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-4.6.2.tgz#9baae7184057edd4e17231cee04264106e092a16" + integrity sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ== dependencies: - "@types/retry" "^0.12.0" + "@types/retry" "0.12.0" retry "^0.13.1" -p-timeout@^3.1.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-3.2.0.tgz#c7e17abc971d2a7962ef83626b35d635acf23dfe" - integrity sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg== - dependencies: - p-finally "^1.0.0" - p-try@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" @@ -5513,16 +5392,26 @@ parse-numeric-range@^1.3.0: resolved "https://registry.yarnpkg.com/parse-numeric-range/-/parse-numeric-range-1.3.0.tgz#7c63b61190d61e4d53a1197f0c83c47bb670ffa3" integrity sha512-twN+njEipszzlMJd4ONUYgSfZPDxgHhT9Ahed5uTigpQn90FggW4SA/AIPq/6a149fTbE9qBEcSwE3FAEp6wQQ== -parse5@^5.0.0: - version "5.1.1" - resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.1.tgz#f68e4e5ba1852ac2cadc00f4555fff6c2abb6178" - integrity sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug== +parse5-htmlparser2-tree-adapter@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz#23c2cc233bcf09bb7beba8b8a69d46b08c62c2f1" + integrity sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g== + dependencies: + domhandler "^5.0.2" + parse5 "^7.0.0" parse5@^6.0.0: version "6.0.1" resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b" integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw== +parse5@^7.0.0: + version "7.1.2" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-7.1.2.tgz#0736bebbfd77793823240a23b7fc5e010b7f8e32" + integrity sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw== + dependencies: + entities "^4.4.0" + parseurl@~1.3.2, parseurl@~1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" @@ -5539,7 +5428,7 @@ pascal-case@^3.1.2: path-exists@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" - integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= + integrity sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ== path-exists@^4.0.0: version "4.0.0" @@ -5549,19 +5438,19 @@ path-exists@^4.0.0: path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== path-is-inside@1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" - integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM= + integrity sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w== path-key@^3.0.0, path-key@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== -path-parse@^1.0.6: +path-parse@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== @@ -5569,7 +5458,7 @@ path-parse@^1.0.6: path-to-regexp@0.1.7: version "0.1.7" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" - integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= + integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== path-to-regexp@2.2.1: version "2.2.1" @@ -5593,15 +5482,10 @@ picocolors@^1.0.0: resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== -picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3: - version "2.3.0" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972" - integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw== - -pify@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" - integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3, picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== pkg-dir@^4.1.0: version "4.2.0" @@ -5617,137 +5501,124 @@ pkg-up@^3.1.0: dependencies: find-up "^3.0.0" -portfinder@^1.0.28: - version "1.0.28" - resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.28.tgz#67c4622852bd5374dd1dd900f779f53462fac778" - integrity sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA== +postcss-calc@^8.2.3: + version "8.2.4" + resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-8.2.4.tgz#77b9c29bfcbe8a07ff6693dc87050828889739a5" + integrity sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q== dependencies: - async "^2.6.2" - debug "^3.1.1" - mkdirp "^0.5.5" + postcss-selector-parser "^6.0.9" + postcss-value-parser "^4.2.0" -postcss-calc@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-8.0.0.tgz#a05b87aacd132740a5db09462a3612453e5df90a" - integrity sha512-5NglwDrcbiy8XXfPM11F3HeC6hoT9W7GUH/Zi5U/p7u3Irv4rHhdDcIZwG0llHXV4ftsBjpfWMXAnXNl4lnt8g== - dependencies: - postcss-selector-parser "^6.0.2" - postcss-value-parser "^4.0.2" - -postcss-colormin@^5.2.1: - version "5.2.1" - resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-5.2.1.tgz#6e444a806fd3c578827dbad022762df19334414d" - integrity sha512-VVwMrEYLcHYePUYV99Ymuoi7WhKrMGy/V9/kTS0DkCoJYmmjdOMneyhzYUxcNgteKDVbrewOkSM7Wje/MFwxzA== +postcss-colormin@^5.3.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-5.3.0.tgz#3cee9e5ca62b2c27e84fce63affc0cfb5901956a" + integrity sha512-WdDO4gOFG2Z8n4P8TWBpshnL3JpmNmJwdnfP2gbk2qBA8PWwOYcmjmI/t3CmMeL72a7Hkd+x/Mg9O2/0rD54Pg== dependencies: browserslist "^4.16.6" caniuse-api "^3.0.0" colord "^2.9.1" - postcss-value-parser "^4.1.0" + postcss-value-parser "^4.2.0" -postcss-convert-values@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-5.0.2.tgz#879b849dc3677c7d6bc94b6a2c1a3f0808798059" - integrity sha512-KQ04E2yadmfa1LqXm7UIDwW1ftxU/QWZmz6NKnHnUvJ3LEYbbcX6i329f/ig+WnEByHegulocXrECaZGLpL8Zg== +postcss-convert-values@^5.1.3: + version "5.1.3" + resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-5.1.3.tgz#04998bb9ba6b65aa31035d669a6af342c5f9d393" + integrity sha512-82pC1xkJZtcJEfiLw6UXnXVXScgtBrjlO5CBmuDQc+dlb88ZYheFsjTn40+zBVi3DkfF7iezO0nJUPLcJK3pvA== dependencies: - postcss-value-parser "^4.1.0" + browserslist "^4.21.4" + postcss-value-parser "^4.2.0" -postcss-discard-comments@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-5.0.1.tgz#9eae4b747cf760d31f2447c27f0619d5718901fe" - integrity sha512-lgZBPTDvWrbAYY1v5GYEv8fEO/WhKOu/hmZqmCYfrpD6eyDWWzAOsl2rF29lpvziKO02Gc5GJQtlpkTmakwOWg== +postcss-discard-comments@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-5.1.2.tgz#8df5e81d2925af2780075840c1526f0660e53696" + integrity sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ== -postcss-discard-duplicates@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-5.0.1.tgz#68f7cc6458fe6bab2e46c9f55ae52869f680e66d" - integrity sha512-svx747PWHKOGpAXXQkCc4k/DsWo+6bc5LsVrAsw+OU+Ibi7klFZCyX54gjYzX4TH+f2uzXjRviLARxkMurA2bA== +postcss-discard-duplicates@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-5.1.0.tgz#9eb4fe8456706a4eebd6d3b7b777d07bad03e848" + integrity sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw== -postcss-discard-empty@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-5.0.1.tgz#ee136c39e27d5d2ed4da0ee5ed02bc8a9f8bf6d8" - integrity sha512-vfU8CxAQ6YpMxV2SvMcMIyF2LX1ZzWpy0lqHDsOdaKKLQVQGVP1pzhrI9JlsO65s66uQTfkQBKBD/A5gp9STFw== +postcss-discard-empty@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-5.1.1.tgz#e57762343ff7f503fe53fca553d18d7f0c369c6c" + integrity sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A== -postcss-discard-overridden@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-5.0.1.tgz#454b41f707300b98109a75005ca4ab0ff2743ac6" - integrity sha512-Y28H7y93L2BpJhrdUR2SR2fnSsT+3TVx1NmVQLbcnZWwIUpJ7mfcTC6Za9M2PG6w8j7UQRfzxqn8jU2VwFxo3Q== +postcss-discard-overridden@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-5.1.0.tgz#7e8c5b53325747e9d90131bb88635282fb4a276e" + integrity sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw== -postcss-discard-unused@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/postcss-discard-unused/-/postcss-discard-unused-5.0.1.tgz#63e35a74a154912f93d4e75a1e6ff3cc146f934b" - integrity sha512-tD6xR/xyZTwfhKYRw0ylfCY8wbfhrjpKAMnDKRTLMy2fNW5hl0hoV6ap5vo2JdCkuHkP3CHw72beO4Y8pzFdww== +postcss-discard-unused@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/postcss-discard-unused/-/postcss-discard-unused-5.1.0.tgz#8974e9b143d887677304e558c1166d3762501142" + integrity sha512-KwLWymI9hbwXmJa0dkrzpRbSJEh0vVUd7r8t0yOGPcfKzyJJxFM8kLyC5Ev9avji6nY95pOp1W6HqIrfT+0VGw== dependencies: postcss-selector-parser "^6.0.5" -postcss-loader@^6.1.1: - version "6.2.0" - resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-6.2.0.tgz#714370a3f567141cf4cadcdf9575f5234d186bc5" - integrity sha512-H9hv447QjQJVDbHj3OUdciyAXY3v5+UDduzEytAlZCVHCpNAAg/mCSwhYYqZr9BiGYhmYspU8QXxZwiHTLn3yA== +postcss-loader@^7.0.0: + version "7.0.1" + resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-7.0.1.tgz#4c883cc0a1b2bfe2074377b7a74c1cd805684395" + integrity sha512-VRviFEyYlLjctSM93gAZtcJJ/iSkPZ79zWbN/1fSH+NisBByEiVLqpdVDrPLVSi8DX0oJo12kL/GppTBdKVXiQ== dependencies: cosmiconfig "^7.0.0" - klona "^2.0.4" - semver "^7.3.5" + klona "^2.0.5" + semver "^7.3.7" -postcss-merge-idents@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/postcss-merge-idents/-/postcss-merge-idents-5.0.1.tgz#6b5856fc28f2571f28ecce49effb9b0e64be9437" - integrity sha512-xu8ueVU0RszbI2gKkxR6mluupsOSSLvt8q4gA2fcKFkA+x6SlH3cb4cFHpDvcRCNFbUmCR/VUub+Y6zPOjPx+Q== +postcss-merge-idents@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/postcss-merge-idents/-/postcss-merge-idents-5.1.1.tgz#7753817c2e0b75d0853b56f78a89771e15ca04a1" + integrity sha512-pCijL1TREiCoog5nQp7wUe+TUonA2tC2sQ54UGeMmryK3UFGIYKqDyjnqd6RcuI4znFn9hWSLNN8xKE/vWcUQw== dependencies: - cssnano-utils "^2.0.1" - postcss-value-parser "^4.1.0" + cssnano-utils "^3.1.0" + postcss-value-parser "^4.2.0" -postcss-merge-longhand@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-5.0.3.tgz#42194a5ffbaa5513edbf606ef79c44958564658b" - integrity sha512-kmB+1TjMTj/bPw6MCDUiqSA5e/x4fvLffiAdthra3a0m2/IjTrWsTmD3FdSskzUjEwkj5ZHBDEbv5dOcqD7CMQ== +postcss-merge-longhand@^5.1.7: + version "5.1.7" + resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-5.1.7.tgz#24a1bdf402d9ef0e70f568f39bdc0344d568fb16" + integrity sha512-YCI9gZB+PLNskrK0BB3/2OzPnGhPkBEwmwhfYk1ilBHYVAZB7/tkTHFBAnCrvBBOmeYyMYw3DMjT55SyxMBzjQ== dependencies: - css-color-names "^1.0.1" - postcss-value-parser "^4.1.0" - stylehacks "^5.0.1" + postcss-value-parser "^4.2.0" + stylehacks "^5.1.1" -postcss-merge-rules@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-5.0.2.tgz#d6e4d65018badbdb7dcc789c4f39b941305d410a" - integrity sha512-5K+Md7S3GwBewfB4rjDeol6V/RZ8S+v4B66Zk2gChRqLTCC8yjnHQ601omj9TKftS19OPGqZ/XzoqpzNQQLwbg== +postcss-merge-rules@^5.1.3: + version "5.1.3" + resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-5.1.3.tgz#8f97679e67cc8d08677a6519afca41edf2220894" + integrity sha512-LbLd7uFC00vpOuMvyZop8+vvhnfRGpp2S+IMQKeuOZZapPRY4SMq5ErjQeHbHsjCUgJkRNrlU+LmxsKIqPKQlA== dependencies: - browserslist "^4.16.6" + browserslist "^4.21.4" caniuse-api "^3.0.0" - cssnano-utils "^2.0.1" + cssnano-utils "^3.1.0" postcss-selector-parser "^6.0.5" - vendors "^1.0.3" -postcss-minify-font-values@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-5.0.1.tgz#a90cefbfdaa075bd3dbaa1b33588bb4dc268addf" - integrity sha512-7JS4qIsnqaxk+FXY1E8dHBDmraYFWmuL6cgt0T1SWGRO5bzJf8sUoelwa4P88LEWJZweHevAiDKxHlofuvtIoA== +postcss-minify-font-values@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-5.1.0.tgz#f1df0014a726083d260d3bd85d7385fb89d1f01b" + integrity sha512-el3mYTgx13ZAPPirSVsHqFzl+BBBDrXvbySvPGFnQcTI4iNslrPaFq4muTkLZmKlGk4gyFAYUBMH30+HurREyA== dependencies: - postcss-value-parser "^4.1.0" + postcss-value-parser "^4.2.0" -postcss-minify-gradients@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-5.0.3.tgz#f970a11cc71e08e9095e78ec3a6b34b91c19550e" - integrity sha512-Z91Ol22nB6XJW+5oe31+YxRsYooxOdFKcbOqY/V8Fxse1Y3vqlNRpi1cxCqoACZTQEhl+xvt4hsbWiV5R+XI9Q== +postcss-minify-gradients@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-5.1.1.tgz#f1fe1b4f498134a5068240c2f25d46fcd236ba2c" + integrity sha512-VGvXMTpCEo4qHTNSa9A0a3D+dxGFZCYwR6Jokk+/3oB6flu2/PnPXAh2x7x52EkY5xlIHLm+Le8tJxe/7TNhzw== dependencies: colord "^2.9.1" - cssnano-utils "^2.0.1" - postcss-value-parser "^4.1.0" + cssnano-utils "^3.1.0" + postcss-value-parser "^4.2.0" -postcss-minify-params@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-5.0.1.tgz#371153ba164b9d8562842fdcd929c98abd9e5b6c" - integrity sha512-4RUC4k2A/Q9mGco1Z8ODc7h+A0z7L7X2ypO1B6V8057eVK6mZ6xwz6QN64nHuHLbqbclkX1wyzRnIrdZehTEHw== +postcss-minify-params@^5.1.4: + version "5.1.4" + resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-5.1.4.tgz#c06a6c787128b3208b38c9364cfc40c8aa5d7352" + integrity sha512-+mePA3MgdmVmv6g+30rn57USjOGSAyuxUmkfiWpzalZ8aiBkdPYjXWtHuwJGm1v5Ojy0Z0LaSYhHaLJQB0P8Jw== dependencies: - alphanum-sort "^1.0.2" - browserslist "^4.16.0" - cssnano-utils "^2.0.1" - postcss-value-parser "^4.1.0" - uniqs "^2.0.0" + browserslist "^4.21.4" + cssnano-utils "^3.1.0" + postcss-value-parser "^4.2.0" -postcss-minify-selectors@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-5.1.0.tgz#4385c845d3979ff160291774523ffa54eafd5a54" - integrity sha512-NzGBXDa7aPsAcijXZeagnJBKBPMYLaJJzB8CQh6ncvyl2sIndLVWfbcDi0SBjRWk5VqEjXvf8tYwzoKf4Z07og== +postcss-minify-selectors@^5.2.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-5.2.1.tgz#d4e7e6b46147b8117ea9325a915a801d5fe656c6" + integrity sha512-nPJu7OjZJTsVUmPdm2TcaiohIwxP+v8ha9NehQ2ye9szv4orirRU3SDdtUmKH+10nzn0bAyOXZ0UEr7OpvLehg== dependencies: - alphanum-sort "^1.0.2" postcss-selector-parser "^6.0.5" postcss-modules-extract-imports@^3.0.0: @@ -5778,159 +5649,147 @@ postcss-modules-values@^4.0.0: dependencies: icss-utils "^5.0.0" -postcss-normalize-charset@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-5.0.1.tgz#121559d1bebc55ac8d24af37f67bd4da9efd91d0" - integrity sha512-6J40l6LNYnBdPSk+BHZ8SF+HAkS4q2twe5jnocgd+xWpz/mx/5Sa32m3W1AA8uE8XaXN+eg8trIlfu8V9x61eg== +postcss-normalize-charset@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz#9302de0b29094b52c259e9b2cf8dc0879879f0ed" + integrity sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg== -postcss-normalize-display-values@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-display-values/-/postcss-normalize-display-values-5.0.1.tgz#62650b965981a955dffee83363453db82f6ad1fd" - integrity sha512-uupdvWk88kLDXi5HEyI9IaAJTE3/Djbcrqq8YgjvAVuzgVuqIk3SuJWUisT2gaJbZm1H9g5k2w1xXilM3x8DjQ== +postcss-normalize-display-values@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-display-values/-/postcss-normalize-display-values-5.1.0.tgz#72abbae58081960e9edd7200fcf21ab8325c3da8" + integrity sha512-WP4KIM4o2dazQXWmFaqMmcvsKmhdINFblgSeRgn8BJ6vxaMyaJkwAzpPpuvSIoG/rmX3M+IrRZEz2H0glrQNEA== dependencies: - cssnano-utils "^2.0.1" - postcss-value-parser "^4.1.0" + postcss-value-parser "^4.2.0" -postcss-normalize-positions@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-positions/-/postcss-normalize-positions-5.0.1.tgz#868f6af1795fdfa86fbbe960dceb47e5f9492fe5" - integrity sha512-rvzWAJai5xej9yWqlCb1OWLd9JjW2Ex2BCPzUJrbaXmtKtgfL8dBMOOMTX6TnvQMtjk3ei1Lswcs78qKO1Skrg== +postcss-normalize-positions@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/postcss-normalize-positions/-/postcss-normalize-positions-5.1.1.tgz#ef97279d894087b59325b45c47f1e863daefbb92" + integrity sha512-6UpCb0G4eofTCQLFVuI3EVNZzBNPiIKcA1AKVka+31fTVySphr3VUgAIULBhxZkKgwLImhzMR2Bw1ORK+37INg== dependencies: - postcss-value-parser "^4.1.0" + postcss-value-parser "^4.2.0" -postcss-normalize-repeat-style@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.0.1.tgz#cbc0de1383b57f5bb61ddd6a84653b5e8665b2b5" - integrity sha512-syZ2itq0HTQjj4QtXZOeefomckiV5TaUO6ReIEabCh3wgDs4Mr01pkif0MeVwKyU/LHEkPJnpwFKRxqWA/7O3w== +postcss-normalize-repeat-style@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.1.1.tgz#e9eb96805204f4766df66fd09ed2e13545420fb2" + integrity sha512-mFpLspGWkQtBcWIRFLmewo8aC3ImN2i/J3v8YCFUwDnPu3Xz4rLohDO26lGjwNsQxB3YF0KKRwspGzE2JEuS0g== dependencies: - cssnano-utils "^2.0.1" - postcss-value-parser "^4.1.0" + postcss-value-parser "^4.2.0" -postcss-normalize-string@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-string/-/postcss-normalize-string-5.0.1.tgz#d9eafaa4df78c7a3b973ae346ef0e47c554985b0" - integrity sha512-Ic8GaQ3jPMVl1OEn2U//2pm93AXUcF3wz+OriskdZ1AOuYV25OdgS7w9Xu2LO5cGyhHCgn8dMXh9bO7vi3i9pA== +postcss-normalize-string@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-string/-/postcss-normalize-string-5.1.0.tgz#411961169e07308c82c1f8c55f3e8a337757e228" + integrity sha512-oYiIJOf4T9T1N4i+abeIc7Vgm/xPCGih4bZz5Nm0/ARVJ7K6xrDlLwvwqOydvyL3RHNf8qZk6vo3aatiw/go3w== dependencies: - postcss-value-parser "^4.1.0" + postcss-value-parser "^4.2.0" -postcss-normalize-timing-functions@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.0.1.tgz#8ee41103b9130429c6cbba736932b75c5e2cb08c" - integrity sha512-cPcBdVN5OsWCNEo5hiXfLUnXfTGtSFiBU9SK8k7ii8UD7OLuznzgNRYkLZow11BkQiiqMcgPyh4ZqXEEUrtQ1Q== +postcss-normalize-timing-functions@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.1.0.tgz#d5614410f8f0b2388e9f240aa6011ba6f52dafbb" + integrity sha512-DOEkzJ4SAXv5xkHl0Wa9cZLF3WCBhF3o1SKVxKQAa+0pYKlueTpCgvkFAHfk+Y64ezX9+nITGrDZeVGgITJXjg== dependencies: - cssnano-utils "^2.0.1" - postcss-value-parser "^4.1.0" + postcss-value-parser "^4.2.0" -postcss-normalize-unicode@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-unicode/-/postcss-normalize-unicode-5.0.1.tgz#82d672d648a411814aa5bf3ae565379ccd9f5e37" - integrity sha512-kAtYD6V3pK0beqrU90gpCQB7g6AOfP/2KIPCVBKJM2EheVsBQmx/Iof+9zR9NFKLAx4Pr9mDhogB27pmn354nA== +postcss-normalize-unicode@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/postcss-normalize-unicode/-/postcss-normalize-unicode-5.1.1.tgz#f67297fca3fea7f17e0d2caa40769afc487aa030" + integrity sha512-qnCL5jzkNUmKVhZoENp1mJiGNPcsJCs1aaRmURmeJGES23Z/ajaln+EPTD+rBeNkSryI+2WTdW+lwcVdOikrpA== dependencies: - browserslist "^4.16.0" - postcss-value-parser "^4.1.0" + browserslist "^4.21.4" + postcss-value-parser "^4.2.0" -postcss-normalize-url@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-5.0.2.tgz#ddcdfb7cede1270740cf3e4dfc6008bd96abc763" - integrity sha512-k4jLTPUxREQ5bpajFQZpx8bCF2UrlqOTzP9kEqcEnOfwsRshWs2+oAFIHfDQB8GO2PaUaSE0NlTAYtbluZTlHQ== +postcss-normalize-url@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-5.1.0.tgz#ed9d88ca82e21abef99f743457d3729a042adcdc" + integrity sha512-5upGeDO+PVthOxSmds43ZeMeZfKH+/DKgGRD7TElkkyS46JXAUhMzIKiCa7BabPeIy3AQcTkXwVVN7DbqsiCew== dependencies: - is-absolute-url "^3.0.3" normalize-url "^6.0.1" - postcss-value-parser "^4.1.0" + postcss-value-parser "^4.2.0" -postcss-normalize-whitespace@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.0.1.tgz#b0b40b5bcac83585ff07ead2daf2dcfbeeef8e9a" - integrity sha512-iPklmI5SBnRvwceb/XH568yyzK0qRVuAG+a1HFUsFRf11lEJTiQQa03a4RSCQvLKdcpX7XsI1Gen9LuLoqwiqA== +postcss-normalize-whitespace@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.1.1.tgz#08a1a0d1ffa17a7cc6efe1e6c9da969cc4493cfa" + integrity sha512-83ZJ4t3NUDETIHTa3uEg6asWjSBYL5EdkVB0sDncx9ERzOKBVJIUeDO9RyA9Zwtig8El1d79HBp0JEi8wvGQnA== dependencies: - postcss-value-parser "^4.1.0" + postcss-value-parser "^4.2.0" -postcss-ordered-values@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-5.0.2.tgz#1f351426977be00e0f765b3164ad753dac8ed044" - integrity sha512-8AFYDSOYWebJYLyJi3fyjl6CqMEG/UVworjiyK1r573I56kb3e879sCJLGvR3merj+fAdPpVplXKQZv+ey6CgQ== +postcss-ordered-values@^5.1.3: + version "5.1.3" + resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-5.1.3.tgz#b6fd2bd10f937b23d86bc829c69e7732ce76ea38" + integrity sha512-9UO79VUhPwEkzbb3RNpqqghc6lcYej1aveQteWY+4POIwlqkYE21HKWaLDF6lWNuqCobEAyTovVhtI32Rbv2RQ== dependencies: - cssnano-utils "^2.0.1" - postcss-value-parser "^4.1.0" + cssnano-utils "^3.1.0" + postcss-value-parser "^4.2.0" -postcss-reduce-idents@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/postcss-reduce-idents/-/postcss-reduce-idents-5.0.1.tgz#99b49ce8ee6f9c179447671cc9693e198e877bb7" - integrity sha512-6Rw8iIVFbqtaZExgWK1rpVgP7DPFRPh0DDFZxJ/ADNqPiH10sPCoq5tgo6kLiTyfh9sxjKYjXdc8udLEcPOezg== +postcss-reduce-idents@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/postcss-reduce-idents/-/postcss-reduce-idents-5.2.0.tgz#c89c11336c432ac4b28792f24778859a67dfba95" + integrity sha512-BTrLjICoSB6gxbc58D5mdBK8OhXRDqud/zodYfdSi52qvDHdMwk+9kB9xsM8yJThH/sZU5A6QVSmMmaN001gIg== dependencies: - postcss-value-parser "^4.1.0" + postcss-value-parser "^4.2.0" -postcss-reduce-initial@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-5.0.1.tgz#9d6369865b0f6f6f6b165a0ef5dc1a4856c7e946" - integrity sha512-zlCZPKLLTMAqA3ZWH57HlbCjkD55LX9dsRyxlls+wfuRfqCi5mSlZVan0heX5cHr154Dq9AfbH70LyhrSAezJw== +postcss-reduce-initial@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-5.1.1.tgz#c18b7dfb88aee24b1f8e4936541c29adbd35224e" + integrity sha512-//jeDqWcHPuXGZLoolFrUXBDyuEGbr9S2rMo19bkTIjBQ4PqkaO+oI8wua5BOUxpfi97i3PCoInsiFIEBfkm9w== dependencies: - browserslist "^4.16.0" + browserslist "^4.21.4" caniuse-api "^3.0.0" -postcss-reduce-transforms@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-5.0.1.tgz#93c12f6a159474aa711d5269923e2383cedcf640" - integrity sha512-a//FjoPeFkRuAguPscTVmRQUODP+f3ke2HqFNgGPwdYnpeC29RZdCBvGRGTsKpMURb/I3p6jdKoBQ2zI+9Q7kA== +postcss-reduce-transforms@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-5.1.0.tgz#333b70e7758b802f3dd0ddfe98bb1ccfef96b6e9" + integrity sha512-2fbdbmgir5AvpW9RLtdONx1QoYG2/EtqpNQbFASDlixBbAYuTcJ0dECwlqNqH7VbaUnEnh8SrxOe2sRIn24XyQ== dependencies: - cssnano-utils "^2.0.1" - postcss-value-parser "^4.1.0" + postcss-value-parser "^4.2.0" -postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4, postcss-selector-parser@^6.0.5: - version "6.0.6" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.6.tgz#2c5bba8174ac2f6981ab631a42ab0ee54af332ea" - integrity sha512-9LXrvaaX3+mcv5xkg5kFwqSzSH1JIObIx51PrndZwlmznwXRfxMddDvo9gve3gVR8ZTKgoFDdWkbRFmEhT4PMg== +postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4, postcss-selector-parser@^6.0.5, postcss-selector-parser@^6.0.9: + version "6.0.11" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.11.tgz#2e41dc39b7ad74046e1615185185cd0b17d0c8dc" + integrity sha512-zbARubNdogI9j7WY4nQJBiNqQf3sLS3wCP4WfOidu+p28LofJqDH1tcXypGrcmMHhDk2t9wGhCsYe/+szLTy1g== dependencies: cssesc "^3.0.0" util-deprecate "^1.0.2" -postcss-sort-media-queries@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/postcss-sort-media-queries/-/postcss-sort-media-queries-4.1.0.tgz#c2ca1374189259049dc039a9e95ba72a31b57bc7" - integrity sha512-pPiw94cMOqGFSlp4QGzOKrhYr8O3VyMNQnb7qlGM25H4EDEii3iKtIUMoFe5gKiCEAt/Iyk2ah47eoRhGqSBGA== +postcss-sort-media-queries@^4.2.1: + version "4.3.0" + resolved "https://registry.yarnpkg.com/postcss-sort-media-queries/-/postcss-sort-media-queries-4.3.0.tgz#f48a77d6ce379e86676fc3f140cf1b10a06f6051" + integrity sha512-jAl8gJM2DvuIJiI9sL1CuiHtKM4s5aEIomkU8G3LFvbP+p8i7Sz8VV63uieTgoewGqKbi+hxBTiOKJlB35upCg== dependencies: - sort-css-media-queries "2.0.4" + sort-css-media-queries "2.1.0" -postcss-svgo@^5.0.3: - version "5.0.3" - resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-5.0.3.tgz#d945185756e5dfaae07f9edb0d3cae7ff79f9b30" - integrity sha512-41XZUA1wNDAZrQ3XgWREL/M2zSw8LJPvb5ZWivljBsUQAGoEKMYm6okHsTjJxKYI4M75RQEH4KYlEM52VwdXVA== +postcss-svgo@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-5.1.0.tgz#0a317400ced789f233a28826e77523f15857d80d" + integrity sha512-D75KsH1zm5ZrHyxPakAxJWtkyXew5qwS70v56exwvw542d9CRtTo78K0WeFxZB4G7JXKKMbEZtZayTGdIky/eA== dependencies: - postcss-value-parser "^4.1.0" + postcss-value-parser "^4.2.0" svgo "^2.7.0" -postcss-unique-selectors@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-5.0.1.tgz#3be5c1d7363352eff838bd62b0b07a0abad43bfc" - integrity sha512-gwi1NhHV4FMmPn+qwBNuot1sG1t2OmacLQ/AX29lzyggnjd+MnVD5uqQmpXO3J17KGL2WAxQruj1qTd3H0gG/w== +postcss-unique-selectors@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-5.1.1.tgz#a9f273d1eacd09e9aa6088f4b0507b18b1b541b6" + integrity sha512-5JiODlELrz8L2HwxfPnhOWZYWDxVHWL83ufOv84NrcgipI7TaeRsatAhK4Tr2/ZiYldpK/wBvw5BD3qfaK96GA== dependencies: - alphanum-sort "^1.0.2" postcss-selector-parser "^6.0.5" - uniqs "^2.0.0" -postcss-value-parser@^4.0.2, postcss-value-parser@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz#443f6a20ced6481a2bda4fa8532a6e55d789a2cb" - integrity sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ== +postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" + integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== -postcss-zindex@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/postcss-zindex/-/postcss-zindex-5.0.1.tgz#c585724beb69d356af8c7e68847b28d6298ece03" - integrity sha512-nwgtJJys+XmmSGoYCcgkf/VczP8Mp/0OfSv3v0+fw0uABY4yxw+eFs0Xp9nAZHIKnS5j+e9ywQ+RD+ONyvl5pA== +postcss-zindex@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/postcss-zindex/-/postcss-zindex-5.1.0.tgz#4a5c7e5ff1050bd4c01d95b1847dfdcc58a496ff" + integrity sha512-fgFMf0OtVSBR1va1JNHYgMxYk73yhn/qb4uQDq1DLGYolz8gHCyr/sesEuGUaYs58E3ZJRcpoGuPVoB7Meiq9A== -postcss@^8.2.15, postcss@^8.3.11, postcss@^8.3.5, postcss@^8.3.7: - version "8.3.11" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.3.11.tgz#c3beca7ea811cd5e1c4a3ec6d2e7599ef1f8f858" - integrity sha512-hCmlUAIlUiav8Xdqw3Io4LcpA1DOt7h3LSTAC4G6JGHFFaWzI6qvFt9oilvl8BmkbBRX1IhM90ZAmpk68zccQA== +postcss@^8.3.11, postcss@^8.4.14, postcss@^8.4.17, postcss@^8.4.18: + version "8.4.19" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.19.tgz#61178e2add236b17351897c8bcc0b4c8ecab56fc" + integrity sha512-h+pbPsyhlYj6N2ozBmHhHrs9DzGmbaarbLvWipMRO7RLS+v4onj26MPFXA5OBYFxyqYhUJK456SwDcY9H2/zsA== dependencies: - nanoid "^3.1.30" + nanoid "^3.3.4" picocolors "^1.0.0" - source-map-js "^0.6.2" - -prepend-http@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" - integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc= + source-map-js "^1.0.2" pretty-error@^4.0.0: version "4.0.0" @@ -5945,15 +5804,15 @@ pretty-time@^1.1.0: resolved "https://registry.yarnpkg.com/pretty-time/-/pretty-time-1.1.0.tgz#ffb7429afabb8535c346a34e41873adf3d74dd0e" integrity sha512-28iF6xPQrP8Oa6uxE6a1biz+lWeTOAPKggvjB8HAs6nVMKZwf5bG++632Dx614hIWgUPkgivRfG+a8uAXGTIbA== -prism-react-renderer@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/prism-react-renderer/-/prism-react-renderer-1.2.1.tgz#392460acf63540960e5e3caa699d851264e99b89" - integrity sha512-w23ch4f75V1Tnz8DajsYKvY5lF7H1+WvzvLUcF0paFxkTHSp42RS0H5CttdN2Q8RR3DRGZ9v5xD/h3n8C8kGmg== +prism-react-renderer@^1.3.5: + version "1.3.5" + resolved "https://registry.yarnpkg.com/prism-react-renderer/-/prism-react-renderer-1.3.5.tgz#786bb69aa6f73c32ba1ee813fbe17a0115435085" + integrity sha512-IJ+MSwBWKG+SM3b2SUfdrhC+gu01QkV2KmRQgREThBfSQRoufqRfxfHUxpG1WcaFjP+kojcFyO9Qqtpgt3qLCg== -prismjs@^1.23.0: - version "1.25.0" - resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.25.0.tgz#6f822df1bdad965734b310b315a23315cf999756" - integrity sha512-WCjJHl1KEWbnkQom1+SzftbtXMKQoezOCYs5rECqMN+jP+apI7ftoflyqigqzopSO3hMhTEb0mFClA8lkolgEg== +prismjs@^1.28.0: + version "1.29.0" + resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.29.0.tgz#f113555a8fa9b57c35e637bba27509dcf802dd12" + integrity sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q== process-nextick-args@~2.0.0: version "2.0.1" @@ -5967,7 +5826,7 @@ promise@^7.1.1: dependencies: asap "~2.0.3" -prompts@^2.4.0, prompts@^2.4.1: +prompts@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069" integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q== @@ -5976,13 +5835,13 @@ prompts@^2.4.0, prompts@^2.4.1: sisteransi "^1.0.5" prop-types@^15.6.2, prop-types@^15.7.2: - version "15.7.2" - resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" - integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ== + version "15.8.1" + resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" + integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg== dependencies: loose-envify "^1.4.0" object-assign "^4.1.1" - react-is "^16.8.1" + react-is "^16.13.1" property-information@^5.0.0, property-information@^5.3.0: version "5.6.0" @@ -5991,7 +5850,7 @@ property-information@^5.0.0, property-information@^5.3.0: dependencies: xtend "^4.0.0" -proxy-addr@~2.0.5: +proxy-addr@~2.0.7: version "2.0.7" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" integrity sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg== @@ -5999,23 +5858,10 @@ proxy-addr@~2.0.5: forwarded "0.2.0" ipaddr.js "1.9.1" -pump@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" - integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== - dependencies: - end-of-stream "^1.1.0" - once "^1.3.1" - -punycode@1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" - integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= - punycode@^1.3.2: version "1.4.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" - integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= + integrity sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ== punycode@^2.1.0: version "2.1.1" @@ -6032,28 +5878,32 @@ pupa@^2.1.1: pure-color@^1.2.0: version "1.3.0" resolved "https://registry.yarnpkg.com/pure-color/-/pure-color-1.3.0.tgz#1fe064fb0ac851f0de61320a8bf796836422f33e" - integrity sha1-H+Bk+wrIUfDeYTIKi/eWg2Qi8z4= - -q@^1.1.2: - version "1.5.1" - resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" - integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc= - -qs@6.7.0: - version "6.7.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" - integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ== + integrity sha512-QFADYnsVoBMw1srW7OVKEYjG+MbIa49s54w1MA1EDY6r2r/sTcKKYqRX1f4GYvnXP7eN/Pe9HFcX+hwzmrXRHA== -querystring@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" - integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= +qs@6.11.0: + version "6.11.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" + integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q== + dependencies: + side-channel "^1.0.4" queue-microtask@^1.2.2: version "1.2.3" resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== +queue@6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/queue/-/queue-6.0.2.tgz#b91525283e2315c7553d2efa18d83e76432fed65" + integrity sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA== + dependencies: + inherits "~2.0.3" + +quick-lru@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-5.1.1.tgz#366493e6b3e42a3a6885e2e99d18f80fb7a8c932" + integrity sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA== + randombytes@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" @@ -6064,24 +5914,24 @@ randombytes@^2.1.0: range-parser@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" - integrity sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4= + integrity sha512-kA5WQoNVo4t9lNx2kQNFCxKeBl5IbbSNBl1M/tLkw9WCn+hxNBAW5Qh8gdhs63CJnhjJ2zQWFoqPJP2sK1AV5A== range-parser@^1.2.1, range-parser@~1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== -raw-body@2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.0.tgz#a1ce6fb9c9bc356ca52e89256ab59059e13d0332" - integrity sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q== +raw-body@2.5.1: + version "2.5.1" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857" + integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig== dependencies: - bytes "3.1.0" - http-errors "1.7.2" + bytes "3.1.2" + http-errors "2.0.0" iconv-lite "0.4.24" unpipe "1.0.0" -rc@^1.2.8: +rc@1.2.8, rc@^1.2.8: version "1.2.8" resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== @@ -6094,44 +5944,44 @@ rc@^1.2.8: react-base16-styling@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/react-base16-styling/-/react-base16-styling-0.6.0.tgz#ef2156d66cf4139695c8a167886cb69ea660792c" - integrity sha1-7yFW1mz0E5aVyKFniGy2nqZgeSw= + integrity sha512-yvh/7CArceR/jNATXOKDlvTnPKPmGZz7zsenQ3jUwLzHkNUR0CvY3yGYJbWJ/nnxsL8Sgmt5cO3/SILVuPO6TQ== dependencies: base16 "^1.0.0" lodash.curry "^4.0.1" lodash.flow "^3.3.0" pure-color "^1.2.0" -react-dev-utils@12.0.0-next.47: - version "12.0.0-next.47" - resolved "https://registry.yarnpkg.com/react-dev-utils/-/react-dev-utils-12.0.0-next.47.tgz#e55c31a05eb30cfd69ca516e8b87d61724e880fb" - integrity sha512-PsE71vP15TZMmp/RZKOJC4fYD5Pvt0+wCoyG3QHclto0d4FyIJI78xGRICOOThZFROqgXYlZP6ddmeybm+jO4w== +react-dev-utils@^12.0.1: + version "12.0.1" + resolved "https://registry.yarnpkg.com/react-dev-utils/-/react-dev-utils-12.0.1.tgz#ba92edb4a1f379bd46ccd6bcd4e7bc398df33e73" + integrity sha512-84Ivxmr17KjUupyqzFode6xKhjwuEJDROWKJy/BthkL7Wn6NJ8h4WE6k/exAv6ImS+0oZLRRW5j/aINMHyeGeQ== dependencies: - "@babel/code-frame" "^7.10.4" + "@babel/code-frame" "^7.16.0" address "^1.1.2" - browserslist "^4.16.5" - chalk "^2.4.2" + browserslist "^4.18.1" + chalk "^4.1.2" cross-spawn "^7.0.3" detect-port-alt "^1.1.6" - escape-string-regexp "^2.0.0" - filesize "^6.1.0" - find-up "^4.1.0" - fork-ts-checker-webpack-plugin "^6.0.5" + escape-string-regexp "^4.0.0" + filesize "^8.0.6" + find-up "^5.0.0" + fork-ts-checker-webpack-plugin "^6.5.0" global-modules "^2.0.0" - globby "^11.0.1" - gzip-size "^5.1.1" - immer "^9.0.6" + globby "^11.0.4" + gzip-size "^6.0.0" + immer "^9.0.7" is-root "^2.1.0" - loader-utils "^2.0.0" - open "^7.0.2" + loader-utils "^3.2.0" + open "^8.4.0" pkg-up "^3.1.0" - prompts "^2.4.0" - react-error-overlay "7.0.0-next.54+1465357b" + prompts "^2.4.2" + react-error-overlay "^6.0.11" recursive-readdir "^2.2.2" - shell-quote "^1.7.2" - strip-ansi "^6.0.0" + shell-quote "^1.7.3" + strip-ansi "^6.0.1" text-table "^0.2.0" -react-dom@^17.0.2: +react-dom@^17: version "17.0.2" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-17.0.2.tgz#ecffb6845e3ad8dbfcdc498f0d0a939736502c23" integrity sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA== @@ -6140,32 +5990,28 @@ react-dom@^17.0.2: object-assign "^4.1.1" scheduler "^0.20.2" -react-error-overlay@7.0.0-next.54+1465357b: - version "7.0.0-next.54" - resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-7.0.0-next.54.tgz#c1eb5ab86aee15e9552e6d97897b08f2bd06d140" - integrity sha512-b96CiTnZahXPDNH9MKplvt5+jD+BkxDw7q5R3jnkUXze/ux1pLv32BBZmlj0OfCUeMqyz4sAmF+0ccJGVMlpXw== - -react-error-overlay@^6.0.9: - version "6.0.9" - resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.9.tgz#3c743010c9359608c375ecd6bc76f35d93995b0a" - integrity sha512-nQTTcUu+ATDbrSD1BZHr5kgSD4oF8OFjxun8uAaL8RwPBacGBNPf/yAuVVdx17N8XNzRDMrZ9XcKZHCjPW+9ew== +react-error-overlay@^6.0.11: + version "6.0.11" + resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.11.tgz#92835de5841c5cf08ba00ddd2d677b6d17ff9adb" + integrity sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg== -react-fast-compare@^3.1.1: +react-fast-compare@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.0.tgz#641a9da81b6a6320f270e89724fb45a0b39e43bb" integrity sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA== -react-helmet@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/react-helmet/-/react-helmet-6.1.0.tgz#a750d5165cb13cf213e44747502652e794468726" - integrity sha512-4uMzEY9nlDlgxr61NL3XbKRy1hEkXmKNXhjbAIOVw5vcFrsdYbH2FEwcNyWvWinl103nXgzYNlns9ca+8kFiWw== +react-helmet-async@*, react-helmet-async@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/react-helmet-async/-/react-helmet-async-1.3.0.tgz#7bd5bf8c5c69ea9f02f6083f14ce33ef545c222e" + integrity sha512-9jZ57/dAn9t3q6hneQS0wukqC2ENOBgMNVEhb/ZG9ZSxUetzVIw4iAmEU38IaVg3QGYauQPhSeUTuIUtFglWpg== dependencies: - object-assign "^4.1.1" + "@babel/runtime" "^7.12.5" + invariant "^2.2.4" prop-types "^15.7.2" - react-fast-compare "^3.1.1" - react-side-effect "^2.1.0" + react-fast-compare "^3.2.0" + shallowequal "^1.1.0" -react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1: +react-is@^16.13.1, react-is@^16.6.0, react-is@^16.7.0: version "16.13.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== @@ -6199,50 +6045,44 @@ react-router-config@^5.1.1: dependencies: "@babel/runtime" "^7.1.2" -react-router-dom@^5.2.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-5.3.0.tgz#da1bfb535a0e89a712a93b97dd76f47ad1f32363" - integrity sha512-ObVBLjUZsphUUMVycibxgMdh5jJ1e3o+KpAZBVeHcNQZ4W+uUGGWsokurzlF4YOldQYRQL4y6yFRWM4m3svmuQ== +react-router-dom@^5.3.3: + version "5.3.4" + resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-5.3.4.tgz#2ed62ffd88cae6db134445f4a0c0ae8b91d2e5e6" + integrity sha512-m4EqFMHv/Ih4kpcBCONHbkT68KoAeHN4p3lAGoNryfHi0dMy0kCzEZakiKRsvg5wHZ/JLrLW8o8KomWiz/qbYQ== dependencies: "@babel/runtime" "^7.12.13" history "^4.9.0" loose-envify "^1.3.1" prop-types "^15.6.2" - react-router "5.2.1" + react-router "5.3.4" tiny-invariant "^1.0.2" tiny-warning "^1.0.0" -react-router@5.2.1, react-router@^5.2.0: - version "5.2.1" - resolved "https://registry.yarnpkg.com/react-router/-/react-router-5.2.1.tgz#4d2e4e9d5ae9425091845b8dbc6d9d276239774d" - integrity sha512-lIboRiOtDLFdg1VTemMwud9vRVuOCZmUIT/7lUoZiSpPODiiH1UQlfXy+vPLC/7IWdFYnhRwAyNqA/+I7wnvKQ== +react-router@5.3.4, react-router@^5.3.3: + version "5.3.4" + resolved "https://registry.yarnpkg.com/react-router/-/react-router-5.3.4.tgz#8ca252d70fcc37841e31473c7a151cf777887bb5" + integrity sha512-Ys9K+ppnJah3QuaRiLxk+jDWOR1MekYQrlytiXxC1RyfbdsZkS5pvKAzCCr031xHixZwpnsYNT5xysdFHQaYsA== dependencies: "@babel/runtime" "^7.12.13" history "^4.9.0" hoist-non-react-statics "^3.1.0" loose-envify "^1.3.1" - mini-create-react-context "^0.4.0" path-to-regexp "^1.7.0" prop-types "^15.6.2" react-is "^16.6.0" tiny-invariant "^1.0.2" tiny-warning "^1.0.0" -react-side-effect@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/react-side-effect/-/react-side-effect-2.1.1.tgz#66c5701c3e7560ab4822a4ee2742dee215d72eb3" - integrity sha512-2FoTQzRNTncBVtnzxFOk2mCpcfxQpenBMbk5kSVBg5UcPqV9fRbgY2zhb7GTWWOlpFmAxhClBDlIq8Rsubz1yQ== - react-textarea-autosize@^8.3.2: - version "8.3.3" - resolved "https://registry.yarnpkg.com/react-textarea-autosize/-/react-textarea-autosize-8.3.3.tgz#f70913945369da453fd554c168f6baacd1fa04d8" - integrity sha512-2XlHXK2TDxS6vbQaoPbMOfQ8GK7+irc2fVK6QFIcC8GOnH3zI/v481n+j1L0WaPVvKxwesnY93fEfH++sus2rQ== + version "8.4.0" + resolved "https://registry.yarnpkg.com/react-textarea-autosize/-/react-textarea-autosize-8.4.0.tgz#4d0244d6a50caa897806b8c44abc0540a69bfc8c" + integrity sha512-YrTFaEHLgJsi8sJVYHBzYn+mkP3prGkmP2DKb/tm0t7CLJY5t1Rxix8070LAKb0wby7bl/lf2EeHkuMihMZMwQ== dependencies: "@babel/runtime" "^7.10.2" - use-composed-ref "^1.0.0" - use-latest "^1.0.0" + use-composed-ref "^1.3.0" + use-latest "^1.2.1" -react@^17.0.2: +react@^17: version "17.0.2" resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037" integrity sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA== @@ -6263,7 +6103,7 @@ readable-stream@^2.0.1: string_decoder "~1.1.1" util-deprecate "~1.0.1" -readable-stream@^3.0.6, readable-stream@^3.1.1: +readable-stream@^3.0.6: version "3.6.0" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== @@ -6287,21 +6127,21 @@ reading-time@^1.5.0: rechoir@^0.6.2: version "0.6.2" resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" - integrity sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q= + integrity sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw== dependencies: resolve "^1.1.6" recursive-readdir@^2.2.2: - version "2.2.2" - resolved "https://registry.yarnpkg.com/recursive-readdir/-/recursive-readdir-2.2.2.tgz#9946fb3274e1628de6e36b2f6714953b4845094f" - integrity sha512-nRCcW9Sj7NuZwa2XvH9co8NPeXUBhZP7CRKJtU+cS6PW9FpCIFoI5ib0NT1ZrbNuPoRy0ylyCaUL8Gih4LSyFg== + version "2.2.3" + resolved "https://registry.yarnpkg.com/recursive-readdir/-/recursive-readdir-2.2.3.tgz#e726f328c0d69153bcabd5c322d3195252379372" + integrity sha512-8HrF5ZsXk5FAH9dgsx3BlUer73nIhuj+9OrQwEbLTPOBzGkL1lsFCR01am+v+0m2Cmbs1nP12hLDl5FA7EszKA== dependencies: - minimatch "3.0.4" + minimatch "^3.0.5" -regenerate-unicode-properties@^9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-9.0.0.tgz#54d09c7115e1f53dc2314a974b32c1c344efe326" - integrity sha512-3E12UeNSPfjrgwjkR81m5J7Aw/T55Tu7nUyZVQYCKEOs+2dkxEY+DpPtZzO4YruuiPb7NkYLVcyJC4+zCbk5pA== +regenerate-unicode-properties@^10.1.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.0.tgz#7c3192cab6dd24e21cb4461e5ddd7dd24fa8374c" + integrity sha512-d1VudCLoIGitcU/hEg2QqvyGZQmdC0Lf8BqdOMXGFSvJP4bNV1+XqbPQeHHLD51Jh4QJJ225dlIFvY4Ly6MXmQ== dependencies: regenerate "^1.4.2" @@ -6310,44 +6150,36 @@ regenerate@^1.4.2: resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== -regenerator-runtime@^0.13.4: - version "0.13.9" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52" - integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA== +regenerator-runtime@^0.13.10: + version "0.13.11" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9" + integrity sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg== -regenerator-transform@^0.14.2: - version "0.14.5" - resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.5.tgz#c98da154683671c9c4dcb16ece736517e1b7feb4" - integrity sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw== +regenerator-transform@^0.15.0: + version "0.15.1" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.15.1.tgz#f6c4e99fc1b4591f780db2586328e4d9a9d8dc56" + integrity sha512-knzmNAcuyxV+gQCufkYcvOqX/qIIfHLv0u5x79kRxuGojfYVky1f15TzZEu2Avte8QGepvUNTnLskf8E6X6Vyg== dependencies: "@babel/runtime" "^7.8.4" -regexp.prototype.flags@^1.2.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.3.1.tgz#7ef352ae8d159e758c0eadca6f8fcb4eef07be26" - integrity sha512-JiBdRBq91WlY7uRJ0ds7R+dU02i6LKi8r3BuQhNXn+kmeLN+EfHhfjqMRis1zJxnlu88hq/4dx0P2OP3APRTOA== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - -regexpu-core@^4.5.4, regexpu-core@^4.7.1: - version "4.8.0" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.8.0.tgz#e5605ba361b67b1718478501327502f4479a98f0" - integrity sha512-1F6bYsoYiz6is+oz70NWur2Vlh9KWtswuRuzJOfeYUrfPX2o8n74AnUVaOGDbUqVGO9fNHu48/pjJO4sNVwsOg== +regexpu-core@^5.1.0: + version "5.2.2" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-5.2.2.tgz#3e4e5d12103b64748711c3aad69934d7718e75fc" + integrity sha512-T0+1Zp2wjF/juXMrMxHxidqGYn8U4R+zleSJhX9tQ1PUsS8a9UtYfbsF9LdiVgNX3kiX8RNaKM42nfSgvFJjmw== dependencies: regenerate "^1.4.2" - regenerate-unicode-properties "^9.0.0" - regjsgen "^0.5.2" - regjsparser "^0.7.0" + regenerate-unicode-properties "^10.1.0" + regjsgen "^0.7.1" + regjsparser "^0.9.1" unicode-match-property-ecmascript "^2.0.0" - unicode-match-property-value-ecmascript "^2.0.0" + unicode-match-property-value-ecmascript "^2.1.0" registry-auth-token@^4.0.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-4.2.1.tgz#6d7b4006441918972ccd5fedcd41dc322c79b250" - integrity sha512-6gkSb4U6aWJB4SF2ZvLb76yCBjcvufXBqvvEx1HbmKPkutswjW1xNVRY0+daljIYRbogN7O0etYSlbiaEQyMyw== + version "4.2.2" + resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-4.2.2.tgz#f02d49c3668884612ca031419491a13539e21fac" + integrity sha512-PC5ZysNb42zpFME6D/XlIgtNGdTl8bBOCw90xQLVMpzuuubJKYDWFAEuUNc+Cn8Z8724tg2SDhDRrkVEsqfDMg== dependencies: - rc "^1.2.8" + rc "1.2.8" registry-url@^5.0.0: version "5.1.0" @@ -6356,42 +6188,24 @@ registry-url@^5.0.0: dependencies: rc "^1.2.8" -regjsgen@^0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.5.2.tgz#92ff295fb1deecbf6ecdab2543d207e91aa33733" - integrity sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A== +regjsgen@^0.7.1: + version "0.7.1" + resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.7.1.tgz#ee5ef30e18d3f09b7c369b76e7c2373ed25546f6" + integrity sha512-RAt+8H2ZEzHeYWxZ3H2z6tF18zyyOnlcdaafLrm21Bguj7uZy6ULibiAFdXEtKQY4Sy7wDTwDiOazasMLc4KPA== -regjsparser@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.7.0.tgz#a6b667b54c885e18b52554cb4960ef71187e9968" - integrity sha512-A4pcaORqmNMDVwUjWoTzuhwMGpP+NykpfqAsEgI1FSH/EzC7lrN5TMd+kN8YCovX+jMpu8eaqXgXPCa0g8FQNQ== +regjsparser@^0.9.1: + version "0.9.1" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.9.1.tgz#272d05aa10c7c1f67095b1ff0addae8442fc5709" + integrity sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ== dependencies: jsesc "~0.5.0" -rehype-parse@^6.0.2: - version "6.0.2" - resolved "https://registry.yarnpkg.com/rehype-parse/-/rehype-parse-6.0.2.tgz#aeb3fdd68085f9f796f1d3137ae2b85a98406964" - integrity sha512-0S3CpvpTAgGmnz8kiCyFLGuW5yA4OQhyNTm/nwPopZ7+PI11WnGl1TTWTGv/2hPEe/g2jRLlhVVSsoDH8waRug== - dependencies: - hast-util-from-parse5 "^5.0.0" - parse5 "^5.0.0" - xtend "^4.0.0" - relateurl@^0.2.7: version "0.2.7" resolved "https://registry.yarnpkg.com/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9" - integrity sha1-VNvzd+UUQKypCkzSdGANP/LYiKk= - -remark-admonitions@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/remark-admonitions/-/remark-admonitions-1.2.1.tgz#87caa1a442aa7b4c0cafa04798ed58a342307870" - integrity sha512-Ji6p68VDvD+H1oS95Fdx9Ar5WA2wcDA4kwrrhVU7fGctC6+d3uiMICu7w7/2Xld+lnU7/gi+432+rRbup5S8ow== - dependencies: - rehype-parse "^6.0.2" - unified "^8.4.2" - unist-util-visit "^2.0.1" + integrity sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog== -remark-emoji@^2.1.0: +remark-emoji@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/remark-emoji/-/remark-emoji-2.2.0.tgz#1c702090a1525da5b80e15a8f963ef2c8236cac7" integrity sha512-P3cj9s5ggsUvWw5fS2uzCHJMGuXYRb0NnZqYlNecewXt8QBU9n5vW3DUUKOhepS8F9CwdMx9B8a3i7pqFWAI5w== @@ -6405,20 +6219,6 @@ remark-footnotes@2.0.0: resolved "https://registry.yarnpkg.com/remark-footnotes/-/remark-footnotes-2.0.0.tgz#9001c4c2ffebba55695d2dd80ffb8b82f7e6303f" integrity sha512-3Clt8ZMH75Ayjp9q4CorNeyjwIxHFcTkaektplKGl2A1jNGEUey8cKL0ZC5vJwfcD5GFGsNLImLG/NGzWIzoMQ== -remark-mdx-remove-exports@^1.6.22: - version "1.6.22" - resolved "https://registry.yarnpkg.com/remark-mdx-remove-exports/-/remark-mdx-remove-exports-1.6.22.tgz#9e34f3d02c9c54b02ca0a1fde946449338d06ecb" - integrity sha512-7g2uiTmTGfz5QyVb+toeX25frbk1Y6yd03RXGPtqx0+DVh86Gb7MkNYbk7H2X27zdZ3CQv1W/JqlFO0Oo8IxVA== - dependencies: - unist-util-remove "2.0.0" - -remark-mdx-remove-imports@^1.6.22: - version "1.6.22" - resolved "https://registry.yarnpkg.com/remark-mdx-remove-imports/-/remark-mdx-remove-imports-1.6.22.tgz#79f711c95359cff437a120d1fbdc1326ec455826" - integrity sha512-lmjAXD8Ltw0TsvBzb45S+Dxx7LTJAtDaMneMAv8LAUIPEyYoKkmGbmVsiF0/pY6mhM1Q16swCmu1TN+ie/vn/A== - dependencies: - unist-util-remove "2.0.0" - remark-mdx@1.6.22: version "1.6.22" resolved "https://registry.yarnpkg.com/remark-mdx/-/remark-mdx-1.6.22.tgz#06a8dab07dcfdd57f3373af7f86bd0e992108bbd" @@ -6476,17 +6276,27 @@ renderkid@^3.0.0: repeat-string@^1.5.4: version "1.6.1" resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" - integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= + integrity sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w== + +require-from-string@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== "require-like@>= 0.1.1": version "0.1.2" resolved "https://registry.yarnpkg.com/require-like/-/require-like-0.1.2.tgz#ad6f30c13becd797010c468afa775c0c0a6b47fa" - integrity sha1-rW8wwTvs15cBDEaK+ndcDAprR/o= + integrity sha512-oyrU88skkMtDdauHDuKVrgR+zuItqr6/c//FXzvmxRGMexSDc6hNvJInGW3LL46n+8b50RykrvwSUIIQH2LQ5A== requires-port@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" - integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= + integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== + +resolve-alpn@^1.2.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/resolve-alpn/-/resolve-alpn-1.2.1.tgz#b7adbdac3546aaaec20b45e7d8265927072726f9" + integrity sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g== resolve-from@^4.0.0: version "4.0.0" @@ -6499,19 +6309,20 @@ resolve-pathname@^3.0.0: integrity sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng== resolve@^1.1.6, resolve@^1.14.2, resolve@^1.3.2: - version "1.20.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975" - integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A== + version "1.22.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" + integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== dependencies: - is-core-module "^2.2.0" - path-parse "^1.0.6" + is-core-module "^2.9.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" -responselike@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" - integrity sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec= +responselike@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/responselike/-/responselike-3.0.0.tgz#20decb6c298aff0dbee1c355ca95461d42823626" + integrity sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg== dependencies: - lowercase-keys "^1.0.0" + lowercase-keys "^3.0.0" retry@^0.13.1: version "0.13.1" @@ -6535,7 +6346,7 @@ rtl-detect@^1.0.4: resolved "https://registry.yarnpkg.com/rtl-detect/-/rtl-detect-1.0.4.tgz#40ae0ea7302a150b96bc75af7d749607392ecac6" integrity sha512-EBR4I2VDSSYr7PkBmFy04uhycIpDKp+21p/jARYXlCSjQksTBQcJ0HFUPOO79EPPH5JS6VAhiIQbycf0O3JAxQ== -rtlcss@^3.3.0: +rtlcss@^3.5.0: version "3.5.0" resolved "https://registry.yarnpkg.com/rtlcss/-/rtlcss-3.5.0.tgz#c9eb91269827a102bac7ae3115dd5d049de636c3" integrity sha512-wzgMaMFHQTnyi9YOwsx9LjOxYXJPzS8sYnFaKm6R5ysvTkwzHiB0vxnbHwchHQT65PTdBjDG21/kQBWI7q9O7A== @@ -6552,19 +6363,19 @@ run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" -rxjs@^7.1.0: - version "7.4.0" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.4.0.tgz#a12a44d7eebf016f5ff2441b87f28c9a51cebc68" - integrity sha512-7SQDi7xeTMCJpqViXh8gL/lebcwlp3d831F05+9B44A4B0WfsEwUQHR64gsH1kvJ+Ep/J9K2+n1hVl1CsGN23w== +rxjs@^7.5.4: + version "7.5.7" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.5.7.tgz#2ec0d57fdc89ece220d2e702730ae8f1e49def39" + integrity sha512-z9MzKh/UcOqB3i20H6rtrlaE/CgjLOvheWK/9ILrbhROGTweAi1BaFsTT9FbwZi5Trr1qNRs+MXkhmR06awzQA== dependencies: - tslib "~2.1.0" + tslib "^2.1.0" safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== -safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@~5.2.0: +safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.1.0, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== @@ -6574,7 +6385,7 @@ safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@~5.2.0: resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -sax@^1.2.4, sax@~1.2.4: +sax@^1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== @@ -6614,6 +6425,16 @@ schema-utils@^3.0.0, schema-utils@^3.1.0, schema-utils@^3.1.1: ajv "^6.12.5" ajv-keywords "^3.5.2" +schema-utils@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.0.0.tgz#60331e9e3ae78ec5d16353c467c34b3a0a1d3df7" + integrity sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg== + dependencies: + "@types/json-schema" "^7.0.9" + ajv "^8.8.0" + ajv-formats "^2.1.1" + ajv-keywords "^5.0.0" + section-matter@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/section-matter/-/section-matter-1.0.0.tgz#e9041953506780ec01d59f292a19c7b850b84167" @@ -6625,14 +6446,14 @@ section-matter@^1.0.0: select-hose@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" - integrity sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo= + integrity sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg== -selfsigned@^1.10.11: - version "1.10.11" - resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-1.10.11.tgz#24929cd906fe0f44b6d01fb23999a739537acbe9" - integrity sha512-aVmbPOfViZqOZPgRBT0+3u4yZFHpmnIghLMlAcb5/xhp5ZtB/RVnKhz5vl2M32CLXAqR4kha9zfhNg0Lf/sxKA== +selfsigned@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-2.1.1.tgz#18a7613d714c0cd3385c48af0075abf3f266af61" + integrity sha512-GSL3aowiF7wa/WtSFwnUrludWFoNhftq8bUkH9pkzjpN2XSPOAYEgg6e0sS9s0rZwgJzJiQRPU18A6clnoW5wQ== dependencies: - node-forge "^0.10.0" + node-forge "^1" semver-diff@^3.1.1: version "3.1.1" @@ -6641,46 +6462,31 @@ semver-diff@^3.1.1: dependencies: semver "^6.3.0" -semver@7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" - integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== - -semver@^5.4.1: - version "5.7.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" - integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== - -semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" - integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== - -semver@^7.3.2, semver@^7.3.4, semver@^7.3.5: - version "7.3.5" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" - integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== +semver@>=7.5.2, semver@^5.4.1, semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0, semver@^7.3.2, semver@^7.3.4, semver@^7.3.7, semver@^7.3.8: + version "7.5.3" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.3.tgz#161ce8c2c6b4b3bdca6caadc9fa3317a4c4fe88e" + integrity sha512-QBlUtyVk/5EeHbi7X0fw6liDZc7BBmEaSYn01fMU1OUYbf6GPsbTtd8WmnqbI20SeycoHSeiybkE/q1Q+qlThQ== dependencies: lru-cache "^6.0.0" -send@0.17.1: - version "0.17.1" - resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8" - integrity sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg== +send@0.18.0: + version "0.18.0" + resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" + integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== dependencies: debug "2.6.9" - depd "~1.1.2" - destroy "~1.0.4" + depd "2.0.0" + destroy "1.2.0" encodeurl "~1.0.2" escape-html "~1.0.3" etag "~1.8.1" fresh "0.5.2" - http-errors "~1.7.2" + http-errors "2.0.0" mime "1.6.0" - ms "2.1.1" - on-finished "~2.3.0" + ms "2.1.3" + on-finished "2.4.1" range-parser "~1.2.1" - statuses "~1.5.0" + statuses "2.0.1" serialize-javascript@^6.0.0: version "6.0.0" @@ -6690,15 +6496,15 @@ serialize-javascript@^6.0.0: randombytes "^2.1.0" serve-handler@^6.1.3: - version "6.1.3" - resolved "https://registry.yarnpkg.com/serve-handler/-/serve-handler-6.1.3.tgz#1bf8c5ae138712af55c758477533b9117f6435e8" - integrity sha512-FosMqFBNrLyeiIDvP1zgO6YoTzFYHxLDEIavhlmQ+knB2Z7l1t+kGLHkZIDN7UVWqQAmKI3D20A6F6jo3nDd4w== + version "6.1.5" + resolved "https://registry.yarnpkg.com/serve-handler/-/serve-handler-6.1.5.tgz#a4a0964f5c55c7e37a02a633232b6f0d6f068375" + integrity sha512-ijPFle6Hwe8zfmBxJdE+5fta53fdIY0lHISJvuikXB3VYFafRjMRpOffSPvCYsbKyBA7pvy9oYr/BT1O3EArlg== dependencies: bytes "3.0.0" content-disposition "0.5.2" fast-url-parser "1.1.3" mime-types "2.1.18" - minimatch "3.0.4" + minimatch "3.1.2" path-is-inside "1.0.2" path-to-regexp "2.2.1" range-parser "1.2.0" @@ -6706,7 +6512,7 @@ serve-handler@^6.1.3: serve-index@^1.9.1: version "1.9.1" resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.1.tgz#d3768d69b1e7d82e5ce050fff5b453bea12a9239" - integrity sha1-03aNabHn2C5c4FD/9bRTvqEqkjk= + integrity sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw== dependencies: accepts "~1.3.4" batch "0.6.1" @@ -6716,30 +6522,30 @@ serve-index@^1.9.1: mime-types "~2.1.17" parseurl "~1.3.2" -serve-static@1.14.1: - version "1.14.1" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9" - integrity sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg== +serve-static@1.15.0: + version "1.15.0" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540" + integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g== dependencies: encodeurl "~1.0.2" escape-html "~1.0.3" parseurl "~1.3.3" - send "0.17.1" + send "0.18.0" setimmediate@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" - integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= + integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA== setprototypeof@1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ== -setprototypeof@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683" - integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw== +setprototypeof@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" + integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== shallow-clone@^3.0.0: version "3.0.1" @@ -6748,6 +6554,11 @@ shallow-clone@^3.0.0: dependencies: kind-of "^6.0.2" +shallowequal@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/shallowequal/-/shallowequal-1.1.0.tgz#188d521de95b9087404fd4dcb68b13df0ae4e7f8" + integrity sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ== + shebang-command@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" @@ -6760,15 +6571,15 @@ shebang-regex@^3.0.0: resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== -shell-quote@^1.7.2: - version "1.7.3" - resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.3.tgz#aa40edac170445b9a431e17bb62c0b881b9c4123" - integrity sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw== +shell-quote@^1.7.3: + version "1.7.4" + resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.4.tgz#33fe15dee71ab2a81fcbd3a52106c5cfb9fb75d8" + integrity sha512-8o/QEhSSRb1a5i7TFR0iM4G16Z0vYB2OQVs4G3aAFXjn3T6yEx8AZxy1PgDF7I00LZHYA3WxaSYIf5e5sAX8Rw== -shelljs@^0.8.4: - version "0.8.4" - resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.4.tgz#de7684feeb767f8716b326078a8a00875890e3c2" - integrity sha512-7gk3UZ9kOfPLIAbslLzyWeGiEqx9e3rxwZM0KE6EL8GlGwjym9Mrlx5/p33bWTu9YG6vcS4MBxYZDHYr5lr8BQ== +shelljs@^0.8.5: + version "0.8.5" + resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.5.tgz#de055408d8361bed66c669d2f000538ced8ee20c" + integrity sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow== dependencies: glob "^7.0.0" interpret "^1.0.0" @@ -6784,17 +6595,17 @@ side-channel@^1.0.4: object-inspect "^1.9.0" signal-exit@^3.0.2, signal-exit@^3.0.3: - version "3.0.5" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.5.tgz#9e3e8cc0c75a99472b44321033a7702e7738252f" - integrity sha512-KWcOiKeQj6ZyXx7zq4YxSMgHRlod4czeBQZrPb8OKcohcqAXShm7E20kEMle9WBt26hFcAf0qLOcp5zmY7kOqQ== + version "3.0.7" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== sirv@^1.0.7: - version "1.0.18" - resolved "https://registry.yarnpkg.com/sirv/-/sirv-1.0.18.tgz#105fab52fb656ce8a2bebbf36b11052005952899" - integrity sha512-f2AOPogZmXgJ9Ma2M22ZEhc1dNtRIzcEkiflMFeVTRq+OViOZMvH1IPMVOwrKaxpSaHioBJiDR0SluRqGa7atA== + version "1.0.19" + resolved "https://registry.yarnpkg.com/sirv/-/sirv-1.0.19.tgz#1d73979b38c7fe91fcba49c85280daa9c2363b49" + integrity sha512-JuLThK3TnZG1TAKDwNIqNq6QA2afLOCcm+iE8D1Kj3GA40pSPsxQjjJl0J8X3tsR7T+CP1GavpzLwYkgVLWrZQ== dependencies: "@polka/url" "^1.0.0-next.20" - mime "^2.3.1" + mrmime "^1.0.0" totalist "^1.0.0" sisteransi@^1.0.5: @@ -6802,12 +6613,12 @@ sisteransi@^1.0.5: resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" integrity sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg== -sitemap@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/sitemap/-/sitemap-7.0.0.tgz#022bef4df8cba42e38e1fe77039f234cab0372b6" - integrity sha512-Ud0jrRQO2k7fEtPAM+cQkBKoMvxQyPKNXKDLn8tRVHxRCsdDQ2JZvw+aZ5IRYYQVAV9iGxEar6boTwZzev+x3g== +sitemap@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/sitemap/-/sitemap-7.1.1.tgz#eeed9ad6d95499161a3eadc60f8c6dce4bea2bef" + integrity sha512-mK3aFtjz4VdJN0igpIJrinf3EO8U8mxOPsTBzSsy06UtjZQJ3YY3o3Xa7zSc5nMqcMrRwlChHZ18Kxg0caiPBg== dependencies: - "@types/node" "^15.0.1" + "@types/node" "^17.0.5" "@types/sax" "^1.2.1" arg "^5.0.0" sax "^1.2.4" @@ -6817,34 +6628,34 @@ slash@^3.0.0: resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== -sockjs@^0.3.21: - version "0.3.21" - resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.21.tgz#b34ffb98e796930b60a0cfa11904d6a339a7d417" - integrity sha512-DhbPFGpxjc6Z3I+uX07Id5ZO2XwYsWOrYjaSeieES78cq+JaJvVe5q/m1uvjIQhXinhIeCFRH6JgXe+mvVMyXw== +slash@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-4.0.0.tgz#2422372176c4c6c5addb5e2ada885af984b396a7" + integrity sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew== + +sockjs@^0.3.24: + version "0.3.24" + resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.24.tgz#c9bc8995f33a111bea0395ec30aa3206bdb5ccce" + integrity sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ== dependencies: faye-websocket "^0.11.3" - uuid "^3.4.0" + uuid "^8.3.2" websocket-driver "^0.7.4" -sort-css-media-queries@2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/sort-css-media-queries/-/sort-css-media-queries-2.0.4.tgz#b2badfa519cb4a938acbc6d3aaa913d4949dc908" - integrity sha512-PAIsEK/XupCQwitjv7XxoMvYhT7EAfyzI3hsy/MyDgTvc+Ft55ctdkctJLOy6cQejaIC+zjpUL4djFVm2ivOOw== - -source-list-map@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" - integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw== +sort-css-media-queries@2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/sort-css-media-queries/-/sort-css-media-queries-2.1.0.tgz#7c85e06f79826baabb232f5560e9745d7a78c4ce" + integrity sha512-IeWvo8NkNiY2vVYdPa27MCQiR0MN0M80johAYFVxWWXQ44KU84WNxjslwBHmc/7ZL2ccwkM7/e6S5aiKZXm7jA== -source-map-js@^0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-0.6.2.tgz#0bb5de631b41cfbda6cfba8bd05a80efdfd2385e" - integrity sha512-/3GptzWzu0+0MBQFrDKzw/DvvMTUORvgY6k6jd/VS6iCR4RDTKWH6v6WPwQoUO8667uQEf9Oe38DxAYWY5F/Ug== +source-map-js@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" + integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== source-map-support@~0.5.20: - version "0.5.20" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.20.tgz#12166089f8f5e5e8c56926b377633392dd2cb6c9" - integrity sha512-n1lZZ8Ve4ksRqizaBQgxXDgKwttHDhyfQjA6YZZn8+AroHbsIz+JjwxQDxbp+7y5OYCI8t1Yk7etjD9CRd2hIw== + version "0.5.21" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" + integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== dependencies: buffer-from "^1.0.0" source-map "^0.6.0" @@ -6852,23 +6663,13 @@ source-map-support@~0.5.20: source-map@^0.5.0: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" - integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= + integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ== -source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1: +source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== -source-map@~0.7.2: - version "0.7.3" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" - integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== - -sourcemap-codec@^1.4.4: - version "1.4.8" - resolved "https://registry.yarnpkg.com/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4" - integrity sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA== - space-separated-tokens@^1.0.0: version "1.1.5" resolved "https://registry.yarnpkg.com/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz#85f32c3d10d9682007e917414ddc5c26d1aa6899" @@ -6900,7 +6701,7 @@ spdy@^4.0.2: sprintf-js@~1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" - integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= + integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== stable@^0.1.8: version "0.1.8" @@ -6912,24 +6713,22 @@ state-toggle@^1.0.0: resolved "https://registry.yarnpkg.com/state-toggle/-/state-toggle-1.0.3.tgz#e123b16a88e143139b09c6852221bc9815917dfe" integrity sha512-d/5Z4/2iiCnHw6Xzghyhb+GcmF89bxwgXG60wjIiZaxnymbyOmI8Hk4VqHXiVVp6u2ysaskFfXg3ekCj4WNftQ== -"statuses@>= 1.4.0 < 2", "statuses@>= 1.5.0 < 2", statuses@~1.5.0: +statuses@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" + integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== + +"statuses@>= 1.4.0 < 2": version "1.5.0" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" - integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= - -std-env@^2.2.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/std-env/-/std-env-2.3.1.tgz#d42271908819c243f8defc77a140fc1fcee336a1" - integrity sha512-eOsoKTWnr6C8aWrqJJ2KAReXoa7Vn5Ywyw6uCXgA/xDhxPoaIsBa5aNJmISY04dLwXPBnDHW4diGM7Sn5K4R/g== - dependencies: - ci-info "^3.1.1" + integrity sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA== std-env@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.0.1.tgz#bc4cbc0e438610197e34c2d79c3df30b491f5182" - integrity sha512-mC1Ps9l77/97qeOZc+HrOL7TIaOboHqMZ24dGVQrlxFcpPpfCHpH+qfUT7Dz+6mlG8+JPA1KfBQo19iC/+Ngcw== + version "3.3.1" + resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.3.1.tgz#93a81835815e618c8aa75e7c8a4dc04f7c314e29" + integrity sha512-3H20QlwQsSm2OvAxWIYhs+j01MzzqwMwGiiO1NQaJYZgJZFPuAbf95/DiKRBSTYIJ2FeGUc+B/6mPGcWP9dO3Q== -string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.2: +string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -6938,21 +6737,14 @@ string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.2: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" -string.prototype.trimend@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz#e75ae90c2942c63504686c18b287b4a0b1a45f80" - integrity sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - -string.prototype.trimstart@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz#b36399af4ab2999b4c9c648bd7a3fb2bb26feeed" - integrity sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw== +string-width@^5.0.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" + integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" + eastasianwidth "^0.2.0" + emoji-regex "^9.2.2" + strip-ansi "^7.0.1" string_decoder@^1.1.1: version "1.3.0" @@ -6984,7 +6776,7 @@ strip-ansi@^6.0.0, strip-ansi@^6.0.1: dependencies: ansi-regex "^5.0.1" -strip-ansi@^7.0.0: +strip-ansi@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.0.1.tgz#61740a08ce36b61e50e65653f07060d000975fb2" integrity sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw== @@ -6994,7 +6786,7 @@ strip-ansi@^7.0.0: strip-bom-string@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/strip-bom-string/-/strip-bom-string-1.0.0.tgz#e5211e9224369fbb81d633a2f00044dc8cedad92" - integrity sha1-5SEekiQ2n7uB1jOi8ABE3IztrZI= + integrity sha512-uCC2VHvQRYu+lMh4My/sFNmF2klFymLX1wHJeXnbEJERpV/ZsVuonzerjfrGpIGF7LBVa1O7i9kjiWvJiFck8g== strip-final-newline@^2.0.0: version "2.0.0" @@ -7009,7 +6801,7 @@ strip-json-comments@^3.1.1: strip-json-comments@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= + integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== style-to-object@0.3.0, style-to-object@^0.3.0: version "0.3.0" @@ -7018,12 +6810,12 @@ style-to-object@0.3.0, style-to-object@^0.3.0: dependencies: inline-style-parser "0.1.1" -stylehacks@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-5.0.1.tgz#323ec554198520986806388c7fdaebc38d2c06fb" - integrity sha512-Es0rVnHIqbWzveU1b24kbw92HsebBepxfcqe5iix7t9j0PQqhs0IxXVXv0pY2Bxa08CgMkzD6OWql7kbGOuEdA== +stylehacks@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-5.1.1.tgz#7934a34eb59d7152149fa69d6e9e56f2fc34bcc9" + integrity sha512-sBpcd5Hx7G6seo7b1LkpttvTz7ikD0LlH5RmdcBNb6fFR0Fl7LQwHDFr300q4cwUqi+IYrFGmsIHieMBfnN/Bw== dependencies: - browserslist "^4.16.0" + browserslist "^4.21.4" postcss-selector-parser "^6.0.4" supports-color@^5.3.0: @@ -7047,31 +6839,17 @@ supports-color@^8.0.0: dependencies: has-flag "^4.0.0" -svg-parser@^2.0.2: +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + +svg-parser@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/svg-parser/-/svg-parser-2.0.4.tgz#fdc2e29e13951736140b76cb122c8ee6630eb6b5" integrity sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ== -svgo@^1.2.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.3.2.tgz#b6dc511c063346c9e415b81e43401145b96d4167" - integrity sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw== - dependencies: - chalk "^2.4.1" - coa "^2.0.2" - css-select "^2.0.0" - css-select-base-adapter "^0.1.1" - css-tree "1.0.0-alpha.37" - csso "^4.0.2" - js-yaml "^3.13.1" - mkdirp "~0.5.1" - object.values "^1.1.0" - sax "~1.2.4" - stable "^0.1.8" - unquote "~1.1.1" - util.promisify "~1.0.0" - -svgo@^2.7.0: +svgo@^2.7.0, svgo@^2.8.0: version "2.8.0" resolved "https://registry.yarnpkg.com/svgo/-/svgo-2.8.0.tgz#4ff80cce6710dc2795f0c7c74101e6764cfccd24" integrity sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg== @@ -7094,48 +6872,43 @@ tapable@^2.0.0, tapable@^2.1.1, tapable@^2.2.0: resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== -terser-webpack-plugin@^5.1.3, terser-webpack-plugin@^5.2.4: - version "5.2.4" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.2.4.tgz#ad1be7639b1cbe3ea49fab995cbe7224b31747a1" - integrity sha512-E2CkNMN+1cho04YpdANyRrn8CyN4yMy+WdFKZIySFZrGXZxJwJP6PMNGGc/Mcr6qygQHUUqRxnAPmi0M9f00XA== +terser-webpack-plugin@^5.1.3, terser-webpack-plugin@^5.3.3: + version "5.3.6" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.6.tgz#5590aec31aa3c6f771ce1b1acca60639eab3195c" + integrity sha512-kfLFk+PoLUQIbLmB1+PZDMRSZS99Mp+/MHqDNmMA6tOItzRt+Npe3E+fsMs5mfcM0wCtrrdU387UnV+vnSffXQ== dependencies: - jest-worker "^27.0.6" - p-limit "^3.1.0" + "@jridgewell/trace-mapping" "^0.3.14" + jest-worker "^27.4.5" schema-utils "^3.1.1" serialize-javascript "^6.0.0" - source-map "^0.6.1" - terser "^5.7.2" + terser "^5.14.1" -terser@^5.7.2: - version "5.9.0" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.9.0.tgz#47d6e629a522963240f2b55fcaa3c99083d2c351" - integrity sha512-h5hxa23sCdpzcye/7b8YqbE5OwKca/ni0RQz1uRX3tGh8haaGHqcuSqbGRybuAKNdntZ0mDgFNXPJ48xQ2RXKQ== +terser@^5.10.0, terser@^5.14.1: + version "5.16.0" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.16.0.tgz#29362c6f5506e71545c73b069ccd199bb28f7f54" + integrity sha512-KjTV81QKStSfwbNiwlBXfcgMcOloyuRdb62/iLFPGBcVNF4EXjhdYBhYHmbJpiBrVxZhDvltE11j+LBQUxEEJg== dependencies: + "@jridgewell/source-map" "^0.3.2" + acorn "^8.5.0" commander "^2.20.0" - source-map "~0.7.2" source-map-support "~0.5.20" text-table@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" - integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= + integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== thunky@^1.0.2: version "1.1.0" resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.1.0.tgz#5abaf714a9405db0504732bbccd2cedd9ef9537d" integrity sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA== -timsort@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4" - integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q= - tiny-invariant@^1.0.2: - version "1.2.0" - resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.2.0.tgz#a1141f86b672a9148c72e978a19a73b9b94a15a9" - integrity sha512-1Uhn/aqw5C6RI4KejVeTg6mIS7IqxnLJ8Mv2tV5rTc0qWobay7pDUz6Wi392Cnc8ak1H0F2cjoRzb2/AW4+Fvg== + version "1.3.1" + resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.3.1.tgz#8560808c916ef02ecfd55e66090df23a4b7aa642" + integrity sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw== -tiny-warning@^1.0.0, tiny-warning@^1.0.3: +tiny-warning@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754" integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA== @@ -7143,12 +6916,7 @@ tiny-warning@^1.0.0, tiny-warning@^1.0.3: to-fast-properties@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" - integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= - -to-readable-stream@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/to-readable-stream/-/to-readable-stream-1.0.0.tgz#ce0aa0c2f3df6adf852efb404a783e77c0475771" - integrity sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q== + integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== to-regex-range@^5.0.1: version "5.0.1" @@ -7157,16 +6925,21 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" -toidentifier@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" - integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== +toidentifier@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35" + integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA== totalist@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/totalist/-/totalist-1.1.0.tgz#a4d65a3e546517701e3e5c37a47a70ac97fe56df" integrity sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g== +tr46@~0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" + integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== + trim-trailing-lines@^1.0.0: version "1.1.4" resolved "https://registry.yarnpkg.com/trim-trailing-lines/-/trim-trailing-lines-1.1.4.tgz#bd4abbec7cc880462f10b2c8b5ce1d8d1ec7c2c0" @@ -7182,27 +6955,22 @@ trough@^1.0.0: resolved "https://registry.yarnpkg.com/trough/-/trough-1.0.5.tgz#b8b639cefad7d0bb2abd37d433ff8293efa5f406" integrity sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA== -ts-essentials@^2.0.3: - version "2.0.12" - resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-2.0.12.tgz#c9303f3d74f75fa7528c3d49b80e089ab09d8745" - integrity sha512-3IVX4nI6B5cc31/GFFE+i8ey/N2eA0CZDbo6n0yrz0zDX8ZJ8djmU1p+XRz7G3is0F3bB3pu2pAroFdAWQKU3w== - -tslib@^2.0.3, tslib@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01" - integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw== - -tslib@~2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.1.0.tgz#da60860f1c2ecaa5703ab7d39bc05b6bf988b97a" - integrity sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A== +tslib@^2.0.3, tslib@^2.1.0, tslib@^2.4.0: + version "2.4.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.1.tgz#0d0bfbaac2880b91e22df0768e55be9753a5b17e" + integrity sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA== type-fest@^0.20.2: version "0.20.2" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== -type-is@~1.6.17, type-is@~1.6.18: +type-fest@^2.5.0: + version "2.19.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-2.19.0.tgz#88068015bb33036a598b952e55e9311a60fd3a9b" + integrity sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA== + +type-is@~1.6.18: version "1.6.18" resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== @@ -7218,19 +6986,9 @@ typedarray-to-buffer@^3.1.5: is-typedarray "^1.0.0" ua-parser-js@^0.7.30: - version "0.7.31" - resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.31.tgz#649a656b191dffab4f21d5e053e27ca17cbff5c6" - integrity sha512-qLK/Xe9E2uzmYI3qLeOmI0tEOt+TBBQyUIAh4aAgU05FVYzeZrKUdkAZfBNVGRaHVgV0TDkdEngJSw/SyQchkQ== - -unbox-primitive@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.1.tgz#085e215625ec3162574dc8859abee78a59b14471" - integrity sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw== - dependencies: - function-bind "^1.1.1" - has-bigints "^1.0.1" - has-symbols "^1.0.2" - which-boxed-primitive "^1.0.2" + version "0.7.32" + resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.32.tgz#cd8c639cdca949e30fa68c44b7813ef13e36d211" + integrity sha512-f9BESNVhzlhEFf2CHMSj40NWOjYPl1YKYbrvIr/hFTDEmLq7SRbWvm7FcdcpCYT95zrOhC7gZSxjdnnTpBcwVw== unherit@^1.0.4: version "1.1.3" @@ -7253,15 +7011,15 @@ unicode-match-property-ecmascript@^2.0.0: unicode-canonical-property-names-ecmascript "^2.0.0" unicode-property-aliases-ecmascript "^2.0.0" -unicode-match-property-value-ecmascript@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz#1a01aa57247c14c568b89775a54938788189a714" - integrity sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw== +unicode-match-property-value-ecmascript@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz#cb5fffdcd16a05124f5a4b0bf7c3770208acbbe0" + integrity sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA== unicode-property-aliases-ecmascript@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.0.0.tgz#0a36cb9a585c4f6abd51ad1deddb285c165297c8" - integrity sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ== + version "2.1.0" + resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz#43d41e3be698bd493ef911077c9b131f827e8ccd" + integrity sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w== unified@9.2.0: version "9.2.0" @@ -7275,22 +7033,18 @@ unified@9.2.0: trough "^1.0.0" vfile "^4.0.0" -unified@^8.4.2: - version "8.4.2" - resolved "https://registry.yarnpkg.com/unified/-/unified-8.4.2.tgz#13ad58b4a437faa2751a4a4c6a16f680c500fff1" - integrity sha512-JCrmN13jI4+h9UAyKEoGcDZV+i1E7BLFuG7OsaDvTXI5P0qhHX+vZO/kOhz9jn8HGENDKbwSeB0nVOg4gVStGA== +unified@^9.2.2: + version "9.2.2" + resolved "https://registry.yarnpkg.com/unified/-/unified-9.2.2.tgz#67649a1abfc3ab85d2969502902775eb03146975" + integrity sha512-Sg7j110mtefBD+qunSLO1lqOEKdrwBFBrR6Qd8f4uwkhWNlbkaqwHse6e7QvD3AP/MNoJdEDLaf8OxYyoWgorQ== dependencies: bail "^1.0.0" extend "^3.0.0" + is-buffer "^2.0.0" is-plain-obj "^2.0.0" trough "^1.0.0" vfile "^4.0.0" -uniqs@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/uniqs/-/uniqs-2.0.0.tgz#ffede4b36b25290696e6e165d4a59edb998e6b02" - integrity sha1-/+3ks2slKQaW5uFl1KWe25mOawI= - unique-string@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-2.0.0.tgz#39c6451f81afb2749de2b233e3f7c5e8843bd89d" @@ -7325,13 +7079,6 @@ unist-util-remove-position@^2.0.0: dependencies: unist-util-visit "^2.0.0" -unist-util-remove@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/unist-util-remove/-/unist-util-remove-2.0.0.tgz#32c2ad5578802f2ca62ab808173d505b2c898488" - integrity sha512-HwwWyNHKkeg/eXRnE11IpzY8JT55JNM1YCwwU9YNCnfzk6s8GhPXrVBBZWiwLeATJbI7euvoGSzcy9M29UeW3g== - dependencies: - unist-util-is "^4.0.0" - unist-util-remove@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/unist-util-remove/-/unist-util-remove-2.1.0.tgz#b0b4738aa7ee445c402fda9328d604a02d010588" @@ -7354,7 +7101,7 @@ unist-util-visit-parents@^3.0.0: "@types/unist" "^2.0.0" unist-util-is "^4.0.0" -unist-util-visit@2.0.3, unist-util-visit@^2.0.0, unist-util-visit@^2.0.1, unist-util-visit@^2.0.2, unist-util-visit@^2.0.3: +unist-util-visit@2.0.3, unist-util-visit@^2.0.0, unist-util-visit@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-2.0.3.tgz#c3703893146df47203bb8a9795af47d7b971208c" integrity sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q== @@ -7371,12 +7118,15 @@ universalify@^2.0.0: unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" - integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= + integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ== -unquote@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/unquote/-/unquote-1.1.1.tgz#8fded7324ec6e88a0ff8b905e7c098cdc086d544" - integrity sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ= +update-browserslist-db@^1.0.9: + version "1.0.10" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz#0f54b876545726f17d00cd9a2561e6dade943ff3" + integrity sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ== + dependencies: + escalade "^3.1.1" + picocolors "^1.0.0" update-notifier@^5.1.0: version "5.1.0" @@ -7414,59 +7164,32 @@ url-loader@^4.1.1: mime-types "^2.1.27" schema-utils "^3.0.0" -url-parse-lax@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c" - integrity sha1-FrXK/Afb42dsGxmZF3gj1lA6yww= - dependencies: - prepend-http "^2.0.0" - -url@^0.11.0: - version "0.11.0" - resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" - integrity sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE= - dependencies: - punycode "1.3.2" - querystring "0.2.0" - -use-composed-ref@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/use-composed-ref/-/use-composed-ref-1.1.0.tgz#9220e4e94a97b7b02d7d27eaeab0b37034438bbc" - integrity sha512-my1lNHGWsSDAhhVAT4MKs6IjBUtG6ZG11uUqexPH9PptiIZDQOzaF4f5tEbJ2+7qvNbtXNBbU3SfmN+fXlWDhg== - dependencies: - ts-essentials "^2.0.3" +use-composed-ref@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/use-composed-ref/-/use-composed-ref-1.3.0.tgz#3d8104db34b7b264030a9d916c5e94fbe280dbda" + integrity sha512-GLMG0Jc/jiKov/3Ulid1wbv3r54K9HlMW29IWcDFPEqFkSO2nS0MuefWgMJpeHQ9YJeXDL3ZUF+P3jdXlZX/cQ== -use-isomorphic-layout-effect@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.1.tgz#7bb6589170cd2987a152042f9084f9effb75c225" - integrity sha512-L7Evj8FGcwo/wpbv/qvSfrkHFtOpCzvM5yl2KVyDJoylVuSvzphiiasmjgQPttIGBAy2WKiBNR98q8w7PiNgKQ== +use-isomorphic-layout-effect@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.2.tgz#497cefb13d863d687b08477d9e5a164ad8c1a6fb" + integrity sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA== -use-latest@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/use-latest/-/use-latest-1.2.0.tgz#a44f6572b8288e0972ec411bdd0840ada366f232" - integrity sha512-d2TEuG6nSLKQLAfW3By8mKr8HurOlTkul0sOpxbClIv4SQ4iOd7BYr7VIzdbktUCnv7dua/60xzd8igMU6jmyw== +use-latest@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/use-latest/-/use-latest-1.2.1.tgz#d13dfb4b08c28e3e33991546a2cee53e14038cf2" + integrity sha512-xA+AVm/Wlg3e2P/JiItTziwS7FK92LWrDB0p+hgXloIMuVCeJJ8v6f0eeHyPZaJrM+usM1FkFfbNCrJGs8A/zw== dependencies: - use-isomorphic-layout-effect "^1.0.0" + use-isomorphic-layout-effect "^1.1.1" util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= - -util.promisify@~1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.1.tgz#6baf7774b80eeb0f7520d8b81d07982a59abbaee" - integrity sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA== - dependencies: - define-properties "^1.1.3" - es-abstract "^1.17.2" - has-symbols "^1.0.1" - object.getownpropertydescriptors "^2.1.0" + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== utila@~0.4: version "0.4.0" resolved "https://registry.yarnpkg.com/utila/-/utila-0.4.0.tgz#8a16a05d445657a3aea5eecc5b12a4fa5379772c" - integrity sha1-ihagXURWV6Oupe7MWxKk+lN5dyw= + integrity sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA== utility-types@^3.10.0: version "3.10.0" @@ -7476,12 +7199,12 @@ utility-types@^3.10.0: utils-merge@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" - integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= + integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== -uuid@^3.4.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" - integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== +uuid@^8.3.2: + version "8.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" + integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== value-equal@^1.0.1: version "1.0.1" @@ -7491,12 +7214,7 @@ value-equal@^1.0.1: vary@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" - integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= - -vendors@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/vendors/-/vendors-1.0.4.tgz#e2b800a53e7a29b93506c3cf41100d16c4c4ad8e" - integrity sha512-/juG65kTL4Cy2su4P8HjtkTxk6VmJDiOPBufWniqQ6wknac6jNiXS9vU+hO3wgusiyqWlzTbVHi0dyJqRONg3w== + integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== vfile-location@^3.0.0, vfile-location@^3.2.0: version "3.2.0" @@ -7521,21 +7239,21 @@ vfile@^4.0.0: unist-util-stringify-position "^2.0.0" vfile-message "^2.0.0" -wait-on@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/wait-on/-/wait-on-6.0.0.tgz#7e9bf8e3d7fe2daecbb7a570ac8ca41e9311c7e7" - integrity sha512-tnUJr9p5r+bEYXPUdRseolmz5XqJTTj98JgOsfBn7Oz2dxfE2g3zw1jE+Mo8lopM3j3et/Mq1yW7kKX6qw7RVw== +wait-on@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/wait-on/-/wait-on-6.0.1.tgz#16bbc4d1e4ebdd41c5b4e63a2e16dbd1f4e5601e" + integrity sha512-zht+KASY3usTY5u2LgaNqn/Cd8MukxLGjdcZxT2ns5QzDmTFc4XoWBgC+C/na+sMRZTuVygQoMYwdcVjHnYIVw== dependencies: - axios "^0.21.1" - joi "^17.4.0" + axios "^0.25.0" + joi "^17.6.0" lodash "^4.17.21" minimist "^1.2.5" - rxjs "^7.1.0" + rxjs "^7.5.4" -watchpack@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.2.0.tgz#47d78f5415fe550ecd740f99fe2882323a58b1ce" - integrity sha512-up4YAn/XHgZHIxFBVCdlMiWDj6WaLKpwVeGQk2I5thdYxF/KmF0aaz6TfJZ/hfl1h/XlcDr7k1KH7ThDagpFaA== +watchpack@^2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.0.tgz#fa33032374962c78113f93c7f2fb4c54c9862a5d" + integrity sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg== dependencies: glob-to-regexp "^0.4.1" graceful-fs "^4.1.2" @@ -7547,15 +7265,20 @@ wbuf@^1.1.0, wbuf@^1.7.3: dependencies: minimalistic-assert "^1.0.0" -web-namespaces@^1.0.0, web-namespaces@^1.1.2: +web-namespaces@^1.0.0: version "1.1.4" resolved "https://registry.yarnpkg.com/web-namespaces/-/web-namespaces-1.1.4.tgz#bc98a3de60dadd7faefc403d1076d529f5e030ec" integrity sha512-wYxSGajtmoP4WxfejAPIr4l0fVh+jeMXZb08wNc0tMg6xsfZXj3cECqIK0G7ZAqUq0PP8WlMDtaOGVBTAWztNw== -webpack-bundle-analyzer@^4.4.2: - version "4.5.0" - resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.5.0.tgz#1b0eea2947e73528754a6f9af3e91b2b6e0f79d5" - integrity sha512-GUMZlM3SKwS8Z+CKeIFx7CVoHn3dXFcUAjT/dcZQQmfSZGvitPfMob2ipjai7ovFFqPvTqkEZ/leL4O0YOdAYQ== +webidl-conversions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" + integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== + +webpack-bundle-analyzer@^4.5.0: + version "4.7.0" + resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.7.0.tgz#33c1c485a7fcae8627c547b5c3328b46de733c66" + integrity sha512-j9b8ynpJS4K+zfO5GGwsAcQX4ZHpWV+yRiHDiL+bE0XHJ8NiPYLTNVQdlFYWxtpg9lfAQNlwJg16J9AJtFSXRg== dependencies: acorn "^8.0.4" acorn-walk "^8.0.0" @@ -7567,47 +7290,51 @@ webpack-bundle-analyzer@^4.4.2: sirv "^1.0.7" ws "^7.3.1" -webpack-dev-middleware@^5.2.1: - version "5.2.1" - resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-5.2.1.tgz#97c948144349177856a3d2d9c612cc3fee180cf1" - integrity sha512-Kx1X+36Rn9JaZcQMrJ7qN3PMAuKmEDD9ZISjUj3Cgq4A6PtwYsC4mpaKotSRYH3iOF6HsUa8viHKS59FlyVifQ== +webpack-dev-middleware@^5.3.1: + version "5.3.3" + resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-5.3.3.tgz#efae67c2793908e7311f1d9b06f2a08dcc97e51f" + integrity sha512-hj5CYrY0bZLB+eTO+x/j67Pkrquiy7kWepMHmUMoPsmcUaeEnQJqFzHJOyxgWlq746/wUuA64p9ta34Kyb01pA== dependencies: colorette "^2.0.10" - memfs "^3.2.2" + memfs "^3.4.3" mime-types "^2.1.31" range-parser "^1.2.1" - schema-utils "^3.1.0" - -webpack-dev-server@^4.4.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.4.0.tgz#10ec17088f840c9ccb2ebb0b43c49ec293206f7e" - integrity sha512-+S0XRIbsopVjPFjCO8I07FXYBWYqkFmuP56ucGMTs2hA/gV4q2M9xTmNo5Tg4o8ffRR+Nm3AsXnQXxKRyYovrA== - dependencies: + schema-utils "^4.0.0" + +webpack-dev-server@^4.9.3: + version "4.11.1" + resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-4.11.1.tgz#ae07f0d71ca0438cf88446f09029b92ce81380b5" + integrity sha512-lILVz9tAUy1zGFwieuaQtYiadImb5M3d+H+L1zDYalYoDl0cksAB1UNyuE5MMWJrG6zR1tXkCP2fitl7yoUJiw== + dependencies: + "@types/bonjour" "^3.5.9" + "@types/connect-history-api-fallback" "^1.3.5" + "@types/express" "^4.17.13" + "@types/serve-index" "^1.9.1" + "@types/serve-static" "^1.13.10" + "@types/sockjs" "^0.3.33" + "@types/ws" "^8.5.1" ansi-html-community "^0.0.8" - bonjour "^3.5.0" - chokidar "^3.5.2" + bonjour-service "^1.0.11" + chokidar "^3.5.3" colorette "^2.0.10" compression "^1.7.4" - connect-history-api-fallback "^1.6.0" - del "^6.0.0" - express "^4.17.1" + connect-history-api-fallback "^2.0.0" + default-gateway "^6.0.3" + express "^4.17.3" graceful-fs "^4.2.6" html-entities "^2.3.2" - http-proxy-middleware "^2.0.0" - internal-ip "^6.2.0" + http-proxy-middleware "^2.0.3" ipaddr.js "^2.0.1" open "^8.0.9" p-retry "^4.5.0" - portfinder "^1.0.28" - schema-utils "^3.1.0" - selfsigned "^1.10.11" + rimraf "^3.0.2" + schema-utils "^4.0.0" + selfsigned "^2.1.1" serve-index "^1.9.1" - sockjs "^0.3.21" + sockjs "^0.3.24" spdy "^4.0.2" - strip-ansi "^7.0.0" - url "^0.11.0" - webpack-dev-middleware "^5.2.1" - ws "^8.1.0" + webpack-dev-middleware "^5.3.1" + ws "^8.4.2" webpack-merge@^5.8.0: version "5.8.0" @@ -7617,50 +7344,42 @@ webpack-merge@^5.8.0: clone-deep "^4.0.1" wildcard "^2.0.0" -webpack-sources@^1.1.0, webpack-sources@^1.4.3: - version "1.4.3" - resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.4.3.tgz#eedd8ec0b928fbf1cbfe994e22d2d890f330a933" - integrity sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ== - dependencies: - source-list-map "^2.0.0" - source-map "~0.6.1" - -webpack-sources@^3.2.0: - version "3.2.1" - resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.1.tgz#251a7d9720d75ada1469ca07dbb62f3641a05b6d" - integrity sha512-t6BMVLQ0AkjBOoRTZgqrWm7xbXMBzD+XDq2EZ96+vMfn3qKgsvdXZhbPZ4ElUOpdv4u+iiGe+w3+J75iy/bYGA== +webpack-sources@^3.2.2, webpack-sources@^3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" + integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== -webpack@^5.61.0: - version "5.62.1" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.62.1.tgz#06f09b56a7b1bb13ed5137ad4b118358a90c9505" - integrity sha512-jNLtnWChS2CMZ7vqWtztv0G6fYB5hz11Zsadp5tE7e4/66zVDj7/KUeQZOsOl8Hz5KrLJH1h2eIDl6AnlyE12Q== +webpack@^5.73.0: + version "5.75.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.75.0.tgz#1e440468647b2505860e94c9ff3e44d5b582c152" + integrity sha512-piaIaoVJlqMsPtX/+3KTTO6jfvrSYgauFVdt8cr9LTHKmcq/AMd4mhzsiP7ZF/PGRNPGA8336jldh9l2Kt2ogQ== dependencies: - "@types/eslint-scope" "^3.7.0" - "@types/estree" "^0.0.50" + "@types/eslint-scope" "^3.7.3" + "@types/estree" "^0.0.51" "@webassemblyjs/ast" "1.11.1" "@webassemblyjs/wasm-edit" "1.11.1" "@webassemblyjs/wasm-parser" "1.11.1" - acorn "^8.4.1" + acorn "^8.7.1" acorn-import-assertions "^1.7.6" browserslist "^4.14.5" chrome-trace-event "^1.0.2" - enhanced-resolve "^5.8.3" + enhanced-resolve "^5.10.0" es-module-lexer "^0.9.0" eslint-scope "5.1.1" events "^3.2.0" glob-to-regexp "^0.4.1" - graceful-fs "^4.2.4" - json-parse-better-errors "^1.0.2" + graceful-fs "^4.2.9" + json-parse-even-better-errors "^2.3.1" loader-runner "^4.2.0" mime-types "^2.1.27" neo-async "^2.6.2" schema-utils "^3.1.0" tapable "^2.1.1" terser-webpack-plugin "^5.1.3" - watchpack "^2.2.0" - webpack-sources "^3.2.0" + watchpack "^2.4.0" + webpack-sources "^3.2.3" -webpackbar@^5.0.0-3: +webpackbar@^5.0.2: version "5.0.2" resolved "https://registry.yarnpkg.com/webpackbar/-/webpackbar-5.0.2.tgz#d3dd466211c73852741dfc842b7556dcbc2b0570" integrity sha512-BmFJo7veBDgQzfWXl/wwYXr/VFus0614qZ8i9znqcl9fnEdiVkdbi0TedLQ6xAK92HZHDJ0QmyQ0fmuZPAgCYQ== @@ -7684,16 +7403,13 @@ websocket-extensions@>=0.1.1: resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42" integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg== -which-boxed-primitive@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" - integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== dependencies: - is-bigint "^1.0.1" - is-boolean-object "^1.1.0" - is-number-object "^1.0.4" - is-string "^1.0.5" - is-symbol "^1.0.3" + tr46 "~0.0.3" + webidl-conversions "^3.0.0" which@^1.3.1: version "1.3.1" @@ -7716,6 +7432,13 @@ widest-line@^3.1.0: dependencies: string-width "^4.0.0" +widest-line@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-4.0.1.tgz#a0fc673aaba1ea6f0a0d35b3c2795c9a9cc2ebf2" + integrity sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig== + dependencies: + string-width "^5.0.1" + wildcard@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.0.tgz#a77d20e5200c6faaac979e4b3aadc7b3dd7f8fec" @@ -7730,10 +7453,19 @@ wrap-ansi@^7.0.0: string-width "^4.1.0" strip-ansi "^6.0.0" +wrap-ansi@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.0.1.tgz#2101e861777fec527d0ea90c57c6b03aac56a5b3" + integrity sha512-QFF+ufAqhoYHvoHdajT/Po7KoXVBPXS2bgjIam5isfWJPfIOnQZ50JtUiVvCv/sjgacf3yRrt2ZKUZ/V4itN4g== + dependencies: + ansi-styles "^6.1.0" + string-width "^5.0.1" + strip-ansi "^7.0.1" + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== write-file-atomic@^3.0.0: version "3.0.3" @@ -7746,14 +7478,14 @@ write-file-atomic@^3.0.0: typedarray-to-buffer "^3.1.5" ws@^7.3.1: - version "7.5.5" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.5.tgz#8b4bc4af518cfabd0473ae4f99144287b33eb881" - integrity sha512-BAkMFcAzl8as1G/hArkxOxq3G7pjUqQ3gzYbLL0/5zNkph70e+lCoxBGnm6AW1+/aiNeV4fnKqZ8m4GZewmH2w== + version "7.5.9" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591" + integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q== -ws@^8.1.0: - version "8.2.3" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.2.3.tgz#63a56456db1b04367d0b721a0b80cae6d8becbba" - integrity sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA== +ws@^8.4.2: + version "8.11.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.11.0.tgz#6a0d36b8edfd9f96d8b25683db2f8d7de6e8e143" + integrity sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg== xdg-basedir@^4.0.0: version "4.0.0" @@ -7782,6 +7514,11 @@ yaml@^1.10.0, yaml@^1.10.2, yaml@^1.7.2: resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== +yarn@^1.22: + version "1.22.19" + resolved "https://registry.yarnpkg.com/yarn/-/yarn-1.22.19.tgz#4ba7fc5c6e704fce2066ecbfb0b0d8976fe62447" + integrity sha512-/0V5q0WbslqnwP91tirOvldvYISzaqhClxzyUKXYxs07yUILIs5jx/k6CFe8bvKSkds5w+eiOqta39Wk3WxdcQ== + yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"