starmapjs
Version:
Starmap makes client-side Waterline/Sails easy!
1,638 lines (1,432 loc) • 1.59 MB
JavaScript
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.starmap = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
var Promise = require('bluebird');
var _ = require('lodash');
var utils = require('./utils');
var EventEmitter = require('events').EventEmitter;
var util = require('util');
var publicModel = require('./publicModel');
var modelItem = require('./modelItem');
/**
* An actual model that syncs with the server
*
* This object contains the internal model representation, and updates any
* objects bound to it.
*
* @param {object} io the socket.io object
* @param {string} name
* @param itemDef {object?}
* @param modelDef {object?}
* @param filter {object?}
* @constructor
*/
function Model(io, name, itemDef, modelDef, filter) {
EventEmitter.call(this);
//name = name.toLowerCase();
this.io = io;
this.name = name;
this.url = utils.resolveName(name);
this.itemDef = itemDef || {};
this.modelDef = modelDef || {};
this.filter = filter || {};
this.children = [];
this.eventHandlers = {};
this.bindings = [];
this.value = publicModel(this, new Promise(function(resolve, reject) {
this.on('ready', resolve());
}.bind(this)));
this.on('created', this._onCreated.bind(this));
this.on('updated', this._onUpdated.bind(this));
this.on('destroyed', this._onDestroyed.bind(this));
io.socket.on(name, function(message) {
this.emit(message.verb, message);
}.bind(this));
this.refresh().then(function() {
this.emit('ready');
}.bind(this));
}
util.inherits(Model, EventEmitter);
module.exports = Model;
Model.prototype._addItem = function(child) {
if (this.value.indexOf(child) !== -1) return;
this.value._push(child);
};
Model.prototype._removeItem = function(child) {
var index = this.value.indexOf(child);
if (index !== -1) this.value._splice(index, 1);
};
Model.prototype._removeAll = function() {
while (this.value.length) this.value._pop();
};
/**
* Triggered when a new item is added to the model
*
* @param {Object} message
* @private
*/
Model.prototype._onCreated = function(message) {
var newChild = modelItem(message.data, this);
this.childMatches(newChild).then(function(matches) {
if (matches) this._addItem(newChild);
}.bind(this));
};
/**
* Triggered when an item is modified
*
* @param {Object} message
* @private
*/
Model.prototype._onUpdated = function(message) {
var itemWithId = this.value.itemById(message.id);
if (itemWithId) itemWithId.update(message.data, false);
};
/**
* Triggered when an item is destroyed
*
* @param {Object} message
* @private
*/
Model.prototype._onDestroyed = function(message) {
var itemWithId = this.value.itemById(message.id);
if(itemWithId) this._removeItem(itemWithId);
};
/**
* Finds if a child matches the filter for this model instance
*
* @param {Object} child
*/
Model.prototype.childMatches = function(child) {
return Promise.resolve((function() {
// if they are not the same model, they do not match
if (child.model.name !== this.name) return false;
// if they are the same model and the model doesn't have a filter, they match
if (_.isEqual(this.filter, {})) return true;
// otherwise compare the filter
return child.matches(this.filter);
}.bind(this)()));
};
/**
* Re-fetches all items and adds them
*
* @returns {Model}
*/
Model.prototype.refresh = function() {
return utils.socketGet(this.io, this.url, this.filter).then(function(data) {
var dat = _.isArray(data) ? data : [data];
this._removeAll();
for (var i = 0; i < dat.length; i++) {
this._addItem(modelItem(dat[i], this));
}
}.bind(this));
};
/**
* Saves all items in the model
*
*/
Model.prototype.save = function() {
_.forEach(this.value, function(item) {
item.save();
});
};
},{"./modelItem":4,"./publicModel":5,"./utils":6,"bluebird":7,"events":8,"lodash":13,"util":12}],2:[function(require,module,exports){
/**
* Internally gets a model
*/
var _ = require('lodash');
var Model = require('./Model');
var utils = require('./utils');
var modelCache = {};
var isSubscribed = {};
/**
* Creates or gets a model from the cache
*
* @param io
* @param {string} name the model name
* @param {object?} itemDef
* @param {object?} modelDef
* @param {object?} filter
* @returns {object}
*/
module.exports = function(io, name, itemDef, modelDef, filter) {
filter = filter || {};
name = name.toLowerCase();
var cacheName = name + JSON.stringify(filter);
if (_.has(modelCache, cacheName)) {
var model = modelCache[cacheName];
// allow modification of itemDef and modelDef after a model has been fetched
if (itemDef) {
model.itemDef = itemDef;
model.refresh();
}
if (modelDef) model.modelDef = modelDef;
return model.value;
}
var mdl = new Model(io, name, itemDef, modelDef, filter);
if (!isSubscribed[name]) {
utils.socketGet(io, mdl.url);
isSubscribed[name] = true;
}
modelCache[cacheName] = mdl;
return mdl.value;
};
},{"./Model":1,"./utils":6,"lodash":13}],3:[function(require,module,exports){
/**
* Starmap - easy database manipulation with Sails
*
* @preserve
*/
var Promise = require('bluebird');
var _ = require('lodash');
var gm = require('./getModel');
var utils = require('./utils');
function get(io) {
/**
* Creates or updates a model definition
*
* @param {string} name
* @param itemDef {object?} the item definition
* @param modelDef {object?} the model definition
* @returns {object} the model
*/
function getModel(name, itemDef, modelDef) {
return gm(io, name, itemDef, modelDef);
}
getModel.model = getModel;
/**
* Creates a new instance of the model
*
* @param {string} name
* @param {object?} props
* @returns {object}
*/
getModel.create = function(name, props) {
return getModel(name).create(props);
};
/**
* Finds all matching items.
* The same as .model(name).find(filter)
*
* @param {string} name
* @param filter
* @returns {Promise}
*/
getModel.find = function(name, filter) {
return getModel(name).find(filter);
};
/**
* Finds a single matching item
* The same as .model(name).findOne(filter)
*
* @param {string} name
* @param filter
* @returns {Promise}
*/
getModel.findOne = function(name, filter) {
return getModel(name).findOne(filter);
};
/**
*
*
* @param func
* @param subProps
* @returns {*}
*/
getModel.calculate = utils.createCalculateProperty;
return getModel;
}
if (window.io) module.exports = get(window.io);
else module.exports = get;
// for testing
window.starmap = module.exports;
},{"./getModel":2,"./utils":6,"bluebird":7,"lodash":13}],4:[function(require,module,exports){
var _ = require('lodash');
var utils = require('./utils');
var Promise = require('bluebird');
/**
* Updates the model to represent the given data
*
* @param {object} item
* @param {Model} model
* @param {object} data the data to add to the model
* @param {object?} funcParams parameters to pass to any precalc functions
* @returns {Promise}
*/
function update(item, model, data, funcParams) {
var working = [];
var definedByData = [];
_.forEach(data, function(value, key) {
if (_.isFunction(value)) {
working.push(Promise.resolve(value()).then(function(val) {
item[key] = val;
}));
} else item[key] = value;
definedByData.push(value);
});
_.forEach(model.itemDef, function(value, key) {
if (value && value.__precalc) {
var func = value.__precalc, previousVal = data[key];
working.push(Promise.resolve(func.call(item, previousVal, funcParams || {})).then(function(val) {
item[key] = (val && val._stWrapped) ? val.val : val;
}));
} // if the property has not been set from the itemDef yet. This allows item def properties to be changed
else if (!_.has(item, key) || definedByData.indexOf(key) !== -1) item[key] = value;
});
return Promise.all(working);
}
/**
* Gets properties to be synced with the server
*
* @param {object} item
* @param {Model} model
* @param {object?} props
* @returns {object}
*/
function serverProperties(item, model, props) {
var result = {};
var toRefresh = [];
_.forEach(props || item, function(val, key) {
if (val == null) return;
if (val._isModelItem) {
result[key] = val.id;
toRefresh.push(val);
} else if (_.isArray(val)) {
result[key] = _.map(val, function(item) {
if (item._isModelItem) {
toRefresh.push(item);
return item.id;
}
return item;
});
} else if (_.has(model.itemDef, key)) {
if (_.has(model.itemDef[key], '__connection')) result[key] = val;
} else result[key] = val;
});
return {
properties: result,
refresh: toRefresh
};
}
/**
* Creates the item on the server
*
* @param {object} item
* @param {Model} model
* @param {object?} data
* @returns {Promise}
*/
function create(item, model, data) {
var serverProps = serverProperties(item, model, data).properties;
return utils.socketPut(model.io, model.url + '/create/', serverProps).then(function(response) {
_.merge(serverProps, response);
return update(item, model, serverProps);
}).then(function() {
// Refresh all items that were referenced - some of their properties might change
return Promise.all(_.map(serverProps.refresh, function(item) {
return item.refresh();
}));
});
}
/**
* A single model item that is synced with the server
*
* @param {object} data
* @param {Model} model
*/
function modelItem(data, model) {
var res = {};
utils.defineProperties(res, {
_isModelItem: { value: true },
model: { value: model.value },
update: { value: function(data, sync) {
if (sync == null) sync = true;
return update(res, model, data).then(function() {
if (!sync) return;
return res.save();
});
} },
save: { value: function() {
if (_.has(res, 'id')) {
var props = serverProperties(res, model);
return utils.socketPost(model.io, model.url + '/update/' + res.id, props.properties).then(function() {
return Promise.all(_.map(props.refresh, function(item) {
return item.refresh();
}));
});
}
return create(res, model);
} },
refresh: { value: function() {
if (!_.has(res, 'id')) return create(res, model);
return utils.socketGet(model.io, model.url + '/' + res.id).then(function(data) {
return update(res, model, data, { noRefresh: true });
});
} },
delete: { value: function() {
model._removeItem(res);
return utils.socketDelete(model.io, model.url, { id: res.id });
} },
matches: { value: function(query) {
return utils.socketGet(model.io, model.url, query).then(function(r) {
for (var i = 0; i < r.length; i++) {
if (r[i].id === res.id) return true;
}
return false;
});
} },
then: { value: function() {
return res.ready.then.apply(res.ready, arguments);
} },
catch: { value: function() {
return res.ready.catch.apply(res.ready, arguments);
} }
});
res.ready = Promise.resolve();
update(res, model, data || {});
return res;
}
module.exports = modelItem;
},{"./utils":6,"bluebird":7,"lodash":13}],5:[function(require,module,exports){
var Promise = require('bluebird');
var _ = require('lodash');
var utils = require('./utils');
var getModel = require('./getModel');
var modelItem = require('./modelItem');
var arrayPop = Array.prototype.pop,
arrayPush = Array.prototype.push,
arrayShift = Array.prototype.shift,
arraySplice = Array.prototype.splice,
arrayUnshift = Array.prototype.unshift,
arraySlice = Array.prototype.slice;
/**
* Creates a public model object
*
* @param {Model} model
* @param {Promise} readyPromise
* @returns {Array} the public object
*/
function publicModel(model, readyPromise) {
var res = [];
function find(filter) {
var mergedFilter = _.merge({}, model.filter, filter);
var filteredModel = getModel(model.io, model.name, model.itemDef, model.modelDef, mergedFilter);
if (model.children.indexOf(filteredModel) === -1) model.children.push(filteredModel);
return filteredModel;
}
function getByIds(ids) {
var items = [];
for (var i = 0; i < res.length; i++) {
if (ids.indexOf(res[i].id) !== -1) items.push(res[i]);
}
return items;
}
utils.defineProperties(res, {
_isModel: { value: true },
name: { value: model.name },
ready: { value: readyPromise },
create: { value: function(props) {
props = props || {};
var item = modelItem(props, model);
item.ready = item.update(props).then(function() {
model._addItem(item);
});
return item;
} },
itemById: { value: function(id) {
for (var i = 0; i < this.length; i++) {
if (this[i].id === id) return this[i];
}
return false;
} },
find: { value: find },
filter: { value: find },
findOne: { value: function(filter) {
return find(filter).then(function(val) {
if (val.length) return val[0];
return false;
});
} },
refresh: { value: function() {
return Promise.all(_.map(this, function(item) {
return item.refresh();
}));
} },
then: { value: function() {
return readyPromise.then.apply(readyPromise, arguments);
} },
catch: { value: function() {
return readyPromise.catch.apply(readyPromise, arguments);
} },
/**
* Override array modification properties
*/
_pop: { value: arrayPop },
pop: { value: function() {
var lastItem = arrayPop.call(this);
lastItem.delete();
return lastItem;
} },
_push: { value: arrayPush },
push: { value: function() {
for (var i = 0; i < arguments.length; i++) {
this.create(arguments[i]);
}
return this.length;
} },
_shift: { value: arrayShift },
shift: { value: function() {
var firstItem = arrayShift.call(this);
firstItem.delete();
return firstItem;
} },
_splice: { value: arraySplice },
splice: { value: function(start, deleteCount) {
var items = _.map(arraySlice.call(arguments, 2), function(itm) {
var item = modelItem(itm, model);
item.ready = item.update(itm);
return item;
});
items.unshift(start, deleteCount);
var removed = arraySplice.apply(this, items);
for (var i = 0; i < removed.length; i++) removed.delete();
return removed;
} },
_unshift: { value: arrayUnshift },
unshift: { value: function() {
return arrayUnshift.apply(this, _.map(arguments, function(itm) {
var item = modelItem(itm, model);
item.ready = item.update(itm);
return item;
}));
} },
__connection: { value: model.name }
});
//Object.defineProperties(res, );
_.merge(res, utils.createCalculateProperty(function(previous, flags) {
if (!previous) return;
var isArray = _.isArray(previous), prevId;
if (isArray) {
prevId = _.map(previous, function(val) {
if (_.isNumber(val)) return val;
return val.id;
});
} else prevId = [_.isNumber(previous) ? previous : previous.id];
return readyPromise.then(function() {
var itms = getByIds(prevId);
function getItems() {
if (isArray) return { _stWrapped: true, val: itms};
return { _stWrapped: true, val: itms.length ? itms[0] : null };
}
if (!flags.noRefresh) {
return Promise.all(_.map(itms, function(item) {
return item.refresh();
})).then(getItems);
}
return getItems();
});
}.bind(this)));
return res;
}
module.exports = publicModel;
},{"./getModel":2,"./modelItem":4,"./utils":6,"bluebird":7,"lodash":13}],6:[function(require,module,exports){
var _ = require('lodash');
/**
* Converts the model name to a path
*
* TODO: this might not be neccessary
*
* @param {string} name
* @returns {string}
*/
exports.resolveName = function(name) {
var prefixIndex = name.indexOf('/'), prefix = '';
if (prefixIndex !== -1) {
prefix = name.substring(0, prefixIndex) + '/';
name = name.substring(prefixIndex + 1);
}
return '/' + prefix + name;
};
var requestId = 0;
function promisifySocket(fName) {
return function(io, url, additional) {
var rid = requestId++;
return (new Promise(function(resolve, reject) {
io.socket[fName](url, additional, function (response) {
if (response.error) reject(response.error);
else if (_.isString(response)) reject(new Error(response));
else resolve(response);
});
}));
}
}
exports.socketGet = promisifySocket("get");
exports.socketPost = promisifySocket("post");
exports.socketPut = promisifySocket("put");
exports.socketDelete = promisifySocket("delete");
exports.defineProperties = (function() {
if (Object.defineProperties) return Object.defineProperties;
return function(base, obj) {
_.extend(base, _.mapValues(obj, function(val) {
return val.value;
}));
}
}());
exports.createCalculateProperty = function(func, subProps) {
return _.merge({
__precalc: func
}, subProps);
};
},{"lodash":13}],7:[function(require,module,exports){
(function (process,global){
/* @preserve
* The MIT License (MIT)
*
* Copyright (c) 2014 Petka Antonov
*
* 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:</p>
*
* 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.
*
*/
/**
* bluebird build version 2.9.27
* Features enabled: core, race, call_get, generators, map, nodeify, promisify, props, reduce, settle, some, cancel, using, filter, any, each, timers
*/
!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.Promise=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof _dereq_=="function"&&_dereq_;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof _dereq_=="function"&&_dereq_;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){
"use strict";
module.exports = function(Promise) {
var SomePromiseArray = Promise._SomePromiseArray;
function any(promises) {
var ret = new SomePromiseArray(promises);
var promise = ret.promise();
ret.setHowMany(1);
ret.setUnwrap();
ret.init();
return promise;
}
Promise.any = function (promises) {
return any(promises);
};
Promise.prototype.any = function () {
return any(this);
};
};
},{}],2:[function(_dereq_,module,exports){
"use strict";
var firstLineError;
try {throw new Error(); } catch (e) {firstLineError = e;}
var schedule = _dereq_("./schedule.js");
var Queue = _dereq_("./queue.js");
var util = _dereq_("./util.js");
function Async() {
this._isTickUsed = false;
this._lateQueue = new Queue(16);
this._normalQueue = new Queue(16);
this._trampolineEnabled = true;
var self = this;
this.drainQueues = function () {
self._drainQueues();
};
this._schedule =
schedule.isStatic ? schedule(this.drainQueues) : schedule;
}
Async.prototype.disableTrampolineIfNecessary = function() {
if (util.hasDevTools) {
this._trampolineEnabled = false;
}
};
Async.prototype.enableTrampoline = function() {
if (!this._trampolineEnabled) {
this._trampolineEnabled = true;
this._schedule = function(fn) {
setTimeout(fn, 0);
};
}
};
Async.prototype.haveItemsQueued = function () {
return this._normalQueue.length() > 0;
};
Async.prototype.throwLater = function(fn, arg) {
if (arguments.length === 1) {
arg = fn;
fn = function () { throw arg; };
}
var domain = this._getDomain();
if (domain !== undefined) fn = domain.bind(fn);
if (typeof setTimeout !== "undefined") {
setTimeout(function() {
fn(arg);
}, 0);
} else try {
this._schedule(function() {
fn(arg);
});
} catch (e) {
throw new Error("No async scheduler available\u000a\u000a See http://goo.gl/m3OTXk\u000a");
}
};
Async.prototype._getDomain = function() {};
if (!true) {
if (util.isNode) {
var EventsModule = _dereq_("events");
var domainGetter = function() {
var domain = process.domain;
if (domain === null) return undefined;
return domain;
};
if (EventsModule.usingDomains) {
Async.prototype._getDomain = domainGetter;
} else {
var descriptor =
Object.getOwnPropertyDescriptor(EventsModule, "usingDomains");
if (descriptor) {
if (!descriptor.configurable) {
process.on("domainsActivated", function() {
Async.prototype._getDomain = domainGetter;
});
} else {
var usingDomains = false;
Object.defineProperty(EventsModule, "usingDomains", {
configurable: false,
enumerable: true,
get: function() {
return usingDomains;
},
set: function(value) {
if (usingDomains || !value) return;
usingDomains = true;
Async.prototype._getDomain = domainGetter;
util.toFastProperties(process);
process.emit("domainsActivated");
}
});
}
}
}
}
}
function AsyncInvokeLater(fn, receiver, arg) {
var domain = this._getDomain();
if (domain !== undefined) fn = domain.bind(fn);
this._lateQueue.push(fn, receiver, arg);
this._queueTick();
}
function AsyncInvoke(fn, receiver, arg) {
var domain = this._getDomain();
if (domain !== undefined) fn = domain.bind(fn);
this._normalQueue.push(fn, receiver, arg);
this._queueTick();
}
function AsyncSettlePromises(promise) {
var domain = this._getDomain();
if (domain !== undefined) {
var fn = domain.bind(promise._settlePromises);
this._normalQueue.push(fn, promise, undefined);
} else {
this._normalQueue._pushOne(promise);
}
this._queueTick();
}
if (!util.hasDevTools) {
Async.prototype.invokeLater = AsyncInvokeLater;
Async.prototype.invoke = AsyncInvoke;
Async.prototype.settlePromises = AsyncSettlePromises;
} else {
Async.prototype.invokeLater = function (fn, receiver, arg) {
if (this._trampolineEnabled) {
AsyncInvokeLater.call(this, fn, receiver, arg);
} else {
setTimeout(function() {
fn.call(receiver, arg);
}, 100);
}
};
Async.prototype.invoke = function (fn, receiver, arg) {
if (this._trampolineEnabled) {
AsyncInvoke.call(this, fn, receiver, arg);
} else {
setTimeout(function() {
fn.call(receiver, arg);
}, 0);
}
};
Async.prototype.settlePromises = function(promise) {
if (this._trampolineEnabled) {
AsyncSettlePromises.call(this, promise);
} else {
setTimeout(function() {
promise._settlePromises();
}, 0);
}
};
}
Async.prototype.invokeFirst = function (fn, receiver, arg) {
var domain = this._getDomain();
if (domain !== undefined) fn = domain.bind(fn);
this._normalQueue.unshift(fn, receiver, arg);
this._queueTick();
};
Async.prototype._drainQueue = function(queue) {
while (queue.length() > 0) {
var fn = queue.shift();
if (typeof fn !== "function") {
fn._settlePromises();
continue;
}
var receiver = queue.shift();
var arg = queue.shift();
fn.call(receiver, arg);
}
};
Async.prototype._drainQueues = function () {
this._drainQueue(this._normalQueue);
this._reset();
this._drainQueue(this._lateQueue);
};
Async.prototype._queueTick = function () {
if (!this._isTickUsed) {
this._isTickUsed = true;
this._schedule(this.drainQueues);
}
};
Async.prototype._reset = function () {
this._isTickUsed = false;
};
module.exports = new Async();
module.exports.firstLineError = firstLineError;
},{"./queue.js":28,"./schedule.js":31,"./util.js":38,"events":39}],3:[function(_dereq_,module,exports){
"use strict";
module.exports = function(Promise, INTERNAL, tryConvertToPromise) {
var rejectThis = function(_, e) {
this._reject(e);
};
var targetRejected = function(e, context) {
context.promiseRejectionQueued = true;
context.bindingPromise._then(rejectThis, rejectThis, null, this, e);
};
var bindingResolved = function(thisArg, context) {
this._setBoundTo(thisArg);
if (this._isPending()) {
this._resolveCallback(context.target);
}
};
var bindingRejected = function(e, context) {
if (!context.promiseRejectionQueued) this._reject(e);
};
Promise.prototype.bind = function (thisArg) {
var maybePromise = tryConvertToPromise(thisArg);
var ret = new Promise(INTERNAL);
ret._propagateFrom(this, 1);
var target = this._target();
if (maybePromise instanceof Promise) {
var context = {
promiseRejectionQueued: false,
promise: ret,
target: target,
bindingPromise: maybePromise
};
target._then(INTERNAL, targetRejected, ret._progress, ret, context);
maybePromise._then(
bindingResolved, bindingRejected, ret._progress, ret, context);
} else {
ret._setBoundTo(thisArg);
ret._resolveCallback(target);
}
return ret;
};
Promise.prototype._setBoundTo = function (obj) {
if (obj !== undefined) {
this._bitField = this._bitField | 131072;
this._boundTo = obj;
} else {
this._bitField = this._bitField & (~131072);
}
};
Promise.prototype._isBound = function () {
return (this._bitField & 131072) === 131072;
};
Promise.bind = function (thisArg, value) {
var maybePromise = tryConvertToPromise(thisArg);
var ret = new Promise(INTERNAL);
if (maybePromise instanceof Promise) {
maybePromise._then(function(thisArg) {
ret._setBoundTo(thisArg);
ret._resolveCallback(value);
}, ret._reject, ret._progress, ret, null);
} else {
ret._setBoundTo(thisArg);
ret._resolveCallback(value);
}
return ret;
};
};
},{}],4:[function(_dereq_,module,exports){
"use strict";
var old;
if (typeof Promise !== "undefined") old = Promise;
function noConflict() {
try { if (Promise === bluebird) Promise = old; }
catch (e) {}
return bluebird;
}
var bluebird = _dereq_("./promise.js")();
bluebird.noConflict = noConflict;
module.exports = bluebird;
},{"./promise.js":23}],5:[function(_dereq_,module,exports){
"use strict";
var cr = Object.create;
if (cr) {
var callerCache = cr(null);
var getterCache = cr(null);
callerCache[" size"] = getterCache[" size"] = 0;
}
module.exports = function(Promise) {
var util = _dereq_("./util.js");
var canEvaluate = util.canEvaluate;
var isIdentifier = util.isIdentifier;
var getMethodCaller;
var getGetter;
if (!true) {
var makeMethodCaller = function (methodName) {
return new Function("ensureMethod", " \n\
return function(obj) { \n\
'use strict' \n\
var len = this.length; \n\
ensureMethod(obj, 'methodName'); \n\
switch(len) { \n\
case 1: return obj.methodName(this[0]); \n\
case 2: return obj.methodName(this[0], this[1]); \n\
case 3: return obj.methodName(this[0], this[1], this[2]); \n\
case 0: return obj.methodName(); \n\
default: \n\
return obj.methodName.apply(obj, this); \n\
} \n\
}; \n\
".replace(/methodName/g, methodName))(ensureMethod);
};
var makeGetter = function (propertyName) {
return new Function("obj", " \n\
'use strict'; \n\
return obj.propertyName; \n\
".replace("propertyName", propertyName));
};
var getCompiled = function(name, compiler, cache) {
var ret = cache[name];
if (typeof ret !== "function") {
if (!isIdentifier(name)) {
return null;
}
ret = compiler(name);
cache[name] = ret;
cache[" size"]++;
if (cache[" size"] > 512) {
var keys = Object.keys(cache);
for (var i = 0; i < 256; ++i) delete cache[keys[i]];
cache[" size"] = keys.length - 256;
}
}
return ret;
};
getMethodCaller = function(name) {
return getCompiled(name, makeMethodCaller, callerCache);
};
getGetter = function(name) {
return getCompiled(name, makeGetter, getterCache);
};
}
function ensureMethod(obj, methodName) {
var fn;
if (obj != null) fn = obj[methodName];
if (typeof fn !== "function") {
var message = "Object " + util.classString(obj) + " has no method '" +
util.toString(methodName) + "'";
throw new Promise.TypeError(message);
}
return fn;
}
function caller(obj) {
var methodName = this.pop();
var fn = ensureMethod(obj, methodName);
return fn.apply(obj, this);
}
Promise.prototype.call = function (methodName) {
var $_len = arguments.length;var args = new Array($_len - 1); for(var $_i = 1; $_i < $_len; ++$_i) {args[$_i - 1] = arguments[$_i];}
if (!true) {
if (canEvaluate) {
var maybeCaller = getMethodCaller(methodName);
if (maybeCaller !== null) {
return this._then(
maybeCaller, undefined, undefined, args, undefined);
}
}
}
args.push(methodName);
return this._then(caller, undefined, undefined, args, undefined);
};
function namedGetter(obj) {
return obj[this];
}
function indexedGetter(obj) {
var index = +this;
if (index < 0) index = Math.max(0, index + obj.length);
return obj[index];
}
Promise.prototype.get = function (propertyName) {
var isIndex = (typeof propertyName === "number");
var getter;
if (!isIndex) {
if (canEvaluate) {
var maybeGetter = getGetter(propertyName);
getter = maybeGetter !== null ? maybeGetter : namedGetter;
} else {
getter = namedGetter;
}
} else {
getter = indexedGetter;
}
return this._then(getter, undefined, undefined, propertyName, undefined);
};
};
},{"./util.js":38}],6:[function(_dereq_,module,exports){
"use strict";
module.exports = function(Promise) {
var errors = _dereq_("./errors.js");
var async = _dereq_("./async.js");
var CancellationError = errors.CancellationError;
Promise.prototype._cancel = function (reason) {
if (!this.isCancellable()) return this;
var parent;
var promiseToReject = this;
while ((parent = promiseToReject._cancellationParent) !== undefined &&
parent.isCancellable()) {
promiseToReject = parent;
}
this._unsetCancellable();
promiseToReject._target()._rejectCallback(reason, false, true);
};
Promise.prototype.cancel = function (reason) {
if (!this.isCancellable()) return this;
if (reason === undefined) reason = new CancellationError();
async.invokeLater(this._cancel, this, reason);
return this;
};
Promise.prototype.cancellable = function () {
if (this._cancellable()) return this;
async.enableTrampoline();
this._setCancellable();
this._cancellationParent = undefined;
return this;
};
Promise.prototype.uncancellable = function () {
var ret = this.then();
ret._unsetCancellable();
return ret;
};
Promise.prototype.fork = function (didFulfill, didReject, didProgress) {
var ret = this._then(didFulfill, didReject, didProgress,
undefined, undefined);
ret._setCancellable();
ret._cancellationParent = undefined;
return ret;
};
};
},{"./async.js":2,"./errors.js":13}],7:[function(_dereq_,module,exports){
"use strict";
module.exports = function() {
var async = _dereq_("./async.js");
var util = _dereq_("./util.js");
var bluebirdFramePattern =
/[\\\/]bluebird[\\\/]js[\\\/](main|debug|zalgo|instrumented)/;
var stackFramePattern = null;
var formatStack = null;
var indentStackFrames = false;
var warn;
function CapturedTrace(parent) {
this._parent = parent;
var length = this._length = 1 + (parent === undefined ? 0 : parent._length);
captureStackTrace(this, CapturedTrace);
if (length > 32) this.uncycle();
}
util.inherits(CapturedTrace, Error);
CapturedTrace.prototype.uncycle = function() {
var length = this._length;
if (length < 2) return;
var nodes = [];
var stackToIndex = {};
for (var i = 0, node = this; node !== undefined; ++i) {
nodes.push(node);
node = node._parent;
}
length = this._length = i;
for (var i = length - 1; i >= 0; --i) {
var stack = nodes[i].stack;
if (stackToIndex[stack] === undefined) {
stackToIndex[stack] = i;
}
}
for (var i = 0; i < length; ++i) {
var currentStack = nodes[i].stack;
var index = stackToIndex[currentStack];
if (index !== undefined && index !== i) {
if (index > 0) {
nodes[index - 1]._parent = undefined;
nodes[index - 1]._length = 1;
}
nodes[i]._parent = undefined;
nodes[i]._length = 1;
var cycleEdgeNode = i > 0 ? nodes[i - 1] : this;
if (index < length - 1) {
cycleEdgeNode._parent = nodes[index + 1];
cycleEdgeNode._parent.uncycle();
cycleEdgeNode._length =
cycleEdgeNode._parent._length + 1;
} else {
cycleEdgeNode._parent = undefined;
cycleEdgeNode._length = 1;
}
var currentChildLength = cycleEdgeNode._length + 1;
for (var j = i - 2; j >= 0; --j) {
nodes[j]._length = currentChildLength;
currentChildLength++;
}
return;
}
}
};
CapturedTrace.prototype.parent = function() {
return this._parent;
};
CapturedTrace.prototype.hasParent = function() {
return this._parent !== undefined;
};
CapturedTrace.prototype.attachExtraTrace = function(error) {
if (error.__stackCleaned__) return;
this.uncycle();
var parsed = CapturedTrace.parseStackAndMessage(error);
var message = parsed.message;
var stacks = [parsed.stack];
var trace = this;
while (trace !== undefined) {
stacks.push(cleanStack(trace.stack.split("\n")));
trace = trace._parent;
}
removeCommonRoots(stacks);
removeDuplicateOrEmptyJumps(stacks);
util.notEnumerableProp(error, "stack", reconstructStack(message, stacks));
util.notEnumerableProp(error, "__stackCleaned__", true);
};
function reconstructStack(message, stacks) {
for (var i = 0; i < stacks.length - 1; ++i) {
stacks[i].push("From previous event:");
stacks[i] = stacks[i].join("\n");
}
if (i < stacks.length) {
stacks[i] = stacks[i].join("\n");
}
return message + "\n" + stacks.join("\n");
}
function removeDuplicateOrEmptyJumps(stacks) {
for (var i = 0; i < stacks.length; ++i) {
if (stacks[i].length === 0 ||
((i + 1 < stacks.length) && stacks[i][0] === stacks[i+1][0])) {
stacks.splice(i, 1);
i--;
}
}
}
function removeCommonRoots(stacks) {
var current = stacks[0];
for (var i = 1; i < stacks.length; ++i) {
var prev = stacks[i];
var currentLastIndex = current.length - 1;
var currentLastLine = current[currentLastIndex];
var commonRootMeetPoint = -1;
for (var j = prev.length - 1; j >= 0; --j) {
if (prev[j] === currentLastLine) {
commonRootMeetPoint = j;
break;
}
}
for (var j = commonRootMeetPoint; j >= 0; --j) {
var line = prev[j];
if (current[currentLastIndex] === line) {
current.pop();
currentLastIndex--;
} else {
break;
}
}
current = prev;
}
}
function cleanStack(stack) {
var ret = [];
for (var i = 0; i < stack.length; ++i) {
var line = stack[i];
var isTraceLine = stackFramePattern.test(line) ||
" (No stack trace)" === line;
var isInternalFrame = isTraceLine && shouldIgnore(line);
if (isTraceLine && !isInternalFrame) {
if (indentStackFrames && line.charAt(0) !== " ") {
line = " " + line;
}
ret.push(line);
}
}
return ret;
}
function stackFramesAsArray(error) {
var stack = error.stack.replace(/\s+$/g, "").split("\n");
for (var i = 0; i < stack.length; ++i) {
var line = stack[i];
if (" (No stack trace)" === line || stackFramePattern.test(line)) {
break;
}
}
if (i > 0) {
stack = stack.slice(i);
}
return stack;
}
CapturedTrace.parseStackAndMessage = function(error) {
var stack = error.stack;
var message = error.toString();
stack = typeof stack === "string" && stack.length > 0
? stackFramesAsArray(error) : [" (No stack trace)"];
return {
message: message,
stack: cleanStack(stack)
};
};
CapturedTrace.formatAndLogError = function(error, title) {
if (typeof console !== "undefined") {
var message;
if (typeof error === "object" || typeof error === "function") {
var stack = error.stack;
message = title + formatStack(stack, error);
} else {
message = title + String(error);
}
if (typeof warn === "function") {
warn(message);
} else if (typeof console.log === "function" ||
typeof console.log === "object") {
console.log(message);
}
}
};
CapturedTrace.unhandledRejection = function (reason) {
CapturedTrace.formatAndLogError(reason, "^--- With additional stack trace: ");
};
CapturedTrace.isSupported = function () {
return typeof captureStackTrace === "function";
};
CapturedTrace.fireRejectionEvent =
function(name, localHandler, reason, promise) {
var localEventFired = false;
try {
if (typeof localHandler === "function") {
localEventFired = true;
if (name === "rejectionHandled") {
localHandler(promise);
} else {
localHandler(reason, promise);
}
}
} catch (e) {
async.throwLater(e);
}
var globalEventFired = false;
try {
globalEventFired = fireGlobalEvent(name, reason, promise);
} catch (e) {
globalEventFired = true;
async.throwLater(e);
}
var domEventFired = false;
if (fireDomEvent) {
try {
domEventFired = fireDomEvent(name.toLowerCase(), {
reason: reason,
promise: promise
});
} catch (e) {
domEventFired = true;
async.throwLater(e);
}
}
if (!globalEventFired && !localEventFired && !domEventFired &&
name === "unhandledRejection") {
CapturedTrace.formatAndLogError(reason, "Unhandled rejection ");
}
};
function formatNonError(obj) {
var str;
if (typeof obj === "function") {
str = "[function " +
(obj.name || "anonymous") +
"]";
} else {
str = obj.toString();
var ruselessToString = /\[object [a-zA-Z0-9$_]+\]/;
if (ruselessToString.test(str)) {
try {
var newStr = JSON.stringify(obj);
str = newStr;
}
catch(e) {
}
}
if (str.length === 0) {
str = "(empty array)";
}
}
return ("(<" + snip(str) + ">, no stack trace)");
}
function snip(str) {
var maxChars = 41;
if (str.length < maxChars) {
return str;
}
return str.substr(0, maxChars - 3) + "...";
}
var shouldIgnore = function() { return false; };
var parseLineInfoRegex = /[\/<\(]([^:\/]+):(\d+):(?:\d+)\)?\s*$/;
function parseLineInfo(line) {
var matches = line.match(parseLineInfoRegex);
if (matches) {
return {
fileName: matches[1],
line: parseInt(matches[2], 10)
};
}
}
CapturedTrace.setBounds = function(firstLineError, lastLineError) {
if (!CapturedTrace.isSupported()) return;
var firstStackLines = firstLineError.stack.split("\n");
var lastStackLines = lastLineError.stack.split("\n");
var firstIndex = -1;
var lastIndex = -1;
var firstFileName;
var lastFileName;
for (var i = 0; i < firstStackLines.length; ++i) {
var result = parseLineInfo(firstStackLines[i]);
if (result) {
firstFileName = result.fileName;
firstIndex = result.line;
break;
}
}
for (var i = 0; i < lastStackLines.length; ++i) {
var result = parseLineInfo(lastStackLines[i]);
if (result) {
lastFileName = result.fileName;
lastIndex = result.line;
break;
}
}
if (firstIndex < 0 || lastIndex < 0 || !firstFileName || !lastFileName ||
firstFileName !== lastFileName || firstIndex >= lastIndex) {
return;
}
shouldIgnore = function(line) {
if (bluebirdFramePattern.test(line)) return true;
var info = parseLineInfo(line);
if (info) {
if (info.fileName === firstFileName &&
(firstIndex <= info.line && info.line <= lastIndex)) {
return true;
}
}
return false;
};
};
var captureStackTrace = (function stackDetection() {
var v8stackFramePattern = /^\s*at\s*/;
var v8stackFormatter = function(stack, error) {
if (typeof stack === "string") return stack;
if (error.name !== undefined &&
error.message !== undefined) {
return error.toString();
}
return formatNonError(error);
};
if (typeof Error.stackTraceLimit === "number" &&
typeof Error.captureStackTrace === "function") {
Error.stackTraceLimit = Error.stackTraceLimit + 6;
stackFramePattern = v8stackFramePattern;
formatStack = v8stackFormatter;
var captureStackTrace = Error.captureStackTrace;
shouldIgnore = function(line) {
return bluebirdFramePattern.test(line);
};
return function(receiver, ignoreUntil) {
Error.stackTraceLimit = Error.stackTraceLimit + 6;
captureStackTrace(receiver, ignoreUntil);
Error.stackTraceLimit = Error.stackTraceLimit - 6;
};
}
var err = new Error();
if (typeof err.stack === "string" &&
err.stack.split("\n")[0].indexOf("stackDetection@") >= 0) {
stackFramePattern = /@/;
formatStack = v8stackFormatter;
indentStackFrames = true;
return function captureStackTrace(o) {
o.stack = new Error().stack;
};
}
var hasStackAfterThrow;
try { throw new Error(); }
catch(e) {
hasStackAfterThrow = ("stack" in e);
}
if (!("stack" in err) && hasStackAfterThrow) {
stackFramePattern = v8stackFramePattern;
formatStack = v8stackFormatter;
return function captureStackTrace(o) {
Error.stackTraceLimit = Error.stackTraceLimit + 6;
try { throw new Error(); }
catch(e) { o.stack = e.stack; }
Error.stackTraceLimit = Error.stackTraceLimit - 6;
};
}
formatStack = function(stack, error) {
if (typeof stack === "string") return stack;
if ((typeof error === "object" ||
typeof error === "function") &&
error.name !== undefined &&
error.message !== undefined) {
return error.toString();
}
return formatNonError(error);
};
return null;
})([]);
var fireDomEvent;
var fireGlobalEvent = (function() {
if (util.isNode) {
return function(name, reason, promise) {
if (name === "rejectionHandled") {
return process.emit(name, promise);
} else {
return process.emit(name, reason, promise);
}
};
} else {
var customEventWorks = false;
var anyEventWorks = true;
try {
va