selenium-webdriver 2.43.5 → 2.44.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.
- package/CHANGES.md +20 -0
- package/README.md +8 -13
- package/builder.js +4 -3
- package/docs/class_webdriver_Alert.html +6 -6
- package/docs/class_webdriver_AlertPromise.html +6 -6
- package/docs/class_webdriver_UnhandledAlertError.html +4 -4
- package/docs/class_webdriver_WebDriver.html +39 -37
- package/docs/class_webdriver_WebDriver_Logs.html +3 -3
- package/docs/class_webdriver_WebDriver_Navigation.html +5 -5
- package/docs/class_webdriver_WebDriver_Options.html +9 -9
- package/docs/class_webdriver_WebDriver_TargetLocator.html +6 -6
- package/docs/class_webdriver_WebDriver_Timeouts.html +4 -4
- package/docs/class_webdriver_WebDriver_Window.html +6 -6
- package/docs/class_webdriver_WebElement.html +23 -23
- package/docs/class_webdriver_WebElementPromise.html +22 -22
- package/docs/class_webdriver_promise_CancellationError.html +3 -0
- package/docs/class_webdriver_promise_ControlFlow.html +32 -32
- package/docs/class_webdriver_promise_Deferred.html +7 -8
- package/docs/class_webdriver_promise_Frame_.html +14 -30
- package/docs/class_webdriver_promise_Promise.html +2 -2
- package/docs/class_webdriver_promise_Task_.html +12 -12
- package/docs/class_webdriver_until_Condition.html +3 -0
- package/docs/enum_webdriver_Key.html +1 -1
- package/docs/enum_webdriver_promise_ControlFlow_EventType.html +1 -1
- package/docs/enum_webdriver_promise_Deferred_State_.html +1 -1
- package/docs/index.html +8 -13
- package/docs/interface_webdriver_promise_Thenable.html +8 -10
- package/docs/license.html +1 -1
- package/docs/module_selenium-webdriver.html +2 -2
- package/docs/module_selenium-webdriver__base.html +1 -1
- package/docs/module_selenium-webdriver__base_class_Context.html +1 -1
- package/docs/module_selenium-webdriver_builder.html +1 -1
- package/docs/module_selenium-webdriver_builder_class_Builder.html +1 -1
- package/docs/module_selenium-webdriver_chrome.html +1 -1
- package/docs/module_selenium-webdriver_chrome_class_Driver.html +2 -2
- package/docs/module_selenium-webdriver_chrome_class_Options.html +2 -2
- package/docs/module_selenium-webdriver_chrome_class_ServiceBuilder.html +1 -1
- package/docs/module_selenium-webdriver_error.html +1 -1
- package/docs/module_selenium-webdriver_executors.html +1 -1
- package/docs/module_selenium-webdriver_firefox.html +1 -1
- package/docs/module_selenium-webdriver_firefox_binary.html +1 -1
- package/docs/module_selenium-webdriver_firefox_binary_class_Binary.html +1 -1
- package/docs/module_selenium-webdriver_firefox_class_Driver.html +2 -2
- package/docs/module_selenium-webdriver_firefox_class_Options.html +1 -1
- package/docs/module_selenium-webdriver_firefox_extension.html +1 -1
- package/docs/module_selenium-webdriver_firefox_profile.html +1 -1
- package/docs/module_selenium-webdriver_firefox_profile_class_Profile.html +1 -1
- package/docs/module_selenium-webdriver_http.html +1 -1
- package/docs/module_selenium-webdriver_http_class_HttpClient.html +1 -1
- package/docs/module_selenium-webdriver_http_util.html +1 -1
- package/docs/module_selenium-webdriver_io.html +1 -1
- package/docs/module_selenium-webdriver_io_exec.html +1 -1
- package/docs/module_selenium-webdriver_net.html +1 -1
- package/docs/module_selenium-webdriver_net_portprober.html +1 -1
- package/docs/module_selenium-webdriver_phantomjs.html +1 -1
- package/docs/module_selenium-webdriver_phantomjs_class_Driver.html +2 -2
- package/docs/module_selenium-webdriver_proxy.html +1 -1
- package/docs/module_selenium-webdriver_remote.html +1 -1
- package/docs/module_selenium-webdriver_remote_class_DriverService.html +2 -2
- package/docs/module_selenium-webdriver_remote_class_SeleniumServer.html +2 -2
- package/docs/module_selenium-webdriver_testing.html +16 -29
- package/docs/module_selenium-webdriver_testing_assert.html +1 -1
- package/docs/namespace_webdriver_promise.html +18 -20
- package/docs/namespace_webdriver_stacktrace.html +15 -15
- package/docs/namespace_webdriver_until.html +32 -0
- package/docs/source/_base.js.src.html +1 -1
- package/docs/source/builder.js.src.html +1 -1
- package/docs/source/chrome.js.src.html +1 -1
- package/docs/source/error.js.src.html +1 -1
- package/docs/source/executors.js.src.html +1 -1
- package/docs/source/firefox/binary.js.src.html +1 -1
- package/docs/source/firefox/extension.js.src.html +1 -1
- package/docs/source/firefox/index.js.src.html +1 -1
- package/docs/source/firefox/profile.js.src.html +1 -1
- package/docs/source/http/index.js.src.html +1 -1
- package/docs/source/http/util.js.src.html +1 -1
- package/docs/source/index.js.src.html +1 -1
- package/docs/source/io/exec.js.src.html +1 -1
- package/docs/source/io/index.js.src.html +1 -1
- package/docs/source/lib/atoms/error.js.src.html +1 -1
- package/docs/source/lib/atoms/json.js.src.html +1 -1
- package/docs/source/lib/atoms/response.js.src.html +1 -1
- package/docs/source/lib/atoms/userAgent.js.src.html +1 -1
- package/docs/source/lib/goog/array/array.js.src.html +1 -1
- package/docs/source/lib/goog/asserts/asserts.js.src.html +1 -1
- package/docs/source/lib/goog/async/nexttick.js.src.html +1 -1
- package/docs/source/lib/goog/async/run.js.src.html +1 -1
- package/docs/source/lib/goog/base.js.src.html +1 -1
- package/docs/source/lib/goog/debug/debug.js.src.html +1 -1
- package/docs/source/lib/goog/debug/entrypointregistry.js.src.html +1 -1
- package/docs/source/lib/goog/debug/error.js.src.html +1 -1
- package/docs/source/lib/goog/debug/logbuffer.js.src.html +1 -1
- package/docs/source/lib/goog/debug/logger.js.src.html +1 -1
- package/docs/source/lib/goog/debug/logrecord.js.src.html +1 -1
- package/docs/source/lib/goog/deps.js.src.html +1 -1
- package/docs/source/lib/goog/disposable/disposable.js.src.html +1 -1
- package/docs/source/lib/goog/disposable/idisposable.js.src.html +1 -1
- package/docs/source/lib/goog/dom/browserfeature.js.src.html +1 -1
- package/docs/source/lib/goog/dom/dom.js.src.html +1 -1
- package/docs/source/lib/goog/dom/nodetype.js.src.html +1 -1
- package/docs/source/lib/goog/dom/tagname.js.src.html +1 -1
- package/docs/source/lib/goog/dom/vendor.js.src.html +1 -1
- package/docs/source/lib/goog/events/browserevent.js.src.html +1 -1
- package/docs/source/lib/goog/events/browserfeature.js.src.html +1 -1
- package/docs/source/lib/goog/events/event.js.src.html +1 -1
- package/docs/source/lib/goog/events/eventid.js.src.html +1 -1
- package/docs/source/lib/goog/events/events.js.src.html +1 -1
- package/docs/source/lib/goog/events/eventtarget.js.src.html +1 -1
- package/docs/source/lib/goog/events/eventtype.js.src.html +1 -1
- package/docs/source/lib/goog/events/keycodes.js.src.html +1 -1
- package/docs/source/lib/goog/events/listenable.js.src.html +1 -1
- package/docs/source/lib/goog/events/listener.js.src.html +1 -1
- package/docs/source/lib/goog/events/listenermap.js.src.html +1 -1
- package/docs/source/lib/goog/functions/functions.js.src.html +1 -1
- package/docs/source/lib/goog/iter/iter.js.src.html +1 -1
- package/docs/source/lib/goog/json/json.js.src.html +1 -1
- package/docs/source/lib/goog/labs/testing/assertthat.js.src.html +1 -1
- package/docs/source/lib/goog/labs/testing/logicmatcher.js.src.html +1 -1
- package/docs/source/lib/goog/labs/testing/matcher.js.src.html +1 -1
- package/docs/source/lib/goog/labs/testing/numbermatcher.js.src.html +1 -1
- package/docs/source/lib/goog/labs/testing/objectmatcher.js.src.html +1 -1
- package/docs/source/lib/goog/labs/testing/stringmatcher.js.src.html +1 -1
- package/docs/source/lib/goog/labs/useragent/browser.js.src.html +1 -1
- package/docs/source/lib/goog/labs/useragent/engine.js.src.html +1 -1
- package/docs/source/lib/goog/labs/useragent/util.js.src.html +1 -1
- package/docs/source/lib/goog/math/box.js.src.html +1 -1
- package/docs/source/lib/goog/math/coordinate.js.src.html +1 -1
- package/docs/source/lib/goog/math/math.js.src.html +1 -1
- package/docs/source/lib/goog/math/rect.js.src.html +1 -1
- package/docs/source/lib/goog/math/size.js.src.html +1 -1
- package/docs/source/lib/goog/net/wrapperxmlhttpfactory.js.src.html +1 -1
- package/docs/source/lib/goog/net/xhrlike.js.src.html +1 -1
- package/docs/source/lib/goog/net/xmlhttp.js.src.html +1 -1
- package/docs/source/lib/goog/net/xmlhttpfactory.js.src.html +1 -1
- package/docs/source/lib/goog/object/object.js.src.html +1 -1
- package/docs/source/lib/goog/reflect/reflect.js.src.html +1 -1
- package/docs/source/lib/goog/string/string.js.src.html +1 -1
- package/docs/source/lib/goog/structs/collection.js.src.html +1 -1
- package/docs/source/lib/goog/structs/map.js.src.html +1 -1
- package/docs/source/lib/goog/structs/set.js.src.html +1 -1
- package/docs/source/lib/goog/structs/structs.js.src.html +1 -1
- package/docs/source/lib/goog/style/style.js.src.html +1 -1
- package/docs/source/lib/goog/testing/asserts.js.src.html +1 -1
- package/docs/source/lib/goog/testing/asynctestcase.js.src.html +1 -1
- package/docs/source/lib/goog/testing/events/events.js.src.html +1 -1
- package/docs/source/lib/goog/testing/functionmock.js.src.html +1 -1
- package/docs/source/lib/goog/testing/jsunit.js.src.html +1 -1
- package/docs/source/lib/goog/testing/loosemock.js.src.html +1 -1
- package/docs/source/lib/goog/testing/mock.js.src.html +1 -1
- package/docs/source/lib/goog/testing/mockclock.js.src.html +1 -1
- package/docs/source/lib/goog/testing/mockcontrol.js.src.html +1 -1
- package/docs/source/lib/goog/testing/mockinterface.js.src.html +1 -1
- package/docs/source/lib/goog/testing/mockmatchers.js.src.html +1 -1
- package/docs/source/lib/goog/testing/objectpropertystring.js.src.html +1 -1
- package/docs/source/lib/goog/testing/propertyreplacer.js.src.html +1 -1
- package/docs/source/lib/goog/testing/recordfunction.js.src.html +1 -1
- package/docs/source/lib/goog/testing/stacktrace.js.src.html +1 -1
- package/docs/source/lib/goog/testing/strictmock.js.src.html +1 -1
- package/docs/source/lib/goog/testing/testcase.js.src.html +1 -1
- package/docs/source/lib/goog/testing/testrunner.js.src.html +1 -1
- package/docs/source/lib/goog/testing/watchers.js.src.html +1 -1
- package/docs/source/lib/goog/uri/uri.js.src.html +1 -1
- package/docs/source/lib/goog/uri/utils.js.src.html +1 -1
- package/docs/source/lib/goog/useragent/product.js.src.html +1 -1
- package/docs/source/lib/goog/useragent/product_isversion.js.src.html +1 -1
- package/docs/source/lib/goog/useragent/useragent.js.src.html +1 -1
- package/docs/source/lib/webdriver/abstractbuilder.js.src.html +1 -1
- package/docs/source/lib/webdriver/actionsequence.js.src.html +1 -1
- package/docs/source/lib/webdriver/builder.js.src.html +1 -1
- package/docs/source/lib/webdriver/button.js.src.html +1 -1
- package/docs/source/lib/webdriver/capabilities.js.src.html +1 -1
- package/docs/source/lib/webdriver/command.js.src.html +1 -1
- package/docs/source/lib/webdriver/events.js.src.html +1 -1
- package/docs/source/lib/webdriver/firefoxdomexecutor.js.src.html +1 -1
- package/docs/source/lib/webdriver/http/corsclient.js.src.html +1 -1
- package/docs/source/lib/webdriver/http/http.js.src.html +1 -1
- package/docs/source/lib/webdriver/http/xhrclient.js.src.html +1 -1
- package/docs/source/lib/webdriver/key.js.src.html +1 -1
- package/docs/source/lib/webdriver/locators.js.src.html +1 -1
- package/docs/source/lib/webdriver/logging.js.src.html +1 -1
- package/docs/source/lib/webdriver/process.js.src.html +1 -1
- package/docs/source/lib/webdriver/promise.js.src.html +1 -1
- package/docs/source/lib/webdriver/session.js.src.html +1 -1
- package/docs/source/lib/webdriver/stacktrace.js.src.html +1 -1
- package/docs/source/lib/webdriver/testing/asserts.js.src.html +1 -1
- package/docs/source/lib/webdriver/testing/testcase.js.src.html +1 -1
- package/docs/source/lib/webdriver/until.js.src.html +1 -0
- package/docs/source/lib/webdriver/webdriver.js.src.html +1 -1
- package/docs/source/net/index.js.src.html +1 -1
- package/docs/source/net/portprober.js.src.html +1 -1
- package/docs/source/phantomjs.js.src.html +1 -1
- package/docs/source/proxy.js.src.html +1 -1
- package/docs/source/remote/index.js.src.html +1 -1
- package/docs/source/testing/assert.js.src.html +1 -1
- package/docs/source/testing/index.js.src.html +1 -1
- package/docs/types.js +1 -1
- package/example/google_search.js +9 -17
- package/example/google_search_generator.js +6 -7
- package/example/google_search_test.js +10 -18
- package/example/parallel_flows.js +4 -7
- package/index.js +6 -0
- package/lib/firefox/webdriver.xpi +0 -0
- package/lib/goog/deps.js +7 -5
- package/lib/test/index.js +0 -8
- package/lib/webdriver/promise.js +263 -251
- package/lib/webdriver/stacktrace.js +15 -1
- package/lib/webdriver/test/promise_flow_test.js +82 -76
- package/lib/webdriver/test/promise_test.js +22 -62
- package/lib/webdriver/test/stacktrace_test.js +18 -0
- package/lib/webdriver/test/until_test.js +388 -0
- package/lib/webdriver/test/webdriver_test.js +41 -0
- package/lib/webdriver/until.js +408 -0
- package/lib/webdriver/webdriver.js +91 -29
- package/package.json +2 -2
- package/test/element_finding_test.js +6 -6
- package/test/http/util_test.js +4 -5
- package/test/page_loading_test.js +7 -7
- package/test/stale_element_test.js +2 -10
- package/testing/index.js +9 -22
package/lib/webdriver/promise.js
CHANGED
|
@@ -61,6 +61,24 @@ goog.require('webdriver.stacktrace.Snapshot');
|
|
|
61
61
|
|
|
62
62
|
|
|
63
63
|
|
|
64
|
+
/**
|
|
65
|
+
* Error used when the computation of a promise is cancelled.
|
|
66
|
+
*
|
|
67
|
+
* @param {string=} opt_msg The cancellation message.
|
|
68
|
+
* @constructor
|
|
69
|
+
* @extends {goog.debug.Error}
|
|
70
|
+
* @final
|
|
71
|
+
*/
|
|
72
|
+
webdriver.promise.CancellationError = function(opt_msg) {
|
|
73
|
+
goog.debug.Error.call(this, opt_msg);
|
|
74
|
+
|
|
75
|
+
/** @override */
|
|
76
|
+
this.name = 'CancellationError';
|
|
77
|
+
};
|
|
78
|
+
goog.inherits(webdriver.promise.CancellationError, goog.debug.Error);
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
|
|
64
82
|
/**
|
|
65
83
|
* Thenable is a promise-like object with a {@code then} method which may be
|
|
66
84
|
* used to schedule callbacks on a promised value.
|
|
@@ -75,9 +93,7 @@ webdriver.promise.Thenable = function() {};
|
|
|
75
93
|
* Cancels the computation of this promise's value, rejecting the promise in the
|
|
76
94
|
* process. This method is a no-op if the promise has alreayd been resolved.
|
|
77
95
|
*
|
|
78
|
-
* @param {
|
|
79
|
-
* {@code Error}, one will be created using the value's string
|
|
80
|
-
* representation.
|
|
96
|
+
* @param {string=} opt_reason The reason this promise is being cancelled.
|
|
81
97
|
*/
|
|
82
98
|
webdriver.promise.Thenable.prototype.cancel = function(opt_reason) {};
|
|
83
99
|
|
|
@@ -297,8 +313,6 @@ webdriver.promise.Promise.prototype.thenFinally = function(callback) {
|
|
|
297
313
|
* the Deferred's canceller function (if provided). The canceller may return a
|
|
298
314
|
* truth-y value to override the reason provided for rejection.
|
|
299
315
|
*
|
|
300
|
-
* @param {Function=} opt_canceller Function to call when cancelling the
|
|
301
|
-
* computation of this instance's value.
|
|
302
316
|
* @param {webdriver.promise.ControlFlow=} opt_flow The control flow
|
|
303
317
|
* this instance was created under. This should only be provided during
|
|
304
318
|
* unit tests.
|
|
@@ -306,7 +320,7 @@ webdriver.promise.Promise.prototype.thenFinally = function(callback) {
|
|
|
306
320
|
* @extends {webdriver.promise.Promise.<T>}
|
|
307
321
|
* @template T
|
|
308
322
|
*/
|
|
309
|
-
webdriver.promise.Deferred = function(
|
|
323
|
+
webdriver.promise.Deferred = function(opt_flow) {
|
|
310
324
|
/* NOTE: This class's implementation diverges from the prototypical style
|
|
311
325
|
* used in the rest of the atoms library. This was done intentionally to
|
|
312
326
|
* protect the internal Deferred state from consumers, as outlined by
|
|
@@ -316,6 +330,12 @@ webdriver.promise.Deferred = function(opt_canceller, opt_flow) {
|
|
|
316
330
|
|
|
317
331
|
var flow = opt_flow || webdriver.promise.controlFlow();
|
|
318
332
|
|
|
333
|
+
/**
|
|
334
|
+
* The deferred this instance is chained from, if any.
|
|
335
|
+
* @private {webdriver.promise.Deferred.<?>}
|
|
336
|
+
*/
|
|
337
|
+
this.parent_ = null;
|
|
338
|
+
|
|
319
339
|
/**
|
|
320
340
|
* The listeners registered with this Deferred. Each element in the list will
|
|
321
341
|
* be a 3-tuple of the callback function, errback function, and the
|
|
@@ -422,7 +442,8 @@ webdriver.promise.Deferred = function(opt_canceller, opt_flow) {
|
|
|
422
442
|
notify(listeners.shift());
|
|
423
443
|
}
|
|
424
444
|
|
|
425
|
-
if (!handled && state == webdriver.promise.Deferred.State_.REJECTED
|
|
445
|
+
if (!handled && state == webdriver.promise.Deferred.State_.REJECTED &&
|
|
446
|
+
!(value instanceof webdriver.promise.CancellationError)) {
|
|
426
447
|
flow.pendingRejections_ += 1;
|
|
427
448
|
pendingRejectionKey = flow.timer.setTimeout(function() {
|
|
428
449
|
pendingRejectionKey = null;
|
|
@@ -457,6 +478,8 @@ webdriver.promise.Deferred = function(opt_canceller, opt_flow) {
|
|
|
457
478
|
*/
|
|
458
479
|
var promise = new webdriver.promise.Promise();
|
|
459
480
|
|
|
481
|
+
var self = this;
|
|
482
|
+
|
|
460
483
|
/**
|
|
461
484
|
* Registers a callback on this Deferred.
|
|
462
485
|
*
|
|
@@ -482,7 +505,9 @@ webdriver.promise.Deferred = function(opt_canceller, opt_flow) {
|
|
|
482
505
|
pendingRejectionKey = null;
|
|
483
506
|
}
|
|
484
507
|
|
|
485
|
-
var deferred = new webdriver.promise.Deferred(
|
|
508
|
+
var deferred = new webdriver.promise.Deferred(flow);
|
|
509
|
+
deferred.parent_ = self;
|
|
510
|
+
|
|
486
511
|
var listener = {
|
|
487
512
|
callback: opt_callback,
|
|
488
513
|
errback: opt_errback,
|
|
@@ -500,8 +525,6 @@ webdriver.promise.Deferred = function(opt_canceller, opt_flow) {
|
|
|
500
525
|
return deferred.promise;
|
|
501
526
|
}
|
|
502
527
|
|
|
503
|
-
var self = this;
|
|
504
|
-
|
|
505
528
|
/**
|
|
506
529
|
* Resolves this promise with the given value. If the value is itself a
|
|
507
530
|
* promise and not a reference to this deferred, this instance will wait for
|
|
@@ -525,18 +548,17 @@ webdriver.promise.Deferred = function(opt_canceller, opt_flow) {
|
|
|
525
548
|
/**
|
|
526
549
|
* Attempts to cancel the computation of this instance's value. This attempt
|
|
527
550
|
* will silently fail if this instance has already resolved.
|
|
528
|
-
* @param {
|
|
529
|
-
*/
|
|
551
|
+
* @param {string=} opt_reason The reason for cancelling this promise. */
|
|
530
552
|
function cancel(opt_reason) {
|
|
531
553
|
if (!isPending()) {
|
|
532
554
|
return;
|
|
533
555
|
}
|
|
534
556
|
|
|
535
|
-
if (
|
|
536
|
-
|
|
557
|
+
if (self.parent_) {
|
|
558
|
+
self.parent_.cancel(opt_reason);
|
|
559
|
+
} else {
|
|
560
|
+
reject(new webdriver.promise.CancellationError(opt_reason));
|
|
537
561
|
}
|
|
538
|
-
|
|
539
|
-
reject(opt_reason);
|
|
540
562
|
}
|
|
541
563
|
|
|
542
564
|
this.promise = promise;
|
|
@@ -630,24 +652,22 @@ webdriver.promise.isPromise = function(value) {
|
|
|
630
652
|
*/
|
|
631
653
|
webdriver.promise.delayed = function(ms) {
|
|
632
654
|
var timer = webdriver.promise.controlFlow().timer;
|
|
633
|
-
var
|
|
634
|
-
var
|
|
655
|
+
var deferred = new webdriver.promise.Deferred();
|
|
656
|
+
var key = timer.setTimeout(deferred.fulfill, ms);
|
|
657
|
+
return deferred.thenCatch(function(e) {
|
|
635
658
|
timer.clearTimeout(key);
|
|
659
|
+
throw e;
|
|
636
660
|
});
|
|
637
|
-
key = timer.setTimeout(deferred.fulfill, ms);
|
|
638
|
-
return deferred.promise;
|
|
639
661
|
};
|
|
640
662
|
|
|
641
663
|
|
|
642
664
|
/**
|
|
643
665
|
* Creates a new deferred object.
|
|
644
|
-
* @param {Function=} opt_canceller Function to call when cancelling the
|
|
645
|
-
* computation of this instance's value.
|
|
646
666
|
* @return {!webdriver.promise.Deferred.<T>} The new deferred object.
|
|
647
667
|
* @template T
|
|
648
668
|
*/
|
|
649
|
-
webdriver.promise.defer = function(
|
|
650
|
-
return new webdriver.promise.Deferred(
|
|
669
|
+
webdriver.promise.defer = function() {
|
|
670
|
+
return new webdriver.promise.Deferred();
|
|
651
671
|
};
|
|
652
672
|
|
|
653
673
|
|
|
@@ -694,9 +714,7 @@ webdriver.promise.rejected = function(opt_reason) {
|
|
|
694
714
|
* result of the provided function's callback.
|
|
695
715
|
*/
|
|
696
716
|
webdriver.promise.checkedNodeCall = function(fn, var_args) {
|
|
697
|
-
var deferred = new webdriver.promise.Deferred(
|
|
698
|
-
throw Error('This Deferred may not be cancelled');
|
|
699
|
-
});
|
|
717
|
+
var deferred = new webdriver.promise.Deferred();
|
|
700
718
|
try {
|
|
701
719
|
var args = goog.array.slice(arguments, 1);
|
|
702
720
|
args.push(function(error, value) {
|
|
@@ -1044,6 +1062,75 @@ webdriver.promise.ControlFlow = function(opt_timer) {
|
|
|
1044
1062
|
* @private {!Array.<!webdriver.promise.Task_>}
|
|
1045
1063
|
*/
|
|
1046
1064
|
this.history_ = [];
|
|
1065
|
+
|
|
1066
|
+
/**
|
|
1067
|
+
* Tracks the active execution frame for this instance. Lazily initialized
|
|
1068
|
+
* when the first task is scheduled.
|
|
1069
|
+
* @private {webdriver.promise.Frame_}
|
|
1070
|
+
*/
|
|
1071
|
+
this.activeFrame_ = null;
|
|
1072
|
+
|
|
1073
|
+
/**
|
|
1074
|
+
* A reference to the frame in which new tasks should be scheduled. If
|
|
1075
|
+
* {@code null}, tasks will be scheduled within the active frame. When forcing
|
|
1076
|
+
* a function to run in the context of a new frame, this pointer is used to
|
|
1077
|
+
* ensure tasks are scheduled within the newly created frame, even though it
|
|
1078
|
+
* won't be active yet.
|
|
1079
|
+
* @private {webdriver.promise.Frame_}
|
|
1080
|
+
* @see {#runInNewFrame_}
|
|
1081
|
+
*/
|
|
1082
|
+
this.schedulingFrame_ = null;
|
|
1083
|
+
|
|
1084
|
+
/**
|
|
1085
|
+
* Timeout ID set when the flow is about to shutdown without any errors
|
|
1086
|
+
* being detected. Upon shutting down, the flow will emit an
|
|
1087
|
+
* {@link webdriver.promise.ControlFlow.EventType.IDLE} event. Idle events
|
|
1088
|
+
* always follow a brief timeout in order to catch latent errors from the last
|
|
1089
|
+
* completed task. If this task had a callback registered, but no errback, and
|
|
1090
|
+
* the task fails, the unhandled failure would not be reported by the promise
|
|
1091
|
+
* system until the next turn of the event loop:
|
|
1092
|
+
*
|
|
1093
|
+
* // Schedule 1 task that fails.
|
|
1094
|
+
* var result = webriver.promise.controlFlow().schedule('example',
|
|
1095
|
+
* function() { return webdriver.promise.rejected('failed'); });
|
|
1096
|
+
* // Set a callback on the result. This delays reporting the unhandled
|
|
1097
|
+
* // failure for 1 turn of the event loop.
|
|
1098
|
+
* result.then(goog.nullFunction);
|
|
1099
|
+
*
|
|
1100
|
+
* @private {?number}
|
|
1101
|
+
*/
|
|
1102
|
+
this.shutdownId_ = null;
|
|
1103
|
+
|
|
1104
|
+
/**
|
|
1105
|
+
* Interval ID for this instance's event loop.
|
|
1106
|
+
* @private {?number}
|
|
1107
|
+
*/
|
|
1108
|
+
this.eventLoopId_ = null;
|
|
1109
|
+
|
|
1110
|
+
/**
|
|
1111
|
+
* The number of "pending" promise rejections.
|
|
1112
|
+
*
|
|
1113
|
+
* <p>Each time a promise is rejected and is not handled by a listener, it
|
|
1114
|
+
* will schedule a 0-based timeout to check if it is still unrejected in the
|
|
1115
|
+
* next turn of the JS-event loop. This allows listeners to attach to, and
|
|
1116
|
+
* handle, the rejected promise at any point in same turn of the event loop
|
|
1117
|
+
* that the promise was rejected.
|
|
1118
|
+
*
|
|
1119
|
+
* <p>When this flow's own event loop triggers, it will not run if there
|
|
1120
|
+
* are any outstanding promise rejections. This allows unhandled promises to
|
|
1121
|
+
* be reported before a new task is started, ensuring the error is reported
|
|
1122
|
+
* to the current task queue.
|
|
1123
|
+
*
|
|
1124
|
+
* @private {number}
|
|
1125
|
+
*/
|
|
1126
|
+
this.pendingRejections_ = 0;
|
|
1127
|
+
|
|
1128
|
+
/**
|
|
1129
|
+
* The number of aborted frames since the last time a task was executed or a
|
|
1130
|
+
* frame completed successfully.
|
|
1131
|
+
* @private {number}
|
|
1132
|
+
*/
|
|
1133
|
+
this.numAbortedFrames_ = 0;
|
|
1047
1134
|
};
|
|
1048
1135
|
goog.inherits(webdriver.promise.ControlFlow, webdriver.EventEmitter);
|
|
1049
1136
|
|
|
@@ -1118,81 +1205,6 @@ webdriver.promise.ControlFlow.EventType = {
|
|
|
1118
1205
|
webdriver.promise.ControlFlow.EVENT_LOOP_FREQUENCY = 10;
|
|
1119
1206
|
|
|
1120
1207
|
|
|
1121
|
-
/**
|
|
1122
|
-
* Tracks the active execution frame for this instance. Lazily initialized
|
|
1123
|
-
* when the first task is scheduled.
|
|
1124
|
-
* @private {webdriver.promise.Frame_}
|
|
1125
|
-
*/
|
|
1126
|
-
webdriver.promise.ControlFlow.prototype.activeFrame_ = null;
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
/**
|
|
1130
|
-
* A reference to the frame in which new tasks should be scheduled. If
|
|
1131
|
-
* {@code null}, tasks will be scheduled within the active frame. When forcing
|
|
1132
|
-
* a function to run in the context of a new frame, this pointer is used to
|
|
1133
|
-
* ensure tasks are scheduled within the newly created frame, even though it
|
|
1134
|
-
* won't be active yet.
|
|
1135
|
-
* @private {webdriver.promise.Frame_}
|
|
1136
|
-
* @see {#runInNewFrame_}
|
|
1137
|
-
*/
|
|
1138
|
-
webdriver.promise.ControlFlow.prototype.schedulingFrame_ = null;
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
/**
|
|
1142
|
-
* Timeout ID set when the flow is about to shutdown without any errors
|
|
1143
|
-
* being detected. Upon shutting down, the flow will emit an
|
|
1144
|
-
* {@link webdriver.promise.ControlFlow.EventType.IDLE} event. Idle events
|
|
1145
|
-
* always follow a brief timeout in order to catch latent errors from the last
|
|
1146
|
-
* completed task. If this task had a callback registered, but no errback, and
|
|
1147
|
-
* the task fails, the unhandled failure would not be reported by the promise
|
|
1148
|
-
* system until the next turn of the event loop:
|
|
1149
|
-
*
|
|
1150
|
-
* // Schedule 1 task that fails.
|
|
1151
|
-
* var result = webriver.promise.controlFlow().schedule('example',
|
|
1152
|
-
* function() { return webdriver.promise.rejected('failed'); });
|
|
1153
|
-
* // Set a callback on the result. This delays reporting the unhandled
|
|
1154
|
-
* // failure for 1 turn of the event loop.
|
|
1155
|
-
* result.then(goog.nullFunction);
|
|
1156
|
-
*
|
|
1157
|
-
* @private {?number}
|
|
1158
|
-
*/
|
|
1159
|
-
webdriver.promise.ControlFlow.prototype.shutdownId_ = null;
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
/**
|
|
1163
|
-
* Interval ID for this instance's event loop.
|
|
1164
|
-
* @private {?number}
|
|
1165
|
-
*/
|
|
1166
|
-
webdriver.promise.ControlFlow.prototype.eventLoopId_ = null;
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
/**
|
|
1170
|
-
* The number of "pending" promise rejections.
|
|
1171
|
-
*
|
|
1172
|
-
* <p>Each time a promise is rejected and is not handled by a listener, it will
|
|
1173
|
-
* schedule a 0-based timeout to check if it is still unrejected in the next
|
|
1174
|
-
* turn of the JS-event loop. This allows listeners to attach to, and handle,
|
|
1175
|
-
* the rejected promise at any point in same turn of the event loop that the
|
|
1176
|
-
* promise was rejected.
|
|
1177
|
-
*
|
|
1178
|
-
* <p>When this flow's own event loop triggers, it will not run if there
|
|
1179
|
-
* are any outstanding promise rejections. This allows unhandled promises to
|
|
1180
|
-
* be reported before a new task is started, ensuring the error is reported to
|
|
1181
|
-
* the current task queue.
|
|
1182
|
-
*
|
|
1183
|
-
* @private {number}
|
|
1184
|
-
*/
|
|
1185
|
-
webdriver.promise.ControlFlow.prototype.pendingRejections_ = 0;
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
/**
|
|
1189
|
-
* The number of aborted frames since the last time a task was executed or a
|
|
1190
|
-
* frame completed successfully.
|
|
1191
|
-
* @private {number}
|
|
1192
|
-
*/
|
|
1193
|
-
webdriver.promise.ControlFlow.prototype.numAbortedFrames_ = 0;
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
1208
|
/**
|
|
1197
1209
|
* Resets this instance, clearing its queue and removing all event listeners.
|
|
1198
1210
|
*/
|
|
@@ -1376,14 +1388,15 @@ webdriver.promise.ControlFlow.prototype.timeout = function(
|
|
|
1376
1388
|
* <p>If the condition function throws, or returns a rejected promise, the
|
|
1377
1389
|
* wait task will fail.
|
|
1378
1390
|
*
|
|
1379
|
-
* @param {
|
|
1391
|
+
* @param {function(): T} condition The condition function to poll.
|
|
1380
1392
|
* @param {number} timeout How long to wait, in milliseconds, for the condition
|
|
1381
1393
|
* to hold before timing out.
|
|
1382
1394
|
* @param {string=} opt_message An optional error message to include if the
|
|
1383
1395
|
* wait times out; defaults to the empty string.
|
|
1384
|
-
* @return {!webdriver.promise.Promise} A promise that will be
|
|
1385
|
-
* condition has been satisified. The promise shall be rejected if
|
|
1386
|
-
* times out waiting for the condition.
|
|
1396
|
+
* @return {!webdriver.promise.Promise.<T>} A promise that will be fulfilled
|
|
1397
|
+
* when the condition has been satisified. The promise shall be rejected if
|
|
1398
|
+
* the wait times out waiting for the condition.
|
|
1399
|
+
* @template T
|
|
1387
1400
|
*/
|
|
1388
1401
|
webdriver.promise.ControlFlow.prototype.wait = function(
|
|
1389
1402
|
condition, timeout, opt_message) {
|
|
@@ -1524,10 +1537,11 @@ webdriver.promise.ControlFlow.prototype.runEventLoop_ = function() {
|
|
|
1524
1537
|
* @private
|
|
1525
1538
|
*/
|
|
1526
1539
|
webdriver.promise.ControlFlow.prototype.getNextTask_ = function() {
|
|
1527
|
-
var
|
|
1540
|
+
var frame = this.activeFrame_;
|
|
1541
|
+
var firstChild = frame.getFirstChild();
|
|
1528
1542
|
if (!firstChild) {
|
|
1529
|
-
if (!
|
|
1530
|
-
this.resolveFrame_(
|
|
1543
|
+
if (!frame.isWaiting) {
|
|
1544
|
+
this.resolveFrame_(frame);
|
|
1531
1545
|
}
|
|
1532
1546
|
return null;
|
|
1533
1547
|
}
|
|
@@ -1537,7 +1551,7 @@ webdriver.promise.ControlFlow.prototype.getNextTask_ = function() {
|
|
|
1537
1551
|
return this.getNextTask_();
|
|
1538
1552
|
}
|
|
1539
1553
|
|
|
1540
|
-
|
|
1554
|
+
frame.removeChild(firstChild);
|
|
1541
1555
|
return firstChild;
|
|
1542
1556
|
};
|
|
1543
1557
|
|
|
@@ -1558,7 +1572,7 @@ webdriver.promise.ControlFlow.prototype.resolveFrame_ = function(frame) {
|
|
|
1558
1572
|
frame.getParent().removeChild(frame);
|
|
1559
1573
|
}
|
|
1560
1574
|
this.trimHistory_();
|
|
1561
|
-
frame.
|
|
1575
|
+
frame.close();
|
|
1562
1576
|
|
|
1563
1577
|
if (!this.activeFrame_) {
|
|
1564
1578
|
this.commenceShutdown_();
|
|
@@ -1596,7 +1610,7 @@ webdriver.promise.ControlFlow.prototype.abortFrame_ = function(error) {
|
|
|
1596
1610
|
|
|
1597
1611
|
var frame = this.activeFrame_;
|
|
1598
1612
|
this.activeFrame_ = parent;
|
|
1599
|
-
frame.
|
|
1613
|
+
frame.abort(error);
|
|
1600
1614
|
};
|
|
1601
1615
|
|
|
1602
1616
|
|
|
@@ -1642,7 +1656,7 @@ webdriver.promise.ControlFlow.prototype.runInNewFrame_ = function(
|
|
|
1642
1656
|
webdriver.promise.popFlow_();
|
|
1643
1657
|
this.schedulingFrame_ = null;
|
|
1644
1658
|
}
|
|
1645
|
-
newFrame.
|
|
1659
|
+
newFrame.isLocked_ = true;
|
|
1646
1660
|
|
|
1647
1661
|
// If there was nothing scheduled in the new frame we can discard the
|
|
1648
1662
|
// frame and return immediately.
|
|
@@ -1652,24 +1666,25 @@ webdriver.promise.ControlFlow.prototype.runInNewFrame_ = function(
|
|
|
1652
1666
|
return;
|
|
1653
1667
|
}
|
|
1654
1668
|
|
|
1655
|
-
newFrame.
|
|
1669
|
+
newFrame.onComplete = function() {
|
|
1656
1670
|
webdriver.promise.asap(result, callback, errback);
|
|
1657
|
-
}
|
|
1671
|
+
};
|
|
1672
|
+
|
|
1673
|
+
newFrame.onAbort = function(e) {
|
|
1658
1674
|
if (webdriver.promise.Thenable.isImplementation(result) &&
|
|
1659
1675
|
result.isPending()) {
|
|
1660
1676
|
result.cancel(e);
|
|
1661
1677
|
e = result;
|
|
1662
1678
|
}
|
|
1663
1679
|
errback(e);
|
|
1664
|
-
}
|
|
1680
|
+
};
|
|
1665
1681
|
} catch (ex) {
|
|
1666
|
-
removeNewFrame(
|
|
1682
|
+
removeNewFrame(ex);
|
|
1667
1683
|
errback(ex);
|
|
1668
1684
|
}
|
|
1669
1685
|
|
|
1670
1686
|
/**
|
|
1671
|
-
* @param {
|
|
1672
|
-
* error that triggered the removal of this frame.
|
|
1687
|
+
* @param {*=} opt_err If provided, the reason that the frame was removed.
|
|
1673
1688
|
*/
|
|
1674
1689
|
function removeNewFrame(opt_err) {
|
|
1675
1690
|
var parent = newFrame.getParent();
|
|
@@ -1678,7 +1693,8 @@ webdriver.promise.ControlFlow.prototype.runInNewFrame_ = function(
|
|
|
1678
1693
|
}
|
|
1679
1694
|
|
|
1680
1695
|
if (opt_err) {
|
|
1681
|
-
newFrame.cancelRemainingTasks(
|
|
1696
|
+
newFrame.cancelRemainingTasks(
|
|
1697
|
+
'Tasks cancelled due to uncaught error: ' + opt_err);
|
|
1682
1698
|
}
|
|
1683
1699
|
self.activeFrame_ = oldFrame;
|
|
1684
1700
|
}
|
|
@@ -1753,44 +1769,98 @@ webdriver.promise.ControlFlow.prototype.abortNow_ = function(error) {
|
|
|
1753
1769
|
|
|
1754
1770
|
|
|
1755
1771
|
/**
|
|
1756
|
-
*
|
|
1772
|
+
* An execution frame within a {@link webdriver.promise.ControlFlow}. Each
|
|
1773
|
+
* frame represents the execution context for either a
|
|
1774
|
+
* {@link webdriver.promise.Task_} or a callback on a
|
|
1775
|
+
* {@link webdriver.promise.Deferred}.
|
|
1776
|
+
*
|
|
1777
|
+
* <p>Each frame may contain sub-frames. If child N is a sub-frame, then the
|
|
1778
|
+
* items queued within it are given priority over child N+1.
|
|
1779
|
+
*
|
|
1757
1780
|
* @param {!webdriver.promise.ControlFlow} flow The flow this instance belongs
|
|
1758
1781
|
* to.
|
|
1759
1782
|
* @constructor
|
|
1760
|
-
* @extends {webdriver.promise.Deferred}
|
|
1761
1783
|
* @private
|
|
1784
|
+
* @final
|
|
1785
|
+
* @struct
|
|
1762
1786
|
*/
|
|
1763
|
-
webdriver.promise.
|
|
1764
|
-
webdriver.promise.
|
|
1765
|
-
|
|
1766
|
-
goog.inherits(webdriver.promise.Node_, webdriver.promise.Deferred);
|
|
1787
|
+
webdriver.promise.Frame_ = function(flow) {
|
|
1788
|
+
/** @private {!webdriver.promise.ControlFlow} */
|
|
1789
|
+
this.flow_ = flow;
|
|
1767
1790
|
|
|
1791
|
+
/** @private {webdriver.promise.Frame_} */
|
|
1792
|
+
this.parent_ = null;
|
|
1768
1793
|
|
|
1769
|
-
/**
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1794
|
+
/**
|
|
1795
|
+
* @private {!Array.<!(webdriver.promise.Frame_|webdriver.promise.Task_)>}
|
|
1796
|
+
*/
|
|
1797
|
+
this.children_ = [];
|
|
1798
|
+
|
|
1799
|
+
|
|
1800
|
+
/** @private {(webdriver.promise.Frame_|webdriver.promise.Task_)} */
|
|
1801
|
+
this.lastInsertedChild_ = null;
|
|
1802
|
+
|
|
1803
|
+
/**
|
|
1804
|
+
* The task currently being executed within this frame.
|
|
1805
|
+
* @private {webdriver.promise.Task_}
|
|
1806
|
+
*/
|
|
1807
|
+
this.pendingTask_ = null;
|
|
1808
|
+
|
|
1809
|
+
/**
|
|
1810
|
+
* Whether this frame is currently locked. A locked frame represents an
|
|
1811
|
+
* executed function that has scheduled all of its tasks.
|
|
1812
|
+
*
|
|
1813
|
+
* <p>Once a frame becomes locked, any new frames which are added as children
|
|
1814
|
+
* represent interrupts (such as a {@link webdriver.promise.Promise}
|
|
1815
|
+
* callback) whose tasks must be given priority over those already scheduled
|
|
1816
|
+
* within this frame. For example:
|
|
1817
|
+
* <code><pre>
|
|
1818
|
+
* var flow = webdriver.promise.controlFlow();
|
|
1819
|
+
* flow.execute('start here', goog.nullFunction).then(function() {
|
|
1820
|
+
* flow.execute('this should execute 2nd', goog.nullFunction);
|
|
1821
|
+
* });
|
|
1822
|
+
* flow.execute('this should execute last', goog.nullFunction);
|
|
1823
|
+
* </pre></code>
|
|
1824
|
+
*
|
|
1825
|
+
* @private {boolean}
|
|
1826
|
+
*/
|
|
1827
|
+
this.isLocked_ = false;
|
|
1828
|
+
|
|
1829
|
+
/** @type {boolean} */
|
|
1830
|
+
this.isWaiting = false;
|
|
1831
|
+
|
|
1832
|
+
/**
|
|
1833
|
+
* The function to notify if this frame executes without error.
|
|
1834
|
+
* @type {?function()}
|
|
1835
|
+
*/
|
|
1836
|
+
this.onComplete = null;
|
|
1837
|
+
|
|
1838
|
+
/**
|
|
1839
|
+
* The function to notify if this frame is aborted with an error.
|
|
1840
|
+
* @type {?function(*)}
|
|
1841
|
+
*/
|
|
1842
|
+
this.onAbort = null;
|
|
1843
|
+
};
|
|
1774
1844
|
|
|
1775
1845
|
|
|
1776
|
-
/** @return {webdriver.promise.
|
|
1777
|
-
webdriver.promise.
|
|
1846
|
+
/** @return {webdriver.promise.Frame_} This frame's parent, if any. */
|
|
1847
|
+
webdriver.promise.Frame_.prototype.getParent = function() {
|
|
1778
1848
|
return this.parent_;
|
|
1779
1849
|
};
|
|
1780
1850
|
|
|
1781
1851
|
|
|
1782
1852
|
/**
|
|
1783
|
-
* @param {webdriver.promise.
|
|
1853
|
+
* @param {webdriver.promise.Frame_} parent This frame's new parent.
|
|
1784
1854
|
*/
|
|
1785
|
-
webdriver.promise.
|
|
1855
|
+
webdriver.promise.Frame_.prototype.setParent = function(parent) {
|
|
1786
1856
|
this.parent_ = parent;
|
|
1787
1857
|
};
|
|
1788
1858
|
|
|
1789
1859
|
|
|
1790
1860
|
/**
|
|
1791
|
-
* @return {!webdriver.promise.
|
|
1861
|
+
* @return {!webdriver.promise.Frame_} The root of this frame's tree.
|
|
1792
1862
|
*/
|
|
1793
|
-
webdriver.promise.
|
|
1863
|
+
webdriver.promise.Frame_.prototype.getRoot = function() {
|
|
1794
1864
|
var root = this;
|
|
1795
1865
|
while (root.parent_) {
|
|
1796
1866
|
root = root.parent_;
|
|
@@ -1799,88 +1869,51 @@ webdriver.promise.Node_.prototype.getRoot = function() {
|
|
|
1799
1869
|
};
|
|
1800
1870
|
|
|
1801
1871
|
|
|
1802
|
-
|
|
1803
1872
|
/**
|
|
1804
|
-
*
|
|
1805
|
-
*
|
|
1806
|
-
* {@link webdriver.promise.Task_} or a callback on a
|
|
1807
|
-
* {@link webdriver.promise.Deferred}.
|
|
1873
|
+
* Aborts the execution of this frame, cancelling all outstanding tasks
|
|
1874
|
+
* scheduled within this frame.
|
|
1808
1875
|
*
|
|
1809
|
-
*
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
this.reject = function(e) {
|
|
1826
|
-
cancelRemainingTasks(new webdriver.promise.CanceledTaskError_(e));
|
|
1827
|
-
reject(e);
|
|
1828
|
-
};
|
|
1829
|
-
|
|
1830
|
-
/**
|
|
1831
|
-
* @private {!Array.<!(webdriver.promise.Frame_|webdriver.promise.Task_)>}
|
|
1832
|
-
*/
|
|
1833
|
-
this.children_ = [];
|
|
1876
|
+
* @param {*} error The error that triggered this abortion.
|
|
1877
|
+
*/
|
|
1878
|
+
webdriver.promise.Frame_.prototype.abort = function(error) {
|
|
1879
|
+
this.cancelRemainingTasks(
|
|
1880
|
+
'Task discarded due to a previous task failure: ' + error);
|
|
1881
|
+
|
|
1882
|
+
var frame = this;
|
|
1883
|
+
frame.flow_.pendingRejections_ += 1;
|
|
1884
|
+
this.flow_.timer.setTimeout(function() {
|
|
1885
|
+
frame.flow_.pendingRejections_ -= 1;
|
|
1886
|
+
if (frame.onAbort) {
|
|
1887
|
+
frame.notify_(frame.onAbort, error);
|
|
1888
|
+
} else {
|
|
1889
|
+
frame.flow_.abortFrame_(error);
|
|
1890
|
+
}
|
|
1891
|
+
}, 0);
|
|
1834
1892
|
};
|
|
1835
|
-
goog.inherits(webdriver.promise.Frame_, webdriver.promise.Node_);
|
|
1836
1893
|
|
|
1837
1894
|
|
|
1838
1895
|
/**
|
|
1839
|
-
*
|
|
1840
|
-
* @private {webdriver.promise.Task_}
|
|
1896
|
+
* Signals that this frame has successfully finished executing.
|
|
1841
1897
|
*/
|
|
1842
|
-
webdriver.promise.Frame_.prototype.
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
*
|
|
1849
|
-
* Adding a sub-frame as a child to an active frame is an indication that
|
|
1850
|
-
* a callback to a {@link webdriver.promise.Deferred} is being invoked and any
|
|
1851
|
-
* tasks scheduled within it should have priority over previously scheduled
|
|
1852
|
-
* tasks:
|
|
1853
|
-
* <code><pre>
|
|
1854
|
-
* var flow = webdriver.promise.controlFlow();
|
|
1855
|
-
* flow.execute('start here', goog.nullFunction).then(function() {
|
|
1856
|
-
* flow.execute('this should execute 2nd', goog.nullFunction);
|
|
1857
|
-
* });
|
|
1858
|
-
* flow.execute('this should execute last', goog.nullFunction);
|
|
1859
|
-
* </pre></code>
|
|
1860
|
-
*
|
|
1861
|
-
* @private {boolean}
|
|
1862
|
-
*/
|
|
1863
|
-
webdriver.promise.Frame_.prototype.isActive_ = false;
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
/**
|
|
1867
|
-
* Whether this frame is currently locked. A locked frame represents a callback
|
|
1868
|
-
* or task function which has run to completion and scheduled all of its tasks.
|
|
1869
|
-
*
|
|
1870
|
-
* <p>Once a frame becomes {@link #isActive_ active}, any new frames which are
|
|
1871
|
-
* added represent callbacks on a {@link webdriver.promise.Deferred}, whose
|
|
1872
|
-
* tasks must be given priority over previously scheduled tasks.
|
|
1873
|
-
*
|
|
1874
|
-
* @private {boolean}
|
|
1875
|
-
*/
|
|
1876
|
-
webdriver.promise.Frame_.prototype.isLocked_ = false;
|
|
1898
|
+
webdriver.promise.Frame_.prototype.close = function() {
|
|
1899
|
+
var frame = this;
|
|
1900
|
+
this.flow_.timer.setTimeout(function() {
|
|
1901
|
+
frame.notify_(frame.onComplete);
|
|
1902
|
+
}, 0);
|
|
1903
|
+
};
|
|
1877
1904
|
|
|
1878
1905
|
|
|
1879
1906
|
/**
|
|
1880
|
-
*
|
|
1881
|
-
* @
|
|
1907
|
+
* @param {?(function(*)|function())} fn The function to notify.
|
|
1908
|
+
* @param {*=} opt_error Value to pass to the notified function, if any.
|
|
1909
|
+
* @private
|
|
1882
1910
|
*/
|
|
1883
|
-
webdriver.promise.Frame_.prototype.
|
|
1911
|
+
webdriver.promise.Frame_.prototype.notify_ = function(fn, opt_error) {
|
|
1912
|
+
this.onAbort = this.onComplete = null;
|
|
1913
|
+
if (fn) {
|
|
1914
|
+
fn(opt_error);
|
|
1915
|
+
}
|
|
1916
|
+
};
|
|
1884
1917
|
|
|
1885
1918
|
|
|
1886
1919
|
/**
|
|
@@ -1901,23 +1934,22 @@ webdriver.promise.Frame_.prototype.lastInsertedChild_ = null;
|
|
|
1901
1934
|
* });
|
|
1902
1935
|
* });
|
|
1903
1936
|
* // flow failed: Error: boom
|
|
1904
|
-
* // task failed!
|
|
1937
|
+
* // task failed! CancelledTaskError: Task discarded due to a previous
|
|
1905
1938
|
* // task failure: Error: boom
|
|
1906
1939
|
*
|
|
1907
|
-
* @param {
|
|
1908
|
-
* error.
|
|
1940
|
+
* @param {string} reason The cancellation reason.
|
|
1909
1941
|
*/
|
|
1910
|
-
webdriver.promise.Frame_.prototype.cancelRemainingTasks = function(
|
|
1942
|
+
webdriver.promise.Frame_.prototype.cancelRemainingTasks = function(reason) {
|
|
1911
1943
|
goog.array.forEach(this.children_, function(child) {
|
|
1912
1944
|
if (child instanceof webdriver.promise.Frame_) {
|
|
1913
|
-
child.cancelRemainingTasks(
|
|
1945
|
+
child.cancelRemainingTasks(reason);
|
|
1914
1946
|
} else {
|
|
1915
1947
|
// None of the previously registered listeners should be notified that
|
|
1916
1948
|
// the task is being canceled, however, we need at least one errback
|
|
1917
1949
|
// to prevent the cancellation from bubbling up.
|
|
1918
1950
|
child.removeAll();
|
|
1919
1951
|
child.thenCatch(goog.nullFunction);
|
|
1920
|
-
child.cancel(
|
|
1952
|
+
child.cancel(reason);
|
|
1921
1953
|
}
|
|
1922
1954
|
});
|
|
1923
1955
|
};
|
|
@@ -1941,12 +1973,6 @@ webdriver.promise.Frame_.prototype.setPendingTask = function(task) {
|
|
|
1941
1973
|
};
|
|
1942
1974
|
|
|
1943
1975
|
|
|
1944
|
-
/** Locks this frame. */
|
|
1945
|
-
webdriver.promise.Frame_.prototype.lockFrame = function() {
|
|
1946
|
-
this.isLocked_ = true;
|
|
1947
|
-
};
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
1976
|
/**
|
|
1951
1977
|
* Adds a new node to this frame.
|
|
1952
1978
|
* @param {!(webdriver.promise.Frame_|webdriver.promise.Task_)} node
|
|
@@ -1960,9 +1986,11 @@ webdriver.promise.Frame_.prototype.addChild = function(node) {
|
|
|
1960
1986
|
return;
|
|
1961
1987
|
}
|
|
1962
1988
|
|
|
1963
|
-
node.
|
|
1989
|
+
if (node instanceof webdriver.promise.Frame_) {
|
|
1990
|
+
node.setParent(this);
|
|
1991
|
+
}
|
|
1964
1992
|
|
|
1965
|
-
if (this.
|
|
1993
|
+
if (this.isLocked_ && node instanceof webdriver.promise.Frame_) {
|
|
1966
1994
|
var index = 0;
|
|
1967
1995
|
if (this.lastInsertedChild_ instanceof
|
|
1968
1996
|
webdriver.promise.Frame_) {
|
|
@@ -1983,7 +2011,7 @@ webdriver.promise.Frame_.prototype.addChild = function(node) {
|
|
|
1983
2011
|
* fist child.
|
|
1984
2012
|
*/
|
|
1985
2013
|
webdriver.promise.Frame_.prototype.getFirstChild = function() {
|
|
1986
|
-
this.
|
|
2014
|
+
this.isLocked_ = true;
|
|
1987
2015
|
this.lastInsertedChild_ = null;
|
|
1988
2016
|
return this.children_[0];
|
|
1989
2017
|
};
|
|
@@ -1996,7 +2024,9 @@ webdriver.promise.Frame_.prototype.getFirstChild = function() {
|
|
|
1996
2024
|
*/
|
|
1997
2025
|
webdriver.promise.Frame_.prototype.removeChild = function(child) {
|
|
1998
2026
|
var index = goog.array.indexOf(this.children_, child);
|
|
1999
|
-
child.
|
|
2027
|
+
if (child instanceof webdriver.promise.Frame_) {
|
|
2028
|
+
child.setParent(null);
|
|
2029
|
+
}
|
|
2000
2030
|
goog.array.removeAt(this.children_, index);
|
|
2001
2031
|
if (this.lastInsertedChild_ === child) {
|
|
2002
2032
|
this.lastInsertedChild_ = null;
|
|
@@ -2018,22 +2048,23 @@ webdriver.promise.Frame_.prototype.toString = function() {
|
|
|
2018
2048
|
*
|
|
2019
2049
|
* @param {!webdriver.promise.ControlFlow} flow The flow this instances belongs
|
|
2020
2050
|
* to.
|
|
2021
|
-
* @param {
|
|
2022
|
-
*
|
|
2023
|
-
*
|
|
2051
|
+
* @param {function(): (T|!webdriver.promise.Promise.<T>)} fn The function to
|
|
2052
|
+
* call when the task executes. If it returns a
|
|
2053
|
+
* {@link webdriver.promise.Promise}, the flow will wait for it to be
|
|
2054
|
+
* resolved before starting the next task.
|
|
2024
2055
|
* @param {string} description A description of the task for debugging.
|
|
2025
2056
|
* @param {!webdriver.stacktrace.Snapshot} snapshot A snapshot of the stack
|
|
2026
2057
|
* when this task was scheduled.
|
|
2027
2058
|
* @constructor
|
|
2028
|
-
* @extends {webdriver.promise.
|
|
2059
|
+
* @extends {webdriver.promise.Deferred.<T>}
|
|
2060
|
+
* @template T
|
|
2029
2061
|
* @private
|
|
2030
2062
|
*/
|
|
2031
2063
|
webdriver.promise.Task_ = function(flow, fn, description, snapshot) {
|
|
2032
|
-
webdriver.promise.
|
|
2064
|
+
webdriver.promise.Deferred.call(this, flow);
|
|
2033
2065
|
|
|
2034
2066
|
/**
|
|
2035
|
-
*
|
|
2036
|
-
* @type {!Function}
|
|
2067
|
+
* @type {function(): (T|!webdriver.promise.Promise.<T>)}
|
|
2037
2068
|
*/
|
|
2038
2069
|
this.execute = fn;
|
|
2039
2070
|
|
|
@@ -2043,7 +2074,7 @@ webdriver.promise.Task_ = function(flow, fn, description, snapshot) {
|
|
|
2043
2074
|
/** @private {!webdriver.stacktrace.Snapshot} */
|
|
2044
2075
|
this.snapshot_ = snapshot;
|
|
2045
2076
|
};
|
|
2046
|
-
goog.inherits(webdriver.promise.Task_, webdriver.promise.
|
|
2077
|
+
goog.inherits(webdriver.promise.Task_, webdriver.promise.Deferred);
|
|
2047
2078
|
|
|
2048
2079
|
|
|
2049
2080
|
/** @return {string} This task's description. */
|
|
@@ -2067,25 +2098,6 @@ webdriver.promise.Task_.prototype.toString = function() {
|
|
|
2067
2098
|
|
|
2068
2099
|
|
|
2069
2100
|
|
|
2070
|
-
/**
|
|
2071
|
-
* Special error used to signal when a task is canceled because a previous
|
|
2072
|
-
* task in the same frame failed.
|
|
2073
|
-
* @param {*} err The error that caused the task cancellation.
|
|
2074
|
-
* @constructor
|
|
2075
|
-
* @extends {goog.debug.Error}
|
|
2076
|
-
* @private
|
|
2077
|
-
*/
|
|
2078
|
-
webdriver.promise.CanceledTaskError_ = function(err) {
|
|
2079
|
-
goog.base(this, 'Task discarded due to a previous task failure: ' + err);
|
|
2080
|
-
};
|
|
2081
|
-
goog.inherits(webdriver.promise.CanceledTaskError_, goog.debug.Error);
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
/** @override */
|
|
2085
|
-
webdriver.promise.CanceledTaskError_.prototype.name = 'CanceledTaskError';
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
2101
|
/**
|
|
2090
2102
|
* The default flow to use if no others are active.
|
|
2091
2103
|
* @private {!webdriver.promise.ControlFlow}
|