selenium-webdriver 3.0.1 → 3.5.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 (67) hide show
  1. package/CHANGES.md +92 -0
  2. package/NOTICE +1 -1
  3. package/README.md +11 -14
  4. package/chrome.js +125 -36
  5. package/edge.js +3 -3
  6. package/example/async_await_test.js +68 -0
  7. package/example/chrome_headless.js +47 -0
  8. package/example/chrome_mobile_emulation.js +1 -1
  9. package/example/firefox_channels.js +73 -0
  10. package/example/google_search_test.js +1 -1
  11. package/firefox/binary.js +114 -57
  12. package/firefox/extension.js +118 -81
  13. package/firefox/index.js +67 -135
  14. package/firefox/profile.js +13 -49
  15. package/ie.js +2 -2
  16. package/index.js +6 -3
  17. package/io/index.js +59 -0
  18. package/io/zip.js +214 -0
  19. package/lib/README +2 -3
  20. package/lib/actions.js +4 -4
  21. package/lib/atoms/getAttribute.js +9 -11
  22. package/lib/atoms/is-displayed.js +102 -0
  23. package/lib/by.js +9 -1
  24. package/lib/capabilities.js +5 -5
  25. package/lib/command.js +2 -0
  26. package/lib/error.js +29 -4
  27. package/lib/events.js +1 -1
  28. package/lib/firefox/webdriver.json +2 -1
  29. package/lib/http.js +84 -69
  30. package/lib/input.js +1 -1
  31. package/lib/promise.js +205 -81
  32. package/lib/symbols.js +1 -1
  33. package/lib/test/data/click_tests/disabled_element.html +12 -0
  34. package/lib/test/data/firefox/webextension.xpi +0 -0
  35. package/lib/test/data/key_logger.html +34 -0
  36. package/lib/test/data/nestedElements.html +10 -1
  37. package/lib/test/data/single_text_input.html +12 -0
  38. package/lib/test/index.js +9 -35
  39. package/lib/until.js +1 -1
  40. package/lib/webdriver.js +130 -34
  41. package/net/portprober.js +1 -1
  42. package/opera.js +2 -2
  43. package/package.json +2 -2
  44. package/phantomjs.js +2 -2
  45. package/remote/index.js +17 -11
  46. package/safari.js +47 -8
  47. package/test/firefox/extension_test.js +41 -17
  48. package/test/firefox/firefox_test.js +70 -23
  49. package/test/firefox/profile_test.js +14 -59
  50. package/test/http/http_test.js +18 -0
  51. package/test/{io_test.js → io/io_test.js} +40 -1
  52. package/test/io/zip_test.js +128 -0
  53. package/test/lib/by_test.js +21 -0
  54. package/test/lib/error_test.js +20 -1
  55. package/test/lib/http_test.js +41 -2
  56. package/test/lib/promise_test.js +19 -0
  57. package/test/lib/until_test.js +28 -13
  58. package/test/lib/webdriver_test.js +107 -3
  59. package/test/page_loading_test.js +0 -6
  60. package/test/rect_test.js +60 -0
  61. package/test/remote_test.js +3 -3
  62. package/test/session_test.js +68 -23
  63. package/testing/index.js +16 -5
  64. package/lib/atoms/isDisplayed.js +0 -106
  65. package/lib/firefox/amd64/libnoblur64.so +0 -0
  66. package/lib/firefox/i386/libnoblur.so +0 -0
  67. package/lib/firefox/webdriver.xpi +0 -0
package/lib/promise.js CHANGED
@@ -48,7 +48,7 @@
48
48
  * > e => console.error('FAILURE: ' + e));
