133 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			133 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| // Copyright 2013 The Closure Library Authors. All Rights Reserved.
 | |
| //
 | |
| // Licensed under the Apache License, Version 2.0 (the "License");
 | |
| // you may not use this file except in compliance with the License.
 | |
| // You may obtain a copy of the License at
 | |
| //
 | |
| //      http://www.apache.org/licenses/LICENSE-2.0
 | |
| //
 | |
| // Unless required by applicable law or agreed to in writing, software
 | |
| // distributed under the License is distributed on an "AS-IS" BASIS,
 | |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | |
| // See the License for the specific language governing permissions and
 | |
| // limitations under the License.
 | |
| 
 | |
| goog.provide('goog.Thenable');
 | |
| 
 | |
| /** @suppress {extraRequire} */
 | |
| goog.forwardDeclare('goog.Promise'); // for the type reference.
 | |
| 
 | |
| 
 | |
| 
 | |
| /**
 | |
|  * Provides a more strict interface for Thenables in terms of
 | |
|  * http://promisesaplus.com for interop with {@see goog.Promise}.
 | |
|  *
 | |
|  * @interface
 | |
|  * @extends {IThenable<TYPE>}
 | |
|  * @template TYPE
 | |
|  */
 | |
| goog.Thenable = function() {};
 | |
| 
 | |
| 
 | |
| /**
 | |
|  * Adds callbacks that will operate on the result of the Thenable, returning a
 | |
|  * new child Promise.
 | |
|  *
 | |
|  * If the Thenable is fulfilled, the {@code onFulfilled} callback will be
 | |
|  * invoked with the fulfillment value as argument, and the child Promise will
 | |
|  * be fulfilled with the return value of the callback. If the callback throws
 | |
|  * an exception, the child Promise will be rejected with the thrown value
 | |
|  * instead.
 | |
|  *
 | |
|  * If the Thenable is rejected, the {@code onRejected} callback will be invoked
 | |
|  * with the rejection reason as argument, and the child Promise will be rejected
 | |
|  * with the return value of the callback or thrown value.
 | |
|  *
 | |
|  * @param {?(function(this:THIS, TYPE): VALUE)=} opt_onFulfilled A
 | |
|  *     function that will be invoked with the fulfillment value if the Promise
 | |
|  *     is fulfilled.
 | |
|  * @param {?(function(this:THIS, *): *)=} opt_onRejected A function that will
 | |
|  *     be invoked with the rejection reason if the Promise is rejected.
 | |
|  * @param {THIS=} opt_context An optional context object that will be the
 | |
|  *     execution context for the callbacks. By default, functions are executed
 | |
|  *     with the default this.
 | |
|  *
 | |
|  * @return {RESULT} A new Promise that will receive the result
 | |
|  *     of the fulfillment or rejection callback.
 | |
|  * @template VALUE
 | |
|  * @template THIS
 | |
|  *
 | |
|  * When a Promise (or thenable) is returned from the fulfilled callback,
 | |
|  * the result is the payload of that promise, not the promise itself.
 | |
|  *
 | |
|  * @template RESULT := type('goog.Promise',
 | |
|  *     cond(isUnknown(VALUE), unknown(),
 | |
|  *       mapunion(VALUE, (V) =>
 | |
|  *         cond(isTemplatized(V) && sub(rawTypeOf(V), 'IThenable'),
 | |
|  *           templateTypeOf(V, 0),
 | |
|  *           cond(sub(V, 'Thenable'),
 | |
|  *              unknown(),
 | |
|  *              V)))))
 | |
|  *  =:
 | |
|  *
 | |
|  */
 | |
| goog.Thenable.prototype.then = function(
 | |
|     opt_onFulfilled, opt_onRejected, opt_context) {};
 | |
| 
 | |
| 
 | |
| /**
 | |
|  * An expando property to indicate that an object implements
 | |
|  * {@code goog.Thenable}.
 | |
|  *
 | |
|  * {@see addImplementation}.
 | |
|  *
 | |
|  * @const
 | |
|  */
 | |
| goog.Thenable.IMPLEMENTED_BY_PROP = '$goog_Thenable';
 | |
| 
 | |
| 
 | |
| /**
 | |
|  * Marks a given class (constructor) as an implementation of Thenable, so
 | |
|  * that we can query that fact at runtime. The class must have already
 | |
|  * implemented the interface.
 | |
|  * Exports a 'then' method on the constructor prototype, so that the objects
 | |
|  * also implement the extern {@see goog.Thenable} interface for interop with
 | |
|  * other Promise implementations.
 | |
|  * @param {function(new:goog.Thenable,...?)} ctor The class constructor. The
 | |
|  *     corresponding class must have already implemented the interface.
 | |
|  */
 | |
| goog.Thenable.addImplementation = function(ctor) {
 | |
|   // Use bracket notation instead of goog.exportSymbol() so that the compiler
 | |
|   // won't create a 'var ctor;' extern when the "create externs from exports"
 | |
|   // mode is enabled.
 | |
|   ctor.prototype['then'] = ctor.prototype.then;
 | |
|   if (COMPILED) {
 | |
|     ctor.prototype[goog.Thenable.IMPLEMENTED_BY_PROP] = true;
 | |
|   } else {
 | |
|     // Avoids dictionary access in uncompiled mode.
 | |
|     ctor.prototype.$goog_Thenable = true;
 | |
|   }
 | |
| };
 | |
| 
 | |
| 
 | |
| /**
 | |
|  * @param {?} object
 | |
|  * @return {boolean} Whether a given instance implements {@code goog.Thenable}.
 | |
|  *     The class/superclass of the instance must call {@code addImplementation}.
 | |
|  */
 | |
| goog.Thenable.isImplementedBy = function(object) {
 | |
|   if (!object) {
 | |
|     return false;
 | |
|   }
 | |
|   try {
 | |
|     if (COMPILED) {
 | |
|       return !!object[goog.Thenable.IMPLEMENTED_BY_PROP];
 | |
|     }
 | |
|     return !!object.$goog_Thenable;
 | |
|   } catch (e) {
 | |
|     // Property access seems to be forbidden.
 | |
|     return false;
 | |
|   }
 | |
| };
 |