From 362f79c2b626e55de2b2f1b624836439822766f4 Mon Sep 17 00:00:00 2001
From: Dave Methvin
Date: Thu, 12 Mar 2015 13:16:53 -0400
Subject: [PATCH] Deferred: Deprecate deferred.pipe(), isResolved(),
isRejected()
Ref #89
Fixes #97
---
Gruntfile.js | 1 +
src/deferred.js | 63 +++++++++++++++++
test/deferred.js | 181 +++++++++++++++++++++++++++++++++++++++++++++++
test/index.html | 1 +
warnings.md | 13 ++++
5 files changed, 259 insertions(+)
create mode 100644 src/deferred.js
create mode 100644 test/deferred.js
diff --git a/Gruntfile.js b/Gruntfile.js
index 58ceea30..3ad611f1 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -27,6 +27,7 @@ module.exports = function(grunt) {
"src/manipulation.js",
"src/event.js",
"src/traversing.js",
+ "src/deferred.js",
"src/outro.js"
],
tests: {
diff --git a/src/deferred.js b/src/deferred.js
new file mode 100644
index 00000000..1715e33b
--- /dev/null
+++ b/src/deferred.js
@@ -0,0 +1,63 @@
+
+var oldDeferred = jQuery.Deferred,
+ tuples = [
+ // action, add listener, callbacks, .then handlers, final state
+ [ "resolve", "done", jQuery.Callbacks("once memory"),
+ jQuery.Callbacks("once memory"), "resolved" ],
+ [ "reject", "fail", jQuery.Callbacks("once memory"),
+ jQuery.Callbacks("once memory"), "rejected" ],
+ [ "notify", "progress", jQuery.Callbacks("memory"),
+ jQuery.Callbacks("memory") ]
+ ];
+
+jQuery.Deferred = function( func ) {
+ var deferred = oldDeferred(),
+ promise = deferred.promise();
+
+ deferred.pipe = promise.pipe = function( /* fnDone, fnFail, fnProgress */ ) {
+ var fns = arguments;
+
+ migrateWarn( "deferred.pipe() is deprecated" );
+
+ return jQuery.Deferred(function( newDefer ) {
+ jQuery.each( tuples, function( i, tuple ) {
+ var fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];
+ // deferred.done(function() { bind to newDefer or newDefer.resolve })
+ // deferred.fail(function() { bind to newDefer or newDefer.reject })
+ // deferred.progress(function() { bind to newDefer or newDefer.notify })
+ deferred[ tuple[1] ](function() {
+ var returned = fn && fn.apply( this, arguments );
+ if ( returned && jQuery.isFunction( returned.promise ) ) {
+ returned.promise()
+ .done( newDefer.resolve )
+ .fail( newDefer.reject )
+ .progress( newDefer.notify );
+ } else {
+ newDefer[ tuple[ 0 ] + "With" ](
+ this === promise ? newDefer.promise() : this,
+ fn ? [ returned ] : arguments
+ );
+ }
+ });
+ });
+ fns = null;
+ }).promise();
+
+ };
+
+ deferred.isResolved = function() {
+ migrateWarn( "deferred.isResolved is deprecated" );
+ return deferred.state() === "resolved";
+ };
+
+ deferred.isRejected = function() {
+ migrateWarn( "deferred.isRejected is deprecated" );
+ return deferred.state() === "rejected";
+ };
+
+ if ( func ) {
+ func.call( deferred, deferred );
+ }
+
+ return deferred;
+};
\ No newline at end of file
diff --git a/test/deferred.js b/test/deferred.js
new file mode 100644
index 00000000..7616c586
--- /dev/null
+++ b/test/deferred.js
@@ -0,0 +1,181 @@
+
+module("deferred");
+
+test( ".pipe() warnings", function( assert ) {
+ assert.expect( 4 );
+
+ var d = jQuery.Deferred(),
+ p = d.promise();
+
+ function checkValue( v ) {
+ assert.equal( v, 1, "got correct value" );
+ }
+
+ // Deferred
+ expectWarning( "pipe", function() {
+ d.pipe( checkValue );
+ });
+
+ // Deferred's promise object
+ expectWarning( "pipe", function() {
+ p.pipe( checkValue );
+ });
+
+ // Should happen synchronously for .pipe()
+ d.resolve( 1 );
+});
+
+test( "[PIPE ONLY] jQuery.Deferred.pipe - filtering (fail)", function( assert ) {
+
+ assert.expect( 4 );
+
+ var value1, value2, value3,
+ defer = jQuery.Deferred(),
+ piped = defer.pipe( null, function( a, b ) {
+ return a * b;
+ }),
+ done = jQuery.map( new Array( 3 ), function() { return assert.async(); } );
+
+ piped.fail(function( result ) {
+ value3 = result;
+ });
+
+ defer.fail(function( a, b ) {
+ value1 = a;
+ value2 = b;
+ });
+
+ defer.reject( 2, 3 ).pipe( null, function() {
+ assert.strictEqual( value1, 2, "first reject value ok" );
+ assert.strictEqual( value2, 3, "second reject value ok" );
+ assert.strictEqual( value3, 6, "result of filter ok" );
+ done.pop().call();
+ });
+
+ jQuery.Deferred().resolve().pipe( null, function() {
+ assert.ok( false, "then should not be called on resolve" );
+ }).then( done.pop() );
+
+ jQuery.Deferred().reject().pipe( null, jQuery.noop ).fail(function( value ) {
+ assert.strictEqual( value, undefined, "then fail callback can return undefined/null" );
+ done.pop().call();
+ });
+});
+
+test( "[PIPE ONLY] jQuery.Deferred.pipe - deferred (progress)", function( assert ) {
+
+ assert.expect( 3 );
+
+ var value1, value2, value3,
+ defer = jQuery.Deferred(),
+ piped = defer.pipe( null, null, function( a, b ) {
+ return jQuery.Deferred(function( defer ) {
+ defer.resolve( a * b );
+ });
+ }),
+ done = assert.async();
+
+ piped.done(function( result ) {
+ value3 = result;
+ });
+
+ defer.progress(function( a, b ) {
+ value1 = a;
+ value2 = b;
+ });
+
+ defer.notify( 2, 3 );
+
+ piped.done(function() {
+ assert.strictEqual( value1, 2, "first progress value ok" );
+ assert.strictEqual( value2, 3, "second progress value ok" );
+ assert.strictEqual( value3, 6, "result of filter ok" );
+ done();
+ });
+});
+
+test( "[PIPE ONLY] jQuery.Deferred.pipe - context", function( assert ) {
+
+ assert.expect( 7 );
+
+ var defer, piped, defer2, piped2,
+ context = {},
+ done = jQuery.map( new Array( 4 ), function() { return assert.async(); } );
+
+ jQuery.Deferred().resolveWith( context, [ 2 ] ).pipe(function( value ) {
+ return value * 3;
+ }).done(function( value ) {
+ assert.strictEqual( this, context, "[PIPE ONLY] custom context correctly propagated" );
+ assert.strictEqual( value, 6, "proper value received" );
+ done.pop().call();
+ });
+
+ jQuery.Deferred().resolve().pipe(function() {
+ return jQuery.Deferred().resolveWith(context);
+ }).done(function() {
+ assert.strictEqual( this, context,
+ "custom context of returned deferred correctly propagated" );
+ done.pop().call();
+ });
+
+ defer = jQuery.Deferred();
+ piped = defer.pipe(function( value ) {
+ return value * 3;
+ });
+
+ defer.resolve( 2 );
+
+ piped.done(function( value ) {
+ assert.strictEqual( this, piped,
+ "default context gets updated to latest promise in the chain" );
+ assert.strictEqual( value, 6, "proper value received" );
+ done.pop().call();
+ });
+
+ defer2 = jQuery.Deferred();
+ piped2 = defer2.pipe();
+
+ defer2.resolve( 2 );
+
+ piped2.done(function( value ) {
+ assert.strictEqual( this, piped2,
+ "default context updated to latest promise in the chain (without passing function)" );
+ assert.strictEqual( value, 2, "proper value received (without passing function)" );
+ done.pop().call();
+ });
+});
+
+test( "isResolved() and isRejected()", function( assert ) {
+
+ assert.expect( 12 );
+
+ var defer = jQuery.Deferred();
+
+ expectWarning( "isResolved unresolved", function() {
+ assert.strictEqual( defer.isResolved(), false, "isResolved pending" );
+ });
+
+ expectWarning( "isRejected unresolved", function() {
+ assert.strictEqual( defer.isRejected(), false, "isRejected pending" );
+ });
+
+ defer.resolve( 1 );
+
+ expectWarning( "isResolved resolved", function() {
+ assert.strictEqual( defer.isResolved(), true, "isResolved resolved" );
+ });
+
+ expectWarning( "isResolved resolved", function() {
+ assert.strictEqual( defer.isRejected(), false, "isRejected resolved" );
+ });
+
+ defer = jQuery.Deferred().reject( 1 );
+
+ expectWarning( "isResolved resolved", function() {
+ assert.strictEqual( defer.isResolved(), false, "isResolved rejected" );
+ });
+
+ expectWarning( "isResolved resolved", function() {
+ assert.strictEqual( defer.isRejected(), true, "isRejected rejected" );
+ });
+});
\ No newline at end of file
diff --git a/test/index.html b/test/index.html
index 213368fe..3edb40f0 100644
--- a/test/index.html
+++ b/test/index.html
@@ -40,6 +40,7 @@
+
diff --git a/warnings.md b/warnings.md
index d3836fdc..1d267e67 100644
--- a/warnings.md
+++ b/warnings.md
@@ -148,6 +148,19 @@ $(document).ajaxStart(function(){ $("#status").text("Ajax started"); });
**Solution**: Boolean properties should generally not be passed to `$().attr` at all; replace with `$().prop` unless you truly intend to update the underlying HTML *attribute*.
+### JQMIGRATE: deferred.pipe() is deprecated
+
+**Cause**: The `.pipe()` method on a `jQuery.Deferred` object was deprecated as of jQuery 1.8, when the `.then()` method was changed to perform the same function.
+
+**Solution**: Change all occurrences of `.pipe()` to `.then()`.
+
+### JQMIGRATE: deferred.isResolved() is deprecated
+### JQMIGRATE: deferred.isRejected() is deprecated
+
+**Cause**: As of jQuery 1.7, the `isResolved()` and `isRejected` methods of the `jQuery.Deferred` object have been deprecated. They were removed in jQuery 1.8 and are no longer available in later versions.
+
+**Solution**: To determine the state of a Deferred object, call `deferred.state()` and check for the `"resolved"` or `"rejected"` string values.
+
### JQMIGRATE: jQuery.clean() is deprecated
**Cause**: `jQuery.buildFragment()` and `jQuery.clean()` are undocumented internal methods. The signature of `jQuery.buildFragment()` was changed in jQuery 1.8 and 1.9, and `jQuery.clean()` was removed in 1.9. However, we are aware of some plugins or other code that may be using them.