49
49
  * > ```
50
50
  * >
51
- * > The motiviation behind this change and full deprecation plan are documented
51
+ * > The motivation behind this change and full deprecation plan are documented
52
52
  * > in [issue 2969](https://github.com/SeleniumHQ/selenium/issues/2969).
53
53
  * >
54
54
  * >
@@ -87,8 +87,7 @@
87
87
  * The control flow is based on the concept of tasks and task queues. Tasks are
88
88
  * functions that define the basic unit of work for the control flow to execute.
89
89
  * Each task is scheduled via {@link ControlFlow#execute()}, which will return
90
- * a {@link ManagedPromise ManagedPromise} that will be resolved with the task's
91
- * result.
90
+ * a {@link ManagedPromise} that will be resolved with the task's result.
92
91
  *
93
92
  * A task queue contains all of the tasks scheduled within a single turn of the
94
93
  * [JavaScript event loop][JSEL]. The control flow will create a new task queue
@@ -103,13 +102,13 @@
103
102
  *
104
103
  * Whenever the control flow creates a new task queue, it will automatically
105
104
  * begin executing tasks in the next available turn of the event loop. This
106
- * execution is scheduled using a "micro-task" timer, such as a (native)
107
- * `ManagedPromise.then()` callback.
105
+ * execution is [scheduled as a microtask][MicrotasksArticle] like e.g. a
106
+ * (native) `Promise.then()` callback.
108
107
  *
109
108
  * setTimeout(() => console.log('a'));
110
- * ManagedPromise.resolve().then(() => console.log('b')); // A native promise.
109
+ * Promise.resolve().then(() => console.log('b')); // A native promise.
111
110
  * flow.execute(() => console.log('c'));
112
- * ManagedPromise.resolve().then(() => console.log('d'));
111
+ * Promise.resolve().then(() => console.log('d'));
113
112
  * setTimeout(() => console.log('fin'));
114
113
  * // b
115
114
  * // c
@@ -118,13 +117,13 @@
118
117
  * // fin
119
118
  *
120
119
  * In the example above, b/c/d is logged before a/fin because native promises
121
- * and this module use "micro-task" timers, which have a higher priority than
122
- * "macro-tasks" like `setTimeout`.
120
+ * and this module use "microtask" timers, which have a higher priority than
121
+ * "macrotasks" like `setTimeout`.
123
122
  *
124
123
  * ## Task Execution
125
124
  *
126
- * Upon creating a task queue, and whenever an exisiting queue completes a task,
127
- * the control flow will schedule a micro-task timer to process any scheduled
125
+ * Upon creating a task queue, and whenever an existing queue completes a task,
126
+ * the control flow will schedule a microtask timer to process any scheduled
128
127
  * tasks. This ensures no task is ever started within the same turn of the
129
128
  * JavaScript event loop in which it was scheduled, nor is a task ever started
130
129
  * within the same turn that another finishes.
@@ -140,13 +139,13 @@
140
139
  * discarded and the task's promised result (previously returned by
141
140
  * {@link ControlFlow#execute()}) is immediately rejected with the thrown
142
141
  * error.
143
- * 3. The task function returns sucessfully.
142
+ * 3. The task function returns successfully.
144
143
  *
145
144
  * If a task function created a new task queue, the control flow will wait for
146
145
  * that queue to complete before processing the task result. If the queue
147
146
  * completes without error, the flow will settle the task's promise with the
148
- * value originaly returned by the task function. On the other hand, if the task
149
- * queue termintes with an error, the task's promise will be rejected with that
147
+ * value originally returned by the task function. On the other hand, if the task
148
+ * queue terminates with an error, the task's promise will be rejected with that
150
149
  * error.
151
150
  *
152
151
  * flow.execute(function() {
@@ -161,7 +160,7 @@
161
160
  * ## ManagedPromise Integration
162
161
  *
163
162
  * In addition to the {@link ControlFlow} class, the promise module also exports
164
- * a [ManagedPromise/A+] {@linkplain ManagedPromise implementation} that is deeply
163
+ * a [Promises/A+] {@linkplain ManagedPromise implementation} that is deeply
165
164
  * integrated with the ControlFlow. First and foremost, each promise
166
165
  * {@linkplain ManagedPromise#then() callback} is scheduled with the
167
166
  * control flow as a task. As a result, each callback is invoked in its own turn
@@ -328,7 +327,7 @@
328
327
  * Even though a subtask's promised result will never resolve while the task
329
328
  * function is on the stack, it will be treated as a promise resolved within the
330
329
  * task. In all other scenarios, a task's promise behaves just like a normal
331
- * promise. In the sample below, `C/D` is loggged before `B` because the
330
+ * promise. In the sample below, `C/D` is logged before `B` because the
332
331
  * resolution of `subtask1` interrupts the flow of the enclosing task. Within
333
332
  * the final subtask, `E/F` is logged in order because `subtask1` is a resolved
334
333
  * promise when that task runs.
@@ -467,17 +466,17 @@
467
466
  *
468
467
  * ES6 promises do not require users to handle a promise rejections. This can
469
468
  * result in subtle bugs as the rejections are silently "swallowed" by the
470
- * ManagedPromise class.
469
+ * Promise class.
471
470
  *
472
- * ManagedPromise.reject(Error('boom'));
471
+ * Promise.reject(Error('boom'));
473
472
  * // ... *crickets* ...
474
473
  *
475
474
  * Selenium's promise module, on the other hand, requires that every rejection
476
475
  * be explicitly handled. When a {@linkplain ManagedPromise ManagedPromise} is
477
476
  * rejected and no callbacks are defined on that promise, it is considered an
478
- * _unhandled rejection_ and reproted to the active task queue. If the rejection
477
+ * _unhandled rejection_ and reported to the active task queue. If the rejection
479
478
  * remains unhandled after a single turn of the [event loop][JSEL] (scheduled
480
- * with a micro-task), it will propagate up the stack.
479
+ * with a microtask), it will propagate up the stack.
481
480
  *
482
481
  * ## Error Propagation
483
482
  *
@@ -534,7 +533,7 @@
534
533
  *
535
534
  * When a subtask is discarded due to an unreported rejection in its parent
536
535
  * frame, the existing callbacks on that task will never settle and the
537
- * callbacks will not be invoked. If a new callback is attached ot the subtask
536
+ * callbacks will not be invoked. If a new callback is attached to the subtask
538
537
  * _after_ it has been discarded, it is handled the same as adding a callback
539
538
  * to a cancelled promise: the error-callback path is invoked. This behavior is
540
539
  * intended to handle cases where the user saves a reference to a task promise,
@@ -582,9 +581,9 @@
582
581
  *
583
582
  * Bottom line: you __*must*__ handle rejected promises.
584
583
  *
585
- * # ManagedPromise/A+ Compatibility
584
+ * # Promises/A+ Compatibility
586
585
  *
587
- * This `promise` module is compliant with the [ManagedPromise/A+][] specification
586
+ * This `promise` module is compliant with the [Promises/A+] specification
588
587
  * except for sections `2.2.6.1` and `2.2.6.2`:
589
588
  *
590
589
  * >
@@ -595,10 +594,10 @@
595
594
  * > must execute in the order of their originating calls to `then`.
596
595
  * >
597
596
  *
598
- * Specifically, the conformance tests contains the following scenario (for
597
+ * Specifically, the conformance tests contain the following scenario (for
599
598
  * brevity, only the fulfillment version is shown):
600
599
  *
601
- * var p1 = ManagedPromise.resolve();
600
+ * var p1 = Promise.resolve();
602
601
  * p1.then(function() {
603
602
  * console.log('A');
604
603
  * p1.then(() => console.log('B'));
@@ -609,7 +608,7 @@
609
608
  * // B
610
609
  *
611
610
  * Since the [ControlFlow](#scheduling_callbacks) executes promise callbacks as
612
- * tasks, with this module, the result would be
611
+ * tasks, with this module, the result would be:
613
612
  *
614
613
  * var p2 = promise.fulfilled();
615
614
  * p2.then(function() {
@@ -623,7 +622,8 @@
623
622
  *
624
623
  * [JSEL]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop
625
624
  * [GF]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*
626
- * [ManagedPromise/A+]: https://promisesaplus.com/
625
+ * [Promises/A+]: https://promisesaplus.com/
626
+ * [MicrotasksArticle]: https://jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/
627
627
  */
628
628
 
629
629
  'use strict';
@@ -667,7 +667,7 @@ function getUid(obj) {
667
667
 
668
668
 
669
669
  /**
670
- * Runs the given function after a micro-task yield.
670
+ * Runs the given function after a microtask yield.
671
671
  * @param {function()} fn The function to run.
672
672
  */
673
673
  function asyncRun(fn) {
@@ -942,7 +942,7 @@ class Thenable {
942
942
 
943
943
  /**
944
944
  * Marker interface for objects that allow consumers to request the cancellation
945
- * of a promies-based operation. A cancelled promise will be rejected with a
945
+ * of a promise-based operation. A cancelled promise will be rejected with a
946
946
  * {@link CancellationError}.
947
947
  *
948
948
  * This interface is considered package-private and should not be used outside
@@ -1003,6 +1003,9 @@ const PromiseState = {
1003
1003
  */
1004
1004
  const ON_CANCEL_HANDLER = new WeakMap;
1005
1005
 
1006
+ const SKIP_LOG = Symbol('skip-log');
1007
+ const FLOW_LOG = logging.getLogger('promise.ControlFlow');
1008
+
1006
1009
 
1007
1010
  /**
1008
1011
  * Represents the eventual value of a completed operation. Each promise may be
@@ -1025,14 +1028,29 @@ class ManagedPromise {
1025
1028
  * functions, one for fulfilling the promise and another for rejecting it.
1026
1029
  * @param {ControlFlow=} opt_flow The control flow
1027
1030
  * this instance was created under. Defaults to the currently active flow.
1031
+ * @param {?=} opt_skipLog An internal parameter used to skip logging the
1032
+ * creation of this promise. This parameter has no effect unless it is
1033
+ * strictly equal to an internal symbol. In other words, this parameter
1034
+ * is always ignored for external code.
1028
1035
  */
1029
- constructor(resolver, opt_flow) {
1036
+ constructor(resolver, opt_flow, opt_skipLog) {
1030
1037
  if (!usePromiseManager()) {
1031
1038
  throw TypeError(
1032
1039
  'Unable to create a managed promise instance: the promise manager has'
1033
1040
  + ' been disabled by the SELENIUM_PROMISE_MANAGER environment'
1034
1041
  + ' variable: ' + process.env['SELENIUM_PROMISE_MANAGER']);
1042
+ } else if (opt_skipLog !== SKIP_LOG) {
1043
+ FLOW_LOG.warning(() => {
1044
+ let e =
1045
+ captureStackTrace(
1046
+ 'ManagedPromiseError',
1047
+ 'Creating a new managed Promise. This call will fail when the'
1048
+ + ' promise manager is disabled',
1049
+ ManagedPromise)
1050
+ return e.stack;
1051
+ });
1035
1052
  }
1053
+
1036
1054
  getUid(this);
1037
1055
 
1038
1056
  /** @private {!ControlFlow} */
@@ -1308,7 +1326,7 @@ class ManagedPromise {
1308
1326
  * @param {!Function} fn The function to use as the top of the stack when
1309
1327
  * recording the callback's creation point.
1310
1328
  * @return {!ManagedPromise<R>} A new promise which will be resolved with the
1311
- * esult of the invoked callback.
1329
+ * result of the invoked callback.
1312
1330
  * @template R
1313
1331
  * @private
1314
1332
  */
@@ -1383,6 +1401,37 @@ function isPending(promise) {
1383
1401
  }
1384
1402
 
1385
1403
 
1404
+ /**
1405
+ * Structural interface for a deferred promise resolver.
1406
+ * @record
1407
+ * @template T
1408
+ */
1409
+ function Resolver() {}
1410
+
1411
+
1412
+ /**
1413
+ * The promised value for this resolver.
1414
+ * @type {!Thenable<T>}
1415
+ */
1416
+ Resolver.prototype.promise;
1417
+
1418
+
1419
+ /**
1420
+ * Resolves the promised value with the given `value`.
1421
+ * @param {T|Thenable<T>} value
1422
+ * @return {void}
1423
+ */
1424
+ Resolver.prototype.resolve;
1425
+
1426
+
1427
+ /**
1428
+ * Rejects the promised value with the given `reason`.
1429
+ * @param {*} reason
1430
+ * @return {void}
1431
+ */
1432
+ Resolver.prototype.reject;
1433
+
1434
+
1386
1435
  /**
1387
1436
  * Represents a value that will be resolved at some point in the future. This
1388
1437
  * class represents the protected "producer" half of a ManagedPromise - each Deferred
@@ -1395,20 +1444,25 @@ function isPending(promise) {
1395
1444
  * {@link ControlFlow} as an unhandled failure.
1396
1445
  *
1397
1446
  * @template T
1447
+ * @implements {Resolver<T>}
1398
1448
  */
1399
1449
  class Deferred {
1400
1450
  /**
1401
1451
  * @param {ControlFlow=} opt_flow The control flow this instance was
1402
1452
  * created under. This should only be provided during unit tests.
1453
+ * @param {?=} opt_skipLog An internal parameter used to skip logging the
1454
+ * creation of this promise. This parameter has no effect unless it is
1455
+ * strictly equal to an internal symbol. In other words, this parameter
1456
+ * is always ignored for external code.
1403
1457
  */
1404
- constructor(opt_flow) {
1458
+ constructor(opt_flow, opt_skipLog) {
1405
1459
  var fulfill, reject;
1406
1460
 
1407
1461
  /** @type {!ManagedPromise<T>} */
1408
1462
  this.promise = new ManagedPromise(function(f, r) {
1409
1463
  fulfill = f;
1410
1464
  reject = r;
1411
- }, opt_flow);
1465
+ }, opt_flow, opt_skipLog);
1412
1466
 
1413
1467
  var self = this;
1414
1468
  var checkNotSelf = function(value) {
@@ -1421,16 +1475,24 @@ class Deferred {
1421
1475
  * Resolves this deferred with the given value. It is safe to call this as a
1422
1476
  * normal function (with no bound "this").
1423
1477
  * @param {(T|IThenable<T>|Thenable)=} opt_value The fulfilled value.
1478
+ * @const
1424
1479
  */
1425
- this.fulfill = function(opt_value) {
1480
+ this.resolve = function(opt_value) {
1426
1481
  checkNotSelf(opt_value);
1427
1482
  fulfill(opt_value);
1428
1483
  };
1429
1484
 
1485
+ /**
1486
+ * An alias for {@link #resolve}.
1487
+ * @const
1488
+ */
1489
+ this.fulfill = this.resolve;
1490
+
1430
1491
  /**
1431
1492
  * Rejects this promise with the given reason. It is safe to call this as a
1432
1493
  * normal function (with no bound "this").
1433
1494
  * @param {*=} opt_reason The rejection reason.
1495
+ * @const
1434
1496
  */
1435
1497
  this.reject = function(opt_reason) {
1436
1498
  checkNotSelf(opt_reason);
@@ -1487,36 +1549,76 @@ function delayed(ms) {
1487
1549
 
1488
1550
 
1489
1551
  /**
1490
- * Creates a new deferred object.
1491
- * @return {!Deferred<T>} The new deferred object.
1552
+ * Creates a new deferred resolver.
1553
+ *
1554
+ * If the promise manager is currently enabled, this function will return a
1555
+ * {@link Deferred} instance. Otherwise, it will return a resolver for a
1556
+ * {@linkplain NativePromise native promise}.
1557
+ *
1558
+ * @return {!Resolver<T>} A new deferred resolver.
1492
1559
  * @template T
1493
1560
  */
1494
1561
  function defer() {
1495
- return new Deferred();
1562
+ if (usePromiseManager()) {
1563
+ return new Deferred();
1564
+ }
1565
+ let resolve, reject;
1566
+ let promise = new NativePromise((_resolve, _reject) => {
1567
+ resolve = _resolve;
1568
+ reject = _reject;
1569
+ });
1570
+ return {promise, resolve, reject};
1496
1571
  }
1497
1572
 
1498
1573
 
1499
1574
  /**
1500
1575
  * Creates a promise that has been resolved with the given value.
1576
+ *
1577
+ * If the promise manager is currently enabled, this function will return a
1578
+ * {@linkplain ManagedPromise managed promise}. Otherwise, it will return a
1579
+ * {@linkplain NativePromise native promise}.
1580
+ *
1501
1581
  * @param {T=} opt_value The resolved value.
1502
- * @return {!ManagedPromise<T>} The resolved promise.
1503
- * @deprecated Use {@link ManagedPromise#resolve Promise.resolve(value)}.
1582
+ * @return {!Thenable<T>} The resolved promise.
1504
1583
  * @template T
1505
1584
  */
1506
1585
  function fulfilled(opt_value) {
1507
- return ManagedPromise.resolve(opt_value);
1586
+ let ctor = usePromiseManager() ? ManagedPromise : NativePromise;
1587
+ if (opt_value instanceof ctor) {
1588
+ return /** @type {!Thenable} */(opt_value);
1589
+ }
1590
+
1591
+ if (usePromiseManager()) {
1592
+ // We can skip logging warnings about creating a managed promise because
1593
+ // this function will automatically switch to use a native promise when
1594
+ // the promise manager is disabled.
1595
+ return new ManagedPromise(
1596
+ resolve => resolve(opt_value), undefined, SKIP_LOG);
1597
+ }
1598
+ return NativePromise.resolve(opt_value);
1508
1599
  }
1509
1600
 
1510
1601
 
1511
1602
  /**
1512
1603
  * Creates a promise that has been rejected with the given reason.
1604
+ *
1605
+ * If the promise manager is currently enabled, this function will return a
1606
+ * {@linkplain ManagedPromise managed promise}. Otherwise, it will return a
1607
+ * {@linkplain NativePromise native promise}.
1608
+ *
1513
1609
  * @param {*=} opt_reason The rejection reason; may be any value, but is
1514
1610
  * usually an Error or a string.
1515
- * @return {!ManagedPromise<?>} The rejected promise.
1516
- * @deprecated Use {@link ManagedPromise#reject Promise.reject(reason)}.
1611
+ * @return {!Thenable<?>} The rejected promise.
1517
1612
  */
1518
1613
  function rejected(opt_reason) {
1519
- return ManagedPromise.reject(opt_reason);
1614
+ if (usePromiseManager()) {
1615
+ // We can skip logging warnings about creating a managed promise because
1616
+ // this function will automatically switch to use a native promise when
1617
+ // the promise manager is disabled.
1618
+ return new ManagedPromise(
1619
+ (_, reject) => reject(opt_reason), undefined, SKIP_LOG);
1620
+ }
1621
+ return NativePromise.reject(opt_reason);
1520
1622
  }
1521
1623
 
1522
1624
 
@@ -1610,21 +1712,17 @@ function thenFinally(promise, callback) {
1610
1712
  * @param {Function=} opt_errback The function to call when the value is
1611
1713
  * rejected.
1612
1714
  * @return {!Thenable} A new promise.
1715
+ * @deprecated Use `promise.fulfilled(value).then(opt_callback, opt_errback)`
1613
1716
  */
1614
1717
  function when(value, opt_callback, opt_errback) {
1615
- if (Thenable.isImplementation(value)) {
1616
- return value.then(opt_callback, opt_errback);
1617
- }
1618
-
1619
- return createPromise(resolve => resolve(value))
1620
- .then(opt_callback, opt_errback);
1718
+ return fulfilled(value).then(opt_callback, opt_errback);
1621
1719
  }
1622
1720
 
1623
1721
 
1624
1722
  /**
1625
1723
  * Invokes the appropriate callback function as soon as a promised `value` is
1626
- * resolved. This function is similar to `when()`, except it does not return
1627
- * a new promise.
1724
+ * resolved.
1725
+ *
1628
1726
  * @param {*} value The value to observe.
1629
1727
  * @param {Function} callback The function to call when the value is
1630
1728
  * resolved successfully.
@@ -1826,7 +1924,7 @@ function filter(arr, fn, opt_self) {
1826
1924
  */
1827
1925
  function fullyResolved(value) {
1828
1926
  if (isPromise(value)) {
1829
- return when(value, fullyResolveValue);
1927
+ return fulfilled(value).then(fullyResolveValue);
1830
1928
  }
1831
1929
  return fullyResolveValue(value);
1832
1930
  }
@@ -1973,7 +2071,7 @@ class Scheduler {
1973
2071
  /**
1974
2072
  * Schedules a task to wait for a condition to hold.
1975
2073
  *
1976
- * If the condition is defined as a function, it may return any value. Promies
2074
+ * If the condition is defined as a function, it may return any value. Promise
1977
2075
  * will be resolved before testing if the condition holds (resolution time
1978
2076
  * counts towards the timeout). Once resolved, values are always evaluated as
1979
2077
  * booleans.
@@ -1997,7 +2095,7 @@ class Scheduler {
1997
2095
  * @param {string=} opt_message An optional error message to include if the
1998
2096
  * wait times out; defaults to the empty string.
1999
2097
  * @return {!Thenable<T>} A promise that will be fulfilled
2000
- * when the condition has been satisified. The promise shall be rejected
2098
+ * when the condition has been satisfied. The promise shall be rejected
2001
2099
  * if the wait times out waiting for the condition.
2002
2100
  * @throws {TypeError} If condition is not a function or promise or if timeout
2003
2101
  * is not a number >= 0.
@@ -2018,6 +2116,10 @@ function usePromiseManager() {
2018
2116
 
2019
2117
 
2020
2118
  /**
2119
+ * Creates a new promise with the given `resolver` function. If the promise
2120
+ * manager is currently enabled, the returned promise will be a
2121
+ * {@linkplain ManagedPromise} instance. Otherwise, it will be a native promise.
2122
+ *
2021
2123
  * @param {function(
2022
2124
  * function((T|IThenable<T>|Thenable|null)=),
2023
2125
  * function(*=))} resolver
@@ -2040,7 +2142,7 @@ function createPromise(resolver) {
2040
2142
  * @param {string=} opt_message An optional error message to include if the
2041
2143
  * wait times out; defaults to the empty string.
2042
2144
  * @return {!Thenable<T>} A promise that will be fulfilled
2043
- * when the condition has been satisified. The promise shall be rejected
2145
+ * when the condition has been satisfied. The promise shall be rejected
2044
2146
  * if the wait times out waiting for the condition.
2045
2147
  * @throws {TypeError} If condition is not a function or promise or if timeout
2046
2148
  * is not a number >= 0.
@@ -2164,7 +2266,7 @@ const SIMPLE_SCHEDULER = new SimpleScheduler;
2164
2266
  /**
2165
2267
  * Handles the execution of scheduled tasks, each of which may be an
2166
2268
  * asynchronous operation. The control flow will ensure tasks are executed in
2167
- * the ordered scheduled, starting each task only once those before it have
2269
+ * the order scheduled, starting each task only once those before it have
2168
2270
  * completed.
2169
2271
  *
2170
2272
  * Each task scheduled within this flow may return a {@link ManagedPromise} to
@@ -2172,21 +2274,21 @@ const SIMPLE_SCHEDULER = new SimpleScheduler;
2172
2274
  * promises to be resolved before marking the task as completed.
2173
2275
  *
2174
2276
  * Tasks and each callback registered on a {@link ManagedPromise} will be run
2175
- * in their own ControlFlow frame. Any tasks scheduled within a frame will take
2277
+ * in their own ControlFlow frame. Any tasks scheduled within a frame will take
2176
2278
  * priority over previously scheduled tasks. Furthermore, if any of the tasks in
2177
2279
  * the frame fail, the remainder of the tasks in that frame will be discarded
2178
2280
  * and the failure will be propagated to the user through the callback/task's
2179
2281
  * promised result.
2180
2282
  *
2181
2283
  * Each time a ControlFlow empties its task queue, it will fire an
2182
- * {@link ControlFlow.EventType.IDLE IDLE} event. Conversely,
2183
- * whenever the flow terminates due to an unhandled error, it will remove all
2284
+ * {@link ControlFlow.EventType.IDLE IDLE} event. Conversely, whenever
2285
+ * the flow terminates due to an unhandled error, it will remove all
2184
2286
  * remaining tasks in its queue and fire an
2185
2287
  * {@link ControlFlow.EventType.UNCAUGHT_EXCEPTION UNCAUGHT_EXCEPTION} event.
2186
2288
  * If there are no listeners registered with the flow, the error will be
2187
2289
  * rethrown to the global error handler.
2188
2290
  *
2189
- * Refer to the {@link ./promise} module documentation for a detailed
2291
+ * Refer to the {@link ./promise} module documentation for a detailed
2190
2292
  * explanation of how the ControlFlow coordinates task execution.
2191
2293
  *
2192
2294
  * @implements {Scheduler}
@@ -2212,7 +2314,7 @@ class ControlFlow extends events.EventEmitter {
2212
2314
  this.taskQueues_ = null;
2213
2315
 
2214
2316
  /**
2215
- * Micro task that controls shutting down the control flow. Upon shut down,
2317
+ * Microtask that controls shutting down the control flow. Upon shut down,
2216
2318
  * the flow will emit an
2217
2319
  * {@link ControlFlow.EventType.IDLE} event. Idle events
2218
2320
  * always follow a brief timeout in order to catch latent errors from the
@@ -2221,8 +2323,8 @@ class ControlFlow extends events.EventEmitter {
2221
2323
  * by the promise system until the next turn of the event loop:
2222
2324
  *
2223
2325
  * // Schedule 1 task that fails.
2224
- * var result = promise.controlFlow().schedule('example',
2225
- * function() { return promise.rejected('failed'); });
2326
+ * var result = promise.controlFlow().execute(
2327
+ * () => promise.rejected('failed'), 'example');
2226
2328
  * // Set a callback on the result. This delays reporting the unhandled
2227
2329
  * // failure for 1 turn of the event loop.
2228
2330
  * result.then(function() {});
@@ -2246,7 +2348,7 @@ class ControlFlow extends events.EventEmitter {
2246
2348
  /**
2247
2349
  * Returns a string representation of this control flow, which is its current
2248
2350
  * {@linkplain #getSchedule() schedule}, sans task stack traces.
2249
- * @return {string} The string representation of this contorl flow.
2351
+ * @return {string} The string representation of this control flow.
2250
2352
  * @override
2251
2353
  */
2252
2354
  toString() {
@@ -2258,8 +2360,7 @@ class ControlFlow extends events.EventEmitter {
2258
2360
  * control flow stack and cause rejections within parent tasks. If error
2259
2361
  * propagation is disabled, tasks will not be aborted when an unhandled
2260
2362
  * promise rejection is detected, but the rejection _will_ trigger an
2261
- * {@link ControlFlow.EventType.UNCAUGHT_EXCEPTION}
2262
- * event.
2363
+ * {@link ControlFlow.EventType.UNCAUGHT_EXCEPTION} event.
2263
2364
  *
2264
2365
  * The default behavior is to propagate all unhandled rejections. _The use
2265
2366
  * of this option is highly discouraged._
@@ -2293,7 +2394,7 @@ class ControlFlow extends events.EventEmitter {
2293
2394
  * {@code opt_includeStackTraces === true}, the string will include the
2294
2395
  * stack trace from when each task was scheduled.
2295
2396
  * @param {string=} opt_includeStackTraces Whether to include the stack traces
2296
- * from when each task was scheduled. Defaults to false.
2397
+ * from when each task was scheduled. Defaults to false.
2297
2398
  * @return {string} String representation of this flow's internal state.
2298
2399
  */
2299
2400
  getSchedule(opt_includeStackTraces) {
@@ -2345,7 +2446,7 @@ class ControlFlow extends events.EventEmitter {
2345
2446
  }
2346
2447
 
2347
2448
  /**
2348
- * Returns the currently actively task queue for this flow. If there is no
2449
+ * Returns the currently active task queue for this flow. If there is no
2349
2450
  * active queue, one will be created.
2350
2451
  * @return {!TaskQueue} the currently active task queue for this flow.
2351
2452
  * @private
@@ -2377,15 +2478,31 @@ class ControlFlow extends events.EventEmitter {
2377
2478
  }
2378
2479
 
2379
2480
  if (!this.hold_) {
2380
- var holdIntervalMs = 2147483647; // 2^31-1; max timer length for Node.js
2481
+ let holdIntervalMs = 2147483647; // 2^31-1; max timer length for Node.js
2381
2482
  this.hold_ = setInterval(function() {}, holdIntervalMs);
2382
2483
  }
2383
2484
 
2384
- var task = new Task(
2485
+ let task = new Task(
2385
2486
  this, fn, opt_description || '<anonymous>',
2386
- {name: 'Task', top: ControlFlow.prototype.execute});
2487
+ {name: 'Task', top: ControlFlow.prototype.execute},
2488
+ true);
2489
+
2490
+ let q = this.getActiveQueue_();
2491
+
2492
+ for (let i = q.tasks_.length; i > 0; i--) {
2493
+ let previousTask = q.tasks_[i - 1];
2494
+ if (previousTask.userTask_) {
2495
+ FLOW_LOG.warning(() => {
2496
+ return `Detected scheduling of an unchained task.
2497
+ When the promise manager is disabled, unchained tasks will not wait for
2498
+ previously scheduled tasks to finish before starting to execute.
2499
+ New task: ${task.promise.stack_.stack}
2500
+ Previous task: ${previousTask.promise.stack_.stack}`.split(/\n/).join('\n ');
2501
+ });
2502
+ break;
2503
+ }
2504
+ }
2387
2505
 
2388
- var q = this.getActiveQueue_();
2389
2506
  q.enqueue(task);
2390
2507
  this.emit(ControlFlow.EventType.SCHEDULE_TASK, task.description);
2391
2508
  return task.promise;
@@ -2393,7 +2510,7 @@ class ControlFlow extends events.EventEmitter {
2393
2510
 
2394
2511
  /** @override */
2395
2512
  promise(resolver) {
2396
- return new ManagedPromise(resolver, this);
2513
+ return new ManagedPromise(resolver, this, SKIP_LOG);
2397
2514
  }
2398
2515
 
2399
2516
  /** @override */
@@ -2622,7 +2739,7 @@ class MicroTask {
2622
2739
  }
2623
2740
 
2624
2741
  /**
2625
- * Runs the given function after a micro-task yield.
2742
+ * Runs the given function after a microtask yield.
2626
2743
  * @param {function()} fn The function to run.
2627
2744
  */
2628
2745
  static run(fn) {
@@ -2662,9 +2779,11 @@ class Task extends Deferred {
2662
2779
  * @param {string} description A description of the task for debugging.
2663
2780
  * @param {{name: string, top: !Function}=} opt_stackOptions Options to use
2664
2781
  * when capturing the stacktrace for when this task was created.
2782
+ * @param {boolean=} opt_isUserTask Whether this task was explicitly scheduled
2783
+ * by the use of the promise manager.
2665
2784
  */
2666
- constructor(flow, fn, description, opt_stackOptions) {
2667
- super(flow);
2785
+ constructor(flow, fn, description, opt_stackOptions, opt_isUserTask) {
2786
+ super(flow, SKIP_LOG);
2668
2787
  getUid(this);
2669
2788
 
2670
2789
  /** @type {function(): (T|!ManagedPromise<T>)} */
@@ -2676,6 +2795,9 @@ class Task extends Deferred {
2676
2795
  /** @type {TaskQueue} */
2677
2796
  this.queue = null;
2678
2797
 
2798
+ /** @private @const {boolean} */
2799
+ this.userTask_ = !!opt_isUserTask;
2800
+
2679
2801
  /**
2680
2802
  * Whether this task is considered block. A blocked task may be registered
2681
2803
  * in a task queue, but will be dropped if it is still blocked when it
@@ -2889,7 +3011,7 @@ class TaskQueue extends events.EventEmitter {
2889
3011
  }
2890
3012
 
2891
3013
  // Now that all of the remaining tasks have been silently cancelled (e.g. no
2892
- // exisitng callbacks on those tasks will fire), clear the silence bit on
3014
+ // existing callbacks on those tasks will fire), clear the silence bit on
2893
3015
  // the cancellation error. This ensures additional callbacks registered in
2894
3016
  // the future will actually execute.
2895
3017
  cancellation.silent_ = false;
@@ -2935,7 +3057,7 @@ class TaskQueue extends events.EventEmitter {
2935
3057
 
2936
3058
  this.subQ_.once('end', () => { // On task completion.
2937
3059
  this.subQ_ = null;
2938
- this.pending_ && this.pending_.task.fulfill(result);
3060
+ this.pending_ && this.pending_.task.resolve(result);
2939
3061
  });
2940
3062
 
2941
3063
  this.subQ_.once('error', e => { // On task failure.
@@ -3068,7 +3190,7 @@ class TaskQueue extends events.EventEmitter {
3068
3190
  }
3069
3191
  return task;
3070
3192
  }
3071
- };
3193
+ }
3072
3194
 
3073
3195
 
3074
3196
 
@@ -3214,7 +3336,7 @@ function consume(generatorFn, opt_self, ...var_args) {
3214
3336
 
3215
3337
  function pump(fn, opt_arg) {
3216
3338
  if (ret instanceof ManagedPromise && !isPending(ret)) {
3217
- return; // Defererd was cancelled; silently abort.
3339
+ return; // Deferred was cancelled; silently abort.
3218
3340
  }
3219
3341
 
3220
3342
  try {
@@ -3246,6 +3368,7 @@ module.exports = {
3246
3368
  MultipleUnhandledRejectionError: MultipleUnhandledRejectionError,
3247
3369
  Thenable: Thenable,
3248
3370
  Promise: ManagedPromise,
3371
+ Resolver: Resolver,
3249
3372
  Scheduler: Scheduler,
3250
3373
  all: all,
3251
3374
  asap: asap,
@@ -3254,6 +3377,7 @@ module.exports = {
3254
3377
  consume: consume,
3255
3378
  controlFlow: controlFlow,
3256
3379
  createFlow: createFlow,
3380
+ createPromise: createPromise,
3257
3381
  defer: defer,
3258
3382
  delayed: delayed,
3259
3383
  filter: filter,
@@ -3275,7 +3399,7 @@ module.exports = {
3275
3399
  * The promise manager is currently enabled by default, but may be disabled
3276
3400
  * by setting the environment variable `SELENIUM_PROMISE_MANAGER=0` or by
3277
3401
  * setting this property to false. Setting this property will always take
3278
- * precedence ove the use of the environment variable.
3402
+ * precedence over the use of the environment variable.
3279
3403
  *
3280
3404
  * @return {boolean} Whether the promise manager is enabled.
3281
3405
  * @see <https://github.com/SeleniumHQ/selenium/issues/2969>