mirror of
https://github.com/google/promises
synced 2026-11-09 22:26:00 +05:45
Initial
This commit is contained in:
commit
543d70a02d
139 files changed
+12415
No files matched your search
@@ -0,0 +1,8 @@
|
||||
BasedOnStyle: Google
|
||||
|
||||
AlignOperands: false
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
BreakBeforeTernaryOperators: false
|
||||
ColumnLimit: 100
|
||||
PointerBindsToType: false
|
||||
+98
@@ -0,0 +1,98 @@
|
||||
# Generic build products
|
||||
|
||||
*.[oa]
|
||||
[Bb]uild/
|
||||
[Pp]re-[Bb]uild/
|
||||
[Dd]eliverables/
|
||||
[Dd]istribution/
|
||||
[Dd]ocumentation/
|
||||
[Dd]ocs/
|
||||
|
||||
# Swift PM
|
||||
|
||||
Packages/
|
||||
.build/
|
||||
*.xcodeproj
|
||||
*.resolved
|
||||
|
||||
# Bazel
|
||||
|
||||
bazel-*
|
||||
|
||||
# Other VCS
|
||||
|
||||
.hg
|
||||
.svn
|
||||
*.prej
|
||||
*.mine
|
||||
CVS
|
||||
|
||||
# OSX
|
||||
|
||||
.DS_Store
|
||||
.DS_Store?
|
||||
._*
|
||||
.~*
|
||||
~$*
|
||||
*.lock
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
.DocumentRevisions-V100
|
||||
.fseventsd
|
||||
.Spotlight-V100
|
||||
.TemporaryItems
|
||||
.Trashes
|
||||
ehthumbs.db
|
||||
Thumbs.db
|
||||
.AppleDB
|
||||
.AppleDesktop
|
||||
.apdisk
|
||||
|
||||
# Windows
|
||||
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
Desktop.ini
|
||||
$RECYCLE.BIN/
|
||||
*.cab
|
||||
*.msi
|
||||
*.msm
|
||||
*.msp
|
||||
*.lnk
|
||||
|
||||
# Xcode
|
||||
|
||||
DerivedData/
|
||||
xcuserdata/
|
||||
project.xcworkspace/
|
||||
*.mode1
|
||||
*.mode1v3
|
||||
*.mode2v3
|
||||
*.perspective
|
||||
*.perspectivev3
|
||||
*.pbxuser
|
||||
*.xccheckout
|
||||
*.moved-aside
|
||||
*.xcuserstate
|
||||
*.xctimeline
|
||||
|
||||
# JetBrains
|
||||
|
||||
.idea/
|
||||
|
||||
# CocoaPods
|
||||
|
||||
!Podfile.lock
|
||||
!Pods/Manifest.lock
|
||||
Pods/Documentation
|
||||
|
||||
#Carthage
|
||||
|
||||
Carthage/
|
||||
|
||||
# SublimeText
|
||||
|
||||
*.tmlanguage.cache
|
||||
*.tmPreferences.cache
|
||||
*.stTheme.cache
|
||||
*.sublime-workspace
|
||||
@@ -0,0 +1,100 @@
|
||||
syntax: glob
|
||||
|
||||
# Generic build products
|
||||
|
||||
*.[oa]
|
||||
[Bb]uild/
|
||||
[Pp]re-[Bb]uild/
|
||||
[Dd]eliverables/
|
||||
[Dd]istribution/
|
||||
[Dd]ocumentation/
|
||||
[Dd]ocs/
|
||||
|
||||
# Swift PM
|
||||
|
||||
Packages/
|
||||
.build/
|
||||
*.xcodeproj
|
||||
*.resolved
|
||||
|
||||
# Bazel
|
||||
|
||||
bazel-*
|
||||
|
||||
# Other VCS
|
||||
|
||||
.hg
|
||||
.svn
|
||||
*.prej
|
||||
*.mine
|
||||
CVS
|
||||
|
||||
# OSX
|
||||
|
||||
.DS_Store
|
||||
.DS_Store?
|
||||
._*
|
||||
.~*
|
||||
~$*
|
||||
*.lock
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
.DocumentRevisions-V100
|
||||
.fseventsd
|
||||
.Spotlight-V100
|
||||
.TemporaryItems
|
||||
.Trashes
|
||||
ehthumbs.db
|
||||
Thumbs.db
|
||||
.AppleDB
|
||||
.AppleDesktop
|
||||
.apdisk
|
||||
|
||||
# Windows
|
||||
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
Desktop.ini
|
||||
$RECYCLE.BIN/
|
||||
*.cab
|
||||
*.msi
|
||||
*.msm
|
||||
*.msp
|
||||
*.lnk
|
||||
|
||||
# Xcode
|
||||
|
||||
DerivedData/
|
||||
xcuserdata/
|
||||
project.xcworkspace/
|
||||
*.mode1
|
||||
*.mode1v3
|
||||
*.mode2v3
|
||||
*.perspective
|
||||
*.perspectivev3
|
||||
*.pbxuser
|
||||
*.xccheckout
|
||||
*.moved-aside
|
||||
*.xcuserstate
|
||||
*.xctimeline
|
||||
|
||||
# JetBrains
|
||||
|
||||
.idea/
|
||||
|
||||
# CocoaPods
|
||||
|
||||
!Podfile.lock
|
||||
!Pods/Manifest.lock
|
||||
Pods/Documentation
|
||||
|
||||
#Carthage
|
||||
|
||||
Carthage/
|
||||
|
||||
# SublimeText
|
||||
|
||||
*.tmlanguage.cache
|
||||
*.tmPreferences.cache
|
||||
*.stTheme.cache
|
||||
*.sublime-workspace
|
||||
@@ -0,0 +1,18 @@
|
||||
disabled_rules:
|
||||
- xctfail_message
|
||||
|
||||
line_length: 100
|
||||
function_body_length:
|
||||
warning: 100
|
||||
error: 200
|
||||
type_body_length:
|
||||
warning: 500
|
||||
error: 1000
|
||||
file_length:
|
||||
warning: 1000
|
||||
error: 2000
|
||||
nesting:
|
||||
type_level:
|
||||
warning: 3
|
||||
error: 5
|
||||
cyclomatic_complexity: 15
|
||||
@@ -0,0 +1,172 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load("@build_bazel_rules_apple//apple:ios.bzl", "ios_unit_test")
|
||||
load("@build_bazel_rules_apple//apple:swift.bzl", "swift_library")
|
||||
|
||||
OBJC_COPTS = [
|
||||
"-Werror",
|
||||
"-Wextra",
|
||||
"-Wall",
|
||||
"-Wdocumentation",
|
||||
]
|
||||
|
||||
SWIFT_COPTS = [
|
||||
"-wmo",
|
||||
]
|
||||
|
||||
swift_library(
|
||||
name = "Promises",
|
||||
srcs = glob([
|
||||
"Sources/Promises/*.swift",
|
||||
]),
|
||||
copts = SWIFT_COPTS,
|
||||
module_name = "Promises",
|
||||
deps = [
|
||||
":FBLPromises",
|
||||
],
|
||||
)
|
||||
|
||||
swift_library(
|
||||
name = "PromisesTestHelpers",
|
||||
testonly = 1,
|
||||
srcs = glob([
|
||||
"Sources/PromisesTestHelpers/*.swift",
|
||||
]),
|
||||
copts = SWIFT_COPTS,
|
||||
module_name = "PromisesTestHelpers",
|
||||
deps = [
|
||||
":Promises",
|
||||
],
|
||||
)
|
||||
|
||||
objc_library(
|
||||
name = "FBLPromises",
|
||||
srcs = glob([
|
||||
"Sources/FBLPromises/*.m",
|
||||
"Sources/FBLPromises/DotSyntax/*.m",
|
||||
]),
|
||||
hdrs = glob([
|
||||
"Sources/FBLPromises/include/*.h",
|
||||
"Sources/FBLPromises/include/DotSyntax/*.h",
|
||||
]) + [
|
||||
"FBLPromises.h",
|
||||
],
|
||||
copts = OBJC_COPTS,
|
||||
defines = [
|
||||
"FBL_PROMISES_DOT_SYNTAX_IS_DEPRECATED",
|
||||
],
|
||||
includes = [
|
||||
"Sources/FBLPromises/include",
|
||||
],
|
||||
module_map = "Sources/FBLPromises/include/module.modulemap",
|
||||
)
|
||||
|
||||
objc_library(
|
||||
name = "FBLPromisesTestHelpers",
|
||||
testonly = 1,
|
||||
srcs = glob([
|
||||
"Sources/FBLPromisesTestHelpers/*.m",
|
||||
]),
|
||||
hdrs = glob([
|
||||
"Sources/FBLPromisesTestHelpers/include/*.h",
|
||||
]),
|
||||
copts = OBJC_COPTS,
|
||||
includes = [
|
||||
"Sources/FBLPromisesTestHelpers/include",
|
||||
],
|
||||
module_map = "Sources/FBLPromisesTestHelpers/include/module.modulemap",
|
||||
deps = [
|
||||
":FBLPromises",
|
||||
],
|
||||
)
|
||||
|
||||
ios_unit_test(
|
||||
name = "Tests",
|
||||
deps = [
|
||||
":FBLPromisesInteroperabilityTests",
|
||||
":FBLPromisesPerformanceTests",
|
||||
":FBLPromisesTests",
|
||||
":PromisesInteroperabilityTests",
|
||||
":PromisesPerformanceTests",
|
||||
":PromisesTests",
|
||||
],
|
||||
)
|
||||
|
||||
swift_library(
|
||||
name = "PromisesTests",
|
||||
testonly = 1,
|
||||
srcs = glob([
|
||||
"Tests/PromisesTests/*.swift",
|
||||
]),
|
||||
copts = SWIFT_COPTS,
|
||||
deps = [
|
||||
":PromisesTestHelpers",
|
||||
],
|
||||
)
|
||||
|
||||
swift_library(
|
||||
name = "PromisesInteroperabilityTests",
|
||||
testonly = 1,
|
||||
srcs = glob([
|
||||
"Tests/PromisesInteroperabilityTests/*.swift",
|
||||
]),
|
||||
copts = SWIFT_COPTS,
|
||||
deps = [
|
||||
":FBLPromisesTestHelpers",
|
||||
":PromisesTestHelpers",
|
||||
],
|
||||
)
|
||||
|
||||
swift_library(
|
||||
name = "PromisesPerformanceTests",
|
||||
testonly = 1,
|
||||
srcs = glob([
|
||||
"Tests/PromisesPerformanceTests/*.swift",
|
||||
]),
|
||||
copts = SWIFT_COPTS,
|
||||
swift_version = 4,
|
||||
deps = [
|
||||
":FBLPromisesTestHelpers",
|
||||
":PromisesTestHelpers",
|
||||
],
|
||||
)
|
||||
|
||||
objc_library(
|
||||
name = "FBLPromisesTests",
|
||||
testonly = 1,
|
||||
srcs = glob([
|
||||
"Tests/FBLPromisesTests/*.m",
|
||||
]),
|
||||
copts = OBJC_COPTS,
|
||||
deps = [
|
||||
":FBLPromisesTestHelpers",
|
||||
],
|
||||
)
|
||||
|
||||
objc_library(
|
||||
name = "FBLPromisesInteroperabilityTests",
|
||||
testonly = 1,
|
||||
srcs = glob([
|
||||
"Tests/FBLPromisesInteroperabilityTests/*.m",
|
||||
]),
|
||||
copts = OBJC_COPTS,
|
||||
includes = [
|
||||
"../Promises",
|
||||
],
|
||||
deps = [
|
||||
":FBLPromisesTestHelpers",
|
||||
":PromisesTestHelpers",
|
||||
],
|
||||
)
|
||||
|
||||
objc_library(
|
||||
name = "FBLPromisesPerformanceTests",
|
||||
testonly = 1,
|
||||
srcs = glob([
|
||||
"Tests/FBLPromisesPerformanceTests/*.m",
|
||||
]),
|
||||
copts = OBJC_COPTS,
|
||||
deps = [
|
||||
":FBLPromisesTestHelpers",
|
||||
],
|
||||
)
|
||||
@@ -0,0 +1,54 @@
|
||||
# How to contribute #
|
||||
|
||||
We'd love to accept your patches and contributions to this project. There are
|
||||
a just a few small guidelines you need to follow.
|
||||
|
||||
|
||||
## Contributor License Agreement ##
|
||||
|
||||
Contributions to any Google project must be accompanied by a Contributor
|
||||
License Agreement. This is not a copyright **assignment**, it simply gives
|
||||
Google permission to use and redistribute your contributions as part of the
|
||||
project.
|
||||
|
||||
* If you are an individual writing original source code and you're sure you
|
||||
own the intellectual property, then you'll need to sign an [individual
|
||||
CLA][].
|
||||
|
||||
* If you work for a company that wants to allow you to contribute your work,
|
||||
then you'll need to sign a [corporate CLA][].
|
||||
|
||||
You generally only need to submit a CLA once, so if you've already submitted
|
||||
one (even if it was for a different project), you probably don't need to do it
|
||||
again.
|
||||
|
||||
[individual CLA]: https://developers.google.com/open-source/cla/individual
|
||||
[corporate CLA]: https://developers.google.com/open-source/cla/corporate
|
||||
|
||||
|
||||
## Submitting a patch ##
|
||||
|
||||
1. It's generally best to start by opening a new issue describing the bug or
|
||||
feature you're intending to fix. Even if you think it's relatively minor,
|
||||
it's helpful to know what people are working on. Mention in the initial
|
||||
issue that you are planning to work on that bug or feature so that it can
|
||||
be assigned to you.
|
||||
|
||||
1. Follow the normal process of [forking][] the project, and setup a new
|
||||
branch to work in. It's important that each group of changes be done in
|
||||
separate branches in order to ensure that a pull request only includes the
|
||||
commits related to that bug or feature.
|
||||
|
||||
1. Any significant changes should almost always be accompanied by tests. The
|
||||
project already has good test coverage, so look at some of the existing
|
||||
tests if you're unsure how to go about it.
|
||||
|
||||
1. Do your best to have [well-formed commit messages][] for each change.
|
||||
This provides consistency throughout the project, and ensures that commit
|
||||
messages are able to be formatted properly by various git tools.
|
||||
|
||||
1. Finally, push the commits to your fork and submit a [pull request][].
|
||||
|
||||
[forking]: https://help.github.com/articles/fork-a-repo
|
||||
[well-formed commit messages]: http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html
|
||||
[pull request]: https://help.github.com/articles/creating-a-pull-request
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
Sources/FBLPromises/include/FBLPromises.h
|
||||
@@ -0,0 +1,202 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
+118
@@ -0,0 +1,118 @@
|
||||
// swift-tools-version:4.0
|
||||
// swiftlint:disable line_length
|
||||
// swiftlint:disable trailing_comma
|
||||
|
||||
// To generate and open project in Xcode run:
|
||||
// swift package -Xswiftc -ISources/FBLPromises/include generate-xcodeproj && open Promises.xcworkspace
|
||||
|
||||
// Copyright 2018 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at:
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import PackageDescription
|
||||
|
||||
let package = Package(
|
||||
name: "Promises",
|
||||
products: [
|
||||
.library(
|
||||
name: "FBLPromises",
|
||||
targets: [
|
||||
"FBLPromises",
|
||||
]
|
||||
),
|
||||
.library(
|
||||
name: "FBLPromisesTestHelpers",
|
||||
targets: [
|
||||
"FBLPromisesTestHelpers",
|
||||
]
|
||||
),
|
||||
.library(
|
||||
name: "Promises",
|
||||
targets: [
|
||||
"Promises",
|
||||
]
|
||||
),
|
||||
.library(
|
||||
name: "PromisesTestHelpers",
|
||||
targets: [
|
||||
"PromisesTestHelpers",
|
||||
]
|
||||
),
|
||||
],
|
||||
targets: [
|
||||
.target(
|
||||
name: "FBLPromises"
|
||||
),
|
||||
.target(
|
||||
name: "FBLPromisesTestHelpers",
|
||||
dependencies: [
|
||||
"FBLPromises",
|
||||
]
|
||||
),
|
||||
.testTarget(
|
||||
name: "FBLPromisesTests",
|
||||
dependencies: [
|
||||
"FBLPromisesTestHelpers",
|
||||
]
|
||||
),
|
||||
// Swift Package Manager doesn't support importing Swift in ObjC just yet.
|
||||
// To work around uncomment the rule below, generate Xcode project and set
|
||||
// CLANG_ENABLE_MODULES = YES for FBLPromisesInteroperabilityTests target
|
||||
// to @import PromisesTestHelpers; instead of #import "PromisesTestHelpers-Swift.h".
|
||||
// .testTarget(
|
||||
// name: "FBLPromisesInteroperabilityTests",
|
||||
// dependencies: [
|
||||
// "FBLPromisesTestHelpers",
|
||||
// "PromisesTestHelpers",
|
||||
// ]
|
||||
// ),
|
||||
.testTarget(
|
||||
name: "FBLPromisesPerformanceTests",
|
||||
dependencies: [
|
||||
"FBLPromisesTestHelpers",
|
||||
]
|
||||
),
|
||||
.target(
|
||||
name: "Promises",
|
||||
dependencies: [
|
||||
"FBLPromises",
|
||||
]
|
||||
),
|
||||
.target(
|
||||
name: "PromisesTestHelpers",
|
||||
dependencies: [
|
||||
"Promises",
|
||||
]
|
||||
),
|
||||
.testTarget(
|
||||
name: "PromisesTests",
|
||||
dependencies: [
|
||||
"PromisesTestHelpers",
|
||||
]
|
||||
),
|
||||
.testTarget(
|
||||
name: "PromisesInteroperabilityTests",
|
||||
dependencies: [
|
||||
"FBLPromisesTestHelpers",
|
||||
"PromisesTestHelpers",
|
||||
]
|
||||
),
|
||||
.testTarget(
|
||||
name: "PromisesPerformanceTests",
|
||||
dependencies: [
|
||||
"FBLPromisesTestHelpers",
|
||||
"PromisesTestHelpers",
|
||||
]
|
||||
),
|
||||
]
|
||||
)
|
||||
@@ -0,0 +1,50 @@
|
||||
// Copyright 2018 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at:
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import Foundation
|
||||
import PlaygroundSupport
|
||||
import Promises
|
||||
|
||||
PlaygroundPage.current.needsIndefiniteExecution = true
|
||||
|
||||
enum PlaygroundError: Error {
|
||||
case invalidNumber
|
||||
}
|
||||
|
||||
func reverse(string: String) -> Promise<String> {
|
||||
return Promise {
|
||||
Thread.sleep(forTimeInterval: 0.1)
|
||||
return String(string.reversed())
|
||||
}
|
||||
}
|
||||
|
||||
func number(from string: String) -> Promise<Int> {
|
||||
return Promise {
|
||||
Thread.sleep(forTimeInterval: 0.1)
|
||||
guard let number = Int(string) else { throw PlaygroundError.invalidNumber }
|
||||
return number
|
||||
}
|
||||
}
|
||||
|
||||
func square(number: Int) -> Int {
|
||||
return number * number
|
||||
}
|
||||
|
||||
reverse(string: "01").then(number(from:)).then(square(number:)).then {
|
||||
print($0) // 100
|
||||
}
|
||||
|
||||
number(from: "hello").catch {
|
||||
print($0) // invalidNumber
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<playground version='5.0' target-platform='macos'>
|
||||
<timeline fileName='timeline.xctimeline'/>
|
||||
</playground>
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "group:Promises.xcodeproj">
|
||||
</FileRef>
|
||||
<FileRef
|
||||
location = "group:Promises.playground">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
@@ -0,0 +1,44 @@
|
||||
# Promises
|
||||
|
||||
[](LICENSE)
|
||||
|
||||
Promises is a modern framework that provides a synchronization construct for
|
||||
Objective-C and Swift that helps simplify writing asynchronous code. The simple
|
||||
and intuitive API will help make your code cleaner, safer, and more readable.
|
||||
|
||||
* [Introduction](g3doc/introduction.md)
|
||||
* [The problem with async
|
||||
code](g3doc/introduction.md#the-problem-with-async-code)
|
||||
* [Promises to the rescue](g3doc/introduction.md#promises-to-the-rescue)
|
||||
* [What is a promise?](g3doc/introduction.md#what-is-a-promise)
|
||||
* [Framework](g3doc/framework.md)
|
||||
* [Features](g3doc/framework.md#features)
|
||||
* [Benchmark](g3doc/framework.md#benchmark)
|
||||
* [Getting started](g3doc/integration.md)
|
||||
* [Add dependency](g3doc/integration.md#add-dependency)
|
||||
* [Import](g3doc/integration.md#import)
|
||||
* [Adopt](g3doc/integration.md#adopt)
|
||||
* [Basics](g3doc/basics.md)
|
||||
* [Creating promises](g3doc/basics.md#creating-promises)
|
||||
* [Observing fulfillment](g3doc/basics.md#observing-fulfillment)
|
||||
* [Observing rejection](g3doc/basics.md#observing-rejection)
|
||||
* [Extensions](g3doc/extensions.md)
|
||||
* [All](g3doc/extensions.md#all)
|
||||
* [Always](g3doc/extensions.md#always)
|
||||
* [Any](g3doc/extensions.md#any)
|
||||
* [Recover](g3doc/extensions.md#recover)
|
||||
* [Resolve](g3doc/extensions.md#resolve)
|
||||
* [Timeout](g3doc/extensions.md#timeout)
|
||||
* [Validate](g3doc/extensions.md#validate)
|
||||
* [When](g3doc/extensions.md#when)
|
||||
* [Advanced topics](g3doc/advanced.md)
|
||||
* [Ownership and retain
|
||||
cycles](g3doc/advanced.md#ownership-and-retain-cycles)
|
||||
* [Testing](g3doc/advanced.md#testing)
|
||||
* [Objective-C <-> Swift
|
||||
interoperability](g3doc/advanced.md#objective-c-wift-interoperability)
|
||||
* [Dot-syntax in Objective-C](g3doc/advanced.md#dot-syntax-in-objective-c)
|
||||
* [Anti-patterns](g3doc/anti-patterns.md)
|
||||
* [Broken chain](g3doc/anti-patterns.md#broken-chain)
|
||||
* [Nested promises](g3doc/anti-patterns.md#nested-promises)
|
||||
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
Copyright 2018 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "DotSyntax/FBLPromise+DotSyntax+All.h"
|
||||
|
||||
@implementation FBLPromise (DotSyntax_AllAdditions)
|
||||
|
||||
+ (FBLPromise<NSArray *> * (^)(NSArray *))all {
|
||||
return ^(NSArray<FBLPromise *> *promises) {
|
||||
return [self all:promises];
|
||||
};
|
||||
}
|
||||
|
||||
+ (FBLPromise<NSArray *> * (^)(dispatch_queue_t, NSArray *))allOn {
|
||||
return ^(dispatch_queue_t queue, NSArray<FBLPromise *> *promises) {
|
||||
return [self onQueue:queue all:promises];
|
||||
};
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
Copyright 2018 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "DotSyntax/FBLPromise+DotSyntax+Always.h"
|
||||
|
||||
@implementation FBLPromise (DotSyntax_AlwaysAdditions)
|
||||
|
||||
- (FBLPromise* (^)(void (^)(void)))always {
|
||||
return ^(void (^work)(void)) {
|
||||
return [self always:work];
|
||||
};
|
||||
}
|
||||
|
||||
- (FBLPromise* (^)(dispatch_queue_t, void (^)(void)))alwaysOn {
|
||||
return ^(dispatch_queue_t queue, void (^work)(void)) {
|
||||
return [self onQueue:queue always:work];
|
||||
};
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
Copyright 2018 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "DotSyntax/FBLPromise+DotSyntax+Any.h"
|
||||
|
||||
@implementation FBLPromise (DotSyntax_AnyAdditions)
|
||||
|
||||
+ (FBLPromise * (^)(NSArray *))any {
|
||||
return ^(NSArray *promises) {
|
||||
return [self any:promises];
|
||||
};
|
||||
}
|
||||
|
||||
+ (FBLPromise * (^)(dispatch_queue_t, NSArray *))anyOn {
|
||||
return ^(dispatch_queue_t queue, NSArray *promises) {
|
||||
return [self onQueue:queue any:promises];
|
||||
};
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
Copyright 2018 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "DotSyntax/FBLPromise+DotSyntax+Async.h"
|
||||
|
||||
@implementation FBLPromise (DotSyntax_AsyncAdditions)
|
||||
|
||||
+ (FBLPromise* (^)(FBLPromiseAsyncWorkBlock))async {
|
||||
return ^(FBLPromiseAsyncWorkBlock work) {
|
||||
return [self async:work];
|
||||
};
|
||||
}
|
||||
|
||||
+ (FBLPromise* (^)(dispatch_queue_t, FBLPromiseAsyncWorkBlock))asyncOn {
|
||||
return ^(dispatch_queue_t queue, FBLPromiseAsyncWorkBlock work) {
|
||||
return [self onQueue:queue async:work];
|
||||
};
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
Copyright 2018 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "DotSyntax/FBLPromise+DotSyntax+Catch.h"
|
||||
|
||||
@implementation FBLPromise (DotSyntax_CatchAdditions)
|
||||
|
||||
- (FBLPromise* (^)(FBLPromiseCatchBlock))catch {
|
||||
return ^(FBLPromiseCatchBlock catch) {
|
||||
return [self catch:catch];
|
||||
};
|
||||
}
|
||||
|
||||
- (FBLPromise* (^)(dispatch_queue_t, FBLPromiseCatchBlock))catchOn {
|
||||
return ^(dispatch_queue_t queue, FBLPromiseCatchBlock catch) {
|
||||
return [self onQueue:queue catch:catch];
|
||||
};
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
Copyright 2018 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "DotSyntax/FBLPromise+DotSyntax+Do.h"
|
||||
|
||||
@implementation FBLPromise (DotSyntax_DoAdditions)
|
||||
|
||||
+ (FBLPromise* (^)(dispatch_queue_t, FBLPromiseDoWorkBlock))doOn {
|
||||
return ^(dispatch_queue_t queue, FBLPromiseDoWorkBlock work) {
|
||||
return [self onQueue:queue do:work];
|
||||
};
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
Copyright 2018 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "DotSyntax/FBLPromise+DotSyntax+Recover.h"
|
||||
|
||||
@implementation FBLPromise (DotSyntax_RecoverAdditions)
|
||||
|
||||
- (FBLPromise * (^)(id __nullable (^)(NSError *)))recover {
|
||||
return ^(FBLPromise * (^recovery)(NSError *)) {
|
||||
return [self recover:recovery];
|
||||
};
|
||||
}
|
||||
|
||||
- (FBLPromise * (^)(dispatch_queue_t, id __nullable (^)(NSError *)))recoverOn {
|
||||
return ^(dispatch_queue_t queue, id __nullable (^recovery)(NSError *)) {
|
||||
return [self onQueue:queue recover:recovery];
|
||||
};
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,91 @@
|
||||
/**
|
||||
Copyright 2018 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "DotSyntax/FBLPromise+DotSyntax+Resolve.h"
|
||||
|
||||
@implementation FBLPromise (DotSyntax_ResolveAdditions)
|
||||
|
||||
+ (FBLPromise * (^)(void (^)(FBLPromiseCompletion)))resolveWhen {
|
||||
return ^(void (^work)(FBLPromiseCompletion)) {
|
||||
return [self resolveWhenCompleted:work];
|
||||
};
|
||||
}
|
||||
|
||||
+ (FBLPromise * (^)(void (^)(FBLPromiseObjectCompletion)))resolveWithObjectWhen {
|
||||
return ^(void (^work)(FBLPromiseObjectCompletion)) {
|
||||
return [self resolveWithObjectWhenCompleted:work];
|
||||
};
|
||||
}
|
||||
|
||||
+ (FBLPromise * (^)(void (^)(FBLPromiseErrorCompletion)))resolveWithErrorWhen {
|
||||
return ^(void (^work)(FBLPromiseErrorCompletion)) {
|
||||
return [self resolveWithErrorWhenCompleted:work];
|
||||
};
|
||||
}
|
||||
|
||||
+ (FBLPromise * (^)(void (^)(FBLPromiseObjectOrErrorCompletion)))resolveWithObjectOrErrorWhen {
|
||||
return ^(void (^work)(FBLPromiseObjectOrErrorCompletion)) {
|
||||
return [self resolveWithObjectOrErrorWhenCompleted:work];
|
||||
};
|
||||
}
|
||||
|
||||
+ (FBLPromise<NSArray *> * (^)(void (^)(FBLPromise2ObjectsOrErrorCompletion)))
|
||||
resolveWith2ObjectsOrErrorWhen {
|
||||
return ^(void (^work)(FBLPromise2ObjectsOrErrorCompletion)) {
|
||||
return [self resolveWith2ObjectsOrErrorWhenCompleted:work];
|
||||
};
|
||||
}
|
||||
|
||||
+ (FBLPromise<NSNumber *> * (^)(void (^)(FBLPromiseBoolCompletion)))resolveWithBoolWhen {
|
||||
return ^(void (^work)(FBLPromiseBoolCompletion)) {
|
||||
return [self resolveWithBoolWhenCompleted:work];
|
||||
};
|
||||
}
|
||||
|
||||
+ (FBLPromise<NSNumber *> * (^)(void (^)(FBLPromiseBoolOrErrorCompletion)))
|
||||
resolveWithBoolOrErrorWhen {
|
||||
return ^(void (^work)(FBLPromiseBoolOrErrorCompletion)) {
|
||||
return [self resolveWithBoolOrErrorWhenCompleted:work];
|
||||
};
|
||||
}
|
||||
|
||||
+ (FBLPromise<NSNumber *> * (^)(void (^)(FBLPromiseIntegerCompletion)))resolveWithIntegerWhen {
|
||||
return ^(void (^work)(FBLPromiseIntegerCompletion)) {
|
||||
return [self resolveWithIntegerWhenCompleted:work];
|
||||
};
|
||||
}
|
||||
|
||||
+ (FBLPromise<NSNumber *> * (^)(void (^)(FBLPromiseIntegerOrErrorCompletion)))
|
||||
resolveWithIntegerOrErrorWhen {
|
||||
return ^(void (^work)(FBLPromiseIntegerOrErrorCompletion)) {
|
||||
return [self resolveWithIntegerOrErrorWhenCompleted:work];
|
||||
};
|
||||
}
|
||||
|
||||
+ (FBLPromise<NSNumber *> * (^)(void (^)(FBLPromiseDoubleCompletion)))resolveWithDoubleWhen {
|
||||
return ^(void (^work)(FBLPromiseDoubleCompletion)) {
|
||||
return [self resolveWithDoubleWhenCompleted:work];
|
||||
};
|
||||
}
|
||||
|
||||
+ (FBLPromise<NSNumber *> * (^)(void (^)(FBLPromiseDoubleOrErrorCompletion)))
|
||||
resolveWithDoubleOrErrorWhen {
|
||||
return ^(void (^work)(FBLPromiseDoubleOrErrorCompletion)) {
|
||||
return [self resolveWithDoubleOrErrorWhenCompleted:work];
|
||||
};
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
Copyright 2018 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "DotSyntax/FBLPromise+DotSyntax+Then.h"
|
||||
|
||||
@implementation FBLPromise (DotSyntax_ThenAdditions)
|
||||
|
||||
- (FBLPromise* (^)(FBLPromiseThenWorkBlock))then {
|
||||
return ^(FBLPromiseThenWorkBlock work) {
|
||||
return [self then:work];
|
||||
};
|
||||
}
|
||||
|
||||
- (FBLPromise* (^)(dispatch_queue_t, FBLPromiseThenWorkBlock))thenOn {
|
||||
return ^(dispatch_queue_t queue, FBLPromiseThenWorkBlock work) {
|
||||
return [self onQueue:queue then:work];
|
||||
};
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
Copyright 2018 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "DotSyntax/FBLPromise+DotSyntax+Timeout.h"
|
||||
|
||||
@implementation FBLPromise (DotSyntax_TimeoutAdditions)
|
||||
|
||||
- (FBLPromise* (^)(NSTimeInterval))timeout {
|
||||
return ^(NSTimeInterval interval) {
|
||||
return [self timeout:interval];
|
||||
};
|
||||
}
|
||||
|
||||
- (FBLPromise* (^)(dispatch_queue_t, NSTimeInterval))timeoutOn {
|
||||
return ^(dispatch_queue_t queue, NSTimeInterval interval) {
|
||||
return [self onQueue:queue timeout:interval];
|
||||
};
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
Copyright 2018 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "DotSyntax/FBLPromise+DotSyntax+Validate.h"
|
||||
|
||||
@implementation FBLPromise (DotSyntax_ValidateAdditions)
|
||||
|
||||
- (FBLPromise* (^)(BOOL (^)(id __nullable)))validate {
|
||||
return ^(BOOL (^predicate)(id __nullable)) {
|
||||
return [self validate:predicate];
|
||||
};
|
||||
}
|
||||
|
||||
- (FBLPromise* (^)(dispatch_queue_t, BOOL (^)(id __nullable)))validateOn {
|
||||
return ^(dispatch_queue_t queue, BOOL (^predicate)(id __nullable)) {
|
||||
return [self onQueue:queue validate:predicate];
|
||||
};
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
Copyright 2018 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "DotSyntax/FBLPromise+DotSyntax+When.h"
|
||||
|
||||
@implementation FBLPromise (DotSyntax_WhenAdditions)
|
||||
|
||||
+ (FBLPromise<NSArray *> * (^)(NSArray *))when {
|
||||
return ^(NSArray *promises) {
|
||||
return [self when:promises];
|
||||
};
|
||||
}
|
||||
|
||||
+ (FBLPromise<NSArray *> * (^)(dispatch_queue_t, NSArray *))whenOn {
|
||||
return ^(dispatch_queue_t queue, NSArray *promises) {
|
||||
return [self onQueue:queue when:promises];
|
||||
};
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
Copyright 2018 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "DotSyntax/FBLPromise+DotSyntax.h"
|
||||
|
||||
@implementation FBLPromise (DotSyntaxAdditions)
|
||||
|
||||
+ (FBLPromise* (^)(id __nullable))resolve {
|
||||
return ^(id resolution) {
|
||||
return [self resolvedWith:resolution];
|
||||
};
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,69 @@
|
||||
/**
|
||||
Copyright 2018 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "FBLPromise+All.h"
|
||||
|
||||
#import "FBLPromise+Async.h"
|
||||
#import "FBLPromisePrivate.h"
|
||||
|
||||
@implementation FBLPromise (AllAdditions)
|
||||
|
||||
+ (FBLPromise<NSArray *> *)all:(NSArray *)promises {
|
||||
return [self onQueue:dispatch_get_main_queue() all:promises];
|
||||
}
|
||||
|
||||
+ (FBLPromise<NSArray *> *)onQueue:(dispatch_queue_t)queue all:(NSArray *)allPromises {
|
||||
NSParameterAssert(allPromises);
|
||||
|
||||
if (allPromises.count == 0) {
|
||||
return [[[self class] alloc] initWithResolution:@[]];
|
||||
}
|
||||
NSMutableArray *promises = [allPromises mutableCopy];
|
||||
return [FBLPromise
|
||||
onQueue:queue
|
||||
async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock reject) {
|
||||
for (NSUInteger i = 0; i < promises.count; ++i) {
|
||||
id promise = promises[i];
|
||||
if ([promise isKindOfClass:self]) {
|
||||
continue;
|
||||
} else if ([promise isKindOfClass:[NSError class]]) {
|
||||
reject(promise);
|
||||
return;
|
||||
} else {
|
||||
[promises replaceObjectAtIndex:i
|
||||
withObject:[[[self class] alloc] initWithResolution:promise]];
|
||||
}
|
||||
}
|
||||
for (FBLPromise *promise in promises) {
|
||||
[promise observeOnQueue:queue
|
||||
fulfill:^(id __unused _) {
|
||||
// Wait until all are fulfilled.
|
||||
for (FBLPromise *promise in promises) {
|
||||
if (!promise.isFulfilled) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
// If called multiple times, only the first one affects the result.
|
||||
fulfill([promises valueForKey:NSStringFromSelector(@selector(value))]);
|
||||
}
|
||||
reject:^(NSError *error) {
|
||||
reject(error);
|
||||
}];
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
Copyright 2018 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "FBLPromise+Always.h"
|
||||
|
||||
#import "FBLPromisePrivate.h"
|
||||
|
||||
@implementation FBLPromise (AlwaysAdditions)
|
||||
|
||||
- (FBLPromise *)always:(void (^)(void))work {
|
||||
return [self onQueue:dispatch_get_main_queue() always:work];
|
||||
}
|
||||
|
||||
- (FBLPromise *)onQueue:(dispatch_queue_t)queue always:(void (^)(void))work {
|
||||
NSParameterAssert(work);
|
||||
|
||||
return [self chainOnQueue:queue
|
||||
chainedFulfill:^id(id value) {
|
||||
work();
|
||||
return value;
|
||||
}
|
||||
chainedReject:^id(NSError *error) {
|
||||
work();
|
||||
return error;
|
||||
}];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
Copyright 2018 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "FBLPromise+Any.h"
|
||||
|
||||
#import "FBLPromise+Async.h"
|
||||
#import "FBLPromisePrivate.h"
|
||||
|
||||
@implementation FBLPromise (AnyAdditions)
|
||||
|
||||
+ (instancetype)any:(NSArray *)promises {
|
||||
return [self onQueue:dispatch_get_main_queue() any:promises];
|
||||
}
|
||||
|
||||
+ (instancetype)onQueue:(dispatch_queue_t)queue any:(NSArray *)anyPromises {
|
||||
NSAssert(anyPromises.count > 0, @"No promises to observe");
|
||||
|
||||
NSArray *promises = [anyPromises copy];
|
||||
return [FBLPromise onQueue:queue
|
||||
async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock reject) {
|
||||
for (id promise in promises) {
|
||||
if (![promise isKindOfClass:self]) {
|
||||
fulfill(promise);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Subscribe all, but only the first one to resolve will change
|
||||
// the resulting promise's state.
|
||||
for (FBLPromise *promise in promises) {
|
||||
[promise observeOnQueue:queue fulfill:fulfill reject:reject];
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
Copyright 2018 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "FBLPromise+Async.h"
|
||||
|
||||
#import "FBLPromisePrivate.h"
|
||||
|
||||
@implementation FBLPromise (AsyncAdditions)
|
||||
|
||||
+ (instancetype)async:(FBLPromiseAsyncWorkBlock)work {
|
||||
return [self onQueue:dispatch_get_main_queue() async:work];
|
||||
}
|
||||
|
||||
+ (instancetype)onQueue:(dispatch_queue_t)queue async:(FBLPromiseAsyncWorkBlock)work {
|
||||
NSParameterAssert(work);
|
||||
|
||||
FBLPromise *promise = [[[self class] alloc] initPending];
|
||||
dispatch_group_async([self class].dispatchGroup, queue, ^{
|
||||
@try {
|
||||
work(
|
||||
^(id __nullable value) {
|
||||
[promise fulfill:value];
|
||||
},
|
||||
^(NSError *error) {
|
||||
[promise reject:error];
|
||||
});
|
||||
} @catch (id exception) {
|
||||
[promise reject:exception];
|
||||
}
|
||||
});
|
||||
return promise;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
Copyright 2018 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "FBLPromise+Catch.h"
|
||||
|
||||
#import "FBLPromisePrivate.h"
|
||||
|
||||
@implementation FBLPromise (CatchAdditions)
|
||||
|
||||
- (FBLPromise *)catch:(FBLPromiseCatchBlock)reject {
|
||||
return [self onQueue:dispatch_get_main_queue() catch:reject];
|
||||
}
|
||||
|
||||
- (FBLPromise *)onQueue:(dispatch_queue_t)queue catch:(FBLPromiseCatchBlock)reject {
|
||||
NSParameterAssert(reject);
|
||||
|
||||
return [self chainOnQueue:queue
|
||||
chainedFulfill:nil
|
||||
chainedReject:^id(NSError *error) {
|
||||
reject(error);
|
||||
return error;
|
||||
}];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
Copyright 2018 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "FBLPromise+Do.h"
|
||||
|
||||
#import "FBLPromisePrivate.h"
|
||||
|
||||
@implementation FBLPromise (DoAdditions)
|
||||
|
||||
+ (instancetype)do:(FBLPromiseDoWorkBlock)work {
|
||||
return [self onQueue:dispatch_get_main_queue() do:work];
|
||||
}
|
||||
|
||||
+ (instancetype)onQueue:(dispatch_queue_t)queue do:(FBLPromiseDoWorkBlock)work {
|
||||
NSParameterAssert(work);
|
||||
|
||||
FBLPromise *promise = [[[self class] alloc] initPending];
|
||||
dispatch_group_async([self class].dispatchGroup, queue, ^{
|
||||
@try {
|
||||
[promise fulfill:work()];
|
||||
} @catch (id exception) {
|
||||
[promise reject:exception];
|
||||
}
|
||||
});
|
||||
return promise;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
Copyright 2018 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "FBLPromise+Recover.h"
|
||||
|
||||
#import "FBLPromisePrivate.h"
|
||||
|
||||
@implementation FBLPromise (RecoverAdditions)
|
||||
|
||||
- (FBLPromise *)recover:(nullable id (^)(NSError *))recovery {
|
||||
return [self onQueue:dispatch_get_main_queue() recover:recovery];
|
||||
}
|
||||
|
||||
- (FBLPromise *)onQueue:(dispatch_queue_t)queue recover:(nullable id (^)(NSError *))recovery {
|
||||
NSParameterAssert(recovery);
|
||||
|
||||
return [self chainOnQueue:queue
|
||||
chainedFulfill:nil
|
||||
chainedReject:^id(NSError *error) {
|
||||
return recovery(error);
|
||||
}];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,179 @@
|
||||
/**
|
||||
Copyright 2018 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "FBLPromise+Resolve.h"
|
||||
|
||||
#import "FBLPromise+Async.h"
|
||||
|
||||
@implementation FBLPromise (ResolveAdditions)
|
||||
|
||||
+ (instancetype)resolveWhenCompleted:(void (^)(FBLPromiseCompletion))work {
|
||||
NSParameterAssert(work);
|
||||
|
||||
return [self async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock __unused _) {
|
||||
work(^{
|
||||
fulfill(nil);
|
||||
});
|
||||
}];
|
||||
}
|
||||
|
||||
+ (instancetype)resolveWithObjectWhenCompleted:(void (^)(FBLPromiseObjectCompletion))work {
|
||||
NSParameterAssert(work);
|
||||
|
||||
return [self async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock __unused _) {
|
||||
work(^(id __nullable value) {
|
||||
fulfill(value);
|
||||
});
|
||||
}];
|
||||
}
|
||||
|
||||
+ (instancetype)resolveWithErrorWhenCompleted:(void (^)(FBLPromiseErrorCompletion))work {
|
||||
NSParameterAssert(work);
|
||||
|
||||
return [self async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock reject) {
|
||||
work(^(NSError *__nullable error) {
|
||||
if (error) {
|
||||
reject(error);
|
||||
} else {
|
||||
fulfill(nil);
|
||||
}
|
||||
});
|
||||
}];
|
||||
}
|
||||
|
||||
+ (instancetype)resolveWithObjectOrErrorWhenCompleted:
|
||||
(void (^)(FBLPromiseObjectOrErrorCompletion))work {
|
||||
NSParameterAssert(work);
|
||||
|
||||
return [self async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock reject) {
|
||||
work(^(id __nullable value, NSError *__nullable error) {
|
||||
if (error) {
|
||||
reject(error);
|
||||
} else {
|
||||
fulfill(value);
|
||||
}
|
||||
});
|
||||
}];
|
||||
}
|
||||
|
||||
+ (instancetype)resolveWithErrorOrObjectWhenCompleted:
|
||||
(void (^)(FBLPromiseErrorOrObjectCompletion))work {
|
||||
NSParameterAssert(work);
|
||||
|
||||
return [self async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock reject) {
|
||||
work(^(NSError *__nullable error, id __nullable value) {
|
||||
if (error) {
|
||||
reject(error);
|
||||
} else {
|
||||
fulfill(value);
|
||||
}
|
||||
});
|
||||
}];
|
||||
}
|
||||
|
||||
+ (FBLPromise<NSArray *> *)resolveWith2ObjectsOrErrorWhenCompleted:
|
||||
(void (^)(FBLPromise2ObjectsOrErrorCompletion))work {
|
||||
NSParameterAssert(work);
|
||||
|
||||
return [self async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock reject) {
|
||||
work(^(id __nullable value1, id __nullable value2, NSError *__nullable error) {
|
||||
if (error) {
|
||||
reject(error);
|
||||
} else {
|
||||
fulfill(@[ value1, value2 ]);
|
||||
}
|
||||
});
|
||||
}];
|
||||
}
|
||||
|
||||
+ (FBLPromise<NSNumber *> *)resolveWithBoolWhenCompleted:(void (^)(FBLPromiseBoolCompletion))work {
|
||||
NSParameterAssert(work);
|
||||
|
||||
return [self async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock __unused _) {
|
||||
work(^(BOOL value) {
|
||||
fulfill(@(value));
|
||||
});
|
||||
}];
|
||||
}
|
||||
|
||||
+ (FBLPromise<NSNumber *> *)resolveWithBoolOrErrorWhenCompleted:
|
||||
(void (^)(FBLPromiseBoolOrErrorCompletion))work {
|
||||
NSParameterAssert(work);
|
||||
|
||||
return [self async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock reject) {
|
||||
work(^(BOOL value, NSError *__nullable error) {
|
||||
if (error) {
|
||||
reject(error);
|
||||
} else {
|
||||
fulfill(@(value));
|
||||
}
|
||||
});
|
||||
}];
|
||||
}
|
||||
|
||||
+ (FBLPromise<NSNumber *> *)resolveWithIntegerWhenCompleted:
|
||||
(void (^)(FBLPromiseIntegerCompletion))work {
|
||||
NSParameterAssert(work);
|
||||
|
||||
return [self async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock __unused _) {
|
||||
work(^(NSInteger value) {
|
||||
fulfill(@(value));
|
||||
});
|
||||
}];
|
||||
}
|
||||
|
||||
+ (FBLPromise<NSNumber *> *)resolveWithIntegerOrErrorWhenCompleted:
|
||||
(void (^)(FBLPromiseIntegerOrErrorCompletion))work {
|
||||
NSParameterAssert(work);
|
||||
|
||||
return [self async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock reject) {
|
||||
work(^(NSInteger value, NSError *__nullable error) {
|
||||
if (error) {
|
||||
reject(error);
|
||||
} else {
|
||||
fulfill(@(value));
|
||||
}
|
||||
});
|
||||
}];
|
||||
}
|
||||
|
||||
+ (FBLPromise<NSNumber *> *)resolveWithDoubleWhenCompleted:
|
||||
(void (^)(FBLPromiseDoubleCompletion))work {
|
||||
NSParameterAssert(work);
|
||||
|
||||
return [self async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock __unused _) {
|
||||
work(^(double value) {
|
||||
fulfill(@(value));
|
||||
});
|
||||
}];
|
||||
}
|
||||
|
||||
+ (FBLPromise<NSNumber *> *)resolveWithDoubleOrErrorWhenCompleted:
|
||||
(void (^)(FBLPromiseDoubleOrErrorCompletion))work {
|
||||
NSParameterAssert(work);
|
||||
|
||||
return [self async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock reject) {
|
||||
work(^(double value, NSError *__nullable error) {
|
||||
if (error) {
|
||||
reject(error);
|
||||
} else {
|
||||
fulfill(@(value));
|
||||
}
|
||||
});
|
||||
}];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
Copyright 2018 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "FBLPromise+Testing.h"
|
||||
|
||||
BOOL FBLWaitForPromisesWithTimeout(NSTimeInterval timeout) {
|
||||
BOOL isTimedOut = NO;
|
||||
NSDate *timeoutDate = [NSDate dateWithTimeIntervalSinceNow:timeout];
|
||||
static NSTimeInterval const minimalTimeout = 0.01;
|
||||
static int64_t const minimalTimeToWait = (int64_t)(minimalTimeout * NSEC_PER_SEC);
|
||||
dispatch_time_t waitTime = dispatch_time(DISPATCH_TIME_NOW, minimalTimeToWait);
|
||||
dispatch_group_t dispatchGroup = FBLPromise.dispatchGroup;
|
||||
NSRunLoop *runLoop = NSRunLoop.currentRunLoop;
|
||||
while (dispatch_group_wait(dispatchGroup, waitTime)) {
|
||||
isTimedOut = timeoutDate.timeIntervalSinceNow < 0.0;
|
||||
if (isTimedOut) {
|
||||
break;
|
||||
}
|
||||
[runLoop runUntilDate:[NSDate dateWithTimeIntervalSinceNow:minimalTimeout]];
|
||||
}
|
||||
return !isTimedOut;
|
||||
}
|
||||
|
||||
@implementation FBLPromise (TestingAdditions)
|
||||
|
||||
// These properties are implemented in the FBLPromise class itself.
|
||||
@dynamic isPending;
|
||||
@dynamic isFulfilled;
|
||||
@dynamic isRejected;
|
||||
@dynamic pendingObjects;
|
||||
@dynamic value;
|
||||
@dynamic error;
|
||||
|
||||
+ (dispatch_group_t)dispatchGroup {
|
||||
static dispatch_group_t gDispatchGroup;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
gDispatchGroup = dispatch_group_create();
|
||||
});
|
||||
return gDispatchGroup;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
Copyright 2018 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "FBLPromise+Then.h"
|
||||
|
||||
#import "FBLPromisePrivate.h"
|
||||
|
||||
@implementation FBLPromise (ThenAdditions)
|
||||
|
||||
- (FBLPromise *)then:(FBLPromiseThenWorkBlock)work {
|
||||
return [self onQueue:dispatch_get_main_queue() then:work];
|
||||
}
|
||||
|
||||
- (FBLPromise *)onQueue:(dispatch_queue_t)queue then:(FBLPromiseThenWorkBlock)work {
|
||||
NSParameterAssert(work);
|
||||
|
||||
return [self chainOnQueue:queue chainedFulfill:work chainedReject:nil];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,43 @@
|
||||
/**
|
||||
Copyright 2018 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "FBLPromise+Timeout.h"
|
||||
|
||||
#import "FBLPromisePrivate.h"
|
||||
|
||||
@implementation FBLPromise (TimeoutAdditions)
|
||||
|
||||
- (FBLPromise *)timeout:(NSTimeInterval)interval {
|
||||
return [self onQueue:dispatch_get_main_queue() timeout:interval];
|
||||
}
|
||||
|
||||
- (FBLPromise *)onQueue:(dispatch_queue_t)queue timeout:(NSTimeInterval)interval {
|
||||
FBLPromise *promise = [[[self class] alloc] initPending];
|
||||
dispatch_group_async([self class].dispatchGroup, queue, ^{
|
||||
[promise fulfill:self];
|
||||
});
|
||||
int64_t const timeToWait = (int64_t)(interval * NSEC_PER_SEC);
|
||||
FBLPromise __weak *weakPromise = promise;
|
||||
dispatch_after(dispatch_time(0, timeToWait), queue, ^{
|
||||
NSError *timedOutError = [NSError errorWithDomain:FBLPromiseErrorDomain
|
||||
code:FBLPromiseErrorCodeTimedOut
|
||||
userInfo:nil];
|
||||
[weakPromise reject:timedOutError];
|
||||
});
|
||||
return promise;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
Copyright 2018 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "FBLPromise+Validate.h"
|
||||
|
||||
#import "FBLPromisePrivate.h"
|
||||
|
||||
@implementation FBLPromise (ValidateAdditions)
|
||||
|
||||
- (FBLPromise *)validate:(BOOL (^)(id __nullable))predicate {
|
||||
return [self onQueue:dispatch_get_main_queue() validate:predicate];
|
||||
}
|
||||
|
||||
- (FBLPromise *)onQueue:(dispatch_queue_t)queue validate:(BOOL (^)(id __nullable))predicate {
|
||||
NSParameterAssert(predicate);
|
||||
|
||||
FBLPromiseChainedFulfillBlock chainedFulfill = ^id(id value) {
|
||||
return predicate(value) ? value : [NSError errorWithDomain:FBLPromiseErrorDomain
|
||||
code:FBLPromiseErrorCodeValidationFailure
|
||||
userInfo:nil];
|
||||
};
|
||||
return [self chainOnQueue:queue chainedFulfill:chainedFulfill chainedReject:nil];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,95 @@
|
||||
/**
|
||||
Copyright 2018 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "FBLPromise+When.h"
|
||||
|
||||
#import "FBLPromise+Async.h"
|
||||
#import "FBLPromisePrivate.h"
|
||||
|
||||
static NSArray *FBLPromiseCombineValuesAndErrors(NSArray<FBLPromise *> *promises) {
|
||||
NSMutableArray *combinedValuesAndErrors = [[NSMutableArray alloc] init];
|
||||
for (FBLPromise *promise in promises) {
|
||||
if (promise.isFulfilled) {
|
||||
[combinedValuesAndErrors addObject:promise.value ?: [NSNull null]];
|
||||
continue;
|
||||
}
|
||||
if (promise.isRejected) {
|
||||
[combinedValuesAndErrors addObject:promise.error];
|
||||
continue;
|
||||
}
|
||||
assert(!promise.isPending);
|
||||
};
|
||||
return combinedValuesAndErrors;
|
||||
}
|
||||
|
||||
@implementation FBLPromise (WhenAdditions)
|
||||
|
||||
+ (FBLPromise<NSArray *> *)when:(NSArray *)promises {
|
||||
return [self onQueue:dispatch_get_main_queue() when:promises];
|
||||
}
|
||||
|
||||
+ (FBLPromise<NSArray *> *)onQueue:(dispatch_queue_t)queue when:(NSArray *)whenPromises {
|
||||
NSParameterAssert(whenPromises);
|
||||
|
||||
if (whenPromises.count == 0) {
|
||||
return [[[self class] alloc] initWithResolution:@[]];
|
||||
}
|
||||
NSMutableArray *promises = [whenPromises mutableCopy];
|
||||
return [FBLPromise
|
||||
onQueue:queue
|
||||
async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock reject) {
|
||||
for (NSUInteger i = 0; i < promises.count; ++i) {
|
||||
id promise = promises[i];
|
||||
if ([promise isKindOfClass:self]) {
|
||||
continue;
|
||||
} else {
|
||||
[promises replaceObjectAtIndex:i
|
||||
withObject:[[[self class] alloc] initWithResolution:promise]];
|
||||
}
|
||||
}
|
||||
for (FBLPromise *promise in promises) {
|
||||
[promise observeOnQueue:queue
|
||||
fulfill:^(id __unused _) {
|
||||
// Wait until all are resolved.
|
||||
for (FBLPromise *promise in promises) {
|
||||
if (promise.isPending) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
// If called multiple times, only the first one affects the result.
|
||||
fulfill(FBLPromiseCombineValuesAndErrors(promises));
|
||||
}
|
||||
reject:^(NSError *error) {
|
||||
BOOL atLeastOneIsFulfilled = NO;
|
||||
for (FBLPromise *promise in promises) {
|
||||
if (promise.isPending) {
|
||||
return;
|
||||
}
|
||||
if (promise.isFulfilled) {
|
||||
atLeastOneIsFulfilled = YES;
|
||||
}
|
||||
}
|
||||
if (atLeastOneIsFulfilled) {
|
||||
fulfill(FBLPromiseCombineValuesAndErrors(promises));
|
||||
} else {
|
||||
reject(error);
|
||||
}
|
||||
}];
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,288 @@
|
||||
/**
|
||||
Copyright 2018 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "FBLPromisePrivate.h"
|
||||
|
||||
#import "FBLPromiseErrorPrivate.h"
|
||||
|
||||
/** All states a promise can be in. */
|
||||
typedef NS_ENUM(NSInteger, FBLPromiseState) {
|
||||
FBLPromiseStatePending = 0,
|
||||
FBLPromiseStateFulfilled,
|
||||
FBLPromiseStateRejected,
|
||||
};
|
||||
|
||||
typedef void (^FBLPromiseObserver)(FBLPromiseState state, id __nullable resolution);
|
||||
|
||||
@implementation FBLPromise {
|
||||
/** Current state of the promise. */
|
||||
FBLPromiseState _state;
|
||||
/**
|
||||
Set of arbitrary objects to keep strongly while the promise is pending.
|
||||
Becomes nil after the promise has been resolved.
|
||||
*/
|
||||
NSMutableSet *__nullable _pendingObjects;
|
||||
/**
|
||||
Value to fulfill the promise with.
|
||||
Can be nil if the promise is still pending, was resolved with nil or after it has been rejected.
|
||||
*/
|
||||
id __nullable _value;
|
||||
/**
|
||||
Error to reject the promise with.
|
||||
Can be nil if the promise is still pending or after it has been fulfilled.
|
||||
*/
|
||||
NSError *__nullable _error;
|
||||
/** List of observers to notify when the promise gets resolved. */
|
||||
NSMutableArray<FBLPromiseObserver> *_observers;
|
||||
}
|
||||
|
||||
+ (instancetype)pendingPromise {
|
||||
return [[self alloc] initPending];
|
||||
}
|
||||
|
||||
+ (instancetype)resolvedWith:(nullable id)resolution {
|
||||
return [[self alloc] initWithResolution:resolution];
|
||||
}
|
||||
|
||||
- (void)fulfill:(nullable id)value {
|
||||
if ([value isKindOfClass:[self class]]) {
|
||||
[(FBLPromise *)value observeOnQueue:dispatch_get_main_queue()
|
||||
fulfill:^(id __nullable value) {
|
||||
[self fulfill:value];
|
||||
}
|
||||
reject:^(NSError *error) {
|
||||
[self reject:error];
|
||||
}];
|
||||
} else if ([value isKindOfClass:[NSError class]]) {
|
||||
[self reject:(NSError *)value];
|
||||
} else if ([value isKindOfClass:[NSException class]]) {
|
||||
[self reject:FBLNSErrorFromNSException((NSException *)value)];
|
||||
} else {
|
||||
@synchronized(self) {
|
||||
if (_state == FBLPromiseStatePending) {
|
||||
_state = FBLPromiseStateFulfilled;
|
||||
_value = value;
|
||||
_pendingObjects = nil;
|
||||
for (FBLPromiseObserver observer in _observers) {
|
||||
observer(_state, _value);
|
||||
}
|
||||
_observers = nil;
|
||||
dispatch_group_leave([self class].dispatchGroup);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)reject:(NSError *)error {
|
||||
if ([error isKindOfClass:[NSException class]]) {
|
||||
error = FBLNSErrorFromNSException((NSException *)error);
|
||||
}
|
||||
NSAssert([error isKindOfClass:[NSError class]], @"Invalid error type.");
|
||||
|
||||
if (![error isKindOfClass:[NSError class]]) {
|
||||
// Give up on invalid error type in Release mode.
|
||||
@throw error; // NOLINT
|
||||
}
|
||||
@synchronized(self) {
|
||||
if (_state == FBLPromiseStatePending) {
|
||||
_state = FBLPromiseStateRejected;
|
||||
_error = error;
|
||||
_pendingObjects = nil;
|
||||
for (FBLPromiseObserver observer in _observers) {
|
||||
observer(_state, _error);
|
||||
}
|
||||
_observers = nil;
|
||||
dispatch_group_leave([self class].dispatchGroup);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - NSObject
|
||||
|
||||
- (NSString *)description {
|
||||
if (self.isFulfilled) {
|
||||
return [NSString stringWithFormat:@"<%@ %p> Fulfilled: %@", NSStringFromClass([self class]),
|
||||
self, self.value];
|
||||
}
|
||||
if (self.isRejected) {
|
||||
return [NSString stringWithFormat:@"<%@ %p> Rejected: %@", NSStringFromClass([self class]),
|
||||
self, self.error];
|
||||
}
|
||||
return [NSString stringWithFormat:@"<%@ %p> Pending", NSStringFromClass([self class]), self];
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
- (instancetype)initPending {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
dispatch_group_enter([self class].dispatchGroup);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithResolution:(nullable id)resolution {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
if ([resolution isKindOfClass:[self class]]) {
|
||||
FBLPromise *anotherPromise = (FBLPromise *)resolution;
|
||||
if (anotherPromise.isRejected) {
|
||||
_state = FBLPromiseStateRejected;
|
||||
_error = anotherPromise.error;
|
||||
} else {
|
||||
_state = FBLPromiseStateFulfilled;
|
||||
_value = anotherPromise.value;
|
||||
}
|
||||
} else if ([resolution isKindOfClass:[NSError class]]) {
|
||||
_state = FBLPromiseStateRejected;
|
||||
_error = (NSError *)resolution;
|
||||
} else if ([resolution isKindOfClass:[NSException class]]) {
|
||||
_state = FBLPromiseStateRejected;
|
||||
_error = FBLNSErrorFromNSException((NSException *)resolution);
|
||||
} else {
|
||||
_state = FBLPromiseStateFulfilled;
|
||||
_value = resolution;
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
if (_state == FBLPromiseStatePending) {
|
||||
dispatch_group_leave([self class].dispatchGroup);
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)isPending {
|
||||
@synchronized(self) {
|
||||
return _state == FBLPromiseStatePending;
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)isFulfilled {
|
||||
@synchronized(self) {
|
||||
return _state == FBLPromiseStateFulfilled;
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)isRejected {
|
||||
@synchronized(self) {
|
||||
return _state == FBLPromiseStateRejected;
|
||||
}
|
||||
}
|
||||
|
||||
- (nullable id)value {
|
||||
@synchronized(self) {
|
||||
return _value;
|
||||
}
|
||||
}
|
||||
|
||||
- (NSError *__nullable)error {
|
||||
@synchronized(self) {
|
||||
return _error;
|
||||
}
|
||||
}
|
||||
|
||||
- (NSMutableSet *__nullable)pendingObjects {
|
||||
@synchronized(self) {
|
||||
if (_state == FBLPromiseStatePending) {
|
||||
if (!_pendingObjects) {
|
||||
_pendingObjects = [[NSMutableSet alloc] init];
|
||||
}
|
||||
}
|
||||
return _pendingObjects;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)observeOnQueue:(dispatch_queue_t)queue
|
||||
fulfill:(FBLPromiseOnFulfillBlock)onFulfill
|
||||
reject:(FBLPromiseOnRejectBlock)onReject {
|
||||
dispatch_group_t dispatchGroup = [self class].dispatchGroup;
|
||||
@synchronized(self) {
|
||||
switch (_state) {
|
||||
case FBLPromiseStatePending: {
|
||||
if (!_observers) {
|
||||
_observers = [[NSMutableArray alloc] init];
|
||||
}
|
||||
[_observers addObject:^(FBLPromiseState state, id __nullable resolution) {
|
||||
dispatch_group_async(dispatchGroup, queue, ^{
|
||||
switch (state) {
|
||||
case FBLPromiseStatePending:
|
||||
break;
|
||||
case FBLPromiseStateFulfilled:
|
||||
onFulfill(resolution);
|
||||
break;
|
||||
case FBLPromiseStateRejected:
|
||||
onReject(resolution);
|
||||
break;
|
||||
}
|
||||
});
|
||||
}];
|
||||
break;
|
||||
}
|
||||
case FBLPromiseStateFulfilled: {
|
||||
dispatch_group_async(dispatchGroup, queue, ^{
|
||||
onFulfill(_value);
|
||||
});
|
||||
break;
|
||||
}
|
||||
case FBLPromiseStateRejected: {
|
||||
dispatch_group_async(dispatchGroup, queue, ^{
|
||||
onReject(_error);
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (FBLPromise *)chainOnQueue:(dispatch_queue_t)queue
|
||||
chainedFulfill:(FBLPromiseChainedFulfillBlock)chainedFulfill
|
||||
chainedReject:(FBLPromiseChainedRejectBlock)chainedReject {
|
||||
FBLPromise *promise = [[[self class] alloc] initPending];
|
||||
FBLPromiseOnFulfillBlock onFulfill;
|
||||
if (chainedFulfill) {
|
||||
onFulfill = ^(id __nullable value) {
|
||||
@try {
|
||||
[promise fulfill:chainedFulfill(value)];
|
||||
} @catch (id exception) {
|
||||
[promise reject:exception];
|
||||
}
|
||||
};
|
||||
} else {
|
||||
onFulfill = ^(id __nullable value) {
|
||||
[promise fulfill:value];
|
||||
};
|
||||
}
|
||||
FBLPromiseOnRejectBlock onReject;
|
||||
if (chainedReject) {
|
||||
onReject = ^(NSError *error) {
|
||||
@try {
|
||||
[promise fulfill:chainedReject(error)];
|
||||
} @catch (id exception) {
|
||||
[promise reject:exception];
|
||||
}
|
||||
};
|
||||
} else {
|
||||
onReject = ^(NSError *error) {
|
||||
[promise reject:error];
|
||||
};
|
||||
}
|
||||
[self observeOnQueue:queue fulfill:onFulfill reject:onReject];
|
||||
return promise;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
Copyright 2018 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "FBLPromiseErrorPrivate.h"
|
||||
|
||||
NSString *const FBLPromiseErrorDomain = @"com.google.FBLPromises.Error";
|
||||
NSString *const FBLPromiseErrorUserInfoExceptionNameKey = @"NSExceptionName";
|
||||
NSString *const FBLPromiseErrorUserInfoExceptionReasonKey = @"NSExceptionReason";
|
||||
NSString *const FBLPromiseErrorUserInfoExceptionUserInfoKey = @"NSExceptionUserInfo";
|
||||
NSString *const FBLPromiseErrorUserInfoExceptionReturnAddressesKey = @"NSExceptionReturnAddresses";
|
||||
NSString *const FBLPromiseErrorUserInfoExceptionCallStackKey = @"NSExceptionCallStack";
|
||||
|
||||
NSError *FBLNSErrorFromNSException(NSException *exception) {
|
||||
NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
|
||||
userInfo[FBLPromiseErrorUserInfoExceptionNameKey] = exception.name;
|
||||
userInfo[FBLPromiseErrorUserInfoExceptionReasonKey] = exception.reason;
|
||||
userInfo[FBLPromiseErrorUserInfoExceptionUserInfoKey] = exception.userInfo;
|
||||
userInfo[FBLPromiseErrorUserInfoExceptionReturnAddressesKey] = exception.callStackReturnAddresses;
|
||||
userInfo[FBLPromiseErrorUserInfoExceptionCallStackKey] = exception.callStackSymbols;
|
||||
return [[NSError alloc] initWithDomain:FBLPromiseErrorDomain
|
||||
code:FBLPromiseErrorCodeException
|
||||
userInfo:userInfo];
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
Copyright 2018 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "DotSyntax/FBLPromise+DotSyntax.h"
|
||||
#import "FBLPromise+All.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
Convenience dot-syntax wrappers for `FBLPromise` `all` operators.
|
||||
Usage: promise.all(@[ ... ])
|
||||
*/
|
||||
@interface FBLPromise<Value>(DotSyntax_AllAdditions)
|
||||
|
||||
+ (FBLPromise<NSArray *> * (^)(NSArray *))all FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE("");
|
||||
+ (FBLPromise<NSArray *> * (^)(dispatch_queue_t, NSArray *))allOn FBL_PROMISES_DOT_SYNTAX
|
||||
NS_SWIFT_UNAVAILABLE("");
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
Copyright 2018 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "DotSyntax/FBLPromise+DotSyntax.h"
|
||||
#import "FBLPromise+Always.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
Convenience dot-syntax wrappers for `FBLPromise` `always` operators.
|
||||
Usage: promise.always(^{...})
|
||||
*/
|
||||
@interface FBLPromise<Value>(DotSyntax_AlwaysAdditions)
|
||||
|
||||
- (FBLPromise* (^)(void (^)(void)))always FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE("");
|
||||
- (FBLPromise* (^)(dispatch_queue_t, void (^)(void)))alwaysOn FBL_PROMISES_DOT_SYNTAX
|
||||
NS_SWIFT_UNAVAILABLE("");
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
Copyright 2018 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "DotSyntax/FBLPromise+DotSyntax.h"
|
||||
#import "FBLPromise+Any.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
Convenience dot-syntax wrappers for `FBLPromise` `any` operators.
|
||||
Usage: promise.any(@[ ... ])
|
||||
*/
|
||||
@interface FBLPromise<Value>(DotSyntax_AnyAdditions)
|
||||
|
||||
+ (FBLPromise * (^)(NSArray *))any FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE("");
|
||||
+ (FBLPromise * (^)(dispatch_queue_t, NSArray *))anyOn FBL_PROMISES_DOT_SYNTAX
|
||||
NS_SWIFT_UNAVAILABLE("");
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
Copyright 2018 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "DotSyntax/FBLPromise+DotSyntax.h"
|
||||
#import "FBLPromise+Async.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
Convenience dot-syntax wrappers for `FBLPromise` `async` operators.
|
||||
Usage: promise.async(^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock reject) { ... })
|
||||
*/
|
||||
@interface FBLPromise<Value>(DotSyntax_AsyncAdditions)
|
||||
|
||||
+ (FBLPromise* (^)(FBLPromiseAsyncWorkBlock))async FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE("");
|
||||
+ (FBLPromise* (^)(dispatch_queue_t, FBLPromiseAsyncWorkBlock))asyncOn FBL_PROMISES_DOT_SYNTAX
|
||||
NS_SWIFT_UNAVAILABLE("");
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
Copyright 2018 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "DotSyntax/FBLPromise+DotSyntax.h"
|
||||
#import "FBLPromise+Catch.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
Convenience dot-syntax wrappers for `FBLPromise` `catch` operators.
|
||||
Usage: promise.catch(^(NSError *error) { ... })
|
||||
*/
|
||||
@interface FBLPromise<Value>(DotSyntax_CatchAdditions)
|
||||
|
||||
- (FBLPromise* (^)(FBLPromiseCatchBlock))catch FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE("");
|
||||
- (FBLPromise* (^)(dispatch_queue_t, FBLPromiseCatchBlock))catchOn FBL_PROMISES_DOT_SYNTAX
|
||||
NS_SWIFT_UNAVAILABLE("");
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
Copyright 2018 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "DotSyntax/FBLPromise+DotSyntax.h"
|
||||
#import "FBLPromise+Do.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
Convenience dot-syntax wrappers for `FBLPromise` `do` operators.
|
||||
Usage: FBLPromise.doOn(queue, ^(NSError *error) { ... })
|
||||
*/
|
||||
@interface FBLPromise<Value>(DotSyntax_DoAdditions)
|
||||
|
||||
+ (FBLPromise * (^)(dispatch_queue_t, FBLPromiseDoWorkBlock))doOn FBL_PROMISES_DOT_SYNTAX
|
||||
NS_SWIFT_UNAVAILABLE("");
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
Copyright 2018 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "DotSyntax/FBLPromise+DotSyntax.h"
|
||||
#import "FBLPromise+Recover.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
Convenience dot-syntax wrappers for `FBLPromise` `recover` operators.
|
||||
Usage: promise.recover(^id(NSError *error) {...})
|
||||
*/
|
||||
@interface FBLPromise<Value>(DotSyntax_RecoverAdditions)
|
||||
|
||||
- (FBLPromise * (^)(id __nullable (^)(NSError *)))recover FBL_PROMISES_DOT_SYNTAX
|
||||
NS_SWIFT_UNAVAILABLE("");
|
||||
- (FBLPromise * (^)(dispatch_queue_t, id __nullable (^)(NSError *)))recoverOn
|
||||
FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE("");
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
Copyright 2018 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "DotSyntax/FBLPromise+DotSyntax.h"
|
||||
#import "FBLPromise+Resolve.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
Convenience dot-syntax wrappers for `FBLPromise` `resolve` operators.
|
||||
Usage: promise.resolveWhen(^(FBLPromiseCompletion handler) {...})
|
||||
*/
|
||||
@interface FBLPromise<Value>(DotSyntax_ResolveAdditions)
|
||||
|
||||
+ (FBLPromise* (^)(void (^)(FBLPromiseCompletion)))resolveWhen FBL_PROMISES_DOT_SYNTAX
|
||||
NS_SWIFT_UNAVAILABLE("");
|
||||
+ (FBLPromise* (^)(void (^)(FBLPromiseObjectCompletion)))resolveWithObjectWhen
|
||||
FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE("");
|
||||
+ (FBLPromise* (^)(void (^)(FBLPromiseErrorCompletion)))resolveWithErrorWhen FBL_PROMISES_DOT_SYNTAX
|
||||
NS_SWIFT_UNAVAILABLE("");
|
||||
+ (FBLPromise* (^)(void (^)(FBLPromiseObjectOrErrorCompletion)))resolveWithObjectOrErrorWhen
|
||||
FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE("");
|
||||
+ (FBLPromise<NSArray*>* (^)(void (^)(FBLPromise2ObjectsOrErrorCompletion)))
|
||||
resolveWith2ObjectsOrErrorWhen FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE("");
|
||||
+ (FBLPromise<NSNumber*>* (^)(void (^)(FBLPromiseBoolCompletion)))resolveWithBoolWhen
|
||||
FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE("");
|
||||
+ (FBLPromise<NSNumber*>* (^)(void (^)(FBLPromiseBoolOrErrorCompletion)))resolveWithBoolOrErrorWhen
|
||||
FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE("");
|
||||
+ (FBLPromise<NSNumber*>* (^)(void (^)(FBLPromiseIntegerCompletion)))resolveWithIntegerWhen
|
||||
FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE("");
|
||||
+ (FBLPromise<NSNumber*>* (^)(void (^)(FBLPromiseIntegerOrErrorCompletion)))
|
||||
resolveWithIntegerOrErrorWhen FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE("");
|
||||
+ (FBLPromise<NSNumber*>* (^)(void (^)(FBLPromiseDoubleCompletion)))resolveWithDoubleWhen
|
||||
FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE("");
|
||||
+ (FBLPromise<NSNumber*>* (^)(void (^)(FBLPromiseDoubleOrErrorCompletion)))
|
||||
resolveWithDoubleOrErrorWhen FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE("");
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
Copyright 2018 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "DotSyntax/FBLPromise+DotSyntax.h"
|
||||
#import "FBLPromise+Then.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
Convenience dot-syntax wrappers for `FBLPromise` `then` operators.
|
||||
Usage: promise.then(^id(id value) { ... })
|
||||
*/
|
||||
@interface FBLPromise<Value>(DotSyntax_ThenAdditions)
|
||||
|
||||
- (FBLPromise* (^)(FBLPromiseThenWorkBlock))then FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE("");
|
||||
- (FBLPromise* (^)(dispatch_queue_t, FBLPromiseThenWorkBlock))thenOn FBL_PROMISES_DOT_SYNTAX
|
||||
NS_SWIFT_UNAVAILABLE("");
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
Copyright 2018 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "DotSyntax/FBLPromise+DotSyntax.h"
|
||||
#import "FBLPromise+Timeout.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
Convenience dot-syntax wrappers for `FBLPromise` `timeout` operators.
|
||||
Usage: promise.timeout(...)
|
||||
*/
|
||||
@interface FBLPromise<Value>(DotSyntax_TimeoutAdditions)
|
||||
|
||||
- (FBLPromise* (^)(NSTimeInterval))timeout FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE("");
|
||||
- (FBLPromise* (^)(dispatch_queue_t, NSTimeInterval))timeoutOn FBL_PROMISES_DOT_SYNTAX
|
||||
NS_SWIFT_UNAVAILABLE("");
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
Copyright 2018 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "DotSyntax/FBLPromise+DotSyntax.h"
|
||||
#import "FBLPromise+Validate.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
Convenience dot-syntax wrappers for `FBLPromise` `validate` operators.
|
||||
Usage: promise.validate(^BOOL(id value) { ... })
|
||||
*/
|
||||
@interface FBLPromise<Value>(DotSyntax_ValidateAdditions)
|
||||
|
||||
- (FBLPromise* (^)(BOOL (^)(Value __nullable)))validate FBL_PROMISES_DOT_SYNTAX
|
||||
NS_SWIFT_UNAVAILABLE("");
|
||||
- (FBLPromise* (^)(dispatch_queue_t, BOOL (^)(Value __nullable)))validateOn FBL_PROMISES_DOT_SYNTAX
|
||||
NS_SWIFT_UNAVAILABLE("");
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,34 @@
|
||||
/**
|
||||
Copyright 2018 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "DotSyntax/FBLPromise+DotSyntax.h"
|
||||
#import "FBLPromise+When.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
Convenience dot-syntax wrappers for `FBLPromise` `when` operators.
|
||||
Usage: promise.when(@[ ... ])
|
||||
*/
|
||||
@interface FBLPromise<Value>(DotSyntax_WhenAdditions)
|
||||
|
||||
+ (FBLPromise<NSArray *> * (^)(NSArray *))when FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE("");
|
||||
+ (FBLPromise<NSArray *> * (^)(dispatch_queue_t, NSArray *))whenOn FBL_PROMISES_DOT_SYNTAX
|
||||
NS_SWIFT_UNAVAILABLE("");
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
Copyright 2018 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "FBLPromise.h"
|
||||
|
||||
#ifdef FBL_PROMISES_DOT_SYNTAX_IS_DEPRECATED
|
||||
#define FBL_PROMISES_DOT_SYNTAX __attribute__((deprecated))
|
||||
#else
|
||||
#define FBL_PROMISES_DOT_SYNTAX
|
||||
#endif
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface FBLPromise<Value>(DotSyntaxAdditions)
|
||||
|
||||
/**
|
||||
Convenience dot-syntax wrappers for FBLPromise.
|
||||
Usage: FBLPromise.resolve(value)
|
||||
*/
|
||||
+ (FBLPromise* (^)(id __nullable))resolve FBL_PROMISES_DOT_SYNTAX NS_SWIFT_UNAVAILABLE("");
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
Copyright 2018 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "FBLPromise.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface FBLPromise<Value>(AllAdditions)
|
||||
|
||||
/**
|
||||
Wait until all of the given promises are fulfilled.
|
||||
If one of the given promises is rejected, then the returned promise is rejected with same error.
|
||||
If any other arbitrary value or `NSError` appears in the array instead of `FBLPromise`,
|
||||
it's implicitly considered a pre-fulfilled or pre-rejected `FBLPromise` correspondingly.
|
||||
Promises resolved with `nil` become `NSNull` instances in the resulting array.
|
||||
|
||||
@param promises Promises to wait for.
|
||||
@return Promise of an array containing the values of input promises in the same order.
|
||||
*/
|
||||
+ (FBLPromise<NSArray *> *)all:(NSArray *)promises NS_SWIFT_UNAVAILABLE("");
|
||||
|
||||
/**
|
||||
Wait until all of the given promises are fulfilled.
|
||||
If one of the given promises is rejected, then the returned promise is rejected with same error.
|
||||
If any other arbitrary value or `NSError` appears in the array instead of `FBLPromise`,
|
||||
it's implicitly considered a pre-fulfilled or pre-rejected FBLPromise correspondingly.
|
||||
Promises resolved with `nil` become `NSNull` instances in the resulting array.
|
||||
|
||||
@param queue A queue to dispatch on.
|
||||
@param promises Promises to wait for.
|
||||
@return Promise of an array containing the values of input promises in the same order.
|
||||
*/
|
||||
+ (FBLPromise<NSArray *> *)onQueue:(dispatch_queue_t)queue
|
||||
all:(NSArray *)promises NS_REFINED_FOR_SWIFT;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
Copyright 2018 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "FBLPromise.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface FBLPromise<Value>(AlwaysAdditions)
|
||||
|
||||
/**
|
||||
@param work A block that always executes, no matter if the receiver is rejected or fulfilled.
|
||||
@return A new pending promise to be resolved with same resolution as the receiver.
|
||||
*/
|
||||
- (FBLPromise *)always:(void (^)(void))work NS_SWIFT_UNAVAILABLE("");
|
||||
|
||||
/**
|
||||
@param queue A queue to dispatch on.
|
||||
@param work A block that always executes, no matter if the receiver is rejected or fulfilled.
|
||||
@return A new pending promise to be resolved with same resolution as the receiver.
|
||||
*/
|
||||
- (FBLPromise *)onQueue:(dispatch_queue_t)queue always:(void (^)(void))work NS_REFINED_FOR_SWIFT;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
Copyright 2018 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "FBLPromise.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface FBLPromise<Value>(AnyAdditions)
|
||||
|
||||
/**
|
||||
Wait until any of the given promises are fulfilled.
|
||||
If one of the promises is rejected, then the returned promise is rejected with same error.
|
||||
If any other arbitrary value or `NSError` appears in the array instead of `FBLPromise`,
|
||||
it's implicitly considered a pre-fulfilled or pre-rejected `FBLPromise` correspondingly.
|
||||
|
||||
@param promises Promises to wait for.
|
||||
@return A new pending promise to be resolved with the same resolution as the first promise, among
|
||||
the given ones, which was resolved.
|
||||
*/
|
||||
+ (instancetype)any:(NSArray *)promises NS_SWIFT_UNAVAILABLE("");
|
||||
|
||||
/**
|
||||
Wait until any of the given promises are fulfilled.
|
||||
If one of the promises is rejected, then the returned promise is rejected with same error.
|
||||
If any other arbitrary value or `NSError` appears in the array instead of `FBLPromise`,
|
||||
it's implicitly considered a pre-fulfilled or pre-rejected `FBLPromise` correspondingly.
|
||||
|
||||
@param queue A queue to dispatch on.
|
||||
@param promises Promises to wait for.
|
||||
@return A new pending promise to be resolved with the same resolution as the first promise, among
|
||||
the given ones, which was resolved.
|
||||
*/
|
||||
+ (instancetype)onQueue:(dispatch_queue_t)queue any:(NSArray *)promises NS_REFINED_FOR_SWIFT;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
Copyright 2018 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "FBLPromise.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface FBLPromise<Value>(AsyncAdditions)
|
||||
|
||||
typedef void (^FBLPromiseFulfillBlock)(Value __nullable value) NS_SWIFT_UNAVAILABLE("");
|
||||
typedef void (^FBLPromiseRejectBlock)(NSError *error) NS_SWIFT_UNAVAILABLE("");
|
||||
typedef void (^FBLPromiseAsyncWorkBlock)(FBLPromiseFulfillBlock fulfill,
|
||||
FBLPromiseRejectBlock reject) NS_SWIFT_UNAVAILABLE("");
|
||||
|
||||
/**
|
||||
Creates a pending promise and executes `work` block asynchronously on the main queue.
|
||||
|
||||
@param work A block to perform any operations needed to resolve the promise.
|
||||
@return A new pending promise.
|
||||
*/
|
||||
+ (instancetype)async:(FBLPromiseAsyncWorkBlock)work NS_SWIFT_UNAVAILABLE("");
|
||||
|
||||
/**
|
||||
Creates a pending promise and executes `work` block asynchronously on the given queue.
|
||||
|
||||
@param queue A queue to invoke the work block on.
|
||||
@param work A block to perform any operations needed to resolve the promise.
|
||||
@return A new pending promise.
|
||||
*/
|
||||
+ (instancetype)onQueue:(dispatch_queue_t)queue
|
||||
async:(FBLPromiseAsyncWorkBlock)work NS_REFINED_FOR_SWIFT;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
Copyright 2018 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "FBLPromise.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface FBLPromise<Value>(CatchAdditions)
|
||||
|
||||
typedef void (^FBLPromiseCatchBlock)(NSError *error) NS_SWIFT_UNAVAILABLE("");
|
||||
|
||||
/**
|
||||
Creates a pending promise which eventually gets resolved with same resolution as the receiver.
|
||||
If receiver is rejected, then `reject` block is executed asynchronously on the main queue.
|
||||
|
||||
@param reject A block to handle the error that receiver was rejected with.
|
||||
@return A new pending promise.
|
||||
*/
|
||||
- (FBLPromise *)catch:(FBLPromiseCatchBlock)reject NS_SWIFT_UNAVAILABLE("");
|
||||
|
||||
/**
|
||||
Creates a pending promise which eventually gets resolved with same resolution as the receiver.
|
||||
If receiver is rejected, then `reject` block is executed asynchronously on the given queue.
|
||||
|
||||
@param queue A queue to invoke the `reject` block on.
|
||||
@param reject A block to handle the error that receiver was rejected with.
|
||||
@return A new pending promise.
|
||||
*/
|
||||
- (FBLPromise *)onQueue:(dispatch_queue_t)queue
|
||||
catch:(FBLPromiseCatchBlock)reject NS_REFINED_FOR_SWIFT;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
Copyright 2018 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "FBLPromise.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface FBLPromise<Value>(DoAdditions)
|
||||
|
||||
typedef id __nullable (^FBLPromiseDoWorkBlock)(void) NS_SWIFT_UNAVAILABLE("");
|
||||
|
||||
/**
|
||||
Creates a pending promise and executes `work` block asynchronously on the main queue.
|
||||
|
||||
@param work A block that returns a value or an error used to resolve the promise.
|
||||
@return A new pending promise.
|
||||
*/
|
||||
+ (instancetype)do:(FBLPromiseDoWorkBlock)work NS_SWIFT_UNAVAILABLE("");
|
||||
|
||||
/**
|
||||
Creates a pending promise and executes `work` block asynchronously on the given queue.
|
||||
|
||||
@param queue A queue to invoke the `work` block on.
|
||||
@param work A block that returns a value or an error used to resolve the promise.
|
||||
@return A new pending promise.
|
||||
*/
|
||||
+ (instancetype)onQueue:(dispatch_queue_t)queue do:(FBLPromiseDoWorkBlock)work NS_REFINED_FOR_SWIFT;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
Copyright 2018 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "FBLPromise.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface FBLPromise<Value>(RecoverAdditions)
|
||||
|
||||
/**
|
||||
Provides a new promise to recover in case the receiver gets rejected.
|
||||
|
||||
@param recovery A block to handle the error that the receiver was rejected with.
|
||||
@return A new pending promise to use instead of the rejected one that gets resolved with resolution
|
||||
returned from `recovery` block.
|
||||
*/
|
||||
- (FBLPromise *)recover:(nullable id (^)(NSError *))recovery NS_SWIFT_UNAVAILABLE("");
|
||||
|
||||
/**
|
||||
Provides a new promise to recover in case the receiver gets rejected.
|
||||
|
||||
@param queue A queue to dispatch on.
|
||||
@param recovery A block to handle the error that the receiver was rejected with.
|
||||
@return A new pending promise to use instead of the rejected one that gets resolved with resolution
|
||||
returned from `recovery` block.
|
||||
*/
|
||||
- (FBLPromise *)onQueue:(dispatch_queue_t)queue
|
||||
recover:(nullable id (^)(NSError *))recovery NS_REFINED_FOR_SWIFT;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,127 @@
|
||||
/**
|
||||
Copyright 2018 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "FBLPromise.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
Different types of completion handlers available to be wrapped with promise.
|
||||
*/
|
||||
typedef void (^FBLPromiseCompletion)(void) NS_SWIFT_UNAVAILABLE("");
|
||||
typedef void (^FBLPromiseObjectCompletion)(id __nullable) NS_SWIFT_UNAVAILABLE("");
|
||||
typedef void (^FBLPromiseErrorCompletion)(NSError* __nullable error) NS_SWIFT_UNAVAILABLE("");
|
||||
typedef void (^FBLPromiseObjectOrErrorCompletion)(id __nullable, NSError* __nullable)
|
||||
NS_SWIFT_UNAVAILABLE("");
|
||||
typedef void (^FBLPromiseErrorOrObjectCompletion)(NSError* __nullable, id __nullable)
|
||||
NS_SWIFT_UNAVAILABLE("");
|
||||
typedef void (^FBLPromise2ObjectsOrErrorCompletion)(id __nullable, id __nullable,
|
||||
NSError* __nullable) NS_SWIFT_UNAVAILABLE("");
|
||||
typedef void (^FBLPromiseBoolCompletion)(BOOL) NS_SWIFT_UNAVAILABLE("");
|
||||
typedef void (^FBLPromiseBoolOrErrorCompletion)(BOOL, NSError* __nullable) NS_SWIFT_UNAVAILABLE("");
|
||||
typedef void (^FBLPromiseIntegerCompletion)(NSInteger) NS_SWIFT_UNAVAILABLE("");
|
||||
typedef void (^FBLPromiseIntegerOrErrorCompletion)(NSInteger, NSError* __nullable)
|
||||
NS_SWIFT_UNAVAILABLE("");
|
||||
typedef void (^FBLPromiseDoubleCompletion)(double) NS_SWIFT_UNAVAILABLE("");
|
||||
typedef void (^FBLPromiseDoubleOrErrorCompletion)(double, NSError* __nullable)
|
||||
NS_SWIFT_UNAVAILABLE("");
|
||||
|
||||
/**
|
||||
Provides an easy way to convert methods that use common callback patterns into promises.
|
||||
*/
|
||||
@interface FBLPromise<Value>(ResolveAdditions)
|
||||
|
||||
/**
|
||||
@returns A promise that resolves with `nil` when completion handler is invoked.
|
||||
*/
|
||||
+ (instancetype)resolveWhenCompleted:(void (^)(FBLPromiseCompletion))work NS_SWIFT_UNAVAILABLE("");
|
||||
|
||||
/**
|
||||
@returns A promise that resolves with an object provided by completion handler.
|
||||
*/
|
||||
+ (instancetype)resolveWithObjectWhenCompleted:(void (^)(FBLPromiseObjectCompletion))work
|
||||
NS_SWIFT_UNAVAILABLE("");
|
||||
|
||||
/**
|
||||
@returns A promise that resolves with an error provided by completion handler.
|
||||
If error is `nil`, fulfills with `nil`, otherwise rejects with the error.
|
||||
*/
|
||||
+ (instancetype)resolveWithErrorWhenCompleted:(void (^)(FBLPromiseErrorCompletion))work
|
||||
NS_SWIFT_UNAVAILABLE("");
|
||||
|
||||
/**
|
||||
@returns A promise that resolves with an object provided by completion handler if error is `nil`.
|
||||
Otherwise, rejects with the error.
|
||||
*/
|
||||
+ (instancetype)resolveWithObjectOrErrorWhenCompleted:
|
||||
(void (^)(FBLPromiseObjectOrErrorCompletion))work NS_SWIFT_UNAVAILABLE("");
|
||||
|
||||
/**
|
||||
@returns A promise that resolves with an error or object provided by completion handler. If error
|
||||
is not `nil`, rejects with the error.
|
||||
*/
|
||||
+ (instancetype)resolveWithErrorOrObjectWhenCompleted:
|
||||
(void (^)(FBLPromiseErrorOrObjectCompletion))work NS_SWIFT_UNAVAILABLE("");
|
||||
|
||||
/**
|
||||
@returns A promise that resolves with an array of objects provided by completion handler in order
|
||||
if error is `nil`. Otherwise, rejects with the error.
|
||||
*/
|
||||
+ (FBLPromise<NSArray*>*)resolveWith2ObjectsOrErrorWhenCompleted:
|
||||
(void (^)(FBLPromise2ObjectsOrErrorCompletion))work NS_SWIFT_UNAVAILABLE("");
|
||||
|
||||
/**
|
||||
@returns A promise that resolves with an `NSNumber` wrapping YES/NO.
|
||||
*/
|
||||
+ (FBLPromise<NSNumber*>*)resolveWithBoolWhenCompleted:(void (^)(FBLPromiseBoolCompletion))work
|
||||
NS_SWIFT_UNAVAILABLE("");
|
||||
|
||||
/**
|
||||
@returns A promise that resolves with an `NSNumber` wrapping YES/NO when error is `nil`.
|
||||
Otherwise rejects with the error.
|
||||
*/
|
||||
+ (FBLPromise<NSNumber*>*)resolveWithBoolOrErrorWhenCompleted:
|
||||
(void (^)(FBLPromiseBoolOrErrorCompletion))work NS_SWIFT_UNAVAILABLE("");
|
||||
|
||||
/**
|
||||
@returns A promise that resolves with an `NSNumber` wrapping an integer.
|
||||
*/
|
||||
+ (FBLPromise<NSNumber*>*)resolveWithIntegerWhenCompleted:
|
||||
(void (^)(FBLPromiseIntegerCompletion))work NS_SWIFT_UNAVAILABLE("");
|
||||
|
||||
/**
|
||||
@returns A promise that resolves with an `NSNumber` wrapping an integer when error is `nil`.
|
||||
Otherwise rejects with the error.
|
||||
*/
|
||||
+ (FBLPromise<NSNumber*>*)resolveWithIntegerOrErrorWhenCompleted:
|
||||
(void (^)(FBLPromiseIntegerOrErrorCompletion))work NS_SWIFT_UNAVAILABLE("");
|
||||
|
||||
/**
|
||||
@returns A promise that resolves with an `NSNumber` wrapping a double.
|
||||
*/
|
||||
+ (FBLPromise<NSNumber*>*)resolveWithDoubleWhenCompleted:(void (^)(FBLPromiseDoubleCompletion))work
|
||||
NS_SWIFT_UNAVAILABLE("");
|
||||
|
||||
/**
|
||||
@returns A promise that resolves with an `NSNumber` wrapping a double when error is `nil`.
|
||||
Otherwise rejects with the error.
|
||||
*/
|
||||
+ (FBLPromise<NSNumber*>*)resolveWithDoubleOrErrorWhenCompleted:
|
||||
(void (^)(FBLPromiseDoubleOrErrorCompletion))work NS_SWIFT_UNAVAILABLE("");
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,63 @@
|
||||
/**
|
||||
Copyright 2018 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "FBLPromise.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
Waits for all scheduled promises blocks.
|
||||
|
||||
@param timeout Maximum time to wait.
|
||||
@return YES if all promises blocks have completed before the timeout and NO otherwise.
|
||||
*/
|
||||
FOUNDATION_EXPORT BOOL FBLWaitForPromisesWithTimeout(NSTimeInterval timeout) NS_REFINED_FOR_SWIFT;
|
||||
|
||||
@interface FBLPromise<Value>(TestingAdditions)
|
||||
|
||||
/**
|
||||
Dispatch group for promises that is typically used to wait for all scheduled blocks.
|
||||
*/
|
||||
@property(class, nonatomic, readonly) dispatch_group_t dispatchGroup NS_REFINED_FOR_SWIFT;
|
||||
|
||||
/**
|
||||
Properties to get the current state of the promise.
|
||||
*/
|
||||
@property(nonatomic, readonly) BOOL isPending NS_REFINED_FOR_SWIFT;
|
||||
@property(nonatomic, readonly) BOOL isFulfilled NS_REFINED_FOR_SWIFT;
|
||||
@property(nonatomic, readonly) BOOL isRejected NS_REFINED_FOR_SWIFT;
|
||||
|
||||
/**
|
||||
Set of arbitrary objects to keep strongly while the promise is pending.
|
||||
Becomes nil after the promise has been resolved.
|
||||
*/
|
||||
@property(nonatomic, readonly, nullable) NSMutableSet *pendingObjects NS_REFINED_FOR_SWIFT;
|
||||
|
||||
/**
|
||||
Value the promise was fulfilled with.
|
||||
Can be nil if the promise is still pending, was resolved with nil or after it has been rejected.
|
||||
*/
|
||||
@property(nonatomic, readonly, nullable) Value value NS_REFINED_FOR_SWIFT;
|
||||
|
||||
/**
|
||||
Error the promise was rejected with.
|
||||
Can be nil if the promise is still pending or after it has been fulfilled.
|
||||
*/
|
||||
@property(nonatomic, readonly, nullable) NSError *error NS_REFINED_FOR_SWIFT;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
Copyright 2018 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "FBLPromise.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface FBLPromise<Value>(ThenAdditions)
|
||||
|
||||
typedef id __nullable (^FBLPromiseThenWorkBlock)(Value __nullable value) NS_SWIFT_UNAVAILABLE("");
|
||||
|
||||
/**
|
||||
Creates a pending promise which eventually gets resolved with resolution returned from `work`
|
||||
block: either value, error or another promise. The `work` block is executed asynchronously on the
|
||||
main queue only when the receiver is fulfilled. If receiver is rejected, the returned promise is
|
||||
also rejected with the same error.
|
||||
|
||||
@param work A block to handle the value that receiver was fulfilled with.
|
||||
@return A new pending promise to be resolved with resolution returned from the `work` block.
|
||||
*/
|
||||
- (FBLPromise *)then:(FBLPromiseThenWorkBlock)work NS_SWIFT_UNAVAILABLE("");
|
||||
|
||||
/**
|
||||
Creates a pending promise which eventually gets resolved with resolution returned from `work`
|
||||
block: either value, error or another promise. The `work` block is executed asynchronously on the
|
||||
main queue only when the receiver is fulfilled. If receiver is rejected, the returned promise is
|
||||
also rejected with the same error.
|
||||
|
||||
@param queue A queue to invoke the `work` block on.
|
||||
@param work A block to handle the value that receiver was fulfilled with.
|
||||
@return A new pending promise to be resolved with resolution returned from the `work` block.
|
||||
*/
|
||||
- (FBLPromise *)onQueue:(dispatch_queue_t)queue
|
||||
then:(FBLPromiseThenWorkBlock)work NS_REFINED_FOR_SWIFT;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
Copyright 2018 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "FBLPromise.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface FBLPromise<Value>(TimeoutAdditions)
|
||||
|
||||
/**
|
||||
Waits for a promise with the specified `timeout`.
|
||||
|
||||
@param interval Time to wait in seconds.
|
||||
@return A new pending promise that gets either resolved with same resolution as the receiver or
|
||||
rejected with `FBLPromiseErrorCodeTimedOut` error code in `FBLPromiseErrorDomain`.
|
||||
*/
|
||||
- (FBLPromise *)timeout:(NSTimeInterval)interval NS_SWIFT_UNAVAILABLE("");
|
||||
|
||||
/**
|
||||
Waits for a promise with the specified `timeout`.
|
||||
|
||||
@param queue A queue to dispatch on.
|
||||
@param interval Time to wait in seconds.
|
||||
@return A new pending promise that gets either resolved with same resolution as the receiver or
|
||||
rejected with `FBLPromiseErrorCodeTimedOut` error code in `FBLPromiseErrorDomain`.
|
||||
*/
|
||||
- (FBLPromise *)onQueue:(dispatch_queue_t)queue
|
||||
timeout:(NSTimeInterval)interval NS_REFINED_FOR_SWIFT;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
Copyright 2018 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "FBLPromise.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface FBLPromise<Value>(ValidateAdditions)
|
||||
|
||||
/**
|
||||
Validates a fulfilled value or rejects the value if it can not be validated.
|
||||
|
||||
@param predicate An expression to validate.
|
||||
@return A new pending promise that gets either resolved with same resolution as the receiver or
|
||||
rejected with `FBLPromiseErrorCodeValidationFailure` error code in `FBLPromiseErrorDomain`.
|
||||
*/
|
||||
- (FBLPromise *)validate:(BOOL (^)(Value __nullable))predicate NS_SWIFT_UNAVAILABLE("");
|
||||
|
||||
/**
|
||||
Validates a fulfilled value or rejects the value if it can not be validated.
|
||||
|
||||
@param queue A queue to dispatch on.
|
||||
@param predicate An expression to validate.
|
||||
@return A new pending promise that gets either resolved with same resolution as the receiver or
|
||||
rejected with `FBLPromiseErrorCodeValidationFailure` error code in `FBLPromiseErrorDomain`.
|
||||
*/
|
||||
- (FBLPromise *)onQueue:(dispatch_queue_t)queue
|
||||
validate:(BOOL (^)(Value __nullable))predicate NS_REFINED_FOR_SWIFT;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
Copyright 2018 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "FBLPromise.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface FBLPromise<Value>(WhenAdditions)
|
||||
|
||||
/**
|
||||
Waits until all of the given promises are either fulfilled or rejected.
|
||||
If all promises are rejected, then the returned promise is rejected with same error
|
||||
as the last one rejected.
|
||||
If at least one of the promises is fulfilled, the resulting promise is fulfilled with an array of
|
||||
values or `NSErrors`, matching the original order of fulfilled or rejected promises respectively.
|
||||
If any other arbitrary value or `NSError` appears in the array instead of `FBLPromise`,
|
||||
it's implicitly considered a pre-fulfilled or pre-rejected `FBLPromise` correspondingly.
|
||||
Promises resolved with `nil` become `NSNull` instances in the resulting array.
|
||||
|
||||
@param promises Promises to wait for.
|
||||
@return Promise of array containing the values or `NSError`s of input promises in the same order.
|
||||
*/
|
||||
+ (FBLPromise<NSArray *> *)when:(NSArray *)promises NS_SWIFT_UNAVAILABLE("");
|
||||
|
||||
/**
|
||||
Waits until all of the given promises are either fulfilled or rejected.
|
||||
If all promises are rejected, then the returned promise is rejected with same error
|
||||
as the last one rejected.
|
||||
If at least one of the promises is fulfilled, the resulting promise is fulfilled with an array of
|
||||
values or `NSError`s, matching the original order of fulfilled or rejected promises respectively.
|
||||
If any other arbitrary value or `NSError` appears in the array instead of `FBLPromise`,
|
||||
it's implicitly considered a pre-fulfilled or pre-rejected `FBLPromise` correspondingly.
|
||||
Promises resolved with `nil` become `NSNull` instances in the resulting array.
|
||||
|
||||
@param queue A queue to dispatch on.
|
||||
@param promises Promises to wait for.
|
||||
@return Promise of array containing the values or `NSError`s of input promises in the same order.
|
||||
*/
|
||||
+ (FBLPromise<NSArray *> *)onQueue:(dispatch_queue_t)queue
|
||||
when:(NSArray *)promises NS_REFINED_FOR_SWIFT;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,58 @@
|
||||
/**
|
||||
Copyright 2018 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "FBLPromiseError.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
Promises synchronization construct in Objective-C.
|
||||
*/
|
||||
@interface FBLPromise<Value> : NSObject
|
||||
|
||||
/**
|
||||
Creates a pending promise.
|
||||
*/
|
||||
+ (instancetype)pendingPromise NS_REFINED_FOR_SWIFT;
|
||||
|
||||
/**
|
||||
Creates a resolved promise.
|
||||
|
||||
@param resolution An object to resolve the promise with: either a value or an error.
|
||||
@return A new resolved promise.
|
||||
*/
|
||||
+ (instancetype)resolvedWith:(nullable id)resolution NS_REFINED_FOR_SWIFT;
|
||||
|
||||
/**
|
||||
Synchronously fulfills the promise with a value.
|
||||
|
||||
@param value An arbitrary value to fulfill the promise with, including `nil`.
|
||||
*/
|
||||
- (void)fulfill:(nullable id)value NS_REFINED_FOR_SWIFT;
|
||||
|
||||
/**
|
||||
Synchronously rejects the promise with an error.
|
||||
|
||||
@param error An error to reject the promise with.
|
||||
*/
|
||||
- (void)reject:(NSError *)error NS_REFINED_FOR_SWIFT;
|
||||
|
||||
+ (instancetype)new NS_UNAVAILABLE;
|
||||
- (instancetype)init NS_UNAVAILABLE;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
Copyright 2018 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
Possible error codes in `FBLPromiseErrorDomain`.
|
||||
*/
|
||||
typedef NS_ENUM(NSInteger, FBLPromiseErrorCode) {
|
||||
/** Objective-C exception was thrown. */
|
||||
FBLPromiseErrorCodeException = 1,
|
||||
/** Promise failed to resolve in time. */
|
||||
FBLPromiseErrorCodeTimedOut = 2,
|
||||
/** Validation predicate returned false. */
|
||||
FBLPromiseErrorCodeValidationFailure = 3,
|
||||
} NS_REFINED_FOR_SWIFT;
|
||||
|
||||
extern NSString* const FBLPromiseErrorDomain NS_REFINED_FOR_SWIFT;
|
||||
extern NSString* const FBLPromiseErrorUserInfoExceptionNameKey NS_REFINED_FOR_SWIFT;
|
||||
extern NSString* const FBLPromiseErrorUserInfoExceptionReasonKey NS_REFINED_FOR_SWIFT;
|
||||
extern NSString* const FBLPromiseErrorUserInfoExceptionUserInfoKey NS_REFINED_FOR_SWIFT;
|
||||
extern NSString* const FBLPromiseErrorUserInfoExceptionReturnAddressesKey NS_REFINED_FOR_SWIFT;
|
||||
extern NSString* const FBLPromiseErrorUserInfoExceptionCallStackKey NS_REFINED_FOR_SWIFT;
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
Copyright 2018 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "FBLPromiseError.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
FOUNDATION_EXPORT NSError *FBLNSErrorFromNSException(NSException *exception)
|
||||
NS_SWIFT_UNAVAILABLE("");
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,67 @@
|
||||
/**
|
||||
Copyright 2018 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "FBLPromise+Testing.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
Miscellaneous low-level private interfaces available to extend standard FBLPromise functionality.
|
||||
*/
|
||||
@interface FBLPromise<Value>()
|
||||
|
||||
typedef void (^__nullable FBLPromiseOnFulfillBlock)(Value __nullable value)
|
||||
NS_SWIFT_UNAVAILABLE("");
|
||||
typedef void (^__nullable FBLPromiseOnRejectBlock)(NSError *error) NS_SWIFT_UNAVAILABLE("");
|
||||
typedef id __nullable (^__nullable FBLPromiseChainedFulfillBlock)(Value __nullable value)
|
||||
NS_SWIFT_UNAVAILABLE("");
|
||||
typedef id __nullable (^__nullable FBLPromiseChainedRejectBlock)(NSError *error)
|
||||
NS_SWIFT_UNAVAILABLE("");
|
||||
|
||||
/**
|
||||
Creates a pending promise.
|
||||
*/
|
||||
- (instancetype)initPending NS_SWIFT_UNAVAILABLE("");
|
||||
|
||||
/**
|
||||
Creates a resolved promise.
|
||||
|
||||
@param resolution An object to resolve the promise with: either a value or an error.
|
||||
@return A new resolved promise.
|
||||
*/
|
||||
- (instancetype)initWithResolution:(nullable id)resolution NS_SWIFT_UNAVAILABLE("");
|
||||
|
||||
/**
|
||||
Invokes `fulfill` and `reject` blocks on `queue` when the receiver gets either fulfilled or
|
||||
rejected respectively.
|
||||
*/
|
||||
- (void)observeOnQueue:(dispatch_queue_t)queue
|
||||
fulfill:(FBLPromiseOnFulfillBlock)onFulfill
|
||||
reject:(FBLPromiseOnRejectBlock)onReject NS_SWIFT_UNAVAILABLE("");
|
||||
|
||||
/**
|
||||
Returns a new promise which gets resolved with the return value of `chainedFulfill` or
|
||||
`chainedReject` blocks respectively. The blocks are invoked when the receiver gets either
|
||||
fulfilled or rejected. If `nil` is passed to either block arg, the returned promise is resolved
|
||||
with the same resolution as the receiver.
|
||||
*/
|
||||
- (FBLPromise *)chainOnQueue:(dispatch_queue_t)queue
|
||||
chainedFulfill:(FBLPromiseChainedFulfillBlock)chainedFulfill
|
||||
chainedReject:(FBLPromiseChainedRejectBlock)chainedReject NS_SWIFT_UNAVAILABLE("");
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,41 @@
|
||||
/**
|
||||
Copyright 2018 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "DotSyntax/FBLPromise+DotSyntax+All.h"
|
||||
#import "DotSyntax/FBLPromise+DotSyntax+Always.h"
|
||||
#import "DotSyntax/FBLPromise+DotSyntax+Any.h"
|
||||
#import "DotSyntax/FBLPromise+DotSyntax+Async.h"
|
||||
#import "DotSyntax/FBLPromise+DotSyntax+Catch.h"
|
||||
#import "DotSyntax/FBLPromise+DotSyntax+Do.h"
|
||||
#import "DotSyntax/FBLPromise+DotSyntax+Recover.h"
|
||||
#import "DotSyntax/FBLPromise+DotSyntax+Resolve.h"
|
||||
#import "DotSyntax/FBLPromise+DotSyntax+Then.h"
|
||||
#import "DotSyntax/FBLPromise+DotSyntax+Timeout.h"
|
||||
#import "DotSyntax/FBLPromise+DotSyntax+Validate.h"
|
||||
#import "DotSyntax/FBLPromise+DotSyntax+When.h"
|
||||
#import "FBLPromise+All.h"
|
||||
#import "FBLPromise+Always.h"
|
||||
#import "FBLPromise+Any.h"
|
||||
#import "FBLPromise+Async.h"
|
||||
#import "FBLPromise+Catch.h"
|
||||
#import "FBLPromise+Do.h"
|
||||
#import "FBLPromise+Recover.h"
|
||||
#import "FBLPromise+Resolve.h"
|
||||
#import "FBLPromise+Testing.h"
|
||||
#import "FBLPromise+Then.h"
|
||||
#import "FBLPromise+Timeout.h"
|
||||
#import "FBLPromise+Validate.h"
|
||||
#import "FBLPromise+When.h"
|
||||
@@ -0,0 +1,36 @@
|
||||
module FBLPromises {
|
||||
umbrella header "FBLPromises.h"
|
||||
|
||||
export *
|
||||
|
||||
header "FBLPromise+All.h"
|
||||
header "FBLPromise+Always.h"
|
||||
header "FBLPromise+Any.h"
|
||||
header "FBLPromise+Async.h"
|
||||
header "FBLPromise+Catch.h"
|
||||
header "FBLPromise+Do.h"
|
||||
header "FBLPromise+Recover.h"
|
||||
header "FBLPromise+Resolve.h"
|
||||
header "FBLPromise+Testing.h"
|
||||
header "FBLPromise+Then.h"
|
||||
header "FBLPromise+Timeout.h"
|
||||
header "FBLPromise+Validate.h"
|
||||
header "FBLPromise+When.h"
|
||||
|
||||
header "DotSyntax/FBLPromise+DotSyntax.h"
|
||||
header "DotSyntax/FBLPromise+DotSyntax+All.h"
|
||||
header "DotSyntax/FBLPromise+DotSyntax+Always.h"
|
||||
header "DotSyntax/FBLPromise+DotSyntax+Any.h"
|
||||
header "DotSyntax/FBLPromise+DotSyntax+Async.h"
|
||||
header "DotSyntax/FBLPromise+DotSyntax+Catch.h"
|
||||
header "DotSyntax/FBLPromise+DotSyntax+Do.h"
|
||||
header "DotSyntax/FBLPromise+DotSyntax+Recover.h"
|
||||
header "DotSyntax/FBLPromise+DotSyntax+Resolve.h"
|
||||
header "DotSyntax/FBLPromise+DotSyntax+Then.h"
|
||||
header "DotSyntax/FBLPromise+DotSyntax+Timeout.h"
|
||||
header "DotSyntax/FBLPromise+DotSyntax+Validate.h"
|
||||
header "DotSyntax/FBLPromise+DotSyntax+When.h"
|
||||
|
||||
exclude header "FBLPromiseErrorPrivate.h"
|
||||
exclude header "FBLPromisePrivate.h"
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
Copyright 2018 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "FBLPromisesTestInteroperability.h"
|
||||
|
||||
#import "FBLPromises.h"
|
||||
#import "FBLPromisesTestHelpers.h"
|
||||
|
||||
@implementation FBLPromisesTestInteroperabilityObjC
|
||||
|
||||
+ (FBLPromise *)fulfillWithObject:(nullable id)object {
|
||||
return [self fulfillWithObject:object delay:0.0];
|
||||
}
|
||||
|
||||
+ (FBLPromise *)fulfillWithObject:(nullable id)object delay:(NSTimeInterval)delay {
|
||||
return [self promiseWithValue:object error:nil delay:delay];
|
||||
}
|
||||
|
||||
+ (FBLPromise *)rejectWithError:(NSError *)error {
|
||||
return [self rejectWithError:error delay:0.0];
|
||||
}
|
||||
|
||||
+ (FBLPromise *)rejectWithError:(NSError *)error delay:(NSTimeInterval)delay {
|
||||
return [self promiseWithValue:nil error:error delay:delay];
|
||||
}
|
||||
|
||||
+ (FBLPromise *)rejectWithException:(NSException *)exception {
|
||||
return [self rejectWithException:exception delay:0.0];
|
||||
}
|
||||
|
||||
+ (FBLPromise *)rejectWithException:(NSException *)exception delay:(NSTimeInterval)delay {
|
||||
return [self promiseThrowException:exception delay:delay];
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
|
||||
/**
|
||||
Returns a promise which gets resolved after a delay either with a given error,
|
||||
or with a value, if error is nil.
|
||||
*/
|
||||
+ (FBLPromise *)promiseWithValue:(nullable id)value
|
||||
error:(NSError *__nullable)error
|
||||
delay:(NSTimeInterval)delay {
|
||||
return [FBLPromise async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock reject) {
|
||||
FBLDelay(delay, ^{
|
||||
if (error) {
|
||||
reject(error);
|
||||
} else {
|
||||
fulfill(value);
|
||||
}
|
||||
});
|
||||
}];
|
||||
}
|
||||
|
||||
+ (FBLPromise *)promiseThrowException:(NSException *__nullable)exception
|
||||
delay:(NSTimeInterval)delay {
|
||||
return [FBLPromise async:^(FBLPromiseFulfillBlock __unused _, FBLPromiseRejectBlock __unused __) {
|
||||
// Can't use asynchronous FBLDelay because the exception will be caught by GCD in that case.
|
||||
[NSThread sleepForTimeInterval:delay];
|
||||
@throw exception; // NOLINT
|
||||
}];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
Copyright 2018 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/**
|
||||
Executes the given work block on the main queue after time interval.
|
||||
*/
|
||||
static inline void FBLDelay(NSTimeInterval interval, void (^work)(void)) {
|
||||
int64_t const timeToWait = (int64_t)(interval * NSEC_PER_SEC);
|
||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, timeToWait),
|
||||
dispatch_get_main_queue(), ^{
|
||||
work();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
Executes the given block multiple times according to the count variable and then returns
|
||||
the average number of nanoseconds per execution. Isn't listed in any public libdispatch header,
|
||||
although comes with a man page, so declaring manually here.
|
||||
*/
|
||||
FOUNDATION_EXTERN uint64_t dispatch_benchmark(size_t count, void (^block)(void));
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
Copyright 2018 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@class FBLPromise<id>;
|
||||
|
||||
@interface FBLPromisesTestInteroperabilityObjC<Value> : NSObject
|
||||
|
||||
+ (FBLPromise<Value> *)fulfillWithObject:(nullable Value)object NS_SWIFT_UNAVAILABLE("");
|
||||
+ (FBLPromise<Value> *)fulfillWithObject:(nullable Value)object
|
||||
delay:(NSTimeInterval)delay NS_SWIFT_NAME(fulfill(_:delay:));
|
||||
+ (FBLPromise<Value> *)rejectWithError:(NSError *)error NS_SWIFT_UNAVAILABLE("");
|
||||
+ (FBLPromise<Value> *)rejectWithError:(NSError *)error
|
||||
delay:(NSTimeInterval)delay NS_SWIFT_NAME(reject(_:delay:));
|
||||
+ (FBLPromise<Value> *)rejectWithException:(NSException *)exception NS_SWIFT_UNAVAILABLE("");
|
||||
+ (FBLPromise<Value> *)rejectWithException:(NSException *)exception
|
||||
delay:(NSTimeInterval)delay NS_SWIFT_NAME(reject(_:delay:));
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
@@ -0,0 +1,4 @@
|
||||
module FBLPromisesTestHelpers {
|
||||
header "FBLPromisesTestHelpers.h"
|
||||
header "FBLPromisesTestInteroperability.h"
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
// Copyright 2018 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at:
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import Dispatch
|
||||
|
||||
/// Waits until all of the promises have been fulfilled.
|
||||
/// If one of the promises is rejected, then the returned promise is rejected with same error.
|
||||
/// If any other arbitrary value or `Error` appears in the array instead of `Promise`,
|
||||
/// it's implicitly considered a pre-fulfilled or pre-rejected `Promise` correspondingly.
|
||||
/// - parameters:
|
||||
/// - queue: A queue to dispatch on.
|
||||
/// - promises: An array of promises to wait for.
|
||||
/// - returns: Promise of an array containing the values of input promises in the same order.
|
||||
public func all<Value>(
|
||||
on queue: DispatchQueue = .main,
|
||||
_ promises: Promise<Value>...
|
||||
) -> Promise<[Value]> {
|
||||
return all(on: queue, promises)
|
||||
}
|
||||
|
||||
/// Waits until all of the promises have been fulfilled.
|
||||
/// If one of the promises is rejected, then the returned promise is rejected with same error.
|
||||
/// If any other arbitrary value or `Error` appears in the array instead of `Promise`,
|
||||
/// it's implicitly considered a pre-fulfilled or pre-rejected `Promise` correspondingly.
|
||||
/// - parameters:
|
||||
/// - queue: A queue to dispatch on.
|
||||
/// - promises: An array of promises to wait for.
|
||||
/// - returns: Promise of an array containing the values of input promises in the same order.
|
||||
public func all<Value, Container: Sequence>(
|
||||
on queue: DispatchQueue = .main,
|
||||
_ promises: Container
|
||||
) -> Promise<[Value]> where Container.Iterator.Element == Promise<Value> {
|
||||
let promise = Promise<[Value]>(
|
||||
Promise<[Value]>.ObjCPromise<AnyObject>.__onQueue(queue, all: promises.map { $0.objCPromise })
|
||||
)
|
||||
// Keep Swift wrapper alive for chained promises until `ObjCPromise` counterpart is resolved.
|
||||
promises.forEach {
|
||||
$0.objCPromise.__pendingObjects?.add(promise)
|
||||
}
|
||||
return promise
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
// Copyright 2018 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at:
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import Dispatch
|
||||
|
||||
public extension Promise {
|
||||
|
||||
/// Provides a way to always execute a given chained block.
|
||||
/// - parameters:
|
||||
/// - queue: A queue to dispatch on.
|
||||
/// - work: A block that always executes, no matter if `self` is rejected or fulfilled.
|
||||
/// - returns: A new pending promise to be resolved with same resolution as `self`.
|
||||
@discardableResult
|
||||
public func always(on queue: DispatchQueue = .main, _ work: @escaping () -> Void) -> Promise {
|
||||
let promise = Promise(objCPromise.__onQueue(queue, always: work))
|
||||
// Keep Swift wrapper alive for chained promise until `ObjCPromise` counterpart is resolved.
|
||||
objCPromise.__pendingObjects?.add(promise)
|
||||
return promise
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
// Copyright 2018 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at:
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import Dispatch
|
||||
|
||||
/// Wait until any of the given promises are fulfilled.
|
||||
/// If one of the given promises is rejected, then the returned promise is rejected with same
|
||||
/// error. If any other arbitrary value or `Error` appears in the array instead of `Promise`,
|
||||
/// it's implicitly considered a pre-fulfilled or pre-rejected `Promise` correspondingly.
|
||||
/// - parameters:
|
||||
/// - queue: A queue to dispatch on.
|
||||
/// - promises: Promises to wait for.
|
||||
/// - returns: First promise, among the given ones, which was fulfilled.
|
||||
public func any<Value>(
|
||||
on queue: DispatchQueue = .main,
|
||||
_ promises: Promise<Value>...
|
||||
) -> Promise<Value> {
|
||||
return any(on: queue, promises)
|
||||
}
|
||||
|
||||
/// Wait until any of the given promises are fulfilled.
|
||||
/// If one of the given promises is rejected, then the returned promise is rejected with same
|
||||
/// error. If any other arbitrary value or `Error` appears in the array instead of `Promise`,
|
||||
/// it's implicitly considered a pre-fulfilled or pre-rejected `Promise` correspondingly.
|
||||
/// - parameters:
|
||||
/// - queue: A queue to dispatch on.
|
||||
/// - promises: Promises to wait for.
|
||||
/// - returns: First promise, among the given ones, which was fulfilled.
|
||||
public func any<Value>(
|
||||
on queue: DispatchQueue = .main,
|
||||
_ promises: [Promise<Value>]
|
||||
) -> Promise<Value> {
|
||||
let promise = Promise<Value>(
|
||||
Promise<Value>.ObjCPromise<AnyObject>.__onQueue(queue, any: promises.map { $0.objCPromise })
|
||||
)
|
||||
// Keep Swift wrapper alive for chained promises until `ObjCPromise` counterpart is resolved.
|
||||
promises.forEach {
|
||||
$0.objCPromise.__pendingObjects?.add(promise)
|
||||
}
|
||||
return promise
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
// Copyright 2018 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at:
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import Foundation
|
||||
|
||||
public extension Promise {
|
||||
public typealias Fulfill = (Value) -> Void
|
||||
public typealias Reject = (Error) -> Void
|
||||
public typealias AsyncWork = (@escaping Fulfill, @escaping Reject) throws -> Void
|
||||
|
||||
/// Creates a pending promise and executes `work` block asynchronously on the given `queue`.
|
||||
/// - parameters:
|
||||
/// - queue: A queue to invoke the `work` block on.
|
||||
/// - work: A block to perform any operations needed to resolve the promise.
|
||||
public convenience init(on queue: DispatchQueue = .main, _ work: @escaping AsyncWork) {
|
||||
let objCPromise = ObjCPromise<AnyObject>.__onQueue(queue) { fulfill, reject in
|
||||
do {
|
||||
try work({ value in
|
||||
if let error = value as? NSError {
|
||||
reject(error)
|
||||
} else {
|
||||
fulfill(Promise<Value>.asAnyObject(value))
|
||||
}
|
||||
}, reject)
|
||||
} catch let error {
|
||||
reject(error as NSError)
|
||||
}
|
||||
}
|
||||
self.init(objCPromise)
|
||||
// Keep Swift wrapper alive for chained promise until `ObjCPromise` counterpart is resolved.
|
||||
objCPromise.__pendingObjects?.add(self)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
// Copyright 2018 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at:
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import Foundation
|
||||
|
||||
public extension Promise {
|
||||
public typealias Catch = (Error) -> Void
|
||||
|
||||
/// Creates a pending promise which eventually gets resolved with same resolution as `self`.
|
||||
/// If `self` is rejected, then `reject` block is executed asynchronously on the main queue.
|
||||
/// - parameters:
|
||||
/// - queue: A queue to invoke the `reject` block on.
|
||||
/// - reject: A block to handle the error that `self` was rejected with.
|
||||
/// - returns: A new pending promise.
|
||||
@discardableResult
|
||||
public func `catch`(on queue: DispatchQueue = .main, _ reject: @escaping Catch) -> Promise {
|
||||
let promise = Promise(objCPromise.__onQueue(queue, catch: { reject($0 as NSError) }))
|
||||
// Keep Swift wrapper alive for chained promise until `ObjCPromise` counterpart is resolved.
|
||||
objCPromise.__pendingObjects?.add(promise)
|
||||
return promise
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
// Copyright 2018 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at:
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import Foundation
|
||||
|
||||
public extension Promise {
|
||||
public typealias Work = () throws -> Value
|
||||
|
||||
/// Creates a pending promise to be resolved with the return value of `work` block which is
|
||||
/// executed asynchronously on the given `queue`.
|
||||
/// - parameters:
|
||||
/// - queue: A queue to invoke the `work` block on.
|
||||
/// - work: A block to perform any operations needed to resolve the promise.
|
||||
public convenience init(on queue: DispatchQueue = .main, _ work: @escaping Work) {
|
||||
let objCPromise = ObjCPromise<AnyObject>.__onQueue(queue) {
|
||||
do {
|
||||
let resolution = try work()
|
||||
return resolution as? NSError ?? Promise<Value>.asAnyObject(resolution)
|
||||
} catch let error {
|
||||
return error as NSError
|
||||
}
|
||||
}
|
||||
self.init(objCPromise)
|
||||
// Keep Swift wrapper alive for chained promise until `ObjCPromise` counterpart is resolved.
|
||||
objCPromise.__pendingObjects?.add(self)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
// Copyright 2018 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at:
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import Foundation
|
||||
|
||||
public extension Promise {
|
||||
|
||||
/// Provides a new promise to recover in case `self` gets rejected.
|
||||
/// - parameters:
|
||||
/// - queue: A queue to execute `recovery` block on.
|
||||
/// - recovery: A block to handle the error that `self` was rejected with.
|
||||
/// - returns: A new pending promise to use instead of the rejected one that gets resolved with
|
||||
/// the same resolution as the promise returned from `recovery` block.
|
||||
@discardableResult
|
||||
public func recover(on queue: DispatchQueue = .main,
|
||||
_ recovery: @escaping (Error) throws -> Promise) -> Promise {
|
||||
let promise = Promise(objCPromise.__onQueue(queue, recover: {
|
||||
do {
|
||||
return try recovery($0).objCPromise
|
||||
} catch let error {
|
||||
return error as NSError
|
||||
}
|
||||
}))
|
||||
// Keep Swift wrapper alive for chained promise until `ObjCPromise` counterpart is resolved.
|
||||
objCPromise.__pendingObjects?.add(promise)
|
||||
return promise
|
||||
}
|
||||
|
||||
/// Provides a new promise to recover in case `self` gets rejected.
|
||||
/// - parameters:
|
||||
/// - queue: A queue to execute `recovery` block on.
|
||||
/// - recovery: A block to handle the error that `self` was rejected with.
|
||||
/// - returns: A new pending promise to use instead of the rejected one that gets resolved with
|
||||
/// the value returned from `recovery` block.
|
||||
@discardableResult
|
||||
public func recover(on queue: DispatchQueue = .main,
|
||||
_ recovery: @escaping (Error) throws -> Value) -> Promise {
|
||||
let promise = Promise(objCPromise.__onQueue(queue, recover: { error in
|
||||
do {
|
||||
return Promise<Value>.asAnyObject(try recovery(error)) as Any
|
||||
} catch let error {
|
||||
return error as NSError
|
||||
}
|
||||
}))
|
||||
// Keep Swift wrapper alive for chained promise until `ObjCPromise` counterpart is resolved.
|
||||
objCPromise.__pendingObjects?.add(promise)
|
||||
return promise
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
// Copyright 2018 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at:
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/// Provides a convenient way to convert methods that use common callback patterns into `Promise`s.
|
||||
|
||||
/// Creates a new promise to be resolved when completion handler gets invoked.
|
||||
/// - parameter work: A block to execute on the main queue to invoke some API that requires
|
||||
/// a completion handler with no arguments.
|
||||
/// - returns: A new pending promise to be resolved with `nil` when completion handler finishes.
|
||||
public func resolve(_ work: @escaping (@escaping () -> Void) throws -> Void) -> Promise<Any?> {
|
||||
return Promise<Any?> { fulfill, _ in
|
||||
try work { fulfill(nil) }
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new promise to be resolved when completion handler gets invoked.
|
||||
/// - parameter work: A block to execute on the main queue to invoke some API that requires
|
||||
/// a completion handler with one argument of generic `Value` type.
|
||||
/// - returns: A new pending promise to be resolved with the value provided by completion handler
|
||||
/// when it finishes.
|
||||
public func resolve<Value>(
|
||||
_ work: @escaping (@escaping (Value) -> Void) throws -> Void
|
||||
) -> Promise<Value> {
|
||||
return Promise<Value> { fulfill, _ in
|
||||
try work { fulfill($0) }
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new promise to be resolved when completion handler gets invoked.
|
||||
/// - parameter work: A block to execute on the main queue to invoke some API that requires
|
||||
/// a completion handler with one argument of optional generic `Value` type.
|
||||
/// - returns: A new pending promise to be resolved with the value or error provided by completion
|
||||
/// handler when it finishes.
|
||||
public func resolve<Value>(
|
||||
_ work: @escaping (@escaping (Value?) -> Void) throws -> Void
|
||||
) -> Promise<Value?> {
|
||||
return Promise<Value?> { fulfill, _ in
|
||||
try work { fulfill($0) }
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new promise to be resolved when completion handler gets invoked.
|
||||
/// - parameter work: A block to execute on the main queue to invoke some API that requires
|
||||
/// a completion handler with two arguments: a generic of `Value` type and
|
||||
/// an optional `Error`.
|
||||
/// - returns: A new pending promise to be resolved with the value or error provided by completion
|
||||
/// handler when it finishes.
|
||||
public func resolve<Value>(
|
||||
_ work: @escaping (@escaping (Value, Error?) -> Void) throws -> Void
|
||||
) -> Promise<Value> {
|
||||
return Promise<Value> { fulfill, reject in
|
||||
try work { value, error in
|
||||
if let error = error {
|
||||
reject(error)
|
||||
} else {
|
||||
fulfill(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new promise to be resolved when completion handler gets invoked.
|
||||
/// - parameter work: A block to execute on the main queue to invoke some API that requires
|
||||
/// a completion handler with two arguments: an optional `Error` and a generic of
|
||||
/// `Value` type.
|
||||
/// - returns: A new pending promise to be resolved with the error or value provided by completion
|
||||
/// handler when it finishes.
|
||||
public func resolve<Value>(
|
||||
_ work: @escaping (@escaping (Error?, Value) -> Void) throws -> Void
|
||||
) -> Promise<Value> {
|
||||
return Promise<Value> { fulfill, reject in
|
||||
try work { error, value in
|
||||
if let error = error {
|
||||
reject(error)
|
||||
} else {
|
||||
fulfill(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new promise to be resolved when completion handler gets invoked.
|
||||
/// - parameter work: A block to execute on the main queue to invoke some API that requires
|
||||
/// a completion handler with two arguments: an optional generic of `Value` type
|
||||
/// and an optional `Error`.
|
||||
/// - returns: A new pending promise to be resolved with the value or error provided by completion
|
||||
/// handler when it finishes.
|
||||
public func resolve<Value>(
|
||||
_ work: @escaping (@escaping (Value?, Error?) -> Void) throws -> Void
|
||||
) -> Promise<Value?> {
|
||||
return Promise<Value?> { fulfill, reject in
|
||||
try work { value, error in
|
||||
if let error = error {
|
||||
reject(error)
|
||||
} else {
|
||||
fulfill(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new promise to be resolved when completion handler gets invoked.
|
||||
/// - parameter work: A block to execute on the main queue to invoke some API that requires
|
||||
/// a completion handler with two arguments: an optional `Error` and an optional
|
||||
/// generic of `Value` type.
|
||||
/// - returns: A new pending promise to be resolved with the error or value provided by completion
|
||||
/// handler when it finishes.
|
||||
public func resolve<Value>(
|
||||
_ work: @escaping (@escaping (Error?, Value?) -> Void) throws -> Void
|
||||
) -> Promise<Value?> {
|
||||
return Promise<Value?> { fulfill, reject in
|
||||
try work { error, value in
|
||||
if let error = error {
|
||||
reject(error)
|
||||
} else {
|
||||
fulfill(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new promise to be resolved when completion handler gets invoked.
|
||||
/// - parameter work: A block to execute on the main queue to invoke some API that requires
|
||||
/// a completion handler with three arguments: two optionals of `Any` type
|
||||
/// and an optional `Error`.
|
||||
/// - returns: A new pending promise to be resolved with a tuple of optional values or an error
|
||||
/// provided by completion handler when it finishes.
|
||||
public func resolve<Value1, Value2>(
|
||||
_ work: @escaping (@escaping (Value1?, Value2?, Error?) -> Void) throws -> Void
|
||||
) -> Promise<(Value1?, Value2?)> {
|
||||
return Promise<(Value1?, Value2?)> { fulfill, reject in
|
||||
try work { value1, value2, error in
|
||||
if let error = error {
|
||||
reject(error)
|
||||
} else {
|
||||
fulfill((value1, value2))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
// Copyright 2018 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at:
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import FBLPromises
|
||||
|
||||
extension DispatchGroup {
|
||||
/// Dispatch group for promises that is typically used to wait for all scheduled blocks.
|
||||
static var promises: DispatchGroup { return Promise<Any>.ObjCPromise<AnyObject>.__dispatchGroup }
|
||||
}
|
||||
|
||||
/// Waits for all scheduled promise blocks.
|
||||
/// - parameter timeout: Maximum time to wait.
|
||||
/// - returns: `true` if all promise blocks have completed before `timeout` and `false` otherwise.
|
||||
func waitForPromises(timeout: TimeInterval) -> Bool {
|
||||
return __FBLWaitForPromisesWithTimeout(timeout)
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
// Copyright 2018 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at:
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import Foundation
|
||||
|
||||
public extension Promise {
|
||||
public typealias Then<Result> = (Value) throws -> Result
|
||||
|
||||
/// Creates a pending promise which eventually gets resolved with the same resolution as the
|
||||
/// promise returned from `work` block. The `work` block is executed asynchronously on the given
|
||||
/// `queue` only when `self` is fulfilled. If `self` is rejected, the returned promise is also
|
||||
/// rejected with the same error.
|
||||
/// - parameters:
|
||||
/// - queue: A queue to invoke the `work` block on.
|
||||
/// - work: A block to handle the value that `self` was fulfilled with.
|
||||
/// - returns: A new pending promise to be resolved with the same resolution as the promise
|
||||
/// returned from the `work` block.
|
||||
@discardableResult
|
||||
public func then<Result>(on queue: DispatchQueue = .main,
|
||||
_ work: @escaping Then<Promise<Result>>) -> Promise<Result> {
|
||||
let promise = Promise<Result>(objCPromise.__onQueue(queue, then: { value in
|
||||
guard let value = Promise<Value>.asValue(value) else { preconditionFailure() }
|
||||
do {
|
||||
return try work(value).objCPromise
|
||||
} catch let error {
|
||||
return error as NSError
|
||||
}
|
||||
}))
|
||||
// Keep Swift wrapper alive for chained promise until `ObjCPromise` counterpart is resolved.
|
||||
objCPromise.__pendingObjects?.add(promise)
|
||||
return promise
|
||||
}
|
||||
|
||||
/// Creates a pending promise which eventually gets resolved with the value returned from `work`
|
||||
/// block. The `work` block is executed asynchronously on the given `queue` only when `self` is
|
||||
/// fulfilled. If `self` is rejected, the returned promise is also rejected with the same error.
|
||||
/// - parameters:
|
||||
/// - queue: A queue to invoke the `work` block on.
|
||||
/// - work: A block to handle the value that `self` was fulfilled with.
|
||||
/// - returns: A new pending promise to be resolved with the value returned from the `work` block.
|
||||
@discardableResult
|
||||
public func then<Result>(on queue: DispatchQueue = .main,
|
||||
_ work: @escaping Then<Result>) -> Promise<Result> {
|
||||
let promise = Promise<Result>(objCPromise.__onQueue(queue, then: { value in
|
||||
guard let value = Promise<Value>.asValue(value) else { preconditionFailure() }
|
||||
do {
|
||||
let value = try work(value)
|
||||
return value as? NSError ?? Promise<Result>.asAnyObject(value)
|
||||
} catch let error {
|
||||
return error as NSError
|
||||
}
|
||||
}))
|
||||
// Keep Swift wrapper alive for chained promise until `ObjCPromise` counterpart is resolved.
|
||||
objCPromise.__pendingObjects?.add(promise)
|
||||
return promise
|
||||
}
|
||||
|
||||
/// Creates a pending promise which eventually gets resolved with the same resolution as `self`.
|
||||
/// `work` block is executed asynchronously on the given `queue` only when `self` is fulfilled.
|
||||
/// If `self` is rejected, the returned promise is also rejected with the same error.
|
||||
/// - parameters:
|
||||
/// - queue: A queue to invoke the `work` block on.
|
||||
/// - work: A block to handle the value that `self` was fulfilled with.
|
||||
/// - returns: A new pending promise to be resolved with the value passed into the `work` block.
|
||||
@discardableResult
|
||||
public func then(on queue: DispatchQueue = .main, _ work: @escaping Then<Void>) -> Promise {
|
||||
let promise = Promise(objCPromise.__onQueue(queue, then: { value in
|
||||
guard let value = Promise<Value>.asValue(value) else { preconditionFailure() }
|
||||
do {
|
||||
try work(value)
|
||||
return Promise<Value>.asAnyObject(value)
|
||||
} catch let error {
|
||||
return error as NSError
|
||||
}
|
||||
}))
|
||||
// Keep Swift wrapper alive for chained promise until `ObjCPromise` counterpart is resolved.
|
||||
objCPromise.__pendingObjects?.add(promise)
|
||||
return promise
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
// Copyright 2018 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at:
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import Foundation
|
||||
|
||||
public extension Promise {
|
||||
|
||||
/// Waits on a promise for a given interval or rejects the promise if it exceeds the time limit.
|
||||
/// - parameters:
|
||||
/// - queue: A queue to dispatch on.
|
||||
/// - interval: Time to wait in seconds.
|
||||
/// - returns: A new pending promise that gets either resolved with same resolution as `self` or
|
||||
/// rejected with `PromiseError.timedOut` error.
|
||||
@discardableResult
|
||||
public func timeout(on queue: DispatchQueue = .main, _ interval: TimeInterval) -> Promise {
|
||||
let promise = Promise(objCPromise.__onQueue(queue, timeout: interval))
|
||||
// Keep Swift wrapper alive for chained promise until `ObjCPromise` counterpart is resolved.
|
||||
objCPromise.__pendingObjects?.add(promise)
|
||||
return promise
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
// Copyright 2018 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at:
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import Dispatch
|
||||
|
||||
public extension Promise {
|
||||
|
||||
/// Validates a fulfilled value or rejects the value if it can not be validated.
|
||||
/// - parameters:
|
||||
/// - queue: A queue to dispatch on.
|
||||
/// - predicate: An expression to validate.
|
||||
/// - returns: A new pending promise that gets either resolved with same resolution as `self` or
|
||||
/// rejected with `PromiseError.validationFailure` error.
|
||||
@discardableResult
|
||||
public func validate(on queue: DispatchQueue = .main,
|
||||
_ predicate: @escaping (Value) -> Bool) -> Promise {
|
||||
return then { (value: Value) -> Value in
|
||||
guard predicate(value) else { throw PromiseError.validationFailure }
|
||||
return value
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
// Copyright 2018 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at:
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import Foundation
|
||||
|
||||
/// Waits for all of the given promises to be fulfilled or rejected.
|
||||
/// If all promises are rejected, then the returned promise is rejected with same error
|
||||
/// as the last one rejected.
|
||||
/// If at least one of the promises is fulfilled, the resulting promise is fulfilled with an array
|
||||
/// of values or `Error`s, matching the original order of fulfilled or rejected promises
|
||||
/// respectively.
|
||||
/// If any other arbitrary value or `Error` appears in the array instead of `Promise`,
|
||||
/// it's implicitly considered a pre-fulfilled or pre-rejected `Promise` correspondingly.
|
||||
/// - parameters:
|
||||
/// - queue: A queue to dispatch on.
|
||||
/// - promises: Promises to wait for.
|
||||
/// - returns: Promise of array containing the values or `Error`s of input promises in their
|
||||
/// original order.
|
||||
public func when<Value>(
|
||||
on queue: DispatchQueue = .main,
|
||||
_ promises: Promise<Value>...
|
||||
) -> Promise<[Value]> {
|
||||
return when(on: queue, promises)
|
||||
}
|
||||
|
||||
/// Waits for all of the given promises to be fulfilled or rejected.
|
||||
/// If all promises are rejected, then the returned promise is rejected with same error
|
||||
/// as the last one rejected.
|
||||
/// If at least one of the promises is fulfilled, the resulting promise is fulfilled with an array
|
||||
/// of values or `Error`s, matching the original order of fulfilled or rejected promises
|
||||
/// respectively.
|
||||
/// If any other arbitrary value or `Error` appears in the array instead of `Promise`,
|
||||
/// it's implicitly considered a pre-fulfilled or pre-rejected `Promise` correspondingly.
|
||||
/// - parameters:
|
||||
/// - queue: A queue to dispatch on.
|
||||
/// - promises: Promises to wait for.
|
||||
/// - returns: Promise of array containing the values or `Error`s of input promises in their
|
||||
/// original order.
|
||||
public func when<Value, Container: Sequence>(
|
||||
on queue: DispatchQueue = .main,
|
||||
_ promises: Container
|
||||
) -> Promise<[Value]> where Container.Iterator.Element == Promise<Value> {
|
||||
let promise = Promise<[Value]>(
|
||||
Promise<[Value]>.ObjCPromise<AnyObject>.__onQueue(queue, when: promises.map { $0.objCPromise })
|
||||
)
|
||||
// Keep Swift wrapper alive for chained promises until `ObjCPromise` counterpart is resolved.
|
||||
promises.forEach {
|
||||
$0.objCPromise.__pendingObjects?.add(promise)
|
||||
}
|
||||
return promise
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
// Copyright 2018 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at:
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import FBLPromises
|
||||
|
||||
/// Promises synchronization construct in Swift. Leverages ObjC implementation internally.
|
||||
public final class Promise<Value> {
|
||||
public typealias ObjCPromise<Value: AnyObject> = FBLPromise<Value>
|
||||
|
||||
/// Creates a new promise with an existing ObjC promise.
|
||||
public init<Value>(_ objCPromise: ObjCPromise<Value>) {
|
||||
guard let objCPromise = objCPromise as? ObjCPromise<AnyObject> else { preconditionFailure() }
|
||||
self.objCPromise = objCPromise
|
||||
}
|
||||
|
||||
/// Creates a new pending promise.
|
||||
public static func pending() -> Promise<Value> {
|
||||
return Promise<Value>.init(ObjCPromise<AnyObject>.__pending())
|
||||
}
|
||||
|
||||
/// Creates a new promise rejected with the given `error`.
|
||||
public convenience init(_ error: Error) {
|
||||
self.init(ObjCPromise<AnyObject>.__resolved(with: error as NSError))
|
||||
}
|
||||
|
||||
/// Creates a new promise resolved with the result of `work` block.
|
||||
public convenience init(_ work: @autoclosure () throws -> Value) {
|
||||
do {
|
||||
let resolution = try work()
|
||||
switch resolution {
|
||||
case let error as NSError:
|
||||
self.init(error)
|
||||
case let objCPromise as ObjCPromise<AnyObject>:
|
||||
self.init(objCPromise)
|
||||
default:
|
||||
self.init(ObjCPromise<AnyObject>.__resolved(with: Promise<Value>.asAnyObject(resolution)))
|
||||
}
|
||||
} catch let error {
|
||||
self.init(error as NSError)
|
||||
}
|
||||
}
|
||||
|
||||
/// Resolves `self` with the given `resolution`.
|
||||
public func fulfill(_ resolution: Value) {
|
||||
objCPromise.__fulfill(Promise<Value>.asAnyObject(resolution))
|
||||
}
|
||||
|
||||
/// Rejects `self` with the given `error`.
|
||||
public func reject(_ error: Error) {
|
||||
objCPromise.__fulfill(error as NSError)
|
||||
}
|
||||
|
||||
/// Converts `self` into ObjC promise.
|
||||
public func asObjCPromise<Value>() -> ObjCPromise<Value> {
|
||||
guard let objCPromise = objCPromise as? ObjCPromise<Value> else { preconditionFailure() }
|
||||
return objCPromise
|
||||
}
|
||||
|
||||
// MARK: Internal
|
||||
|
||||
/// Underlying ObjC counterpart.
|
||||
let objCPromise: ObjCPromise<AnyObject>
|
||||
|
||||
var isPending: Bool { return objCPromise.__isPending }
|
||||
|
||||
var isFulfilled: Bool { return objCPromise.__isFulfilled }
|
||||
|
||||
var isRejected: Bool { return objCPromise.__isRejected }
|
||||
|
||||
var value: Value? {
|
||||
let objCValue = objCPromise.__value
|
||||
if Promise<AnyObject>.isBridgedNil(objCValue) { return nil }
|
||||
guard let value = objCValue as? Value else { preconditionFailure() }
|
||||
return value
|
||||
}
|
||||
|
||||
var error: Error? { return objCPromise.__error }
|
||||
|
||||
/// Converts generic `Value` to `AnyObject`.
|
||||
static func asAnyObject(_ value: Value) -> AnyObject? {
|
||||
return Promise<Value>.isBridgedNil(value) ? nil : value as AnyObject
|
||||
}
|
||||
|
||||
/// Converts `AnyObject` to generic `Value`.
|
||||
static func asValue(_ value: AnyObject?) -> Value? {
|
||||
// Swift nil becomes NSNull during bridging.
|
||||
return value as? Value ?? NSNull() as AnyObject as? Value
|
||||
}
|
||||
|
||||
// MARK: Private
|
||||
|
||||
/// Checks if generic `Value` is bridged ObjC `nil`.
|
||||
private static func isBridgedNil(_ value: Value?) -> Bool {
|
||||
// Swift nil becomes NSNull during bridging.
|
||||
return !(value is NSNull) && value as AnyObject is NSNull
|
||||
}
|
||||
}
|
||||
|
||||
extension Promise: CustomStringConvertible {
|
||||
public var description: String {
|
||||
return isFulfilled ? "Fulfilled: \(String(describing: value ?? nil))" :
|
||||
isRejected ? "Rejected: \(String(describing: error ?? nil))" : "Pending: \(Value.self)"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
// Copyright 2018 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at:
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import FBLPromises
|
||||
|
||||
/// Internal errors that `Promise` can throw.
|
||||
/// Indirectly conforms to `Swift.Error` through conformance to `Swift.CustomNSError` below.
|
||||
/// Not placing it under extension `Promise` for convenience to avoid collisions with `Swift.Error`.
|
||||
public enum PromiseError {
|
||||
case nsException(NSExceptionName, String?, [AnyHashable: Any]?, [NSNumber], [String])
|
||||
case timedOut
|
||||
case validationFailure
|
||||
}
|
||||
|
||||
/// Downcasting from `Swift.Error` and `NSException`.
|
||||
extension PromiseError {
|
||||
public init?(_ error: Error) {
|
||||
let error = error as NSError
|
||||
if error.domain != __FBLPromiseErrorDomain { return nil }
|
||||
switch error.code {
|
||||
case __FBLPromiseErrorCode.exception.rawValue:
|
||||
let errorUserInfo = error.userInfo
|
||||
guard let name = errorUserInfo[__FBLPromiseErrorUserInfoExceptionNameKey] as? NSExceptionName,
|
||||
let returnAddresses: [NSNumber] =
|
||||
errorUserInfo[__FBLPromiseErrorUserInfoExceptionReturnAddressesKey] as? [NSNumber],
|
||||
let callStack: [String] =
|
||||
errorUserInfo[__FBLPromiseErrorUserInfoExceptionCallStackKey] as? [String]
|
||||
else { return nil }
|
||||
let reason = errorUserInfo[__FBLPromiseErrorUserInfoExceptionReasonKey] as? String
|
||||
let userInfo =
|
||||
errorUserInfo[__FBLPromiseErrorUserInfoExceptionUserInfoKey] as? [AnyHashable: Any]
|
||||
self = .nsException(name, reason, userInfo, returnAddresses, callStack)
|
||||
case __FBLPromiseErrorCode.timedOut.rawValue:
|
||||
self = .timedOut
|
||||
case __FBLPromiseErrorCode.validationFailure.rawValue:
|
||||
self = .validationFailure
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
public init?(_ nsException: NSException) {
|
||||
self = .nsException(nsException.name,
|
||||
nsException.reason,
|
||||
nsException.userInfo,
|
||||
nsException.callStackReturnAddresses,
|
||||
nsException.callStackSymbols)
|
||||
}
|
||||
}
|
||||
|
||||
extension PromiseError: CustomNSError {
|
||||
public static var errorDomain: String {
|
||||
return __FBLPromiseErrorDomain
|
||||
}
|
||||
|
||||
public var errorCode: Int {
|
||||
switch self {
|
||||
case .nsException:
|
||||
return __FBLPromiseErrorCode.exception.rawValue
|
||||
case .timedOut:
|
||||
return __FBLPromiseErrorCode.timedOut.rawValue
|
||||
case .validationFailure:
|
||||
return __FBLPromiseErrorCode.validationFailure.rawValue
|
||||
}
|
||||
}
|
||||
|
||||
public var errorUserInfo: [String: Any] {
|
||||
if case let .nsException(name, reason, userInfo, returnAddresses, callStack) = self {
|
||||
return [
|
||||
__FBLPromiseErrorUserInfoExceptionNameKey: name,
|
||||
__FBLPromiseErrorUserInfoExceptionReasonKey: reason as Any,
|
||||
__FBLPromiseErrorUserInfoExceptionUserInfoKey: userInfo as Any,
|
||||
__FBLPromiseErrorUserInfoExceptionReturnAddressesKey: returnAddresses,
|
||||
__FBLPromiseErrorUserInfoExceptionCallStackKey: callStack
|
||||
]
|
||||
}
|
||||
return [String: Any]()
|
||||
}
|
||||
}
|
||||
|
||||
extension PromiseError: Equatable {
|
||||
public static func == (lhs: PromiseError, rhs: PromiseError) -> Bool {
|
||||
return (lhs as NSError).isEqual(rhs as NSError)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
// Copyright 2018 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at:
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import Foundation
|
||||
|
||||
/// Namespace for test helpers.
|
||||
public struct Test {
|
||||
|
||||
/// Executes `work` after a time `interval` on the main queue.
|
||||
public static func delay(_ interval: TimeInterval, work: @escaping () -> Void) {
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + interval) {
|
||||
work()
|
||||
}
|
||||
}
|
||||
|
||||
// Phony errors.
|
||||
public enum Error: Int, CustomNSError {
|
||||
case code13 = 13
|
||||
case code42 = 42
|
||||
|
||||
public static var errorDomain: String {
|
||||
return "com.google.Promises.Test.Error"
|
||||
}
|
||||
|
||||
public var errorCode: Int { return rawValue }
|
||||
|
||||
public var errorUserInfo: [String: Any] { return [:] }
|
||||
}
|
||||
}
|
||||
|
||||
/// Convenience `NSError` accessors for `Error` protocol.
|
||||
public extension Error {
|
||||
var domain: String { return (self as NSError).domain }
|
||||
var code: Int { return (self as NSError).code }
|
||||
var userInfo: [AnyHashable: Any] { return (self as NSError).userInfo }
|
||||
}
|
||||
|
||||
/// Compare two `Error`.
|
||||
public func == (lhs: Error?, rhs: Error?) -> Bool {
|
||||
switch (lhs, rhs) {
|
||||
case (nil, nil):
|
||||
return true
|
||||
case (nil, _?), (_?, nil):
|
||||
return false
|
||||
case let (lhs?, rhs?):
|
||||
return (lhs as NSError).isEqual(rhs as NSError)
|
||||
}
|
||||
}
|
||||
|
||||
/// Compare two arrays of the same generic type conforming to `Equatable` protocol.
|
||||
public func ==<T: Equatable>(lhs: [T?], rhs: [T?]) -> Bool {
|
||||
if lhs.count != rhs.count { return false }
|
||||
for (l, r) in zip(lhs, rhs) where l != r { return false }
|
||||
return true
|
||||
}
|
||||
|
||||
/// Compare two arrays of different primitive types.
|
||||
public func == (lhs: [Any?], rhs: [Any?]) -> Bool {
|
||||
if lhs.count != rhs.count { return false }
|
||||
for (l, r) in zip(lhs, rhs) {
|
||||
switch (l, r) {
|
||||
case (nil, nil):
|
||||
break
|
||||
case (let l as [Any?], let r as [Any?]):
|
||||
guard l == r else { return false }
|
||||
case (let l as Int, let r as Int):
|
||||
guard l == r else { return false }
|
||||
case (let l as Double, let r as Double):
|
||||
guard l == r else { return false }
|
||||
case (let l as String, let r as String):
|
||||
guard l == r else { return false }
|
||||
case (let l as Error, let r as Error):
|
||||
guard l == r else { return false }
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
// Copyright 2018 Google Inc. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at:
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import Foundation
|
||||
import Promises
|
||||
|
||||
@objc(FBLPromisesTestInteroperabilitySwift)
|
||||
public class Interoperability: NSObject {
|
||||
@objc
|
||||
public static func fulfill(
|
||||
_ object: Any?, delay: TimeInterval
|
||||
) -> Promise<Any?>.ObjCPromise<AnyObject> {
|
||||
return promise(object, error: nil, delay: delay).asObjCPromise()
|
||||
}
|
||||
|
||||
@objc
|
||||
public static func fulfill(
|
||||
number: NSNumber?, delay: TimeInterval
|
||||
) -> Promise<NSNumber?>.ObjCPromise<NSNumber> {
|
||||
return promise(number, error: nil, delay: delay).asObjCPromise()
|
||||
}
|
||||
|
||||
@objc
|
||||
public static func reject(
|
||||
_ error: Error, delay: TimeInterval
|
||||
) -> Promise<Any?>.ObjCPromise<AnyObject> {
|
||||
return (promise(nil, error: error, delay: delay) as Promise<Any?>).asObjCPromise()
|
||||
}
|
||||
|
||||
@objc
|
||||
public static func `throw`(
|
||||
_ error: Error, delay: TimeInterval
|
||||
) -> Promise<Any?>.ObjCPromise<AnyObject> {
|
||||
return (
|
||||
promise(nil, error: error, shouldThrow: true, delay: delay) as Promise<Any?>
|
||||
).asObjCPromise()
|
||||
}
|
||||
|
||||
// MARK: Internal
|
||||
|
||||
static func promise<T>(
|
||||
_ value: T, error: Error? = nil, shouldThrow: Bool = false, delay: TimeInterval = 0.0
|
||||
) -> Promise<T> {
|
||||
return Promise { fulfill, reject in
|
||||
if let error = error, shouldThrow {
|
||||
Thread.sleep(forTimeInterval: delay)
|
||||
throw error
|
||||
}
|
||||
Test.delay(delay) {
|
||||
if let error = error {
|
||||
reject(error)
|
||||
} else {
|
||||
fulfill(value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
Copyright 2018 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "FBLPromise+Catch.h"
|
||||
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
#import "FBLPromise+Testing.h"
|
||||
#import "FBLPromisesTestHelpers.h"
|
||||
#import "PromisesTestHelpers-Swift.h"
|
||||
|
||||
@interface FBLPromiseCatchInteroperabilityTests : XCTestCase
|
||||
@end
|
||||
|
||||
@implementation FBLPromiseCatchInteroperabilityTests
|
||||
|
||||
- (void)testPromiseReject {
|
||||
// Arrange.
|
||||
NSError *expectedError = [NSError errorWithDomain:FBLPromiseErrorDomain code:42 userInfo:nil];
|
||||
|
||||
// Act.
|
||||
FBLPromise *promise = [FBLPromisesTestInteroperabilitySwift
|
||||
reject:[NSError errorWithDomain:FBLPromiseErrorDomain code:42 userInfo:nil]
|
||||
delay:0.1];
|
||||
[promise catch:^(NSError *error) {
|
||||
XCTAssertEqual(error.code, 42);
|
||||
}];
|
||||
|
||||
// Assert.
|
||||
XCTAssert(FBLWaitForPromisesWithTimeout(10));
|
||||
XCTAssertEqualObjects(promise.error, expectedError);
|
||||
XCTAssertNil(promise.value);
|
||||
}
|
||||
|
||||
- (void)testPromiseThrow {
|
||||
// Arrange.
|
||||
NSError *expectedError = [NSError errorWithDomain:FBLPromiseErrorDomain code:42 userInfo:nil];
|
||||
|
||||
// Act.
|
||||
FBLPromise *promise = [FBLPromisesTestInteroperabilitySwift
|
||||
throw:[NSError errorWithDomain:FBLPromiseErrorDomain code:42 userInfo:nil]
|
||||
delay:0.1];
|
||||
[promise catch:^(NSError *error) {
|
||||
XCTAssertEqual(error.code, 42);
|
||||
}];
|
||||
|
||||
// Assert.
|
||||
XCTAssert(FBLWaitForPromisesWithTimeout(10));
|
||||
XCTAssertEqualObjects(promise.error, expectedError);
|
||||
XCTAssertNil(promise.value);
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
Copyright 2018 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "FBLPromise+Then.h"
|
||||
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
#import "FBLPromise+Testing.h"
|
||||
#import "FBLPromisesTestHelpers.h"
|
||||
#import "PromisesTestHelpers-Swift.h"
|
||||
|
||||
@interface FBLPromiseThenInteroperabilityTests : XCTestCase
|
||||
@end
|
||||
|
||||
@implementation FBLPromiseThenInteroperabilityTests
|
||||
|
||||
- (void)testPromiseFulfillNumberNil {
|
||||
// Act.
|
||||
FBLPromise<NSNumber *> *promise =
|
||||
[FBLPromisesTestInteroperabilitySwift fulfillWithNumber:nil delay:0.1];
|
||||
[promise then:^id(NSNumber *value) {
|
||||
XCTAssertNil(value);
|
||||
return value;
|
||||
}];
|
||||
|
||||
// Assert.
|
||||
XCTAssert(FBLWaitForPromisesWithTimeout(10));
|
||||
XCTAssertNil(promise.value);
|
||||
XCTAssertNil(promise.error);
|
||||
}
|
||||
|
||||
- (void)testPromiseFulfillNumberNonNil {
|
||||
// Act.
|
||||
FBLPromise<NSNumber *> *promise =
|
||||
[FBLPromisesTestInteroperabilitySwift fulfillWithNumber:@42 delay:0.1];
|
||||
[promise then:^id(NSNumber *value) {
|
||||
XCTAssertEqualObjects(value, @42);
|
||||
return value;
|
||||
}];
|
||||
|
||||
// Assert.
|
||||
XCTAssert(FBLWaitForPromisesWithTimeout(10));
|
||||
XCTAssertEqualObjects(promise.value, @42);
|
||||
XCTAssertNil(promise.error);
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,300 @@
|
||||
/**
|
||||
Copyright 2018 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "FBLPromise+Then.h"
|
||||
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
#import "FBLPromisesTestHelpers.h"
|
||||
|
||||
static size_t const FBLPromisePerformanceTestIterationCount = 10000;
|
||||
|
||||
NS_INLINE void FBLLogAverageTime(uint64_t time) {
|
||||
NSLog(@"Average time: %.10lf", (double)time / NSEC_PER_SEC);
|
||||
}
|
||||
|
||||
NS_INLINE void FBLLogTotalTime(NSTimeInterval time) {
|
||||
NSLog(@"Total time: %.10lf", time);
|
||||
}
|
||||
|
||||
@interface FBLPromiseThenPerformanceTests : XCTestCase
|
||||
@end
|
||||
|
||||
@implementation FBLPromiseThenPerformanceTests
|
||||
|
||||
#pragma mark GCD
|
||||
|
||||
/**
|
||||
Measures the average time needed to get into a dispatch_async block.
|
||||
*/
|
||||
- (void)testDispatchAsyncOnSerialQueue {
|
||||
// Arrange.
|
||||
XCTestExpectation *expectation = [self expectationWithDescription:@""];
|
||||
expectation.expectedFulfillmentCount = FBLPromisePerformanceTestIterationCount;
|
||||
dispatch_queue_t queue = dispatch_queue_create(
|
||||
__FUNCTION__,
|
||||
dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_USER_INITIATED, 0));
|
||||
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
|
||||
|
||||
// Act.
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
uint64_t time = dispatch_benchmark(FBLPromisePerformanceTestIterationCount, ^{
|
||||
dispatch_async(queue, ^{
|
||||
dispatch_semaphore_signal(semaphore);
|
||||
[expectation fulfill];
|
||||
});
|
||||
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
|
||||
});
|
||||
FBLLogAverageTime(time);
|
||||
});
|
||||
|
||||
// Assert.
|
||||
[self waitForExpectationsWithTimeout:10 handler:nil];
|
||||
}
|
||||
|
||||
/**
|
||||
Measures the average time needed to get into a doubly nested dispatch_async block.
|
||||
*/
|
||||
- (void)testDoubleDispatchAsyncOnSerialQueue {
|
||||
// Arrange.
|
||||
XCTestExpectation *expectation = [self expectationWithDescription:@""];
|
||||
expectation.expectedFulfillmentCount = FBLPromisePerformanceTestIterationCount;
|
||||
dispatch_queue_t queue = dispatch_queue_create(
|
||||
__FUNCTION__,
|
||||
dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_USER_INITIATED, 0));
|
||||
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
|
||||
|
||||
// Act.
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
uint64_t time = dispatch_benchmark(FBLPromisePerformanceTestIterationCount, ^{
|
||||
dispatch_async(queue, ^{
|
||||
dispatch_async(queue, ^{
|
||||
dispatch_semaphore_signal(semaphore);
|
||||
[expectation fulfill];
|
||||
});
|
||||
});
|
||||
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
|
||||
});
|
||||
FBLLogAverageTime(time);
|
||||
});
|
||||
|
||||
// Assert.
|
||||
[self waitForExpectationsWithTimeout:10 handler:nil];
|
||||
}
|
||||
|
||||
/**
|
||||
Measures the average time needed to get into a triply nested dispatch_async block.
|
||||
*/
|
||||
- (void)testTripleDispatchAsyncOnSerialQueue {
|
||||
// Arrange.
|
||||
XCTestExpectation *expectation = [self expectationWithDescription:@""];
|
||||
expectation.expectedFulfillmentCount = FBLPromisePerformanceTestIterationCount;
|
||||
dispatch_queue_t queue = dispatch_queue_create(
|
||||
__FUNCTION__,
|
||||
dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_USER_INITIATED, 0));
|
||||
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
|
||||
|
||||
// Act.
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
uint64_t time = dispatch_benchmark(FBLPromisePerformanceTestIterationCount, ^{
|
||||
dispatch_async(queue, ^{
|
||||
dispatch_async(queue, ^{
|
||||
dispatch_async(queue, ^{
|
||||
dispatch_semaphore_signal(semaphore);
|
||||
[expectation fulfill];
|
||||
});
|
||||
});
|
||||
});
|
||||
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
|
||||
});
|
||||
FBLLogAverageTime(time);
|
||||
});
|
||||
|
||||
// Assert.
|
||||
[self waitForExpectationsWithTimeout:10 handler:nil];
|
||||
}
|
||||
|
||||
/**
|
||||
Measures the total time needed to perform a lot of dispatch_async blocks on a concurrent queue.
|
||||
*/
|
||||
- (void)testDispatchAsyncOnConcurrentQueue {
|
||||
// Arrange.
|
||||
dispatch_queue_t queue = dispatch_queue_create(
|
||||
__FUNCTION__, dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_CONCURRENT,
|
||||
QOS_CLASS_USER_INITIATED, 0));
|
||||
dispatch_group_t group = dispatch_group_create();
|
||||
NSMutableArray<dispatch_block_t> *blocks =
|
||||
[NSMutableArray arrayWithCapacity:FBLPromisePerformanceTestIterationCount];
|
||||
for (NSUInteger i = 0; i < FBLPromisePerformanceTestIterationCount; ++i) {
|
||||
dispatch_group_enter(group);
|
||||
void (^block)() = ^{
|
||||
dispatch_group_leave(group);
|
||||
};
|
||||
[blocks addObject:block];
|
||||
}
|
||||
NSDate *startDate = [NSDate date];
|
||||
|
||||
// Act.
|
||||
for (NSUInteger i = 0; i < FBLPromisePerformanceTestIterationCount; ++i) {
|
||||
dispatch_async(queue, blocks[i]);
|
||||
}
|
||||
|
||||
// Assert.
|
||||
XCTAssert(dispatch_group_wait(group, dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC)) == 0,
|
||||
@"Asynchronous wait failed: Exceeded timeout of 1 second.");
|
||||
NSDate *endDate = [NSDate date];
|
||||
FBLLogTotalTime([endDate timeIntervalSinceDate:startDate]);
|
||||
}
|
||||
|
||||
#pragma mark FBLPromises
|
||||
|
||||
/**
|
||||
Measures the average time needed to create a resolved FBLPromise and get into a `then` block
|
||||
chained to it.
|
||||
*/
|
||||
- (void)testThenOnSerialQueue {
|
||||
// Arrange.
|
||||
XCTestExpectation *expectation = [self expectationWithDescription:@""];
|
||||
expectation.expectedFulfillmentCount = FBLPromisePerformanceTestIterationCount;
|
||||
dispatch_queue_t queue = dispatch_queue_create(
|
||||
__FUNCTION__,
|
||||
dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_USER_INITIATED, 0));
|
||||
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
|
||||
|
||||
// Act.
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
uint64_t time = dispatch_benchmark(FBLPromisePerformanceTestIterationCount, ^{
|
||||
[[FBLPromise resolvedWith:@YES] onQueue:queue
|
||||
then:^id(id result) {
|
||||
dispatch_semaphore_signal(semaphore);
|
||||
[expectation fulfill];
|
||||
return result;
|
||||
}];
|
||||
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
|
||||
});
|
||||
FBLLogAverageTime(time);
|
||||
});
|
||||
|
||||
// Assert.
|
||||
[self waitForExpectationsWithTimeout:10 handler:nil];
|
||||
}
|
||||
|
||||
/**
|
||||
Measures the average time needed to create a resolved FBLPromise, chain two `then` blocks on it
|
||||
and get into the last `then` block.
|
||||
*/
|
||||
- (void)testDoubleThenOnSerialQueue {
|
||||
// Arrange.
|
||||
XCTestExpectation *expectation = [self expectationWithDescription:@""];
|
||||
expectation.expectedFulfillmentCount = FBLPromisePerformanceTestIterationCount;
|
||||
dispatch_queue_t queue = dispatch_queue_create(
|
||||
__FUNCTION__,
|
||||
dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_USER_INITIATED, 0));
|
||||
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
|
||||
|
||||
// Act.
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
uint64_t time = dispatch_benchmark(FBLPromisePerformanceTestIterationCount, ^{
|
||||
[[[FBLPromise resolvedWith:@YES] onQueue:queue
|
||||
then:^id(id result) {
|
||||
return result;
|
||||
}] onQueue:queue
|
||||
then:^id(id result) {
|
||||
dispatch_semaphore_signal(semaphore);
|
||||
[expectation fulfill];
|
||||
return result;
|
||||
}];
|
||||
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
|
||||
});
|
||||
FBLLogAverageTime(time);
|
||||
});
|
||||
|
||||
// Assert.
|
||||
[self waitForExpectationsWithTimeout:10 handler:nil];
|
||||
}
|
||||
|
||||
/**
|
||||
Measures the average time needed to create a resolved FBLPromise, chain three `then` blocks on it
|
||||
and get into the last `then` block.
|
||||
*/
|
||||
- (void)testTripleThenOnSerialQueue {
|
||||
// Arrange.
|
||||
XCTestExpectation *expectation = [self expectationWithDescription:@""];
|
||||
expectation.expectedFulfillmentCount = FBLPromisePerformanceTestIterationCount;
|
||||
dispatch_queue_t queue = dispatch_queue_create(
|
||||
__FUNCTION__,
|
||||
dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_USER_INITIATED, 0));
|
||||
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
|
||||
|
||||
// Act.
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
uint64_t time = dispatch_benchmark(FBLPromisePerformanceTestIterationCount, ^{
|
||||
[[[[FBLPromise resolvedWith:@YES] onQueue:queue
|
||||
then:^id(id result) {
|
||||
return result;
|
||||
}] onQueue:queue
|
||||
then:^id(id result) {
|
||||
return result;
|
||||
}] onQueue:queue
|
||||
then:^id(id result) {
|
||||
dispatch_semaphore_signal(semaphore);
|
||||
[expectation fulfill];
|
||||
return result;
|
||||
}];
|
||||
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
|
||||
});
|
||||
FBLLogAverageTime(time);
|
||||
});
|
||||
|
||||
// Assert.
|
||||
[self waitForExpectationsWithTimeout:10 handler:nil];
|
||||
}
|
||||
|
||||
/**
|
||||
Measures the total time needed to resolve a lot of pending FBLPromise with chained `then` blocks
|
||||
on them on a concurrent queue and wait for each of them to get into chained block.
|
||||
*/
|
||||
- (void)testThenOnConcurrentQueue {
|
||||
// Arrange.
|
||||
dispatch_queue_t queue = dispatch_queue_create(
|
||||
__FUNCTION__, dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_CONCURRENT,
|
||||
QOS_CLASS_USER_INITIATED, 0));
|
||||
dispatch_group_t group = dispatch_group_create();
|
||||
NSMutableArray<FBLPromise *> *promises =
|
||||
[NSMutableArray arrayWithCapacity:FBLPromisePerformanceTestIterationCount];
|
||||
for (NSUInteger i = 0; i < FBLPromisePerformanceTestIterationCount; ++i) {
|
||||
dispatch_group_enter(group);
|
||||
FBLPromise *promise = [FBLPromise pendingPromise];
|
||||
[promise onQueue:queue
|
||||
then:^id(id result) {
|
||||
dispatch_group_leave(group);
|
||||
return result;
|
||||
}];
|
||||
[promises addObject:promise];
|
||||
}
|
||||
NSDate *startDate = [NSDate date];
|
||||
|
||||
// Act.
|
||||
[promises makeObjectsPerformSelector:@selector(fulfill:) withObject:@YES];
|
||||
|
||||
// Assert.
|
||||
XCTAssert(dispatch_group_wait(group, dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC)) == 0,
|
||||
@"Asynchronous wait failed: Exceeded timeout of 1 second.");
|
||||
NSDate *endDate = [NSDate date];
|
||||
FBLLogTotalTime([endDate timeIntervalSinceDate:startDate]);
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,232 @@
|
||||
/**
|
||||
Copyright 2018 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "FBLPromise+All.h"
|
||||
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
#import "FBLPromise+Async.h"
|
||||
#import "FBLPromise+Catch.h"
|
||||
#import "FBLPromise+Testing.h"
|
||||
#import "FBLPromise+Then.h"
|
||||
#import "FBLPromisesTestHelpers.h"
|
||||
|
||||
@interface FBLPromiseAllTests : XCTestCase
|
||||
@end
|
||||
|
||||
@implementation FBLPromiseAllTests
|
||||
|
||||
- (void)testPromiseAll {
|
||||
// Arrange.
|
||||
NSArray *expectedValues = @[ @42, @"hello world", @[ @42 ], [NSNull null] ];
|
||||
FBLPromise<NSNumber *> *promise1 =
|
||||
[FBLPromise async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock __unused _) {
|
||||
FBLDelay(0.1, ^{
|
||||
fulfill(@42);
|
||||
});
|
||||
}];
|
||||
FBLPromise<NSString *> *promise2 =
|
||||
[FBLPromise async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock __unused _) {
|
||||
FBLDelay(1, ^{
|
||||
fulfill(@"hello world");
|
||||
});
|
||||
}];
|
||||
FBLPromise<NSArray<NSNumber *> *> *promise3 =
|
||||
[FBLPromise async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock __unused _) {
|
||||
FBLDelay(2, ^{
|
||||
fulfill(@[ @42 ]);
|
||||
});
|
||||
}];
|
||||
FBLPromise *promise4 =
|
||||
[FBLPromise async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock __unused _) {
|
||||
FBLDelay(3, ^{
|
||||
fulfill(nil);
|
||||
});
|
||||
}];
|
||||
|
||||
// Act.
|
||||
FBLPromise<NSArray *> *combinedPromise =
|
||||
[[FBLPromise all:@[ promise1, promise2, promise3, promise4 ]] then:^id(NSArray *value) {
|
||||
XCTAssertEqualObjects(value, expectedValues);
|
||||
return value;
|
||||
}];
|
||||
|
||||
// Assert.
|
||||
XCTAssert(FBLWaitForPromisesWithTimeout(10));
|
||||
XCTAssertEqualObjects(combinedPromise.value, expectedValues);
|
||||
XCTAssertNil(combinedPromise.error);
|
||||
}
|
||||
|
||||
- (void)testPromiseAllEmpty {
|
||||
// Act.
|
||||
FBLPromise<NSArray *> *promise = [[FBLPromise all:@[]] then:^id(NSArray *value) {
|
||||
XCTAssertEqualObjects(value, @[]);
|
||||
return value;
|
||||
}];
|
||||
|
||||
// Assert.
|
||||
XCTAssert(FBLWaitForPromisesWithTimeout(10));
|
||||
XCTAssertEqualObjects(promise.value, @[]);
|
||||
XCTAssertNil(promise.error);
|
||||
}
|
||||
|
||||
- (void)testPromiseAllRejectFirst {
|
||||
// Arrange.
|
||||
FBLPromise<NSNumber *> *promise1 =
|
||||
[FBLPromise async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock __unused _) {
|
||||
FBLDelay(1, ^{
|
||||
fulfill(@42);
|
||||
});
|
||||
}];
|
||||
FBLPromise<NSString *> *promise2 =
|
||||
[FBLPromise async:^(FBLPromiseFulfillBlock __unused _, FBLPromiseRejectBlock reject) {
|
||||
FBLDelay(0.1, ^{
|
||||
reject([NSError errorWithDomain:FBLPromiseErrorDomain code:42 userInfo:nil]);
|
||||
});
|
||||
}];
|
||||
|
||||
// Act.
|
||||
FBLPromise<NSArray *> *combinedPromise =
|
||||
[[[FBLPromise all:@[ promise1, promise2 ]] then:^id(id __unused _) {
|
||||
XCTFail();
|
||||
return nil;
|
||||
}] catch:^(NSError *error) {
|
||||
XCTAssertEqual(error.code, 42);
|
||||
}];
|
||||
|
||||
// Assert.
|
||||
XCTAssert(FBLWaitForPromisesWithTimeout(10));
|
||||
XCTAssertEqual(combinedPromise.error.code, 42);
|
||||
XCTAssertNil(combinedPromise.value);
|
||||
}
|
||||
|
||||
- (void)testPromiseAllRejectLast {
|
||||
// Arrange.
|
||||
FBLPromise<NSNumber *> *promise1 =
|
||||
[FBLPromise async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock __unused _) {
|
||||
FBLDelay(0.1, ^{
|
||||
fulfill(@42);
|
||||
});
|
||||
}];
|
||||
FBLPromise<NSString *> *promise2 =
|
||||
[FBLPromise async:^(FBLPromiseFulfillBlock __unused _, FBLPromiseRejectBlock reject) {
|
||||
FBLDelay(1, ^{
|
||||
reject([NSError errorWithDomain:FBLPromiseErrorDomain code:42 userInfo:nil]);
|
||||
});
|
||||
}];
|
||||
|
||||
// Act.
|
||||
FBLPromise<NSArray *> *combinedPromise =
|
||||
[[[FBLPromise all:@[ promise1, promise2 ]] then:^id(id __unused _) {
|
||||
XCTFail();
|
||||
return nil;
|
||||
}] catch:^(NSError *error) {
|
||||
XCTAssertEqual(error.code, 42);
|
||||
}];
|
||||
|
||||
// Assert.
|
||||
XCTAssert(FBLWaitForPromisesWithTimeout(10));
|
||||
XCTAssertEqual(combinedPromise.error.code, 42);
|
||||
XCTAssertNil(combinedPromise.value);
|
||||
}
|
||||
|
||||
- (void)testPromiseAllWithValues {
|
||||
// Arrange.
|
||||
NSArray *expectedValues = @[ @42, @"hello world", @[ @42 ], [NSNull null] ];
|
||||
FBLPromise<NSArray<NSNumber *> *> *promise1 =
|
||||
[FBLPromise async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock __unused _) {
|
||||
FBLDelay(0.1, ^{
|
||||
fulfill(@[ @42 ]);
|
||||
});
|
||||
}];
|
||||
FBLPromise *promise2 =
|
||||
[FBLPromise async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock __unused _) {
|
||||
FBLDelay(1, ^{
|
||||
fulfill(nil);
|
||||
});
|
||||
}];
|
||||
|
||||
// Act.
|
||||
FBLPromise<NSArray *> *combinedPromise =
|
||||
[[FBLPromise all:@[ @42, @"hello world", promise1, promise2 ]] then:^id(NSArray *value) {
|
||||
XCTAssertEqualObjects(value, expectedValues);
|
||||
return value;
|
||||
}];
|
||||
|
||||
// Assert.
|
||||
XCTAssert(FBLWaitForPromisesWithTimeout(10));
|
||||
XCTAssertEqualObjects(combinedPromise.value, expectedValues);
|
||||
XCTAssertNil(combinedPromise.error);
|
||||
}
|
||||
|
||||
- (void)testPromiseAllWithError {
|
||||
// Arrange.
|
||||
NSError *error = [NSError errorWithDomain:FBLPromiseErrorDomain code:42 userInfo:nil];
|
||||
FBLPromise<NSArray<NSNumber *> *> *promise =
|
||||
[FBLPromise async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock __unused _) {
|
||||
FBLDelay(0.1, ^{
|
||||
fulfill(@[ @42 ]);
|
||||
});
|
||||
}];
|
||||
|
||||
// Act.
|
||||
FBLPromise<NSArray *> *combinedPromise =
|
||||
[[[FBLPromise all:@[ @42, error, promise ]] then:^id(id __unused _) {
|
||||
XCTFail();
|
||||
return nil;
|
||||
}] catch:^(NSError *error) {
|
||||
XCTAssertEqual(error.code, 42);
|
||||
}];
|
||||
|
||||
// Assert.
|
||||
XCTAssert(FBLWaitForPromisesWithTimeout(10));
|
||||
XCTAssertEqual(combinedPromise.error.code, 42);
|
||||
XCTAssertNil(combinedPromise.value);
|
||||
}
|
||||
|
||||
/**
|
||||
Promise created with `all` should not deallocate until it gets resolved.
|
||||
*/
|
||||
- (void)testPromiseAllNoDeallocUntilResolved {
|
||||
// Arrange.
|
||||
FBLPromise *promise = [FBLPromise pendingPromise];
|
||||
FBLPromise __weak *weakExtendedPromise1;
|
||||
FBLPromise __weak *weakExtendedPromise2;
|
||||
|
||||
// Act.
|
||||
@autoreleasepool {
|
||||
XCTAssertNil(weakExtendedPromise1);
|
||||
XCTAssertNil(weakExtendedPromise2);
|
||||
FBLPromise *extendedPromise1 = [FBLPromise all:@[ promise ]];
|
||||
FBLPromise *extendedPromise2 = [FBLPromise all:@[ promise ]];
|
||||
weakExtendedPromise1 = extendedPromise1;
|
||||
weakExtendedPromise2 = extendedPromise2;
|
||||
XCTAssertNotNil(weakExtendedPromise1);
|
||||
XCTAssertNotNil(weakExtendedPromise2);
|
||||
}
|
||||
|
||||
// Assert.
|
||||
XCTAssertNotNil(weakExtendedPromise1);
|
||||
XCTAssertNotNil(weakExtendedPromise2);
|
||||
|
||||
[promise fulfill:@42];
|
||||
XCTAssert(FBLWaitForPromisesWithTimeout(10));
|
||||
|
||||
XCTAssertNil(weakExtendedPromise1);
|
||||
XCTAssertNil(weakExtendedPromise2);
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,119 @@
|
||||
/**
|
||||
Copyright 2018 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "FBLPromise+Always.h"
|
||||
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
#import "FBLPromise+Async.h"
|
||||
#import "FBLPromise+Catch.h"
|
||||
#import "FBLPromise+Testing.h"
|
||||
#import "FBLPromise+Then.h"
|
||||
#import "FBLPromisesTestHelpers.h"
|
||||
|
||||
@interface FBLPromiseAlwaysTests : XCTestCase
|
||||
@end
|
||||
|
||||
@implementation FBLPromiseAlwaysTests
|
||||
|
||||
- (void)testPromiseAlwaysOnFulfilled {
|
||||
// Arrange.
|
||||
NSUInteger __block count = 0;
|
||||
NSUInteger const expectedCount = 3;
|
||||
|
||||
// Act.
|
||||
FBLPromise<NSNumber *> *promise =
|
||||
[[[[FBLPromise async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock __unused _) {
|
||||
FBLDelay(0.1, ^{
|
||||
fulfill(@42);
|
||||
});
|
||||
}] always:^{
|
||||
++count;
|
||||
}] then:^id(NSNumber *value) {
|
||||
XCTAssertEqualObjects(value, @42);
|
||||
++count;
|
||||
return value;
|
||||
}] always:^{
|
||||
++count;
|
||||
}];
|
||||
|
||||
// Assert.
|
||||
XCTAssert(FBLWaitForPromisesWithTimeout(10));
|
||||
XCTAssertEqual(count, expectedCount);
|
||||
XCTAssertEqualObjects(promise.value, @42);
|
||||
XCTAssertNil(promise.error);
|
||||
}
|
||||
|
||||
- (void)testPromiseAlwaysOnRejected {
|
||||
// Arrange.
|
||||
NSUInteger __block count = 0;
|
||||
NSUInteger const expectedCount = 3;
|
||||
|
||||
// Act.
|
||||
FBLPromise<NSNumber *> *promise =
|
||||
[[[[FBLPromise async:^(FBLPromiseFulfillBlock __unused _, FBLPromiseRejectBlock reject) {
|
||||
FBLDelay(0.1, ^{
|
||||
reject([NSError errorWithDomain:FBLPromiseErrorDomain code:42 userInfo:nil]);
|
||||
});
|
||||
}] always:^{
|
||||
++count;
|
||||
}] catch:^(NSError *error) {
|
||||
XCTAssertEqual(error.code, 42);
|
||||
++count;
|
||||
}] always:^{
|
||||
++count;
|
||||
}];
|
||||
|
||||
// Assert.
|
||||
XCTAssert(FBLWaitForPromisesWithTimeout(10));
|
||||
XCTAssertEqual(count, expectedCount);
|
||||
XCTAssertEqual(promise.error.code, 42);
|
||||
XCTAssertNil(promise.value);
|
||||
}
|
||||
|
||||
/**
|
||||
Promise created with `always` should not deallocate until it gets resolved.
|
||||
*/
|
||||
- (void)testPromiseAlwaysNoDeallocUntilResolved {
|
||||
// Arrange.
|
||||
FBLPromise *promise = [FBLPromise pendingPromise];
|
||||
FBLPromise __weak *weakExtendedPromise1;
|
||||
FBLPromise __weak *weakExtendedPromise2;
|
||||
|
||||
// Act.
|
||||
@autoreleasepool {
|
||||
XCTAssertNil(weakExtendedPromise1);
|
||||
XCTAssertNil(weakExtendedPromise2);
|
||||
FBLPromise *extendedPromise1 = [promise always:^{}];
|
||||
FBLPromise *extendedPromise2 = [promise always:^{}];
|
||||
weakExtendedPromise1 = extendedPromise1;
|
||||
weakExtendedPromise2 = extendedPromise2;
|
||||
XCTAssertNotNil(weakExtendedPromise1);
|
||||
XCTAssertNotNil(weakExtendedPromise2);
|
||||
}
|
||||
|
||||
// Assert.
|
||||
XCTAssertNotNil(weakExtendedPromise1);
|
||||
XCTAssertNotNil(weakExtendedPromise2);
|
||||
|
||||
[promise fulfill:@42];
|
||||
XCTAssert(FBLWaitForPromisesWithTimeout(10));
|
||||
|
||||
XCTAssertNil(weakExtendedPromise1);
|
||||
XCTAssertNil(weakExtendedPromise2);
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,229 @@
|
||||
/**
|
||||
Copyright 2018 Google Inc. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
#import "FBLPromise+Any.h"
|
||||
|
||||
#import <XCTest/XCTest.h>
|
||||
|
||||
#import "FBLPromise+Async.h"
|
||||
#import "FBLPromise+Catch.h"
|
||||
#import "FBLPromise+Testing.h"
|
||||
#import "FBLPromise+Then.h"
|
||||
#import "FBLPromisesTestHelpers.h"
|
||||
|
||||
@interface FBLPromiseAnyTests : XCTestCase
|
||||
@end
|
||||
|
||||
@implementation FBLPromiseAnyTests
|
||||
|
||||
- (void)testPromiseAny {
|
||||
// Arrange.
|
||||
FBLPromise<NSNumber *> *promise1 =
|
||||
[FBLPromise async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock __unused _) {
|
||||
FBLDelay(0.1, ^{
|
||||
fulfill(@42);
|
||||
});
|
||||
}];
|
||||
FBLPromise<NSString *> *promise2 =
|
||||
[FBLPromise async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock __unused _) {
|
||||
FBLDelay(1, ^{
|
||||
fulfill(@"hello world");
|
||||
});
|
||||
}];
|
||||
FBLPromise<NSArray<NSNumber *> *> *promise3 =
|
||||
[FBLPromise async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock __unused _) {
|
||||
FBLDelay(2, ^{
|
||||
fulfill(@[ @42 ]);
|
||||
});
|
||||
}];
|
||||
FBLPromise *promise4 =
|
||||
[FBLPromise async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock __unused _) {
|
||||
FBLDelay(3, ^{
|
||||
fulfill(nil);
|
||||
});
|
||||
}];
|
||||
|
||||
// Act.
|
||||
FBLPromise *fastestPromise =
|
||||
[[FBLPromise any:@[ promise1, promise2, promise3, promise4 ]] then:^id(NSNumber *value) {
|
||||
XCTAssertEqualObjects(value, @42);
|
||||
return value;
|
||||
}];
|
||||
|
||||
// Assert.
|
||||
XCTAssert(FBLWaitForPromisesWithTimeout(10));
|
||||
XCTAssertEqualObjects(fastestPromise.value, @42);
|
||||
XCTAssertNil(fastestPromise.error);
|
||||
}
|
||||
|
||||
- (void)testPromiseAnyRejectFirst {
|
||||
// Arrange.
|
||||
FBLPromise<NSNumber *> *promise1 =
|
||||
[FBLPromise async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock __unused _) {
|
||||
FBLDelay(1, ^{
|
||||
fulfill(@42);
|
||||
});
|
||||
}];
|
||||
FBLPromise<NSString *> *promise2 =
|
||||
[FBLPromise async:^(FBLPromiseFulfillBlock __unused _, FBLPromiseRejectBlock reject) {
|
||||
FBLDelay(0.1, ^{
|
||||
reject([NSError errorWithDomain:FBLPromiseErrorDomain code:42 userInfo:nil]);
|
||||
});
|
||||
}];
|
||||
|
||||
// Act.
|
||||
FBLPromise *fastestPromise = [[[FBLPromise any:@[ promise1, promise2 ]] then:^id(id __unused _) {
|
||||
XCTFail();
|
||||
return nil;
|
||||
}] catch:^(NSError *error) {
|
||||
XCTAssertEqual(error.code, 42);
|
||||
}];
|
||||
|
||||
// Assert.
|
||||
XCTAssert(FBLWaitForPromisesWithTimeout(10));
|
||||
XCTAssertEqual(fastestPromise.error.code, 42);
|
||||
XCTAssertNil(fastestPromise.value);
|
||||
}
|
||||
|
||||
- (void)testPromiseAnyRejectLast {
|
||||
// Arrange.
|
||||
FBLPromise<NSNumber *> *promise1 =
|
||||
[FBLPromise async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock __unused _) {
|
||||
FBLDelay(0.1, ^{
|
||||
fulfill(@42);
|
||||
});
|
||||
}];
|
||||
FBLPromise<NSString *> *promise2 =
|
||||
[FBLPromise async:^(FBLPromiseFulfillBlock __unused _, FBLPromiseRejectBlock reject) {
|
||||
FBLDelay(1, ^{
|
||||
reject([NSError errorWithDomain:FBLPromiseErrorDomain code:42 userInfo:nil]);
|
||||
});
|
||||
}];
|
||||
|
||||
// Act.
|
||||
FBLPromise *fastestPromise = [[FBLPromise any:@[ promise1, promise2 ]] then:^id(NSNumber *value) {
|
||||
XCTAssertEqualObjects(value, @42);
|
||||
return value;
|
||||
}];
|
||||
|
||||
// Assert.
|
||||
XCTAssert(FBLWaitForPromisesWithTimeout(10));
|
||||
XCTAssertEqualObjects(fastestPromise.value, @42);
|
||||
XCTAssertNil(fastestPromise.error);
|
||||
}
|
||||
|
||||
- (void)testPromiseAnyWithValues {
|
||||
// Arrange.
|
||||
FBLPromise<NSArray<NSNumber *> *> *promise =
|
||||
[FBLPromise async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock __unused _) {
|
||||
FBLDelay(0.1, ^{
|
||||
fulfill(@[ @42 ]);
|
||||
});
|
||||
}];
|
||||
|
||||
// Act.
|
||||
FBLPromise *fastestPromise =
|
||||
[[FBLPromise any:@[ @42, @"hello world", promise ]] then:^id(NSNumber *value) {
|
||||
XCTAssertEqualObjects(value, @42);
|
||||
return value;
|
||||
}];
|
||||
|
||||
// Assert.
|
||||
XCTAssert(FBLWaitForPromisesWithTimeout(10));
|
||||
XCTAssertEqualObjects(fastestPromise.value, @42);
|
||||
XCTAssertNil(fastestPromise.error);
|
||||
}
|
||||
|
||||
- (void)testPromiseAnyWithErrorFirst {
|
||||
// Arrange.
|
||||
NSError *error = [NSError errorWithDomain:FBLPromiseErrorDomain code:42 userInfo:nil];
|
||||
FBLPromise<NSArray<NSNumber *> *> *promise =
|
||||
[FBLPromise async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock __unused _) {
|
||||
FBLDelay(0.1, ^{
|
||||
fulfill(@[ @42 ]);
|
||||
});
|
||||
}];
|
||||
|
||||
// Act.
|
||||
FBLPromise *fastestPromise = [[[FBLPromise any:@[ promise, error, @42 ]] then:^id(id __unused _) {
|
||||
XCTFail();
|
||||
return nil;
|
||||
}] catch:^(NSError *error) {
|
||||
XCTAssertEqual(error.code, 42);
|
||||
}];
|
||||
|
||||
// Assert.
|
||||
XCTAssert(FBLWaitForPromisesWithTimeout(10));
|
||||
XCTAssertEqual(fastestPromise.error.code, 42);
|
||||
XCTAssertNil(fastestPromise.value);
|
||||
}
|
||||
|
||||
- (void)testPromiseAnyWithErrorLast {
|
||||
// Arrange.
|
||||
NSError *error = [NSError errorWithDomain:FBLPromiseErrorDomain code:42 userInfo:nil];
|
||||
FBLPromise<NSArray<NSNumber *> *> *promise =
|
||||
[FBLPromise async:^(FBLPromiseFulfillBlock fulfill, FBLPromiseRejectBlock __unused _) {
|
||||
FBLDelay(0.1, ^{
|
||||
fulfill(@[ @42 ]);
|
||||
});
|
||||
}];
|
||||
|
||||
// Act.
|
||||
FBLPromise *fastestPromise =
|
||||
[[FBLPromise any:@[ promise, @42, error ]] then:^id(NSNumber *value) {
|
||||
XCTAssertEqualObjects(value, @42);
|
||||
return value;
|
||||
}];
|
||||
|
||||
// Assert.
|
||||
XCTAssert(FBLWaitForPromisesWithTimeout(10));
|
||||
XCTAssertEqualObjects(fastestPromise.value, @42);
|
||||
XCTAssertNil(fastestPromise.error);
|
||||
}
|
||||
|
||||
/**
|
||||
Promise created with `any` should not deallocate until it gets resolved.
|
||||
*/
|
||||
- (void)testPromiseAnyNoDeallocUntilResolved {
|
||||
// Arrange.
|
||||
FBLPromise *promise = [FBLPromise pendingPromise];
|
||||
FBLPromise __weak *weakExtendedPromise1;
|
||||
FBLPromise __weak *weakExtendedPromise2;
|
||||
|
||||
// Act.
|
||||
@autoreleasepool {
|
||||
XCTAssertNil(weakExtendedPromise1);
|
||||
XCTAssertNil(weakExtendedPromise2);
|
||||
FBLPromise *extendedPromise1 = [FBLPromise any:@[ promise ]];
|
||||
FBLPromise *extendedPromise2 = [FBLPromise any:@[ promise ]];
|
||||
weakExtendedPromise1 = extendedPromise1;
|
||||
weakExtendedPromise2 = extendedPromise2;
|
||||
XCTAssertNotNil(weakExtendedPromise1);
|
||||
XCTAssertNotNil(weakExtendedPromise2);
|
||||
}
|
||||
|
||||
// Assert.
|
||||
XCTAssertNotNil(weakExtendedPromise1);
|
||||
XCTAssertNotNil(weakExtendedPromise2);
|
||||
|
||||
[promise fulfill:@42];
|
||||
XCTAssert(FBLWaitForPromisesWithTimeout(10));
|
||||
|
||||
XCTAssertNil(weakExtendedPromise1);
|
||||
XCTAssertNil(weakExtendedPromise2);
|
||||
}
|
||||
|
||||
@end
|
||||
Loaded 100 of 139 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user