mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-07-13 03:27:39 +03:00
Promises (first look)
Thread dropdown Small fixes
This commit is contained in:
parent
dd41d30f9b
commit
c23ba31e17
61 changed files with 12442 additions and 130 deletions
|
|
@ -421,6 +421,12 @@
|
||||||
'MailServerError': 901,
|
'MailServerError': 901,
|
||||||
'ClientViewError': 902,
|
'ClientViewError': 902,
|
||||||
'InvalidInputArgument': 903,
|
'InvalidInputArgument': 903,
|
||||||
|
|
||||||
|
'AjaxFalse': 950,
|
||||||
|
'AjaxAbort': 951,
|
||||||
|
'AjaxParse': 952,
|
||||||
|
'AjaxTimeout': 953,
|
||||||
|
|
||||||
'UnknownNotification': 999,
|
'UnknownNotification': 999,
|
||||||
'UnknownError': 999
|
'UnknownError': 999
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -134,9 +134,6 @@
|
||||||
'allowedContent': true,
|
'allowedContent': true,
|
||||||
'extraAllowedContent': true,
|
'extraAllowedContent': true,
|
||||||
|
|
||||||
'forceEnterMode': true,
|
|
||||||
|
|
||||||
'autoParagraph': false,
|
|
||||||
'fillEmptyBlocks': false,
|
'fillEmptyBlocks': false,
|
||||||
'ignoreEmptyParagraph': true,
|
'ignoreEmptyParagraph': true,
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -613,7 +613,7 @@
|
||||||
*/
|
*/
|
||||||
Utils.microtime = function ()
|
Utils.microtime = function ()
|
||||||
{
|
{
|
||||||
return (new Date()).getTime();
|
return (new window.Date()).getTime();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -848,7 +848,7 @@
|
||||||
},
|
},
|
||||||
|
|
||||||
convertBlockquote = function (sText) {
|
convertBlockquote = function (sText) {
|
||||||
sText = splitPlainText($.trim(sText));
|
sText = Utils.trim(sText);
|
||||||
sText = '> ' + sText.replace(/\n/gm, '\n> ');
|
sText = '> ' + sText.replace(/\n/gm, '\n> ');
|
||||||
return sText.replace(/(^|\n)([> ]+)/gm, function () {
|
return sText.replace(/(^|\n)([> ]+)/gm, function () {
|
||||||
return (arguments && 2 < arguments.length) ? arguments[1] + $.trim(arguments[2].replace(/[\s]/g, '')) + ' ' : '';
|
return (arguments && 2 < arguments.length) ? arguments[1] + $.trim(arguments[2].replace(/[\s]/g, '')) + ' ' : '';
|
||||||
|
|
@ -920,8 +920,10 @@
|
||||||
.replace(/&/gi, '&')
|
.replace(/&/gi, '&')
|
||||||
;
|
;
|
||||||
|
|
||||||
|
sText = splitPlainText(Utils.trim(sText));
|
||||||
|
|
||||||
iPos = 0;
|
iPos = 0;
|
||||||
iLimit = 100;
|
iLimit = 800;
|
||||||
|
|
||||||
while (0 < iLimit)
|
while (0 < iLimit)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
172
dev/Promises/AbstractAjax.js
Normal file
172
dev/Promises/AbstractAjax.js
Normal file
|
|
@ -0,0 +1,172 @@
|
||||||
|
|
||||||
|
(function () {
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var
|
||||||
|
_ = require('_'),
|
||||||
|
$ = require('$'),
|
||||||
|
Q = require('Q'),
|
||||||
|
|
||||||
|
Consts = require('Common/Consts'),
|
||||||
|
Enums = require('Common/Enums'),
|
||||||
|
Utils = require('Common/Utils'),
|
||||||
|
Links = require('Common/Links'),
|
||||||
|
|
||||||
|
Settings = require('Storage/Settings')
|
||||||
|
;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
function AbstractAjaxPromises()
|
||||||
|
{
|
||||||
|
this.oRequests = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
AbstractAjaxPromises.prototype.func = function (fFunc)
|
||||||
|
{
|
||||||
|
fFunc();
|
||||||
|
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
AbstractAjaxPromises.prototype.fastPromise = function (mData)
|
||||||
|
{
|
||||||
|
var oDeferred = Q.defer();
|
||||||
|
oDeferred.resolve(mData);
|
||||||
|
return oDeferred.promise;
|
||||||
|
};
|
||||||
|
|
||||||
|
AbstractAjaxPromises.prototype.abort = function (sAction, bClearOnly)
|
||||||
|
{
|
||||||
|
if (this.oRequests[sAction])
|
||||||
|
{
|
||||||
|
if (!bClearOnly && this.oRequests[sAction].abort)
|
||||||
|
{
|
||||||
|
this.oRequests[sAction].__aborted = true;
|
||||||
|
this.oRequests[sAction].abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.oRequests[sAction] = null;
|
||||||
|
delete this.oRequests[sAction];
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
AbstractAjaxPromises.prototype.ajaxRequest = function (sAction, bPost, iTimeOut, oParameters, sAdditionalGetString, fTrigger)
|
||||||
|
{
|
||||||
|
var
|
||||||
|
oH = null,
|
||||||
|
self = this,
|
||||||
|
iStart = Utils.microtime(),
|
||||||
|
oDeferred = Q.defer()
|
||||||
|
;
|
||||||
|
|
||||||
|
iTimeOut = Utils.isNormal(iTimeOut) ? iTimeOut : Consts.Defaults.DefaultAjaxTimeout;
|
||||||
|
sAdditionalGetString = Utils.isUnd(sAdditionalGetString) ? '' : Utils.pString(sAdditionalGetString);
|
||||||
|
|
||||||
|
if (bPost)
|
||||||
|
{
|
||||||
|
oParameters['XToken'] = Settings.settingsGet('Token');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fTrigger)
|
||||||
|
{
|
||||||
|
fTrigger(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
oH = $.ajax({
|
||||||
|
'type': bPost ? 'POST' : 'GET',
|
||||||
|
'url': Links.ajax(sAdditionalGetString),
|
||||||
|
'async': true,
|
||||||
|
'dataType': 'json',
|
||||||
|
'data': bPost ? (oParameters || {}) : {},
|
||||||
|
'timeout': iTimeOut,
|
||||||
|
'global': true
|
||||||
|
}).always(function (oData, sTextStatus) {
|
||||||
|
|
||||||
|
var bCached = false;
|
||||||
|
if (oData && oData['Time'])
|
||||||
|
{
|
||||||
|
bCached = Utils.pInt(oData['Time']) > Utils.microtime() - iStart;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ('success' === sTextStatus)
|
||||||
|
{
|
||||||
|
if (oData && oData.Result && sAction === oData.Action)
|
||||||
|
{
|
||||||
|
oData.Result.__cached__ = bCached;
|
||||||
|
oDeferred.resolve(oData.Result);
|
||||||
|
}
|
||||||
|
else if (oData && oData.Action)
|
||||||
|
{
|
||||||
|
oDeferred.reject(oData.ErrorCode ? oData.ErrorCode : Enums.Notification.AjaxFalse);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
oDeferred.reject(Enums.Notification.AjaxParse);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ('timeout' === sTextStatus)
|
||||||
|
{
|
||||||
|
oDeferred.reject(Enums.Notification.AjaxTimeout);
|
||||||
|
}
|
||||||
|
else if ('abort' === sTextStatus)
|
||||||
|
{
|
||||||
|
if (!oData || !oData.__aborted)
|
||||||
|
{
|
||||||
|
oDeferred.reject(Enums.Notification.AjaxAbort);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
oDeferred.reject(Enums.Notification.AjaxParse);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self.oRequests[sAction])
|
||||||
|
{
|
||||||
|
self.oRequests[sAction] = null;
|
||||||
|
delete self.oRequests[sAction];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fTrigger)
|
||||||
|
{
|
||||||
|
fTrigger(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (oH)
|
||||||
|
{
|
||||||
|
if (this.oRequests[sAction])
|
||||||
|
{
|
||||||
|
this.oRequests[sAction] = null;
|
||||||
|
delete this.oRequests[sAction];
|
||||||
|
}
|
||||||
|
|
||||||
|
this.oRequests[sAction] = oH;
|
||||||
|
}
|
||||||
|
|
||||||
|
return oDeferred.promise;
|
||||||
|
};
|
||||||
|
|
||||||
|
AbstractAjaxPromises.prototype.getRequest = function (sAction, fTrigger, sAdditionalGetString, iTimeOut)
|
||||||
|
{
|
||||||
|
sAdditionalGetString = Utils.isUnd(sAdditionalGetString) ? '' : Utils.pString(sAdditionalGetString);
|
||||||
|
sAdditionalGetString = sAction + '/' + sAdditionalGetString;
|
||||||
|
|
||||||
|
return this.ajaxRequest(sAction, false, iTimeOut, null, sAdditionalGetString, fTrigger);
|
||||||
|
};
|
||||||
|
|
||||||
|
AbstractAjaxPromises.prototype.postRequest = function (sAction, fTrigger, oParameters, iTimeOut)
|
||||||
|
{
|
||||||
|
oParameters = oParameters || {};
|
||||||
|
oParameters['Action'] = sAction;
|
||||||
|
|
||||||
|
return this.ajaxRequest(sAction, true, iTimeOut, oParameters, '', fTrigger);
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = AbstractAjaxPromises;
|
||||||
|
|
||||||
|
}());
|
||||||
58
dev/Promises/User/Ajax.js
Normal file
58
dev/Promises/User/Ajax.js
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
|
||||||
|
(function () {
|
||||||
|
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var
|
||||||
|
_ = require('_'),
|
||||||
|
ko = require('ko'),
|
||||||
|
|
||||||
|
AbstractAjaxPromises = require('Promises/AbstractAjax'),
|
||||||
|
|
||||||
|
MessageModel = require('Model/Message')
|
||||||
|
;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor
|
||||||
|
* @extends AbstractAjaxPromises
|
||||||
|
*/
|
||||||
|
function PromisesUserAjax()
|
||||||
|
{
|
||||||
|
AbstractAjaxPromises.call(this);
|
||||||
|
|
||||||
|
this.messageListSimple.loading = ko.observable(false).extend({'rateLimit': 1});
|
||||||
|
this.messageListSimple.hash = '';
|
||||||
|
this.messageListSimple.cache = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
PromisesUserAjax.prototype.messageListSimple = function (sFolder, aUids)
|
||||||
|
{
|
||||||
|
var self = this, sHash = sFolder + '~' + aUids.join('/');
|
||||||
|
if (sHash === this.messageListSimple.hash && this.messageListSimple.cache)
|
||||||
|
{
|
||||||
|
return this.fastPromise(this.messageListSimple.cache);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.abort('MessageListSimple')
|
||||||
|
.postRequest('MessageListSimple', this.messageListSimple.loading, {
|
||||||
|
'Folder': sFolder,
|
||||||
|
'Uids': aUids
|
||||||
|
}).then(function (aData) {
|
||||||
|
|
||||||
|
var aResult = _.compact(_.map(aData, function (aItem) {
|
||||||
|
return MessageModel.newInstanceFromJson(aItem);
|
||||||
|
}));
|
||||||
|
|
||||||
|
self.messageListSimple.hash = sHash;
|
||||||
|
self.messageListSimple.cache = aResult;
|
||||||
|
|
||||||
|
return aResult;
|
||||||
|
})
|
||||||
|
;
|
||||||
|
};
|
||||||
|
|
||||||
|
_.extend(PromisesUserAjax.prototype, AbstractAjaxPromises.prototype);
|
||||||
|
|
||||||
|
module.exports = new PromisesUserAjax();
|
||||||
|
|
||||||
|
}());
|
||||||
|
|
@ -24,7 +24,7 @@
|
||||||
* @constructor
|
* @constructor
|
||||||
* @extends AbstractRemoteStorage
|
* @extends AbstractRemoteStorage
|
||||||
*/
|
*/
|
||||||
function RemoteUserStorage()
|
function RemoteUserAjax()
|
||||||
{
|
{
|
||||||
AbstractAjaxRemote.call(this);
|
AbstractAjaxRemote.call(this);
|
||||||
|
|
||||||
|
|
@ -33,12 +33,12 @@
|
||||||
this.sSubSubQuery = '&ss=/';
|
this.sSubSubQuery = '&ss=/';
|
||||||
}
|
}
|
||||||
|
|
||||||
_.extend(RemoteUserStorage.prototype, AbstractAjaxRemote.prototype);
|
_.extend(RemoteUserAjax.prototype, AbstractAjaxRemote.prototype);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {?Function} fCallback
|
* @param {?Function} fCallback
|
||||||
*/
|
*/
|
||||||
RemoteUserStorage.prototype.folders = function (fCallback)
|
RemoteUserAjax.prototype.folders = function (fCallback)
|
||||||
{
|
{
|
||||||
this.defaultRequest(fCallback, 'Folders', {
|
this.defaultRequest(fCallback, 'Folders', {
|
||||||
'SentFolder': Settings.settingsGet('SentFolder'),
|
'SentFolder': Settings.settingsGet('SentFolder'),
|
||||||
|
|
@ -59,7 +59,7 @@
|
||||||
* @param {string=} sAdditionalCode
|
* @param {string=} sAdditionalCode
|
||||||
* @param {boolean=} bAdditionalCodeSignMe
|
* @param {boolean=} bAdditionalCodeSignMe
|
||||||
*/
|
*/
|
||||||
RemoteUserStorage.prototype.login = function (fCallback, sEmail, sLogin, sPassword, bSignMe, sLanguage, sAdditionalCode, bAdditionalCodeSignMe)
|
RemoteUserAjax.prototype.login = function (fCallback, sEmail, sLogin, sPassword, bSignMe, sLanguage, sAdditionalCode, bAdditionalCodeSignMe)
|
||||||
{
|
{
|
||||||
this.defaultRequest(fCallback, 'Login', {
|
this.defaultRequest(fCallback, 'Login', {
|
||||||
'Email': sEmail,
|
'Email': sEmail,
|
||||||
|
|
@ -75,7 +75,7 @@
|
||||||
/**
|
/**
|
||||||
* @param {?Function} fCallback
|
* @param {?Function} fCallback
|
||||||
*/
|
*/
|
||||||
RemoteUserStorage.prototype.getTwoFactor = function (fCallback)
|
RemoteUserAjax.prototype.getTwoFactor = function (fCallback)
|
||||||
{
|
{
|
||||||
this.defaultRequest(fCallback, 'GetTwoFactorInfo');
|
this.defaultRequest(fCallback, 'GetTwoFactorInfo');
|
||||||
};
|
};
|
||||||
|
|
@ -83,7 +83,7 @@
|
||||||
/**
|
/**
|
||||||
* @param {?Function} fCallback
|
* @param {?Function} fCallback
|
||||||
*/
|
*/
|
||||||
RemoteUserStorage.prototype.createTwoFactor = function (fCallback)
|
RemoteUserAjax.prototype.createTwoFactor = function (fCallback)
|
||||||
{
|
{
|
||||||
this.defaultRequest(fCallback, 'CreateTwoFactorSecret');
|
this.defaultRequest(fCallback, 'CreateTwoFactorSecret');
|
||||||
};
|
};
|
||||||
|
|
@ -91,7 +91,7 @@
|
||||||
/**
|
/**
|
||||||
* @param {?Function} fCallback
|
* @param {?Function} fCallback
|
||||||
*/
|
*/
|
||||||
RemoteUserStorage.prototype.clearTwoFactor = function (fCallback)
|
RemoteUserAjax.prototype.clearTwoFactor = function (fCallback)
|
||||||
{
|
{
|
||||||
this.defaultRequest(fCallback, 'ClearTwoFactorInfo');
|
this.defaultRequest(fCallback, 'ClearTwoFactorInfo');
|
||||||
};
|
};
|
||||||
|
|
@ -99,7 +99,7 @@
|
||||||
/**
|
/**
|
||||||
* @param {?Function} fCallback
|
* @param {?Function} fCallback
|
||||||
*/
|
*/
|
||||||
RemoteUserStorage.prototype.showTwoFactorSecret = function (fCallback)
|
RemoteUserAjax.prototype.showTwoFactorSecret = function (fCallback)
|
||||||
{
|
{
|
||||||
this.defaultRequest(fCallback, 'ShowTwoFactorSecret');
|
this.defaultRequest(fCallback, 'ShowTwoFactorSecret');
|
||||||
};
|
};
|
||||||
|
|
@ -108,7 +108,7 @@
|
||||||
* @param {?Function} fCallback
|
* @param {?Function} fCallback
|
||||||
* @param {string} sCode
|
* @param {string} sCode
|
||||||
*/
|
*/
|
||||||
RemoteUserStorage.prototype.testTwoFactor = function (fCallback, sCode)
|
RemoteUserAjax.prototype.testTwoFactor = function (fCallback, sCode)
|
||||||
{
|
{
|
||||||
this.defaultRequest(fCallback, 'TestTwoFactorInfo', {
|
this.defaultRequest(fCallback, 'TestTwoFactorInfo', {
|
||||||
'Code': sCode
|
'Code': sCode
|
||||||
|
|
@ -119,7 +119,7 @@
|
||||||
* @param {?Function} fCallback
|
* @param {?Function} fCallback
|
||||||
* @param {boolean} bEnable
|
* @param {boolean} bEnable
|
||||||
*/
|
*/
|
||||||
RemoteUserStorage.prototype.enableTwoFactor = function (fCallback, bEnable)
|
RemoteUserAjax.prototype.enableTwoFactor = function (fCallback, bEnable)
|
||||||
{
|
{
|
||||||
this.defaultRequest(fCallback, 'EnableTwoFactor', {
|
this.defaultRequest(fCallback, 'EnableTwoFactor', {
|
||||||
'Enable': bEnable ? '1' : '0'
|
'Enable': bEnable ? '1' : '0'
|
||||||
|
|
@ -129,7 +129,7 @@
|
||||||
/**
|
/**
|
||||||
* @param {?Function} fCallback
|
* @param {?Function} fCallback
|
||||||
*/
|
*/
|
||||||
RemoteUserStorage.prototype.clearTwoFactorInfo = function (fCallback)
|
RemoteUserAjax.prototype.clearTwoFactorInfo = function (fCallback)
|
||||||
{
|
{
|
||||||
this.defaultRequest(fCallback, 'ClearTwoFactorInfo');
|
this.defaultRequest(fCallback, 'ClearTwoFactorInfo');
|
||||||
};
|
};
|
||||||
|
|
@ -137,7 +137,7 @@
|
||||||
/**
|
/**
|
||||||
* @param {?Function} fCallback
|
* @param {?Function} fCallback
|
||||||
*/
|
*/
|
||||||
RemoteUserStorage.prototype.contactsSync = function (fCallback)
|
RemoteUserAjax.prototype.contactsSync = function (fCallback)
|
||||||
{
|
{
|
||||||
this.defaultRequest(fCallback, 'ContactsSync', null, Consts.Defaults.ContactsSyncAjaxTimeout);
|
this.defaultRequest(fCallback, 'ContactsSync', null, Consts.Defaults.ContactsSyncAjaxTimeout);
|
||||||
};
|
};
|
||||||
|
|
@ -149,7 +149,7 @@
|
||||||
* @param {string} sUser
|
* @param {string} sUser
|
||||||
* @param {string} sPassword
|
* @param {string} sPassword
|
||||||
*/
|
*/
|
||||||
RemoteUserStorage.prototype.saveContactsSyncData = function (fCallback, bEnable, sUrl, sUser, sPassword)
|
RemoteUserAjax.prototype.saveContactsSyncData = function (fCallback, bEnable, sUrl, sUser, sPassword)
|
||||||
{
|
{
|
||||||
this.defaultRequest(fCallback, 'SaveContactsSyncData', {
|
this.defaultRequest(fCallback, 'SaveContactsSyncData', {
|
||||||
'Enable': bEnable ? '1' : '0',
|
'Enable': bEnable ? '1' : '0',
|
||||||
|
|
@ -165,7 +165,7 @@
|
||||||
* @param {string} sPassword
|
* @param {string} sPassword
|
||||||
* @param {boolean=} bNew
|
* @param {boolean=} bNew
|
||||||
*/
|
*/
|
||||||
RemoteUserStorage.prototype.accountSetup = function (fCallback, sEmail, sPassword, bNew)
|
RemoteUserAjax.prototype.accountSetup = function (fCallback, sEmail, sPassword, bNew)
|
||||||
{
|
{
|
||||||
bNew = Utils.isUnd(bNew) ? true : !!bNew;
|
bNew = Utils.isUnd(bNew) ? true : !!bNew;
|
||||||
|
|
||||||
|
|
@ -180,7 +180,7 @@
|
||||||
* @param {?Function} fCallback
|
* @param {?Function} fCallback
|
||||||
* @param {string} sEmailToDelete
|
* @param {string} sEmailToDelete
|
||||||
*/
|
*/
|
||||||
RemoteUserStorage.prototype.accountDelete = function (fCallback, sEmailToDelete)
|
RemoteUserAjax.prototype.accountDelete = function (fCallback, sEmailToDelete)
|
||||||
{
|
{
|
||||||
this.defaultRequest(fCallback, 'AccountDelete', {
|
this.defaultRequest(fCallback, 'AccountDelete', {
|
||||||
'EmailToDelete': sEmailToDelete
|
'EmailToDelete': sEmailToDelete
|
||||||
|
|
@ -192,7 +192,7 @@
|
||||||
* @param {Array} aAccounts
|
* @param {Array} aAccounts
|
||||||
* @param {Array} aIdentities
|
* @param {Array} aIdentities
|
||||||
*/
|
*/
|
||||||
RemoteUserStorage.prototype.accountsAndIdentitiesSortOrder = function (fCallback, aAccounts, aIdentities)
|
RemoteUserAjax.prototype.accountsAndIdentitiesSortOrder = function (fCallback, aAccounts, aIdentities)
|
||||||
{
|
{
|
||||||
this.defaultRequest(fCallback, 'AccountsAndIdentitiesSortOrder', {
|
this.defaultRequest(fCallback, 'AccountsAndIdentitiesSortOrder', {
|
||||||
'Accounts': aAccounts,
|
'Accounts': aAccounts,
|
||||||
|
|
@ -210,7 +210,7 @@
|
||||||
* @param {string} sSignature
|
* @param {string} sSignature
|
||||||
* @param {boolean} bSignatureInsertBefore
|
* @param {boolean} bSignatureInsertBefore
|
||||||
*/
|
*/
|
||||||
RemoteUserStorage.prototype.identityUpdate = function (fCallback, sId, sEmail, sName, sReplyTo, sBcc,
|
RemoteUserAjax.prototype.identityUpdate = function (fCallback, sId, sEmail, sName, sReplyTo, sBcc,
|
||||||
sSignature, bSignatureInsertBefore)
|
sSignature, bSignatureInsertBefore)
|
||||||
{
|
{
|
||||||
this.defaultRequest(fCallback, 'IdentityUpdate', {
|
this.defaultRequest(fCallback, 'IdentityUpdate', {
|
||||||
|
|
@ -228,7 +228,7 @@
|
||||||
* @param {?Function} fCallback
|
* @param {?Function} fCallback
|
||||||
* @param {string} sIdToDelete
|
* @param {string} sIdToDelete
|
||||||
*/
|
*/
|
||||||
RemoteUserStorage.prototype.identityDelete = function (fCallback, sIdToDelete)
|
RemoteUserAjax.prototype.identityDelete = function (fCallback, sIdToDelete)
|
||||||
{
|
{
|
||||||
this.defaultRequest(fCallback, 'IdentityDelete', {
|
this.defaultRequest(fCallback, 'IdentityDelete', {
|
||||||
'IdToDelete': sIdToDelete
|
'IdToDelete': sIdToDelete
|
||||||
|
|
@ -238,7 +238,7 @@
|
||||||
/**
|
/**
|
||||||
* @param {?Function} fCallback
|
* @param {?Function} fCallback
|
||||||
*/
|
*/
|
||||||
RemoteUserStorage.prototype.accountsAndIdentities = function (fCallback)
|
RemoteUserAjax.prototype.accountsAndIdentities = function (fCallback)
|
||||||
{
|
{
|
||||||
this.defaultRequest(fCallback, 'AccountsAndIdentities');
|
this.defaultRequest(fCallback, 'AccountsAndIdentities');
|
||||||
};
|
};
|
||||||
|
|
@ -246,7 +246,7 @@
|
||||||
/**
|
/**
|
||||||
* @param {?Function} fCallback
|
* @param {?Function} fCallback
|
||||||
*/
|
*/
|
||||||
RemoteUserStorage.prototype.accountsCounts = function (fCallback)
|
RemoteUserAjax.prototype.accountsCounts = function (fCallback)
|
||||||
{
|
{
|
||||||
this.defaultRequest(fCallback, 'AccountsCounts');
|
this.defaultRequest(fCallback, 'AccountsCounts');
|
||||||
};
|
};
|
||||||
|
|
@ -254,7 +254,7 @@
|
||||||
/**
|
/**
|
||||||
* @param {?Function} fCallback
|
* @param {?Function} fCallback
|
||||||
*/
|
*/
|
||||||
RemoteUserStorage.prototype.filtersSave = function (fCallback,
|
RemoteUserAjax.prototype.filtersSave = function (fCallback,
|
||||||
aFilters, sRaw, bRawIsActive)
|
aFilters, sRaw, bRawIsActive)
|
||||||
{
|
{
|
||||||
this.defaultRequest(fCallback, 'FiltersSave', {
|
this.defaultRequest(fCallback, 'FiltersSave', {
|
||||||
|
|
@ -269,7 +269,7 @@
|
||||||
/**
|
/**
|
||||||
* @param {?Function} fCallback
|
* @param {?Function} fCallback
|
||||||
*/
|
*/
|
||||||
RemoteUserStorage.prototype.filtersGet = function (fCallback)
|
RemoteUserAjax.prototype.filtersGet = function (fCallback)
|
||||||
{
|
{
|
||||||
this.defaultRequest(fCallback, 'Filters', {});
|
this.defaultRequest(fCallback, 'Filters', {});
|
||||||
};
|
};
|
||||||
|
|
@ -277,7 +277,7 @@
|
||||||
/**
|
/**
|
||||||
* @param {?Function} fCallback
|
* @param {?Function} fCallback
|
||||||
*/
|
*/
|
||||||
RemoteUserStorage.prototype.templates = function (fCallback)
|
RemoteUserAjax.prototype.templates = function (fCallback)
|
||||||
{
|
{
|
||||||
this.defaultRequest(fCallback, 'Templates', {});
|
this.defaultRequest(fCallback, 'Templates', {});
|
||||||
};
|
};
|
||||||
|
|
@ -285,7 +285,7 @@
|
||||||
/**
|
/**
|
||||||
* @param {?Function} fCallback
|
* @param {?Function} fCallback
|
||||||
*/
|
*/
|
||||||
RemoteUserStorage.prototype.templateGetById = function (fCallback, sID)
|
RemoteUserAjax.prototype.templateGetById = function (fCallback, sID)
|
||||||
{
|
{
|
||||||
this.defaultRequest(fCallback, 'TemplateGetByID', {
|
this.defaultRequest(fCallback, 'TemplateGetByID', {
|
||||||
'ID': sID
|
'ID': sID
|
||||||
|
|
@ -295,7 +295,7 @@
|
||||||
/**
|
/**
|
||||||
* @param {?Function} fCallback
|
* @param {?Function} fCallback
|
||||||
*/
|
*/
|
||||||
RemoteUserStorage.prototype.templateDelete = function (fCallback, sID)
|
RemoteUserAjax.prototype.templateDelete = function (fCallback, sID)
|
||||||
{
|
{
|
||||||
this.defaultRequest(fCallback, 'TemplateDelete', {
|
this.defaultRequest(fCallback, 'TemplateDelete', {
|
||||||
'IdToDelete': sID
|
'IdToDelete': sID
|
||||||
|
|
@ -305,7 +305,7 @@
|
||||||
/**
|
/**
|
||||||
* @param {?Function} fCallback
|
* @param {?Function} fCallback
|
||||||
*/
|
*/
|
||||||
RemoteUserStorage.prototype.templateSetup = function (fCallback, sID, sName, sBody)
|
RemoteUserAjax.prototype.templateSetup = function (fCallback, sID, sName, sBody)
|
||||||
{
|
{
|
||||||
this.defaultRequest(fCallback, 'TemplateSetup', {
|
this.defaultRequest(fCallback, 'TemplateSetup', {
|
||||||
'ID': sID,
|
'ID': sID,
|
||||||
|
|
@ -319,7 +319,7 @@
|
||||||
* @param {string} sFolderFullNameRaw
|
* @param {string} sFolderFullNameRaw
|
||||||
* @param {Array} aUids
|
* @param {Array} aUids
|
||||||
*/
|
*/
|
||||||
RemoteUserStorage.prototype.messageListSimple = function (fCallback, sFolderFullNameRaw, aUids)
|
RemoteUserAjax.prototype.messageListSimple = function (fCallback, sFolderFullNameRaw, aUids)
|
||||||
{
|
{
|
||||||
return this.defaultRequest(fCallback, 'MessageListSimple', {
|
return this.defaultRequest(fCallback, 'MessageListSimple', {
|
||||||
'Folder': Utils.pString(sFolderFullNameRaw),
|
'Folder': Utils.pString(sFolderFullNameRaw),
|
||||||
|
|
@ -335,7 +335,7 @@
|
||||||
* @param {string=} sSearch = ''
|
* @param {string=} sSearch = ''
|
||||||
* @param {boolean=} bSilent = false
|
* @param {boolean=} bSilent = false
|
||||||
*/
|
*/
|
||||||
RemoteUserStorage.prototype.messageList = function (fCallback, sFolderFullNameRaw, iOffset, iLimit, sSearch, bSilent)
|
RemoteUserAjax.prototype.messageList = function (fCallback, sFolderFullNameRaw, iOffset, iLimit, sSearch, bSilent)
|
||||||
{
|
{
|
||||||
sFolderFullNameRaw = Utils.pString(sFolderFullNameRaw);
|
sFolderFullNameRaw = Utils.pString(sFolderFullNameRaw);
|
||||||
|
|
||||||
|
|
@ -381,7 +381,7 @@
|
||||||
* @param {?Function} fCallback
|
* @param {?Function} fCallback
|
||||||
* @param {Array} aDownloads
|
* @param {Array} aDownloads
|
||||||
*/
|
*/
|
||||||
RemoteUserStorage.prototype.messageUploadAttachments = function (fCallback, aDownloads)
|
RemoteUserAjax.prototype.messageUploadAttachments = function (fCallback, aDownloads)
|
||||||
{
|
{
|
||||||
this.defaultRequest(fCallback, 'MessageUploadAttachments', {
|
this.defaultRequest(fCallback, 'MessageUploadAttachments', {
|
||||||
'Attachments': aDownloads
|
'Attachments': aDownloads
|
||||||
|
|
@ -394,7 +394,7 @@
|
||||||
* @param {number} iUid
|
* @param {number} iUid
|
||||||
* @return {boolean}
|
* @return {boolean}
|
||||||
*/
|
*/
|
||||||
RemoteUserStorage.prototype.message = function (fCallback, sFolderFullNameRaw, iUid)
|
RemoteUserAjax.prototype.message = function (fCallback, sFolderFullNameRaw, iUid)
|
||||||
{
|
{
|
||||||
sFolderFullNameRaw = Utils.pString(sFolderFullNameRaw);
|
sFolderFullNameRaw = Utils.pString(sFolderFullNameRaw);
|
||||||
iUid = Utils.pInt(iUid);
|
iUid = Utils.pInt(iUid);
|
||||||
|
|
@ -421,7 +421,7 @@
|
||||||
* @param {number} iUid
|
* @param {number} iUid
|
||||||
* @return {boolean}
|
* @return {boolean}
|
||||||
*/
|
*/
|
||||||
RemoteUserStorage.prototype.messageThreadsFromCache = function (fCallback, sFolderFullNameRaw, iUid)
|
RemoteUserAjax.prototype.messageThreadsFromCache = function (fCallback, sFolderFullNameRaw, iUid)
|
||||||
{
|
{
|
||||||
sFolderFullNameRaw = Utils.pString(sFolderFullNameRaw);
|
sFolderFullNameRaw = Utils.pString(sFolderFullNameRaw);
|
||||||
iUid = Utils.pInt(iUid);
|
iUid = Utils.pInt(iUid);
|
||||||
|
|
@ -448,7 +448,7 @@
|
||||||
* @param {?Function} fCallback
|
* @param {?Function} fCallback
|
||||||
* @param {Array} aExternals
|
* @param {Array} aExternals
|
||||||
*/
|
*/
|
||||||
RemoteUserStorage.prototype.composeUploadExternals = function (fCallback, aExternals)
|
RemoteUserAjax.prototype.composeUploadExternals = function (fCallback, aExternals)
|
||||||
{
|
{
|
||||||
this.defaultRequest(fCallback, 'ComposeUploadExternals', {
|
this.defaultRequest(fCallback, 'ComposeUploadExternals', {
|
||||||
'Externals': aExternals
|
'Externals': aExternals
|
||||||
|
|
@ -460,7 +460,7 @@
|
||||||
* @param {string} sUrl
|
* @param {string} sUrl
|
||||||
* @param {string} sAccessToken
|
* @param {string} sAccessToken
|
||||||
*/
|
*/
|
||||||
RemoteUserStorage.prototype.composeUploadDrive = function (fCallback, sUrl, sAccessToken)
|
RemoteUserAjax.prototype.composeUploadDrive = function (fCallback, sUrl, sAccessToken)
|
||||||
{
|
{
|
||||||
this.defaultRequest(fCallback, 'ComposeUploadDrive', {
|
this.defaultRequest(fCallback, 'ComposeUploadDrive', {
|
||||||
'AccessToken': sAccessToken,
|
'AccessToken': sAccessToken,
|
||||||
|
|
@ -473,7 +473,7 @@
|
||||||
* @param {string} sFolder
|
* @param {string} sFolder
|
||||||
* @param {Array=} aList = []
|
* @param {Array=} aList = []
|
||||||
*/
|
*/
|
||||||
RemoteUserStorage.prototype.folderInformation = function (fCallback, sFolder, aList)
|
RemoteUserAjax.prototype.folderInformation = function (fCallback, sFolder, aList)
|
||||||
{
|
{
|
||||||
var
|
var
|
||||||
bRequest = true,
|
bRequest = true,
|
||||||
|
|
@ -524,7 +524,7 @@
|
||||||
* @param {?Function} fCallback
|
* @param {?Function} fCallback
|
||||||
* @param {Array} aFolders
|
* @param {Array} aFolders
|
||||||
*/
|
*/
|
||||||
RemoteUserStorage.prototype.folderInformationMultiply = function (fCallback, aFolders)
|
RemoteUserAjax.prototype.folderInformationMultiply = function (fCallback, aFolders)
|
||||||
{
|
{
|
||||||
this.defaultRequest(fCallback, 'FolderInformationMultiply', {
|
this.defaultRequest(fCallback, 'FolderInformationMultiply', {
|
||||||
'Folders': aFolders
|
'Folders': aFolders
|
||||||
|
|
@ -534,7 +534,7 @@
|
||||||
/**
|
/**
|
||||||
* @param {?Function} fCallback
|
* @param {?Function} fCallback
|
||||||
*/
|
*/
|
||||||
RemoteUserStorage.prototype.logout = function (fCallback)
|
RemoteUserAjax.prototype.logout = function (fCallback)
|
||||||
{
|
{
|
||||||
this.defaultRequest(fCallback, 'Logout');
|
this.defaultRequest(fCallback, 'Logout');
|
||||||
};
|
};
|
||||||
|
|
@ -545,7 +545,7 @@
|
||||||
* @param {Array} aUids
|
* @param {Array} aUids
|
||||||
* @param {boolean} bSetFlagged
|
* @param {boolean} bSetFlagged
|
||||||
*/
|
*/
|
||||||
RemoteUserStorage.prototype.messageSetFlagged = function (fCallback, sFolderFullNameRaw, aUids, bSetFlagged)
|
RemoteUserAjax.prototype.messageSetFlagged = function (fCallback, sFolderFullNameRaw, aUids, bSetFlagged)
|
||||||
{
|
{
|
||||||
this.defaultRequest(fCallback, 'MessageSetFlagged', {
|
this.defaultRequest(fCallback, 'MessageSetFlagged', {
|
||||||
'Folder': sFolderFullNameRaw,
|
'Folder': sFolderFullNameRaw,
|
||||||
|
|
@ -560,7 +560,7 @@
|
||||||
* @param {Array} aUids
|
* @param {Array} aUids
|
||||||
* @param {boolean} bSetSeen
|
* @param {boolean} bSetSeen
|
||||||
*/
|
*/
|
||||||
RemoteUserStorage.prototype.messageSetSeen = function (fCallback, sFolderFullNameRaw, aUids, bSetSeen)
|
RemoteUserAjax.prototype.messageSetSeen = function (fCallback, sFolderFullNameRaw, aUids, bSetSeen)
|
||||||
{
|
{
|
||||||
this.defaultRequest(fCallback, 'MessageSetSeen', {
|
this.defaultRequest(fCallback, 'MessageSetSeen', {
|
||||||
'Folder': sFolderFullNameRaw,
|
'Folder': sFolderFullNameRaw,
|
||||||
|
|
@ -574,7 +574,7 @@
|
||||||
* @param {string} sFolderFullNameRaw
|
* @param {string} sFolderFullNameRaw
|
||||||
* @param {boolean} bSetSeen
|
* @param {boolean} bSetSeen
|
||||||
*/
|
*/
|
||||||
RemoteUserStorage.prototype.messageSetSeenToAll = function (fCallback, sFolderFullNameRaw, bSetSeen)
|
RemoteUserAjax.prototype.messageSetSeenToAll = function (fCallback, sFolderFullNameRaw, bSetSeen)
|
||||||
{
|
{
|
||||||
this.defaultRequest(fCallback, 'MessageSetSeenToAll', {
|
this.defaultRequest(fCallback, 'MessageSetSeenToAll', {
|
||||||
'Folder': sFolderFullNameRaw,
|
'Folder': sFolderFullNameRaw,
|
||||||
|
|
@ -600,7 +600,7 @@
|
||||||
* @param {string} sReferences
|
* @param {string} sReferences
|
||||||
* @param {boolean} bMarkAsImportant
|
* @param {boolean} bMarkAsImportant
|
||||||
*/
|
*/
|
||||||
RemoteUserStorage.prototype.saveMessage = function (fCallback, sIdentityID, sMessageFolder, sMessageUid, sDraftFolder,
|
RemoteUserAjax.prototype.saveMessage = function (fCallback, sIdentityID, sMessageFolder, sMessageUid, sDraftFolder,
|
||||||
sTo, sCc, sBcc, sReplyTo, sSubject, bTextIsHtml, sText, aAttachments, aDraftInfo, sInReplyTo, sReferences, bMarkAsImportant)
|
sTo, sCc, sBcc, sReplyTo, sSubject, bTextIsHtml, sText, aAttachments, aDraftInfo, sInReplyTo, sReferences, bMarkAsImportant)
|
||||||
{
|
{
|
||||||
this.defaultRequest(fCallback, 'SaveMessage', {
|
this.defaultRequest(fCallback, 'SaveMessage', {
|
||||||
|
|
@ -632,7 +632,7 @@
|
||||||
* @param {string} sSubject
|
* @param {string} sSubject
|
||||||
* @param {string} sText
|
* @param {string} sText
|
||||||
*/
|
*/
|
||||||
RemoteUserStorage.prototype.sendReadReceiptMessage = function (fCallback, sMessageFolder, sMessageUid, sReadReceipt, sSubject, sText)
|
RemoteUserAjax.prototype.sendReadReceiptMessage = function (fCallback, sMessageFolder, sMessageUid, sReadReceipt, sSubject, sText)
|
||||||
{
|
{
|
||||||
this.defaultRequest(fCallback, 'SendReadReceiptMessage', {
|
this.defaultRequest(fCallback, 'SendReadReceiptMessage', {
|
||||||
'MessageFolder': sMessageFolder,
|
'MessageFolder': sMessageFolder,
|
||||||
|
|
@ -664,7 +664,7 @@
|
||||||
* @param {boolean} bRequestReadReceipt
|
* @param {boolean} bRequestReadReceipt
|
||||||
* @param {boolean} bMarkAsImportant
|
* @param {boolean} bMarkAsImportant
|
||||||
*/
|
*/
|
||||||
RemoteUserStorage.prototype.sendMessage = function (fCallback, sIdentityID, sMessageFolder, sMessageUid, sSentFolder,
|
RemoteUserAjax.prototype.sendMessage = function (fCallback, sIdentityID, sMessageFolder, sMessageUid, sSentFolder,
|
||||||
sTo, sCc, sBcc, sReplyTo, sSubject, bTextIsHtml, sText, aAttachments, aDraftInfo, sInReplyTo, sReferences,
|
sTo, sCc, sBcc, sReplyTo, sSubject, bTextIsHtml, sText, aAttachments, aDraftInfo, sInReplyTo, sReferences,
|
||||||
bRequestDsn, bRequestReadReceipt, bMarkAsImportant)
|
bRequestDsn, bRequestReadReceipt, bMarkAsImportant)
|
||||||
{
|
{
|
||||||
|
|
@ -694,7 +694,7 @@
|
||||||
* @param {?Function} fCallback
|
* @param {?Function} fCallback
|
||||||
* @param {Object} oData
|
* @param {Object} oData
|
||||||
*/
|
*/
|
||||||
RemoteUserStorage.prototype.saveSystemFolders = function (fCallback, oData)
|
RemoteUserAjax.prototype.saveSystemFolders = function (fCallback, oData)
|
||||||
{
|
{
|
||||||
this.defaultRequest(fCallback, 'SystemFoldersUpdate', oData);
|
this.defaultRequest(fCallback, 'SystemFoldersUpdate', oData);
|
||||||
};
|
};
|
||||||
|
|
@ -703,7 +703,7 @@
|
||||||
* @param {?Function} fCallback
|
* @param {?Function} fCallback
|
||||||
* @param {Object} oData
|
* @param {Object} oData
|
||||||
*/
|
*/
|
||||||
RemoteUserStorage.prototype.saveSettings = function (fCallback, oData)
|
RemoteUserAjax.prototype.saveSettings = function (fCallback, oData)
|
||||||
{
|
{
|
||||||
this.defaultRequest(fCallback, 'SettingsUpdate', oData);
|
this.defaultRequest(fCallback, 'SettingsUpdate', oData);
|
||||||
};
|
};
|
||||||
|
|
@ -713,7 +713,7 @@
|
||||||
* @param {string} sPrevPassword
|
* @param {string} sPrevPassword
|
||||||
* @param {string} sNewPassword
|
* @param {string} sNewPassword
|
||||||
*/
|
*/
|
||||||
RemoteUserStorage.prototype.changePassword = function (fCallback, sPrevPassword, sNewPassword)
|
RemoteUserAjax.prototype.changePassword = function (fCallback, sPrevPassword, sNewPassword)
|
||||||
{
|
{
|
||||||
this.defaultRequest(fCallback, 'ChangePassword', {
|
this.defaultRequest(fCallback, 'ChangePassword', {
|
||||||
'PrevPassword': sPrevPassword,
|
'PrevPassword': sPrevPassword,
|
||||||
|
|
@ -726,7 +726,7 @@
|
||||||
* @param {string} sNewFolderName
|
* @param {string} sNewFolderName
|
||||||
* @param {string} sParentName
|
* @param {string} sParentName
|
||||||
*/
|
*/
|
||||||
RemoteUserStorage.prototype.folderCreate = function (fCallback, sNewFolderName, sParentName)
|
RemoteUserAjax.prototype.folderCreate = function (fCallback, sNewFolderName, sParentName)
|
||||||
{
|
{
|
||||||
this.defaultRequest(fCallback, 'FolderCreate', {
|
this.defaultRequest(fCallback, 'FolderCreate', {
|
||||||
'Folder': sNewFolderName,
|
'Folder': sNewFolderName,
|
||||||
|
|
@ -738,7 +738,7 @@
|
||||||
* @param {?Function} fCallback
|
* @param {?Function} fCallback
|
||||||
* @param {string} sFolderFullNameRaw
|
* @param {string} sFolderFullNameRaw
|
||||||
*/
|
*/
|
||||||
RemoteUserStorage.prototype.folderDelete = function (fCallback, sFolderFullNameRaw)
|
RemoteUserAjax.prototype.folderDelete = function (fCallback, sFolderFullNameRaw)
|
||||||
{
|
{
|
||||||
this.defaultRequest(fCallback, 'FolderDelete', {
|
this.defaultRequest(fCallback, 'FolderDelete', {
|
||||||
'Folder': sFolderFullNameRaw
|
'Folder': sFolderFullNameRaw
|
||||||
|
|
@ -750,7 +750,7 @@
|
||||||
* @param {string} sPrevFolderFullNameRaw
|
* @param {string} sPrevFolderFullNameRaw
|
||||||
* @param {string} sNewFolderName
|
* @param {string} sNewFolderName
|
||||||
*/
|
*/
|
||||||
RemoteUserStorage.prototype.folderRename = function (fCallback, sPrevFolderFullNameRaw, sNewFolderName)
|
RemoteUserAjax.prototype.folderRename = function (fCallback, sPrevFolderFullNameRaw, sNewFolderName)
|
||||||
{
|
{
|
||||||
this.defaultRequest(fCallback, 'FolderRename', {
|
this.defaultRequest(fCallback, 'FolderRename', {
|
||||||
'Folder': sPrevFolderFullNameRaw,
|
'Folder': sPrevFolderFullNameRaw,
|
||||||
|
|
@ -762,7 +762,7 @@
|
||||||
* @param {?Function} fCallback
|
* @param {?Function} fCallback
|
||||||
* @param {string} sFolderFullNameRaw
|
* @param {string} sFolderFullNameRaw
|
||||||
*/
|
*/
|
||||||
RemoteUserStorage.prototype.folderClear = function (fCallback, sFolderFullNameRaw)
|
RemoteUserAjax.prototype.folderClear = function (fCallback, sFolderFullNameRaw)
|
||||||
{
|
{
|
||||||
this.defaultRequest(fCallback, 'FolderClear', {
|
this.defaultRequest(fCallback, 'FolderClear', {
|
||||||
'Folder': sFolderFullNameRaw
|
'Folder': sFolderFullNameRaw
|
||||||
|
|
@ -774,7 +774,7 @@
|
||||||
* @param {string} sFolderFullNameRaw
|
* @param {string} sFolderFullNameRaw
|
||||||
* @param {boolean} bSubscribe
|
* @param {boolean} bSubscribe
|
||||||
*/
|
*/
|
||||||
RemoteUserStorage.prototype.folderSetSubscribe = function (fCallback, sFolderFullNameRaw, bSubscribe)
|
RemoteUserAjax.prototype.folderSetSubscribe = function (fCallback, sFolderFullNameRaw, bSubscribe)
|
||||||
{
|
{
|
||||||
this.defaultRequest(fCallback, 'FolderSubscribe', {
|
this.defaultRequest(fCallback, 'FolderSubscribe', {
|
||||||
'Folder': sFolderFullNameRaw,
|
'Folder': sFolderFullNameRaw,
|
||||||
|
|
@ -789,7 +789,7 @@
|
||||||
* @param {Array} aUids
|
* @param {Array} aUids
|
||||||
* @param {string=} sLearning
|
* @param {string=} sLearning
|
||||||
*/
|
*/
|
||||||
RemoteUserStorage.prototype.messagesMove = function (fCallback, sFolder, sToFolder, aUids, sLearning)
|
RemoteUserAjax.prototype.messagesMove = function (fCallback, sFolder, sToFolder, aUids, sLearning)
|
||||||
{
|
{
|
||||||
this.defaultRequest(fCallback, 'MessageMove', {
|
this.defaultRequest(fCallback, 'MessageMove', {
|
||||||
'FromFolder': sFolder,
|
'FromFolder': sFolder,
|
||||||
|
|
@ -805,7 +805,7 @@
|
||||||
* @param {string} sToFolder
|
* @param {string} sToFolder
|
||||||
* @param {Array} aUids
|
* @param {Array} aUids
|
||||||
*/
|
*/
|
||||||
RemoteUserStorage.prototype.messagesCopy = function (fCallback, sFolder, sToFolder, aUids)
|
RemoteUserAjax.prototype.messagesCopy = function (fCallback, sFolder, sToFolder, aUids)
|
||||||
{
|
{
|
||||||
this.defaultRequest(fCallback, 'MessageCopy', {
|
this.defaultRequest(fCallback, 'MessageCopy', {
|
||||||
'FromFolder': sFolder,
|
'FromFolder': sFolder,
|
||||||
|
|
@ -819,7 +819,7 @@
|
||||||
* @param {string} sFolder
|
* @param {string} sFolder
|
||||||
* @param {Array} aUids
|
* @param {Array} aUids
|
||||||
*/
|
*/
|
||||||
RemoteUserStorage.prototype.messagesDelete = function (fCallback, sFolder, aUids)
|
RemoteUserAjax.prototype.messagesDelete = function (fCallback, sFolder, aUids)
|
||||||
{
|
{
|
||||||
this.defaultRequest(fCallback, 'MessageDelete', {
|
this.defaultRequest(fCallback, 'MessageDelete', {
|
||||||
'Folder': sFolder,
|
'Folder': sFolder,
|
||||||
|
|
@ -830,7 +830,7 @@
|
||||||
/**
|
/**
|
||||||
* @param {?Function} fCallback
|
* @param {?Function} fCallback
|
||||||
*/
|
*/
|
||||||
RemoteUserStorage.prototype.appDelayStart = function (fCallback)
|
RemoteUserAjax.prototype.appDelayStart = function (fCallback)
|
||||||
{
|
{
|
||||||
this.defaultRequest(fCallback, 'AppDelayStart');
|
this.defaultRequest(fCallback, 'AppDelayStart');
|
||||||
};
|
};
|
||||||
|
|
@ -838,7 +838,7 @@
|
||||||
/**
|
/**
|
||||||
* @param {?Function} fCallback
|
* @param {?Function} fCallback
|
||||||
*/
|
*/
|
||||||
RemoteUserStorage.prototype.quota = function (fCallback)
|
RemoteUserAjax.prototype.quota = function (fCallback)
|
||||||
{
|
{
|
||||||
this.defaultRequest(fCallback, 'Quota');
|
this.defaultRequest(fCallback, 'Quota');
|
||||||
};
|
};
|
||||||
|
|
@ -849,7 +849,7 @@
|
||||||
* @param {number} iLimit
|
* @param {number} iLimit
|
||||||
* @param {string} sSearch
|
* @param {string} sSearch
|
||||||
*/
|
*/
|
||||||
RemoteUserStorage.prototype.contacts = function (fCallback, iOffset, iLimit, sSearch)
|
RemoteUserAjax.prototype.contacts = function (fCallback, iOffset, iLimit, sSearch)
|
||||||
{
|
{
|
||||||
this.defaultRequest(fCallback, 'Contacts', {
|
this.defaultRequest(fCallback, 'Contacts', {
|
||||||
'Offset': iOffset,
|
'Offset': iOffset,
|
||||||
|
|
@ -864,7 +864,7 @@
|
||||||
* @param {string} sUid
|
* @param {string} sUid
|
||||||
* @param {Array} aProperties
|
* @param {Array} aProperties
|
||||||
*/
|
*/
|
||||||
RemoteUserStorage.prototype.contactSave = function (fCallback, sRequestUid, sUid, aProperties)
|
RemoteUserAjax.prototype.contactSave = function (fCallback, sRequestUid, sUid, aProperties)
|
||||||
{
|
{
|
||||||
this.defaultRequest(fCallback, 'ContactSave', {
|
this.defaultRequest(fCallback, 'ContactSave', {
|
||||||
'RequestUid': sRequestUid,
|
'RequestUid': sRequestUid,
|
||||||
|
|
@ -877,7 +877,7 @@
|
||||||
* @param {?Function} fCallback
|
* @param {?Function} fCallback
|
||||||
* @param {Array} aUids
|
* @param {Array} aUids
|
||||||
*/
|
*/
|
||||||
RemoteUserStorage.prototype.contactsDelete = function (fCallback, aUids)
|
RemoteUserAjax.prototype.contactsDelete = function (fCallback, aUids)
|
||||||
{
|
{
|
||||||
this.defaultRequest(fCallback, 'ContactsDelete', {
|
this.defaultRequest(fCallback, 'ContactsDelete', {
|
||||||
'Uids': aUids.join(',')
|
'Uids': aUids.join(',')
|
||||||
|
|
@ -889,7 +889,7 @@
|
||||||
* @param {string} sQuery
|
* @param {string} sQuery
|
||||||
* @param {number} iPage
|
* @param {number} iPage
|
||||||
*/
|
*/
|
||||||
RemoteUserStorage.prototype.suggestions = function (fCallback, sQuery, iPage)
|
RemoteUserAjax.prototype.suggestions = function (fCallback, sQuery, iPage)
|
||||||
{
|
{
|
||||||
this.defaultRequest(fCallback, 'Suggestions', {
|
this.defaultRequest(fCallback, 'Suggestions', {
|
||||||
'Query': sQuery,
|
'Query': sQuery,
|
||||||
|
|
@ -900,7 +900,7 @@
|
||||||
/**
|
/**
|
||||||
* @param {?Function} fCallback
|
* @param {?Function} fCallback
|
||||||
*/
|
*/
|
||||||
RemoteUserStorage.prototype.clearUserBackground = function (fCallback)
|
RemoteUserAjax.prototype.clearUserBackground = function (fCallback)
|
||||||
{
|
{
|
||||||
this.defaultRequest(fCallback, 'ClearUserBackground');
|
this.defaultRequest(fCallback, 'ClearUserBackground');
|
||||||
};
|
};
|
||||||
|
|
@ -908,7 +908,7 @@
|
||||||
/**
|
/**
|
||||||
* @param {?Function} fCallback
|
* @param {?Function} fCallback
|
||||||
*/
|
*/
|
||||||
RemoteUserStorage.prototype.facebookUser = function (fCallback)
|
RemoteUserAjax.prototype.facebookUser = function (fCallback)
|
||||||
{
|
{
|
||||||
this.defaultRequest(fCallback, 'SocialFacebookUserInformation');
|
this.defaultRequest(fCallback, 'SocialFacebookUserInformation');
|
||||||
};
|
};
|
||||||
|
|
@ -916,7 +916,7 @@
|
||||||
/**
|
/**
|
||||||
* @param {?Function} fCallback
|
* @param {?Function} fCallback
|
||||||
*/
|
*/
|
||||||
RemoteUserStorage.prototype.facebookDisconnect = function (fCallback)
|
RemoteUserAjax.prototype.facebookDisconnect = function (fCallback)
|
||||||
{
|
{
|
||||||
this.defaultRequest(fCallback, 'SocialFacebookDisconnect');
|
this.defaultRequest(fCallback, 'SocialFacebookDisconnect');
|
||||||
};
|
};
|
||||||
|
|
@ -924,7 +924,7 @@
|
||||||
/**
|
/**
|
||||||
* @param {?Function} fCallback
|
* @param {?Function} fCallback
|
||||||
*/
|
*/
|
||||||
RemoteUserStorage.prototype.twitterUser = function (fCallback)
|
RemoteUserAjax.prototype.twitterUser = function (fCallback)
|
||||||
{
|
{
|
||||||
this.defaultRequest(fCallback, 'SocialTwitterUserInformation');
|
this.defaultRequest(fCallback, 'SocialTwitterUserInformation');
|
||||||
};
|
};
|
||||||
|
|
@ -932,7 +932,7 @@
|
||||||
/**
|
/**
|
||||||
* @param {?Function} fCallback
|
* @param {?Function} fCallback
|
||||||
*/
|
*/
|
||||||
RemoteUserStorage.prototype.twitterDisconnect = function (fCallback)
|
RemoteUserAjax.prototype.twitterDisconnect = function (fCallback)
|
||||||
{
|
{
|
||||||
this.defaultRequest(fCallback, 'SocialTwitterDisconnect');
|
this.defaultRequest(fCallback, 'SocialTwitterDisconnect');
|
||||||
};
|
};
|
||||||
|
|
@ -940,7 +940,7 @@
|
||||||
/**
|
/**
|
||||||
* @param {?Function} fCallback
|
* @param {?Function} fCallback
|
||||||
*/
|
*/
|
||||||
RemoteUserStorage.prototype.googleUser = function (fCallback)
|
RemoteUserAjax.prototype.googleUser = function (fCallback)
|
||||||
{
|
{
|
||||||
this.defaultRequest(fCallback, 'SocialGoogleUserInformation');
|
this.defaultRequest(fCallback, 'SocialGoogleUserInformation');
|
||||||
};
|
};
|
||||||
|
|
@ -948,7 +948,7 @@
|
||||||
/**
|
/**
|
||||||
* @param {?Function} fCallback
|
* @param {?Function} fCallback
|
||||||
*/
|
*/
|
||||||
RemoteUserStorage.prototype.googleDisconnect = function (fCallback)
|
RemoteUserAjax.prototype.googleDisconnect = function (fCallback)
|
||||||
{
|
{
|
||||||
this.defaultRequest(fCallback, 'SocialGoogleDisconnect');
|
this.defaultRequest(fCallback, 'SocialGoogleDisconnect');
|
||||||
};
|
};
|
||||||
|
|
@ -956,11 +956,11 @@
|
||||||
/**
|
/**
|
||||||
* @param {?Function} fCallback
|
* @param {?Function} fCallback
|
||||||
*/
|
*/
|
||||||
RemoteUserStorage.prototype.socialUsers = function (fCallback)
|
RemoteUserAjax.prototype.socialUsers = function (fCallback)
|
||||||
{
|
{
|
||||||
this.defaultRequest(fCallback, 'SocialUsers');
|
this.defaultRequest(fCallback, 'SocialUsers');
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = new RemoteUserStorage();
|
module.exports = new RemoteUserAjax();
|
||||||
|
|
||||||
}());
|
}());
|
||||||
|
|
@ -364,6 +364,20 @@ html.rl-no-preview-pane {
|
||||||
border-radius: @rlLowBorderRadius;
|
border-radius: @rlLowBorderRadius;
|
||||||
border-color: darken(@rlMainDarkColor, 5%);
|
border-color: darken(@rlMainDarkColor, 5%);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.thread-list {
|
||||||
|
|
||||||
|
.e-link {
|
||||||
|
padding: 3px 5px 3px 10px;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hread-date {
|
||||||
|
font-size: 13px;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
html.rl-no-preview-pane .messageView {
|
html.rl-no-preview-pane .messageView {
|
||||||
|
|
|
||||||
|
|
@ -504,6 +504,8 @@
|
||||||
|
|
||||||
this.driveCallback = _.bind(this.driveCallback, this);
|
this.driveCallback = _.bind(this.driveCallback, this);
|
||||||
|
|
||||||
|
this.onMessageUploadAttachments = _.bind(this.onMessageUploadAttachments, this);
|
||||||
|
|
||||||
this.bDisabeCloseOnEsc = true;
|
this.bDisabeCloseOnEsc = true;
|
||||||
this.sDefaultKeyScope = Enums.KeyState.Compose;
|
this.sDefaultKeyScope = Enums.KeyState.Compose;
|
||||||
|
|
||||||
|
|
@ -1228,37 +1230,7 @@
|
||||||
aDownloads = this.getAttachmentsDownloadsForUpload();
|
aDownloads = this.getAttachmentsDownloadsForUpload();
|
||||||
if (Utils.isNonEmptyArray(aDownloads))
|
if (Utils.isNonEmptyArray(aDownloads))
|
||||||
{
|
{
|
||||||
Remote.messageUploadAttachments(function (sResult, oData) {
|
Remote.messageUploadAttachments(this.onMessageUploadAttachments, aDownloads);
|
||||||
|
|
||||||
if (Enums.StorageResultType.Success === sResult && oData && oData.Result)
|
|
||||||
{
|
|
||||||
var
|
|
||||||
oAttachment = null,
|
|
||||||
sTempName = ''
|
|
||||||
;
|
|
||||||
|
|
||||||
if (!self.viewModelVisibility())
|
|
||||||
{
|
|
||||||
for (sTempName in oData.Result)
|
|
||||||
{
|
|
||||||
if (oData.Result.hasOwnProperty(sTempName))
|
|
||||||
{
|
|
||||||
oAttachment = self.getAttachmentById(oData.Result[sTempName]);
|
|
||||||
if (oAttachment)
|
|
||||||
{
|
|
||||||
oAttachment.tempName(sTempName);
|
|
||||||
oAttachment.waiting(false).uploading(false).complete(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
self.setMessageAttachmentFailedDownloadText();
|
|
||||||
}
|
|
||||||
|
|
||||||
}, aDownloads);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (oIdentity)
|
if (oIdentity)
|
||||||
|
|
@ -1269,6 +1241,37 @@
|
||||||
this.resizerTrigger();
|
this.resizerTrigger();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ComposePopupView.prototype.onMessageUploadAttachments = function (sResult, oData)
|
||||||
|
{
|
||||||
|
if (Enums.StorageResultType.Success === sResult && oData && oData.Result)
|
||||||
|
{
|
||||||
|
var
|
||||||
|
oAttachment = null,
|
||||||
|
sTempName = ''
|
||||||
|
;
|
||||||
|
|
||||||
|
if (!this.viewModelVisibility())
|
||||||
|
{
|
||||||
|
for (sTempName in oData.Result)
|
||||||
|
{
|
||||||
|
if (oData.Result.hasOwnProperty(sTempName))
|
||||||
|
{
|
||||||
|
oAttachment = this.getAttachmentById(oData.Result[sTempName]);
|
||||||
|
if (oAttachment)
|
||||||
|
{
|
||||||
|
oAttachment.tempName(sTempName);
|
||||||
|
oAttachment.waiting(false).uploading(false).complete(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.setMessageAttachmentFailedDownloadText();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
ComposePopupView.prototype.setFocusInPopup = function ()
|
ComposePopupView.prototype.setFocusInPopup = function ()
|
||||||
{
|
{
|
||||||
if (!Globals.bMobileDevice)
|
if (!Globals.bMobileDevice)
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,8 @@
|
||||||
Local = require('Storage/Client'),
|
Local = require('Storage/Client'),
|
||||||
Remote = require('Remote/User/Ajax'),
|
Remote = require('Remote/User/Ajax'),
|
||||||
|
|
||||||
|
Promises = require('Promises/User/Ajax'),
|
||||||
|
|
||||||
kn = require('Knoin/Knoin'),
|
kn = require('Knoin/Knoin'),
|
||||||
AbstractView = require('Knoin/AbstractView')
|
AbstractView = require('Knoin/AbstractView')
|
||||||
;
|
;
|
||||||
|
|
@ -73,6 +75,8 @@
|
||||||
|
|
||||||
this.fullScreenMode = MessageStore.messageFullScreenMode;
|
this.fullScreenMode = MessageStore.messageFullScreenMode;
|
||||||
|
|
||||||
|
this.messageListOfThreadsLoading = Promises.messageListSimple.loading;
|
||||||
|
|
||||||
this.lastReplyAction_ = ko.observable('');
|
this.lastReplyAction_ = ko.observable('');
|
||||||
this.lastReplyAction = ko.computed({
|
this.lastReplyAction = ko.computed({
|
||||||
read: this.lastReplyAction_,
|
read: this.lastReplyAction_,
|
||||||
|
|
@ -205,9 +209,11 @@
|
||||||
|
|
||||||
// THREADS
|
// THREADS
|
||||||
this.viewThreads = ko.observableArray([]);
|
this.viewThreads = ko.observableArray([]);
|
||||||
this.viewThreadMessages = ko.observableArray([]);
|
|
||||||
this.viewThreads.trigger = ko.observable(false);
|
this.viewThreads.trigger = ko.observable(false);
|
||||||
|
|
||||||
|
this.viewThreadMessages = ko.observableArray([]);
|
||||||
|
this.viewThreadMessages.hash = '';
|
||||||
|
|
||||||
MessageStore.messageLastThreadUidsData.subscribe(function (oData) {
|
MessageStore.messageLastThreadUidsData.subscribe(function (oData) {
|
||||||
if (oData && oData['Uids'])
|
if (oData && oData['Uids'])
|
||||||
{
|
{
|
||||||
|
|
@ -290,14 +296,39 @@
|
||||||
}, this.viewThreadsControlForwardAllow);
|
}, this.viewThreadsControlForwardAllow);
|
||||||
|
|
||||||
this.threadListCommand = Utils.createCommand(this, function () {
|
this.threadListCommand = Utils.createCommand(this, function () {
|
||||||
var aList = [], aStatus = this.viewThreads.status();
|
|
||||||
|
var
|
||||||
|
self = this,
|
||||||
|
sFolder = this.viewFolder,
|
||||||
|
sUid = this.viewUid,
|
||||||
|
aUids = this.viewThreads(),
|
||||||
|
aStatus = this.viewThreads.status()
|
||||||
|
;
|
||||||
|
|
||||||
if (aStatus && aStatus[0])
|
if (aStatus && aStatus[0])
|
||||||
{
|
{
|
||||||
this.viewThreadMessages(aList);
|
self.viewThreadMessages([]);
|
||||||
// window.console.log(aStatus);
|
Promises.messageListSimple(sFolder, aUids).then(function (aList) {
|
||||||
|
|
||||||
|
_.each(aList, function (oItem) {
|
||||||
|
if (oItem && oItem.uid)
|
||||||
|
{
|
||||||
|
oItem.selected(sUid === oItem.uid);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
self.viewThreadMessages(aList);
|
||||||
|
|
||||||
|
}, function (iErrorCode) {
|
||||||
|
|
||||||
|
window.alert(Translator.getNotification(iErrorCode));
|
||||||
|
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}, function () {
|
}, function () {
|
||||||
return !this.messageLoadingThrottle();
|
return !this.messageLoadingThrottle() &&
|
||||||
|
!this.messageListOfThreadsLoading();
|
||||||
});
|
});
|
||||||
|
|
||||||
// PGP
|
// PGP
|
||||||
|
|
@ -675,6 +706,13 @@
|
||||||
oEvent.stopPropagation();
|
oEvent.stopPropagation();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
.on('click', '.thread-list .thread-list-message', function () {
|
||||||
|
var oMessage = ko.dataFor(this);
|
||||||
|
if (oMessage && oMessage.folderFullNameRaw && oMessage.uid)
|
||||||
|
{
|
||||||
|
self.openThreadMessage(oMessage.uid);
|
||||||
|
}
|
||||||
|
})
|
||||||
.on('click', '.attachmentsPlace .attachmentItem .attachmentNameParent', function () {
|
.on('click', '.attachmentsPlace .attachmentItem .attachmentNameParent', function () {
|
||||||
|
|
||||||
var
|
var
|
||||||
|
|
|
||||||
|
|
@ -168,6 +168,7 @@ cfg.paths.js = {
|
||||||
'vendors/ssm/ssm.min.js',
|
'vendors/ssm/ssm.min.js',
|
||||||
'vendors/jua/jua.min.js',
|
'vendors/jua/jua.min.js',
|
||||||
'vendors/buzz/buzz.min.js',
|
'vendors/buzz/buzz.min.js',
|
||||||
|
'vendors/Q/q.js',
|
||||||
'vendors/Autolinker/Autolinker.min.js',
|
'vendors/Autolinker/Autolinker.min.js',
|
||||||
'vendors/photoswipe/photoswipe.min.js',
|
'vendors/photoswipe/photoswipe.min.js',
|
||||||
'vendors/photoswipe/photoswipe-ui-default.min.js',
|
'vendors/photoswipe/photoswipe-ui-default.min.js',
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
"name": "RainLoop",
|
"name": "RainLoop",
|
||||||
"title": "RainLoop Webmail",
|
"title": "RainLoop Webmail",
|
||||||
"version": "1.8.2",
|
"version": "1.8.2",
|
||||||
"release": "284",
|
"release": "287",
|
||||||
"description": "Simple, modern & fast web-based email client",
|
"description": "Simple, modern & fast web-based email client",
|
||||||
"homepage": "http://rainloop.net",
|
"homepage": "http://rainloop.net",
|
||||||
"main": "gulpfile.js",
|
"main": "gulpfile.js",
|
||||||
|
|
|
||||||
|
|
@ -2217,6 +2217,16 @@ END;
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $sIp
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public static function ValidateIP($sIp)
|
||||||
|
{
|
||||||
|
return !empty($sIp) && $sIp === @\filter_var($sIp, FILTER_VALIDATE_IP);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return \Net_IDNA2
|
* @return \Net_IDNA2
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -154,6 +154,26 @@ class MailClient
|
||||||
return $this->oImapClient->IsLoggined();
|
return $this->oImapClient->IsLoggined();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
private function getEnvelopeOrHeadersRequestStringForSimpleList()
|
||||||
|
{
|
||||||
|
return \MailSo\Imap\Enumerations\FetchType::BuildBodyCustomHeaderRequest(array(
|
||||||
|
\MailSo\Mime\Enumerations\Header::RETURN_PATH,
|
||||||
|
\MailSo\Mime\Enumerations\Header::RECEIVED,
|
||||||
|
\MailSo\Mime\Enumerations\Header::MIME_VERSION,
|
||||||
|
\MailSo\Mime\Enumerations\Header::FROM_,
|
||||||
|
\MailSo\Mime\Enumerations\Header::TO_,
|
||||||
|
\MailSo\Mime\Enumerations\Header::CC,
|
||||||
|
\MailSo\Mime\Enumerations\Header::SENDER,
|
||||||
|
\MailSo\Mime\Enumerations\Header::REPLY_TO,
|
||||||
|
\MailSo\Mime\Enumerations\Header::DATE,
|
||||||
|
\MailSo\Mime\Enumerations\Header::SUBJECT,
|
||||||
|
\MailSo\Mime\Enumerations\Header::CONTENT_TYPE
|
||||||
|
), true);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
|
|
@ -1622,11 +1642,12 @@ class MailClient
|
||||||
* @param \MailSo\Mail\MessageCollection &$oMessageCollection
|
* @param \MailSo\Mail\MessageCollection &$oMessageCollection
|
||||||
* @param array $aRequestIndexOrUids
|
* @param array $aRequestIndexOrUids
|
||||||
* @param bool $bIndexAsUid
|
* @param bool $bIndexAsUid
|
||||||
|
* @param bool $bSimple = false
|
||||||
*
|
*
|
||||||
* @throws \MailSo\Net\Exceptions\Exception
|
* @throws \MailSo\Net\Exceptions\Exception
|
||||||
* @throws \MailSo\Imap\Exceptions\Exception
|
* @throws \MailSo\Imap\Exceptions\Exception
|
||||||
*/
|
*/
|
||||||
public function MessageListByRequestIndexOrUids(&$oMessageCollection, $aRequestIndexOrUids, $bIndexAsUid)
|
public function MessageListByRequestIndexOrUids(&$oMessageCollection, $aRequestIndexOrUids, $bIndexAsUid, $bSimple = false)
|
||||||
{
|
{
|
||||||
if (\is_array($aRequestIndexOrUids) && 0 < \count($aRequestIndexOrUids))
|
if (\is_array($aRequestIndexOrUids) && 0 < \count($aRequestIndexOrUids))
|
||||||
{
|
{
|
||||||
|
|
@ -1637,7 +1658,8 @@ class MailClient
|
||||||
\MailSo\Imap\Enumerations\FetchType::INTERNALDATE,
|
\MailSo\Imap\Enumerations\FetchType::INTERNALDATE,
|
||||||
\MailSo\Imap\Enumerations\FetchType::FLAGS,
|
\MailSo\Imap\Enumerations\FetchType::FLAGS,
|
||||||
\MailSo\Imap\Enumerations\FetchType::BODYSTRUCTURE,
|
\MailSo\Imap\Enumerations\FetchType::BODYSTRUCTURE,
|
||||||
$this->getEnvelopeOrHeadersRequestString()
|
$bSimple ? $this->getEnvelopeOrHeadersRequestStringForSimpleList() :
|
||||||
|
$this->getEnvelopeOrHeadersRequestString()
|
||||||
), \MailSo\Base\Utils::PrepearFetchSequence($aRequestIndexOrUids), $bIndexAsUid);
|
), \MailSo\Base\Utils::PrepearFetchSequence($aRequestIndexOrUids), $bIndexAsUid);
|
||||||
|
|
||||||
if (\is_array($aFetchResponse) && 0 < \count($aFetchResponse))
|
if (\is_array($aFetchResponse) && 0 < \count($aFetchResponse))
|
||||||
|
|
@ -1862,6 +1884,33 @@ class MailClient
|
||||||
return \array_map('trim', $aResult);
|
return \array_map('trim', $aResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $sFolderName
|
||||||
|
* @param array $aUids
|
||||||
|
*
|
||||||
|
* @return \MailSo\Mail\MessageCollection
|
||||||
|
*
|
||||||
|
* @throws \MailSo\Base\Exceptions\InvalidArgumentException
|
||||||
|
* @throws \MailSo\Net\Exceptions\Exception
|
||||||
|
* @throws \MailSo\Imap\Exceptions\Exception
|
||||||
|
*/
|
||||||
|
public function MessageListSimple($sFolderName, $aUids)
|
||||||
|
{
|
||||||
|
if (0 === \strlen($sFolderName) || !\MailSo\Base\Validator::NotEmptyArray($aUids))
|
||||||
|
{
|
||||||
|
throw new \MailSo\Base\Exceptions\InvalidArgumentException();
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->oImapClient->FolderExamine($sFolderName);
|
||||||
|
|
||||||
|
$oMessageCollection = \MailSo\Mail\MessageCollection::NewInstance();
|
||||||
|
$oMessageCollection->FolderName = $sFolderName;
|
||||||
|
|
||||||
|
$this->MessageListByRequestIndexOrUids($oMessageCollection, $aUids, true, true);
|
||||||
|
|
||||||
|
return $oMessageCollection->GetAsArray();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $sFolderName
|
* @param string $sFolderName
|
||||||
* @param int $iOffset = 0
|
* @param int $iOffset = 0
|
||||||
|
|
|
||||||
|
|
@ -1520,7 +1520,8 @@ class Actions
|
||||||
$aResult['AllowDropboxSocial'] = (bool) $oConfig->Get('social', 'dropbox_enable', false);
|
$aResult['AllowDropboxSocial'] = (bool) $oConfig->Get('social', 'dropbox_enable', false);
|
||||||
$aResult['DropboxApiKey'] = (string) $oConfig->Get('social', 'dropbox_api_key', '');
|
$aResult['DropboxApiKey'] = (string) $oConfig->Get('social', 'dropbox_api_key', '');
|
||||||
|
|
||||||
$aResult['SubscriptionEnabled'] = \MailSo\Base\Utils::ValidateDomain($aResult['AdminDomain']);
|
$aResult['SubscriptionEnabled'] = \MailSo\Base\Utils::ValidateDomain($aResult['AdminDomain']) ||
|
||||||
|
\MailSo\Base\Utils::ValidateIP($aResult['AdminDomain']);
|
||||||
|
|
||||||
$aResult['WeakPassword'] = $oConfig->ValidatePassword('12345');
|
$aResult['WeakPassword'] = $oConfig->ValidatePassword('12345');
|
||||||
$aResult['CoreAccess'] = $this->rainLoopCoreAccess();
|
$aResult['CoreAccess'] = $this->rainLoopCoreAccess();
|
||||||
|
|
@ -5478,6 +5479,40 @@ class Actions
|
||||||
return $this->DefaultResponse(__FUNCTION__, $oMessageList);
|
return $this->DefaultResponse(__FUNCTION__, $oMessageList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
*
|
||||||
|
* @throws \MailSo\Base\Exceptions\Exception
|
||||||
|
*/
|
||||||
|
public function DoMessageListSimple()
|
||||||
|
{
|
||||||
|
// \sleep(2);
|
||||||
|
// throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::CantGetMessageList);
|
||||||
|
|
||||||
|
$sFolder = $this->GetActionParam('Folder', '');
|
||||||
|
$aUids = $this->GetActionParam('Uids', null);
|
||||||
|
|
||||||
|
if (0 === \strlen($sFolder) || !\is_array($aUids))
|
||||||
|
{
|
||||||
|
throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::InvalidInputArgument);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->initMailClientConnection();
|
||||||
|
|
||||||
|
$aMessageList = array();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$aMessageList = $this->MailClient()->MessageListSimple($sFolder, $aUids);
|
||||||
|
}
|
||||||
|
catch (\Exception $oException)
|
||||||
|
{
|
||||||
|
throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::CantGetMessageList, $oException);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->DefaultResponse(__FUNCTION__, $aMessageList);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param \RainLoop\Model\Account $oAccount
|
* @param \RainLoop\Model\Account $oAccount
|
||||||
* @param bool $bWithDraftInfo = true
|
* @param bool $bWithDraftInfo = true
|
||||||
|
|
|
||||||
|
|
@ -186,26 +186,30 @@
|
||||||
<a class="btn btn-thin" data-tooltip-placement="bottom" data-bind="command: threadForwardCommand">
|
<a class="btn btn-thin" data-tooltip-placement="bottom" data-bind="command: threadForwardCommand">
|
||||||
<i class="icon-left-middle"></i>
|
<i class="icon-left-middle"></i>
|
||||||
</a>
|
</a>
|
||||||
<a class="btn btn-thin btn-dark-disabled-border dropdown-toggle" id="thread-list-view-dropdown-id" data-toggle="dropdown"
|
<a class="btn btn-dark-disabled-border dropdown-toggle" id="thread-list-view-dropdown-id" data-toggle="dropdown"
|
||||||
href="#" tabindex="-1" data-tooltip-placement="bottom">
|
href="#" tabindex="-1" data-tooltip-placement="bottom" data-bind="command: threadListCommand">
|
||||||
<!--href="#" tabindex="-1" data-tooltip-placement="bottom" data-bind="command: threadListCommand">-->
|
<i class="icon-list"
|
||||||
<i class="icon-list"></i>
|
data-bind="css: {'icon-list': !messageListOfThreadsLoading(), 'icon-spinner animated': messageListOfThreadsLoading()}"></i>
|
||||||
<!--<b data-bind="text: viewThreadsControlDesc"></b>-->
|
|
||||||
</a>
|
</a>
|
||||||
<a class="btn btn-thin" data-tooltip-placement="bottom" data-bind="command: threadBackCommand">
|
<a class="btn btn-thin" data-tooltip-placement="bottom" data-bind="command: threadBackCommand">
|
||||||
<i class="icon-right-middle"></i>
|
<i class="icon-right-middle"></i>
|
||||||
</a>
|
</a>
|
||||||
<!-- <ul class="dropdown-menu g-ui-menu" role="menu" aria-labelledby="thread-list-view-dropdown-id"
|
<ul class="dropdown-menu g-ui-menu thread-list" role="menu" aria-labelledby="thread-list-view-dropdown-id"
|
||||||
style="min-width: 400px; max-width: 400px; width: 400px;">
|
style="min-width: 400px; max-width: 400px; width: 400px;">
|
||||||
<li class="e-item" role="presentation">
|
<div data-bind="visible: messageListOfThreadsLoading" style="text-align: center; padding: 10px">
|
||||||
<a class="e-link menuitem" href="#" tabindex="-1">
|
<i class="icon-spinner animated" />
|
||||||
<span class="thread-from">test@rainloop.de</span>
|
</div >
|
||||||
<span class="thread-date">05/20</span>
|
<div data-bind="foreach: viewThreadMessages, visible: !messageListOfThreadsLoading()">
|
||||||
<br />
|
<li class="e-item thread-list-message" role="presentation" data-bind="css: {'selected': selected}">
|
||||||
<span class="thread-subject">Re: thread</span>
|
<a class="e-link menuitem" href="#" tabindex="-1">
|
||||||
</a>
|
<span class="thread-from" data-bind="text: senderEmailsString"></span>
|
||||||
</li>
|
<span class="hread-date pull-right" data-moment-format="SHORT" data-bind="moment: dateTimeStampInUTC"></span>
|
||||||
</ul>-->
|
<br />
|
||||||
|
<span class="thread-subject" data-bind="text: subject"></span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</div>
|
||||||
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</nobr>
|
</nobr>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@
|
||||||
<!-- ko foreach: accounts -->
|
<!-- ko foreach: accounts -->
|
||||||
<li class="e-item" role="presentation">
|
<li class="e-item" role="presentation">
|
||||||
<a class="e-link menuitem account-item" href="#" data-bind="click: $root.accountClick,
|
<a class="e-link menuitem account-item" href="#" data-bind="click: $root.accountClick,
|
||||||
attr: {'href': changeAccountLink()}, css: {current: $root.accountEmail() === email}">
|
attr: {'href': changeAccountLink()}, css: {'current': $root.accountEmail() === email}">
|
||||||
<!-- <b class="pull-right counter" data-bind="visible: 0 < count()">
|
<!-- <b class="pull-right counter" data-bind="visible: 0 < count()">
|
||||||
<span data-bind="text: count, visible: 100 > count()"></span>
|
<span data-bind="text: count, visible: 100 > count()"></span>
|
||||||
<span data-bind="visible: 99 < count()">99+</span>
|
<span data-bind="visible: 99 < count()">99+</span>
|
||||||
|
|
|
||||||
1
vendors/Q/.coverignore
vendored
Normal file
1
vendors/Q/.coverignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
spec/
|
||||||
14
vendors/Q/.gitignore
vendored
Normal file
14
vendors/Q/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
node_modules
|
||||||
|
npm-debug.log
|
||||||
|
CHANGES.html
|
||||||
|
README.html
|
||||||
|
.tmp
|
||||||
|
q.min.js
|
||||||
|
|
||||||
|
.coverage_data/
|
||||||
|
.coverage_debug/
|
||||||
|
cover_html/
|
||||||
|
|
||||||
|
# IntelliJ IDEA project files
|
||||||
|
.idea
|
||||||
|
*.iml
|
||||||
27
vendors/Q/.jshintrc
vendored
Normal file
27
vendors/Q/.jshintrc
vendored
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
{
|
||||||
|
"browser": true,
|
||||||
|
"node": true,
|
||||||
|
|
||||||
|
"curly": true,
|
||||||
|
"eqeqeq": true,
|
||||||
|
"es3": true,
|
||||||
|
"newcap": false,
|
||||||
|
"noarg": true,
|
||||||
|
"nonew": true,
|
||||||
|
"quotmark": "double",
|
||||||
|
"strict": true,
|
||||||
|
"trailing": true,
|
||||||
|
"undef": true,
|
||||||
|
"unused": true,
|
||||||
|
|
||||||
|
"globals": {
|
||||||
|
"self": false,
|
||||||
|
"bootstrap": false,
|
||||||
|
"cajaVM": false,
|
||||||
|
"define": false,
|
||||||
|
"ReturnValue": false,
|
||||||
|
"ses": false,
|
||||||
|
"setImmediate": false,
|
||||||
|
"Q": true
|
||||||
|
}
|
||||||
|
}
|
||||||
2
vendors/Q/.mailmap
vendored
Normal file
2
vendors/Q/.mailmap
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
Domenic Denicola <domenic@domenicdenicola.com>
|
||||||
|
Kris Kowal <kris.kowal@cixar.com>
|
||||||
5
vendors/Q/.travis.yml
vendored
Normal file
5
vendors/Q/.travis.yml
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
language: node_js
|
||||||
|
node_js:
|
||||||
|
- "0.10"
|
||||||
|
script:
|
||||||
|
npm run lint && npm test
|
||||||
762
vendors/Q/CHANGES.md
vendored
Normal file
762
vendors/Q/CHANGES.md
vendored
Normal file
|
|
@ -0,0 +1,762 @@
|
||||||
|
<!-- vim:ts=4:sts=4:sw=4:et:tw=70 -->
|
||||||
|
|
||||||
|
## 1.1.2
|
||||||
|
|
||||||
|
- Removed extraneous files from the npm package by using the "files"
|
||||||
|
whitelist in package.json instead of the .npmignore blacklist.
|
||||||
|
(@anton-rudeshko)
|
||||||
|
|
||||||
|
## 1.1.1
|
||||||
|
|
||||||
|
- Fix a pair of regressions in bootstrapping, one which precluded
|
||||||
|
WebWorker support, and another that precluded support in
|
||||||
|
``<script>`` usage outright. #607
|
||||||
|
|
||||||
|
## 1.1.0
|
||||||
|
|
||||||
|
- Adds support for enabling long stack traces in node.js by setting
|
||||||
|
environment variable `Q_DEBUG=1`.
|
||||||
|
- Introduces the `tap` method to promises, which will see a value
|
||||||
|
pass through without alteration.
|
||||||
|
- Use instanceof to recognize own promise instances as opposed to
|
||||||
|
thenables.
|
||||||
|
- Construct timeout errors with `code === ETIMEDOUT` (Kornel Lesiński)
|
||||||
|
- More descriminant CommonJS module environment detection.
|
||||||
|
- Dropped continuous integration for Node.js 0.6 and 0.8 because of
|
||||||
|
changes to npm that preclude the use of new `^` version predicate
|
||||||
|
operator in any transitive dependency.
|
||||||
|
- Users can now override `Q.nextTick`.
|
||||||
|
|
||||||
|
## 1.0.1
|
||||||
|
|
||||||
|
- Adds support for `Q.Promise`, which implements common usage of the
|
||||||
|
ES6 `Promise` constructor and its methods. `Promise` does not have
|
||||||
|
a valid promise constructor and a proper implementation awaits
|
||||||
|
version 2 of Q.
|
||||||
|
- Removes the console stopgap for a promise inspector. This no longer
|
||||||
|
works with any degree of reliability.
|
||||||
|
- Fixes support for content security policies that forbid eval. Now
|
||||||
|
using the `StopIteration` global to distinguish SpiderMonkey
|
||||||
|
generators from ES6 generators, assuming that they will never
|
||||||
|
coexist.
|
||||||
|
|
||||||
|
## 1.0.0
|
||||||
|
|
||||||
|
:cake: This is all but a re-release of version 0.9, which has settled
|
||||||
|
into a gentle maintenance mode and rightly deserves an official 1.0.
|
||||||
|
An ambitious 2.0 release is already around the corner, but 0.9/1.0
|
||||||
|
have been distributed far and wide and demand long term support.
|
||||||
|
|
||||||
|
- Q will now attempt to post a debug message in browsers regardless
|
||||||
|
of whether window.Touch is defined. Chrome at least now has this
|
||||||
|
property regardless of whether touch is supported by the underlying
|
||||||
|
hardware.
|
||||||
|
- Remove deprecation warning from `promise.valueOf`. The function is
|
||||||
|
called by the browser in various ways so there is no way to
|
||||||
|
distinguish usage that should be migrated from usage that cannot be
|
||||||
|
altered.
|
||||||
|
|
||||||
|
## 0.9.7
|
||||||
|
|
||||||
|
- :warning: `q.min.js` is no longer checked-in. It is however still
|
||||||
|
created by Grunt and NPM.
|
||||||
|
- Fixes a bug that inhibited `Q.async` with implementations of the new
|
||||||
|
ES6 generators.
|
||||||
|
- Fixes a bug with `nextTick` affecting Safari 6.0.5 the first time a
|
||||||
|
page loads when an `iframe` is involved.
|
||||||
|
- Introduces `passByCopy`, `join`, and `race`.
|
||||||
|
- Shows stack traces or error messages on the console, instead of
|
||||||
|
`Error` objects.
|
||||||
|
- Elimintates wrapper methods for improved performance.
|
||||||
|
- `Q.all` now propagates progress notifications of the form you might
|
||||||
|
expect of ES6 iterations, `{value, index}` where the `value` is the
|
||||||
|
progress notification from the promise at `index`.
|
||||||
|
|
||||||
|
## 0.9.6
|
||||||
|
|
||||||
|
- Fixes a bug in recognizing the difference between compatible Q
|
||||||
|
promises, and Q promises from before the implementation of "inspect".
|
||||||
|
The latter are now coerced.
|
||||||
|
- Fixes an infinite asynchronous coercion cycle introduced by former
|
||||||
|
solution, in two independently sufficient ways. 1.) All promises
|
||||||
|
returned by makePromise now implement "inspect", albeit a default
|
||||||
|
that reports that the promise has an "unknown" state. 2.) The
|
||||||
|
implementation of "then/when" is now in "then" instead of "when", so
|
||||||
|
that the responsibility to "coerce" the given promise rests solely in
|
||||||
|
the "when" method and the "then" method may assume that "this" is a
|
||||||
|
promise of the right type.
|
||||||
|
- Refactors `nextTick` to use an unrolled microtask within Q regardless
|
||||||
|
of how new ticks a requested. #316 @rkatic
|
||||||
|
|
||||||
|
## 0.9.5
|
||||||
|
|
||||||
|
- Introduces `inspect` for getting the state of a promise as
|
||||||
|
`{state: "fulfilled" | "rejected" | "pending", value | reason}`.
|
||||||
|
- Introduces `allSettled` which produces an array of promises states
|
||||||
|
for the input promises once they have all "settled". This is in
|
||||||
|
accordance with a discussion on Promises/A+ that "settled" refers to
|
||||||
|
a promise that is "fulfilled" or "rejected". "resolved" refers to a
|
||||||
|
deferred promise that has been "resolved" to another promise,
|
||||||
|
"sealing its fate" to the fate of the successor promise.
|
||||||
|
- Long stack traces are now off by default. Set `Q.longStackSupport`
|
||||||
|
to true to enable long stack traces.
|
||||||
|
- Long stack traces can now follow the entire asynchronous history of a
|
||||||
|
promise, not just a single jump.
|
||||||
|
- Introduces `spawn` for an immediately invoked asychronous generator.
|
||||||
|
@jlongster
|
||||||
|
- Support for *experimental* synonyms `mapply`, `mcall`, `nmapply`,
|
||||||
|
`nmcall` for method invocation.
|
||||||
|
|
||||||
|
## 0.9.4
|
||||||
|
|
||||||
|
- `isPromise` and `isPromiseAlike` now always returns a boolean
|
||||||
|
(even for falsy values). #284 @lfac-pt
|
||||||
|
- Support for ES6 Generators in `async` #288 @andywingo
|
||||||
|
- Clear duplicate promise rejections from dispatch methods #238 @SLaks
|
||||||
|
- Unhandled rejection API #296 @domenic
|
||||||
|
`stopUnhandledRejectionTracking`, `getUnhandledReasons`,
|
||||||
|
`resetUnhandledRejections`.
|
||||||
|
|
||||||
|
## 0.9.3
|
||||||
|
|
||||||
|
- Add the ability to give `Q.timeout`'s errors a custom error message. #270
|
||||||
|
@jgrenon
|
||||||
|
- Fix Q's call-stack busting behavior in Node.js 0.10, by switching from
|
||||||
|
`process.nextTick` to `setImmediate`. #254 #259
|
||||||
|
- Fix Q's behavior when used with the Mocha test runner in the browser, since
|
||||||
|
Mocha introduces a fake `process` global without a `nextTick` property. #267
|
||||||
|
- Fix some, but not all, cases wherein Q would give false positives in its
|
||||||
|
unhandled rejection detection (#252). A fix for other cases (#238) is
|
||||||
|
hopefully coming soon.
|
||||||
|
- Made `Q.promise` throw early if given a non-function.
|
||||||
|
|
||||||
|
## 0.9.2
|
||||||
|
|
||||||
|
- Pass through progress notifications when using `timeout`. #229 @omares
|
||||||
|
- Pass through progress notifications when using `delay`.
|
||||||
|
- Fix `nbind` to actually bind the `thisArg`. #232 @davidpadbury
|
||||||
|
|
||||||
|
## 0.9.1
|
||||||
|
|
||||||
|
- Made the AMD detection compatible with the RequireJS optimizer's `namespace`
|
||||||
|
option. #225 @terinjokes
|
||||||
|
- Fix side effects from `valueOf`, and thus from `isFulfilled`, `isRejected`,
|
||||||
|
and `isPending`. #226 @benjamn
|
||||||
|
|
||||||
|
## 0.9.0
|
||||||
|
|
||||||
|
This release removes many layers of deprecated methods and brings Q closer to
|
||||||
|
alignment with Mark Miller’s TC39 [strawman][] for concurrency. At the same
|
||||||
|
time, it fixes many bugs and adds a few features around error handling. Finally,
|
||||||
|
it comes with an updated and comprehensive [API Reference][].
|
||||||
|
|
||||||
|
[strawman]: http://wiki.ecmascript.org/doku.php?id=strawman:concurrency
|
||||||
|
[API Reference]: https://github.com/kriskowal/q/wiki/API-Reference
|
||||||
|
|
||||||
|
### API Cleanup
|
||||||
|
|
||||||
|
The following deprecated or undocumented methods have been removed.
|
||||||
|
Their replacements are listed here:
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>0.8.x method</th>
|
||||||
|
<th>0.9 replacement</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td><code>Q.ref</code></td>
|
||||||
|
<td><code>Q</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>call</code>, <code>apply</code>, <code>bind</code> (*)</td>
|
||||||
|
<td><code>fcall</code>/<code>invoke</code>, <code>fapply</code>/<code>post</code>, <code>fbind</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>ncall</code>, <code>napply</code> (*)</td>
|
||||||
|
<td><code>nfcall</code>/<code>ninvoke</code>, <code>nfapply</code>/<code>npost</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>end</code></td>
|
||||||
|
<td><code>done</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>put</code></td>
|
||||||
|
<td><code>set</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>node</code></td>
|
||||||
|
<td><code>nbind</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>nend</code></td>
|
||||||
|
<td><code>nodeify</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>isResolved</code></td>
|
||||||
|
<td><code>isPending</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>deferred.node</code></td>
|
||||||
|
<td><code>deferred.makeNodeResolver</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>Method</code>, <code>sender</code></td>
|
||||||
|
<td><code>dispatcher</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>send</code></td>
|
||||||
|
<td><code>dispatch</code></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>view</code>, <code>viewInfo</code></td>
|
||||||
|
<td>(none)</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
|
||||||
|
(*) Use of ``thisp`` is discouraged. For calling methods, use ``post`` or
|
||||||
|
``invoke``.
|
||||||
|
|
||||||
|
### Alignment with the Concurrency Strawman
|
||||||
|
|
||||||
|
- Q now exports a `Q(value)` function, an alias for `resolve`.
|
||||||
|
`Q.call`, `Q.apply`, and `Q.bind` were removed to make room for the
|
||||||
|
same methods on the function prototype.
|
||||||
|
- `invoke` has been aliased to `send` in all its forms.
|
||||||
|
- `post` with no method name acts like `fapply`.
|
||||||
|
|
||||||
|
### Error Handling
|
||||||
|
|
||||||
|
- Long stack traces can be turned off by setting `Q.stackJumpLimit` to zero.
|
||||||
|
In the future, this property will be used to fine tune how many stack jumps
|
||||||
|
are retained in long stack traces; for now, anything nonzero is treated as
|
||||||
|
one (since Q only tracks one stack jump at the moment, see #144). #168
|
||||||
|
- In Node.js, if there are unhandled rejections when the process exits, they
|
||||||
|
are output to the console. #115
|
||||||
|
|
||||||
|
### Other
|
||||||
|
|
||||||
|
- `delete` and `set` (née `put`) no longer have a fulfillment value.
|
||||||
|
- Q promises are no longer frozen, which
|
||||||
|
[helps with performance](http://code.google.com/p/v8/issues/detail?id=1858).
|
||||||
|
- `thenReject` is now included, as a counterpart to `thenResolve`.
|
||||||
|
- The included browser `nextTick` shim is now faster. #195 @rkatic.
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
- Q now works in Internet Explorer 10. #186 @ForbesLindesay
|
||||||
|
- `fbind` no longer hard-binds the returned function's `this` to `undefined`.
|
||||||
|
#202
|
||||||
|
- `Q.reject` no longer leaks memory. #148
|
||||||
|
- `npost` with no arguments now works. #207
|
||||||
|
- `allResolved` now works with non-Q promises ("thenables"). #179
|
||||||
|
- `keys` behavior is now correct even in browsers without native
|
||||||
|
`Object.keys`. #192 @rkatic
|
||||||
|
- `isRejected` and the `exception` property now work correctly if the
|
||||||
|
rejection reason is falsy. #198
|
||||||
|
|
||||||
|
### Internals and Advanced
|
||||||
|
|
||||||
|
- The internal interface for a promise now uses
|
||||||
|
`dispatchPromise(resolve, op, operands)` instead of `sendPromise(op,
|
||||||
|
resolve, ...operands)`, which reduces the cases where Q needs to do
|
||||||
|
argument slicing.
|
||||||
|
- The internal protocol uses different operands. "put" is now "set".
|
||||||
|
"del" is now "delete". "view" and "viewInfo" have been removed.
|
||||||
|
- `Q.fulfill` has been added. It is distinct from `Q.resolve` in that
|
||||||
|
it does not pass promises through, nor coerces promises from other
|
||||||
|
systems. The promise becomes the fulfillment value. This is only
|
||||||
|
recommended for use when trying to fulfill a promise with an object that has
|
||||||
|
a `then` function that is at the same time not a promise.
|
||||||
|
|
||||||
|
## 0.8.12
|
||||||
|
- Treat foreign promises as unresolved in `Q.isFulfilled`; this lets `Q.all`
|
||||||
|
work on arrays containing foreign promises. #154
|
||||||
|
- Fix minor incompliances with the [Promises/A+ spec][] and [test suite][]. #157
|
||||||
|
#158
|
||||||
|
|
||||||
|
[Promises/A+ spec]: http://promises-aplus.github.com/promises-spec/
|
||||||
|
[test suite]: https://github.com/promises-aplus/promises-tests
|
||||||
|
|
||||||
|
## 0.8.11
|
||||||
|
|
||||||
|
- Added ``nfcall``, ``nfapply``, and ``nfbind`` as ``thisp``-less versions of
|
||||||
|
``ncall``, ``napply``, and ``nbind``. The latter are now deprecated. #142
|
||||||
|
- Long stack traces no longer cause linearly-growing memory usage when chaining
|
||||||
|
promises together. #111
|
||||||
|
- Inspecting ``error.stack`` in a rejection handler will now give a long stack
|
||||||
|
trace. #103
|
||||||
|
- Fixed ``Q.timeout`` to clear its timeout handle when the promise is rejected;
|
||||||
|
previously, it kept the event loop alive until the timeout period expired.
|
||||||
|
#145 @dfilatov
|
||||||
|
- Added `q/queue` module, which exports an infinite promise queue
|
||||||
|
constructor.
|
||||||
|
|
||||||
|
## 0.8.10
|
||||||
|
|
||||||
|
- Added ``done`` as a replacement for ``end``, taking the usual fulfillment,
|
||||||
|
rejection, and progress handlers. It's essentially equivalent to
|
||||||
|
``then(f, r, p).end()``.
|
||||||
|
- Added ``Q.onerror``, a settable error trap that you can use to get full stack
|
||||||
|
traces for uncaught errors. #94
|
||||||
|
- Added ``thenResolve`` as a shortcut for returning a constant value once a
|
||||||
|
promise is fulfilled. #108 @ForbesLindesay
|
||||||
|
- Various tweaks to progress notification, including propagation and
|
||||||
|
transformation of progress values and only forwarding a single progress
|
||||||
|
object.
|
||||||
|
- Renamed ``nend`` to ``nodeify``. It no longer returns an always-fulfilled
|
||||||
|
promise when a Node callback is passed.
|
||||||
|
- ``deferred.resolve`` and ``deferred.reject`` no longer (sometimes) return
|
||||||
|
``deferred.promise``.
|
||||||
|
- Fixed stack traces getting mangled if they hit ``end`` twice. #116 #121 @ef4
|
||||||
|
- Fixed ``ninvoke`` and ``npost`` to work on promises for objects with Node
|
||||||
|
methods. #134
|
||||||
|
- Fixed accidental coercion of objects with nontrivial ``valueOf`` methods,
|
||||||
|
like ``Date``s, by the promise's ``valueOf`` method. #135
|
||||||
|
- Fixed ``spread`` not calling the passed rejection handler if given a rejected
|
||||||
|
promise.
|
||||||
|
|
||||||
|
## 0.8.9
|
||||||
|
|
||||||
|
- Added ``nend``
|
||||||
|
- Added preliminary progress notification support, via
|
||||||
|
``promise.then(onFulfilled, onRejected, onProgress)``,
|
||||||
|
``promise.progress(onProgress)``, and ``deferred.notify(...progressData)``.
|
||||||
|
- Made ``put`` and ``del`` return the object acted upon for easier chaining.
|
||||||
|
#84
|
||||||
|
- Fixed coercion cycles with cooperating promises. #106
|
||||||
|
|
||||||
|
## 0.8.7
|
||||||
|
|
||||||
|
- Support [Montage Require](http://github.com/kriskowal/mr)
|
||||||
|
|
||||||
|
## 0.8.6
|
||||||
|
|
||||||
|
- Fixed ``npost`` and ``ninvoke`` to pass the correct ``thisp``. #74
|
||||||
|
- Fixed various cases involving unorthodox rejection reasons. #73 #90
|
||||||
|
@ef4
|
||||||
|
- Fixed double-resolving of misbehaved custom promises. #75
|
||||||
|
- Sped up ``Q.all`` for arrays contain already-resolved promises or scalar
|
||||||
|
values. @ForbesLindesay
|
||||||
|
- Made stack trace filtering work when concatenating assets. #93 @ef4
|
||||||
|
- Added warnings for deprecated methods. @ForbesLindesay
|
||||||
|
- Added ``.npmignore`` file so that dependent packages get a slimmer
|
||||||
|
``node_modules`` directory.
|
||||||
|
|
||||||
|
## 0.8.5
|
||||||
|
|
||||||
|
- Added preliminary support for long traces (@domenic)
|
||||||
|
- Added ``fapply``, ``fcall``, ``fbind`` for non-thisp
|
||||||
|
promised function calls.
|
||||||
|
- Added ``return`` for async generators, where generators
|
||||||
|
are implemented.
|
||||||
|
- Rejected promises now have an "exception" property. If an object
|
||||||
|
isRejected(object), then object.valueOf().exception will
|
||||||
|
be the wrapped error.
|
||||||
|
- Added Jasmine specifications
|
||||||
|
- Support Internet Explorers 7–9 (with multiple bug fixes @domenic)
|
||||||
|
- Support Firefox 12
|
||||||
|
- Support Safari 5.1.5
|
||||||
|
- Support Chrome 18
|
||||||
|
|
||||||
|
## 0.8.4
|
||||||
|
|
||||||
|
- WARNING: ``promise.timeout`` is now rejected with an ``Error`` object
|
||||||
|
and the message now includes the duration of the timeout in
|
||||||
|
miliseconds. This doesn't constitute (in my opinion) a
|
||||||
|
backward-incompatibility since it is a change of an undocumented and
|
||||||
|
unspecified public behavior, but if you happened to depend on the
|
||||||
|
exception being a string, you will need to revise your code.
|
||||||
|
- Added ``deferred.makeNodeResolver()`` to replace the more cryptic
|
||||||
|
``deferred.node()`` method.
|
||||||
|
- Added experimental ``Q.promise(maker(resolve, reject))`` to make a
|
||||||
|
promise inside a callback, such that thrown exceptions in the
|
||||||
|
callback are converted and the resolver and rejecter are arguments.
|
||||||
|
This is a shorthand for making a deferred directly and inspired by
|
||||||
|
@gozala’s stream constructor pattern and the Microsoft Windows Metro
|
||||||
|
Promise constructor interface.
|
||||||
|
- Added experimental ``Q.begin()`` that is intended to kick off chains
|
||||||
|
of ``.then`` so that each of these can be reordered without having to
|
||||||
|
edit the new and former first step.
|
||||||
|
|
||||||
|
## 0.8.3
|
||||||
|
|
||||||
|
- Added ``isFulfilled``, ``isRejected``, and ``isResolved``
|
||||||
|
to the promise prototype.
|
||||||
|
- Added ``allResolved`` for waiting for every promise to either be
|
||||||
|
fulfilled or rejected, without propagating an error. @utvara #53
|
||||||
|
- Added ``Q.bind`` as a method to transform functions that
|
||||||
|
return and throw into promise-returning functions. See
|
||||||
|
[an example](https://gist.github.com/1782808). @domenic
|
||||||
|
- Renamed ``node`` export to ``nbind``, and added ``napply`` to
|
||||||
|
complete the set. ``node`` remains as deprecated. @domenic #58
|
||||||
|
- Renamed ``Method`` export to ``sender``. ``Method``
|
||||||
|
remains as deprecated and will be removed in the next
|
||||||
|
major version since I expect it has very little usage.
|
||||||
|
- Added browser console message indicating a live list of
|
||||||
|
unhandled errors.
|
||||||
|
- Added support for ``msSetImmediate`` (IE10) or ``setImmediate``
|
||||||
|
(available via [polyfill](https://github.com/NobleJS/setImmediate))
|
||||||
|
as a browser-side ``nextTick`` implementation. #44 #50 #59
|
||||||
|
- Stopped using the event-queue dependency, which was in place for
|
||||||
|
Narwhal support: now directly using ``process.nextTick``.
|
||||||
|
- WARNING: EXPERIMENTAL: added ``finally`` alias for ``fin``, ``catch``
|
||||||
|
alias for ``fail``, ``try`` alias for ``call``, and ``delete`` alias
|
||||||
|
for ``del``. These properties are enquoted in the library for
|
||||||
|
cross-browser compatibility, but may be used as property names in
|
||||||
|
modern engines.
|
||||||
|
|
||||||
|
## 0.8.2
|
||||||
|
|
||||||
|
- Deprecated ``ref`` in favor of ``resolve`` as recommended by
|
||||||
|
@domenic.
|
||||||
|
- Update event-queue dependency.
|
||||||
|
|
||||||
|
## 0.8.1
|
||||||
|
|
||||||
|
- Fixed Opera bug. #35 @cadorn
|
||||||
|
- Fixed ``Q.all([])`` #32 @domenic
|
||||||
|
|
||||||
|
## 0.8.0
|
||||||
|
|
||||||
|
- WARNING: ``enqueue`` removed. Use ``nextTick`` instead.
|
||||||
|
This is more consistent with NodeJS and (subjectively)
|
||||||
|
more explicit and intuitive.
|
||||||
|
- WARNING: ``def`` removed. Use ``master`` instead. The
|
||||||
|
term ``def`` was too confusing to new users.
|
||||||
|
- WARNING: ``spy`` removed in favor of ``fin``.
|
||||||
|
- WARNING: ``wait`` removed. Do ``all(args).get(0)`` instead.
|
||||||
|
- WARNING: ``join`` removed. Do ``all(args).spread(callback)`` instead.
|
||||||
|
- WARNING: Removed the ``Q`` function module.exports alias
|
||||||
|
for ``Q.ref``. It conflicts with ``Q.apply`` in weird
|
||||||
|
ways, making it uncallable.
|
||||||
|
- Revised ``delay`` so that it accepts both ``(value,
|
||||||
|
timeout)`` and ``(timeout)`` variations based on
|
||||||
|
arguments length.
|
||||||
|
- Added ``ref().spread(cb(...args))``, a variant of
|
||||||
|
``then`` that spreads an array across multiple arguments.
|
||||||
|
Useful with ``all()``.
|
||||||
|
- Added ``defer().node()`` Node callback generator. The
|
||||||
|
callback accepts ``(error, value)`` or ``(error,
|
||||||
|
...values)``. For multiple value arguments, the
|
||||||
|
fulfillment value is an array, useful in conjunction with
|
||||||
|
``spread``.
|
||||||
|
- Added ``node`` and ``ncall``, both with the signature
|
||||||
|
``(fun, thisp_opt, ...args)``. The former is a decorator
|
||||||
|
and the latter calls immediately. ``node`` optional
|
||||||
|
binds and partially applies. ``ncall`` can bind and pass
|
||||||
|
arguments.
|
||||||
|
|
||||||
|
## 0.7.2
|
||||||
|
|
||||||
|
- Fixed thenable promise assimilation.
|
||||||
|
|
||||||
|
## 0.7.1
|
||||||
|
|
||||||
|
- Stopped shimming ``Array.prototype.reduce``. The
|
||||||
|
enumerable property has bad side-effects. Libraries that
|
||||||
|
depend on this (for example, QQ) will need to be revised.
|
||||||
|
|
||||||
|
## 0.7.0 - BACKWARD INCOMPATIBILITY
|
||||||
|
|
||||||
|
- WARNING: Removed ``report`` and ``asap``
|
||||||
|
- WARNING: The ``callback`` argument of the ``fin``
|
||||||
|
function no longer receives any arguments. Thus, it can
|
||||||
|
be used to call functions that should not receive
|
||||||
|
arguments on resolution. Use ``when``, ``then``, or
|
||||||
|
``fail`` if you need a value.
|
||||||
|
- IMPORTANT: Fixed a bug in the use of ``MessageChannel``
|
||||||
|
for ``nextTick``.
|
||||||
|
- Renamed ``enqueue`` to ``nextTick``.
|
||||||
|
- Added experimental ``view`` and ``viewInfo`` for creating
|
||||||
|
views of promises either when or before they're
|
||||||
|
fulfilled.
|
||||||
|
- Shims are now externally applied so subsequent scripts or
|
||||||
|
dependees can use them.
|
||||||
|
- Improved minification results.
|
||||||
|
- Improved readability.
|
||||||
|
|
||||||
|
## 0.6.0 - BACKWARD INCOMPATIBILITY
|
||||||
|
|
||||||
|
- WARNING: In practice, the implementation of ``spy`` and
|
||||||
|
the name ``fin`` were useful. I've removed the old
|
||||||
|
``fin`` implementation and renamed/aliased ``spy``.
|
||||||
|
- The "q" module now exports its ``ref`` function as a "Q"
|
||||||
|
constructor, with module systems that support exports
|
||||||
|
assignment including NodeJS, RequireJS, and when used as
|
||||||
|
a ``<script>`` tag. Notably, strictly compliant CommonJS
|
||||||
|
does not support this, but UncommonJS does.
|
||||||
|
- Added ``async`` decorator for generators that use yield
|
||||||
|
to "trampoline" promises. In engines that support
|
||||||
|
generators (SpiderMonkey), this will greatly reduce the
|
||||||
|
need for nested callbacks.
|
||||||
|
- Made ``when`` chainable.
|
||||||
|
- Made ``all`` chainable.
|
||||||
|
|
||||||
|
## 0.5.3
|
||||||
|
|
||||||
|
- Added ``all`` and refactored ``join`` and ``wait`` to use
|
||||||
|
it. All of these will now reject at the earliest
|
||||||
|
rejection.
|
||||||
|
|
||||||
|
## 0.5.2
|
||||||
|
|
||||||
|
- Minor improvement to ``spy``; now waits for resolution of
|
||||||
|
callback promise.
|
||||||
|
|
||||||
|
## 0.5.1
|
||||||
|
|
||||||
|
- Made most Q API methods chainable on promise objects, and
|
||||||
|
turned the previous promise-methods of ``join``,
|
||||||
|
``wait``, and ``report`` into Q API methods.
|
||||||
|
- Added ``apply`` and ``call`` to the Q API, and ``apply``
|
||||||
|
as a promise handler.
|
||||||
|
- Added ``fail``, ``fin``, and ``spy`` to Q and the promise
|
||||||
|
prototype for convenience when observing rejection,
|
||||||
|
fulfillment and rejection, or just observing without
|
||||||
|
affecting the resolution.
|
||||||
|
- Renamed ``def`` (although ``def`` remains shimmed until
|
||||||
|
the next major release) to ``master``.
|
||||||
|
- Switched to using ``MessageChannel`` for next tick task
|
||||||
|
enqueue in browsers that support it.
|
||||||
|
|
||||||
|
## 0.5.0 - MINOR BACKWARD INCOMPATIBILITY
|
||||||
|
|
||||||
|
- Exceptions are no longer reported when consumed.
|
||||||
|
- Removed ``error`` from the API. Since exceptions are
|
||||||
|
getting consumed, throwing them in an errback causes the
|
||||||
|
exception to silently disappear. Use ``end``.
|
||||||
|
- Added ``end`` as both an API method and a promise-chain
|
||||||
|
ending method. It causes propagated rejections to be
|
||||||
|
thrown, which allows Node to write stack traces and
|
||||||
|
emit ``uncaughtException`` events, and browsers to
|
||||||
|
likewise emit ``onerror`` and log to the console.
|
||||||
|
- Added ``join`` and ``wait`` as promise chain functions,
|
||||||
|
so you can wait for variadic promises, returning your own
|
||||||
|
promise back, or join variadic promises, resolving with a
|
||||||
|
callback that receives variadic fulfillment values.
|
||||||
|
|
||||||
|
## 0.4.4
|
||||||
|
|
||||||
|
- ``end`` no longer returns a promise. It is the end of the
|
||||||
|
promise chain.
|
||||||
|
- Stopped reporting thrown exceptions in ``when`` callbacks
|
||||||
|
and errbacks. These must be explicitly reported through
|
||||||
|
``.end()``, ``.then(null, Q.error)``, or some other
|
||||||
|
mechanism.
|
||||||
|
- Added ``report`` as an API method, which can be used as
|
||||||
|
an errback to report and propagate an error.
|
||||||
|
- Added ``report`` as a promise-chain method, so an error
|
||||||
|
can be reported if it passes such a gate.
|
||||||
|
|
||||||
|
## 0.4.3
|
||||||
|
|
||||||
|
- Fixed ``<script>`` support that regressed with 0.4.2
|
||||||
|
because of "use strict" in the module system
|
||||||
|
multi-plexer.
|
||||||
|
|
||||||
|
## 0.4.2
|
||||||
|
|
||||||
|
- Added support for RequireJS (jburke)
|
||||||
|
|
||||||
|
## 0.4.1
|
||||||
|
|
||||||
|
- Added an "end" method to the promise prototype,
|
||||||
|
as a shorthand for waiting for the promise to
|
||||||
|
be resolved gracefully, and failing to do so,
|
||||||
|
to dump an error message.
|
||||||
|
|
||||||
|
## 0.4.0 - BACKWARD INCOMPATIBLE*
|
||||||
|
|
||||||
|
- *Removed the utility modules. NPM and Node no longer
|
||||||
|
expose any module except the main module. These have
|
||||||
|
been moved and merged into the "qq" package.
|
||||||
|
- *In a non-CommonJS browser, q.js can be used as a script.
|
||||||
|
It now creates a Q global variable.
|
||||||
|
- Fixed thenable assimilation.
|
||||||
|
- Fixed some issues with asap, when it resolves to
|
||||||
|
undefined, or throws an exception.
|
||||||
|
|
||||||
|
## 0.3.0 - BACKWARD-INCOMPATIBLE
|
||||||
|
|
||||||
|
- The `post` method has been reverted to its original
|
||||||
|
signature, as provided in Tyler Close's `ref_send` API.
|
||||||
|
That is, `post` accepts two arguments, the second of
|
||||||
|
which is an arbitrary object, but usually invocation
|
||||||
|
arguments as an `Array`. To provide variadic arguments
|
||||||
|
to `post`, there is a new `invoke` function that posts
|
||||||
|
the variadic arguments to the value given in the first
|
||||||
|
argument.
|
||||||
|
- The `defined` method has been moved from `q` to `q/util`
|
||||||
|
since it gets no use in practice but is still
|
||||||
|
theoretically useful.
|
||||||
|
- The `Promise` constructor has been renamed to
|
||||||
|
`makePromise` to be consistent with the convention that
|
||||||
|
functions that do not require the `new` keyword to be
|
||||||
|
used as constructors have camelCase names.
|
||||||
|
- The `isResolved` function has been renamed to
|
||||||
|
`isFulfilled`. There is a new `isResolved` function that
|
||||||
|
indicates whether a value is not a promise or, if it is a
|
||||||
|
promise, whether it has been either fulfilled or
|
||||||
|
rejected. The code has been revised to reflect this
|
||||||
|
nuance in terminology.
|
||||||
|
|
||||||
|
## 0.2.10
|
||||||
|
|
||||||
|
- Added `join` to `"q/util"` for variadically joining
|
||||||
|
multiple promises.
|
||||||
|
|
||||||
|
## 0.2.9
|
||||||
|
|
||||||
|
- The future-compatible `invoke` method has been added,
|
||||||
|
to replace `post`, since `post` will become backward-
|
||||||
|
incompatible in the next major release.
|
||||||
|
- Exceptions thrown in the callbacks of a `when` call are
|
||||||
|
now emitted to Node's `"uncaughtException"` `process`
|
||||||
|
event in addition to being returned as a rejection reason.
|
||||||
|
|
||||||
|
## 0.2.8
|
||||||
|
|
||||||
|
- Exceptions thrown in the callbacks of a `when` call
|
||||||
|
are now consumed, warned, and transformed into
|
||||||
|
rejections of the promise returned by `when`.
|
||||||
|
|
||||||
|
## 0.2.7
|
||||||
|
|
||||||
|
- Fixed a minor bug in thenable assimilation, regressed
|
||||||
|
because of the change in the forwarding protocol.
|
||||||
|
- Fixed behavior of "q/util" `deep` method on dates and
|
||||||
|
other primitives. Github issue #11.
|
||||||
|
|
||||||
|
## 0.2.6
|
||||||
|
|
||||||
|
- Thenables (objects with a "then" method) are accepted
|
||||||
|
and provided, bringing this implementation of Q
|
||||||
|
into conformance with Promises/A, B, and D.
|
||||||
|
- Added `makePromise`, to replace the `Promise` function
|
||||||
|
eventually.
|
||||||
|
- Rejections are now also duck-typed. A rejection is a
|
||||||
|
promise with a valueOf method that returns a rejection
|
||||||
|
descriptor. A rejection descriptor has a
|
||||||
|
"promiseRejected" property equal to "true" and a
|
||||||
|
"reason" property corresponding to the rejection reason.
|
||||||
|
- Altered the `makePromise` API such that the `fallback`
|
||||||
|
method no longer receives a superfluous `resolved` method
|
||||||
|
after the `operator`. The fallback method is responsible
|
||||||
|
only for returning a resolution. This breaks an
|
||||||
|
undocumented API, so third-party API's depending on the
|
||||||
|
previous undocumented behavior may break.
|
||||||
|
|
||||||
|
## 0.2.5
|
||||||
|
|
||||||
|
- Changed promises into a duck-type such that multiple
|
||||||
|
instances of the Q module can exchange promise objects.
|
||||||
|
A promise is now defined as "an object that implements the
|
||||||
|
`promiseSend(op, resolved, ...)` method and `valueOf`".
|
||||||
|
- Exceptions in promises are now captured and returned
|
||||||
|
as rejections.
|
||||||
|
|
||||||
|
## 0.2.4
|
||||||
|
|
||||||
|
- Fixed bug in `ref` that prevented `del` messages from
|
||||||
|
being received (gozala)
|
||||||
|
- Fixed a conflict with FireFox 4; constructor property
|
||||||
|
is now read-only.
|
||||||
|
|
||||||
|
## 0.2.3
|
||||||
|
|
||||||
|
- Added `keys` message to promises and to the promise API.
|
||||||
|
|
||||||
|
## 0.2.2
|
||||||
|
|
||||||
|
- Added boilerplate to `q/queue` and `q/util`.
|
||||||
|
- Fixed missing dependency to `q/queue`.
|
||||||
|
|
||||||
|
## 0.2.1
|
||||||
|
|
||||||
|
- The `resolve` and `reject` methods of `defer` objects now
|
||||||
|
return the resolution promise for convenience.
|
||||||
|
- Added `q/util`, which provides `step`, `delay`, `shallow`,
|
||||||
|
`deep`, and three reduction orders.
|
||||||
|
- Added `q/queue` module for a promise `Queue`.
|
||||||
|
- Added `q-comm` to the list of compatible libraries.
|
||||||
|
- Deprecated `defined` from `q`, with intent to move it to
|
||||||
|
`q/util`.
|
||||||
|
|
||||||
|
## 0.2.0 - BACKWARD INCOMPATIBLE
|
||||||
|
|
||||||
|
- Changed post(ref, name, args) to variadic
|
||||||
|
post(ref, name, ...args). BACKWARD INCOMPATIBLE
|
||||||
|
- Added a def(value) method to annotate an object as being
|
||||||
|
necessarily a local value that cannot be serialized, such
|
||||||
|
that inter-process/worker/vat promise communication
|
||||||
|
libraries will send messages to it, but never send it
|
||||||
|
back.
|
||||||
|
- Added a send(value, op, ...args) method to the public API, for
|
||||||
|
forwarding messages to a value or promise in a future turn.
|
||||||
|
|
||||||
|
## 0.1.9
|
||||||
|
|
||||||
|
- Added isRejected() for testing whether a value is a rejected
|
||||||
|
promise. isResolved() retains the behavior of stating
|
||||||
|
that rejected promises are not resolved.
|
||||||
|
|
||||||
|
## 0.1.8
|
||||||
|
|
||||||
|
- Fixed isResolved(null) and isResolved(undefined) [issue #9]
|
||||||
|
- Fixed a problem with the Object.create shim
|
||||||
|
|
||||||
|
## 0.1.7
|
||||||
|
|
||||||
|
- shimmed ES5 Object.create in addition to Object.freeze
|
||||||
|
for compatibility on non-ES5 engines (gozala)
|
||||||
|
|
||||||
|
## 0.1.6
|
||||||
|
|
||||||
|
- Q.isResolved added
|
||||||
|
- promise.valueOf() now returns the value of resolved
|
||||||
|
and near values
|
||||||
|
- asap retried
|
||||||
|
- promises are frozen when possible
|
||||||
|
|
||||||
|
## 0.1.5
|
||||||
|
|
||||||
|
- fixed dependency list for Teleport (gozala)
|
||||||
|
- all unit tests now pass (gozala)
|
||||||
|
|
||||||
|
## 0.1.4
|
||||||
|
|
||||||
|
- added support for Teleport as an engine (gozala)
|
||||||
|
- simplified and updated methods for getting internal
|
||||||
|
print and enqueue functions universally (gozala)
|
||||||
|
|
||||||
|
## 0.1.3
|
||||||
|
|
||||||
|
- fixed erroneous link to the q module in package.json
|
||||||
|
|
||||||
|
## 0.1.2
|
||||||
|
|
||||||
|
- restructured for overlay style package compatibility
|
||||||
|
|
||||||
|
## 0.1.0
|
||||||
|
|
||||||
|
- removed asap because it was broken, probably down to the
|
||||||
|
philosophy.
|
||||||
|
|
||||||
|
## 0.0.3
|
||||||
|
|
||||||
|
- removed q-util
|
||||||
|
- fixed asap so it returns a value if completed
|
||||||
|
|
||||||
|
## 0.0.2
|
||||||
|
|
||||||
|
- added q-util
|
||||||
|
|
||||||
|
## 0.0.1
|
||||||
|
|
||||||
|
- initial version
|
||||||
|
|
||||||
40
vendors/Q/CONTRIBUTING.md
vendored
Normal file
40
vendors/Q/CONTRIBUTING.md
vendored
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
|
||||||
|
For pull requests:
|
||||||
|
|
||||||
|
- Be consistent with prevalent style and design decisions.
|
||||||
|
- Add a Jasmine spec to `specs/q-spec.js`.
|
||||||
|
- Use `npm test` to avoid regressions.
|
||||||
|
- Run tests in `q-spec/run.html` in as many supported browsers as you
|
||||||
|
can find the will to deal with.
|
||||||
|
- Do not build minified versions; we do this each release.
|
||||||
|
- If you would be so kind, add a note to `CHANGES.md` in an
|
||||||
|
appropriate section:
|
||||||
|
|
||||||
|
- `Next Major Version` if it introduces backward incompatibilities
|
||||||
|
to code in the wild using documented features.
|
||||||
|
- `Next Minor Version` if it adds a new feature.
|
||||||
|
- `Next Patch Version` if it fixes a bug.
|
||||||
|
|
||||||
|
For releases:
|
||||||
|
|
||||||
|
- Run `npm test`.
|
||||||
|
- Run tests in `q-spec/run.html` in a representative sample of every
|
||||||
|
browser under the sun.
|
||||||
|
- Run `npm run cover` and make sure you're happy with the results.
|
||||||
|
- Run `npm run minify` and be sure to commit the resulting `q.min.js`.
|
||||||
|
- Note the Gzipped size output by the previous command, and update
|
||||||
|
`README.md` if it has changed to 1 significant digit.
|
||||||
|
- Stash any local changes.
|
||||||
|
- Update `CHANGES.md` to reflect all changes in the differences
|
||||||
|
between `HEAD` and the previous tagged version. Give credit where
|
||||||
|
credit is due.
|
||||||
|
- Update `README.md` to address all new, non-experimental features.
|
||||||
|
- Update the API reference on the Wiki to reflect all non-experimental
|
||||||
|
features.
|
||||||
|
- Use `npm version major|minor|patch` to update `package.json`,
|
||||||
|
commit, and tag the new version.
|
||||||
|
- Use `npm publish` to send up a new release.
|
||||||
|
- Send an email to the q-continuum mailing list announcing the new
|
||||||
|
release and the notes from the change log. This helps folks
|
||||||
|
maintaining other package ecosystems.
|
||||||
|
|
||||||
16
vendors/Q/Gruntfile.js
vendored
Normal file
16
vendors/Q/Gruntfile.js
vendored
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
module.exports = function (grunt) {
|
||||||
|
grunt.loadNpmTasks("grunt-contrib-uglify");
|
||||||
|
|
||||||
|
grunt.initConfig({
|
||||||
|
uglify: {
|
||||||
|
"q.min.js": ["q.js"],
|
||||||
|
options: {
|
||||||
|
report: "gzip"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
grunt.registerTask("default", ["uglify"]);
|
||||||
|
};
|
||||||
18
vendors/Q/LICENSE
vendored
Normal file
18
vendors/Q/LICENSE
vendored
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
Copyright 2009–2014 Kristopher Michael Kowal. All rights reserved.
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to
|
||||||
|
deal in the Software without restriction, including without limitation the
|
||||||
|
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
|
sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in
|
||||||
|
all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||||
|
IN THE SOFTWARE.
|
||||||
869
vendors/Q/README.md
vendored
Normal file
869
vendors/Q/README.md
vendored
Normal file
|
|
@ -0,0 +1,869 @@
|
||||||
|
[](http://travis-ci.org/kriskowal/q)
|
||||||
|
|
||||||
|
<a href="http://promises-aplus.github.com/promises-spec">
|
||||||
|
<img src="http://kriskowal.github.io/q/q.png"
|
||||||
|
align="right" alt="Q logo" />
|
||||||
|
</a>
|
||||||
|
|
||||||
|
*This is Q version 1, from the `v1` branch in Git. This documentation applies to
|
||||||
|
the latest of both the version 1 and version 0.9 release trains. These releases
|
||||||
|
are stable. There will be no further releases of 0.9 after 0.9.7 which is nearly
|
||||||
|
equivalent to version 1.0.0. All further releases of `q@~1.0` will be backward
|
||||||
|
compatible. The version 2 release train introduces significant and
|
||||||
|
backward-incompatible changes and is experimental at this time.*
|
||||||
|
|
||||||
|
If a function cannot return a value or throw an exception without
|
||||||
|
blocking, it can return a promise instead. A promise is an object
|
||||||
|
that represents the return value or the thrown exception that the
|
||||||
|
function may eventually provide. A promise can also be used as a
|
||||||
|
proxy for a [remote object][Q-Connection] to overcome latency.
|
||||||
|
|
||||||
|
[Q-Connection]: https://github.com/kriskowal/q-connection
|
||||||
|
|
||||||
|
On the first pass, promises can mitigate the “[Pyramid of
|
||||||
|
Doom][POD]”: the situation where code marches to the right faster
|
||||||
|
than it marches forward.
|
||||||
|
|
||||||
|
[POD]: http://calculist.org/blog/2011/12/14/why-coroutines-wont-work-on-the-web/
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
step1(function (value1) {
|
||||||
|
step2(value1, function(value2) {
|
||||||
|
step3(value2, function(value3) {
|
||||||
|
step4(value3, function(value4) {
|
||||||
|
// Do something with value4
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
With a promise library, you can flatten the pyramid.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
Q.fcall(promisedStep1)
|
||||||
|
.then(promisedStep2)
|
||||||
|
.then(promisedStep3)
|
||||||
|
.then(promisedStep4)
|
||||||
|
.then(function (value4) {
|
||||||
|
// Do something with value4
|
||||||
|
})
|
||||||
|
.catch(function (error) {
|
||||||
|
// Handle any error from all above steps
|
||||||
|
})
|
||||||
|
.done();
|
||||||
|
```
|
||||||
|
|
||||||
|
With this approach, you also get implicit error propagation, just like `try`,
|
||||||
|
`catch`, and `finally`. An error in `promisedStep1` will flow all the way to
|
||||||
|
the `catch` function, where it’s caught and handled. (Here `promisedStepN` is
|
||||||
|
a version of `stepN` that returns a promise.)
|
||||||
|
|
||||||
|
The callback approach is called an “inversion of control”.
|
||||||
|
A function that accepts a callback instead of a return value
|
||||||
|
is saying, “Don’t call me, I’ll call you.”. Promises
|
||||||
|
[un-invert][IOC] the inversion, cleanly separating the input
|
||||||
|
arguments from control flow arguments. This simplifies the
|
||||||
|
use and creation of API’s, particularly variadic,
|
||||||
|
rest and spread arguments.
|
||||||
|
|
||||||
|
[IOC]: http://www.slideshare.net/domenicdenicola/callbacks-promises-and-coroutines-oh-my-the-evolution-of-asynchronicity-in-javascript
|
||||||
|
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
The Q module can be loaded as:
|
||||||
|
|
||||||
|
- A ``<script>`` tag (creating a ``Q`` global variable): ~2.5 KB minified and
|
||||||
|
gzipped.
|
||||||
|
- A Node.js and CommonJS module, available in [npm](https://npmjs.org/) as
|
||||||
|
the [q](https://npmjs.org/package/q) package
|
||||||
|
- An AMD module
|
||||||
|
- A [component](https://github.com/component/component) as ``microjs/q``
|
||||||
|
- Using [bower](http://bower.io/) as `q#1.0.1`
|
||||||
|
- Using [NuGet](http://nuget.org/) as [Q](https://nuget.org/packages/q)
|
||||||
|
|
||||||
|
Q can exchange promises with jQuery, Dojo, When.js, WinJS, and more.
|
||||||
|
|
||||||
|
## Resources
|
||||||
|
|
||||||
|
Our [wiki][] contains a number of useful resources, including:
|
||||||
|
|
||||||
|
- A method-by-method [Q API reference][reference].
|
||||||
|
- A growing [examples gallery][examples], showing how Q can be used to make
|
||||||
|
everything better. From XHR to database access to accessing the Flickr API,
|
||||||
|
Q is there for you.
|
||||||
|
- There are many libraries that produce and consume Q promises for everything
|
||||||
|
from file system/database access or RPC to templating. For a list of some of
|
||||||
|
the more popular ones, see [Libraries][].
|
||||||
|
- If you want materials that introduce the promise concept generally, and the
|
||||||
|
below tutorial isn't doing it for you, check out our collection of
|
||||||
|
[presentations, blog posts, and podcasts][resources].
|
||||||
|
- A guide for those [coming from jQuery's `$.Deferred`][jquery].
|
||||||
|
|
||||||
|
We'd also love to have you join the Q-Continuum [mailing list][].
|
||||||
|
|
||||||
|
[wiki]: https://github.com/kriskowal/q/wiki
|
||||||
|
[reference]: https://github.com/kriskowal/q/wiki/API-Reference
|
||||||
|
[examples]: https://github.com/kriskowal/q/wiki/Examples-Gallery
|
||||||
|
[Libraries]: https://github.com/kriskowal/q/wiki/Libraries
|
||||||
|
[resources]: https://github.com/kriskowal/q/wiki/General-Promise-Resources
|
||||||
|
[jquery]: https://github.com/kriskowal/q/wiki/Coming-from-jQuery
|
||||||
|
[mailing list]: https://groups.google.com/forum/#!forum/q-continuum
|
||||||
|
|
||||||
|
|
||||||
|
## Tutorial
|
||||||
|
|
||||||
|
Promises have a ``then`` method, which you can use to get the eventual
|
||||||
|
return value (fulfillment) or thrown exception (rejection).
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
promiseMeSomething()
|
||||||
|
.then(function (value) {
|
||||||
|
}, function (reason) {
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
If ``promiseMeSomething`` returns a promise that gets fulfilled later
|
||||||
|
with a return value, the first function (the fulfillment handler) will be
|
||||||
|
called with the value. However, if the ``promiseMeSomething`` function
|
||||||
|
gets rejected later by a thrown exception, the second function (the
|
||||||
|
rejection handler) will be called with the exception.
|
||||||
|
|
||||||
|
Note that resolution of a promise is always asynchronous: that is, the
|
||||||
|
fulfillment or rejection handler will always be called in the next turn of the
|
||||||
|
event loop (i.e. `process.nextTick` in Node). This gives you a nice
|
||||||
|
guarantee when mentally tracing the flow of your code, namely that
|
||||||
|
``then`` will always return before either handler is executed.
|
||||||
|
|
||||||
|
In this tutorial, we begin with how to consume and work with promises. We'll
|
||||||
|
talk about how to create them, and thus create functions like
|
||||||
|
`promiseMeSomething` that return promises, [below](#the-beginning).
|
||||||
|
|
||||||
|
|
||||||
|
### Propagation
|
||||||
|
|
||||||
|
The ``then`` method returns a promise, which in this example, I’m
|
||||||
|
assigning to ``outputPromise``.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
var outputPromise = getInputPromise()
|
||||||
|
.then(function (input) {
|
||||||
|
}, function (reason) {
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
The ``outputPromise`` variable becomes a new promise for the return
|
||||||
|
value of either handler. Since a function can only either return a
|
||||||
|
value or throw an exception, only one handler will ever be called and it
|
||||||
|
will be responsible for resolving ``outputPromise``.
|
||||||
|
|
||||||
|
- If you return a value in a handler, ``outputPromise`` will get
|
||||||
|
fulfilled.
|
||||||
|
|
||||||
|
- If you throw an exception in a handler, ``outputPromise`` will get
|
||||||
|
rejected.
|
||||||
|
|
||||||
|
- If you return a **promise** in a handler, ``outputPromise`` will
|
||||||
|
“become” that promise. Being able to become a new promise is useful
|
||||||
|
for managing delays, combining results, or recovering from errors.
|
||||||
|
|
||||||
|
If the ``getInputPromise()`` promise gets rejected and you omit the
|
||||||
|
rejection handler, the **error** will go to ``outputPromise``:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
var outputPromise = getInputPromise()
|
||||||
|
.then(function (value) {
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
If the input promise gets fulfilled and you omit the fulfillment handler, the
|
||||||
|
**value** will go to ``outputPromise``:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
var outputPromise = getInputPromise()
|
||||||
|
.then(null, function (error) {
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
Q promises provide a ``fail`` shorthand for ``then`` when you are only
|
||||||
|
interested in handling the error:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
var outputPromise = getInputPromise()
|
||||||
|
.fail(function (error) {
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
If you are writing JavaScript for modern engines only or using
|
||||||
|
CoffeeScript, you may use `catch` instead of `fail`.
|
||||||
|
|
||||||
|
Promises also have a ``fin`` function that is like a ``finally`` clause.
|
||||||
|
The final handler gets called, with no arguments, when the promise
|
||||||
|
returned by ``getInputPromise()`` either returns a value or throws an
|
||||||
|
error. The value returned or error thrown by ``getInputPromise()``
|
||||||
|
passes directly to ``outputPromise`` unless the final handler fails, and
|
||||||
|
may be delayed if the final handler returns a promise.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
var outputPromise = getInputPromise()
|
||||||
|
.fin(function () {
|
||||||
|
// close files, database connections, stop servers, conclude tests
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
- If the handler returns a value, the value is ignored
|
||||||
|
- If the handler throws an error, the error passes to ``outputPromise``
|
||||||
|
- If the handler returns a promise, ``outputPromise`` gets postponed. The
|
||||||
|
eventual value or error has the same effect as an immediate return
|
||||||
|
value or thrown error: a value would be ignored, an error would be
|
||||||
|
forwarded.
|
||||||
|
|
||||||
|
If you are writing JavaScript for modern engines only or using
|
||||||
|
CoffeeScript, you may use `finally` instead of `fin`.
|
||||||
|
|
||||||
|
### Chaining
|
||||||
|
|
||||||
|
There are two ways to chain promises. You can chain promises either
|
||||||
|
inside or outside handlers. The next two examples are equivalent.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
return getUsername()
|
||||||
|
.then(function (username) {
|
||||||
|
return getUser(username)
|
||||||
|
.then(function (user) {
|
||||||
|
// if we get here without an error,
|
||||||
|
// the value returned here
|
||||||
|
// or the exception thrown here
|
||||||
|
// resolves the promise returned
|
||||||
|
// by the first line
|
||||||
|
})
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
return getUsername()
|
||||||
|
.then(function (username) {
|
||||||
|
return getUser(username);
|
||||||
|
})
|
||||||
|
.then(function (user) {
|
||||||
|
// if we get here without an error,
|
||||||
|
// the value returned here
|
||||||
|
// or the exception thrown here
|
||||||
|
// resolves the promise returned
|
||||||
|
// by the first line
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
The only difference is nesting. It’s useful to nest handlers if you
|
||||||
|
need to capture multiple input values in your closure.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
function authenticate() {
|
||||||
|
return getUsername()
|
||||||
|
.then(function (username) {
|
||||||
|
return getUser(username);
|
||||||
|
})
|
||||||
|
// chained because we will not need the user name in the next event
|
||||||
|
.then(function (user) {
|
||||||
|
return getPassword()
|
||||||
|
// nested because we need both user and password next
|
||||||
|
.then(function (password) {
|
||||||
|
if (user.passwordHash !== hash(password)) {
|
||||||
|
throw new Error("Can't authenticate");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### Combination
|
||||||
|
|
||||||
|
You can turn an array of promises into a promise for the whole,
|
||||||
|
fulfilled array using ``all``.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
return Q.all([
|
||||||
|
eventualAdd(2, 2),
|
||||||
|
eventualAdd(10, 20)
|
||||||
|
]);
|
||||||
|
```
|
||||||
|
|
||||||
|
If you have a promise for an array, you can use ``spread`` as a
|
||||||
|
replacement for ``then``. The ``spread`` function “spreads” the
|
||||||
|
values over the arguments of the fulfillment handler. The rejection handler
|
||||||
|
will get called at the first sign of failure. That is, whichever of
|
||||||
|
the received promises fails first gets handled by the rejection handler.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
function eventualAdd(a, b) {
|
||||||
|
return Q.spread([a, b], function (a, b) {
|
||||||
|
return a + b;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
But ``spread`` calls ``all`` initially, so you can skip it in chains.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
return getUsername()
|
||||||
|
.then(function (username) {
|
||||||
|
return [username, getUser(username)];
|
||||||
|
})
|
||||||
|
.spread(function (username, user) {
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
The ``all`` function returns a promise for an array of values. When this
|
||||||
|
promise is fulfilled, the array contains the fulfillment values of the original
|
||||||
|
promises, in the same order as those promises. If one of the given promises
|
||||||
|
is rejected, the returned promise is immediately rejected, not waiting for the
|
||||||
|
rest of the batch. If you want to wait for all of the promises to either be
|
||||||
|
fulfilled or rejected, you can use ``allSettled``.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
Q.allSettled(promises)
|
||||||
|
.then(function (results) {
|
||||||
|
results.forEach(function (result) {
|
||||||
|
if (result.state === "fulfilled") {
|
||||||
|
var value = result.value;
|
||||||
|
} else {
|
||||||
|
var reason = result.reason;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### Sequences
|
||||||
|
|
||||||
|
If you have a number of promise-producing functions that need
|
||||||
|
to be run sequentially, you can of course do so manually:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
return foo(initialVal).then(bar).then(baz).then(qux);
|
||||||
|
```
|
||||||
|
|
||||||
|
However, if you want to run a dynamically constructed sequence of
|
||||||
|
functions, you'll want something like this:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
var funcs = [foo, bar, baz, qux];
|
||||||
|
|
||||||
|
var result = Q(initialVal);
|
||||||
|
funcs.forEach(function (f) {
|
||||||
|
result = result.then(f);
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
```
|
||||||
|
|
||||||
|
You can make this slightly more compact using `reduce`:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
return funcs.reduce(function (soFar, f) {
|
||||||
|
return soFar.then(f);
|
||||||
|
}, Q(initialVal));
|
||||||
|
```
|
||||||
|
|
||||||
|
Or, you could use the ultra-compact version:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
return funcs.reduce(Q.when, Q(initialVal));
|
||||||
|
```
|
||||||
|
|
||||||
|
### Handling Errors
|
||||||
|
|
||||||
|
One sometimes-unintuive aspect of promises is that if you throw an
|
||||||
|
exception in the fulfillment handler, it will not be caught by the error
|
||||||
|
handler.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
return foo()
|
||||||
|
.then(function (value) {
|
||||||
|
throw new Error("Can't bar.");
|
||||||
|
}, function (error) {
|
||||||
|
// We only get here if "foo" fails
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
To see why this is, consider the parallel between promises and
|
||||||
|
``try``/``catch``. We are ``try``-ing to execute ``foo()``: the error
|
||||||
|
handler represents a ``catch`` for ``foo()``, while the fulfillment handler
|
||||||
|
represents code that happens *after* the ``try``/``catch`` block.
|
||||||
|
That code then needs its own ``try``/``catch`` block.
|
||||||
|
|
||||||
|
In terms of promises, this means chaining your rejection handler:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
return foo()
|
||||||
|
.then(function (value) {
|
||||||
|
throw new Error("Can't bar.");
|
||||||
|
})
|
||||||
|
.fail(function (error) {
|
||||||
|
// We get here with either foo's error or bar's error
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### Progress Notification
|
||||||
|
|
||||||
|
It's possible for promises to report their progress, e.g. for tasks that take a
|
||||||
|
long time like a file upload. Not all promises will implement progress
|
||||||
|
notifications, but for those that do, you can consume the progress values using
|
||||||
|
a third parameter to ``then``:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
return uploadFile()
|
||||||
|
.then(function () {
|
||||||
|
// Success uploading the file
|
||||||
|
}, function (err) {
|
||||||
|
// There was an error, and we get the reason for error
|
||||||
|
}, function (progress) {
|
||||||
|
// We get notified of the upload's progress as it is executed
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
Like `fail`, Q also provides a shorthand for progress callbacks
|
||||||
|
called `progress`:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
return uploadFile().progress(function (progress) {
|
||||||
|
// We get notified of the upload's progress
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### The End
|
||||||
|
|
||||||
|
When you get to the end of a chain of promises, you should either
|
||||||
|
return the last promise or end the chain. Since handlers catch
|
||||||
|
errors, it’s an unfortunate pattern that the exceptions can go
|
||||||
|
unobserved.
|
||||||
|
|
||||||
|
So, either return it,
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
return foo()
|
||||||
|
.then(function () {
|
||||||
|
return "bar";
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
Or, end it.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
foo()
|
||||||
|
.then(function () {
|
||||||
|
return "bar";
|
||||||
|
})
|
||||||
|
.done();
|
||||||
|
```
|
||||||
|
|
||||||
|
Ending a promise chain makes sure that, if an error doesn’t get
|
||||||
|
handled before the end, it will get rethrown and reported.
|
||||||
|
|
||||||
|
This is a stopgap. We are exploring ways to make unhandled errors
|
||||||
|
visible without any explicit handling.
|
||||||
|
|
||||||
|
|
||||||
|
### The Beginning
|
||||||
|
|
||||||
|
Everything above assumes you get a promise from somewhere else. This
|
||||||
|
is the common case. Every once in a while, you will need to create a
|
||||||
|
promise from scratch.
|
||||||
|
|
||||||
|
#### Using ``Q.fcall``
|
||||||
|
|
||||||
|
You can create a promise from a value using ``Q.fcall``. This returns a
|
||||||
|
promise for 10.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
return Q.fcall(function () {
|
||||||
|
return 10;
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also use ``fcall`` to get a promise for an exception.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
return Q.fcall(function () {
|
||||||
|
throw new Error("Can't do it");
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
As the name implies, ``fcall`` can call functions, or even promised
|
||||||
|
functions. This uses the ``eventualAdd`` function above to add two
|
||||||
|
numbers.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
return Q.fcall(eventualAdd, 2, 2);
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
#### Using Deferreds
|
||||||
|
|
||||||
|
If you have to interface with asynchronous functions that are callback-based
|
||||||
|
instead of promise-based, Q provides a few shortcuts (like ``Q.nfcall`` and
|
||||||
|
friends). But much of the time, the solution will be to use *deferreds*.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
var deferred = Q.defer();
|
||||||
|
FS.readFile("foo.txt", "utf-8", function (error, text) {
|
||||||
|
if (error) {
|
||||||
|
deferred.reject(new Error(error));
|
||||||
|
} else {
|
||||||
|
deferred.resolve(text);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return deferred.promise;
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that a deferred can be resolved with a value or a promise. The
|
||||||
|
``reject`` function is a shorthand for resolving with a rejected
|
||||||
|
promise.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// this:
|
||||||
|
deferred.reject(new Error("Can't do it"));
|
||||||
|
|
||||||
|
// is shorthand for:
|
||||||
|
var rejection = Q.fcall(function () {
|
||||||
|
throw new Error("Can't do it");
|
||||||
|
});
|
||||||
|
deferred.resolve(rejection);
|
||||||
|
```
|
||||||
|
|
||||||
|
This is a simplified implementation of ``Q.delay``.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
function delay(ms) {
|
||||||
|
var deferred = Q.defer();
|
||||||
|
setTimeout(deferred.resolve, ms);
|
||||||
|
return deferred.promise;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
This is a simplified implementation of ``Q.timeout``
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
function timeout(promise, ms) {
|
||||||
|
var deferred = Q.defer();
|
||||||
|
Q.when(promise, deferred.resolve);
|
||||||
|
delay(ms).then(function () {
|
||||||
|
deferred.reject(new Error("Timed out"));
|
||||||
|
});
|
||||||
|
return deferred.promise;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Finally, you can send a progress notification to the promise with
|
||||||
|
``deferred.notify``.
|
||||||
|
|
||||||
|
For illustration, this is a wrapper for XML HTTP requests in the browser. Note
|
||||||
|
that a more [thorough][XHR] implementation would be in order in practice.
|
||||||
|
|
||||||
|
[XHR]: https://github.com/montagejs/mr/blob/71e8df99bb4f0584985accd6f2801ef3015b9763/browser.js#L29-L73
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
function requestOkText(url) {
|
||||||
|
var request = new XMLHttpRequest();
|
||||||
|
var deferred = Q.defer();
|
||||||
|
|
||||||
|
request.open("GET", url, true);
|
||||||
|
request.onload = onload;
|
||||||
|
request.onerror = onerror;
|
||||||
|
request.onprogress = onprogress;
|
||||||
|
request.send();
|
||||||
|
|
||||||
|
function onload() {
|
||||||
|
if (request.status === 200) {
|
||||||
|
deferred.resolve(request.responseText);
|
||||||
|
} else {
|
||||||
|
deferred.reject(new Error("Status code was " + request.status));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onerror() {
|
||||||
|
deferred.reject(new Error("Can't XHR " + JSON.stringify(url)));
|
||||||
|
}
|
||||||
|
|
||||||
|
function onprogress(event) {
|
||||||
|
deferred.notify(event.loaded / event.total);
|
||||||
|
}
|
||||||
|
|
||||||
|
return deferred.promise;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Below is an example of how to use this ``requestOkText`` function:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
requestOkText("http://localhost:3000")
|
||||||
|
.then(function (responseText) {
|
||||||
|
// If the HTTP response returns 200 OK, log the response text.
|
||||||
|
console.log(responseText);
|
||||||
|
}, function (error) {
|
||||||
|
// If there's an error or a non-200 status code, log the error.
|
||||||
|
console.error(error);
|
||||||
|
}, function (progress) {
|
||||||
|
// Log the progress as it comes in.
|
||||||
|
console.log("Request progress: " + Math.round(progress * 100) + "%");
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Using `Q.Promise`
|
||||||
|
|
||||||
|
This is an alternative promise-creation API that has the same power as
|
||||||
|
the deferred concept, but without introducing another conceptual entity.
|
||||||
|
|
||||||
|
Rewriting the `requestOkText` example above using `Q.Promise`:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
function requestOkText(url) {
|
||||||
|
return Q.Promise(function(resolve, reject, notify) {
|
||||||
|
var request = new XMLHttpRequest();
|
||||||
|
|
||||||
|
request.open("GET", url, true);
|
||||||
|
request.onload = onload;
|
||||||
|
request.onerror = onerror;
|
||||||
|
request.onprogress = onprogress;
|
||||||
|
request.send();
|
||||||
|
|
||||||
|
function onload() {
|
||||||
|
if (request.status === 200) {
|
||||||
|
resolve(request.responseText);
|
||||||
|
} else {
|
||||||
|
reject(new Error("Status code was " + request.status));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onerror() {
|
||||||
|
reject(new Error("Can't XHR " + JSON.stringify(url)));
|
||||||
|
}
|
||||||
|
|
||||||
|
function onprogress(event) {
|
||||||
|
notify(event.loaded / event.total);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
If `requestOkText` were to throw an exception, the returned promise would be
|
||||||
|
rejected with that thrown exception as the rejection reason.
|
||||||
|
|
||||||
|
### The Middle
|
||||||
|
|
||||||
|
If you are using a function that may return a promise, but just might
|
||||||
|
return a value if it doesn’t need to defer, you can use the “static”
|
||||||
|
methods of the Q library.
|
||||||
|
|
||||||
|
The ``when`` function is the static equivalent for ``then``.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
return Q.when(valueOrPromise, function (value) {
|
||||||
|
}, function (error) {
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
All of the other methods on a promise have static analogs with the
|
||||||
|
same name.
|
||||||
|
|
||||||
|
The following are equivalent:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
return Q.all([a, b]);
|
||||||
|
```
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
return Q.fcall(function () {
|
||||||
|
return [a, b];
|
||||||
|
})
|
||||||
|
.all();
|
||||||
|
```
|
||||||
|
|
||||||
|
When working with promises provided by other libraries, you should
|
||||||
|
convert it to a Q promise. Not all promise libraries make the same
|
||||||
|
guarantees as Q and certainly don’t provide all of the same methods.
|
||||||
|
Most libraries only provide a partially functional ``then`` method.
|
||||||
|
This thankfully is all we need to turn them into vibrant Q promises.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
return Q($.ajax(...))
|
||||||
|
.then(function () {
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
If there is any chance that the promise you receive is not a Q promise
|
||||||
|
as provided by your library, you should wrap it using a Q function.
|
||||||
|
You can even use ``Q.invoke`` as a shorthand.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
return Q.invoke($, 'ajax', ...)
|
||||||
|
.then(function () {
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### Over the Wire
|
||||||
|
|
||||||
|
A promise can serve as a proxy for another object, even a remote
|
||||||
|
object. There are methods that allow you to optimistically manipulate
|
||||||
|
properties or call functions. All of these interactions return
|
||||||
|
promises, so they can be chained.
|
||||||
|
|
||||||
|
```
|
||||||
|
direct manipulation using a promise as a proxy
|
||||||
|
-------------------------- -------------------------------
|
||||||
|
value.foo promise.get("foo")
|
||||||
|
value.foo = value promise.put("foo", value)
|
||||||
|
delete value.foo promise.del("foo")
|
||||||
|
value.foo(...args) promise.post("foo", [args])
|
||||||
|
value.foo(...args) promise.invoke("foo", ...args)
|
||||||
|
value(...args) promise.fapply([args])
|
||||||
|
value(...args) promise.fcall(...args)
|
||||||
|
```
|
||||||
|
|
||||||
|
If the promise is a proxy for a remote object, you can shave
|
||||||
|
round-trips by using these functions instead of ``then``. To take
|
||||||
|
advantage of promises for remote objects, check out [Q-Connection][].
|
||||||
|
|
||||||
|
[Q-Connection]: https://github.com/kriskowal/q-connection
|
||||||
|
|
||||||
|
Even in the case of non-remote objects, these methods can be used as
|
||||||
|
shorthand for particularly-simple fulfillment handlers. For example, you
|
||||||
|
can replace
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
return Q.fcall(function () {
|
||||||
|
return [{ foo: "bar" }, { foo: "baz" }];
|
||||||
|
})
|
||||||
|
.then(function (value) {
|
||||||
|
return value[0].foo;
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
with
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
return Q.fcall(function () {
|
||||||
|
return [{ foo: "bar" }, { foo: "baz" }];
|
||||||
|
})
|
||||||
|
.get(0)
|
||||||
|
.get("foo");
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### Adapting Node
|
||||||
|
|
||||||
|
If you're working with functions that make use of the Node.js callback pattern,
|
||||||
|
where callbacks are in the form of `function(err, result)`, Q provides a few
|
||||||
|
useful utility functions for converting between them. The most straightforward
|
||||||
|
are probably `Q.nfcall` and `Q.nfapply` ("Node function call/apply") for calling
|
||||||
|
Node.js-style functions and getting back a promise:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
return Q.nfcall(FS.readFile, "foo.txt", "utf-8");
|
||||||
|
return Q.nfapply(FS.readFile, ["foo.txt", "utf-8"]);
|
||||||
|
```
|
||||||
|
|
||||||
|
If you are working with methods, instead of simple functions, you can easily
|
||||||
|
run in to the usual problems where passing a method to another function—like
|
||||||
|
`Q.nfcall`—"un-binds" the method from its owner. To avoid this, you can either
|
||||||
|
use `Function.prototype.bind` or some nice shortcut methods we provide:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
return Q.ninvoke(redisClient, "get", "user:1:id");
|
||||||
|
return Q.npost(redisClient, "get", ["user:1:id"]);
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also create reusable wrappers with `Q.denodeify` or `Q.nbind`:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
var readFile = Q.denodeify(FS.readFile);
|
||||||
|
return readFile("foo.txt", "utf-8");
|
||||||
|
|
||||||
|
var redisClientGet = Q.nbind(redisClient.get, redisClient);
|
||||||
|
return redisClientGet("user:1:id");
|
||||||
|
```
|
||||||
|
|
||||||
|
Finally, if you're working with raw deferred objects, there is a
|
||||||
|
`makeNodeResolver` method on deferreds that can be handy:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
var deferred = Q.defer();
|
||||||
|
FS.readFile("foo.txt", "utf-8", deferred.makeNodeResolver());
|
||||||
|
return deferred.promise;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Long Stack Traces
|
||||||
|
|
||||||
|
Q comes with optional support for “long stack traces,” wherein the `stack`
|
||||||
|
property of `Error` rejection reasons is rewritten to be traced along
|
||||||
|
asynchronous jumps instead of stopping at the most recent one. As an example:
|
||||||
|
|
||||||
|
```js
|
||||||
|
function theDepthsOfMyProgram() {
|
||||||
|
Q.delay(100).done(function explode() {
|
||||||
|
throw new Error("boo!");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
theDepthsOfMyProgram();
|
||||||
|
```
|
||||||
|
|
||||||
|
usually would give a rather unhelpful stack trace looking something like
|
||||||
|
|
||||||
|
```
|
||||||
|
Error: boo!
|
||||||
|
at explode (/path/to/test.js:3:11)
|
||||||
|
at _fulfilled (/path/to/test.js:q:54)
|
||||||
|
at resolvedValue.promiseDispatch.done (/path/to/q.js:823:30)
|
||||||
|
at makePromise.promise.promiseDispatch (/path/to/q.js:496:13)
|
||||||
|
at pending (/path/to/q.js:397:39)
|
||||||
|
at process.startup.processNextTick.process._tickCallback (node.js:244:9)
|
||||||
|
```
|
||||||
|
|
||||||
|
But, if you turn this feature on by setting
|
||||||
|
|
||||||
|
```js
|
||||||
|
Q.longStackSupport = true;
|
||||||
|
```
|
||||||
|
|
||||||
|
then the above code gives a nice stack trace to the tune of
|
||||||
|
|
||||||
|
```
|
||||||
|
Error: boo!
|
||||||
|
at explode (/path/to/test.js:3:11)
|
||||||
|
From previous event:
|
||||||
|
at theDepthsOfMyProgram (/path/to/test.js:2:16)
|
||||||
|
at Object.<anonymous> (/path/to/test.js:7:1)
|
||||||
|
```
|
||||||
|
|
||||||
|
Note how you can see the function that triggered the async operation in the
|
||||||
|
stack trace! This is very helpful for debugging, as otherwise you end up getting
|
||||||
|
only the first line, plus a bunch of Q internals, with no sign of where the
|
||||||
|
operation started.
|
||||||
|
|
||||||
|
In node.js, this feature can also be enabled through the Q_DEBUG environment
|
||||||
|
variable:
|
||||||
|
|
||||||
|
```
|
||||||
|
Q_DEBUG=1 node server.js
|
||||||
|
```
|
||||||
|
|
||||||
|
This will enable long stack support in every instance of Q.
|
||||||
|
|
||||||
|
This feature does come with somewhat-serious performance and memory overhead,
|
||||||
|
however. If you're working with lots of promises, or trying to scale a server
|
||||||
|
to many users, you should probably keep it off. But in development, go for it!
|
||||||
|
|
||||||
|
## Tests
|
||||||
|
|
||||||
|
You can view the results of the Q test suite [in your browser][tests]!
|
||||||
|
|
||||||
|
[tests]: https://rawgithub.com/kriskowal/q/v1/spec/q-spec.html
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
Copyright 2009–2014 Kristopher Michael Kowal
|
||||||
|
MIT License (enclosed)
|
||||||
|
|
||||||
18
vendors/Q/VERSIONS.md
vendored
Normal file
18
vendors/Q/VERSIONS.md
vendored
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
<!-- vim:ts=4:sts=4:sw=4:et:tw=60 -->
|
||||||
|
|
||||||
|
This library has the following policy about versions.
|
||||||
|
|
||||||
|
- Presently, all planned versions have a major version number of 0.
|
||||||
|
- The minor version number increases for every backward-incompatible
|
||||||
|
change to a documented behavior.
|
||||||
|
- The patch version number increases for every added feature,
|
||||||
|
backward-incompatible changes to undocumented features, and
|
||||||
|
bug-fixes.
|
||||||
|
|
||||||
|
Upon the release of a version 1.0.0, the strategy will be revised.
|
||||||
|
|
||||||
|
- The major version will increase for any backward-incompatible
|
||||||
|
changes.
|
||||||
|
- The minor version will increase for added features.
|
||||||
|
- The patch version will increase for bug-fixes.
|
||||||
|
|
||||||
71
vendors/Q/benchmark/compare-with-callbacks.js
vendored
Normal file
71
vendors/Q/benchmark/compare-with-callbacks.js
vendored
Normal file
|
|
@ -0,0 +1,71 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var Q = require("../q");
|
||||||
|
var fs = require("fs");
|
||||||
|
|
||||||
|
suite("A single simple async operation", function () {
|
||||||
|
bench("with an immediately-fulfilled promise", function (done) {
|
||||||
|
Q().then(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
bench("with direct setImmediate usage", function (done) {
|
||||||
|
setImmediate(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
bench("with direct setTimeout(…, 0)", function (done) {
|
||||||
|
setTimeout(done, 0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
suite("A fs.readFile", function () {
|
||||||
|
var denodeified = Q.denodeify(fs.readFile);
|
||||||
|
|
||||||
|
set("iterations", 1000);
|
||||||
|
set("delay", 1000);
|
||||||
|
|
||||||
|
bench("directly, with callbacks", function (done) {
|
||||||
|
fs.readFile(__filename, done);
|
||||||
|
});
|
||||||
|
|
||||||
|
bench("with Q.nfcall", function (done) {
|
||||||
|
Q.nfcall(fs.readFile, __filename).then(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
bench("with a Q.denodeify'ed version", function (done) {
|
||||||
|
denodeified(__filename).then(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
bench("with manual usage of deferred.makeNodeResolver", function (done) {
|
||||||
|
var deferred = Q.defer();
|
||||||
|
fs.readFile(__filename, deferred.makeNodeResolver());
|
||||||
|
deferred.promise.then(done);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
suite("1000 operations in parallel", function () {
|
||||||
|
function makeCounter(desiredCount, ultimateCallback) {
|
||||||
|
var soFar = 0;
|
||||||
|
return function () {
|
||||||
|
if (++soFar === desiredCount) {
|
||||||
|
ultimateCallback();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
var numberOfOps = 1000;
|
||||||
|
|
||||||
|
bench("with immediately-fulfilled promises", function (done) {
|
||||||
|
var counter = makeCounter(numberOfOps, done);
|
||||||
|
|
||||||
|
for (var i = 0; i < numberOfOps; ++i) {
|
||||||
|
Q().then(counter);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
bench("with direct setImmediate usage", function (done) {
|
||||||
|
var counter = makeCounter(numberOfOps, done);
|
||||||
|
|
||||||
|
for (var i = 0; i < numberOfOps; ++i) {
|
||||||
|
setImmediate(counter);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
36
vendors/Q/benchmark/scenarios.js
vendored
Normal file
36
vendors/Q/benchmark/scenarios.js
vendored
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var Q = require("../q");
|
||||||
|
|
||||||
|
suite("Chaining", function () {
|
||||||
|
var numberToChain = 1000;
|
||||||
|
|
||||||
|
bench("Chaining many already-fulfilled promises together", function (done) {
|
||||||
|
var currentPromise = Q();
|
||||||
|
for (var i = 0; i < numberToChain; ++i) {
|
||||||
|
currentPromise = currentPromise.then(function () {
|
||||||
|
return Q();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
currentPromise.then(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
bench("Chaining and then fulfilling the end of the chain", function (done) {
|
||||||
|
var deferred = Q.defer();
|
||||||
|
|
||||||
|
var currentPromise = deferred.promise;
|
||||||
|
for (var i = 0; i < numberToChain; ++i) {
|
||||||
|
(function () {
|
||||||
|
var promiseToReturn = currentPromise;
|
||||||
|
currentPromise = Q().then(function () {
|
||||||
|
return promiseToReturn;
|
||||||
|
});
|
||||||
|
}());
|
||||||
|
}
|
||||||
|
|
||||||
|
currentPromise.then(done);
|
||||||
|
|
||||||
|
deferred.resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
1026
vendors/Q/design/README.js
vendored
Normal file
1026
vendors/Q/design/README.js
vendored
Normal file
File diff suppressed because it is too large
Load diff
22
vendors/Q/design/q0.js
vendored
Normal file
22
vendors/Q/design/q0.js
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
|
||||||
|
var defer = function () {
|
||||||
|
var pending = [], value;
|
||||||
|
return {
|
||||||
|
resolve: function (_value) {
|
||||||
|
value = _value;
|
||||||
|
for (var i = 0, ii = pending.length; i < ii; i++) {
|
||||||
|
var callback = pending[i];
|
||||||
|
callback(value);
|
||||||
|
}
|
||||||
|
pending = undefined;
|
||||||
|
},
|
||||||
|
then: function (callback) {
|
||||||
|
if (pending) {
|
||||||
|
pending.push(callback);
|
||||||
|
} else {
|
||||||
|
callback(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
26
vendors/Q/design/q1.js
vendored
Normal file
26
vendors/Q/design/q1.js
vendored
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
|
||||||
|
var defer = function () {
|
||||||
|
var pending = [], value;
|
||||||
|
return {
|
||||||
|
resolve: function (_value) {
|
||||||
|
if (pending) {
|
||||||
|
value = _value;
|
||||||
|
for (var i = 0, ii = pending.length; i < ii; i++) {
|
||||||
|
var callback = pending[i];
|
||||||
|
callback(value);
|
||||||
|
}
|
||||||
|
pending = undefined;
|
||||||
|
} else {
|
||||||
|
throw new Error("A promise can only be resolved once.");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
then: function (callback) {
|
||||||
|
if (pending) {
|
||||||
|
pending.push(callback);
|
||||||
|
} else {
|
||||||
|
callback(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
33
vendors/Q/design/q2.js
vendored
Normal file
33
vendors/Q/design/q2.js
vendored
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
|
||||||
|
var Promise = function () {
|
||||||
|
};
|
||||||
|
|
||||||
|
var isPromise = function (value) {
|
||||||
|
return value instanceof Promise;
|
||||||
|
};
|
||||||
|
|
||||||
|
var defer = function () {
|
||||||
|
var pending = [], value;
|
||||||
|
var promise = new Promise();
|
||||||
|
promise.then = function (callback) {
|
||||||
|
if (pending) {
|
||||||
|
pending.push(callback);
|
||||||
|
} else {
|
||||||
|
callback(value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return {
|
||||||
|
resolve: function (_value) {
|
||||||
|
if (pending) {
|
||||||
|
value = _value;
|
||||||
|
for (var i = 0, ii = pending.length; i < ii; i++) {
|
||||||
|
var callback = pending[i];
|
||||||
|
callback(value);
|
||||||
|
}
|
||||||
|
pending = undefined;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
promise: promise
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
30
vendors/Q/design/q3.js
vendored
Normal file
30
vendors/Q/design/q3.js
vendored
Normal file
|
|
@ -0,0 +1,30 @@
|
||||||
|
|
||||||
|
var isPromise = function (value) {
|
||||||
|
return value && typeof value.then === "function";
|
||||||
|
};
|
||||||
|
|
||||||
|
var defer = function () {
|
||||||
|
var pending = [], value;
|
||||||
|
return {
|
||||||
|
resolve: function (_value) {
|
||||||
|
if (pending) {
|
||||||
|
value = _value;
|
||||||
|
for (var i = 0, ii = pending.length; i < ii; i++) {
|
||||||
|
var callback = pending[i];
|
||||||
|
callback(value);
|
||||||
|
}
|
||||||
|
pending = undefined;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
promise: {
|
||||||
|
then: function (callback) {
|
||||||
|
if (pending) {
|
||||||
|
pending.push(callback);
|
||||||
|
} else {
|
||||||
|
callback(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
48
vendors/Q/design/q4.js
vendored
Normal file
48
vendors/Q/design/q4.js
vendored
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
|
||||||
|
var isPromise = function (value) {
|
||||||
|
return value && typeof value.then === "function";
|
||||||
|
};
|
||||||
|
|
||||||
|
var defer = function () {
|
||||||
|
var pending = [], value;
|
||||||
|
return {
|
||||||
|
resolve: function (_value) {
|
||||||
|
if (pending) {
|
||||||
|
value = ref(_value); // values wrapped in a promise
|
||||||
|
for (var i = 0, ii = pending.length; i < ii; i++) {
|
||||||
|
var callback = pending[i];
|
||||||
|
value.then(callback); // then called instead
|
||||||
|
}
|
||||||
|
pending = undefined;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
promise: {
|
||||||
|
then: function (_callback) {
|
||||||
|
var result = defer();
|
||||||
|
// callback is wrapped so that its return
|
||||||
|
// value is captured and used to resolve the promise
|
||||||
|
// that "then" returns
|
||||||
|
var callback = function (value) {
|
||||||
|
result.resolve(_callback(value));
|
||||||
|
};
|
||||||
|
if (pending) {
|
||||||
|
pending.push(callback);
|
||||||
|
} else {
|
||||||
|
value.then(callback);
|
||||||
|
}
|
||||||
|
return result.promise;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
var ref = function (value) {
|
||||||
|
if (value && typeof value.then === "function")
|
||||||
|
return value;
|
||||||
|
return {
|
||||||
|
then: function (callback) {
|
||||||
|
return ref(callback(value));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
56
vendors/Q/design/q5.js
vendored
Normal file
56
vendors/Q/design/q5.js
vendored
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
|
||||||
|
var isPromise = function (value) {
|
||||||
|
return value && typeof value.then === "function";
|
||||||
|
};
|
||||||
|
|
||||||
|
var defer = function () {
|
||||||
|
var pending = [], value;
|
||||||
|
return {
|
||||||
|
resolve: function (_value) {
|
||||||
|
if (pending) {
|
||||||
|
value = ref(_value);
|
||||||
|
for (var i = 0, ii = pending.length; i < ii; i++) {
|
||||||
|
// apply the pending arguments to "then"
|
||||||
|
value.then.apply(value, pending[i]);
|
||||||
|
}
|
||||||
|
pending = undefined;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
promise: {
|
||||||
|
then: function (_callback, _errback) {
|
||||||
|
var result = defer();
|
||||||
|
var callback = function (value) {
|
||||||
|
result.resolve(_callback(value));
|
||||||
|
};
|
||||||
|
var errback = function (reason) {
|
||||||
|
result.resolve(_errback(reason));
|
||||||
|
};
|
||||||
|
if (pending) {
|
||||||
|
pending.push([callback, errback]);
|
||||||
|
} else {
|
||||||
|
value.then(callback, errback);
|
||||||
|
}
|
||||||
|
return result.promise;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
var ref = function (value) {
|
||||||
|
if (value && typeof value.then === "function")
|
||||||
|
return value;
|
||||||
|
return {
|
||||||
|
then: function (callback) {
|
||||||
|
return ref(callback(value));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
var reject = function (reason) {
|
||||||
|
return {
|
||||||
|
then: function (callback, errback) {
|
||||||
|
return ref(errback(reason));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
64
vendors/Q/design/q6.js
vendored
Normal file
64
vendors/Q/design/q6.js
vendored
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
|
||||||
|
var isPromise = function (value) {
|
||||||
|
return value && typeof value.then === "function";
|
||||||
|
};
|
||||||
|
|
||||||
|
var defer = function () {
|
||||||
|
var pending = [], value;
|
||||||
|
return {
|
||||||
|
resolve: function (_value) {
|
||||||
|
if (pending) {
|
||||||
|
value = ref(_value);
|
||||||
|
for (var i = 0, ii = pending.length; i < ii; i++) {
|
||||||
|
value.then.apply(value, pending[i]);
|
||||||
|
}
|
||||||
|
pending = undefined;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
promise: {
|
||||||
|
then: function (_callback, _errback) {
|
||||||
|
var result = defer();
|
||||||
|
// provide default callbacks and errbacks
|
||||||
|
_callback = _callback || function (value) {
|
||||||
|
// by default, forward fulfillment
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
_errback = _errback || function (reason) {
|
||||||
|
// by default, forward rejection
|
||||||
|
return reject(reason);
|
||||||
|
};
|
||||||
|
var callback = function (value) {
|
||||||
|
result.resolve(_callback(value));
|
||||||
|
};
|
||||||
|
var errback = function (reason) {
|
||||||
|
result.resolve(_errback(reason));
|
||||||
|
};
|
||||||
|
if (pending) {
|
||||||
|
pending.push([callback, errback]);
|
||||||
|
} else {
|
||||||
|
value.then(callback, errback);
|
||||||
|
}
|
||||||
|
return result.promise;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
var ref = function (value) {
|
||||||
|
if (value && typeof value.then === "function")
|
||||||
|
return value;
|
||||||
|
return {
|
||||||
|
then: function (callback) {
|
||||||
|
return ref(callback(value));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
var reject = function (reason) {
|
||||||
|
return {
|
||||||
|
then: function (callback, errback) {
|
||||||
|
return ref(errback(reason));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
126
vendors/Q/design/q7.js
vendored
Normal file
126
vendors/Q/design/q7.js
vendored
Normal file
|
|
@ -0,0 +1,126 @@
|
||||||
|
|
||||||
|
var enqueue = function (callback) {
|
||||||
|
//process.nextTick(callback); // NodeJS
|
||||||
|
setTimeout(callback, 1); // Naïve browser solution
|
||||||
|
};
|
||||||
|
|
||||||
|
var isPromise = function (value) {
|
||||||
|
return value && typeof value.then === "function";
|
||||||
|
};
|
||||||
|
|
||||||
|
var defer = function () {
|
||||||
|
var pending = [], value;
|
||||||
|
return {
|
||||||
|
resolve: function (_value) {
|
||||||
|
if (pending) {
|
||||||
|
value = ref(_value);
|
||||||
|
for (var i = 0, ii = pending.length; i < ii; i++) {
|
||||||
|
// XXX
|
||||||
|
enqueue(function () {
|
||||||
|
value.then.apply(value, pending[i]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
pending = undefined;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
promise: {
|
||||||
|
then: function (_callback, _errback) {
|
||||||
|
var result = defer();
|
||||||
|
_callback = _callback || function (value) {
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
_errback = _errback || function (reason) {
|
||||||
|
return reject(reason);
|
||||||
|
};
|
||||||
|
var callback = function (value) {
|
||||||
|
result.resolve(_callback(value));
|
||||||
|
};
|
||||||
|
var errback = function (reason) {
|
||||||
|
result.resolve(_errback(reason));
|
||||||
|
};
|
||||||
|
if (pending) {
|
||||||
|
pending.push([callback, errback]);
|
||||||
|
} else {
|
||||||
|
// XXX
|
||||||
|
enqueue(function () {
|
||||||
|
value.then(callback, errback);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return result.promise;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
var ref = function (value) {
|
||||||
|
if (value && value.then)
|
||||||
|
return value;
|
||||||
|
return {
|
||||||
|
then: function (callback) {
|
||||||
|
var result = defer();
|
||||||
|
// XXX
|
||||||
|
enqueue(function () {
|
||||||
|
result.resolve(callback(value));
|
||||||
|
});
|
||||||
|
return result.promise;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
var reject = function (reason) {
|
||||||
|
return {
|
||||||
|
then: function (callback, errback) {
|
||||||
|
var result = defer();
|
||||||
|
// XXX
|
||||||
|
enqueue(function () {
|
||||||
|
result.resolve(errback(reason));
|
||||||
|
});
|
||||||
|
return result.promise;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
var when = function (value, _callback, _errback) {
|
||||||
|
var result = defer();
|
||||||
|
var done;
|
||||||
|
|
||||||
|
_callback = _callback || function (value) {
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
_errback = _errback || function (reason) {
|
||||||
|
return reject(reason);
|
||||||
|
};
|
||||||
|
|
||||||
|
// XXX
|
||||||
|
var callback = function (value) {
|
||||||
|
try {
|
||||||
|
return _callback(value);
|
||||||
|
} catch (reason) {
|
||||||
|
return reject(reason);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
var errback = function (reason) {
|
||||||
|
try {
|
||||||
|
return _errback(reason);
|
||||||
|
} catch (reason) {
|
||||||
|
return reject(reason);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
enqueue(function () {
|
||||||
|
ref(value).then(function (value) {
|
||||||
|
if (done)
|
||||||
|
return;
|
||||||
|
done = true;
|
||||||
|
result.resolve(ref(value).then(callback, errback));
|
||||||
|
}, function (reason) {
|
||||||
|
if (done)
|
||||||
|
return;
|
||||||
|
done = true;
|
||||||
|
result.resolve(errback(reason));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return result.promise;
|
||||||
|
};
|
||||||
|
|
||||||
21
vendors/Q/examples/all.js
vendored
Normal file
21
vendors/Q/examples/all.js
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var Q = require("../q");
|
||||||
|
|
||||||
|
function eventually(value) {
|
||||||
|
return Q.delay(value, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
Q.all([1, 2, 3].map(eventually))
|
||||||
|
.done(function (result) {
|
||||||
|
console.log(result);
|
||||||
|
});
|
||||||
|
|
||||||
|
Q.all([
|
||||||
|
eventually(10),
|
||||||
|
eventually(20)
|
||||||
|
])
|
||||||
|
.spread(function (x, y) {
|
||||||
|
console.log(x, y);
|
||||||
|
})
|
||||||
|
.done();
|
||||||
36
vendors/Q/examples/async-generators/0.html
vendored
Normal file
36
vendors/Q/examples/async-generators/0.html
vendored
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Q.async animation example</title>
|
||||||
|
<!--
|
||||||
|
Works in browsers that support ES6 geneartors, like Chromium 29 with
|
||||||
|
the --harmony flag.
|
||||||
|
|
||||||
|
Peter Hallam, Tom van Cutsem, Mark S. Miller, Dave Herman, Andy Wingo.
|
||||||
|
The animation example was taken from
|
||||||
|
<http://wiki.ecmascript.org/doku.php?id=strawman:deferred_functions>
|
||||||
|
-->
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="box" style="width: 20px; height: 20px; background-color: red;"></div>
|
||||||
|
|
||||||
|
<script src="../../q.js"></script>
|
||||||
|
<script>
|
||||||
|
(function () {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var deferredAnimate = Q.async(function* (element) {
|
||||||
|
for (var i = 0; i < 100; ++i) {
|
||||||
|
element.style.marginLeft = i + "px";
|
||||||
|
yield Q.delay(20);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Q.spawn(function* () {
|
||||||
|
yield deferredAnimate(document.getElementById("box"));
|
||||||
|
alert("Done!");
|
||||||
|
});
|
||||||
|
}());
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
19
vendors/Q/examples/async-generators/1-return.js
vendored
Normal file
19
vendors/Q/examples/async-generators/1-return.js
vendored
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var Q = require("../../q");
|
||||||
|
|
||||||
|
var generator = Q.async(function* () {
|
||||||
|
var ten = yield 10;
|
||||||
|
console.log(ten, 10);
|
||||||
|
var twenty = yield ten + 10;
|
||||||
|
console.log(twenty, 20);
|
||||||
|
var thirty = yield twenty + 10;
|
||||||
|
console.log(thirty, 30);
|
||||||
|
return thirty + 10;
|
||||||
|
});
|
||||||
|
|
||||||
|
generator().then(function (forty) {
|
||||||
|
console.log(forty, 40);
|
||||||
|
}, function (reason) {
|
||||||
|
console.log("reason", reason);
|
||||||
|
});
|
||||||
21
vendors/Q/examples/async-generators/2-error-propagation.js
vendored
Normal file
21
vendors/Q/examples/async-generators/2-error-propagation.js
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var Q = require("../../q");
|
||||||
|
|
||||||
|
var generator = Q.async(function* () {
|
||||||
|
try {
|
||||||
|
var ten = yield Q.reject(new Error("Rejected!"));
|
||||||
|
console.log("Should not get here 1");
|
||||||
|
} catch (exception) {
|
||||||
|
console.log("Should get here 1");
|
||||||
|
console.log(exception.message, "should be", "Rejected!");
|
||||||
|
throw new Error("Threw!");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
generator().then(function () {
|
||||||
|
console.log("Should not get here 2");
|
||||||
|
}, function (reason) {
|
||||||
|
console.log("Should get here 2");
|
||||||
|
console.log(reason.message, "should be", "Threw!");
|
||||||
|
});
|
||||||
21
vendors/Q/examples/async-generators/3-spawn.js
vendored
Normal file
21
vendors/Q/examples/async-generators/3-spawn.js
vendored
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var Q = require("../../q");
|
||||||
|
|
||||||
|
function foo() {
|
||||||
|
return Q.delay(5, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
function bar() {
|
||||||
|
return Q.delay(10, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
Q.spawn(function* () {
|
||||||
|
var x = yield foo();
|
||||||
|
console.log(x);
|
||||||
|
|
||||||
|
var y = yield bar();
|
||||||
|
console.log(y);
|
||||||
|
|
||||||
|
console.log("result", x + y);
|
||||||
|
});
|
||||||
42
vendors/Q/examples/async-generators/4-flow-control.js
vendored
Normal file
42
vendors/Q/examples/async-generators/4-flow-control.js
vendored
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var Q = require("../../q");
|
||||||
|
|
||||||
|
// We get back blocking semantics: can use promises with `if`, `while`, `for`,
|
||||||
|
// etc.
|
||||||
|
var filter = Q.async(function* (promises, test) {
|
||||||
|
var results = [];
|
||||||
|
for (var i = 0; i < promises.length; i++) {
|
||||||
|
var val = yield promises[i];
|
||||||
|
if (test(val)) {
|
||||||
|
results.push(val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
});
|
||||||
|
|
||||||
|
var promises = [
|
||||||
|
Q.delay("a", 500),
|
||||||
|
Q.delay("d", 1000),
|
||||||
|
Q("l")
|
||||||
|
];
|
||||||
|
|
||||||
|
filter(promises, function (letter) {
|
||||||
|
return "f" > letter;
|
||||||
|
}).done(function (all) {
|
||||||
|
console.log(all); // [ "a", "d" ]
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// we can use try and catch to handle rejected promises
|
||||||
|
var logRejections = Q.async(function* (work) {
|
||||||
|
try {
|
||||||
|
yield work;
|
||||||
|
console.log("Never end up here");
|
||||||
|
} catch (e) {
|
||||||
|
console.log("Caught:", e.message);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var rejection = Q.reject(new Error("Oh dear"));
|
||||||
|
logRejections(rejection); // Caught: Oh dear
|
||||||
66
vendors/Q/examples/async-generators/README.md
vendored
Normal file
66
vendors/Q/examples/async-generators/README.md
vendored
Normal file
|
|
@ -0,0 +1,66 @@
|
||||||
|
:warning: Warning: The behavior described here is likely to be quickly
|
||||||
|
obseleted by developments in standardization and implementation. Tread with
|
||||||
|
care.
|
||||||
|
|
||||||
|
Q has an `async` function. This can be used to decorate a generator function
|
||||||
|
such that `yield` is effectively equivalent to `await` or `defer` syntax as
|
||||||
|
supported by languages like Go and C# 5.
|
||||||
|
|
||||||
|
Generator functions are presently on the standards track for ES6. As of July
|
||||||
|
2013, they are only fully supported by bleeding edge V8, which hasn't made it
|
||||||
|
out to a released Chromium yet but will probably be in Chromium 29. Even then,
|
||||||
|
they must be enabled from [chrome://flags](chrome://flags) as "Experimental
|
||||||
|
JavaScript features." SpiderMonkey (used in Firefox) includes an older style of
|
||||||
|
generators, but these are not supported by Q.
|
||||||
|
|
||||||
|
Here's an example of using generators by themselves, without any Q features:
|
||||||
|
|
||||||
|
```js
|
||||||
|
function* count() {
|
||||||
|
var i = 0;
|
||||||
|
while (true) {
|
||||||
|
yield i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var counter = count();
|
||||||
|
counter.next().value === 0;
|
||||||
|
counter.next().value === 1;
|
||||||
|
counter.next().value === 2;
|
||||||
|
```
|
||||||
|
|
||||||
|
`yield` can also return a value, if the `next` method of the generator is
|
||||||
|
called with a parameter:
|
||||||
|
|
||||||
|
```js
|
||||||
|
var buffer = (function* () {
|
||||||
|
var x;
|
||||||
|
while (true) {
|
||||||
|
x = yield x;
|
||||||
|
}
|
||||||
|
}());
|
||||||
|
|
||||||
|
buffer.next(1).value === undefined;
|
||||||
|
buffer.next("a").value === 1;
|
||||||
|
buffer.value(2).value === "a";
|
||||||
|
buffer.next().value === 2;
|
||||||
|
buffer.next().value === undefined;
|
||||||
|
buffer.next().value === undefined;
|
||||||
|
```
|
||||||
|
|
||||||
|
Inside functions wrapped with `Q.async`, we can use `yield` to wait for a
|
||||||
|
promise to settle:
|
||||||
|
|
||||||
|
```js
|
||||||
|
var eventualAdd = Q.async(function* (oneP, twoP) {
|
||||||
|
var one = yield oneP;
|
||||||
|
var two = yield twoP;
|
||||||
|
return one + two;
|
||||||
|
});
|
||||||
|
|
||||||
|
eventualAdd(eventualOne, eventualTwo).then(function (three) {
|
||||||
|
three === 3;
|
||||||
|
});
|
||||||
|
```
|
||||||
|
You can see more examples of how this works, as well as the `Q.spawn` function,
|
||||||
|
in the other files in this folder.
|
||||||
79
vendors/Q/package.json
vendored
Normal file
79
vendors/Q/package.json
vendored
Normal file
|
|
@ -0,0 +1,79 @@
|
||||||
|
{
|
||||||
|
"name": "q",
|
||||||
|
"version": "1.1.2",
|
||||||
|
"description": "A library for promises (CommonJS/Promises/A,B,D)",
|
||||||
|
"homepage": "https://github.com/kriskowal/q",
|
||||||
|
"author": "Kris Kowal <kris@cixar.com> (https://github.com/kriskowal)",
|
||||||
|
"keywords": [
|
||||||
|
"q",
|
||||||
|
"promise",
|
||||||
|
"promises",
|
||||||
|
"promises-a",
|
||||||
|
"promises-aplus",
|
||||||
|
"deferred",
|
||||||
|
"future",
|
||||||
|
"async",
|
||||||
|
"flow control",
|
||||||
|
"fluent",
|
||||||
|
"browser",
|
||||||
|
"node"
|
||||||
|
],
|
||||||
|
"contributors": [
|
||||||
|
"Kris Kowal <kris@cixar.com> (https://github.com/kriskowal)",
|
||||||
|
"Irakli Gozalishvili <rfobic@gmail.com> (http://jeditoolkit.com)",
|
||||||
|
"Domenic Denicola <domenic@domenicdenicola.com> (http://domenicdenicola.com)"
|
||||||
|
],
|
||||||
|
"bugs": {
|
||||||
|
"mail": "kris@cixar.com",
|
||||||
|
"url": "http://github.com/kriskowal/q/issues"
|
||||||
|
},
|
||||||
|
"license": {
|
||||||
|
"type": "MIT",
|
||||||
|
"url": "http://github.com/kriskowal/q/raw/master/LICENSE"
|
||||||
|
},
|
||||||
|
"main": "q.js",
|
||||||
|
"files": [
|
||||||
|
"LICENSE",
|
||||||
|
"q.js",
|
||||||
|
"queue.js"
|
||||||
|
],
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git://github.com/kriskowal/q.git"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.6.0",
|
||||||
|
"teleport": ">=0.2.0"
|
||||||
|
},
|
||||||
|
"dependencies": {},
|
||||||
|
"devDependencies": {
|
||||||
|
"jshint": "~2.1.9",
|
||||||
|
"cover": "*",
|
||||||
|
"jasmine-node": "1.11.0",
|
||||||
|
"opener": "*",
|
||||||
|
"promises-aplus-tests": "1.x",
|
||||||
|
"grunt": "~0.4.1",
|
||||||
|
"grunt-cli": "~0.1.9",
|
||||||
|
"grunt-contrib-uglify": "~0.2.2",
|
||||||
|
"matcha": "~0.2.0"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"test": "jasmine-node spec && promises-aplus-tests spec/aplus-adapter",
|
||||||
|
"test-browser": "opener spec/q-spec.html",
|
||||||
|
"benchmark": "matcha",
|
||||||
|
"lint": "jshint q.js",
|
||||||
|
"cover": "cover run node_modules/jasmine-node/bin/jasmine-node spec && cover report html && opener cover_html/index.html",
|
||||||
|
"minify": "grunt",
|
||||||
|
"prepublish": "grunt"
|
||||||
|
},
|
||||||
|
"overlay": {
|
||||||
|
"teleport": {
|
||||||
|
"dependencies": {
|
||||||
|
"system": ">=0.0.4"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"directories": {
|
||||||
|
"test": "./spec"
|
||||||
|
}
|
||||||
|
}
|
||||||
1937
vendors/Q/q.js
vendored
Normal file
1937
vendors/Q/q.js
vendored
Normal file
File diff suppressed because it is too large
Load diff
BIN
vendors/Q/q.png
vendored
Normal file
BIN
vendors/Q/q.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 33 KiB |
114
vendors/Q/q.svg
vendored
Normal file
114
vendors/Q/q.svg
vendored
Normal file
|
|
@ -0,0 +1,114 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="157.5"
|
||||||
|
height="180"
|
||||||
|
id="svg2"
|
||||||
|
version="1.1"
|
||||||
|
inkscape:version="0.48.1 r9760"
|
||||||
|
sodipodi:docname="q.svg"
|
||||||
|
inkscape:export-filename="/home/kris/art/q.png"
|
||||||
|
inkscape:export-xdpi="51.200001"
|
||||||
|
inkscape:export-ydpi="51.200001">
|
||||||
|
<defs
|
||||||
|
id="defs4" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="2"
|
||||||
|
inkscape:cx="62.864072"
|
||||||
|
inkscape:cy="167.31214"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
showgrid="false"
|
||||||
|
units="in"
|
||||||
|
inkscape:window-width="1680"
|
||||||
|
inkscape:window-height="973"
|
||||||
|
inkscape:window-x="0"
|
||||||
|
inkscape:window-y="24"
|
||||||
|
inkscape:window-maximized="1" />
|
||||||
|
<metadata
|
||||||
|
id="metadata7">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title></dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1"
|
||||||
|
transform="translate(0,-872.3622)">
|
||||||
|
<path
|
||||||
|
sodipodi:type="star"
|
||||||
|
style="fill:#f9df34;fill-opacity:1;stroke:none;opacity:1"
|
||||||
|
id="path3833"
|
||||||
|
sodipodi:sides="6"
|
||||||
|
sodipodi:cx="1118"
|
||||||
|
sodipodi:cy="456.36218"
|
||||||
|
sodipodi:r1="277.59683"
|
||||||
|
sodipodi:r2="240.40591"
|
||||||
|
sodipodi:arg1="0.52359878"
|
||||||
|
sodipodi:arg2="1.0471976"
|
||||||
|
inkscape:flatsided="true"
|
||||||
|
inkscape:rounded="0"
|
||||||
|
inkscape:randomized="0"
|
||||||
|
d="M 1358.4059,595.1606 1118,733.95901 877.59409,595.1606 l 0,-277.59683 L 1118,178.76535 1358.4059,317.56377 z"
|
||||||
|
transform="matrix(0.28609737,0,0,0.28609737,-241.10686,831.79819)" />
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path3840"
|
||||||
|
d="m 23.150536,930.17141 c 0.02584,21.44054 0.05616,42.88112 0.0266,64.32167 18.544384,10.71192 37.074475,21.44862 55.599461,32.19412 18.524303,-10.7114 37.048573,-21.4227 55.572863,-32.13419 -0.0259,-21.44055 -0.0561,-42.88112 -0.0266,-64.32168 C 115.77802,919.52027 97.24878,908.78212 78.723431,898.0372 60.199152,908.74861 41.674869,919.46002 23.150565,930.17141 z m 55.792247,-8.92728 c 11.80936,6.85273 23.635797,13.68573 35.470907,20.49746 -0.004,13.75374 -0.009,27.50747 -0.0132,41.2612 -3.04307,1.75007 -6.08198,3.50751 -9.12033,5.26584 -6.092341,-10.55513 -12.176786,-21.11483 -18.260622,-31.67487 -5.796593,3.34635 -11.593186,6.69268 -17.389782,10.03903 6.083829,10.56004 12.168276,21.11974 18.260615,31.67487 -3.035798,1.77164 -6.093381,3.50564 -9.120329,5.29244 -11.883066,-6.88841 -23.778192,-13.75616 -35.676998,-20.61727 0.0022,-13.75374 0.0045,-27.50747 0.0066,-41.2612 11.884425,-6.85251 23.763957,-13.71376 35.630451,-20.59733 l 0.185407,0.10445 0.02732,0.0154 z"
|
||||||
|
style="fill:#b7a634;fill-opacity:1;stroke:#524839;stroke-width:5.37970828999999995;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;opacity:0.96" />
|
||||||
|
<path
|
||||||
|
style="fill:#f9df34;fill-opacity:1;stroke:#524839;stroke-width:5.54999999999999982;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||||
|
d="m 3.9712996,919.13021 c 0.034761,28.79449 0.07553,57.58902 0.035762,86.38349 24.9413394,14.3861 49.8634534,28.8054 74.7787004,43.2365 24.914328,-14.3853 49.828638,-28.7707 74.742938,-43.156 -0.0347,-28.79449 -0.0755,-57.58901 -0.0358,-86.38352 -24.942,-14.38487 -49.86297,-28.80613 -74.778703,-43.23647 -24.914303,14.38534 -49.828606,28.77067 -74.7429375,43.156 z M 79.00929,907.14095 c 15.883039,9.20316 31.78905,18.37981 47.70674,27.52793 -0.006,18.47116 -0.0123,36.94232 -0.0177,55.41348 -4.0928,2.35032 -8.17998,4.71056 -12.26643,7.07197 -8.19391,-14.17545 -16.377211,-28.35704 -24.559682,-42.5391 -7.796153,4.49411 -15.592307,8.98822 -23.38846,13.48234 8.182471,14.18206 16.365771,28.36365 24.559685,42.53913 -4.08301,2.3792 -8.195316,4.7081 -12.266424,7.1077 -15.982172,-9.2511 -31.980565,-18.47444 -47.983908,-27.68886 0.0029,-18.47116 0.006,-36.94232 0.0089,-55.41348 15.984003,-9.20286 31.961425,-18.41747 47.92131,-27.66204 l 0.249362,0.14026 0.03674,0.0207 z"
|
||||||
|
id="path2993"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<g
|
||||||
|
id="g4862"
|
||||||
|
transform="matrix(0.11775097,-0.06798356,0.06798356,0.11775097,5.1642661,919.0661)">
|
||||||
|
<path
|
||||||
|
style="fill:#524739"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
d="m 217.503,388.691 v 14.757 h -16.155 v 39.766 c 0,3.729 0.621,6.214 1.864,7.457 1.243,1.242 3.728,1.863 7.456,1.863 1.243,0 2.432,-0.051 3.573,-0.155 1.138,-0.102 2.226,-0.257 3.262,-0.466 V 469 c -1.864,0.311 -3.937,0.517 -6.213,0.621 -2.279,0.103 -4.505,0.155 -6.68,0.155 -3.417,0 -6.655,-0.232 -9.708,-0.698 -3.056,-0.467 -5.747,-1.372 -8.077,-2.719 -2.33,-1.345 -4.17,-3.262 -5.515,-5.747 -1.347,-2.485 -2.019,-5.748 -2.019,-9.786 v -47.378 h -13.359 v -14.757 h 13.359 v -24.077 h 22.058 v 24.077 h 16.154 z"
|
||||||
|
id="path4864" />
|
||||||
|
|
||||||
|
<path
|
||||||
|
style="fill:#524739"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
d="m 248.569,358.091 v 41.785 h 0.466 c 2.796,-4.66 6.369,-8.051 10.718,-10.175 4.349,-2.121 8.594,-3.185 12.737,-3.185 5.903,0 10.742,0.804 14.524,2.408 3.778,1.606 6.757,3.832 8.932,6.68 2.175,2.849 3.701,6.317 4.582,10.407 0.879,4.092 1.32,8.621 1.32,13.592 V 469 H 279.79 v -45.357 c 0,-6.627 -1.036,-11.573 -3.106,-14.835 -2.073,-3.262 -5.747,-4.894 -11.029,-4.894 -6.007,0 -10.356,1.787 -13.048,5.359 -2.694,3.573 -4.039,9.451 -4.039,17.631 V 469 H 226.51 V 358.091 h 22.059 z"
|
||||||
|
id="path4866" />
|
||||||
|
|
||||||
|
<path
|
||||||
|
style="fill:#524739"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
d="m 334.467,449.738 c 3.313,3.211 8.077,4.815 14.291,4.815 4.451,0 8.283,-1.111 11.495,-3.34 3.208,-2.226 5.177,-4.582 5.902,-7.067 h 19.417 c -3.106,9.631 -7.871,16.519 -14.291,20.659 -6.422,4.144 -14.188,6.214 -23.3,6.214 -6.318,0 -12.015,-1.01 -17.087,-3.029 -5.075,-2.02 -9.374,-4.893 -12.894,-8.621 -3.521,-3.728 -6.24,-8.18 -8.154,-13.358 -1.918,-5.178 -2.874,-10.874 -2.874,-17.087 0,-6.005 0.982,-11.597 2.951,-16.776 1.966,-5.177 4.762,-9.655 8.388,-13.437 3.624,-3.779 7.947,-6.757 12.971,-8.932 5.021,-2.175 10.587,-3.263 16.699,-3.263 6.834,0 12.788,1.32 17.863,3.962 5.072,2.641 9.242,6.188 12.504,10.64 3.263,4.454 5.617,9.529 7.068,15.224 1.449,5.696 1.966,11.649 1.553,17.863 H 329.03 c 0.311,7.146 2.121,12.325 5.437,15.533 z m 24.931,-42.251 c -2.641,-2.898 -6.655,-4.35 -12.039,-4.35 -3.521,0 -6.446,0.598 -8.776,1.786 -2.33,1.192 -4.193,2.668 -5.592,4.428 -1.398,1.762 -2.384,3.626 -2.951,5.592 -0.57,1.969 -0.908,3.728 -1.01,5.281 h 35.882 c -1.036,-5.591 -2.873,-9.836 -5.514,-12.737 z"
|
||||||
|
id="path4868" />
|
||||||
|
|
||||||
|
<path
|
||||||
|
style="fill:#524739"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
d="m 413.221,388.691 v 11.185 h 0.466 c 2.796,-4.66 6.42,-8.051 10.874,-10.175 4.451,-2.121 9.009,-3.185 13.669,-3.185 5.903,0 10.742,0.804 14.524,2.408 3.778,1.606 6.757,3.832 8.932,6.68 2.175,2.849 3.701,6.317 4.582,10.407 0.879,4.092 1.32,8.621 1.32,13.592 V 469 H 445.53 v -45.357 c 0,-6.627 -1.036,-11.573 -3.106,-14.835 -2.073,-3.262 -5.747,-4.894 -11.029,-4.894 -6.007,0 -10.356,1.787 -13.048,5.359 -2.694,3.573 -4.039,9.451 -4.039,17.631 V 469 H 392.25 v -80.309 h 20.971 z"
|
||||||
|
id="path4870" />
|
||||||
|
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 7.6 KiB |
35
vendors/Q/queue.js
vendored
Normal file
35
vendors/Q/queue.js
vendored
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
|
||||||
|
var Q = require("./q");
|
||||||
|
|
||||||
|
module.exports = Queue;
|
||||||
|
function Queue() {
|
||||||
|
var ends = Q.defer();
|
||||||
|
var closed = Q.defer();
|
||||||
|
return {
|
||||||
|
put: function (value) {
|
||||||
|
var next = Q.defer();
|
||||||
|
ends.resolve({
|
||||||
|
head: value,
|
||||||
|
tail: next.promise
|
||||||
|
});
|
||||||
|
ends.resolve = next.resolve;
|
||||||
|
},
|
||||||
|
get: function () {
|
||||||
|
var result = ends.promise.get("head");
|
||||||
|
ends.promise = ends.promise.get("tail");
|
||||||
|
return result.fail(function (error) {
|
||||||
|
closed.resolve(error);
|
||||||
|
throw error;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
closed: closed.promise,
|
||||||
|
close: function (error) {
|
||||||
|
error = error || new Error("Can't get value from closed queue");
|
||||||
|
var end = {head: Q.reject(error)};
|
||||||
|
end.tail = end;
|
||||||
|
ends.resolve(end);
|
||||||
|
return closed.promise;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
26
vendors/Q/ref_send.md
vendored
Normal file
26
vendors/Q/ref_send.md
vendored
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
|
||||||
|
This API varies from Tyler Closes ref_send in the
|
||||||
|
following ways:
|
||||||
|
|
||||||
|
* Promises can be resolved to function values.
|
||||||
|
* Promises can be resolved to null or undefined.
|
||||||
|
* Promises are distinguishable from arbitrary functions.
|
||||||
|
* The promise API is abstracted with a Promise constructor
|
||||||
|
that accepts a descriptor that receives all of the
|
||||||
|
messages forwarded to that promise and handles the
|
||||||
|
common patterns for message receivers. The promise
|
||||||
|
constructor also takes optional fallback and valueOf
|
||||||
|
methods which handle the cases for missing handlers on
|
||||||
|
the descriptor (rejection by default) and the valueOf
|
||||||
|
call (which returns the promise itself by default)
|
||||||
|
* near(ref) has been changed to Promise.valueOf() in
|
||||||
|
keeping with JavaScript's existing Object.valueOf().
|
||||||
|
* post(promise, name, args) has been altered to a variadic
|
||||||
|
post(promise, name ...args)
|
||||||
|
* variadic arguments are used internally where
|
||||||
|
applicable. However, I have not altered the Q.post()
|
||||||
|
API to expand variadic arguments since Tyler Close
|
||||||
|
informed the CommonJS list that it would restrict
|
||||||
|
usage patterns for web_send, posting arbitrary JSON
|
||||||
|
objects as the "arguments" over HTTP.
|
||||||
|
|
||||||
15
vendors/Q/spec/aplus-adapter.js
vendored
Normal file
15
vendors/Q/spec/aplus-adapter.js
vendored
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var Q = require("../q");
|
||||||
|
|
||||||
|
exports.fulfilled = Q.resolve;
|
||||||
|
exports.rejected = Q.reject;
|
||||||
|
exports.pending = function () {
|
||||||
|
var deferred = Q.defer();
|
||||||
|
|
||||||
|
return {
|
||||||
|
promise: deferred.promise,
|
||||||
|
fulfill: deferred.resolve,
|
||||||
|
reject: deferred.reject
|
||||||
|
};
|
||||||
|
};
|
||||||
20
vendors/Q/spec/lib/jasmine-1.2.0/MIT.LICENSE
vendored
Normal file
20
vendors/Q/spec/lib/jasmine-1.2.0/MIT.LICENSE
vendored
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
Copyright (c) 2008-2011 Pivotal Labs
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of this software and associated documentation files (the
|
||||||
|
"Software"), to deal in the Software without restriction, including
|
||||||
|
without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be
|
||||||
|
included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
616
vendors/Q/spec/lib/jasmine-1.2.0/jasmine-html.js
vendored
Normal file
616
vendors/Q/spec/lib/jasmine-1.2.0/jasmine-html.js
vendored
Normal file
|
|
@ -0,0 +1,616 @@
|
||||||
|
jasmine.HtmlReporterHelpers = {};
|
||||||
|
|
||||||
|
jasmine.HtmlReporterHelpers.createDom = function(type, attrs, childrenVarArgs) {
|
||||||
|
var el = document.createElement(type);
|
||||||
|
|
||||||
|
for (var i = 2; i < arguments.length; i++) {
|
||||||
|
var child = arguments[i];
|
||||||
|
|
||||||
|
if (typeof child === 'string') {
|
||||||
|
el.appendChild(document.createTextNode(child));
|
||||||
|
} else {
|
||||||
|
if (child) {
|
||||||
|
el.appendChild(child);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var attr in attrs) {
|
||||||
|
if (attr == "className") {
|
||||||
|
el[attr] = attrs[attr];
|
||||||
|
} else {
|
||||||
|
el.setAttribute(attr, attrs[attr]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return el;
|
||||||
|
};
|
||||||
|
|
||||||
|
jasmine.HtmlReporterHelpers.getSpecStatus = function(child) {
|
||||||
|
var results = child.results();
|
||||||
|
var status = results.passed() ? 'passed' : 'failed';
|
||||||
|
if (results.skipped) {
|
||||||
|
status = 'skipped';
|
||||||
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
|
};
|
||||||
|
|
||||||
|
jasmine.HtmlReporterHelpers.appendToSummary = function(child, childElement) {
|
||||||
|
var parentDiv = this.dom.summary;
|
||||||
|
var parentSuite = (typeof child.parentSuite == 'undefined') ? 'suite' : 'parentSuite';
|
||||||
|
var parent = child[parentSuite];
|
||||||
|
|
||||||
|
if (parent) {
|
||||||
|
if (typeof this.views.suites[parent.id] == 'undefined') {
|
||||||
|
this.views.suites[parent.id] = new jasmine.HtmlReporter.SuiteView(parent, this.dom, this.views);
|
||||||
|
}
|
||||||
|
parentDiv = this.views.suites[parent.id].element;
|
||||||
|
}
|
||||||
|
|
||||||
|
parentDiv.appendChild(childElement);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
jasmine.HtmlReporterHelpers.addHelpers = function(ctor) {
|
||||||
|
for(var fn in jasmine.HtmlReporterHelpers) {
|
||||||
|
ctor.prototype[fn] = jasmine.HtmlReporterHelpers[fn];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
jasmine.HtmlReporter = function(_doc) {
|
||||||
|
var self = this;
|
||||||
|
var doc = _doc || window.document;
|
||||||
|
|
||||||
|
var reporterView;
|
||||||
|
|
||||||
|
var dom = {};
|
||||||
|
|
||||||
|
// Jasmine Reporter Public Interface
|
||||||
|
self.logRunningSpecs = false;
|
||||||
|
|
||||||
|
self.reportRunnerStarting = function(runner) {
|
||||||
|
var specs = runner.specs() || [];
|
||||||
|
|
||||||
|
if (specs.length == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
createReporterDom(runner.env.versionString());
|
||||||
|
doc.body.appendChild(dom.reporter);
|
||||||
|
|
||||||
|
reporterView = new jasmine.HtmlReporter.ReporterView(dom);
|
||||||
|
reporterView.addSpecs(specs, self.specFilter);
|
||||||
|
};
|
||||||
|
|
||||||
|
self.reportRunnerResults = function(runner) {
|
||||||
|
reporterView && reporterView.complete();
|
||||||
|
};
|
||||||
|
|
||||||
|
self.reportSuiteResults = function(suite) {
|
||||||
|
reporterView.suiteComplete(suite);
|
||||||
|
};
|
||||||
|
|
||||||
|
self.reportSpecStarting = function(spec) {
|
||||||
|
if (self.logRunningSpecs) {
|
||||||
|
self.log('>> Jasmine Running ' + spec.suite.description + ' ' + spec.description + '...');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
self.reportSpecResults = function(spec) {
|
||||||
|
reporterView.specComplete(spec);
|
||||||
|
};
|
||||||
|
|
||||||
|
self.log = function() {
|
||||||
|
var console = jasmine.getGlobal().console;
|
||||||
|
if (console && console.log) {
|
||||||
|
if (console.log.apply) {
|
||||||
|
console.log.apply(console, arguments);
|
||||||
|
} else {
|
||||||
|
console.log(arguments); // ie fix: console.log.apply doesn't exist on ie
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
self.specFilter = function(spec) {
|
||||||
|
if (!focusedSpecName()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return spec.getFullName().indexOf(focusedSpecName()) === 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
return self;
|
||||||
|
|
||||||
|
function focusedSpecName() {
|
||||||
|
var specName;
|
||||||
|
|
||||||
|
(function memoizeFocusedSpec() {
|
||||||
|
if (specName) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var paramMap = [];
|
||||||
|
var params = doc.location.search.substring(1).split('&');
|
||||||
|
|
||||||
|
for (var i = 0; i < params.length; i++) {
|
||||||
|
var p = params[i].split('=');
|
||||||
|
paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
specName = paramMap.spec;
|
||||||
|
})();
|
||||||
|
|
||||||
|
return specName;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createReporterDom(version) {
|
||||||
|
dom.reporter = self.createDom('div', { id: 'HTMLReporter', className: 'jasmine_reporter' },
|
||||||
|
dom.banner = self.createDom('div', { className: 'banner' },
|
||||||
|
self.createDom('span', { className: 'title' }, "Jasmine "),
|
||||||
|
self.createDom('span', { className: 'version' }, version)),
|
||||||
|
|
||||||
|
dom.symbolSummary = self.createDom('ul', {className: 'symbolSummary'}),
|
||||||
|
dom.alert = self.createDom('div', {className: 'alert'}),
|
||||||
|
dom.results = self.createDom('div', {className: 'results'},
|
||||||
|
dom.summary = self.createDom('div', { className: 'summary' }),
|
||||||
|
dom.details = self.createDom('div', { id: 'details' }))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter);jasmine.HtmlReporter.ReporterView = function(dom) {
|
||||||
|
this.startedAt = new Date();
|
||||||
|
this.runningSpecCount = 0;
|
||||||
|
this.completeSpecCount = 0;
|
||||||
|
this.passedCount = 0;
|
||||||
|
this.failedCount = 0;
|
||||||
|
this.skippedCount = 0;
|
||||||
|
|
||||||
|
this.createResultsMenu = function() {
|
||||||
|
this.resultsMenu = this.createDom('span', {className: 'resultsMenu bar'},
|
||||||
|
this.summaryMenuItem = this.createDom('a', {className: 'summaryMenuItem', href: "#"}, '0 specs'),
|
||||||
|
' | ',
|
||||||
|
this.detailsMenuItem = this.createDom('a', {className: 'detailsMenuItem', href: "#"}, '0 failing'));
|
||||||
|
|
||||||
|
this.summaryMenuItem.onclick = function() {
|
||||||
|
dom.reporter.className = dom.reporter.className.replace(/ showDetails/g, '');
|
||||||
|
};
|
||||||
|
|
||||||
|
this.detailsMenuItem.onclick = function() {
|
||||||
|
showDetails();
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
this.addSpecs = function(specs, specFilter) {
|
||||||
|
this.totalSpecCount = specs.length;
|
||||||
|
|
||||||
|
this.views = {
|
||||||
|
specs: {},
|
||||||
|
suites: {}
|
||||||
|
};
|
||||||
|
|
||||||
|
for (var i = 0; i < specs.length; i++) {
|
||||||
|
var spec = specs[i];
|
||||||
|
this.views.specs[spec.id] = new jasmine.HtmlReporter.SpecView(spec, dom, this.views);
|
||||||
|
if (specFilter(spec)) {
|
||||||
|
this.runningSpecCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.specComplete = function(spec) {
|
||||||
|
this.completeSpecCount++;
|
||||||
|
|
||||||
|
if (isUndefined(this.views.specs[spec.id])) {
|
||||||
|
this.views.specs[spec.id] = new jasmine.HtmlReporter.SpecView(spec, dom);
|
||||||
|
}
|
||||||
|
|
||||||
|
var specView = this.views.specs[spec.id];
|
||||||
|
|
||||||
|
switch (specView.status()) {
|
||||||
|
case 'passed':
|
||||||
|
this.passedCount++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'failed':
|
||||||
|
this.failedCount++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'skipped':
|
||||||
|
this.skippedCount++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
specView.refresh();
|
||||||
|
this.refresh();
|
||||||
|
};
|
||||||
|
|
||||||
|
this.suiteComplete = function(suite) {
|
||||||
|
var suiteView = this.views.suites[suite.id];
|
||||||
|
if (isUndefined(suiteView)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
suiteView.refresh();
|
||||||
|
};
|
||||||
|
|
||||||
|
this.refresh = function() {
|
||||||
|
|
||||||
|
if (isUndefined(this.resultsMenu)) {
|
||||||
|
this.createResultsMenu();
|
||||||
|
}
|
||||||
|
|
||||||
|
// currently running UI
|
||||||
|
if (isUndefined(this.runningAlert)) {
|
||||||
|
this.runningAlert = this.createDom('a', {href: "?", className: "runningAlert bar"});
|
||||||
|
dom.alert.appendChild(this.runningAlert);
|
||||||
|
}
|
||||||
|
this.runningAlert.innerHTML = "Running " + this.completeSpecCount + " of " + specPluralizedFor(this.totalSpecCount);
|
||||||
|
|
||||||
|
// skipped specs UI
|
||||||
|
if (isUndefined(this.skippedAlert)) {
|
||||||
|
this.skippedAlert = this.createDom('a', {href: "?", className: "skippedAlert bar"});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.skippedAlert.innerHTML = "Skipping " + this.skippedCount + " of " + specPluralizedFor(this.totalSpecCount) + " - run all";
|
||||||
|
|
||||||
|
if (this.skippedCount === 1 && isDefined(dom.alert)) {
|
||||||
|
dom.alert.appendChild(this.skippedAlert);
|
||||||
|
}
|
||||||
|
|
||||||
|
// passing specs UI
|
||||||
|
if (isUndefined(this.passedAlert)) {
|
||||||
|
this.passedAlert = this.createDom('span', {href: "?", className: "passingAlert bar"});
|
||||||
|
}
|
||||||
|
this.passedAlert.innerHTML = "Passing " + specPluralizedFor(this.passedCount);
|
||||||
|
|
||||||
|
// failing specs UI
|
||||||
|
if (isUndefined(this.failedAlert)) {
|
||||||
|
this.failedAlert = this.createDom('span', {href: "?", className: "failingAlert bar"});
|
||||||
|
}
|
||||||
|
this.failedAlert.innerHTML = "Failing " + specPluralizedFor(this.failedCount);
|
||||||
|
|
||||||
|
if (this.failedCount === 1 && isDefined(dom.alert)) {
|
||||||
|
dom.alert.appendChild(this.failedAlert);
|
||||||
|
dom.alert.appendChild(this.resultsMenu);
|
||||||
|
}
|
||||||
|
|
||||||
|
// summary info
|
||||||
|
this.summaryMenuItem.innerHTML = "" + specPluralizedFor(this.runningSpecCount);
|
||||||
|
this.detailsMenuItem.innerHTML = "" + this.failedCount + " failing";
|
||||||
|
};
|
||||||
|
|
||||||
|
this.complete = function() {
|
||||||
|
dom.alert.removeChild(this.runningAlert);
|
||||||
|
|
||||||
|
this.skippedAlert.innerHTML = "Ran " + this.runningSpecCount + " of " + specPluralizedFor(this.totalSpecCount) + " - run all";
|
||||||
|
|
||||||
|
if (this.failedCount === 0) {
|
||||||
|
dom.alert.appendChild(this.createDom('span', {className: 'passingAlert bar'}, "Passing " + specPluralizedFor(this.passedCount)));
|
||||||
|
} else {
|
||||||
|
showDetails();
|
||||||
|
}
|
||||||
|
|
||||||
|
dom.banner.appendChild(this.createDom('span', {className: 'duration'}, "finished in " + ((new Date().getTime() - this.startedAt.getTime()) / 1000) + "s"));
|
||||||
|
};
|
||||||
|
|
||||||
|
return this;
|
||||||
|
|
||||||
|
function showDetails() {
|
||||||
|
if (dom.reporter.className.search(/showDetails/) === -1) {
|
||||||
|
dom.reporter.className += " showDetails";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function isUndefined(obj) {
|
||||||
|
return typeof obj === 'undefined';
|
||||||
|
}
|
||||||
|
|
||||||
|
function isDefined(obj) {
|
||||||
|
return !isUndefined(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
function specPluralizedFor(count) {
|
||||||
|
var str = count + " spec";
|
||||||
|
if (count > 1) {
|
||||||
|
str += "s"
|
||||||
|
}
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter.ReporterView);
|
||||||
|
|
||||||
|
|
||||||
|
jasmine.HtmlReporter.SpecView = function(spec, dom, views) {
|
||||||
|
this.spec = spec;
|
||||||
|
this.dom = dom;
|
||||||
|
this.views = views;
|
||||||
|
|
||||||
|
this.symbol = this.createDom('li', { className: 'pending' });
|
||||||
|
this.dom.symbolSummary.appendChild(this.symbol);
|
||||||
|
|
||||||
|
this.summary = this.createDom('div', { className: 'specSummary' },
|
||||||
|
this.createDom('a', {
|
||||||
|
className: 'description',
|
||||||
|
href: '?spec=' + encodeURIComponent(this.spec.getFullName()),
|
||||||
|
title: this.spec.getFullName()
|
||||||
|
}, this.spec.description)
|
||||||
|
);
|
||||||
|
|
||||||
|
this.detail = this.createDom('div', { className: 'specDetail' },
|
||||||
|
this.createDom('a', {
|
||||||
|
className: 'description',
|
||||||
|
href: '?spec=' + encodeURIComponent(this.spec.getFullName()),
|
||||||
|
title: this.spec.getFullName()
|
||||||
|
}, this.spec.getFullName())
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
jasmine.HtmlReporter.SpecView.prototype.status = function() {
|
||||||
|
return this.getSpecStatus(this.spec);
|
||||||
|
};
|
||||||
|
|
||||||
|
jasmine.HtmlReporter.SpecView.prototype.refresh = function() {
|
||||||
|
this.symbol.className = this.status();
|
||||||
|
|
||||||
|
switch (this.status()) {
|
||||||
|
case 'skipped':
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'passed':
|
||||||
|
this.appendSummaryToSuiteDiv();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'failed':
|
||||||
|
this.appendSummaryToSuiteDiv();
|
||||||
|
this.appendFailureDetail();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
jasmine.HtmlReporter.SpecView.prototype.appendSummaryToSuiteDiv = function() {
|
||||||
|
this.summary.className += ' ' + this.status();
|
||||||
|
this.appendToSummary(this.spec, this.summary);
|
||||||
|
};
|
||||||
|
|
||||||
|
jasmine.HtmlReporter.SpecView.prototype.appendFailureDetail = function() {
|
||||||
|
this.detail.className += ' ' + this.status();
|
||||||
|
|
||||||
|
var resultItems = this.spec.results().getItems();
|
||||||
|
var messagesDiv = this.createDom('div', { className: 'messages' });
|
||||||
|
|
||||||
|
for (var i = 0; i < resultItems.length; i++) {
|
||||||
|
var result = resultItems[i];
|
||||||
|
|
||||||
|
if (result.type == 'log') {
|
||||||
|
messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage log'}, result.toString()));
|
||||||
|
} else if (result.type == 'expect' && result.passed && !result.passed()) {
|
||||||
|
messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage fail'}, result.message));
|
||||||
|
|
||||||
|
if (result.trace.stack) {
|
||||||
|
messagesDiv.appendChild(this.createDom('div', {className: 'stackTrace'}, result.trace.stack));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (messagesDiv.childNodes.length > 0) {
|
||||||
|
this.detail.appendChild(messagesDiv);
|
||||||
|
this.dom.details.appendChild(this.detail);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter.SpecView);jasmine.HtmlReporter.SuiteView = function(suite, dom, views) {
|
||||||
|
this.suite = suite;
|
||||||
|
this.dom = dom;
|
||||||
|
this.views = views;
|
||||||
|
|
||||||
|
this.element = this.createDom('div', { className: 'suite' },
|
||||||
|
this.createDom('a', { className: 'description', href: '?spec=' + encodeURIComponent(this.suite.getFullName()) }, this.suite.description)
|
||||||
|
);
|
||||||
|
|
||||||
|
this.appendToSummary(this.suite, this.element);
|
||||||
|
};
|
||||||
|
|
||||||
|
jasmine.HtmlReporter.SuiteView.prototype.status = function() {
|
||||||
|
return this.getSpecStatus(this.suite);
|
||||||
|
};
|
||||||
|
|
||||||
|
jasmine.HtmlReporter.SuiteView.prototype.refresh = function() {
|
||||||
|
this.element.className += " " + this.status();
|
||||||
|
};
|
||||||
|
|
||||||
|
jasmine.HtmlReporterHelpers.addHelpers(jasmine.HtmlReporter.SuiteView);
|
||||||
|
|
||||||
|
/* @deprecated Use jasmine.HtmlReporter instead
|
||||||
|
*/
|
||||||
|
jasmine.TrivialReporter = function(doc) {
|
||||||
|
this.document = doc || document;
|
||||||
|
this.suiteDivs = {};
|
||||||
|
this.logRunningSpecs = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
jasmine.TrivialReporter.prototype.createDom = function(type, attrs, childrenVarArgs) {
|
||||||
|
var el = document.createElement(type);
|
||||||
|
|
||||||
|
for (var i = 2; i < arguments.length; i++) {
|
||||||
|
var child = arguments[i];
|
||||||
|
|
||||||
|
if (typeof child === 'string') {
|
||||||
|
el.appendChild(document.createTextNode(child));
|
||||||
|
} else {
|
||||||
|
if (child) { el.appendChild(child); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var attr in attrs) {
|
||||||
|
if (attr == "className") {
|
||||||
|
el[attr] = attrs[attr];
|
||||||
|
} else {
|
||||||
|
el.setAttribute(attr, attrs[attr]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return el;
|
||||||
|
};
|
||||||
|
|
||||||
|
jasmine.TrivialReporter.prototype.reportRunnerStarting = function(runner) {
|
||||||
|
var showPassed, showSkipped;
|
||||||
|
|
||||||
|
this.outerDiv = this.createDom('div', { id: 'TrivialReporter', className: 'jasmine_reporter' },
|
||||||
|
this.createDom('div', { className: 'banner' },
|
||||||
|
this.createDom('div', { className: 'logo' },
|
||||||
|
this.createDom('span', { className: 'title' }, "Jasmine"),
|
||||||
|
this.createDom('span', { className: 'version' }, runner.env.versionString())),
|
||||||
|
this.createDom('div', { className: 'options' },
|
||||||
|
"Show ",
|
||||||
|
showPassed = this.createDom('input', { id: "__jasmine_TrivialReporter_showPassed__", type: 'checkbox' }),
|
||||||
|
this.createDom('label', { "for": "__jasmine_TrivialReporter_showPassed__" }, " passed "),
|
||||||
|
showSkipped = this.createDom('input', { id: "__jasmine_TrivialReporter_showSkipped__", type: 'checkbox' }),
|
||||||
|
this.createDom('label', { "for": "__jasmine_TrivialReporter_showSkipped__" }, " skipped")
|
||||||
|
)
|
||||||
|
),
|
||||||
|
|
||||||
|
this.runnerDiv = this.createDom('div', { className: 'runner running' },
|
||||||
|
this.createDom('a', { className: 'run_spec', href: '?' }, "run all"),
|
||||||
|
this.runnerMessageSpan = this.createDom('span', {}, "Running..."),
|
||||||
|
this.finishedAtSpan = this.createDom('span', { className: 'finished-at' }, ""))
|
||||||
|
);
|
||||||
|
|
||||||
|
this.document.body.appendChild(this.outerDiv);
|
||||||
|
|
||||||
|
var suites = runner.suites();
|
||||||
|
for (var i = 0; i < suites.length; i++) {
|
||||||
|
var suite = suites[i];
|
||||||
|
var suiteDiv = this.createDom('div', { className: 'suite' },
|
||||||
|
this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, "run"),
|
||||||
|
this.createDom('a', { className: 'description', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, suite.description));
|
||||||
|
this.suiteDivs[suite.id] = suiteDiv;
|
||||||
|
var parentDiv = this.outerDiv;
|
||||||
|
if (suite.parentSuite) {
|
||||||
|
parentDiv = this.suiteDivs[suite.parentSuite.id];
|
||||||
|
}
|
||||||
|
parentDiv.appendChild(suiteDiv);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.startedAt = new Date();
|
||||||
|
|
||||||
|
var self = this;
|
||||||
|
showPassed.onclick = function(evt) {
|
||||||
|
if (showPassed.checked) {
|
||||||
|
self.outerDiv.className += ' show-passed';
|
||||||
|
} else {
|
||||||
|
self.outerDiv.className = self.outerDiv.className.replace(/ show-passed/, '');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
showSkipped.onclick = function(evt) {
|
||||||
|
if (showSkipped.checked) {
|
||||||
|
self.outerDiv.className += ' show-skipped';
|
||||||
|
} else {
|
||||||
|
self.outerDiv.className = self.outerDiv.className.replace(/ show-skipped/, '');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
jasmine.TrivialReporter.prototype.reportRunnerResults = function(runner) {
|
||||||
|
var results = runner.results();
|
||||||
|
var className = (results.failedCount > 0) ? "runner failed" : "runner passed";
|
||||||
|
this.runnerDiv.setAttribute("class", className);
|
||||||
|
//do it twice for IE
|
||||||
|
this.runnerDiv.setAttribute("className", className);
|
||||||
|
var specs = runner.specs();
|
||||||
|
var specCount = 0;
|
||||||
|
for (var i = 0; i < specs.length; i++) {
|
||||||
|
if (this.specFilter(specs[i])) {
|
||||||
|
specCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var message = "" + specCount + " spec" + (specCount == 1 ? "" : "s" ) + ", " + results.failedCount + " failure" + ((results.failedCount == 1) ? "" : "s");
|
||||||
|
message += " in " + ((new Date().getTime() - this.startedAt.getTime()) / 1000) + "s";
|
||||||
|
this.runnerMessageSpan.replaceChild(this.createDom('a', { className: 'description', href: '?'}, message), this.runnerMessageSpan.firstChild);
|
||||||
|
|
||||||
|
this.finishedAtSpan.appendChild(document.createTextNode("Finished at " + new Date().toString()));
|
||||||
|
};
|
||||||
|
|
||||||
|
jasmine.TrivialReporter.prototype.reportSuiteResults = function(suite) {
|
||||||
|
var results = suite.results();
|
||||||
|
var status = results.passed() ? 'passed' : 'failed';
|
||||||
|
if (results.totalCount === 0) { // todo: change this to check results.skipped
|
||||||
|
status = 'skipped';
|
||||||
|
}
|
||||||
|
this.suiteDivs[suite.id].className += " " + status;
|
||||||
|
};
|
||||||
|
|
||||||
|
jasmine.TrivialReporter.prototype.reportSpecStarting = function(spec) {
|
||||||
|
if (this.logRunningSpecs) {
|
||||||
|
this.log('>> Jasmine Running ' + spec.suite.description + ' ' + spec.description + '...');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
jasmine.TrivialReporter.prototype.reportSpecResults = function(spec) {
|
||||||
|
var results = spec.results();
|
||||||
|
var status = results.passed() ? 'passed' : 'failed';
|
||||||
|
if (results.skipped) {
|
||||||
|
status = 'skipped';
|
||||||
|
}
|
||||||
|
var specDiv = this.createDom('div', { className: 'spec ' + status },
|
||||||
|
this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(spec.getFullName()) }, "run"),
|
||||||
|
this.createDom('a', {
|
||||||
|
className: 'description',
|
||||||
|
href: '?spec=' + encodeURIComponent(spec.getFullName()),
|
||||||
|
title: spec.getFullName()
|
||||||
|
}, spec.description));
|
||||||
|
|
||||||
|
|
||||||
|
var resultItems = results.getItems();
|
||||||
|
var messagesDiv = this.createDom('div', { className: 'messages' });
|
||||||
|
for (var i = 0; i < resultItems.length; i++) {
|
||||||
|
var result = resultItems[i];
|
||||||
|
|
||||||
|
if (result.type == 'log') {
|
||||||
|
messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage log'}, result.toString()));
|
||||||
|
} else if (result.type == 'expect' && result.passed && !result.passed()) {
|
||||||
|
messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage fail'}, result.message));
|
||||||
|
|
||||||
|
if (result.trace.stack) {
|
||||||
|
messagesDiv.appendChild(this.createDom('div', {className: 'stackTrace'}, result.trace.stack));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (messagesDiv.childNodes.length > 0) {
|
||||||
|
specDiv.appendChild(messagesDiv);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.suiteDivs[spec.suite.id].appendChild(specDiv);
|
||||||
|
};
|
||||||
|
|
||||||
|
jasmine.TrivialReporter.prototype.log = function() {
|
||||||
|
var console = jasmine.getGlobal().console;
|
||||||
|
if (console && console.log) {
|
||||||
|
if (console.log.apply) {
|
||||||
|
console.log.apply(console, arguments);
|
||||||
|
} else {
|
||||||
|
console.log(arguments); // ie fix: console.log.apply doesn't exist on ie
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
jasmine.TrivialReporter.prototype.getLocation = function() {
|
||||||
|
return this.document.location;
|
||||||
|
};
|
||||||
|
|
||||||
|
jasmine.TrivialReporter.prototype.specFilter = function(spec) {
|
||||||
|
var paramMap = {};
|
||||||
|
var params = this.getLocation().search.substring(1).split('&');
|
||||||
|
for (var i = 0; i < params.length; i++) {
|
||||||
|
var p = params[i].split('=');
|
||||||
|
paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!paramMap.spec) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return spec.getFullName().indexOf(paramMap.spec) === 0;
|
||||||
|
};
|
||||||
81
vendors/Q/spec/lib/jasmine-1.2.0/jasmine.css
vendored
Normal file
81
vendors/Q/spec/lib/jasmine-1.2.0/jasmine.css
vendored
Normal file
|
|
@ -0,0 +1,81 @@
|
||||||
|
body { background-color: #eeeeee; padding: 0; margin: 5px; overflow-y: scroll; }
|
||||||
|
|
||||||
|
#HTMLReporter { font-size: 11px; font-family: Monaco, "Lucida Console", monospace; line-height: 14px; color: #333333; }
|
||||||
|
#HTMLReporter a { text-decoration: none; }
|
||||||
|
#HTMLReporter a:hover { text-decoration: underline; }
|
||||||
|
#HTMLReporter p, #HTMLReporter h1, #HTMLReporter h2, #HTMLReporter h3, #HTMLReporter h4, #HTMLReporter h5, #HTMLReporter h6 { margin: 0; line-height: 14px; }
|
||||||
|
#HTMLReporter .banner, #HTMLReporter .symbolSummary, #HTMLReporter .summary, #HTMLReporter .resultMessage, #HTMLReporter .specDetail .description, #HTMLReporter .alert .bar, #HTMLReporter .stackTrace { padding-left: 9px; padding-right: 9px; }
|
||||||
|
#HTMLReporter #jasmine_content { position: fixed; right: 100%; }
|
||||||
|
#HTMLReporter .version { color: #aaaaaa; }
|
||||||
|
#HTMLReporter .banner { margin-top: 14px; }
|
||||||
|
#HTMLReporter .duration { color: #aaaaaa; float: right; }
|
||||||
|
#HTMLReporter .symbolSummary { overflow: hidden; *zoom: 1; margin: 14px 0; }
|
||||||
|
#HTMLReporter .symbolSummary li { display: block; float: left; height: 7px; width: 14px; margin-bottom: 7px; font-size: 16px; }
|
||||||
|
#HTMLReporter .symbolSummary li.passed { font-size: 14px; }
|
||||||
|
#HTMLReporter .symbolSummary li.passed:before { color: #5e7d00; content: "\02022"; }
|
||||||
|
#HTMLReporter .symbolSummary li.failed { line-height: 9px; }
|
||||||
|
#HTMLReporter .symbolSummary li.failed:before { color: #b03911; content: "x"; font-weight: bold; margin-left: -1px; }
|
||||||
|
#HTMLReporter .symbolSummary li.skipped { font-size: 14px; }
|
||||||
|
#HTMLReporter .symbolSummary li.skipped:before { color: #bababa; content: "\02022"; }
|
||||||
|
#HTMLReporter .symbolSummary li.pending { line-height: 11px; }
|
||||||
|
#HTMLReporter .symbolSummary li.pending:before { color: #aaaaaa; content: "-"; }
|
||||||
|
#HTMLReporter .bar { line-height: 28px; font-size: 14px; display: block; color: #eee; }
|
||||||
|
#HTMLReporter .runningAlert { background-color: #666666; }
|
||||||
|
#HTMLReporter .skippedAlert { background-color: #aaaaaa; }
|
||||||
|
#HTMLReporter .skippedAlert:first-child { background-color: #333333; }
|
||||||
|
#HTMLReporter .skippedAlert:hover { text-decoration: none; color: white; text-decoration: underline; }
|
||||||
|
#HTMLReporter .passingAlert { background-color: #a6b779; }
|
||||||
|
#HTMLReporter .passingAlert:first-child { background-color: #5e7d00; }
|
||||||
|
#HTMLReporter .failingAlert { background-color: #cf867e; }
|
||||||
|
#HTMLReporter .failingAlert:first-child { background-color: #b03911; }
|
||||||
|
#HTMLReporter .results { margin-top: 14px; }
|
||||||
|
#HTMLReporter #details { display: none; }
|
||||||
|
#HTMLReporter .resultsMenu, #HTMLReporter .resultsMenu a { background-color: #fff; color: #333333; }
|
||||||
|
#HTMLReporter.showDetails .summaryMenuItem { font-weight: normal; text-decoration: inherit; }
|
||||||
|
#HTMLReporter.showDetails .summaryMenuItem:hover { text-decoration: underline; }
|
||||||
|
#HTMLReporter.showDetails .detailsMenuItem { font-weight: bold; text-decoration: underline; }
|
||||||
|
#HTMLReporter.showDetails .summary { display: none; }
|
||||||
|
#HTMLReporter.showDetails #details { display: block; }
|
||||||
|
#HTMLReporter .summaryMenuItem { font-weight: bold; text-decoration: underline; }
|
||||||
|
#HTMLReporter .summary { margin-top: 14px; }
|
||||||
|
#HTMLReporter .summary .suite .suite, #HTMLReporter .summary .specSummary { margin-left: 14px; }
|
||||||
|
#HTMLReporter .summary .specSummary.passed a { color: #5e7d00; }
|
||||||
|
#HTMLReporter .summary .specSummary.failed a { color: #b03911; }
|
||||||
|
#HTMLReporter .description + .suite { margin-top: 0; }
|
||||||
|
#HTMLReporter .suite { margin-top: 14px; }
|
||||||
|
#HTMLReporter .suite a { color: #333333; }
|
||||||
|
#HTMLReporter #details .specDetail { margin-bottom: 28px; }
|
||||||
|
#HTMLReporter #details .specDetail .description { display: block; color: white; background-color: #b03911; }
|
||||||
|
#HTMLReporter .resultMessage { padding-top: 14px; color: #333333; }
|
||||||
|
#HTMLReporter .resultMessage span.result { display: block; }
|
||||||
|
#HTMLReporter .stackTrace { margin: 5px 0 0 0; max-height: 224px; overflow: auto; line-height: 18px; color: #666666; border: 1px solid #ddd; background: white; white-space: pre; }
|
||||||
|
|
||||||
|
#TrivialReporter { padding: 8px 13px; position: absolute; top: 0; bottom: 0; left: 0; right: 0; overflow-y: scroll; background-color: white; font-family: "Helvetica Neue Light", "Lucida Grande", "Calibri", "Arial", sans-serif; /*.resultMessage {*/ /*white-space: pre;*/ /*}*/ }
|
||||||
|
#TrivialReporter a:visited, #TrivialReporter a { color: #303; }
|
||||||
|
#TrivialReporter a:hover, #TrivialReporter a:active { color: blue; }
|
||||||
|
#TrivialReporter .run_spec { float: right; padding-right: 5px; font-size: .8em; text-decoration: none; }
|
||||||
|
#TrivialReporter .banner { color: #303; background-color: #fef; padding: 5px; }
|
||||||
|
#TrivialReporter .logo { float: left; font-size: 1.1em; padding-left: 5px; }
|
||||||
|
#TrivialReporter .logo .version { font-size: .6em; padding-left: 1em; }
|
||||||
|
#TrivialReporter .runner.running { background-color: yellow; }
|
||||||
|
#TrivialReporter .options { text-align: right; font-size: .8em; }
|
||||||
|
#TrivialReporter .suite { border: 1px outset gray; margin: 5px 0; padding-left: 1em; }
|
||||||
|
#TrivialReporter .suite .suite { margin: 5px; }
|
||||||
|
#TrivialReporter .suite.passed { background-color: #dfd; }
|
||||||
|
#TrivialReporter .suite.failed { background-color: #fdd; }
|
||||||
|
#TrivialReporter .spec { margin: 5px; padding-left: 1em; clear: both; }
|
||||||
|
#TrivialReporter .spec.failed, #TrivialReporter .spec.passed, #TrivialReporter .spec.skipped { padding-bottom: 5px; border: 1px solid gray; }
|
||||||
|
#TrivialReporter .spec.failed { background-color: #fbb; border-color: red; }
|
||||||
|
#TrivialReporter .spec.passed { background-color: #bfb; border-color: green; }
|
||||||
|
#TrivialReporter .spec.skipped { background-color: #bbb; }
|
||||||
|
#TrivialReporter .messages { border-left: 1px dashed gray; padding-left: 1em; padding-right: 1em; }
|
||||||
|
#TrivialReporter .passed { background-color: #cfc; display: none; }
|
||||||
|
#TrivialReporter .failed { background-color: #fbb; }
|
||||||
|
#TrivialReporter .skipped { color: #777; background-color: #eee; display: none; }
|
||||||
|
#TrivialReporter .resultMessage span.result { display: block; line-height: 2em; color: black; }
|
||||||
|
#TrivialReporter .resultMessage .mismatch { color: black; }
|
||||||
|
#TrivialReporter .stackTrace { white-space: pre; font-size: .8em; margin-left: 10px; max-height: 5em; overflow: auto; border: 1px inset red; padding: 1em; background: #eef; }
|
||||||
|
#TrivialReporter .finished-at { padding-left: 1em; font-size: .6em; }
|
||||||
|
#TrivialReporter.show-passed .passed, #TrivialReporter.show-skipped .skipped { display: block; }
|
||||||
|
#TrivialReporter #jasmine_content { position: fixed; right: 100%; }
|
||||||
|
#TrivialReporter .runner { border: 1px solid gray; display: block; margin: 5px 0; padding: 2px 0 2px 10px; }
|
||||||
2529
vendors/Q/spec/lib/jasmine-1.2.0/jasmine.js
vendored
Normal file
2529
vendors/Q/spec/lib/jasmine-1.2.0/jasmine.js
vendored
Normal file
File diff suppressed because it is too large
Load diff
91
vendors/Q/spec/lib/jasmine-promise.js
vendored
Normal file
91
vendors/Q/spec/lib/jasmine-promise.js
vendored
Normal file
|
|
@ -0,0 +1,91 @@
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Modifies the way that individual specs are run to easily test async
|
||||||
|
* code with promises.
|
||||||
|
*
|
||||||
|
* A spec may return a promise. If it does, then the spec passes if and
|
||||||
|
* only if that promise is fulfilled within a very short period of time.
|
||||||
|
* If it is rejected, or if it isn't fulfilled quickly, the spec fails.
|
||||||
|
*
|
||||||
|
* In this way, we can use promise chaining to structure our asynchronous
|
||||||
|
* tests. Expectations all down the chain of promises are all checked and
|
||||||
|
* guaranteed to be run and resolved or the test fails.
|
||||||
|
*
|
||||||
|
* This is a big win over the runs() and watches() code that jasmine
|
||||||
|
* supports out of the box.
|
||||||
|
*/
|
||||||
|
jasmine.Block.prototype.execute = function (onComplete) {
|
||||||
|
var spec = this.spec;
|
||||||
|
try {
|
||||||
|
var result = this.func.call(spec, onComplete);
|
||||||
|
|
||||||
|
// It seems Jasmine likes to return the suite if you pass it anything.
|
||||||
|
// So make sure it's a promise first.
|
||||||
|
if (result && typeof result.then === "function") {
|
||||||
|
Q.timeout(result, 500).then(function () {
|
||||||
|
onComplete();
|
||||||
|
}, function (error) {
|
||||||
|
spec.fail(error);
|
||||||
|
onComplete();
|
||||||
|
});
|
||||||
|
} else if (this.func.length === 0) {
|
||||||
|
onComplete();
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
spec.fail(error);
|
||||||
|
onComplete();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests and documents the behavior of the above extension to jasmine.
|
||||||
|
*/
|
||||||
|
describe('jasmine-promise', function() {
|
||||||
|
it('passes if the deferred resolves immediately', function() {
|
||||||
|
var deferred = Q.defer();
|
||||||
|
deferred.resolve();
|
||||||
|
return deferred.promise;
|
||||||
|
});
|
||||||
|
it('passes if the deferred resolves after a short delay', function() {
|
||||||
|
var deferred = Q.defer();
|
||||||
|
setTimeout(function() {deferred.resolve();}, 100);
|
||||||
|
return deferred.promise;
|
||||||
|
});
|
||||||
|
it('lets specs that return nothing pass', function() {
|
||||||
|
|
||||||
|
});
|
||||||
|
it('lets specs that return non-promises pass', function() {
|
||||||
|
return {'some object': 'with values'};
|
||||||
|
});
|
||||||
|
it('works ok with specs that return crappy non-Q promises', function() {
|
||||||
|
return {
|
||||||
|
'then': function(callback) {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// These are expected to fail. Remove the x from xdescribe to test that.
|
||||||
|
xdescribe('failure cases (expected to fail)', function() {
|
||||||
|
it('fails if the deferred is rejected', function() {
|
||||||
|
var deferred = Q.defer();
|
||||||
|
deferred.reject();
|
||||||
|
return deferred.promise;
|
||||||
|
});
|
||||||
|
it('fails if the deferred takes too long to resolve', function() {
|
||||||
|
var deferred = Q.defer();
|
||||||
|
setTimeout(function() {deferred.resolve()}, 5 * 1000);
|
||||||
|
return deferred.promise;
|
||||||
|
});
|
||||||
|
it('fails if a returned crappy non-Q promise is rejected', function() {
|
||||||
|
return {
|
||||||
|
'then': function(_, callback) {callback()}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
it('fails if a returned crappy promise is never resolved', function() {
|
||||||
|
return {
|
||||||
|
'then': function() {}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
})
|
||||||
|
});
|
||||||
52
vendors/Q/spec/q-spec.html
vendored
Normal file
52
vendors/Q/spec/q-spec.html
vendored
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Jasmine Spec Runner</title>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
|
||||||
|
<link rel="shortcut icon" type="image/png" href="lib/jasmine-1.2.0/jasmine_favicon.png" />
|
||||||
|
<link rel="stylesheet" href="lib/jasmine-1.2.0/jasmine.css" />
|
||||||
|
<script src="lib/jasmine-1.2.0/jasmine.js"></script>
|
||||||
|
<script src="lib/jasmine-1.2.0/jasmine-html.js"></script>
|
||||||
|
<script src="lib/jasmine-promise.js"></script>
|
||||||
|
|
||||||
|
<!-- include source files here... -->
|
||||||
|
<script src="../q.js"></script>
|
||||||
|
|
||||||
|
<!-- include spec files here... -->
|
||||||
|
<script src="q-spec.js"></script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
(function() {
|
||||||
|
var jasmineEnv = jasmine.getEnv();
|
||||||
|
jasmineEnv.updateInterval = 1000;
|
||||||
|
|
||||||
|
var htmlReporter = new jasmine.HtmlReporter();
|
||||||
|
|
||||||
|
jasmineEnv.addReporter(htmlReporter);
|
||||||
|
|
||||||
|
jasmineEnv.specFilter = function(spec) {
|
||||||
|
return htmlReporter.specFilter(spec);
|
||||||
|
};
|
||||||
|
|
||||||
|
var currentWindowOnload = window.onload;
|
||||||
|
|
||||||
|
window.onload = function() {
|
||||||
|
if (currentWindowOnload) {
|
||||||
|
currentWindowOnload();
|
||||||
|
}
|
||||||
|
execJasmine();
|
||||||
|
};
|
||||||
|
|
||||||
|
function execJasmine() {
|
||||||
|
jasmineEnv.execute();
|
||||||
|
}
|
||||||
|
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
2611
vendors/Q/spec/q-spec.js
vendored
Normal file
2611
vendors/Q/spec/q-spec.js
vendored
Normal file
File diff suppressed because it is too large
Load diff
180
vendors/Q/spec/queue-spec.js
vendored
Normal file
180
vendors/Q/spec/queue-spec.js
vendored
Normal file
|
|
@ -0,0 +1,180 @@
|
||||||
|
|
||||||
|
var Q = require("../q");
|
||||||
|
var Queue = require("../queue");
|
||||||
|
|
||||||
|
global.Q = Q;
|
||||||
|
require("./lib/jasmine-promise");
|
||||||
|
|
||||||
|
describe("queue", function () {
|
||||||
|
|
||||||
|
it("should enqueue then dequeue", function () {
|
||||||
|
var queue = Queue();
|
||||||
|
queue.put(1);
|
||||||
|
return queue.get().then(function (value) {
|
||||||
|
expect(value).toBe(1);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should dequeue then enqueue", function () {
|
||||||
|
var queue = Queue();
|
||||||
|
var promise = queue.get().then(function (value) {
|
||||||
|
expect(value).toBe(1);
|
||||||
|
});
|
||||||
|
queue.put(1);
|
||||||
|
return promise;
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should stream", function () {
|
||||||
|
var queue = Queue();
|
||||||
|
|
||||||
|
Q.try(function () {
|
||||||
|
return Q.delay(20).then(function () {
|
||||||
|
queue.put(1);
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.then(function () {
|
||||||
|
return Q.delay(20).then(function () {
|
||||||
|
queue.put(2);
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.then(function () {
|
||||||
|
return Q.delay(20).then(function () {
|
||||||
|
queue.put(3);
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.done();
|
||||||
|
|
||||||
|
return Q.try(function () {
|
||||||
|
return queue.get()
|
||||||
|
.then(function (value) {
|
||||||
|
expect(value).toBe(1);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.then(function () {
|
||||||
|
return queue.get()
|
||||||
|
.then(function (value) {
|
||||||
|
expect(value).toBe(2);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.then(function () {
|
||||||
|
return queue.get()
|
||||||
|
.then(function (value) {
|
||||||
|
expect(value).toBe(3);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should be order agnostic", function () {
|
||||||
|
var queue = Queue();
|
||||||
|
|
||||||
|
Q.try(function () {
|
||||||
|
return Q.delay(20).then(function () {
|
||||||
|
queue.put(1);
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.then(function () {
|
||||||
|
return Q.delay(20).then(function () {
|
||||||
|
queue.put(2);
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.then(function () {
|
||||||
|
return Q.delay(20).then(function () {
|
||||||
|
queue.put(3);
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.done();
|
||||||
|
|
||||||
|
return Q.all([
|
||||||
|
queue.get()
|
||||||
|
.then(function (value) {
|
||||||
|
expect(value).toBe(1);
|
||||||
|
}),
|
||||||
|
queue.get()
|
||||||
|
.then(function (value) {
|
||||||
|
expect(value).toBe(2);
|
||||||
|
}),
|
||||||
|
queue.get()
|
||||||
|
.then(function (value) {
|
||||||
|
expect(value).toBe(3);
|
||||||
|
})
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should close", function () {
|
||||||
|
|
||||||
|
var queue = Queue();
|
||||||
|
|
||||||
|
Q.try(function () {
|
||||||
|
return Q.delay(20).then(function () {
|
||||||
|
queue.put(1);
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.then(function () {
|
||||||
|
return Q.delay(20).then(function () {
|
||||||
|
queue.put(2);
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.then(function () {
|
||||||
|
queue.close();
|
||||||
|
})
|
||||||
|
.done();
|
||||||
|
|
||||||
|
return Q.try(function () {
|
||||||
|
return queue.get()
|
||||||
|
.then(function (value) {
|
||||||
|
expect(value).toBe(1);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.then(function () {
|
||||||
|
return queue.get()
|
||||||
|
.then(function (value) {
|
||||||
|
expect(value).toBe(2);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.then(function () {
|
||||||
|
return queue.get()
|
||||||
|
.then(function (value) {
|
||||||
|
expect(false).toBe(true); // should not get here
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(function (error) {
|
||||||
|
expect(error.message).toBe("Can't get value from closed queue");
|
||||||
|
return queue.get();
|
||||||
|
})
|
||||||
|
.catch(function (error) {
|
||||||
|
expect(error.message).toBe("Can't get value from closed queue");
|
||||||
|
})
|
||||||
|
.then(function () {
|
||||||
|
return queue.closed;
|
||||||
|
})
|
||||||
|
.then(function (error) {
|
||||||
|
expect(error.message).toBe("Can't get value from closed queue");
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should close with alternate error", function () {
|
||||||
|
|
||||||
|
var queue = Queue();
|
||||||
|
queue.close(new Error("Alternate reason"));
|
||||||
|
|
||||||
|
return Q.try(function () {
|
||||||
|
return queue.get();
|
||||||
|
})
|
||||||
|
.catch(function (error) {
|
||||||
|
expect(error.message).toBe("Alternate reason");
|
||||||
|
return queue.get();
|
||||||
|
})
|
||||||
|
.catch(function (error) {
|
||||||
|
expect(error.message).toBe("Alternate reason");
|
||||||
|
})
|
||||||
|
.then(function () {
|
||||||
|
return queue.closed;
|
||||||
|
})
|
||||||
|
.then(function (error) {
|
||||||
|
expect(error.message).toBe("Alternate reason");
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
@ -43,6 +43,7 @@ module.exports = {
|
||||||
'ssm': 'window.ssm',
|
'ssm': 'window.ssm',
|
||||||
'key': 'window.key',
|
'key': 'window.key',
|
||||||
'_': 'window._',
|
'_': 'window._',
|
||||||
|
'Q': 'window.Q',
|
||||||
'$': 'window.jQuery'
|
'$': 'window.jQuery'
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Loading…
Add table
Add a link
Reference in a new issue