selenium-webdriver 2.47.0 → 2.52.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (529) hide show
  1. package/CHANGES.md +96 -0
  2. package/NOTICE +1 -1
  3. package/README.md +57 -6
  4. package/builder.js +375 -358
  5. package/chrome.js +549 -586
  6. package/edge.js +378 -0
  7. package/error.js +597 -5
  8. package/example/google_search_generator.js +2 -4
  9. package/example/logging.js +6 -2
  10. package/executors.js +11 -27
  11. package/firefox/binary.js +80 -114
  12. package/firefox/extension.js +10 -19
  13. package/firefox/index.js +175 -171
  14. package/firefox/profile.js +221 -239
  15. package/http/index.js +396 -77
  16. package/http/util.js +35 -35
  17. package/ie.js +288 -309
  18. package/index.js +34 -125
  19. package/io/exec.js +58 -39
  20. package/io/index.js +54 -48
  21. package/lib/actions.js +594 -0
  22. package/lib/by.js +276 -0
  23. package/lib/capabilities.js +404 -0
  24. package/lib/{webdriver/command.js → command.js} +89 -72
  25. package/lib/{webdriver/button.js → devmode.js} +13 -8
  26. package/lib/events.js +210 -0
  27. package/lib/firefox/amd64/libnoblur64.so +0 -0
  28. package/lib/firefox/i386/libnoblur.so +0 -0
  29. package/lib/firefox/webdriver.json +6 -1
  30. package/lib/firefox/webdriver.xpi +0 -0
  31. package/lib/{webdriver/key.js → input.js} +82 -2
  32. package/lib/logging.js +668 -0
  33. package/lib/promise.js +3093 -0
  34. package/lib/safari/client.js +697 -659
  35. package/lib/session.js +79 -0
  36. package/{test/promise_aplus_test.js → lib/symbols.js} +15 -25
  37. package/lib/test/build.js +4 -4
  38. package/lib/test/data/click_tests/disappearing_element.html +62 -0
  39. package/lib/test/data/click_tests/html5_submit_buttons.html +2 -1
  40. package/lib/test/data/click_tests/overlapping_elements.html +70 -0
  41. package/lib/test/data/click_tests/partially_overlapping_elements.html +124 -0
  42. package/lib/test/data/click_tests/wrapped_overlapping_elements.html +13 -0
  43. package/lib/test/data/readOnlyPage.html +3 -1
  44. package/lib/test/data/selectPage.html +18 -2
  45. package/lib/test/data/simpleTest.html +1 -0
  46. package/lib/test/fileserver.js +3 -4
  47. package/lib/test/index.js +13 -4
  48. package/lib/test/resources.js +1 -1
  49. package/lib/until.js +428 -0
  50. package/lib/webdriver.js +2351 -0
  51. package/net/portprober.js +15 -11
  52. package/opera.js +295 -314
  53. package/package.json +6 -5
  54. package/phantomjs.js +135 -140
  55. package/proxy.js +6 -4
  56. package/remote/index.js +234 -219
  57. package/safari.js +319 -310
  58. package/test/chrome/options_test.js +11 -9
  59. package/test/element_finding_test.js +51 -13
  60. package/test/error_test.js +163 -0
  61. package/test/execute_script_test.js +1 -1
  62. package/test/firefox/firefox_test.js +24 -0
  63. package/test/http/http_test.js +354 -43
  64. package/test/http/util_test.js +25 -23
  65. package/test/io_test.js +6 -1
  66. package/test/lib/by_test.js +127 -0
  67. package/test/lib/capabilities_test.js +84 -0
  68. package/test/lib/events_test.js +177 -0
  69. package/test/lib/logging_test.js +272 -0
  70. package/test/lib/promise_aplus_test.js +74 -0
  71. package/test/lib/promise_error_test.js +808 -0
  72. package/test/lib/promise_flow_test.js +2282 -0
  73. package/test/lib/promise_generator_test.js +308 -0
  74. package/test/lib/promise_test.js +996 -0
  75. package/test/lib/testutil.js +90 -0
  76. package/test/lib/until_test.js +436 -0
  77. package/test/lib/webdriver_test.js +2207 -0
  78. package/test/page_loading_test.js +7 -9
  79. package/test/stale_element_test.js +2 -2
  80. package/test/testing/assert_test.js +374 -0
  81. package/test/testing/index_test.js +9 -11
  82. package/testing/assert.js +334 -17
  83. package/testing/index.js +10 -0
  84. package/_base.js +0 -200
  85. package/docs/Changes.html +0 -317
  86. package/docs/class_bot_Error.html +0 -15
  87. package/docs/class_webdriver_ActionSequence.html +0 -115
  88. package/docs/class_webdriver_Alert.html +0 -24
  89. package/docs/class_webdriver_AlertPromise.html +0 -91
  90. package/docs/class_webdriver_Capabilities.html +0 -60
  91. package/docs/class_webdriver_Command.html +0 -15
  92. package/docs/class_webdriver_EventEmitter.html +0 -35
  93. package/docs/class_webdriver_FileDetector.html +0 -21
  94. package/docs/class_webdriver_Locator.html +0 -12
  95. package/docs/class_webdriver_Serializable.html +0 -9
  96. package/docs/class_webdriver_Session.html +0 -13
  97. package/docs/class_webdriver_TouchSequence.html +0 -49
  98. package/docs/class_webdriver_UnhandledAlertError.html +0 -18
  99. package/docs/class_webdriver_WebDriver.html +0 -313
  100. package/docs/class_webdriver_WebDriver_Logs.html +0 -15
  101. package/docs/class_webdriver_WebDriver_Navigation.html +0 -16
  102. package/docs/class_webdriver_WebDriver_Options.html +0 -41
  103. package/docs/class_webdriver_WebDriver_TargetLocator.html +0 -38
  104. package/docs/class_webdriver_WebDriver_Timeouts.html +0 -29
  105. package/docs/class_webdriver_WebDriver_Window.html +0 -27
  106. package/docs/class_webdriver_WebElement.html +0 -216
  107. package/docs/class_webdriver_WebElementPromise.html +0 -266
  108. package/docs/class_webdriver_http_Executor.html +0 -22
  109. package/docs/class_webdriver_http_Request.html +0 -12
  110. package/docs/class_webdriver_http_Response.html +0 -13
  111. package/docs/class_webdriver_logging_Entry.html +0 -15
  112. package/docs/class_webdriver_logging_Level.html +0 -55
  113. package/docs/class_webdriver_logging_LogRecord.html +0 -45
  114. package/docs/class_webdriver_logging_Logger.html +0 -119
  115. package/docs/class_webdriver_logging_Preferences.html +0 -8
  116. package/docs/class_webdriver_promise_CancellationError.html +0 -18
  117. package/docs/class_webdriver_promise_ControlFlow.html +0 -109
  118. package/docs/class_webdriver_promise_Deferred.html +0 -84
  119. package/docs/class_webdriver_promise_Promise.html +0 -74
  120. package/docs/class_webdriver_stacktrace_Frame.html +0 -20
  121. package/docs/class_webdriver_stacktrace_Snapshot.html +0 -6
  122. package/docs/class_webdriver_testing_Assertion.html +0 -99
  123. package/docs/class_webdriver_testing_Assertion_DelegatingMatcher_.html +0 -13
  124. package/docs/class_webdriver_testing_ContainsMatcher.html +0 -11
  125. package/docs/class_webdriver_testing_NegatedAssertion.html +0 -97
  126. package/docs/class_webdriver_until_Condition.html +0 -7
  127. package/docs/dossier.css +0 -1
  128. package/docs/dossier.js +0 -86
  129. package/docs/enum_bot_ErrorCode.html +0 -3
  130. package/docs/enum_bot_Error_State.html +0 -2
  131. package/docs/enum_webdriver_Browser.html +0 -2
  132. package/docs/enum_webdriver_Button.html +0 -2
  133. package/docs/enum_webdriver_Capability.html +0 -33
  134. package/docs/enum_webdriver_CommandName.html +0 -3
  135. package/docs/enum_webdriver_Key.html +0 -12
  136. package/docs/enum_webdriver_logging_Type.html +0 -6
  137. package/docs/enum_webdriver_promise_ControlFlow_EventType.html +0 -9
  138. package/docs/index.html +0 -123
  139. package/docs/interface_webdriver_CommandExecutor.html +0 -9
  140. package/docs/interface_webdriver_http_Client.html +0 -10
  141. package/docs/interface_webdriver_promise_Thenable.html +0 -77
  142. package/docs/module_selenium-webdriver.html +0 -23
  143. package/docs/module_selenium-webdriver__base.html +0 -23
  144. package/docs/module_selenium-webdriver__base_class_Context.html +0 -5
  145. package/docs/module_selenium-webdriver_builder.html +0 -2
  146. package/docs/module_selenium-webdriver_builder_class_Builder.html +0 -138
  147. package/docs/module_selenium-webdriver_chrome.html +0 -90
  148. package/docs/module_selenium-webdriver_chrome_class_Driver.html +0 -280
  149. package/docs/module_selenium-webdriver_chrome_class_Options.html +0 -127
  150. package/docs/module_selenium-webdriver_chrome_class_ServiceBuilder.html +0 -46
  151. package/docs/module_selenium-webdriver_class_ActionSequence.html +0 -115
  152. package/docs/module_selenium-webdriver_class_Builder.html +0 -138
  153. package/docs/module_selenium-webdriver_class_Capabilities.html +0 -60
  154. package/docs/module_selenium-webdriver_class_Command.html +0 -15
  155. package/docs/module_selenium-webdriver_class_EventEmitter.html +0 -35
  156. package/docs/module_selenium-webdriver_class_FileDetector.html +0 -21
  157. package/docs/module_selenium-webdriver_class_Serializable.html +0 -9
  158. package/docs/module_selenium-webdriver_class_Session.html +0 -13
  159. package/docs/module_selenium-webdriver_class_WebDriver.html +0 -313
  160. package/docs/module_selenium-webdriver_class_WebElement.html +0 -216
  161. package/docs/module_selenium-webdriver_class_WebElementPromise.html +0 -266
  162. package/docs/module_selenium-webdriver_enum_Browser.html +0 -2
  163. package/docs/module_selenium-webdriver_enum_Button.html +0 -2
  164. package/docs/module_selenium-webdriver_enum_Capability.html +0 -33
  165. package/docs/module_selenium-webdriver_enum_CommandName.html +0 -3
  166. package/docs/module_selenium-webdriver_enum_Key.html +0 -12
  167. package/docs/module_selenium-webdriver_error.html +0 -4
  168. package/docs/module_selenium-webdriver_error_class_Error.html +0 -15
  169. package/docs/module_selenium-webdriver_error_enum_ErrorCode.html +0 -3
  170. package/docs/module_selenium-webdriver_executors.html +0 -10
  171. package/docs/module_selenium-webdriver_executors_class_DeferredExecutor.html +0 -12
  172. package/docs/module_selenium-webdriver_firefox.html +0 -67
  173. package/docs/module_selenium-webdriver_firefox_binary.html +0 -4
  174. package/docs/module_selenium-webdriver_firefox_binary_class_Binary.html +0 -21
  175. package/docs/module_selenium-webdriver_firefox_class_Binary.html +0 -21
  176. package/docs/module_selenium-webdriver_firefox_class_Driver.html +0 -276
  177. package/docs/module_selenium-webdriver_firefox_class_Options.html +0 -19
  178. package/docs/module_selenium-webdriver_firefox_class_Profile.html +0 -50
  179. package/docs/module_selenium-webdriver_firefox_extension.html +0 -8
  180. package/docs/module_selenium-webdriver_firefox_profile.html +0 -13
  181. package/docs/module_selenium-webdriver_firefox_profile_class_Profile.html +0 -50
  182. package/docs/module_selenium-webdriver_http.html +0 -9
  183. package/docs/module_selenium-webdriver_http_class_Executor.html +0 -22
  184. package/docs/module_selenium-webdriver_http_class_HttpClient.html +0 -16
  185. package/docs/module_selenium-webdriver_http_class_Request.html +0 -12
  186. package/docs/module_selenium-webdriver_http_class_Response.html +0 -13
  187. package/docs/module_selenium-webdriver_http_util.html +0 -17
  188. package/docs/module_selenium-webdriver_ie.html +0 -11
  189. package/docs/module_selenium-webdriver_ie_class_Driver.html +0 -274
  190. package/docs/module_selenium-webdriver_ie_class_Options.html +0 -89
  191. package/docs/module_selenium-webdriver_ie_enum_Level.html +0 -1
  192. package/docs/module_selenium-webdriver_io.html +0 -37
  193. package/docs/module_selenium-webdriver_io_exec.html +0 -6
  194. package/docs/module_selenium-webdriver_namespace_By.html +0 -56
  195. package/docs/module_selenium-webdriver_namespace_error.html +0 -4
  196. package/docs/module_selenium-webdriver_namespace_logging.html +0 -18
  197. package/docs/module_selenium-webdriver_namespace_promise.html +0 -162
  198. package/docs/module_selenium-webdriver_namespace_stacktrace.html +0 -17
  199. package/docs/module_selenium-webdriver_namespace_until.html +0 -82
  200. package/docs/module_selenium-webdriver_net.html +0 -7
  201. package/docs/module_selenium-webdriver_net_portprober.html +0 -12
  202. package/docs/module_selenium-webdriver_opera.html +0 -62
  203. package/docs/module_selenium-webdriver_opera_class_Driver.html +0 -276
  204. package/docs/module_selenium-webdriver_opera_class_Options.html +0 -44
  205. package/docs/module_selenium-webdriver_opera_class_ServiceBuilder.html +0 -35
  206. package/docs/module_selenium-webdriver_phantomjs.html +0 -2
  207. package/docs/module_selenium-webdriver_phantomjs_class_Driver.html +0 -299
  208. package/docs/module_selenium-webdriver_proxy.html +0 -28
  209. package/docs/module_selenium-webdriver_remote.html +0 -8
  210. package/docs/module_selenium-webdriver_remote_class_DriverService.html +0 -32
  211. package/docs/module_selenium-webdriver_remote_class_FileDetector.html +0 -22
  212. package/docs/module_selenium-webdriver_remote_class_SeleniumServer.html +0 -40
  213. package/docs/module_selenium-webdriver_safari.html +0 -9
  214. package/docs/module_selenium-webdriver_safari_class_Driver.html +0 -279
  215. package/docs/module_selenium-webdriver_safari_class_Options.html +0 -23
  216. package/docs/module_selenium-webdriver_testing.html +0 -74
  217. package/docs/module_selenium-webdriver_testing_assert.html +0 -9
  218. package/docs/namespace_bot.html +0 -4
  219. package/docs/namespace_bot_json.html +0 -20
  220. package/docs/namespace_bot_response.html +0 -18
  221. package/docs/namespace_bot_userAgent.html +0 -33
  222. package/docs/namespace_webdriver.html +0 -30
  223. package/docs/namespace_webdriver_By.html +0 -56
  224. package/docs/namespace_webdriver_http.html +0 -6
  225. package/docs/namespace_webdriver_logging.html +0 -70
  226. package/docs/namespace_webdriver_promise.html +0 -165
  227. package/docs/namespace_webdriver_stacktrace.html +0 -17
  228. package/docs/namespace_webdriver_testing.html +0 -7
  229. package/docs/namespace_webdriver_testing_assert.html +0 -9
  230. package/docs/namespace_webdriver_testing_asserts.html +0 -18
  231. package/docs/namespace_webdriver_until.html +0 -82
  232. package/docs/source/_base.js.src.html +0 -1
  233. package/docs/source/builder.js.src.html +0 -1
  234. package/docs/source/chrome.js.src.html +0 -1
  235. package/docs/source/error.js.src.html +0 -1
  236. package/docs/source/executors.js.src.html +0 -1
  237. package/docs/source/firefox/binary.js.src.html +0 -1
  238. package/docs/source/firefox/extension.js.src.html +0 -1
  239. package/docs/source/firefox/index.js.src.html +0 -1
  240. package/docs/source/firefox/profile.js.src.html +0 -1
  241. package/docs/source/http/index.js.src.html +0 -1
  242. package/docs/source/http/util.js.src.html +0 -1
  243. package/docs/source/ie.js.src.html +0 -1
  244. package/docs/source/index.js.src.html +0 -1
  245. package/docs/source/io/exec.js.src.html +0 -1
  246. package/docs/source/io/index.js.src.html +0 -1
  247. package/docs/source/lib/atoms/error.js.src.html +0 -1
  248. package/docs/source/lib/atoms/json.js.src.html +0 -1
  249. package/docs/source/lib/atoms/response.js.src.html +0 -1
  250. package/docs/source/lib/atoms/userAgent.js.src.html +0 -1
  251. package/docs/source/lib/goog/array/array.js.src.html +0 -1
  252. package/docs/source/lib/goog/asserts/asserts.js.src.html +0 -1
  253. package/docs/source/lib/goog/async/freelist.js.src.html +0 -1
  254. package/docs/source/lib/goog/async/nexttick.js.src.html +0 -1
  255. package/docs/source/lib/goog/async/run.js.src.html +0 -1
  256. package/docs/source/lib/goog/async/workqueue.js.src.html +0 -1
  257. package/docs/source/lib/goog/base.js.src.html +0 -1
  258. package/docs/source/lib/goog/debug/debug.js.src.html +0 -1
  259. package/docs/source/lib/goog/debug/entrypointregistry.js.src.html +0 -1
  260. package/docs/source/lib/goog/debug/error.js.src.html +0 -1
  261. package/docs/source/lib/goog/debug/logbuffer.js.src.html +0 -1
  262. package/docs/source/lib/goog/debug/logger.js.src.html +0 -1
  263. package/docs/source/lib/goog/debug/logrecord.js.src.html +0 -1
  264. package/docs/source/lib/goog/deps.js.src.html +0 -1
  265. package/docs/source/lib/goog/disposable/disposable.js.src.html +0 -1
  266. package/docs/source/lib/goog/disposable/idisposable.js.src.html +0 -1
  267. package/docs/source/lib/goog/dom/browserfeature.js.src.html +0 -1
  268. package/docs/source/lib/goog/dom/dom.js.src.html +0 -1
  269. package/docs/source/lib/goog/dom/nodetype.js.src.html +0 -1
  270. package/docs/source/lib/goog/dom/safe.js.src.html +0 -1
  271. package/docs/source/lib/goog/dom/tagname.js.src.html +0 -1
  272. package/docs/source/lib/goog/dom/tags.js.src.html +0 -1
  273. package/docs/source/lib/goog/dom/vendor.js.src.html +0 -1
  274. package/docs/source/lib/goog/events/browserevent.js.src.html +0 -1
  275. package/docs/source/lib/goog/events/browserfeature.js.src.html +0 -1
  276. package/docs/source/lib/goog/events/event.js.src.html +0 -1
  277. package/docs/source/lib/goog/events/eventid.js.src.html +0 -1
  278. package/docs/source/lib/goog/events/events.js.src.html +0 -1
  279. package/docs/source/lib/goog/events/eventtarget.js.src.html +0 -1
  280. package/docs/source/lib/goog/events/eventtype.js.src.html +0 -1
  281. package/docs/source/lib/goog/events/keycodes.js.src.html +0 -1
  282. package/docs/source/lib/goog/events/listenable.js.src.html +0 -1
  283. package/docs/source/lib/goog/events/listener.js.src.html +0 -1
  284. package/docs/source/lib/goog/events/listenermap.js.src.html +0 -1
  285. package/docs/source/lib/goog/fs/url.js.src.html +0 -1
  286. package/docs/source/lib/goog/functions/functions.js.src.html +0 -1
  287. package/docs/source/lib/goog/html/safehtml.js.src.html +0 -1
  288. package/docs/source/lib/goog/html/safescript.js.src.html +0 -1
  289. package/docs/source/lib/goog/html/safestyle.js.src.html +0 -1
  290. package/docs/source/lib/goog/html/safestylesheet.js.src.html +0 -1
  291. package/docs/source/lib/goog/html/safeurl.js.src.html +0 -1
  292. package/docs/source/lib/goog/html/trustedresourceurl.js.src.html +0 -1
  293. package/docs/source/lib/goog/html/uncheckedconversions.js.src.html +0 -1
  294. package/docs/source/lib/goog/i18n/bidi.js.src.html +0 -1
  295. package/docs/source/lib/goog/iter/iter.js.src.html +0 -1
  296. package/docs/source/lib/goog/json/json.js.src.html +0 -1
  297. package/docs/source/lib/goog/labs/testing/assertthat.js.src.html +0 -1
  298. package/docs/source/lib/goog/labs/testing/logicmatcher.js.src.html +0 -1
  299. package/docs/source/lib/goog/labs/testing/matcher.js.src.html +0 -1
  300. package/docs/source/lib/goog/labs/testing/numbermatcher.js.src.html +0 -1
  301. package/docs/source/lib/goog/labs/testing/objectmatcher.js.src.html +0 -1
  302. package/docs/source/lib/goog/labs/testing/stringmatcher.js.src.html +0 -1
  303. package/docs/source/lib/goog/labs/useragent/browser.js.src.html +0 -1
  304. package/docs/source/lib/goog/labs/useragent/engine.js.src.html +0 -1
  305. package/docs/source/lib/goog/labs/useragent/platform.js.src.html +0 -1
  306. package/docs/source/lib/goog/labs/useragent/util.js.src.html +0 -1
  307. package/docs/source/lib/goog/math/box.js.src.html +0 -1
  308. package/docs/source/lib/goog/math/coordinate.js.src.html +0 -1
  309. package/docs/source/lib/goog/math/math.js.src.html +0 -1
  310. package/docs/source/lib/goog/math/rect.js.src.html +0 -1
  311. package/docs/source/lib/goog/math/size.js.src.html +0 -1
  312. package/docs/source/lib/goog/net/wrapperxmlhttpfactory.js.src.html +0 -1
  313. package/docs/source/lib/goog/net/xhrlike.js.src.html +0 -1
  314. package/docs/source/lib/goog/net/xmlhttp.js.src.html +0 -1
  315. package/docs/source/lib/goog/net/xmlhttpfactory.js.src.html +0 -1
  316. package/docs/source/lib/goog/object/object.js.src.html +0 -1
  317. package/docs/source/lib/goog/promise/promise.js.src.html +0 -1
  318. package/docs/source/lib/goog/promise/resolver.js.src.html +0 -1
  319. package/docs/source/lib/goog/promise/thenable.js.src.html +0 -1
  320. package/docs/source/lib/goog/reflect/reflect.js.src.html +0 -1
  321. package/docs/source/lib/goog/string/const.js.src.html +0 -1
  322. package/docs/source/lib/goog/string/string.js.src.html +0 -1
  323. package/docs/source/lib/goog/string/typedstring.js.src.html +0 -1
  324. package/docs/source/lib/goog/structs/collection.js.src.html +0 -1
  325. package/docs/source/lib/goog/structs/map.js.src.html +0 -1
  326. package/docs/source/lib/goog/structs/set.js.src.html +0 -1
  327. package/docs/source/lib/goog/structs/structs.js.src.html +0 -1
  328. package/docs/source/lib/goog/style/style.js.src.html +0 -1
  329. package/docs/source/lib/goog/testing/asserts.js.src.html +0 -1
  330. package/docs/source/lib/goog/testing/events/events.js.src.html +0 -1
  331. package/docs/source/lib/goog/testing/functionmock.js.src.html +0 -1
  332. package/docs/source/lib/goog/testing/jsunit.js.src.html +0 -1
  333. package/docs/source/lib/goog/testing/loosemock.js.src.html +0 -1
  334. package/docs/source/lib/goog/testing/mock.js.src.html +0 -1
  335. package/docs/source/lib/goog/testing/mockclock.js.src.html +0 -1
  336. package/docs/source/lib/goog/testing/mockcontrol.js.src.html +0 -1
  337. package/docs/source/lib/goog/testing/mockinterface.js.src.html +0 -1
  338. package/docs/source/lib/goog/testing/mockmatchers.js.src.html +0 -1
  339. package/docs/source/lib/goog/testing/objectpropertystring.js.src.html +0 -1
  340. package/docs/source/lib/goog/testing/propertyreplacer.js.src.html +0 -1
  341. package/docs/source/lib/goog/testing/recordfunction.js.src.html +0 -1
  342. package/docs/source/lib/goog/testing/stacktrace.js.src.html +0 -1
  343. package/docs/source/lib/goog/testing/strictmock.js.src.html +0 -1
  344. package/docs/source/lib/goog/testing/testcase.js.src.html +0 -1
  345. package/docs/source/lib/goog/testing/testrunner.js.src.html +0 -1
  346. package/docs/source/lib/goog/testing/watchers.js.src.html +0 -1
  347. package/docs/source/lib/goog/uri/uri.js.src.html +0 -1
  348. package/docs/source/lib/goog/uri/utils.js.src.html +0 -1
  349. package/docs/source/lib/goog/useragent/product.js.src.html +0 -1
  350. package/docs/source/lib/goog/useragent/product_isversion.js.src.html +0 -1
  351. package/docs/source/lib/goog/useragent/useragent.js.src.html +0 -1
  352. package/docs/source/lib/webdriver/actionsequence.js.src.html +0 -1
  353. package/docs/source/lib/webdriver/button.js.src.html +0 -1
  354. package/docs/source/lib/webdriver/capabilities.js.src.html +0 -1
  355. package/docs/source/lib/webdriver/command.js.src.html +0 -1
  356. package/docs/source/lib/webdriver/events.js.src.html +0 -1
  357. package/docs/source/lib/webdriver/http/http.js.src.html +0 -1
  358. package/docs/source/lib/webdriver/key.js.src.html +0 -1
  359. package/docs/source/lib/webdriver/locators.js.src.html +0 -1
  360. package/docs/source/lib/webdriver/logging.js.src.html +0 -1
  361. package/docs/source/lib/webdriver/promise.js.src.html +0 -1
  362. package/docs/source/lib/webdriver/serializable.js.src.html +0 -1
  363. package/docs/source/lib/webdriver/session.js.src.html +0 -1
  364. package/docs/source/lib/webdriver/stacktrace.js.src.html +0 -1
  365. package/docs/source/lib/webdriver/testing/asserts.js.src.html +0 -1
  366. package/docs/source/lib/webdriver/touchsequence.js.src.html +0 -1
  367. package/docs/source/lib/webdriver/until.js.src.html +0 -1
  368. package/docs/source/lib/webdriver/webdriver.js.src.html +0 -1
  369. package/docs/source/net/index.js.src.html +0 -1
  370. package/docs/source/net/portprober.js.src.html +0 -1
  371. package/docs/source/opera.js.src.html +0 -1
  372. package/docs/source/phantomjs.js.src.html +0 -1
  373. package/docs/source/proxy.js.src.html +0 -1
  374. package/docs/source/remote/index.js.src.html +0 -1
  375. package/docs/source/safari.js.src.html +0 -1
  376. package/docs/source/testing/assert.js.src.html +0 -1
  377. package/docs/source/testing/index.js.src.html +0 -1
  378. package/docs/types.js +0 -1
  379. package/lib/atoms/error.js +0 -202
  380. package/lib/atoms/json.js +0 -80
  381. package/lib/atoms/response.js +0 -110
  382. package/lib/atoms/userAgent.js +0 -257
  383. package/lib/goog/LICENSE +0 -176
  384. package/lib/goog/array/array.js +0 -1655
  385. package/lib/goog/asserts/asserts.js +0 -365
  386. package/lib/goog/async/freelist.js +0 -88
  387. package/lib/goog/async/nexttick.js +0 -241
  388. package/lib/goog/async/run.js +0 -139
  389. package/lib/goog/async/workqueue.js +0 -139
  390. package/lib/goog/base.js +0 -2547
  391. package/lib/goog/debug/debug.js +0 -653
  392. package/lib/goog/debug/entrypointregistry.js +0 -158
  393. package/lib/goog/debug/error.js +0 -63
  394. package/lib/goog/debug/logbuffer.js +0 -148
  395. package/lib/goog/debug/logger.js +0 -873
  396. package/lib/goog/debug/logrecord.js +0 -242
  397. package/lib/goog/deps.js +0 -151
  398. package/lib/goog/disposable/disposable.js +0 -307
  399. package/lib/goog/disposable/idisposable.js +0 -45
  400. package/lib/goog/dom/browserfeature.js +0 -72
  401. package/lib/goog/dom/dom.js +0 -2995
  402. package/lib/goog/dom/nodetype.js +0 -48
  403. package/lib/goog/dom/safe.js +0 -347
  404. package/lib/goog/dom/tagname.js +0 -160
  405. package/lib/goog/dom/tags.js +0 -42
  406. package/lib/goog/dom/vendor.js +0 -96
  407. package/lib/goog/events/browserevent.js +0 -386
  408. package/lib/goog/events/browserfeature.js +0 -85
  409. package/lib/goog/events/event.js +0 -143
  410. package/lib/goog/events/eventid.js +0 -47
  411. package/lib/goog/events/events.js +0 -984
  412. package/lib/goog/events/eventtarget.js +0 -394
  413. package/lib/goog/events/eventtype.js +0 -233
  414. package/lib/goog/events/keycodes.js +0 -420
  415. package/lib/goog/events/listenable.js +0 -335
  416. package/lib/goog/events/listener.js +0 -131
  417. package/lib/goog/events/listenermap.js +0 -308
  418. package/lib/goog/fs/url.js +0 -105
  419. package/lib/goog/functions/functions.js +0 -332
  420. package/lib/goog/html/safehtml.js +0 -756
  421. package/lib/goog/html/safescript.js +0 -234
  422. package/lib/goog/html/safestyle.js +0 -442
  423. package/lib/goog/html/safestylesheet.js +0 -276
  424. package/lib/goog/html/safeurl.js +0 -431
  425. package/lib/goog/html/trustedresourceurl.js +0 -224
  426. package/lib/goog/html/uncheckedconversions.js +0 -231
  427. package/lib/goog/i18n/bidi.js +0 -908
  428. package/lib/goog/iter/iter.js +0 -1305
  429. package/lib/goog/json/json.js +0 -365
  430. package/lib/goog/labs/testing/assertthat.js +0 -58
  431. package/lib/goog/labs/testing/logicmatcher.js +0 -212
  432. package/lib/goog/labs/testing/matcher.js +0 -80
  433. package/lib/goog/labs/testing/numbermatcher.js +0 -346
  434. package/lib/goog/labs/testing/objectmatcher.js +0 -317
  435. package/lib/goog/labs/testing/stringmatcher.js +0 -415
  436. package/lib/goog/labs/useragent/browser.js +0 -327
  437. package/lib/goog/labs/useragent/engine.js +0 -160
  438. package/lib/goog/labs/useragent/platform.js +0 -160
  439. package/lib/goog/labs/useragent/util.js +0 -148
  440. package/lib/goog/math/box.js +0 -389
  441. package/lib/goog/math/coordinate.js +0 -268
  442. package/lib/goog/math/math.js +0 -451
  443. package/lib/goog/math/rect.js +0 -476
  444. package/lib/goog/math/size.js +0 -227
  445. package/lib/goog/net/wrapperxmlhttpfactory.js +0 -71
  446. package/lib/goog/net/xhrlike.js +0 -124
  447. package/lib/goog/net/xmlhttp.js +0 -246
  448. package/lib/goog/net/xmlhttpfactory.js +0 -67
  449. package/lib/goog/object/object.js +0 -686
  450. package/lib/goog/promise/promise.js +0 -1310
  451. package/lib/goog/promise/resolver.js +0 -48
  452. package/lib/goog/promise/thenable.js +0 -126
  453. package/lib/goog/reflect/reflect.js +0 -78
  454. package/lib/goog/string/const.js +0 -182
  455. package/lib/goog/string/string.js +0 -1565
  456. package/lib/goog/string/typedstring.js +0 -48
  457. package/lib/goog/structs/collection.js +0 -56
  458. package/lib/goog/structs/map.js +0 -456
  459. package/lib/goog/structs/set.js +0 -279
  460. package/lib/goog/structs/structs.js +0 -354
  461. package/lib/goog/style/style.js +0 -2054
  462. package/lib/goog/testing/asserts.js +0 -1265
  463. package/lib/goog/testing/events/events.js +0 -727
  464. package/lib/goog/testing/functionmock.js +0 -176
  465. package/lib/goog/testing/jsunit.js +0 -162
  466. package/lib/goog/testing/loosemock.js +0 -242
  467. package/lib/goog/testing/mock.js +0 -645
  468. package/lib/goog/testing/mockclock.js +0 -617
  469. package/lib/goog/testing/mockcontrol.js +0 -220
  470. package/lib/goog/testing/mockinterface.js +0 -45
  471. package/lib/goog/testing/mockmatchers.js +0 -400
  472. package/lib/goog/testing/objectpropertystring.js +0 -68
  473. package/lib/goog/testing/propertyreplacer.js +0 -245
  474. package/lib/goog/testing/recordfunction.js +0 -215
  475. package/lib/goog/testing/stacktrace.js +0 -594
  476. package/lib/goog/testing/strictmock.js +0 -130
  477. package/lib/goog/testing/testcase.js +0 -1569
  478. package/lib/goog/testing/testrunner.js +0 -440
  479. package/lib/goog/testing/watchers.js +0 -46
  480. package/lib/goog/uri/uri.js +0 -1507
  481. package/lib/goog/uri/utils.js +0 -1116
  482. package/lib/goog/useragent/product.js +0 -175
  483. package/lib/goog/useragent/product_isversion.js +0 -143
  484. package/lib/goog/useragent/useragent.js +0 -538
  485. package/lib/webdriver/actionsequence.js +0 -356
  486. package/lib/webdriver/builder.js +0 -208
  487. package/lib/webdriver/capabilities.js +0 -411
  488. package/lib/webdriver/events.js +0 -179
  489. package/lib/webdriver/firefoxdomexecutor.js +0 -175
  490. package/lib/webdriver/http/corsclient.js +0 -133
  491. package/lib/webdriver/http/http.js +0 -523
  492. package/lib/webdriver/http/xhrclient.js +0 -67
  493. package/lib/webdriver/locators.js +0 -257
  494. package/lib/webdriver/logging.js +0 -347
  495. package/lib/webdriver/promise.js +0 -2609
  496. package/lib/webdriver/serializable.js +0 -41
  497. package/lib/webdriver/session.js +0 -74
  498. package/lib/webdriver/stacktrace.js +0 -619
  499. package/lib/webdriver/test/builder_test.js +0 -53
  500. package/lib/webdriver/test/capabilities_test.js +0 -72
  501. package/lib/webdriver/test/events_test.js +0 -203
  502. package/lib/webdriver/test/http/corsclient_test.js +0 -151
  503. package/lib/webdriver/test/http/http_test.js +0 -428
  504. package/lib/webdriver/test/http/xhrclient_test.js +0 -196
  505. package/lib/webdriver/test/locators_test.js +0 -59
  506. package/lib/webdriver/test/logging_test.js +0 -85
  507. package/lib/webdriver/test/promise_error_test.js +0 -719
  508. package/lib/webdriver/test/promise_flow_test.js +0 -1957
  509. package/lib/webdriver/test/promise_generator_test.js +0 -251
  510. package/lib/webdriver/test/promise_test.js +0 -1981
  511. package/lib/webdriver/test/stacktrace_test.js +0 -480
  512. package/lib/webdriver/test/test_bootstrap.js +0 -67
  513. package/lib/webdriver/test/testing/asserts_test.js +0 -117
  514. package/lib/webdriver/test/testing/client_test.js +0 -88
  515. package/lib/webdriver/test/testing/testcase_test.js +0 -229
  516. package/lib/webdriver/test/testutil.js +0 -209
  517. package/lib/webdriver/test/testutil_test.js +0 -104
  518. package/lib/webdriver/test/until_test.js +0 -411
  519. package/lib/webdriver/test/webdriver_generator_test.js +0 -92
  520. package/lib/webdriver/test/webdriver_test.js +0 -2369
  521. package/lib/webdriver/testing/asserts.js +0 -487
  522. package/lib/webdriver/testing/client.js +0 -179
  523. package/lib/webdriver/testing/jsunit.js +0 -363
  524. package/lib/webdriver/testing/testcase.js +0 -168
  525. package/lib/webdriver/testing/window.js +0 -244
  526. package/lib/webdriver/touchsequence.js +0 -248
  527. package/lib/webdriver/until.js +0 -412
  528. package/lib/webdriver/webdriver.js +0 -2492
  529. package/test/_base_test.js +0 -129
