From 195cf614db9736db63829e85ad5342b1aa7b62f2 Mon Sep 17 00:00:00 2001 From: Jason Leyba Date: Sun, 22 Jan 2017 09:38:00 -0800 Subject: [PATCH] [js] Changed promise.{fulfilled, rejected, defer} to all use native promises when the promise manager is disabled. Deprecated promise.when() For #2969 --- javascript/node/selenium-webdriver/CHANGES.md | 5 + .../node/selenium-webdriver/lib/promise.js | 104 ++++++++++++++---- 2 files changed, 89 insertions(+), 20 deletions(-) diff --git a/javascript/node/selenium-webdriver/CHANGES.md b/javascript/node/selenium-webdriver/CHANGES.md index 34527fbb5ab11..46040268772b3 100644 --- a/javascript/node/selenium-webdriver/CHANGES.md +++ b/javascript/node/selenium-webdriver/CHANGES.md @@ -1,6 +1,11 @@ ## v.next * The `lib` package is once again platform agnostic (excluding `lib/devmode`). +* Deprecated `promise.when(value, callback, errback)`. + Use `promise.fulfilled(value).then(callback, errback)` +* Changed `promise.fulfilled(value)`, `promise.rejected(reason)` and + `promise.defer()` to all use native promises when the promise manager is + disabled. ## v3.0.1 diff --git a/javascript/node/selenium-webdriver/lib/promise.js b/javascript/node/selenium-webdriver/lib/promise.js index 2599c52ef31a7..d59d9b7e783c8 100644 --- a/javascript/node/selenium-webdriver/lib/promise.js +++ b/javascript/node/selenium-webdriver/lib/promise.js @@ -1383,6 +1383,37 @@ function isPending(promise) { } +/** + * Structural interface for a deferred promise resolver. + * @record + * @template T + */ +function Resolver() {} + + +/** + * The promised value for this resolver. + * @type {!Thenable} + */ +Resolver.prototype.promise; + + +/** + * Resolves the promised value with the given `value`. + * @param {T|Thenable} value + * @return {void} + */ +Resolver.prototype.resolve; + + +/** + * Rejects the promised value with the given `reason`. + * @param {*} reason + * @return {void} + */ +Resolver.prototype.reject; + + /** * Represents a value that will be resolved at some point in the future. This * class represents the protected "producer" half of a ManagedPromise - each Deferred @@ -1395,6 +1426,7 @@ function isPending(promise) { * {@link ControlFlow} as an unhandled failure. * * @template T + * @implements {Resolver} */ class Deferred { /** @@ -1421,16 +1453,24 @@ class Deferred { * Resolves this deferred with the given value. It is safe to call this as a * normal function (with no bound "this"). * @param {(T|IThenable|Thenable)=} opt_value The fulfilled value. + * @const */ - this.fulfill = function(opt_value) { + this.resolve = function(opt_value) { checkNotSelf(opt_value); fulfill(opt_value); }; + /** + * An alias for {@link #resolve}. + * @const + */ + this.fulfill = this.resolve; + /** * Rejects this promise with the given reason. It is safe to call this as a * normal function (with no bound "this"). * @param {*=} opt_reason The rejection reason. + * @const */ this.reject = function(opt_reason) { checkNotSelf(opt_reason); @@ -1487,36 +1527,63 @@ function delayed(ms) { /** - * Creates a new deferred object. - * @return {!Deferred} The new deferred object. + * Creates a new deferred resolver. + * + * If the promise manager is currently enabled, this function will return a + * {@link Deferred} instance. Otherwise, it will return a resolver for a + * {@linkplain NativePromise native promise}. + * + * @return {!Resolver} A new deferred resolver. * @template T */ function defer() { - return new Deferred(); + if (usePromiseManager()) { + return new Deferred(); + } + let resolve, reject; + let promise = new NativePromise((_resolve, _reject) => { + resolve = _resolve; + reject = _reject; + }); + return {promise, resolve, reject}; } /** * Creates a promise that has been resolved with the given value. + * + * If the promise manager is currently enabled, this function will return a + * {@linkplain ManagedPromise managed promise}. Otherwise, it will return a + * {@linkplain NativePromise native promise}. + * * @param {T=} opt_value The resolved value. - * @return {!ManagedPromise} The resolved promise. - * @deprecated Use {@link ManagedPromise#resolve Promise.resolve(value)}. + * @return {!Thenable} The resolved promise. * @template T */ function fulfilled(opt_value) { - return ManagedPromise.resolve(opt_value); + if (usePromiseManager()) { + return ManagedPromise.resolve(opt_value); + } + return NativePromise.resolve(opt_value); } /** * Creates a promise that has been rejected with the given reason. + * + * If the promise manager is currently enabled, this function will return a + * {@linkplain ManagedPromise managed promise}. Otherwise, it will return a + * {@linkplain NativePromise native promise}. + * * @param {*=} opt_reason The rejection reason; may be any value, but is * usually an Error or a string. - * @return {!ManagedPromise} The rejected promise. - * @deprecated Use {@link ManagedPromise#reject Promise.reject(reason)}. + * @return {!Thenable} The rejected promise. */ function rejected(opt_reason) { - return ManagedPromise.reject(opt_reason); + if (usePromiseManager()) { + return ManagedPromise.reject(opt_reason); + } + return NativePromise.reject(opt_reason); } @@ -1610,21 +1677,17 @@ function thenFinally(promise, callback) { * @param {Function=} opt_errback The function to call when the value is * rejected. * @return {!Thenable} A new promise. + * @deprecated Use `promise.fulfilled(value).then(opt_callback, opt_errback)` */ function when(value, opt_callback, opt_errback) { - if (Thenable.isImplementation(value)) { - return value.then(opt_callback, opt_errback); - } - - return createPromise(resolve => resolve(value)) - .then(opt_callback, opt_errback); + return fulfilled(value).then(opt_callback, opt_errback); } /** * Invokes the appropriate callback function as soon as a promised `value` is - * resolved. This function is similar to `when()`, except it does not return - * a new promise. + * resolved. + * * @param {*} value The value to observe. * @param {Function} callback The function to call when the value is * resolved successfully. @@ -1826,7 +1889,7 @@ function filter(arr, fn, opt_self) { */ function fullyResolved(value) { if (isPromise(value)) { - return when(value, fullyResolveValue); + return fulfilled(value).then(fullyResolveValue); } return fullyResolveValue(value); } @@ -2934,7 +2997,7 @@ class TaskQueue extends events.EventEmitter { this.subQ_.once('end', () => { // On task completion. this.subQ_ = null; - this.pending_ && this.pending_.task.fulfill(result); + this.pending_ && this.pending_.task.resolve(result); }); this.subQ_.once('error', e => { // On task failure. @@ -3245,6 +3308,7 @@ module.exports = { MultipleUnhandledRejectionError: MultipleUnhandledRejectionError, Thenable: Thenable, Promise: ManagedPromise, + Resolver: Resolver, Scheduler: Scheduler, all: all, asap: asap,