Created
April 24, 2014 16:40
-
-
Save legastero/11261047 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
!function(e){if("object"==typeof exports)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.XMPP=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 require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.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(_dereq_,module,exports){ | |
"use strict"; | |
exports.Stream = _dereq_('./lib/stanza/stream'); | |
exports.BOSH = _dereq_('./lib/stanza/bosh'); | |
exports.Message = _dereq_('./lib/stanza/message'); | |
exports.Presence = _dereq_('./lib/stanza/presence'); | |
exports.Iq = _dereq_('./lib/stanza/iq'); | |
exports.PubsubEvent = _dereq_('./lib/stanza/pubsub').EventItem; | |
exports.PubsubItem = _dereq_('./lib/stanza/pubsub').Item; | |
exports.JID = _dereq_('./lib/jid'); | |
exports.Client = _dereq_('./lib/client'); | |
exports.crypto = _dereq_('crypto'); | |
exports.jxt = _dereq_('jxt'); | |
exports.createClient = function (opts) { | |
var client = new exports.Client(opts); | |
client.use(_dereq_('./lib/plugins')); | |
return client; | |
}; | |
},{"./lib/client":3,"./lib/jid":4,"./lib/plugins":22,"./lib/stanza/bosh":46,"./lib/stanza/iq":60,"./lib/stanza/message":64,"./lib/stanza/presence":69,"./lib/stanza/pubsub":72,"./lib/stanza/stream":80,"crypto":134,"jxt":164}],2:[function(_dereq_,module,exports){ | |
(function (process){ | |
"use strict"; | |
var _ = _dereq_('underscore'); | |
var util = _dereq_('util'); | |
var async = _dereq_('async'); | |
var Promise = _dereq_('bluebird'); | |
var request = Promise.promisify(_dereq_('request')); | |
var WildEmitter = _dereq_('wildemitter'); | |
var stanza = _dereq_('jxt'); | |
var BOSH = _dereq_('./stanza/bosh'); | |
var StreamError = _dereq_('./stanza/streamError'); | |
var Message = _dereq_('./stanza/message'); | |
var Presence = _dereq_('./stanza/presence'); | |
var Iq = _dereq_('./stanza/iq'); | |
function ConnectionError() {} | |
util.inherits(ConnectionError, Error); | |
function retryRequest(opts, timeout, allowedRetries, retries) { | |
retries = retries || 0; | |
var req = request(opts).cancellable().timeout((timeout || 20) * 1000); | |
return req.spread(function (req, body) { | |
if (req.statusCode < 200 || req.statusCode >= 400) { | |
throw new ConnectionError('HTTP Status Error'); | |
} | |
return body; | |
}).catch(Promise.TimeoutError, function () { | |
throw new ConnectionError('Dead Connection, exceeded timeout limit'); | |
}).catch(Promise.CancellationError, function () { | |
return; // We only cancel on manual disconnect, so let things die silently | |
}).catch(function (err) { | |
if (retries < allowedRetries) { | |
return Promise.delay(100).then(function () { | |
return retryRequest(opts, timeout, allowedRetries, retries + 1); | |
}); | |
} else { | |
throw new ConnectionError('Dead Connection, exceeded retry limit'); | |
} | |
}); | |
} | |
function BOSHConnection(sm) { | |
var self = this; | |
WildEmitter.call(this); | |
self.sm = sm; | |
self.sendQueue = []; | |
self.requests = []; | |
self.maxRequests = 2; | |
self.sid = ''; | |
self.on('raw:incoming', function (data) { | |
data = data.trim(); | |
if (data === '') { | |
return; | |
} | |
var bosh, err; | |
try { | |
bosh = stanza.parse(data, BOSH); | |
} catch (e) { | |
err = new StreamError({ | |
condition: 'invalid-xml' | |
}); | |
self.emit('stream:error', err, e); | |
self.send(err); | |
return self.disconnect(); | |
} | |
if (!self.hasStream) { | |
self.hasStream = true; | |
self.stream = { | |
id: bosh.sid, | |
lang: bosh.lang || 'en', | |
version: bosh.version || '1.0', | |
to: bosh.to, | |
from: bosh.from | |
}; | |
self.sid = bosh.sid; | |
self.maxRequests = bosh.requests; | |
} | |
var payload = bosh.payload; | |
payload.forEach(function (stanzaObj) { | |
if (!stanzaObj.lang) { | |
stanzaObj.lang = self.stream.lang; | |
} | |
self.emit('stream:data', stanzaObj); | |
}); | |
if (bosh.type == 'terminate') { | |
self.rid = undefined; | |
self.sid = undefined; | |
self.emit('bosh:terminate', bosh); | |
self.emit('stream:end'); | |
self.emit('disconnected', self); | |
} | |
}); | |
} | |
util.inherits(BOSHConnection, WildEmitter); | |
BOSHConnection.prototype.connect = function (opts) { | |
var self = this; | |
self.config = _.extend({ | |
rid: Math.ceil(Math.random() * 9999999999), | |
wait: 30, | |
maxRetries: 5 | |
}, opts); | |
self.hasStream = false; | |
self.sm.started = false; | |
self.url = opts.boshURL; | |
self.rid = self.config.rid; | |
self.requests = []; | |
self.rid++; | |
self.request(new BOSH({ | |
version: self.config.version || '1.0', | |
to: self.config.server, | |
lang: self.config.lang || 'en', | |
wait: self.config.wait, | |
ver: '1.6', | |
hold: 1 | |
})); | |
}; | |
BOSHConnection.prototype.disconnect = function () { | |
if (this.hasStream) { | |
this.rid++; | |
this.request(new BOSH({ | |
type: 'terminate' | |
})); | |
} else { | |
this.requests.forEach(function (ticket) { | |
ticket.request.cancel(); | |
}); | |
this.stream = undefined; | |
this.sid = undefined; | |
this.rid = undefined; | |
this.emit('disconnected', this); | |
} | |
}; | |
BOSHConnection.prototype.restart = function () { | |
var self = this; | |
self.rid++; | |
self.request(new BOSH({ | |
to: self.config.server, | |
lang: self.config.lang || 'en', | |
restart: 'true' | |
})); | |
}; | |
BOSHConnection.prototype.send = function (data) { | |
var self = this; | |
if (self.hasStream) { | |
self.sm.track(data); | |
self.sendQueue.push(data); | |
process.nextTick(self.longPoll.bind(self)); | |
} | |
}; | |
BOSHConnection.prototype.longPoll = function () { | |
var self = this; | |
var canReceive = this.requests.length === 0; | |
var canSend = this.sendQueue.length > 0 && this.requests.length < this.maxRequests; | |
if (!this.sid || (!canReceive && !canSend)) return; | |
var stanzas = this.sendQueue; | |
this.sendQueue = []; | |
this.rid++; | |
this.request(new BOSH({ | |
payload: stanzas | |
})); | |
}; | |
BOSHConnection.prototype.request = function (bosh) { | |
var self = this; | |
var ticket = {id: self.rid, request: null}; | |
bosh.rid = self.rid; | |
bosh.sid = self.sid; | |
var body = bosh.toString(); | |
self.emit('raw:outgoing', body); | |
self.requests.push(ticket); | |
var req = retryRequest({ | |
uri: self.url, | |
body: body, | |
method: 'POST', | |
strictSSL: true | |
}, self.config.wait * 1.5, this.config.maxRetries); | |
ticket.request = req; | |
return req.then(function (body) { | |
self.emit('raw:incoming', body); | |
}).catch(ConnectionError, function (err) { | |
self.hasStream = false; | |
var serr = new StreamError({ | |
condition: 'connection-timeout' | |
}); | |
self.emit('stream:error', serr, err); | |
self.disconnect(); | |
}).catch(function (err) { | |
var serr = new StreamError({ | |
condition: 'undefined-condition' | |
}); | |
self.emit('stream:error', serr, err); | |
self.send(serr); | |
self.disconnect(); | |
}).finally(function () { | |
self.requests = _.filter(self.requests, function (item) { | |
return item.id !== ticket.id; | |
}); | |
if (bosh.type !== 'terminate') { | |
// Delay next auto-request by two ticks since we're likely | |
// to send data anyway next tick. | |
process.nextTick(function () { | |
process.nextTick(self.longPoll.bind(self)); | |
}); | |
} | |
}); | |
}; | |
module.exports = BOSHConnection; | |
}).call(this,_dereq_("/Users/lance/Projects/stanza.io/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js")) | |
},{"./stanza/bosh":46,"./stanza/iq":60,"./stanza/message":64,"./stanza/presence":69,"./stanza/streamError":81,"/Users/lance/Projects/stanza.io/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js":140,"async":89,"bluebird":93,"jxt":164,"request":128,"underscore":187,"util":142,"wildemitter":188}],3:[function(_dereq_,module,exports){ | |
"use strict"; | |
var _ = _dereq_('underscore'); | |
var WildEmitter = _dereq_('wildemitter'); | |
var util = _dereq_('util'); | |
var Promise = _dereq_('bluebird'); | |
var async = _dereq_('async'); | |
var uuid = _dereq_('node-uuid'); | |
var b64decode = _dereq_('atob'); | |
var b64encode = _dereq_('btoa'); | |
var SASL = _dereq_('./stanza/sasl'); | |
var Message = _dereq_('./stanza/message'); | |
var Presence = _dereq_('./stanza/presence'); | |
var StreamError = _dereq_('./stanza/streamError'); | |
var Iq = _dereq_('./stanza/iq'); | |
var JID = _dereq_('./jid'); | |
var StreamManagement = _dereq_('./sm'); | |
var WSConnection = _dereq_('./websocket'); | |
var OldWSConnection = _dereq_('./old-websocket'); | |
var BOSHConnection = _dereq_('./bosh'); | |
var getHostMeta = _dereq_('hostmeta'); | |
var SASLFactory = _dereq_('saslmechanisms'); | |
SASLFactory = new SASLFactory(); | |
var SASL_MECHS = { | |
external: _dereq_('sasl-external'), | |
'scram-sha-1': _dereq_('sasl-scram-sha-1'), | |
'digest-md5': _dereq_('sasl-digest-md5'), | |
plain: _dereq_('sasl-plain'), | |
anonymous: _dereq_('sasl-anonymous') | |
}; | |
// Ensure that all basic stanza relationships are established | |
_dereq_('./stanza/stream'); | |
_dereq_('./stanza/sm'); | |
_dereq_('./stanza/error'); | |
_dereq_('./stanza/streamFeatures'); | |
_dereq_('./stanza/bind'); | |
_dereq_('./stanza/session'); | |
function Client(opts) { | |
var self = this; | |
WildEmitter.call(this); | |
opts = opts || {}; | |
this.config = _.extend({ | |
useStreamManagement: true, | |
transports: ['websocket', 'bosh'], | |
sasl: ['external', 'scram-sha-1', 'digest-md5', 'plain', 'anonymous'] | |
}, opts); | |
// Enable SASL authentication mechanisms (and their preferred order) | |
// based on user configuration. | |
if (!_.isArray(this.config.sasl)) { | |
this.config.sasl = [this.config.sasl]; | |
} | |
this.config.sasl.forEach(function (mech) { | |
if (typeof mech === 'string') { | |
var existingMech = SASL_MECHS[mech.toLowerCase()]; | |
if (existingMech) { | |
SASLFactory.use(existingMech); | |
} | |
} else { | |
SASLFactory.use(mech); | |
} | |
}); | |
this.jid = new JID(); | |
this.transports = { | |
websocket: function (client, config) { | |
var ws = client.transport = new WSConnection(client.sm); | |
ws.on('*', function (event, data) { | |
client.emit(event, data); | |
}); | |
ws.connect(config); | |
}, | |
bosh: function (client, config) { | |
var bosh = client.transport = new BOSHConnection(client.sm); | |
bosh.on('*', function (event, data) { | |
client.emit(event, data); | |
}); | |
bosh.connect(config); | |
}, | |
'old-websocket': function (client, config) { | |
var ws = client.transport = new OldWSConnection(client.sm); | |
ws.on('*', function (event, data) { | |
client.emit(event, data); | |
}); | |
ws.connect(config); | |
} | |
}; | |
this.negotiatedFeatures = {}; | |
this.featureOrder = [ | |
'sasl', | |
'streamManagement', | |
'bind', | |
'streamManagement', | |
'caps', | |
'session' | |
]; | |
this.features = {}; | |
this.sm = new StreamManagement(); | |
this.on('stream:data', function (data) { | |
var json = data.toJSON(); | |
if (data._name === 'iq') { | |
json._xmlChildCount = 0; | |
_.each(data.xml.childNodes, function (child) { | |
if (child.nodeType === 1) { | |
json._xmlChildCount += 1; | |
} | |
}); | |
} | |
self.emit(data._eventname || data._name, json); | |
if (data._name === 'message' || data._name === 'presence' || data._name === 'iq') { | |
self.sm.handle(json); | |
self.emit('stanza', json); | |
} else if (data._name === 'smAck') { | |
return self.sm.process(json); | |
} else if (data._name === 'smRequest') { | |
return self.sm.ack(); | |
} | |
if (json.id) { | |
self.emit('id:' + json.id, json); | |
} | |
}); | |
this.on('streamFeatures', function (features) { | |
var series = []; | |
self.featureOrder.forEach(function (name) { | |
if (features[name] && !self.negotiatedFeatures[name]) { | |
series.push(function (cb) { | |
if (!self.negotiatedFeatures[name] && self.features[name]) { | |
self.features[name](features, cb); | |
} else { | |
cb(); | |
} | |
}); | |
} | |
}); | |
async.series(series, function (cmd) { | |
if (cmd === 'restart') { | |
self.transport.restart(); | |
} else if (cmd === 'disconnect') { | |
var serr = new StreamError({ | |
condition: 'policy-violation', | |
text: 'failed to negotiate stream features' | |
}); | |
self.emit('stream:error', serr); | |
self.disconnect(); | |
} | |
}); | |
}); | |
this.features.sasl = function (features, cb) { | |
var mech = SASLFactory.create(features.sasl.mechanisms); | |
self.on('sasl:success', 'sasl', function () { | |
self.negotiatedFeatures.sasl = true; | |
self.releaseGroup('sasl'); | |
self.emit('auth:success'); | |
cb('restart'); | |
}); | |
self.on('sasl:challenge', 'sasl', function (challenge) { | |
mech.challenge(challenge.value); | |
self.send(new SASL.Response({ | |
value: mech.response(self.getCredentials()) | |
})); | |
if (mech.cache) { | |
_.each(mech.cache, function (val, key) { | |
if (val) { | |
self.config.credentials[key] = b64encode(val); | |
} | |
}); | |
self.emit('credentials:update', self.config.credentials); | |
} | |
cb(); | |
}); | |
self.on('sasl:failure', 'sasl', function () { | |
self.releaseGroup('sasl'); | |
self.emit('auth:failed'); | |
cb('disconnect'); | |
}); | |
self.on('sasl:abort', 'sasl', function () { | |
self.releaseGroup('sasl'); | |
self.emit('auth:failed'); | |
cb('disconnect'); | |
}); | |
var auth = { | |
mechanism: mech.name | |
}; | |
if (mech.clientFirst) { | |
auth.value = mech.response(self.getCredentials()); | |
} | |
self.send(new SASL.Auth(auth)); | |
}; | |
this.features.bind = function (features, cb) { | |
self.sendIq({ | |
type: 'set', | |
bind: { | |
resource: self.config.resource | |
} | |
}).then(function (resp) { | |
self.negotiatedFeatures.bind = true; | |
self.emit('session:bound', resp.bind.jid); | |
self.jid = new JID(resp.bind.jid); | |
if (!self.sessionStarted && !features.session) { | |
self.sessionStarted = true; | |
self.emit('session:started', resp.bind.jid); | |
} | |
cb(); | |
}).catch(function (err) { | |
self.emit('session:error', err); | |
cb('disconnect'); | |
}); | |
}; | |
this.features.session = function (features, cb) { | |
self.sendIq({ | |
type: 'set', | |
session: {} | |
}, function () { | |
self.negotiatedFeatures.session = true; | |
if (!self.sessionStarted) { | |
self.sessionStarted = true; | |
self.emit('session:started', self.jid); | |
} | |
cb(); | |
}); | |
}; | |
this.features.caps = function (features, cb) { | |
self.emit('disco:caps', {from: new JID(self.jid.domain), caps: features.caps}); | |
self.negotiatedFeatures.caps = true; | |
cb(); | |
}; | |
this.features.streamManagement = function (features, cb) { | |
if (!self.config.useStreamManagement) { | |
return cb(); | |
} | |
self.on('stream:management:enabled', 'sm', function (enabled) { | |
self.sm.enabled(enabled); | |
self.negotiatedFeatures.streamManagement = true; | |
self.releaseGroup('sm'); | |
cb(); | |
}); | |
self.on('stream:management:resumed', 'sm', function (resumed) { | |
self.sm.enabled(resumed); | |
self.negotiatedFeatures.streamManagement = true; | |
self.negotiatedFeatures.bind = true; | |
self.sessionStarted = true; | |
self.releaseGroup('sm'); | |
cb(); | |
}); | |
self.on('stream:management:failed', 'sm', function (failed) { | |
self.sm.failed(); | |
self.emit('session:end'); | |
self.releaseGroup('session'); | |
self.releaseGroup('sm'); | |
cb(); | |
}); | |
if (!self.sm.id) { | |
if (self.negotiatedFeatures.bind) { | |
self.sm.enable(self.transport); | |
} else { | |
cb(); | |
} | |
} else if (self.sm.id && self.sm.allowResume) { | |
self.sm.resume(self.transport); | |
} else { | |
cb(); | |
} | |
}; | |
this.on('disconnected', function () { | |
if (self.transport) { | |
self.transport.off('*'); | |
delete self.transport; | |
} | |
self.sessionStarted = false; | |
self.negotiatedFeatures.sasl = false; | |
self.negotiatedFeatures.streamManagement = false; | |
self.negotiatedFeatures.bind = false; | |
self.negotiatedFeatures.session = false; | |
self.releaseGroup('connection'); | |
}); | |
this.on('iq', function (iq) { | |
var iqType = iq.type; | |
var xmlChildCount = iq._xmlChildCount; | |
delete iq._xmlChildCount; | |
var exts = Object.keys(iq); | |
if (iq.type === 'get' || iq.type === 'set') { | |
// Invalid request | |
if (xmlChildCount != 1) { | |
return self.sendIq(iq.errorReply({ | |
error: { | |
type: 'modify', | |
condition: 'bad-request' | |
} | |
})); | |
} | |
// Valid request, but we don't have support for the | |
// payload data. | |
if (!exts.length) { | |
return self.sendIq(iq.errorReply({ | |
error: { | |
type: 'cancel', | |
condition: 'feature-not-implemented' | |
} | |
})); | |
} | |
var iqEvent = 'iq:' + iqType + ':' + exts[0]; | |
if (self.callbacks[iqEvent]) { | |
self.emit(iqEvent, iq); | |
} else { | |
// We support the payload data, but there's | |
// nothing registered to handle it. | |
self.sendIq(iq.errorReply({ | |
error: { | |
type: 'cancel', | |
condition: 'feature-not-implemented' | |
} | |
})); | |
} | |
} | |
}); | |
this.on('message', function (msg) { | |
if (Object.keys(msg.$body || {}).length) { | |
if (msg.type === 'chat' || msg.type === 'normal') { | |
self.emit('chat', msg); | |
} else if (msg.type === 'groupchat') { | |
self.emit('groupchat', msg); | |
} | |
} | |
if (msg.type === 'error') { | |
self.emit('message:error', msg); | |
} | |
}); | |
this.on('presence', function (pres) { | |
var presType = pres.type || 'available'; | |
if (presType === 'error') { | |
presType = 'presence:error'; | |
} | |
self.emit(presType, pres); | |
}); | |
} | |
util.inherits(Client, WildEmitter); | |
Client.prototype.__defineGetter__('stream', function () { | |
return this.transport ? this.transport.stream : undefined; | |
}); | |
Client.prototype.use = function (pluginInit) { | |
pluginInit(this); | |
}; | |
Client.prototype.nextId = function () { | |
return uuid.v4(); | |
}; | |
Client.prototype.discoverBindings = function (server, cb) { | |
getHostMeta(server, function (err, data) { | |
if (err) return cb(err, []); | |
var results = { | |
websocket: [], | |
bosh: [] | |
}; | |
var links = data.links || []; | |
links.forEach(function (link) { | |
if (link.href && link.rel === 'urn:xmpp:alt-connections:websocket') { | |
results.websocket.push(link.href); | |
} | |
if (link.href && link.rel === 'urn:xmpp:altconnect:websocket') { | |
results.websocket.push(link.href); | |
} | |
if (link.href && link.rel === 'urn:xmpp:alt-connections:xbosh') { | |
results.bosh.push(link.href); | |
} | |
if (link.href && link.rel === 'urn:xmpp:altconnect:bosh') { | |
results.bosh.push(link.href); | |
} | |
}); | |
cb(false, results); | |
}); | |
}; | |
Client.prototype.getCredentials = function () { | |
var creds = this.config.credentials || {}; | |
var requestedJID = new JID(this.config.jid); | |
var username = creds.username || requestedJID.local; | |
var server = creds.server || requestedJID.domain; | |
var defaultCreds = { | |
username: username, | |
password: this.config.password, | |
server: server, | |
host: server, | |
realm: server, | |
serviceType: 'xmpp', | |
serviceName: server | |
}; | |
var result = _.extend(defaultCreds, creds); | |
var cachedBinary = ['saltedPassword', 'clientKey', 'serverKey']; | |
cachedBinary.forEach(function (key) { | |
if (result[key]) { | |
result[key] = b64decode(result[key]); | |
} | |
}); | |
return result; | |
}; | |
Client.prototype.connect = function (opts) { | |
var self = this; | |
_.extend(self.config, opts || {}); | |
self.config.jid = new JID(self.config.jid); | |
if (!self.config.server) { | |
self.config.server = self.config.jid.domain; | |
} | |
if (self.config.password) { | |
self.config.credentials = self.config.credentials || {}; | |
self.config.credentials.password = self.config.password; | |
delete self.config.password; | |
} | |
if (self.config.transport) { | |
return self.transports[self.config.transport](self, self.config); | |
} | |
return self.discoverBindings(self.config.server, function (err, endpoints) { | |
if (err) { | |
return self.disconnect(); | |
} | |
for (var t = 0, tlen = self.config.transports.length; t < tlen; t++) { | |
var transport = self.config.transports[t]; | |
console.log('Checking for %s endpoints', transport); | |
for (var i = 0, len = (endpoints[transport] || []).length; i < len; i++) { | |
var uri = endpoints[transport][i]; | |
if (uri.indexOf('wss://') === 0 || uri.indexOf('https://') === 0) { | |
if (transport == 'websocket') { | |
self.config.wsURL = uri; | |
} else { | |
self.config.boshURL = uri; | |
} | |
console.log('Using %s endpoint: %s', transport, uri); | |
self.config.transport = transport; | |
return self.connect(); | |
} else { | |
console.warn('Discovered unencrypted %s endpoint (%s). Ignoring', transport, uri); | |
} | |
} | |
} | |
console.warn('No endpoints found for the requested transports.'); | |
return self.disconnect(); | |
}); | |
}; | |
Client.prototype.disconnect = function () { | |
if (this.sessionStarted) { | |
this.emit('session:end'); | |
this.releaseGroup('session'); | |
} | |
this.sessionStarted = false; | |
this.releaseGroup('connection'); | |
if (this.transport) { | |
this.transport.disconnect(); | |
} else { | |
this.emit('disconnected'); | |
} | |
}; | |
Client.prototype.send = function (data) { | |
this.transport.send(data); | |
}; | |
Client.prototype.sendMessage = function (data) { | |
data = data || {}; | |
if (!data.id) { | |
data.id = this.nextId(); | |
} | |
var message = new Message(data); | |
this.emit('message:sent', message); | |
this.send(message); | |
return data.id; | |
}; | |
Client.prototype.sendPresence = function (data) { | |
data = data || {}; | |
if (!data.id) { | |
data.id = this.nextId(); | |
} | |
this.send(new Presence(data)); | |
return data.id; | |
}; | |
Client.prototype.sendIq = function (data, cb) { | |
var result, respEvent, allowed, dest; | |
var self = this; | |
data = data || {}; | |
if (!data.id) { | |
data.id = this.nextId(); | |
} | |
var iq = (!data.toJSON) ? new Iq(data) : data; | |
if (data.type === 'error') { | |
this.send(iq); | |
return; | |
} | |
dest = new JID(data.to); | |
allowed = {}; | |
allowed[''] = true; | |
allowed[dest.full] = true; | |
allowed[dest.bare] = true; | |
allowed[dest.domain] = true; | |
allowed[self.jid.bare] = true; | |
allowed[self.jid.domain] = true; | |
respEvent = 'id:' + data.id; | |
result = new Promise(function (resolve, reject) { | |
var handler = function (res) { | |
if (!allowed[res.from.full]) return; | |
self.off(respEvent, handler); | |
if (!res.error) { | |
resolve(res); | |
} else { | |
reject(res); | |
} | |
}; | |
self.on(respEvent, 'session', handler); | |
}); | |
this.send(iq); | |
return result.timeout(self.config.timeout * 1000 || 15000) | |
.catch(Promise.TimeoutError, function () { | |
return {type: 'error', error: {condition: 'timeout'}}; | |
}) | |
.nodeify(cb); | |
}; | |
Client.prototype.sendStreamError = function (data) { | |
data = data || {}; | |
var error = new StreamError(data); | |
this.emit('stream:error', error); | |
this.send(error); | |
this.disconnect(); | |
}; | |
Client.prototype.JID = function (jid) { | |
return new JID(jid); | |
}; | |
module.exports = Client; | |
},{"./bosh":2,"./jid":4,"./old-websocket":5,"./sm":41,"./stanza/bind":43,"./stanza/error":54,"./stanza/iq":60,"./stanza/message":64,"./stanza/presence":69,"./stanza/sasl":77,"./stanza/session":78,"./stanza/sm":79,"./stanza/stream":80,"./stanza/streamError":81,"./stanza/streamFeatures":82,"./websocket":88,"async":89,"atob":90,"bluebird":93,"btoa":143,"hostmeta":144,"node-uuid":169,"sasl-anonymous":171,"sasl-digest-md5":173,"sasl-external":175,"sasl-plain":177,"sasl-scram-sha-1":179,"saslmechanisms":186,"underscore":187,"util":142,"wildemitter":188}],4:[function(_dereq_,module,exports){ | |
"use strict"; | |
function JID(jid) { | |
jid = jid || ''; | |
if (typeof jid === 'string') { | |
this.jid = jid; | |
this.parts = {}; | |
} else { | |
this.jid = jid.jid || jid.full; | |
this.parts = jid.parts; | |
} | |
} | |
JID.prototype = { | |
constructor: { | |
value: JID | |
}, | |
toString: function () { | |
return this.jid; | |
}, | |
toJSON: function () { | |
return { | |
full: this.full, | |
bare: this.bare, | |
resource: this.resource, | |
local: this.local, | |
domain: this.domain | |
}; | |
}, | |
get full() { | |
return this.jid; | |
}, | |
get bare() { | |
if (this.parts.bare) { | |
return this.parts.bare; | |
} | |
var split = this.jid.indexOf('/'); | |
if (split > 0) { | |
this.parts.bare = this.jid.slice(0, split); | |
} else { | |
this.parts.bare = this.jid; | |
} | |
return this.parts.bare; | |
}, | |
get resource() { | |
if (this.parts.resource) { | |
return this.parts.resource; | |
} | |
var split = this.jid.indexOf('/'); | |
if (split > 0) { | |
this.parts.resource = this.jid.slice(split + 1); | |
} else { | |
this.parts.resource = ''; | |
} | |
return this.parts.resource; | |
}, | |
get local() { | |
if (this.parts.local) { | |
return this.parts.local; | |
} | |
var bare = this.bare; | |
var split = bare.indexOf('@'); | |
if (split > 0) { | |
this.parts.local = bare.slice(0, split); | |
} else { | |
this.parts.local = bare; | |
} | |
return this.parts.local; | |
}, | |
get domain() { | |
if (this.parts.domain) { | |
return this.parts.domain; | |
} | |
var bare = this.bare; | |
var split = bare.indexOf('@'); | |
if (split > 0) { | |
this.parts.domain = bare.slice(split + 1); | |
} else { | |
this.parts.domain = bare; | |
} | |
return this.parts.domain; | |
} | |
}; | |
module.exports = JID; | |
},{}],5:[function(_dereq_,module,exports){ | |
"use strict"; | |
var WSConnection = _dereq_('./websocket'); | |
var _ = _dereq_('underscore'); | |
var util = _dereq_('util'); | |
var stanza = _dereq_('jxt'); | |
var Stream = _dereq_('./stanza/stream'); | |
var StreamError = _dereq_('./stanza/streamError'); | |
var Message = _dereq_('./stanza/message'); | |
var Presence = _dereq_('./stanza/presence'); | |
var Iq = _dereq_('./stanza/iq'); | |
var WS_OPEN = 1; | |
function OldWSConnection(sm) { | |
WSConnection.call(this, sm); | |
var self = this; | |
function wrap(data) { | |
return [self.streamStart, data, self.streamEnd].join(''); | |
} | |
self.on('connected', function () { | |
self.streamStart = '<stream:stream xmlns:stream="http://etherx.jabber.org/streams">'; | |
self.streamEnd = '</stream:stream>'; | |
}); | |
self.off('raw:incoming'); | |
self.on('raw:incoming', function (data) { | |
var streamData, ended, err; | |
data = data.trim(); | |
data = data.replace(/^(\s*<\?.*\?>\s*)*/, ''); | |
if (data === '') { | |
return; | |
} | |
if (data.match(self.streamEnd)) { | |
return self.disconnect(); | |
} else if (self.hasStream) { | |
try { | |
streamData = stanza.parse(wrap(data), Stream); | |
} catch (e) { | |
err = new StreamError({ | |
condition: 'invalid-xml' | |
}); | |
self.emit('stream:error', err, e); | |
self.send(err); | |
return self.disconnect(); | |
} | |
} else { | |
// Inspect start of stream element to get NS prefix name | |
var parts = data.match(/^<(\S+:)?(\S+) /); | |
self.streamStart = data; | |
self.streamEnd = '</' + (parts[1] || '') + parts[2] + '>'; | |
ended = false; | |
try { | |
streamData = stanza.parse(data + self.streamEnd, Stream); | |
} catch (e) { | |
try { | |
streamData = stanza.parse(data, Stream); | |
ended = true; | |
} catch (e2) { | |
err = new StreamError({ | |
condition: 'invalid-xml' | |
}); | |
self.emit('stream:error', err, e2); | |
self.send(err); | |
return self.disconnect(); | |
} | |
} | |
self.hasStream = true; | |
self.stream = streamData; | |
self.emit('stream:start', streamData); | |
} | |
_.each(streamData._extensions, function (stanzaObj) { | |
if (!stanzaObj.lang) { | |
stanzaObj.lang = self.stream.lang; | |
} | |
self.emit('stream:data', stanzaObj); | |
}); | |
if (ended) { | |
self.emit('stream:end'); | |
} | |
}); | |
} | |
util.inherits(OldWSConnection, WSConnection); | |
OldWSConnection.prototype.startHeader = function () { | |
return [ | |
'<stream:stream', | |
'xmlns:stream="http://etherx.jabber.org/streams"', | |
'xmlns="jabber:client"', | |
'version="' + (this.config.version || '1.0') + '"', | |
'xml:lang="' + (this.config.lang || 'en') + '"', | |
'to="' + this.config.server + '">' | |
].join(' '); | |
}; | |
OldWSConnection.prototype.closeHeader = function () { | |
return '</stream:stream>'; | |
}; | |
module.exports = OldWSConnection; | |
},{"./stanza/iq":60,"./stanza/message":64,"./stanza/presence":69,"./stanza/stream":80,"./stanza/streamError":81,"./websocket":88,"jxt":164,"underscore":187,"util":142}],6:[function(_dereq_,module,exports){ | |
"use strict"; | |
module.exports = function (client) { | |
client.disco.addFeature('urn:xmpp:attention:0'); | |
client.getAttention = function (jid, opts) { | |
opts = opts || {}; | |
opts.to = jid; | |
opts.type = 'headline'; | |
opts.attention = true; | |
client.sendMessage(opts); | |
}; | |
client.on('message', function (msg) { | |
if (msg.attention) { | |
client.emit('attention', msg); | |
} | |
}); | |
}; | |
},{}],7:[function(_dereq_,module,exports){ | |
"use strict"; | |
var stanzas = _dereq_('../stanza/avatar'); | |
module.exports = function (client) { | |
client.disco.addFeature('urn:xmpp:avatar:metadata+notify'); | |
client.on('pubsub:event', function (msg) { | |
if (!msg.event.updated) return; | |
if (msg.event.updated.node !== 'urn:xmpp:avatar:metadata') return; | |
client.emit('avatar', { | |
jid: msg.from, | |
source: 'pubsub', | |
avatars: msg.event.updated.published[0].avatars | |
}); | |
}); | |
client.on('presence', function (pres) { | |
if (pres.avatarId) { | |
client.emit('avatar', { | |
jid: pres.from, | |
source: 'vcard', | |
avatars: [{ | |
id: pres.avatarId | |
}] | |
}); | |
} | |
}); | |
client.publishAvatar = function (id, data, cb) { | |
return this.publish('', 'urn:xmpp:avatar:data', { | |
id: id, | |
avatarData: data | |
}, cb); | |
}; | |
client.useAvatars = function (info, cb) { | |
return this.publish('', 'urn:xmpp:avatar:metadata', { | |
id: 'current', | |
avatars: info | |
}, cb); | |
}; | |
client.getAvatar = function (jid, id, cb) { | |
return this.getItem(jid, 'urn:xmpp:avatar:data', id, cb); | |
}; | |
}; | |
},{"../stanza/avatar":42}],8:[function(_dereq_,module,exports){ | |
"use strict"; | |
_dereq_('../stanza/blocking'); | |
module.exports = function (client) { | |
client.disco.addFeature('urn:xmpp:blocking'); | |
client.block = function (jid, cb) { | |
return client.sendIq({ | |
type: 'set', | |
block: { | |
jids: [jid] | |
} | |
}, cb); | |
}; | |
client.unblock = function (jid, cb) { | |
return client.sendIq({ | |
type: 'set', | |
unblock: { | |
jids: [jid] | |
} | |
}, cb); | |
}; | |
client.getBlocked = function (cb) { | |
return client.sendIq({ | |
type: 'get', | |
blockList: {} | |
}, cb); | |
}; | |
client.on('iq:set:block', function (iq) { | |
client.emit('block', { | |
jids: iq.block.jids | |
}); | |
client.sendIq(iq.resultReply()); | |
}); | |
client.on('iq:set:unblock', function (iq) { | |
client.emit('unblock', { | |
jids: iq.unblock.jids | |
}); | |
client.sendIq(iq.resultReply()); | |
}); | |
}; | |
},{"../stanza/blocking":44}],9:[function(_dereq_,module,exports){ | |
"use strict"; | |
var _ = _dereq_('underscore'); | |
var stanzas = _dereq_('../stanza/bookmarks'); | |
var JID = _dereq_('../jid'); | |
module.exports = function (client) { | |
client.getBookmarks = function (cb) { | |
return this.getPrivateData({bookmarks: {}}, cb); | |
}; | |
client.setBookmarks = function (opts, cb) { | |
return this.setPrivateData({bookmarks: opts}, cb); | |
}; | |
client.addBookmark = function (bookmark, cb) { | |
bookmark.jid = new JID(bookmark.jid); | |
return this.getBookmarks().then(function (res) { | |
var bookmarks = res.privateStorage.bookmarks.conferences || []; | |
var existing = _.filter(bookmarks, function (bm) { | |
return bm.jid.bare == bookmark.jid.bare; | |
}); | |
if (existing.length) { | |
_.extend(existing[0], bookmark); | |
} else { | |
bookmarks.push(bookmark); | |
} | |
return client.setBookmarks({conferences: bookmarks}); | |
}).nodeify(cb); | |
}; | |
client.removeBookmark = function (jid, cb) { | |
jid = new JID(jid); | |
return this.getBookmarks().then(function (res) { | |
var bookmarks = res.privateStorage.bookmarks.conferences || []; | |
bookmarks = _.filter(bookmarks, function (bm) { | |
return jid.bare !== bm.jid.bare; | |
}); | |
return client.setBookmarks({conferences: bookmarks}); | |
}).nodeify(cb); | |
}; | |
}; | |
},{"../jid":4,"../stanza/bookmarks":45,"underscore":187}],10:[function(_dereq_,module,exports){ | |
"use strict"; | |
var stanzas = _dereq_('../stanza/carbons'); | |
module.exports = function (client) { | |
client.disco.addFeature('urn:xmpp:carbons:2'); | |
client.enableCarbons = function (cb) { | |
return this.sendIq({ | |
type: 'set', | |
enableCarbons: true | |
}, cb); | |
}; | |
client.disableCarbons = function (cb) { | |
return this.sendIq({ | |
type: 'set', | |
disableCarbons: true | |
}, cb); | |
}; | |
client.on('message', function (msg) { | |
if (msg.carbonSent) { | |
return client.emit('carbon:sent', msg); | |
} | |
if (msg.carbonReceived) { | |
return client.emit('carbon:received', msg); | |
} | |
}); | |
}; | |
},{"../stanza/carbons":48}],11:[function(_dereq_,module,exports){ | |
"use strict"; | |
var stanzas = _dereq_('../stanza/chatstates'); | |
module.exports = function (client) { | |
client.disco.addFeature('http://jabber.org/protocol/chatstates'); | |
client.on('message', function (msg) { | |
if (msg.chatState) { | |
client.emit('chat:state', { | |
to: msg.to, | |
from: msg.from, | |
chatState: msg.chatState | |
}); | |
client.emit('chatState', { | |
to: msg.to, | |
from: msg.from, | |
chatState: msg.chatState | |
}); | |
} | |
}); | |
}; | |
},{"../stanza/chatstates":49}],12:[function(_dereq_,module,exports){ | |
"use strict"; | |
var NS = 'http://jabber.org/protocol/commands'; | |
var stanzas = _dereq_('../stanza/command'); | |
module.exports = function (client) { | |
client.disco.addFeature(NS); | |
client.disco.addItem({ | |
name: 'Ad-Hoc Commands', | |
node: NS | |
}); | |
client.getCommands = function (jid, cb) { | |
return client.getDiscoItems(jid, NS, cb); | |
}; | |
}; | |
},{"../stanza/command":50}],13:[function(_dereq_,module,exports){ | |
"use strict"; | |
module.exports = function (client) { | |
client.disco.addFeature('urn:xmpp:message-correct:0'); | |
client.on('message', function (msg) { | |
if (msg.replace) { | |
client.emit('replace', msg); | |
client.emit('replace:' + msg.id, msg); | |
} | |
}); | |
}; | |
},{}],14:[function(_dereq_,module,exports){ | |
"use strict"; | |
_dereq_('../stanza/dataforms'); | |
module.exports = function (client) { | |
client.disco.addFeature('jabber:x:data'); | |
client.disco.addFeature('urn:xmpp:media-element'); | |
client.on('message', function (msg) { | |
if (msg.form) { | |
client.emit('dataform', msg); | |
} | |
}); | |
}; | |
},{"../stanza/dataforms":51}],15:[function(_dereq_,module,exports){ | |
"use strict"; | |
var stanzas = _dereq_('../stanza/delayed'); | |
module.exports = function (client) { | |
client.disco.addFeature('urn:xmpp:delay'); | |
}; | |
},{"../stanza/delayed":52}],16:[function(_dereq_,module,exports){ | |
/*global unescape, escape */ | |
"use strict"; | |
var _ = _dereq_('underscore'); | |
var crypto = _dereq_('crypto'); | |
_dereq_('../stanza/disco'); | |
_dereq_('../stanza/caps'); | |
var UTF8 = { | |
encode: function (s) { | |
return unescape(encodeURIComponent(s)); | |
}, | |
decode: function (s) { | |
return decodeURIComponent(escape(s)); | |
} | |
}; | |
function generateVerString(info, hash) { | |
var S = ''; | |
var features = info.features.sort(); | |
var identities = []; | |
var formTypes = {}; | |
var formOrder = []; | |
_.forEach(info.identities, function (identity) { | |
identities.push([ | |
identity.category || '', | |
identity.type || '', | |
identity.lang || '', | |
identity.name || '' | |
].join('/')); | |
}); | |
var idLen = identities.length; | |
var featureLen = features.length; | |
identities = _.unique(identities, true); | |
features = _.unique(features, true); | |
if (featureLen != features.length || idLen != identities.length) { | |
return false; | |
} | |
S += identities.join('<') + '<'; | |
S += features.join('<') + '<'; | |
var illFormed = false; | |
_.forEach(info.extensions, function (ext) { | |
var fields = ext.fields; | |
for (var i = 0, len = fields.length; i < len; i++) { | |
if (fields[i].name == 'FORM_TYPE' && fields[i].type == 'hidden') { | |
var name = fields[i].value; | |
if (formTypes[name]) { | |
illFormed = true; | |
return; | |
} | |
formTypes[name] = ext; | |
formOrder.push(name); | |
return; | |
} | |
} | |
}); | |
if (illFormed) { | |
return false; | |
} | |
formOrder.sort(); | |
_.forEach(formOrder, function (name) { | |
var ext = formTypes[name]; | |
var fields = {}; | |
var fieldOrder = []; | |
S += '<' + name; | |
_.forEach(ext.fields, function (field) { | |
var fieldName = field.name; | |
if (fieldName != 'FORM_TYPE') { | |
var values = field.value || ''; | |
if (typeof values != 'object') { | |
values = values.split('\n'); | |
} | |
fields[fieldName] = values.sort(); | |
fieldOrder.push(fieldName); | |
} | |
}); | |
fieldOrder.sort(); | |
_.forEach(fieldOrder, function (fieldName) { | |
S += '<' + fieldName; | |
_.forEach(fields[fieldName], function (val) { | |
S += '<' + val; | |
}); | |
}); | |
}); | |
if (hash === 'sha-1') { | |
hash = 'sha1'; | |
} | |
var ver = crypto.createHash(hash).update(UTF8.encode(S)).digest('base64'); | |
var padding = 4 - ver.length % 4; | |
if (padding === 4) { | |
padding = 0; | |
} | |
for (var i = 0; i < padding; i++) { | |
ver += '='; | |
} | |
return ver; | |
} | |
function verifyVerString(info, hash, check) { | |
if (hash === 'sha-1') { | |
hash = 'sha1'; | |
} | |
var computed = generateVerString(info, hash); | |
return computed && computed == check; | |
} | |
function Disco(client) { | |
this.features = {}; | |
this.identities = {}; | |
this.extensions = {}; | |
this.items = {}; | |
this.caps = {}; | |
} | |
Disco.prototype = { | |
constructor: { | |
value: Disco | |
}, | |
addFeature: function (feature, node) { | |
node = node || ''; | |
if (!this.features[node]) { | |
this.features[node] = []; | |
} | |
this.features[node].push(feature); | |
}, | |
addIdentity: function (identity, node) { | |
node = node || ''; | |
if (!this.identities[node]) { | |
this.identities[node] = []; | |
} | |
this.identities[node].push(identity); | |
}, | |
addItem: function (item, node) { | |
node = node || ''; | |
if (!this.items[node]) { | |
this.items[node] = []; | |
} | |
this.items[node].push(item); | |
}, | |
addExtension: function (form, node) { | |
node = node || ''; | |
if (!this.extensions[node]) { | |
this.extensions[node] = []; | |
} | |
this.extensions[node].push(form); | |
} | |
}; | |
module.exports = function (client) { | |
client.disco = new Disco(client); | |
client.disco.addFeature('http://jabber.org/protocol/disco#info'); | |
client.disco.addIdentity({ | |
category: 'client', | |
type: 'web' | |
}); | |
client.getDiscoInfo = function (jid, node, cb) { | |
return this.sendIq({ | |
to: jid, | |
type: 'get', | |
discoInfo: { | |
node: node | |
} | |
}, cb); | |
}; | |
client.getDiscoItems = function (jid, node, cb) { | |
return this.sendIq({ | |
to: jid, | |
type: 'get', | |
discoItems: { | |
node: node | |
} | |
}, cb); | |
}; | |
client.updateCaps = function () { | |
var node = this.config.capsNode || 'https://stanza.io'; | |
var data = JSON.parse(JSON.stringify({ | |
identities: this.disco.identities[''], | |
features: this.disco.features[''], | |
extensions: this.disco.extensions[''] | |
})); | |
var ver = generateVerString(data, 'sha-1'); | |
this.disco.caps = { | |
node: node, | |
hash: 'sha-1', | |
ver: ver | |
}; | |
node = node + '#' + ver; | |
this.disco.features[node] = data.features; | |
this.disco.identities[node] = data.identities; | |
this.disco.extensions[node] = data.extensions; | |
return client.getCurrentCaps(); | |
}; | |
client.getCurrentCaps = function () { | |
var caps = client.disco.caps; | |
if (!caps.ver) { | |
return {ver: null, discoInfo: null}; | |
} | |
var node = caps.node + '#' + caps.ver; | |
return { | |
ver: caps.ver, | |
discoInfo: { | |
identities: client.disco.identities[node], | |
features: client.disco.features[node], | |
extensions: client.disco.extensions[node] | |
} | |
}; | |
}; | |
client.on('presence', function (pres) { | |
if (pres.caps) { | |
client.emit('disco:caps', pres); | |
} | |
}); | |
client.on('iq:get:discoInfo', function (iq) { | |
var node = iq.discoInfo.node; | |
var reportedNode = iq.discoInfo.node; | |
if (node === client.disco.caps.node + '#' + client.disco.caps.ver) { | |
reportedNode = node; | |
node = ''; | |
} | |
client.sendIq(iq.resultReply({ | |
discoInfo: { | |
node: reportedNode, | |
identities: client.disco.identities[node] || [], | |
features: client.disco.features[node] || [], | |
extensions: client.disco.extensions[node] || [] | |
} | |
})); | |
}); | |
client.on('iq:get:discoItems', function (iq) { | |
var node = iq.discoInfo.node; | |
client.sendIq(iq.resultReply({ | |
discoItems: { | |
node: node, | |
items: client.disco.items[node] || [] | |
} | |
})); | |
}); | |
client.verifyVerString = verifyVerString; | |
client.generateVerString = generateVerString; | |
}; | |
},{"../stanza/caps":47,"../stanza/disco":53,"crypto":134,"underscore":187}],17:[function(_dereq_,module,exports){ | |
"use strict"; | |
var stanzas = _dereq_('../stanza/extdisco'); | |
module.exports = function (client) { | |
client.disco.addFeature('urn:xmpp:extdisco:1'); | |
client.getServices = function (jid, type, cb) { | |
return this.sendIq({ | |
type: 'get', | |
to: jid, | |
services: { | |
type: type | |
} | |
}, cb); | |
}; | |
client.getServiceCredentials = function (jid, host, cb) { | |
return this.sendIq({ | |
type: 'get', | |
to: jid, | |
credentials: { | |
service: { | |
host: host | |
} | |
} | |
}, cb); | |
}; | |
}; | |
},{"../stanza/extdisco":55}],18:[function(_dereq_,module,exports){ | |
"use strict"; | |
var stanzas = _dereq_('../stanza/forwarded'); | |
module.exports = function (client) { | |
client.disco.addFeature('urn:xmpp:forward:0'); | |
}; | |
},{"../stanza/forwarded":56}],19:[function(_dereq_,module,exports){ | |
"use strict"; | |
var stanzas = _dereq_('../stanza/geoloc'); | |
module.exports = function (client) { | |
client.disco.addFeature('http://jabber.org/protocol/geoloc'); | |
client.disco.addFeature('http://jabber.org/protocol/geoloc+notify'); | |
client.on('pubsub:event', function (msg) { | |
if (!msg.event.updated) return; | |
if (msg.event.updated.node !== 'http://jabber.org/protocol/geoloc') return; | |
client.emit('geoloc', { | |
jid: msg.from, | |
geoloc: msg.event.updated.published[0].geoloc | |
}); | |
}); | |
client.publishGeoLoc = function (data, cb) { | |
return this.publish('', 'http://jabber.org/protocol/geoloc', { | |
geoloc: data | |
}, cb); | |
}; | |
}; | |
},{"../stanza/geoloc":58}],20:[function(_dereq_,module,exports){ | |
"use strict"; | |
module.exports = function (client) { | |
client.disco.addFeature('urn:xmpp:hashes:1'); | |
client.disco.addFeature('urn:xmpp:hash-function-text-names:md5'); | |
client.disco.addFeature('urn:xmpp:hash-function-text-names:sha-1'); | |
client.disco.addFeature('urn:xmpp:hash-function-text-names:sha-256'); | |
}; | |
},{}],21:[function(_dereq_,module,exports){ | |
"use strict"; | |
module.exports = function (client) { | |
client.disco.addFeature('urn:xmpp:idle:1'); | |
}; | |
},{}],22:[function(_dereq_,module,exports){ | |
"use strict"; | |
module.exports = function (client) { | |
// We always need this one first | |
client.use(_dereq_('./disco')); | |
client.use(_dereq_('./attention')); | |
client.use(_dereq_('./avatar')); | |
client.use(_dereq_('./blocking')); | |
client.use(_dereq_('./bookmarks')); | |
client.use(_dereq_('./carbons')); | |
client.use(_dereq_('./chatstates')); | |
client.use(_dereq_('./command')); | |
client.use(_dereq_('./correction')); | |
client.use(_dereq_('./dataforms')); | |
client.use(_dereq_('./delayed')); | |
client.use(_dereq_('./extdisco')); | |
client.use(_dereq_('./forwarding')); | |
client.use(_dereq_('./geoloc')); | |
client.use(_dereq_('./hashes')); | |
client.use(_dereq_('./idle')); | |
client.use(_dereq_('./invisible')); | |
client.use(_dereq_('./jingle')); | |
client.use(_dereq_('./json')); | |
client.use(_dereq_('./keepalive')); | |
client.use(_dereq_('./mam')); | |
client.use(_dereq_('./muc')); | |
client.use(_dereq_('./nick')); | |
client.use(_dereq_('./oob')); | |
client.use(_dereq_('./ping')); | |
client.use(_dereq_('./private')); | |
client.use(_dereq_('./psa')); | |
client.use(_dereq_('./pubsub')); | |
client.use(_dereq_('./reach')); | |
client.use(_dereq_('./receipts')); | |
client.use(_dereq_('./roster')); | |
client.use(_dereq_('./time')); | |
client.use(_dereq_('./vcard')); | |
client.use(_dereq_('./version')); | |
}; | |
},{"./attention":6,"./avatar":7,"./blocking":8,"./bookmarks":9,"./carbons":10,"./chatstates":11,"./command":12,"./correction":13,"./dataforms":14,"./delayed":15,"./disco":16,"./extdisco":17,"./forwarding":18,"./geoloc":19,"./hashes":20,"./idle":21,"./invisible":23,"./jingle":24,"./json":25,"./keepalive":26,"./mam":27,"./muc":28,"./nick":29,"./oob":30,"./ping":31,"./private":32,"./psa":33,"./pubsub":34,"./reach":35,"./receipts":36,"./roster":37,"./time":38,"./vcard":39,"./version":40}],23:[function(_dereq_,module,exports){ | |
"use strict"; | |
_dereq_('../stanza/visibility'); | |
module.exports = function (client) { | |
client.goInvisible = function (cb) { | |
return this.sendIq({ | |
type: 'set', | |
invisible: true | |
}, cb); | |
}; | |
client.goVisible = function (cb) { | |
return this.sendIq({ | |
type: 'set', | |
visible: true | |
}, cb); | |
}; | |
}; | |
},{"../stanza/visibility":87}],24:[function(_dereq_,module,exports){ | |
"use strict"; | |
var Jingle = _dereq_('jingle'); | |
var stanza = _dereq_('../stanza/jingle'); | |
var rtp = _dereq_('../stanza/rtp'); | |
var ice = _dereq_('../stanza/iceUdp'); | |
module.exports = function (client) { | |
var jingle = client.jingle = new Jingle(); | |
jingle.capabilities.forEach(function (cap) { | |
client.disco.addFeature(cap); | |
}); | |
var mappedEvents = [ | |
'outgoing', 'incoming', 'accepted', 'terminated', | |
'ringing', 'mute', 'unmute', 'hold', 'resumed' | |
]; | |
mappedEvents.forEach(function (event) { | |
jingle.on(event, function (session, arg1) { | |
client.emit('jingle:' + event, session, arg1); | |
}); | |
}); | |
jingle.on('localStream', function (stream) { | |
client.emit('jingle:localstream:added', stream); | |
}); | |
jingle.on('localStreamStopped', function () { | |
client.emit('jingle:localstream:removed'); | |
}); | |
jingle.on('peerStreamAdded', function (session, stream) { | |
client.emit('jingle:remotestream:added', session, stream); | |
}); | |
jingle.on('peerStreamRemoved', function (session, stream) { | |
client.emit('jingle:remotestream:removed', session, stream); | |
}); | |
jingle.on('send', function (data) { | |
client.sendIq(data); | |
}); | |
client.on('iq:set:jingle', function (data) { | |
jingle.process(data); | |
}); | |
client.on('unavailable', function (pres) { | |
var peer = pres.from.full; | |
jingle.endPeerSessions(peer); | |
}); | |
client.call = function (peer) { | |
peer = peer.full || peer; | |
var sess = jingle.createMediaSession(peer); | |
client.sendPresence({to: peer}); | |
sess.start(); | |
return sess; | |
}; | |
client.discoverICEServers = function (cb) { | |
return this.getServices(client.config.server).then(function (res) { | |
var services = res.services.services; | |
var discovered = []; | |
for (var i = 0; i < services.length; i++) { | |
var service = services[i]; | |
var ice = {}; | |
if (service.type === 'stun') { | |
ice.url = 'stun:' + service.host; | |
if (service.port) { | |
ice.url += ':' + service.port; | |
} | |
discovered.push(ice); | |
client.jingle.addICEServer(ice); | |
} else if (service.type === 'turn') { | |
ice.url = 'turn:' + service.host; | |
if (service.port) { | |
ice.url += ':' + service.port; | |
} | |
if (service.transport && service.transport !== 'udp') { | |
ice.url += '?transport=' + service.transport; | |
} | |
if (service.username) { | |
ice.username = service.username; | |
} | |
if (service.password) { | |
ice.credential = service.password; | |
} | |
discovered.push(ice); | |
client.jingle.addICEServer(ice); | |
} | |
} | |
return discovered; | |
}).nodeify(cb); | |
}; | |
}; | |
},{"../stanza/iceUdp":59,"../stanza/jingle":61,"../stanza/rtp":76,"jingle":146}],25:[function(_dereq_,module,exports){ | |
"use strict"; | |
var stanza = _dereq_('../stanza/json'); | |
module.exports = function (client) { | |
client.disco.addFeature('urn:xmpp:json:tmp'); | |
}; | |
},{"../stanza/json":62}],26:[function(_dereq_,module,exports){ | |
"use strict"; | |
var Promise = _dereq_('bluebird'); | |
function checkConnection(client, timeout) { | |
return new Promise(function (resolve, reject) { | |
if (client.sm.started) { | |
client.once('stream:management:ack', resolve); | |
client.sm.request(); | |
} else { | |
client.ping().then(resolve).catch(function (err) { | |
if (err.error && err.error.condition !== 'timeout') { | |
resolve(); | |
} else { | |
reject(); | |
} | |
}); | |
} | |
}).timeout(timeout * 1000 || 15000); | |
} | |
module.exports = function (client) { | |
client.enableKeepAlive = function (opts) { | |
opts = opts || {}; | |
// Ping every 5 minutes | |
opts.interval = opts.interval || 300; | |
// Disconnect if no response in 15 seconds | |
opts.timeout = opts.timeout || 15; | |
function keepalive() { | |
if (client.sessionStarted) { | |
checkConnection(client, opts.timeout).catch(function () { | |
client.sendStreamError({ | |
condition: 'connection-timeout' | |
}); | |
}); | |
} | |
} | |
client._keepAliveInterval = setInterval(keepalive, opts.interval * 1000); | |
}; | |
client.disableKeepAlive = function () { | |
if (client._keepAliveInterval) { | |
clearInterval(client._keepAliveInterval); | |
delete client._keepAliveInterval; | |
} | |
}; | |
client.on('disconnected', function () { | |
client.disableKeepAlive(); | |
}); | |
}; | |
},{"bluebird":93}],27:[function(_dereq_,module,exports){ | |
"use strict"; | |
var stanzas = _dereq_('../stanza/mam'); | |
var JID = _dereq_('../jid'); | |
module.exports = function (client) { | |
client.disco.addFeature('urn:xmpp:mam:tmp'); | |
client.getHistory = function (opts, cb) { | |
var self = this; | |
var queryid = this.nextId(); | |
opts = opts || {}; | |
opts.queryid = queryid; | |
var to = opts.to || ''; | |
delete opts.to; | |
var dest = new JID(to || client.jid.bare); | |
var allowed = {}; | |
allowed[''] = true; | |
allowed[dest.full] = true; | |
allowed[dest.bare] = true; | |
allowed[dest.domain] = true; | |
allowed[client.jid.bare] = true; | |
allowed[client.jid.domain] = true; | |
var mamResults = []; | |
this.on('mam:' + queryid, 'session', function (msg) { | |
if (!allowed[msg.from.full]) return; | |
mamResults.push(msg); | |
}); | |
return this.sendIq({ | |
type: 'get', | |
to: to, | |
id: queryid, | |
mamQuery: opts | |
}).then(function (resp) { | |
resp.mamQuery.results = mamResults; | |
return resp; | |
}).finally(function () { | |
self.off('mam:' + queryid); | |
}).nodeify(cb); | |
}; | |
client.getHistoryPreferences = function (cb) { | |
return this.sendIq({ | |
type: 'get', | |
mamPrefs: {} | |
}, cb); | |
}; | |
client.setHistoryPreferences = function (opts, cb) { | |
return this.sendIq({ | |
type: 'set', | |
mamPrefs: opts | |
}, cb); | |
}; | |
client.on('message', function (msg) { | |
if (msg.mam) { | |
client.emit('mam:' + msg.mam.queryid, msg); | |
} | |
}); | |
}; | |
},{"../jid":4,"../stanza/mam":63}],28:[function(_dereq_,module,exports){ | |
"use strict"; | |
var _ = _dereq_('underscore'); | |
var JID = _dereq_('../jid'); | |
_dereq_('../stanza/muc'); | |
module.exports = function (client) { | |
client.disco.addFeature('http://jabber.org/protocol/muc'); | |
client.disco.addFeature('jabber:x:conference'); | |
client.joinedRooms = {}; | |
function rejoinRooms() { | |
_.each(client.joinedRooms, function (nick, room) { | |
client.joinedRooms[room] = false; | |
client.joinRoom(room, nick); | |
}); | |
} | |
client.on('session:started', rejoinRooms); | |
client.on('stream:management:resumed', rejoinRooms); | |
client.on('message', function (msg) { | |
if (msg.muc) { | |
if (msg.muc.invite) { | |
client.emit('muc:invite', { | |
from: msg.muc.invite.from, | |
room: msg.from, | |
reason: msg.muc.invite.reason, | |
password: msg.muc.password, | |
thread: msg.muc.invite.thread, | |
type: 'mediated' | |
}); | |
} | |
if (msg.muc.destroyed) { | |
client.emit('muc:destroyed', { | |
room: msg.from, | |
newRoom: msg.muc.destroyed.jid, | |
reason: msg.muc.destroyed.reason, | |
password: msg.muc.password | |
}); | |
} | |
if (msg.muc.decline) { | |
client.emit('muc:declined', { | |
room: msg.from, | |
from: msg.muc.decline.from, | |
reason: msg.muc.decline.reason | |
}); | |
} | |
} else if (msg.mucInvite) { | |
client.emit('muc:invite', { | |
from: msg.from, | |
room: msg.mucInvite.jid, | |
reason: msg.mucInvite.reason, | |
password: msg.mucInvite.password, | |
thread: msg.mucInvite.thread, | |
type: 'direct' | |
}); | |
} | |
if (msg.type === 'groupchat' && msg.subject) { | |
client.emit('muc:subject', msg); | |
} | |
}); | |
client.on('presence', function (pres) { | |
if (pres.muc) { | |
var isSelf = pres.muc.codes && pres.muc.codes.indexOf('110') >= 0; | |
if (pres.type == 'error') { | |
client.emit('muc:error', pres); | |
} else if (pres.type == 'unavailable') { | |
client.emit('muc:unavailable', pres); | |
if (isSelf) { | |
client.emit('muc:leave', pres); | |
delete client.joinedRooms[pres.from.bare]; | |
} | |
} else { | |
client.emit('muc:available', pres); | |
if (isSelf && !client.joinedRooms[pres.from.bare]) { | |
client.emit('muc:join', pres); | |
client.joinedRooms[pres.from.bare] = pres.from.resource; | |
} | |
} | |
} | |
}); | |
client.joinRoom = function (room, nick, opts) { | |
opts = opts || {}; | |
opts.to = room + '/' + nick; | |
opts.caps = this.disco.caps; | |
opts.joinMuc = opts.joinMuc || {}; | |
this.sendPresence(opts); | |
}; | |
client.leaveRoom = function (room, nick, opts) { | |
opts = opts || {}; | |
opts.to = room + '/' + nick; | |
opts.type = 'unavailable'; | |
this.sendPresence(opts); | |
}; | |
client.ban = function (room, jid, reason, cb) { | |
client.setRoomAffiliation(room, jid, 'outcast', reason, cb); | |
}; | |
client.kick = function (room, nick, reason, cb) { | |
client.setRoomRole(room, nick, 'none', reason, cb); | |
}; | |
client.invite = function (room, opts) { | |
client.sendMessage({ | |
to: room, | |
muc: { | |
invites: opts | |
} | |
}); | |
}; | |
client.directInvite = function (room, opts) { | |
opts.jid = room; | |
client.sendMessage({ | |
to: opts.to, | |
mucInvite: opts | |
}); | |
}; | |
client.declineInvite = function (room, sender, reason) { | |
client.sendMessage({ | |
to: room, | |
muc: { | |
decline: { | |
to: sender, | |
reason: reason | |
} | |
} | |
}); | |
}; | |
client.changeNick = function (room, nick) { | |
client.sendPresence({ | |
to: (new JID(room)).bare + '/' + nick | |
}); | |
}; | |
client.setSubject = function (room, subject) { | |
client.sendMessage({ | |
to: room, | |
type: 'groupchat', | |
subject: subject | |
}); | |
}; | |
client.discoverReservedNick = function (room, cb) { | |
client.getDiscoInfo(room, 'x-roomuser-item', function (err, res) { | |
if (err) return cb(err); | |
var ident = res.discoInfo.identities[0] || {}; | |
cb(null, ident.name); | |
}); | |
}; | |
client.requestRoomVoice = function (room) { | |
client.sendMessage({ | |
to: room, | |
form: { | |
fields: [ | |
{ | |
name: 'FORM_TYPE', | |
value: 'http://jabber.org/protocol/muc#request' | |
}, | |
{ | |
name: 'muc#role', | |
type: 'text-single', | |
value: 'participant' | |
} | |
] | |
} | |
}); | |
}; | |
client.setRoomAffiliation = function (room, jid, affiliation, reason, cb) { | |
return this.sendIq({ | |
type: 'set', | |
to: room, | |
mucAdmin: { | |
jid: jid, | |
affiliation: affiliation, | |
reason: reason | |
} | |
}, cb); | |
}; | |
client.setRoomRole = function (room, nick, role, reason, cb) { | |
return this.sendIq({ | |
type: 'set', | |
to: room, | |
mucAdmin: { | |
nick: nick, | |
role: role, | |
reason: reason | |
} | |
}, cb); | |
}; | |
client.getRoomMembers = function (room, opts, cb) { | |
return this.sendIq({ | |
type: 'get', | |
to: room, | |
mucAdmin: opts | |
}, cb); | |
}; | |
client.getRoomConfig = function (jid, cb) { | |
return this.sendIq({ | |
to: jid, | |
type: 'get', | |
mucOwner: {} | |
}, cb); | |
}; | |
client.configureRoom = function (jid, form, cb) { | |
if (!form.type) form.type = 'submit'; | |
return this.sendIq({ | |
to: jid, | |
type: 'set', | |
mucOwner: { | |
form: form | |
} | |
}, cb); | |
}; | |
}; | |
},{"../jid":4,"../stanza/muc":65,"underscore":187}],29:[function(_dereq_,module,exports){ | |
"use strict"; | |
var stanza = _dereq_('../stanza/nick'); | |
var NS = 'http://jabber.org/protocol/nick'; | |
module.exports = function (client) { | |
client.disco.addFeature(NS); | |
client.disco.addFeature(NS + '+notify'); | |
client.on('pubsub:event', function (msg) { | |
if (!msg.event.updated) return; | |
if (msg.event.updated.node !== NS) return; | |
client.emit('nick', { | |
jid: msg.from, | |
nick: msg.event.updated.published[0].nick | |
}); | |
}); | |
client.publishNick = function (nick, cb) { | |
return this.publish('', NS, { | |
nick: nick | |
}, cb); | |
}; | |
}; | |
},{"../stanza/nick":66}],30:[function(_dereq_,module,exports){ | |
"use strict"; | |
var stanzas = _dereq_('../stanza/oob'); | |
module.exports = function (client) { | |
client.disco.addFeature('jabber:x:oob'); | |
}; | |
},{"../stanza/oob":67}],31:[function(_dereq_,module,exports){ | |
"use strict"; | |
var stanzas = _dereq_('../stanza/ping'); | |
module.exports = function (client) { | |
client.disco.addFeature('urn:xmpp:ping'); | |
client.on('iq:get:ping', function (iq) { | |
client.sendIq(iq.resultReply()); | |
}); | |
client.ping = function (jid, cb) { | |
return this.sendIq({ | |
to: jid, | |
type: 'get', | |
ping: {} | |
}); | |
}; | |
}; | |
},{"../stanza/ping":68}],32:[function(_dereq_,module,exports){ | |
"use strict"; | |
var stanzas = _dereq_('../stanza/private'); | |
module.exports = function (client) { | |
client.getPrivateData = function (opts, cb) { | |
return this.sendIq({ | |
type: 'get', | |
privateStorage: opts | |
}, cb); | |
}; | |
client.setPrivateData = function (opts, cb) { | |
return this.sendIq({ | |
type: 'set', | |
privateStorage: opts | |
}, cb); | |
}; | |
}; | |
},{"../stanza/private":70}],33:[function(_dereq_,module,exports){ | |
"use strict"; | |
_dereq_('../stanza/psa'); | |
module.exports = function (client) { | |
client.disco.addFeature('urn:xmpp:psa'); | |
}; | |
},{"../stanza/psa":71}],34:[function(_dereq_,module,exports){ | |
"use strict"; | |
var stanzas = _dereq_('../stanza/pubsub'); | |
module.exports = function (client) { | |
client.on('message', function (msg) { | |
if (msg.event) { | |
client.emit('pubsub:event', msg); | |
client.emit('pubsubEvent', msg); | |
} | |
}); | |
client.subscribeToNode = function (jid, opts, cb) { | |
return this.sendIq({ | |
type: 'set', | |
to: jid, | |
pubsub: { | |
subscribe: { | |
node: opts.node, | |
jid: opts.jid || client.jid | |
} | |
} | |
}, cb); | |
}; | |
client.unsubscribeFromNode = function (jid, opts, cb) { | |
return this.sendIq({ | |
type: 'set', | |
to: jid, | |
pubsub: { | |
unsubscribe: { | |
node: opts.node, | |
jid: opts.jid || client.jid.split('/')[0] | |
} | |
} | |
}, cb); | |
}; | |
client.publish = function (jid, node, item, cb) { | |
return this.sendIq({ | |
type: 'set', | |
to: jid, | |
pubsub: { | |
publish: { | |
node: node, | |
item: item | |
} | |
} | |
}, cb); | |
}; | |
client.getItem = function (jid, node, id, cb) { | |
return this.sendIq({ | |
type: 'get', | |
to: jid, | |
pubsub: { | |
retrieve: { | |
node: node, | |
item: id | |
} | |
} | |
}, cb); | |
}; | |
client.getItems = function (jid, node, opts, cb) { | |
opts = opts || {}; | |
opts.node = node; | |
return this.sendIq({ | |
type: 'get', | |
to: jid, | |
pubsub: { | |
retrieve: { | |
node: node, | |
max: opts.max | |
}, | |
rsm: opts.rsm | |
} | |
}, cb); | |
}; | |
client.retract = function (jid, node, id, notify, cb) { | |
return this.sendIq({ | |
type: 'set', | |
to: jid, | |
pubsub: { | |
retract: { | |
node: node, | |
notify: notify, | |
id: id | |
} | |
} | |
}, cb); | |
}; | |
client.purgeNode = function (jid, node, cb) { | |
return this.sendIq({ | |
type: 'set', | |
to: jid, | |
pubsubOwner: { | |
purge: node | |
} | |
}, cb); | |
}; | |
client.deleteNode = function (jid, node, cb) { | |
return this.sendIq({ | |
type: 'set', | |
to: jid, | |
pubsubOwner: { | |
del: node | |
} | |
}, cb); | |
}; | |
client.createNode = function (jid, node, config, cb) { | |
var cmd = { | |
type: 'set', | |
to: jid, | |
pubsubOwner: { | |
create: node | |
} | |
}; | |
if (config) { | |
cmd.pubsubOwner.config = {form: config}; | |
} | |
return this.sendIq(cmd, cb); | |
}; | |
}; | |
},{"../stanza/pubsub":72}],35:[function(_dereq_,module,exports){ | |
"use strict"; | |
var stanzas = _dereq_('../stanza/reach'); | |
module.exports = function (client) { | |
client.disco.addFeature('urn:xmpp:reach:0'); | |
client.disco.addFeature('urn:xmpp:reach:0+notify'); | |
client.on('pubsub:event', function (msg) { | |
if (!msg.event.updated) return; | |
if (msg.event.updated.node !== 'urn:xmpp:reach:0') return; | |
client.emit('reachability', { | |
jid: msg.from, | |
addresses: msg.event.updated.published[0].reach | |
}); | |
}); | |
client.on('presence', function (pres) { | |
if (!pres.reach || !pres.reach.length) return; | |
client.emit('reachability', { | |
jid: pres.from, | |
addresses: pres.reach | |
}); | |
}); | |
client.publishReachability = function (data, cb) { | |
return this.publish('', 'urn:xmpp:reach:0', { | |
reach: data | |
}, cb); | |
}; | |
}; | |
},{"../stanza/reach":73}],36:[function(_dereq_,module,exports){ | |
"use strict"; | |
module.exports = function (client) { | |
client.disco.addFeature('urn:xmpp:receipts'); | |
client.on('message', function (msg) { | |
var ackTypes = { | |
normal: true, | |
chat: true, | |
headline: true | |
}; | |
if (ackTypes[msg.type] && msg.requestReceipt && !msg.receipt) { | |
client.sendMessage({ | |
to: msg.from, | |
receipt: msg.id, | |
id: msg.id | |
}); | |
} | |
if (msg.receipt) { | |
client.emit('receipt', msg); | |
client.emit('receipt:' + msg.receipt); | |
} | |
}); | |
}; | |
},{}],37:[function(_dereq_,module,exports){ | |
"use strict"; | |
var stanzas = _dereq_('../stanza/roster'); | |
module.exports = function (client) { | |
client.on('iq:set:roster', function (iq) { | |
var allowed = {}; | |
allowed[''] = true; | |
allowed[client.jid.bare] = true; | |
allowed[client.jid.domain] = true; | |
if (!allowed[iq.from.full]) { | |
return client.sendIq(iq.errorReply({ | |
error: { | |
type: 'cancel', | |
condition: 'service-unavailable' | |
} | |
})); | |
} | |
client.emit('roster:update', iq); | |
client.sendIq({ | |
id: iq.id, | |
type: 'result' | |
}); | |
}); | |
client.getRoster = function (cb) { | |
var self = this; | |
cb = cb || function () {}; | |
return client.sendIq({ | |
type: 'get', | |
roster: { | |
ver: self.config.rosterVer | |
} | |
}).then(function (resp) { | |
var ver = resp.roster.ver; | |
if (ver) { | |
self.config.rosterVer = ver; | |
self.emit('roster:ver', ver); | |
} | |
return resp; | |
}).nodeify(cb); | |
}; | |
client.updateRosterItem = function (item, cb) { | |
return client.sendIq({ | |
type: 'set', | |
roster: { | |
items: [item] | |
} | |
}, cb); | |
}; | |
client.removeRosterItem = function (jid, cb) { | |
return client.updateRosterItem({jid: jid, subscription: 'remove'}, cb); | |
}; | |
client.subscribe = function (jid) { | |
client.sendPresence({type: 'subscribe', to: jid}); | |
}; | |
client.unsubscribe = function (jid) { | |
client.sendPresence({type: 'unsubscribe', to: jid}); | |
}; | |
client.acceptSubscription = function (jid) { | |
client.sendPresence({type: 'subscribed', to: jid}); | |
}; | |
client.denySubscription = function (jid) { | |
client.sendPresence({type: 'unsubscribed', to: jid}); | |
}; | |
}; | |
},{"../stanza/roster":74}],38:[function(_dereq_,module,exports){ | |
"use strict"; | |
var stanzas = _dereq_('../stanza/time'); | |
module.exports = function (client) { | |
client.disco.addFeature('urn:xmpp:time'); | |
client.getTime = function (jid, cb) { | |
return this.sendIq({ | |
to: jid, | |
type: 'get', | |
time: true | |
}, cb); | |
}; | |
client.on('iq:get:time', function (iq) { | |
var time = new Date(); | |
client.sendIq(iq.resultReply({ | |
time: { | |
utc: time, | |
tzo: time.getTimezoneOffset() | |
} | |
})); | |
}); | |
}; | |
},{"../stanza/time":83}],39:[function(_dereq_,module,exports){ | |
"use strict"; | |
var stanzas = _dereq_('../stanza/vcard'); | |
module.exports = function (client) { | |
client.disco.addFeature('vcard-temp'); | |
client.getVCard = function (jid, cb) { | |
return this.sendIq({ | |
to: jid, | |
type: 'get', | |
vCardTemp: {} | |
}, cb); | |
}; | |
client.publishVCard = function (vcard, cb) { | |
return this.sendIq({ | |
type: 'set', | |
vCardTemp: vcard | |
}, cb); | |
}; | |
}; | |
},{"../stanza/vcard":85}],40:[function(_dereq_,module,exports){ | |
"use strict"; | |
_dereq_('../stanza/version'); | |
module.exports = function (client) { | |
client.disco.addFeature('jabber:iq:version'); | |
client.on('iq:get:version', function (iq) { | |
client.sendIq(iq.resultReply({ | |
version: client.config.version || { | |
name: 'stanza.io' | |
} | |
})); | |
}); | |
client.getSoftwareVersion = function (jid, cb) { | |
return this.sendIq({ | |
to: jid, | |
type: 'get', | |
version: {} | |
}, cb); | |
}; | |
}; | |
},{"../stanza/version":86}],41:[function(_dereq_,module,exports){ | |
"use strict"; | |
var SM = _dereq_('./stanza/sm'); | |
var MAX_SEQ = Math.pow(2, 32); | |
function mod(v, n) { | |
return ((v % n) + n) % n; | |
} | |
function StreamManagement() { | |
this.conn = null; | |
this.id = false; | |
this.allowResume = true; | |
this.started = false; | |
this.lastAck = 0; | |
this.handled = 0; | |
this.windowSize = 1; | |
this.unacked = []; | |
this.pendingAck = false; | |
} | |
StreamManagement.prototype = { | |
constructor: { | |
value: StreamManagement | |
}, | |
enable: function (conn) { | |
this.conn = conn; | |
var enable = new SM.Enable(); | |
enable.resume = this.allowResume; | |
this.conn.send(enable); | |
this.handled = 0; | |
this.started = true; | |
}, | |
resume: function (conn) { | |
this.conn = conn; | |
var resume = new SM.Resume({ | |
h: this.handled, | |
previd: this.id | |
}); | |
this.conn.send(resume); | |
this.started = true; | |
}, | |
enabled: function (resp) { | |
this.id = resp.id; | |
}, | |
resumed: function (resp) { | |
this.id = resp.id; | |
if (resp.h) { | |
this.process(resp, true); | |
} | |
}, | |
failed: function (resp) { | |
this.started = false; | |
this.id = false; | |
this.lastAck = 0; | |
this.handled = 0; | |
this.unacked = []; | |
}, | |
ack: function () { | |
this.conn.send(new SM.Ack({ | |
h: this.handled | |
})); | |
}, | |
request: function () { | |
this.pendingAck = true; | |
this.conn.send(new SM.Request()); | |
}, | |
process: function (ack, resend) { | |
var self = this; | |
var numAcked = mod(ack.h - this.lastAck, MAX_SEQ); | |
this.pendingAck = false; | |
for (var i = 0; i < numAcked && this.unacked.length > 0; i++) { | |
this.conn.emit('stanza:acked', this.unacked.shift()); | |
} | |
this.lastAck = ack.h; | |
if (resend) { | |
var resendUnacked = this.unacked; | |
this.unacked = []; | |
resendUnacked.forEach(function (stanza) { | |
self.conn.send(stanza); | |
}); | |
} | |
if (this.needAck()) { | |
this.request(); | |
} | |
}, | |
track: function (stanza) { | |
var name = stanza._name; | |
var acceptable = { | |
message: true, | |
presence: true, | |
iq: true | |
}; | |
if (this.started && acceptable[name]) { | |
this.unacked.push(stanza); | |
if (this.needAck()) { | |
this.request(); | |
} | |
} | |
}, | |
handle: function (stanza) { | |
if (this.started) { | |
this.handled = mod(this.handled + 1, MAX_SEQ); | |
} | |
}, | |
needAck: function () { | |
return !this.pendingAck && this.unacked.length >= this.windowSize; | |
} | |
}; | |
module.exports = StreamManagement; | |
},{"./stanza/sm":79}],42:[function(_dereq_,module,exports){ | |
"use strict"; | |
var _ = _dereq_('underscore'); | |
var stanza = _dereq_('jxt'); | |
var Item = _dereq_('./pubsub').Item; | |
var EventItem = _dereq_('./pubsub').EventItem; | |
var Avatar = module.exports = stanza.define({ | |
name: 'avatar', | |
namespace: 'urn:xmpp:avatar:metadata', | |
element: 'info', | |
fields: { | |
id: stanza.attribute('id'), | |
bytes: stanza.attribute('bytes'), | |
height: stanza.attribute('height'), | |
width: stanza.attribute('width'), | |
type: stanza.attribute('type', 'image/png'), | |
url: stanza.attribute('url') | |
} | |
}); | |
var avatars = { | |
get: function () { | |
var metadata = stanza.find(this.xml, 'urn:xmpp:avatar:metadata', 'metadata'); | |
var results = []; | |
if (metadata.length) { | |
var avatars = stanza.find(metadata[0], 'urn:xmpp:avatar:metadata', 'info'); | |
_.forEach(avatars, function (info) { | |
results.push(new Avatar({}, info)); | |
}); | |
} | |
return results; | |
}, | |
set: function (value) { | |
var metadata = stanza.findOrCreate(this.xml, 'urn:xmpp:avatar:metadata', 'metadata'); | |
stanza.setAttribute(metadata, 'xmlns', 'urn:xmpp:avatar:metadata'); | |
_.forEach(value, function (info) { | |
var avatar = new Avatar(info); | |
metadata.appendChild(avatar.xml); | |
}); | |
} | |
}; | |
stanza.add(Item, 'avatars', avatars); | |
stanza.add(EventItem, 'avatars', avatars); | |
stanza.add(Item, 'avatarData', stanza.subText('urn:xmpp:avatar:data', 'data')); | |
stanza.add(EventItem, 'avatarData', stanza.subText('urn:xmpp:avatar:data', 'data')); | |
},{"./pubsub":72,"jxt":164,"underscore":187}],43:[function(_dereq_,module,exports){ | |
var stanza = _dereq_('jxt'); | |
var Iq = _dereq_('./iq'); | |
var StreamFeatures = _dereq_('./streamFeatures'); | |
var util = _dereq_('./util'); | |
var NS = 'urn:ietf:params:xml:ns:xmpp-bind'; | |
var Bind = module.exports = stanza.define({ | |
name: 'bind', | |
namespace: NS, | |
element: 'bind', | |
fields: { | |
resource: stanza.subText(NS, 'resource'), | |
jid: util.jidSub(NS, 'jid') | |
} | |
}); | |
stanza.extend(Iq, Bind); | |
stanza.extend(StreamFeatures, Bind); | |
},{"./iq":60,"./streamFeatures":82,"./util":84,"jxt":164}],44:[function(_dereq_,module,exports){ | |
"use strict"; | |
var stanza = _dereq_('jxt'); | |
var util = _dereq_('./util'); | |
var Iq = _dereq_('./iq'); | |
var JID = _dereq_('../jid'); | |
var NS = 'urn:xmpp:blocking'; | |
var jids = { | |
get: function () { | |
var result = []; | |
var items = stanza.find(this.xml, NS, 'item'); | |
if (!items.length) return result; | |
items.forEach(function (item) { | |
result.push(new JID(stanza.getAttribute(item, 'jid', ''))); | |
}); | |
return result; | |
}, | |
set: function (values) { | |
var self = this; | |
values.forEach(function (value) { | |
var item = stanza.createElement(NS, 'item', NS); | |
stanza.setAttribute(item, 'jid', value.toString()); | |
self.xml.appendChild(item); | |
}); | |
} | |
}; | |
exports.Block = stanza.define({ | |
name: 'block', | |
namespace: NS, | |
element: 'block', | |
fields: { | |
jids: jids | |
} | |
}); | |
exports.Unblock = stanza.define({ | |
name: 'unblock', | |
namespace: NS, | |
element: 'unblock', | |
fields: { | |
jids: jids | |
} | |
}); | |
exports.BlockList = stanza.define({ | |
name: 'blockList', | |
namespace: NS, | |
element: 'blocklist', | |
fields: { | |
jids: jids | |
} | |
}); | |
stanza.extend(Iq, exports.Block); | |
stanza.extend(Iq, exports.Unblock); | |
stanza.extend(Iq, exports.BlockList); | |
},{"../jid":4,"./iq":60,"./util":84,"jxt":164}],45:[function(_dereq_,module,exports){ | |
var stanza = _dereq_('jxt'); | |
var util = _dereq_('./util'); | |
var PrivateStorage = _dereq_('./private'); | |
var Conference = stanza.define({ | |
name: '_conference', | |
namespace: 'storage:bookmarks', | |
element: 'conference', | |
fields: { | |
name: stanza.attribute('name'), | |
autoJoin: stanza.boolAttribute('autojoin'), | |
jid: util.jidAttribute('jid'), | |
nick: stanza.subText('storage:bookmarks', 'nick') | |
} | |
}); | |
var Bookmarks = module.exports = stanza.define({ | |
name: 'bookmarks', | |
namespace: 'storage:bookmarks', | |
element: 'storage' | |
}); | |
stanza.extend(PrivateStorage, Bookmarks); | |
stanza.extend(Bookmarks, Conference, 'conferences'); | |
},{"./private":70,"./util":84,"jxt":164}],46:[function(_dereq_,module,exports){ | |
"use strict"; | |
var stanza = _dereq_('jxt'); | |
var util = _dereq_('./util'); | |
var NS = 'http://jabber.org/protocol/httpbind'; | |
var XMPP_NS = 'urn:xmpp:xbosh'; | |
module.exports = stanza.define({ | |
name: 'bosh', | |
namespace: NS, | |
element: 'body', | |
prefixes: { | |
xmpp: XMPP_NS | |
}, | |
fields: { | |
accept: stanza.attribute('accept'), | |
ack: stanza.numberAttribute('ack'), | |
authid: stanza.attribute('authid'), | |
charsets: stanza.attribute('charsets'), | |
condition: stanza.attribute('condition'), | |
content: stanza.attribute('content'), | |
from: util.jidAttribute('from'), | |
hold: stanza.numberAttribute('hold'), | |
inactivity: stanza.numberAttribute('inactivity'), | |
key: stanza.attribute('key'), | |
maxpause: stanza.numberAttribute('maxpause'), | |
newKey: stanza.attribute('newkey'), | |
pause: stanza.numberAttribute('pause'), | |
polling: stanza.numberAttribute('polling'), | |
resport: stanza.numberAttribute('report'), | |
requests: stanza.numberAttribute('requests'), | |
rid: stanza.numberAttribute('rid'), | |
sid: stanza.attribute('sid'), | |
stream: stanza.attribute('stream'), | |
time: stanza.attribute('time'), | |
to: util.jidAttribute('to'), | |
type: stanza.attribute('type'), | |
ver: stanza.attribute('ver'), | |
wait: stanza.numberAttribute('wait'), | |
uri: stanza.subText(NS, 'uri'), | |
lang: stanza.langAttribute(), | |
// These three should be using namespaced attributes, but browsers are stupid | |
// when it comes to serializing attributes with namespaces | |
version: stanza.attribute('xmpp:version', '1.0'), | |
restart: stanza.attribute('xmpp:restart'), | |
restartLogic: stanza.boolAttribute('xmpp:restartLogic'), | |
payload: { | |
get: function () { | |
var results = []; | |
for (var i = 0, len = this.xml.childNodes.length; i < len; i++) { | |
var obj = stanza.build(this.xml.childNodes[i]); | |
if (obj !== undefined) { | |
results.push(obj); | |
} | |
} | |
return results; | |
}, | |
set: function (values) { | |
var self = this; | |
values.forEach(function (stanza) { | |
self.xml.appendChild(stanza.xml); | |
}); | |
} | |
} | |
} | |
}); | |
},{"./util":84,"jxt":164}],47:[function(_dereq_,module,exports){ | |
var stanza = _dereq_('jxt'); | |
var Presence = _dereq_('./presence'); | |
var StreamFeatures = _dereq_('./streamFeatures'); | |
var Caps = module.exports = stanza.define({ | |
name: 'caps', | |
namespace: 'http://jabber.org/protocol/caps', | |
element: 'c', | |
fields: { | |
ver: stanza.attribute('ver'), | |
node: stanza.attribute('node'), | |
hash: stanza.attribute('hash'), | |
ext: stanza.attribute('ext') | |
} | |
}); | |
stanza.extend(Presence, Caps); | |
stanza.extend(StreamFeatures, Caps); | |
},{"./presence":69,"./streamFeatures":82,"jxt":164}],48:[function(_dereq_,module,exports){ | |
var stanza = _dereq_('jxt'); | |
var Message = _dereq_('./message'); | |
var Iq = _dereq_('./iq'); | |
var Forwarded = _dereq_('./forwarded'); | |
exports.Sent = stanza.define({ | |
name: 'carbonSent', | |
eventName: 'carbon:sent', | |
namespace: 'urn:xmpp:carbons:2', | |
element: 'sent' | |
}); | |
exports.Received = stanza.define({ | |
name: 'carbonReceived', | |
eventName: 'carbon:received', | |
namespace: 'urn:xmpp:carbons:2', | |
element: 'received' | |
}); | |
exports.Private = stanza.define({ | |
name: 'carbonPrivate', | |
eventName: 'carbon:private', | |
namespace: 'urn:xmpp:carbons:2', | |
element: 'private' | |
}); | |
exports.Enable = stanza.define({ | |
name: 'enableCarbons', | |
namespace: 'urn:xmpp:carbons:2', | |
element: 'enable' | |
}); | |
exports.Disable = stanza.define({ | |
name: 'disableCarbons', | |
namespace: 'urn:xmpp:carbons:2', | |
element: 'disable' | |
}); | |
stanza.extend(exports.Sent, Forwarded); | |
stanza.extend(exports.Received, Forwarded); | |
stanza.extend(Message, exports.Sent); | |
stanza.extend(Message, exports.Received); | |
stanza.extend(Message, exports.Private); | |
stanza.extend(Iq, exports.Enable); | |
stanza.extend(Iq, exports.Disable); | |
},{"./forwarded":56,"./iq":60,"./message":64,"jxt":164}],49:[function(_dereq_,module,exports){ | |
"use strict"; | |
var stanza = _dereq_('jxt'); | |
var Message = _dereq_('./message'); | |
var NS = 'http://jabber.org/protocol/chatstates'; | |
var Active = stanza.define({ | |
name: 'chatStateActive', | |
eventName: 'chat:active', | |
namespace: NS, | |
element: 'active' | |
}); | |
var Composing = stanza.define({ | |
name: 'chatStateComposing', | |
eventName: 'chat:composing', | |
namespace: NS, | |
element: 'composing' | |
}); | |
var Paused = stanza.define({ | |
name: 'chatStatePaused', | |
eventName: 'chat:paused', | |
namespace: NS, | |
element: 'paused' | |
}); | |
var Inactive = stanza.define({ | |
name: 'chatStateInactive', | |
eventName: 'chat:inactive', | |
namespace: NS, | |
element: 'inactive' | |
}); | |
var Gone = stanza.define({ | |
name: 'chatStateGone', | |
eventName: 'chat:gone', | |
namespace: NS, | |
element: 'gone' | |
}); | |
stanza.extend(Message, Active); | |
stanza.extend(Message, Composing); | |
stanza.extend(Message, Paused); | |
stanza.extend(Message, Inactive); | |
stanza.extend(Message, Gone); | |
stanza.add(Message, 'chatState', { | |
get: function () { | |
var self = this; | |
var states = ['Active', 'Composing', 'Paused', 'Inactive', 'Gone']; | |
for (var i = 0; i < states.length; i++) { | |
if (self._extensions['chatState' + states[i]]) { | |
return states[i].toLowerCase(); | |
} | |
} | |
return ''; | |
}, | |
set: function (value) { | |
var self = this; | |
var states = ['Active', 'Composing', 'Paused', 'Inactive', 'Gone']; | |
states.forEach(function (state) { | |
if (self._extensions['chatState' + state]) { | |
self.xml.removeChild(self._extensions['chatState' + state].xml); | |
delete self._extensions['chatState' + state]; | |
} | |
}); | |
if (value) { | |
this['chatState' + value.charAt(0).toUpperCase() + value.slice(1)]; | |
} | |
} | |
}); | |
},{"./message":64,"jxt":164}],50:[function(_dereq_,module,exports){ | |
"use strict"; | |
var stanza = _dereq_('jxt'); | |
var DataForm = _dereq_('./dataforms').DataForm; | |
var ErrorStanza = _dereq_('./error'); | |
var Iq = _dereq_('./iq'); | |
var NS = 'http://jabber.org/protocol/commands'; | |
var ACTIONS = ['next', 'prev', 'complete', 'cancel']; | |
var CONDITIONS = [ | |
'bad-action', 'bad-locale', 'bad-payload', 'bad-sessionid', | |
'malformed-action', 'session-expired' | |
]; | |
var Command = module.exports = stanza.define({ | |
name: 'command', | |
namespace: NS, | |
element: 'command', | |
fields: { | |
action: stanza.attribute('action'), | |
node: stanza.attribute('node'), | |
sessionid: stanza.attribute('sessionid'), | |
status: stanza.attribute('status'), | |
noteType: stanza.subAttribute(NS, 'note', 'type'), | |
note: stanza.subText(NS, 'note'), | |
execute: stanza.subAttribute(NS, 'actions', 'execute'), | |
actions: { | |
get: function () { | |
var result = []; | |
var actionSet = stanza.find(this.xml, NS, 'actions'); | |
if (!actionSet.length) return []; | |
ACTIONS.forEach(function (action) { | |
var existing = stanza.find(actionSet[0], NS, action); | |
if (existing.length) { | |
result.push(action); | |
} | |
}); | |
return result; | |
}, | |
set: function (values) { | |
var actionSet = stanza.findOrCreate(this.xml, NS, 'actions'); | |
for (var i = 0, len = actionSet.childNodes.length; i < len; i++) { | |
actionSet.removeChild(actionSet.childNodes[i]); | |
} | |
values.forEach(function (value) { | |
actionSet.appendChild(stanza.createElement(NS, value.toLowerCase(), NS)); | |
}); | |
} | |
} | |
} | |
}); | |
stanza.add(ErrorStanza, 'adhocCommandCondition', { | |
get: function () { | |
var self = this; | |
var result = []; | |
CONDITIONS.forEach(function (condition) { | |
var exists = stanza.find(self.xml, NS, condition); | |
if (exists.length) { | |
result.push(exists[0].tagName); | |
} | |
}); | |
return result[0] || ''; | |
}, | |
set: function (value) { | |
var self = this; | |
CONDITIONS.forEach(function (condition) { | |
var exists = stanza.find(self.xml, NS, condition); | |
if (exists.length) { | |
self.xml.removeChild(exists[0]); | |
} | |
}); | |
if (value) { | |
var condition = stanza.createElement(NS, value); | |
this.xml.appendChild(condition); | |
} | |
} | |
}); | |
stanza.extend(Iq, Command); | |
stanza.extend(Command, DataForm); | |
},{"./dataforms":51,"./error":54,"./iq":60,"jxt":164}],51:[function(_dereq_,module,exports){ | |
"use strict"; | |
var _ = _dereq_('underscore'); | |
var stanza = _dereq_('jxt'); | |
var util = _dereq_('./util'); | |
var Message = _dereq_('./message'); | |
var FORM_NS = 'jabber:x:data'; | |
var MEDIA_NS = 'urn:xmpp:media-element'; | |
exports.DataForm = stanza.define({ | |
name: 'form', | |
namespace: FORM_NS, | |
element: 'x', | |
fields: { | |
title: stanza.subText(FORM_NS, 'title'), | |
instructions: stanza.multiSubText(FORM_NS, 'instructions'), | |
type: stanza.attribute('type', 'form') | |
} | |
}); | |
exports.Field = stanza.define({ | |
name: '_field', | |
namespace: FORM_NS, | |
element: 'field', | |
init: function (data) { | |
this._type = (data || {}).type || this.type; | |
}, | |
fields: { | |
type: { | |
get: function () { | |
return stanza.getAttribute(this.xml, 'type', 'text-single'); | |
}, | |
set: function (value) { | |
this._type = value; | |
stanza.setAttribute(this.xml, 'type', value); | |
} | |
}, | |
name: stanza.attribute('var'), | |
desc: stanza.subText(FORM_NS, 'desc'), | |
required: stanza.boolSub(FORM_NS, 'required'), | |
label: stanza.attribute('label'), | |
value: { | |
get: function () { | |
var vals = stanza.getMultiSubText(this.xml, FORM_NS, 'value'); | |
if (this._type === 'boolean') { | |
return vals[0] === '1' || vals[0] === 'true'; | |
} | |
if (vals.length > 1) { | |
if (this._type === 'text-multi') { | |
return vals.join('\n'); | |
} | |
return vals; | |
} | |
return vals[0]; | |
}, | |
set: function (value) { | |
if (this._type === 'boolean') { | |
stanza.setSubText(this.xml, FORM_NS, 'value', value ? '1' : '0'); | |
} else { | |
if (this._type === 'text-multi') { | |
value = value.split('\n'); | |
} | |
stanza.setMultiSubText(this.xml, FORM_NS, 'value', value); | |
} | |
} | |
}, | |
options: { | |
get: function () { | |
var self = this; | |
return stanza.getMultiSubText(this.xml, FORM_NS, 'option', function (sub) { | |
return stanza.getSubText(sub, FORM_NS, 'value'); | |
}); | |
}, | |
set: function (value) { | |
var self = this; | |
stanza.setMultiSubText(this.xml, FORM_NS, 'option', value, function (val) { | |
var opt = stanza.createElement(FORM_NS, 'option', FORM_NS); | |
var value = stanza.createElement(FORM_NS, 'value', FORM_NS); | |
opt.appendChild(value); | |
value.textContent = val; | |
self.xml.appendChild(opt); | |
}); | |
} | |
} | |
} | |
}); | |
exports.Media = stanza.define({ | |
name: 'media', | |
element: 'media', | |
namespace: MEDIA_NS, | |
fields: { | |
height: stanza.numberAttribute('height'), | |
width: stanza.numberAttribute('width') | |
} | |
}); | |
exports.MediaURI = stanza.define({ | |
name: '_mediaURI', | |
element: 'uri', | |
namespace: MEDIA_NS, | |
fields: { | |
uri: stanza.text(), | |
type: stanza.attribute('type') | |
} | |
}); | |
stanza.extend(Message, exports.DataForm); | |
stanza.extend(exports.DataForm, exports.Field, 'fields'); | |
stanza.extend(exports.Field, exports.Media); | |
stanza.extend(exports.Media, exports.MediaURI, 'uris'); | |
},{"./message":64,"./util":84,"jxt":164,"underscore":187}],52:[function(_dereq_,module,exports){ | |
var stanza = _dereq_('jxt'); | |
var Message = _dereq_('./message'); | |
var Presence = _dereq_('./presence'); | |
var util = _dereq_('./util'); | |
var DelayedDelivery = module.exports = stanza.define({ | |
name: 'delay', | |
namespace: 'urn:xmpp:delay', | |
element: 'delay', | |
fields: { | |
from: util.jidAttribute('from'), | |
stamp: stanza.dateAttribute('stamp'), | |
reason: stanza.text() | |
} | |
}); | |
stanza.extend(Message, DelayedDelivery); | |
stanza.extend(Presence, DelayedDelivery); | |
},{"./message":64,"./presence":69,"./util":84,"jxt":164}],53:[function(_dereq_,module,exports){ | |
"use strict"; | |
var _ = _dereq_('underscore'); | |
var stanza = _dereq_('jxt'); | |
var JID = _dereq_('../jid'); | |
var Iq = _dereq_('./iq'); | |
var RSM = _dereq_('./rsm'); | |
var DataForm = _dereq_('./dataforms').DataForm; | |
exports.DiscoInfo = stanza.define({ | |
name: 'discoInfo', | |
namespace: 'http://jabber.org/protocol/disco#info', | |
element: 'query', | |
fields: { | |
node: stanza.attribute('node'), | |
identities: { | |
get: function () { | |
var result = []; | |
var identities = stanza.find(this.xml, this._NS, 'identity'); | |
identities.forEach(function (identity) { | |
result.push({ | |
category: stanza.getAttribute(identity, 'category'), | |
type: stanza.getAttribute(identity, 'type'), | |
lang: identity.getAttributeNS(stanza.XML_NS, 'lang'), | |
name: stanza.getAttribute(identity, 'name') | |
}); | |
}); | |
return result; | |
}, | |
set: function (values) { | |
var self = this; | |
var existing = stanza.find(this.xml, this._NS, 'identity'); | |
existing.forEach(function (item) { | |
self.xml.removeChild(item); | |
}); | |
values.forEach(function (value) { | |
var identity = stanza.createElement(self._NS, 'identity', self._NS); | |
stanza.setAttribute(identity, 'category', value.category); | |
stanza.setAttribute(identity, 'type', value.type); | |
stanza.setAttribute(identity, 'name', value.name); | |
if (value.lang) { | |
identity.setAttributeNS(stanza.XML_NS, 'lang', value.lang); | |
} | |
self.xml.appendChild(identity); | |
}); | |
} | |
}, | |
features: { | |
get: function () { | |
var result = []; | |
var features = stanza.find(this.xml, this._NS, 'feature'); | |
features.forEach(function (feature) { | |
result.push(feature.getAttribute('var')); | |
}); | |
return result; | |
}, | |
set: function (values) { | |
var self = this; | |
var existing = stanza.find(this.xml, this._NS, 'feature'); | |
existing.forEach(function (item) { | |
self.xml.removeChild(item); | |
}); | |
values.forEach(function (value) { | |
var feature = stanza.createElement(self._NS, 'feature', self._NS); | |
feature.setAttribute('var', value); | |
self.xml.appendChild(feature); | |
}); | |
} | |
} | |
} | |
}); | |
exports.DiscoItems = stanza.define({ | |
name: 'discoItems', | |
namespace: 'http://jabber.org/protocol/disco#items', | |
element: 'query', | |
fields: { | |
node: stanza.attribute('node'), | |
items: { | |
get: function () { | |
var result = []; | |
var items = stanza.find(this.xml, this._NS, 'item'); | |
items.forEach(function (item) { | |
result.push({ | |
jid: new JID(stanza.getAttribute(item, 'jid')), | |
node: stanza.getAttribute(item, 'node'), | |
name: stanza.getAttribute(item, 'name') | |
}); | |
}); | |
return result; | |
}, | |
set: function (values) { | |
var self = this; | |
var existing = stanza.find(this.xml, this._NS, 'item'); | |
existing.forEach(function (item) { | |
self.xml.removeChild(item); | |
}); | |
values.forEach(function (value) { | |
var item = stanza.createElement(self._NS, 'item', self._NS); | |
if (value.jid) { | |
stanza.setAttribute(item, 'jid', value.jid.toString()); | |
} | |
stanza.setAttribute(item, 'node', value.node); | |
stanza.setAttribute(item, 'name', value.name); | |
self.xml.appendChild(item); | |
}); | |
} | |
} | |
} | |
}); | |
stanza.extend(Iq, exports.DiscoInfo); | |
stanza.extend(Iq, exports.DiscoItems); | |
stanza.extend(exports.DiscoItems, RSM); | |
stanza.extend(exports.DiscoInfo, DataForm, 'extensions'); | |
},{"../jid":4,"./dataforms":51,"./iq":60,"./rsm":75,"jxt":164,"underscore":187}],54:[function(_dereq_,module,exports){ | |
"use strict"; | |
var _ = _dereq_('underscore'); | |
var stanza = _dereq_('jxt'); | |
var util = _dereq_('./util'); | |
var Message = _dereq_('./message'); | |
var Presence = _dereq_('./presence'); | |
var Iq = _dereq_('./iq'); | |
var ERR_NS = 'urn:ietf:params:xml:ns:xmpp-stanzas'; | |
var CONDITIONS = [ | |
'bad-request', 'conflict', 'feature-not-implemented', | |
'forbidden', 'gone', 'internal-server-error', | |
'item-not-found', 'jid-malformed', 'not-acceptable', | |
'not-allowed', 'not-authorized', 'payment-required', | |
'recipient-unavailable', 'redirect', | |
'registration-required', 'remote-server-not-found', | |
'remote-server-timeout', 'resource-constraint', | |
'service-unavailable', 'subscription-required', | |
'undefined-condition', 'unexpected-request' | |
]; | |
var ErrorStanza = module.exports = stanza.define({ | |
name: 'error', | |
namespace: 'jabber:client', | |
element: 'error', | |
fields: { | |
lang: { | |
get: function () { | |
return (this.parent || {}).lang || ''; | |
} | |
}, | |
condition: { | |
get: function () { | |
var self = this; | |
var result = []; | |
CONDITIONS.forEach(function (condition) { | |
var exists = stanza.find(self.xml, ERR_NS, condition); | |
if (exists.length) { | |
result.push(exists[0].tagName); | |
} | |
}); | |
return result[0] || ''; | |
}, | |
set: function (value) { | |
var self = this; | |
CONDITIONS.forEach(function (condition) { | |
var exists = stanza.find(self.xml, ERR_NS, condition); | |
if (exists.length) { | |
self.xml.removeChild(exists[0]); | |
} | |
}); | |
if (value) { | |
var condition = stanza.createElement(ERR_NS, value); | |
this.xml.appendChild(condition); | |
} | |
} | |
}, | |
gone: { | |
get: function () { | |
return stanza.getSubText(this.xml, ERR_NS, 'gone'); | |
}, | |
set: function (value) { | |
this.condition = 'gone'; | |
stanza.setSubText(this.xml, ERR_NS, 'gone', value); | |
} | |
}, | |
redirect: { | |
get: function () { | |
return stanza.getSubText(this.xml, ERR_NS, 'redirect'); | |
}, | |
set: function (value) { | |
this.condition = 'redirect'; | |
stanza.setSubText(this.xml, ERR_NS, 'redirect', value); | |
} | |
}, | |
code: stanza.attribute('code'), | |
type: stanza.attribute('type'), | |
by: util.jidAttribute('by'), | |
$text: { | |
get: function () { | |
return stanza.getSubLangText(this.xml, ERR_NS, 'text', this.lang); | |
} | |
}, | |
text: { | |
get: function () { | |
var text = this.$text; | |
return text[this.lang] || ''; | |
}, | |
set: function (value) { | |
stanza.setSubLangText(this.xml, ERR_NS, 'text', value, this.lang); | |
} | |
} | |
} | |
}); | |
stanza.extend(Message, ErrorStanza); | |
stanza.extend(Presence, ErrorStanza); | |
stanza.extend(Iq, ErrorStanza); | |
},{"./iq":60,"./message":64,"./presence":69,"./util":84,"jxt":164,"underscore":187}],55:[function(_dereq_,module,exports){ | |
var stanza = _dereq_('jxt'); | |
var Iq = _dereq_('./iq'); | |
var DataForm = _dereq_('./dataforms').DataForm; | |
var NS = 'urn:xmpp:extdisco:1'; | |
var Services = exports.Services = stanza.define({ | |
name: 'services', | |
namespace: NS, | |
element: 'services', | |
fields: { | |
type: stanza.attribute('type') | |
} | |
}); | |
var Credentials = exports.Credentials = stanza.define({ | |
name: 'credentials', | |
namespace: NS, | |
element: 'credentials' | |
}); | |
var Service = stanza.define({ | |
name: 'service', | |
namespace: NS, | |
element: 'service', | |
fields: { | |
host: stanza.attribute('host'), | |
port: stanza.attribute('port'), | |
transport: stanza.attribute('transport'), | |
type: stanza.attribute('type'), | |
username: stanza.attribute('username'), | |
password: stanza.attribute('password') | |
} | |
}); | |
stanza.extend(Services, Service, 'services'); | |
stanza.extend(Credentials, Service); | |
stanza.extend(Service, DataForm); | |
stanza.extend(Iq, Services); | |
stanza.extend(Iq, Credentials); | |
},{"./dataforms":51,"./iq":60,"jxt":164}],56:[function(_dereq_,module,exports){ | |
var stanza = _dereq_('jxt'); | |
var Message = _dereq_('./message'); | |
var Presence = _dereq_('./presence'); | |
var Iq = _dereq_('./iq'); | |
var DelayedDelivery = _dereq_('./delayed'); | |
var Forwarded = module.exports = stanza.define({ | |
name: 'forwarded', | |
eventName: 'forward', | |
namespace: 'urn:xmpp:forward:0', | |
element: 'forwarded' | |
}); | |
stanza.extend(Message, Forwarded); | |
stanza.extend(Forwarded, Message); | |
stanza.extend(Forwarded, Presence); | |
stanza.extend(Forwarded, Iq); | |
stanza.extend(Forwarded, DelayedDelivery); | |
},{"./delayed":52,"./iq":60,"./message":64,"./presence":69,"jxt":164}],57:[function(_dereq_,module,exports){ | |
"use strict"; | |
var stanza = _dereq_('jxt'); | |
var util = _dereq_('./util'); | |
var NS = 'urn:ietf:params:xml:ns:xmpp-framing'; | |
exports.Open = stanza.define({ | |
name: 'openStream', | |
namespace: NS, | |
element: 'open', | |
topLevel: true, | |
fields: { | |
lang: stanza.langAttribute(), | |
id: stanza.attribute('id'), | |
version: stanza.attribute('version', '1.0'), | |
to: util.jidAttribute('to'), | |
from: util.jidAttribute('from') | |
} | |
}); | |
exports.Close = stanza.define({ | |
name: 'closeStream', | |
namespace: NS, | |
element: 'close', | |
topLevel: true, | |
fields: { | |
seeOtherURI: stanza.attribute('see-other-uri') | |
} | |
}); | |
},{"./util":84,"jxt":164}],58:[function(_dereq_,module,exports){ | |
"use strict"; | |
var stanza = _dereq_('jxt'); | |
var Item = _dereq_('./pubsub').Item; | |
var EventItem = _dereq_('./pubsub').EventItem; | |
var NS = 'http://jabber.org/protocol/geoloc'; | |
var GeoLoc = module.exports = stanza.define({ | |
name: 'geoloc', | |
namespace: NS, | |
element: 'geoloc', | |
fields: { | |
accuracy: stanza.numberSub(NS, 'accuracy', true), | |
altitude: stanza.numberSub(NS, 'alt', true), | |
area: stanza.subText(NS, 'area'), | |
heading: stanza.numberSub(NS, 'bearing', true), | |
bearing: stanza.numberSub(NS, 'bearing', true), | |
building: stanza.subText(NS, 'building'), | |
country: stanza.subText(NS, 'country'), | |
countrycode: stanza.subText(NS, 'countrycode'), | |
datum: stanza.subText(NS, 'datum'), | |
description: stanza.subText(NS, 'description'), | |
error: stanza.numberSub(NS, 'error', true), | |
floor: stanza.subText(NS, 'floor'), | |
latitude: stanza.numberSub(NS, 'lat', true), | |
locality: stanza.subText(NS, 'locality'), | |
longitude: stanza.numberSub(NS, 'lon', true), | |
postalcode: stanza.subText(NS, 'postalcode'), | |
region: stanza.subText(NS, 'region'), | |
room: stanza.subText(NS, 'room'), | |
speed: stanza.numberSub(NS, 'speed', true), | |
street: stanza.subText(NS, 'street'), | |
text: stanza.subText(NS, 'text'), | |
timestamp: stanza.dateSub(NS, 'timestamp'), | |
uri: stanza.subText(NS, 'uri') | |
} | |
}); | |
stanza.extend(Item, GeoLoc); | |
stanza.extend(EventItem, GeoLoc); | |
},{"./pubsub":72,"jxt":164}],59:[function(_dereq_,module,exports){ | |
var _ = _dereq_('underscore'); | |
var stanza = _dereq_('jxt'); | |
var util = _dereq_('./util'); | |
var jingle = _dereq_('./jingle'); | |
var NS = 'urn:xmpp:jingle:transports:ice-udp:1'; | |
exports.ICEUDP = stanza.define({ | |
name: '_iceUdp', | |
namespace: NS, | |
element: 'transport', | |
fields: { | |
transType: {value: 'iceUdp'}, | |
pwd: stanza.attribute('pwd'), | |
ufrag: stanza.attribute('ufrag') | |
} | |
}); | |
exports.RemoteCandidate = stanza.define({ | |
name: 'remoteCandidate', | |
namespace: NS, | |
element: 'remote-candidate', | |
fields: { | |
component: stanza.attribute('component'), | |
ip: stanza.attribute('ip'), | |
port: stanza.attribute('port') | |
} | |
}); | |
exports.Candidate = stanza.define({ | |
name: '_iceUdpCandidate', | |
namespace: NS, | |
element: 'candidate', | |
fields: { | |
component: stanza.attribute('component'), | |
foundation: stanza.attribute('foundation'), | |
generation: stanza.attribute('generation'), | |
id: stanza.attribute('id'), | |
ip: stanza.attribute('ip'), | |
network: stanza.attribute('network'), | |
port: stanza.attribute('port'), | |
priority: stanza.attribute('priority'), | |
protocol: stanza.attribute('protocol'), | |
relAddr: stanza.attribute('rel-addr'), | |
relPort: stanza.attribute('rel-port'), | |
type: stanza.attribute('type') | |
} | |
}); | |
exports.Fingerprint = stanza.define({ | |
name: '_iceFingerprint', | |
namespace: 'urn:xmpp:tmp:jingle:apps:dtls:0', | |
element: 'fingerprint', | |
fields: { | |
hash: stanza.attribute('hash'), | |
value: stanza.text(), | |
required: stanza.boolAttribute('required') | |
} | |
}); | |
stanza.extend(jingle.Content, exports.ICEUDP); | |
stanza.extend(exports.ICEUDP, exports.Candidate, 'candidates'); | |
stanza.extend(exports.ICEUDP, exports.RemoteCandidate); | |
stanza.extend(exports.ICEUDP, exports.Fingerprint, 'fingerprints'); | |
},{"./jingle":61,"./util":84,"jxt":164,"underscore":187}],60:[function(_dereq_,module,exports){ | |
"use strict"; | |
var stanza = _dereq_('jxt'); | |
var util = _dereq_('./util'); | |
var Iq = module.exports = stanza.define({ | |
name: 'iq', | |
namespace: 'jabber:client', | |
element: 'iq', | |
topLevel: true, | |
fields: { | |
lang: stanza.langAttribute(), | |
id: stanza.attribute('id'), | |
to: util.jidAttribute('to'), | |
from: util.jidAttribute('from'), | |
type: stanza.attribute('type') | |
} | |
}); | |
Iq.prototype.resultReply = function (data) { | |
data = data || {}; | |
data.to = this.from; | |
data.id = this.id; | |
data.type = 'result'; | |
return new Iq(data); | |
}; | |
Iq.prototype.errorReply = function (data) { | |
data = data || {}; | |
data.to = this.from; | |
data.id = this.id; | |
data.type = 'error'; | |
return new Iq(data); | |
}; | |
},{"./util":84,"jxt":164}],61:[function(_dereq_,module,exports){ | |
"use strict"; | |
var _ = _dereq_('underscore'); | |
var stanza = _dereq_('jxt'); | |
var util = _dereq_('./util'); | |
var Iq = _dereq_('./iq'); | |
var ErrorStanza = _dereq_('./error'); | |
var NS = 'urn:xmpp:jingle:1'; | |
var ERRNS = 'urn:xmpp:jingle:errors:1'; | |
var CONDITIONS = ['out-of-order', 'tie-break', 'unknown-session', 'unsupported-info']; | |
var REASONS = [ | |
'alternative-session', 'busy', 'cancel', 'connectivity-error', | |
'decline', 'expired', 'failed-application', 'failed-transport', | |
'general-error', 'gone', 'incompatible-parameters', 'media-error', | |
'security-error', 'success', 'timeout', 'unsupported-applications', | |
'unsupported-transports' | |
]; | |
exports.Jingle = stanza.define({ | |
name: 'jingle', | |
namespace: NS, | |
element: 'jingle', | |
fields: { | |
action: stanza.attribute('action'), | |
initiator: stanza.attribute('initiator'), | |
responder: stanza.attribute('responder'), | |
sid: stanza.attribute('sid') | |
} | |
}); | |
exports.Content = stanza.define({ | |
name: '_jingleContent', | |
namespace: NS, | |
element: 'content', | |
fields: { | |
creator: stanza.attribute('creator'), | |
disposition: stanza.attribute('disposition', 'session'), | |
name: stanza.attribute('name'), | |
senders: stanza.attribute('senders', 'both'), | |
description: { | |
get: function () { | |
var opts = ['_rtp']; | |
for (var i = 0; i < opts.length; i++) { | |
if (this._extensions[opts[i]]) { | |
return this._extensions[opts[i]]; | |
} | |
} | |
}, | |
set: function (value) { | |
var ext = '_' + value.descType; | |
this[ext] = value; | |
} | |
}, | |
transport: { | |
get: function () { | |
var opts = ['_iceUdp']; | |
for (var i = 0; i < opts.length; i++) { | |
if (this._extensions[opts[i]]) { | |
return this._extensions[opts[i]]; | |
} | |
} | |
}, | |
set: function (value) { | |
var ext = '_' + value.transType; | |
this[ext] = value; | |
} | |
} | |
} | |
}); | |
exports.Reason = stanza.define({ | |
name: 'reason', | |
namespace: NS, | |
element: 'reason', | |
fields: { | |
condition: { | |
get: function () { | |
var self = this; | |
var result = []; | |
REASONS.forEach(function (condition) { | |
var exists = stanza.find(self.xml, NS, condition); | |
if (exists.length) { | |
result.push(exists[0].tagName); | |
} | |
}); | |
return result[0] || ''; | |
}, | |
set: function (value) { | |
var self = this; | |
REASONS.forEach(function (condition) { | |
var exists = stanza.find(self.xml, NS, condition); | |
if (exists.length) { | |
self.xml.removeChild(exists[0]); | |
} | |
}); | |
if (value) { | |
var condition = stanza.createElement(NS, value, NS); | |
this.xml.appendChild(condition); | |
} | |
} | |
}, | |
alternativeSession: { | |
get: function () { | |
return stanza.getSubText(this.xml, NS, 'alternative-session'); | |
}, | |
set: function (value) { | |
this.condition = 'alternative-session'; | |
stanza.setSubText(this.xml, NS, 'alternative-session', value); | |
} | |
}, | |
text: stanza.subText(NS, 'text') | |
} | |
}); | |
stanza.add(ErrorStanza, 'jingleCondition', { | |
get: function () { | |
var self = this; | |
var result = []; | |
CONDITIONS.forEach(function (condition) { | |
var exists = stanza.find(self.xml, ERRNS, condition); | |
if (exists.length) { | |
result.push(exists[0].tagName); | |
} | |
}); | |
return result[0] || ''; | |
}, | |
set: function (value) { | |
var self = this; | |
CONDITIONS.forEach(function (condition) { | |
var exists = stanza.find(self.xml, ERRNS, condition); | |
if (exists.length) { | |
self.xml.removeChild(exists[0]); | |
} | |
}); | |
if (value) { | |
var condition = stanza.createElement(ERRNS, value); | |
this.xml.appendChild(condition); | |
} | |
} | |
}); | |
stanza.extend(Iq, exports.Jingle); | |
stanza.extend(exports.Jingle, exports.Content, 'contents'); | |
stanza.extend(exports.Jingle, exports.Reason); | |
},{"./error":54,"./iq":60,"./util":84,"jxt":164,"underscore":187}],62:[function(_dereq_,module,exports){ | |
"use strict"; | |
var stanza = _dereq_('jxt'); | |
var Message = _dereq_('./message'); | |
var Item = _dereq_('./pubsub').Item; | |
var EventItem = _dereq_('./pubsub').EventItem; | |
var JSONExtension = module.exports = { | |
get: function () { | |
var data = stanza.getSubText(this.xml, 'urn:xmpp:json:0', 'json'); | |
if (data) { | |
return JSON.parse(data); | |
} | |
}, | |
set: function (value) { | |
value = JSON.stringify(value); | |
if (value) { | |
stanza.setSubText(this.xml, 'urn:xmpp:json:0', 'json', value); | |
} | |
} | |
}; | |
stanza.add(Message, 'json', JSONExtension); | |
stanza.add(Item, 'json', JSONExtension); | |
stanza.add(EventItem, 'json', JSONExtension); | |
},{"./message":64,"./pubsub":72,"jxt":164}],63:[function(_dereq_,module,exports){ | |
"use strict"; | |
var stanza = _dereq_('jxt'); | |
var util = _dereq_('./util'); | |
var Message = _dereq_('./message'); | |
var Iq = _dereq_('./iq'); | |
var Forwarded = _dereq_('./forwarded'); | |
var RSM = _dereq_('./rsm'); | |
var JID = _dereq_('../jid'); | |
exports.MAMQuery = stanza.define({ | |
name: 'mamQuery', | |
namespace: 'urn:xmpp:mam:tmp', | |
element: 'query', | |
fields: { | |
queryid: stanza.attribute('queryid'), | |
start: stanza.dateSub('urn:xmpp:mam:tmp', 'start'), | |
end: stanza.dateSub('urn:xmpp:mam:tmp', 'end'), | |
'with': util.jidSub('urn:xmpp:mam:tmp', 'with') | |
} | |
}); | |
exports.Result = stanza.define({ | |
name: 'mam', | |
eventName: 'mam:result', | |
namespace: 'urn:xmpp:mam:tmp', | |
element: 'result', | |
fields: { | |
queryid: stanza.attribute('queryid'), | |
id: stanza.attribute('id') | |
} | |
}); | |
exports.Archived = stanza.define({ | |
name: 'mamArchived', | |
namespace: 'urn:xmpp:mam:tmp', | |
element: 'archived', | |
fields: { | |
by: util.jidAttribute('by'), | |
id: stanza.attribute('id') | |
} | |
}); | |
exports.Prefs = stanza.define({ | |
name: 'mamPrefs', | |
namespace: 'urn:xmpp:mam:tmp', | |
element: 'prefs', | |
fields: { | |
defaultCondition: stanza.attribute('default'), | |
always: { | |
get: function () { | |
var results = []; | |
var container = stanza.find(this.xml, this._NS, 'always'); | |
if (container.length === 0) { | |
return results; | |
} | |
container = container[0]; | |
var jids = stanza.getMultiSubText(container, this._NS, 'jid'); | |
jids.forEach(function (jid) { | |
results.push(new JID(jid.textContent)); | |
}); | |
return results; | |
}, | |
set: function (value) { | |
if (value.length > 0) { | |
var container = stanza.find(this.xml, this._NS, 'always'); | |
stanza.setMultiSubText(container, this._NS, 'jid', value); | |
} | |
} | |
}, | |
never: { | |
get: function () { | |
var results = []; | |
var container = stanza.find(this.xml, this._NS, 'always'); | |
if (container.length === 0) { | |
return results; | |
} | |
container = container[0]; | |
var jids = stanza.getMultiSubText(container, this._NS, 'jid'); | |
jids.forEach(function (jid) { | |
results.push(new JID(jid.textContent)); | |
}); | |
return results; | |
}, | |
set: function (value) { | |
if (value.length > 0) { | |
var container = stanza.find(this.xml, this._NS, 'never'); | |
stanza.setMultiSubText(container, this._NS, 'jid', value); | |
} | |
} | |
} | |
} | |
}); | |
stanza.extend(Message, exports.Archived, 'archived'); | |
stanza.extend(Iq, exports.MAMQuery); | |
stanza.extend(Iq, exports.Prefs); | |
stanza.extend(Message, exports.Result); | |
stanza.extend(exports.Result, Forwarded); | |
stanza.extend(exports.MAMQuery, RSM); | |
},{"../jid":4,"./forwarded":56,"./iq":60,"./message":64,"./rsm":75,"./util":84,"jxt":164}],64:[function(_dereq_,module,exports){ | |
"use strict"; | |
var _ = _dereq_('underscore'); | |
var stanza = _dereq_('jxt'); | |
var util = _dereq_('./util'); | |
module.exports = stanza.define({ | |
name: 'message', | |
namespace: 'jabber:client', | |
element: 'message', | |
topLevel: true, | |
fields: { | |
lang: stanza.langAttribute(), | |
id: stanza.attribute('id'), | |
to: util.jidAttribute('to'), | |
from: util.jidAttribute('from'), | |
type: stanza.attribute('type', 'normal'), | |
thread: stanza.subText('jabber:client', 'thread'), | |
parentThread: stanza.subAttribute('jabber:client', 'thread', 'parent'), | |
subject: stanza.subText('jabber:client', 'subject'), | |
$body: { | |
get: function () { | |
return stanza.getSubLangText(this.xml, this._NS, 'body', this.lang); | |
} | |
}, | |
body: { | |
get: function () { | |
var bodies = this.$body; | |
return bodies[this.lang] || ''; | |
}, | |
set: function (value) { | |
stanza.setSubLangText(this.xml, this._NS, 'body', value, this.lang); | |
} | |
}, | |
attention: stanza.boolSub('urn:xmpp:attention:0', 'attention'), | |
replace: stanza.subAttribute('urn:xmpp:message-correct:0', 'replace', 'id'), | |
requestReceipt: stanza.boolSub('urn:xmpp:receipts', 'request'), | |
receipt: stanza.subAttribute('urn:xmpp:receipts', 'received', 'id') | |
} | |
}); | |
},{"./util":84,"jxt":164,"underscore":187}],65:[function(_dereq_,module,exports){ | |
'use strict'; | |
var stanza = _dereq_('jxt'); | |
var Message = _dereq_('./message'); | |
var Presence = _dereq_('./presence'); | |
var Iq = _dereq_('./iq'); | |
var DataForm = _dereq_('./dataforms').DataForm; | |
var util = _dereq_('./util'); | |
var NS = 'http://jabber.org/protocol/muc'; | |
var USER_NS = NS + '#user'; | |
var ADMIN_NS = NS + '#admin'; | |
var OWNER_NS = NS + '#owner'; | |
var proxy = function (child, field) { | |
return { | |
get: function () { | |
if (this._extensions[child]) { | |
return this[child][field]; | |
} | |
}, | |
set: function (value) { | |
this[child][field] = value; | |
} | |
}; | |
}; | |
var UserItem = stanza.define({ | |
name: '_mucUserItem', | |
namespace: USER_NS, | |
element: 'item', | |
fields: { | |
affiliation: stanza.attribute('affiliation'), | |
nick: stanza.attribute('nick'), | |
jid: util.jidAttribute('jid'), | |
role: stanza.attribute('role'), | |
reason: stanza.subText(USER_NS, 'reason') | |
} | |
}); | |
var UserActor = stanza.define({ | |
name: '_mucUserActor', | |
namespace: USER_NS, | |
element: 'actor', | |
fields: { | |
nick: stanza.attribute('nick'), | |
jid: util.jidAttribute('jid') | |
} | |
}); | |
var Destroyed = stanza.define({ | |
name: 'destroyed', | |
namespace: USER_NS, | |
element: 'destroy', | |
fields: { | |
jid: util.jidAttribute('jid'), | |
reason: stanza.subText(USER_NS, 'reason') | |
} | |
}); | |
var Invite = stanza.define({ | |
name: 'invite', | |
namespace: USER_NS, | |
element: 'invite', | |
fields: { | |
to: util.jidAttribute('to'), | |
from: util.jidAttribute('from'), | |
reason: stanza.subText(USER_NS, 'reason'), | |
thread: stanza.subAttribute(USER_NS, 'continue', 'thread'), | |
'continue': stanza.boolSub(USER_NS, 'continue') | |
} | |
}); | |
var Decline = stanza.define({ | |
name: 'decline', | |
namespace: USER_NS, | |
element: 'decline', | |
fields: { | |
to: util.jidAttribute('to'), | |
from: util.jidAttribute('from'), | |
reason: stanza.subText(USER_NS, 'reason') | |
} | |
}); | |
var AdminItem = stanza.define({ | |
name: '_mucAdminItem', | |
namespace: ADMIN_NS, | |
element: 'item', | |
fields: { | |
affiliation: stanza.attribute('affiliation'), | |
nick: stanza.attribute('nick'), | |
jid: util.jidAttribute('jid'), | |
role: stanza.attribute('role'), | |
reason: stanza.subText(ADMIN_NS, 'reason') | |
} | |
}); | |
var AdminActor = stanza.define({ | |
name: 'actor', | |
namespace: USER_NS, | |
element: 'actor', | |
fields: { | |
nick: stanza.attribute('nick'), | |
jid: util.jidAttribute('jid') | |
} | |
}); | |
var Destroy = stanza.define({ | |
name: 'destroy', | |
namespace: OWNER_NS, | |
element: 'destroy', | |
fields: { | |
jid: util.jidAttribute('jid'), | |
password: stanza.subText(OWNER_NS, 'password'), | |
reason: stanza.subText(OWNER_NS, 'reason') | |
} | |
}); | |
exports.MUC = stanza.define({ | |
name: 'muc', | |
namespace: USER_NS, | |
element: 'x', | |
fields: { | |
affiliation: proxy('_mucUserItem', 'affiliation'), | |
nick: proxy('_mucUserItem', 'nick'), | |
jid: proxy('_mucUserItem', 'jid'), | |
role: proxy('_mucUserItem', 'role'), | |
actor: proxy('_mucUserItem', '_mucUserActor'), | |
reason: proxy('_mucUserItem', 'reason'), | |
password: stanza.subText(USER_NS, 'password'), | |
codes: { | |
get: function () { | |
return stanza.getMultiSubText(this.xml, USER_NS, 'status', function (sub) { | |
return stanza.getAttribute(sub, 'code'); | |
}); | |
}, | |
set: function (value) { | |
var self = this; | |
stanza.setMultiSubText(this.xml, USER_NS, 'status', value, function (val) { | |
var child = stanza.createElement(USER_NS, 'status', USER_NS); | |
stanza.setAttribute(child, 'code', val); | |
self.xml.appendChild(child); | |
}); | |
} | |
} | |
} | |
}); | |
exports.MUCAdmin = stanza.define({ | |
name: 'mucAdmin', | |
namespace: ADMIN_NS, | |
element: 'query', | |
fields: { | |
affiliation: proxy('_mucAdminItem', 'affiliation'), | |
nick: proxy('_mucAdminItem', 'nick'), | |
jid: proxy('_mucAdminItem', 'jid'), | |
role: proxy('_mucAdminItem', 'role'), | |
actor: proxy('_mucAdminItem', '_mucAdminActor'), | |
reason: proxy('_mucAdminItem', 'reason') | |
} | |
}); | |
exports.MUCOwner = stanza.define({ | |
name: 'mucOwner', | |
namespace: OWNER_NS, | |
element: 'query' | |
}); | |
exports.MUCJoin = stanza.define({ | |
name: 'joinMuc', | |
namespace: NS, | |
element: 'x', | |
fields: { | |
password: stanza.subText(NS, 'password'), | |
history: { | |
get: function () { | |
var result = {}; | |
var hist = stanza.find(this.xml, this._NS, 'history'); | |
if (!hist.length) { | |
return {}; | |
} | |
hist = hist[0]; | |
var maxchars = hist.getAttribute('maxchars') || ''; | |
var maxstanzas = hist.getAttribute('maxstanas') || ''; | |
var seconds = hist.getAttribute('seconds') || ''; | |
var since = hist.getAttribute('since') || ''; | |
if (maxchars) { | |
result.maxchars = parseInt(maxchars, 10); | |
} | |
if (maxstanzas) { | |
result.maxstanzas = parseInt(maxstanzas, 10); | |
} | |
if (seconds) { | |
result.seconds = parseInt(seconds, 10); | |
} | |
if (since) { | |
result.since = new Date(since); | |
} | |
}, | |
set: function (opts) { | |
var existing = stanza.find(this.xml, this._NS, 'history'); | |
if (existing.length) { | |
for (var i = 0; i < existing.length; i++) { | |
this.xml.removeChild(existing[i]); | |
} | |
} | |
var hist = stanza.createElement(this._NS, 'history', this._NS); | |
this.xml.appendChild(hist); | |
if (opts.maxchars) { | |
hist.setAttribute('' + opts.maxchars); | |
} | |
if (opts.maxstanzas) { | |
hist.setAttribute('' + opts.maxstanzas); | |
} | |
if (opts.seconds) { | |
hist.setAttribute('' + opts.seconds); | |
} | |
if (opts.since) { | |
hist.setAttribute(opts.since.toISOString()); | |
} | |
} | |
} | |
} | |
}); | |
exports.DirectInvite = stanza.define({ | |
name: 'mucInvite', | |
namespace: 'jabber:x:conference', | |
element: 'x', | |
fields: { | |
jid: util.jidAttribute('jid'), | |
password: stanza.attribute('password'), | |
reason: stanza.attribute('reason'), | |
thread: stanza.attribute('thread'), | |
'continue': stanza.boolAttribute('continue') | |
} | |
}); | |
stanza.extend(UserItem, UserActor); | |
stanza.extend(exports.MUC, UserItem); | |
stanza.extend(exports.MUC, Invite, 'invites'); | |
stanza.extend(exports.MUC, Decline); | |
stanza.extend(exports.MUC, Destroyed); | |
stanza.extend(AdminItem, AdminActor); | |
stanza.extend(exports.MUCAdmin, AdminItem, 'items'); | |
stanza.extend(exports.MUCOwner, Destroy); | |
stanza.extend(exports.MUCOwner, DataForm); | |
stanza.extend(Presence, exports.MUC); | |
stanza.extend(Message, exports.MUC); | |
stanza.extend(Presence, exports.MUCJoin); | |
stanza.extend(Message, exports.DirectInvite); | |
stanza.extend(Iq, exports.MUCAdmin); | |
stanza.extend(Iq, exports.MUCOwner); | |
},{"./dataforms":51,"./iq":60,"./message":64,"./presence":69,"./util":84,"jxt":164}],66:[function(_dereq_,module,exports){ | |
"use strict"; | |
var stanza = _dereq_('jxt'); | |
var Item = _dereq_('./pubsub').Item; | |
var EventItem = _dereq_('./pubsub').EventItem; | |
var Presence = _dereq_('./presence'); | |
var Message = _dereq_('./message'); | |
var nick = stanza.subText('http://jabber.org/protocol/nick', 'nick'); | |
stanza.add(Item, 'nick', nick); | |
stanza.add(EventItem, 'nick', nick); | |
stanza.add(Presence, 'nick', nick); | |
stanza.add(Message, 'nick', nick); | |
},{"./message":64,"./presence":69,"./pubsub":72,"jxt":164}],67:[function(_dereq_,module,exports){ | |
"use strict"; | |
var stanza = _dereq_('jxt'); | |
var Message = _dereq_('./message'); | |
var NS = 'jabber:x:oob'; | |
var OOB = module.exports = stanza.define({ | |
name: 'oob', | |
element: 'x', | |
namespace: NS, | |
fields: { | |
url: stanza.subText(NS, 'url'), | |
desc: stanza.subText(NS, 'desc') | |
} | |
}); | |
stanza.extend(Message, OOB, 'oobURIs'); | |
},{"./message":64,"jxt":164}],68:[function(_dereq_,module,exports){ | |
var stanza = _dereq_('jxt'); | |
var Iq = _dereq_('./iq'); | |
var NS = 'urn:xmpp:ping'; | |
var Ping = module.exports = stanza.define({ | |
name: 'ping', | |
namespace: NS, | |
element: 'ping', | |
fields: { | |
} | |
}); | |
stanza.extend(Iq, Ping); | |
},{"./iq":60,"jxt":164}],69:[function(_dereq_,module,exports){ | |
"use strict"; | |
var _ = _dereq_('underscore'); | |
var stanza = _dereq_('jxt'); | |
var util = _dereq_('./util'); | |
module.exports = stanza.define({ | |
name: 'presence', | |
namespace: 'jabber:client', | |
element: 'presence', | |
topLevel: true, | |
fields: { | |
lang: stanza.langAttribute(), | |
id: stanza.attribute('id'), | |
to: util.jidAttribute('to'), | |
from: util.jidAttribute('from'), | |
priority: stanza.numberSub('jabber:client', 'priority'), | |
show: stanza.subText('jabber:client', 'show'), | |
type: { | |
get: function () { | |
return stanza.getAttribute(this.xml, 'type', 'available'); | |
}, | |
set: function (value) { | |
if (value === 'available') { | |
value = false; | |
} | |
stanza.setAttribute(this.xml, 'type', value); | |
} | |
}, | |
$status: { | |
get: function () { | |
return stanza.getSubLangText(this.xml, this._NS, 'status', this.lang); | |
} | |
}, | |
status: { | |
get: function () { | |
var statuses = this.$status; | |
return statuses[this.lang] || ''; | |
}, | |
set: function (value) { | |
stanza.setSubLangText(this.xml, this._NS, 'status', value, this.lang); | |
} | |
}, | |
idleSince: stanza.dateSubAttribute('urn:xmpp:idle:1', 'idle', 'since'), | |
decloak: stanza.subAttribute('urn:xmpp:decloak:0', 'decloak', 'reason'), | |
avatarId: { | |
get: function () { | |
var NS = 'vcard-temp:x:update'; | |
var update = stanza.find(this.xml, NS, 'x'); | |
if (!update.length) return ''; | |
return stanza.getSubText(update[0], NS, 'photo'); | |
}, | |
set: function (value) { | |
var NS = 'vcard-temp:x:update'; | |
var update = stanza.findOrCreate(this.xml, NS, 'x'); | |
if (value === '') { | |
stanza.setBoolSub(update, NS, 'photo', true); | |
} else if (value === true) { | |
return; | |
} else if (value) { | |
stanza.setSubText(update, NS, 'photo', value); | |
} else { | |
this.xml.removeChild(update); | |
} | |
} | |
} | |
} | |
}); | |
},{"./util":84,"jxt":164,"underscore":187}],70:[function(_dereq_,module,exports){ | |
var stanza = _dereq_('jxt'); | |
var Iq = _dereq_('./iq'); | |
var PrivateStorage = module.exports = stanza.define({ | |
name: 'privateStorage', | |
namespace: 'jabber:iq:private', | |
element: 'query' | |
}); | |
stanza.extend(Iq, PrivateStorage); | |
},{"./iq":60,"jxt":164}],71:[function(_dereq_,module,exports){ | |
"use strict"; | |
var stanza = _dereq_('jxt'); | |
var util = _dereq_('./util'); | |
var Presence = _dereq_('./presence'); | |
var NS = 'urn:xmpp:psa'; | |
var CONDITIONS = [ | |
'server-unavailable', 'connection-paused' | |
]; | |
var PSA = module.exports = stanza.define({ | |
name: 'state', | |
namespace: NS, | |
element: 'state-annotation', | |
fields: { | |
from: util.jidAttribute('from'), | |
condition: { | |
get: function () { | |
var self = this; | |
var result = []; | |
CONDITIONS.forEach(function (condition) { | |
var exists = stanza.find(self.xml, NS, condition); | |
if (exists.length) { | |
result.push(exists[0].tagName); | |
} | |
}); | |
return result[0] || ''; | |
}, | |
set: function (value) { | |
var self = this; | |
CONDITIONS.forEach(function (condition) { | |
var exists = stanza.find(self.xml, NS, condition); | |
if (exists.length) { | |
self.xml.removeChild(exists[0]); | |
} | |
}); | |
if (value) { | |
var condition = stanza.createElement(NS, value, NS); | |
self.xml.appendChild(condition); | |
} | |
} | |
}, | |
description: stanza.subText(NS, 'description') | |
} | |
}); | |
stanza.extend(Presence, PSA); | |
},{"./presence":69,"./util":84,"jxt":164}],72:[function(_dereq_,module,exports){ | |
"use strict"; | |
var _ = _dereq_('underscore'); | |
var stanza = _dereq_('jxt'); | |
var util = _dereq_('./util'); | |
var Iq = _dereq_('./iq'); | |
var Message = _dereq_('./message'); | |
var Form = _dereq_('./dataforms').DataForm; | |
var RSM = _dereq_('./rsm'); | |
var JID = _dereq_('../jid'); | |
var NS = 'http://jabber.org/protocol/pubsub'; | |
var OwnerNS = 'http://jabber.org/protocol/pubsub#owner'; | |
var EventNS = 'http://jabber.org/protocol/pubsub#event'; | |
exports.Pubsub = stanza.define({ | |
name: 'pubsub', | |
namespace: 'http://jabber.org/protocol/pubsub', | |
element: 'pubsub', | |
fields: { | |
publishOptions: { | |
get: function () { | |
var conf = stanza.find(this.xml, this._NS, 'publish-options'); | |
if (conf.length && conf[0].childNodes.length) { | |
return new Form({}, conf[0].childNodes[0]); | |
} | |
}, | |
set: function (value) { | |
var conf = stanza.findOrCreate(this.xml, this._NS, 'publish-options'); | |
if (value) { | |
var form = new Form(value); | |
conf.appendChild(form.xml); | |
} | |
} | |
} | |
} | |
}); | |
exports.PubsubOwner = stanza.define({ | |
name: 'pubsubOwner', | |
namespace: OwnerNS, | |
element: 'pubsub', | |
fields: { | |
create: stanza.subAttribute(OwnerNS, 'create', 'node'), | |
purge: stanza.subAttribute(OwnerNS, 'purge', 'node'), | |
del: stanza.subAttribute(OwnerNS, 'delete', 'node'), | |
redirect: { | |
get: function () { | |
var del = stanza.find(this.xml, this._NS, 'delete'); | |
if (del.length) { | |
return stanza.getSubAttribute(del[0], this._NS, 'redirect', 'uri'); | |
} | |
return ''; | |
}, | |
set: function (value) { | |
var del = stanza.findOrCreate(this.xml, this._NS, 'delete'); | |
stanza.setSubAttribute(del, this._NS, 'redirect', 'uri', value); | |
} | |
} | |
} | |
}); | |
exports.Configure = stanza.define({ | |
name: 'config', | |
namespace: OwnerNS, | |
element: 'configure', | |
fields: { | |
node: stanza.attribute('node') | |
} | |
}); | |
exports.Event = stanza.define({ | |
name: 'event', | |
namespace: EventNS, | |
element: 'event' | |
}); | |
exports.Subscribe = stanza.define({ | |
name: 'subscribe', | |
namespace: NS, | |
element: 'subscribe', | |
fields: { | |
node: stanza.attribute('node'), | |
jid: util.jidAttribute('jid') | |
} | |
}); | |
exports.Subscription = stanza.define({ | |
name: 'subscription', | |
namespace: NS, | |
element: 'subscription', | |
fields: { | |
node: stanza.attribute('node'), | |
jid: util.jidAttribute('jid'), | |
subid: stanza.attribute('subid'), | |
type: stanza.attribute('subscription') | |
} | |
}); | |
exports.Unsubscribe = stanza.define({ | |
name: 'unsubscribe', | |
namespace: NS, | |
element: 'unsubscribe', | |
fields: { | |
node: stanza.attribute('node'), | |
jid: util.jidAttribute('jid') | |
} | |
}); | |
exports.Publish = stanza.define({ | |
name: 'publish', | |
namespace: NS, | |
element: 'publish', | |
fields: { | |
node: stanza.attribute('node'), | |
} | |
}); | |
exports.Retract = stanza.define({ | |
name: 'retract', | |
namespace: NS, | |
element: 'retract', | |
fields: { | |
node: stanza.attribute('node'), | |
notify: stanza.boolAttribute('notify'), | |
id: stanza.subAttribute(NS, 'item', 'id') | |
} | |
}); | |
exports.Retrieve = stanza.define({ | |
name: 'retrieve', | |
namespace: NS, | |
element: 'items', | |
fields: { | |
node: stanza.attribute('node'), | |
max: stanza.attribute('max_items') | |
} | |
}); | |
exports.Item = stanza.define({ | |
name: 'item', | |
namespace: NS, | |
element: 'item', | |
fields: { | |
id: stanza.attribute('id') | |
} | |
}); | |
exports.EventItems = stanza.define({ | |
name: 'updated', | |
namespace: EventNS, | |
element: 'items', | |
fields: { | |
node: stanza.attribute('node'), | |
retracted: { | |
get: function () { | |
var results = []; | |
var retracted = stanza.find(this.xml, this._NS, 'retract'); | |
_.forEach(retracted, function (xml) { | |
results.push(xml.getAttribute('id')); | |
}); | |
return results; | |
}, | |
set: function (value) { | |
var self = this; | |
_.forEach(value, function (id) { | |
var retracted = stanza.createElement(self._NS, 'retract', self._NS); | |
retracted.setAttribute('id', id); | |
this.xml.appendChild(retracted); | |
}); | |
} | |
} | |
} | |
}); | |
exports.EventItem = stanza.define({ | |
name: 'eventItem', | |
namespace: EventNS, | |
element: 'item', | |
fields: { | |
id: stanza.attribute('id'), | |
node: stanza.attribute('node'), | |
publisher: util.jidAttribute('publisher') | |
} | |
}); | |
stanza.extend(exports.Pubsub, exports.Subscribe); | |
stanza.extend(exports.Pubsub, exports.Unsubscribe); | |
stanza.extend(exports.Pubsub, exports.Publish); | |
stanza.extend(exports.Pubsub, exports.Retrieve); | |
stanza.extend(exports.Pubsub, exports.Subscription); | |
stanza.extend(exports.PubsubOwner, exports.Configure); | |
stanza.extend(exports.Publish, exports.Item, 'items'); | |
stanza.extend(exports.Retrieve, exports.Item, 'items'); | |
stanza.extend(exports.Configure, Form); | |
stanza.extend(exports.Pubsub, RSM); | |
stanza.extend(exports.Event, exports.EventItems); | |
stanza.extend(exports.EventItems, exports.EventItem, 'published'); | |
stanza.extend(Message, exports.Event); | |
stanza.extend(Iq, exports.Pubsub); | |
stanza.extend(Iq, exports.PubsubOwner); | |
},{"../jid":4,"./dataforms":51,"./iq":60,"./message":64,"./rsm":75,"./util":84,"jxt":164,"underscore":187}],73:[function(_dereq_,module,exports){ | |
"use strict"; | |
var _ = _dereq_('underscore'); | |
var stanza = _dereq_('jxt'); | |
var Item = _dereq_('./pubsub').Item; | |
var EventItem = _dereq_('./pubsub').EventItem; | |
var Presence = _dereq_('./presence'); | |
var NS = 'urn:xmpp:reach:0'; | |
var ReachURI = module.exports = stanza.define({ | |
name: '_reachAddr', | |
namespace: NS, | |
element: 'addr', | |
fields: { | |
uri: stanza.attribute('uri'), | |
$desc: { | |
get: function () { | |
return stanza.getSubLangText(this.xml, NS, 'desc', this.lang); | |
} | |
}, | |
desc: { | |
get: function () { | |
var descs = this.$desc; | |
return descs[this.lang] || ''; | |
}, | |
set: function (value) { | |
stanza.setSubLangText(this.xml, NS, 'desc', value, this.lang); | |
} | |
} | |
} | |
}); | |
var reachability = { | |
get: function () { | |
var reach = stanza.find(this.xml, NS, 'reach'); | |
var results = []; | |
if (reach.length) { | |
var addrs = stanza.find(reach[0], NS, 'addr'); | |
_.forEach(addrs, function (addr) { | |
results.push(new ReachURI({}, addr)); | |
}); | |
} | |
return results; | |
}, | |
set: function (value) { | |
var reach = stanza.findOrCreate(this.xml, NS, 'reach'); | |
stanza.setAttribute(reach, 'xmlns', NS); | |
_.forEach(value, function (info) { | |
var addr = new ReachURI(info); | |
reach.appendChild(addr.xml); | |
}); | |
} | |
}; | |
stanza.add(Item, 'reach', reachability); | |
stanza.add(EventItem, 'reach', reachability); | |
stanza.add(Presence, 'reach', reachability); | |
},{"./presence":69,"./pubsub":72,"jxt":164,"underscore":187}],74:[function(_dereq_,module,exports){ | |
"use strict"; | |
var _ = _dereq_('underscore'); | |
var stanza = _dereq_('jxt'); | |
var Iq = _dereq_('./iq'); | |
var JID = _dereq_('../jid'); | |
var Roster = module.exports = stanza.define({ | |
name: 'roster', | |
namespace: 'jabber:iq:roster', | |
element: 'query', | |
fields: { | |
ver: { | |
get: function () { | |
return stanza.getAttribute(this.xml, 'ver'); | |
}, | |
set: function (value) { | |
var force = (value === ''); | |
stanza.setAttribute(this.xml, 'ver', value, force); | |
} | |
}, | |
items: { | |
get: function () { | |
var self = this; | |
var items = stanza.find(this.xml, this._NS, 'item'); | |
if (!items.length) { | |
return []; | |
} | |
var results = []; | |
items.forEach(function (item) { | |
var data = { | |
jid: new JID(stanza.getAttribute(item, 'jid', '')), | |
name: stanza.getAttribute(item, 'name', undefined), | |
subscription: stanza.getAttribute(item, 'subscription', 'none'), | |
ask: stanza.getAttribute(item, 'ask', undefined), | |
groups: [] | |
}; | |
var groups = stanza.find(item, self._NS, 'group'); | |
groups.forEach(function (group) { | |
data.groups.push(group.textContent); | |
}); | |
results.push(data); | |
}); | |
return results; | |
}, | |
set: function (values) { | |
var self = this; | |
values.forEach(function (value) { | |
var item = stanza.createElement(self._NS, 'item', self._NS); | |
stanza.setAttribute(item, 'jid', value.jid.toString()); | |
stanza.setAttribute(item, 'name', value.name); | |
stanza.setAttribute(item, 'subscription', value.subscription); | |
stanza.setAttribute(item, 'ask', value.ask); | |
(value.groups || []).forEach(function (name) { | |
var group = stanza.createElement(self._NS, 'group', self._NS); | |
group.textContent = name; | |
item.appendChild(group); | |
}); | |
self.xml.appendChild(item); | |
}); | |
} | |
} | |
} | |
}); | |
stanza.extend(Iq, Roster); | |
},{"../jid":4,"./iq":60,"jxt":164,"underscore":187}],75:[function(_dereq_,module,exports){ | |
"use strict"; | |
var stanza = _dereq_('jxt'); | |
var util = _dereq_('./util'); | |
var NS = 'http://jabber.org/protocol/rsm'; | |
module.exports = stanza.define({ | |
name: 'rsm', | |
namespace: NS, | |
element: 'set', | |
fields: { | |
after: stanza.subText(NS, 'after'), | |
before: { | |
get: function () { | |
return stanza.getSubText(this.xml, this._NS, 'before'); | |
}, | |
set: function (value) { | |
if (value === true) { | |
stanza.findOrCreate(this.xml, this._NS, 'before'); | |
} else { | |
stanza.setSubText(this.xml, this._NS, 'before', value); | |
} | |
} | |
}, | |
count: stanza.numberSub(NS, 'count'), | |
first: stanza.subText(NS, 'first'), | |
firstIndex: stanza.subAttribute(NS, 'first', 'index'), | |
index: stanza.subText(NS, 'index'), | |
last: stanza.subText(NS, 'last'), | |
max: stanza.subText(NS, 'max') | |
} | |
}); | |
},{"./util":84,"jxt":164}],76:[function(_dereq_,module,exports){ | |
"use strict"; | |
var _ = _dereq_('underscore'); | |
var stanza = _dereq_('jxt'); | |
var util = _dereq_('./util'); | |
var jingle = _dereq_('./jingle'); | |
var NS = 'urn:xmpp:jingle:apps:rtp:1'; | |
var FBNS = 'urn:xmpp:jingle:apps:rtp:rtcp-fb:0'; | |
var HDRNS = 'urn:xmpp:jingle:apps:rtp:rtp-hdrext:0'; | |
var INFONS = 'urn:xmpp:jingle:apps:rtp:info:1'; | |
var SSMANS = 'urn:xmpp:jingle:apps:rtp:ssma:0'; | |
var Feedback = { | |
get: function () { | |
var existing = stanza.find(this.xml, FBNS, 'rtcp-fb'); | |
var result = []; | |
existing.forEach(function (xml) { | |
result.push({ | |
type: stanza.getAttribute(xml, 'type'), | |
subtype: stanza.getAttribute(xml, 'subtype') | |
}); | |
}); | |
existing = stanza.find(this.xml, FBNS, 'rtcp-fb-trr-int'); | |
existing.forEach(function (xml) { | |
result.push({ | |
type: stanza.getAttribute(xml, 'type'), | |
value: stanza.getAttribute(xml, 'value') | |
}); | |
}); | |
return result; | |
}, | |
set: function (values) { | |
var self = this; | |
var existing = stanza.find(this.xml, FBNS, 'rtcp-fb'); | |
existing.forEach(function (item) { | |
self.xml.removeChild(item); | |
}); | |
existing = stanza.find(this.xml, FBNS, 'rtcp-fb-trr-int'); | |
existing.forEach(function (item) { | |
self.xml.removeChild(item); | |
}); | |
values.forEach(function (value) { | |
var fb; | |
if (value.type === 'trr-int') { | |
fb = stanza.createElement(FBNS, 'rtcp-fb-trr-int', NS); | |
stanza.setAttribute(fb, 'type', value.type); | |
stanza.setAttribute(fb, 'value', value.value); | |
} else { | |
fb = stanza.createElement(FBNS, 'rtcp-fb', NS); | |
stanza.setAttribute(fb, 'type', value.type); | |
stanza.setAttribute(fb, 'subtype', value.subtype); | |
} | |
self.xml.appendChild(fb); | |
}); | |
} | |
}; | |
exports.RTP = stanza.define({ | |
name: '_rtp', | |
namespace: NS, | |
element: 'description', | |
fields: { | |
descType: {value: 'rtp'}, | |
media: stanza.attribute('media'), | |
ssrc: stanza.attribute('ssrc'), | |
bandwidth: stanza.subText(NS, 'bandwidth'), | |
bandwidthType: stanza.subAttribute(NS, 'bandwidth', 'type'), | |
mux: stanza.boolSub(NS, 'rtcp-mux'), | |
encryption: { | |
get: function () { | |
var enc = stanza.find(this.xml, NS, 'encryption'); | |
if (!enc.length) return []; | |
enc = enc[0]; | |
var self = this; | |
var data = stanza.find(enc, NS, 'crypto'); | |
var results = []; | |
data.forEach(function (xml) { | |
results.push(new exports.Crypto({}, xml, self).toJSON()); | |
}); | |
return results; | |
}, | |
set: function (values) { | |
var enc = stanza.find(this.xml, NS, 'encryption'); | |
if (enc.length) { | |
this.xml.removeChild(enc); | |
} | |
if (!values.length) return; | |
stanza.setBoolSubAttribute(this.xml, NS, 'encryption', 'required', true); | |
enc = stanza.find(this.xml, NS, 'encryption')[0]; | |
var self = this; | |
values.forEach(function (value) { | |
var content = new exports.Crypto(value, null, self); | |
enc.appendChild(content.xml); | |
}); | |
} | |
}, | |
feedback: Feedback, | |
headerExtensions: { | |
get: function () { | |
var existing = stanza.find(this.xml, HDRNS, 'rtp-hdrext'); | |
var result = []; | |
existing.forEach(function (xml) { | |
result.push({ | |
id: stanza.getAttribute(xml, 'id'), | |
uri: stanza.getAttribute(xml, 'uri'), | |
senders: stanza.getAttribute(xml, 'senders') | |
}); | |
}); | |
return result; | |
}, | |
set: function (values) { | |
var self = this; | |
var existing = stanza.find(this.xml, HDRNS, 'rtp-hdrext'); | |
existing.forEach(function (item) { | |
self.xml.removeChild(item); | |
}); | |
values.forEach(function (value) { | |
var hdr = stanza.createElement(HDRNS, 'rtp-hdrext', NS); | |
stanza.setAttribute(hdr, 'id', value.id); | |
stanza.setAttribute(hdr, 'uri', value.uri); | |
stanza.setAttribute(hdr, 'senders', value.senders); | |
self.xml.appendChild(hdr); | |
}); | |
} | |
} | |
} | |
}); | |
exports.PayloadType = stanza.define({ | |
name: '_payloadType', | |
namespace: NS, | |
element: 'payload-type', | |
fields: { | |
channels: stanza.attribute('channels'), | |
clockrate: stanza.attribute('clockrate'), | |
id: stanza.attribute('id'), | |
maxptime: stanza.attribute('maxptime'), | |
name: stanza.attribute('name'), | |
ptime: stanza.attribute('ptime'), | |
feedback: Feedback, | |
parameters: { | |
get: function () { | |
var result = []; | |
var params = stanza.find(this.xml, NS, 'parameter'); | |
params.forEach(function (param) { | |
result.push({ | |
key: stanza.getAttribute(param, 'name'), | |
value: stanza.getAttribute(param, 'value') | |
}); | |
}); | |
return result; | |
}, | |
set: function (values) { | |
var self = this; | |
values.forEach(function (value) { | |
var param = stanza.createElement(NS, 'parameter'); | |
stanza.setAttribute(param, 'name', value.key); | |
stanza.setAttribute(param, 'value', value.value); | |
self.xml.appendChild(param); | |
}); | |
} | |
} | |
} | |
}); | |
exports.Crypto = stanza.define({ | |
name: 'crypto', | |
namespace: NS, | |
element: 'crypto', | |
fields: { | |
cipherSuite: stanza.attribute('crypto-suite'), | |
keyParams: stanza.attribute('key-params'), | |
sessionParams: stanza.attribute('session-params'), | |
tag: stanza.attribute('tag') | |
} | |
}); | |
exports.ContentGroup = stanza.define({ | |
name: '_group', | |
namespace: 'urn:xmpp:jingle:apps:grouping:0', | |
element: 'group', | |
fields: { | |
semantics: stanza.attribute('semantics'), | |
contents: { | |
get: function () { | |
var self = this; | |
return stanza.getMultiSubText(this.xml, this._NS, 'content', function (sub) { | |
return stanza.getAttribute(sub, 'name'); | |
}); | |
}, | |
set: function (value) { | |
var self = this; | |
stanza.setMultiSubText(this.xml, this._NS, 'content', value, function (val) { | |
var child = stanza.createElement(self._NS, 'content', self._NS); | |
stanza.setAttribute(child, 'name', val); | |
self.xml.appendChild(child); | |
}); | |
} | |
} | |
} | |
}); | |
exports.SourceGroup = stanza.define({ | |
name: '_sourceGroup', | |
namespace: SSMANS, | |
element: 'ssrc-group', | |
fields: { | |
semantics: stanza.attribute('semantics'), | |
sources: { | |
get: function () { | |
var self = this; | |
return stanza.getMultiSubText(this.xml, this._NS, 'source', function (sub) { | |
return stanza.getAttribute(sub, 'ssrc'); | |
}); | |
}, | |
set: function (value) { | |
var self = this; | |
stanza.setMultiSubText(this.xml, this._NS, 'source', value, function (val) { | |
var child = stanza.createElement(self._NS, 'source', self._NS); | |
stanza.setAttribute(child, 'ssrc', val); | |
self.xml.appendChild(child); | |
}); | |
} | |
} | |
} | |
}); | |
exports.Source = stanza.define({ | |
name: '_source', | |
namespace: SSMANS, | |
element: 'source', | |
fields: { | |
ssrc: stanza.attribute('ssrc'), | |
parameters: { | |
get: function () { | |
var result = []; | |
var params = stanza.find(this.xml, SSMANS, 'parameter'); | |
params.forEach(function (param) { | |
result.push({ | |
key: stanza.getAttribute(param, 'name'), | |
value: stanza.getAttribute(param, 'value') | |
}); | |
}); | |
return result; | |
}, | |
set: function (values) { | |
var self = this; | |
values.forEach(function (value) { | |
var param = stanza.createElement(SSMANS, 'parameter'); | |
stanza.setAttribute(param, 'name', value.key); | |
stanza.setAttribute(param, 'value', value.value); | |
self.xml.appendChild(param); | |
}); | |
} | |
} | |
} | |
}); | |
exports.Mute = stanza.define({ | |
name: 'mute', | |
namespace: INFONS, | |
element: 'mute', | |
fields: { | |
creator: stanza.attribute('creator'), | |
name: stanza.attribute('name') | |
} | |
}); | |
exports.Unmute = stanza.define({ | |
name: 'unmute', | |
namespace: INFONS, | |
element: 'unmute', | |
fields: { | |
creator: stanza.attribute('creator'), | |
name: stanza.attribute('name') | |
} | |
}); | |
stanza.extend(jingle.Content, exports.RTP); | |
stanza.extend(exports.RTP, exports.PayloadType, 'payloads'); | |
stanza.extend(exports.RTP, exports.Source, 'sources'); | |
stanza.extend(exports.RTP, exports.SourceGroup, 'sourceGroups'); | |
stanza.extend(jingle.Jingle, exports.Mute); | |
stanza.extend(jingle.Jingle, exports.Unmute); | |
stanza.extend(jingle.Jingle, exports.ContentGroup, 'groups'); | |
stanza.add(jingle.Jingle, 'ringing', stanza.boolSub(INFONS, 'ringing')); | |
stanza.add(jingle.Jingle, 'hold', stanza.boolSub(INFONS, 'hold')); | |
stanza.add(jingle.Jingle, 'active', stanza.boolSub(INFONS, 'active')); | |
},{"./jingle":61,"./util":84,"jxt":164,"underscore":187}],77:[function(_dereq_,module,exports){ | |
"use strict"; | |
var _ = _dereq_('underscore'); | |
var stanza = _dereq_('jxt'); | |
var util = _dereq_('./util'); | |
var StreamFeatures = _dereq_('./streamFeatures'); | |
var NS = 'urn:ietf:params:xml:ns:xmpp-sasl'; | |
var CONDITIONS = [ | |
'aborted', 'account-disabled', 'credentials-expired', | |
'encryption-required', 'incorrect-encoding', 'invalid-authzid', | |
'invalid-mechanism', 'malformed-request', 'mechanism-too-weak', | |
'not-authorized', 'temporary-auth-failure' | |
]; | |
exports.Mechanisms = stanza.define({ | |
name: 'sasl', | |
namespace: NS, | |
element: 'mechanisms', | |
fields: { | |
mechanisms: stanza.multiSubText(NS, 'mechanism') | |
} | |
}); | |
exports.Auth = stanza.define({ | |
name: 'saslAuth', | |
eventName: 'sasl:auth', | |
namespace: NS, | |
element: 'auth', | |
topLevel: true, | |
fields: { | |
value: stanza.b64Text(), | |
mechanism: stanza.attribute('mechanism') | |
} | |
}); | |
exports.Challenge = stanza.define({ | |
name: 'saslChallenge', | |
eventName: 'sasl:challenge', | |
namespace: NS, | |
element: 'challenge', | |
topLevel: true, | |
fields: { | |
value: stanza.b64Text() | |
} | |
}); | |
exports.Response = stanza.define({ | |
name: 'saslResponse', | |
eventName: 'sasl:response', | |
namespace: NS, | |
element: 'response', | |
topLevel: true, | |
fields: { | |
value: stanza.b64Text() | |
} | |
}); | |
exports.Abort = stanza.define({ | |
name: 'saslAbort', | |
eventName: 'sasl:abort', | |
namespace: NS, | |
element: 'abort', | |
topLevel: true | |
}); | |
exports.Success = stanza.define({ | |
name: 'saslSuccess', | |
eventName: 'sasl:success', | |
namespace: NS, | |
element: 'success', | |
topLevel: true, | |
fields: { | |
value: stanza.b64Text() | |
} | |
}); | |
exports.Failure = stanza.define({ | |
name: 'saslFailure', | |
eventName: 'sasl:failure', | |
namespace: NS, | |
element: 'failure', | |
topLevel: true, | |
fields: { | |
lang: { | |
get: function () { | |
return this._lang || ''; | |
}, | |
set: function (value) { | |
this._lang = value; | |
} | |
}, | |
condition: { | |
get: function () { | |
var self = this; | |
var result = []; | |
CONDITIONS.forEach(function (condition) { | |
var exists = stanza.find(self.xml, NS, condition); | |
if (exists.length) { | |
result.push(exists[0].tagName); | |
} | |
}); | |
return result[0] || ''; | |
}, | |
set: function (value) { | |
var self = this; | |
this._CONDITIONS.forEach(function (condition) { | |
var exists = stanza.find(self.xml, NS, condition); | |
if (exists.length) { | |
self.xml.removeChild(exists[0]); | |
} | |
}); | |
if (value) { | |
var condition = stanza.createElementNS(NS, value); | |
condition.setAttribute('xmlns', NS); | |
this.xml.appendChild(condition); | |
} | |
} | |
}, | |
$text: { | |
get: function () { | |
return stanza.getSubLangText(this.xml, NS, 'text', this.lang); | |
} | |
}, | |
text: { | |
get: function () { | |
var text = this.$text; | |
return text[this.lang] || ''; | |
}, | |
set: function (value) { | |
stanza.setSubLangText(this.xml, NS, 'text', value, this.lang); | |
} | |
} | |
} | |
}); | |
stanza.extend(StreamFeatures, exports.Mechanisms); | |
},{"./streamFeatures":82,"./util":84,"jxt":164,"underscore":187}],78:[function(_dereq_,module,exports){ | |
var stanza = _dereq_('jxt'); | |
var Iq = _dereq_('./iq'); | |
var StreamFeatures = _dereq_('./streamFeatures'); | |
var Session = module.exports = stanza.define({ | |
name: 'session', | |
namespace: 'urn:ietf:params:xml:ns:xmpp-session', | |
element: 'session' | |
}); | |
stanza.extend(StreamFeatures, Session); | |
stanza.extend(Iq, Session); | |
},{"./iq":60,"./streamFeatures":82,"jxt":164}],79:[function(_dereq_,module,exports){ | |
var stanza = _dereq_('jxt'); | |
var util = _dereq_('./util'); | |
var StreamFeatures = _dereq_('./streamFeatures'); | |
var NS = 'urn:xmpp:sm:3'; | |
exports.SMFeature = stanza.define({ | |
name: 'streamManagement', | |
namespace: NS, | |
element: 'sm' | |
}); | |
exports.Enable = stanza.define({ | |
name: 'smEnable', | |
eventName: 'stream:management:enable', | |
namespace: NS, | |
element: 'enable', | |
topLevel: true, | |
fields: { | |
resume: stanza.boolAttribute('resume') | |
} | |
}); | |
exports.Enabled = stanza.define({ | |
name: 'smEnabled', | |
eventName: 'stream:management:enabled', | |
namespace: NS, | |
element: 'enabled', | |
topLevel: true, | |
fields: { | |
id: stanza.attribute('id'), | |
resume: stanza.boolAttribute('resume') | |
} | |
}); | |
exports.Resume = stanza.define({ | |
name: 'smResume', | |
eventName: 'stream:management:resume', | |
namespace: NS, | |
element: 'resume', | |
topLevel: true, | |
fields: { | |
h: stanza.numberAttribute('h'), | |
previd: stanza.attribute('previd') | |
} | |
}); | |
exports.Resumed = stanza.define({ | |
name: 'smResumed', | |
eventName: 'stream:management:resumed', | |
namespace: NS, | |
element: 'resumed', | |
topLevel: true, | |
fields: { | |
h: stanza.numberAttribute('h'), | |
previd: stanza.attribute('previd') | |
} | |
}); | |
exports.Failed = stanza.define({ | |
name: 'smFailed', | |
eventName: 'stream:management:failed', | |
namespace: NS, | |
element: 'failed', | |
topLevel: true | |
}); | |
exports.Ack = stanza.define({ | |
name: 'smAck', | |
eventName: 'stream:management:ack', | |
namespace: NS, | |
element: 'a', | |
topLevel: true, | |
fields: { | |
h: stanza.numberAttribute('h') | |
} | |
}); | |
exports.Request = stanza.define({ | |
name: 'smRequest', | |
eventName: 'stream:management:request', | |
namespace: NS, | |
element: 'r', | |
topLevel: true | |
}); | |
stanza.extend(StreamFeatures, exports.SMFeature); | |
},{"./streamFeatures":82,"./util":84,"jxt":164}],80:[function(_dereq_,module,exports){ | |
"use strict"; | |
var stanza = _dereq_('jxt'); | |
var util = _dereq_('./util'); | |
module.exports = stanza.define({ | |
name: 'stream', | |
namespace: 'http://etherx.jabber.org/streams', | |
element: 'stream', | |
fields: { | |
lang: stanza.langAttribute(), | |
id: stanza.attribute('id'), | |
version: stanza.attribute('version', '1.0'), | |
to: util.jidAttribute('to'), | |
from: util.jidAttribute('from') | |
} | |
}); | |
},{"./util":84,"jxt":164}],81:[function(_dereq_,module,exports){ | |
"use strict"; | |
var _ = _dereq_('underscore'); | |
var stanza = _dereq_('jxt'); | |
var ERR_NS = 'urn:ietf:params:xml:ns:xmpp-streams'; | |
var CONDITIONS = [ | |
'bad-format', 'bad-namespace-prefix', 'conflict', | |
'connection-timeout', 'host-gone', 'host-unknown', | |
'improper-addressing', 'internal-server-error', 'invalid-from', | |
'invalid-namespace', 'invalid-xml', 'not-authorized', | |
'not-well-formed', 'policy-violation', 'remote-connection-failed', | |
'reset', 'resource-constraint', 'restricted-xml', 'see-other-host', | |
'system-shutdown', 'undefined-condition', 'unsupported-encoding', | |
'unsupported-feature', 'unsupported-stanza-type', | |
'unsupported-version' | |
]; | |
module.exports = stanza.define({ | |
name: 'streamError', | |
namespace: 'http://etherx.jabber.org/streams', | |
element: 'error', | |
topLevel: true, | |
fields: { | |
lang: { | |
get: function () { | |
return this._lang || ''; | |
}, | |
set: function (value) { | |
this._lang = value; | |
} | |
}, | |
condition: { | |
get: function () { | |
var self = this; | |
var result = []; | |
CONDITIONS.forEach(function (condition) { | |
var exists = stanza.find(self.xml, ERR_NS, condition); | |
if (exists.length) { | |
result.push(exists[0].tagName); | |
} | |
}); | |
return result[0] || ''; | |
}, | |
set: function (value) { | |
var self = this; | |
CONDITIONS.forEach(function (condition) { | |
var exists = stanza.find(self.xml, ERR_NS, condition); | |
if (exists.length) { | |
self.xml.removeChild(exists[0]); | |
} | |
}); | |
if (value) { | |
var condition = stanza.createElement(ERR_NS, value); | |
condition.setAttribute('xmlns', ERR_NS); | |
this.xml.appendChild(condition); | |
} | |
} | |
}, | |
seeOtherHost: { | |
get: function () { | |
return stanza.getSubText(this.xml, ERR_NS, 'see-other-host'); | |
}, | |
set: function (value) { | |
this.condition = 'see-other-host'; | |
stanza.setSubText(this.xml, ERR_NS, 'see-other-host', value); | |
} | |
}, | |
$text: { | |
get: function () { | |
return stanza.getSubLangText(this.xml, ERR_NS, 'text', this.lang); | |
} | |
}, | |
text: { | |
get: function () { | |
var text = this.$text; | |
return text[this.lang] || ''; | |
}, | |
set: function (value) { | |
stanza.setSubLangText(this.xml, ERR_NS, 'text', value, this.lang); | |
} | |
} | |
} | |
}); | |
},{"jxt":164,"underscore":187}],82:[function(_dereq_,module,exports){ | |
"use strict"; | |
var stanza = _dereq_('jxt'); | |
var StreamFeatures = module.exports = stanza.define({ | |
name: 'streamFeatures', | |
namespace: 'http://etherx.jabber.org/streams', | |
element: 'features', | |
topLevel: true, | |
fields: { | |
features: { | |
get: function () { | |
return this._extensions; | |
} | |
} | |
} | |
}); | |
var RosterVerFeature = stanza.define({ | |
name: 'rosterVersioning', | |
namespace: 'urn:xmpp:features:rosterver', | |
element: 'ver' | |
}); | |
var SubscriptionPreApprovalFeature = stanza.define({ | |
name: 'subscriptionPreApproval', | |
namespace: 'urn:xmpp:features:pre-approval', | |
element: 'sub' | |
}); | |
stanza.extend(StreamFeatures, RosterVerFeature); | |
stanza.extend(StreamFeatures, SubscriptionPreApprovalFeature); | |
},{"jxt":164}],83:[function(_dereq_,module,exports){ | |
"use strict"; | |
var stanza = _dereq_('jxt'); | |
var util = _dereq_('./util'); | |
var Iq = _dereq_('./iq'); | |
var EntityTime = module.exports = stanza.define({ | |
name: 'time', | |
namespace: 'urn:xmpp:time', | |
element: 'time', | |
fields: { | |
utc: stanza.dateSub('urn:xmpp:time', 'utc'), | |
tzo: { | |
get: function () { | |
var split, hrs, min; | |
var sign = -1; | |
var formatted = stanza.getSubText(this.xml, this._NS, 'tzo'); | |
if (!formatted) { | |
return 0; | |
} | |
if (formatted.charAt(0) === '-') { | |
sign = 1; | |
formatted = formatted.slice(1); | |
} | |
split = formatted.split(':'); | |
hrs = parseInt(split[0], 10); | |
min = parseInt(split[1], 10); | |
return (hrs * 60 + min) * sign; | |
}, | |
set: function (value) { | |
var hrs, min; | |
var formatted = '-'; | |
if (typeof value === 'number') { | |
if (value < 0) { | |
value = -value; | |
formatted = '+'; | |
} | |
hrs = value / 60; | |
min = value % 60; | |
formatted += (hrs < 10 ? '0' : '') + hrs + ':' + (min < 10 ? '0' : '') + min; | |
} else { | |
formatted = value; | |
} | |
stanza.setSubText(this.xml, this._NS, 'tzo', formatted); | |
} | |
} | |
} | |
}); | |
stanza.extend(Iq, EntityTime); | |
},{"./iq":60,"./util":84,"jxt":164}],84:[function(_dereq_,module,exports){ | |
"use strict"; | |
var stanza = _dereq_('jxt'); | |
var JID = _dereq_('../jid'); | |
exports.jidAttribute = stanza.field( | |
function (xml, attr) { | |
return new JID(stanza.getAttribute(xml, attr)); | |
}, | |
function (xml, attr, value) { | |
stanza.setAttribute(xml, attr, (value || '').toString()); | |
} | |
); | |
exports.jidSub = stanza.field( | |
function (xml, NS, sub) { | |
return new JID(stanza.getSubText(xml, NS, sub)); | |
}, | |
function (xml, NS, sub, value) { | |
stanza.setSubText(xml, NS, sub, (value || '').toString()); | |
} | |
); | |
},{"../jid":4,"jxt":164}],85:[function(_dereq_,module,exports){ | |
"use strict"; | |
var stanza = _dereq_('jxt'); | |
var Iq = _dereq_('./iq'); | |
var NS = 'vcard-temp'; | |
var VCardTemp = module.exports = stanza.define({ | |
name: 'vCardTemp', | |
namespace: NS, | |
element: 'vCard', | |
fields: { | |
role: stanza.subText(NS, 'ROLE'), | |
website: stanza.subText(NS, 'URL'), | |
title: stanza.subText(NS, 'TITLE'), | |
description: stanza.subText(NS, 'DESC'), | |
fullName: stanza.subText(NS, 'FN'), | |
birthday: stanza.dateSub(NS, 'BDAY'), | |
nicknames: stanza.multiSubText(NS, 'NICKNAME'), | |
jids: stanza.multiSubText(NS, 'JABBERID') | |
} | |
}); | |
var Email = stanza.define({ | |
name: '_email', | |
namespace: NS, | |
element: 'EMAIL', | |
fields: { | |
email: stanza.subText(NS, 'USERID'), | |
home: stanza.boolSub(NS, 'HOME'), | |
work: stanza.boolSub(NS, 'WORK'), | |
preferred: stanza.boolSub(NS, 'PREF') | |
} | |
}); | |
var PhoneNumber = stanza.define({ | |
name: '_tel', | |
namespace: NS, | |
element: 'TEL', | |
fields: { | |
number: stanza.subText(NS, 'NUMBER'), | |
home: stanza.boolSub(NS, 'HOME'), | |
work: stanza.boolSub(NS, 'WORK'), | |
mobile: stanza.boolSub(NS, 'CELL'), | |
preferred: stanza.boolSub(NS, 'PREF') | |
} | |
}); | |
var Address = stanza.define({ | |
name: '_address', | |
namespace: NS, | |
element: 'ADR', | |
fields: { | |
street: stanza.subText(NS, 'STREET'), | |
street2: stanza.subText(NS, 'EXTADD'), | |
country: stanza.subText(NS, 'CTRY'), | |
city: stanza.subText(NS, 'LOCALITY'), | |
region: stanza.subText(NS, 'REGION'), | |
postalCode: stanza.subText(NS, 'PCODE'), | |
pobox: stanza.subText(NS, 'POBOX'), | |
home: stanza.boolSub(NS, 'HOME'), | |
work: stanza.boolSub(NS, 'WORK'), | |
preferred: stanza.boolSub(NS, 'PREF') | |
} | |
}); | |
var Organization = stanza.define({ | |
name: 'organization', | |
namespace: NS, | |
element: 'ORG', | |
fields: { | |
name: stanza.subText(NS, 'ORGNAME'), | |
unit: stanza.subText(NS, 'ORGUNIT') | |
} | |
}); | |
var Name = stanza.define({ | |
name: 'name', | |
namespace: NS, | |
element: 'N', | |
fields: { | |
family: stanza.subText(NS, 'FAMILY'), | |
given: stanza.subText(NS, 'GIVEN'), | |
middle: stanza.subText(NS, 'MIDDLE'), | |
prefix: stanza.subText(NS, 'PREFIX'), | |
suffix: stanza.subText(NS, 'SUFFIX') | |
} | |
}); | |
var Photo = stanza.define({ | |
name: 'photo', | |
namespace: NS, | |
element: 'PHOTO', | |
fields: { | |
type: stanza.subText(NS, 'TYPE'), | |
data: stanza.subText(NS, 'BINVAL'), | |
url: stanza.subText(NS, 'EXTVAL') | |
} | |
}); | |
stanza.extend(VCardTemp, Email, 'emails'); | |
stanza.extend(VCardTemp, Address, 'addresses'); | |
stanza.extend(VCardTemp, PhoneNumber, 'phoneNumbers'); | |
stanza.extend(VCardTemp, Organization); | |
stanza.extend(VCardTemp, Name); | |
stanza.extend(VCardTemp, Photo); | |
stanza.extend(Iq, VCardTemp); | |
},{"./iq":60,"jxt":164}],86:[function(_dereq_,module,exports){ | |
var stanza = _dereq_('jxt'); | |
var Iq = _dereq_('./iq'); | |
var NS = 'jabber:iq:version'; | |
var Version = module.exports = stanza.define({ | |
name: 'version', | |
namespace: NS, | |
element: 'query', | |
fields: { | |
name: stanza.subText(NS, 'name'), | |
version: stanza.subText(NS, 'version'), | |
os: stanza.subText(NS, 'os') | |
} | |
}); | |
stanza.extend(Iq, Version); | |
},{"./iq":60,"jxt":164}],87:[function(_dereq_,module,exports){ | |
var stanza = _dereq_('jxt'); | |
var Iq = _dereq_('./iq'); | |
stanza.add(Iq, 'visible', stanza.boolSub('urn:xmpp:invisible:0', 'visible')); | |
stanza.add(Iq, 'invisible', stanza.boolSub('urn:xmpp:invisible:0', 'invisible')); | |
},{"./iq":60,"jxt":164}],88:[function(_dereq_,module,exports){ | |
"use strict"; | |
var _ = _dereq_('underscore'); | |
var util = _dereq_('util'); | |
var stanza = _dereq_('jxt'); | |
var WildEmitter = _dereq_('wildemitter'); | |
var async = _dereq_('async'); | |
var framing = _dereq_('./stanza/framing'); | |
var StreamError = _dereq_('./stanza/streamError'); | |
var Message = _dereq_('./stanza/message'); | |
var Presence = _dereq_('./stanza/presence'); | |
var Iq = _dereq_('./stanza/iq'); | |
var WS = (_dereq_('faye-websocket') && _dereq_('faye-websocket').Client) ? | |
_dereq_('faye-websocket').Client : | |
window.WebSocket; | |
var WS_OPEN = 1; | |
function WSConnection(sm) { | |
var self = this; | |
WildEmitter.call(this); | |
self.sm = sm; | |
self.closing = false; | |
self.sendQueue = async.queue(function (data, cb) { | |
if (self.conn) { | |
self.sm.track(data); | |
if (typeof data !== 'string') { | |
data = data.toString(); | |
} | |
self.emit('raw:outgoing', data); | |
if (self.conn.readyState === WS_OPEN) { | |
self.conn.send(data); | |
} | |
} | |
cb(); | |
}, 1); | |
self.on('connected', function () { | |
self.send(self.startHeader()); | |
}); | |
self.on('raw:incoming', function (data) { | |
var stanzaObj, ended, err; | |
data = data.trim(); | |
if (data === '') { | |
return; | |
} | |
try { | |
stanzaObj = stanza.parse(data); | |
} catch (e) { | |
err = new StreamError({ | |
condition: 'invalid-xml' | |
}); | |
self.emit('stream:error', err, e); | |
self.send(err); | |
return self.disconnect(); | |
} | |
if (stanzaObj._name === 'openStream') { | |
self.hasStream = true; | |
self.stream = stanzaObj; | |
return self.emit('stream:start', stanzaObj.toJSON()); | |
} | |
if (stanzaObj._name === 'closeStream') { | |
self.emit('stream:end'); | |
return self.disconnect(); | |
} | |
if (!stanzaObj.lang) { | |
stanzaObj.lang = self.stream.lang; | |
} | |
self.emit('stream:data', stanzaObj); | |
}); | |
} | |
util.inherits(WSConnection, WildEmitter); | |
WSConnection.prototype.connect = function (opts) { | |
var self = this; | |
self.config = opts; | |
self.hasStream = false; | |
self.closing = false; | |
self.conn = new WS(opts.wsURL, 'xmpp'); | |
self.conn.onerror = function (e) { | |
e.preventDefault(); | |
self.emit('disconnected', self); | |
}; | |
self.conn.onclose = function () { | |
self.emit('disconnected', self); | |
}; | |
self.conn.onopen = function () { | |
self.sm.started = false; | |
self.emit('connected', self); | |
}; | |
self.conn.onmessage = function (wsMsg) { | |
self.emit('raw:incoming', wsMsg.data); | |
}; | |
}; | |
WSConnection.prototype.startHeader = function () { | |
return new framing.Open({ | |
version: this.config.version || '1.0', | |
lang: this.config.lang || 'en', | |
to: this.config.server | |
}); | |
}; | |
WSConnection.prototype.closeHeader = function () { | |
return new framing.Close(); | |
}; | |
WSConnection.prototype.disconnect = function () { | |
if (this.conn && !this.closing) { | |
this.closing = true; | |
this.send(this.closeHeader()); | |
} else { | |
this.hasStream = false; | |
this.stream = undefined; | |
this.sm.failed(); | |
if (this.conn.readyState === WS_OPEN) { | |
this.conn.close(); | |
} | |
this.conn = undefined; | |
} | |
}; | |
WSConnection.prototype.restart = function () { | |
var self = this; | |
self.hasStream = false; | |
self.send(this.startHeader()); | |
}; | |
WSConnection.prototype.send = function (data) { | |
this.sendQueue.push(data); | |
}; | |
module.exports = WSConnection; | |
},{"./stanza/framing":57,"./stanza/iq":60,"./stanza/message":64,"./stanza/presence":69,"./stanza/streamError":81,"async":89,"faye-websocket":129,"jxt":164,"underscore":187,"util":142,"wildemitter":188}],89:[function(_dereq_,module,exports){ | |
(function (process){ | |
/*jshint onevar: false, indent:4 */ | |
/*global setImmediate: false, setTimeout: false, console: false */ | |
(function () { | |
var async = {}; | |
// global on the server, window in the browser | |
var root, previous_async; | |
root = this; | |
if (root != null) { | |
previous_async = root.async; | |
} | |
async.noConflict = function () { | |
root.async = previous_async; | |
return async; | |
}; | |
function only_once(fn) { | |
var called = false; | |
return function() { | |
if (called) throw new Error("Callback was already called."); | |
called = true; | |
fn.apply(root, arguments); | |
} | |
} | |
//// cross-browser compatiblity functions //// | |
var _toString = Object.prototype.toString; | |
var _isArray = Array.isArray || function (obj) { | |
return _toString.call(obj) === '[object Array]'; | |
}; | |
var _each = function (arr, iterator) { | |
if (arr.forEach) { | |
return arr.forEach(iterator); | |
} | |
for (var i = 0; i < arr.length; i += 1) { | |
iterator(arr[i], i, arr); | |
} | |
}; | |
var _map = function (arr, iterator) { | |
if (arr.map) { | |
return arr.map(iterator); | |
} | |
var results = []; | |
_each(arr, function (x, i, a) { | |
results.push(iterator(x, i, a)); | |
}); | |
return results; | |
}; | |
var _reduce = function (arr, iterator, memo) { | |
if (arr.reduce) { | |
return arr.reduce(iterator, memo); | |
} | |
_each(arr, function (x, i, a) { | |
memo = iterator(memo, x, i, a); | |
}); | |
return memo; | |
}; | |
var _keys = function (obj) { | |
if (Object.keys) { | |
return Object.keys(obj); | |
} | |
var keys = []; | |
for (var k in obj) { | |
if (obj.hasOwnProperty(k)) { | |
keys.push(k); | |
} | |
} | |
return keys; | |
}; | |
//// exported async module functions //// | |
//// nextTick implementation with browser-compatible fallback //// | |
if (typeof process === 'undefined' || !(process.nextTick)) { | |
if (typeof setImmediate === 'function') { | |
async.nextTick = function (fn) { | |
// not a direct alias for IE10 compatibility | |
setImmediate(fn); | |
}; | |
async.setImmediate = async.nextTick; | |
} | |
else { | |
async.nextTick = function (fn) { | |
setTimeout(fn, 0); | |
}; | |
async.setImmediate = async.nextTick; | |
} | |
} | |
else { | |
async.nextTick = process.nextTick; | |
if (typeof setImmediate !== 'undefined') { | |
async.setImmediate = function (fn) { | |
// not a direct alias for IE10 compatibility | |
setImmediate(fn); | |
}; | |
} | |
else { | |
async.setImmediate = async.nextTick; | |
} | |
} | |
async.each = function (arr, iterator, callback) { | |
callback = callback || function () {}; | |
if (!arr.length) { | |
return callback(); | |
} | |
var completed = 0; | |
_each(arr, function (x) { | |
iterator(x, only_once(done) ); | |
}); | |
function done(err) { | |
if (err) { | |
callback(err); | |
callback = function () {}; | |
} | |
else { | |
completed += 1; | |
if (completed >= arr.length) { | |
callback(); | |
} | |
} | |
} | |
}; | |
async.forEach = async.each; | |
async.eachSeries = function (arr, iterator, callback) { | |
callback = callback || function () {}; | |
if (!arr.length) { | |
return callback(); | |
} | |
var completed = 0; | |
var iterate = function () { | |
iterator(arr[completed], function (err) { | |
if (err) { | |
callback(err); | |
callback = function () {}; | |
} | |
else { | |
completed += 1; | |
if (completed >= arr.length) { | |
callback(); | |
} | |
else { | |
iterate(); | |
} | |
} | |
}); | |
}; | |
iterate(); | |
}; | |
async.forEachSeries = async.eachSeries; | |
async.eachLimit = function (arr, limit, iterator, callback) { | |
var fn = _eachLimit(limit); | |
fn.apply(null, [arr, iterator, callback]); | |
}; | |
async.forEachLimit = async.eachLimit; | |
var _eachLimit = function (limit) { | |
return function (arr, iterator, callback) { | |
callback = callback || function () {}; | |
if (!arr.length || limit <= 0) { | |
return callback(); | |
} | |
var completed = 0; | |
var started = 0; | |
var running = 0; | |
(function replenish () { | |
if (completed >= arr.length) { | |
return callback(); | |
} | |
while (running < limit && started < arr.length) { | |
started += 1; | |
running += 1; | |
iterator(arr[started - 1], function (err) { | |
if (err) { | |
callback(err); | |
callback = function () {}; | |
} | |
else { | |
completed += 1; | |
running -= 1; | |
if (completed >= arr.length) { | |
callback(); | |
} | |
else { | |
replenish(); | |
} | |
} | |
}); | |
} | |
})(); | |
}; | |
}; | |
var doParallel = function (fn) { | |
return function () { | |
var args = Array.prototype.slice.call(arguments); | |
return fn.apply(null, [async.each].concat(args)); | |
}; | |
}; | |
var doParallelLimit = function(limit, fn) { | |
return function () { | |
var args = Array.prototype.slice.call(arguments); | |
return fn.apply(null, [_eachLimit(limit)].concat(args)); | |
}; | |
}; | |
var doSeries = function (fn) { | |
return function () { | |
var args = Array.prototype.slice.call(arguments); | |
return fn.apply(null, [async.eachSeries].concat(args)); | |
}; | |
}; | |
var _asyncMap = function (eachfn, arr, iterator, callback) { | |
var results = []; | |
arr = _map(arr, function (x, i) { | |
return {index: i, value: x}; | |
}); | |
eachfn(arr, function (x, callback) { | |
iterator(x.value, function (err, v) { | |
results[x.index] = v; | |
callback(err); | |
}); | |
}, function (err) { | |
callback(err, results); | |
}); | |
}; | |
async.map = doParallel(_asyncMap); | |
async.mapSeries = doSeries(_asyncMap); | |
async.mapLimit = function (arr, limit, iterator, callback) { | |
return _mapLimit(limit)(arr, iterator, callback); | |
}; | |
var _mapLimit = function(limit) { | |
return doParallelLimit(limit, _asyncMap); | |
}; | |
// reduce only has a series version, as doing reduce in parallel won't | |
// work in many situations. | |
async.reduce = function (arr, memo, iterator, callback) { | |
async.eachSeries(arr, function (x, callback) { | |
iterator(memo, x, function (err, v) { | |
memo = v; | |
callback(err); | |
}); | |
}, function (err) { | |
callback(err, memo); | |
}); | |
}; | |
// inject alias | |
async.inject = async.reduce; | |
// foldl alias | |
async.foldl = async.reduce; | |
async.reduceRight = function (arr, memo, iterator, callback) { | |
var reversed = _map(arr, function (x) { | |
return x; | |
}).reverse(); | |
async.reduce(reversed, memo, iterator, callback); | |
}; | |
// foldr alias | |
async.foldr = async.reduceRight; | |
var _filter = function (eachfn, arr, iterator, callback) { | |
var results = []; | |
arr = _map(arr, function (x, i) { | |
return {index: i, value: x}; | |
}); | |
eachfn(arr, function (x, callback) { | |
iterator(x.value, function (v) { | |
if (v) { | |
results.push(x); | |
} | |
callback(); | |
}); | |
}, function (err) { | |
callback(_map(results.sort(function (a, b) { | |
return a.index - b.index; | |
}), function (x) { | |
return x.value; | |
})); | |
}); | |
}; | |
async.filter = doParallel(_filter); | |
async.filterSeries = doSeries(_filter); | |
// select alias | |
async.select = async.filter; | |
async.selectSeries = async.filterSeries; | |
var _reject = function (eachfn, arr, iterator, callback) { | |
var results = []; | |
arr = _map(arr, function (x, i) { | |
return {index: i, value: x}; | |
}); | |
eachfn(arr, function (x, callback) { | |
iterator(x.value, function (v) { | |
if (!v) { | |
results.push(x); | |
} | |
callback(); | |
}); | |
}, function (err) { | |
callback(_map(results.sort(function (a, b) { | |
return a.index - b.index; | |
}), function (x) { | |
return x.value; | |
})); | |
}); | |
}; | |
async.reject = doParallel(_reject); | |
async.rejectSeries = doSeries(_reject); | |
var _detect = function (eachfn, arr, iterator, main_callback) { | |
eachfn(arr, function (x, callback) { | |
iterator(x, function (result) { | |
if (result) { | |
main_callback(x); | |
main_callback = function () {}; | |
} | |
else { | |
callback(); | |
} | |
}); | |
}, function (err) { | |
main_callback(); | |
}); | |
}; | |
async.detect = doParallel(_detect); | |
async.detectSeries = doSeries(_detect); | |
async.some = function (arr, iterator, main_callback) { | |
async.each(arr, function (x, callback) { | |
iterator(x, function (v) { | |
if (v) { | |
main_callback(true); | |
main_callback = function () {}; | |
} | |
callback(); | |
}); | |
}, function (err) { | |
main_callback(false); | |
}); | |
}; | |
// any alias | |
async.any = async.some; | |
async.every = function (arr, iterator, main_callback) { | |
async.each(arr, function (x, callback) { | |
iterator(x, function (v) { | |
if (!v) { | |
main_callback(false); | |
main_callback = function () {}; | |
} | |
callback(); | |
}); | |
}, function (err) { | |
main_callback(true); | |
}); | |
}; | |
// all alias | |
async.all = async.every; | |
async.sortBy = function (arr, iterator, callback) { | |
async.map(arr, function (x, callback) { | |
iterator(x, function (err, criteria) { | |
if (err) { | |
callback(err); | |
} | |
else { | |
callback(null, {value: x, criteria: criteria}); | |
} | |
}); | |
}, function (err, results) { | |
if (err) { | |
return callback(err); | |
} | |
else { | |
var fn = function (left, right) { | |
var a = left.criteria, b = right.criteria; | |
return a < b ? -1 : a > b ? 1 : 0; | |
}; | |
callback(null, _map(results.sort(fn), function (x) { | |
return x.value; | |
})); | |
} | |
}); | |
}; | |
async.auto = function (tasks, callback) { | |
callback = callback || function () {}; | |
var keys = _keys(tasks); | |
var remainingTasks = keys.length | |
if (!remainingTasks) { | |
return callback(); | |
} | |
var results = {}; | |
var listeners = []; | |
var addListener = function (fn) { | |
listeners.unshift(fn); | |
}; | |
var removeListener = function (fn) { | |
for (var i = 0; i < listeners.length; i += 1) { | |
if (listeners[i] === fn) { | |
listeners.splice(i, 1); | |
return; | |
} | |
} | |
}; | |
var taskComplete = function () { | |
remainingTasks-- | |
_each(listeners.slice(0), function (fn) { | |
fn(); | |
}); | |
}; | |
addListener(function () { | |
if (!remainingTasks) { | |
var theCallback = callback; | |
// prevent final callback from calling itself if it errors | |
callback = function () {}; | |
theCallback(null, results); | |
} | |
}); | |
_each(keys, function (k) { | |
var task = _isArray(tasks[k]) ? tasks[k]: [tasks[k]]; | |
var taskCallback = function (err) { | |
var args = Array.prototype.slice.call(arguments, 1); | |
if (args.length <= 1) { | |
args = args[0]; | |
} | |
if (err) { | |
var safeResults = {}; | |
_each(_keys(results), function(rkey) { | |
safeResults[rkey] = results[rkey]; | |
}); | |
safeResults[k] = args; | |
callback(err, safeResults); | |
// stop subsequent errors hitting callback multiple times | |
callback = function () {}; | |
} | |
else { | |
results[k] = args; | |
async.setImmediate(taskComplete); | |
} | |
}; | |
var requires = task.slice(0, Math.abs(task.length - 1)) || []; | |
var ready = function () { | |
return _reduce(requires, function (a, x) { | |
return (a && results.hasOwnProperty(x)); | |
}, true) && !results.hasOwnProperty(k); | |
}; | |
if (ready()) { | |
task[task.length - 1](taskCallback, results); | |
} | |
else { | |
var listener = function () { | |
if (ready()) { | |
removeListener(listener); | |
task[task.length - 1](taskCallback, results); | |
} | |
}; | |
addListener(listener); | |
} | |
}); | |
}; | |
async.retry = function(times, task, callback) { | |
var DEFAULT_TIMES = 5; | |
var attempts = []; | |
// Use defaults if times not passed | |
if (typeof times === 'function') { | |
callback = task; | |
task = times; | |
times = DEFAULT_TIMES; | |
} | |
// Make sure times is a number | |
times = parseInt(times, 10) || DEFAULT_TIMES; | |
var wrappedTask = function(wrappedCallback, wrappedResults) { | |
var retryAttempt = function(task, finalAttempt) { | |
return function(seriesCallback) { | |
task(function(err, result){ | |
seriesCallback(!err || finalAttempt, {err: err, result: result}); | |
}, wrappedResults); | |
}; | |
}; | |
while (times) { | |
attempts.push(retryAttempt(task, !(times-=1))); | |
} | |
async.series(attempts, function(done, data){ | |
data = data[data.length - 1]; | |
(wrappedCallback || callback)(data.err, data.result); | |
}); | |
} | |
// If a callback is passed, run this as a controll flow | |
return callback ? wrappedTask() : wrappedTask | |
}; | |
async.waterfall = function (tasks, callback) { | |
callback = callback || function () {}; | |
if (!_isArray(tasks)) { | |
var err = new Error('First argument to waterfall must be an array of functions'); | |
return callback(err); | |
} | |
if (!tasks.length) { | |
return callback(); | |
} | |
var wrapIterator = function (iterator) { | |
return function (err) { | |
if (err) { | |
callback.apply(null, arguments); | |
callback = function () {}; | |
} | |
else { | |
var args = Array.prototype.slice.call(arguments, 1); | |
var next = iterator.next(); | |
if (next) { | |
args.push(wrapIterator(next)); | |
} | |
else { | |
args.push(callback); | |
} | |
async.setImmediate(function () { | |
iterator.apply(null, args); | |
}); | |
} | |
}; | |
}; | |
wrapIterator(async.iterator(tasks))(); | |
}; | |
var _parallel = function(eachfn, tasks, callback) { | |
callback = callback || function () {}; | |
if (_isArray(tasks)) { | |
eachfn.map(tasks, function (fn, callback) { | |
if (fn) { | |
fn(function (err) { | |
var args = Array.prototype.slice.call(arguments, 1); | |
if (args.length <= 1) { | |
args = args[0]; | |
} | |
callback.call(null, err, args); | |
}); | |
} | |
}, callback); | |
} | |
else { | |
var results = {}; | |
eachfn.each(_keys(tasks), function (k, callback) { | |
tasks[k](function (err) { | |
var args = Array.prototype.slice.call(arguments, 1); | |
if (args.length <= 1) { | |
args = args[0]; | |
} | |
results[k] = args; | |
callback(err); | |
}); | |
}, function (err) { | |
callback(err, results); | |
}); | |
} | |
}; | |
async.parallel = function (tasks, callback) { | |
_parallel({ map: async.map, each: async.each }, tasks, callback); | |
}; | |
async.parallelLimit = function(tasks, limit, callback) { | |
_parallel({ map: _mapLimit(limit), each: _eachLimit(limit) }, tasks, callback); | |
}; | |
async.series = function (tasks, callback) { | |
callback = callback || function () {}; | |
if (_isArray(tasks)) { | |
async.mapSeries(tasks, function (fn, callback) { | |
if (fn) { | |
fn(function (err) { | |
var args = Array.prototype.slice.call(arguments, 1); | |
if (args.length <= 1) { | |
args = args[0]; | |
} | |
callback.call(null, err, args); | |
}); | |
} | |
}, callback); | |
} | |
else { | |
var results = {}; | |
async.eachSeries(_keys(tasks), function (k, callback) { | |
tasks[k](function (err) { | |
var args = Array.prototype.slice.call(arguments, 1); | |
if (args.length <= 1) { | |
args = args[0]; | |
} | |
results[k] = args; | |
callback(err); | |
}); | |
}, function (err) { | |
callback(err, results); | |
}); | |
} | |
}; | |
async.iterator = function (tasks) { | |
var makeCallback = function (index) { | |
var fn = function () { | |
if (tasks.length) { | |
tasks[index].apply(null, arguments); | |
} | |
return fn.next(); | |
}; | |
fn.next = function () { | |
return (index < tasks.length - 1) ? makeCallback(index + 1): null; | |
}; | |
return fn; | |
}; | |
return makeCallback(0); | |
}; | |
async.apply = function (fn) { | |
var args = Array.prototype.slice.call(arguments, 1); | |
return function () { | |
return fn.apply( | |
null, args.concat(Array.prototype.slice.call(arguments)) | |
); | |
}; | |
}; | |
var _concat = function (eachfn, arr, fn, callback) { | |
var r = []; | |
eachfn(arr, function (x, cb) { | |
fn(x, function (err, y) { | |
r = r.concat(y || []); | |
cb(err); | |
}); | |
}, function (err) { | |
callback(err, r); | |
}); | |
}; | |
async.concat = doParallel(_concat); | |
async.concatSeries = doSeries(_concat); | |
async.whilst = function (test, iterator, callback) { | |
if (test()) { | |
iterator(function (err) { | |
if (err) { | |
return callback(err); | |
} | |
async.whilst(test, iterator, callback); | |
}); | |
} | |
else { | |
callback(); | |
} | |
}; | |
async.doWhilst = function (iterator, test, callback) { | |
iterator(function (err) { | |
if (err) { | |
return callback(err); | |
} | |
var args = Array.prototype.slice.call(arguments, 1); | |
if (test.apply(null, args)) { | |
async.doWhilst(iterator, test, callback); | |
} | |
else { | |
callback(); | |
} | |
}); | |
}; | |
async.until = function (test, iterator, callback) { | |
if (!test()) { | |
iterator(function (err) { | |
if (err) { | |
return callback(err); | |
} | |
async.until(test, iterator, callback); | |
}); | |
} | |
else { | |
callback(); | |
} | |
}; | |
async.doUntil = function (iterator, test, callback) { | |
iterator(function (err) { | |
if (err) { | |
return callback(err); | |
} | |
var args = Array.prototype.slice.call(arguments, 1); | |
if (!test.apply(null, args)) { | |
async.doUntil(iterator, test, callback); | |
} | |
else { | |
callback(); | |
} | |
}); | |
}; | |
async.queue = function (worker, concurrency) { | |
if (concurrency === undefined) { | |
concurrency = 1; | |
} | |
function _insert(q, data, pos, callback) { | |
if (!q.started){ | |
q.started = true; | |
} | |
if (!_isArray(data)) { | |
data = [data]; | |
} | |
if(data.length == 0) { | |
// call drain immediately if there are no tasks | |
return async.setImmediate(function() { | |
if (q.drain) { | |
q.drain(); | |
} | |
}); | |
} | |
_each(data, function(task) { | |
var item = { | |
data: task, | |
callback: typeof callback === 'function' ? callback : null | |
}; | |
if (pos) { | |
q.tasks.unshift(item); | |
} else { | |
q.tasks.push(item); | |
} | |
if (q.saturated && q.tasks.length === q.concurrency) { | |
q.saturated(); | |
} | |
async.setImmediate(q.process); | |
}); | |
} | |
var workers = 0; | |
var q = { | |
tasks: [], | |
concurrency: concurrency, | |
saturated: null, | |
empty: null, | |
drain: null, | |
started: false, | |
paused: false, | |
push: function (data, callback) { | |
_insert(q, data, false, callback); | |
}, | |
kill: function () { | |
q.drain = null; | |
q.tasks = []; | |
}, | |
unshift: function (data, callback) { | |
_insert(q, data, true, callback); | |
}, | |
process: function () { | |
if (!q.paused && workers < q.concurrency && q.tasks.length) { | |
var task = q.tasks.shift(); | |
if (q.empty && q.tasks.length === 0) { | |
q.empty(); | |
} | |
workers += 1; | |
var next = function () { | |
workers -= 1; | |
if (task.callback) { | |
task.callback.apply(task, arguments); | |
} | |
if (q.drain && q.tasks.length + workers === 0) { | |
q.drain(); | |
} | |
q.process(); | |
}; | |
var cb = only_once(next); | |
worker(task.data, cb); | |
} | |
}, | |
length: function () { | |
return q.tasks.length; | |
}, | |
running: function () { | |
return workers; | |
}, | |
idle: function() { | |
return q.tasks.length + workers === 0; | |
}, | |
pause: function () { | |
if (q.paused === true) { return; } | |
q.paused = true; | |
q.process(); | |
}, | |
resume: function () { | |
if (q.paused === false) { return; } | |
q.paused = false; | |
q.process(); | |
} | |
}; | |
return q; | |
}; | |
async.cargo = function (worker, payload) { | |
var working = false, | |
tasks = []; | |
var cargo = { | |
tasks: tasks, | |
payload: payload, | |
saturated: null, | |
empty: null, | |
drain: null, | |
drained: true, | |
push: function (data, callback) { | |
if (!_isArray(data)) { | |
data = [data]; | |
} | |
_each(data, function(task) { | |
tasks.push({ | |
data: task, | |
callback: typeof callback === 'function' ? callback : null | |
}); | |
cargo.drained = false; | |
if (cargo.saturated && tasks.length === payload) { | |
cargo.saturated(); | |
} | |
}); | |
async.setImmediate(cargo.process); | |
}, | |
process: function process() { | |
if (working) return; | |
if (tasks.length === 0) { | |
if(cargo.drain && !cargo.drained) cargo.drain(); | |
cargo.drained = true; | |
return; | |
} | |
var ts = typeof payload === 'number' | |
? tasks.splice(0, payload) | |
: tasks.splice(0, tasks.length); | |
var ds = _map(ts, function (task) { | |
return task.data; | |
}); | |
if(cargo.empty) cargo.empty(); | |
working = true; | |
worker(ds, function () { | |
working = false; | |
var args = arguments; | |
_each(ts, function (data) { | |
if (data.callback) { | |
data.callback.apply(null, args); | |
} | |
}); | |
process(); | |
}); | |
}, | |
length: function () { | |
return tasks.length; | |
}, | |
running: function () { | |
return working; | |
} | |
}; | |
return cargo; | |
}; | |
var _console_fn = function (name) { | |
return function (fn) { | |
var args = Array.prototype.slice.call(arguments, 1); | |
fn.apply(null, args.concat([function (err) { | |
var args = Array.prototype.slice.call(arguments, 1); | |
if (typeof console !== 'undefined') { | |
if (err) { | |
if (console.error) { | |
console.error(err); | |
} | |
} | |
else if (console[name]) { | |
_each(args, function (x) { | |
console[name](x); | |
}); | |
} | |
} | |
}])); | |
}; | |
}; | |
async.log = _console_fn('log'); | |
async.dir = _console_fn('dir'); | |
/*async.info = _console_fn('info'); | |
async.warn = _console_fn('warn'); | |
async.error = _console_fn('error');*/ | |
async.memoize = function (fn, hasher) { | |
var memo = {}; | |
var queues = {}; | |
hasher = hasher || function (x) { | |
return x; | |
}; | |
var memoized = function () { | |
var args = Array.prototype.slice.call(arguments); | |
var callback = args.pop(); | |
var key = hasher.apply(null, args); | |
if (key in memo) { | |
async.nextTick(function () { | |
callback.apply(null, memo[key]); | |
}); | |
} | |
else if (key in queues) { | |
queues[key].push(callback); | |
} | |
else { | |
queues[key] = [callback]; | |
fn.apply(null, args.concat([function () { | |
memo[key] = arguments; | |
var q = queues[key]; | |
delete queues[key]; | |
for (var i = 0, l = q.length; i < l; i++) { | |
q[i].apply(null, arguments); | |
} | |
}])); | |
} | |
}; | |
memoized.memo = memo; | |
memoized.unmemoized = fn; | |
return memoized; | |
}; | |
async.unmemoize = function (fn) { | |
return function () { | |
return (fn.unmemoized || fn).apply(null, arguments); | |
}; | |
}; | |
async.times = function (count, iterator, callback) { | |
var counter = []; | |
for (var i = 0; i < count; i++) { | |
counter.push(i); | |
} | |
return async.map(counter, iterator, callback); | |
}; | |
async.timesSeries = function (count, iterator, callback) { | |
var counter = []; | |
for (var i = 0; i < count; i++) { | |
counter.push(i); | |
} | |
return async.mapSeries(counter, iterator, callback); | |
}; | |
async.seq = function (/* functions... */) { | |
var fns = arguments; | |
return function () { | |
var that = this; | |
var args = Array.prototype.slice.call(arguments); | |
var callback = args.pop(); | |
async.reduce(fns, args, function (newargs, fn, cb) { | |
fn.apply(that, newargs.concat([function () { | |
var err = arguments[0]; | |
var nextargs = Array.prototype.slice.call(arguments, 1); | |
cb(err, nextargs); | |
}])) | |
}, | |
function (err, results) { | |
callback.apply(that, [err].concat(results)); | |
}); | |
}; | |
}; | |
async.compose = function (/* functions... */) { | |
return async.seq.apply(null, Array.prototype.reverse.call(arguments)); | |
}; | |
var _applyEach = function (eachfn, fns /*args...*/) { | |
var go = function () { | |
var that = this; | |
var args = Array.prototype.slice.call(arguments); | |
var callback = args.pop(); | |
return eachfn(fns, function (fn, cb) { | |
fn.apply(that, args.concat([cb])); | |
}, | |
callback); | |
}; | |
if (arguments.length > 2) { | |
var args = Array.prototype.slice.call(arguments, 2); | |
return go.apply(this, args); | |
} | |
else { | |
return go; | |
} | |
}; | |
async.applyEach = doParallel(_applyEach); | |
async.applyEachSeries = doSeries(_applyEach); | |
async.forever = function (fn, callback) { | |
function next(err) { | |
if (err) { | |
if (callback) { | |
return callback(err); | |
} | |
throw err; | |
} | |
fn(next); | |
} | |
next(); | |
}; | |
// Node.js | |
if (typeof module !== 'undefined' && module.exports) { | |
module.exports = async; | |
} | |
// AMD / RequireJS | |
else if (typeof define !== 'undefined' && define.amd) { | |
define([], function () { | |
return async; | |
}); | |
} | |
// included directly via <script> tag | |
else { | |
root.async = async; | |
} | |
}()); | |
}).call(this,_dereq_("/Users/lance/Projects/stanza.io/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js")) | |
},{"/Users/lance/Projects/stanza.io/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js":140}],90:[function(_dereq_,module,exports){ | |
(function (Buffer){ | |
(function () { | |
"use strict"; | |
function atob(str) { | |
return new Buffer(str, 'base64').toString('binary'); | |
} | |
module.exports = atob; | |
}()); | |
}).call(this,_dereq_("buffer").Buffer) | |
},{"buffer":130}],91:[function(_dereq_,module,exports){ | |
/** | |
* 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. | |
* | |
*/ | |
"use strict"; | |
module.exports = function(Promise, Promise$_CreatePromiseArray, PromiseArray) { | |
var SomePromiseArray = _dereq_("./some_promise_array.js")(PromiseArray); | |
function Promise$_Any(promises, useBound) { | |
var ret = Promise$_CreatePromiseArray( | |
promises, | |
SomePromiseArray, | |
useBound === true && promises._isBound() | |
? promises._boundTo | |
: void 0 | |
); | |
var promise = ret.promise(); | |
if (promise.isRejected()) { | |
return promise; | |
} | |
ret.setHowMany(1); | |
ret.setUnwrap(); | |
ret.init(); | |
return promise; | |
} | |
Promise.any = function Promise$Any(promises) { | |
return Promise$_Any(promises, false); | |
}; | |
Promise.prototype.any = function Promise$any() { | |
return Promise$_Any(this, true); | |
}; | |
}; | |
},{"./some_promise_array.js":123}],92:[function(_dereq_,module,exports){ | |
/** | |
* 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. | |
* | |
*/ | |
"use strict"; | |
var schedule = _dereq_("./schedule.js"); | |
var Queue = _dereq_("./queue.js"); | |
var errorObj = _dereq_("./util.js").errorObj; | |
var tryCatch1 = _dereq_("./util.js").tryCatch1; | |
var process = _dereq_("./global.js").process; | |
function Async() { | |
this._isTickUsed = false; | |
this._length = 0; | |
this._lateBuffer = new Queue(); | |
this._functionBuffer = new Queue(25000 * 3); | |
var self = this; | |
this.consumeFunctionBuffer = function Async$consumeFunctionBuffer() { | |
self._consumeFunctionBuffer(); | |
}; | |
} | |
Async.prototype.haveItemsQueued = function Async$haveItemsQueued() { | |
return this._length > 0; | |
}; | |
Async.prototype.invokeLater = function Async$invokeLater(fn, receiver, arg) { | |
if (process !== void 0 && | |
process.domain != null && | |
!fn.domain) { | |
fn = process.domain.bind(fn); | |
} | |
this._lateBuffer.push(fn, receiver, arg); | |
this._queueTick(); | |
}; | |
Async.prototype.invoke = function Async$invoke(fn, receiver, arg) { | |
if (process !== void 0 && | |
process.domain != null && | |
!fn.domain) { | |
fn = process.domain.bind(fn); | |
} | |
var functionBuffer = this._functionBuffer; | |
functionBuffer.push(fn, receiver, arg); | |
this._length = functionBuffer.length(); | |
this._queueTick(); | |
}; | |
Async.prototype._consumeFunctionBuffer = | |
function Async$_consumeFunctionBuffer() { | |
var functionBuffer = this._functionBuffer; | |
while(functionBuffer.length() > 0) { | |
var fn = functionBuffer.shift(); | |
var receiver = functionBuffer.shift(); | |
var arg = functionBuffer.shift(); | |
fn.call(receiver, arg); | |
} | |
this._reset(); | |
this._consumeLateBuffer(); | |
}; | |
Async.prototype._consumeLateBuffer = function Async$_consumeLateBuffer() { | |
var buffer = this._lateBuffer; | |
while(buffer.length() > 0) { | |
var fn = buffer.shift(); | |
var receiver = buffer.shift(); | |
var arg = buffer.shift(); | |
var res = tryCatch1(fn, receiver, arg); | |
if (res === errorObj) { | |
this._queueTick(); | |
if (fn.domain != null) { | |
fn.domain.emit("error", res.e); | |
} | |
else { | |
throw res.e; | |
} | |
} | |
} | |
}; | |
Async.prototype._queueTick = function Async$_queue() { | |
if (!this._isTickUsed) { | |
schedule(this.consumeFunctionBuffer); | |
this._isTickUsed = true; | |
} | |
}; | |
Async.prototype._reset = function Async$_reset() { | |
this._isTickUsed = false; | |
this._length = 0; | |
}; | |
module.exports = new Async(); | |
},{"./global.js":105,"./queue.js":116,"./schedule.js":119,"./util.js":127}],93:[function(_dereq_,module,exports){ | |
/** | |
* 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. | |
* | |
*/ | |
"use strict"; | |
var Promise = _dereq_("./promise.js")(); | |
module.exports = Promise; | |
},{"./promise.js":109}],94:[function(_dereq_,module,exports){ | |
/** | |
* 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. | |
* | |
*/ | |
"use strict"; | |
module.exports = function(Promise) { | |
Promise.prototype.call = function Promise$call(propertyName) { | |
var $_len = arguments.length;var args = new Array($_len - 1); for(var $_i = 1; $_i < $_len; ++$_i) {args[$_i - 1] = arguments[$_i];} | |
return this._then(function(obj) { | |
return obj[propertyName].apply(obj, args); | |
}, | |
void 0, | |
void 0, | |
void 0, | |
void 0 | |
); | |
}; | |
function Promise$getter(obj) { | |
var prop = typeof this === "string" | |
? this | |
: ("" + this); | |
return obj[prop]; | |
} | |
Promise.prototype.get = function Promise$get(propertyName) { | |
return this._then( | |
Promise$getter, | |
void 0, | |
void 0, | |
propertyName, | |
void 0 | |
); | |
}; | |
}; | |
},{}],95:[function(_dereq_,module,exports){ | |
/** | |
* 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. | |
* | |
*/ | |
"use strict"; | |
module.exports = function(Promise, INTERNAL) { | |
var errors = _dereq_("./errors.js"); | |
var async = _dereq_("./async.js"); | |
var CancellationError = errors.CancellationError; | |
Promise.prototype._cancel = function Promise$_cancel() { | |
if (!this.isCancellable()) return this; | |
var parent; | |
var promiseToReject = this; | |
while ((parent = promiseToReject._cancellationParent) !== void 0 && | |
parent.isCancellable()) { | |
promiseToReject = parent; | |
} | |
var err = new CancellationError(); | |
promiseToReject._attachExtraTrace(err); | |
promiseToReject._rejectUnchecked(err); | |
}; | |
Promise.prototype.cancel = function Promise$cancel() { | |
if (!this.isCancellable()) return this; | |
async.invokeLater(this._cancel, this, void 0); | |
return this; | |
}; | |
Promise.prototype.cancellable = function Promise$cancellable() { | |
if (this._cancellable()) return this; | |
this._setCancellable(); | |
this._cancellationParent = void 0; | |
return this; | |
}; | |
Promise.prototype.uncancellable = function Promise$uncancellable() { | |
var ret = new Promise(INTERNAL); | |
ret._setTrace(this); | |
ret._follow(this); | |
ret._unsetCancellable(); | |
if (this._isBound()) ret._setBoundTo(this._boundTo); | |
return ret; | |
}; | |
Promise.prototype.fork = | |
function Promise$fork(didFulfill, didReject, didProgress) { | |
var ret = this._then(didFulfill, didReject, didProgress, | |
void 0, void 0); | |
ret._setCancellable(); | |
ret._cancellationParent = void 0; | |
return ret; | |
}; | |
}; | |
},{"./async.js":92,"./errors.js":99}],96:[function(_dereq_,module,exports){ | |
/** | |
* 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. | |
* | |
*/ | |
"use strict"; | |
module.exports = function() { | |
var inherits = _dereq_("./util.js").inherits; | |
var defineProperty = _dereq_("./es5.js").defineProperty; | |
var rignore = new RegExp( | |
"\\b(?:[a-zA-Z0-9.]+\\$_\\w+|" + | |
"tryCatch(?:1|2|Apply)|new \\w*PromiseArray|" + | |
"\\w*PromiseArray\\.\\w*PromiseArray|" + | |
"setTimeout|CatchFilter\\$_\\w+|makeNodePromisified|processImmediate|" + | |
"process._tickCallback|nextTick|Async\\$\\w+)\\b" | |
); | |
var rtraceline = null; | |
var formatStack = null; | |
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) + "..."; | |
} | |
function CapturedTrace(ignoreUntil, isTopLevel) { | |
this.captureStackTrace(CapturedTrace, isTopLevel); | |
} | |
inherits(CapturedTrace, Error); | |
CapturedTrace.prototype.captureStackTrace = | |
function CapturedTrace$captureStackTrace(ignoreUntil, isTopLevel) { | |
captureStackTrace(this, ignoreUntil, isTopLevel); | |
}; | |
CapturedTrace.possiblyUnhandledRejection = | |
function CapturedTrace$PossiblyUnhandledRejection(reason) { | |
if (typeof console === "object") { | |
var message; | |
if (typeof reason === "object" || typeof reason === "function") { | |
var stack = reason.stack; | |
message = "Possibly unhandled " + formatStack(stack, reason); | |
} | |
else { | |
message = "Possibly unhandled " + String(reason); | |
} | |
if (typeof console.error === "function" || | |
typeof console.error === "object") { | |
console.error(message); | |
} | |
else if (typeof console.log === "function" || | |
typeof console.log === "object") { | |
console.log(message); | |
} | |
} | |
}; | |
CapturedTrace.combine = function CapturedTrace$Combine(current, prev) { | |
var curLast = current.length - 1; | |
for (var i = prev.length - 1; i >= 0; --i) { | |
var line = prev[i]; | |
if (current[curLast] === line) { | |
current.pop(); | |
curLast--; | |
} | |
else { | |
break; | |
} | |
} | |
current.push("From previous event:"); | |
var lines = current.concat(prev); | |
var ret = []; | |
for (var i = 0, len = lines.length; i < len; ++i) { | |
if ((rignore.test(lines[i]) || | |
(i > 0 && !rtraceline.test(lines[i])) && | |
lines[i] !== "From previous event:") | |
) { | |
continue; | |
} | |
ret.push(lines[i]); | |
} | |
return ret; | |
}; | |
CapturedTrace.isSupported = function CapturedTrace$IsSupported() { | |
return typeof captureStackTrace === "function"; | |
}; | |
var captureStackTrace = (function stackDetection() { | |
if (typeof Error.stackTraceLimit === "number" && | |
typeof Error.captureStackTrace === "function") { | |
rtraceline = /^\s*at\s*/; | |
formatStack = function(stack, error) { | |
if (typeof stack === "string") return stack; | |
if (error.name !== void 0 && | |
error.message !== void 0) { | |
return error.name + ". " + error.message; | |
} | |
return formatNonError(error); | |
}; | |
var captureStackTrace = Error.captureStackTrace; | |
return function CapturedTrace$_captureStackTrace( | |
receiver, ignoreUntil) { | |
captureStackTrace(receiver, ignoreUntil); | |
}; | |
} | |
var err = new Error(); | |
if (typeof err.stack === "string" && | |
typeof "".startsWith === "function" && | |
(err.stack.startsWith("stackDetection@")) && | |
stackDetection.name === "stackDetection") { | |
defineProperty(Error, "stackTraceLimit", { | |
writable: true, | |
enumerable: false, | |
configurable: false, | |
value: 25 | |
}); | |
rtraceline = /@/; | |
var rline = /[@\n]/; | |
formatStack = function(stack, error) { | |
if (typeof stack === "string") { | |
return (error.name + ". " + error.message + "\n" + stack); | |
} | |
if (error.name !== void 0 && | |
error.message !== void 0) { | |
return error.name + ". " + error.message; | |
} | |
return formatNonError(error); | |
}; | |
return function captureStackTrace(o) { | |
var stack = new Error().stack; | |
var split = stack.split(rline); | |
var len = split.length; | |
var ret = ""; | |
for (var i = 0; i < len; i += 2) { | |
ret += split[i]; | |
ret += "@"; | |
ret += split[i + 1]; | |
ret += "\n"; | |
} | |
o.stack = ret; | |
}; | |
} | |
else { | |
formatStack = function(stack, error) { | |
if (typeof stack === "string") return stack; | |
if ((typeof error === "object" || | |
typeof error === "function") && | |
error.name !== void 0 && | |
error.message !== void 0) { | |
return error.name + ". " + error.message; | |
} | |
return formatNonError(error); | |
}; | |
return null; | |
} | |
})(); | |
return CapturedTrace; | |
}; | |
},{"./es5.js":101,"./util.js":127}],97:[function(_dereq_,module,exports){ | |
/** | |
* 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. | |
* | |
*/ | |
"use strict"; | |
module.exports = function(NEXT_FILTER) { | |
var util = _dereq_("./util.js"); | |
var errors = _dereq_("./errors.js"); | |
var tryCatch1 = util.tryCatch1; | |
var errorObj = util.errorObj; | |
var keys = _dereq_("./es5.js").keys; | |
var TypeError = errors.TypeError; | |
function CatchFilter(instances, callback, promise) { | |
this._instances = instances; | |
this._callback = callback; | |
this._promise = promise; | |
} | |
function CatchFilter$_safePredicate(predicate, e) { | |
var safeObject = {}; | |
var retfilter = tryCatch1(predicate, safeObject, e); | |
if (retfilter === errorObj) return retfilter; | |
var safeKeys = keys(safeObject); | |
if (safeKeys.length) { | |
errorObj.e = new TypeError( | |
"Catch filter must inherit from Error " | |
+ "or be a simple predicate function"); | |
return errorObj; | |
} | |
return retfilter; | |
} | |
CatchFilter.prototype.doFilter = function CatchFilter$_doFilter(e) { | |
var cb = this._callback; | |
var promise = this._promise; | |
var boundTo = promise._isBound() ? promise._boundTo : void 0; | |
for (var i = 0, len = this._instances.length; i < len; ++i) { | |
var item = this._instances[i]; | |
var itemIsErrorType = item === Error || | |
(item != null && item.prototype instanceof Error); | |
if (itemIsErrorType && e instanceof item) { | |
var ret = tryCatch1(cb, boundTo, e); | |
if (ret === errorObj) { | |
NEXT_FILTER.e = ret.e; | |
return NEXT_FILTER; | |
} | |
return ret; | |
} else if (typeof item === "function" && !itemIsErrorType) { | |
var shouldHandle = CatchFilter$_safePredicate(item, e); | |
if (shouldHandle === errorObj) { | |
var trace = errors.canAttach(errorObj.e) | |
? errorObj.e | |
: new Error(errorObj.e + ""); | |
this._promise._attachExtraTrace(trace); | |
e = errorObj.e; | |
break; | |
} else if (shouldHandle) { | |
var ret = tryCatch1(cb, boundTo, e); | |
if (ret === errorObj) { | |
NEXT_FILTER.e = ret.e; | |
return NEXT_FILTER; | |
} | |
return ret; | |
} | |
} | |
} | |
NEXT_FILTER.e = e; | |
return NEXT_FILTER; | |
}; | |
return CatchFilter; | |
}; | |
},{"./errors.js":99,"./es5.js":101,"./util.js":127}],98:[function(_dereq_,module,exports){ | |
/** | |
* 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. | |
* | |
*/ | |
"use strict"; | |
var util = _dereq_("./util.js"); | |
var isPrimitive = util.isPrimitive; | |
var wrapsPrimitiveReceiver = util.wrapsPrimitiveReceiver; | |
module.exports = function(Promise) { | |
var returner = function Promise$_returner() { | |
return this; | |
}; | |
var thrower = function Promise$_thrower() { | |
throw this; | |
}; | |
var wrapper = function Promise$_wrapper(value, action) { | |
if (action === 1) { | |
return function Promise$_thrower() { | |
throw value; | |
}; | |
} | |
else if (action === 2) { | |
return function Promise$_returner() { | |
return value; | |
}; | |
} | |
}; | |
Promise.prototype["return"] = | |
Promise.prototype.thenReturn = | |
function Promise$thenReturn(value) { | |
if (wrapsPrimitiveReceiver && isPrimitive(value)) { | |
return this._then( | |
wrapper(value, 2), | |
void 0, | |
void 0, | |
void 0, | |
void 0 | |
); | |
} | |
return this._then(returner, void 0, void 0, value, void 0); | |
}; | |
Promise.prototype["throw"] = | |
Promise.prototype.thenThrow = | |
function Promise$thenThrow(reason) { | |
if (wrapsPrimitiveReceiver && isPrimitive(reason)) { | |
return this._then( | |
wrapper(reason, 1), | |
void 0, | |
void 0, | |
void 0, | |
void 0 | |
); | |
} | |
return this._then(thrower, void 0, void 0, reason, void 0); | |
}; | |
}; | |
},{"./util.js":127}],99:[function(_dereq_,module,exports){ | |
/** | |
* 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. | |
* | |
*/ | |
"use strict"; | |
var global = _dereq_("./global.js"); | |
var Objectfreeze = _dereq_("./es5.js").freeze; | |
var util = _dereq_("./util.js"); | |
var inherits = util.inherits; | |
var notEnumerableProp = util.notEnumerableProp; | |
var Error = global.Error; | |
function markAsOriginatingFromRejection(e) { | |
try { | |
notEnumerableProp(e, "isAsync", true); | |
} | |
catch(ignore) {} | |
} | |
function originatesFromRejection(e) { | |
if (e == null) return false; | |
return ((e instanceof RejectionError) || | |
e["isAsync"] === true); | |
} | |
function isError(obj) { | |
return obj instanceof Error; | |
} | |
function canAttach(obj) { | |
return isError(obj); | |
} | |
function subError(nameProperty, defaultMessage) { | |
function SubError(message) { | |
if (!(this instanceof SubError)) return new SubError(message); | |
this.message = typeof message === "string" ? message : defaultMessage; | |
this.name = nameProperty; | |
if (Error.captureStackTrace) { | |
Error.captureStackTrace(this, this.constructor); | |
} | |
} | |
inherits(SubError, Error); | |
return SubError; | |
} | |
var TypeError = global.TypeError; | |
if (typeof TypeError !== "function") { | |
TypeError = subError("TypeError", "type error"); | |
} | |
var RangeError = global.RangeError; | |
if (typeof RangeError !== "function") { | |
RangeError = subError("RangeError", "range error"); | |
} | |
var CancellationError = subError("CancellationError", "cancellation error"); | |
var TimeoutError = subError("TimeoutError", "timeout error"); | |
function RejectionError(message) { | |
this.name = "RejectionError"; | |
this.message = message; | |
this.cause = message; | |
this.isAsync = true; | |
if (message instanceof Error) { | |
this.message = message.message; | |
this.stack = message.stack; | |
} | |
else if (Error.captureStackTrace) { | |
Error.captureStackTrace(this, this.constructor); | |
} | |
} | |
inherits(RejectionError, Error); | |
var key = "__BluebirdErrorTypes__"; | |
var errorTypes = global[key]; | |
if (!errorTypes) { | |
errorTypes = Objectfreeze({ | |
CancellationError: CancellationError, | |
TimeoutError: TimeoutError, | |
RejectionError: RejectionError | |
}); | |
notEnumerableProp(global, key, errorTypes); | |
} | |
module.exports = { | |
Error: Error, | |
TypeError: TypeError, | |
RangeError: RangeError, | |
CancellationError: errorTypes.CancellationError, | |
RejectionError: errorTypes.RejectionError, | |
TimeoutError: errorTypes.TimeoutError, | |
originatesFromRejection: originatesFromRejection, | |
markAsOriginatingFromRejection: markAsOriginatingFromRejection, | |
canAttach: canAttach | |
}; | |
},{"./es5.js":101,"./global.js":105,"./util.js":127}],100:[function(_dereq_,module,exports){ | |
/** | |
* 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. | |
* | |
*/ | |
"use strict"; | |
module.exports = function(Promise) { | |
var TypeError = _dereq_('./errors.js').TypeError; | |
function apiRejection(msg) { | |
var error = new TypeError(msg); | |
var ret = Promise.rejected(error); | |
var parent = ret._peekContext(); | |
if (parent != null) { | |
parent._attachExtraTrace(error); | |
} | |
return ret; | |
} | |
return apiRejection; | |
}; | |
},{"./errors.js":99}],101:[function(_dereq_,module,exports){ | |
/** | |
* 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. | |
* | |
*/ | |
var isES5 = (function(){ | |
"use strict"; | |
return this === void 0; | |
})(); | |
if (isES5) { | |
module.exports = { | |
freeze: Object.freeze, | |
defineProperty: Object.defineProperty, | |
keys: Object.keys, | |
getPrototypeOf: Object.getPrototypeOf, | |
isArray: Array.isArray, | |
isES5: isES5 | |
}; | |
} | |
else { | |
var has = {}.hasOwnProperty; | |
var str = {}.toString; | |
var proto = {}.constructor.prototype; | |
function ObjectKeys(o) { | |
var ret = []; | |
for (var key in o) { | |
if (has.call(o, key)) { | |
ret.push(key); | |
} | |
} | |
return ret; | |
} | |
function ObjectDefineProperty(o, key, desc) { | |
o[key] = desc.value; | |
return o; | |
} | |
function ObjectFreeze(obj) { | |
return obj; | |
} | |
function ObjectGetPrototypeOf(obj) { | |
try { | |
return Object(obj).constructor.prototype; | |
} | |
catch (e) { | |
return proto; | |
} | |
} | |
function ArrayIsArray(obj) { | |
try { | |
return str.call(obj) === "[object Array]"; | |
} | |
catch(e) { | |
return false; | |
} | |
} | |
module.exports = { | |
isArray: ArrayIsArray, | |
keys: ObjectKeys, | |
defineProperty: ObjectDefineProperty, | |
freeze: ObjectFreeze, | |
getPrototypeOf: ObjectGetPrototypeOf, | |
isES5: isES5 | |
}; | |
} | |
},{}],102:[function(_dereq_,module,exports){ | |
/** | |
* 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. | |
* | |
*/ | |
"use strict"; | |
module.exports = function(Promise) { | |
var isArray = _dereq_("./util.js").isArray; | |
function Promise$_filter(booleans) { | |
var values = this instanceof Promise ? this._settledValue : this; | |
var len = values.length; | |
var ret = new Array(len); | |
var j = 0; | |
for (var i = 0; i < len; ++i) { | |
if (booleans[i]) ret[j++] = values[i]; | |
} | |
ret.length = j; | |
return ret; | |
} | |
var ref = {ref: null}; | |
Promise.filter = function Promise$Filter(promises, fn) { | |
return Promise.map(promises, fn, ref) | |
._then(Promise$_filter, void 0, void 0, ref.ref, void 0); | |
}; | |
Promise.prototype.filter = function Promise$filter(fn) { | |
return this.map(fn, ref) | |
._then(Promise$_filter, void 0, void 0, ref.ref, void 0); | |
}; | |
}; | |
},{"./util.js":127}],103:[function(_dereq_,module,exports){ | |
/** | |
* 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. | |
* | |
*/ | |
"use strict"; | |
module.exports = function(Promise, NEXT_FILTER) { | |
var util = _dereq_("./util.js"); | |
var wrapsPrimitiveReceiver = util.wrapsPrimitiveReceiver; | |
var isPrimitive = util.isPrimitive; | |
var thrower = util.thrower; | |
function returnThis() { | |
return this; | |
} | |
function throwThis() { | |
throw this; | |
} | |
function return$(r) { | |
return function Promise$_returner() { | |
return r; | |
}; | |
} | |
function throw$(r) { | |
return function Promise$_thrower() { | |
throw r; | |
}; | |
} | |
function promisedFinally(ret, reasonOrValue, isFulfilled) { | |
var then; | |
if (wrapsPrimitiveReceiver && isPrimitive(reasonOrValue)) { | |
then = isFulfilled ? return$(reasonOrValue) : throw$(reasonOrValue); | |
} | |
else { | |
then = isFulfilled ? returnThis : throwThis; | |
} | |
return ret._then(then, thrower, void 0, reasonOrValue, void 0); | |
} | |
function finallyHandler(reasonOrValue) { | |
var promise = this.promise; | |
var handler = this.handler; | |
var ret = promise._isBound() | |
? handler.call(promise._boundTo) | |
: handler(); | |
if (ret !== void 0) { | |
var maybePromise = Promise._cast(ret, void 0); | |
if (maybePromise instanceof Promise) { | |
return promisedFinally(maybePromise, reasonOrValue, | |
promise.isFulfilled()); | |
} | |
} | |
if (promise.isRejected()) { | |
NEXT_FILTER.e = reasonOrValue; | |
return NEXT_FILTER; | |
} | |
else { | |
return reasonOrValue; | |
} | |
} | |
function tapHandler(value) { | |
var promise = this.promise; | |
var handler = this.handler; | |
var ret = promise._isBound() | |
? handler.call(promise._boundTo, value) | |
: handler(value); | |
if (ret !== void 0) { | |
var maybePromise = Promise._cast(ret, void 0); | |
if (maybePromise instanceof Promise) { | |
return promisedFinally(maybePromise, value, true); | |
} | |
} | |
return value; | |
} | |
Promise.prototype._passThroughHandler = | |
function Promise$_passThroughHandler(handler, isFinally) { | |
if (typeof handler !== "function") return this.then(); | |
var promiseAndHandler = { | |
promise: this, | |
handler: handler | |
}; | |
return this._then( | |
isFinally ? finallyHandler : tapHandler, | |
isFinally ? finallyHandler : void 0, void 0, | |
promiseAndHandler, void 0); | |
}; | |
Promise.prototype.lastly = | |
Promise.prototype["finally"] = function Promise$finally(handler) { | |
return this._passThroughHandler(handler, true); | |
}; | |
Promise.prototype.tap = function Promise$tap(handler) { | |
return this._passThroughHandler(handler, false); | |
}; | |
}; | |
},{"./util.js":127}],104:[function(_dereq_,module,exports){ | |
/** | |
* 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. | |
* | |
*/ | |
"use strict"; | |
module.exports = function(Promise, apiRejection, INTERNAL) { | |
var PromiseSpawn = _dereq_("./promise_spawn.js")(Promise, INTERNAL); | |
var errors = _dereq_("./errors.js"); | |
var TypeError = errors.TypeError; | |
var deprecated = _dereq_("./util.js").deprecated; | |
Promise.coroutine = function Promise$Coroutine(generatorFunction) { | |
if (typeof generatorFunction !== "function") { | |
throw new TypeError("generatorFunction must be a function"); | |
} | |
var PromiseSpawn$ = PromiseSpawn; | |
return function () { | |
var generator = generatorFunction.apply(this, arguments); | |
var spawn = new PromiseSpawn$(void 0, void 0); | |
spawn._generator = generator; | |
spawn._next(void 0); | |
return spawn.promise(); | |
}; | |
}; | |
Promise.coroutine.addYieldHandler = PromiseSpawn.addYieldHandler; | |
Promise.spawn = function Promise$Spawn(generatorFunction) { | |
deprecated("Promise.spawn is deprecated. Use Promise.coroutine instead."); | |
if (typeof generatorFunction !== "function") { | |
return apiRejection("generatorFunction must be a function"); | |
} | |
var spawn = new PromiseSpawn(generatorFunction, this); | |
var ret = spawn.promise(); | |
spawn._run(Promise.spawn); | |
return ret; | |
}; | |
}; | |
},{"./errors.js":99,"./promise_spawn.js":112,"./util.js":127}],105:[function(_dereq_,module,exports){ | |
(function (global){ | |
/** | |
* 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. | |
* | |
*/ | |
module.exports = (function() { | |
if (this !== void 0) return this; | |
try {return global;} | |
catch(e) {} | |
try {return window;} | |
catch(e) {} | |
try {return self;} | |
catch(e) {} | |
})(); | |
}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) | |
},{}],106:[function(_dereq_,module,exports){ | |
/** | |
* 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. | |
* | |
*/ | |
"use strict"; | |
module.exports = function(Promise, PromiseArray, INTERNAL, apiRejection) { | |
var all = Promise.all; | |
var util = _dereq_("./util.js"); | |
var canAttach = _dereq_("./errors.js").canAttach; | |
var isArray = util.isArray; | |
var _cast = Promise._cast; | |
function unpack(values) { | |
return Promise$_Map(values, this[0], this[1], this[2]); | |
} | |
function Promise$_Map(promises, fn, useBound, ref) { | |
if (typeof fn !== "function") { | |
return apiRejection("fn must be a function"); | |
} | |
var receiver = void 0; | |
if (useBound === true) { | |
if (promises._isBound()) { | |
receiver = promises._boundTo; | |
} | |
} | |
else if (useBound !== false) { | |
receiver = useBound; | |
} | |
var shouldUnwrapItems = ref !== void 0; | |
if (shouldUnwrapItems) ref.ref = promises; | |
if (promises instanceof Promise) { | |
var pack = [fn, receiver, ref]; | |
return promises._then(unpack, void 0, void 0, pack, void 0); | |
} | |
else if (!isArray(promises)) { | |
return apiRejection("expecting an array, a promise or a thenable"); | |
} | |
var promise = new Promise(INTERNAL); | |
if (receiver !== void 0) promise._setBoundTo(receiver); | |
promise._setTrace(void 0); | |
var mapping = new Mapping(promise, | |
fn, | |
promises, | |
receiver, | |
shouldUnwrapItems); | |
mapping.init(); | |
return promise; | |
} | |
var pending = {}; | |
function Mapping(promise, callback, items, receiver, shouldUnwrapItems) { | |
this.shouldUnwrapItems = shouldUnwrapItems; | |
this.index = 0; | |
this.items = items; | |
this.callback = callback; | |
this.receiver = receiver; | |
this.promise = promise; | |
this.result = new Array(items.length); | |
} | |
util.inherits(Mapping, PromiseArray); | |
Mapping.prototype.init = function Mapping$init() { | |
var items = this.items; | |
var len = items.length; | |
var result = this.result; | |
var isRejected = false; | |
for (var i = 0; i < len; ++i) { | |
var maybePromise = _cast(items[i], void 0); | |
if (maybePromise instanceof Promise) { | |
if (maybePromise.isPending()) { | |
result[i] = pending; | |
maybePromise._proxyPromiseArray(this, i); | |
} | |
else if (maybePromise.isFulfilled()) { | |
result[i] = maybePromise.value(); | |
} | |
else { | |
maybePromise._unsetRejectionIsUnhandled(); | |
if (!isRejected) { | |
this.reject(maybePromise.reason()); | |
isRejected = true; | |
} | |
} | |
} | |
else { | |
result[i] = maybePromise; | |
} | |
} | |
if (!isRejected) this.iterate(); | |
}; | |
Mapping.prototype.isResolved = function Mapping$isResolved() { | |
return this.promise === null; | |
}; | |
Mapping.prototype._promiseProgressed = | |
function Mapping$_promiseProgressed(value) { | |
if (this.isResolved()) return; | |
this.promise._progress(value); | |
}; | |
Mapping.prototype._promiseFulfilled = | |
function Mapping$_promiseFulfilled(value, index) { | |
if (this.isResolved()) return; | |
this.result[index] = value; | |
if (this.shouldUnwrapItems) this.items[index] = value; | |
if (this.index === index) this.iterate(); | |
}; | |
Mapping.prototype._promiseRejected = | |
function Mapping$_promiseRejected(reason) { | |
this.reject(reason); | |
}; | |
Mapping.prototype.reject = function Mapping$reject(reason) { | |
if (this.isResolved()) return; | |
var trace = canAttach(reason) ? reason : new Error(reason + ""); | |
this.promise._attachExtraTrace(trace); | |
this.promise._reject(reason, trace); | |
}; | |
Mapping.prototype.iterate = function Mapping$iterate() { | |
var i = this.index; | |
var items = this.items; | |
var result = this.result; | |
var len = items.length; | |
var result = this.result; | |
var receiver = this.receiver; | |
var callback = this.callback; | |
for (; i < len; ++i) { | |
var value = result[i]; | |
if (value === pending) { | |
this.index = i; | |
return; | |
} | |
try { result[i] = callback.call(receiver, value, i, len); } | |
catch (e) { return this.reject(e); } | |
} | |
this.promise._follow(all(result)); | |
this.items = this.result = this.callback = this.promise = null; | |
}; | |
Promise.prototype.map = function Promise$map(fn, ref) { | |
return Promise$_Map(this, fn, true, ref); | |
}; | |
Promise.map = function Promise$Map(promises, fn, ref) { | |
return Promise$_Map(promises, fn, false, ref); | |
}; | |
}; | |
},{"./errors.js":99,"./util.js":127}],107:[function(_dereq_,module,exports){ | |
/** | |
* 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. | |
* | |
*/ | |
"use strict"; | |
module.exports = function(Promise) { | |
var util = _dereq_("./util.js"); | |
var async = _dereq_("./async.js"); | |
var tryCatch2 = util.tryCatch2; | |
var tryCatch1 = util.tryCatch1; | |
var errorObj = util.errorObj; | |
function thrower(r) { | |
throw r; | |
} | |
function Promise$_successAdapter(val, receiver) { | |
var nodeback = this; | |
var ret = val === void 0 | |
? tryCatch1(nodeback, receiver, null) | |
: tryCatch2(nodeback, receiver, null, val); | |
if (ret === errorObj) { | |
async.invokeLater(thrower, void 0, ret.e); | |
} | |
} | |
function Promise$_errorAdapter(reason, receiver) { | |
var nodeback = this; | |
var ret = tryCatch1(nodeback, receiver, reason); | |
if (ret === errorObj) { | |
async.invokeLater(thrower, void 0, ret.e); | |
} | |
} | |
Promise.prototype.nodeify = function Promise$nodeify(nodeback) { | |
if (typeof nodeback == "function") { | |
this._then( | |
Promise$_successAdapter, | |
Promise$_errorAdapter, | |
void 0, | |
nodeback, | |
this._isBound() ? this._boundTo : null | |
); | |
} | |
return this; | |
}; | |
}; | |
},{"./async.js":92,"./util.js":127}],108:[function(_dereq_,module,exports){ | |
/** | |
* 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. | |
* | |
*/ | |
"use strict"; | |
module.exports = function(Promise, isPromiseArrayProxy) { | |
var util = _dereq_("./util.js"); | |
var async = _dereq_("./async.js"); | |
var errors = _dereq_("./errors.js"); | |
var tryCatch1 = util.tryCatch1; | |
var errorObj = util.errorObj; | |
Promise.prototype.progressed = function Promise$progressed(handler) { | |
return this._then(void 0, void 0, handler, void 0, void 0); | |
}; | |
Promise.prototype._progress = function Promise$_progress(progressValue) { | |
if (this._isFollowingOrFulfilledOrRejected()) return; | |
this._progressUnchecked(progressValue); | |
}; | |
Promise.prototype._progressHandlerAt = | |
function Promise$_progressHandlerAt(index) { | |
if (index === 0) return this._progressHandler0; | |
return this[index + 2 - 5]; | |
}; | |
Promise.prototype._doProgressWith = | |
function Promise$_doProgressWith(progression) { | |
var progressValue = progression.value; | |
var handler = progression.handler; | |
var promise = progression.promise; | |
var receiver = progression.receiver; | |
this._pushContext(); | |
var ret = tryCatch1(handler, receiver, progressValue); | |
this._popContext(); | |
if (ret === errorObj) { | |
if (ret.e != null && | |
ret.e.name !== "StopProgressPropagation") { | |
var trace = errors.canAttach(ret.e) | |
? ret.e : new Error(ret.e + ""); | |
promise._attachExtraTrace(trace); | |
promise._progress(ret.e); | |
} | |
} | |
else if (ret instanceof Promise) { | |
ret._then(promise._progress, null, null, promise, void 0); | |
} | |
else { | |
promise._progress(ret); | |
} | |
}; | |
Promise.prototype._progressUnchecked = | |
function Promise$_progressUnchecked(progressValue) { | |
if (!this.isPending()) return; | |
var len = this._length(); | |
var progress = this._progress; | |
for (var i = 0; i < len; i += 5) { | |
var handler = this._progressHandlerAt(i); | |
var promise = this._promiseAt(i); | |
if (!(promise instanceof Promise)) { | |
var receiver = this._receiverAt(i); | |
if (typeof handler === "function") { | |
handler.call(receiver, progressValue, promise); | |
} | |
else if (receiver instanceof Promise && receiver._isProxied()) { | |
receiver._progressUnchecked(progressValue); | |
} | |
else if (isPromiseArrayProxy(receiver, promise)) { | |
receiver._promiseProgressed(progressValue, promise); | |
} | |
continue; | |
} | |
if (typeof handler === "function") { | |
async.invoke(this._doProgressWith, this, { | |
handler: handler, | |
promise: promise, | |
receiver: this._receiverAt(i), | |
value: progressValue | |
}); | |
} | |
else { | |
async.invoke(progress, promise, progressValue); | |
} | |
} | |
}; | |
}; | |
},{"./async.js":92,"./errors.js":99,"./util.js":127}],109:[function(_dereq_,module,exports){ | |
(function (process){ | |
/** | |
* 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. | |
* | |
*/ | |
"use strict"; | |
module.exports = function() { | |
var global = _dereq_("./global.js"); | |
var util = _dereq_("./util.js"); | |
var async = _dereq_("./async.js"); | |
var errors = _dereq_("./errors.js"); | |
var INTERNAL = function(){}; | |
var APPLY = {}; | |
var NEXT_FILTER = {e: null}; | |
var PromiseArray = _dereq_("./promise_array.js")(Promise, INTERNAL); | |
var CapturedTrace = _dereq_("./captured_trace.js")(); | |
var CatchFilter = _dereq_("./catch_filter.js")(NEXT_FILTER); | |
var PromiseResolver = _dereq_("./promise_resolver.js"); | |
var isArray = util.isArray; | |
var errorObj = util.errorObj; | |
var tryCatch1 = util.tryCatch1; | |
var tryCatch2 = util.tryCatch2; | |
var tryCatchApply = util.tryCatchApply; | |
var RangeError = errors.RangeError; | |
var TypeError = errors.TypeError; | |
var CancellationError = errors.CancellationError; | |
var TimeoutError = errors.TimeoutError; | |
var RejectionError = errors.RejectionError; | |
var originatesFromRejection = errors.originatesFromRejection; | |
var markAsOriginatingFromRejection = errors.markAsOriginatingFromRejection; | |
var canAttach = errors.canAttach; | |
var thrower = util.thrower; | |
var apiRejection = _dereq_("./errors_api_rejection")(Promise); | |
var makeSelfResolutionError = function Promise$_makeSelfResolutionError() { | |
return new TypeError("circular promise resolution chain"); | |
}; | |
function isPromise(obj) { | |
if (obj === void 0) return false; | |
return obj instanceof Promise; | |
} | |
function isPromiseArrayProxy(receiver, promiseSlotValue) { | |
if (receiver instanceof PromiseArray) { | |
return promiseSlotValue >= 0; | |
} | |
return false; | |
} | |
function Promise(resolver) { | |
if (typeof resolver !== "function") { | |
throw new TypeError("the promise constructor requires a resolver function"); | |
} | |
if (this.constructor !== Promise) { | |
throw new TypeError("the promise constructor cannot be invoked directly"); | |
} | |
this._bitField = 0; | |
this._fulfillmentHandler0 = void 0; | |
this._rejectionHandler0 = void 0; | |
this._promise0 = void 0; | |
this._receiver0 = void 0; | |
this._settledValue = void 0; | |
this._boundTo = void 0; | |
if (resolver !== INTERNAL) this._resolveFromResolver(resolver); | |
} | |
Promise.prototype.bind = function Promise$bind(thisArg) { | |
var ret = new Promise(INTERNAL); | |
ret._setTrace(this); | |
ret._follow(this); | |
ret._setBoundTo(thisArg); | |
if (this._cancellable()) { | |
ret._setCancellable(); | |
ret._cancellationParent = this; | |
} | |
return ret; | |
}; | |
Promise.prototype.toString = function Promise$toString() { | |
return "[object Promise]"; | |
}; | |
Promise.prototype.caught = Promise.prototype["catch"] = | |
function Promise$catch(fn) { | |
var len = arguments.length; | |
if (len > 1) { | |
var catchInstances = new Array(len - 1), | |
j = 0, i; | |
for (i = 0; i < len - 1; ++i) { | |
var item = arguments[i]; | |
if (typeof item === "function") { | |
catchInstances[j++] = item; | |
} | |
else { | |
var catchFilterTypeError = | |
new TypeError( | |
"A catch filter must be an error constructor " | |
+ "or a filter function"); | |
this._attachExtraTrace(catchFilterTypeError); | |
async.invoke(this._reject, this, catchFilterTypeError); | |
return; | |
} | |
} | |
catchInstances.length = j; | |
fn = arguments[i]; | |
this._resetTrace(); | |
var catchFilter = new CatchFilter(catchInstances, fn, this); | |
return this._then(void 0, catchFilter.doFilter, void 0, | |
catchFilter, void 0); | |
} | |
return this._then(void 0, fn, void 0, void 0, void 0); | |
}; | |
Promise.prototype.then = | |
function Promise$then(didFulfill, didReject, didProgress) { | |
return this._then(didFulfill, didReject, didProgress, | |
void 0, void 0); | |
}; | |
Promise.prototype.done = | |
function Promise$done(didFulfill, didReject, didProgress) { | |
var promise = this._then(didFulfill, didReject, didProgress, | |
void 0, void 0); | |
promise._setIsFinal(); | |
}; | |
Promise.prototype.spread = function Promise$spread(didFulfill, didReject) { | |
return this._then(didFulfill, didReject, void 0, | |
APPLY, void 0); | |
}; | |
Promise.prototype.isCancellable = function Promise$isCancellable() { | |
return !this.isResolved() && | |
this._cancellable(); | |
}; | |
Promise.prototype.toJSON = function Promise$toJSON() { | |
var ret = { | |
isFulfilled: false, | |
isRejected: false, | |
fulfillmentValue: void 0, | |
rejectionReason: void 0 | |
}; | |
if (this.isFulfilled()) { | |
ret.fulfillmentValue = this._settledValue; | |
ret.isFulfilled = true; | |
} | |
else if (this.isRejected()) { | |
ret.rejectionReason = this._settledValue; | |
ret.isRejected = true; | |
} | |
return ret; | |
}; | |
Promise.prototype.all = function Promise$all() { | |
return Promise$_all(this, true); | |
}; | |
Promise.is = isPromise; | |
function Promise$_all(promises, useBound) { | |
return Promise$_CreatePromiseArray( | |
promises, | |
PromiseArray, | |
useBound === true && promises._isBound() | |
? promises._boundTo | |
: void 0 | |
).promise(); | |
} | |
Promise.all = function Promise$All(promises) { | |
return Promise$_all(promises, false); | |
}; | |
Promise.join = function Promise$Join() { | |
var $_len = arguments.length;var args = new Array($_len); for(var $_i = 0; $_i < $_len; ++$_i) {args[$_i] = arguments[$_i];} | |
return Promise$_CreatePromiseArray(args, PromiseArray, void 0).promise(); | |
}; | |
Promise.resolve = Promise.fulfilled = | |
function Promise$Resolve(value) { | |
var ret = new Promise(INTERNAL); | |
ret._setTrace(void 0); | |
if (ret._tryFollow(value)) { | |
return ret; | |
} | |
ret._cleanValues(); | |
ret._setFulfilled(); | |
ret._settledValue = value; | |
return ret; | |
}; | |
Promise.reject = Promise.rejected = function Promise$Reject(reason) { | |
var ret = new Promise(INTERNAL); | |
ret._setTrace(void 0); | |
markAsOriginatingFromRejection(reason); | |
ret._cleanValues(); | |
ret._setRejected(); | |
ret._settledValue = reason; | |
if (!canAttach(reason)) { | |
var trace = new Error(reason + ""); | |
ret._setCarriedStackTrace(trace); | |
} | |
ret._ensurePossibleRejectionHandled(); | |
return ret; | |
}; | |
Promise.prototype.error = function Promise$_error(fn) { | |
return this.caught(originatesFromRejection, fn); | |
}; | |
Promise.prototype._resolveFromSyncValue = | |
function Promise$_resolveFromSyncValue(value) { | |
if (value === errorObj) { | |
this._cleanValues(); | |
this._setRejected(); | |
this._settledValue = value.e; | |
this._ensurePossibleRejectionHandled(); | |
} | |
else { | |
var maybePromise = Promise._cast(value, void 0); | |
if (maybePromise instanceof Promise) { | |
this._follow(maybePromise); | |
} | |
else { | |
this._cleanValues(); | |
this._setFulfilled(); | |
this._settledValue = value; | |
} | |
} | |
}; | |
Promise.method = function Promise$_Method(fn) { | |
if (typeof fn !== "function") { | |
throw new TypeError("fn must be a function"); | |
} | |
return function Promise$_method() { | |
var value; | |
switch(arguments.length) { | |
case 0: value = tryCatch1(fn, this, void 0); break; | |
case 1: value = tryCatch1(fn, this, arguments[0]); break; | |
case 2: value = tryCatch2(fn, this, arguments[0], arguments[1]); break; | |
default: | |
var $_len = arguments.length;var args = new Array($_len); for(var $_i = 0; $_i < $_len; ++$_i) {args[$_i] = arguments[$_i];} | |
value = tryCatchApply(fn, args, this); break; | |
} | |
var ret = new Promise(INTERNAL); | |
ret._setTrace(void 0); | |
ret._resolveFromSyncValue(value); | |
return ret; | |
}; | |
}; | |
Promise.attempt = Promise["try"] = function Promise$_Try(fn, args, ctx) { | |
if (typeof fn !== "function") { | |
return apiRejection("fn must be a function"); | |
} | |
var value = isArray(args) | |
? tryCatchApply(fn, args, ctx) | |
: tryCatch1(fn, ctx, args); | |
var ret = new Promise(INTERNAL); | |
ret._setTrace(void 0); | |
ret._resolveFromSyncValue(value); | |
return ret; | |
}; | |
Promise.defer = Promise.pending = function Promise$Defer() { | |
var promise = new Promise(INTERNAL); | |
promise._setTrace(void 0); | |
return new PromiseResolver(promise); | |
}; | |
Promise.bind = function Promise$Bind(thisArg) { | |
var ret = new Promise(INTERNAL); | |
ret._setTrace(void 0); | |
ret._setFulfilled(); | |
ret._setBoundTo(thisArg); | |
return ret; | |
}; | |
Promise.cast = function Promise$_Cast(obj) { | |
var ret = Promise._cast(obj, void 0); | |
if (!(ret instanceof Promise)) { | |
return Promise.resolve(ret); | |
} | |
return ret; | |
}; | |
Promise.onPossiblyUnhandledRejection = | |
function Promise$OnPossiblyUnhandledRejection(fn) { | |
CapturedTrace.possiblyUnhandledRejection = typeof fn === "function" | |
? fn : void 0; | |
}; | |
var unhandledRejectionHandled; | |
Promise.onUnhandledRejectionHandled = | |
function Promise$onUnhandledRejectionHandled(fn) { | |
unhandledRejectionHandled = typeof fn === "function" ? fn : void 0; | |
}; | |
var debugging = false || !!( | |
typeof process !== "undefined" && | |
typeof process.execPath === "string" && | |
typeof process.env === "object" && | |
(process.env["BLUEBIRD_DEBUG"] || | |
process.env["NODE_ENV"] === "development") | |
); | |
Promise.longStackTraces = function Promise$LongStackTraces() { | |
if (async.haveItemsQueued() && | |
debugging === false | |
) { | |
throw new Error("cannot enable long stack traces after promises have been created"); | |
} | |
debugging = CapturedTrace.isSupported(); | |
}; | |
Promise.hasLongStackTraces = function Promise$HasLongStackTraces() { | |
return debugging && CapturedTrace.isSupported(); | |
}; | |
Promise.prototype._setProxyHandlers = | |
function Promise$_setProxyHandlers(receiver, promiseSlotValue) { | |
var index = this._length(); | |
if (index >= 524287 - 5) { | |
index = 0; | |
this._setLength(0); | |
} | |
if (index === 0) { | |
this._promise0 = promiseSlotValue; | |
this._receiver0 = receiver; | |
} | |
else { | |
var i = index - 5; | |
this[i + 3] = promiseSlotValue; | |
this[i + 4] = receiver; | |
this[i + 0] = | |
this[i + 1] = | |
this[i + 2] = void 0; | |
} | |
this._setLength(index + 5); | |
}; | |
Promise.prototype._proxyPromiseArray = | |
function Promise$_proxyPromiseArray(promiseArray, index) { | |
this._setProxyHandlers(promiseArray, index); | |
}; | |
Promise.prototype._proxyPromise = function Promise$_proxyPromise(promise) { | |
promise._setProxied(); | |
this._setProxyHandlers(promise, -1); | |
}; | |
Promise.prototype._then = | |
function Promise$_then( | |
didFulfill, | |
didReject, | |
didProgress, | |
receiver, | |
internalData | |
) { | |
var haveInternalData = internalData !== void 0; | |
var ret = haveInternalData ? internalData : new Promise(INTERNAL); | |
if (debugging && !haveInternalData) { | |
var haveSameContext = this._peekContext() === this._traceParent; | |
ret._traceParent = haveSameContext ? this._traceParent : this; | |
ret._setTrace(this); | |
} | |
if (!haveInternalData && this._isBound()) { | |
ret._setBoundTo(this._boundTo); | |
} | |
var callbackIndex = | |
this._addCallbacks(didFulfill, didReject, didProgress, ret, receiver); | |
if (!haveInternalData && this._cancellable()) { | |
ret._setCancellable(); | |
ret._cancellationParent = this; | |
} | |
if (this.isResolved()) { | |
async.invoke(this._queueSettleAt, this, callbackIndex); | |
} | |
return ret; | |
}; | |
Promise.prototype._length = function Promise$_length() { | |
return this._bitField & 524287; | |
}; | |
Promise.prototype._isFollowingOrFulfilledOrRejected = | |
function Promise$_isFollowingOrFulfilledOrRejected() { | |
return (this._bitField & 939524096) > 0; | |
}; | |
Promise.prototype._isFollowing = function Promise$_isFollowing() { | |
return (this._bitField & 536870912) === 536870912; | |
}; | |
Promise.prototype._setLength = function Promise$_setLength(len) { | |
this._bitField = (this._bitField & -524288) | | |
(len & 524287); | |
}; | |
Promise.prototype._setFulfilled = function Promise$_setFulfilled() { | |
this._bitField = this._bitField | 268435456; | |
}; | |
Promise.prototype._setRejected = function Promise$_setRejected() { | |
this._bitField = this._bitField | 134217728; | |
}; | |
Promise.prototype._setFollowing = function Promise$_setFollowing() { | |
this._bitField = this._bitField | 536870912; | |
}; | |
Promise.prototype._setIsFinal = function Promise$_setIsFinal() { | |
this._bitField = this._bitField | 33554432; | |
}; | |
Promise.prototype._isFinal = function Promise$_isFinal() { | |
return (this._bitField & 33554432) > 0; | |
}; | |
Promise.prototype._cancellable = function Promise$_cancellable() { | |
return (this._bitField & 67108864) > 0; | |
}; | |
Promise.prototype._setCancellable = function Promise$_setCancellable() { | |
this._bitField = this._bitField | 67108864; | |
}; | |
Promise.prototype._unsetCancellable = function Promise$_unsetCancellable() { | |
this._bitField = this._bitField & (~67108864); | |
}; | |
Promise.prototype._setRejectionIsUnhandled = | |
function Promise$_setRejectionIsUnhandled() { | |
this._bitField = this._bitField | 2097152; | |
}; | |
Promise.prototype._unsetRejectionIsUnhandled = | |
function Promise$_unsetRejectionIsUnhandled() { | |
this._bitField = this._bitField & (~2097152); | |
if (this._isUnhandledRejectionNotified()) { | |
this._unsetUnhandledRejectionIsNotified(); | |
this._notifyUnhandledRejectionIsHandled(); | |
} | |
}; | |
Promise.prototype._isRejectionUnhandled = | |
function Promise$_isRejectionUnhandled() { | |
return (this._bitField & 2097152) > 0; | |
}; | |
Promise.prototype._setUnhandledRejectionIsNotified = | |
function Promise$_setUnhandledRejectionIsNotified() { | |
this._bitField = this._bitField | 524288; | |
}; | |
Promise.prototype._unsetUnhandledRejectionIsNotified = | |
function Promise$_unsetUnhandledRejectionIsNotified() { | |
this._bitField = this._bitField & (~524288); | |
}; | |
Promise.prototype._isUnhandledRejectionNotified = | |
function Promise$_isUnhandledRejectionNotified() { | |
return (this._bitField & 524288) > 0; | |
}; | |
Promise.prototype._setCarriedStackTrace = | |
function Promise$_setCarriedStackTrace(capturedTrace) { | |
this._bitField = this._bitField | 1048576; | |
this._fulfillmentHandler0 = capturedTrace; | |
}; | |
Promise.prototype._unsetCarriedStackTrace = | |
function Promise$_unsetCarriedStackTrace() { | |
this._bitField = this._bitField & (~1048576); | |
this._fulfillmentHandler0 = void 0; | |
}; | |
Promise.prototype._isCarryingStackTrace = | |
function Promise$_isCarryingStackTrace() { | |
return (this._bitField & 1048576) > 0; | |
}; | |
Promise.prototype._getCarriedStackTrace = | |
function Promise$_getCarriedStackTrace() { | |
return this._isCarryingStackTrace() | |
? this._fulfillmentHandler0 | |
: void 0; | |
}; | |
Promise.prototype._receiverAt = function Promise$_receiverAt(index) { | |
var ret; | |
if (index === 0) { | |
ret = this._receiver0; | |
} | |
else { | |
ret = this[index + 4 - 5]; | |
} | |
if (this._isBound() && ret === void 0) { | |
return this._boundTo; | |
} | |
return ret; | |
}; | |
Promise.prototype._promiseAt = function Promise$_promiseAt(index) { | |
if (index === 0) return this._promise0; | |
return this[index + 3 - 5]; | |
}; | |
Promise.prototype._fulfillmentHandlerAt = | |
function Promise$_fulfillmentHandlerAt(index) { | |
if (index === 0) return this._fulfillmentHandler0; | |
return this[index + 0 - 5]; | |
}; | |
Promise.prototype._rejectionHandlerAt = | |
function Promise$_rejectionHandlerAt(index) { | |
if (index === 0) return this._rejectionHandler0; | |
return this[index + 1 - 5]; | |
}; | |
Promise.prototype._unsetAt = function Promise$_unsetAt(index) { | |
if (index === 0) { | |
this._rejectionHandler0 = | |
this._progressHandler0 = | |
this._promise0 = | |
this._receiver0 = void 0; | |
if (!this._isCarryingStackTrace()) { | |
this._fulfillmentHandler0 = void 0; | |
} | |
} | |
else { | |
this[index - 5 + 0] = | |
this[index - 5 + 1] = | |
this[index - 5 + 2] = | |
this[index - 5 + 3] = | |
this[index - 5 + 4] = void 0; | |
} | |
}; | |
Promise.prototype._resolveFromResolver = | |
function Promise$_resolveFromResolver(resolver) { | |
var promise = this; | |
this._setTrace(void 0); | |
this._pushContext(); | |
function Promise$_resolver(val) { | |
if (promise._tryFollow(val)) { | |
return; | |
} | |
promise._fulfill(val); | |
} | |
function Promise$_rejecter(val) { | |
var trace = canAttach(val) ? val : new Error(val + ""); | |
promise._attachExtraTrace(trace); | |
markAsOriginatingFromRejection(val); | |
promise._reject(val, trace === val ? void 0 : trace); | |
} | |
var r = tryCatch2(resolver, void 0, Promise$_resolver, Promise$_rejecter); | |
this._popContext(); | |
if (r !== void 0 && r === errorObj) { | |
var e = r.e; | |
var trace = canAttach(e) ? e : new Error(e + ""); | |
promise._reject(e, trace); | |
} | |
}; | |
Promise.prototype._addCallbacks = function Promise$_addCallbacks( | |
fulfill, | |
reject, | |
progress, | |
promise, | |
receiver | |
) { | |
var index = this._length(); | |
if (index >= 524287 - 5) { | |
index = 0; | |
this._setLength(0); | |
} | |
if (index === 0) { | |
this._promise0 = promise; | |
if (receiver !== void 0) this._receiver0 = receiver; | |
if (typeof fulfill === "function" && !this._isCarryingStackTrace()) | |
this._fulfillmentHandler0 = fulfill; | |
if (typeof reject === "function") this._rejectionHandler0 = reject; | |
if (typeof progress === "function") this._progressHandler0 = progress; | |
} | |
else { | |
var i = index - 5; | |
this[i + 3] = promise; | |
this[i + 4] = receiver; | |
this[i + 0] = typeof fulfill === "function" | |
? fulfill : void 0; | |
this[i + 1] = typeof reject === "function" | |
? reject : void 0; | |
this[i + 2] = typeof progress === "function" | |
? progress : void 0; | |
} | |
this._setLength(index + 5); | |
return index; | |
}; | |
Promise.prototype._setBoundTo = function Promise$_setBoundTo(obj) { | |
if (obj !== void 0) { | |
this._bitField = this._bitField | 8388608; | |
this._boundTo = obj; | |
} | |
else { | |
this._bitField = this._bitField & (~8388608); | |
} | |
}; | |
Promise.prototype._isBound = function Promise$_isBound() { | |
return (this._bitField & 8388608) === 8388608; | |
}; | |
Promise.prototype._spreadSlowCase = | |
function Promise$_spreadSlowCase(targetFn, promise, values, boundTo) { | |
var promiseForAll = | |
Promise$_CreatePromiseArray | |
(values, PromiseArray, boundTo) | |
.promise() | |
._then(function() { | |
return targetFn.apply(boundTo, arguments); | |
}, void 0, void 0, APPLY, void 0); | |
promise._follow(promiseForAll); | |
}; | |
Promise.prototype._callSpread = | |
function Promise$_callSpread(handler, promise, value, localDebugging) { | |
var boundTo = this._isBound() ? this._boundTo : void 0; | |
if (isArray(value)) { | |
for (var i = 0, len = value.length; i < len; ++i) { | |
if (isPromise(Promise._cast(value[i], void 0))) { | |
this._spreadSlowCase(handler, promise, value, boundTo); | |
return; | |
} | |
} | |
} | |
if (localDebugging) promise._pushContext(); | |
return tryCatchApply(handler, value, boundTo); | |
}; | |
Promise.prototype._callHandler = | |
function Promise$_callHandler( | |
handler, receiver, promise, value, localDebugging) { | |
var x; | |
if (receiver === APPLY && !this.isRejected()) { | |
x = this._callSpread(handler, promise, value, localDebugging); | |
} | |
else { | |
if (localDebugging) promise._pushContext(); | |
x = tryCatch1(handler, receiver, value); | |
} | |
if (localDebugging) promise._popContext(); | |
return x; | |
}; | |
Promise.prototype._settlePromiseFromHandler = | |
function Promise$_settlePromiseFromHandler( | |
handler, receiver, value, promise | |
) { | |
if (!isPromise(promise)) { | |
handler.call(receiver, value, promise); | |
return; | |
} | |
var localDebugging = debugging; | |
var x = this._callHandler(handler, receiver, | |
promise, value, localDebugging); | |
if (promise._isFollowing()) return; | |
if (x === errorObj || x === promise || x === NEXT_FILTER) { | |
var err = x === promise | |
? makeSelfResolutionError() | |
: x.e; | |
var trace = canAttach(err) ? err : new Error(err + ""); | |
if (x !== NEXT_FILTER) promise._attachExtraTrace(trace); | |
promise._rejectUnchecked(err, trace); | |
} | |
else { | |
var castValue = Promise._cast(x, promise); | |
if (isPromise(castValue)) { | |
if (castValue.isRejected() && | |
!castValue._isCarryingStackTrace() && | |
!canAttach(castValue._settledValue)) { | |
var trace = new Error(castValue._settledValue + ""); | |
promise._attachExtraTrace(trace); | |
castValue._setCarriedStackTrace(trace); | |
} | |
promise._follow(castValue); | |
if (castValue._cancellable()) { | |
promise._cancellationParent = castValue; | |
promise._setCancellable(); | |
} | |
} | |
else { | |
promise._fulfillUnchecked(x); | |
} | |
} | |
}; | |
Promise.prototype._follow = | |
function Promise$_follow(promise) { | |
this._setFollowing(); | |
if (promise.isPending()) { | |
if (promise._cancellable() ) { | |
this._cancellationParent = promise; | |
this._setCancellable(); | |
} | |
promise._proxyPromise(this); | |
} | |
else if (promise.isFulfilled()) { | |
this._fulfillUnchecked(promise._settledValue); | |
} | |
else { | |
this._rejectUnchecked(promise._settledValue, | |
promise._getCarriedStackTrace()); | |
} | |
if (promise._isRejectionUnhandled()) promise._unsetRejectionIsUnhandled(); | |
if (debugging && | |
promise._traceParent == null) { | |
promise._traceParent = this; | |
} | |
}; | |
Promise.prototype._tryFollow = | |
function Promise$_tryFollow(value) { | |
if (this._isFollowingOrFulfilledOrRejected() || | |
value === this) { | |
return false; | |
} | |
var maybePromise = Promise._cast(value, void 0); | |
if (!isPromise(maybePromise)) { | |
return false; | |
} | |
this._follow(maybePromise); | |
return true; | |
}; | |
Promise.prototype._resetTrace = function Promise$_resetTrace() { | |
if (debugging) { | |
this._trace = new CapturedTrace(this._peekContext() === void 0); | |
} | |
}; | |
Promise.prototype._setTrace = function Promise$_setTrace(parent) { | |
if (debugging) { | |
var context = this._peekContext(); | |
this._traceParent = context; | |
var isTopLevel = context === void 0; | |
if (parent !== void 0 && | |
parent._traceParent === context) { | |
this._trace = parent._trace; | |
} | |
else { | |
this._trace = new CapturedTrace(isTopLevel); | |
} | |
} | |
return this; | |
}; | |
Promise.prototype._attachExtraTrace = | |
function Promise$_attachExtraTrace(error) { | |
if (debugging) { | |
var promise = this; | |
var stack = error.stack; | |
stack = typeof stack === "string" | |
? stack.split("\n") : []; | |
var headerLineCount = 1; | |
while(promise != null && | |
promise._trace != null) { | |
stack = CapturedTrace.combine( | |
stack, | |
promise._trace.stack.split("\n") | |
); | |
promise = promise._traceParent; | |
} | |
var max = Error.stackTraceLimit + headerLineCount; | |
var len = stack.length; | |
if (len > max) { | |
stack.length = max; | |
} | |
if (stack.length <= headerLineCount) { | |
error.stack = "(No stack trace)"; | |
} | |
else { | |
error.stack = stack.join("\n"); | |
} | |
} | |
}; | |
Promise.prototype._cleanValues = function Promise$_cleanValues() { | |
if (this._cancellable()) { | |
this._cancellationParent = void 0; | |
} | |
}; | |
Promise.prototype._fulfill = function Promise$_fulfill(value) { | |
if (this._isFollowingOrFulfilledOrRejected()) return; | |
this._fulfillUnchecked(value); | |
}; | |
Promise.prototype._reject = | |
function Promise$_reject(reason, carriedStackTrace) { | |
if (this._isFollowingOrFulfilledOrRejected()) return; | |
this._rejectUnchecked(reason, carriedStackTrace); | |
}; | |
Promise.prototype._settlePromiseAt = function Promise$_settlePromiseAt(index) { | |
var handler = this.isFulfilled() | |
? this._fulfillmentHandlerAt(index) | |
: this._rejectionHandlerAt(index); | |
var value = this._settledValue; | |
var receiver = this._receiverAt(index); | |
var promise = this._promiseAt(index); | |
if (typeof handler === "function") { | |
this._settlePromiseFromHandler(handler, receiver, value, promise); | |
} | |
else { | |
var done = false; | |
var isFulfilled = this.isFulfilled(); | |
if (receiver !== void 0) { | |
if (receiver instanceof Promise && | |
receiver._isProxied()) { | |
receiver._unsetProxied(); | |
if (isFulfilled) receiver._fulfillUnchecked(value); | |
else receiver._rejectUnchecked(value, | |
this._getCarriedStackTrace()); | |
done = true; | |
} | |
else if (isPromiseArrayProxy(receiver, promise)) { | |
if (isFulfilled) receiver._promiseFulfilled(value, promise); | |
else receiver._promiseRejected(value, promise); | |
done = true; | |
} | |
} | |
if (!done) { | |
if (isFulfilled) promise._fulfill(value); | |
else promise._reject(value, this._getCarriedStackTrace()); | |
} | |
} | |
if (index >= 256) { | |
this._queueGC(); | |
} | |
}; | |
Promise.prototype._isProxied = function Promise$_isProxied() { | |
return (this._bitField & 4194304) === 4194304; | |
}; | |
Promise.prototype._setProxied = function Promise$_setProxied() { | |
this._bitField = this._bitField | 4194304; | |
}; | |
Promise.prototype._unsetProxied = function Promise$_unsetProxied() { | |
this._bitField = this._bitField & (~4194304); | |
}; | |
Promise.prototype._isGcQueued = function Promise$_isGcQueued() { | |
return (this._bitField & -1073741824) === -1073741824; | |
}; | |
Promise.prototype._setGcQueued = function Promise$_setGcQueued() { | |
this._bitField = this._bitField | -1073741824; | |
}; | |
Promise.prototype._unsetGcQueued = function Promise$_unsetGcQueued() { | |
this._bitField = this._bitField & (~-1073741824); | |
}; | |
Promise.prototype._queueGC = function Promise$_queueGC() { | |
if (this._isGcQueued()) return; | |
this._setGcQueued(); | |
async.invokeLater(this._gc, this, void 0); | |
}; | |
Promise.prototype._gc = function Promise$gc() { | |
var len = this._length(); | |
this._unsetAt(0); | |
for (var i = 0; i < len; i++) { | |
delete this[i]; | |
} | |
this._setLength(0); | |
this._unsetGcQueued(); | |
}; | |
Promise.prototype._queueSettleAt = function Promise$_queueSettleAt(index) { | |
if (this._isRejectionUnhandled()) this._unsetRejectionIsUnhandled(); | |
async.invoke(this._settlePromiseAt, this, index); | |
}; | |
Promise.prototype._fulfillUnchecked = | |
function Promise$_fulfillUnchecked(value) { | |
if (!this.isPending()) return; | |
if (value === this) { | |
var err = makeSelfResolutionError(); | |
this._attachExtraTrace(err); | |
return this._rejectUnchecked(err, void 0); | |
} | |
this._cleanValues(); | |
this._setFulfilled(); | |
this._settledValue = value; | |
var len = this._length(); | |
if (len > 0) { | |
async.invoke(this._settlePromises, this, len); | |
} | |
}; | |
Promise.prototype._rejectUncheckedCheckError = | |
function Promise$_rejectUncheckedCheckError(reason) { | |
var trace = canAttach(reason) ? reason : new Error(reason + ""); | |
this._rejectUnchecked(reason, trace === reason ? void 0 : trace); | |
}; | |
Promise.prototype._rejectUnchecked = | |
function Promise$_rejectUnchecked(reason, trace) { | |
if (!this.isPending()) return; | |
if (reason === this) { | |
var err = makeSelfResolutionError(); | |
this._attachExtraTrace(err); | |
return this._rejectUnchecked(err); | |
} | |
this._cleanValues(); | |
this._setRejected(); | |
this._settledValue = reason; | |
if (this._isFinal()) { | |
async.invokeLater(thrower, void 0, trace === void 0 ? reason : trace); | |
return; | |
} | |
var len = this._length(); | |
if (trace !== void 0) this._setCarriedStackTrace(trace); | |
if (len > 0) { | |
async.invoke(this._rejectPromises, this, null); | |
} | |
else { | |
this._ensurePossibleRejectionHandled(); | |
} | |
}; | |
Promise.prototype._rejectPromises = function Promise$_rejectPromises() { | |
this._settlePromises(); | |
this._unsetCarriedStackTrace(); | |
}; | |
Promise.prototype._settlePromises = function Promise$_settlePromises() { | |
var len = this._length(); | |
for (var i = 0; i < len; i+= 5) { | |
this._settlePromiseAt(i); | |
} | |
}; | |
Promise.prototype._ensurePossibleRejectionHandled = | |
function Promise$_ensurePossibleRejectionHandled() { | |
this._setRejectionIsUnhandled(); | |
if (CapturedTrace.possiblyUnhandledRejection !== void 0) { | |
async.invokeLater(this._notifyUnhandledRejection, this, void 0); | |
} | |
}; | |
Promise.prototype._notifyUnhandledRejectionIsHandled = | |
function Promise$_notifyUnhandledRejectionIsHandled() { | |
if (typeof unhandledRejectionHandled === "function") { | |
async.invokeLater(unhandledRejectionHandled, void 0, this); | |
} | |
}; | |
Promise.prototype._notifyUnhandledRejection = | |
function Promise$_notifyUnhandledRejection() { | |
if (this._isRejectionUnhandled()) { | |
var reason = this._settledValue; | |
var trace = this._getCarriedStackTrace(); | |
this._setUnhandledRejectionIsNotified(); | |
if (trace !== void 0) { | |
this._unsetCarriedStackTrace(); | |
reason = trace; | |
} | |
if (typeof CapturedTrace.possiblyUnhandledRejection === "function") { | |
CapturedTrace.possiblyUnhandledRejection(reason, this); | |
} | |
} | |
}; | |
var contextStack = []; | |
Promise.prototype._peekContext = function Promise$_peekContext() { | |
var lastIndex = contextStack.length - 1; | |
if (lastIndex >= 0) { | |
return contextStack[lastIndex]; | |
} | |
return void 0; | |
}; | |
Promise.prototype._pushContext = function Promise$_pushContext() { | |
if (!debugging) return; | |
contextStack.push(this); | |
}; | |
Promise.prototype._popContext = function Promise$_popContext() { | |
if (!debugging) return; | |
contextStack.pop(); | |
}; | |
function Promise$_CreatePromiseArray( | |
promises, PromiseArrayConstructor, boundTo) { | |
var list = null; | |
if (isArray(promises)) { | |
list = promises; | |
} | |
else { | |
list = Promise._cast(promises, void 0); | |
if (list !== promises) { | |
list._setBoundTo(boundTo); | |
} | |
else if (!isPromise(list)) { | |
list = null; | |
} | |
} | |
if (list !== null) { | |
return new PromiseArrayConstructor(list, boundTo); | |
} | |
return { | |
promise: function() {return apiRejection("expecting an array, a promise or a thenable");} | |
}; | |
} | |
var old = global.Promise; | |
Promise.noConflict = function() { | |
if (global.Promise === Promise) { | |
global.Promise = old; | |
} | |
return Promise; | |
}; | |
if (!CapturedTrace.isSupported()) { | |
Promise.longStackTraces = function(){}; | |
debugging = false; | |
} | |
Promise._makeSelfResolutionError = makeSelfResolutionError; | |
_dereq_("./finally.js")(Promise, NEXT_FILTER); | |
_dereq_("./direct_resolve.js")(Promise); | |
_dereq_("./thenables.js")(Promise, INTERNAL); | |
_dereq_("./synchronous_inspection.js")(Promise); | |
Promise.RangeError = RangeError; | |
Promise.CancellationError = CancellationError; | |
Promise.TimeoutError = TimeoutError; | |
Promise.TypeError = TypeError; | |
Promise.RejectionError = RejectionError; | |
util.toFastProperties(Promise); | |
util.toFastProperties(Promise.prototype); | |
_dereq_('./timers.js')(Promise,INTERNAL); | |
_dereq_('./any.js')(Promise,Promise$_CreatePromiseArray,PromiseArray); | |
_dereq_('./race.js')(Promise,INTERNAL); | |
_dereq_('./call_get.js')(Promise); | |
_dereq_('./filter.js')(Promise,Promise$_CreatePromiseArray,PromiseArray,apiRejection); | |
_dereq_('./generators.js')(Promise,apiRejection,INTERNAL); | |
_dereq_('./map.js')(Promise,PromiseArray,INTERNAL,apiRejection); | |
_dereq_('./nodeify.js')(Promise); | |
_dereq_('./promisify.js')(Promise,INTERNAL); | |
_dereq_('./props.js')(Promise,PromiseArray); | |
_dereq_('./reduce.js')(Promise,Promise$_CreatePromiseArray,PromiseArray,apiRejection,INTERNAL); | |
_dereq_('./settle.js')(Promise,Promise$_CreatePromiseArray,PromiseArray); | |
_dereq_('./some.js')(Promise,Promise$_CreatePromiseArray,PromiseArray,apiRejection); | |
_dereq_('./progress.js')(Promise,isPromiseArrayProxy); | |
_dereq_('./cancel.js')(Promise,INTERNAL); | |
Promise.prototype = Promise.prototype; | |
return Promise; | |
}; | |
}).call(this,_dereq_("/Users/lance/Projects/stanza.io/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js")) | |
},{"./any.js":91,"./async.js":92,"./call_get.js":94,"./cancel.js":95,"./captured_trace.js":96,"./catch_filter.js":97,"./direct_resolve.js":98,"./errors.js":99,"./errors_api_rejection":100,"./filter.js":102,"./finally.js":103,"./generators.js":104,"./global.js":105,"./map.js":106,"./nodeify.js":107,"./progress.js":108,"./promise_array.js":110,"./promise_resolver.js":111,"./promisify.js":113,"./props.js":115,"./race.js":117,"./reduce.js":118,"./settle.js":120,"./some.js":122,"./synchronous_inspection.js":124,"./thenables.js":125,"./timers.js":126,"./util.js":127,"/Users/lance/Projects/stanza.io/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js":140}],110:[function(_dereq_,module,exports){ | |
/** | |
* 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. | |
* | |
*/ | |
"use strict"; | |
module.exports = function(Promise, INTERNAL) { | |
var canAttach = _dereq_("./errors.js").canAttach; | |
var util = _dereq_("./util.js"); | |
var async = _dereq_("./async.js"); | |
var hasOwn = {}.hasOwnProperty; | |
var isArray = util.isArray; | |
function toResolutionValue(val) { | |
switch(val) { | |
case -1: return void 0; | |
case -2: return []; | |
case -3: return {}; | |
} | |
} | |
function PromiseArray(values, boundTo) { | |
var promise = this._promise = new Promise(INTERNAL); | |
var parent = void 0; | |
if (values instanceof Promise) { | |
parent = values; | |
if (values._cancellable()) { | |
promise._setCancellable(); | |
promise._cancellationParent = values; | |
} | |
if (values._isBound()) { | |
promise._setBoundTo(boundTo); | |
} | |
} | |
promise._setTrace(parent); | |
this._values = values; | |
this._length = 0; | |
this._totalResolved = 0; | |
this._init(void 0, -2); | |
} | |
PromiseArray.PropertiesPromiseArray = function() {}; | |
PromiseArray.prototype.length = function PromiseArray$length() { | |
return this._length; | |
}; | |
PromiseArray.prototype.promise = function PromiseArray$promise() { | |
return this._promise; | |
}; | |
PromiseArray.prototype._init = | |
function PromiseArray$_init(_, resolveValueIfEmpty) { | |
var values = this._values; | |
if (values instanceof Promise) { | |
if (values.isFulfilled()) { | |
values = values._settledValue; | |
if (!isArray(values)) { | |
var err = new Promise.TypeError("expecting an array, a promise or a thenable"); | |
this.__hardReject__(err); | |
return; | |
} | |
this._values = values; | |
} | |
else if (values.isPending()) { | |
values._then( | |
this._init, | |
this._reject, | |
void 0, | |
this, | |
resolveValueIfEmpty | |
); | |
return; | |
} | |
else { | |
values._unsetRejectionIsUnhandled(); | |
this._reject(values._settledValue); | |
return; | |
} | |
} | |
if (values.length === 0) { | |
this._resolve(toResolutionValue(resolveValueIfEmpty)); | |
return; | |
} | |
var len = values.length; | |
var newLen = len; | |
var newValues; | |
if (this instanceof PromiseArray.PropertiesPromiseArray) { | |
newValues = this._values; | |
} | |
else { | |
newValues = new Array(len); | |
} | |
var isDirectScanNeeded = false; | |
for (var i = 0; i < len; ++i) { | |
var promise = values[i]; | |
if (promise === void 0 && !hasOwn.call(values, i)) { | |
newLen--; | |
continue; | |
} | |
var maybePromise = Promise._cast(promise, void 0); | |
if (maybePromise instanceof Promise) { | |
if (maybePromise.isPending()) { | |
maybePromise._proxyPromiseArray(this, i); | |
} | |
else { | |
maybePromise._unsetRejectionIsUnhandled(); | |
isDirectScanNeeded = true; | |
} | |
} | |
else { | |
isDirectScanNeeded = true; | |
} | |
newValues[i] = maybePromise; | |
} | |
if (newLen === 0) { | |
if (resolveValueIfEmpty === -2) { | |
this._resolve(newValues); | |
} | |
else { | |
this._resolve(toResolutionValue(resolveValueIfEmpty)); | |
} | |
return; | |
} | |
this._values = newValues; | |
this._length = newLen; | |
if (isDirectScanNeeded) { | |
var scanMethod = newLen === len | |
? this._scanDirectValues | |
: this._scanDirectValuesHoled; | |
async.invoke(scanMethod, this, len); | |
} | |
}; | |
PromiseArray.prototype._settlePromiseAt = | |
function PromiseArray$_settlePromiseAt(index) { | |
var value = this._values[index]; | |
if (!(value instanceof Promise)) { | |
this._promiseFulfilled(value, index); | |
} | |
else if (value.isFulfilled()) { | |
this._promiseFulfilled(value._settledValue, index); | |
} | |
else if (value.isRejected()) { | |
this._promiseRejected(value._settledValue, index); | |
} | |
}; | |
PromiseArray.prototype._scanDirectValuesHoled = | |
function PromiseArray$_scanDirectValuesHoled(len) { | |
for (var i = 0; i < len; ++i) { | |
if (this._isResolved()) { | |
break; | |
} | |
if (hasOwn.call(this._values, i)) { | |
this._settlePromiseAt(i); | |
} | |
} | |
}; | |
PromiseArray.prototype._scanDirectValues = | |
function PromiseArray$_scanDirectValues(len) { | |
for (var i = 0; i < len; ++i) { | |
if (this._isResolved()) { | |
break; | |
} | |
this._settlePromiseAt(i); | |
} | |
}; | |
PromiseArray.prototype._isResolved = function PromiseArray$_isResolved() { | |
return this._values === null; | |
}; | |
PromiseArray.prototype._resolve = function PromiseArray$_resolve(value) { | |
this._values = null; | |
this._promise._fulfill(value); | |
}; | |
PromiseArray.prototype.__hardReject__ = | |
PromiseArray.prototype._reject = function PromiseArray$_reject(reason) { | |
this._values = null; | |
var trace = canAttach(reason) ? reason : new Error(reason + ""); | |
this._promise._attachExtraTrace(trace); | |
this._promise._reject(reason, trace); | |
}; | |
PromiseArray.prototype._promiseProgressed = | |
function PromiseArray$_promiseProgressed(progressValue, index) { | |
if (this._isResolved()) return; | |
this._promise._progress({ | |
index: index, | |
value: progressValue | |
}); | |
}; | |
PromiseArray.prototype._promiseFulfilled = | |
function PromiseArray$_promiseFulfilled(value, index) { | |
if (this._isResolved()) return; | |
this._values[index] = value; | |
var totalResolved = ++this._totalResolved; | |
if (totalResolved >= this._length) { | |
this._resolve(this._values); | |
} | |
}; | |
PromiseArray.prototype._promiseRejected = | |
function PromiseArray$_promiseRejected(reason, index) { | |
if (this._isResolved()) return; | |
this._totalResolved++; | |
this._reject(reason); | |
}; | |
return PromiseArray; | |
}; | |
},{"./async.js":92,"./errors.js":99,"./util.js":127}],111:[function(_dereq_,module,exports){ | |
/** | |
* 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. | |
* | |
*/ | |
"use strict"; | |
var util = _dereq_("./util.js"); | |
var maybeWrapAsError = util.maybeWrapAsError; | |
var errors = _dereq_("./errors.js"); | |
var TimeoutError = errors.TimeoutError; | |
var RejectionError = errors.RejectionError; | |
var async = _dereq_("./async.js"); | |
var haveGetters = util.haveGetters; | |
var es5 = _dereq_("./es5.js"); | |
function isUntypedError(obj) { | |
return obj instanceof Error && | |
es5.getPrototypeOf(obj) === Error.prototype; | |
} | |
function wrapAsRejectionError(obj) { | |
var ret; | |
if (isUntypedError(obj)) { | |
ret = new RejectionError(obj); | |
} | |
else { | |
ret = obj; | |
} | |
errors.markAsOriginatingFromRejection(ret); | |
return ret; | |
} | |
function nodebackForPromise(promise) { | |
function PromiseResolver$_callback(err, value) { | |
if (promise === null) return; | |
if (err) { | |
var wrapped = wrapAsRejectionError(maybeWrapAsError(err)); | |
promise._attachExtraTrace(wrapped); | |
promise._reject(wrapped); | |
} | |
else { | |
if (arguments.length > 2) { | |
var $_len = arguments.length;var args = new Array($_len - 1); for(var $_i = 1; $_i < $_len; ++$_i) {args[$_i - 1] = arguments[$_i];} | |
promise._fulfill(args); | |
} | |
else { | |
promise._fulfill(value); | |
} | |
} | |
promise = null; | |
} | |
return PromiseResolver$_callback; | |
} | |
var PromiseResolver; | |
if (!haveGetters) { | |
PromiseResolver = function PromiseResolver(promise) { | |
this.promise = promise; | |
this.asCallback = nodebackForPromise(promise); | |
this.callback = this.asCallback; | |
}; | |
} | |
else { | |
PromiseResolver = function PromiseResolver(promise) { | |
this.promise = promise; | |
}; | |
} | |
if (haveGetters) { | |
var prop = { | |
get: function() { | |
return nodebackForPromise(this.promise); | |
} | |
}; | |
es5.defineProperty(PromiseResolver.prototype, "asCallback", prop); | |
es5.defineProperty(PromiseResolver.prototype, "callback", prop); | |
} | |
PromiseResolver._nodebackForPromise = nodebackForPromise; | |
PromiseResolver.prototype.toString = function PromiseResolver$toString() { | |
return "[object PromiseResolver]"; | |
}; | |
PromiseResolver.prototype.resolve = | |
PromiseResolver.prototype.fulfill = function PromiseResolver$resolve(value) { | |
var promise = this.promise; | |
if (promise._tryFollow(value)) { | |
return; | |
} | |
async.invoke(promise._fulfill, promise, value); | |
}; | |
PromiseResolver.prototype.reject = function PromiseResolver$reject(reason) { | |
var promise = this.promise; | |
errors.markAsOriginatingFromRejection(reason); | |
var trace = errors.canAttach(reason) ? reason : new Error(reason + ""); | |
promise._attachExtraTrace(trace); | |
async.invoke(promise._reject, promise, reason); | |
if (trace !== reason) { | |
async.invoke(this._setCarriedStackTrace, this, trace); | |
} | |
}; | |
PromiseResolver.prototype.progress = | |
function PromiseResolver$progress(value) { | |
async.invoke(this.promise._progress, this.promise, value); | |
}; | |
PromiseResolver.prototype.cancel = function PromiseResolver$cancel() { | |
async.invoke(this.promise.cancel, this.promise, void 0); | |
}; | |
PromiseResolver.prototype.timeout = function PromiseResolver$timeout() { | |
this.reject(new TimeoutError("timeout")); | |
}; | |
PromiseResolver.prototype.isResolved = function PromiseResolver$isResolved() { | |
return this.promise.isResolved(); | |
}; | |
PromiseResolver.prototype.toJSON = function PromiseResolver$toJSON() { | |
return this.promise.toJSON(); | |
}; | |
PromiseResolver.prototype._setCarriedStackTrace = | |
function PromiseResolver$_setCarriedStackTrace(trace) { | |
if (this.promise.isRejected()) { | |
this.promise._setCarriedStackTrace(trace); | |
} | |
}; | |
module.exports = PromiseResolver; | |
},{"./async.js":92,"./errors.js":99,"./es5.js":101,"./util.js":127}],112:[function(_dereq_,module,exports){ | |
/** | |
* 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. | |
* | |
*/ | |
"use strict"; | |
module.exports = function(Promise, INTERNAL) { | |
var errors = _dereq_("./errors.js"); | |
var TypeError = errors.TypeError; | |
var util = _dereq_("./util.js"); | |
var isArray = util.isArray; | |
var errorObj = util.errorObj; | |
var tryCatch1 = util.tryCatch1; | |
var yieldHandlers = []; | |
function promiseFromYieldHandler(value) { | |
var _yieldHandlers = yieldHandlers; | |
var _errorObj = errorObj; | |
var _Promise = Promise; | |
var len = _yieldHandlers.length; | |
for (var i = 0; i < len; ++i) { | |
var result = tryCatch1(_yieldHandlers[i], void 0, value); | |
if (result === _errorObj) { | |
return _Promise.reject(_errorObj.e); | |
} | |
var maybePromise = _Promise._cast(result, | |
promiseFromYieldHandler, void 0); | |
if (maybePromise instanceof _Promise) return maybePromise; | |
} | |
return null; | |
} | |
function PromiseSpawn(generatorFunction, receiver) { | |
var promise = this._promise = new Promise(INTERNAL); | |
promise._setTrace(void 0); | |
this._generatorFunction = generatorFunction; | |
this._receiver = receiver; | |
this._generator = void 0; | |
} | |
PromiseSpawn.prototype.promise = function PromiseSpawn$promise() { | |
return this._promise; | |
}; | |
PromiseSpawn.prototype._run = function PromiseSpawn$_run() { | |
this._generator = this._generatorFunction.call(this._receiver); | |
this._receiver = | |
this._generatorFunction = void 0; | |
this._next(void 0); | |
}; | |
PromiseSpawn.prototype._continue = function PromiseSpawn$_continue(result) { | |
if (result === errorObj) { | |
this._generator = void 0; | |
var trace = errors.canAttach(result.e) | |
? result.e : new Error(result.e + ""); | |
this._promise._attachExtraTrace(trace); | |
this._promise._reject(result.e, trace); | |
return; | |
} | |
var value = result.value; | |
if (result.done === true) { | |
this._generator = void 0; | |
if (!this._promise._tryFollow(value)) { | |
this._promise._fulfill(value); | |
} | |
} | |
else { | |
var maybePromise = Promise._cast(value, PromiseSpawn$_continue, void 0); | |
if (!(maybePromise instanceof Promise)) { | |
if (isArray(maybePromise)) { | |
maybePromise = Promise.all(maybePromise); | |
} | |
else { | |
maybePromise = promiseFromYieldHandler(maybePromise); | |
} | |
if (maybePromise === null) { | |
this._throw(new TypeError("A value was yielded that could not be treated as a promise")); | |
return; | |
} | |
} | |
maybePromise._then( | |
this._next, | |
this._throw, | |
void 0, | |
this, | |
null | |
); | |
} | |
}; | |
PromiseSpawn.prototype._throw = function PromiseSpawn$_throw(reason) { | |
if (errors.canAttach(reason)) | |
this._promise._attachExtraTrace(reason); | |
this._continue( | |
tryCatch1(this._generator["throw"], this._generator, reason) | |
); | |
}; | |
PromiseSpawn.prototype._next = function PromiseSpawn$_next(value) { | |
this._continue( | |
tryCatch1(this._generator.next, this._generator, value) | |
); | |
}; | |
PromiseSpawn.addYieldHandler = function PromiseSpawn$AddYieldHandler(fn) { | |
if (typeof fn !== "function") throw new TypeError("fn must be a function"); | |
yieldHandlers.push(fn); | |
}; | |
return PromiseSpawn; | |
}; | |
},{"./errors.js":99,"./util.js":127}],113:[function(_dereq_,module,exports){ | |
/** | |
* 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. | |
* | |
*/ | |
"use strict"; | |
module.exports = function(Promise, INTERNAL) { | |
var THIS = {}; | |
var util = _dereq_("./util.js"); | |
var es5 = _dereq_("./es5.js"); | |
var nodebackForPromise = _dereq_("./promise_resolver.js") | |
._nodebackForPromise; | |
var withAppended = util.withAppended; | |
var maybeWrapAsError = util.maybeWrapAsError; | |
var canEvaluate = util.canEvaluate; | |
var deprecated = util.deprecated; | |
var TypeError = _dereq_("./errors").TypeError; | |
var rasyncSuffix = new RegExp("Async" + "$"); | |
function isPromisified(fn) { | |
return fn.__isPromisified__ === true; | |
} | |
function hasPromisified(obj, key) { | |
var containsKey = ((key + "Async") in obj); | |
return containsKey ? isPromisified(obj[key + "Async"]) | |
: false; | |
} | |
function checkValid(ret) { | |
for (var i = 0; i < ret.length; i += 2) { | |
var key = ret[i]; | |
if (rasyncSuffix.test(key)) { | |
var keyWithoutAsyncSuffix = key.replace(rasyncSuffix, ""); | |
for (var j = 0; j < ret.length; j += 2) { | |
if (ret[j] === keyWithoutAsyncSuffix) { | |
throw new TypeError("Cannot promisify an API " + | |
"that has normal methods with Async-suffix"); | |
} | |
} | |
} | |
} | |
} | |
var inheritedMethods = (function() { | |
if (es5.isES5) { | |
var create = Object.create; | |
var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; | |
return function(cur) { | |
var ret = []; | |
var visitedKeys = create(null); | |
var original = cur; | |
while (cur !== null) { | |
var keys = es5.keys(cur); | |
for (var i = 0, len = keys.length; i < len; ++i) { | |
var key = keys[i]; | |
if (visitedKeys[key]) continue; | |
visitedKeys[key] = true; | |
var desc = getOwnPropertyDescriptor(cur, key); | |
if (desc != null && | |
typeof desc.value === "function" && | |
!isPromisified(desc.value) && | |
!hasPromisified(original, key)) { | |
ret.push(key, desc.value); | |
} | |
} | |
cur = es5.getPrototypeOf(cur); | |
} | |
checkValid(ret); | |
return ret; | |
}; | |
} | |
else { | |
return function(obj) { | |
var ret = []; | |
/*jshint forin:false */ | |
for (var key in obj) { | |
var fn = obj[key]; | |
if (typeof fn === "function" && | |
!isPromisified(fn) && | |
!hasPromisified(obj, key)) { | |
ret.push(key, fn); | |
} | |
} | |
checkValid(ret); | |
return ret; | |
}; | |
} | |
})(); | |
function switchCaseArgumentOrder(likelyArgumentCount) { | |
var ret = [likelyArgumentCount]; | |
var min = Math.max(0, likelyArgumentCount - 1 - 5); | |
for(var i = likelyArgumentCount - 1; i >= min; --i) { | |
if (i === likelyArgumentCount) continue; | |
ret.push(i); | |
} | |
for(var i = likelyArgumentCount + 1; i <= 5; ++i) { | |
ret.push(i); | |
} | |
return ret; | |
} | |
function parameterDeclaration(parameterCount) { | |
var ret = new Array(parameterCount); | |
for(var i = 0; i < ret.length; ++i) { | |
ret[i] = "_arg" + i; | |
} | |
return ret.join(", "); | |
} | |
function parameterCount(fn) { | |
if (typeof fn.length === "number") { | |
return Math.max(Math.min(fn.length, 1023 + 1), 0); | |
} | |
return 0; | |
} | |
function propertyAccess(id) { | |
var rident = /^[a-z$_][a-z$_0-9]*$/i; | |
if (rident.test(id)) { | |
return "." + id; | |
} | |
else return "['" + id.replace(/(['\\])/g, "\\$1") + "']"; | |
} | |
function makeNodePromisifiedEval(callback, receiver, originalName, fn) { | |
var newParameterCount = Math.max(0, parameterCount(fn) - 1); | |
var argumentOrder = switchCaseArgumentOrder(newParameterCount); | |
var callbackName = (typeof originalName === "string" ? | |
originalName + "Async" : | |
"promisified"); | |
function generateCallForArgumentCount(count) { | |
var args = new Array(count); | |
for (var i = 0, len = args.length; i < len; ++i) { | |
args[i] = "arguments[" + i + "]"; | |
} | |
var comma = count > 0 ? "," : ""; | |
if (typeof callback === "string" && | |
receiver === THIS) { | |
return "this" + propertyAccess(callback) + "("+args.join(",") + | |
comma +" fn);"+ | |
"break;"; | |
} | |
return (receiver === void 0 | |
? "callback("+args.join(",")+ comma +" fn);" | |
: "callback.call("+(receiver === THIS | |
? "this" | |
: "receiver")+", "+args.join(",") + comma + " fn);") + | |
"break;"; | |
} | |
function generateArgumentSwitchCase() { | |
var ret = ""; | |
for(var i = 0; i < argumentOrder.length; ++i) { | |
ret += "case " + argumentOrder[i] +":" + | |
generateCallForArgumentCount(argumentOrder[i]); | |
} | |
ret += "default: var args = new Array(len + 1);" + | |
"var i = 0;" + | |
"for (var i = 0; i < len; ++i) { " + | |
" args[i] = arguments[i];" + | |
"}" + | |
"args[i] = fn;" + | |
(typeof callback === "string" | |
? "this" + propertyAccess(callback) + ".apply(" | |
: "callback.apply(") + | |
(receiver === THIS ? "this" : "receiver") + | |
", args); break;"; | |
return ret; | |
} | |
return new Function("Promise", "callback", "receiver", | |
"withAppended", "maybeWrapAsError", "nodebackForPromise", | |
"INTERNAL", | |
"var ret = function " + callbackName + | |
"(" + parameterDeclaration(newParameterCount) + ") {\"use strict\";" + | |
"var len = arguments.length;" + | |
"var promise = new Promise(INTERNAL);"+ | |
"promise._setTrace(void 0);" + | |
"var fn = nodebackForPromise(promise);"+ | |
"try {" + | |
"switch(len) {" + | |
generateArgumentSwitchCase() + | |
"}" + | |
"}" + | |
"catch(e){ " + | |
"var wrapped = maybeWrapAsError(e);" + | |
"promise._attachExtraTrace(wrapped);" + | |
"promise._reject(wrapped);" + | |
"}" + | |
"return promise;" + | |
"" + | |
"}; ret.__isPromisified__ = true; return ret;" | |
)(Promise, callback, receiver, withAppended, | |
maybeWrapAsError, nodebackForPromise, INTERNAL); | |
} | |
function makeNodePromisifiedClosure(callback, receiver) { | |
function promisified() { | |
var _receiver = receiver; | |
if (receiver === THIS) _receiver = this; | |
if (typeof callback === "string") { | |
callback = _receiver[callback]; | |
} | |
var promise = new Promise(INTERNAL); | |
promise._setTrace(void 0); | |
var fn = nodebackForPromise(promise); | |
try { | |
callback.apply(_receiver, withAppended(arguments, fn)); | |
} | |
catch(e) { | |
var wrapped = maybeWrapAsError(e); | |
promise._attachExtraTrace(wrapped); | |
promise._reject(wrapped); | |
} | |
return promise; | |
} | |
promisified.__isPromisified__ = true; | |
return promisified; | |
} | |
var makeNodePromisified = canEvaluate | |
? makeNodePromisifiedEval | |
: makeNodePromisifiedClosure; | |
function _promisify(callback, receiver, isAll) { | |
if (isAll) { | |
var methods = inheritedMethods(callback); | |
for (var i = 0, len = methods.length; i < len; i+= 2) { | |
var key = methods[i]; | |
var fn = methods[i+1]; | |
var promisifiedKey = key + "Async"; | |
callback[promisifiedKey] = makeNodePromisified(key, THIS, key, fn); | |
} | |
util.toFastProperties(callback); | |
return callback; | |
} | |
else { | |
return makeNodePromisified(callback, receiver, void 0, callback); | |
} | |
} | |
Promise.promisify = function Promise$Promisify(fn, receiver) { | |
if (typeof fn === "object" && fn !== null) { | |
deprecated("Promise.promisify for promisifying entire objects is deprecated. Use Promise.promisifyAll instead."); | |
return _promisify(fn, receiver, true); | |
} | |
if (typeof fn !== "function") { | |
throw new TypeError("fn must be a function"); | |
} | |
if (isPromisified(fn)) { | |
return fn; | |
} | |
return _promisify( | |
fn, | |
arguments.length < 2 ? THIS : receiver, | |
false); | |
}; | |
Promise.promisifyAll = function Promise$PromisifyAll(target) { | |
if (typeof target !== "function" && typeof target !== "object") { | |
throw new TypeError("the target of promisifyAll must be an object or a function"); | |
} | |
return _promisify(target, void 0, true); | |
}; | |
}; | |
},{"./errors":99,"./es5.js":101,"./promise_resolver.js":111,"./util.js":127}],114:[function(_dereq_,module,exports){ | |
/** | |
* 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. | |
* | |
*/ | |
"use strict"; | |
module.exports = function(Promise, PromiseArray) { | |
var util = _dereq_("./util.js"); | |
var inherits = util.inherits; | |
var es5 = _dereq_("./es5.js"); | |
function PropertiesPromiseArray(obj, boundTo) { | |
var keys = es5.keys(obj); | |
var values = new Array(keys.length); | |
for (var i = 0, len = values.length; i < len; ++i) { | |
values[i] = obj[keys[i]]; | |
} | |
this.constructor$(values, boundTo); | |
if (!this._isResolved()) { | |
for (var i = 0, len = keys.length; i < len; ++i) { | |
values.push(keys[i]); | |
} | |
} | |
} | |
inherits(PropertiesPromiseArray, PromiseArray); | |
PropertiesPromiseArray.prototype._init = | |
function PropertiesPromiseArray$_init() { | |
this._init$(void 0, -3) ; | |
}; | |
PropertiesPromiseArray.prototype._promiseFulfilled = | |
function PropertiesPromiseArray$_promiseFulfilled(value, index) { | |
if (this._isResolved()) return; | |
this._values[index] = value; | |
var totalResolved = ++this._totalResolved; | |
if (totalResolved >= this._length) { | |
var val = {}; | |
var keyOffset = this.length(); | |
for (var i = 0, len = this.length(); i < len; ++i) { | |
val[this._values[i + keyOffset]] = this._values[i]; | |
} | |
this._resolve(val); | |
} | |
}; | |
PropertiesPromiseArray.prototype._promiseProgressed = | |
function PropertiesPromiseArray$_promiseProgressed(value, index) { | |
if (this._isResolved()) return; | |
this._promise._progress({ | |
key: this._values[index + this.length()], | |
value: value | |
}); | |
}; | |
PromiseArray.PropertiesPromiseArray = PropertiesPromiseArray; | |
return PropertiesPromiseArray; | |
}; | |
},{"./es5.js":101,"./util.js":127}],115:[function(_dereq_,module,exports){ | |
/** | |
* 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. | |
* | |
*/ | |
"use strict"; | |
module.exports = function(Promise, PromiseArray) { | |
var PropertiesPromiseArray = _dereq_("./properties_promise_array.js")( | |
Promise, PromiseArray); | |
var util = _dereq_("./util.js"); | |
var apiRejection = _dereq_("./errors_api_rejection")(Promise); | |
var isObject = util.isObject; | |
function Promise$_Props(promises, useBound) { | |
var ret; | |
var castValue = Promise._cast(promises, void 0); | |
if (!isObject(castValue)) { | |
return apiRejection("cannot await properties of a non-object"); | |
} | |
else if (castValue instanceof Promise) { | |
ret = castValue._then(Promise.props, void 0, void 0, | |
void 0, void 0); | |
} | |
else { | |
ret = new PropertiesPromiseArray( | |
castValue, | |
useBound === true && castValue._isBound() | |
? castValue._boundTo | |
: void 0 | |
).promise(); | |
useBound = false; | |
} | |
if (useBound === true && castValue._isBound()) { | |
ret._setBoundTo(castValue._boundTo); | |
} | |
return ret; | |
} | |
Promise.prototype.props = function Promise$props() { | |
return Promise$_Props(this, true); | |
}; | |
Promise.props = function Promise$Props(promises) { | |
return Promise$_Props(promises, false); | |
}; | |
}; | |
},{"./errors_api_rejection":100,"./properties_promise_array.js":114,"./util.js":127}],116:[function(_dereq_,module,exports){ | |
/** | |
* 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. | |
* | |
*/ | |
"use strict"; | |
function arrayCopy(src, srcIndex, dst, dstIndex, len) { | |
for (var j = 0; j < len; ++j) { | |
dst[j + dstIndex] = src[j + srcIndex]; | |
} | |
} | |
function pow2AtLeast(n) { | |
n = n >>> 0; | |
n = n - 1; | |
n = n | (n >> 1); | |
n = n | (n >> 2); | |
n = n | (n >> 4); | |
n = n | (n >> 8); | |
n = n | (n >> 16); | |
return n + 1; | |
} | |
function getCapacity(capacity) { | |
if (typeof capacity !== "number") return 16; | |
return pow2AtLeast( | |
Math.min( | |
Math.max(16, capacity), 1073741824) | |
); | |
} | |
function Queue(capacity) { | |
this._capacity = getCapacity(capacity); | |
this._length = 0; | |
this._front = 0; | |
this._makeCapacity(); | |
} | |
Queue.prototype._willBeOverCapacity = | |
function Queue$_willBeOverCapacity(size) { | |
return this._capacity < size; | |
}; | |
Queue.prototype._pushOne = function Queue$_pushOne(arg) { | |
var length = this.length(); | |
this._checkCapacity(length + 1); | |
var i = (this._front + length) & (this._capacity - 1); | |
this[i] = arg; | |
this._length = length + 1; | |
}; | |
Queue.prototype.push = function Queue$push(fn, receiver, arg) { | |
var length = this.length() + 3; | |
if (this._willBeOverCapacity(length)) { | |
this._pushOne(fn); | |
this._pushOne(receiver); | |
this._pushOne(arg); | |
return; | |
} | |
var j = this._front + length - 3; | |
this._checkCapacity(length); | |
var wrapMask = this._capacity - 1; | |
this[(j + 0) & wrapMask] = fn; | |
this[(j + 1) & wrapMask] = receiver; | |
this[(j + 2) & wrapMask] = arg; | |
this._length = length; | |
}; | |
Queue.prototype.shift = function Queue$shift() { | |
var front = this._front, | |
ret = this[front]; | |
this[front] = void 0; | |
this._front = (front + 1) & (this._capacity - 1); | |
this._length--; | |
return ret; | |
}; | |
Queue.prototype.length = function Queue$length() { | |
return this._length; | |
}; | |
Queue.prototype._makeCapacity = function Queue$_makeCapacity() { | |
var len = this._capacity; | |
for (var i = 0; i < len; ++i) { | |
this[i] = void 0; | |
} | |
}; | |
Queue.prototype._checkCapacity = function Queue$_checkCapacity(size) { | |
if (this._capacity < size) { | |
this._resizeTo(this._capacity << 3); | |
} | |
}; | |
Queue.prototype._resizeTo = function Queue$_resizeTo(capacity) { | |
var oldFront = this._front; | |
var oldCapacity = this._capacity; | |
var oldQueue = new Array(oldCapacity); | |
var length = this.length(); | |
arrayCopy(this, 0, oldQueue, 0, oldCapacity); | |
this._capacity = capacity; | |
this._makeCapacity(); | |
this._front = 0; | |
if (oldFront + length <= oldCapacity) { | |
arrayCopy(oldQueue, oldFront, this, 0, length); | |
} | |
else { var lengthBeforeWrapping = | |
length - ((oldFront + length) & (oldCapacity - 1)); | |
arrayCopy(oldQueue, oldFront, this, 0, lengthBeforeWrapping); | |
arrayCopy(oldQueue, 0, this, lengthBeforeWrapping, | |
length - lengthBeforeWrapping); | |
} | |
}; | |
module.exports = Queue; | |
},{}],117:[function(_dereq_,module,exports){ | |
/** | |
* 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. | |
* | |
*/ | |
"use strict"; | |
module.exports = function(Promise, INTERNAL) { | |
var apiRejection = _dereq_("./errors_api_rejection.js")(Promise); | |
var isArray = _dereq_("./util.js").isArray; | |
var raceLater = function Promise$_raceLater(promise) { | |
return promise.then(function(array) { | |
return Promise$_Race(array, promise); | |
}); | |
}; | |
var hasOwn = {}.hasOwnProperty; | |
function Promise$_Race(promises, parent) { | |
var maybePromise = Promise._cast(promises, void 0); | |
if (maybePromise instanceof Promise) { | |
return raceLater(maybePromise); | |
} | |
else if (!isArray(promises)) { | |
return apiRejection("expecting an array, a promise or a thenable"); | |
} | |
var ret = new Promise(INTERNAL); | |
ret._setTrace(parent); | |
if (parent !== void 0) { | |
if (parent._isBound()) { | |
ret._setBoundTo(parent._boundTo); | |
} | |
if (parent._cancellable()) { | |
ret._setCancellable(); | |
ret._cancellationParent = parent; | |
} | |
} | |
var fulfill = ret._fulfill; | |
var reject = ret._reject; | |
for (var i = 0, len = promises.length; i < len; ++i) { | |
var val = promises[i]; | |
if (val === void 0 && !(hasOwn.call(promises, i))) { | |
continue; | |
} | |
Promise.cast(val)._then( | |
fulfill, | |
reject, | |
void 0, | |
ret, | |
null | |
); | |
} | |
return ret; | |
} | |
Promise.race = function Promise$Race(promises) { | |
return Promise$_Race(promises, void 0); | |
}; | |
Promise.prototype.race = function Promise$race() { | |
return Promise$_Race(this, void 0); | |
}; | |
}; | |
},{"./errors_api_rejection.js":100,"./util.js":127}],118:[function(_dereq_,module,exports){ | |
/** | |
* 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. | |
* | |
*/ | |
"use strict"; | |
module.exports = function( | |
Promise, Promise$_CreatePromiseArray, | |
PromiseArray, apiRejection, INTERNAL) { | |
function Reduction(callback, index, accum, items, receiver) { | |
this.promise = new Promise(INTERNAL); | |
this.index = index; | |
this.length = items.length; | |
this.items = items; | |
this.callback = callback; | |
this.receiver = receiver; | |
this.accum = accum; | |
} | |
Reduction.prototype.reject = function Reduction$reject(e) { | |
this.promise._reject(e); | |
}; | |
Reduction.prototype.fulfill = function Reduction$fulfill(value, index) { | |
this.accum = value; | |
this.index = index + 1; | |
this.iterate(); | |
}; | |
Reduction.prototype.iterate = function Reduction$iterate() { | |
var i = this.index; | |
var len = this.length; | |
var items = this.items; | |
var result = this.accum; | |
var receiver = this.receiver; | |
var callback = this.callback; | |
for (; i < len; ++i) { | |
result = callback.call(receiver, result, items[i], i, len); | |
result = Promise._cast(result, void 0); | |
if (result instanceof Promise) { | |
result._then( | |
this.fulfill, this.reject, void 0, this, i); | |
return; | |
} | |
} | |
this.promise._fulfill(result); | |
}; | |
function Promise$_reducer(fulfilleds, initialValue) { | |
var fn = this; | |
var receiver = void 0; | |
if (typeof fn !== "function") { | |
receiver = fn.receiver; | |
fn = fn.fn; | |
} | |
var len = fulfilleds.length; | |
var accum = void 0; | |
var startIndex = 0; | |
if (initialValue !== void 0) { | |
accum = initialValue; | |
startIndex = 0; | |
} | |
else { | |
startIndex = 1; | |
if (len > 0) accum = fulfilleds[0]; | |
} | |
var i = startIndex; | |
if (i >= len) { | |
return accum; | |
} | |
var reduction = new Reduction(fn, i, accum, fulfilleds, receiver); | |
reduction.iterate(); | |
return reduction.promise; | |
} | |
function Promise$_unpackReducer(fulfilleds) { | |
var fn = this.fn; | |
var initialValue = this.initialValue; | |
return Promise$_reducer.call(fn, fulfilleds, initialValue); | |
} | |
function Promise$_slowReduce( | |
promises, fn, initialValue, useBound) { | |
return initialValue._then(function(initialValue) { | |
return Promise$_Reduce( | |
promises, fn, initialValue, useBound); | |
}, void 0, void 0, void 0, void 0); | |
} | |
function Promise$_Reduce(promises, fn, initialValue, useBound) { | |
if (typeof fn !== "function") { | |
return apiRejection("fn must be a function"); | |
} | |
if (useBound === true && promises._isBound()) { | |
fn = { | |
fn: fn, | |
receiver: promises._boundTo | |
}; | |
} | |
if (initialValue !== void 0) { | |
if (initialValue instanceof Promise) { | |
if (initialValue.isFulfilled()) { | |
initialValue = initialValue._settledValue; | |
} | |
else { | |
return Promise$_slowReduce(promises, | |
fn, initialValue, useBound); | |
} | |
} | |
return Promise$_CreatePromiseArray(promises, PromiseArray, | |
useBound === true && promises._isBound() | |
? promises._boundTo | |
: void 0) | |
.promise() | |
._then(Promise$_unpackReducer, void 0, void 0, { | |
fn: fn, | |
initialValue: initialValue | |
}, void 0); | |
} | |
return Promise$_CreatePromiseArray(promises, PromiseArray, | |
useBound === true && promises._isBound() | |
? promises._boundTo | |
: void 0).promise() | |
._then(Promise$_reducer, void 0, void 0, fn, void 0); | |
} | |
Promise.reduce = function Promise$Reduce(promises, fn, initialValue) { | |
return Promise$_Reduce(promises, fn, initialValue, false); | |
}; | |
Promise.prototype.reduce = function Promise$reduce(fn, initialValue) { | |
return Promise$_Reduce(this, fn, initialValue, true); | |
}; | |
}; | |
},{}],119:[function(_dereq_,module,exports){ | |
(function (process){ | |
/** | |
* 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. | |
* | |
*/ | |
"use strict"; | |
var global = _dereq_("./global.js"); | |
var schedule; | |
if (typeof process !== "undefined" && process !== null && | |
typeof process.cwd === "function" && | |
typeof process.nextTick === "function" && | |
typeof process.version === "string") { | |
schedule = function Promise$_Scheduler(fn) { | |
process.nextTick(fn); | |
}; | |
} | |
else if ((typeof global.MutationObserver === "function" || | |
typeof global.WebkitMutationObserver === "function" || | |
typeof global.WebKitMutationObserver === "function") && | |
typeof document !== "undefined" && | |
typeof document.createElement === "function") { | |
schedule = (function(){ | |
var MutationObserver = global.MutationObserver || | |
global.WebkitMutationObserver || | |
global.WebKitMutationObserver; | |
var div = document.createElement("div"); | |
var queuedFn = void 0; | |
var observer = new MutationObserver( | |
function Promise$_Scheduler() { | |
var fn = queuedFn; | |
queuedFn = void 0; | |
fn(); | |
} | |
); | |
observer.observe(div, { | |
attributes: true | |
}); | |
return function Promise$_Scheduler(fn) { | |
queuedFn = fn; | |
div.setAttribute("class", "foo"); | |
}; | |
})(); | |
} | |
else if (typeof global.postMessage === "function" && | |
typeof global.importScripts !== "function" && | |
typeof global.addEventListener === "function" && | |
typeof global.removeEventListener === "function") { | |
var MESSAGE_KEY = "bluebird_message_key_" + Math.random(); | |
schedule = (function(){ | |
var queuedFn = void 0; | |
function Promise$_Scheduler(e) { | |
if (e.source === global && | |
e.data === MESSAGE_KEY) { | |
var fn = queuedFn; | |
queuedFn = void 0; | |
fn(); | |
} | |
} | |
global.addEventListener("message", Promise$_Scheduler, false); | |
return function Promise$_Scheduler(fn) { | |
queuedFn = fn; | |
global.postMessage( | |
MESSAGE_KEY, "*" | |
); | |
}; | |
})(); | |
} | |
else if (typeof global.MessageChannel === "function") { | |
schedule = (function(){ | |
var queuedFn = void 0; | |
var channel = new global.MessageChannel(); | |
channel.port1.onmessage = function Promise$_Scheduler() { | |
var fn = queuedFn; | |
queuedFn = void 0; | |
fn(); | |
}; | |
return function Promise$_Scheduler(fn) { | |
queuedFn = fn; | |
channel.port2.postMessage(null); | |
}; | |
})(); | |
} | |
else if (global.setTimeout) { | |
schedule = function Promise$_Scheduler(fn) { | |
setTimeout(fn, 4); | |
}; | |
} | |
else { | |
schedule = function Promise$_Scheduler(fn) { | |
fn(); | |
}; | |
} | |
module.exports = schedule; | |
}).call(this,_dereq_("/Users/lance/Projects/stanza.io/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js")) | |
},{"./global.js":105,"/Users/lance/Projects/stanza.io/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js":140}],120:[function(_dereq_,module,exports){ | |
/** | |
* 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. | |
* | |
*/ | |
"use strict"; | |
module.exports = | |
function(Promise, Promise$_CreatePromiseArray, PromiseArray) { | |
var SettledPromiseArray = _dereq_("./settled_promise_array.js")( | |
Promise, PromiseArray); | |
function Promise$_Settle(promises, useBound) { | |
return Promise$_CreatePromiseArray( | |
promises, | |
SettledPromiseArray, | |
useBound === true && promises._isBound() | |
? promises._boundTo | |
: void 0 | |
).promise(); | |
} | |
Promise.settle = function Promise$Settle(promises) { | |
return Promise$_Settle(promises, false); | |
}; | |
Promise.prototype.settle = function Promise$settle() { | |
return Promise$_Settle(this, true); | |
}; | |
}; | |
},{"./settled_promise_array.js":121}],121:[function(_dereq_,module,exports){ | |
/** | |
* 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. | |
* | |
*/ | |
"use strict"; | |
module.exports = function(Promise, PromiseArray) { | |
var PromiseInspection = Promise.PromiseInspection; | |
var util = _dereq_("./util.js"); | |
var inherits = util.inherits; | |
function SettledPromiseArray(values, boundTo) { | |
this.constructor$(values, boundTo); | |
} | |
inherits(SettledPromiseArray, PromiseArray); | |
SettledPromiseArray.prototype._promiseResolved = | |
function SettledPromiseArray$_promiseResolved(index, inspection) { | |
this._values[index] = inspection; | |
var totalResolved = ++this._totalResolved; | |
if (totalResolved >= this._length) { | |
this._resolve(this._values); | |
} | |
}; | |
SettledPromiseArray.prototype._promiseFulfilled = | |
function SettledPromiseArray$_promiseFulfilled(value, index) { | |
if (this._isResolved()) return; | |
var ret = new PromiseInspection(); | |
ret._bitField = 268435456; | |
ret._settledValue = value; | |
this._promiseResolved(index, ret); | |
}; | |
SettledPromiseArray.prototype._promiseRejected = | |
function SettledPromiseArray$_promiseRejected(reason, index) { | |
if (this._isResolved()) return; | |
var ret = new PromiseInspection(); | |
ret._bitField = 134217728; | |
ret._settledValue = reason; | |
this._promiseResolved(index, ret); | |
}; | |
return SettledPromiseArray; | |
}; | |
},{"./util.js":127}],122:[function(_dereq_,module,exports){ | |
/** | |
* 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. | |
* | |
*/ | |
"use strict"; | |
module.exports = | |
function(Promise, Promise$_CreatePromiseArray, PromiseArray, apiRejection) { | |
var SomePromiseArray = _dereq_("./some_promise_array.js")(PromiseArray); | |
function Promise$_Some(promises, howMany, useBound) { | |
if ((howMany | 0) !== howMany || howMany < 0) { | |
return apiRejection("expecting a positive integer"); | |
} | |
var ret = Promise$_CreatePromiseArray( | |
promises, | |
SomePromiseArray, | |
useBound === true && promises._isBound() | |
? promises._boundTo | |
: void 0 | |
); | |
var promise = ret.promise(); | |
if (promise.isRejected()) { | |
return promise; | |
} | |
ret.setHowMany(howMany); | |
ret.init(); | |
return promise; | |
} | |
Promise.some = function Promise$Some(promises, howMany) { | |
return Promise$_Some(promises, howMany, false); | |
}; | |
Promise.prototype.some = function Promise$some(count) { | |
return Promise$_Some(this, count, true); | |
}; | |
}; | |
},{"./some_promise_array.js":123}],123:[function(_dereq_,module,exports){ | |
/** | |
* 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. | |
* | |
*/ | |
"use strict"; | |
module.exports = function (PromiseArray) { | |
var util = _dereq_("./util.js"); | |
var RangeError = _dereq_("./errors.js").RangeError; | |
var inherits = util.inherits; | |
var isArray = util.isArray; | |
function SomePromiseArray(values, boundTo) { | |
this.constructor$(values, boundTo); | |
this._howMany = 0; | |
this._unwrap = false; | |
this._initialized = false; | |
} | |
inherits(SomePromiseArray, PromiseArray); | |
SomePromiseArray.prototype._init = function SomePromiseArray$_init() { | |
if (!this._initialized) { | |
return; | |
} | |
if (this._howMany === 0) { | |
this._resolve([]); | |
return; | |
} | |
this._init$(void 0, -2); | |
var isArrayResolved = isArray(this._values); | |
this._holes = isArrayResolved ? this._values.length - this.length() : 0; | |
if (!this._isResolved() && | |
isArrayResolved && | |
this._howMany > this._canPossiblyFulfill()) { | |
var message = "(Promise.some) input array contains less than " + | |
this._howMany + " promises"; | |
this._reject(new RangeError(message)); | |
} | |
}; | |
SomePromiseArray.prototype.init = function SomePromiseArray$init() { | |
this._initialized = true; | |
this._init(); | |
}; | |
SomePromiseArray.prototype.setUnwrap = function SomePromiseArray$setUnwrap() { | |
this._unwrap = true; | |
}; | |
SomePromiseArray.prototype.howMany = function SomePromiseArray$howMany() { | |
return this._howMany; | |
}; | |
SomePromiseArray.prototype.setHowMany = | |
function SomePromiseArray$setHowMany(count) { | |
if (this._isResolved()) return; | |
this._howMany = count; | |
}; | |
SomePromiseArray.prototype._promiseFulfilled = | |
function SomePromiseArray$_promiseFulfilled(value) { | |
if (this._isResolved()) return; | |
this._addFulfilled(value); | |
if (this._fulfilled() === this.howMany()) { | |
this._values.length = this.howMany(); | |
if (this.howMany() === 1 && this._unwrap) { | |
this._resolve(this._values[0]); | |
} | |
else { | |
this._resolve(this._values); | |
} | |
} | |
}; | |
SomePromiseArray.prototype._promiseRejected = | |
function SomePromiseArray$_promiseRejected(reason) { | |
if (this._isResolved()) return; | |
this._addRejected(reason); | |
if (this.howMany() > this._canPossiblyFulfill()) { | |
if (this._values.length === this.length()) { | |
this._reject([]); | |
} | |
else { | |
this._reject(this._values.slice(this.length() + this._holes)); | |
} | |
} | |
}; | |
SomePromiseArray.prototype._fulfilled = function SomePromiseArray$_fulfilled() { | |
return this._totalResolved; | |
}; | |
SomePromiseArray.prototype._rejected = function SomePromiseArray$_rejected() { | |
return this._values.length - this.length() - this._holes; | |
}; | |
SomePromiseArray.prototype._addRejected = | |
function SomePromiseArray$_addRejected(reason) { | |
this._values.push(reason); | |
}; | |
SomePromiseArray.prototype._addFulfilled = | |
function SomePromiseArray$_addFulfilled(value) { | |
this._values[this._totalResolved++] = value; | |
}; | |
SomePromiseArray.prototype._canPossiblyFulfill = | |
function SomePromiseArray$_canPossiblyFulfill() { | |
return this.length() - this._rejected(); | |
}; | |
return SomePromiseArray; | |
}; | |
},{"./errors.js":99,"./util.js":127}],124:[function(_dereq_,module,exports){ | |
/** | |
* 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. | |
* | |
*/ | |
"use strict"; | |
module.exports = function(Promise) { | |
function PromiseInspection(promise) { | |
if (promise !== void 0) { | |
this._bitField = promise._bitField; | |
this._settledValue = promise.isResolved() | |
? promise._settledValue | |
: void 0; | |
} | |
else { | |
this._bitField = 0; | |
this._settledValue = void 0; | |
} | |
} | |
PromiseInspection.prototype.isFulfilled = | |
Promise.prototype.isFulfilled = function Promise$isFulfilled() { | |
return (this._bitField & 268435456) > 0; | |
}; | |
PromiseInspection.prototype.isRejected = | |
Promise.prototype.isRejected = function Promise$isRejected() { | |
return (this._bitField & 134217728) > 0; | |
}; | |
PromiseInspection.prototype.isPending = | |
Promise.prototype.isPending = function Promise$isPending() { | |
return (this._bitField & 402653184) === 0; | |
}; | |
PromiseInspection.prototype.value = | |
Promise.prototype.value = function Promise$value() { | |
if (!this.isFulfilled()) { | |
throw new TypeError("cannot get fulfillment value of a non-fulfilled promise"); | |
} | |
return this._settledValue; | |
}; | |
PromiseInspection.prototype.error = | |
Promise.prototype.reason = function Promise$reason() { | |
if (!this.isRejected()) { | |
throw new TypeError("cannot get rejection reason of a non-rejected promise"); | |
} | |
return this._settledValue; | |
}; | |
PromiseInspection.prototype.isResolved = | |
Promise.prototype.isResolved = function Promise$isResolved() { | |
return (this._bitField & 402653184) > 0; | |
}; | |
Promise.prototype.inspect = function Promise$inspect() { | |
return new PromiseInspection(this); | |
}; | |
Promise.PromiseInspection = PromiseInspection; | |
}; | |
},{}],125:[function(_dereq_,module,exports){ | |
/** | |
* 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. | |
* | |
*/ | |
"use strict"; | |
module.exports = function(Promise, INTERNAL) { | |
var util = _dereq_("./util.js"); | |
var canAttach = _dereq_("./errors.js").canAttach; | |
var errorObj = util.errorObj; | |
var isObject = util.isObject; | |
function getThen(obj) { | |
try { | |
return obj.then; | |
} | |
catch(e) { | |
errorObj.e = e; | |
return errorObj; | |
} | |
} | |
function Promise$_Cast(obj, originalPromise) { | |
if (isObject(obj)) { | |
if (obj instanceof Promise) { | |
return obj; | |
} | |
else if (isAnyBluebirdPromise(obj)) { | |
var ret = new Promise(INTERNAL); | |
ret._setTrace(void 0); | |
obj._then( | |
ret._fulfillUnchecked, | |
ret._rejectUncheckedCheckError, | |
ret._progressUnchecked, | |
ret, | |
null | |
); | |
ret._setFollowing(); | |
return ret; | |
} | |
var then = getThen(obj); | |
if (then === errorObj) { | |
if (originalPromise !== void 0 && canAttach(then.e)) { | |
originalPromise._attachExtraTrace(then.e); | |
} | |
return Promise.reject(then.e); | |
} | |
else if (typeof then === "function") { | |
return Promise$_doThenable(obj, then, originalPromise); | |
} | |
} | |
return obj; | |
} | |
var hasProp = {}.hasOwnProperty; | |
function isAnyBluebirdPromise(obj) { | |
return hasProp.call(obj, "_promise0"); | |
} | |
function Promise$_doThenable(x, then, originalPromise) { | |
var resolver = Promise.defer(); | |
var called = false; | |
try { | |
then.call( | |
x, | |
Promise$_resolveFromThenable, | |
Promise$_rejectFromThenable, | |
Promise$_progressFromThenable | |
); | |
} | |
catch(e) { | |
if (!called) { | |
called = true; | |
var trace = canAttach(e) ? e : new Error(e + ""); | |
if (originalPromise !== void 0) { | |
originalPromise._attachExtraTrace(trace); | |
} | |
resolver.promise._reject(e, trace); | |
} | |
} | |
return resolver.promise; | |
function Promise$_resolveFromThenable(y) { | |
if (called) return; | |
called = true; | |
if (x === y) { | |
var e = Promise._makeSelfResolutionError(); | |
if (originalPromise !== void 0) { | |
originalPromise._attachExtraTrace(e); | |
} | |
resolver.promise._reject(e, void 0); | |
return; | |
} | |
resolver.resolve(y); | |
} | |
function Promise$_rejectFromThenable(r) { | |
if (called) return; | |
called = true; | |
var trace = canAttach(r) ? r : new Error(r + ""); | |
if (originalPromise !== void 0) { | |
originalPromise._attachExtraTrace(trace); | |
} | |
resolver.promise._reject(r, trace); | |
} | |
function Promise$_progressFromThenable(v) { | |
if (called) return; | |
var promise = resolver.promise; | |
if (typeof promise._progress === "function") { | |
promise._progress(v); | |
} | |
} | |
} | |
Promise._cast = Promise$_Cast; | |
}; | |
},{"./errors.js":99,"./util.js":127}],126:[function(_dereq_,module,exports){ | |
/** | |
* 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. | |
* | |
*/ | |
"use strict"; | |
var global = _dereq_("./global.js"); | |
var setTimeout = function(fn, ms) { | |
var $_len = arguments.length;var args = new Array($_len - 2); for(var $_i = 2; $_i < $_len; ++$_i) {args[$_i - 2] = arguments[$_i];} | |
global.setTimeout(function(){ | |
fn.apply(void 0, args); | |
}, ms); | |
}; | |
module.exports = function(Promise, INTERNAL) { | |
var util = _dereq_("./util.js"); | |
var errors = _dereq_("./errors.js"); | |
var apiRejection = _dereq_("./errors_api_rejection")(Promise); | |
var TimeoutError = Promise.TimeoutError; | |
var afterTimeout = function Promise$_afterTimeout(promise, message, ms) { | |
if (!promise.isPending()) return; | |
if (typeof message !== "string") { | |
message = "operation timed out after" + " " + ms + " ms" | |
} | |
var err = new TimeoutError(message); | |
errors.markAsOriginatingFromRejection(err); | |
promise._attachExtraTrace(err); | |
promise._rejectUnchecked(err); | |
}; | |
var afterDelay = function Promise$_afterDelay(value, promise) { | |
promise._fulfill(value); | |
}; | |
var delay = Promise.delay = function Promise$Delay(value, ms) { | |
if (ms === void 0) { | |
ms = value; | |
value = void 0; | |
} | |
ms = +ms; | |
var maybePromise = Promise._cast(value, void 0); | |
var promise = new Promise(INTERNAL); | |
if (maybePromise instanceof Promise) { | |
if (maybePromise._isBound()) { | |
promise._setBoundTo(maybePromise._boundTo); | |
} | |
if (maybePromise._cancellable()) { | |
promise._setCancellable(); | |
promise._cancellationParent = maybePromise; | |
} | |
promise._setTrace(maybePromise); | |
promise._follow(maybePromise); | |
return promise.then(function(value) { | |
return Promise.delay(value, ms); | |
}); | |
} | |
else { | |
promise._setTrace(void 0); | |
setTimeout(afterDelay, ms, value, promise); | |
} | |
return promise; | |
}; | |
Promise.prototype.delay = function Promise$delay(ms) { | |
return delay(this, ms); | |
}; | |
Promise.prototype.timeout = function Promise$timeout(ms, message) { | |
ms = +ms; | |
var ret = new Promise(INTERNAL); | |
ret._setTrace(this); | |
if (this._isBound()) ret._setBoundTo(this._boundTo); | |
if (this._cancellable()) { | |
ret._setCancellable(); | |
ret._cancellationParent = this; | |
} | |
ret._follow(this); | |
setTimeout(afterTimeout, ms, ret, message, ms); | |
return ret; | |
}; | |
}; | |
},{"./errors.js":99,"./errors_api_rejection":100,"./global.js":105,"./util.js":127}],127:[function(_dereq_,module,exports){ | |
/** | |
* 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. | |
* | |
*/ | |
"use strict"; | |
var global = _dereq_("./global.js"); | |
var es5 = _dereq_("./es5.js"); | |
var haveGetters = (function(){ | |
try { | |
var o = {}; | |
es5.defineProperty(o, "f", { | |
get: function () { | |
return 3; | |
} | |
}); | |
return o.f === 3; | |
} | |
catch (e) { | |
return false; | |
} | |
})(); | |
var canEvaluate = (function() { | |
if (typeof window !== "undefined" && window !== null && | |
typeof window.document !== "undefined" && | |
typeof navigator !== "undefined" && navigator !== null && | |
typeof navigator.appName === "string" && | |
window === global) { | |
return false; | |
} | |
return true; | |
})(); | |
function deprecated(msg) { | |
if (typeof console !== "undefined" && console !== null && | |
typeof console.warn === "function") { | |
console.warn("Bluebird: " + msg); | |
} | |
} | |
var errorObj = {e: {}}; | |
function tryCatch1(fn, receiver, arg) { | |
try { | |
return fn.call(receiver, arg); | |
} | |
catch (e) { | |
errorObj.e = e; | |
return errorObj; | |
} | |
} | |
function tryCatch2(fn, receiver, arg, arg2) { | |
try { | |
return fn.call(receiver, arg, arg2); | |
} | |
catch (e) { | |
errorObj.e = e; | |
return errorObj; | |
} | |
} | |
function tryCatchApply(fn, args, receiver) { | |
try { | |
return fn.apply(receiver, args); | |
} | |
catch (e) { | |
errorObj.e = e; | |
return errorObj; | |
} | |
} | |
var inherits = function(Child, Parent) { | |
var hasProp = {}.hasOwnProperty; | |
function T() { | |
this.constructor = Child; | |
this.constructor$ = Parent; | |
for (var propertyName in Parent.prototype) { | |
if (hasProp.call(Parent.prototype, propertyName) && | |
propertyName.charAt(propertyName.length-1) !== "$" | |
) { | |
this[propertyName + "$"] = Parent.prototype[propertyName]; | |
} | |
} | |
} | |
T.prototype = Parent.prototype; | |
Child.prototype = new T(); | |
return Child.prototype; | |
}; | |
function asString(val) { | |
return typeof val === "string" ? val : ("" + val); | |
} | |
function isPrimitive(val) { | |
return val == null || val === true || val === false || | |
typeof val === "string" || typeof val === "number"; | |
} | |
function isObject(value) { | |
return !isPrimitive(value); | |
} | |
function maybeWrapAsError(maybeError) { | |
if (!isPrimitive(maybeError)) return maybeError; | |
return new Error(asString(maybeError)); | |
} | |
function withAppended(target, appendee) { | |
var len = target.length; | |
var ret = new Array(len + 1); | |
var i; | |
for (i = 0; i < len; ++i) { | |
ret[i] = target[i]; | |
} | |
ret[i] = appendee; | |
return ret; | |
} | |
function notEnumerableProp(obj, name, value) { | |
if (isPrimitive(obj)) return obj; | |
var descriptor = { | |
value: value, | |
configurable: true, | |
enumerable: false, | |
writable: true | |
}; | |
es5.defineProperty(obj, name, descriptor); | |
return obj; | |
} | |
var wrapsPrimitiveReceiver = (function() { | |
return this !== "string"; | |
}).call("string"); | |
function thrower(r) { | |
throw r; | |
} | |
function toFastProperties(obj) { | |
/*jshint -W027*/ | |
function f() {} | |
f.prototype = obj; | |
return f; | |
eval(obj); | |
} | |
var ret = { | |
thrower: thrower, | |
isArray: es5.isArray, | |
haveGetters: haveGetters, | |
notEnumerableProp: notEnumerableProp, | |
isPrimitive: isPrimitive, | |
isObject: isObject, | |
canEvaluate: canEvaluate, | |
deprecated: deprecated, | |
errorObj: errorObj, | |
tryCatch1: tryCatch1, | |
tryCatch2: tryCatch2, | |
tryCatchApply: tryCatchApply, | |
inherits: inherits, | |
withAppended: withAppended, | |
asString: asString, | |
maybeWrapAsError: maybeWrapAsError, | |
wrapsPrimitiveReceiver: wrapsPrimitiveReceiver, | |
toFastProperties: toFastProperties | |
}; | |
module.exports = ret; | |
},{"./es5.js":101,"./global.js":105}],128:[function(_dereq_,module,exports){ | |
// Browser Request | |
// | |
// Licensed under the Apache License, Version 2.0 (the "License"); | |
// you may not use this file except in compliance with the License. | |
// You may obtain a copy of the License at | |
// | |
// http://www.apache.org/licenses/LICENSE-2.0 | |
// | |
// Unless required by applicable law or agreed to in writing, software | |
// distributed under the License is distributed on an "AS IS" BASIS, | |
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
// See the License for the specific language governing permissions and | |
// limitations under the License. | |
var XHR = XMLHttpRequest | |
if (!XHR) throw new Error('missing XMLHttpRequest') | |
module.exports = request | |
request.log = { | |
'trace': noop, 'debug': noop, 'info': noop, 'warn': noop, 'error': noop | |
} | |
var DEFAULT_TIMEOUT = 3 * 60 * 1000 // 3 minutes | |
// | |
// request | |
// | |
function request(options, callback) { | |
// The entry-point to the API: prep the options object and pass the real work to run_xhr. | |
if(typeof callback !== 'function') | |
throw new Error('Bad callback given: ' + callback) | |
if(!options) | |
throw new Error('No options given') | |
var options_onResponse = options.onResponse; // Save this for later. | |
if(typeof options === 'string') | |
options = {'uri':options}; | |
else | |
options = JSON.parse(JSON.stringify(options)); // Use a duplicate for mutating. | |
options.onResponse = options_onResponse // And put it back. | |
if (options.verbose) request.log = getLogger(); | |
if(options.url) { | |
options.uri = options.url; | |
delete options.url; | |
} | |
if(!options.uri && options.uri !== "") | |
throw new Error("options.uri is a required argument"); | |
if(typeof options.uri != "string") | |
throw new Error("options.uri must be a string"); | |
var unsupported_options = ['proxy', '_redirectsFollowed', 'maxRedirects', 'followRedirect'] | |
for (var i = 0; i < unsupported_options.length; i++) | |
if(options[ unsupported_options[i] ]) | |
throw new Error("options." + unsupported_options[i] + " is not supported") | |
options.callback = callback | |
options.method = options.method || 'GET'; | |
options.headers = options.headers || {}; | |
options.body = options.body || null | |
options.timeout = options.timeout || request.DEFAULT_TIMEOUT | |
if(options.headers.host) | |
throw new Error("Options.headers.host is not supported"); | |
if(options.json) { | |
options.headers.accept = options.headers.accept || 'application/json' | |
if(options.method !== 'GET') | |
options.headers['content-type'] = 'application/json' | |
if(typeof options.json !== 'boolean') | |
options.body = JSON.stringify(options.json) | |
else if(typeof options.body !== 'string') | |
options.body = JSON.stringify(options.body) | |
} | |
// If onResponse is boolean true, call back immediately when the response is known, | |
// not when the full request is complete. | |
options.onResponse = options.onResponse || noop | |
if(options.onResponse === true) { | |
options.onResponse = callback | |
options.callback = noop | |
} | |
// XXX Browsers do not like this. | |
//if(options.body) | |
// options.headers['content-length'] = options.body.length; | |
// HTTP basic authentication | |
if(!options.headers.authorization && options.auth) | |
options.headers.authorization = 'Basic ' + b64_enc(options.auth.username + ':' + options.auth.password); | |
return run_xhr(options) | |
} | |
var req_seq = 0 | |
function run_xhr(options) { | |
var xhr = new XHR | |
, timed_out = false | |
, is_cors = is_crossDomain(options.uri) | |
, supports_cors = ('withCredentials' in xhr) | |
req_seq += 1 | |
xhr.seq_id = req_seq | |
xhr.id = req_seq + ': ' + options.method + ' ' + options.uri | |
xhr._id = xhr.id // I know I will type "_id" from habit all the time. | |
if(is_cors && !supports_cors) { | |
var cors_err = new Error('Browser does not support cross-origin request: ' + options.uri) | |
cors_err.cors = 'unsupported' | |
return options.callback(cors_err, xhr) | |
} | |
xhr.timeoutTimer = setTimeout(too_late, options.timeout) | |
function too_late() { | |
timed_out = true | |
var er = new Error('ETIMEDOUT') | |
er.code = 'ETIMEDOUT' | |
er.duration = options.timeout | |
request.log.error('Timeout', { 'id':xhr._id, 'milliseconds':options.timeout }) | |
return options.callback(er, xhr) | |
} | |
// Some states can be skipped over, so remember what is still incomplete. | |
var did = {'response':false, 'loading':false, 'end':false} | |
xhr.onreadystatechange = on_state_change | |
xhr.open(options.method, options.uri, true) // asynchronous | |
if(is_cors) | |
xhr.withCredentials = !! options.withCredentials | |
xhr.send(options.body) | |
return xhr | |
function on_state_change(event) { | |
if(timed_out) | |
return request.log.debug('Ignoring timed out state change', {'state':xhr.readyState, 'id':xhr.id}) | |
request.log.debug('State change', {'state':xhr.readyState, 'id':xhr.id, 'timed_out':timed_out}) | |
if(xhr.readyState === XHR.OPENED) { | |
request.log.debug('Request started', {'id':xhr.id}) | |
for (var key in options.headers) | |
xhr.setRequestHeader(key, options.headers[key]) | |
} | |
else if(xhr.readyState === XHR.HEADERS_RECEIVED) | |
on_response() | |
else if(xhr.readyState === XHR.LOADING) { | |
on_response() | |
on_loading() | |
} | |
else if(xhr.readyState === XHR.DONE) { | |
on_response() | |
on_loading() | |
on_end() | |
} | |
} | |
function on_response() { | |
if(did.response) | |
return | |
did.response = true | |
request.log.debug('Got response', {'id':xhr.id, 'status':xhr.status}) | |
clearTimeout(xhr.timeoutTimer) | |
xhr.statusCode = xhr.status // Node request compatibility | |
// Detect failed CORS requests. | |
if(is_cors && xhr.statusCode == 0) { | |
var cors_err = new Error('CORS request rejected: ' + options.uri) | |
cors_err.cors = 'rejected' | |
// Do not process this request further. | |
did.loading = true | |
did.end = true | |
return options.callback(cors_err, xhr) | |
} | |
options.onResponse(null, xhr) | |
} | |
function on_loading() { | |
if(did.loading) | |
return | |
did.loading = true | |
request.log.debug('Response body loading', {'id':xhr.id}) | |
// TODO: Maybe simulate "data" events by watching xhr.responseText | |
} | |
function on_end() { | |
if(did.end) | |
return | |
did.end = true | |
request.log.debug('Request done', {'id':xhr.id}) | |
xhr.body = xhr.responseText | |
if(options.json) { | |
try { xhr.body = JSON.parse(xhr.responseText) } | |
catch (er) { return options.callback(er, xhr) } | |
} | |
options.callback(null, xhr, xhr.body) | |
} | |
} // request | |
request.withCredentials = false; | |
request.DEFAULT_TIMEOUT = DEFAULT_TIMEOUT; | |
// | |
// defaults | |
// | |
request.defaults = function(options, requester) { | |
var def = function (method) { | |
var d = function (params, callback) { | |
if(typeof params === 'string') | |
params = {'uri': params}; | |
else { | |
params = JSON.parse(JSON.stringify(params)); | |
} | |
for (var i in options) { | |
if (params[i] === undefined) params[i] = options[i] | |
} | |
return method(params, callback) | |
} | |
return d | |
} | |
var de = def(request) | |
de.get = def(request.get) | |
de.post = def(request.post) | |
de.put = def(request.put) | |
de.head = def(request.head) | |
return de | |
} | |
// | |
// HTTP method shortcuts | |
// | |
var shortcuts = [ 'get', 'put', 'post', 'head' ]; | |
shortcuts.forEach(function(shortcut) { | |
var method = shortcut.toUpperCase(); | |
var func = shortcut.toLowerCase(); | |
request[func] = function(opts) { | |
if(typeof opts === 'string') | |
opts = {'method':method, 'uri':opts}; | |
else { | |
opts = JSON.parse(JSON.stringify(opts)); | |
opts.method = method; | |
} | |
var args = [opts].concat(Array.prototype.slice.apply(arguments, [1])); | |
return request.apply(this, args); | |
} | |
}) | |
// | |
// CouchDB shortcut | |
// | |
request.couch = function(options, callback) { | |
if(typeof options === 'string') | |
options = {'uri':options} | |
// Just use the request API to do JSON. | |
options.json = true | |
if(options.body) | |
options.json = options.body | |
delete options.body | |
callback = callback || noop | |
var xhr = request(options, couch_handler) | |
return xhr | |
function couch_handler(er, resp, body) { | |
if(er) | |
return callback(er, resp, body) | |
if((resp.statusCode < 200 || resp.statusCode > 299) && body.error) { | |
// The body is a Couch JSON object indicating the error. | |
er = new Error('CouchDB error: ' + (body.error.reason || body.error.error)) | |
for (var key in body) | |
er[key] = body[key] | |
return callback(er, resp, body); | |
} | |
return callback(er, resp, body); | |
} | |
} | |
// | |
// Utility | |
// | |
function noop() {} | |
function getLogger() { | |
var logger = {} | |
, levels = ['trace', 'debug', 'info', 'warn', 'error'] | |
, level, i | |
for(i = 0; i < levels.length; i++) { | |
level = levels[i] | |
logger[level] = noop | |
if(typeof console !== 'undefined' && console && console[level]) | |
logger[level] = formatted(console, level) | |
} | |
return logger | |
} | |
function formatted(obj, method) { | |
return formatted_logger | |
function formatted_logger(str, context) { | |
if(typeof context === 'object') | |
str += ' ' + JSON.stringify(context) | |
return obj[method].call(obj, str) | |
} | |
} | |
// Return whether a URL is a cross-domain request. | |
function is_crossDomain(url) { | |
var rurl = /^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/ | |
// jQuery #8138, IE may throw an exception when accessing | |
// a field from window.location if document.domain has been set | |
var ajaxLocation | |
try { ajaxLocation = location.href } | |
catch (e) { | |
// Use the href attribute of an A element since IE will modify it given document.location | |
ajaxLocation = document.createElement( "a" ); | |
ajaxLocation.href = ""; | |
ajaxLocation = ajaxLocation.href; | |
} | |
var ajaxLocParts = rurl.exec(ajaxLocation.toLowerCase()) || [] | |
, parts = rurl.exec(url.toLowerCase() ) | |
var result = !!( | |
parts && | |
( parts[1] != ajaxLocParts[1] | |
|| parts[2] != ajaxLocParts[2] | |
|| (parts[3] || (parts[1] === "http:" ? 80 : 443)) != (ajaxLocParts[3] || (ajaxLocParts[1] === "http:" ? 80 : 443)) | |
) | |
) | |
//console.debug('is_crossDomain('+url+') -> ' + result) | |
return result | |
} | |
// MIT License from http://phpjs.org/functions/base64_encode:358 | |
function b64_enc (data) { | |
// Encodes string using MIME base64 algorithm | |
var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; | |
var o1, o2, o3, h1, h2, h3, h4, bits, i = 0, ac = 0, enc="", tmp_arr = []; | |
if (!data) { | |
return data; | |
} | |
// assume utf8 data | |
// data = this.utf8_encode(data+''); | |
do { // pack three octets into four hexets | |
o1 = data.charCodeAt(i++); | |
o2 = data.charCodeAt(i++); | |
o3 = data.charCodeAt(i++); | |
bits = o1<<16 | o2<<8 | o3; | |
h1 = bits>>18 & 0x3f; | |
h2 = bits>>12 & 0x3f; | |
h3 = bits>>6 & 0x3f; | |
h4 = bits & 0x3f; | |
// use hexets to index into b64, and append result to encoded string | |
tmp_arr[ac++] = b64.charAt(h1) + b64.charAt(h2) + b64.charAt(h3) + b64.charAt(h4); | |
} while (i < data.length); | |
enc = tmp_arr.join(''); | |
switch (data.length % 3) { | |
case 1: | |
enc = enc.slice(0, -2) + '=='; | |
break; | |
case 2: | |
enc = enc.slice(0, -1) + '='; | |
break; | |
} | |
return enc; | |
} | |
},{}],129:[function(_dereq_,module,exports){ | |
},{}],130:[function(_dereq_,module,exports){ | |
/*! | |
* The buffer module from node.js, for the browser. | |
* | |
* @author Feross Aboukhadijeh <[email protected]> <http://feross.org> | |
* @license MIT | |
*/ | |
var base64 = _dereq_('base64-js') | |
var ieee754 = _dereq_('ieee754') | |
exports.Buffer = Buffer | |
exports.SlowBuffer = Buffer | |
exports.INSPECT_MAX_BYTES = 50 | |
Buffer.poolSize = 8192 | |
/** | |
* If `Buffer._useTypedArrays`: | |
* === true Use Uint8Array implementation (fastest) | |
* === false Use Object implementation (compatible down to IE6) | |
*/ | |
Buffer._useTypedArrays = (function () { | |
// Detect if browser supports Typed Arrays. Supported browsers are IE 10+, Firefox 4+, | |
// Chrome 7+, Safari 5.1+, Opera 11.6+, iOS 4.2+. If the browser does not support adding | |
// properties to `Uint8Array` instances, then that's the same as no `Uint8Array` support | |
// because we need to be able to add all the node Buffer API methods. This is an issue | |
// in Firefox 4-29. Now fixed: https://bugzilla.mozilla.org/show_bug.cgi?id=695438 | |
try { | |
var buf = new ArrayBuffer(0) | |
var arr = new Uint8Array(buf) | |
arr.foo = function () { return 42 } | |
return 42 === arr.foo() && | |
typeof arr.subarray === 'function' // Chrome 9-10 lack `subarray` | |
} catch (e) { | |
return false | |
} | |
})() | |
/** | |
* Class: Buffer | |
* ============= | |
* | |
* The Buffer constructor returns instances of `Uint8Array` that are augmented | |
* with function properties for all the node `Buffer` API functions. We use | |
* `Uint8Array` so that square bracket notation works as expected -- it returns | |
* a single octet. | |
* | |
* By augmenting the instances, we can avoid modifying the `Uint8Array` | |
* prototype. | |
*/ | |
function Buffer (subject, encoding, noZero) { | |
if (!(this instanceof Buffer)) | |
return new Buffer(subject, encoding, noZero) | |
var type = typeof subject | |
// Workaround: node's base64 implementation allows for non-padded strings | |
// while base64-js does not. | |
if (encoding === 'base64' && type === 'string') { | |
subject = stringtrim(subject) | |
while (subject.length % 4 !== 0) { | |
subject = subject + '=' | |
} | |
} | |
// Find the length | |
var length | |
if (type === 'number') | |
length = coerce(subject) | |
else if (type === 'string') | |
length = Buffer.byteLength(subject, encoding) | |
else if (type === 'object') | |
length = coerce(subject.length) // assume that object is array-like | |
else | |
throw new Error('First argument needs to be a number, array or string.') | |
var buf | |
if (Buffer._useTypedArrays) { | |
// Preferred: Return an augmented `Uint8Array` instance for best performance | |
buf = Buffer._augment(new Uint8Array(length)) | |
} else { | |
// Fallback: Return THIS instance of Buffer (created by `new`) | |
buf = this | |
buf.length = length | |
buf._isBuffer = true | |
} | |
var i | |
if (Buffer._useTypedArrays && typeof subject.byteLength === 'number') { | |
// Speed optimization -- use set if we're copying from a typed array | |
buf._set(subject) | |
} else if (isArrayish(subject)) { | |
// Treat array-ish objects as a byte array | |
for (i = 0; i < length; i++) { | |
if (Buffer.isBuffer(subject)) | |
buf[i] = subject.readUInt8(i) | |
else | |
buf[i] = subject[i] | |
} | |
} else if (type === 'string') { | |
buf.write(subject, 0, encoding) | |
} else if (type === 'number' && !Buffer._useTypedArrays && !noZero) { | |
for (i = 0; i < length; i++) { | |
buf[i] = 0 | |
} | |
} | |
return buf | |
} | |
// STATIC METHODS | |
// ============== | |
Buffer.isEncoding = function (encoding) { | |
switch (String(encoding).toLowerCase()) { | |
case 'hex': | |
case 'utf8': | |
case 'utf-8': | |
case 'ascii': | |
case 'binary': | |
case 'base64': | |
case 'raw': | |
case 'ucs2': | |
case 'ucs-2': | |
case 'utf16le': | |
case 'utf-16le': | |
return true | |
default: | |
return false | |
} | |
} | |
Buffer.isBuffer = function (b) { | |
return !!(b !== null && b !== undefined && b._isBuffer) | |
} | |
Buffer.byteLength = function (str, encoding) { | |
var ret | |
str = str + '' | |
switch (encoding || 'utf8') { | |
case 'hex': | |
ret = str.length / 2 | |
break | |
case 'utf8': | |
case 'utf-8': | |
ret = utf8ToBytes(str).length | |
break | |
case 'ascii': | |
case 'binary': | |
case 'raw': | |
ret = str.length | |
break | |
case 'base64': | |
ret = base64ToBytes(str).length | |
break | |
case 'ucs2': | |
case 'ucs-2': | |
case 'utf16le': | |
case 'utf-16le': | |
ret = str.length * 2 | |
break | |
default: | |
throw new Error('Unknown encoding') | |
} | |
return ret | |
} | |
Buffer.concat = function (list, totalLength) { | |
assert(isArray(list), 'Usage: Buffer.concat(list, [totalLength])\n' + | |
'list should be an Array.') | |
if (list.length === 0) { | |
return new Buffer(0) | |
} else if (list.length === 1) { | |
return list[0] | |
} | |
var i | |
if (typeof totalLength !== 'number') { | |
totalLength = 0 | |
for (i = 0; i < list.length; i++) { | |
totalLength += list[i].length | |
} | |
} | |
var buf = new Buffer(totalLength) | |
var pos = 0 | |
for (i = 0; i < list.length; i++) { | |
var item = list[i] | |
item.copy(buf, pos) | |
pos += item.length | |
} | |
return buf | |
} | |
// BUFFER INSTANCE METHODS | |
// ======================= | |
function _hexWrite (buf, string, offset, length) { | |
offset = Number(offset) || 0 | |
var remaining = buf.length - offset | |
if (!length) { | |
length = remaining | |
} else { | |
length = Number(length) | |
if (length > remaining) { | |
length = remaining | |
} | |
} | |
// must be an even number of digits | |
var strLen = string.length | |
assert(strLen % 2 === 0, 'Invalid hex string') | |
if (length > strLen / 2) { | |
length = strLen / 2 | |
} | |
for (var i = 0; i < length; i++) { | |
var byte = parseInt(string.substr(i * 2, 2), 16) | |
assert(!isNaN(byte), 'Invalid hex string') | |
buf[offset + i] = byte | |
} | |
Buffer._charsWritten = i * 2 | |
return i | |
} | |
function _utf8Write (buf, string, offset, length) { | |
var charsWritten = Buffer._charsWritten = | |
blitBuffer(utf8ToBytes(string), buf, offset, length) | |
return charsWritten | |
} | |
function _asciiWrite (buf, string, offset, length) { | |
var charsWritten = Buffer._charsWritten = | |
blitBuffer(asciiToBytes(string), buf, offset, length) | |
return charsWritten | |
} | |
function _binaryWrite (buf, string, offset, length) { | |
return _asciiWrite(buf, string, offset, length) | |
} | |
function _base64Write (buf, string, offset, length) { | |
var charsWritten = Buffer._charsWritten = | |
blitBuffer(base64ToBytes(string), buf, offset, length) | |
return charsWritten | |
} | |
function _utf16leWrite (buf, string, offset, length) { | |
var charsWritten = Buffer._charsWritten = | |
blitBuffer(utf16leToBytes(string), buf, offset, length) | |
return charsWritten | |
} | |
Buffer.prototype.write = function (string, offset, length, encoding) { | |
// Support both (string, offset, length, encoding) | |
// and the legacy (string, encoding, offset, length) | |
if (isFinite(offset)) { | |
if (!isFinite(length)) { | |
encoding = length | |
length = undefined | |
} | |
} else { // legacy | |
var swap = encoding | |
encoding = offset | |
offset = length | |
length = swap | |
} | |
offset = Number(offset) || 0 | |
var remaining = this.length - offset | |
if (!length) { | |
length = remaining | |
} else { | |
length = Number(length) | |
if (length > remaining) { | |
length = remaining | |
} | |
} | |
encoding = String(encoding || 'utf8').toLowerCase() | |
var ret | |
switch (encoding) { | |
case 'hex': | |
ret = _hexWrite(this, string, offset, length) | |
break | |
case 'utf8': | |
case 'utf-8': | |
ret = _utf8Write(this, string, offset, length) | |
break | |
case 'ascii': | |
ret = _asciiWrite(this, string, offset, length) | |
break | |
case 'binary': | |
ret = _binaryWrite(this, string, offset, length) | |
break | |
case 'base64': | |
ret = _base64Write(this, string, offset, length) | |
break | |
case 'ucs2': | |
case 'ucs-2': | |
case 'utf16le': | |
case 'utf-16le': | |
ret = _utf16leWrite(this, string, offset, length) | |
break | |
default: | |
throw new Error('Unknown encoding') | |
} | |
return ret | |
} | |
Buffer.prototype.toString = function (encoding, start, end) { | |
var self = this | |
encoding = String(encoding || 'utf8').toLowerCase() | |
start = Number(start) || 0 | |
end = (end !== undefined) | |
? Number(end) | |
: end = self.length | |
// Fastpath empty strings | |
if (end === start) | |
return '' | |
var ret | |
switch (encoding) { | |
case 'hex': | |
ret = _hexSlice(self, start, end) | |
break | |
case 'utf8': | |
case 'utf-8': | |
ret = _utf8Slice(self, start, end) | |
break | |
case 'ascii': | |
ret = _asciiSlice(self, start, end) | |
break | |
case 'binary': | |
ret = _binarySlice(self, start, end) | |
break | |
case 'base64': | |
ret = _base64Slice(self, start, end) | |
break | |
case 'ucs2': | |
case 'ucs-2': | |
case 'utf16le': | |
case 'utf-16le': | |
ret = _utf16leSlice(self, start, end) | |
break | |
default: | |
throw new Error('Unknown encoding') | |
} | |
return ret | |
} | |
Buffer.prototype.toJSON = function () { | |
return { | |
type: 'Buffer', | |
data: Array.prototype.slice.call(this._arr || this, 0) | |
} | |
} | |
// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length) | |
Buffer.prototype.copy = function (target, target_start, start, end) { | |
var source = this | |
if (!start) start = 0 | |
if (!end && end !== 0) end = this.length | |
if (!target_start) target_start = 0 | |
// Copy 0 bytes; we're done | |
if (end === start) return | |
if (target.length === 0 || source.length === 0) return | |
// Fatal error conditions | |
assert(end >= start, 'sourceEnd < sourceStart') | |
assert(target_start >= 0 && target_start < target.length, | |
'targetStart out of bounds') | |
assert(start >= 0 && start < source.length, 'sourceStart out of bounds') | |
assert(end >= 0 && end <= source.length, 'sourceEnd out of bounds') | |
// Are we oob? | |
if (end > this.length) | |
end = this.length | |
if (target.length - target_start < end - start) | |
end = target.length - target_start + start | |
var len = end - start | |
if (len < 100 || !Buffer._useTypedArrays) { | |
for (var i = 0; i < len; i++) | |
target[i + target_start] = this[i + start] | |
} else { | |
target._set(this.subarray(start, start + len), target_start) | |
} | |
} | |
function _base64Slice (buf, start, end) { | |
if (start === 0 && end === buf.length) { | |
return base64.fromByteArray(buf) | |
} else { | |
return base64.fromByteArray(buf.slice(start, end)) | |
} | |
} | |
function _utf8Slice (buf, start, end) { | |
var res = '' | |
var tmp = '' | |
end = Math.min(buf.length, end) | |
for (var i = start; i < end; i++) { | |
if (buf[i] <= 0x7F) { | |
res += decodeUtf8Char(tmp) + String.fromCharCode(buf[i]) | |
tmp = '' | |
} else { | |
tmp += '%' + buf[i].toString(16) | |
} | |
} | |
return res + decodeUtf8Char(tmp) | |
} | |
function _asciiSlice (buf, start, end) { | |
var ret = '' | |
end = Math.min(buf.length, end) | |
for (var i = start; i < end; i++) | |
ret += String.fromCharCode(buf[i]) | |
return ret | |
} | |
function _binarySlice (buf, start, end) { | |
return _asciiSlice(buf, start, end) | |
} | |
function _hexSlice (buf, start, end) { | |
var len = buf.length | |
if (!start || start < 0) start = 0 | |
if (!end || end < 0 || end > len) end = len | |
var out = '' | |
for (var i = start; i < end; i++) { | |
out += toHex(buf[i]) | |
} | |
return out | |
} | |
function _utf16leSlice (buf, start, end) { | |
var bytes = buf.slice(start, end) | |
var res = '' | |
for (var i = 0; i < bytes.length; i += 2) { | |
res += String.fromCharCode(bytes[i] + bytes[i+1] * 256) | |
} | |
return res | |
} | |
Buffer.prototype.slice = function (start, end) { | |
var len = this.length | |
start = clamp(start, len, 0) | |
end = clamp(end, len, len) | |
if (Buffer._useTypedArrays) { | |
return Buffer._augment(this.subarray(start, end)) | |
} else { | |
var sliceLen = end - start | |
var newBuf = new Buffer(sliceLen, undefined, true) | |
for (var i = 0; i < sliceLen; i++) { | |
newBuf[i] = this[i + start] | |
} | |
return newBuf | |
} | |
} | |
// `get` will be removed in Node 0.13+ | |
Buffer.prototype.get = function (offset) { | |
console.log('.get() is deprecated. Access using array indexes instead.') | |
return this.readUInt8(offset) | |
} | |
// `set` will be removed in Node 0.13+ | |
Buffer.prototype.set = function (v, offset) { | |
console.log('.set() is deprecated. Access using array indexes instead.') | |
return this.writeUInt8(v, offset) | |
} | |
Buffer.prototype.readUInt8 = function (offset, noAssert) { | |
if (!noAssert) { | |
assert(offset !== undefined && offset !== null, 'missing offset') | |
assert(offset < this.length, 'Trying to read beyond buffer length') | |
} | |
if (offset >= this.length) | |
return | |
return this[offset] | |
} | |
function _readUInt16 (buf, offset, littleEndian, noAssert) { | |
if (!noAssert) { | |
assert(typeof littleEndian === 'boolean', 'missing or invalid endian') | |
assert(offset !== undefined && offset !== null, 'missing offset') | |
assert(offset + 1 < buf.length, 'Trying to read beyond buffer length') | |
} | |
var len = buf.length | |
if (offset >= len) | |
return | |
var val | |
if (littleEndian) { | |
val = buf[offset] | |
if (offset + 1 < len) | |
val |= buf[offset + 1] << 8 | |
} else { | |
val = buf[offset] << 8 | |
if (offset + 1 < len) | |
val |= buf[offset + 1] | |
} | |
return val | |
} | |
Buffer.prototype.readUInt16LE = function (offset, noAssert) { | |
return _readUInt16(this, offset, true, noAssert) | |
} | |
Buffer.prototype.readUInt16BE = function (offset, noAssert) { | |
return _readUInt16(this, offset, false, noAssert) | |
} | |
function _readUInt32 (buf, offset, littleEndian, noAssert) { | |
if (!noAssert) { | |
assert(typeof littleEndian === 'boolean', 'missing or invalid endian') | |
assert(offset !== undefined && offset !== null, 'missing offset') | |
assert(offset + 3 < buf.length, 'Trying to read beyond buffer length') | |
} | |
var len = buf.length | |
if (offset >= len) | |
return | |
var val | |
if (littleEndian) { | |
if (offset + 2 < len) | |
val = buf[offset + 2] << 16 | |
if (offset + 1 < len) | |
val |= buf[offset + 1] << 8 | |
val |= buf[offset] | |
if (offset + 3 < len) | |
val = val + (buf[offset + 3] << 24 >>> 0) | |
} else { | |
if (offset + 1 < len) | |
val = buf[offset + 1] << 16 | |
if (offset + 2 < len) | |
val |= buf[offset + 2] << 8 | |
if (offset + 3 < len) | |
val |= buf[offset + 3] | |
val = val + (buf[offset] << 24 >>> 0) | |
} | |
return val | |
} | |
Buffer.prototype.readUInt32LE = function (offset, noAssert) { | |
return _readUInt32(this, offset, true, noAssert) | |
} | |
Buffer.prototype.readUInt32BE = function (offset, noAssert) { | |
return _readUInt32(this, offset, false, noAssert) | |
} | |
Buffer.prototype.readInt8 = function (offset, noAssert) { | |
if (!noAssert) { | |
assert(offset !== undefined && offset !== null, | |
'missing offset') | |
assert(offset < this.length, 'Trying to read beyond buffer length') | |
} | |
if (offset >= this.length) | |
return | |
var neg = this[offset] & 0x80 | |
if (neg) | |
return (0xff - this[offset] + 1) * -1 | |
else | |
return this[offset] | |
} | |
function _readInt16 (buf, offset, littleEndian, noAssert) { | |
if (!noAssert) { | |
assert(typeof littleEndian === 'boolean', 'missing or invalid endian') | |
assert(offset !== undefined && offset !== null, 'missing offset') | |
assert(offset + 1 < buf.length, 'Trying to read beyond buffer length') | |
} | |
var len = buf.length | |
if (offset >= len) | |
return | |
var val = _readUInt16(buf, offset, littleEndian, true) | |
var neg = val & 0x8000 | |
if (neg) | |
return (0xffff - val + 1) * -1 | |
else | |
return val | |
} | |
Buffer.prototype.readInt16LE = function (offset, noAssert) { | |
return _readInt16(this, offset, true, noAssert) | |
} | |
Buffer.prototype.readInt16BE = function (offset, noAssert) { | |
return _readInt16(this, offset, false, noAssert) | |
} | |
function _readInt32 (buf, offset, littleEndian, noAssert) { | |
if (!noAssert) { | |
assert(typeof littleEndian === 'boolean', 'missing or invalid endian') | |
assert(offset !== undefined && offset !== null, 'missing offset') | |
assert(offset + 3 < buf.length, 'Trying to read beyond buffer length') | |
} | |
var len = buf.length | |
if (offset >= len) | |
return | |
var val = _readUInt32(buf, offset, littleEndian, true) | |
var neg = val & 0x80000000 | |
if (neg) | |
return (0xffffffff - val + 1) * -1 | |
else | |
return val | |
} | |
Buffer.prototype.readInt32LE = function (offset, noAssert) { | |
return _readInt32(this, offset, true, noAssert) | |
} | |
Buffer.prototype.readInt32BE = function (offset, noAssert) { | |
return _readInt32(this, offset, false, noAssert) | |
} | |
function _readFloat (buf, offset, littleEndian, noAssert) { | |
if (!noAssert) { | |
assert(typeof littleEndian === 'boolean', 'missing or invalid endian') | |
assert(offset + 3 < buf.length, 'Trying to read beyond buffer length') | |
} | |
return ieee754.read(buf, offset, littleEndian, 23, 4) | |
} | |
Buffer.prototype.readFloatLE = function (offset, noAssert) { | |
return _readFloat(this, offset, true, noAssert) | |
} | |
Buffer.prototype.readFloatBE = function (offset, noAssert) { | |
return _readFloat(this, offset, false, noAssert) | |
} | |
function _readDouble (buf, offset, littleEndian, noAssert) { | |
if (!noAssert) { | |
assert(typeof littleEndian === 'boolean', 'missing or invalid endian') | |
assert(offset + 7 < buf.length, 'Trying to read beyond buffer length') | |
} | |
return ieee754.read(buf, offset, littleEndian, 52, 8) | |
} | |
Buffer.prototype.readDoubleLE = function (offset, noAssert) { | |
return _readDouble(this, offset, true, noAssert) | |
} | |
Buffer.prototype.readDoubleBE = function (offset, noAssert) { | |
return _readDouble(this, offset, false, noAssert) | |
} | |
Buffer.prototype.writeUInt8 = function (value, offset, noAssert) { | |
if (!noAssert) { | |
assert(value !== undefined && value !== null, 'missing value') | |
assert(offset !== undefined && offset !== null, 'missing offset') | |
assert(offset < this.length, 'trying to write beyond buffer length') | |
verifuint(value, 0xff) | |
} | |
if (offset >= this.length) return | |
this[offset] = value | |
} | |
function _writeUInt16 (buf, value, offset, littleEndian, noAssert) { | |
if (!noAssert) { | |
assert(value !== undefined && value !== null, 'missing value') | |
assert(typeof littleEndian === 'boolean', 'missing or invalid endian') | |
assert(offset !== undefined && offset !== null, 'missing offset') | |
assert(offset + 1 < buf.length, 'trying to write beyond buffer length') | |
verifuint(value, 0xffff) | |
} | |
var len = buf.length | |
if (offset >= len) | |
return | |
for (var i = 0, j = Math.min(len - offset, 2); i < j; i++) { | |
buf[offset + i] = | |
(value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>> | |
(littleEndian ? i : 1 - i) * 8 | |
} | |
} | |
Buffer.prototype.writeUInt16LE = function (value, offset, noAssert) { | |
_writeUInt16(this, value, offset, true, noAssert) | |
} | |
Buffer.prototype.writeUInt16BE = function (value, offset, noAssert) { | |
_writeUInt16(this, value, offset, false, noAssert) | |
} | |
function _writeUInt32 (buf, value, offset, littleEndian, noAssert) { | |
if (!noAssert) { | |
assert(value !== undefined && value !== null, 'missing value') | |
assert(typeof littleEndian === 'boolean', 'missing or invalid endian') | |
assert(offset !== undefined && offset !== null, 'missing offset') | |
assert(offset + 3 < buf.length, 'trying to write beyond buffer length') | |
verifuint(value, 0xffffffff) | |
} | |
var len = buf.length | |
if (offset >= len) | |
return | |
for (var i = 0, j = Math.min(len - offset, 4); i < j; i++) { | |
buf[offset + i] = | |
(value >>> (littleEndian ? i : 3 - i) * 8) & 0xff | |
} | |
} | |
Buffer.prototype.writeUInt32LE = function (value, offset, noAssert) { | |
_writeUInt32(this, value, offset, true, noAssert) | |
} | |
Buffer.prototype.writeUInt32BE = function (value, offset, noAssert) { | |
_writeUInt32(this, value, offset, false, noAssert) | |
} | |
Buffer.prototype.writeInt8 = function (value, offset, noAssert) { | |
if (!noAssert) { | |
assert(value !== undefined && value !== null, 'missing value') | |
assert(offset !== undefined && offset !== null, 'missing offset') | |
assert(offset < this.length, 'Trying to write beyond buffer length') | |
verifsint(value, 0x7f, -0x80) | |
} | |
if (offset >= this.length) | |
return | |
if (value >= 0) | |
this.writeUInt8(value, offset, noAssert) | |
else | |
this.writeUInt8(0xff + value + 1, offset, noAssert) | |
} | |
function _writeInt16 (buf, value, offset, littleEndian, noAssert) { | |
if (!noAssert) { | |
assert(value !== undefined && value !== null, 'missing value') | |
assert(typeof littleEndian === 'boolean', 'missing or invalid endian') | |
assert(offset !== undefined && offset !== null, 'missing offset') | |
assert(offset + 1 < buf.length, 'Trying to write beyond buffer length') | |
verifsint(value, 0x7fff, -0x8000) | |
} | |
var len = buf.length | |
if (offset >= len) | |
return | |
if (value >= 0) | |
_writeUInt16(buf, value, offset, littleEndian, noAssert) | |
else | |
_writeUInt16(buf, 0xffff + value + 1, offset, littleEndian, noAssert) | |
} | |
Buffer.prototype.writeInt16LE = function (value, offset, noAssert) { | |
_writeInt16(this, value, offset, true, noAssert) | |
} | |
Buffer.prototype.writeInt16BE = function (value, offset, noAssert) { | |
_writeInt16(this, value, offset, false, noAssert) | |
} | |
function _writeInt32 (buf, value, offset, littleEndian, noAssert) { | |
if (!noAssert) { | |
assert(value !== undefined && value !== null, 'missing value') | |
assert(typeof littleEndian === 'boolean', 'missing or invalid endian') | |
assert(offset !== undefined && offset !== null, 'missing offset') | |
assert(offset + 3 < buf.length, 'Trying to write beyond buffer length') | |
verifsint(value, 0x7fffffff, -0x80000000) | |
} | |
var len = buf.length | |
if (offset >= len) | |
return | |
if (value >= 0) | |
_writeUInt32(buf, value, offset, littleEndian, noAssert) | |
else | |
_writeUInt32(buf, 0xffffffff + value + 1, offset, littleEndian, noAssert) | |
} | |
Buffer.prototype.writeInt32LE = function (value, offset, noAssert) { | |
_writeInt32(this, value, offset, true, noAssert) | |
} | |
Buffer.prototype.writeInt32BE = function (value, offset, noAssert) { | |
_writeInt32(this, value, offset, false, noAssert) | |
} | |
function _writeFloat (buf, value, offset, littleEndian, noAssert) { | |
if (!noAssert) { | |
assert(value !== undefined && value !== null, 'missing value') | |
assert(typeof littleEndian === 'boolean', 'missing or invalid endian') | |
assert(offset !== undefined && offset !== null, 'missing offset') | |
assert(offset + 3 < buf.length, 'Trying to write beyond buffer length') | |
verifIEEE754(value, 3.4028234663852886e+38, -3.4028234663852886e+38) | |
} | |
var len = buf.length | |
if (offset >= len) | |
return | |
ieee754.write(buf, value, offset, littleEndian, 23, 4) | |
} | |
Buffer.prototype.writeFloatLE = function (value, offset, noAssert) { | |
_writeFloat(this, value, offset, true, noAssert) | |
} | |
Buffer.prototype.writeFloatBE = function (value, offset, noAssert) { | |
_writeFloat(this, value, offset, false, noAssert) | |
} | |
function _writeDouble (buf, value, offset, littleEndian, noAssert) { | |
if (!noAssert) { | |
assert(value !== undefined && value !== null, 'missing value') | |
assert(typeof littleEndian === 'boolean', 'missing or invalid endian') | |
assert(offset !== undefined && offset !== null, 'missing offset') | |
assert(offset + 7 < buf.length, | |
'Trying to write beyond buffer length') | |
verifIEEE754(value, 1.7976931348623157E+308, -1.7976931348623157E+308) | |
} | |
var len = buf.length | |
if (offset >= len) | |
return | |
ieee754.write(buf, value, offset, littleEndian, 52, 8) | |
} | |
Buffer.prototype.writeDoubleLE = function (value, offset, noAssert) { | |
_writeDouble(this, value, offset, true, noAssert) | |
} | |
Buffer.prototype.writeDoubleBE = function (value, offset, noAssert) { | |
_writeDouble(this, value, offset, false, noAssert) | |
} | |
// fill(value, start=0, end=buffer.length) | |
Buffer.prototype.fill = function (value, start, end) { | |
if (!value) value = 0 | |
if (!start) start = 0 | |
if (!end) end = this.length | |
if (typeof value === 'string') { | |
value = value.charCodeAt(0) | |
} | |
assert(typeof value === 'number' && !isNaN(value), 'value is not a number') | |
assert(end >= start, 'end < start') | |
// Fill 0 bytes; we're done | |
if (end === start) return | |
if (this.length === 0) return | |
assert(start >= 0 && start < this.length, 'start out of bounds') | |
assert(end >= 0 && end <= this.length, 'end out of bounds') | |
for (var i = start; i < end; i++) { | |
this[i] = value | |
} | |
} | |
Buffer.prototype.inspect = function () { | |
var out = [] | |
var len = this.length | |
for (var i = 0; i < len; i++) { | |
out[i] = toHex(this[i]) | |
if (i === exports.INSPECT_MAX_BYTES) { | |
out[i + 1] = '...' | |
break | |
} | |
} | |
return '<Buffer ' + out.join(' ') + '>' | |
} | |
/** | |
* Creates a new `ArrayBuffer` with the *copied* memory of the buffer instance. | |
* Added in Node 0.12. Only available in browsers that support ArrayBuffer. | |
*/ | |
Buffer.prototype.toArrayBuffer = function () { | |
if (typeof Uint8Array !== 'undefined') { | |
if (Buffer._useTypedArrays) { | |
return (new Buffer(this)).buffer | |
} else { | |
var buf = new Uint8Array(this.length) | |
for (var i = 0, len = buf.length; i < len; i += 1) | |
buf[i] = this[i] | |
return buf.buffer | |
} | |
} else { | |
throw new Error('Buffer.toArrayBuffer not supported in this browser') | |
} | |
} | |
// HELPER FUNCTIONS | |
// ================ | |
function stringtrim (str) { | |
if (str.trim) return str.trim() | |
return str.replace(/^\s+|\s+$/g, '') | |
} | |
var BP = Buffer.prototype | |
/** | |
* Augment a Uint8Array *instance* (not the Uint8Array class!) with Buffer methods | |
*/ | |
Buffer._augment = function (arr) { | |
arr._isBuffer = true | |
// save reference to original Uint8Array get/set methods before overwriting | |
arr._get = arr.get | |
arr._set = arr.set | |
// deprecated, will be removed in node 0.13+ | |
arr.get = BP.get | |
arr.set = BP.set | |
arr.write = BP.write | |
arr.toString = BP.toString | |
arr.toLocaleString = BP.toString | |
arr.toJSON = BP.toJSON | |
arr.copy = BP.copy | |
arr.slice = BP.slice | |
arr.readUInt8 = BP.readUInt8 | |
arr.readUInt16LE = BP.readUInt16LE | |
arr.readUInt16BE = BP.readUInt16BE | |
arr.readUInt32LE = BP.readUInt32LE | |
arr.readUInt32BE = BP.readUInt32BE | |
arr.readInt8 = BP.readInt8 | |
arr.readInt16LE = BP.readInt16LE | |
arr.readInt16BE = BP.readInt16BE | |
arr.readInt32LE = BP.readInt32LE | |
arr.readInt32BE = BP.readInt32BE | |
arr.readFloatLE = BP.readFloatLE | |
arr.readFloatBE = BP.readFloatBE | |
arr.readDoubleLE = BP.readDoubleLE | |
arr.readDoubleBE = BP.readDoubleBE | |
arr.writeUInt8 = BP.writeUInt8 | |
arr.writeUInt16LE = BP.writeUInt16LE | |
arr.writeUInt16BE = BP.writeUInt16BE | |
arr.writeUInt32LE = BP.writeUInt32LE | |
arr.writeUInt32BE = BP.writeUInt32BE | |
arr.writeInt8 = BP.writeInt8 | |
arr.writeInt16LE = BP.writeInt16LE | |
arr.writeInt16BE = BP.writeInt16BE | |
arr.writeInt32LE = BP.writeInt32LE | |
arr.writeInt32BE = BP.writeInt32BE | |
arr.writeFloatLE = BP.writeFloatLE | |
arr.writeFloatBE = BP.writeFloatBE | |
arr.writeDoubleLE = BP.writeDoubleLE | |
arr.writeDoubleBE = BP.writeDoubleBE | |
arr.fill = BP.fill | |
arr.inspect = BP.inspect | |
arr.toArrayBuffer = BP.toArrayBuffer | |
return arr | |
} | |
// slice(start, end) | |
function clamp (index, len, defaultValue) { | |
if (typeof index !== 'number') return defaultValue | |
index = ~~index; // Coerce to integer. | |
if (index >= len) return len | |
if (index >= 0) return index | |
index += len | |
if (index >= 0) return index | |
return 0 | |
} | |
function coerce (length) { | |
// Coerce length to a number (possibly NaN), round up | |
// in case it's fractional (e.g. 123.456) then do a | |
// double negate to coerce a NaN to 0. Easy, right? | |
length = ~~Math.ceil(+length) | |
return length < 0 ? 0 : length | |
} | |
function isArray (subject) { | |
return (Array.isArray || function (subject) { | |
return Object.prototype.toString.call(subject) === '[object Array]' | |
})(subject) | |
} | |
function isArrayish (subject) { | |
return isArray(subject) || Buffer.isBuffer(subject) || | |
subject && typeof subject === 'object' && | |
typeof subject.length === 'number' | |
} | |
function toHex (n) { | |
if (n < 16) return '0' + n.toString(16) | |
return n.toString(16) | |
} | |
function utf8ToBytes (str) { | |
var byteArray = [] | |
for (var i = 0; i < str.length; i++) { | |
var b = str.charCodeAt(i) | |
if (b <= 0x7F) | |
byteArray.push(str.charCodeAt(i)) | |
else { | |
var start = i | |
if (b >= 0xD800 && b <= 0xDFFF) i++ | |
var h = encodeURIComponent(str.slice(start, i+1)).substr(1).split('%') | |
for (var j = 0; j < h.length; j++) | |
byteArray.push(parseInt(h[j], 16)) | |
} | |
} | |
return byteArray | |
} | |
function asciiToBytes (str) { | |
var byteArray = [] | |
for (var i = 0; i < str.length; i++) { | |
// Node's code seems to be doing this and not & 0x7F.. | |
byteArray.push(str.charCodeAt(i) & 0xFF) | |
} | |
return byteArray | |
} | |
function utf16leToBytes (str) { | |
var c, hi, lo | |
var byteArray = [] | |
for (var i = 0; i < str.length; i++) { | |
c = str.charCodeAt(i) | |
hi = c >> 8 | |
lo = c % 256 | |
byteArray.push(lo) | |
byteArray.push(hi) | |
} | |
return byteArray | |
} | |
function base64ToBytes (str) { | |
return base64.toByteArray(str) | |
} | |
function blitBuffer (src, dst, offset, length) { | |
var pos | |
for (var i = 0; i < length; i++) { | |
if ((i + offset >= dst.length) || (i >= src.length)) | |
break | |
dst[i + offset] = src[i] | |
} | |
return i | |
} | |
function decodeUtf8Char (str) { | |
try { | |
return decodeURIComponent(str) | |
} catch (err) { | |
return String.fromCharCode(0xFFFD) // UTF 8 invalid char | |
} | |
} | |
/* | |
* We have to make sure that the value is a valid integer. This means that it | |
* is non-negative. It has no fractional component and that it does not | |
* exceed the maximum allowed value. | |
*/ | |
function verifuint (value, max) { | |
assert(typeof value === 'number', 'cannot write a non-number as a number') | |
assert(value >= 0, 'specified a negative value for writing an unsigned value') | |
assert(value <= max, 'value is larger than maximum value for type') | |
assert(Math.floor(value) === value, 'value has a fractional component') | |
} | |
function verifsint (value, max, min) { | |
assert(typeof value === 'number', 'cannot write a non-number as a number') | |
assert(value <= max, 'value larger than maximum allowed value') | |
assert(value >= min, 'value smaller than minimum allowed value') | |
assert(Math.floor(value) === value, 'value has a fractional component') | |
} | |
function verifIEEE754 (value, max, min) { | |
assert(typeof value === 'number', 'cannot write a non-number as a number') | |
assert(value <= max, 'value larger than maximum allowed value') | |
assert(value >= min, 'value smaller than minimum allowed value') | |
} | |
function assert (test, message) { | |
if (!test) throw new Error(message || 'Failed assertion') | |
} | |
},{"base64-js":131,"ieee754":132}],131:[function(_dereq_,module,exports){ | |
var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; | |
;(function (exports) { | |
'use strict'; | |
var Arr = (typeof Uint8Array !== 'undefined') | |
? Uint8Array | |
: Array | |
var ZERO = '0'.charCodeAt(0) | |
var PLUS = '+'.charCodeAt(0) | |
var SLASH = '/'.charCodeAt(0) | |
var NUMBER = '0'.charCodeAt(0) | |
var LOWER = 'a'.charCodeAt(0) | |
var UPPER = 'A'.charCodeAt(0) | |
function decode (elt) { | |
var code = elt.charCodeAt(0) | |
if (code === PLUS) | |
return 62 // '+' | |
if (code === SLASH) | |
return 63 // '/' | |
if (code < NUMBER) | |
return -1 //no match | |
if (code < NUMBER + 10) | |
return code - NUMBER + 26 + 26 | |
if (code < UPPER + 26) | |
return code - UPPER | |
if (code < LOWER + 26) | |
return code - LOWER + 26 | |
} | |
function b64ToByteArray (b64) { | |
var i, j, l, tmp, placeHolders, arr | |
if (b64.length % 4 > 0) { | |
throw new Error('Invalid string. Length must be a multiple of 4') | |
} | |
// the number of equal signs (place holders) | |
// if there are two placeholders, than the two characters before it | |
// represent one byte | |
// if there is only one, then the three characters before it represent 2 bytes | |
// this is just a cheap hack to not do indexOf twice | |
var len = b64.length | |
placeHolders = '=' === b64.charAt(len - 2) ? 2 : '=' === b64.charAt(len - 1) ? 1 : 0 | |
// base64 is 4/3 + up to two characters of the original data | |
arr = new Arr(b64.length * 3 / 4 - placeHolders) | |
// if there are placeholders, only get up to the last complete 4 chars | |
l = placeHolders > 0 ? b64.length - 4 : b64.length | |
var L = 0 | |
function push (v) { | |
arr[L++] = v | |
} | |
for (i = 0, j = 0; i < l; i += 4, j += 3) { | |
tmp = (decode(b64.charAt(i)) << 18) | (decode(b64.charAt(i + 1)) << 12) | (decode(b64.charAt(i + 2)) << 6) | decode(b64.charAt(i + 3)) | |
push((tmp & 0xFF0000) >> 16) | |
push((tmp & 0xFF00) >> 8) | |
push(tmp & 0xFF) | |
} | |
if (placeHolders === 2) { | |
tmp = (decode(b64.charAt(i)) << 2) | (decode(b64.charAt(i + 1)) >> 4) | |
push(tmp & 0xFF) | |
} else if (placeHolders === 1) { | |
tmp = (decode(b64.charAt(i)) << 10) | (decode(b64.charAt(i + 1)) << 4) | (decode(b64.charAt(i + 2)) >> 2) | |
push((tmp >> 8) & 0xFF) | |
push(tmp & 0xFF) | |
} | |
return arr | |
} | |
function uint8ToBase64 (uint8) { | |
var i, | |
extraBytes = uint8.length % 3, // if we have 1 byte left, pad 2 bytes | |
output = "", | |
temp, length | |
function encode (num) { | |
return lookup.charAt(num) | |
} | |
function tripletToBase64 (num) { | |
return encode(num >> 18 & 0x3F) + encode(num >> 12 & 0x3F) + encode(num >> 6 & 0x3F) + encode(num & 0x3F) | |
} | |
// go through the array every three bytes, we'll deal with trailing stuff later | |
for (i = 0, length = uint8.length - extraBytes; i < length; i += 3) { | |
temp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2]) | |
output += tripletToBase64(temp) | |
} | |
// pad the end with zeros, but make sure to not forget the extra bytes | |
switch (extraBytes) { | |
case 1: | |
temp = uint8[uint8.length - 1] | |
output += encode(temp >> 2) | |
output += encode((temp << 4) & 0x3F) | |
output += '==' | |
break | |
case 2: | |
temp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1]) | |
output += encode(temp >> 10) | |
output += encode((temp >> 4) & 0x3F) | |
output += encode((temp << 2) & 0x3F) | |
output += '=' | |
break | |
} | |
return output | |
} | |
module.exports.toByteArray = b64ToByteArray | |
module.exports.fromByteArray = uint8ToBase64 | |
}()) | |
},{}],132:[function(_dereq_,module,exports){ | |
exports.read = function(buffer, offset, isLE, mLen, nBytes) { | |
var e, m, | |
eLen = nBytes * 8 - mLen - 1, | |
eMax = (1 << eLen) - 1, | |
eBias = eMax >> 1, | |
nBits = -7, | |
i = isLE ? (nBytes - 1) : 0, | |
d = isLE ? -1 : 1, | |
s = buffer[offset + i]; | |
i += d; | |
e = s & ((1 << (-nBits)) - 1); | |
s >>= (-nBits); | |
nBits += eLen; | |
for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8); | |
m = e & ((1 << (-nBits)) - 1); | |
e >>= (-nBits); | |
nBits += mLen; | |
for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8); | |
if (e === 0) { | |
e = 1 - eBias; | |
} else if (e === eMax) { | |
return m ? NaN : ((s ? -1 : 1) * Infinity); | |
} else { | |
m = m + Math.pow(2, mLen); | |
e = e - eBias; | |
} | |
return (s ? -1 : 1) * m * Math.pow(2, e - mLen); | |
}; | |
exports.write = function(buffer, value, offset, isLE, mLen, nBytes) { | |
var e, m, c, | |
eLen = nBytes * 8 - mLen - 1, | |
eMax = (1 << eLen) - 1, | |
eBias = eMax >> 1, | |
rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0), | |
i = isLE ? 0 : (nBytes - 1), | |
d = isLE ? 1 : -1, | |
s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0; | |
value = Math.abs(value); | |
if (isNaN(value) || value === Infinity) { | |
m = isNaN(value) ? 1 : 0; | |
e = eMax; | |
} else { | |
e = Math.floor(Math.log(value) / Math.LN2); | |
if (value * (c = Math.pow(2, -e)) < 1) { | |
e--; | |
c *= 2; | |
} | |
if (e + eBias >= 1) { | |
value += rt / c; | |
} else { | |
value += rt * Math.pow(2, 1 - eBias); | |
} | |
if (value * c >= 2) { | |
e++; | |
c /= 2; | |
} | |
if (e + eBias >= eMax) { | |
m = 0; | |
e = eMax; | |
} else if (e + eBias >= 1) { | |
m = (value * c - 1) * Math.pow(2, mLen); | |
e = e + eBias; | |
} else { | |
m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen); | |
e = 0; | |
} | |
} | |
for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8); | |
e = (e << mLen) | m; | |
eLen += mLen; | |
for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8); | |
buffer[offset + i - d] |= s * 128; | |
}; | |
},{}],133:[function(_dereq_,module,exports){ | |
var Buffer = _dereq_('buffer').Buffer; | |
var intSize = 4; | |
var zeroBuffer = new Buffer(intSize); zeroBuffer.fill(0); | |
var chrsz = 8; | |
function toArray(buf, bigEndian) { | |
if ((buf.length % intSize) !== 0) { | |
var len = buf.length + (intSize - (buf.length % intSize)); | |
buf = Buffer.concat([buf, zeroBuffer], len); | |
} | |
var arr = []; | |
var fn = bigEndian ? buf.readInt32BE : buf.readInt32LE; | |
for (var i = 0; i < buf.length; i += intSize) { | |
arr.push(fn.call(buf, i)); | |
} | |
return arr; | |
} | |
function toBuffer(arr, size, bigEndian) { | |
var buf = new Buffer(size); | |
var fn = bigEndian ? buf.writeInt32BE : buf.writeInt32LE; | |
for (var i = 0; i < arr.length; i++) { | |
fn.call(buf, arr[i], i * 4, true); | |
} | |
return buf; | |
} | |
function hash(buf, fn, hashSize, bigEndian) { | |
if (!Buffer.isBuffer(buf)) buf = new Buffer(buf); | |
var arr = fn(toArray(buf, bigEndian), buf.length * chrsz); | |
return toBuffer(arr, hashSize, bigEndian); | |
} | |
module.exports = { hash: hash }; | |
},{"buffer":130}],134:[function(_dereq_,module,exports){ | |
var Buffer = _dereq_('buffer').Buffer | |
var sha = _dereq_('./sha') | |
var sha256 = _dereq_('./sha256') | |
var rng = _dereq_('./rng') | |
var md5 = _dereq_('./md5') | |
var algorithms = { | |
sha1: sha, | |
sha256: sha256, | |
md5: md5 | |
} | |
var blocksize = 64 | |
var zeroBuffer = new Buffer(blocksize); zeroBuffer.fill(0) | |
function hmac(fn, key, data) { | |
if(!Buffer.isBuffer(key)) key = new Buffer(key) | |
if(!Buffer.isBuffer(data)) data = new Buffer(data) | |
if(key.length > blocksize) { | |
key = fn(key) | |
} else if(key.length < blocksize) { | |
key = Buffer.concat([key, zeroBuffer], blocksize) | |
} | |
var ipad = new Buffer(blocksize), opad = new Buffer(blocksize) | |
for(var i = 0; i < blocksize; i++) { | |
ipad[i] = key[i] ^ 0x36 | |
opad[i] = key[i] ^ 0x5C | |
} | |
var hash = fn(Buffer.concat([ipad, data])) | |
return fn(Buffer.concat([opad, hash])) | |
} | |
function hash(alg, key) { | |
alg = alg || 'sha1' | |
var fn = algorithms[alg] | |
var bufs = [] | |
var length = 0 | |
if(!fn) error('algorithm:', alg, 'is not yet supported') | |
return { | |
update: function (data) { | |
if(!Buffer.isBuffer(data)) data = new Buffer(data) | |
bufs.push(data) | |
length += data.length | |
return this | |
}, | |
digest: function (enc) { | |
var buf = Buffer.concat(bufs) | |
var r = key ? hmac(fn, key, buf) : fn(buf) | |
bufs = null | |
return enc ? r.toString(enc) : r | |
} | |
} | |
} | |
function error () { | |
var m = [].slice.call(arguments).join(' ') | |
throw new Error([ | |
m, | |
'we accept pull requests', | |
'http://github.com/dominictarr/crypto-browserify' | |
].join('\n')) | |
} | |
exports.createHash = function (alg) { return hash(alg) } | |
exports.createHmac = function (alg, key) { return hash(alg, key) } | |
exports.randomBytes = function(size, callback) { | |
if (callback && callback.call) { | |
try { | |
callback.call(this, undefined, new Buffer(rng(size))) | |
} catch (err) { callback(err) } | |
} else { | |
return new Buffer(rng(size)) | |
} | |
} | |
function each(a, f) { | |
for(var i in a) | |
f(a[i], i) | |
} | |
// the least I can do is make error messages for the rest of the node.js/crypto api. | |
each(['createCredentials' | |
, 'createCipher' | |
, 'createCipheriv' | |
, 'createDecipher' | |
, 'createDecipheriv' | |
, 'createSign' | |
, 'createVerify' | |
, 'createDiffieHellman' | |
, 'pbkdf2'], function (name) { | |
exports[name] = function () { | |
error('sorry,', name, 'is not implemented yet') | |
} | |
}) | |
},{"./md5":135,"./rng":136,"./sha":137,"./sha256":138,"buffer":130}],135:[function(_dereq_,module,exports){ | |
/* | |
* A JavaScript implementation of the RSA Data Security, Inc. MD5 Message | |
* Digest Algorithm, as defined in RFC 1321. | |
* Version 2.1 Copyright (C) Paul Johnston 1999 - 2002. | |
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet | |
* Distributed under the BSD License | |
* See http://pajhome.org.uk/crypt/md5 for more info. | |
*/ | |
var helpers = _dereq_('./helpers'); | |
/* | |
* Perform a simple self-test to see if the VM is working | |
*/ | |
function md5_vm_test() | |
{ | |
return hex_md5("abc") == "900150983cd24fb0d6963f7d28e17f72"; | |
} | |
/* | |
* Calculate the MD5 of an array of little-endian words, and a bit length | |
*/ | |
function core_md5(x, len) | |
{ | |
/* append padding */ | |
x[len >> 5] |= 0x80 << ((len) % 32); | |
x[(((len + 64) >>> 9) << 4) + 14] = len; | |
var a = 1732584193; | |
var b = -271733879; | |
var c = -1732584194; | |
var d = 271733878; | |
for(var i = 0; i < x.length; i += 16) | |
{ | |
var olda = a; | |
var oldb = b; | |
var oldc = c; | |
var oldd = d; | |
a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936); | |
d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586); | |
c = md5_ff(c, d, a, b, x[i+ 2], 17, 606105819); | |
b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330); | |
a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897); | |
d = md5_ff(d, a, b, c, x[i+ 5], 12, 1200080426); | |
c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341); | |
b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983); | |
a = md5_ff(a, b, c, d, x[i+ 8], 7 , 1770035416); | |
d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417); | |
c = md5_ff(c, d, a, b, x[i+10], 17, -42063); | |
b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162); | |
a = md5_ff(a, b, c, d, x[i+12], 7 , 1804603682); | |
d = md5_ff(d, a, b, c, x[i+13], 12, -40341101); | |
c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290); | |
b = md5_ff(b, c, d, a, x[i+15], 22, 1236535329); | |
a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510); | |
d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632); | |
c = md5_gg(c, d, a, b, x[i+11], 14, 643717713); | |
b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302); | |
a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691); | |
d = md5_gg(d, a, b, c, x[i+10], 9 , 38016083); | |
c = md5_gg(c, d, a, b, x[i+15], 14, -660478335); | |
b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848); | |
a = md5_gg(a, b, c, d, x[i+ 9], 5 , 568446438); | |
d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690); | |
c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961); | |
b = md5_gg(b, c, d, a, x[i+ 8], 20, 1163531501); | |
a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467); | |
d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784); | |
c = md5_gg(c, d, a, b, x[i+ 7], 14, 1735328473); | |
b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734); | |
a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558); | |
d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463); | |
c = md5_hh(c, d, a, b, x[i+11], 16, 1839030562); | |
b = md5_hh(b, c, d, a, x[i+14], 23, -35309556); | |
a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060); | |
d = md5_hh(d, a, b, c, x[i+ 4], 11, 1272893353); | |
c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632); | |
b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640); | |
a = md5_hh(a, b, c, d, x[i+13], 4 , 681279174); | |
d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222); | |
c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979); | |
b = md5_hh(b, c, d, a, x[i+ 6], 23, 76029189); | |
a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487); | |
d = md5_hh(d, a, b, c, x[i+12], 11, -421815835); | |
c = md5_hh(c, d, a, b, x[i+15], 16, 530742520); | |
b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651); | |
a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844); | |
d = md5_ii(d, a, b, c, x[i+ 7], 10, 1126891415); | |
c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905); | |
b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055); | |
a = md5_ii(a, b, c, d, x[i+12], 6 , 1700485571); | |
d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606); | |
c = md5_ii(c, d, a, b, x[i+10], 15, -1051523); | |
b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799); | |
a = md5_ii(a, b, c, d, x[i+ 8], 6 , 1873313359); | |
d = md5_ii(d, a, b, c, x[i+15], 10, -30611744); | |
c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380); | |
b = md5_ii(b, c, d, a, x[i+13], 21, 1309151649); | |
a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070); | |
d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379); | |
c = md5_ii(c, d, a, b, x[i+ 2], 15, 718787259); | |
b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551); | |
a = safe_add(a, olda); | |
b = safe_add(b, oldb); | |
c = safe_add(c, oldc); | |
d = safe_add(d, oldd); | |
} | |
return Array(a, b, c, d); | |
} | |
/* | |
* These functions implement the four basic operations the algorithm uses. | |
*/ | |
function md5_cmn(q, a, b, x, s, t) | |
{ | |
return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b); | |
} | |
function md5_ff(a, b, c, d, x, s, t) | |
{ | |
return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t); | |
} | |
function md5_gg(a, b, c, d, x, s, t) | |
{ | |
return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t); | |
} | |
function md5_hh(a, b, c, d, x, s, t) | |
{ | |
return md5_cmn(b ^ c ^ d, a, b, x, s, t); | |
} | |
function md5_ii(a, b, c, d, x, s, t) | |
{ | |
return md5_cmn(c ^ (b | (~d)), a, b, x, s, t); | |
} | |
/* | |
* Add integers, wrapping at 2^32. This uses 16-bit operations internally | |
* to work around bugs in some JS interpreters. | |
*/ | |
function safe_add(x, y) | |
{ | |
var lsw = (x & 0xFFFF) + (y & 0xFFFF); | |
var msw = (x >> 16) + (y >> 16) + (lsw >> 16); | |
return (msw << 16) | (lsw & 0xFFFF); | |
} | |
/* | |
* Bitwise rotate a 32-bit number to the left. | |
*/ | |
function bit_rol(num, cnt) | |
{ | |
return (num << cnt) | (num >>> (32 - cnt)); | |
} | |
module.exports = function md5(buf) { | |
return helpers.hash(buf, core_md5, 16); | |
}; | |
},{"./helpers":133}],136:[function(_dereq_,module,exports){ | |
// Original code adapted from Robert Kieffer. | |
// details at https://github.com/broofa/node-uuid | |
(function() { | |
var _global = this; | |
var mathRNG, whatwgRNG; | |
// NOTE: Math.random() does not guarantee "cryptographic quality" | |
mathRNG = function(size) { | |
var bytes = new Array(size); | |
var r; | |
for (var i = 0, r; i < size; i++) { | |
if ((i & 0x03) == 0) r = Math.random() * 0x100000000; | |
bytes[i] = r >>> ((i & 0x03) << 3) & 0xff; | |
} | |
return bytes; | |
} | |
if (_global.crypto && crypto.getRandomValues) { | |
whatwgRNG = function(size) { | |
var bytes = new Uint8Array(size); | |
crypto.getRandomValues(bytes); | |
return bytes; | |
} | |
} | |
module.exports = whatwgRNG || mathRNG; | |
}()) | |
},{}],137:[function(_dereq_,module,exports){ | |
/* | |
* A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined | |
* in FIPS PUB 180-1 | |
* Version 2.1a Copyright Paul Johnston 2000 - 2002. | |
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet | |
* Distributed under the BSD License | |
* See http://pajhome.org.uk/crypt/md5 for details. | |
*/ | |
var helpers = _dereq_('./helpers'); | |
/* | |
* Calculate the SHA-1 of an array of big-endian words, and a bit length | |
*/ | |
function core_sha1(x, len) | |
{ | |
/* append padding */ | |
x[len >> 5] |= 0x80 << (24 - len % 32); | |
x[((len + 64 >> 9) << 4) + 15] = len; | |
var w = Array(80); | |
var a = 1732584193; | |
var b = -271733879; | |
var c = -1732584194; | |
var d = 271733878; | |
var e = -1009589776; | |
for(var i = 0; i < x.length; i += 16) | |
{ | |
var olda = a; | |
var oldb = b; | |
var oldc = c; | |
var oldd = d; | |
var olde = e; | |
for(var j = 0; j < 80; j++) | |
{ | |
if(j < 16) w[j] = x[i + j]; | |
else w[j] = rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1); | |
var t = safe_add(safe_add(rol(a, 5), sha1_ft(j, b, c, d)), | |
safe_add(safe_add(e, w[j]), sha1_kt(j))); | |
e = d; | |
d = c; | |
c = rol(b, 30); | |
b = a; | |
a = t; | |
} | |
a = safe_add(a, olda); | |
b = safe_add(b, oldb); | |
c = safe_add(c, oldc); | |
d = safe_add(d, oldd); | |
e = safe_add(e, olde); | |
} | |
return Array(a, b, c, d, e); | |
} | |
/* | |
* Perform the appropriate triplet combination function for the current | |
* iteration | |
*/ | |
function sha1_ft(t, b, c, d) | |
{ | |
if(t < 20) return (b & c) | ((~b) & d); | |
if(t < 40) return b ^ c ^ d; | |
if(t < 60) return (b & c) | (b & d) | (c & d); | |
return b ^ c ^ d; | |
} | |
/* | |
* Determine the appropriate additive constant for the current iteration | |
*/ | |
function sha1_kt(t) | |
{ | |
return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 : | |
(t < 60) ? -1894007588 : -899497514; | |
} | |
/* | |
* Add integers, wrapping at 2^32. This uses 16-bit operations internally | |
* to work around bugs in some JS interpreters. | |
*/ | |
function safe_add(x, y) | |
{ | |
var lsw = (x & 0xFFFF) + (y & 0xFFFF); | |
var msw = (x >> 16) + (y >> 16) + (lsw >> 16); | |
return (msw << 16) | (lsw & 0xFFFF); | |
} | |
/* | |
* Bitwise rotate a 32-bit number to the left. | |
*/ | |
function rol(num, cnt) | |
{ | |
return (num << cnt) | (num >>> (32 - cnt)); | |
} | |
module.exports = function sha1(buf) { | |
return helpers.hash(buf, core_sha1, 20, true); | |
}; | |
},{"./helpers":133}],138:[function(_dereq_,module,exports){ | |
/** | |
* A JavaScript implementation of the Secure Hash Algorithm, SHA-256, as defined | |
* in FIPS 180-2 | |
* Version 2.2-beta Copyright Angel Marin, Paul Johnston 2000 - 2009. | |
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet | |
* | |
*/ | |
var helpers = _dereq_('./helpers'); | |
var safe_add = function(x, y) { | |
var lsw = (x & 0xFFFF) + (y & 0xFFFF); | |
var msw = (x >> 16) + (y >> 16) + (lsw >> 16); | |
return (msw << 16) | (lsw & 0xFFFF); | |
}; | |
var S = function(X, n) { | |
return (X >>> n) | (X << (32 - n)); | |
}; | |
var R = function(X, n) { | |
return (X >>> n); | |
}; | |
var Ch = function(x, y, z) { | |
return ((x & y) ^ ((~x) & z)); | |
}; | |
var Maj = function(x, y, z) { | |
return ((x & y) ^ (x & z) ^ (y & z)); | |
}; | |
var Sigma0256 = function(x) { | |
return (S(x, 2) ^ S(x, 13) ^ S(x, 22)); | |
}; | |
var Sigma1256 = function(x) { | |
return (S(x, 6) ^ S(x, 11) ^ S(x, 25)); | |
}; | |
var Gamma0256 = function(x) { | |
return (S(x, 7) ^ S(x, 18) ^ R(x, 3)); | |
}; | |
var Gamma1256 = function(x) { | |
return (S(x, 17) ^ S(x, 19) ^ R(x, 10)); | |
}; | |
var core_sha256 = function(m, l) { | |
var K = new Array(0x428A2F98,0x71374491,0xB5C0FBCF,0xE9B5DBA5,0x3956C25B,0x59F111F1,0x923F82A4,0xAB1C5ED5,0xD807AA98,0x12835B01,0x243185BE,0x550C7DC3,0x72BE5D74,0x80DEB1FE,0x9BDC06A7,0xC19BF174,0xE49B69C1,0xEFBE4786,0xFC19DC6,0x240CA1CC,0x2DE92C6F,0x4A7484AA,0x5CB0A9DC,0x76F988DA,0x983E5152,0xA831C66D,0xB00327C8,0xBF597FC7,0xC6E00BF3,0xD5A79147,0x6CA6351,0x14292967,0x27B70A85,0x2E1B2138,0x4D2C6DFC,0x53380D13,0x650A7354,0x766A0ABB,0x81C2C92E,0x92722C85,0xA2BFE8A1,0xA81A664B,0xC24B8B70,0xC76C51A3,0xD192E819,0xD6990624,0xF40E3585,0x106AA070,0x19A4C116,0x1E376C08,0x2748774C,0x34B0BCB5,0x391C0CB3,0x4ED8AA4A,0x5B9CCA4F,0x682E6FF3,0x748F82EE,0x78A5636F,0x84C87814,0x8CC70208,0x90BEFFFA,0xA4506CEB,0xBEF9A3F7,0xC67178F2); | |
var HASH = new Array(0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19); | |
var W = new Array(64); | |
var a, b, c, d, e, f, g, h, i, j; | |
var T1, T2; | |
/* append padding */ | |
m[l >> 5] |= 0x80 << (24 - l % 32); | |
m[((l + 64 >> 9) << 4) + 15] = l; | |
for (var i = 0; i < m.length; i += 16) { | |
a = HASH[0]; b = HASH[1]; c = HASH[2]; d = HASH[3]; e = HASH[4]; f = HASH[5]; g = HASH[6]; h = HASH[7]; | |
for (var j = 0; j < 64; j++) { | |
if (j < 16) { | |
W[j] = m[j + i]; | |
} else { | |
W[j] = safe_add(safe_add(safe_add(Gamma1256(W[j - 2]), W[j - 7]), Gamma0256(W[j - 15])), W[j - 16]); | |
} | |
T1 = safe_add(safe_add(safe_add(safe_add(h, Sigma1256(e)), Ch(e, f, g)), K[j]), W[j]); | |
T2 = safe_add(Sigma0256(a), Maj(a, b, c)); | |
h = g; g = f; f = e; e = safe_add(d, T1); d = c; c = b; b = a; a = safe_add(T1, T2); | |
} | |
HASH[0] = safe_add(a, HASH[0]); HASH[1] = safe_add(b, HASH[1]); HASH[2] = safe_add(c, HASH[2]); HASH[3] = safe_add(d, HASH[3]); | |
HASH[4] = safe_add(e, HASH[4]); HASH[5] = safe_add(f, HASH[5]); HASH[6] = safe_add(g, HASH[6]); HASH[7] = safe_add(h, HASH[7]); | |
} | |
return HASH; | |
}; | |
module.exports = function sha256(buf) { | |
return helpers.hash(buf, core_sha256, 32, true); | |
}; | |
},{"./helpers":133}],139:[function(_dereq_,module,exports){ | |
if (typeof Object.create === 'function') { | |
// implementation from standard node.js 'util' module | |
module.exports = function inherits(ctor, superCtor) { | |
ctor.super_ = superCtor | |
ctor.prototype = Object.create(superCtor.prototype, { | |
constructor: { | |
value: ctor, | |
enumerable: false, | |
writable: true, | |
configurable: true | |
} | |
}); | |
}; | |
} else { | |
// old school shim for old browsers | |
module.exports = function inherits(ctor, superCtor) { | |
ctor.super_ = superCtor | |
var TempCtor = function () {} | |
TempCtor.prototype = superCtor.prototype | |
ctor.prototype = new TempCtor() | |
ctor.prototype.constructor = ctor | |
} | |
} | |
},{}],140:[function(_dereq_,module,exports){ | |
// shim for using process in browser | |
var process = module.exports = {}; | |
process.nextTick = (function () { | |
var canSetImmediate = typeof window !== 'undefined' | |
&& window.setImmediate; | |
var canPost = typeof window !== 'undefined' | |
&& window.postMessage && window.addEventListener | |
; | |
if (canSetImmediate) { | |
return function (f) { return window.setImmediate(f) }; | |
} | |
if (canPost) { | |
var queue = []; | |
window.addEventListener('message', function (ev) { | |
var source = ev.source; | |
if ((source === window || source === null) && ev.data === 'process-tick') { | |
ev.stopPropagation(); | |
if (queue.length > 0) { | |
var fn = queue.shift(); | |
fn(); | |
} | |
} | |
}, true); | |
return function nextTick(fn) { | |
queue.push(fn); | |
window.postMessage('process-tick', '*'); | |
}; | |
} | |
return function nextTick(fn) { | |
setTimeout(fn, 0); | |
}; | |
})(); | |
process.title = 'browser'; | |
process.browser = true; | |
process.env = {}; | |
process.argv = []; | |
function noop() {} | |
process.on = noop; | |
process.once = noop; | |
process.off = noop; | |
process.emit = noop; | |
process.binding = function (name) { | |
throw new Error('process.binding is not supported'); | |
} | |
// TODO(shtylman) | |
process.cwd = function () { return '/' }; | |
process.chdir = function (dir) { | |
throw new Error('process.chdir is not supported'); | |
}; | |
},{}],141:[function(_dereq_,module,exports){ | |
module.exports = function isBuffer(arg) { | |
return arg && typeof arg === 'object' | |
&& typeof arg.copy === 'function' | |
&& typeof arg.fill === 'function' | |
&& typeof arg.readUInt8 === 'function'; | |
} | |
},{}],142:[function(_dereq_,module,exports){ | |
(function (process,global){ | |
// Copyright Joyent, Inc. and other Node contributors. | |
// | |
// 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. | |
var formatRegExp = /%[sdj%]/g; | |
exports.format = function(f) { | |
if (!isString(f)) { | |
var objects = []; | |
for (var i = 0; i < arguments.length; i++) { | |
objects.push(inspect(arguments[i])); | |
} | |
return objects.join(' '); | |
} | |
var i = 1; | |
var args = arguments; | |
var len = args.length; | |
var str = String(f).replace(formatRegExp, function(x) { | |
if (x === '%%') return '%'; | |
if (i >= len) return x; | |
switch (x) { | |
case '%s': return String(args[i++]); | |
case '%d': return Number(args[i++]); | |
case '%j': | |
try { | |
return JSON.stringify(args[i++]); | |
} catch (_) { | |
return '[Circular]'; | |
} | |
default: | |
return x; | |
} | |
}); | |
for (var x = args[i]; i < len; x = args[++i]) { | |
if (isNull(x) || !isObject(x)) { | |
str += ' ' + x; | |
} else { | |
str += ' ' + inspect(x); | |
} | |
} | |
return str; | |
}; | |
// Mark that a method should not be used. | |
// Returns a modified function which warns once by default. | |
// If --no-deprecation is set, then it is a no-op. | |
exports.deprecate = function(fn, msg) { | |
// Allow for deprecating things in the process of starting up. | |
if (isUndefined(global.process)) { | |
return function() { | |
return exports.deprecate(fn, msg).apply(this, arguments); | |
}; | |
} | |
if (process.noDeprecation === true) { | |
return fn; | |
} | |
var warned = false; | |
function deprecated() { | |
if (!warned) { | |
if (process.throwDeprecation) { | |
throw new Error(msg); | |
} else if (process.traceDeprecation) { | |
console.trace(msg); | |
} else { | |
console.error(msg); | |
} | |
warned = true; | |
} | |
return fn.apply(this, arguments); | |
} | |
return deprecated; | |
}; | |
var debugs = {}; | |
var debugEnviron; | |
exports.debuglog = function(set) { | |
if (isUndefined(debugEnviron)) | |
debugEnviron = process.env.NODE_DEBUG || ''; | |
set = set.toUpperCase(); | |
if (!debugs[set]) { | |
if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) { | |
var pid = process.pid; | |
debugs[set] = function() { | |
var msg = exports.format.apply(exports, arguments); | |
console.error('%s %d: %s', set, pid, msg); | |
}; | |
} else { | |
debugs[set] = function() {}; | |
} | |
} | |
return debugs[set]; | |
}; | |
/** | |
* Echos the value of a value. Trys to print the value out | |
* in the best way possible given the different types. | |
* | |
* @param {Object} obj The object to print out. | |
* @param {Object} opts Optional options object that alters the output. | |
*/ | |
/* legacy: obj, showHidden, depth, colors*/ | |
function inspect(obj, opts) { | |
// default options | |
var ctx = { | |
seen: [], | |
stylize: stylizeNoColor | |
}; | |
// legacy... | |
if (arguments.length >= 3) ctx.depth = arguments[2]; | |
if (arguments.length >= 4) ctx.colors = arguments[3]; | |
if (isBoolean(opts)) { | |
// legacy... | |
ctx.showHidden = opts; | |
} else if (opts) { | |
// got an "options" object | |
exports._extend(ctx, opts); | |
} | |
// set default options | |
if (isUndefined(ctx.showHidden)) ctx.showHidden = false; | |
if (isUndefined(ctx.depth)) ctx.depth = 2; | |
if (isUndefined(ctx.colors)) ctx.colors = false; | |
if (isUndefined(ctx.customInspect)) ctx.customInspect = true; | |
if (ctx.colors) ctx.stylize = stylizeWithColor; | |
return formatValue(ctx, obj, ctx.depth); | |
} | |
exports.inspect = inspect; | |
// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics | |
inspect.colors = { | |
'bold' : [1, 22], | |
'italic' : [3, 23], | |
'underline' : [4, 24], | |
'inverse' : [7, 27], | |
'white' : [37, 39], | |
'grey' : [90, 39], | |
'black' : [30, 39], | |
'blue' : [34, 39], | |
'cyan' : [36, 39], | |
'green' : [32, 39], | |
'magenta' : [35, 39], | |
'red' : [31, 39], | |
'yellow' : [33, 39] | |
}; | |
// Don't use 'blue' not visible on cmd.exe | |
inspect.styles = { | |
'special': 'cyan', | |
'number': 'yellow', | |
'boolean': 'yellow', | |
'undefined': 'grey', | |
'null': 'bold', | |
'string': 'green', | |
'date': 'magenta', | |
// "name": intentionally not styling | |
'regexp': 'red' | |
}; | |
function stylizeWithColor(str, styleType) { | |
var style = inspect.styles[styleType]; | |
if (style) { | |
return '\u001b[' + inspect.colors[style][0] + 'm' + str + | |
'\u001b[' + inspect.colors[style][1] + 'm'; | |
} else { | |
return str; | |
} | |
} | |
function stylizeNoColor(str, styleType) { | |
return str; | |
} | |
function arrayToHash(array) { | |
var hash = {}; | |
array.forEach(function(val, idx) { | |
hash[val] = true; | |
}); | |
return hash; | |
} | |
function formatValue(ctx, value, recurseTimes) { | |
// Provide a hook for user-specified inspect functions. | |
// Check that value is an object with an inspect function on it | |
if (ctx.customInspect && | |
value && | |
isFunction(value.inspect) && | |
// Filter out the util module, it's inspect function is special | |
value.inspect !== exports.inspect && | |
// Also filter out any prototype objects using the circular check. | |
!(value.constructor && value.constructor.prototype === value)) { | |
var ret = value.inspect(recurseTimes, ctx); | |
if (!isString(ret)) { | |
ret = formatValue(ctx, ret, recurseTimes); | |
} | |
return ret; | |
} | |
// Primitive types cannot have properties | |
var primitive = formatPrimitive(ctx, value); | |
if (primitive) { | |
return primitive; | |
} | |
// Look up the keys of the object. | |
var keys = Object.keys(value); | |
var visibleKeys = arrayToHash(keys); | |
if (ctx.showHidden) { | |
keys = Object.getOwnPropertyNames(value); | |
} | |
// IE doesn't make error fields non-enumerable | |
// http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx | |
if (isError(value) | |
&& (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) { | |
return formatError(value); | |
} | |
// Some type of object without properties can be shortcutted. | |
if (keys.length === 0) { | |
if (isFunction(value)) { | |
var name = value.name ? ': ' + value.name : ''; | |
return ctx.stylize('[Function' + name + ']', 'special'); | |
} | |
if (isRegExp(value)) { | |
return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); | |
} | |
if (isDate(value)) { | |
return ctx.stylize(Date.prototype.toString.call(value), 'date'); | |
} | |
if (isError(value)) { | |
return formatError(value); | |
} | |
} | |
var base = '', array = false, braces = ['{', '}']; | |
// Make Array say that they are Array | |
if (isArray(value)) { | |
array = true; | |
braces = ['[', ']']; | |
} | |
// Make functions say that they are functions | |
if (isFunction(value)) { | |
var n = value.name ? ': ' + value.name : ''; | |
base = ' [Function' + n + ']'; | |
} | |
// Make RegExps say that they are RegExps | |
if (isRegExp(value)) { | |
base = ' ' + RegExp.prototype.toString.call(value); | |
} | |
// Make dates with properties first say the date | |
if (isDate(value)) { | |
base = ' ' + Date.prototype.toUTCString.call(value); | |
} | |
// Make error with message first say the error | |
if (isError(value)) { | |
base = ' ' + formatError(value); | |
} | |
if (keys.length === 0 && (!array || value.length == 0)) { | |
return braces[0] + base + braces[1]; | |
} | |
if (recurseTimes < 0) { | |
if (isRegExp(value)) { | |
return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); | |
} else { | |
return ctx.stylize('[Object]', 'special'); | |
} | |
} | |
ctx.seen.push(value); | |
var output; | |
if (array) { | |
output = formatArray(ctx, value, recurseTimes, visibleKeys, keys); | |
} else { | |
output = keys.map(function(key) { | |
return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array); | |
}); | |
} | |
ctx.seen.pop(); | |
return reduceToSingleString(output, base, braces); | |
} | |
function formatPrimitive(ctx, value) { | |
if (isUndefined(value)) | |
return ctx.stylize('undefined', 'undefined'); | |
if (isString(value)) { | |
var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '') | |
.replace(/'/g, "\\'") | |
.replace(/\\"/g, '"') + '\''; | |
return ctx.stylize(simple, 'string'); | |
} | |
if (isNumber(value)) | |
return ctx.stylize('' + value, 'number'); | |
if (isBoolean(value)) | |
return ctx.stylize('' + value, 'boolean'); | |
// For some reason typeof null is "object", so special case here. | |
if (isNull(value)) | |
return ctx.stylize('null', 'null'); | |
} | |
function formatError(value) { | |
return '[' + Error.prototype.toString.call(value) + ']'; | |
} | |
function formatArray(ctx, value, recurseTimes, visibleKeys, keys) { | |
var output = []; | |
for (var i = 0, l = value.length; i < l; ++i) { | |
if (hasOwnProperty(value, String(i))) { | |
output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, | |
String(i), true)); | |
} else { | |
output.push(''); | |
} | |
} | |
keys.forEach(function(key) { | |
if (!key.match(/^\d+$/)) { | |
output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, | |
key, true)); | |
} | |
}); | |
return output; | |
} | |
function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) { | |
var name, str, desc; | |
desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] }; | |
if (desc.get) { | |
if (desc.set) { | |
str = ctx.stylize('[Getter/Setter]', 'special'); | |
} else { | |
str = ctx.stylize('[Getter]', 'special'); | |
} | |
} else { | |
if (desc.set) { | |
str = ctx.stylize('[Setter]', 'special'); | |
} | |
} | |
if (!hasOwnProperty(visibleKeys, key)) { | |
name = '[' + key + ']'; | |
} | |
if (!str) { | |
if (ctx.seen.indexOf(desc.value) < 0) { | |
if (isNull(recurseTimes)) { | |
str = formatValue(ctx, desc.value, null); | |
} else { | |
str = formatValue(ctx, desc.value, recurseTimes - 1); | |
} | |
if (str.indexOf('\n') > -1) { | |
if (array) { | |
str = str.split('\n').map(function(line) { | |
return ' ' + line; | |
}).join('\n').substr(2); | |
} else { | |
str = '\n' + str.split('\n').map(function(line) { | |
return ' ' + line; | |
}).join('\n'); | |
} | |
} | |
} else { | |
str = ctx.stylize('[Circular]', 'special'); | |
} | |
} | |
if (isUndefined(name)) { | |
if (array && key.match(/^\d+$/)) { | |
return str; | |
} | |
name = JSON.stringify('' + key); | |
if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { | |
name = name.substr(1, name.length - 2); | |
name = ctx.stylize(name, 'name'); | |
} else { | |
name = name.replace(/'/g, "\\'") | |
.replace(/\\"/g, '"') | |
.replace(/(^"|"$)/g, "'"); | |
name = ctx.stylize(name, 'string'); | |
} | |
} | |
return name + ': ' + str; | |
} | |
function reduceToSingleString(output, base, braces) { | |
var numLinesEst = 0; | |
var length = output.reduce(function(prev, cur) { | |
numLinesEst++; | |
if (cur.indexOf('\n') >= 0) numLinesEst++; | |
return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1; | |
}, 0); | |
if (length > 60) { | |
return braces[0] + | |
(base === '' ? '' : base + '\n ') + | |
' ' + | |
output.join(',\n ') + | |
' ' + | |
braces[1]; | |
} | |
return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1]; | |
} | |
// NOTE: These type checking functions intentionally don't use `instanceof` | |
// because it is fragile and can be easily faked with `Object.create()`. | |
function isArray(ar) { | |
return Array.isArray(ar); | |
} | |
exports.isArray = isArray; | |
function isBoolean(arg) { | |
return typeof arg === 'boolean'; | |
} | |
exports.isBoolean = isBoolean; | |
function isNull(arg) { | |
return arg === null; | |
} | |
exports.isNull = isNull; | |
function isNullOrUndefined(arg) { | |
return arg == null; | |
} | |
exports.isNullOrUndefined = isNullOrUndefined; | |
function isNumber(arg) { | |
return typeof arg === 'number'; | |
} | |
exports.isNumber = isNumber; | |
function isString(arg) { | |
return typeof arg === 'string'; | |
} | |
exports.isString = isString; | |
function isSymbol(arg) { | |
return typeof arg === 'symbol'; | |
} | |
exports.isSymbol = isSymbol; | |
function isUndefined(arg) { | |
return arg === void 0; | |
} | |
exports.isUndefined = isUndefined; | |
function isRegExp(re) { | |
return isObject(re) && objectToString(re) === '[object RegExp]'; | |
} | |
exports.isRegExp = isRegExp; | |
function isObject(arg) { | |
return typeof arg === 'object' && arg !== null; | |
} | |
exports.isObject = isObject; | |
function isDate(d) { | |
return isObject(d) && objectToString(d) === '[object Date]'; | |
} | |
exports.isDate = isDate; | |
function isError(e) { | |
return isObject(e) && | |
(objectToString(e) === '[object Error]' || e instanceof Error); | |
} | |
exports.isError = isError; | |
function isFunction(arg) { | |
return typeof arg === 'function'; | |
} | |
exports.isFunction = isFunction; | |
function isPrimitive(arg) { | |
return arg === null || | |
typeof arg === 'boolean' || | |
typeof arg === 'number' || | |
typeof arg === 'string' || | |
typeof arg === 'symbol' || // ES6 symbol | |
typeof arg === 'undefined'; | |
} | |
exports.isPrimitive = isPrimitive; | |
exports.isBuffer = _dereq_('./support/isBuffer'); | |
function objectToString(o) { | |
return Object.prototype.toString.call(o); | |
} | |
function pad(n) { | |
return n < 10 ? '0' + n.toString(10) : n.toString(10); | |
} | |
var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', | |
'Oct', 'Nov', 'Dec']; | |
// 26 Feb 16:19:34 | |
function timestamp() { | |
var d = new Date(); | |
var time = [pad(d.getHours()), | |
pad(d.getMinutes()), | |
pad(d.getSeconds())].join(':'); | |
return [d.getDate(), months[d.getMonth()], time].join(' '); | |
} | |
// log is just a thin wrapper to console.log that prepends a timestamp | |
exports.log = function() { | |
console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments)); | |
}; | |
/** | |
* Inherit the prototype methods from one constructor into another. | |
* | |
* The Function.prototype.inherits from lang.js rewritten as a standalone | |
* function (not on Function.prototype). NOTE: If this file is to be loaded | |
* during bootstrapping this function needs to be rewritten using some native | |
* functions as prototype setup using normal JavaScript does not work as | |
* expected during bootstrapping (see mirror.js in r114903). | |
* | |
* @param {function} ctor Constructor function which needs to inherit the | |
* prototype. | |
* @param {function} superCtor Constructor function to inherit prototype from. | |
*/ | |
exports.inherits = _dereq_('inherits'); | |
exports._extend = function(origin, add) { | |
// Don't do anything if add isn't an object | |
if (!add || !isObject(add)) return origin; | |
var keys = Object.keys(add); | |
var i = keys.length; | |
while (i--) { | |
origin[keys[i]] = add[keys[i]]; | |
} | |
return origin; | |
}; | |
function hasOwnProperty(obj, prop) { | |
return Object.prototype.hasOwnProperty.call(obj, prop); | |
} | |
}).call(this,_dereq_("/Users/lance/Projects/stanza.io/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js"),typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) | |
},{"./support/isBuffer":141,"/Users/lance/Projects/stanza.io/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js":140,"inherits":139}],143:[function(_dereq_,module,exports){ | |
(function (Buffer){ | |
(function () { | |
"use strict"; | |
function btoa(str) { | |
var buffer | |
; | |
if (str instanceof Buffer) { | |
buffer = str; | |
} else { | |
buffer = new Buffer(str.toString(), 'binary'); | |
} | |
return buffer.toString('base64'); | |
} | |
module.exports = btoa; | |
}()); | |
}).call(this,_dereq_("buffer").Buffer) | |
},{"buffer":130}],144:[function(_dereq_,module,exports){ | |
"use strict"; | |
var _ = _dereq_('underscore'); | |
var Promise = _dereq_('bluebird'); | |
var request = Promise.promisify(_dereq_('request')); | |
var jxt = _dereq_('jxt'); | |
var XRD = _dereq_('./lib/xrd'); | |
module.exports = function (opts, cb) { | |
if (typeof opts === 'string') { | |
opts = {host: opts}; | |
} | |
opts = _.extend({ | |
ssl: true, | |
json: true, | |
xrd: true | |
}, opts); | |
var scheme = opts.ssl ? 'https://' : 'http://'; | |
var getJSON = new Promise(function (resolve, reject) { | |
request(scheme + opts.host + '/.well-known/host-meta.json').spread(function (req, body) { | |
resolve(JSON.parse(body)); | |
}).catch(reject); | |
}); | |
var getXRD = new Promise(function (resolve, reject) { | |
request(scheme + opts.host + '/.well-known/host-meta').spread(function (req, body) { | |
var xrd = jxt.parse(body, XRD); | |
resolve(xrd.toJSON()); | |
}).catch(reject); | |
}); | |
return new Promise(function (resolve, reject) { | |
Promise.some([getJSON, getXRD], 1).spread(resolve).catch(function () { | |
reject('no-host-meta'); | |
}); | |
}).nodeify(cb); | |
}; | |
},{"./lib/xrd":145,"bluebird":93,"jxt":164,"request":128,"underscore":187}],145:[function(_dereq_,module,exports){ | |
"use strict"; | |
var _ = _dereq_('underscore'); | |
var jxt = _dereq_('jxt'); | |
var NS = 'http://docs.oasis-open.org/ns/xri/xrd-1.0'; | |
var Properties = { | |
get: function () { | |
var results = {}; | |
var props = jxt.find(this.xml, NS, 'Property'); | |
_.each(props, function (property) { | |
var type = jxt.getAttribute(property, 'type'); | |
results[type] = property.textContent; | |
}); | |
return results; | |
} | |
}; | |
var XRD = module.exports = jxt.define({ | |
name: 'xrd', | |
namespace: NS, | |
element: 'XRD', | |
fields: { | |
subject: jxt.subText(NS, 'Subject'), | |
expires: jxt.dateSub(NS, 'Expires'), | |
aliases: jxt.multiSubText(NS, 'Alias'), | |
properties: Properties | |
} | |
}); | |
var Link = jxt.define({ | |
name: 'xrdlink', | |
namespace: NS, | |
element: 'Link', | |
fields: { | |
rel: jxt.attribute('rel'), | |
href: jxt.attribute('href'), | |
type: jxt.attribute('type'), | |
template: jxt.attribute('template'), | |
titles: jxt.subLangText(NS, 'Title', 'default'), | |
properties: Properties | |
} | |
}); | |
jxt.extend(XRD, Link, 'links'); | |
},{"jxt":164,"underscore":187}],146:[function(_dereq_,module,exports){ | |
module.exports = _dereq_('./lib/sessionManager'); | |
},{"./lib/sessionManager":149}],147:[function(_dereq_,module,exports){ | |
var bows = _dereq_('bows'); | |
var async = _dereq_('async'); | |
var WildEmitter = _dereq_('wildemitter'); | |
var log = bows('JingleSession'); | |
function actionToMethod(action) { | |
var words = action.split('-'); | |
return 'on' + words[0][0].toUpperCase() + words[0].substr(1) + words[1][0].toUpperCase() + words[1].substr(1); | |
} | |
function JingleSession(opts) { | |
var self = this; | |
this.sid = opts.sid || Date.now().toString(); | |
this.peer = opts.peer; | |
this.isInitiator = opts.initiator || false; | |
this.state = 'starting'; | |
this.parent = opts.parent; | |
this.processingQueue = async.queue(function (task, next) { | |
var action = task.action; | |
var changes = task.changes; | |
var cb = task.cb; | |
log(self.sid + ': ' + action); | |
self[action](changes, function (err) { | |
cb(err); | |
next(); | |
}); | |
}); | |
} | |
JingleSession.prototype = Object.create(WildEmitter.prototype, { | |
constructor: { | |
value: JingleSession | |
} | |
}); | |
JingleSession.prototype.process = function (action, changes, cb) { | |
var self = this; | |
var method = actionToMethod(action); | |
this.processingQueue.push({ | |
action: method, | |
changes: changes, | |
cb: cb | |
}); | |
}; | |
JingleSession.prototype.send = function (type, data) { | |
data = data || {}; | |
data.sid = this.sid; | |
data.action = type; | |
this.parent.emit('send', { | |
to: this.peer, | |
type: 'set', | |
jingle: data | |
}); | |
}; | |
Object.defineProperty(JingleSession.prototype, 'state', { | |
get: function () { | |
return this._state; | |
}, | |
set: function (value) { | |
var validStates = { | |
starting: true, | |
pending: true, | |
active: true, | |
ended: true | |
}; | |
if (!validStates[value]) { | |
throw new Error('Invalid Jingle Session State: ' + value); | |
} | |
if (this._state !== value) { | |
this._state = value; | |
log(this.sid + ': State changed to ' + value); | |
} | |
} | |
}); | |
Object.defineProperty(JingleSession.prototype, 'starting', { | |
get: function () { | |
return this._state == 'starting'; | |
} | |
}); | |
Object.defineProperty(JingleSession.prototype, 'pending', { | |
get: function () { | |
return this._state == 'pending'; | |
} | |
}); | |
Object.defineProperty(JingleSession.prototype, 'active', { | |
get: function () { | |
return this._state == 'active'; | |
} | |
}); | |
Object.defineProperty(JingleSession.prototype, 'ended', { | |
get: function () { | |
return this._state == 'ended'; | |
} | |
}); | |
JingleSession.prototype.start = function () { | |
this.state = 'pending'; | |
log(this.sid + ': Can not start generic session'); | |
}; | |
JingleSession.prototype.end = function (reason, silence) { | |
this.parent.peers[this.peer].splice(this.parent.peers[this.peer].indexOf(this), 1); | |
delete this.parent.sessions[this.sid]; | |
this.state = 'ended'; | |
reason = reason || {}; | |
if (!silence) { | |
this.send('session-terminate', {reason: reason}); | |
} | |
this.parent.emit('terminated', this, reason); | |
}; | |
var actions = [ | |
'content-accept', 'content-add', 'content-modify', | |
'content-reject', 'content-remove', 'description-info', | |
'session-accept', 'session-info', 'session-initiate', | |
'session-terminate', 'transport-accept', 'transport-info', | |
'transport-reject', 'transport-replace' | |
]; | |
actions.forEach(function (action) { | |
var method = actionToMethod(action); | |
JingleSession.prototype[method] = function (changes, cb) { | |
log(this.sid + ': Unsupported action ' + action); | |
cb(); | |
}; | |
}); | |
module.exports = JingleSession; | |
},{"async":89,"bows":150,"wildemitter":188}],148:[function(_dereq_,module,exports){ | |
var _ = _dereq_('underscore'); | |
var util = _dereq_('util'); | |
var bows = _dereq_('bows'); | |
var JingleSession = _dereq_('./genericSession'); | |
var RTCPeerConnection = _dereq_('rtcpeerconnection'); | |
var log = bows('JingleMedia'); | |
function MediaSession(opts) { | |
JingleSession.call(this, opts); | |
var self = this; | |
var config = this.parent.config.peerConnectionConfig; | |
var constraints = this.parent.config.peerConnectionConstraints; | |
config.useJingle = true; | |
this.pc = new RTCPeerConnection(config, constraints); | |
this.pc.on('ice', this.onIceCandidate.bind(this)); | |
this.pc.on('addStream', this.onStreamAdded.bind(this)); | |
this.pc.on('removeStream', this.onStreamRemoved.bind(this)); | |
if (this.parent.localStream) { | |
this.pc.addStream(this.parent.localStream); | |
this.localStream = this.parent.localStream; | |
} else { | |
this.parent.once('localStream', function (stream) { | |
self.pc.addStream(stream); | |
this.localStream = stream; | |
}); | |
} | |
} | |
util.inherits(MediaSession, JingleSession); | |
Object.defineProperty(MediaSession.prototype, 'streams', { | |
get: function () { | |
return this.pc.remoteStreams; | |
} | |
}); | |
MediaSession.prototype = _.extend(MediaSession.prototype, { | |
start: function () { | |
var self = this; | |
this.state = 'pending'; | |
this.pc.isInitiator = true; | |
this.pc.offer(function (err, sessDesc) { | |
self.send('session-initiate', sessDesc.jingle); | |
}); | |
}, | |
end: function (reason) { | |
var self = this; | |
this.pc.close(); | |
_.each(this.streams, function (stream) { | |
self.onStreamRemoved({stream: stream}); | |
}); | |
JingleSession.prototype.end.call(this, reason); | |
}, | |
accept: function () { | |
var self = this; | |
log(this.sid + ': Accepted incoming session'); | |
this.state = 'active'; | |
this.pc.answer(function (err, answer) { | |
if (err) { | |
return log(self.sid + ': Could not create WebRTC answer', err); | |
} | |
self.send('session-accept', answer.jingle); | |
}); | |
}, | |
ring: function () { | |
log(this.sid + ': Ringing on incoming session'); | |
this.send('session-info', {ringing: true}); | |
}, | |
mute: function (creator, name) { | |
log(this.sid + ': Muting'); | |
this.send('session-info', {mute: {creator: creator, name: name}}); | |
}, | |
unmute: function (creator, name) { | |
log(this.sid + ': Unmuting'); | |
this.send('session-info', {unmute: {creator: creator, name: name}}); | |
}, | |
hold: function () { | |
log(this.sid + ': Placing on hold'); | |
this.send('session-info', {hold: true}); | |
}, | |
resume: function () { | |
log(this.sid + ': Resuing from hold'); | |
this.send('session-info', {active: true}); | |
}, | |
onSessionInitiate: function (changes, cb) { | |
var self = this; | |
log(self.sid + ': Initiating incoming session'); | |
this.state = 'pending'; | |
this.pc.isInitiator = false; | |
this.pc.handleOffer({type: 'offer', jingle: changes}, function (err) { | |
if (err) { | |
log(self.sid + ': Could not create WebRTC answer', err); | |
return cb({condition: 'general-error'}); | |
} | |
cb(); | |
}); | |
}, | |
onSessionAccept: function (changes, cb) { | |
var self = this; | |
log(this.sid + ': Activating accepted outbound session'); | |
this.state = 'active'; | |
this.pc.handleAnswer({type: 'answer', jingle: changes}, function (err) { | |
if (err) { | |
log(self.sid + ': Could not process WebRTC answer', err); | |
return cb({condition: 'general-error'}); | |
} | |
self.parent.emit('accepted', self); | |
cb(); | |
}); | |
}, | |
onSessionTerminate: function (changes, cb) { | |
var self = this; | |
log(this.sid + ': Terminating session'); | |
this.pc.close(); | |
_.each(this.streams, function (stream) { | |
self.onStreamRemoved({stream: stream}); | |
}); | |
JingleSession.prototype.end.call(this, changes.reason, true); | |
cb(); | |
}, | |
onTransportInfo: function (changes, cb) { | |
var self = this; | |
log(this.sid + ': Adding ICE candidate'); | |
this.pc.processIce(changes, function (err) { | |
if (err) { | |
log(self.sid + ': Could not process ICE candidate', err); | |
} | |
cb(); | |
}); | |
}, | |
onSessionInfo: function (info, cb) { | |
log(info); | |
if (info.ringing) { | |
log(this.sid + ': Ringing on remote stream'); | |
this.parent.emit('ringing', this); | |
} | |
if (info.hold) { | |
log(this.sid + ': On hold'); | |
this.parent.emit('hold', this); | |
} | |
if (info.active) { | |
log(this.sid + ': Resumed from hold'); | |
this.parent.emit('resumed', this); | |
} | |
if (info.mute) { | |
log(this.sid + ': Muted', info.mute); | |
this.parent.emit('mute', this, info.mute); | |
} | |
if (info.unmute) { | |
log(this.sid + ': Unmuted', info.unmute); | |
this.parent.emit('unmute', this, info.unmute); | |
} | |
cb(); | |
}, | |
onIceCandidate: function (candidateInfo) { | |
log(this.sid + ': Discovered new ICE candidate', candidateInfo.jingle); | |
this.send('transport-info', candidateInfo.jingle); | |
}, | |
onStreamAdded: function (event) { | |
var self = this; | |
log(this.sid + ': Remote media stream added'); | |
event.stream.onended = function () { | |
self.onStreamRemoved({stream: event.stream}); | |
}; | |
this.parent.emit('peerStreamAdded', this, event.stream); | |
}, | |
onStreamRemoved: function (event) { | |
log(this.sid + ': Remote media stream removed'); | |
this.parent.emit('peerStreamRemoved', this, event.stream); | |
} | |
}); | |
module.exports = MediaSession; | |
},{"./genericSession":147,"bows":150,"rtcpeerconnection":158,"underscore":187,"util":142}],149:[function(_dereq_,module,exports){ | |
var _ = _dereq_('underscore'); | |
var bows = _dereq_('bows'); | |
var hark = _dereq_('hark'); | |
var webrtc = _dereq_('webrtcsupport'); | |
var mockconsole = _dereq_('mockconsole'); | |
var getUserMedia = _dereq_('getusermedia'); | |
var WildEmitter = _dereq_('wildemitter'); | |
var GainController = _dereq_('mediastream-gain'); | |
var GenericSession = _dereq_('./genericSession'); | |
var MediaSession = _dereq_('./mediaSession'); | |
var log = bows('Jingle'); | |
function Jingle(opts) { | |
var self = this; | |
opts = opts || {}; | |
var config = this.config = { | |
debug: false, | |
peerConnectionConfig: { | |
iceServers: [{"url": "stun:stun.l.google.com:19302"}] | |
}, | |
peerConnectionConstraints: { | |
optional: [ | |
{DtlsSrtpKeyAgreement: true}, | |
{RtpDataChannels: false} | |
] | |
}, | |
autoAdjustMic: false, | |
media: { | |
audio: true, | |
video: true | |
} | |
}; | |
this.MediaSession = MediaSession; | |
this.jid = opts.jid; | |
this.sessions = {}; | |
this.peers = {}; | |
this.screenSharingSupport = webrtc.screenSharing; | |
for (var item in opts) { | |
config[item] = opts[item]; | |
} | |
this.capabilities = [ | |
'urn:xmpp:jingle:1' | |
]; | |
if (webrtc.support) { | |
this.capabilities = [ | |
'urn:xmpp:jingle:1', | |
'urn:xmpp:jingle:apps:rtp:1', | |
'urn:xmpp:jingle:apps:rtp:audio', | |
'urn:xmpp:jingle:apps:rtp:video', | |
'urn:xmpp:jingle:apps:rtp:rtcb-fb:0', | |
'urn:xmpp:jingle:apps:rtp:rtp-hdrext:0', | |
'urn:xmpp:jingle:apps:rtp:ssma:0', | |
'urn:xmpp:jingle:apps:dtls:0', | |
'urn:xmpp:jingle:apps:grouping:0', | |
'urn:xmpp:jingle:transports:ice-udp:1', | |
'urn:ietf:rfc:3264', | |
'urn:ietf:rfc:5576', | |
'urn:ietf:rfc:5888' | |
]; | |
} else { | |
log('WebRTC not supported'); | |
} | |
WildEmitter.call(this); | |
if (this.config.debug) { | |
this.on('*', function (event, val1, val2) { | |
log(event, val1, val2); | |
}); | |
} | |
} | |
Jingle.prototype = Object.create(WildEmitter.prototype, { | |
constructor: { | |
value: Jingle | |
} | |
}); | |
Jingle.prototype.addICEServer = function (server) { | |
this.config.peerConnectionConfig.iceServers.push(server); | |
}; | |
Jingle.prototype.startLocalMedia = function (mediaConstraints, cb) { | |
var self = this; | |
var constraints = mediaConstraints || {video: true, audio: true}; | |
getUserMedia(constraints, function (err, stream) { | |
if (!err) { | |
if (constraints.audio && self.config.detectSpeakingEvents) { | |
self.setupAudioMonitor(stream); | |
} | |
self.localStream = stream; | |
if (self.config.autoAdjustMic) { | |
self.gainController = new GainController(stream); | |
self.setMicIfEnabled(0.5); | |
} | |
log('Local media stream started'); | |
self.emit('localStream', stream); | |
} else { | |
log('Could not start local media'); | |
} | |
if (cb) cb(err, stream); | |
}); | |
}; | |
Jingle.prototype.stopLocalMedia = function () { | |
if (this.localStream) { | |
this.localStream.stop(); | |
this.localStream = null; | |
this.emit('localStreamStopped'); | |
} | |
}; | |
Jingle.prototype.setupAudioMonitor = function (stream) { | |
log('Setup audio'); | |
var audio = hark(stream); | |
var self = this; | |
var timeout; | |
audio.on('speaking', function () { | |
if (self.hardMuted) return; | |
self.setMicIfEnabled(1); | |
self.emit('speaking'); | |
}); | |
audio.on('stopped_speaking', function () { | |
if (self.hardMuted) return; | |
if (timeout) clearTimeout(timeout); | |
timeout = setTimeout(function () { | |
self.setMicIfEnabled(0.5); | |
self.emit('stoppedSpeaking'); | |
}, 1000); | |
}); | |
}; | |
Jingle.prototype.setMicIfEnabled = function (volume) { | |
if (!this.config.autoAdjustMic) return; | |
this.gainController.setGain(volume); | |
}; | |
Jingle.prototype.sendError = function (to, id, data) { | |
data.type = 'cancel'; | |
this.emit('send', { | |
to: to, | |
id: id, | |
type: 'error', | |
error: data | |
}); | |
}; | |
Jingle.prototype.process = function (req) { | |
var self = this; | |
if (req.type === 'error') { | |
return this.emit('error', req); | |
} | |
if (req.type === 'result') { | |
return; | |
} | |
var sids, currsid, sess; | |
var sid = req.jingle.sid; | |
var action = req.jingle.action; | |
var contents = req.jingle.contents || []; | |
var contentTypes = _.map(contents, function (content) { | |
return (content.description || {}).descType; | |
}); | |
var session = this.sessions[sid] || null; | |
var sender = req.from.full || req.from; | |
var reqid = req.id; | |
if (action !== 'session-initiate') { | |
// Can't modify a session that we don't have. | |
if (!session) { | |
log('Unknown session', sid); | |
return this.sendError(sender, reqid, { | |
condition: 'item-not-found', | |
jingleCondition: 'unknown-session' | |
}); | |
} | |
// Check if someone is trying to hijack a session. | |
if (session.peer !== sender || session.ended) { | |
log('Session has ended, or action has wrong sender'); | |
return this.sendError(sender, reqid, { | |
condition: 'item-not-found', | |
jingleCondition: 'unknown-session' | |
}); | |
} | |
// Can't accept a session twice | |
if (action === 'session-accept' && !session.pending) { | |
log('Tried to accept session twice', sid); | |
return this.sendError(sender, reqid, { | |
condition: 'unexpected-request', | |
jingleCondition: 'out-of-order' | |
}); | |
} | |
// Can't process two requests at once, need to tie break | |
if (action !== 'session-terminate' && session.pendingAction) { | |
log('Tie break during pending request'); | |
if (session.isInitiator) { | |
return this.sendError(sender, reqid, { | |
condition: 'conflict', | |
jingleCondition: 'tie-break' | |
}); | |
} | |
} | |
} else if (session) { | |
// Don't accept a new session if we already have one. | |
if (session.peer !== sender) { | |
log('Duplicate sid from new sender'); | |
return this.sendError(sender, reqid, { | |
condition: 'service-unavailable' | |
}); | |
} | |
// Check if we need to have a tie breaker because both parties | |
// happened to pick the same random sid. | |
if (session.pending) { | |
if (this.jid > session.peer) { | |
log('Tie break new session because of duplicate sids'); | |
return this.sendError(sender, reqid, { | |
condition: 'conflict', | |
jingleCondition: 'tie-break' | |
}); | |
} | |
} | |
// The other side is just doing it wrong. | |
log('Someone is doing this wrong'); | |
return this.sendError(sender, reqid, { | |
condition: 'unexpected-request', | |
jingleCondition: 'out-of-order' | |
}); | |
} else if (Object.keys(this.peers[sender] || {}).length) { | |
// Check if we need to have a tie breaker because we already have | |
// a different session that is using the requested content types. | |
sids = Object.keys(this.peers[sender]); | |
for (var i = 0; i < sids.length; i++) { | |
currsid = sids[i]; | |
sess = this.sessions[currsid]; | |
if (sess && sess.pending) { | |
if (_.intersection(contentTypes, sess.contentTypes).length) { | |
// We already have a pending session request for this content type. | |
if (currsid > sid) { | |
// We won the tie breaker | |
log('Tie break'); | |
return this.sendError(sender, reqid, { | |
condition: 'conflict', | |
jingleCondition: 'tie-break' | |
}); | |
} | |
} | |
} | |
} | |
} | |
if (action === 'session-initiate') { | |
var opts = { | |
sid: sid, | |
peer: sender, | |
initiator: false, | |
parent: this | |
}; | |
if (contentTypes.indexOf('rtp') >= 0) { | |
session = new MediaSession(opts); | |
} else { | |
session = new GenericSession(opts); | |
} | |
this.sessions[sid] = session; | |
if (!this.peers[sender]) { | |
this.peers[sender] = []; | |
} | |
this.peers[sender].push(session); | |
} | |
session.process(action, req.jingle, function (err) { | |
if (err) { | |
log('Could not process request', req, err); | |
self.sendError(sender, reqid, err); | |
} else { | |
self.emit( | |
'send', | |
{ to: sender, id: reqid, type: 'result', action: action } | |
); | |
if (action === 'session-initiate') { | |
log('Incoming session request from ', sender, session); | |
self.emit('incoming', session); | |
} | |
} | |
}); | |
}; | |
Jingle.prototype.createMediaSession = function (peer, sid) { | |
var session = new MediaSession({ | |
sid: sid, | |
peer: peer, | |
initiator: true, | |
parent: this | |
}); | |
sid = session.sid; | |
this.sessions[sid] = session; | |
if (!this.peers[peer]) { | |
this.peers[peer] = []; | |
} | |
this.peers[peer].push(session); | |
log('Outgoing session', session.sid, session); | |
this.emit('outgoing', session); | |
return session; | |
}; | |
Jingle.prototype.endPeerSessions = function (peer) { | |
log('Ending all sessions with', peer); | |
var sessions = this.peers[peer] || []; | |
sessions.forEach(function (session) { | |
session.end(); | |
}); | |
}; | |
Jingle.prototype.endAllPeerSessions = function () { | |
log('Ending all peer sessions'); | |
var self = this; | |
Object.keys(this.peers).forEach(function (peer) { | |
self.endPeerSessions(peer); | |
}); | |
}; | |
module.exports = Jingle; | |
},{"./genericSession":147,"./mediaSession":148,"bows":150,"getusermedia":152,"hark":153,"mediastream-gain":155,"mockconsole":156,"underscore":187,"webrtcsupport":163,"wildemitter":188}],150:[function(_dereq_,module,exports){ | |
(function() { | |
function checkColorSupport() { | |
var chrome = !!window.chrome, | |
firefox = /firefox/i.test(navigator.userAgent), | |
firebug = firefox && !!window.console.exception; | |
return chrome || firebug; | |
} | |
var inNode = typeof window === 'undefined', | |
ls = !inNode && window.localStorage, | |
debug = ls.debug, | |
logger = _dereq_('andlog'), | |
hue = 0, | |
padLength = 15, | |
noop = function() {}, | |
colorsSupported = ls.debugColors || checkColorSupport(), | |
yieldColor, | |
bows, | |
debugRegex; | |
yieldColor = function() { | |
var goldenRatio = 0.618033988749895; | |
hue += goldenRatio; | |
hue = hue % 1; | |
return hue * 360; | |
}; | |
debugRegex = debug && debug[0]==='/' && new RegExp(debug.substring(1,debug.length-1)); | |
bows = function(str) { | |
var msg, colorString, logfn; | |
msg = (str.slice(0, padLength)); | |
msg += Array(padLength + 3 - msg.length).join(' ') + '|'; | |
if (debugRegex && !str.match(debugRegex)) return noop; | |
if (colorsSupported) { | |
var color = yieldColor(); | |
msg = "%c" + msg; | |
colorString = "color: hsl(" + (color) + ",99%,40%); font-weight: bold"; | |
logfn = logger.log.bind(logger, msg, colorString); | |
['log', 'debug', 'warn', 'error', 'info'].forEach(function (f) { | |
logfn[f] = logger[f].bind(logger, msg, colorString); | |
}); | |
} else { | |
logfn = logger.log.bind(logger, msg); | |
['log', 'debug', 'warn', 'error', 'info'].forEach(function (f) { | |
logfn[f] = logger[f].bind(logger, msg); | |
}); | |
} | |
return logfn; | |
}; | |
bows.config = function(config) { | |
if (config.padLength) { | |
this.padLength = config.padLength; | |
} | |
}; | |
if (typeof module !== 'undefined') { | |
module.exports = bows; | |
} else { | |
window.bows = bows; | |
} | |
}).call(); | |
},{"andlog":151}],151:[function(_dereq_,module,exports){ | |
// follow @HenrikJoreteg and @andyet if you like this ;) | |
(function () { | |
var inNode = typeof window === 'undefined', | |
ls = !inNode && window.localStorage, | |
out = {}; | |
if (inNode) { | |
module.exports = console; | |
return; | |
} | |
if (ls && ls.debug && window.console) { | |
out = window.console; | |
} else { | |
var methods = "assert,count,debug,dir,dirxml,error,exception,group,groupCollapsed,groupEnd,info,log,markTimeline,profile,profileEnd,time,timeEnd,trace,warn".split(","), | |
l = methods.length, | |
fn = function () {}; | |
while (l--) { | |
out[methods[l]] = fn; | |
} | |
} | |
if (typeof exports !== 'undefined') { | |
module.exports = out; | |
} else { | |
window.console = out; | |
} | |
})(); | |
},{}],152:[function(_dereq_,module,exports){ | |
// getUserMedia helper by @HenrikJoreteg | |
var func = (window.navigator.getUserMedia || | |
window.navigator.webkitGetUserMedia || | |
window.navigator.mozGetUserMedia || | |
window.navigator.msGetUserMedia); | |
module.exports = function (constraints, cb) { | |
var options; | |
var haveOpts = arguments.length === 2; | |
var defaultOpts = {video: true, audio: true}; | |
var error; | |
var denied = 'PERMISSION_DENIED'; | |
var notSatified = 'CONSTRAINT_NOT_SATISFIED'; | |
// make constraints optional | |
if (!haveOpts) { | |
cb = constraints; | |
constraints = defaultOpts; | |
} | |
// treat lack of browser support like an error | |
if (!func) { | |
// throw proper error per spec | |
error = new Error('NavigatorUserMediaError'); | |
error.name = 'NOT_SUPPORTED_ERROR'; | |
return cb(error); | |
} | |
func.call(window.navigator, constraints, function (stream) { | |
cb(null, stream); | |
}, function (err) { | |
var error; | |
// coerce into an error object since FF gives us a string | |
// there are only two valid names according to the spec | |
// we coerce all non-denied to "constraint not satisfied". | |
if (typeof err === 'string') { | |
error = new Error('NavigatorUserMediaError'); | |
if (err === denied) { | |
error.name = denied; | |
} else { | |
error.name = notSatified; | |
} | |
} else { | |
// if we get an error object make sure '.name' property is set | |
// according to spec: http://dev.w3.org/2011/webrtc/editor/getusermedia.html#navigatorusermediaerror-and-navigatorusermediaerrorcallback | |
error = err; | |
if (!error.name) { | |
// this is likely chrome which | |
// sets a property called "ERROR_DENIED" on the error object | |
// if so we make sure to set a name | |
if (error[denied]) { | |
err.name = denied; | |
} else { | |
err.name = notSatified; | |
} | |
} | |
} | |
cb(error); | |
}); | |
}; | |
},{}],153:[function(_dereq_,module,exports){ | |
var WildEmitter = _dereq_('wildemitter'); | |
function getMaxVolume (analyser, fftBins) { | |
var maxVolume = -Infinity; | |
analyser.getFloatFrequencyData(fftBins); | |
for(var i=0, ii=fftBins.length; i < ii; i++) { | |
if (fftBins[i] > maxVolume && fftBins[i] < 0) { | |
maxVolume = fftBins[i]; | |
} | |
}; | |
return maxVolume; | |
} | |
var audioContextType = window.webkitAudioContext || window.AudioContext; | |
// use a single audio context due to hardware limits | |
var audioContext = null; | |
module.exports = function(stream, options) { | |
var harker = new WildEmitter(); | |
// make it not break in non-supported browsers | |
if (!audioContextType) return harker; | |
//Config | |
var options = options || {}, | |
smoothing = (options.smoothing || 0.5), | |
interval = (options.interval || 100), | |
threshold = options.threshold, | |
play = options.play, | |
running = true; | |
//Setup Audio Context | |
if (!audioContext) { | |
audioContext = new audioContextType(); | |
} | |
var sourceNode, fftBins, analyser; | |
analyser = audioContext.createAnalyser(); | |
analyser.fftSize = 512; | |
analyser.smoothingTimeConstant = smoothing; | |
fftBins = new Float32Array(analyser.fftSize); | |
if (stream.jquery) stream = stream[0]; | |
if (stream instanceof HTMLAudioElement) { | |
//Audio Tag | |
sourceNode = audioContext.createMediaElementSource(stream); | |
if (typeof play === 'undefined') play = true; | |
threshold = threshold || -65; | |
} else { | |
//WebRTC Stream | |
sourceNode = audioContext.createMediaStreamSource(stream); | |
threshold = threshold || -45; | |
} | |
sourceNode.connect(analyser); | |
if (play) analyser.connect(audioContext.destination); | |
harker.speaking = false; | |
harker.setThreshold = function(t) { | |
threshold = t; | |
}; | |
harker.setInterval = function(i) { | |
interval = i; | |
}; | |
harker.stop = function() { | |
running = false; | |
harker.emit('volume_change', -100, threshold); | |
if (harker.speaking) { | |
harker.speaking = false; | |
harker.emit('stopped_speaking'); | |
} | |
}; | |
// Poll the analyser node to determine if speaking | |
// and emit events if changed | |
var looper = function() { | |
setTimeout(function() { | |
//check if stop has been called | |
if(!running) { | |
return; | |
} | |
var currentVolume = getMaxVolume(analyser, fftBins); | |
harker.emit('volume_change', currentVolume, threshold); | |
if (currentVolume > threshold) { | |
if (!harker.speaking) { | |
harker.speaking = true; | |
harker.emit('speaking'); | |
} | |
} else { | |
if (harker.speaking) { | |
harker.speaking = false; | |
harker.emit('stopped_speaking'); | |
} | |
} | |
looper(); | |
}, interval); | |
}; | |
looper(); | |
return harker; | |
} | |
},{"wildemitter":154}],154:[function(_dereq_,module,exports){ | |
/* | |
WildEmitter.js is a slim little event emitter by @henrikjoreteg largely based | |
on @visionmedia's Emitter from UI Kit. | |
Why? I wanted it standalone. | |
I also wanted support for wildcard emitters like this: | |
emitter.on('*', function (eventName, other, event, payloads) { | |
}); | |
emitter.on('somenamespace*', function (eventName, payloads) { | |
}); | |
Please note that callbacks triggered by wildcard registered events also get | |
the event name as the first argument. | |
*/ | |
module.exports = WildEmitter; | |
function WildEmitter() { | |
this.callbacks = {}; | |
} | |
// Listen on the given `event` with `fn`. Store a group name if present. | |
WildEmitter.prototype.on = function (event, groupName, fn) { | |
var hasGroup = (arguments.length === 3), | |
group = hasGroup ? arguments[1] : undefined, | |
func = hasGroup ? arguments[2] : arguments[1]; | |
func._groupName = group; | |
(this.callbacks[event] = this.callbacks[event] || []).push(func); | |
return this; | |
}; | |
// Adds an `event` listener that will be invoked a single | |
// time then automatically removed. | |
WildEmitter.prototype.once = function (event, groupName, fn) { | |
var self = this, | |
hasGroup = (arguments.length === 3), | |
group = hasGroup ? arguments[1] : undefined, | |
func = hasGroup ? arguments[2] : arguments[1]; | |
function on() { | |
self.off(event, on); | |
func.apply(this, arguments); | |
} | |
this.on(event, group, on); | |
return this; | |
}; | |
// Unbinds an entire group | |
WildEmitter.prototype.releaseGroup = function (groupName) { | |
var item, i, len, handlers; | |
for (item in this.callbacks) { | |
handlers = this.callbacks[item]; | |
for (i = 0, len = handlers.length; i < len; i++) { | |
if (handlers[i]._groupName === groupName) { | |
//console.log('removing'); | |
// remove it and shorten the array we're looping through | |
handlers.splice(i, 1); | |
i--; | |
len--; | |
} | |
} | |
} | |
return this; | |
}; | |
// Remove the given callback for `event` or all | |
// registered callbacks. | |
WildEmitter.prototype.off = function (event, fn) { | |
var callbacks = this.callbacks[event], | |
i; | |
if (!callbacks) return this; | |
// remove all handlers | |
if (arguments.length === 1) { | |
delete this.callbacks[event]; | |
return this; | |
} | |
// remove specific handler | |
i = callbacks.indexOf(fn); | |
callbacks.splice(i, 1); | |
return this; | |
}; | |
// Emit `event` with the given args. | |
// also calls any `*` handlers | |
WildEmitter.prototype.emit = function (event) { | |
var args = [].slice.call(arguments, 1), | |
callbacks = this.callbacks[event], | |
specialCallbacks = this.getWildcardCallbacks(event), | |
i, | |
len, | |
item; | |
if (callbacks) { | |
for (i = 0, len = callbacks.length; i < len; ++i) { | |
if (callbacks[i]) { | |
callbacks[i].apply(this, args); | |
} else { | |
break; | |
} | |
} | |
} | |
if (specialCallbacks) { | |
for (i = 0, len = specialCallbacks.length; i < len; ++i) { | |
if (specialCallbacks[i]) { | |
specialCallbacks[i].apply(this, [event].concat(args)); | |
} else { | |
break; | |
} | |
} | |
} | |
return this; | |
}; | |
// Helper for for finding special wildcard event handlers that match the event | |
WildEmitter.prototype.getWildcardCallbacks = function (eventName) { | |
var item, | |
split, | |
result = []; | |
for (item in this.callbacks) { | |
split = item.split('*'); | |
if (item === '*' || (split.length === 2 && eventName.slice(0, split[1].length) === split[1])) { | |
result = result.concat(this.callbacks[item]); | |
} | |
} | |
return result; | |
}; | |
},{}],155:[function(_dereq_,module,exports){ | |
var support = _dereq_('webrtcsupport'); | |
function GainController(stream) { | |
this.support = support.webAudio && support.mediaStream; | |
// set our starting value | |
this.gain = 1; | |
if (this.support) { | |
var context = this.context = new support.AudioContext(); | |
this.microphone = context.createMediaStreamSource(stream); | |
this.gainFilter = context.createGain(); | |
this.destination = context.createMediaStreamDestination(); | |
this.outputStream = this.destination.stream; | |
this.microphone.connect(this.gainFilter); | |
this.gainFilter.connect(this.destination); | |
stream.removeTrack(stream.getAudioTracks()[0]); | |
stream.addTrack(this.outputStream.getAudioTracks()[0]); | |
} | |
this.stream = stream; | |
} | |
// setting | |
GainController.prototype.setGain = function (val) { | |
// check for support | |
if (!this.support) return; | |
this.gainFilter.gain.value = val; | |
this.gain = val; | |
}; | |
GainController.prototype.getGain = function () { | |
return this.gain; | |
}; | |
GainController.prototype.off = function () { | |
return this.setGain(0); | |
}; | |
GainController.prototype.on = function () { | |
this.setGain(1); | |
}; | |
module.exports = GainController; | |
},{"webrtcsupport":163}],156:[function(_dereq_,module,exports){ | |
var methods = "assert,count,debug,dir,dirxml,error,exception,group,groupCollapsed,groupEnd,info,log,markTimeline,profile,profileEnd,time,timeEnd,trace,warn".split(","); | |
var l = methods.length; | |
var fn = function () {}; | |
var mockconsole = {}; | |
while (l--) { | |
mockconsole[methods[l]] = fn; | |
} | |
module.exports = mockconsole; | |
},{}],157:[function(_dereq_,module,exports){ | |
// based on https://github.com/ESTOS/strophe.jingle/ | |
// adds wildemitter support | |
var util = _dereq_('util'); | |
var webrtc = _dereq_('webrtcsupport'); | |
var WildEmitter = _dereq_('wildemitter'); | |
function dumpSDP(description) { | |
return 'type: ' + description.type + '\r\n' + description.sdp; | |
} | |
function TraceablePeerConnection(config, constraints) { | |
var self = this; | |
WildEmitter.call(this); | |
this.peerconnection = new webrtc.PeerConnection(config, constraints); | |
this.trace = function (what, info) { | |
self.emit('PeerConnectionTrace', { | |
time: new Date(), | |
type: what, | |
value: info || "" | |
}); | |
}; | |
this.onicecandidate = null; | |
this.peerconnection.onicecandidate = function (event) { | |
self.trace('onicecandidate', JSON.stringify(event.candidate, null, ' ')); | |
if (self.onicecandidate !== null) { | |
self.onicecandidate(event); | |
} | |
}; | |
this.onaddstream = null; | |
this.peerconnection.onaddstream = function (event) { | |
self.trace('onaddstream', event.stream.id); | |
if (self.onaddstream !== null) { | |
self.onaddstream(event); | |
} | |
}; | |
this.onremovestream = null; | |
this.peerconnection.onremovestream = function (event) { | |
self.trace('onremovestream', event.stream.id); | |
if (self.onremovestream !== null) { | |
self.onremovestream(event); | |
} | |
}; | |
this.onsignalingstatechange = null; | |
this.peerconnection.onsignalingstatechange = function (event) { | |
self.trace('onsignalingstatechange', self.signalingState); | |
if (self.onsignalingstatechange !== null) { | |
self.onsignalingstatechange(event); | |
} | |
}; | |
this.oniceconnectionstatechange = null; | |
this.peerconnection.oniceconnectionstatechange = function (event) { | |
self.trace('oniceconnectionstatechange', self.iceConnectionState); | |
if (self.oniceconnectionstatechange !== null) { | |
self.oniceconnectionstatechange(event); | |
} | |
}; | |
this.onnegotiationneeded = null; | |
this.peerconnection.onnegotiationneeded = function (event) { | |
self.trace('onnegotiationneeded'); | |
if (self.onnegotiationneeded !== null) { | |
self.onnegotiationneeded(event); | |
} | |
}; | |
self.ondatachannel = null; | |
this.peerconnection.ondatachannel = function (event) { | |
self.trace('ondatachannel', event); | |
if (self.ondatachannel !== null) { | |
self.ondatachannel(event); | |
} | |
}; | |
} | |
util.inherits(TraceablePeerConnection, WildEmitter); | |
if (TraceablePeerConnection.prototype.__defineGetter__ !== undefined) { | |
TraceablePeerConnection.prototype.__defineGetter__('signalingState', function () { return this.peerconnection.signalingState; }); | |
TraceablePeerConnection.prototype.__defineGetter__('iceConnectionState', function () { return this.peerconnection.iceConnectionState; }); | |
TraceablePeerConnection.prototype.__defineGetter__('localDescription', function () { return this.peerconnection.localDescription; }); | |
TraceablePeerConnection.prototype.__defineGetter__('remoteDescription', function () { return this.peerconnection.remoteDescription; }); | |
} | |
TraceablePeerConnection.prototype.addStream = function (stream) { | |
this.trace('addStream', stream.id); | |
this.peerconnection.addStream(stream); | |
}; | |
TraceablePeerConnection.prototype.removeStream = function (stream) { | |
this.trace('removeStream', stream.id); | |
this.peerconnection.removeStream(stream); | |
}; | |
TraceablePeerConnection.prototype.createDataChannel = function (label, opts) { | |
this.trace('createDataChannel', label, opts); | |
return this.peerconnection.createDataChannel(label, opts); | |
}; | |
TraceablePeerConnection.prototype.setLocalDescription = function (description, successCallback, failureCallback) { | |
var self = this; | |
this.trace('setLocalDescription', dumpSDP(description)); | |
this.peerconnection.setLocalDescription(description, | |
function () { | |
self.trace('setLocalDescriptionOnSuccess'); | |
successCallback(); | |
}, | |
function (err) { | |
self.trace('setLocalDescriptionOnFailure', err); | |
failureCallback(err); | |
} | |
); | |
}; | |
TraceablePeerConnection.prototype.setRemoteDescription = function (description, successCallback, failureCallback) { | |
var self = this; | |
this.trace('setRemoteDescription', dumpSDP(description)); | |
this.peerconnection.setRemoteDescription(description, | |
function () { | |
self.trace('setRemoteDescriptionOnSuccess'); | |
successCallback(); | |
}, | |
function (err) { | |
self.trace('setRemoteDescriptionOnFailure', err); | |
failureCallback(err); | |
} | |
); | |
}; | |
TraceablePeerConnection.prototype.close = function () { | |
this.trace('stop'); | |
if (this.statsinterval !== null) { | |
window.clearInterval(this.statsinterval); | |
this.statsinterval = null; | |
} | |
if (this.peerconnection.signalingState != 'closed') { | |
this.peerconnection.close(); | |
} | |
}; | |
TraceablePeerConnection.prototype.createOffer = function (successCallback, failureCallback, constraints) { | |
var self = this; | |
this.trace('createOffer', JSON.stringify(constraints, null, ' ')); | |
this.peerconnection.createOffer( | |
function (offer) { | |
self.trace('createOfferOnSuccess', dumpSDP(offer)); | |
successCallback(offer); | |
}, | |
function (err) { | |
self.trace('createOfferOnFailure', err); | |
failureCallback(err); | |
}, | |
constraints | |
); | |
}; | |
TraceablePeerConnection.prototype.createAnswer = function (successCallback, failureCallback, constraints) { | |
var self = this; | |
this.trace('createAnswer', JSON.stringify(constraints, null, ' ')); | |
this.peerconnection.createAnswer( | |
function (answer) { | |
self.trace('createAnswerOnSuccess', dumpSDP(answer)); | |
successCallback(answer); | |
}, | |
function (err) { | |
self.trace('createAnswerOnFailure', err); | |
failureCallback(err); | |
}, | |
constraints | |
); | |
}; | |
TraceablePeerConnection.prototype.addIceCandidate = function (candidate, successCallback, failureCallback) { | |
var self = this; | |
this.trace('addIceCandidate', JSON.stringify(candidate, null, ' ')); | |
this.peerconnection.addIceCandidate(candidate); | |
/* maybe later | |
this.peerconnection.addIceCandidate(candidate, | |
function () { | |
self.trace('addIceCandidateOnSuccess'); | |
successCallback(); | |
}, | |
function (err) { | |
self.trace('addIceCandidateOnFailure', err); | |
failureCallback(err); | |
} | |
); | |
*/ | |
}; | |
TraceablePeerConnection.prototype.getStats = function (callback, errback) { | |
if (navigator.mozGetUserMedia) { | |
this.peerconnection.getStats(null, callback, errback); | |
} else { | |
this.peerconnection.getStats(callback); | |
} | |
}; | |
module.exports = TraceablePeerConnection; | |
},{"util":142,"webrtcsupport":163,"wildemitter":188}],158:[function(_dereq_,module,exports){ | |
var _ = _dereq_('underscore'); | |
var util = _dereq_('util'); | |
var webrtc = _dereq_('webrtcsupport'); | |
var SJJ = _dereq_('sdp-jingle-json'); | |
var WildEmitter = _dereq_('wildemitter'); | |
var peerconn = _dereq_('traceablepeerconnection'); | |
function PeerConnection(config, constraints) { | |
var self = this; | |
var item; | |
WildEmitter.call(this); | |
config = config || {}; | |
config.iceServers = config.iceServers || []; | |
this.pc = new peerconn(config, constraints); | |
// proxy events | |
this.pc.on('*', function () { | |
self.emit.apply(self, arguments); | |
}); | |
// proxy some events directly | |
this.pc.onremovestream = this.emit.bind(this, 'removeStream'); | |
this.pc.onnegotiationneeded = this.emit.bind(this, 'negotiationNeeded'); | |
this.pc.oniceconnectionstatechange = this.emit.bind(this, 'iceConnectionStateChange'); | |
this.pc.onsignalingstatechange = this.emit.bind(this, 'signalingStateChange'); | |
// handle incoming ice and data channel events | |
this.pc.onaddstream = this._onAddStream.bind(this); | |
this.pc.onicecandidate = this._onIce.bind(this); | |
this.pc.ondatachannel = this._onDataChannel.bind(this); | |
this.localDescription = { | |
contents: [] | |
}; | |
this.remoteDescription = { | |
contents: [] | |
}; | |
this.localStream = null; | |
this.remoteStreams = []; | |
this.config = { | |
debug: false, | |
ice: {}, | |
sid: '', | |
isInitiator: true, | |
sdpSessionID: Date.now(), | |
useJingle: false | |
}; | |
// apply our config | |
for (item in config) { | |
this.config[item] = config[item]; | |
} | |
if (this.config.debug) { | |
this.on('*', function (eventName, event) { | |
var logger = config.logger || console; | |
logger.log('PeerConnection event:', arguments); | |
}); | |
} | |
} | |
util.inherits(PeerConnection, WildEmitter); | |
if (PeerConnection.prototype.__defineGetter__) { | |
PeerConnection.prototype.__defineGetter__('signalingState', function () { | |
return this.pc.signalingState; | |
}); | |
PeerConnection.prototype.__defineGetter__('iceConnectionState', function () { | |
return this.pc.iceConnectionState; | |
}); | |
} | |
// Add a stream to the peer connection object | |
PeerConnection.prototype.addStream = function (stream) { | |
this.localStream = stream; | |
this.pc.addStream(stream); | |
}; | |
// Init and add ice candidate object with correct constructor | |
PeerConnection.prototype.processIce = function (update, cb) { | |
cb = cb || function () {}; | |
var self = this; | |
if (update.contents) { | |
var contentNames = _.pluck(this.remoteDescription.contents, 'name'); | |
var contents = update.contents; | |
contents.forEach(function (content) { | |
var transport = content.transport || {}; | |
var candidates = transport.candidates || []; | |
var mline = contentNames.indexOf(content.name); | |
var mid = content.name; | |
candidates.forEach(function (candidate) { | |
console.log('addicecandidate'); | |
var iceCandidate = SJJ.toCandidateSDP(candidate) + '\r\n'; | |
self.pc.addIceCandidate(new webrtc.IceCandidate({ | |
candidate: iceCandidate, | |
sdpMLineIndex: mline, | |
sdpMid: mid | |
}) | |
/* not yet, breaks Chrome M32 */ | |
/* | |
, function () { | |
// well, this success callback is pretty meaningless | |
}, | |
function (err) { | |
self.emit('error', err); | |
} | |
*/ | |
); | |
}); | |
}); | |
} else { | |
self.pc.addIceCandidate(new webrtc.IceCandidate(update.candidate)); | |
} | |
cb(); | |
}; | |
// Generate and emit an offer with the given constraints | |
PeerConnection.prototype.offer = function (constraints, cb) { | |
var self = this; | |
var hasConstraints = arguments.length === 2; | |
var mediaConstraints = hasConstraints ? constraints : { | |
mandatory: { | |
OfferToReceiveAudio: true, | |
OfferToReceiveVideo: true | |
} | |
}; | |
cb = hasConstraints ? cb : constraints; | |
cb = cb || function () {}; | |
// Actually generate the offer | |
this.pc.createOffer( | |
function (offer) { | |
self.pc.setLocalDescription(offer, | |
function () { | |
var jingle; | |
var expandedOffer = { | |
type: 'offer', | |
sdp: offer.sdp | |
}; | |
if (self.config.useJingle) { | |
jingle = SJJ.toSessionJSON(offer.sdp, self.config.isInitiator ? 'initiator' : 'responder'); | |
jingle.sid = self.config.sid; | |
self.localDescription = jingle; | |
// Save ICE credentials | |
_.each(jingle.contents, function (content) { | |
var transport = content.transport || {}; | |
if (transport.ufrag) { | |
self.config.ice[content.name] = { | |
ufrag: transport.ufrag, | |
pwd: transport.pwd | |
}; | |
} | |
}); | |
expandedOffer.jingle = jingle; | |
} | |
self.emit('offer', expandedOffer); | |
cb(null, expandedOffer); | |
}, | |
function (err) { | |
self.emit('error', err); | |
cb(err); | |
} | |
); | |
}, | |
function (err) { | |
self.emit('error', err); | |
cb(err); | |
}, | |
mediaConstraints | |
); | |
}; | |
// Process an incoming offer so that ICE may proceed before deciding | |
// to answer the request. | |
PeerConnection.prototype.handleOffer = function (offer, cb) { | |
cb = cb || function () {}; | |
var self = this; | |
offer.type = 'offer'; | |
if (offer.jingle) { | |
offer.sdp = SJJ.toSessionSDP(offer.jingle, self.config.sdpSessionID); | |
} | |
self.pc.setRemoteDescription(new webrtc.SessionDescription(offer), function () { | |
cb(); | |
}, cb); | |
}; | |
// Answer an offer with audio only | |
PeerConnection.prototype.answerAudioOnly = function (cb) { | |
var mediaConstraints = { | |
mandatory: { | |
OfferToReceiveAudio: true, | |
OfferToReceiveVideo: false | |
} | |
}; | |
this._answer(mediaConstraints, cb); | |
}; | |
// Answer an offer without offering to recieve | |
PeerConnection.prototype.answerBroadcastOnly = function (cb) { | |
var mediaConstraints = { | |
mandatory: { | |
OfferToReceiveAudio: false, | |
OfferToReceiveVideo: false | |
} | |
}; | |
this._answer(mediaConstraints, cb); | |
}; | |
// Answer an offer with given constraints default is audio/video | |
PeerConnection.prototype.answer = function (constraints, cb) { | |
var self = this; | |
var hasConstraints = arguments.length === 2; | |
var callback = hasConstraints ? cb : constraints; | |
var mediaConstraints = hasConstraints ? constraints : { | |
mandatory: { | |
OfferToReceiveAudio: true, | |
OfferToReceiveVideo: true | |
} | |
}; | |
this._answer(mediaConstraints, callback); | |
}; | |
// Process an answer | |
PeerConnection.prototype.handleAnswer = function (answer, cb) { | |
cb = cb || function () {}; | |
var self = this; | |
if (answer.jingle) { | |
answer.sdp = SJJ.toSessionSDP(answer.jingle, self.config.sdpSessionID); | |
self.remoteDescription = answer.jingle; | |
} | |
self.pc.setRemoteDescription( | |
new webrtc.SessionDescription(answer), | |
function () { | |
cb(null); | |
}, | |
cb | |
); | |
}; | |
// Close the peer connection | |
PeerConnection.prototype.close = function () { | |
this.pc.close(); | |
this.emit('close'); | |
}; | |
// Internal code sharing for various types of answer methods | |
PeerConnection.prototype._answer = function (constraints, cb) { | |
cb = cb || function () {}; | |
var self = this; | |
if (!this.pc.remoteDescription) { | |
// the old API is used, call handleOffer | |
throw new Error('remoteDescription not set'); | |
} | |
self.pc.createAnswer( | |
function (answer) { | |
self.pc.setLocalDescription(answer, | |
function () { | |
var expandedAnswer = { | |
type: 'answer', | |
sdp: answer.sdp | |
}; | |
if (self.config.useJingle) { | |
var jingle = SJJ.toSessionJSON(answer.sdp); | |
jingle.sid = self.config.sid; | |
self.localDescription = jingle; | |
expandedAnswer.jingle = jingle; | |
} | |
self.emit('answer', expandedAnswer); | |
cb(null, expandedAnswer); | |
}, | |
function (err) { | |
self.emit('error', err); | |
cb(err); | |
} | |
); | |
}, | |
function (err) { | |
self.emit('error', err); | |
cb(err); | |
}, | |
constraints | |
); | |
}; | |
// Internal method for emitting ice candidates on our peer object | |
PeerConnection.prototype._onIce = function (event) { | |
var self = this; | |
if (event.candidate) { | |
var ice = event.candidate; | |
var expandedCandidate = { | |
candidate: event.candidate | |
}; | |
if (self.config.useJingle) { | |
if (!self.config.ice[ice.sdpMid]) { | |
var jingle = SJJ.toSessionJSON(self.pc.localDescription.sdp, self.config.isInitiator ? 'initiator' : 'responder'); | |
_.each(jingle.contents, function (content) { | |
var transport = content.transport || {}; | |
if (transport.ufrag) { | |
self.config.ice[content.name] = { | |
ufrag: transport.ufrag, | |
pwd: transport.pwd | |
}; | |
} | |
}); | |
} | |
expandedCandidate.jingle = { | |
contents: [{ | |
name: ice.sdpMid, | |
creator: self.config.isInitiator ? 'initiator' : 'responder', | |
transport: { | |
transType: 'iceUdp', | |
ufrag: self.config.ice[ice.sdpMid].ufrag, | |
pwd: self.config.ice[ice.sdpMid].pwd, | |
candidates: [ | |
SJJ.toCandidateJSON(ice.candidate) | |
] | |
} | |
}] | |
}; | |
} | |
this.emit('ice', expandedCandidate); | |
} else { | |
this.emit('endOfCandidates'); | |
} | |
}; | |
// Internal method for processing a new data channel being added by the | |
// other peer. | |
PeerConnection.prototype._onDataChannel = function (event) { | |
this.emit('addChannel', event.channel); | |
}; | |
// Internal handling of adding stream | |
PeerConnection.prototype._onAddStream = function (event) { | |
this.remoteStreams.push(event.stream); | |
this.emit('addStream', event); | |
}; | |
// Create a data channel spec reference: | |
// http://dev.w3.org/2011/webrtc/editor/webrtc.html#idl-def-RTCDataChannelInit | |
PeerConnection.prototype.createDataChannel = function (name, opts) { | |
var channel = this.pc.createDataChannel(name, opts); | |
return channel; | |
}; | |
// a wrapper around getStats which hides the differences (where possible) | |
PeerConnection.prototype.getStats = function (cb) { | |
if (webrtc.prefix === 'moz') { | |
this.pc.getStats( | |
function (res) { | |
var items = []; | |
res.forEach(function (result) { | |
items.push(result); | |
}); | |
cb(null, items); | |
}, | |
cb | |
); | |
} else { | |
this.pc.getStats(function (res) { | |
var items = []; | |
res.result().forEach(function (result) { | |
var item = {}; | |
result.names().forEach(function (name) { | |
item[name] = result.stat(name); | |
}); | |
item.id = result.id; | |
item.type = result.type; | |
item.timestamp = result.timestamp; | |
items.push(item); | |
}); | |
cb(null, items); | |
}); | |
} | |
}; | |
module.exports = PeerConnection; | |
},{"sdp-jingle-json":159,"traceablepeerconnection":157,"underscore":187,"util":142,"webrtcsupport":163,"wildemitter":188}],159:[function(_dereq_,module,exports){ | |
var tosdp = _dereq_('./lib/tosdp'); | |
var tojson = _dereq_('./lib/tojson'); | |
exports.toSessionSDP = tosdp.toSessionSDP; | |
exports.toMediaSDP = tosdp.toMediaSDP; | |
exports.toCandidateSDP = tosdp.toCandidateSDP; | |
exports.toSessionJSON = tojson.toSessionJSON; | |
exports.toMediaJSON = tojson.toMediaJSON; | |
exports.toCandidateJSON = tojson.toCandidateJSON; | |
},{"./lib/tojson":161,"./lib/tosdp":162}],160:[function(_dereq_,module,exports){ | |
exports.lines = function (sdp) { | |
return sdp.split('\r\n').filter(function (line) { | |
return line.length > 0; | |
}); | |
}; | |
exports.findLine = function (prefix, mediaLines, sessionLines) { | |
var prefixLength = prefix.length; | |
for (var i = 0; i < mediaLines.length; i++) { | |
if (mediaLines[i].substr(0, prefixLength) === prefix) { | |
return mediaLines[i]; | |
} | |
} | |
// Continue searching in parent session section | |
if (!sessionLines) { | |
return false; | |
} | |
for (var j = 0; j < sessionLines.length; j++) { | |
if (sessionLines[j].substr(0, prefixLength) === prefix) { | |
return sessionLines[j]; | |
} | |
} | |
return false; | |
}; | |
exports.findLines = function (prefix, mediaLines, sessionLines) { | |
var results = []; | |
var prefixLength = prefix.length; | |
for (var i = 0; i < mediaLines.length; i++) { | |
if (mediaLines[i].substr(0, prefixLength) === prefix) { | |
results.push(mediaLines[i]); | |
} | |
} | |
if (results.length || !sessionLines) { | |
return results; | |
} | |
for (var j = 0; j < sessionLines.length; j++) { | |
if (sessionLines[j].substr(0, prefixLength) === prefix) { | |
results.push(sessionLines[j]); | |
} | |
} | |
return results; | |
}; | |
exports.mline = function (line) { | |
var parts = line.substr(2).split(' '); | |
var parsed = { | |
media: parts[0], | |
port: parts[1], | |
proto: parts[2], | |
formats: [] | |
}; | |
for (var i = 3; i < parts.length; i++) { | |
if (parts[i]) { | |
parsed.formats.push(parts[i]); | |
} | |
} | |
return parsed; | |
}; | |
exports.rtpmap = function (line) { | |
var parts = line.substr(9).split(' '); | |
var parsed = { | |
id: parts.shift() | |
}; | |
parts = parts[0].split('/'); | |
parsed.name = parts[0]; | |
parsed.clockrate = parts[1]; | |
parsed.channels = parts.length == 3 ? parts[2] : '1'; | |
return parsed; | |
}; | |
exports.fmtp = function (line) { | |
var kv, key, value; | |
var parts = line.substr(line.indexOf(' ') + 1).split(';'); | |
var parsed = []; | |
for (var i = 0; i < parts.length; i++) { | |
kv = parts[i].split('='); | |
key = kv[0].trim(); | |
value = kv[1]; | |
if (key && value) { | |
parsed.push({key: key, value: value}); | |
} else if (key) { | |
parsed.push({key: '', value: key}); | |
} | |
} | |
return parsed; | |
}; | |
exports.crypto = function (line) { | |
var parts = line.substr(9).split(' '); | |
var parsed = { | |
tag: parts[0], | |
cipherSuite: parts[1], | |
keyParams: parts[2], | |
sessionParams: parts.slice(3).join(' ') | |
}; | |
return parsed; | |
}; | |
exports.fingerprint = function (line) { | |
var parts = line.substr(14).split(' '); | |
return { | |
hash: parts[0], | |
value: parts[1] | |
}; | |
}; | |
exports.extmap = function (line) { | |
var parts = line.substr(9).split(' '); | |
var parsed = {}; | |
var idpart = parts.shift(); | |
var sp = idpart.indexOf('/'); | |
if (sp >= 0) { | |
parsed.id = idpart.substr(0, sp); | |
parsed.senders = idpart.substr(sp + 1); | |
} else { | |
parsed.id = idpart; | |
parsed.senders = 'sendrecv'; | |
} | |
parsed.uri = parts.shift() || ''; | |
return parsed; | |
}; | |
exports.rtcpfb = function (line) { | |
var parts = line.substr(10).split(' '); | |
var parsed = {}; | |
parsed.id = parts.shift(); | |
parsed.type = parts.shift(); | |
if (parsed.type === 'trr-int') { | |
parsed.value = parts.shift(); | |
} else { | |
parsed.subtype = parts.shift() || ''; | |
} | |
parsed.parameters = parts; | |
return parsed; | |
}; | |
exports.candidate = function (line) { | |
var parts = line.substring(12).split(' '); | |
var candidate = { | |
foundation: parts[0], | |
component: parts[1], | |
protocol: parts[2].toLowerCase(), | |
priority: parts[3], | |
ip: parts[4], | |
port: parts[5], | |
// skip parts[6] == 'typ' | |
type: parts[7], | |
generation: '0' | |
}; | |
for (var i = 8; i < parts.length; i += 2) { | |
if (parts[i] === 'raddr') { | |
candidate.relAddr = parts[i + 1]; | |
} else if (parts[i] === 'rport') { | |
candidate.relPort = parts[i + 1]; | |
} else if (parts[i] === 'generation') { | |
candidate.generation = parts[i + 1]; | |
} | |
} | |
candidate.network = '1'; | |
return candidate; | |
}; | |
exports.sourceGroups = function (lines) { | |
var parsed = []; | |
for (var i = 0; i < lines.length; i++) { | |
var parts = lines[i].substr(13).split(' '); | |
parsed.push({ | |
semantics: parts.shift(), | |
sources: parts | |
}); | |
} | |
return parsed; | |
}; | |
exports.sources = function (lines) { | |
// http://tools.ietf.org/html/rfc5576 | |
var parsed = []; | |
var sources = {}; | |
for (var i = 0; i < lines.length; i++) { | |
var parts = lines[i].substr(7).split(' '); | |
var ssrc = parts.shift(); | |
if (!sources[ssrc]) { | |
var source = { | |
ssrc: ssrc, | |
parameters: [] | |
}; | |
parsed.push(source); | |
// Keep an index | |
sources[ssrc] = source; | |
} | |
parts = parts.join(' ').split(':'); | |
var attribute = parts.shift(); | |
var value = parts.join(':') || null; | |
sources[ssrc].parameters.push({ | |
key: attribute, | |
value: value | |
}); | |
} | |
return parsed; | |
}; | |
exports.groups = function (lines) { | |
// http://tools.ietf.org/html/rfc5888 | |
var parsed = []; | |
var parts; | |
for (var i = 0; i < lines.length; i++) { | |
parts = lines[i].substr(8).split(' '); | |
parsed.push({ | |
semantics: parts.shift(), | |
contents: parts | |
}); | |
} | |
return parsed; | |
}; | |
},{}],161:[function(_dereq_,module,exports){ | |
var parsers = _dereq_('./parsers'); | |
var idCounter = Math.random(); | |
exports._setIdCounter = function (counter) { | |
idCounter = counter; | |
}; | |
exports.toSessionJSON = function (sdp, creator) { | |
// Divide the SDP into session and media sections. | |
var media = sdp.split('\r\nm='); | |
for (var i = 1; i < media.length; i++) { | |
media[i] = 'm=' + media[i]; | |
if (i !== media.length - 1) { | |
media[i] += '\r\n'; | |
} | |
} | |
var session = media.shift() + '\r\n'; | |
var sessionLines = parsers.lines(session); | |
var parsed = {}; | |
var contents = []; | |
media.forEach(function (m) { | |
contents.push(exports.toMediaJSON(m, session, creator)); | |
}); | |
parsed.contents = contents; | |
var groupLines = parsers.findLines('a=group:', sessionLines); | |
if (groupLines.length) { | |
parsed.groups = parsers.groups(groupLines); | |
} | |
return parsed; | |
}; | |
exports.toMediaJSON = function (media, session, creator) { | |
var lines = parsers.lines(media); | |
var sessionLines = parsers.lines(session); | |
var mline = parsers.mline(lines[0]); | |
var content = { | |
creator: creator, | |
name: mline.media, | |
description: { | |
descType: 'rtp', | |
media: mline.media, | |
payloads: [], | |
encryption: [], | |
feedback: [], | |
headerExtensions: [] | |
}, | |
transport: { | |
transType: 'iceUdp', | |
candidates: [], | |
fingerprints: [] | |
} | |
}; | |
var desc = content.description; | |
var trans = content.transport; | |
var ssrc = parsers.findLine('a=ssrc:', lines); | |
if (ssrc) { | |
desc.ssrc = ssrc.substr(7).split(' ')[0]; | |
} | |
// If we have a mid, use that for the content name instead. | |
var mid = parsers.findLine('a=mid:', lines); | |
if (mid) { | |
content.name = mid.substr(6); | |
} | |
if (parsers.findLine('a=sendrecv', lines, sessionLines)) { | |
content.senders = 'both'; | |
} else if (parsers.findLine('a=sendonly', lines, sessionLines)) { | |
content.senders = 'initiator'; | |
} else if (parsers.findLine('a=recvonly', lines, sessionLines)) { | |
content.senders = 'responder'; | |
} else if (parsers.findLine('a=inactive', lines, sessionLines)) { | |
content.senders = 'none'; | |
} | |
var rtpmapLines = parsers.findLines('a=rtpmap:', lines); | |
rtpmapLines.forEach(function (line) { | |
var payload = parsers.rtpmap(line); | |
payload.feedback = []; | |
var fmtpLines = parsers.findLines('a=fmtp:' + payload.id, lines); | |
fmtpLines.forEach(function (line) { | |
payload.parameters = parsers.fmtp(line); | |
}); | |
var fbLines = parsers.findLines('a=rtcp-fb:' + payload.id, lines); | |
fbLines.forEach(function (line) { | |
payload.feedback.push(parsers.rtcpfb(line)); | |
}); | |
desc.payloads.push(payload); | |
}); | |
var cryptoLines = parsers.findLines('a=crypto:', lines, sessionLines); | |
cryptoLines.forEach(function (line) { | |
desc.encryption.push(parsers.crypto(line)); | |
}); | |
if (parsers.findLine('a=rtcp-mux', lines)) { | |
desc.mux = true; | |
} | |
var fbLines = parsers.findLines('a=rtcp-fb:*', lines); | |
fbLines.forEach(function (line) { | |
desc.feedback.push(parsers.rtcpfb(line)); | |
}); | |
var extLines = parsers.findLines('a=extmap:', lines); | |
extLines.forEach(function (line) { | |
var ext = parsers.extmap(line); | |
var senders = { | |
sendonly: 'responder', | |
recvonly: 'initiator', | |
sendrecv: 'both', | |
inactive: 'none' | |
}; | |
ext.senders = senders[ext.senders]; | |
desc.headerExtensions.push(ext); | |
}); | |
var ssrcGroupLines = parsers.findLines('a=ssrc-group:', lines); | |
desc.sourceGroups = parsers.sourceGroups(ssrcGroupLines || []); | |
var ssrcLines = parsers.findLines('a=ssrc:', lines); | |
desc.sources = parsers.sources(ssrcLines || []); | |
var fingerprintLines = parsers.findLines('a=fingerprint:', lines, sessionLines); | |
fingerprintLines.forEach(function (line) { | |
var fp = parsers.fingerprint(line); | |
var setup = parsers.findLine('a=setup:', lines, sessionLines); | |
if (setup) { | |
fp.setup = setup.substr(8); | |
} | |
trans.fingerprints.push(fp); | |
}); | |
var ufragLine = parsers.findLine('a=ice-ufrag:', lines, sessionLines); | |
var pwdLine = parsers.findLine('a=ice-pwd:', lines, sessionLines); | |
if (ufragLine && pwdLine) { | |
trans.ufrag = ufragLine.substr(12); | |
trans.pwd = pwdLine.substr(10); | |
trans.candidates = []; | |
var candidateLines = parsers.findLines('a=candidate:', lines, sessionLines); | |
candidateLines.forEach(function (line) { | |
trans.candidates.push(exports.toCandidateJSON(line)); | |
}); | |
} | |
return content; | |
}; | |
exports.toCandidateJSON = function (line) { | |
var candidate = parsers.candidate(line.split('\r\n')[0]); | |
candidate.id = (idCounter++).toString(36).substr(0, 12); | |
return candidate; | |
}; | |
},{"./parsers":160}],162:[function(_dereq_,module,exports){ | |
var senders = { | |
'initiator': 'sendonly', | |
'responder': 'recvonly', | |
'both': 'sendrecv', | |
'none': 'inactive', | |
'sendonly': 'initator', | |
'recvonly': 'responder', | |
'sendrecv': 'both', | |
'inactive': 'none' | |
}; | |
exports.toSessionSDP = function (session, sid, time) { | |
var sdp = [ | |
'v=0', | |
'o=- ' + (sid || session.sid || Date.now()) + ' ' + (time || Date.now()) + ' IN IP4 0.0.0.0', | |
's=-', | |
't=0 0' | |
]; | |
var groups = session.groups || []; | |
groups.forEach(function (group) { | |
sdp.push('a=group:' + group.semantics + ' ' + group.contents.join(' ')); | |
}); | |
var contents = session.contents || []; | |
contents.forEach(function (content) { | |
sdp.push(exports.toMediaSDP(content)); | |
}); | |
return sdp.join('\r\n') + '\r\n'; | |
}; | |
exports.toMediaSDP = function (content) { | |
var sdp = []; | |
var desc = content.description; | |
var transport = content.transport; | |
var payloads = desc.payloads || []; | |
var fingerprints = (transport && transport.fingerprints) || []; | |
var mline = [desc.media, '1']; | |
if ((desc.encryption && desc.encryption.length > 0) || (fingerprints.length > 0)) { | |
mline.push('RTP/SAVPF'); | |
} else { | |
mline.push('RTP/AVPF'); | |
} | |
payloads.forEach(function (payload) { | |
mline.push(payload.id); | |
}); | |
sdp.push('m=' + mline.join(' ')); | |
sdp.push('c=IN IP4 0.0.0.0'); | |
sdp.push('a=rtcp:1 IN IP4 0.0.0.0'); | |
if (transport) { | |
if (transport.ufrag) { | |
sdp.push('a=ice-ufrag:' + transport.ufrag); | |
} | |
if (transport.pwd) { | |
sdp.push('a=ice-pwd:' + transport.pwd); | |
} | |
if (transport.setup) { | |
sdp.push('a=setup:' + transport.setup); | |
} | |
fingerprints.forEach(function (fingerprint) { | |
sdp.push('a=fingerprint:' + fingerprint.hash + ' ' + fingerprint.value); | |
}); | |
} | |
sdp.push('a=' + (senders[content.senders] || 'sendrecv')); | |
sdp.push('a=mid:' + content.name); | |
if (desc.mux) { | |
sdp.push('a=rtcp-mux'); | |
} | |
var encryption = desc.encryption || []; | |
encryption.forEach(function (crypto) { | |
sdp.push('a=crypto:' + crypto.tag + ' ' + crypto.cipherSuite + ' ' + crypto.keyParams + (crypto.sessionParams ? ' ' + crypto.sessionParams : '')); | |
}); | |
payloads.forEach(function (payload) { | |
var rtpmap = 'a=rtpmap:' + payload.id + ' ' + payload.name + '/' + payload.clockrate; | |
if (payload.channels && payload.channels != '1') { | |
rtpmap += '/' + payload.channels; | |
} | |
sdp.push(rtpmap); | |
if (payload.parameters && payload.parameters.length) { | |
var fmtp = ['a=fmtp:' + payload.id]; | |
payload.parameters.forEach(function (param) { | |
fmtp.push((param.key ? param.key + '=' : '') + param.value); | |
}); | |
sdp.push(fmtp.join(' ')); | |
} | |
if (payload.feedback) { | |
payload.feedback.forEach(function (fb) { | |
if (fb.type === 'trr-int') { | |
sdp.push('a=rtcp-fb:' + payload.id + ' trr-int ' + fb.value ? fb.value : '0'); | |
} else { | |
sdp.push('a=rtcp-fb:' + payload.id + ' ' + fb.type + (fb.subtype ? ' ' + fb.subtype : '')); | |
} | |
}); | |
} | |
}); | |
if (desc.feedback) { | |
desc.feedback.forEach(function (fb) { | |
if (fb.type === 'trr-int') { | |
sdp.push('a=rtcp-fb:* trr-int ' + fb.value ? fb.value : '0'); | |
} else { | |
sdp.push('a=rtcp-fb:* ' + fb.type + (fb.subtype ? ' ' + fb.subtype : '')); | |
} | |
}); | |
} | |
var hdrExts = desc.headerExtensions || []; | |
hdrExts.forEach(function (hdr) { | |
sdp.push('a=extmap:' + hdr.id + (hdr.senders ? '/' + senders[hdr.senders] : '') + ' ' + hdr.uri); | |
}); | |
var ssrcGroups = desc.sourceGroups || []; | |
ssrcGroups.forEach(function (ssrcGroup) { | |
sdp.push('a=ssrc-group:' + ssrcGroup.semantics + ' ' + ssrcGroup.sources.join(' ')); | |
}); | |
var ssrcs = desc.sources || []; | |
ssrcs.forEach(function (ssrc) { | |
for (var i = 0; i < ssrc.parameters.length; i++) { | |
var param = ssrc.parameters[i]; | |
sdp.push('a=ssrc:' + (ssrc.ssrc || desc.ssrc) + ' ' + param.key + (param.value ? (':' + param.value) : '')); | |
} | |
}); | |
var candidates = transport.candidates || []; | |
candidates.forEach(function (candidate) { | |
sdp.push(exports.toCandidateSDP(candidate)); | |
}); | |
return sdp.join('\r\n'); | |
}; | |
exports.toCandidateSDP = function (candidate) { | |
var sdp = []; | |
sdp.push(candidate.foundation); | |
sdp.push(candidate.component); | |
sdp.push(candidate.protocol); | |
sdp.push(candidate.priority); | |
sdp.push(candidate.ip); | |
sdp.push(candidate.port); | |
var type = candidate.type; | |
sdp.push('typ'); | |
sdp.push(type); | |
if (type === 'srflx' || type === 'prflx' || type === 'relay') { | |
if (candidate.relAddr && candidate.relPort) { | |
sdp.push('raddr'); | |
sdp.push(candidate.relAddr); | |
sdp.push('rport'); | |
sdp.push(candidate.relPort); | |
} | |
} | |
sdp.push('generation'); | |
sdp.push(candidate.generation || '0'); | |
return 'a=candidate:' + sdp.join(' '); | |
}; | |
},{}],163:[function(_dereq_,module,exports){ | |
// created by @HenrikJoreteg | |
var prefix; | |
var isChrome = false; | |
var isFirefox = false; | |
var ua = window.navigator.userAgent.toLowerCase(); | |
// basic sniffing | |
if (ua.indexOf('firefox') !== -1) { | |
prefix = 'moz'; | |
isFirefox = true; | |
} else if (ua.indexOf('chrome') !== -1) { | |
prefix = 'webkit'; | |
isChrome = true; | |
} | |
var PC = window.mozRTCPeerConnection || window.webkitRTCPeerConnection; | |
var IceCandidate = window.mozRTCIceCandidate || window.RTCIceCandidate; | |
var SessionDescription = window.mozRTCSessionDescription || window.RTCSessionDescription; | |
var MediaStream = window.webkitMediaStream || window.MediaStream; | |
var screenSharing = window.location.protocol === 'https:' && window.navigator.userAgent.match('Chrome') && parseInt(window.navigator.userAgent.match(/Chrome\/(.*) /)[1], 10) >= 26; | |
var AudioContext = window.webkitAudioContext || window.AudioContext; | |
// export support flags and constructors.prototype && PC | |
module.exports = { | |
support: !!PC, | |
dataChannel: isChrome || isFirefox || (PC && PC.prototype && PC.prototype.createDataChannel), | |
prefix: prefix, | |
webAudio: !!(AudioContext && AudioContext.prototype.createMediaStreamSource), | |
mediaStream: !!(MediaStream && MediaStream.prototype.removeTrack), | |
screenSharing: !!screenSharing, | |
AudioContext: AudioContext, | |
PeerConnection: PC, | |
SessionDescription: SessionDescription, | |
IceCandidate: IceCandidate | |
}; | |
},{}],164:[function(_dereq_,module,exports){ | |
"use strict"; | |
var _ = _dereq_('underscore'); | |
var core = _dereq_('./lib/core'); | |
var helpers = _dereq_('./lib/helpers'); | |
var types = _dereq_('./lib/types'); | |
module.exports = _.extend({}, core, helpers, types); | |
},{"./lib/core":165,"./lib/helpers":166,"./lib/types":167,"underscore":187}],165:[function(_dereq_,module,exports){ | |
"use strict"; | |
var _ = _dereq_('underscore'); | |
var xmlshim = _dereq_('ltx-dom-shim'); | |
var helpers = _dereq_('./helpers'); | |
var types = _dereq_('./types'); | |
var find = helpers.find; | |
var LOOKUP = {}; | |
var LOOKUP_EXT = {}; | |
var TOP_LEVEL_LOOKUP = {}; | |
function topLevel(JXT) { | |
var name = JXT.prototype._NS + '|' + JXT.prototype._EL; | |
LOOKUP[name] = JXT; | |
TOP_LEVEL_LOOKUP[name] = JXT; | |
} | |
function toString(xml) { | |
return xmlshim.serializeToString(xml); | |
} | |
function toJSON(jxt) { | |
var prop; | |
var result = {}; | |
var exclude = { | |
constructor: true, | |
_EL: true, | |
_NS: true, | |
_extensions: true, | |
_name: true, | |
parent: true, | |
prototype: true, | |
toJSON: true, | |
toString: true, | |
xml: true | |
}; | |
for (prop in jxt._extensions) { | |
if (jxt._extensions[prop].toJSON && prop[0] !== '_') { | |
result[prop] = jxt._extensions[prop].toJSON(); | |
} | |
} | |
for (prop in jxt) { | |
if (!exclude[prop] && !((LOOKUP_EXT[jxt._NS + '|' + jxt._EL] || {})[prop]) && !jxt._extensions[prop] && prop[0] !== '_') { | |
var val = jxt[prop]; | |
if (typeof val == 'function') continue; | |
var type = Object.prototype.toString.call(val); | |
if (type.indexOf('Object') >= 0) { | |
if (Object.keys(val).length > 0) { | |
result[prop] = val; | |
} | |
} else if (type.indexOf('Array') >= 0) { | |
if (val.length > 0) { | |
result[prop] = val; | |
} | |
} else if (val !== undefined && val !== false && val !== '') { | |
result[prop] = val; | |
} | |
} | |
} | |
return result; | |
} | |
exports.build = function (xml) { | |
var JXT = TOP_LEVEL_LOOKUP[xml.namespaceURI + '|' + xml.localName]; | |
if (JXT) { | |
return new JXT(null, xml); | |
} | |
}; | |
exports.parse = function (str, JXT, lookupContext) { | |
lookupContext = lookupContext || TOP_LEVEL_LOOKUP; | |
var nodes = xmlshim.parseFromString(str, 'application/xml').childNodes; | |
for (var i = 0; i < nodes.length; i++) { | |
if (nodes[i].nodeType === 1) { | |
// Check for parse errors because browsers are stupid | |
if (nodes[i].nodeName === 'parsererror') { | |
// Matches Firefox parse error | |
throw new Error({name: 'parsererror', message: 'Could not parse: ' + str}); | |
} else if (nodes[i].childElementCount > 0 && nodes[i].childNodes[0].nodeName === 'parsererror') { | |
// Matches Webkit parse error | |
throw new Error({name: 'parsererror', message: 'Could not parse: ' + str}); | |
} | |
var xml = nodes[i]; | |
if (JXT) { | |
return new JXT(null, xml); | |
} else { | |
JXT = lookupContext[xml.namespaceURI + '|' + xml.localName]; | |
return new JXT(null, xml); | |
} | |
} | |
} | |
throw new Error({name: 'parsererror', message: 'Could not parse: ' + str}); | |
}; | |
exports.extend = function (ParentJXT, ChildJXT, multiName) { | |
var parentName = ParentJXT.prototype._NS + '|' + ParentJXT.prototype._EL; | |
var name = ChildJXT.prototype._name; | |
var qName = ChildJXT.prototype._NS + '|' + ChildJXT.prototype._EL; | |
LOOKUP[qName] = ChildJXT; | |
if (!LOOKUP_EXT[qName]) { | |
LOOKUP_EXT[qName] = {}; | |
} | |
if (!LOOKUP_EXT[parentName]) { | |
LOOKUP_EXT[parentName] = {}; | |
} | |
LOOKUP_EXT[parentName][name] = ChildJXT; | |
exports.add(ParentJXT, name, types.extension(ChildJXT)); | |
if (multiName) { | |
exports.add(ParentJXT, multiName, types.multiExtension(ChildJXT)); | |
} | |
}; | |
exports.add = function (ParentJXT, fieldName, field) { | |
field.enumerable = true; | |
Object.defineProperty(ParentJXT.prototype, fieldName, field); | |
}; | |
exports.define = function (opts) { | |
var StanzaConstructor = function (data, xml, parent) { | |
var self = this; | |
var parentNode = (xml || {}).parentNode || (parent || {}).xml; | |
var parentNS = (parentNode || {}).namespaceURI; | |
self.xml = xml || helpers.createElement(self._NS, self._EL, parentNS); | |
var prefixes = opts.prefixes || {}; | |
_.each(opts.prefixes || {}, function (namespace, prefix) { | |
self.xml.setAttribute('xmlns:' + prefix, namespace); | |
}); | |
self._extensions = {}; | |
_.each(self.xml.childNodes, function (child) { | |
var childName = child.namespaceURI + '|' + child.localName; | |
var ChildJXT = LOOKUP[childName]; | |
if (ChildJXT !== undefined) { | |
var name = ChildJXT.prototype._name; | |
self._extensions[name] = new ChildJXT(null, child); | |
self._extensions[name].parent = self; | |
} | |
}); | |
_.extend(self, data); | |
if (opts.init) { | |
opts.init.apply(self, [data]); | |
} | |
return self; | |
}; | |
StanzaConstructor.prototype = { | |
constructor: { | |
value: StanzaConstructor | |
}, | |
_name: opts.name, | |
_eventname: opts.eventName, | |
_NS: opts.namespace, | |
_EL: opts.element, | |
toString: function () { return toString(this.xml); }, | |
toJSON: function () { return toJSON(this); } | |
}; | |
var fieldNames = Object.keys(opts.fields || {}); | |
fieldNames.forEach(function (fieldName) { | |
exports.add(StanzaConstructor, fieldName, opts.fields[fieldName]); | |
}); | |
if (opts.topLevel) { | |
topLevel(StanzaConstructor); | |
} | |
return StanzaConstructor; | |
}; | |
},{"./helpers":166,"./types":167,"ltx-dom-shim":168,"underscore":187}],166:[function(_dereq_,module,exports){ | |
"use strict"; | |
var _ = _dereq_('underscore'); | |
var xmlshim = _dereq_('ltx-dom-shim'); | |
var XML_NS = exports.XML_NS = 'http://www.w3.org/XML/1998/namespace'; | |
exports.createElement = function (NS, name, parentNS) { | |
var el = xmlshim.createElementNS(NS, name); | |
if (!parentNS || parentNS !== NS) { | |
exports.setAttribute(el, 'xmlns', NS); | |
} | |
return el; | |
}; | |
var find = exports.find = function (xml, NS, selector) { | |
var children = xml.getElementsByTagName(selector); | |
return _.filter(children, function (child) { | |
return child.namespaceURI === NS && child.parentNode == xml; | |
}); | |
}; | |
exports.findOrCreate = function (xml, NS, selector) { | |
var existing = exports.find(xml, NS, selector); | |
if (existing.length) { | |
return existing[0]; | |
} else { | |
var created = exports.createElement(NS, selector, xml.namespaceURI); | |
xml.appendChild(created); | |
return created; | |
} | |
}; | |
exports.getAttribute = function (xml, attr, defaultVal) { | |
return xml.getAttribute(attr) || defaultVal || ''; | |
}; | |
exports.getAttributeNS = function (xml, NS, attr, defaultVal) { | |
return xml.getAttributeNS(NS, attr) || defaultVal || ''; | |
}; | |
exports.setAttribute = function (xml, attr, value, force) { | |
if (value || force) { | |
xml.setAttribute(attr, value); | |
} else { | |
xml.removeAttribute(attr); | |
} | |
}; | |
exports.setAttributeNS = function (xml, NS, attr, value, force) { | |
if (value || force) { | |
xml.setAttributeNS(NS, attr, value); | |
} else { | |
xml.removeAttributeNS(NS, attr); | |
} | |
}; | |
exports.getBoolAttribute = function (xml, attr, defaultVal) { | |
var val = xml.getAttribute(attr) || defaultVal || ''; | |
return val === 'true' || val === '1'; | |
}; | |
exports.setBoolAttribute = function (xml, attr, value) { | |
if (value) { | |
xml.setAttribute(attr, '1'); | |
} else { | |
xml.removeAttribute(attr); | |
} | |
}; | |
exports.getSubAttribute = function (xml, NS, sub, attr, defaultVal) { | |
var subs = find(xml, NS, sub); | |
if (!subs) { | |
return ''; | |
} | |
for (var i = 0; i < subs.length; i++) { | |
return subs[i].getAttribute(attr) || defaultVal || ''; | |
} | |
return ''; | |
}; | |
exports.setSubAttribute = function (xml, NS, sub, attr, value) { | |
var subs = find(xml, NS, sub); | |
if (!subs.length) { | |
if (value) { | |
sub = exports.createElement(NS, sub, xml.namespaceURI); | |
sub.setAttribute(attr, value); | |
xml.appendChild(sub); | |
} | |
} else { | |
for (var i = 0; i < subs.length; i++) { | |
if (value) { | |
subs[i].setAttribute(attr, value); | |
return; | |
} else { | |
subs[i].removeAttribute(attr); | |
} | |
} | |
} | |
}; | |
exports.getBoolSubAttribute = function (xml, NS, sub, attr, defaultVal) { | |
var val = xml.getSubAttribute(NS, sub, attr) || defaultVal || ''; | |
return val === 'true' || val === '1'; | |
}; | |
exports.setBoolSubAttribute = function (xml, NS, sub, attr, value) { | |
value = value ? '1' : ''; | |
exports.setSubAttribute(xml, NS, sub, attr, value); | |
}; | |
exports.getText = function (xml) { | |
return xml.textContent; | |
}; | |
exports.setText = function (xml, value) { | |
xml.textContent = value; | |
}; | |
exports.getSubText = function (xml, NS, element, defaultVal) { | |
var subs = find(xml, NS, element); | |
defaultVal = defaultVal || ''; | |
if (!subs.length) { | |
return defaultVal; | |
} | |
return subs[0].textContent || defaultVal; | |
}; | |
exports.setSubText = function (xml, NS, element, value) { | |
var subs = find(xml, NS, element); | |
if (!subs.length) { | |
if (value) { | |
var sub = exports.createElement(NS, element, xml.namespaceURI); | |
sub.textContent = value; | |
xml.appendChild(sub); | |
} | |
} else { | |
for (var i = 0; i < subs.length; i++) { | |
if (value) { | |
subs[i].textContent = value; | |
return; | |
} else { | |
xml.removeChild(subs[i]); | |
} | |
} | |
} | |
}; | |
exports.getMultiSubText = function (xml, NS, element, extractor) { | |
var subs = find(xml, NS, element); | |
var results = []; | |
extractor = extractor || function (sub) { | |
return sub.textContent || ''; | |
}; | |
for (var i = 0; i < subs.length; i++) { | |
results.push(extractor(subs[i])); | |
} | |
return results; | |
}; | |
exports.setMultiSubText = function (xml, NS, element, value, builder) { | |
var subs = find(xml, NS, element); | |
var values = []; | |
builder = builder || function (value) { | |
var sub = exports.createElement(NS, element, xml.namespaceURI); | |
sub.textContent = value; | |
xml.appendChild(sub); | |
}; | |
if (typeof value === 'string') { | |
values = (value || '').split('\n'); | |
} else { | |
values = value; | |
} | |
_.forEach(subs, function (sub) { | |
xml.removeChild(sub); | |
}); | |
_.forEach(values, function (val) { | |
if (val) { | |
builder(val); | |
} | |
}); | |
}; | |
exports.getSubLangText = function (xml, NS, element, defaultLang) { | |
var subs = find(xml, NS, element); | |
if (!subs.length) { | |
return {}; | |
} | |
var lang, sub; | |
var results = {}; | |
var langs = []; | |
for (var i = 0; i < subs.length; i++) { | |
sub = subs[i]; | |
lang = sub.getAttributeNS(XML_NS, 'lang') || defaultLang; | |
langs.push(lang); | |
results[lang] = sub.textContent || ''; | |
} | |
return results; | |
}; | |
exports.setSubLangText = function (xml, NS, element, value, defaultLang) { | |
var sub, lang; | |
var subs = find(xml, NS, element); | |
if (subs.length) { | |
for (var i = 0; i < subs.length; i++) { | |
xml.removeChild(subs[i]); | |
} | |
} | |
if (typeof value === 'string') { | |
sub = exports.createElement(NS, element, xml.namespaceURI); | |
sub.textContent = value; | |
xml.appendChild(sub); | |
} else if (typeof value === 'object') { | |
for (lang in value) { | |
if (value.hasOwnProperty(lang)) { | |
sub = exports.createElement(NS, element, xml.namespaceURI); | |
if (lang !== defaultLang) { | |
sub.setAttributeNS(XML_NS, 'lang', lang); | |
} | |
sub.textContent = value[lang]; | |
xml.appendChild(sub); | |
} | |
} | |
} | |
}; | |
exports.getBoolSub = function (xml, NS, element) { | |
var subs = find(xml, NS, element); | |
return !!subs.length; | |
}; | |
exports.setBoolSub = function (xml, NS, element, value) { | |
var subs = find(xml, NS, element); | |
if (!subs.length) { | |
if (value) { | |
var sub = exports.createElement(NS, element, xml.namespaceURI); | |
xml.appendChild(sub); | |
} | |
} else { | |
for (var i = 0; i < subs.length; i++) { | |
if (value) { | |
return; | |
} else { | |
xml.removeChild(subs[i]); | |
} | |
} | |
} | |
}; | |
},{"ltx-dom-shim":168,"underscore":187}],167:[function(_dereq_,module,exports){ | |
"use strict"; | |
var _ = _dereq_('underscore'); | |
var fromB64 = _dereq_('atob'); | |
var toB64 = _dereq_('btoa'); | |
var helpers = _dereq_('./helpers'); | |
var find = helpers.find; | |
var field = exports.field = function (getter, setter) { | |
return function () { | |
var args = _.toArray(arguments); | |
return { | |
get: function () { | |
return getter.apply(null, [this.xml].concat(args)); | |
}, | |
set: function (value) { | |
setter.apply(null, ([this.xml].concat(args)).concat([value])); | |
} | |
}; | |
}; | |
}; | |
exports.field = field; | |
exports.boolAttribute = field(helpers.getBoolAttribute, | |
helpers.setBoolAttribute); | |
exports.subAttribute = field(helpers.getSubAttribute, | |
helpers.setSubAttribute); | |
exports.boolSubAttribute = field(helpers.getSubBoolAttribute, | |
helpers.setSubBoolAttribute); | |
exports.text = field(helpers.getText, | |
helpers.setText); | |
exports.subText = field(helpers.getSubText, | |
helpers.setSubText); | |
exports.multiSubText = field(helpers.getMultiSubText, | |
helpers.setMultiSubText); | |
exports.subLangText = field(helpers.getSubLangText, | |
helpers.setSubLangText); | |
exports.boolSub = field(helpers.getBoolSub, | |
helpers.setBoolSub); | |
exports.langAttribute = field( | |
function (xml) { | |
return xml.getAttributeNS(helpers.XML_NS, 'lang') || ''; | |
}, | |
function (xml, value) { | |
xml.setAttributeNS(helpers.XML_NS, 'lang', value); | |
} | |
); | |
exports.b64Text = field( | |
function (xml) { | |
if (xml.textContent && xml.textContent != '=') { | |
return fromB64(xml.textContent); | |
} | |
return ''; | |
}, | |
function (xml, value) { | |
xml.textContent = toB64(value) || '='; | |
} | |
); | |
exports.dateAttribute = function (attr, now) { | |
return { | |
get: function () { | |
var data = helpers.getAttribute(this.xml, attr); | |
if (data) return new Date(data); | |
if (now) return new Date(Date.now()); | |
}, | |
set: function (value) { | |
if (!value) return; | |
if (typeof value != 'string') { | |
value = value.toISOString(); | |
} | |
helpers.setAttribute(this.xml, attr, value); | |
} | |
}; | |
}; | |
exports.dateSub = function (NS, sub, now) { | |
return { | |
get: function () { | |
var data = helpers.getSubText(this.xml, NS, sub); | |
if (data) return new Date(data); | |
if (now) return new Date(Date.now()); | |
}, | |
set: function (value) { | |
if (!value) return; | |
if (typeof value != 'string') { | |
value = value.toISOString(); | |
} | |
helpers.setSubText(this.xml, NS, sub, value); | |
} | |
}; | |
}; | |
exports.dateSubAttribute = function (NS, sub, attr, now) { | |
return { | |
get: function () { | |
var data = helpers.getSubAttribute(this.xml, NS, sub, attr); | |
if (data) return new Date(data); | |
if (now) return new Date(Date.now()); | |
}, | |
set: function (value) { | |
if (!value) return; | |
if (typeof value != 'string') { | |
value = value.toISOString(); | |
} | |
helpers.setSubAttribute(this.xml, NS, sub, attr, value); | |
} | |
}; | |
}; | |
exports.numberAttribute = function (attr, isFloat) { | |
return { | |
get: function () { | |
var parse = isFloat ? parseFloat : parseInt; | |
return parse(helpers.getAttribute(this.xml, attr, '0'), 10); | |
}, | |
set: function (value) { | |
helpers.setAttribute(this.xml, attr, value.toString()); | |
} | |
}; | |
}; | |
exports.numberSub = function (NS, sub, isFloat) { | |
return { | |
get: function () { | |
var parse = isFloat ? parseFloat : parseInt; | |
return parse(helpers.getSubText(this.xml, NS, sub, '0'), 10); | |
}, | |
set: function (value) { | |
helpers.setSubText(this.xml, NS, sub, value.toString()); | |
} | |
}; | |
}; | |
exports.attribute = function (name, defaultVal) { | |
return { | |
get: function () { | |
return helpers.getAttribute(this.xml, name, defaultVal); | |
}, | |
set: function (value) { | |
helpers.setAttribute(this.xml, name, value); | |
} | |
}; | |
}; | |
exports.attributeNS = function (NS, name, defaultVal) { | |
return { | |
get: function () { | |
return helpers.getAttributeNS(this.xml, NS, name, defaultVal); | |
}, | |
set: function (value) { | |
helpers.setAttributeNS(this.xml, NS, name, value); | |
} | |
}; | |
}; | |
exports.extension = function (ChildJXT) { | |
return { | |
get: function () { | |
var self = this; | |
var name = ChildJXT.prototype._name; | |
if (!this._extensions[name]) { | |
var existing = find(this.xml, ChildJXT.prototype._NS, ChildJXT.prototype._EL); | |
if (!existing.length) { | |
this._extensions[name] = new ChildJXT({}, null, self); | |
this.xml.appendChild(this._extensions[name].xml); | |
} else { | |
this._extensions[name] = new ChildJXT(null, existing[0], self); | |
} | |
this._extensions[name].parent = this; | |
} | |
return this._extensions[name]; | |
}, | |
set: function (value) { | |
var child = this[ChildJXT.prototype._name]; | |
_.extend(child, value); | |
} | |
}; | |
}; | |
exports.multiExtension = function (ChildJXT) { | |
return { | |
get: function () { | |
var self = this; | |
var data = find(this.xml, ChildJXT.prototype._NS, ChildJXT.prototype._EL); | |
var results = []; | |
_.forEach(data, function (xml) { | |
results.push(new ChildJXT({}, xml, self).toJSON()); | |
}); | |
return results; | |
}, | |
set: function (value) { | |
var self = this; | |
var existing = find(this.xml, ChildJXT.prototype._NS, ChildJXT.prototype._EL); | |
_.forEach(existing, function (item) { | |
self.xml.removeChild(item); | |
}); | |
_.forEach(value, function (data) { | |
var content = new ChildJXT(data, null, self); | |
self.xml.appendChild(content.xml); | |
}); | |
} | |
}; | |
}; | |
},{"./helpers":166,"atob":90,"btoa":143,"underscore":187}],168:[function(_dereq_,module,exports){ | |
var parser = new window.DOMParser(); | |
var serializer = new window.XMLSerializer(); | |
module.exports = { | |
serializeToString: function (obj) { | |
return serializer.serializeToString(obj); | |
}, | |
parseFromString: function (str, mimetype) { | |
return parser.parseFromString(str, mimetype); | |
}, | |
createElementNS: function (ns, name) { | |
return document.createElementNS(ns, name); | |
} | |
}; | |
},{}],169:[function(_dereq_,module,exports){ | |
(function (Buffer){ | |
// uuid.js | |
// | |
// Copyright (c) 2010-2012 Robert Kieffer | |
// MIT License - http://opensource.org/licenses/mit-license.php | |
(function() { | |
var _global = this; | |
// Unique ID creation requires a high quality random # generator. We feature | |
// detect to determine the best RNG source, normalizing to a function that | |
// returns 128-bits of randomness, since that's what's usually required | |
var _rng; | |
// Node.js crypto-based RNG - http://nodejs.org/docs/v0.6.2/api/crypto.html | |
// | |
// Moderately fast, high quality | |
if (typeof(_dereq_) == 'function') { | |
try { | |
var _rb = _dereq_('crypto').randomBytes; | |
_rng = _rb && function() {return _rb(16);}; | |
} catch(e) {} | |
} | |
if (!_rng && _global.crypto && crypto.getRandomValues) { | |
// WHATWG crypto-based RNG - http://wiki.whatwg.org/wiki/Crypto | |
// | |
// Moderately fast, high quality | |
var _rnds8 = new Uint8Array(16); | |
_rng = function whatwgRNG() { | |
crypto.getRandomValues(_rnds8); | |
return _rnds8; | |
}; | |
} | |
if (!_rng) { | |
// Math.random()-based (RNG) | |
// | |
// If all else fails, use Math.random(). It's fast, but is of unspecified | |
// quality. | |
var _rnds = new Array(16); | |
_rng = function() { | |
for (var i = 0, r; i < 16; i++) { | |
if ((i & 0x03) === 0) r = Math.random() * 0x100000000; | |
_rnds[i] = r >>> ((i & 0x03) << 3) & 0xff; | |
} | |
return _rnds; | |
}; | |
} | |
// Buffer class to use | |
var BufferClass = typeof(Buffer) == 'function' ? Buffer : Array; | |
// Maps for number <-> hex string conversion | |
var _byteToHex = []; | |
var _hexToByte = {}; | |
for (var i = 0; i < 256; i++) { | |
_byteToHex[i] = (i + 0x100).toString(16).substr(1); | |
_hexToByte[_byteToHex[i]] = i; | |
} | |
// **`parse()` - Parse a UUID into it's component bytes** | |
function parse(s, buf, offset) { | |
var i = (buf && offset) || 0, ii = 0; | |
buf = buf || []; | |
s.toLowerCase().replace(/[0-9a-f]{2}/g, function(oct) { | |
if (ii < 16) { // Don't overflow! | |
buf[i + ii++] = _hexToByte[oct]; | |
} | |
}); | |
// Zero out remaining bytes if string was short | |
while (ii < 16) { | |
buf[i + ii++] = 0; | |
} | |
return buf; | |
} | |
// **`unparse()` - Convert UUID byte array (ala parse()) into a string** | |
function unparse(buf, offset) { | |
var i = offset || 0, bth = _byteToHex; | |
return bth[buf[i++]] + bth[buf[i++]] + | |
bth[buf[i++]] + bth[buf[i++]] + '-' + | |
bth[buf[i++]] + bth[buf[i++]] + '-' + | |
bth[buf[i++]] + bth[buf[i++]] + '-' + | |
bth[buf[i++]] + bth[buf[i++]] + '-' + | |
bth[buf[i++]] + bth[buf[i++]] + | |
bth[buf[i++]] + bth[buf[i++]] + | |
bth[buf[i++]] + bth[buf[i++]]; | |
} | |
// **`v1()` - Generate time-based UUID** | |
// | |
// Inspired by https://github.com/LiosK/UUID.js | |
// and http://docs.python.org/library/uuid.html | |
// random #'s we need to init node and clockseq | |
var _seedBytes = _rng(); | |
// Per 4.5, create and 48-bit node id, (47 random bits + multicast bit = 1) | |
var _nodeId = [ | |
_seedBytes[0] | 0x01, | |
_seedBytes[1], _seedBytes[2], _seedBytes[3], _seedBytes[4], _seedBytes[5] | |
]; | |
// Per 4.2.2, randomize (14 bit) clockseq | |
var _clockseq = (_seedBytes[6] << 8 | _seedBytes[7]) & 0x3fff; | |
// Previous uuid creation time | |
var _lastMSecs = 0, _lastNSecs = 0; | |
// See https://github.com/broofa/node-uuid for API details | |
function v1(options, buf, offset) { | |
var i = buf && offset || 0; | |
var b = buf || []; | |
options = options || {}; | |
var clockseq = options.clockseq != null ? options.clockseq : _clockseq; | |
// UUID timestamps are 100 nano-second units since the Gregorian epoch, | |
// (1582-10-15 00:00). JSNumbers aren't precise enough for this, so | |
// time is handled internally as 'msecs' (integer milliseconds) and 'nsecs' | |
// (100-nanoseconds offset from msecs) since unix epoch, 1970-01-01 00:00. | |
var msecs = options.msecs != null ? options.msecs : new Date().getTime(); | |
// Per 4.2.1.2, use count of uuid's generated during the current clock | |
// cycle to simulate higher resolution clock | |
var nsecs = options.nsecs != null ? options.nsecs : _lastNSecs + 1; | |
// Time since last uuid creation (in msecs) | |
var dt = (msecs - _lastMSecs) + (nsecs - _lastNSecs)/10000; | |
// Per 4.2.1.2, Bump clockseq on clock regression | |
if (dt < 0 && options.clockseq == null) { | |
clockseq = clockseq + 1 & 0x3fff; | |
} | |
// Reset nsecs if clock regresses (new clockseq) or we've moved onto a new | |
// time interval | |
if ((dt < 0 || msecs > _lastMSecs) && options.nsecs == null) { | |
nsecs = 0; | |
} | |
// Per 4.2.1.2 Throw error if too many uuids are requested | |
if (nsecs >= 10000) { | |
throw new Error('uuid.v1(): Can\'t create more than 10M uuids/sec'); | |
} | |
_lastMSecs = msecs; | |
_lastNSecs = nsecs; | |
_clockseq = clockseq; | |
// Per 4.1.4 - Convert from unix epoch to Gregorian epoch | |
msecs += 12219292800000; | |
// `time_low` | |
var tl = ((msecs & 0xfffffff) * 10000 + nsecs) % 0x100000000; | |
b[i++] = tl >>> 24 & 0xff; | |
b[i++] = tl >>> 16 & 0xff; | |
b[i++] = tl >>> 8 & 0xff; | |
b[i++] = tl & 0xff; | |
// `time_mid` | |
var tmh = (msecs / 0x100000000 * 10000) & 0xfffffff; | |
b[i++] = tmh >>> 8 & 0xff; | |
b[i++] = tmh & 0xff; | |
// `time_high_and_version` | |
b[i++] = tmh >>> 24 & 0xf | 0x10; // include version | |
b[i++] = tmh >>> 16 & 0xff; | |
// `clock_seq_hi_and_reserved` (Per 4.2.2 - include variant) | |
b[i++] = clockseq >>> 8 | 0x80; | |
// `clock_seq_low` | |
b[i++] = clockseq & 0xff; | |
// `node` | |
var node = options.node || _nodeId; | |
for (var n = 0; n < 6; n++) { | |
b[i + n] = node[n]; | |
} | |
return buf ? buf : unparse(b); | |
} | |
// **`v4()` - Generate random UUID** | |
// See https://github.com/broofa/node-uuid for API details | |
function v4(options, buf, offset) { | |
// Deprecated - 'format' argument, as supported in v1.2 | |
var i = buf && offset || 0; | |
if (typeof(options) == 'string') { | |
buf = options == 'binary' ? new BufferClass(16) : null; | |
options = null; | |
} | |
options = options || {}; | |
var rnds = options.random || (options.rng || _rng)(); | |
// Per 4.4, set bits for version and `clock_seq_hi_and_reserved` | |
rnds[6] = (rnds[6] & 0x0f) | 0x40; | |
rnds[8] = (rnds[8] & 0x3f) | 0x80; | |
// Copy bytes to buffer, if provided | |
if (buf) { | |
for (var ii = 0; ii < 16; ii++) { | |
buf[i + ii] = rnds[ii]; | |
} | |
} | |
return buf || unparse(rnds); | |
} | |
// Export public API | |
var uuid = v4; | |
uuid.v1 = v1; | |
uuid.v4 = v4; | |
uuid.parse = parse; | |
uuid.unparse = unparse; | |
uuid.BufferClass = BufferClass; | |
if (typeof define === 'function' && define.amd) { | |
// Publish as AMD module | |
define(function() {return uuid;}); | |
} else if (typeof(module) != 'undefined' && module.exports) { | |
// Publish as node.js module | |
module.exports = uuid; | |
} else { | |
// Publish as global (in browsers) | |
var _previousRoot = _global.uuid; | |
// **`noConflict()` - (browser only) to reset global 'uuid' var** | |
uuid.noConflict = function() { | |
_global.uuid = _previousRoot; | |
return uuid; | |
}; | |
_global.uuid = uuid; | |
} | |
}).call(this); | |
}).call(this,_dereq_("buffer").Buffer) | |
},{"buffer":130,"crypto":134}],170:[function(_dereq_,module,exports){ | |
(function(root, factory) { | |
if (typeof exports === 'object') { | |
// CommonJS | |
factory(exports, module); | |
} else if (typeof define === 'function' && define.amd) { | |
// AMD | |
define(['exports', 'module'], factory); | |
} | |
}(this, function(exports, module) { | |
/** | |
* ANONYMOUS `Mechanism` constructor. | |
* | |
* This class implements the ANONYMOUS SASL mechanism. | |
* | |
* The ANONYMOUS SASL mechanism provides support for permitting anonymous | |
* access to various services | |
* | |
* References: | |
* - [RFC 4505](http://tools.ietf.org/html/rfc4505) | |
* | |
* @api public | |
*/ | |
function Mechanism() { | |
} | |
Mechanism.prototype.name = 'ANONYMOUS'; | |
Mechanism.prototype.clientFirst = true; | |
/** | |
* Encode a response using optional trace information. | |
* | |
* Options: | |
* - `trace` trace information (optional) | |
* | |
* @param {Object} cred | |
* @api public | |
*/ | |
Mechanism.prototype.response = function(cred) { | |
return cred.trace || ''; | |
}; | |
/** | |
* Decode a challenge issued by the server. | |
* | |
* @param {String} chal | |
* @api public | |
*/ | |
Mechanism.prototype.challenge = function(chal) { | |
}; | |
exports = module.exports = Mechanism; | |
})); | |
},{}],171:[function(_dereq_,module,exports){ | |
(function(root, factory) { | |
if (typeof exports === 'object') { | |
// CommonJS | |
factory(exports, | |
module, | |
_dereq_('./lib/mechanism')); | |
} else if (typeof define === 'function' && define.amd) { | |
// AMD | |
define(['exports', | |
'module', | |
'./lib/mechanism'], factory); | |
} | |
}(this, function(exports, module, Mechanism) { | |
exports = module.exports = Mechanism; | |
exports.Mechanism = Mechanism; | |
})); | |
},{"./lib/mechanism":170}],172:[function(_dereq_,module,exports){ | |
(function(root, factory) { | |
if (typeof exports === 'object') { | |
// CommonJS | |
factory(exports, module, _dereq_('crypto')); | |
} else if (typeof define === 'function' && define.amd) { | |
// AMD | |
define(['exports', 'module', 'crypto'], factory); | |
} | |
}(this, function(exports, module, crypto) { | |
/** | |
* DIGEST-MD5 `Mechanism` constructor. | |
* | |
* This class implements the DIGEST-MD5 SASL mechanism. | |
* | |
* References: | |
* - [RFC 2831](http://tools.ietf.org/html/rfc2831) | |
* | |
* @api public | |
*/ | |
function Mechanism(options) { | |
options = options || {}; | |
this._genNonce = options.genNonce || genNonce(32); | |
} | |
Mechanism.prototype.name = 'DIGEST-MD5'; | |
Mechanism.prototype.clientFirst = false; | |
/** | |
* Encode a response using given credential. | |
* | |
* Options: | |
* - `username` | |
* - `password` | |
* - `host` | |
* - `serviceType` | |
* - `authzid` authorization identity (optional) | |
* | |
* @param {Object} cred | |
* @api public | |
*/ | |
Mechanism.prototype.response = function(cred) { | |
// TODO: Implement support for subsequent authentication. This requires | |
// that the client be able to store username, realm, nonce, | |
// nonce-count, cnonce, and qop values from prior authentication. | |
// The impact of this requirement needs to be investigated. | |
// | |
// See RFC 2831 (Section 2.2) for further details. | |
// TODO: Implement support for auth-int and auth-conf, as defined in RFC | |
// 2831 sections 2.3 Integrity Protection and 2.4 Confidentiality | |
// Protection, respectively. | |
// | |
// Note that supporting this functionality has implications | |
// regarding the negotiation of security layers via SASL. Due to | |
// the fact that TLS has largely superseded this functionality, | |
// implementing it is a low priority. | |
var uri = cred.serviceType + '/' + cred.host; | |
if (cred.serviceName && cred.host !== cred.serviceName) { | |
uri += '/' + serviceName; | |
} | |
var realm = cred.realm || this._realm || '' | |
, cnonce = this._genNonce() | |
, nc = '00000001' | |
, qop = 'auth' | |
, ha1 | |
, ha2 | |
, digest; | |
var str = ''; | |
str += 'username="' + cred.username + '"'; | |
if (realm) { str += ',realm="' + realm + '"'; }; | |
str += ',nonce="' + this._nonce + '"'; | |
str += ',cnonce="' + cnonce + '"'; | |
str += ',nc=' + nc; | |
str += ',qop=' + qop; | |
str += ',digest-uri="' + uri + '"'; | |
if (cred.authzid) { | |
ha1 = md5(md5(cred.username + ":" + realm + ":" + cred.password, 'binary') + ":" + this._nonce + ":" + cnonce + ":" + cred.authzid); | |
} else { | |
ha1 = md5(md5(cred.username + ":" + realm + ":" + cred.password, 'binary') + ":" + this._nonce + ":" + cnonce); | |
} | |
if (qop == 'auth') { | |
ha2 = md5('AUTHENTICATE:' + uri); | |
} else if (qop == 'auth-int' || qop == 'auth-conf') { | |
ha2 = md5('AUTHENTICATE:' + uri + ':00000000000000000000000000000000'); | |
} | |
digest = md5(ha1 + ":" + this._nonce + ":" + nc + ":" + cnonce + ":" + qop + ":" + ha2); | |
str += ',response=' + digest; | |
if (this._charset == 'utf-8') { str += ',charset=utf-8'; } | |
if (cred.authzid) { str += 'authzid="' + cred.authzid + '"'; } | |
return str; | |
}; | |
/** | |
* Decode a challenge issued by the server. | |
* | |
* @param {String} chal | |
* @return {Mechanism} for chaining | |
* @api public | |
*/ | |
Mechanism.prototype.challenge = function(chal) { | |
var dtives = parse(chal); | |
// TODO: Implement support for multiple realm directives, as allowed by the | |
// DIGEST-MD5 specification. | |
this._realm = dtives['realm']; | |
this._nonce = dtives['nonce']; | |
this._qop = (dtives['qop'] || 'auth').split(','); | |
this._stale = dtives['stale']; | |
this._maxbuf = parseInt(dtives['maxbuf']) || 65536; | |
this._charset = dtives['charset']; | |
this._algo = dtives['algorithm']; | |
this._cipher = dtives['cipher']; | |
if (this._cipher) { this._cipher.split(','); } | |
return this; | |
}; | |
/** | |
* Parse challenge. | |
* | |
* @api private | |
*/ | |
function parse(chal) { | |
var dtives = {}; | |
var tokens = chal.split(/,(?=(?:[^"]|"[^"]*")*$)/); | |
for (var i = 0, len = tokens.length; i < len; i++) { | |
var dtiv = /(\w+)=["]?([^"]+)["]?$/.exec(tokens[i]); | |
if (dtiv) { | |
dtives[dtiv[1]] = dtiv[2]; | |
} | |
} | |
return dtives; | |
} | |
/** | |
* Return a unique nonce with the given `len`. | |
* | |
* genNonce(10)(); | |
* // => "FDaS435D2z" | |
* | |
* @param {Number} len | |
* @return {Function} | |
* @api private | |
*/ | |
function genNonce(len) { | |
var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789' | |
, charlen = chars.length; | |
return function() { | |
var buf = []; | |
for (var i = 0; i < len; ++i) { | |
buf.push(chars[Math.random() * charlen | 0]); | |
} | |
return buf.join(''); | |
} | |
} | |
/** | |
* Return md5 hash of the given string and optional encoding, | |
* defaulting to hex. | |
* | |
* md5('wahoo'); | |
* // => "e493298061761236c96b02ea6aa8a2ad" | |
* | |
* @param {String} str | |
* @param {String} encoding | |
* @return {String} | |
* @api private | |
*/ | |
function md5(str, encoding){ | |
return crypto | |
.createHash('md5') | |
.update(str) | |
.digest(encoding || 'hex'); | |
} | |
exports = module.exports = Mechanism; | |
})); | |
},{"crypto":134}],173:[function(_dereq_,module,exports){ | |
arguments[4][171][0].apply(exports,arguments) | |
},{"./lib/mechanism":172}],174:[function(_dereq_,module,exports){ | |
(function(root, factory) { | |
if (typeof exports === 'object') { | |
// CommonJS | |
factory(exports, module); | |
} else if (typeof define === 'function' && define.amd) { | |
// AMD | |
define(['exports', 'module'], factory); | |
} | |
}(this, function(exports, module) { | |
/** | |
* EXTERNAL `Mechanism` constructor. | |
* | |
* This class implements the EXTERNAL SASL mechanism. | |
* | |
* The EXTERNAL SASL mechanism provides support for authentication using | |
* credentials established by external means. | |
* | |
* References: | |
* - [RFC 4422](http://tools.ietf.org/html/rfc4422) | |
* | |
* @api public | |
*/ | |
function Mechanism() { | |
} | |
Mechanism.prototype.name = 'EXTERNAL'; | |
Mechanism.prototype.clientFirst = true; | |
/** | |
* Encode a response using given credential. | |
* | |
* Options: | |
* - `authzid` authorization identity (optional) | |
* | |
* @param {Object} cred | |
* @api public | |
*/ | |
Mechanism.prototype.response = function(cred) { | |
return cred.authzid || ''; | |
}; | |
/** | |
* Decode a challenge issued by the server. | |
* | |
* @param {String} chal | |
* @api public | |
*/ | |
Mechanism.prototype.challenge = function(chal) { | |
}; | |
exports = module.exports = Mechanism; | |
})); | |
},{}],175:[function(_dereq_,module,exports){ | |
arguments[4][171][0].apply(exports,arguments) | |
},{"./lib/mechanism":174}],176:[function(_dereq_,module,exports){ | |
(function(root, factory) { | |
if (typeof exports === 'object') { | |
// CommonJS | |
factory(exports, module); | |
} else if (typeof define === 'function' && define.amd) { | |
// AMD | |
define(['exports', 'module'], factory); | |
} | |
}(this, function(exports, module) { | |
/** | |
* PLAIN `Mechanism` constructor. | |
* | |
* This class implements the PLAIN SASL mechanism. | |
* | |
* The PLAIN SASL mechanism provides support for exchanging a clear-text | |
* username and password. This mechanism should not be used without adequate | |
* security provided by an underlying transport layer. | |
* | |
* References: | |
* - [RFC 4616](http://tools.ietf.org/html/rfc4616) | |
* | |
* @api public | |
*/ | |
function Mechanism() { | |
} | |
Mechanism.prototype.name = 'PLAIN'; | |
Mechanism.prototype.clientFirst = true; | |
/** | |
* Encode a response using given credential. | |
* | |
* Options: | |
* - `username` | |
* - `password` | |
* - `authzid` authorization identity (optional) | |
* | |
* @param {Object} cred | |
* @api public | |
*/ | |
Mechanism.prototype.response = function(cred) { | |
var str = ''; | |
str += cred.authzid || ''; | |
str += '\0'; | |
str += cred.username; | |
str += '\0'; | |
str += cred.password; | |
return str; | |
}; | |
/** | |
* Decode a challenge issued by the server. | |
* | |
* @param {String} chal | |
* @return {Mechanism} for chaining | |
* @api public | |
*/ | |
Mechanism.prototype.challenge = function(chal) { | |
return this; | |
}; | |
exports = module.exports = Mechanism; | |
})); | |
},{}],177:[function(_dereq_,module,exports){ | |
arguments[4][171][0].apply(exports,arguments) | |
},{"./lib/mechanism":176}],178:[function(_dereq_,module,exports){ | |
(function(root, factory) { | |
if (typeof exports === 'object') { | |
// CommonJS | |
factory(exports, module, _dereq_('crypto'), _dereq_('buffer')); | |
} else if (typeof define === 'function' && define.amd) { | |
// AMD | |
define(['exports', 'module', 'crypto', 'buffer'], factory); | |
} | |
}(this, function(exports, module, crypto, buffer) { | |
var Buffer = buffer.Buffer; | |
/** | |
* SCRAM-SHA-1 `Mechanism` constructor. | |
* | |
* This class implements the SCRAM-SHA-1 SASL mechanism. | |
* | |
* References: | |
* - [RFC 5802](http://tools.ietf.org/html/rfc5802) | |
* | |
* @api public | |
*/ | |
function Mechanism(options) { | |
options = options || {}; | |
this._genNonce = options.genNonce || genNonce(32); | |
this._stage = 0; | |
} | |
Mechanism.prototype.name = 'SCRAM-SHA-1'; | |
Mechanism.prototype.clientFirst = true; | |
/** | |
* Encode a response using given credentials. | |
* | |
* Options: | |
* - `username` | |
* - `password` | |
* - `authzid` | |
* | |
* @param {object} cred | |
* @api public | |
*/ | |
Mechanism.prototype.response = function (cred) { | |
return responses[this._stage](this, cred); | |
}; | |
/** | |
* Decode a challenge issued by the server. | |
* | |
* @param {String} chal | |
* @return {Mechanism} for chaining | |
* @api public | |
*/ | |
Mechanism.prototype.challenge = function (chal) { | |
var values = parse(chal); | |
this._salt = new Buffer(values.s || '', 'base64').toString('binary'); | |
this._iterationCount = parseInt(values.i, 10); | |
this._nonce = values.r; | |
this._verifier = values.v; | |
this._error = values.e; | |
this._challenge = chal; | |
return this; | |
}; | |
var responses = {}; | |
responses[0] = function (mech, cred) { | |
mech._cnonce = mech._genNonce(); | |
var authzid = ''; | |
if (cred.authzid) { | |
authzid = 'a=' + saslname(cred.authzid); | |
} | |
mech._gs2Header = 'n,' + authzid + ','; | |
var nonce = 'r=' + mech._cnonce; | |
var username = 'n=' + saslname(cred.username); | |
mech._clientFirstMessageBare = username + ',' + nonce; | |
var result = mech._gs2Header + mech._clientFirstMessageBare | |
mech._stage = 1; | |
return result; | |
}; | |
responses[1] = function (mech, cred) { | |
var gs2Header = new Buffer(mech._gs2Header).toString('base64'); | |
mech._clientFinalMessageWithoutProof = 'c=' + gs2Header + ',r=' + mech._nonce; | |
var saltedPassword, clientKey, serverKey; | |
if (cred.clientKey && cred.serverKey) { | |
clientKey = cred.clientKey; | |
serverKey = cred.serverKey; | |
} else { | |
saltedPassword = cred.saltedPassword || Hi(cred.password, mech._salt, mech._iterationCount); | |
clientKey = HMAC(saltedPassword, 'Client Key'); | |
serverKey = HMAC(saltedPassword, 'Server Key'); | |
} | |
var storedKey = H(clientKey); | |
var authMessage = mech._clientFirstMessageBare + ',' + | |
mech._challenge + ',' + | |
mech._clientFinalMessageWithoutProof; | |
var clientSignature = HMAC(storedKey, authMessage); | |
var xorstuff = XOR(clientKey, clientSignature); | |
var clientProof = new Buffer(xorstuff, 'binary').toString('base64'); | |
mech._serverSignature = HMAC(serverKey, authMessage); | |
var result = mech._clientFinalMessageWithoutProof + ',p=' + clientProof; | |
mech._stage = 2; | |
mech.cache = { | |
saltedPassword: saltedPassword, | |
clientKey: clientKey, | |
serverKey: serverKey | |
}; | |
return result; | |
}; | |
responses[2] = function (mech, cred) { | |
// TODO: Signal errors | |
return ''; | |
}; | |
/** | |
* Create a SHA-1 HMAC. | |
* | |
* @param {String} key | |
* @param {String} msg | |
* @api private | |
*/ | |
function HMAC(key, msg) { | |
return crypto.createHmac('sha1', key).update(msg).digest('binary'); | |
} | |
/** | |
* Iteratively create an HMAC, with a salt. | |
* | |
* @param {String} text | |
* @param {String} salt | |
* @param {Number} iterations | |
* @api private | |
*/ | |
function Hi(text, salt, iterations) { | |
var ui1 = HMAC(text, salt + '\0\0\0\1'); | |
var ui = ui1; | |
for (var i = 0; i < iterations - 1; i++) { | |
ui1 = HMAC(text, ui1); | |
ui = XOR(ui, ui1); | |
} | |
return ui; | |
} | |
/** | |
* Create a SHA-1 hash. | |
* | |
* @param {String} text | |
* @api private | |
*/ | |
function H(text) { | |
return crypto.createHash('sha1').update(text).digest('binary'); | |
} | |
/** | |
* String XOR | |
* | |
* @param {String} a | |
* @param {String} b | |
* @api private | |
*/ | |
function XOR(a, b) { | |
a = new Buffer(a, 'binary'); | |
b = new Buffer(b, 'binary'); | |
var len = Math.min(a.length, b.length); | |
result = []; | |
for (var i = 0; i < len; i++) { | |
result.push(a[i] ^ b[i]); | |
} | |
result = new Buffer(result, 'binary'); | |
return result.toString('binary'); | |
} | |
/** | |
* Escape special characters in username values. | |
* | |
* @param {String} name | |
* @api private | |
*/ | |
function saslname(name) { | |
var escaped = []; | |
var curr = ''; | |
for (var i = 0; i < name.length; i++) { | |
curr = name[i]; | |
if (curr === ',') { | |
escaped.push('=2C'); | |
} else if (curr === '=') { | |
escaped.push('=3D'); | |
} else { | |
escaped.push(curr); | |
} | |
} | |
return escaped.join(''); | |
} | |
/** | |
* Parse challenge. | |
* | |
* @api private | |
*/ | |
function parse(chal) { | |
var dtives = {}; | |
var tokens = chal.split(/,(?=(?:[^"]|"[^"]*")*$)/); | |
for (var i = 0, len = tokens.length; i < len; i++) { | |
var dtiv = /(\w+)=["]?([^"]+)["]?$/.exec(tokens[i]); | |
if (dtiv) { | |
dtives[dtiv[1]] = dtiv[2]; | |
} | |
} | |
return dtives; | |
} | |
/** | |
* Return a unique nonce with the given `len`. | |
* | |
* genNonce(10)(); | |
* // => "FDaS435D2z" | |
* | |
* @param {Number} len | |
* @return {Function} | |
* @api private | |
*/ | |
function genNonce(len) { | |
var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; | |
var charlen = chars.length; | |
return function() { | |
var buf = []; | |
for (var i = 0; i < len; ++i) { | |
buf.push(chars[Math.random() * charlen | 0]); | |
} | |
return buf.join(''); | |
} | |
} | |
exports = module.exports = Mechanism; | |
})); | |
},{"buffer":130,"crypto":180}],179:[function(_dereq_,module,exports){ | |
arguments[4][171][0].apply(exports,arguments) | |
},{"./lib/mechanism":178}],180:[function(_dereq_,module,exports){ | |
var Buffer = _dereq_('buffer').Buffer | |
var sha = _dereq_('./sha') | |
var sha256 = _dereq_('./sha256') | |
var rng = _dereq_('./rng') | |
var md5 = _dereq_('./md5') | |
var algorithms = { | |
sha1: { | |
hex: sha.hex_sha1, | |
base64: sha.b64_sha1, | |
binary: sha.str_sha1 | |
}, | |
sha256: { | |
hex: sha256.hex_sha256, | |
base64: sha256.b64_sha256, | |
binary: sha256.str_sha256 | |
}, | |
md5: { | |
hex: md5.hex_md5, | |
base64: md5.b64_md5, | |
binary: md5.bin_md5 | |
} | |
} | |
var algorithmsHmac = { | |
sha1: { | |
hex: sha.hex_hmac_sha1, | |
base64: sha.b64_hmac_sha1, | |
binary: sha.str_hmac_sha1 | |
}, | |
sha256: { | |
hex: sha256.hex_hmac_sha256, | |
base64: sha256.b64_hmac_sha256, | |
binary: sha256.str_hmac_sha256 | |
}, | |
md5: { | |
hex: md5.hex_hmac_md5, | |
base64: md5.b64_hmac_md5, | |
binary: md5.bin_hmac_md5 | |
} | |
} | |
function error () { | |
var m = [].slice.call(arguments).join(' ') | |
throw new Error([ | |
m, | |
'we accept pull requests', | |
'http://github.com/dominictarr/crypto-browserify' | |
].join('\n')) | |
} | |
exports.createHash = function (alg) { | |
alg = alg || 'sha1' | |
if(!algorithms[alg]) | |
error('algorithm:', alg, 'is not yet supported') | |
var s = '' | |
var _alg = algorithms[alg] | |
return { | |
update: function (data) { | |
s += data | |
return this | |
}, | |
digest: function (enc) { | |
enc = enc || 'binary' | |
var fn | |
if(!(fn = _alg[enc])) | |
error('encoding:', enc , 'is not yet supported for algorithm', alg) | |
var r = fn(s) | |
s = null //not meant to use the hash after you've called digest. | |
return r | |
} | |
} | |
} | |
exports.createHmac = function (alg, key) { | |
if (!algorithmsHmac[alg]) | |
error('algorithm:', alg, 'is not yet supported') | |
if (typeof key != 'string') | |
key = key.toString('binary') | |
var s = '' | |
var _alg = algorithmsHmac[alg] | |
return { | |
update: function (data) { | |
s += data | |
return this | |
}, | |
digest: function (enc) { | |
enc = enc || 'binary' | |
var fn | |
if (!(fn = _alg[enc])) | |
error('encoding:', enc, 'is not yet support for algorithm', alg) | |
var r = fn(key, s) | |
s = null | |
return r | |
} | |
} | |
} | |
exports.randomBytes = function(size, callback) { | |
if (callback && callback.call) { | |
try { | |
callback.call(this, undefined, new Buffer(rng(size))); | |
} catch (err) { callback(err); } | |
} else { | |
return new Buffer(rng(size)); | |
} | |
} | |
function each(a, f) { | |
for(var i in a) | |
f(a[i], i) | |
} | |
// the least I can do is make error messages for the rest of the node.js/crypto api. | |
each(['createCredentials' | |
, 'createCipher' | |
, 'createCipheriv' | |
, 'createDecipher' | |
, 'createDecipheriv' | |
, 'createSign' | |
, 'createVerify' | |
, 'createDiffieHellman' | |
, 'pbkdf2'], function (name) { | |
exports[name] = function () { | |
error('sorry,', name, 'is not implemented yet') | |
} | |
}) | |
},{"./md5":181,"./rng":182,"./sha":183,"./sha256":184,"buffer":130}],181:[function(_dereq_,module,exports){ | |
/* | |
* A JavaScript implementation of the RSA Data Security, Inc. MD5 Message | |
* Digest Algorithm, as defined in RFC 1321. | |
* Version 2.1 Copyright (C) Paul Johnston 1999 - 2002. | |
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet | |
* Distributed under the BSD License | |
* See http://pajhome.org.uk/crypt/md5 for more info. | |
*/ | |
/* | |
* Configurable variables. You may need to tweak these to be compatible with | |
* the server-side, but the defaults work in most cases. | |
*/ | |
var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */ | |
var b64pad = "="; /* base-64 pad character. "=" for strict RFC compliance */ | |
var chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode */ | |
/* | |
* These are the functions you'll usually want to call | |
* They take string arguments and return either hex or base-64 encoded strings | |
*/ | |
function hex_md5(s){ return binl2hex(core_md5(str2binl(s), s.length * chrsz));} | |
function b64_md5(s){ return binl2b64(core_md5(str2binl(s), s.length * chrsz));} | |
function str_md5(s){ return binl2str(core_md5(str2binl(s), s.length * chrsz));} | |
function hex_hmac_md5(key, data) { return binl2hex(core_hmac_md5(key, data)); } | |
function b64_hmac_md5(key, data) { return binl2b64(core_hmac_md5(key, data)); } | |
function str_hmac_md5(key, data) { return binl2str(core_hmac_md5(key, data)); } | |
/* | |
* Perform a simple self-test to see if the VM is working | |
*/ | |
function md5_vm_test() | |
{ | |
return hex_md5("abc") == "900150983cd24fb0d6963f7d28e17f72"; | |
} | |
/* | |
* Calculate the MD5 of an array of little-endian words, and a bit length | |
*/ | |
function core_md5(x, len) | |
{ | |
/* append padding */ | |
x[len >> 5] |= 0x80 << ((len) % 32); | |
x[(((len + 64) >>> 9) << 4) + 14] = len; | |
var a = 1732584193; | |
var b = -271733879; | |
var c = -1732584194; | |
var d = 271733878; | |
for(var i = 0; i < x.length; i += 16) | |
{ | |
var olda = a; | |
var oldb = b; | |
var oldc = c; | |
var oldd = d; | |
a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936); | |
d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586); | |
c = md5_ff(c, d, a, b, x[i+ 2], 17, 606105819); | |
b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330); | |
a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897); | |
d = md5_ff(d, a, b, c, x[i+ 5], 12, 1200080426); | |
c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341); | |
b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983); | |
a = md5_ff(a, b, c, d, x[i+ 8], 7 , 1770035416); | |
d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417); | |
c = md5_ff(c, d, a, b, x[i+10], 17, -42063); | |
b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162); | |
a = md5_ff(a, b, c, d, x[i+12], 7 , 1804603682); | |
d = md5_ff(d, a, b, c, x[i+13], 12, -40341101); | |
c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290); | |
b = md5_ff(b, c, d, a, x[i+15], 22, 1236535329); | |
a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510); | |
d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632); | |
c = md5_gg(c, d, a, b, x[i+11], 14, 643717713); | |
b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302); | |
a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691); | |
d = md5_gg(d, a, b, c, x[i+10], 9 , 38016083); | |
c = md5_gg(c, d, a, b, x[i+15], 14, -660478335); | |
b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848); | |
a = md5_gg(a, b, c, d, x[i+ 9], 5 , 568446438); | |
d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690); | |
c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961); | |
b = md5_gg(b, c, d, a, x[i+ 8], 20, 1163531501); | |
a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467); | |
d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784); | |
c = md5_gg(c, d, a, b, x[i+ 7], 14, 1735328473); | |
b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734); | |
a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558); | |
d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463); | |
c = md5_hh(c, d, a, b, x[i+11], 16, 1839030562); | |
b = md5_hh(b, c, d, a, x[i+14], 23, -35309556); | |
a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060); | |
d = md5_hh(d, a, b, c, x[i+ 4], 11, 1272893353); | |
c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632); | |
b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640); | |
a = md5_hh(a, b, c, d, x[i+13], 4 , 681279174); | |
d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222); | |
c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979); | |
b = md5_hh(b, c, d, a, x[i+ 6], 23, 76029189); | |
a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487); | |
d = md5_hh(d, a, b, c, x[i+12], 11, -421815835); | |
c = md5_hh(c, d, a, b, x[i+15], 16, 530742520); | |
b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651); | |
a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844); | |
d = md5_ii(d, a, b, c, x[i+ 7], 10, 1126891415); | |
c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905); | |
b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055); | |
a = md5_ii(a, b, c, d, x[i+12], 6 , 1700485571); | |
d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606); | |
c = md5_ii(c, d, a, b, x[i+10], 15, -1051523); | |
b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799); | |
a = md5_ii(a, b, c, d, x[i+ 8], 6 , 1873313359); | |
d = md5_ii(d, a, b, c, x[i+15], 10, -30611744); | |
c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380); | |
b = md5_ii(b, c, d, a, x[i+13], 21, 1309151649); | |
a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070); | |
d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379); | |
c = md5_ii(c, d, a, b, x[i+ 2], 15, 718787259); | |
b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551); | |
a = safe_add(a, olda); | |
b = safe_add(b, oldb); | |
c = safe_add(c, oldc); | |
d = safe_add(d, oldd); | |
} | |
return Array(a, b, c, d); | |
} | |
/* | |
* These functions implement the four basic operations the algorithm uses. | |
*/ | |
function md5_cmn(q, a, b, x, s, t) | |
{ | |
return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b); | |
} | |
function md5_ff(a, b, c, d, x, s, t) | |
{ | |
return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t); | |
} | |
function md5_gg(a, b, c, d, x, s, t) | |
{ | |
return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t); | |
} | |
function md5_hh(a, b, c, d, x, s, t) | |
{ | |
return md5_cmn(b ^ c ^ d, a, b, x, s, t); | |
} | |
function md5_ii(a, b, c, d, x, s, t) | |
{ | |
return md5_cmn(c ^ (b | (~d)), a, b, x, s, t); | |
} | |
/* | |
* Calculate the HMAC-MD5, of a key and some data | |
*/ | |
function core_hmac_md5(key, data) | |
{ | |
var bkey = str2binl(key); | |
if(bkey.length > 16) bkey = core_md5(bkey, key.length * chrsz); | |
var ipad = Array(16), opad = Array(16); | |
for(var i = 0; i < 16; i++) | |
{ | |
ipad[i] = bkey[i] ^ 0x36363636; | |
opad[i] = bkey[i] ^ 0x5C5C5C5C; | |
} | |
var hash = core_md5(ipad.concat(str2binl(data)), 512 + data.length * chrsz); | |
return core_md5(opad.concat(hash), 512 + 128); | |
} | |
/* | |
* Add integers, wrapping at 2^32. This uses 16-bit operations internally | |
* to work around bugs in some JS interpreters. | |
*/ | |
function safe_add(x, y) | |
{ | |
var lsw = (x & 0xFFFF) + (y & 0xFFFF); | |
var msw = (x >> 16) + (y >> 16) + (lsw >> 16); | |
return (msw << 16) | (lsw & 0xFFFF); | |
} | |
/* | |
* Bitwise rotate a 32-bit number to the left. | |
*/ | |
function bit_rol(num, cnt) | |
{ | |
return (num << cnt) | (num >>> (32 - cnt)); | |
} | |
/* | |
* Convert a string to an array of little-endian words | |
* If chrsz is ASCII, characters >255 have their hi-byte silently ignored. | |
*/ | |
function str2binl(str) | |
{ | |
var bin = Array(); | |
var mask = (1 << chrsz) - 1; | |
for(var i = 0; i < str.length * chrsz; i += chrsz) | |
bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (i%32); | |
return bin; | |
} | |
/* | |
* Convert an array of little-endian words to a string | |
*/ | |
function binl2str(bin) | |
{ | |
var str = ""; | |
var mask = (1 << chrsz) - 1; | |
for(var i = 0; i < bin.length * 32; i += chrsz) | |
str += String.fromCharCode((bin[i>>5] >>> (i % 32)) & mask); | |
return str; | |
} | |
/* | |
* Convert an array of little-endian words to a hex string. | |
*/ | |
function binl2hex(binarray) | |
{ | |
var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef"; | |
var str = ""; | |
for(var i = 0; i < binarray.length * 4; i++) | |
{ | |
str += hex_tab.charAt((binarray[i>>2] >> ((i%4)*8+4)) & 0xF) + | |
hex_tab.charAt((binarray[i>>2] >> ((i%4)*8 )) & 0xF); | |
} | |
return str; | |
} | |
/* | |
* Convert an array of little-endian words to a base-64 string | |
*/ | |
function binl2b64(binarray) | |
{ | |
var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; | |
var str = ""; | |
for(var i = 0; i < binarray.length * 4; i += 3) | |
{ | |
var triplet = (((binarray[i >> 2] >> 8 * ( i %4)) & 0xFF) << 16) | |
| (((binarray[i+1 >> 2] >> 8 * ((i+1)%4)) & 0xFF) << 8 ) | |
| ((binarray[i+2 >> 2] >> 8 * ((i+2)%4)) & 0xFF); | |
for(var j = 0; j < 4; j++) | |
{ | |
if(i * 8 + j * 6 > binarray.length * 32) str += b64pad; | |
else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F); | |
} | |
} | |
return str; | |
} | |
exports.hex_md5 = hex_md5; | |
exports.b64_md5 = b64_md5; | |
exports.bin_md5 = str_md5; | |
exports.hex_hmac_md5 = hex_hmac_md5; | |
exports.b64_hmac_md5 = b64_hmac_md5; | |
exports.bin_hmac_md5 = str_hmac_md5; | |
},{}],182:[function(_dereq_,module,exports){ | |
// Original code adapted from Robert Kieffer. | |
// details at https://github.com/broofa/node-uuid | |
(function() { | |
var _global = this; | |
var mathRNG, whatwgRNG; | |
// NOTE: Math.random() does not guarantee "cryptographic quality" | |
mathRNG = function(size) { | |
var bytes = new Array(size); | |
var r; | |
for (var i = 0, r; i < size; i++) { | |
if ((i & 0x03) == 0) r = Math.random() * 0x100000000; | |
bytes[i] = r >>> ((i & 0x03) << 3) & 0xff; | |
} | |
return bytes; | |
} | |
if (_global.crypto && crypto.getRandomValues) { | |
var _rnds = new Uint32Array(4); | |
whatwgRNG = function(size) { | |
var bytes = new Array(size); | |
crypto.getRandomValues(_rnds); | |
for (var c = 0 ; c < size; c++) { | |
bytes[c] = _rnds[c >> 2] >>> ((c & 0x03) * 8) & 0xff; | |
} | |
return bytes; | |
} | |
} | |
module.exports = whatwgRNG || mathRNG; | |
}()) | |
},{}],183:[function(_dereq_,module,exports){ | |
/* | |
* A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined | |
* in FIPS PUB 180-1 | |
* Version 2.1a Copyright Paul Johnston 2000 - 2002. | |
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet | |
* Distributed under the BSD License | |
* See http://pajhome.org.uk/crypt/md5 for details. | |
*/ | |
exports.hex_sha1 = hex_sha1; | |
exports.b64_sha1 = b64_sha1; | |
exports.str_sha1 = str_sha1; | |
exports.hex_hmac_sha1 = hex_hmac_sha1; | |
exports.b64_hmac_sha1 = b64_hmac_sha1; | |
exports.str_hmac_sha1 = str_hmac_sha1; | |
/* | |
* Configurable variables. You may need to tweak these to be compatible with | |
* the server-side, but the defaults work in most cases. | |
*/ | |
var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */ | |
var b64pad = "="; /* base-64 pad character. "=" for strict RFC compliance */ | |
var chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode */ | |
/* | |
* These are the functions you'll usually want to call | |
* They take string arguments and return either hex or base-64 encoded strings | |
*/ | |
function hex_sha1(s){return binb2hex(core_sha1(str2binb(s),s.length * chrsz));} | |
function b64_sha1(s){return binb2b64(core_sha1(str2binb(s),s.length * chrsz));} | |
function str_sha1(s){return binb2str(core_sha1(str2binb(s),s.length * chrsz));} | |
function hex_hmac_sha1(key, data){ return binb2hex(core_hmac_sha1(key, data));} | |
function b64_hmac_sha1(key, data){ return binb2b64(core_hmac_sha1(key, data));} | |
function str_hmac_sha1(key, data){ return binb2str(core_hmac_sha1(key, data));} | |
/* | |
* Perform a simple self-test to see if the VM is working | |
*/ | |
function sha1_vm_test() | |
{ | |
return hex_sha1("abc") == "a9993e364706816aba3e25717850c26c9cd0d89d"; | |
} | |
/* | |
* Calculate the SHA-1 of an array of big-endian words, and a bit length | |
*/ | |
function core_sha1(x, len) | |
{ | |
/* append padding */ | |
x[len >> 5] |= 0x80 << (24 - len % 32); | |
x[((len + 64 >> 9) << 4) + 15] = len; | |
var w = Array(80); | |
var a = 1732584193; | |
var b = -271733879; | |
var c = -1732584194; | |
var d = 271733878; | |
var e = -1009589776; | |
for(var i = 0; i < x.length; i += 16) | |
{ | |
var olda = a; | |
var oldb = b; | |
var oldc = c; | |
var oldd = d; | |
var olde = e; | |
for(var j = 0; j < 80; j++) | |
{ | |
if(j < 16) w[j] = x[i + j]; | |
else w[j] = rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1); | |
var t = safe_add(safe_add(rol(a, 5), sha1_ft(j, b, c, d)), | |
safe_add(safe_add(e, w[j]), sha1_kt(j))); | |
e = d; | |
d = c; | |
c = rol(b, 30); | |
b = a; | |
a = t; | |
} | |
a = safe_add(a, olda); | |
b = safe_add(b, oldb); | |
c = safe_add(c, oldc); | |
d = safe_add(d, oldd); | |
e = safe_add(e, olde); | |
} | |
return Array(a, b, c, d, e); | |
} | |
/* | |
* Perform the appropriate triplet combination function for the current | |
* iteration | |
*/ | |
function sha1_ft(t, b, c, d) | |
{ | |
if(t < 20) return (b & c) | ((~b) & d); | |
if(t < 40) return b ^ c ^ d; | |
if(t < 60) return (b & c) | (b & d) | (c & d); | |
return b ^ c ^ d; | |
} | |
/* | |
* Determine the appropriate additive constant for the current iteration | |
*/ | |
function sha1_kt(t) | |
{ | |
return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 : | |
(t < 60) ? -1894007588 : -899497514; | |
} | |
/* | |
* Calculate the HMAC-SHA1 of a key and some data | |
*/ | |
function core_hmac_sha1(key, data) | |
{ | |
var bkey = str2binb(key); | |
if(bkey.length > 16) bkey = core_sha1(bkey, key.length * chrsz); | |
var ipad = Array(16), opad = Array(16); | |
for(var i = 0; i < 16; i++) | |
{ | |
ipad[i] = bkey[i] ^ 0x36363636; | |
opad[i] = bkey[i] ^ 0x5C5C5C5C; | |
} | |
var hash = core_sha1(ipad.concat(str2binb(data)), 512 + data.length * chrsz); | |
return core_sha1(opad.concat(hash), 512 + 160); | |
} | |
/* | |
* Add integers, wrapping at 2^32. This uses 16-bit operations internally | |
* to work around bugs in some JS interpreters. | |
*/ | |
function safe_add(x, y) | |
{ | |
var lsw = (x & 0xFFFF) + (y & 0xFFFF); | |
var msw = (x >> 16) + (y >> 16) + (lsw >> 16); | |
return (msw << 16) | (lsw & 0xFFFF); | |
} | |
/* | |
* Bitwise rotate a 32-bit number to the left. | |
*/ | |
function rol(num, cnt) | |
{ | |
return (num << cnt) | (num >>> (32 - cnt)); | |
} | |
/* | |
* Convert an 8-bit or 16-bit string to an array of big-endian words | |
* In 8-bit function, characters >255 have their hi-byte silently ignored. | |
*/ | |
function str2binb(str) | |
{ | |
var bin = Array(); | |
var mask = (1 << chrsz) - 1; | |
for(var i = 0; i < str.length * chrsz; i += chrsz) | |
bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (32 - chrsz - i%32); | |
return bin; | |
} | |
/* | |
* Convert an array of big-endian words to a string | |
*/ | |
function binb2str(bin) | |
{ | |
var str = ""; | |
var mask = (1 << chrsz) - 1; | |
for(var i = 0; i < bin.length * 32; i += chrsz) | |
str += String.fromCharCode((bin[i>>5] >>> (32 - chrsz - i%32)) & mask); | |
return str; | |
} | |
/* | |
* Convert an array of big-endian words to a hex string. | |
*/ | |
function binb2hex(binarray) | |
{ | |
var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef"; | |
var str = ""; | |
for(var i = 0; i < binarray.length * 4; i++) | |
{ | |
str += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) + | |
hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8 )) & 0xF); | |
} | |
return str; | |
} | |
/* | |
* Convert an array of big-endian words to a base-64 string | |
*/ | |
function binb2b64(binarray) | |
{ | |
var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; | |
var str = ""; | |
for(var i = 0; i < binarray.length * 4; i += 3) | |
{ | |
var triplet = (((binarray[i >> 2] >> 8 * (3 - i %4)) & 0xFF) << 16) | |
| (((binarray[i+1 >> 2] >> 8 * (3 - (i+1)%4)) & 0xFF) << 8 ) | |
| ((binarray[i+2 >> 2] >> 8 * (3 - (i+2)%4)) & 0xFF); | |
for(var j = 0; j < 4; j++) | |
{ | |
if(i * 8 + j * 6 > binarray.length * 32) str += b64pad; | |
else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F); | |
} | |
} | |
return str; | |
} | |
},{}],184:[function(_dereq_,module,exports){ | |
/** | |
* A JavaScript implementation of the Secure Hash Algorithm, SHA-256, as defined | |
* in FIPS 180-2 | |
* Version 2.2-beta Copyright Angel Marin, Paul Johnston 2000 - 2009. | |
* Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet | |
* | |
*/ | |
exports.hex_sha256 = hex_sha256; | |
exports.b64_sha256 = b64_sha256; | |
exports.str_sha256 = str_sha256; | |
exports.hex_hmac_sha256 = hex_hmac_sha256; | |
exports.b64_hmac_sha256 = b64_hmac_sha256; | |
exports.str_hmac_sha256 = str_hmac_sha256; | |
/* | |
* Configurable variables. You may need to tweak these to be compatible with | |
* the server-side, but the defaults work in most cases. | |
*/ | |
var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */ | |
var b64pad = "="; /* base-64 pad character. "=" for strict RFC compliance */ | |
var chrsz = 8; /* bits per input character. 8 - ASCII; 16 - Unicode */ | |
/* | |
* These are the functions you'll usually want to call | |
* They take string arguments and return either hex or base-64 encoded strings | |
*/ | |
function hex_sha256(s){return binb2hex(core_sha256(str2binb(s),s.length * chrsz));} | |
function b64_sha256(s){return binb2b64(core_sha256(str2binb(s),s.length * chrsz));} | |
function str_sha256(s){return binb2str(core_sha256(str2binb(s),s.length * chrsz));} | |
function hex_hmac_sha256(key, data){ return binb2hex(core_hmac_sha256(key, data));} | |
function b64_hmac_sha256(key, data){ return binb2b64(core_hmac_sha256(key, data));} | |
function str_hmac_sha256(key, data){ return binb2str(core_hmac_sha256(key, data));} | |
var safe_add = function(x, y) { | |
var lsw = (x & 0xFFFF) + (y & 0xFFFF); | |
var msw = (x >> 16) + (y >> 16) + (lsw >> 16); | |
return (msw << 16) | (lsw & 0xFFFF); | |
}; | |
var S = function(X, n) { | |
return (X >>> n) | (X << (32 - n)); | |
}; | |
var R = function(X, n) { | |
return (X >>> n); | |
}; | |
var Ch = function(x, y, z) { | |
return ((x & y) ^ ((~x) & z)); | |
}; | |
var Maj = function(x, y, z) { | |
return ((x & y) ^ (x & z) ^ (y & z)); | |
}; | |
var Sigma0256 = function(x) { | |
return (S(x, 2) ^ S(x, 13) ^ S(x, 22)); | |
}; | |
var Sigma1256 = function(x) { | |
return (S(x, 6) ^ S(x, 11) ^ S(x, 25)); | |
}; | |
var Gamma0256 = function(x) { | |
return (S(x, 7) ^ S(x, 18) ^ R(x, 3)); | |
}; | |
var Gamma1256 = function(x) { | |
return (S(x, 17) ^ S(x, 19) ^ R(x, 10)); | |
}; | |
var core_sha256 = function(m, l) { | |
var K = new Array(0x428A2F98,0x71374491,0xB5C0FBCF,0xE9B5DBA5,0x3956C25B,0x59F111F1,0x923F82A4,0xAB1C5ED5,0xD807AA98,0x12835B01,0x243185BE,0x550C7DC3,0x72BE5D74,0x80DEB1FE,0x9BDC06A7,0xC19BF174,0xE49B69C1,0xEFBE4786,0xFC19DC6,0x240CA1CC,0x2DE92C6F,0x4A7484AA,0x5CB0A9DC,0x76F988DA,0x983E5152,0xA831C66D,0xB00327C8,0xBF597FC7,0xC6E00BF3,0xD5A79147,0x6CA6351,0x14292967,0x27B70A85,0x2E1B2138,0x4D2C6DFC,0x53380D13,0x650A7354,0x766A0ABB,0x81C2C92E,0x92722C85,0xA2BFE8A1,0xA81A664B,0xC24B8B70,0xC76C51A3,0xD192E819,0xD6990624,0xF40E3585,0x106AA070,0x19A4C116,0x1E376C08,0x2748774C,0x34B0BCB5,0x391C0CB3,0x4ED8AA4A,0x5B9CCA4F,0x682E6FF3,0x748F82EE,0x78A5636F,0x84C87814,0x8CC70208,0x90BEFFFA,0xA4506CEB,0xBEF9A3F7,0xC67178F2); | |
var HASH = new Array(0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19); | |
var W = new Array(64); | |
var a, b, c, d, e, f, g, h, i, j; | |
var T1, T2; | |
/* append padding */ | |
m[l >> 5] |= 0x80 << (24 - l % 32); | |
m[((l + 64 >> 9) << 4) + 15] = l; | |
for (var i = 0; i < m.length; i += 16) { | |
a = HASH[0]; b = HASH[1]; c = HASH[2]; d = HASH[3]; e = HASH[4]; f = HASH[5]; g = HASH[6]; h = HASH[7]; | |
for (var j = 0; j < 64; j++) { | |
if (j < 16) { | |
W[j] = m[j + i]; | |
} else { | |
W[j] = safe_add(safe_add(safe_add(Gamma1256(W[j - 2]), W[j - 7]), Gamma0256(W[j - 15])), W[j - 16]); | |
} | |
T1 = safe_add(safe_add(safe_add(safe_add(h, Sigma1256(e)), Ch(e, f, g)), K[j]), W[j]); | |
T2 = safe_add(Sigma0256(a), Maj(a, b, c)); | |
h = g; g = f; f = e; e = safe_add(d, T1); d = c; c = b; b = a; a = safe_add(T1, T2); | |
} | |
HASH[0] = safe_add(a, HASH[0]); HASH[1] = safe_add(b, HASH[1]); HASH[2] = safe_add(c, HASH[2]); HASH[3] = safe_add(d, HASH[3]); | |
HASH[4] = safe_add(e, HASH[4]); HASH[5] = safe_add(f, HASH[5]); HASH[6] = safe_add(g, HASH[6]); HASH[7] = safe_add(h, HASH[7]); | |
} | |
return HASH; | |
}; | |
var str2binb = function(str) { | |
var bin = Array(); | |
var mask = (1 << chrsz) - 1; | |
for (var i = 0; i < str.length * chrsz; i += chrsz) { | |
bin[i >> 5] |= (str.charCodeAt(i / chrsz) & mask) << (24 - i % 32); | |
} | |
return bin; | |
}; | |
/* | |
* Convert an array of big-endian words to a string | |
*/ | |
function binb2str(bin) | |
{ | |
var str = ""; | |
var mask = (1 << chrsz) - 1; | |
for (var i = 0; i < bin.length * 32; i += chrsz) | |
str += String.fromCharCode((bin[i >> 5] >>> (32 - chrsz - i % 32)) & mask); | |
return str; | |
} | |
var hex2binb = function(a) { | |
var b = [], length = a.length, i, num; | |
for (i = 0; i < length; i += 2) { | |
num = parseInt(a.substr(i, 2), 16); | |
if (!isNaN(num)) { | |
b[i >> 3] |= num << (24 - (4 * (i % 8))); | |
} else { | |
return "INVALID HEX STRING"; | |
} | |
} | |
return b; | |
}; | |
var binb2hex = function(binarray) { | |
//var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */ | |
var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef"; | |
var str = ""; | |
for (var i = 0; i < binarray.length * 4; i++) { | |
str += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) + hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8 )) & 0xF); | |
} | |
return str; | |
}; | |
var binb2b64 = function(a) { | |
var b = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" + "0123456789+/", str = "", length = a.length * 4, i, j, triplet; | |
var b64pad = "="; | |
for (i = 0; i < length; i += 3) { | |
triplet = (((a[i >> 2] >> 8 * (3 - i % 4)) & 0xFF) << 16) | (((a[i + 1 >> 2] >> 8 * (3 - (i + 1) % 4)) & 0xFF) << 8) | ((a[i + 2 >> 2] >> 8 * (3 - (i + 2) % 4)) & 0xFF); | |
for (j = 0; j < 4; j += 1) { | |
if (i * 8 + j * 6 <= a.length * 32) { | |
str += b.charAt((triplet >> 6 * (3 - j)) & 0x3F); | |
} else { | |
str += b64pad; | |
} | |
} | |
} | |
return str; | |
}; | |
var core_hmac_sha256 = function(key, data) { | |
var bkey = str2binb(key); | |
if (bkey.length > 16) { | |
bkey = core_sha256(bkey, key.length * chrsz); | |
} | |
var ipad = Array(16), opad = Array(16); | |
for (var i = 0; i < 16; i++) { | |
ipad[i] = bkey[i] ^ 0x36363636; | |
opad[i] = bkey[i] ^ 0x5C5C5C5C; | |
} | |
var hash = core_sha256(ipad.concat(str2binb(data)), 512 + data.length * chrsz); | |
return core_sha256(opad.concat(hash), 512 + 256); | |
}; | |
},{}],185:[function(_dereq_,module,exports){ | |
(function(root, factory) { | |
if (typeof exports === 'object') { | |
// CommonJS | |
factory(exports, module); | |
} else if (typeof define === 'function' && define.amd) { | |
// AMD | |
define(['exports', 'module'], factory); | |
} | |
}(this, function(exports, module) { | |
/** | |
* `Factory` constructor. | |
* | |
* @api public | |
*/ | |
function Factory() { | |
this._mechs = []; | |
} | |
/** | |
* Utilize the given `mech` with optional `name`, overridding the mechanism's | |
* default name. | |
* | |
* Examples: | |
* | |
* factory.use(FooMechanism); | |
* | |
* factory.use('XFOO', FooMechanism); | |
* | |
* @param {String|Mechanism} name | |
* @param {Mechanism} mech | |
* @return {Factory} for chaining | |
* @api public | |
*/ | |
Factory.prototype.use = function(name, mech) { | |
if (!mech) { | |
mech = name; | |
name = mech.prototype.name; | |
} | |
this._mechs.push({ name: name, mech: mech }); | |
return this; | |
}; | |
/** | |
* Create a new mechanism from supported list of `mechs`. | |
* | |
* If no mechanisms are supported, returns `null`. | |
* | |
* Examples: | |
* | |
* var mech = factory.create(['FOO', 'BAR']); | |
* | |
* @param {Array} mechs | |
* @return {Mechanism} | |
* @api public | |
*/ | |
Factory.prototype.create = function(mechs) { | |
for (var i = 0, len = this._mechs.length; i < len; i++) { | |
for (var j = 0, jlen = mechs.length; j < jlen; j++) { | |
var entry = this._mechs[i]; | |
if (entry.name == mechs[j]) { | |
return new entry.mech(); | |
} | |
} | |
} | |
return null; | |
}; | |
exports = module.exports = Factory; | |
})); | |
},{}],186:[function(_dereq_,module,exports){ | |
(function(root, factory) { | |
if (typeof exports === 'object') { | |
// CommonJS | |
factory(exports, | |
module, | |
_dereq_('./lib/factory')); | |
} else if (typeof define === 'function' && define.amd) { | |
// AMD | |
define(['exports', | |
'module', | |
'./lib/factory'], factory); | |
} | |
}(this, function(exports, module, Factory) { | |
exports = module.exports = Factory; | |
exports.Factory = Factory; | |
})); | |
},{"./lib/factory":185}],187:[function(_dereq_,module,exports){ | |
// Underscore.js 1.6.0 | |
// http://underscorejs.org | |
// (c) 2009-2014 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors | |
// Underscore may be freely distributed under the MIT license. | |
(function() { | |
// Baseline setup | |
// -------------- | |
// Establish the root object, `window` in the browser, or `exports` on the server. | |
var root = this; | |
// Save the previous value of the `_` variable. | |
var previousUnderscore = root._; | |
// Establish the object that gets returned to break out of a loop iteration. | |
var breaker = {}; | |
// Save bytes in the minified (but not gzipped) version: | |
var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype; | |
// Create quick reference variables for speed access to core prototypes. | |
var | |
push = ArrayProto.push, | |
slice = ArrayProto.slice, | |
concat = ArrayProto.concat, | |
toString = ObjProto.toString, | |
hasOwnProperty = ObjProto.hasOwnProperty; | |
// All **ECMAScript 5** native function implementations that we hope to use | |
// are declared here. | |
var | |
nativeForEach = ArrayProto.forEach, | |
nativeMap = ArrayProto.map, | |
nativeReduce = ArrayProto.reduce, | |
nativeReduceRight = ArrayProto.reduceRight, | |
nativeFilter = ArrayProto.filter, | |
nativeEvery = ArrayProto.every, | |
nativeSome = ArrayProto.some, | |
nativeIndexOf = ArrayProto.indexOf, | |
nativeLastIndexOf = ArrayProto.lastIndexOf, | |
nativeIsArray = Array.isArray, | |
nativeKeys = Object.keys, | |
nativeBind = FuncProto.bind; | |
// Create a safe reference to the Underscore object for use below. | |
var _ = function(obj) { | |
if (obj instanceof _) return obj; | |
if (!(this instanceof _)) return new _(obj); | |
this._wrapped = obj; | |
}; | |
// Export the Underscore object for **Node.js**, with | |
// backwards-compatibility for the old `require()` API. If we're in | |
// the browser, add `_` as a global object via a string identifier, | |
// for Closure Compiler "advanced" mode. | |
if (typeof exports !== 'undefined') { | |
if (typeof module !== 'undefined' && module.exports) { | |
exports = module.exports = _; | |
} | |
exports._ = _; | |
} else { | |
root._ = _; | |
} | |
// Current version. | |
_.VERSION = '1.6.0'; | |
// Collection Functions | |
// -------------------- | |
// The cornerstone, an `each` implementation, aka `forEach`. | |
// Handles objects with the built-in `forEach`, arrays, and raw objects. | |
// Delegates to **ECMAScript 5**'s native `forEach` if available. | |
var each = _.each = _.forEach = function(obj, iterator, context) { | |
if (obj == null) return obj; | |
if (nativeForEach && obj.forEach === nativeForEach) { | |
obj.forEach(iterator, context); | |
} else if (obj.length === +obj.length) { | |
for (var i = 0, length = obj.length; i < length; i++) { | |
if (iterator.call(context, obj[i], i, obj) === breaker) return; | |
} | |
} else { | |
var keys = _.keys(obj); | |
for (var i = 0, length = keys.length; i < length; i++) { | |
if (iterator.call(context, obj[keys[i]], keys[i], obj) === breaker) return; | |
} | |
} | |
return obj; | |
}; | |
// Return the results of applying the iterator to each element. | |
// Delegates to **ECMAScript 5**'s native `map` if available. | |
_.map = _.collect = function(obj, iterator, context) { | |
var results = []; | |
if (obj == null) return results; | |
if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context); | |
each(obj, function(value, index, list) { | |
results.push(iterator.call(context, value, index, list)); | |
}); | |
return results; | |
}; | |
var reduceError = 'Reduce of empty array with no initial value'; | |
// **Reduce** builds up a single result from a list of values, aka `inject`, | |
// or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available. | |
_.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) { | |
var initial = arguments.length > 2; | |
if (obj == null) obj = []; | |
if (nativeReduce && obj.reduce === nativeReduce) { | |
if (context) iterator = _.bind(iterator, context); | |
return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator); | |
} | |
each(obj, function(value, index, list) { | |
if (!initial) { | |
memo = value; | |
initial = true; | |
} else { | |
memo = iterator.call(context, memo, value, index, list); | |
} | |
}); | |
if (!initial) throw new TypeError(reduceError); | |
return memo; | |
}; | |
// The right-associative version of reduce, also known as `foldr`. | |
// Delegates to **ECMAScript 5**'s native `reduceRight` if available. | |
_.reduceRight = _.foldr = function(obj, iterator, memo, context) { | |
var initial = arguments.length > 2; | |
if (obj == null) obj = []; | |
if (nativeReduceRight && obj.reduceRight === nativeReduceRight) { | |
if (context) iterator = _.bind(iterator, context); | |
return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator); | |
} | |
var length = obj.length; | |
if (length !== +length) { | |
var keys = _.keys(obj); | |
length = keys.length; | |
} | |
each(obj, function(value, index, list) { | |
index = keys ? keys[--length] : --length; | |
if (!initial) { | |
memo = obj[index]; | |
initial = true; | |
} else { | |
memo = iterator.call(context, memo, obj[index], index, list); | |
} | |
}); | |
if (!initial) throw new TypeError(reduceError); | |
return memo; | |
}; | |
// Return the first value which passes a truth test. Aliased as `detect`. | |
_.find = _.detect = function(obj, predicate, context) { | |
var result; | |
any(obj, function(value, index, list) { | |
if (predicate.call(context, value, index, list)) { | |
result = value; | |
return true; | |
} | |
}); | |
return result; | |
}; | |
// Return all the elements that pass a truth test. | |
// Delegates to **ECMAScript 5**'s native `filter` if available. | |
// Aliased as `select`. | |
_.filter = _.select = function(obj, predicate, context) { | |
var results = []; | |
if (obj == null) return results; | |
if (nativeFilter && obj.filter === nativeFilter) return obj.filter(predicate, context); | |
each(obj, function(value, index, list) { | |
if (predicate.call(context, value, index, list)) results.push(value); | |
}); | |
return results; | |
}; | |
// Return all the elements for which a truth test fails. | |
_.reject = function(obj, predicate, context) { | |
return _.filter(obj, function(value, index, list) { | |
return !predicate.call(context, value, index, list); | |
}, context); | |
}; | |
// Determine whether all of the elements match a truth test. | |
// Delegates to **ECMAScript 5**'s native `every` if available. | |
// Aliased as `all`. | |
_.every = _.all = function(obj, predicate, context) { | |
predicate || (predicate = _.identity); | |
var result = true; | |
if (obj == null) return result; | |
if (nativeEvery && obj.every === nativeEvery) return obj.every(predicate, context); | |
each(obj, function(value, index, list) { | |
if (!(result = result && predicate.call(context, value, index, list))) return breaker; | |
}); | |
return !!result; | |
}; | |
// Determine if at least one element in the object matches a truth test. | |
// Delegates to **ECMAScript 5**'s native `some` if available. | |
// Aliased as `any`. | |
var any = _.some = _.any = function(obj, predicate, context) { | |
predicate || (predicate = _.identity); | |
var result = false; | |
if (obj == null) return result; | |
if (nativeSome && obj.some === nativeSome) return obj.some(predicate, context); | |
each(obj, function(value, index, list) { | |
if (result || (result = predicate.call(context, value, index, list))) return breaker; | |
}); | |
return !!result; | |
}; | |
// Determine if the array or object contains a given value (using `===`). | |
// Aliased as `include`. | |
_.contains = _.include = function(obj, target) { | |
if (obj == null) return false; | |
if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1; | |
return any(obj, function(value) { | |
return value === target; | |
}); | |
}; | |
// Invoke a method (with arguments) on every item in a collection. | |
_.invoke = function(obj, method) { | |
var args = slice.call(arguments, 2); | |
var isFunc = _.isFunction(method); | |
return _.map(obj, function(value) { | |
return (isFunc ? method : value[method]).apply(value, args); | |
}); | |
}; | |
// Convenience version of a common use case of `map`: fetching a property. | |
_.pluck = function(obj, key) { | |
return _.map(obj, _.property(key)); | |
}; | |
// Convenience version of a common use case of `filter`: selecting only objects | |
// containing specific `key:value` pairs. | |
_.where = function(obj, attrs) { | |
return _.filter(obj, _.matches(attrs)); | |
}; | |
// Convenience version of a common use case of `find`: getting the first object | |
// containing specific `key:value` pairs. | |
_.findWhere = function(obj, attrs) { | |
return _.find(obj, _.matches(attrs)); | |
}; | |
// Return the maximum element or (element-based computation). | |
// Can't optimize arrays of integers longer than 65,535 elements. | |
// See [WebKit Bug 80797](https://bugs.webkit.org/show_bug.cgi?id=80797) | |
_.max = function(obj, iterator, context) { | |
if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) { | |
return Math.max.apply(Math, obj); | |
} | |
var result = -Infinity, lastComputed = -Infinity; | |
each(obj, function(value, index, list) { | |
var computed = iterator ? iterator.call(context, value, index, list) : value; | |
if (computed > lastComputed) { | |
result = value; | |
lastComputed = computed; | |
} | |
}); | |
return result; | |
}; | |
// Return the minimum element (or element-based computation). | |
_.min = function(obj, iterator, context) { | |
if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) { | |
return Math.min.apply(Math, obj); | |
} | |
var result = Infinity, lastComputed = Infinity; | |
each(obj, function(value, index, list) { | |
var computed = iterator ? iterator.call(context, value, index, list) : value; | |
if (computed < lastComputed) { | |
result = value; | |
lastComputed = computed; | |
} | |
}); | |
return result; | |
}; | |
// Shuffle an array, using the modern version of the | |
// [Fisher-Yates shuffle](http://en.wikipedia.org/wiki/Fisher–Yates_shuffle). | |
_.shuffle = function(obj) { | |
var rand; | |
var index = 0; | |
var shuffled = []; | |
each(obj, function(value) { | |
rand = _.random(index++); | |
shuffled[index - 1] = shuffled[rand]; | |
shuffled[rand] = value; | |
}); | |
return shuffled; | |
}; | |
// Sample **n** random values from a collection. | |
// If **n** is not specified, returns a single random element. | |
// The internal `guard` argument allows it to work with `map`. | |
_.sample = function(obj, n, guard) { | |
if (n == null || guard) { | |
if (obj.length !== +obj.length) obj = _.values(obj); | |
return obj[_.random(obj.length - 1)]; | |
} | |
return _.shuffle(obj).slice(0, Math.max(0, n)); | |
}; | |
// An internal function to generate lookup iterators. | |
var lookupIterator = function(value) { | |
if (value == null) return _.identity; | |
if (_.isFunction(value)) return value; | |
return _.property(value); | |
}; | |
// Sort the object's values by a criterion produced by an iterator. | |
_.sortBy = function(obj, iterator, context) { | |
iterator = lookupIterator(iterator); | |
return _.pluck(_.map(obj, function(value, index, list) { | |
return { | |
value: value, | |
index: index, | |
criteria: iterator.call(context, value, index, list) | |
}; | |
}).sort(function(left, right) { | |
var a = left.criteria; | |
var b = right.criteria; | |
if (a !== b) { | |
if (a > b || a === void 0) return 1; | |
if (a < b || b === void 0) return -1; | |
} | |
return left.index - right.index; | |
}), 'value'); | |
}; | |
// An internal function used for aggregate "group by" operations. | |
var group = function(behavior) { | |
return function(obj, iterator, context) { | |
var result = {}; | |
iterator = lookupIterator(iterator); | |
each(obj, function(value, index) { | |
var key = iterator.call(context, value, index, obj); | |
behavior(result, key, value); | |
}); | |
return result; | |
}; | |
}; | |
// Groups the object's values by a criterion. Pass either a string attribute | |
// to group by, or a function that returns the criterion. | |
_.groupBy = group(function(result, key, value) { | |
_.has(result, key) ? result[key].push(value) : result[key] = [value]; | |
}); | |
// Indexes the object's values by a criterion, similar to `groupBy`, but for | |
// when you know that your index values will be unique. | |
_.indexBy = group(function(result, key, value) { | |
result[key] = value; | |
}); | |
// Counts instances of an object that group by a certain criterion. Pass | |
// either a string attribute to count by, or a function that returns the | |
// criterion. | |
_.countBy = group(function(result, key) { | |
_.has(result, key) ? result[key]++ : result[key] = 1; | |
}); | |
// Use a comparator function to figure out the smallest index at which | |
// an object should be inserted so as to maintain order. Uses binary search. | |
_.sortedIndex = function(array, obj, iterator, context) { | |
iterator = lookupIterator(iterator); | |
var value = iterator.call(context, obj); | |
var low = 0, high = array.length; | |
while (low < high) { | |
var mid = (low + high) >>> 1; | |
iterator.call(context, array[mid]) < value ? low = mid + 1 : high = mid; | |
} | |
return low; | |
}; | |
// Safely create a real, live array from anything iterable. | |
_.toArray = function(obj) { | |
if (!obj) return []; | |
if (_.isArray(obj)) return slice.call(obj); | |
if (obj.length === +obj.length) return _.map(obj, _.identity); | |
return _.values(obj); | |
}; | |
// Return the number of elements in an object. | |
_.size = function(obj) { | |
if (obj == null) return 0; | |
return (obj.length === +obj.length) ? obj.length : _.keys(obj).length; | |
}; | |
// Array Functions | |
// --------------- | |
// Get the first element of an array. Passing **n** will return the first N | |
// values in the array. Aliased as `head` and `take`. The **guard** check | |
// allows it to work with `_.map`. | |
_.first = _.head = _.take = function(array, n, guard) { | |
if (array == null) return void 0; | |
if ((n == null) || guard) return array[0]; | |
if (n < 0) return []; | |
return slice.call(array, 0, n); | |
}; | |
// Returns everything but the last entry of the array. Especially useful on | |
// the arguments object. Passing **n** will return all the values in | |
// the array, excluding the last N. The **guard** check allows it to work with | |
// `_.map`. | |
_.initial = function(array, n, guard) { | |
return slice.call(array, 0, array.length - ((n == null) || guard ? 1 : n)); | |
}; | |
// Get the last element of an array. Passing **n** will return the last N | |
// values in the array. The **guard** check allows it to work with `_.map`. | |
_.last = function(array, n, guard) { | |
if (array == null) return void 0; | |
if ((n == null) || guard) return array[array.length - 1]; | |
return slice.call(array, Math.max(array.length - n, 0)); | |
}; | |
// Returns everything but the first entry of the array. Aliased as `tail` and `drop`. | |
// Especially useful on the arguments object. Passing an **n** will return | |
// the rest N values in the array. The **guard** | |
// check allows it to work with `_.map`. | |
_.rest = _.tail = _.drop = function(array, n, guard) { | |
return slice.call(array, (n == null) || guard ? 1 : n); | |
}; | |
// Trim out all falsy values from an array. | |
_.compact = function(array) { | |
return _.filter(array, _.identity); | |
}; | |
// Internal implementation of a recursive `flatten` function. | |
var flatten = function(input, shallow, output) { | |
if (shallow && _.every(input, _.isArray)) { | |
return concat.apply(output, input); | |
} | |
each(input, function(value) { | |
if (_.isArray(value) || _.isArguments(value)) { | |
shallow ? push.apply(output, value) : flatten(value, shallow, output); | |
} else { | |
output.push(value); | |
} | |
}); | |
return output; | |
}; | |
// Flatten out an array, either recursively (by default), or just one level. | |
_.flatten = function(array, shallow) { | |
return flatten(array, shallow, []); | |
}; | |
// Return a version of the array that does not contain the specified value(s). | |
_.without = function(array) { | |
return _.difference(array, slice.call(arguments, 1)); | |
}; | |
// Split an array into two arrays: one whose elements all satisfy the given | |
// predicate, and one whose elements all do not satisfy the predicate. | |
_.partition = function(array, predicate) { | |
var pass = [], fail = []; | |
each(array, function(elem) { | |
(predicate(elem) ? pass : fail).push(elem); | |
}); | |
return [pass, fail]; | |
}; | |
// Produce a duplicate-free version of the array. If the array has already | |
// been sorted, you have the option of using a faster algorithm. | |
// Aliased as `unique`. | |
_.uniq = _.unique = function(array, isSorted, iterator, context) { | |
if (_.isFunction(isSorted)) { | |
context = iterator; | |
iterator = isSorted; | |
isSorted = false; | |
} | |
var initial = iterator ? _.map(array, iterator, context) : array; | |
var results = []; | |
var seen = []; | |
each(initial, function(value, index) { | |
if (isSorted ? (!index || seen[seen.length - 1] !== value) : !_.contains(seen, value)) { | |
seen.push(value); | |
results.push(array[index]); | |
} | |
}); | |
return results; | |
}; | |
// Produce an array that contains the union: each distinct element from all of | |
// the passed-in arrays. | |
_.union = function() { | |
return _.uniq(_.flatten(arguments, true)); | |
}; | |
// Produce an array that contains every item shared between all the | |
// passed-in arrays. | |
_.intersection = function(array) { | |
var rest = slice.call(arguments, 1); | |
return _.filter(_.uniq(array), function(item) { | |
return _.every(rest, function(other) { | |
return _.contains(other, item); | |
}); | |
}); | |
}; | |
// Take the difference between one array and a number of other arrays. | |
// Only the elements present in just the first array will remain. | |
_.difference = function(array) { | |
var rest = concat.apply(ArrayProto, slice.call(arguments, 1)); | |
return _.filter(array, function(value){ return !_.contains(rest, value); }); | |
}; | |
// Zip together multiple lists into a single array -- elements that share | |
// an index go together. | |
_.zip = function() { | |
var length = _.max(_.pluck(arguments, 'length').concat(0)); | |
var results = new Array(length); | |
for (var i = 0; i < length; i++) { | |
results[i] = _.pluck(arguments, '' + i); | |
} | |
return results; | |
}; | |
// Converts lists into objects. Pass either a single array of `[key, value]` | |
// pairs, or two parallel arrays of the same length -- one of keys, and one of | |
// the corresponding values. | |
_.object = function(list, values) { | |
if (list == null) return {}; | |
var result = {}; | |
for (var i = 0, length = list.length; i < length; i++) { | |
if (values) { | |
result[list[i]] = values[i]; | |
} else { | |
result[list[i][0]] = list[i][1]; | |
} | |
} | |
return result; | |
}; | |
// If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**), | |
// we need this function. Return the position of the first occurrence of an | |
// item in an array, or -1 if the item is not included in the array. | |
// Delegates to **ECMAScript 5**'s native `indexOf` if available. | |
// If the array is large and already in sort order, pass `true` | |
// for **isSorted** to use binary search. | |
_.indexOf = function(array, item, isSorted) { | |
if (array == null) return -1; | |
var i = 0, length = array.length; | |
if (isSorted) { | |
if (typeof isSorted == 'number') { | |
i = (isSorted < 0 ? Math.max(0, length + isSorted) : isSorted); | |
} else { | |
i = _.sortedIndex(array, item); | |
return array[i] === item ? i : -1; | |
} | |
} | |
if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item, isSorted); | |
for (; i < length; i++) if (array[i] === item) return i; | |
return -1; | |
}; | |
// Delegates to **ECMAScript 5**'s native `lastIndexOf` if available. | |
_.lastIndexOf = function(array, item, from) { | |
if (array == null) return -1; | |
var hasIndex = from != null; | |
if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) { | |
return hasIndex ? array.lastIndexOf(item, from) : array.lastIndexOf(item); | |
} | |
var i = (hasIndex ? from : array.length); | |
while (i--) if (array[i] === item) return i; | |
return -1; | |
}; | |
// Generate an integer Array containing an arithmetic progression. A port of | |
// the native Python `range()` function. See | |
// [the Python documentation](http://docs.python.org/library/functions.html#range). | |
_.range = function(start, stop, step) { | |
if (arguments.length <= 1) { | |
stop = start || 0; | |
start = 0; | |
} | |
step = arguments[2] || 1; | |
var length = Math.max(Math.ceil((stop - start) / step), 0); | |
var idx = 0; | |
var range = new Array(length); | |
while(idx < length) { | |
range[idx++] = start; | |
start += step; | |
} | |
return range; | |
}; | |
// Function (ahem) Functions | |
// ------------------ | |
// Reusable constructor function for prototype setting. | |
var ctor = function(){}; | |
// Create a function bound to a given object (assigning `this`, and arguments, | |
// optionally). Delegates to **ECMAScript 5**'s native `Function.bind` if | |
// available. | |
_.bind = function(func, context) { | |
var args, bound; | |
if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1)); | |
if (!_.isFunction(func)) throw new TypeError; | |
args = slice.call(arguments, 2); | |
return bound = function() { | |
if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments))); | |
ctor.prototype = func.prototype; | |
var self = new ctor; | |
ctor.prototype = null; | |
var result = func.apply(self, args.concat(slice.call(arguments))); | |
if (Object(result) === result) return result; | |
return self; | |
}; | |
}; | |
// Partially apply a function by creating a version that has had some of its | |
// arguments pre-filled, without changing its dynamic `this` context. _ acts | |
// as a placeholder, allowing any combination of arguments to be pre-filled. | |
_.partial = function(func) { | |
var boundArgs = slice.call(arguments, 1); | |
return function() { | |
var position = 0; | |
var args = boundArgs.slice(); | |
for (var i = 0, length = args.length; i < length; i++) { | |
if (args[i] === _) args[i] = arguments[position++]; | |
} | |
while (position < arguments.length) args.push(arguments[position++]); | |
return func.apply(this, args); | |
}; | |
}; | |
// Bind a number of an object's methods to that object. Remaining arguments | |
// are the method names to be bound. Useful for ensuring that all callbacks | |
// defined on an object belong to it. | |
_.bindAll = function(obj) { | |
var funcs = slice.call(arguments, 1); | |
if (funcs.length === 0) throw new Error('bindAll must be passed function names'); | |
each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); }); | |
return obj; | |
}; | |
// Memoize an expensive function by storing its results. | |
_.memoize = function(func, hasher) { | |
var memo = {}; | |
hasher || (hasher = _.identity); | |
return function() { | |
var key = hasher.apply(this, arguments); | |
return _.has(memo, key) ? memo[key] : (memo[key] = func.apply(this, arguments)); | |
}; | |
}; | |
// Delays a function for the given number of milliseconds, and then calls | |
// it with the arguments supplied. | |
_.delay = function(func, wait) { | |
var args = slice.call(arguments, 2); | |
return setTimeout(function(){ return func.apply(null, args); }, wait); | |
}; | |
// Defers a function, scheduling it to run after the current call stack has | |
// cleared. | |
_.defer = function(func) { | |
return _.delay.apply(_, [func, 1].concat(slice.call(arguments, 1))); | |
}; | |
// Returns a function, that, when invoked, will only be triggered at most once | |
// during a given window of time. Normally, the throttled function will run | |
// as much as it can, without ever going more than once per `wait` duration; | |
// but if you'd like to disable the execution on the leading edge, pass | |
// `{leading: false}`. To disable execution on the trailing edge, ditto. | |
_.throttle = function(func, wait, options) { | |
var context, args, result; | |
var timeout = null; | |
var previous = 0; | |
options || (options = {}); | |
var later = function() { | |
previous = options.leading === false ? 0 : _.now(); | |
timeout = null; | |
result = func.apply(context, args); | |
context = args = null; | |
}; | |
return function() { | |
var now = _.now(); | |
if (!previous && options.leading === false) previous = now; | |
var remaining = wait - (now - previous); | |
context = this; | |
args = arguments; | |
if (remaining <= 0) { | |
clearTimeout(timeout); | |
timeout = null; | |
previous = now; | |
result = func.apply(context, args); | |
context = args = null; | |
} else if (!timeout && options.trailing !== false) { | |
timeout = setTimeout(later, remaining); | |
} | |
return result; | |
}; | |
}; | |
// Returns a function, that, as long as it continues to be invoked, will not | |
// be triggered. The function will be called after it stops being called for | |
// N milliseconds. If `immediate` is passed, trigger the function on the | |
// leading edge, instead of the trailing. | |
_.debounce = function(func, wait, immediate) { | |
var timeout, args, context, timestamp, result; | |
var later = function() { | |
var last = _.now() - timestamp; | |
if (last < wait) { | |
timeout = setTimeout(later, wait - last); | |
} else { | |
timeout = null; | |
if (!immediate) { | |
result = func.apply(context, args); | |
context = args = null; | |
} | |
} | |
}; | |
return function() { | |
context = this; | |
args = arguments; | |
timestamp = _.now(); | |
var callNow = immediate && !timeout; | |
if (!timeout) { | |
timeout = setTimeout(later, wait); | |
} | |
if (callNow) { | |
result = func.apply(context, args); | |
context = args = null; | |
} | |
return result; | |
}; | |
}; | |
// Returns a function that will be executed at most one time, no matter how | |
// often you call it. Useful for lazy initialization. | |
_.once = function(func) { | |
var ran = false, memo; | |
return function() { | |
if (ran) return memo; | |
ran = true; | |
memo = func.apply(this, arguments); | |
func = null; | |
return memo; | |
}; | |
}; | |
// Returns the first function passed as an argument to the second, | |
// allowing you to adjust arguments, run code before and after, and | |
// conditionally execute the original function. | |
_.wrap = function(func, wrapper) { | |
return _.partial(wrapper, func); | |
}; | |
// Returns a function that is the composition of a list of functions, each | |
// consuming the return value of the function that follows. | |
_.compose = function() { | |
var funcs = arguments; | |
return function() { | |
var args = arguments; | |
for (var i = funcs.length - 1; i >= 0; i--) { | |
args = [funcs[i].apply(this, args)]; | |
} | |
return args[0]; | |
}; | |
}; | |
// Returns a function that will only be executed after being called N times. | |
_.after = function(times, func) { | |
return function() { | |
if (--times < 1) { | |
return func.apply(this, arguments); | |
} | |
}; | |
}; | |
// Object Functions | |
// ---------------- | |
// Retrieve the names of an object's properties. | |
// Delegates to **ECMAScript 5**'s native `Object.keys` | |
_.keys = function(obj) { | |
if (!_.isObject(obj)) return []; | |
if (nativeKeys) return nativeKeys(obj); | |
var keys = []; | |
for (var key in obj) if (_.has(obj, key)) keys.push(key); | |
return keys; | |
}; | |
// Retrieve the values of an object's properties. | |
_.values = function(obj) { | |
var keys = _.keys(obj); | |
var length = keys.length; | |
var values = new Array(length); | |
for (var i = 0; i < length; i++) { | |
values[i] = obj[keys[i]]; | |
} | |
return values; | |
}; | |
// Convert an object into a list of `[key, value]` pairs. | |
_.pairs = function(obj) { | |
var keys = _.keys(obj); | |
var length = keys.length; | |
var pairs = new Array(length); | |
for (var i = 0; i < length; i++) { | |
pairs[i] = [keys[i], obj[keys[i]]]; | |
} | |
return pairs; | |
}; | |
// Invert the keys and values of an object. The values must be serializable. | |
_.invert = function(obj) { | |
var result = {}; | |
var keys = _.keys(obj); | |
for (var i = 0, length = keys.length; i < length; i++) { | |
result[obj[keys[i]]] = keys[i]; | |
} | |
return result; | |
}; | |
// Return a sorted list of the function names available on the object. | |
// Aliased as `methods` | |
_.functions = _.methods = function(obj) { | |
var names = []; | |
for (var key in obj) { | |
if (_.isFunction(obj[key])) names.push(key); | |
} | |
return names.sort(); | |
}; | |
// Extend a given object with all the properties in passed-in object(s). | |
_.extend = function(obj) { | |
each(slice.call(arguments, 1), function(source) { | |
if (source) { | |
for (var prop in source) { | |
obj[prop] = source[prop]; | |
} | |
} | |
}); | |
return obj; | |
}; | |
// Return a copy of the object only containing the whitelisted properties. | |
_.pick = function(obj) { | |
var copy = {}; | |
var keys = concat.apply(ArrayProto, slice.call(arguments, 1)); | |
each(keys, function(key) { | |
if (key in obj) copy[key] = obj[key]; | |
}); | |
return copy; | |
}; | |
// Return a copy of the object without the blacklisted properties. | |
_.omit = function(obj) { | |
var copy = {}; | |
var keys = concat.apply(ArrayProto, slice.call(arguments, 1)); | |
for (var key in obj) { | |
if (!_.contains(keys, key)) copy[key] = obj[key]; | |
} | |
return copy; | |
}; | |
// Fill in a given object with default properties. | |
_.defaults = function(obj) { | |
each(slice.call(arguments, 1), function(source) { | |
if (source) { | |
for (var prop in source) { | |
if (obj[prop] === void 0) obj[prop] = source[prop]; | |
} | |
} | |
}); | |
return obj; | |
}; | |
// Create a (shallow-cloned) duplicate of an object. | |
_.clone = function(obj) { | |
if (!_.isObject(obj)) return obj; | |
return _.isArray(obj) ? obj.slice() : _.extend({}, obj); | |
}; | |
// Invokes interceptor with the obj, and then returns obj. | |
// The primary purpose of this method is to "tap into" a method chain, in | |
// order to perform operations on intermediate results within the chain. | |
_.tap = function(obj, interceptor) { | |
interceptor(obj); | |
return obj; | |
}; | |
// Internal recursive comparison function for `isEqual`. | |
var eq = function(a, b, aStack, bStack) { | |
// Identical objects are equal. `0 === -0`, but they aren't identical. | |
// See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal). | |
if (a === b) return a !== 0 || 1 / a == 1 / b; | |
// A strict comparison is necessary because `null == undefined`. | |
if (a == null || b == null) return a === b; | |
// Unwrap any wrapped objects. | |
if (a instanceof _) a = a._wrapped; | |
if (b instanceof _) b = b._wrapped; | |
// Compare `[[Class]]` names. | |
var className = toString.call(a); | |
if (className != toString.call(b)) return false; | |
switch (className) { | |
// Strings, numbers, dates, and booleans are compared by value. | |
case '[object String]': | |
// Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is | |
// equivalent to `new String("5")`. | |
return a == String(b); | |
case '[object Number]': | |
// `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for | |
// other numeric values. | |
return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b); | |
case '[object Date]': | |
case '[object Boolean]': | |
// Coerce dates and booleans to numeric primitive values. Dates are compared by their | |
// millisecond representations. Note that invalid dates with millisecond representations | |
// of `NaN` are not equivalent. | |
return +a == +b; | |
// RegExps are compared by their source patterns and flags. | |
case '[object RegExp]': | |
return a.source == b.source && | |
a.global == b.global && | |
a.multiline == b.multiline && | |
a.ignoreCase == b.ignoreCase; | |
} | |
if (typeof a != 'object' || typeof b != 'object') return false; | |
// Assume equality for cyclic structures. The algorithm for detecting cyclic | |
// structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`. | |
var length = aStack.length; | |
while (length--) { | |
// Linear search. Performance is inversely proportional to the number of | |
// unique nested structures. | |
if (aStack[length] == a) return bStack[length] == b; | |
} | |
// Objects with different constructors are not equivalent, but `Object`s | |
// from different frames are. | |
var aCtor = a.constructor, bCtor = b.constructor; | |
if (aCtor !== bCtor && !(_.isFunction(aCtor) && (aCtor instanceof aCtor) && | |
_.isFunction(bCtor) && (bCtor instanceof bCtor)) | |
&& ('constructor' in a && 'constructor' in b)) { | |
return false; | |
} | |
// Add the first object to the stack of traversed objects. | |
aStack.push(a); | |
bStack.push(b); | |
var size = 0, result = true; | |
// Recursively compare objects and arrays. | |
if (className == '[object Array]') { | |
// Compare array lengths to determine if a deep comparison is necessary. | |
size = a.length; | |
result = size == b.length; | |
if (result) { | |
// Deep compare the contents, ignoring non-numeric properties. | |
while (size--) { | |
if (!(result = eq(a[size], b[size], aStack, bStack))) break; | |
} | |
} | |
} else { | |
// Deep compare objects. | |
for (var key in a) { | |
if (_.has(a, key)) { | |
// Count the expected number of properties. | |
size++; | |
// Deep compare each member. | |
if (!(result = _.has(b, key) && eq(a[key], b[key], aStack, bStack))) break; | |
} | |
} | |
// Ensure that both objects contain the same number of properties. | |
if (result) { | |
for (key in b) { | |
if (_.has(b, key) && !(size--)) break; | |
} | |
result = !size; | |
} | |
} | |
// Remove the first object from the stack of traversed objects. | |
aStack.pop(); | |
bStack.pop(); | |
return result; | |
}; | |
// Perform a deep comparison to check if two objects are equal. | |
_.isEqual = function(a, b) { | |
return eq(a, b, [], []); | |
}; | |
// Is a given array, string, or object empty? | |
// An "empty" object has no enumerable own-properties. | |
_.isEmpty = function(obj) { | |
if (obj == null) return true; | |
if (_.isArray(obj) || _.isString(obj)) return obj.length === 0; | |
for (var key in obj) if (_.has(obj, key)) return false; | |
return true; | |
}; | |
// Is a given value a DOM element? | |
_.isElement = function(obj) { | |
return !!(obj && obj.nodeType === 1); | |
}; | |
// Is a given value an array? | |
// Delegates to ECMA5's native Array.isArray | |
_.isArray = nativeIsArray || function(obj) { | |
return toString.call(obj) == '[object Array]'; | |
}; | |
// Is a given variable an object? | |
_.isObject = function(obj) { | |
return obj === Object(obj); | |
}; | |
// Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp. | |
each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) { | |
_['is' + name] = function(obj) { | |
return toString.call(obj) == '[object ' + name + ']'; | |
}; | |
}); | |
// Define a fallback version of the method in browsers (ahem, IE), where | |
// there isn't any inspectable "Arguments" type. | |
if (!_.isArguments(arguments)) { | |
_.isArguments = function(obj) { | |
return !!(obj && _.has(obj, 'callee')); | |
}; | |
} | |
// Optimize `isFunction` if appropriate. | |
if (typeof (/./) !== 'function') { | |
_.isFunction = function(obj) { | |
return typeof obj === 'function'; | |
}; | |
} | |
// Is a given object a finite number? | |
_.isFinite = function(obj) { | |
return isFinite(obj) && !isNaN(parseFloat(obj)); | |
}; | |
// Is the given value `NaN`? (NaN is the only number which does not equal itself). | |
_.isNaN = function(obj) { | |
return _.isNumber(obj) && obj != +obj; | |
}; | |
// Is a given value a boolean? | |
_.isBoolean = function(obj) { | |
return obj === true || obj === false || toString.call(obj) == '[object Boolean]'; | |
}; | |
// Is a given value equal to null? | |
_.isNull = function(obj) { | |
return obj === null; | |
}; | |
// Is a given variable undefined? | |
_.isUndefined = function(obj) { | |
return obj === void 0; | |
}; | |
// Shortcut function for checking if an object has a given property directly | |
// on itself (in other words, not on a prototype). | |
_.has = function(obj, key) { | |
return hasOwnProperty.call(obj, key); | |
}; | |
// Utility Functions | |
// ----------------- | |
// Run Underscore.js in *noConflict* mode, returning the `_` variable to its | |
// previous owner. Returns a reference to the Underscore object. | |
_.noConflict = function() { | |
root._ = previousUnderscore; | |
return this; | |
}; | |
// Keep the identity function around for default iterators. | |
_.identity = function(value) { | |
return value; | |
}; | |
_.constant = function(value) { | |
return function () { | |
return value; | |
}; | |
}; | |
_.property = function(key) { | |
return function(obj) { | |
return obj[key]; | |
}; | |
}; | |
// Returns a predicate for checking whether an object has a given set of `key:value` pairs. | |
_.matches = function(attrs) { | |
return function(obj) { | |
if (obj === attrs) return true; //avoid comparing an object to itself. | |
for (var key in attrs) { | |
if (attrs[key] !== obj[key]) | |
return false; | |
} | |
return true; | |
} | |
}; | |
// Run a function **n** times. | |
_.times = function(n, iterator, context) { | |
var accum = Array(Math.max(0, n)); | |
for (var i = 0; i < n; i++) accum[i] = iterator.call(context, i); | |
return accum; | |
}; | |
// Return a random integer between min and max (inclusive). | |
_.random = function(min, max) { | |
if (max == null) { | |
max = min; | |
min = 0; | |
} | |
return min + Math.floor(Math.random() * (max - min + 1)); | |
}; | |
// A (possibly faster) way to get the current timestamp as an integer. | |
_.now = Date.now || function() { return new Date().getTime(); }; | |
// List of HTML entities for escaping. | |
var entityMap = { | |
escape: { | |
'&': '&', | |
'<': '<', | |
'>': '>', | |
'"': '"', | |
"'": ''' | |
} | |
}; | |
entityMap.unescape = _.invert(entityMap.escape); | |
// Regexes containing the keys and values listed immediately above. | |
var entityRegexes = { | |
escape: new RegExp('[' + _.keys(entityMap.escape).join('') + ']', 'g'), | |
unescape: new RegExp('(' + _.keys(entityMap.unescape).join('|') + ')', 'g') | |
}; | |
// Functions for escaping and unescaping strings to/from HTML interpolation. | |
_.each(['escape', 'unescape'], function(method) { | |
_[method] = function(string) { | |
if (string == null) return ''; | |
return ('' + string).replace(entityRegexes[method], function(match) { | |
return entityMap[method][match]; | |
}); | |
}; | |
}); | |
// If the value of the named `property` is a function then invoke it with the | |
// `object` as context; otherwise, return it. | |
_.result = function(object, property) { | |
if (object == null) return void 0; | |
var value = object[property]; | |
return _.isFunction(value) ? value.call(object) : value; | |
}; | |
// Add your own custom functions to the Underscore object. | |
_.mixin = function(obj) { | |
each(_.functions(obj), function(name) { | |
var func = _[name] = obj[name]; | |
_.prototype[name] = function() { | |
var args = [this._wrapped]; | |
push.apply(args, arguments); | |
return result.call(this, func.apply(_, args)); | |
}; | |
}); | |
}; | |
// Generate a unique integer id (unique within the entire client session). | |
// Useful for temporary DOM ids. | |
var idCounter = 0; | |
_.uniqueId = function(prefix) { | |
var id = ++idCounter + ''; | |
return prefix ? prefix + id : id; | |
}; | |
// By default, Underscore uses ERB-style template delimiters, change the | |
// following template settings to use alternative delimiters. | |
_.templateSettings = { | |
evaluate : /<%([\s\S]+?)%>/g, | |
interpolate : /<%=([\s\S]+?)%>/g, | |
escape : /<%-([\s\S]+?)%>/g | |
}; | |
// When customizing `templateSettings`, if you don't want to define an | |
// interpolation, evaluation or escaping regex, we need one that is | |
// guaranteed not to match. | |
var noMatch = /(.)^/; | |
// Certain characters need to be escaped so that they can be put into a | |
// string literal. | |
var escapes = { | |
"'": "'", | |
'\\': '\\', | |
'\r': 'r', | |
'\n': 'n', | |
'\t': 't', | |
'\u2028': 'u2028', | |
'\u2029': 'u2029' | |
}; | |
var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g; | |
// JavaScript micro-templating, similar to John Resig's implementation. | |
// Underscore templating handles arbitrary delimiters, preserves whitespace, | |
// and correctly escapes quotes within interpolated code. | |
_.template = function(text, data, settings) { | |
var render; | |
settings = _.defaults({}, settings, _.templateSettings); | |
// Combine delimiters into one regular expression via alternation. | |
var matcher = new RegExp([ | |
(settings.escape || noMatch).source, | |
(settings.interpolate || noMatch).source, | |
(settings.evaluate || noMatch).source | |
].join('|') + '|$', 'g'); | |
// Compile the template source, escaping string literals appropriately. | |
var index = 0; | |
var source = "__p+='"; | |
text.replace(matcher, function(match, escape, interpolate, evaluate, offset) { | |
source += text.slice(index, offset) | |
.replace(escaper, function(match) { return '\\' + escapes[match]; }); | |
if (escape) { | |
source += "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'"; | |
} | |
if (interpolate) { | |
source += "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'"; | |
} | |
if (evaluate) { | |
source += "';\n" + evaluate + "\n__p+='"; | |
} | |
index = offset + match.length; | |
return match; | |
}); | |
source += "';\n"; | |
// If a variable is not specified, place data values in local scope. | |
if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n'; | |
source = "var __t,__p='',__j=Array.prototype.join," + | |
"print=function(){__p+=__j.call(arguments,'');};\n" + | |
source + "return __p;\n"; | |
try { | |
render = new Function(settings.variable || 'obj', '_', source); | |
} catch (e) { | |
e.source = source; | |
throw e; | |
} | |
if (data) return render(data, _); | |
var template = function(data) { | |
return render.call(this, data, _); | |
}; | |
// Provide the compiled function source as a convenience for precompilation. | |
template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}'; | |
return template; | |
}; | |
// Add a "chain" function, which will delegate to the wrapper. | |
_.chain = function(obj) { | |
return _(obj).chain(); | |
}; | |
// OOP | |
// --------------- | |
// If Underscore is called as a function, it returns a wrapped object that | |
// can be used OO-style. This wrapper holds altered versions of all the | |
// underscore functions. Wrapped objects may be chained. | |
// Helper function to continue chaining intermediate results. | |
var result = function(obj) { | |
return this._chain ? _(obj).chain() : obj; | |
}; | |
// Add all of the Underscore functions to the wrapper object. | |
_.mixin(_); | |
// Add all mutator Array functions to the wrapper. | |
each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) { | |
var method = ArrayProto[name]; | |
_.prototype[name] = function() { | |
var obj = this._wrapped; | |
method.apply(obj, arguments); | |
if ((name == 'shift' || name == 'splice') && obj.length === 0) delete obj[0]; | |
return result.call(this, obj); | |
}; | |
}); | |
// Add all accessor Array functions to the wrapper. | |
each(['concat', 'join', 'slice'], function(name) { | |
var method = ArrayProto[name]; | |
_.prototype[name] = function() { | |
return result.call(this, method.apply(this._wrapped, arguments)); | |
}; | |
}); | |
_.extend(_.prototype, { | |
// Start chaining a wrapped Underscore object. | |
chain: function() { | |
this._chain = true; | |
return this; | |
}, | |
// Extracts the result from a wrapped and chained object. | |
value: function() { | |
return this._wrapped; | |
} | |
}); | |
// AMD registration happens at the end for compatibility with AMD loaders | |
// that may not enforce next-turn semantics on modules. Even though general | |
// practice for AMD registration is to be anonymous, underscore registers | |
// as a named module because, like jQuery, it is a base library that is | |
// popular enough to be bundled in a third party lib, but not be part of | |
// an AMD load request. Those cases could generate an error when an | |
// anonymous define() is called outside of a loader request. | |
if (typeof define === 'function' && define.amd) { | |
define('underscore', [], function() { | |
return _; | |
}); | |
} | |
}).call(this); | |
},{}],188:[function(_dereq_,module,exports){ | |
/* | |
WildEmitter.js is a slim little event emitter by @henrikjoreteg largely based | |
on @visionmedia's Emitter from UI Kit. | |
Why? I wanted it standalone. | |
I also wanted support for wildcard emitters like this: | |
emitter.on('*', function (eventName, other, event, payloads) { | |
}); | |
emitter.on('somenamespace*', function (eventName, payloads) { | |
}); | |
Please note that callbacks triggered by wildcard registered events also get | |
the event name as the first argument. | |
*/ | |
module.exports = WildEmitter; | |
function WildEmitter() { | |
this.callbacks = {}; | |
} | |
// Listen on the given `event` with `fn`. Store a group name if present. | |
WildEmitter.prototype.on = function (event, groupName, fn) { | |
var hasGroup = (arguments.length === 3), | |
group = hasGroup ? arguments[1] : undefined, | |
func = hasGroup ? arguments[2] : arguments[1]; | |
func._groupName = group; | |
(this.callbacks[event] = this.callbacks[event] || []).push(func); | |
return this; | |
}; | |
// Adds an `event` listener that will be invoked a single | |
// time then automatically removed. | |
WildEmitter.prototype.once = function (event, groupName, fn) { | |
var self = this, | |
hasGroup = (arguments.length === 3), | |
group = hasGroup ? arguments[1] : undefined, | |
func = hasGroup ? arguments[2] : arguments[1]; | |
function on() { | |
self.off(event, on); | |
func.apply(this, arguments); | |
} | |
this.on(event, group, on); | |
return this; | |
}; | |
// Unbinds an entire group | |
WildEmitter.prototype.releaseGroup = function (groupName) { | |
var item, i, len, handlers; | |
for (item in this.callbacks) { | |
handlers = this.callbacks[item]; | |
for (i = 0, len = handlers.length; i < len; i++) { | |
if (handlers[i]._groupName === groupName) { | |
//console.log('removing'); | |
// remove it and shorten the array we're looping through | |
handlers.splice(i, 1); | |
i--; | |
len--; | |
} | |
} | |
} | |
return this; | |
}; | |
// Remove the given callback for `event` or all | |
// registered callbacks. | |
WildEmitter.prototype.off = function (event, fn) { | |
var callbacks = this.callbacks[event], | |
i; | |
if (!callbacks) return this; | |
// remove all handlers | |
if (arguments.length === 1) { | |
delete this.callbacks[event]; | |
return this; | |
} | |
// remove specific handler | |
i = callbacks.indexOf(fn); | |
callbacks.splice(i, 1); | |
return this; | |
}; | |
/// Emit `event` with the given args. | |
// also calls any `*` handlers | |
WildEmitter.prototype.emit = function (event) { | |
var args = [].slice.call(arguments, 1), | |
callbacks = this.callbacks[event], | |
specialCallbacks = this.getWildcardCallbacks(event), | |
i, | |
len, | |
item, | |
listeners; | |
if (callbacks) { | |
listeners = callbacks.slice(); | |
for (i = 0, len = listeners.length; i < len; ++i) { | |
if (listeners[i]) { | |
listeners[i].apply(this, args); | |
} else { | |
break; | |
} | |
} | |
} | |
if (specialCallbacks) { | |
len = specialCallbacks.length; | |
listeners = specialCallbacks.slice(); | |
for (i = 0, len = listeners.length; i < len; ++i) { | |
if (listeners[i]) { | |
listeners[i].apply(this, [event].concat(args)); | |
} else { | |
break; | |
} | |
} | |
} | |
return this; | |
}; | |
// Helper for for finding special wildcard event handlers that match the event | |
WildEmitter.prototype.getWildcardCallbacks = function (eventName) { | |
var item, | |
split, | |
result = []; | |
for (item in this.callbacks) { | |
split = item.split('*'); | |
if (item === '*' || (split.length === 2 && eventName.slice(0, split[0].length) === split[0])) { | |
result = result.concat(this.callbacks[item]); | |
} | |
} | |
return result; | |
}; | |
},{}]},{},[1]) | |
(1) | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment