Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

fix($q): pass promise-aplus-tests v2.0.3 WIP #5536

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions lib/promises-aplus/promises-aplus-test-adapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ var isFunction = function isFunction(value){return typeof value == 'function';}

var $q = qFactory(process.nextTick, function noopExceptionHandler() {});

exports.fulfilled = $q.resolve;
exports.resolved = $q.resolve;
exports.rejected = $q.reject;
exports.pending = function () {
var deferred = $q.defer();
exports.deferred = function () {
var deferred = $q.defer();

return {
promise: deferred.promise,
fulfill: deferred.resolve,
reject: deferred.reject
};
return {
promise: deferred.promise,
resolve: deferred.resolve,
reject: deferred.reject
};
};
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
"grunt-parallel": "~0.3.1",
"grunt-ddescribe-iit": "~0.0.1",
"grunt-merge-conflict": "~0.0.1",
"promises-aplus-tests": "~1.3.2",
"promises-aplus-tests": "~2.0.3",
"grunt-shell": "~0.4.0",
"semver": "~2.1.0",
"lodash": "~2.1.0",
Expand Down
279 changes: 173 additions & 106 deletions src/ng/q.js
Original file line number Diff line number Diff line change
Expand Up @@ -187,51 +187,115 @@ function $QProvider() {
* @returns {object} Promise manager.
*/
function qFactory(nextTick, exceptionHandler) {
function wrap(deferred, method, value) {
if (isFunction(value)) {
return function(val) {
try {
deferred.resolve(value(val));
} catch (e) {
deferred.reject(e);
exceptionHandler(e);
}
};
}
return function(value) {
deferred[method](value);
};
}

/**
* @ngdoc
* @name ng.$q#defer
* @methodOf ng.$q
* @description
* Creates a `Deferred` object which represents a task which will finish in the future.
*
* @returns {Deferred} Returns a new instance of deferred.
*/
var defer = function() {
var pending = [],
value, deferred;
function Thenable(ctx) {
this.then = function(callback, errback, progressback) {
var result = defer();

deferred = {
var wrappedCallback = wrap(result, 'resolve', callback);
var wrappedErrback = wrap(result, 'reject', errback);

resolve: function(val) {
if (pending) {
var callbacks = pending;
pending = undefined;
value = ref(val);
var wrappedProgressback = function(progress) {
try {
result.notify((isFunction(progressback) ? progressback : defaultCallback)(progress));
} catch(e) {
exceptionHandler(e);
}
};

if (callbacks.length) {
nextTick(function() {
var callback;
for (var i = 0, ii = callbacks.length; i < ii; i++) {
callback = callbacks[i];
value.then(callback[0], callback[1], callback[2]);
}
});
}
if (ctx.pending) {
ctx.pending.push([wrappedCallback, wrappedErrback, wrappedProgressback]);
} else {
ctx.value.then(wrappedCallback, wrappedErrback, wrappedProgressback);
}

return result.promise;
};
}
Thenable.prototype = {
constructor: Thenable,

"catch": function(callback) {
return this.then(null, callback);
},

"finally": function(callback) {

function makePromise(value, resolved) {
var result = defer();
if (resolved) {
result.resolve(value);
} else {
result.reject(value);
}
return result.promise;
}

function handleCallback(value, isResolved) {
var callbackOutput = null;
try {
callbackOutput = (callback ||defaultCallback)();
} catch(e) {
return makePromise(e, false);
}
if (callbackOutput && isFunction(callbackOutput.then)) {
return callbackOutput.then(function() {
return makePromise(value, isResolved);
}, function(error) {
return makePromise(error, false);
});
} else {
return makePromise(value, isResolved);
}
}

return this.then(function(value) {
return handleCallback(value, true);
}, function(error) {
return handleCallback(error, false);
});
}
};

function Deferred() {
var self = this, deferred;
this.pending = [];

this.deferred = deferred = {
resolve: function(val) {
if (self.pending) {
doResolve(self, deferred, val, true);
}
},


reject: function(reason) {
deferred.resolve(reject(reason));
if (self.pending) {
doResolve(self, deferred, reason);
}
},


notify: function(progress) {
if (pending) {
var callbacks = pending;
if (self.pending) {
var callbacks = self.pending;

if (pending.length) {
if (callbacks.length) {
nextTick(function() {
var callback;
for (var i = 0, ii = callbacks.length; i < ii; i++) {
Expand All @@ -243,90 +307,81 @@ function qFactory(nextTick, exceptionHandler) {
}
},

promise: new Thenable(self)
};
}

promise: {
then: function(callback, errback, progressback) {
var result = defer();

var wrappedCallback = function(value) {
try {
result.resolve((isFunction(callback) ? callback : defaultCallback)(value));
} catch(e) {
result.reject(e);
exceptionHandler(e);
}
};

var wrappedErrback = function(reason) {
try {
result.resolve((isFunction(errback) ? errback : defaultErrback)(reason));
} catch(e) {
result.reject(e);
exceptionHandler(e);
}
};
function doResolve(ctx, deferred, x, fulfilled) {
var then;
if (x === deferred.promise) {
throw new TypeError();
}

var wrappedProgressback = function(progress) {
try {
result.notify((isFunction(progressback) ? progressback : defaultCallback)(progress));
} catch(e) {
exceptionHandler(e);
if (x instanceof Thenable) {
x.then(function(value) {
deferred.resolve(value);
}, function(reason) {
deferred.reject(reason);
});
return deferred.promise;
} else if (x && typeof x === 'object' || isFunction(x)) {
try {
then = x.then;
} catch (e) {
deferred.reject(e);
return deferred.promise;
}
if (isFunction(then)) {
var called = 0;
try {
then.call(x, function resolvePromise(y) {
if (!called) {
called = 1;
deferred.resolve(y);
}
};

if (pending) {
pending.push([wrappedCallback, wrappedErrback, wrappedProgressback]);
} else {
value.then(wrappedCallback, wrappedErrback, wrappedProgressback);
}

return result.promise;
},

"catch": function(callback) {
return this.then(null, callback);
},

"finally": function(callback) {

function makePromise(value, resolved) {
var result = defer();
if (resolved) {
result.resolve(value);
} else {
result.reject(value);
}, function rejectPromise(r) {
if (!called) {
called = 1;
deferred.reject(r);
}
return result.promise;
});
} catch (e) {
if (!called) {
deferred.reject(e);
}
}
return deferred.promise;
}
}

function handleCallback(value, isResolved) {
var callbackOutput = null;
try {
callbackOutput = (callback ||defaultCallback)();
} catch(e) {
return makePromise(e, false);
}
if (callbackOutput && isFunction(callbackOutput.then)) {
return callbackOutput.then(function() {
return makePromise(value, isResolved);
}, function(error) {
return makePromise(error, false);
});
} else {
return makePromise(value, isResolved);
}
}
var callbacks = ctx.pending, cb = fulfilled ? 0 : 1;
ctx.pending = null;
ctx.value = fulfilled ? ref(x) : ref1(x);

return this.then(function(value) {
return handleCallback(value, true);
}, function(error) {
return handleCallback(error, false);
});
if (callbacks.length) {
nextTick(function() {
var callback;
for (var i = 0, ii = callbacks.length; i < ii; i++) {
callback = callbacks[i];
callback[cb](x);
}
}
};
});
}

return deferred;
return deferred.promise;
}

/**
* @ngdoc
* @name ng.$q#defer
* @methodOf ng.$q
* @description
* Creates a `Deferred` object which represents a task which will finish in the future.
*
* @returns {Deferred} Returns a new instance of deferred.
*/
var defer = function() {
return new Deferred().deferred;
};


Expand All @@ -344,6 +399,18 @@ function qFactory(nextTick, exceptionHandler) {
};


var ref1 = function(value) {
return {
then: function(callback, errback) {
var result = defer();
nextTick(function() {
result.resolve(errback(value));
});
return result.promise;
}
};
};

/**
* @ngdoc
* @name ng.$q#reject
Expand Down