@@ -1,2609 +0,0 @@
1
- // Licensed to the Software Freedom Conservancy (SFC) under one
2
- // or more contributor license agreements. See the NOTICE file
3
- // distributed with this work for additional information
4
- // regarding copyright ownership. The SFC licenses this file
5
- // to you under the Apache License, Version 2.0 (the
6
- // "License"); you may not use this file except in compliance
7
- // with the License. You may obtain a copy of the License at
8
- //
9
- // http://www.apache.org/licenses/LICENSE-2.0
10
- //
11
- // Unless required by applicable law or agreed to in writing,
12
- // software distributed under the License is distributed on an
13
- // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14
- // KIND, either express or implied. See the License for the
15
- // specific language governing permissions and limitations
16
- // under the License.
17
-
18
- /**
19
- * @license Portions of this code are from the Dojo toolkit, received under the
20
- * BSD License:
21
- * Redistribution and use in source and binary forms, with or without
22
- * modification, are permitted provided that the following conditions are met:
23
- *
24
- * * Redistributions of source code must retain the above copyright notice,
25
- * this list of conditions and the following disclaimer.
26
- * * Redistributions in binary form must reproduce the above copyright notice,
27
- * this list of conditions and the following disclaimer in the documentation
28
- * and/or other materials provided with the distribution.
29
- * * Neither the name of the Dojo Foundation nor the names of its contributors
30
- * may be used to endorse or promote products derived from this software
31
- * without specific prior written permission.
32
- *
33
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
34
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
35
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
36
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
37
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
38
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
39
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
40
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
41
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
42
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
43
- * POSSIBILITY OF SUCH DAMAGE.
44
- */
45
-
46
- /**
47
- * @fileoverview A promise implementation based on the CommonJS promise/A and
48
- * promise/B proposals. For more information, see
49
- * http://wiki.commonjs.org/wiki/Promises.
50
- */
51
-
52
- goog.module('webdriver.promise');
53
- goog.module.declareLegacyNamespace();
54
-
55
- var Arrays = goog.require('goog.array');
56
- var asserts = goog.require('goog.asserts');
57
- var asyncRun = goog.require('goog.async.run');
58
- var throwException = goog.require('goog.async.throwException');
59
- var DebugError = goog.require('goog.debug.Error');
60
- var Objects = goog.require('goog.object');
61
- var EventEmitter = goog.require('webdriver.EventEmitter');
62
- var stacktrace = goog.require('webdriver.stacktrace');
63
-
64
-
65
-
66
- /**
67
- * @define {boolean} Whether to append traces of {@code then} to rejection
68
- * errors.
69
- */
70
- goog.define('webdriver.promise.LONG_STACK_TRACES', false);
71
-
72
- /** @const */
73
- var promise = exports;
74
-
75
-
76
- /**
77
- * Generates an error to capture the current stack trace.
78
- * @param {string} name Error name for this stack trace.
79
- * @param {string} msg Message to record.
80
- * @param {!Function} topFn The function that should appear at the top of the
81
- * stack; only applicable in V8.
82
- * @return {!Error} The generated error.
83
- */
84
- promise.captureStackTrace = function(name, msg, topFn) {
85
- var e = Error(msg);
86
- e.name = name;
87
- if (Error.captureStackTrace) {
88
- Error.captureStackTrace(e, topFn);
89
- } else {
90
- var stack = stacktrace.getStack(e);
91
- e.stack = e.toString();
92
- if (stack) {
93
- e.stack += '\n' + stack;
94
- }
95
- }
96
- return e;
97
- };
98
-
99
-
100
- /**
101
- * Error used when the computation of a promise is cancelled.
102
- *
103
- * @param {string=} opt_msg The cancellation message.
104
- * @constructor
105
- * @extends {DebugError}
106
- * @final
107
- */
108
- promise.CancellationError = function(opt_msg) {
109
- DebugError.call(this, opt_msg);
110
-
111
- /** @override */
112
- this.name = 'CancellationError';
113
- };
114
- goog.inherits(promise.CancellationError, DebugError);
115
-
116
-
117
- /**
118
- * Wraps the given error in a CancellationError. Will trivially return
119
- * the error itself if it is an instanceof CancellationError.
120
- *
121
- * @param {*} error The error to wrap.
122
- * @param {string=} opt_msg The prefix message to use.
123
- * @return {!promise.CancellationError} A cancellation error.
124
- */
125
- promise.CancellationError.wrap = function(error, opt_msg) {
126
- if (error instanceof promise.CancellationError) {
127
- return /** @type {!promise.CancellationError} */(error);
128
- } else if (opt_msg) {
129
- var message = opt_msg;
130
- if (error) {
131
- message += ': ' + error;
132
- }
133
- return new promise.CancellationError(message);
134
- }
135
- var message;
136
- if (error) {
137
- message = error + '';
138
- }
139
- return new promise.CancellationError(message);
140
- };
141
-
142
-
143
-
144
- /**
145
- * Thenable is a promise-like object with a {@code then} method which may be
146
- * used to schedule callbacks on a promised value.
147
- *
148
- * @interface
149
- * @extends {IThenable<T>}
150
- * @template T
151
- */
152
- promise.Thenable = function() {};
153
-
154
-
155
- /**
156
- * Cancels the computation of this promise's value, rejecting the promise in the
157
- * process. This method is a no-op if the promise has already been resolved.
158
- *
159
- * @param {(string|promise.CancellationError)=} opt_reason The reason this
160
- * promise is being cancelled.
161
- */
162
- promise.Thenable.prototype.cancel = function(opt_reason) {};
163
-
164
-
165
- /** @return {boolean} Whether this promise's value is still being computed. */
166
- promise.Thenable.prototype.isPending = function() {};
167
-
168
-
169
- /**
170
- * Registers listeners for when this instance is resolved.
171
- *
172
- * @param {?(function(T): (R|IThenable<R>))=} opt_callback The
173
- * function to call if this promise is successfully resolved. The function
174
- * should expect a single argument: the promise's resolved value.
175
- * @param {?(function(*): (R|IThenable<R>))=} opt_errback
176
- * The function to call if this promise is rejected. The function should
177
- * expect a single argument: the rejection reason.
178
- * @return {!promise.Promise<R>} A new promise which will be
179
- * resolved with the result of the invoked callback.
180
- * @template R
181
- */
182
- promise.Thenable.prototype.then = function(opt_callback, opt_errback) {};
183
-
184
-
185
- /**
186
- * Registers a listener for when this promise is rejected. This is synonymous
187
- * with the {@code catch} clause in a synchronous API:
188
- *
189
- * // Synchronous API:
190
- * try {
191
- * doSynchronousWork();
192
- * } catch (ex) {
193
- * console.error(ex);
194
- * }
195
- *
196
- * // Asynchronous promise API:
197
- * doAsynchronousWork().thenCatch(function(ex) {
198
- * console.error(ex);
199
- * });
200
- *
201
- * @param {function(*): (R|IThenable<R>)} errback The
202
- * function to call if this promise is rejected. The function should
203
- * expect a single argument: the rejection reason.
204
- * @return {!promise.Promise<R>} A new promise which will be
205
- * resolved with the result of the invoked callback.
206
- * @template R
207
- */
208
- promise.Thenable.prototype.thenCatch = function(errback) {};
209
-
210
-
211
- /**
212
- * Registers a listener to invoke when this promise is resolved, regardless
213
- * of whether the promise's value was successfully computed. This function
214
- * is synonymous with the {@code finally} clause in a synchronous API:
215
- *
216
- * // Synchronous API:
217
- * try {
218
- * doSynchronousWork();
219
- * } finally {
220
- * cleanUp();
221
- * }
222
- *
223
- * // Asynchronous promise API:
224
- * doAsynchronousWork().thenFinally(cleanUp);
225
- *
226
- * __Note:__ similar to the {@code finally} clause, if the registered
227
- * callback returns a rejected promise or throws an error, it will silently
228
- * replace the rejection error (if any) from this promise:
229
- *
230
- * try {
231
- * throw Error('one');
232
- * } finally {
233
- * throw Error('two'); // Hides Error: one
234
- * }
235
- *
236
- * promise.rejected(Error('one'))
237
- * .thenFinally(function() {
238
- * throw Error('two'); // Hides Error: one
239
- * });
240
- *
241
- * @param {function(): (R|IThenable<R>)} callback The function
242
- * to call when this promise is resolved.
243
- * @return {!promise.Promise<R>} A promise that will be fulfilled
244
- * with the callback result.
245
- * @template R
246
- */
247
- promise.Thenable.prototype.thenFinally = function(callback) {};
248
-
249
-
250
- /**
251
- * Property used to flag constructor's as implementing the Thenable interface
252
- * for runtime type checking.
253
- * @type {string}
254
- * @const
255
- */
256
- var IMPLEMENTED_BY_PROP = '$webdriver_Thenable';
257
-
258
-
259
- /**
260
- * Adds a property to a class prototype to allow runtime checks of whether
261
- * instances of that class implement the Thenable interface. This function will
262
- * also ensure the prototype's {@code then} function is exported from compiled
263
- * code.
264
- * @param {function(new: promise.Thenable, ...?)} ctor The
265
- * constructor whose prototype to modify.
266
- */
267
- promise.Thenable.addImplementation = function(ctor) {
268
- // Based on goog.promise.Thenable.isImplementation.
269
- ctor.prototype['then'] = ctor.prototype.then;
270
- try {
271
- // Old IE7 does not support defineProperty; IE8 only supports it for
272
- // DOM elements.
273
- Object.defineProperty(
274
- ctor.prototype,
275
- IMPLEMENTED_BY_PROP,
276
- {'value': true, 'enumerable': false});
277
- } catch (ex) {
278
- ctor.prototype[IMPLEMENTED_BY_PROP] = true;
279
- }
280
- };
281
-
282
-
283
- /**
284
- * Checks if an object has been tagged for implementing the Thenable interface
285
- * as defined by {@link webdriver.promise.Thenable.addImplementation}.
286
- * @param {*} object The object to test.
287
- * @return {boolean} Whether the object is an implementation of the Thenable
288
- * interface.
289
- */
290
- promise.Thenable.isImplementation = function(object) {
291
- // Based on goog.promise.Thenable.isImplementation.
292
- if (!object) {
293
- return false;
294
- }
295
- try {
296
- return !!object[IMPLEMENTED_BY_PROP];
297
- } catch (e) {
298
- return false; // Property access seems to be forbidden.
299
- }
300
- };
301
-
302
-
303
-
304
- /**
305
- * @enum {string}
306
- */
307
- var PromiseState = {
308
- PENDING: 'pending',
309
- BLOCKED: 'blocked',
310
- REJECTED: 'rejected',
311
- FULFILLED: 'fulfilled'
312
- };
313
-
314
-
315
-
316
- /**
317
- * Represents the eventual value of a completed operation. Each promise may be
318
- * in one of three states: pending, fulfilled, or rejected. Each promise starts
319
- * in the pending state and may make a single transition to either a
320
- * fulfilled or rejected state, at which point the promise is considered
321
- * resolved.
322
- *
323
- * @param {function(
324
- * function((T|IThenable<T>|Thenable)=),
325
- * function(*=))} resolver
326
- * Function that is invoked immediately to begin computation of this
327
- * promise's value. The function should accept a pair of callback functions,
328
- * one for fulfilling the promise and another for rejecting it.
329
- * @param {promise.ControlFlow=} opt_flow The control flow
330
- * this instance was created under. Defaults to the currently active flow.
331
- * @constructor
332
- * @implements {promise.Thenable<T>}
333
- * @template T
334
- * @see http://promises-aplus.github.io/promises-spec/
335
- */
336
- promise.Promise = function(resolver, opt_flow) {
337
- goog.getUid(this);
338
-
339
- /** @private {!promise.ControlFlow} */
340
- this.flow_ = opt_flow || promise.controlFlow();
341
-
342
- /** @private {Error} */
343
- this.stack_ = null;
344
- if (promise.LONG_STACK_TRACES) {
345
- this.stack_ = promise.captureStackTrace('Promise', 'new', promise.Promise);
346
- }
347
-
348
- /** @private {promise.Promise<?>} */
349
- this.parent_ = null;
350
-
351
- /** @private {Array<!Callback>} */
352
- this.callbacks_ = null;
353
-
354
- /** @private {PromiseState} */
355
- this.state_ = PromiseState.PENDING;
356
-
357
- /** @private {boolean} */
358
- this.handled_ = false;
359
-
360
- /** @private {boolean} */
361
- this.pendingNotifications_ = false;
362
-
363
- /** @private {*} */
364
- this.value_ = undefined;
365
-
366
- try {
367
- var self = this;
368
- resolver(function(value) {
369
- self.resolve_(PromiseState.FULFILLED, value);
370
- }, function(reason) {
371
- self.resolve_(PromiseState.REJECTED, reason);
372
- });
373
- } catch (ex) {
374
- this.resolve_(PromiseState.REJECTED, ex);
375
- }
376
- };
377
- promise.Thenable.addImplementation(promise.Promise);
378
-
379
-
380
- /** @override */
381
- promise.Promise.prototype.toString = function() {
382
- return 'Promise::' + goog.getUid(this) +
383
- ' {[[PromiseStatus]]: "' + this.state_ + '"}';
384
- };
385
-
386
-
387
- /**
388
- * Resolves this promise. If the new value is itself a promise, this function
389
- * will wait for it to be resolved before notifying the registered listeners.
390
- * @param {PromiseState} newState The promise's new state.
391
- * @param {*} newValue The promise's new value.
392
- * @throws {TypeError} If {@code newValue === this}.
393
- * @private
394
- */
395
- promise.Promise.prototype.resolve_ = function(newState, newValue) {
396
- if (PromiseState.PENDING !== this.state_) {
397
- return;
398
- }
399
-
400
- if (newValue === this) {
401
- // See promise a+, 2.3.1
402
- // http://promises-aplus.github.io/promises-spec/#point-48
403
- throw new TypeError('A promise may not resolve to itself');
404
- }
405
-
406
- this.parent_ = null;
407
- this.state_ = PromiseState.BLOCKED;
408
-
409
- if (promise.Thenable.isImplementation(newValue)) {
410
- // 2.3.2
411
- newValue = /** @type {!promise.Thenable} */(newValue);
412
- newValue.then(
413
- this.unblockAndResolve_.bind(this, PromiseState.FULFILLED),
414
- this.unblockAndResolve_.bind(this, PromiseState.REJECTED));
415
- return;
416
-
417
- } else if (goog.isObject(newValue)) {
418
- // 2.3.3
419
-
420
- try {
421
- // 2.3.3.1
422
- var then = newValue['then'];
423
- } catch (e) {
424
- // 2.3.3.2
425
- this.state_ = PromiseState.REJECTED;
426
- this.value_ = e;
427
- this.scheduleNotifications_();
428
- return;
429
- }
430
-
431
- // NB: goog.isFunction is loose and will accept instanceof Function.
432
- if (typeof then === 'function') {
433
- // 2.3.3.3
434
- this.invokeThen_(newValue, then);
435
- return;
436
- }
437
- }
438
-
439
- if (newState === PromiseState.REJECTED &&
440
- isError(newValue) && newValue.stack && this.stack_) {
441
- newValue.stack += '\nFrom: ' + (this.stack_.stack || this.stack_);
442
- }
443
-
444
- // 2.3.3.4 and 2.3.4
445
- this.state_ = newState;
446
- this.value_ = newValue;
447
- this.scheduleNotifications_();
448
- };
449
-
450
-
451
- /**
452
- * Invokes a thenable's "then" method according to 2.3.3.3 of the promise
453
- * A+ spec.
454
- * @param {!Object} x The thenable object.
455
- * @param {!Function} then The "then" function to invoke.
456
- * @private
457
- */
458
- promise.Promise.prototype.invokeThen_ = function(x, then) {
459
- var called = false;
460
- var self = this;
461
-
462
- var resolvePromise = function(value) {
463
- if (!called) { // 2.3.3.3.3
464
- called = true;
465
- // 2.3.3.3.1
466
- self.unblockAndResolve_(PromiseState.FULFILLED, value);
467
- }
468
- };
469
-
470
- var rejectPromise = function(reason) {
471
- if (!called) { // 2.3.3.3.3
472
- called = true;
473
- // 2.3.3.3.2
474
- self.unblockAndResolve_(PromiseState.REJECTED, reason);
475
- }
476
- };
477
-
478
- try {
479
- // 2.3.3.3
480
- then.call(x, resolvePromise, rejectPromise);
481
- } catch (e) {
482
- // 2.3.3.3.4.2
483
- rejectPromise(e);
484
- }
485
- };
486
-
487
-
488
- /**
489
- * @param {PromiseState} newState The promise's new state.
490
- * @param {*} newValue The promise's new value.
491
- * @private
492
- */
493
- promise.Promise.prototype.unblockAndResolve_ = function(newState, newValue) {
494
- if (this.state_ === PromiseState.BLOCKED) {
495
- this.state_ = PromiseState.PENDING;
496
- this.resolve_(newState, newValue);
497
- }
498
- };
499
-
500
-
501
- /**
502
- * @private
503
- */
504
- promise.Promise.prototype.scheduleNotifications_ = function() {
505
- if (!this.pendingNotifications_) {
506
- this.pendingNotifications_ = true;
507
- this.flow_.suspend_();
508
-
509
- var activeFrame;
510
-
511
- if (!this.handled_ &&
512
- this.state_ === PromiseState.REJECTED &&
513
- !(this.value_ instanceof promise.CancellationError)) {
514
- activeFrame = this.flow_.getActiveFrame_();
515
- activeFrame.pendingRejection = true;
516
- }
517
-
518
- if (this.callbacks_ && this.callbacks_.length) {
519
- activeFrame = this.flow_.getRunningFrame_();
520
- var self = this;
521
- this.callbacks_.forEach(function(callback) {
522
- if (!callback.frame_.getParent()) {
523
- activeFrame.addChild(callback.frame_);
524
- }
525
- });
526
- }
527
-
528
- asyncRun(goog.bind(this.notifyAll_, this, activeFrame));
529
- }
530
- };
531
-
532
-
533
- /**
534
- * Notifies all of the listeners registered with this promise that its state
535
- * has changed.
536
- * @param {Frame} frame The active frame from when this round of
537
- * notifications were scheduled.
538
- * @private
539
- */
540
- promise.Promise.prototype.notifyAll_ = function(frame) {
541
- this.flow_.resume_();
542
- this.pendingNotifications_ = false;
543
-
544
- if (!this.handled_ &&
545
- this.state_ === PromiseState.REJECTED &&
546
- !(this.value_ instanceof promise.CancellationError)) {
547
- this.flow_.abortFrame_(this.value_, frame);
548
- }
549
-
550
- if (this.callbacks_) {
551
- var callbacks = this.callbacks_;
552
- this.callbacks_ = null;
553
- callbacks.forEach(this.notify_, this);
554
- }
555
- };
556
-
557
-
558
- /**
559
- * Notifies a single callback of this promise's change ins tate.
560
- * @param {Callback} callback The callback to notify.
561
- * @private
562
- */
563
- promise.Promise.prototype.notify_ = function(callback) {
564
- callback.notify(this.state_, this.value_);
565
- };
566
-
567
-
568
- /** @override */
569
- promise.Promise.prototype.cancel = function(opt_reason) {
570
- if (!this.isPending()) {
571
- return;
572
- }
573
-
574
- if (this.parent_) {
575
- this.parent_.cancel(opt_reason);
576
- } else {
577
- this.resolve_(
578
- PromiseState.REJECTED,
579
- promise.CancellationError.wrap(opt_reason));
580
- }
581
- };
582
-
583
-
584
- /** @override */
585
- promise.Promise.prototype.isPending = function() {
586
- return this.state_ === PromiseState.PENDING;
587
- };
588
-
589
-
590
- /** @override */
591
- promise.Promise.prototype.then = function(opt_callback, opt_errback) {
592
- return this.addCallback_(
593
- opt_callback, opt_errback, 'then', promise.Promise.prototype.then);
594
- };
595
-
596
-
597
- /** @override */
598
- promise.Promise.prototype.thenCatch = function(errback) {
599
- return this.addCallback_(
600
- null, errback, 'thenCatch', promise.Promise.prototype.thenCatch);
601
- };
602
-
603
-
604
- /** @override */
605
- promise.Promise.prototype.thenFinally = function(callback) {
606
- var error;
607
- var mustThrow = false;
608
- return this.then(function() {
609
- return callback();
610
- }, function(err) {
611
- error = err;
612
- mustThrow = true;
613
- return callback();
614
- }).then(function() {
615
- if (mustThrow) {
616
- throw error;
617
- }
618
- });
619
- };
620
-
621
-
622
- /**
623
- * Registers a new callback with this promise
624
- * @param {(function(T): (R|IThenable<R>)|null|undefined)} callback The
625
- * fulfillment callback.
626
- * @param {(function(*): (R|IThenable<R>)|null|undefined)} errback The
627
- * rejection callback.
628
- * @param {string} name The callback name.
629
- * @param {!Function} fn The function to use as the top of the stack when
630
- * recording the callback's creation point.
631
- * @return {!promise.Promise<R>} A new promise which will be resolved with the
632
- * esult of the invoked callback.
633
- * @template R
634
- * @private
635
- */
636
- promise.Promise.prototype.addCallback_ = function(callback, errback, name, fn) {
637
- if (!goog.isFunction(callback) && !goog.isFunction(errback)) {
638
- return this;
639
- }
640
-
641
- this.handled_ = true;
642
- var cb = new Callback(this, callback, errback, name, fn);
643
-
644
- if (!this.callbacks_) {
645
- this.callbacks_ = [];
646
- }
647
- this.callbacks_.push(cb);
648
-
649
- if (this.state_ !== PromiseState.PENDING &&
650
- this.state_ !== PromiseState.BLOCKED) {
651
- this.flow_.getSchedulingFrame_().addChild(cb.frame_);
652
- this.scheduleNotifications_();
653
- }
654
- return cb.promise;
655
- };
656
-
657
-
658
- /**
659
- * Represents a value that will be resolved at some point in the future. This
660
- * class represents the protected "producer" half of a Promise - each Deferred
661
- * has a {@code promise} property that may be returned to consumers for
662
- * registering callbacks, reserving the ability to resolve the deferred to the
663
- * producer.
664
- *
665
- * If this Deferred is rejected and there are no listeners registered before
666
- * the next turn of the event loop, the rejection will be passed to the
667
- * {@link webdriver.promise.ControlFlow} as an unhandled failure.
668
- *
669
- * @param {promise.ControlFlow=} opt_flow The control flow
670
- * this instance was created under. This should only be provided during
671
- * unit tests.
672
- * @constructor
673
- * @implements {promise.Thenable<T>}
674
- * @template T
675
- */
676
- promise.Deferred = function(opt_flow) {
677
- var fulfill, reject;
678
-
679
- /** @type {!promise.Promise<T>} */
680
- this.promise = new promise.Promise(function(f, r) {
681
- fulfill = f;
682
- reject = r;
683
- }, opt_flow);
684
-
685
- var self = this;
686
- var checkNotSelf = function(value) {
687
- if (value === self) {
688
- throw new TypeError('May not resolve a Deferred with itself');
689
- }
690
- };
691
-
692
- /**
693
- * Resolves this deferred with the given value. It is safe to call this as a
694
- * normal function (with no bound "this").
695
- * @param {(T|IThenable<T>|Thenable)=} opt_value The fulfilled value.
696
- */
697
- this.fulfill = function(opt_value) {
698
- checkNotSelf(opt_value);
699
- fulfill(opt_value);
700
- };
701
-
702
- /**
703
- * Rejects this promise with the given reason. It is safe to call this as a
704
- * normal function (with no bound "this").
705
- * @param {*=} opt_reason The rejection reason.
706
- */
707
- this.reject = function(opt_reason) {
708
- checkNotSelf(opt_reason);
709
- reject(opt_reason);
710
- };
711
- };
712
- promise.Thenable.addImplementation(promise.Deferred);
713
-
714
-
715
- /** @override */
716
- promise.Deferred.prototype.isPending = function() {
717
- return this.promise.isPending();
718
- };
719
-
720
-
721
- /** @override */
722
- promise.Deferred.prototype.cancel = function(opt_reason) {
723
- this.promise.cancel(opt_reason);
724
- };
725
-
726
-
727
- /**
728
- * @override
729
- * @deprecated Use {@code then} from the promise property directly.
730
- */
731
- promise.Deferred.prototype.then = function(opt_cb, opt_eb) {
732
- return this.promise.then(opt_cb, opt_eb);
733
- };
734
-
735
-
736
- /**
737
- * @override
738
- * @deprecated Use {@code thenCatch} from the promise property directly.
739
- */
740
- promise.Deferred.prototype.thenCatch = function(opt_eb) {
741
- return this.promise.thenCatch(opt_eb);
742
- };
743
-
744
-
745
- /**
746
- * @override
747
- * @deprecated Use {@code thenFinally} from the promise property directly.
748
- */
749
- promise.Deferred.prototype.thenFinally = function(opt_cb) {
750
- return this.promise.thenFinally(opt_cb);
751
- };
752
-
753
-
754
- /**
755
- * Tests if a value is an Error-like object. This is more than an straight
756
- * instanceof check since the value may originate from another context.
757
- * @param {*} value The value to test.
758
- * @return {boolean} Whether the value is an error.
759
- */
760
- function isError(value) {
761
- return value instanceof Error ||
762
- goog.isObject(value) &&
763
- (goog.isString(value.message) ||
764
- // A special test for goog.testing.JsUnitException.
765
- value.isJsUnitException);
766
-
767
- };
768
-
769
-
770
- /**
771
- * Determines whether a {@code value} should be treated as a promise.
772
- * Any object whose "then" property is a function will be considered a promise.
773
- *
774
- * @param {*} value The value to test.
775
- * @return {boolean} Whether the value is a promise.
776
- */
777
- promise.isPromise = function(value) {
778
- return !!value && goog.isObject(value) &&
779
- // Use array notation so the Closure compiler does not obfuscate away our
780
- // contract. Use typeof rather than goog.isFunction because
781
- // goog.isFunction accepts instanceof Function, which the promise spec
782
- // does not.
783
- typeof value['then'] === 'function';
784
- };
785
-
786
-
787
- /**
788
- * Creates a promise that will be resolved at a set time in the future.
789
- * @param {number} ms The amount of time, in milliseconds, to wait before
790
- * resolving the promise.
791
- * @return {!promise.Promise} The promise.
792
- */
793
- promise.delayed = function(ms) {
794
- var key;
795
- return new promise.Promise(function(fulfill) {
796
- key = setTimeout(function() {
797
- key = null;
798
- fulfill();
799
- }, ms);
800
- }).thenCatch(function(e) {
801
- clearTimeout(key);
802
- key = null;
803
- throw e;
804
- });
805
- };
806
-
807
-
808
- /**
809
- * Creates a new deferred object.
810
- * @return {!promise.Deferred<T>} The new deferred object.
811
- * @template T
812
- */
813
- promise.defer = function() {
814
- return new promise.Deferred();
815
- };
816
-
817
-
818
- /**
819
- * Creates a promise that has been resolved with the given value.
820
- * @param {T=} opt_value The resolved value.
821
- * @return {!promise.Promise<T>} The resolved promise.
822
- * @template T
823
- */
824
- promise.fulfilled = function(opt_value) {
825
- if (opt_value instanceof promise.Promise) {
826
- return opt_value;
827
- }
828
- return new promise.Promise(function(fulfill) {
829
- fulfill(opt_value);
830
- });
831
- };
832
-
833
-
834
- /**
835
- * Creates a promise that has been rejected with the given reason.
836
- * @param {*=} opt_reason The rejection reason; may be any value, but is
837
- * usually an Error or a string.
838
- * @return {!promise.Promise<T>} The rejected promise.
839
- * @template T
840
- */
841
- promise.rejected = function(opt_reason) {
842
- if (opt_reason instanceof promise.Promise) {
843
- return opt_reason;
844
- }
845
- return new promise.Promise(function(_, reject) {
846
- reject(opt_reason);
847
- });
848
- };
849
-
850
-
851
- /**
852
- * Wraps a function that expects a node-style callback as its final
853
- * argument. This callback expects two arguments: an error value (which will be
854
- * null if the call succeeded), and the success value as the second argument.
855
- * The callback will the resolve or reject the returned promise, based on its arguments.
856
- * @param {!Function} fn The function to wrap.
857
- * @param {...?} var_args The arguments to apply to the function, excluding the
858
- * final callback.
859
- * @return {!promise.Promise} A promise that will be resolved with the
860
- * result of the provided function's callback.
861
- */
862
- promise.checkedNodeCall = function(fn, var_args) {
863
- var args = Arrays.slice(arguments, 1);
864
- return new promise.Promise(function(fulfill, reject) {
865
- try {
866
- args.push(function(error, value) {
867
- error ? reject(error) : fulfill(value);
868
- });
869
- fn.apply(undefined, args);
870
- } catch (ex) {
871
- reject(ex);
872
- }
873
- });
874
- };
875
-
876
-
877
- /**
878
- * Registers an observer on a promised {@code value}, returning a new promise
879
- * that will be resolved when the value is. If {@code value} is not a promise,
880
- * then the return promise will be immediately resolved.
881
- * @param {*} value The value to observe.
882
- * @param {Function=} opt_callback The function to call when the value is
883
- * resolved successfully.
884
- * @param {Function=} opt_errback The function to call when the value is
885
- * rejected.
886
- * @return {!promise.Promise} A new promise.
887
- */
888
- promise.when = function(value, opt_callback, opt_errback) {
889
- if (promise.Thenable.isImplementation(value)) {
890
- return value.then(opt_callback, opt_errback);
891
- }
892
-
893
- return new promise.Promise(function(fulfill, reject) {
894
- promise.asap(value, fulfill, reject);
895
- }).then(opt_callback, opt_errback);
896
- };
897
-
898
-
899
- /**
900
- * Invokes the appropriate callback function as soon as a promised
901
- * {@code value} is resolved. This function is similar to
902
- * {@link webdriver.promise.when}, except it does not return a new promise.
903
- * @param {*} value The value to observe.
904
- * @param {Function} callback The function to call when the value is
905
- * resolved successfully.
906
- * @param {Function=} opt_errback The function to call when the value is
907
- * rejected.
908
- */
909
- promise.asap = function(value, callback, opt_errback) {
910
- if (promise.isPromise(value)) {
911
- value.then(callback, opt_errback);
912
-
913
- // Maybe a Dojo-like deferred object?
914
- } else if (!!value && goog.isObject(value) &&
915
- goog.isFunction(value.addCallbacks)) {
916
- value.addCallbacks(callback, opt_errback);
917
-
918
- // A raw value, return a resolved promise.
919
- } else if (callback) {
920
- callback(value);
921
- }
922
- };
923
-
924
-
925
- /**
926
- * Given an array of promises, will return a promise that will be fulfilled
927
- * with the fulfillment values of the input array's values. If any of the
928
- * input array's promises are rejected, the returned promise will be rejected
929
- * with the same reason.
930
- *
931
- * @param {!Array<(T|!promise.Promise<T>)>} arr An array of
932
- * promises to wait on.
933
- * @return {!promise.Promise<!Array<T>>} A promise that is
934
- * fulfilled with an array containing the fulfilled values of the
935
- * input array, or rejected with the same reason as the first
936
- * rejected value.
937
- * @template T
938
- */
939
- promise.all = function(arr) {
940
- return new promise.Promise(function(fulfill, reject) {
941
- var n = arr.length;
942
- var values = [];
943
-
944
- if (!n) {
945
- fulfill(values);
946
- return;
947
- }
948
-
949
- var toFulfill = n;
950
- var onFulfilled = function(index, value) {
951
- values[index] = value;
952
- toFulfill--;
953
- if (toFulfill == 0) {
954
- fulfill(values);
955
- }
956
- };
957
-
958
- for (var i = 0; i < n; ++i) {
959
- promise.asap(arr[i], goog.partial(onFulfilled, i), reject);
960
- }
961
- });
962
- };
963
-
964
-
965
- /**
966
- * Calls a function for each element in an array and inserts the result into a
967
- * new array, which is used as the fulfillment value of the promise returned
968
- * by this function.
969
- *
970
- * If the return value of the mapping function is a promise, this function
971
- * will wait for it to be fulfilled before inserting it into the new array.
972
- *
973
- * If the mapping function throws or returns a rejected promise, the
974
- * promise returned by this function will be rejected with the same reason.
975
- * Only the first failure will be reported; all subsequent errors will be
976
- * silently ignored.
977
- *
978
- * @param {!(Array<TYPE>|promise.Promise<!Array<TYPE>>)} arr The
979
- * array to iterator over, or a promise that will resolve to said array.
980
- * @param {function(this: SELF, TYPE, number, !Array<TYPE>): ?} fn The
981
- * function to call for each element in the array. This function should
982
- * expect three arguments (the element, the index, and the array itself.
983
- * @param {SELF=} opt_self The object to be used as the value of 'this' within
984
- * {@code fn}.
985
- * @template TYPE, SELF
986
- */
987
- promise.map = function(arr, fn, opt_self) {
988
- return promise.fulfilled(arr).then(function(arr) {
989
- goog.asserts.assertNumber(arr.length, 'not an array like value');
990
- return new promise.Promise(function(fulfill, reject) {
991
- var n = arr.length;
992
- var values = new Array(n);
993
- (function processNext(i) {
994
- for (; i < n; i++) {
995
- if (i in arr) {
996
- break;
997
- }
998
- }
999
- if (i >= n) {
1000
- fulfill(values);
1001
- return;
1002
- }
1003
- try {
1004
- promise.asap(
1005
- fn.call(opt_self, arr[i], i, /** @type {!Array} */(arr)),
1006
- function(value) {
1007
- values[i] = value;
1008
- processNext(i + 1);
1009
- },
1010
- reject);
1011
- } catch (ex) {
1012
- reject(ex);
1013
- }
1014
- })(0);
1015
- });
1016
- });
1017
- };
1018
-
1019
-
1020
- /**
1021
- * Calls a function for each element in an array, and if the function returns
1022
- * true adds the element to a new array.
1023
- *
1024
- * If the return value of the filter function is a promise, this function
1025
- * will wait for it to be fulfilled before determining whether to insert the
1026
- * element into the new array.
1027
- *
1028
- * If the filter function throws or returns a rejected promise, the promise
1029
- * returned by this function will be rejected with the same reason. Only the
1030
- * first failure will be reported; all subsequent errors will be silently
1031
- * ignored.
1032
- *
1033
- * @param {!(Array<TYPE>|promise.Promise<!Array<TYPE>>)} arr The
1034
- * array to iterator over, or a promise that will resolve to said array.
1035
- * @param {function(this: SELF, TYPE, number, !Array<TYPE>): (
1036
- * boolean|promise.Promise<boolean>)} fn The function
1037
- * to call for each element in the array.
1038
- * @param {SELF=} opt_self The object to be used as the value of 'this' within
1039
- * {@code fn}.
1040
- * @template TYPE, SELF
1041
- */
1042
- promise.filter = function(arr, fn, opt_self) {
1043
- return promise.fulfilled(arr).then(function(arr) {
1044
- goog.asserts.assertNumber(arr.length, 'not an array like value');
1045
- return new promise.Promise(function(fulfill, reject) {
1046
- var n = arr.length;
1047
- var values = [];
1048
- var valuesLength = 0;
1049
- (function processNext(i) {
1050
- for (; i < n; i++) {
1051
- if (i in arr) {
1052
- break;
1053
- }
1054
- }
1055
- if (i >= n) {
1056
- fulfill(values);
1057
- return;
1058
- }
1059
- try {
1060
- var value = arr[i];
1061
- var include = fn.call(opt_self, value, i, /** @type {!Array} */(arr));
1062
- promise.asap(include, function(include) {
1063
- if (include) {
1064
- values[valuesLength++] = value;
1065
- }
1066
- processNext(i + 1);
1067
- }, reject);
1068
- } catch (ex) {
1069
- reject(ex);
1070
- }
1071
- })(0);
1072
- });
1073
- });
1074
- };
1075
-
1076
-
1077
- /**
1078
- * Returns a promise that will be resolved with the input value in a
1079
- * fully-resolved state. If the value is an array, each element will be fully
1080
- * resolved. Likewise, if the value is an object, all keys will be fully
1081
- * resolved. In both cases, all nested arrays and objects will also be
1082
- * fully resolved. All fields are resolved in place; the returned promise will
1083
- * resolve on {@code value} and not a copy.
1084
- *
1085
- * Warning: This function makes no checks against objects that contain
1086
- * cyclical references:
1087
- *
1088
- * var value = {};
1089
- * value['self'] = value;
1090
- * promise.fullyResolved(value); // Stack overflow.
1091
- *
1092
- * @param {*} value The value to fully resolve.
1093
- * @return {!promise.Promise} A promise for a fully resolved version
1094
- * of the input value.
1095
- */
1096
- promise.fullyResolved = function(value) {
1097
- if (promise.isPromise(value)) {
1098
- return promise.when(value, fullyResolveValue);
1099
- }
1100
- return fullyResolveValue(value);
1101
- };
1102
-
1103
-
1104
- /**
1105
- * @param {*} value The value to fully resolve. If a promise, assumed to
1106
- * already be resolved.
1107
- * @return {!promise.Promise} A promise for a fully resolved version
1108
- * of the input value.
1109
- */
1110
- function fullyResolveValue(value) {
1111
- switch (goog.typeOf(value)) {
1112
- case 'array':
1113
- return fullyResolveKeys(/** @type {!Array} */ (value));
1114
-
1115
- case 'object':
1116
- if (promise.isPromise(value)) {
1117
- // We get here when the original input value is a promise that
1118
- // resolves to itself. When the user provides us with such a promise,
1119
- // trust that it counts as a "fully resolved" value and return it.
1120
- // Of course, since it's already a promise, we can just return it
1121
- // to the user instead of wrapping it in another promise.
1122
- return /** @type {!promise.Promise} */ (value);
1123
- }
1124
-
1125
- if (goog.isNumber(value.nodeType) &&
1126
- goog.isObject(value.ownerDocument) &&
1127
- goog.isNumber(value.ownerDocument.nodeType)) {
1128
- // DOM node; return early to avoid infinite recursion. Should we
1129
- // only support objects with a certain level of nesting?
1130
- return promise.fulfilled(value);
1131
- }
1132
-
1133
- return fullyResolveKeys(/** @type {!Object} */ (value));
1134
-
1135
- default: // boolean, function, null, number, string, undefined
1136
- return promise.fulfilled(value);
1137
- }
1138
- };
1139
-
1140
-
1141
- /**
1142
- * @param {!(Array|Object)} obj the object to resolve.
1143
- * @return {!promise.Promise} A promise that will be resolved with the
1144
- * input object once all of its values have been fully resolved.
1145
- */
1146
- function fullyResolveKeys(obj) {
1147
- var isArray = goog.isArray(obj);
1148
- var numKeys = isArray ? obj.length : Objects.getCount(obj);
1149
- if (!numKeys) {
1150
- return promise.fulfilled(obj);
1151
- }
1152
-
1153
- var numResolved = 0;
1154
- return new promise.Promise(function(fulfill, reject) {
1155
- // In pre-IE9, goog.array.forEach will not iterate properly over arrays
1156
- // containing undefined values because "index in array" returns false
1157
- // when array[index] === undefined (even for x = [undefined, 1]). To get
1158
- // around this, we need to use our own forEach implementation.
1159
- // DO NOT REMOVE THIS UNTIL WE NO LONGER SUPPORT IE8. This cannot be
1160
- // reproduced in IE9 by changing the browser/document modes, it requires an
1161
- // actual pre-IE9 browser. Yay, IE!
1162
- var forEachKey = !isArray ? Objects.forEach : function(arr, fn) {
1163
- var n = arr.length;
1164
- for (var i = 0; i < n; ++i) {
1165
- fn.call(null, arr[i], i, arr);
1166
- }
1167
- };
1168
-
1169
- forEachKey(obj, function(partialValue, key) {
1170
- var type = goog.typeOf(partialValue);
1171
- if (type != 'array' && type != 'object') {
1172
- maybeResolveValue();
1173
- return;
1174
- }
1175
-
1176
- promise.fullyResolved(partialValue).then(
1177
- function(resolvedValue) {
1178
- obj[key] = resolvedValue;
1179
- maybeResolveValue();
1180
- },
1181
- reject);
1182
- });
1183
-
1184
- function maybeResolveValue() {
1185
- if (++numResolved == numKeys) {
1186
- fulfill(obj);
1187
- }
1188
- }
1189
- });
1190
- };
1191
-
1192
-
1193
- //////////////////////////////////////////////////////////////////////////////
1194
- //
1195
- // promise.ControlFlow
1196
- //
1197
- //////////////////////////////////////////////////////////////////////////////
1198
-
1199
-
1200
-
1201
- /**
1202
- * Handles the execution of scheduled tasks, each of which may be an
1203
- * asynchronous operation. The control flow will ensure tasks are executed in
1204
- * the ordered scheduled, starting each task only once those before it have
1205
- * completed.
1206
- *
1207
- * Each task scheduled within this flow may return a
1208
- * {@link webdriver.promise.Promise} to indicate it is an asynchronous
1209
- * operation. The ControlFlow will wait for such promises to be resolved before
1210
- * marking the task as completed.
1211
- *
1212
- * Tasks and each callback registered on a {@link webdriver.promise.Promise}
1213
- * will be run in their own ControlFlow frame. Any tasks scheduled within a
1214
- * frame will take priority over previously scheduled tasks. Furthermore, if any
1215
- * of the tasks in the frame fail, the remainder of the tasks in that frame will
1216
- * be discarded and the failure will be propagated to the user through the
1217
- * callback/task's promised result.
1218
- *
1219
- * Each time a ControlFlow empties its task queue, it will fire an
1220
- * {@link webdriver.promise.ControlFlow.EventType.IDLE IDLE} event. Conversely,
1221
- * whenever the flow terminates due to an unhandled error, it will remove all
1222
- * remaining tasks in its queue and fire an
1223
- * {@link webdriver.promise.ControlFlow.EventType.UNCAUGHT_EXCEPTION
1224
- * UNCAUGHT_EXCEPTION} event. If there are no listeners registered with the
1225
- * flow, the error will be rethrown to the global error handler.
1226
- *
1227
- * @constructor
1228
- * @extends {EventEmitter}
1229
- * @final
1230
- */
1231
- promise.ControlFlow = function() {
1232
- EventEmitter.call(this);
1233
- goog.getUid(this);
1234
-
1235
- /**
1236
- * Tracks the active execution frame for this instance. Lazily initialized
1237
- * when the first task is scheduled.
1238
- * @private {Frame}
1239
- */
1240
- this.activeFrame_ = null;
1241
-
1242
- /**
1243
- * A reference to the frame which is currently top of the stack in
1244
- * {@link #runInFrame_}. The {@link #activeFrame_} will always be an ancestor
1245
- * of the {@link #runningFrame_}, but the two will often not be the same. The
1246
- * active frame represents which frame is currently executing a task while the
1247
- * running frame represents either the task itself or a promise callback which
1248
- * has fired asynchronously.
1249
- * @private {Frame}
1250
- */
1251
- this.runningFrame_ = null;
1252
-
1253
- /**
1254
- * A reference to the frame in which new tasks should be scheduled. If
1255
- * {@code null}, tasks will be scheduled within the active frame. When forcing
1256
- * a function to run in the context of a new frame, this pointer is used to
1257
- * ensure tasks are scheduled within the newly created frame, even though it
1258
- * won't be active yet.
1259
- * @private {Frame}
1260
- * @see {#runInFrame_}
1261
- */
1262
- this.schedulingFrame_ = null;
1263
-
1264
- /**
1265
- * Micro task that controls shutting down the control flow. Upon shut down,
1266
- * the flow will emit an {@link webdriver.promise.ControlFlow.EventType.IDLE}
1267
- * event. Idle events always follow a brief timeout in order to catch latent
1268
- * errors from the last completed task. If this task had a callback
1269
- * registered, but no errback, and the task fails, the unhandled failure would
1270
- * not be reported by the promise system until the next turn of the event
1271
- * loop:
1272
- *
1273
- * // Schedule 1 task that fails.
1274
- * var result = promise.controlFlow().schedule('example',
1275
- * function() { return promise.rejected('failed'); });
1276
- * // Set a callback on the result. This delays reporting the unhandled
1277
- * // failure for 1 turn of the event loop.
1278
- * result.then(goog.nullFunction);
1279
- *
1280
- * @private {MicroTask}
1281
- */
1282
- this.shutdownTask_ = null;
1283
-
1284
- /**
1285
- * Micro task used to trigger execution of this instance's event loop.
1286
- * @private {MicroTask}
1287
- */
1288
- this.eventLoopTask_ = null;
1289
-
1290
- /**
1291
- * ID for a long running interval used to keep a Node.js process running
1292
- * while a control flow's event loop has yielded. This is a cheap hack
1293
- * required since the {@link #runEventLoop_} is only scheduled to run when
1294
- * there is _actually_ something to run. When a control flow is waiting on
1295
- * a task, there will be nothing in the JS event loop and the process would
1296
- * terminate without this.
1297
- *
1298
- * An alternative solution would be to change {@link #runEventLoop_} to run
1299
- * as an interval rather than as on-demand micro-tasks. While this approach
1300
- * (which was previously used) requires fewer micro-task allocations, it
1301
- * results in many unnecessary invocations of {@link #runEventLoop_}.
1302
- *
1303
- * @private {?number}
1304
- */
1305
- this.hold_ = null;
1306
-
1307
- /**
1308
- * The number of holds placed on this flow. These represent points where the
1309
- * flow must not execute any further actions so an asynchronous action may
1310
- * run first. One such example are notifications fired by a
1311
- * {@link webdriver.promise.Promise}: the Promise spec requires that callbacks
1312
- * are invoked in a turn of the event loop after they are scheduled. To ensure
1313
- * tasks within a callback are scheduled in the correct frame, a promise will
1314
- * make the parent flow yield before its notifications are fired.
1315
- * @private {number}
1316
- */
1317
- this.yieldCount_ = 0;
1318
- };
1319
- goog.inherits(promise.ControlFlow, EventEmitter);
1320
-
1321
-
1322
- /**
1323
- * Events that may be emitted by an {@link webdriver.promise.ControlFlow}.
1324
- * @enum {string}
1325
- */
1326
- promise.ControlFlow.EventType = {
1327
-
1328
- /** Emitted when all tasks have been successfully executed. */
1329
- IDLE: 'idle',
1330
-
1331
- /** Emitted when a ControlFlow has been reset. */
1332
- RESET: 'reset',
1333
-
1334
- /** Emitted whenever a new task has been scheduled. */
1335
- SCHEDULE_TASK: 'scheduleTask',
1336
-
1337
- /**
1338
- * Emitted whenever a control flow aborts due to an unhandled promise
1339
- * rejection. This event will be emitted along with the offending rejection
1340
- * reason. Upon emitting this event, the control flow will empty its task
1341
- * queue and revert to its initial state.
1342
- */
1343
- UNCAUGHT_EXCEPTION: 'uncaughtException'
1344
- };
1345
-
1346
-
1347
- /**
1348
- * Returns a string representation of this control flow, which is its current
1349
- * {@link #getSchedule() schedule}, sans task stack traces.
1350
- * @return {string} The string representation of this contorl flow.
1351
- * @override
1352
- */
1353
- promise.ControlFlow.prototype.toString = function() {
1354
- return this.getSchedule();
1355
- };
1356
-
1357
-
1358
- /**
1359
- * Resets this instance, clearing its queue and removing all event listeners.
1360
- */
1361
- promise.ControlFlow.prototype.reset = function() {
1362
- this.activeFrame_ = null;
1363
- this.schedulingFrame_ = null;
1364
- this.emit(promise.ControlFlow.EventType.RESET);
1365
- this.removeAllListeners();
1366
- this.cancelShutdown_();
1367
- this.cancelEventLoop_();
1368
- };
1369
-
1370
-
1371
- /**
1372
- * Generates an annotated string describing the internal state of this control
1373
- * flow, including the currently executing as well as pending tasks. If
1374
- * {@code opt_includeStackTraces === true}, the string will include the
1375
- * stack trace from when each task was scheduled.
1376
- * @param {string=} opt_includeStackTraces Whether to include the stack traces
1377
- * from when each task was scheduled. Defaults to false.
1378
- * @return {string} String representation of this flow's internal state.
1379
- */
1380
- promise.ControlFlow.prototype.getSchedule = function(opt_includeStackTraces) {
1381
- var ret = 'ControlFlow::' + goog.getUid(this);
1382
- var activeFrame = this.activeFrame_;
1383
- var runningFrame = this.runningFrame_;
1384
- if (!activeFrame) {
1385
- return ret;
1386
- }
1387
- var childIndent = '| ';
1388
- return ret + '\n' + toStringHelper(activeFrame.getRoot(), childIndent);
1389
-
1390
- /**
1391
- * @param {!(Frame|Task)} node .
1392
- * @param {string} indent .
1393
- * @param {boolean=} opt_isPending .
1394
- * @return {string} .
1395
- */
1396
- function toStringHelper(node, indent, opt_isPending) {
1397
- var ret = node.toString();
1398
- if (opt_isPending) {
1399
- ret = '(pending) ' + ret;
1400
- }
1401
- if (node === activeFrame) {
1402
- ret = '(active) ' + ret;
1403
- }
1404
- if (node === runningFrame) {
1405
- ret = '(running) ' + ret;
1406
- }
1407
- if (node instanceof Frame) {
1408
- if (node.getPendingTask()) {
1409
- ret += '\n' + toStringHelper(
1410
- /** @type {!Task} */(node.getPendingTask()),
1411
- childIndent,
1412
- true);
1413
- }
1414
- if (node.children_) {
1415
- node.children_.forEach(function(child) {
1416
- if (!node.getPendingTask() ||
1417
- node.getPendingTask().getFrame() !== child) {
1418
- ret += '\n' + toStringHelper(child, childIndent);
1419
- }
1420
- });
1421
- }
1422
- } else {
1423
- var task = /** @type {!Task} */(node);
1424
- if (opt_includeStackTraces && task.promise.stack_) {
1425
- ret += '\n' + childIndent +
1426
- (task.promise.stack_.stack || task.promise.stack_).
1427
- replace(/\n/g, '\n' + childIndent);
1428
- }
1429
- if (task.getFrame()) {
1430
- ret += '\n' + toStringHelper(
1431
- /** @type {!Frame} */(task.getFrame()),
1432
- childIndent);
1433
- }
1434
- }
1435
- return indent + ret.replace(/\n/g, '\n' + indent);
1436
- }
1437
- };
1438
-
1439
-
1440
- /**
1441
- * @return {!Frame} The active frame for this flow.
1442
- * @private
1443
- */
1444
- promise.ControlFlow.prototype.getActiveFrame_ = function() {
1445
- this.cancelShutdown_();
1446
- if (!this.activeFrame_) {
1447
- this.activeFrame_ = new Frame(this);
1448
- this.activeFrame_.once(Frame.ERROR_EVENT, this.abortNow_, this);
1449
- this.scheduleEventLoopStart_();
1450
- }
1451
- return this.activeFrame_;
1452
- };
1453
-
1454
-
1455
- /**
1456
- * @return {!Frame} The frame that new items should be added to.
1457
- * @private
1458
- */
1459
- promise.ControlFlow.prototype.getSchedulingFrame_ = function() {
1460
- return this.schedulingFrame_ || this.getActiveFrame_();
1461
- };
1462
-
1463
-
1464
- /**
1465
- * @return {!Frame} The frame that is current executing.
1466
- * @private
1467
- */
1468
- promise.ControlFlow.prototype.getRunningFrame_ = function() {
1469
- return this.runningFrame_ || this.getActiveFrame_();
1470
- };
1471
-
1472
-
1473
- /**
1474
- * Schedules a task for execution. If there is nothing currently in the
1475
- * queue, the task will be executed in the next turn of the event loop. If
1476
- * the task function is a generator, the task will be executed using
1477
- * {@link webdriver.promise.consume}.
1478
- *
1479
- * @param {function(): (T|promise.Promise<T>)} fn The function to
1480
- * call to start the task. If the function returns a
1481
- * {@link webdriver.promise.Promise}, this instance will wait for it to be
1482
- * resolved before starting the next task.
1483
- * @param {string=} opt_description A description of the task.
1484
- * @return {!promise.Promise<T>} A promise that will be resolved
1485
- * with the result of the action.
1486
- * @template T
1487
- */
1488
- promise.ControlFlow.prototype.execute = function(fn, opt_description) {
1489
- if (promise.isGenerator(fn)) {
1490
- fn = goog.partial(promise.consume, fn);
1491
- }
1492
-
1493
- if (!this.hold_) {
1494
- var holdIntervalMs = 2147483647; // 2^31-1; max timer length for Node.js
1495
- this.hold_ = setInterval(goog.nullFunction, holdIntervalMs);
1496
- }
1497
-
1498
- var description = opt_description || '<anonymous>';
1499
- var task = new Task(this, fn, description);
1500
- task.promise.stack_ = promise.captureStackTrace('Task', description,
1501
- promise.ControlFlow.prototype.execute);
1502
-
1503
- this.getSchedulingFrame_().addChild(task);
1504
- this.emit(promise.ControlFlow.EventType.SCHEDULE_TASK, opt_description);
1505
- this.scheduleEventLoopStart_();
1506
- return task.promise;
1507
- };
1508
-
1509
-
1510
- /**
1511
- * Inserts a {@code setTimeout} into the command queue. This is equivalent to
1512
- * a thread sleep in a synchronous programming language.
1513
- *
1514
- * @param {number} ms The timeout delay, in milliseconds.
1515
- * @param {string=} opt_description A description to accompany the timeout.
1516
- * @return {!promise.Promise} A promise that will be resolved with
1517
- * the result of the action.
1518
- */
1519
- promise.ControlFlow.prototype.timeout = function(ms, opt_description) {
1520
- return this.execute(function() {
1521
- return promise.delayed(ms);
1522
- }, opt_description);
1523
- };
1524
-
1525
-
1526
- /**
1527
- * Schedules a task that shall wait for a condition to hold. Each condition
1528
- * function may return any value, but it will always be evaluated as a boolean.
1529
- *
1530
- * Condition functions may schedule sub-tasks with this instance, however,
1531
- * their execution time will be factored into whether a wait has timed out.
1532
- *
1533
- * In the event a condition returns a Promise, the polling loop will wait for
1534
- * it to be resolved before evaluating whether the condition has been satisfied.
1535
- * The resolution time for a promise is factored into whether a wait has timed
1536
- * out.
1537
- *
1538
- * If the condition function throws, or returns a rejected promise, the
1539
- * wait task will fail.
1540
- *
1541
- * If the condition is defined as a promise, the flow will wait for it to
1542
- * settle. If the timeout expires before the promise settles, the promise
1543
- * returned by this function will be rejected.
1544
- *
1545
- * If this function is invoked with `timeout === 0`, or the timeout is omitted,
1546
- * the flow will wait indefinitely for the condition to be satisfied.
1547
- *
1548
- * @param {(!promise.Promise<T>|function())} condition The condition to poll,
1549
- * or a promise to wait on.
1550
- * @param {number=} opt_timeout How long to wait, in milliseconds, for the
1551
- * condition to hold before timing out. If omitted, the flow will wait
1552
- * indefinitely.
1553
- * @param {string=} opt_message An optional error message to include if the
1554
- * wait times out; defaults to the empty string.
1555
- * @return {!promise.Promise<T>} A promise that will be fulfilled
1556
- * when the condition has been satisified. The promise shall be rejected if
1557
- * the wait times out waiting for the condition.
1558
- * @throws {TypeError} If condition is not a function or promise or if timeout
1559
- * is not a number >= 0.
1560
- * @template T
1561
- */
1562
- promise.ControlFlow.prototype.wait = function(
1563
- condition, opt_timeout, opt_message) {
1564
- var timeout = opt_timeout || 0;
1565
- if (!goog.isNumber(timeout) || timeout < 0) {
1566
- throw TypeError('timeout must be a number >= 0: ' + timeout);
1567
- }
1568
-
1569
- if (promise.isPromise(condition)) {
1570
- return this.execute(function() {
1571
- if (!timeout) {
1572
- return condition;
1573
- }
1574
- return new promise.Promise(function(fulfill, reject) {
1575
- var start = goog.now();
1576
- var timer = setTimeout(function() {
1577
- timer = null;
1578
- reject(Error((opt_message ? opt_message + '\n' : '') +
1579
- 'Timed out waiting for promise to resolve after ' +
1580
- (goog.now() - start) + 'ms'));
1581
- }, timeout);
1582
-
1583
- /** @type {Thenable} */(condition).then(
1584
- function(value) {
1585
- timer && clearTimeout(timer);
1586
- fulfill(value);
1587
- },
1588
- function(error) {
1589
- timer && clearTimeout(timer);
1590
- reject(error);
1591
- });
1592
- });
1593
- }, opt_message || '<anonymous wait: promise resolution>');
1594
- }
1595
-
1596
- if (!goog.isFunction(condition)) {
1597
- throw TypeError('Invalid condition; must be a function or promise: ' +
1598
- goog.typeOf(condition));
1599
- }
1600
-
1601
- if (promise.isGenerator(condition)) {
1602
- condition = goog.partial(promise.consume, condition);
1603
- }
1604
-
1605
- var self = this;
1606
- return this.execute(function() {
1607
- var startTime = goog.now();
1608
- return new promise.Promise(function(fulfill, reject) {
1609
- self.suspend_();
1610
- pollCondition();
1611
-
1612
- function pollCondition() {
1613
- self.resume_();
1614
- self.execute(/**@type {function()}*/(condition)).then(function(value) {
1615
- var elapsed = goog.now() - startTime;
1616
- if (!!value) {
1617
- fulfill(value);
1618
- } else if (timeout && elapsed >= timeout) {
1619
- reject(new Error((opt_message ? opt_message + '\n' : '') +
1620
- 'Wait timed out after ' + elapsed + 'ms'));
1621
- } else {
1622
- self.suspend_();
1623
- // Do not use asyncRun here because we need a non-micro yield
1624
- // here so the UI thread is given a chance when running in a
1625
- // browser.
1626
- setTimeout(pollCondition, 0);
1627
- }
1628
- }, reject);
1629
- }
1630
- });
1631
- }, opt_message || '<anonymous wait>');
1632
- };
1633
-
1634
-
1635
- /**
1636
- * Schedules the interval for this instance's event loop, if necessary.
1637
- * @private
1638
- */
1639
- promise.ControlFlow.prototype.scheduleEventLoopStart_ = function() {
1640
- if (!this.eventLoopTask_ && !this.yieldCount_ && this.activeFrame_ &&
1641
- !this.activeFrame_.getPendingTask()) {
1642
- this.eventLoopTask_ = new MicroTask(this.runEventLoop_, this);
1643
- }
1644
- };
1645
-
1646
-
1647
- /**
1648
- * Cancels the event loop, if necessary.
1649
- * @private
1650
- */
1651
- promise.ControlFlow.prototype.cancelEventLoop_ = function() {
1652
- if (this.eventLoopTask_) {
1653
- this.eventLoopTask_.cancel();
1654
- this.eventLoopTask_ = null;
1655
- }
1656
- };
1657
-
1658
-
1659
- /**
1660
- * Suspends this control flow, preventing it from executing any more tasks.
1661
- * @private
1662
- */
1663
- promise.ControlFlow.prototype.suspend_ = function() {
1664
- this.yieldCount_ += 1;
1665
- this.cancelEventLoop_();
1666
- };
1667
-
1668
-
1669
- /**
1670
- * Resumes execution of tasks scheduled within this control flow.
1671
- * @private
1672
- */
1673
- promise.ControlFlow.prototype.resume_ = function() {
1674
- this.yieldCount_ -= 1;
1675
- if (!this.yieldCount_ && this.activeFrame_) {
1676
- this.scheduleEventLoopStart_();
1677
- }
1678
- };
1679
-
1680
-
1681
- /**
1682
- * Executes the next task for the current frame. If the current frame has no
1683
- * more tasks, the frame's result will be resolved, returning control to the
1684
- * frame's creator. This will terminate the flow if the completed frame was at
1685
- * the top of the stack.
1686
- * @private
1687
- */
1688
- promise.ControlFlow.prototype.runEventLoop_ = function() {
1689
- this.eventLoopTask_ = null;
1690
-
1691
- if (this.yieldCount_) {
1692
- return;
1693
- }
1694
-
1695
- if (!this.activeFrame_) {
1696
- this.commenceShutdown_();
1697
- return;
1698
- }
1699
-
1700
- if (this.activeFrame_.getPendingTask()) {
1701
- return;
1702
- }
1703
-
1704
- var task = this.getNextTask_();
1705
- if (!task) {
1706
- return;
1707
- }
1708
-
1709
- var activeFrame = this.activeFrame_;
1710
- var scheduleEventLoop = goog.bind(this.scheduleEventLoopStart_, this);
1711
-
1712
- var onSuccess = function(value) {
1713
- activeFrame.setPendingTask(null);
1714
- task.setFrame(null);
1715
- task.fulfill(value);
1716
- scheduleEventLoop();
1717
- };
1718
-
1719
- var onFailure = function(reason) {
1720
- activeFrame.setPendingTask(null);
1721
- task.setFrame(null);
1722
- task.reject(reason);
1723
- scheduleEventLoop();
1724
- };
1725
-
1726
- activeFrame.setPendingTask(task);
1727
- var frame = new Frame(this);
1728
- task.setFrame(frame);
1729
- this.runInFrame_(frame, task.execute, function(result) {
1730
- promise.asap(result, onSuccess, onFailure);
1731
- }, onFailure, true);
1732
- };
1733
-
1734
-
1735
- /**
1736
- * @return {Task} The next task to execute, or
1737
- * {@code null} if a frame was resolved.
1738
- * @private
1739
- */
1740
- promise.ControlFlow.prototype.getNextTask_ = function() {
1741
- var frame = this.activeFrame_;
1742
- var firstChild = frame.getFirstChild();
1743
- if (!firstChild) {
1744
- if (!frame.pendingCallback && !frame.isBlocked_) {
1745
- this.resolveFrame_(frame);
1746
- }
1747
- return null;
1748
- }
1749
-
1750
- if (firstChild instanceof Frame) {
1751
- this.activeFrame_ = firstChild;
1752
- return this.getNextTask_();
1753
- }
1754
-
1755
- frame.removeChild(firstChild);
1756
- if (!firstChild.isPending()) {
1757
- return this.getNextTask_();
1758
- }
1759
- return firstChild;
1760
- };
1761
-
1762
-
1763
- /**
1764
- * @param {!Frame} frame The frame to resolve.
1765
- * @private
1766
- */
1767
- promise.ControlFlow.prototype.resolveFrame_ = function(frame) {
1768
- if (this.activeFrame_ === frame) {
1769
- this.activeFrame_ = frame.getParent();
1770
- }
1771
-
1772
- if (frame.getParent()) {
1773
- frame.getParent().removeChild(frame);
1774
- }
1775
- frame.emit(Frame.CLOSE_EVENT);
1776
-
1777
- if (!this.activeFrame_) {
1778
- this.commenceShutdown_();
1779
- } else {
1780
- this.scheduleEventLoopStart_();
1781
- }
1782
- };
1783
-
1784
-
1785
- /**
1786
- * Aborts the current frame. The frame, and all of the tasks scheduled within it
1787
- * will be discarded. If this instance does not have an active frame, it will
1788
- * immediately terminate all execution.
1789
- * @param {*} error The reason the frame is being aborted; typically either
1790
- * an Error or string.
1791
- * @param {Frame=} opt_frame The frame to abort; will use the
1792
- * currently active frame if not specified.
1793
- * @private
1794
- */
1795
- promise.ControlFlow.prototype.abortFrame_ = function(error, opt_frame) {
1796
- if (!this.activeFrame_) {
1797
- this.abortNow_(error);
1798
- return;
1799
- }
1800
-
1801
- // Frame parent is always another frame, but the compiler is not smart
1802
- // enough to recognize this.
1803
- var parent = /** @type {Frame} */ (
1804
- this.activeFrame_.getParent());
1805
- if (parent) {
1806
- parent.removeChild(this.activeFrame_);
1807
- }
1808
-
1809
- var frame = this.activeFrame_;
1810
- this.activeFrame_ = parent;
1811
- frame.abort(error);
1812
- };
1813
-
1814
-
1815
- /**
1816
- * Executes a function within a specific frame. If the function does not
1817
- * schedule any new tasks, the frame will be discarded and the function's result
1818
- * returned passed to the given callback immediately. Otherwise, the callback
1819
- * will be invoked once all of the tasks scheduled within the function have been
1820
- * completed. If the frame is aborted, the `errback` will be invoked with the
1821
- * offending error.
1822
- *
1823
- * @param {!Frame} newFrame The frame to use.
1824
- * @param {!Function} fn The function to execute.
1825
- * @param {function(T)} callback The function to call with a successful result.
1826
- * @param {function(*)} errback The function to call if there is an error.
1827
- * @param {boolean=} opt_isTask Whether the function is a task and the frame
1828
- * should be immediately activated to capture subtasks and errors.
1829
- * @throws {Error} If this function is invoked while another call to this
1830
- * function is present on the stack.
1831
- * @template T
1832
- * @private
1833
- */
1834
- promise.ControlFlow.prototype.runInFrame_ = function(
1835
- newFrame, fn, callback, errback, opt_isTask) {
1836
- asserts.assert(
1837
- !this.runningFrame_, 'unexpected recursive call to runInFrame');
1838
-
1839
- var self = this,
1840
- oldFrame = this.activeFrame_;
1841
-
1842
- try {
1843
- if (this.activeFrame_ !== newFrame && !newFrame.getParent()) {
1844
- this.activeFrame_.addChild(newFrame);
1845
- }
1846
-
1847
- // Activate the new frame to force tasks to be treated as sub-tasks of
1848
- // the parent frame.
1849
- if (opt_isTask) {
1850
- this.activeFrame_ = newFrame;
1851
- }
1852
-
1853
- try {
1854
- this.runningFrame_ = newFrame;
1855
- this.schedulingFrame_ = newFrame;
1856
- activeFlows.push(this);
1857
- var result = fn();
1858
- } finally {
1859
- activeFlows.pop();
1860
- this.schedulingFrame_ = null;
1861
-
1862
- // `newFrame` should only be considered the running frame when it is
1863
- // actually executing. After it finishes, set top of stack to its parent
1864
- // so any failures/interrupts that occur while processing newFrame's
1865
- // result are handled there.
1866
- this.runningFrame_ = newFrame.parent_;
1867
- }
1868
- newFrame.isLocked_ = true;
1869
-
1870
- // If there was nothing scheduled in the new frame we can discard the
1871
- // frame and return immediately.
1872
- if (isCloseable(newFrame) && (!opt_isTask || !promise.isPromise(result))) {
1873
- removeNewFrame();
1874
- callback(result);
1875
- return;
1876
- }
1877
-
1878
- // If the executed function returned a promise, wait for it to resolve. If
1879
- // there is nothing scheduled in the frame, go ahead and discard it.
1880
- // Otherwise, we wait for the frame to be closed out by the event loop.
1881
- var shortCircuitTask;
1882
- if (promise.isPromise(result)) {
1883
- newFrame.isBlocked_ = true;
1884
- var onResolve = function() {
1885
- newFrame.isBlocked_ = false;
1886
- shortCircuitTask = new MicroTask(function() {
1887
- if (isCloseable(newFrame)) {
1888
- removeNewFrame();
1889
- callback(result);
1890
- }
1891
- });
1892
- };
1893
- /** @type {Thenable} */(result).then(onResolve, onResolve);
1894
-
1895
- // If the result is a thenable, attach a listener to silence any unhandled
1896
- // rejection warnings. This is safe because we *will* handle it once the
1897
- // frame has completed.
1898
- } else if (promise.Thenable.isImplementation(result)) {
1899
- /** @type {!promise.Thenable} */(result).thenCatch(goog.nullFunction);
1900
- }
1901
-
1902
- newFrame.once(Frame.CLOSE_EVENT, function() {
1903
- shortCircuitTask && shortCircuitTask.cancel();
1904
- if (isCloseable(newFrame)) {
1905
- removeNewFrame();
1906
- }
1907
- callback(result);
1908
- }).once(Frame.ERROR_EVENT, function(reason) {
1909
- shortCircuitTask && shortCircuitTask.cancel();
1910
- if (promise.Thenable.isImplementation(result) && result.isPending()) {
1911
- result.cancel(reason);
1912
- }
1913
- errback(reason);
1914
- });
1915
- } catch (ex) {
1916
- removeNewFrame(ex);
1917
- errback(ex);
1918
- } finally {
1919
- // No longer running anything, clear the reference.
1920
- this.runningFrame_ = null;
1921
- }
1922
-
1923
- function isCloseable(frame) {
1924
- return (!frame.children_ || !frame.children_.length)
1925
- && !frame.pendingRejection;
1926
- }
1927
-
1928
- /**
1929
- * @param {*=} opt_err If provided, the reason that the frame was removed.
1930
- */
1931
- function removeNewFrame(opt_err) {
1932
- var parent = newFrame.getParent();
1933
- if (parent) {
1934
- parent.removeChild(newFrame);
1935
- asyncRun(function() {
1936
- if (isCloseable(parent) && parent !== self.activeFrame_) {
1937
- parent.emit(Frame.CLOSE_EVENT);
1938
- }
1939
- });
1940
- self.scheduleEventLoopStart_();
1941
- }
1942
-
1943
- if (opt_err) {
1944
- newFrame.cancelRemainingTasks(promise.CancellationError.wrap(
1945
- opt_err, 'Tasks cancelled due to uncaught error'));
1946
- }
1947
- self.activeFrame_ = oldFrame;
1948
- }
1949
- };
1950
-
1951
-
1952
- /**
1953
- * Commences the shutdown sequence for this instance. After one turn of the
1954
- * event loop, this object will emit the
1955
- * {@link webdriver.promise.ControlFlow.EventType.IDLE IDLE} event to signal
1956
- * listeners that it has completed. During this wait, if another task is
1957
- * scheduled, the shutdown will be aborted.
1958
- * @private
1959
- */
1960
- promise.ControlFlow.prototype.commenceShutdown_ = function() {
1961
- if (!this.shutdownTask_) {
1962
- // Go ahead and stop the event loop now. If we're in here, then there are
1963
- // no more frames with tasks to execute. If we waited to cancel the event
1964
- // loop in our timeout below, the event loop could trigger *before* the
1965
- // timeout, generating an error from there being no frames.
1966
- // If #execute is called before the timeout below fires, it will cancel
1967
- // the timeout and restart the event loop.
1968
- this.cancelEventLoop_();
1969
- this.shutdownTask_ = new MicroTask(this.shutdown_, this);
1970
- }
1971
- };
1972
-
1973
-
1974
- /** @private */
1975
- promise.ControlFlow.prototype.cancelHold_ = function() {
1976
- if (this.hold_) {
1977
- clearInterval(this.hold_);
1978
- this.hold_ = null;
1979
- }
1980
- };
1981
-
1982
-
1983
- /** @private */
1984
- promise.ControlFlow.prototype.shutdown_ = function() {
1985
- this.cancelHold_();
1986
- this.shutdownTask_ = null;
1987
- this.emit(promise.ControlFlow.EventType.IDLE);
1988
- };
1989
-
1990
-
1991
- /**
1992
- * Cancels the shutdown sequence if it is currently scheduled.
1993
- * @private
1994
- */
1995
- promise.ControlFlow.prototype.cancelShutdown_ = function() {
1996
- if (this.shutdownTask_) {
1997
- this.shutdownTask_.cancel();
1998
- this.shutdownTask_ = null;
1999
- }
2000
- };
2001
-
2002
-
2003
- /**
2004
- * Aborts this flow, abandoning all remaining tasks. If there are
2005
- * listeners registered, an {@code UNCAUGHT_EXCEPTION} will be emitted with the
2006
- * offending {@code error}, otherwise, the {@code error} will be rethrown to the
2007
- * global error handler.
2008
- * @param {*} error Object describing the error that caused the flow to
2009
- * abort; usually either an Error or string value.
2010
- * @private
2011
- */
2012
- promise.ControlFlow.prototype.abortNow_ = function(error) {
2013
- this.activeFrame_ = null;
2014
- this.cancelShutdown_();
2015
- this.cancelEventLoop_();
2016
- this.cancelHold_();
2017
-
2018
- var listeners = this.listeners(
2019
- promise.ControlFlow.EventType.UNCAUGHT_EXCEPTION);
2020
- if (!listeners.length) {
2021
- throwException(error);
2022
- } else {
2023
- this.emit(promise.ControlFlow.EventType.UNCAUGHT_EXCEPTION, error);
2024
- }
2025
- };
2026
-
2027
-
2028
- /**
2029
- * Wraps a function to execute as a cancellable micro task.
2030
- * @final
2031
- */
2032
- var MicroTask = goog.defineClass(null, {
2033
- /**
2034
- * @param {function(this: THIS)} fn The function to run as a micro task.
2035
- * @param {THIS=} opt_scope The scope to run the function in.
2036
- * @template THIS
2037
- */
2038
- constructor: function(fn, opt_scope) {
2039
- /** @private {boolean} */
2040
- this.cancelled_ = false;
2041
- asyncRun(function() {
2042
- if (!this.cancelled_) {
2043
- fn.call(opt_scope);
2044
- }
2045
- }, this);
2046
- },
2047
-
2048
- /**
2049
- * Cancels the execution of this task. Note: this will not prevent the task
2050
- * timer from firing, just the invocation of the wrapped function.
2051
- */
2052
- cancel: function() {
2053
- this.cancelled_ = true;
2054
- }
2055
- });
2056
-
2057
-
2058
- /**
2059
- * An execution frame within a {@link webdriver.promise.ControlFlow}. Each
2060
- * frame represents the execution context for either a
2061
- * {@link webdriver.Task} or a callback on a
2062
- * {@link webdriver.promise.Promise}.
2063
- *
2064
- * Each frame may contain sub-frames. If child N is a sub-frame, then the
2065
- * items queued within it are given priority over child N+1.
2066
- *
2067
- * @unrestricted
2068
- * @final
2069
- * @private
2070
- */
2071
- var Frame = goog.defineClass(EventEmitter, {
2072
- /**
2073
- * @param {!promise.ControlFlow} flow The flow this instance belongs to.
2074
- */
2075
- constructor: function(flow) {
2076
- EventEmitter.call(this);
2077
- goog.getUid(this);
2078
-
2079
- /** @private {!promise.ControlFlow} */
2080
- this.flow_ = flow;
2081
-
2082
- /** @private {Frame} */
2083
- this.parent_ = null;
2084
-
2085
- /** @private {Array<!(Frame|Task)>} */
2086
- this.children_ = null;
2087
-
2088
- /** @private {(Frame|Task)} */
2089
- this.lastInsertedChild_ = null;
2090
-
2091
- /**
2092
- * The task currently being executed within this frame.
2093
- * @private {Task}
2094
- */
2095
- this.pendingTask_ = null;
2096
-
2097
- /**
2098
- * Whether this frame is currently locked. A locked frame represents an
2099
- * executed function that has scheduled all of its tasks.
2100
- *
2101
- * Once a frame becomes locked, any new frames which are added as children
2102
- * represent interrupts (such as a {@link webdriver.promise.Promise}
2103
- * callback) whose tasks must be given priority over those already scheduled
2104
- * within this frame. For example:
2105
- *
2106
- * var flow = promise.controlFlow();
2107
- * flow.execute('start here', goog.nullFunction).then(function() {
2108
- * flow.execute('this should execute 2nd', goog.nullFunction);
2109
- * });
2110
- * flow.execute('this should execute last', goog.nullFunction);
2111
- *
2112
- * @private {boolean}
2113
- */
2114
- this.isLocked_ = false;
2115
-
2116
- /**
2117
- * Whether this frame's completion is blocked on the resolution of a promise
2118
- * returned by its main function.
2119
- * @private
2120
- */
2121
- this.isBlocked_ = false;
2122
-
2123
- /**
2124
- * Whether this frame represents a pending callback attached to a
2125
- * {@link webdriver.promise.Promise}.
2126
- * @private {boolean}
2127
- */
2128
- this.pendingCallback = false;
2129
-
2130
- /**
2131
- * Whether there are pending unhandled rejections detected within this frame.
2132
- * @private {boolean}
2133
- */
2134
- this.pendingRejection = false;
2135
-
2136
- /** @private {promise.CancellationError} */
2137
- this.cancellationError_ = null;
2138
- },
2139
-
2140
- statics: {
2141
- /** @const */
2142
- CLOSE_EVENT: 'close',
2143
-
2144
- /** @const */
2145
- ERROR_EVENT: 'error',
2146
-
2147
- /**
2148
- * @param {!promise.CancellationError} error The cancellation error.
2149
- * @param {!(Frame|Task)} child The child to cancel.
2150
- * @private
2151
- */
2152
- cancelChild_: function(error, child) {
2153
- if (child instanceof Frame) {
2154
- child.cancelRemainingTasks(error);
2155
- } else {
2156
- child.promise.callbacks_ = null;
2157
- child.cancel(error);
2158
- }
2159
- }
2160
- },
2161
-
2162
- /** @return {Frame} This frame's parent, if any. */
2163
- getParent: function() {
2164
- return this.parent_;
2165
- },
2166
-
2167
- /** @param {Frame} parent This frame's new parent. */
2168
- setParent: function(parent) {
2169
- this.parent_ = parent;
2170
- },
2171
-
2172
- /** @return {!Frame} The root of this frame's tree. */
2173
- getRoot: function() {
2174
- var root = this;
2175
- while (root.parent_) {
2176
- root = root.parent_;
2177
- }
2178
- return root;
2179
- },
2180
-
2181
- /**
2182
- * Aborts the execution of this frame, cancelling all outstanding tasks
2183
- * scheduled within this frame.
2184
- *
2185
- * @param {*} error The error that triggered this abortion.
2186
- */
2187
- abort: function(error) {
2188
- this.cancellationError_ = promise.CancellationError.wrap(
2189
- error, 'Task discarded due to a previous task failure');
2190
- this.cancelRemainingTasks(this.cancellationError_);
2191
- if (!this.pendingCallback) {
2192
- this.emit(Frame.ERROR_EVENT, error);
2193
- }
2194
- },
2195
-
2196
- /**
2197
- * Marks all of the tasks that are descendants of this frame in the execution
2198
- * tree as cancelled. This is necessary for callbacks scheduled asynchronous.
2199
- * For example:
2200
- *
2201
- * var someResult;
2202
- * promise.createFlow(function(flow) {
2203
- * someResult = flow.execute(function() {});
2204
- * throw Error();
2205
- * }).thenCatch(function(err) {
2206
- * console.log('flow failed: ' + err);
2207
- * someResult.then(function() {
2208
- * console.log('task succeeded!');
2209
- * }, function(err) {
2210
- * console.log('task failed! ' + err);
2211
- * });
2212
- * });
2213
- * // flow failed: Error: boom
2214
- * // task failed! CancelledTaskError: Task discarded due to a previous
2215
- * // task failure: Error: boom
2216
- *
2217
- * @param {!promise.CancellationError} reason The cancellation reason.
2218
- */
2219
- cancelRemainingTasks: function(reason) {
2220
- if (this.children_) {
2221
- this.children_.forEach(function(child) {
2222
- Frame.cancelChild_(reason, child);
2223
- });
2224
- }
2225
- },
2226
-
2227
- /**
2228
- * @return {Task} The task currently executing
2229
- * within this frame, if any.
2230
- */
2231
- getPendingTask: function() {
2232
- return this.pendingTask_;
2233
- },
2234
-
2235
- /**
2236
- * @param {Task} task The task currently
2237
- * executing within this frame, if any.
2238
- */
2239
- setPendingTask: function(task) {
2240
- this.pendingTask_ = task;
2241
- },
2242
-
2243
- /**
2244
- * @return {boolean} Whether this frame is empty (has no scheduled tasks or
2245
- * pending callback frames).
2246
- */
2247
- isEmpty: function() {
2248
- return !this.children_ || !this.children_.length;
2249
- },
2250
-
2251
- /**
2252
- * Adds a new node to this frame.
2253
- * @param {!(Frame|Task)} node The node to insert.
2254
- */
2255
- addChild: function(node) {
2256
- if (this.cancellationError_) {
2257
- Frame.cancelChild_(this.cancellationError_, node);
2258
- return; // Child will never run, no point keeping a reference.
2259
- }
2260
-
2261
- if (!this.children_) {
2262
- this.children_ = [];
2263
- }
2264
-
2265
- node.setParent(this);
2266
- if (this.isLocked_ && node instanceof Frame) {
2267
- var index = 0;
2268
- if (this.lastInsertedChild_ instanceof Frame) {
2269
- index = this.children_.indexOf(this.lastInsertedChild_);
2270
- // If the last inserted child into a locked frame is a pending callback,
2271
- // it is an interrupt and the new interrupt must come after it. Otherwise,
2272
- // we have our first interrupt for this frame and it shoudl go before the
2273
- // last inserted child.
2274
- index += (this.lastInsertedChild_.pendingCallback) ? 1 : -1;
2275
- }
2276
- this.children_.splice(Math.max(index, 0), 0, node);
2277
- this.lastInsertedChild_ = node;
2278
- return;
2279
- }
2280
-
2281
- this.lastInsertedChild_ = node;
2282
- this.children_.push(node);
2283
- },
2284
-
2285
- /**
2286
- * @return {(Frame|Task)} This frame's fist child.
2287
- */
2288
- getFirstChild: function() {
2289
- this.isLocked_ = true;
2290
- return this.children_ && this.children_[0];
2291
- },
2292
-
2293
- /**
2294
- * Removes a child from this frame.
2295
- * @param {!(Frame|Task)} child The child to remove.
2296
- */
2297
- removeChild: function(child) {
2298
- goog.asserts.assert(child.parent_ === this, 'not a child of this frame');
2299
- goog.asserts.assert(this.children_ !== null, 'frame has no children!');
2300
- var index = this.children_.indexOf(child);
2301
- child.setParent(null);
2302
- this.children_.splice(index, 1);
2303
- if (this.lastInsertedChild_ === child) {
2304
- this.lastInsertedChild_ = this.children_[index - 1] || null;
2305
- }
2306
- if (!this.children_.length) {
2307
- this.children_ = null;
2308
- }
2309
- },
2310
-
2311
- /** @override */
2312
- toString: function() {
2313
- return 'Frame::' + goog.getUid(this);
2314
- }
2315
- });
2316
-
2317
-
2318
- /**
2319
- * A task to be executed by a {@link webdriver.promise.ControlFlow}.
2320
- *
2321
- * @unrestricted
2322
- * @final
2323
- */
2324
- var Task = goog.defineClass(promise.Deferred, {
2325
- /**
2326
- * @param {!promise.ControlFlow} flow The flow this instances belongs
2327
- * to.
2328
- * @param {function(): (T|!promise.Promise<T>)} fn The function to
2329
- * call when the task executes. If it returns a
2330
- * {@link webdriver.promise.Promise}, the flow will wait for it to be
2331
- * resolved before starting the next task.
2332
- * @param {string} description A description of the task for debugging.
2333
- * @constructor
2334
- * @extends {promise.Deferred<T>}
2335
- * @template T
2336
- */
2337
- constructor: function(flow, fn, description) {
2338
- Task.base(this, 'constructor', flow);
2339
- goog.getUid(this);
2340
-
2341
- /**
2342
- * @type {function(): (T|!promise.Promise<T>)}
2343
- */
2344
- this.execute = fn;
2345
-
2346
- /** @private {string} */
2347
- this.description_ = description;
2348
-
2349
- /** @private {Frame} */
2350
- this.parent_ = null;
2351
-
2352
- /** @private {Frame} */
2353
- this.frame_ = null;
2354
- },
2355
-
2356
- /**
2357
- * @return {Frame} frame The frame used to run this task's
2358
- * {@link #execute} method.
2359
- */
2360
- getFrame: function() {
2361
- return this.frame_;
2362
- },
2363
-
2364
- /**
2365
- * @param {Frame} frame The frame used to run this task's
2366
- * {@link #execute} method.
2367
- */
2368
- setFrame: function(frame) {
2369
- this.frame_ = frame;
2370
- },
2371
-
2372
- /**
2373
- * @param {Frame} frame The frame this task is scheduled in.
2374
- */
2375
- setParent: function(frame) {
2376
- goog.asserts.assert(goog.isNull(this.parent_) || goog.isNull(frame),
2377
- 'parent already set');
2378
- this.parent_ = frame;
2379
- },
2380
-
2381
- /** @return {string} This task's description. */
2382
- getDescription: function() {
2383
- return this.description_;
2384
- },
2385
-
2386
- /** @override */
2387
- toString: function() {
2388
- return 'Task::' + goog.getUid(this) + '<' + this.description_ + '>';
2389
- }
2390
- });
2391
-
2392
-
2393
- /**
2394
- * Manages a callback attached to a {@link webdriver.promise.Promise}. When the
2395
- * promise is resolved, this callback will invoke the appropriate callback
2396
- * function based on the promise's resolved value.
2397
- *
2398
- * @unrestricted
2399
- * @final
2400
- */
2401
- var Callback = goog.defineClass(promise.Deferred, {
2402
- /**
2403
- * @param {!promise.Promise} parent The promise this callback is attached to.
2404
- * @param {(function(T): (IThenable<R>|R)|null|undefined)} callback
2405
- * The fulfillment callback.
2406
- * @param {(function(*): (IThenable<R>|R)|null|undefined)} errback
2407
- * The rejection callback.
2408
- * @param {string} name The callback name.
2409
- * @param {!Function} fn The function to use as the top of the stack when
2410
- * recording the callback's creation point.
2411
- * @extends {promise.Deferred<R>}
2412
- * @template T, R
2413
- */
2414
- constructor: function(parent, callback, errback, name, fn) {
2415
- Callback.base(this, 'constructor', parent.flow_);
2416
-
2417
- /** @private {(function(T): (IThenable<R>|R)|null|undefined)} */
2418
- this.callback_ = callback;
2419
-
2420
- /** @private {(function(*): (IThenable<R>|R)|null|undefined)} */
2421
- this.errback_ = errback;
2422
-
2423
- /** @private {!Frame} */
2424
- this.frame_ = new Frame(parent.flow_);
2425
- this.frame_.pendingCallback = true;
2426
-
2427
- this.promise.parent_ = parent;
2428
- if (promise.LONG_STACK_TRACES) {
2429
- this.promise.stack_ = promise.captureStackTrace('Promise', name, fn);
2430
- }
2431
- },
2432
-
2433
- /**
2434
- * Called by the parent promise when it has been resolved.
2435
- * @param {!PromiseState} state The parent's new state.
2436
- * @param {*} value The parent's new value.
2437
- */
2438
- notify: function(state, value) {
2439
- var callback = this.callback_;
2440
- var fallback = this.fulfill;
2441
- if (state === PromiseState.REJECTED) {
2442
- callback = this.errback_;
2443
- fallback = this.reject;
2444
- }
2445
-
2446
- this.frame_.pendingCallback = false;
2447
- if (goog.isFunction(callback)) {
2448
- this.frame_.flow_.runInFrame_(
2449
- this.frame_,
2450
- goog.bind(callback, undefined, value),
2451
- this.fulfill, this.reject);
2452
- } else {
2453
- if (this.frame_.getParent()) {
2454
- this.frame_.getParent().removeChild(this.frame_);
2455
- }
2456
- fallback(value);
2457
- }
2458
- }
2459
- });
2460
-
2461
-
2462
-
2463
- /**
2464
- * The default flow to use if no others are active.
2465
- * @type {!promise.ControlFlow}
2466
- */
2467
- var defaultFlow = new promise.ControlFlow();
2468
-
2469
-
2470
- /**
2471
- * A stack of active control flows, with the top of the stack used to schedule
2472
- * commands. When there are multiple flows on the stack, the flow at index N
2473
- * represents a callback triggered within a task owned by the flow at index
2474
- * N-1.
2475
- * @type {!Array<!promise.ControlFlow>}
2476
- */
2477
- var activeFlows = [];
2478
-
2479
-
2480
- /**
2481
- * Changes the default flow to use when no others are active.
2482
- * @param {!promise.ControlFlow} flow The new default flow.
2483
- * @throws {Error} If the default flow is not currently active.
2484
- */
2485
- promise.setDefaultFlow = function(flow) {
2486
- if (activeFlows.length) {
2487
- throw Error('You may only change the default flow while it is active');
2488
- }
2489
- defaultFlow = flow;
2490
- };
2491
-
2492
-
2493
- /**
2494
- * @return {!promise.ControlFlow} The currently active control flow.
2495
- */
2496
- promise.controlFlow = function() {
2497
- return /** @type {!promise.ControlFlow} */ (
2498
- Arrays.peek(activeFlows) || defaultFlow);
2499
- };
2500
-
2501
-
2502
- /**
2503
- * Creates a new control flow. The provided callback will be invoked as the
2504
- * first task within the new flow, with the flow as its sole argument. Returns
2505
- * a promise that resolves to the callback result.
2506
- * @param {function(!promise.ControlFlow)} callback The entry point
2507
- * to the newly created flow.
2508
- * @return {!promise.Promise} A promise that resolves to the callback
2509
- * result.
2510
- */
2511
- promise.createFlow = function(callback) {
2512
- var flow = new promise.ControlFlow;
2513
- return flow.execute(function() {
2514
- return callback(flow);
2515
- });
2516
- };
2517
-
2518
-
2519
- /**
2520
- * Tests is a function is a generator.
2521
- * @param {!Function} fn The function to test.
2522
- * @return {boolean} Whether the function is a generator.
2523
- */
2524
- promise.isGenerator = function(fn) {
2525
- return fn.constructor.name === 'GeneratorFunction';
2526
- };
2527
-
2528
-
2529
- /**
2530
- * Consumes a {@code GeneratorFunction}. Each time the generator yields a
2531
- * promise, this function will wait for it to be fulfilled before feeding the
2532
- * fulfilled value back into {@code next}. Likewise, if a yielded promise is
2533
- * rejected, the rejection error will be passed to {@code throw}.
2534
- *
2535
- * __Example 1:__ the Fibonacci Sequence.
2536
- *
2537
- * promise.consume(function* fibonacci() {
2538
- * var n1 = 1, n2 = 1;
2539
- * for (var i = 0; i < 4; ++i) {
2540
- * var tmp = yield n1 + n2;
2541
- * n1 = n2;
2542
- * n2 = tmp;
2543
- * }
2544
- * return n1 + n2;
2545
- * }).then(function(result) {
2546
- * console.log(result); // 13
2547
- * });
2548
- *
2549
- * __Example 2:__ a generator that throws.
2550
- *
2551
- * promise.consume(function* () {
2552
- * yield promise.delayed(250).then(function() {
2553
- * throw Error('boom');
2554
- * });
2555
- * }).thenCatch(function(e) {
2556
- * console.log(e.toString()); // Error: boom
2557
- * });
2558
- *
2559
- * @param {!Function} generatorFn The generator function to execute.
2560
- * @param {Object=} opt_self The object to use as "this" when invoking the
2561
- * initial generator.
2562
- * @param {...*} var_args Any arguments to pass to the initial generator.
2563
- * @return {!promise.Promise<?>} A promise that will resolve to the
2564
- * generator's final result.
2565
- * @throws {TypeError} If the given function is not a generator.
2566
- */
2567
- promise.consume = function(generatorFn, opt_self, var_args) {
2568
- if (!promise.isGenerator(generatorFn)) {
2569
- throw new TypeError('Input is not a GeneratorFunction: ' +
2570
- generatorFn.constructor.name);
2571
- }
2572
-
2573
- var deferred = promise.defer();
2574
- var generator = generatorFn.apply(opt_self, Arrays.slice(arguments, 2));
2575
- callNext();
2576
- return deferred.promise;
2577
-
2578
- /** @param {*=} opt_value . */
2579
- function callNext(opt_value) {
2580
- pump(generator.next, opt_value);
2581
- }
2582
-
2583
- /** @param {*=} opt_error . */
2584
- function callThrow(opt_error) {
2585
- // Dictionary lookup required because Closure compiler's built-in
2586
- // externs does not include GeneratorFunction.prototype.throw.
2587
- pump(generator['throw'], opt_error);
2588
- }
2589
-
2590
- function pump(fn, opt_arg) {
2591
- if (!deferred.isPending()) {
2592
- return; // Defererd was cancelled; silently abort.
2593
- }
2594
-
2595
- try {
2596
- var result = fn.call(generator, opt_arg);
2597
- } catch (ex) {
2598
- deferred.reject(ex);
2599
- return;
2600
- }
2601
-
2602
- if (result.done) {
2603
- deferred.fulfill(result.value);
2604
- return;
2605
- }
2606
-
2607
- promise.asap(result.value, callNext, callThrow);
2608
- }
2609
- };