Skip to content

Instantly share code, notes, and snippets.

@nolanlawson
Last active August 26, 2015 21:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nolanlawson/ac387be0722dad3a207c to your computer and use it in GitHub Desktop.
Save nolanlawson/ac387be0722dad3a207c to your computer and use it in GitHub Desktop.
Basic PouchDB authentication test site
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Mocha Tests</title>
<link rel="stylesheet" href="./mocha.css" />
<script src="./mocha.js"></script>
<script>
mocha.setup('bdd');
</script>
<script src="./test-bundle.js"></script>
</head>
<body>
<div id="mocha"></div>
<script>
mocha.run();
</script>
</body>
</html>
@charset "utf-8";
body {
margin:0;
}
#mocha {
font: 20px/1.5 "Helvetica Neue", Helvetica, Arial, sans-serif;
margin: 60px 50px;
}
#mocha ul, #mocha li {
margin: 0;
padding: 0;
}
#mocha ul {
list-style: none;
}
#mocha h1, #mocha h2 {
margin: 0;
}
#mocha h1 {
margin-top: 15px;
font-size: 1em;
font-weight: 200;
}
#mocha h1 a {
text-decoration: none;
color: inherit;
}
#mocha h1 a:hover {
text-decoration: underline;
}
#mocha .suite .suite h1 {
margin-top: 0;
font-size: .8em;
}
#mocha .hidden {
display: none;
}
#mocha h2 {
font-size: 12px;
font-weight: normal;
cursor: pointer;
}
#mocha .suite {
margin-left: 15px;
}
#mocha .test {
margin-left: 15px;
overflow: hidden;
}
#mocha .test.pending:hover h2::after {
content: '(pending)';
font-family: arial, sans-serif;
}
#mocha .test.pass.medium .duration {
background: #C09853;
}
#mocha .test.pass.slow .duration {
background: #B94A48;
}
#mocha .test.pass::before {
content: '✓';
font-size: 12px;
display: block;
float: left;
margin-right: 5px;
color: #00d6b2;
}
#mocha .test.pass .duration {
font-size: 9px;
margin-left: 5px;
padding: 2px 5px;
color: white;
-webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
-moz-box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
-ms-border-radius: 5px;
-o-border-radius: 5px;
border-radius: 5px;
}
#mocha .test.pass.fast .duration {
display: none;
}
#mocha .test.pending {
color: #0b97c4;
}
#mocha .test.pending::before {
content: '◦';
color: #0b97c4;
}
#mocha .test.fail {
color: #c00;
}
#mocha .test.fail pre {
color: black;
}
#mocha .test.fail::before {
content: '✖';
font-size: 12px;
display: block;
float: left;
margin-right: 5px;
color: #c00;
}
#mocha .test pre.error {
color: #c00;
max-height: 300px;
overflow: auto;
}
#mocha .test pre {
display: block;
float: left;
clear: left;
font: 12px/1.5 monaco, monospace;
margin: 5px;
padding: 15px;
border: 1px solid #eee;
border-bottom-color: #ddd;
-webkit-border-radius: 3px;
-webkit-box-shadow: 0 1px 3px #eee;
-moz-border-radius: 3px;
-moz-box-shadow: 0 1px 3px #eee;
border-radius: 3px;
}
#mocha .test h2 {
position: relative;
}
#mocha .test a.replay {
position: absolute;
top: 3px;
right: 0;
text-decoration: none;
vertical-align: middle;
display: block;
width: 15px;
height: 15px;
line-height: 15px;
text-align: center;
background: #eee;
font-size: 15px;
-moz-border-radius: 15px;
border-radius: 15px;
-webkit-transition: opacity 200ms;
-moz-transition: opacity 200ms;
transition: opacity 200ms;
opacity: 0.3;
color: #888;
}
#mocha .test:hover a.replay {
opacity: 1;
}
#mocha-report.pass .test.fail {
display: none;
}
#mocha-report.fail .test.pass {
display: none;
}
#mocha-report.pending .test.pass,
#mocha-report.pending .test.fail {
display: none;
}
#mocha-report.pending .test.pass.pending {
display: block;
}
#mocha-error {
color: #c00;
font-size: 1.5em;
font-weight: 100;
letter-spacing: 1px;
}
#mocha-stats {
position: fixed;
top: 15px;
right: 10px;
font-size: 12px;
margin: 0;
color: #888;
z-index: 1;
}
#mocha-stats .progress {
float: right;
padding-top: 0;
}
#mocha-stats em {
color: black;
}
#mocha-stats a {
text-decoration: none;
color: inherit;
}
#mocha-stats a:hover {
border-bottom: 1px solid #eee;
}
#mocha-stats li {
display: inline-block;
margin: 0 5px;
list-style: none;
padding-top: 11px;
}
#mocha-stats canvas {
width: 40px;
height: 40px;
}
#mocha code .comment { color: #ddd }
#mocha code .init { color: #2F6FAD }
#mocha code .string { color: #5890AD }
#mocha code .keyword { color: #8A6343 }
#mocha code .number { color: #2F6FAD }
@media screen and (max-device-width: 480px) {
#mocha {
margin: 60px 0px;
}
#mocha #stats {
position: absolute;
}
}
;(function(){
// CommonJS require()
function require(p){
var path = require.resolve(p)
, mod = require.modules[path];
if (!mod) throw new Error('failed to require "' + p + '"');
if (!mod.exports) {
mod.exports = {};
mod.call(mod.exports, mod, mod.exports, require.relative(path));
}
return mod.exports;
}
require.modules = {};
require.resolve = function (path){
var orig = path
, reg = path + '.js'
, index = path + '/index.js';
return require.modules[reg] && reg
|| require.modules[index] && index
|| orig;
};
require.register = function (path, fn){
require.modules[path] = fn;
};
require.relative = function (parent) {
return function(p){
if ('.' != p.charAt(0)) return require(p);
var path = parent.split('/')
, segs = p.split('/');
path.pop();
for (var i = 0; i < segs.length; i++) {
var seg = segs[i];
if ('..' == seg) path.pop();
else if ('.' != seg) path.push(seg);
}
return require(path.join('/'));
};
};
require.register("browser/debug.js", function(module, exports, require){
module.exports = function(type){
return function(){
}
};
}); // module: browser/debug.js
require.register("browser/diff.js", function(module, exports, require){
/* See LICENSE file for terms of use */
/*
* Text diff implementation.
*
* This library supports the following APIS:
* JsDiff.diffChars: Character by character diff
* JsDiff.diffWords: Word (as defined by \b regex) diff which ignores whitespace
* JsDiff.diffLines: Line based diff
*
* JsDiff.diffCss: Diff targeted at CSS content
*
* These methods are based on the implementation proposed in
* "An O(ND) Difference Algorithm and its Variations" (Myers, 1986).
* http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.4.6927
*/
var JsDiff = (function() {
/*jshint maxparams: 5*/
function clonePath(path) {
return { newPos: path.newPos, components: path.components.slice(0) };
}
function removeEmpty(array) {
var ret = [];
for (var i = 0; i < array.length; i++) {
if (array[i]) {
ret.push(array[i]);
}
}
return ret;
}
function escapeHTML(s) {
var n = s;
n = n.replace(/&/g, '&amp;');
n = n.replace(/</g, '&lt;');
n = n.replace(/>/g, '&gt;');
n = n.replace(/"/g, '&quot;');
return n;
}
var Diff = function(ignoreWhitespace) {
this.ignoreWhitespace = ignoreWhitespace;
};
Diff.prototype = {
diff: function(oldString, newString) {
// Handle the identity case (this is due to unrolling editLength == 0
if (newString === oldString) {
return [{ value: newString }];
}
if (!newString) {
return [{ value: oldString, removed: true }];
}
if (!oldString) {
return [{ value: newString, added: true }];
}
newString = this.tokenize(newString);
oldString = this.tokenize(oldString);
var newLen = newString.length, oldLen = oldString.length;
var maxEditLength = newLen + oldLen;
var bestPath = [{ newPos: -1, components: [] }];
// Seed editLength = 0
var oldPos = this.extractCommon(bestPath[0], newString, oldString, 0);
if (bestPath[0].newPos+1 >= newLen && oldPos+1 >= oldLen) {
return bestPath[0].components;
}
for (var editLength = 1; editLength <= maxEditLength; editLength++) {
for (var diagonalPath = -1*editLength; diagonalPath <= editLength; diagonalPath+=2) {
var basePath;
var addPath = bestPath[diagonalPath-1],
removePath = bestPath[diagonalPath+1];
oldPos = (removePath ? removePath.newPos : 0) - diagonalPath;
if (addPath) {
// No one else is going to attempt to use this value, clear it
bestPath[diagonalPath-1] = undefined;
}
var canAdd = addPath && addPath.newPos+1 < newLen;
var canRemove = removePath && 0 <= oldPos && oldPos < oldLen;
if (!canAdd && !canRemove) {
bestPath[diagonalPath] = undefined;
continue;
}
// Select the diagonal that we want to branch from. We select the prior
// path whose position in the new string is the farthest from the origin
// and does not pass the bounds of the diff graph
if (!canAdd || (canRemove && addPath.newPos < removePath.newPos)) {
basePath = clonePath(removePath);
this.pushComponent(basePath.components, oldString[oldPos], undefined, true);
} else {
basePath = clonePath(addPath);
basePath.newPos++;
this.pushComponent(basePath.components, newString[basePath.newPos], true, undefined);
}
var oldPos = this.extractCommon(basePath, newString, oldString, diagonalPath);
if (basePath.newPos+1 >= newLen && oldPos+1 >= oldLen) {
return basePath.components;
} else {
bestPath[diagonalPath] = basePath;
}
}
}
},
pushComponent: function(components, value, added, removed) {
var last = components[components.length-1];
if (last && last.added === added && last.removed === removed) {
// We need to clone here as the component clone operation is just
// as shallow array clone
components[components.length-1] =
{value: this.join(last.value, value), added: added, removed: removed };
} else {
components.push({value: value, added: added, removed: removed });
}
},
extractCommon: function(basePath, newString, oldString, diagonalPath) {
var newLen = newString.length,
oldLen = oldString.length,
newPos = basePath.newPos,
oldPos = newPos - diagonalPath;
while (newPos+1 < newLen && oldPos+1 < oldLen && this.equals(newString[newPos+1], oldString[oldPos+1])) {
newPos++;
oldPos++;
this.pushComponent(basePath.components, newString[newPos], undefined, undefined);
}
basePath.newPos = newPos;
return oldPos;
},
equals: function(left, right) {
var reWhitespace = /\S/;
if (this.ignoreWhitespace && !reWhitespace.test(left) && !reWhitespace.test(right)) {
return true;
} else {
return left === right;
}
},
join: function(left, right) {
return left + right;
},
tokenize: function(value) {
return value;
}
};
var CharDiff = new Diff();
var WordDiff = new Diff(true);
var WordWithSpaceDiff = new Diff();
WordDiff.tokenize = WordWithSpaceDiff.tokenize = function(value) {
return removeEmpty(value.split(/(\s+|\b)/));
};
var CssDiff = new Diff(true);
CssDiff.tokenize = function(value) {
return removeEmpty(value.split(/([{}:;,]|\s+)/));
};
var LineDiff = new Diff();
LineDiff.tokenize = function(value) {
return value.split(/^/m);
};
return {
Diff: Diff,
diffChars: function(oldStr, newStr) { return CharDiff.diff(oldStr, newStr); },
diffWords: function(oldStr, newStr) { return WordDiff.diff(oldStr, newStr); },
diffWordsWithSpace: function(oldStr, newStr) { return WordWithSpaceDiff.diff(oldStr, newStr); },
diffLines: function(oldStr, newStr) { return LineDiff.diff(oldStr, newStr); },
diffCss: function(oldStr, newStr) { return CssDiff.diff(oldStr, newStr); },
createPatch: function(fileName, oldStr, newStr, oldHeader, newHeader) {
var ret = [];
ret.push('Index: ' + fileName);
ret.push('===================================================================');
ret.push('--- ' + fileName + (typeof oldHeader === 'undefined' ? '' : '\t' + oldHeader));
ret.push('+++ ' + fileName + (typeof newHeader === 'undefined' ? '' : '\t' + newHeader));
var diff = LineDiff.diff(oldStr, newStr);
if (!diff[diff.length-1].value) {
diff.pop(); // Remove trailing newline add
}
diff.push({value: '', lines: []}); // Append an empty value to make cleanup easier
function contextLines(lines) {
return lines.map(function(entry) { return ' ' + entry; });
}
function eofNL(curRange, i, current) {
var last = diff[diff.length-2],
isLast = i === diff.length-2,
isLastOfType = i === diff.length-3 && (current.added !== last.added || current.removed !== last.removed);
// Figure out if this is the last line for the given file and missing NL
if (!/\n$/.test(current.value) && (isLast || isLastOfType)) {
curRange.push('\\ No newline at end of file');
}
}
var oldRangeStart = 0, newRangeStart = 0, curRange = [],
oldLine = 1, newLine = 1;
for (var i = 0; i < diff.length; i++) {
var current = diff[i],
lines = current.lines || current.value.replace(/\n$/, '').split('\n');
current.lines = lines;
if (current.added || current.removed) {
if (!oldRangeStart) {
var prev = diff[i-1];
oldRangeStart = oldLine;
newRangeStart = newLine;
if (prev) {
curRange = contextLines(prev.lines.slice(-4));
oldRangeStart -= curRange.length;
newRangeStart -= curRange.length;
}
}
curRange.push.apply(curRange, lines.map(function(entry) { return (current.added?'+':'-') + entry; }));
eofNL(curRange, i, current);
if (current.added) {
newLine += lines.length;
} else {
oldLine += lines.length;
}
} else {
if (oldRangeStart) {
// Close out any changes that have been output (or join overlapping)
if (lines.length <= 8 && i < diff.length-2) {
// Overlapping
curRange.push.apply(curRange, contextLines(lines));
} else {
// end the range and output
var contextSize = Math.min(lines.length, 4);
ret.push(
'@@ -' + oldRangeStart + ',' + (oldLine-oldRangeStart+contextSize)
+ ' +' + newRangeStart + ',' + (newLine-newRangeStart+contextSize)
+ ' @@');
ret.push.apply(ret, curRange);
ret.push.apply(ret, contextLines(lines.slice(0, contextSize)));
if (lines.length <= 4) {
eofNL(ret, i, current);
}
oldRangeStart = 0; newRangeStart = 0; curRange = [];
}
}
oldLine += lines.length;
newLine += lines.length;
}
}
return ret.join('\n') + '\n';
},
applyPatch: function(oldStr, uniDiff) {
var diffstr = uniDiff.split('\n');
var diff = [];
var remEOFNL = false,
addEOFNL = false;
for (var i = (diffstr[0][0]==='I'?4:0); i < diffstr.length; i++) {
if(diffstr[i][0] === '@') {
var meh = diffstr[i].split(/@@ -(\d+),(\d+) \+(\d+),(\d+) @@/);
diff.unshift({
start:meh[3],
oldlength:meh[2],
oldlines:[],
newlength:meh[4],
newlines:[]
});
} else if(diffstr[i][0] === '+') {
diff[0].newlines.push(diffstr[i].substr(1));
} else if(diffstr[i][0] === '-') {
diff[0].oldlines.push(diffstr[i].substr(1));
} else if(diffstr[i][0] === ' ') {
diff[0].newlines.push(diffstr[i].substr(1));
diff[0].oldlines.push(diffstr[i].substr(1));
} else if(diffstr[i][0] === '\\') {
if (diffstr[i-1][0] === '+') {
remEOFNL = true;
} else if(diffstr[i-1][0] === '-') {
addEOFNL = true;
}
}
}
var str = oldStr.split('\n');
for (var i = diff.length - 1; i >= 0; i--) {
var d = diff[i];
for (var j = 0; j < d.oldlength; j++) {
if(str[d.start-1+j] !== d.oldlines[j]) {
return false;
}
}
Array.prototype.splice.apply(str,[d.start-1,+d.oldlength].concat(d.newlines));
}
if (remEOFNL) {
while (!str[str.length-1]) {
str.pop();
}
} else if (addEOFNL) {
str.push('');
}
return str.join('\n');
},
convertChangesToXML: function(changes){
var ret = [];
for ( var i = 0; i < changes.length; i++) {
var change = changes[i];
if (change.added) {
ret.push('<ins>');
} else if (change.removed) {
ret.push('<del>');
}
ret.push(escapeHTML(change.value));
if (change.added) {
ret.push('</ins>');
} else if (change.removed) {
ret.push('</del>');
}
}
return ret.join('');
},
// See: http://code.google.com/p/google-diff-match-patch/wiki/API
convertChangesToDMP: function(changes){
var ret = [], change;
for ( var i = 0; i < changes.length; i++) {
change = changes[i];
ret.push([(change.added ? 1 : change.removed ? -1 : 0), change.value]);
}
return ret;
}
};
})();
if (typeof module !== 'undefined') {
module.exports = JsDiff;
}
}); // module: browser/diff.js
require.register("browser/events.js", function(module, exports, require){
/**
* Module exports.
*/
exports.EventEmitter = EventEmitter;
/**
* Check if `obj` is an array.
*/
function isArray(obj) {
return '[object Array]' == {}.toString.call(obj);
}
/**
* Event emitter constructor.
*
* @api public
*/
function EventEmitter(){};
/**
* Adds a listener.
*
* @api public
*/
EventEmitter.prototype.on = function (name, fn) {
if (!this.$events) {
this.$events = {};
}
if (!this.$events[name]) {
this.$events[name] = fn;
} else if (isArray(this.$events[name])) {
this.$events[name].push(fn);
} else {
this.$events[name] = [this.$events[name], fn];
}
return this;
};
EventEmitter.prototype.addListener = EventEmitter.prototype.on;
/**
* Adds a volatile listener.
*
* @api public
*/
EventEmitter.prototype.once = function (name, fn) {
var self = this;
function on () {
self.removeListener(name, on);
fn.apply(this, arguments);
};
on.listener = fn;
this.on(name, on);
return this;
};
/**
* Removes a listener.
*
* @api public
*/
EventEmitter.prototype.removeListener = function (name, fn) {
if (this.$events && this.$events[name]) {
var list = this.$events[name];
if (isArray(list)) {
var pos = -1;
for (var i = 0, l = list.length; i < l; i++) {
if (list[i] === fn || (list[i].listener && list[i].listener === fn)) {
pos = i;
break;
}
}
if (pos < 0) {
return this;
}
list.splice(pos, 1);
if (!list.length) {
delete this.$events[name];
}
} else if (list === fn || (list.listener && list.listener === fn)) {
delete this.$events[name];
}
}
return this;
};
/**
* Removes all listeners for an event.
*
* @api public
*/
EventEmitter.prototype.removeAllListeners = function (name) {
if (name === undefined) {
this.$events = {};
return this;
}
if (this.$events && this.$events[name]) {
this.$events[name] = null;
}
return this;
};
/**
* Gets all listeners for a certain event.
*
* @api public
*/
EventEmitter.prototype.listeners = function (name) {
if (!this.$events) {
this.$events = {};
}
if (!this.$events[name]) {
this.$events[name] = [];
}
if (!isArray(this.$events[name])) {
this.$events[name] = [this.$events[name]];
}
return this.$events[name];
};
/**
* Emits an event.
*
* @api public
*/
EventEmitter.prototype.emit = function (name) {
if (!this.$events) {
return false;
}
var handler = this.$events[name];
if (!handler) {
return false;
}
var args = [].slice.call(arguments, 1);
if ('function' == typeof handler) {
handler.apply(this, args);
} else if (isArray(handler)) {
var listeners = handler.slice();
for (var i = 0, l = listeners.length; i < l; i++) {
listeners[i].apply(this, args);
}
} else {
return false;
}
return true;
};
}); // module: browser/events.js
require.register("browser/fs.js", function(module, exports, require){
}); // module: browser/fs.js
require.register("browser/path.js", function(module, exports, require){
}); // module: browser/path.js
require.register("browser/progress.js", function(module, exports, require){
/**
* Expose `Progress`.
*/
module.exports = Progress;
/**
* Initialize a new `Progress` indicator.
*/
function Progress() {
this.percent = 0;
this.size(0);
this.fontSize(11);
this.font('helvetica, arial, sans-serif');
}
/**
* Set progress size to `n`.
*
* @param {Number} n
* @return {Progress} for chaining
* @api public
*/
Progress.prototype.size = function(n){
this._size = n;
return this;
};
/**
* Set text to `str`.
*
* @param {String} str
* @return {Progress} for chaining
* @api public
*/
Progress.prototype.text = function(str){
this._text = str;
return this;
};
/**
* Set font size to `n`.
*
* @param {Number} n
* @return {Progress} for chaining
* @api public
*/
Progress.prototype.fontSize = function(n){
this._fontSize = n;
return this;
};
/**
* Set font `family`.
*
* @param {String} family
* @return {Progress} for chaining
*/
Progress.prototype.font = function(family){
this._font = family;
return this;
};
/**
* Update percentage to `n`.
*
* @param {Number} n
* @return {Progress} for chaining
*/
Progress.prototype.update = function(n){
this.percent = n;
return this;
};
/**
* Draw on `ctx`.
*
* @param {CanvasRenderingContext2d} ctx
* @return {Progress} for chaining
*/
Progress.prototype.draw = function(ctx){
var percent = Math.min(this.percent, 100)
, size = this._size
, half = size / 2
, x = half
, y = half
, rad = half - 1
, fontSize = this._fontSize;
ctx.font = fontSize + 'px ' + this._font;
var angle = Math.PI * 2 * (percent / 100);
ctx.clearRect(0, 0, size, size);
// outer circle
ctx.strokeStyle = '#9f9f9f';
ctx.beginPath();
ctx.arc(x, y, rad, 0, angle, false);
ctx.stroke();
// inner circle
ctx.strokeStyle = '#eee';
ctx.beginPath();
ctx.arc(x, y, rad - 1, 0, angle, true);
ctx.stroke();
// text
var text = this._text || (percent | 0) + '%'
, w = ctx.measureText(text).width;
ctx.fillText(
text
, x - w / 2 + 1
, y + fontSize / 2 - 1);
return this;
};
}); // module: browser/progress.js
require.register("browser/tty.js", function(module, exports, require){
exports.isatty = function(){
return true;
};
exports.getWindowSize = function(){
if ('innerHeight' in global) {
return [global.innerHeight, global.innerWidth];
} else {
// In a Web Worker, the DOM Window is not available.
return [640, 480];
}
};
}); // module: browser/tty.js
require.register("context.js", function(module, exports, require){
/**
* Expose `Context`.
*/
module.exports = Context;
/**
* Initialize a new `Context`.
*
* @api private
*/
function Context(){}
/**
* Set or get the context `Runnable` to `runnable`.
*
* @param {Runnable} runnable
* @return {Context}
* @api private
*/
Context.prototype.runnable = function(runnable){
if (0 == arguments.length) return this._runnable;
this.test = this._runnable = runnable;
return this;
};
/**
* Set test timeout `ms`.
*
* @param {Number} ms
* @return {Context} self
* @api private
*/
Context.prototype.timeout = function(ms){
this.runnable().timeout(ms);
return this;
};
/**
* Set test slowness threshold `ms`.
*
* @param {Number} ms
* @return {Context} self
* @api private
*/
Context.prototype.slow = function(ms){
this.runnable().slow(ms);
return this;
};
/**
* Inspect the context void of `._runnable`.
*
* @return {String}
* @api private
*/
Context.prototype.inspect = function(){
return JSON.stringify(this, function(key, val){
if ('_runnable' == key) return;
if ('test' == key) return;
return val;
}, 2);
};
}); // module: context.js
require.register("hook.js", function(module, exports, require){
/**
* Module dependencies.
*/
var Runnable = require('./runnable');
/**
* Expose `Hook`.
*/
module.exports = Hook;
/**
* Initialize a new `Hook` with the given `title` and callback `fn`.
*
* @param {String} title
* @param {Function} fn
* @api private
*/
function Hook(title, fn) {
Runnable.call(this, title, fn);
this.type = 'hook';
}
/**
* Inherit from `Runnable.prototype`.
*/
function F(){};
F.prototype = Runnable.prototype;
Hook.prototype = new F;
Hook.prototype.constructor = Hook;
/**
* Get or set the test `err`.
*
* @param {Error} err
* @return {Error}
* @api public
*/
Hook.prototype.error = function(err){
if (0 == arguments.length) {
var err = this._error;
this._error = null;
return err;
}
this._error = err;
};
}); // module: hook.js
require.register("interfaces/bdd.js", function(module, exports, require){
/**
* Module dependencies.
*/
var Suite = require('../suite')
, Test = require('../test')
, utils = require('../utils');
/**
* BDD-style interface:
*
* describe('Array', function(){
* describe('#indexOf()', function(){
* it('should return -1 when not present', function(){
*
* });
*
* it('should return the index when present', function(){
*
* });
* });
* });
*
*/
module.exports = function(suite){
var suites = [suite];
suite.on('pre-require', function(context, file, mocha){
/**
* Execute before running tests.
*/
context.before = function(fn){
suites[0].beforeAll(fn);
};
/**
* Execute after running tests.
*/
context.after = function(fn){
suites[0].afterAll(fn);
};
/**
* Execute before each test case.
*/
context.beforeEach = function(fn){
suites[0].beforeEach(fn);
};
/**
* Execute after each test case.
*/
context.afterEach = function(fn){
suites[0].afterEach(fn);
};
/**
* Describe a "suite" with the given `title`
* and callback `fn` containing nested suites
* and/or tests.
*/
context.describe = context.context = function(title, fn){
var suite = Suite.create(suites[0], title);
suites.unshift(suite);
fn.call(suite);
suites.shift();
return suite;
};
/**
* Pending describe.
*/
context.xdescribe =
context.xcontext =
context.describe.skip = function(title, fn){
var suite = Suite.create(suites[0], title);
suite.pending = true;
suites.unshift(suite);
fn.call(suite);
suites.shift();
};
/**
* Exclusive suite.
*/
context.describe.only = function(title, fn){
var suite = context.describe(title, fn);
mocha.grep(suite.fullTitle());
return suite;
};
/**
* Describe a specification or test-case
* with the given `title` and callback `fn`
* acting as a thunk.
*/
context.it = context.specify = function(title, fn){
var suite = suites[0];
if (suite.pending) var fn = null;
var test = new Test(title, fn);
suite.addTest(test);
return test;
};
/**
* Exclusive test-case.
*/
context.it.only = function(title, fn){
var test = context.it(title, fn);
var reString = '^' + utils.escapeRegexp(test.fullTitle()) + '$';
mocha.grep(new RegExp(reString));
return test;
};
/**
* Pending test case.
*/
context.xit =
context.xspecify =
context.it.skip = function(title){
context.it(title);
};
});
};
}); // module: interfaces/bdd.js
require.register("interfaces/exports.js", function(module, exports, require){
/**
* Module dependencies.
*/
var Suite = require('../suite')
, Test = require('../test');
/**
* TDD-style interface:
*
* exports.Array = {
* '#indexOf()': {
* 'should return -1 when the value is not present': function(){
*
* },
*
* 'should return the correct index when the value is present': function(){
*
* }
* }
* };
*
*/
module.exports = function(suite){
var suites = [suite];
suite.on('require', visit);
function visit(obj) {
var suite;
for (var key in obj) {
if ('function' == typeof obj[key]) {
var fn = obj[key];
switch (key) {
case 'before':
suites[0].beforeAll(fn);
break;
case 'after':
suites[0].afterAll(fn);
break;
case 'beforeEach':
suites[0].beforeEach(fn);
break;
case 'afterEach':
suites[0].afterEach(fn);
break;
default:
suites[0].addTest(new Test(key, fn));
}
} else {
var suite = Suite.create(suites[0], key);
suites.unshift(suite);
visit(obj[key]);
suites.shift();
}
}
}
};
}); // module: interfaces/exports.js
require.register("interfaces/index.js", function(module, exports, require){
exports.bdd = require('./bdd');
exports.tdd = require('./tdd');
exports.qunit = require('./qunit');
exports.exports = require('./exports');
}); // module: interfaces/index.js
require.register("interfaces/qunit.js", function(module, exports, require){
/**
* Module dependencies.
*/
var Suite = require('../suite')
, Test = require('../test')
, utils = require('../utils');
/**
* QUnit-style interface:
*
* suite('Array');
*
* test('#length', function(){
* var arr = [1,2,3];
* ok(arr.length == 3);
* });
*
* test('#indexOf()', function(){
* var arr = [1,2,3];
* ok(arr.indexOf(1) == 0);
* ok(arr.indexOf(2) == 1);
* ok(arr.indexOf(3) == 2);
* });
*
* suite('String');
*
* test('#length', function(){
* ok('foo'.length == 3);
* });
*
*/
module.exports = function(suite){
var suites = [suite];
suite.on('pre-require', function(context, file, mocha){
/**
* Execute before running tests.
*/
context.before = function(fn){
suites[0].beforeAll(fn);
};
/**
* Execute after running tests.
*/
context.after = function(fn){
suites[0].afterAll(fn);
};
/**
* Execute before each test case.
*/
context.beforeEach = function(fn){
suites[0].beforeEach(fn);
};
/**
* Execute after each test case.
*/
context.afterEach = function(fn){
suites[0].afterEach(fn);
};
/**
* Describe a "suite" with the given `title`.
*/
context.suite = function(title){
if (suites.length > 1) suites.shift();
var suite = Suite.create(suites[0], title);
suites.unshift(suite);
return suite;
};
/**
* Exclusive test-case.
*/
context.suite.only = function(title, fn){
var suite = context.suite(title, fn);
mocha.grep(suite.fullTitle());
};
/**
* Describe a specification or test-case
* with the given `title` and callback `fn`
* acting as a thunk.
*/
context.test = function(title, fn){
var test = new Test(title, fn);
suites[0].addTest(test);
return test;
};
/**
* Exclusive test-case.
*/
context.test.only = function(title, fn){
var test = context.test(title, fn);
var reString = '^' + utils.escapeRegexp(test.fullTitle()) + '$';
mocha.grep(new RegExp(reString));
};
/**
* Pending test case.
*/
context.test.skip = function(title){
context.test(title);
};
});
};
}); // module: interfaces/qunit.js
require.register("interfaces/tdd.js", function(module, exports, require){
/**
* Module dependencies.
*/
var Suite = require('../suite')
, Test = require('../test')
, utils = require('../utils');;
/**
* TDD-style interface:
*
* suite('Array', function(){
* suite('#indexOf()', function(){
* suiteSetup(function(){
*
* });
*
* test('should return -1 when not present', function(){
*
* });
*
* test('should return the index when present', function(){
*
* });
*
* suiteTeardown(function(){
*
* });
* });
* });
*
*/
module.exports = function(suite){
var suites = [suite];
suite.on('pre-require', function(context, file, mocha){
/**
* Execute before each test case.
*/
context.setup = function(fn){
suites[0].beforeEach(fn);
};
/**
* Execute after each test case.
*/
context.teardown = function(fn){
suites[0].afterEach(fn);
};
/**
* Execute before the suite.
*/
context.suiteSetup = function(fn){
suites[0].beforeAll(fn);
};
/**
* Execute after the suite.
*/
context.suiteTeardown = function(fn){
suites[0].afterAll(fn);
};
/**
* Describe a "suite" with the given `title`
* and callback `fn` containing nested suites
* and/or tests.
*/
context.suite = function(title, fn){
var suite = Suite.create(suites[0], title);
suites.unshift(suite);
fn.call(suite);
suites.shift();
return suite;
};
/**
* Pending suite.
*/
context.suite.skip = function(title, fn) {
var suite = Suite.create(suites[0], title);
suite.pending = true;
suites.unshift(suite);
fn.call(suite);
suites.shift();
};
/**
* Exclusive test-case.
*/
context.suite.only = function(title, fn){
var suite = context.suite(title, fn);
mocha.grep(suite.fullTitle());
};
/**
* Describe a specification or test-case
* with the given `title` and callback `fn`
* acting as a thunk.
*/
context.test = function(title, fn){
var suite = suites[0];
if (suite.pending) var fn = null;
var test = new Test(title, fn);
suite.addTest(test);
return test;
};
/**
* Exclusive test-case.
*/
context.test.only = function(title, fn){
var test = context.test(title, fn);
var reString = '^' + utils.escapeRegexp(test.fullTitle()) + '$';
mocha.grep(new RegExp(reString));
};
/**
* Pending test case.
*/
context.test.skip = function(title){
context.test(title);
};
});
};
}); // module: interfaces/tdd.js
require.register("mocha.js", function(module, exports, require){
/*!
* mocha
* Copyright(c) 2011 TJ Holowaychuk <tj@vision-media.ca>
* MIT Licensed
*/
/**
* Module dependencies.
*/
var path = require('browser/path')
, utils = require('./utils');
/**
* Expose `Mocha`.
*/
exports = module.exports = Mocha;
/**
* Expose internals.
*/
exports.utils = utils;
exports.interfaces = require('./interfaces');
exports.reporters = require('./reporters');
exports.Runnable = require('./runnable');
exports.Context = require('./context');
exports.Runner = require('./runner');
exports.Suite = require('./suite');
exports.Hook = require('./hook');
exports.Test = require('./test');
/**
* Return image `name` path.
*
* @param {String} name
* @return {String}
* @api private
*/
function image(name) {
return __dirname + '/../images/' + name + '.png';
}
/**
* Setup mocha with `options`.
*
* Options:
*
* - `ui` name "bdd", "tdd", "exports" etc
* - `reporter` reporter instance, defaults to `mocha.reporters.Dot`
* - `globals` array of accepted globals
* - `timeout` timeout in milliseconds
* - `bail` bail on the first test failure
* - `slow` milliseconds to wait before considering a test slow
* - `ignoreLeaks` ignore global leaks
* - `grep` string or regexp to filter tests with
*
* @param {Object} options
* @api public
*/
function Mocha(options) {
options = options || {};
this.files = [];
this.options = options;
this.grep(options.grep);
this.suite = new exports.Suite('', new exports.Context);
this.ui(options.ui);
this.bail(options.bail);
this.reporter(options.reporter);
if (null != options.timeout) this.timeout(options.timeout);
this.useColors(options.useColors)
if (options.slow) this.slow(options.slow);
}
/**
* Enable or disable bailing on the first failure.
*
* @param {Boolean} [bail]
* @api public
*/
Mocha.prototype.bail = function(bail){
if (0 == arguments.length) bail = true;
this.suite.bail(bail);
return this;
};
/**
* Add test `file`.
*
* @param {String} file
* @api public
*/
Mocha.prototype.addFile = function(file){
this.files.push(file);
return this;
};
/**
* Set reporter to `reporter`, defaults to "dot".
*
* @param {String|Function} reporter name or constructor
* @api public
*/
Mocha.prototype.reporter = function(reporter){
if ('function' == typeof reporter) {
this._reporter = reporter;
} else {
reporter = reporter || 'dot';
var _reporter;
try { _reporter = require('./reporters/' + reporter); } catch (err) {};
if (!_reporter) try { _reporter = require(reporter); } catch (err) {};
if (!_reporter && reporter === 'teamcity')
console.warn('The Teamcity reporter was moved to a package named ' +
'mocha-teamcity-reporter ' +
'(https://npmjs.org/package/mocha-teamcity-reporter).');
if (!_reporter) throw new Error('invalid reporter "' + reporter + '"');
this._reporter = _reporter;
}
return this;
};
/**
* Set test UI `name`, defaults to "bdd".
*
* @param {String} bdd
* @api public
*/
Mocha.prototype.ui = function(name){
name = name || 'bdd';
this._ui = exports.interfaces[name];
if (!this._ui) try { this._ui = require(name); } catch (err) {};
if (!this._ui) throw new Error('invalid interface "' + name + '"');
this._ui = this._ui(this.suite);
return this;
};
/**
* Load registered files.
*
* @api private
*/
Mocha.prototype.loadFiles = function(fn){
var self = this;
var suite = this.suite;
var pending = this.files.length;
this.files.forEach(function(file){
file = path.resolve(file);
suite.emit('pre-require', global, file, self);
suite.emit('require', require(file), file, self);
suite.emit('post-require', global, file, self);
--pending || (fn && fn());
});
};
/**
* Enable growl support.
*
* @api private
*/
Mocha.prototype._growl = function(runner, reporter) {
var notify = require('growl');
runner.on('end', function(){
var stats = reporter.stats;
if (stats.failures) {
var msg = stats.failures + ' of ' + runner.total + ' tests failed';
notify(msg, { name: 'mocha', title: 'Failed', image: image('error') });
} else {
notify(stats.passes + ' tests passed in ' + stats.duration + 'ms', {
name: 'mocha'
, title: 'Passed'
, image: image('ok')
});
}
});
};
/**
* Add regexp to grep, if `re` is a string it is escaped.
*
* @param {RegExp|String} re
* @return {Mocha}
* @api public
*/
Mocha.prototype.grep = function(re){
this.options.grep = 'string' == typeof re
? new RegExp(utils.escapeRegexp(re))
: re;
return this;
};
/**
* Invert `.grep()` matches.
*
* @return {Mocha}
* @api public
*/
Mocha.prototype.invert = function(){
this.options.invert = true;
return this;
};
/**
* Ignore global leaks.
*
* @param {Boolean} ignore
* @return {Mocha}
* @api public
*/
Mocha.prototype.ignoreLeaks = function(ignore){
this.options.ignoreLeaks = !!ignore;
return this;
};
/**
* Enable global leak checking.
*
* @return {Mocha}
* @api public
*/
Mocha.prototype.checkLeaks = function(){
this.options.ignoreLeaks = false;
return this;
};
/**
* Enable growl support.
*
* @return {Mocha}
* @api public
*/
Mocha.prototype.growl = function(){
this.options.growl = true;
return this;
};
/**
* Ignore `globals` array or string.
*
* @param {Array|String} globals
* @return {Mocha}
* @api public
*/
Mocha.prototype.globals = function(globals){
this.options.globals = (this.options.globals || []).concat(globals);
return this;
};
/**
* Emit color output.
*
* @param {Boolean} colors
* @return {Mocha}
* @api public
*/
Mocha.prototype.useColors = function(colors){
this.options.useColors = arguments.length && colors != undefined
? colors
: true;
return this;
};
/**
* Set the timeout in milliseconds.
*
* @param {Number} timeout
* @return {Mocha}
* @api public
*/
Mocha.prototype.timeout = function(timeout){
this.suite.timeout(timeout);
return this;
};
/**
* Set slowness threshold in milliseconds.
*
* @param {Number} slow
* @return {Mocha}
* @api public
*/
Mocha.prototype.slow = function(slow){
this.suite.slow(slow);
return this;
};
/**
* Makes all tests async (accepting a callback)
*
* @return {Mocha}
* @api public
*/
Mocha.prototype.asyncOnly = function(){
this.options.asyncOnly = true;
return this;
};
/**
* Run tests and invoke `fn()` when complete.
*
* @param {Function} fn
* @return {Runner}
* @api public
*/
Mocha.prototype.run = function(fn){
if (this.files.length) this.loadFiles();
var suite = this.suite;
var options = this.options;
var runner = new exports.Runner(suite);
var reporter = new this._reporter(runner);
runner.ignoreLeaks = false !== options.ignoreLeaks;
runner.asyncOnly = options.asyncOnly;
if (options.grep) runner.grep(options.grep, options.invert);
if (options.globals) runner.globals(options.globals);
if (options.growl) this._growl(runner, reporter);
exports.reporters.Base.useColors = options.useColors;
return runner.run(fn);
};
}); // module: mocha.js
require.register("ms.js", function(module, exports, require){
/**
* Helpers.
*/
var s = 1000;
var m = s * 60;
var h = m * 60;
var d = h * 24;
var y = d * 365.25;
/**
* Parse or format the given `val`.
*
* Options:
*
* - `long` verbose formatting [false]
*
* @param {String|Number} val
* @param {Object} options
* @return {String|Number}
* @api public
*/
module.exports = function(val, options){
options = options || {};
if ('string' == typeof val) return parse(val);
return options.long
? long(val)
: short(val);
};
/**
* Parse the given `str` and return milliseconds.
*
* @param {String} str
* @return {Number}
* @api private
*/
function parse(str) {
var match = /^((?:\d+)?\.?\d+) *(ms|seconds?|s|minutes?|m|hours?|h|days?|d|years?|y)?$/i.exec(str);
if (!match) return;
var n = parseFloat(match[1]);
var type = (match[2] || 'ms').toLowerCase();
switch (type) {
case 'years':
case 'year':
case 'y':
return n * y;
case 'days':
case 'day':
case 'd':
return n * d;
case 'hours':
case 'hour':
case 'h':
return n * h;
case 'minutes':
case 'minute':
case 'm':
return n * m;
case 'seconds':
case 'second':
case 's':
return n * s;
case 'ms':
return n;
}
}
/**
* Short format for `ms`.
*
* @param {Number} ms
* @return {String}
* @api private
*/
function short(ms) {
if (ms >= d) return Math.round(ms / d) + 'd';
if (ms >= h) return Math.round(ms / h) + 'h';
if (ms >= m) return Math.round(ms / m) + 'm';
if (ms >= s) return Math.round(ms / s) + 's';
return ms + 'ms';
}
/**
* Long format for `ms`.
*
* @param {Number} ms
* @return {String}
* @api private
*/
function long(ms) {
return plural(ms, d, 'day')
|| plural(ms, h, 'hour')
|| plural(ms, m, 'minute')
|| plural(ms, s, 'second')
|| ms + ' ms';
}
/**
* Pluralization helper.
*/
function plural(ms, n, name) {
if (ms < n) return;
if (ms < n * 1.5) return Math.floor(ms / n) + ' ' + name;
return Math.ceil(ms / n) + ' ' + name + 's';
}
}); // module: ms.js
require.register("reporters/base.js", function(module, exports, require){
/**
* Module dependencies.
*/
var tty = require('browser/tty')
, diff = require('browser/diff')
, ms = require('../ms');
/**
* Save timer references to avoid Sinon interfering (see GH-237).
*/
var Date = global.Date
, setTimeout = global.setTimeout
, setInterval = global.setInterval
, clearTimeout = global.clearTimeout
, clearInterval = global.clearInterval;
/**
* Check if both stdio streams are associated with a tty.
*/
var isatty = tty.isatty(1) && tty.isatty(2);
/**
* Expose `Base`.
*/
exports = module.exports = Base;
/**
* Enable coloring by default.
*/
exports.useColors = isatty || (process.env.MOCHA_COLORS !== undefined);
/**
* Inline diffs instead of +/-
*/
exports.inlineDiffs = false;
/**
* Default color map.
*/
exports.colors = {
'pass': 90
, 'fail': 31
, 'bright pass': 92
, 'bright fail': 91
, 'bright yellow': 93
, 'pending': 36
, 'suite': 0
, 'error title': 0
, 'error message': 31
, 'error stack': 90
, 'checkmark': 32
, 'fast': 90
, 'medium': 33
, 'slow': 31
, 'green': 32
, 'light': 90
, 'diff gutter': 90
, 'diff added': 42
, 'diff removed': 41
};
/**
* Default symbol map.
*/
exports.symbols = {
ok: '✓',
err: '✖',
dot: '․'
};
// With node.js on Windows: use symbols available in terminal default fonts
if ('win32' == process.platform) {
exports.symbols.ok = '\u221A';
exports.symbols.err = '\u00D7';
exports.symbols.dot = '.';
}
/**
* Color `str` with the given `type`,
* allowing colors to be disabled,
* as well as user-defined color
* schemes.
*
* @param {String} type
* @param {String} str
* @return {String}
* @api private
*/
var color = exports.color = function(type, str) {
if (!exports.useColors) return str;
return '\u001b[' + exports.colors[type] + 'm' + str + '\u001b[0m';
};
/**
* Expose term window size, with some
* defaults for when stderr is not a tty.
*/
exports.window = {
width: isatty
? process.stdout.getWindowSize
? process.stdout.getWindowSize(1)[0]
: tty.getWindowSize()[1]
: 75
};
/**
* Expose some basic cursor interactions
* that are common among reporters.
*/
exports.cursor = {
hide: function(){
isatty && process.stdout.write('\u001b[?25l');
},
show: function(){
isatty && process.stdout.write('\u001b[?25h');
},
deleteLine: function(){
isatty && process.stdout.write('\u001b[2K');
},
beginningOfLine: function(){
isatty && process.stdout.write('\u001b[0G');
},
CR: function(){
if (isatty) {
exports.cursor.deleteLine();
exports.cursor.beginningOfLine();
} else {
process.stdout.write('\n');
}
}
};
/**
* Outut the given `failures` as a list.
*
* @param {Array} failures
* @api public
*/
exports.list = function(failures){
console.error();
failures.forEach(function(test, i){
// format
var fmt = color('error title', ' %s) %s:\n')
+ color('error message', ' %s')
+ color('error stack', '\n%s\n');
// msg
var err = test.err
, message = err.message || ''
, stack = err.stack || message
, index = stack.indexOf(message) + message.length
, msg = stack.slice(0, index)
, actual = err.actual
, expected = err.expected
, escape = true;
// uncaught
if (err.uncaught) {
msg = 'Uncaught ' + msg;
}
// explicitly show diff
if (err.showDiff && sameType(actual, expected)) {
escape = false;
err.actual = actual = stringify(actual);
err.expected = expected = stringify(expected);
}
// actual / expected diff
if ('string' == typeof actual && 'string' == typeof expected) {
fmt = color('error title', ' %s) %s:\n%s') + color('error stack', '\n%s\n');
var match = message.match(/^([^:]+): expected/);
msg = match ? '\n ' + color('error message', match[1]) : '';
if (exports.inlineDiffs) {
msg += inlineDiff(err, escape);
} else {
msg += unifiedDiff(err, escape);
}
}
// indent stack trace without msg
stack = stack.slice(index ? index + 1 : index)
.replace(/^/gm, ' ');
console.error(fmt, (i + 1), test.fullTitle(), msg, stack);
});
};
/**
* Initialize a new `Base` reporter.
*
* All other reporters generally
* inherit from this reporter, providing
* stats such as test duration, number
* of tests passed / failed etc.
*
* @param {Runner} runner
* @api public
*/
function Base(runner) {
var self = this
, stats = this.stats = { suites: 0, tests: 0, passes: 0, pending: 0, failures: 0 }
, failures = this.failures = [];
if (!runner) return;
this.runner = runner;
runner.stats = stats;
runner.on('start', function(){
stats.start = new Date;
});
runner.on('suite', function(suite){
stats.suites = stats.suites || 0;
suite.root || stats.suites++;
});
runner.on('test end', function(test){
stats.tests = stats.tests || 0;
stats.tests++;
});
runner.on('pass', function(test){
stats.passes = stats.passes || 0;
var medium = test.slow() / 2;
test.speed = test.duration > test.slow()
? 'slow'
: test.duration > medium
? 'medium'
: 'fast';
stats.passes++;
});
runner.on('fail', function(test, err){
stats.failures = stats.failures || 0;
stats.failures++;
test.err = err;
failures.push(test);
});
runner.on('end', function(){
stats.end = new Date;
stats.duration = new Date - stats.start;
});
runner.on('pending', function(){
stats.pending++;
});
}
/**
* Output common epilogue used by many of
* the bundled reporters.
*
* @api public
*/
Base.prototype.epilogue = function(){
var stats = this.stats;
var tests;
var fmt;
console.log();
// passes
fmt = color('bright pass', ' ')
+ color('green', ' %d passing')
+ color('light', ' (%s)');
console.log(fmt,
stats.passes || 0,
ms(stats.duration));
// pending
if (stats.pending) {
fmt = color('pending', ' ')
+ color('pending', ' %d pending');
console.log(fmt, stats.pending);
}
// failures
if (stats.failures) {
fmt = color('fail', ' %d failing');
console.error(fmt,
stats.failures);
Base.list(this.failures);
console.error();
}
console.log();
};
/**
* Pad the given `str` to `len`.
*
* @param {String} str
* @param {String} len
* @return {String}
* @api private
*/
function pad(str, len) {
str = String(str);
return Array(len - str.length + 1).join(' ') + str;
}
/**
* Returns an inline diff between 2 strings with coloured ANSI output
*
* @param {Error} Error with actual/expected
* @return {String} Diff
* @api private
*/
function inlineDiff(err, escape) {
var msg = errorDiff(err, 'WordsWithSpace', escape);
// linenos
var lines = msg.split('\n');
if (lines.length > 4) {
var width = String(lines.length).length;
msg = lines.map(function(str, i){
return pad(++i, width) + ' |' + ' ' + str;
}).join('\n');
}
// legend
msg = '\n'
+ color('diff removed', 'actual')
+ ' '
+ color('diff added', 'expected')
+ '\n\n'
+ msg
+ '\n';
// indent
msg = msg.replace(/^/gm, ' ');
return msg;
}
/**
* Returns a unified diff between 2 strings
*
* @param {Error} Error with actual/expected
* @return {String} Diff
* @api private
*/
function unifiedDiff(err, escape) {
var indent = ' ';
function cleanUp(line) {
if (escape) {
line = escapeInvisibles(line);
}
if (line[0] === '+') return indent + colorLines('diff added', line);
if (line[0] === '-') return indent + colorLines('diff removed', line);
if (line.match(/\@\@/)) return null;
if (line.match(/\\ No newline/)) return null;
else return indent + line;
}
function notBlank(line) {
return line != null;
}
msg = diff.createPatch('string', err.actual, err.expected);
var lines = msg.split('\n').splice(4);
return '\n '
+ colorLines('diff added', '+ expected') + ' '
+ colorLines('diff removed', '- actual')
+ '\n\n'
+ lines.map(cleanUp).filter(notBlank).join('\n');
}
/**
* Return a character diff for `err`.
*
* @param {Error} err
* @return {String}
* @api private
*/
function errorDiff(err, type, escape) {
var actual = escape ? escapeInvisibles(err.actual) : err.actual;
var expected = escape ? escapeInvisibles(err.expected) : err.expected;
return diff['diff' + type](actual, expected).map(function(str){
if (str.added) return colorLines('diff added', str.value);
if (str.removed) return colorLines('diff removed', str.value);
return str.value;
}).join('');
}
/**
* Returns a string with all invisible characters in plain text
*
* @param {String} line
* @return {String}
* @api private
*/
function escapeInvisibles(line) {
return line.replace(/\t/g, '<tab>')
.replace(/\r/g, '<CR>')
.replace(/\n/g, '<LF>\n');
}
/**
* Color lines for `str`, using the color `name`.
*
* @param {String} name
* @param {String} str
* @return {String}
* @api private
*/
function colorLines(name, str) {
return str.split('\n').map(function(str){
return color(name, str);
}).join('\n');
}
/**
* Stringify `obj`.
*
* @param {Mixed} obj
* @return {String}
* @api private
*/
function stringify(obj) {
if (obj instanceof RegExp) return obj.toString();
return JSON.stringify(obj, null, 2);
}
/**
* Check that a / b have the same type.
*
* @param {Object} a
* @param {Object} b
* @return {Boolean}
* @api private
*/
function sameType(a, b) {
a = Object.prototype.toString.call(a);
b = Object.prototype.toString.call(b);
return a == b;
}
}); // module: reporters/base.js
require.register("reporters/doc.js", function(module, exports, require){
/**
* Module dependencies.
*/
var Base = require('./base')
, utils = require('../utils');
/**
* Expose `Doc`.
*/
exports = module.exports = Doc;
/**
* Initialize a new `Doc` reporter.
*
* @param {Runner} runner
* @api public
*/
function Doc(runner) {
Base.call(this, runner);
var self = this
, stats = this.stats
, total = runner.total
, indents = 2;
function indent() {
return Array(indents).join(' ');
}
runner.on('suite', function(suite){
if (suite.root) return;
++indents;
console.log('%s<section class="suite">', indent());
++indents;
console.log('%s<h1>%s</h1>', indent(), utils.escape(suite.title));
console.log('%s<dl>', indent());
});
runner.on('suite end', function(suite){
if (suite.root) return;
console.log('%s</dl>', indent());
--indents;
console.log('%s</section>', indent());
--indents;
});
runner.on('pass', function(test){
console.log('%s <dt>%s</dt>', indent(), utils.escape(test.title));
var code = utils.escape(utils.clean(test.fn.toString()));
console.log('%s <dd><pre><code>%s</code></pre></dd>', indent(), code);
});
}
}); // module: reporters/doc.js
require.register("reporters/dot.js", function(module, exports, require){
/**
* Module dependencies.
*/
var Base = require('./base')
, color = Base.color;
/**
* Expose `Dot`.
*/
exports = module.exports = Dot;
/**
* Initialize a new `Dot` matrix test reporter.
*
* @param {Runner} runner
* @api public
*/
function Dot(runner) {
Base.call(this, runner);
var self = this
, stats = this.stats
, width = Base.window.width * .75 | 0
, n = 0;
runner.on('start', function(){
process.stdout.write('\n ');
});
runner.on('pending', function(test){
process.stdout.write(color('pending', Base.symbols.dot));
});
runner.on('pass', function(test){
if (++n % width == 0) process.stdout.write('\n ');
if ('slow' == test.speed) {
process.stdout.write(color('bright yellow', Base.symbols.dot));
} else {
process.stdout.write(color(test.speed, Base.symbols.dot));
}
});
runner.on('fail', function(test, err){
if (++n % width == 0) process.stdout.write('\n ');
process.stdout.write(color('fail', Base.symbols.dot));
});
runner.on('end', function(){
console.log();
self.epilogue();
});
}
/**
* Inherit from `Base.prototype`.
*/
function F(){};
F.prototype = Base.prototype;
Dot.prototype = new F;
Dot.prototype.constructor = Dot;
}); // module: reporters/dot.js
require.register("reporters/html-cov.js", function(module, exports, require){
/**
* Module dependencies.
*/
var JSONCov = require('./json-cov')
, fs = require('browser/fs');
/**
* Expose `HTMLCov`.
*/
exports = module.exports = HTMLCov;
/**
* Initialize a new `JsCoverage` reporter.
*
* @param {Runner} runner
* @api public
*/
function HTMLCov(runner) {
var jade = require('jade')
, file = __dirname + '/templates/coverage.jade'
, str = fs.readFileSync(file, 'utf8')
, fn = jade.compile(str, { filename: file })
, self = this;
JSONCov.call(this, runner, false);
runner.on('end', function(){
process.stdout.write(fn({
cov: self.cov
, coverageClass: coverageClass
}));
});
}
/**
* Return coverage class for `n`.
*
* @return {String}
* @api private
*/
function coverageClass(n) {
if (n >= 75) return 'high';
if (n >= 50) return 'medium';
if (n >= 25) return 'low';
return 'terrible';
}
}); // module: reporters/html-cov.js
require.register("reporters/html.js", function(module, exports, require){
/**
* Module dependencies.
*/
var Base = require('./base')
, utils = require('../utils')
, Progress = require('../browser/progress')
, escape = utils.escape;
/**
* Save timer references to avoid Sinon interfering (see GH-237).
*/
var Date = global.Date
, setTimeout = global.setTimeout
, setInterval = global.setInterval
, clearTimeout = global.clearTimeout
, clearInterval = global.clearInterval;
/**
* Expose `HTML`.
*/
exports = module.exports = HTML;
/**
* Stats template.
*/
var statsTemplate = '<ul id="mocha-stats">'
+ '<li class="progress"><canvas width="40" height="40"></canvas></li>'
+ '<li class="passes"><a href="#">passes:</a> <em>0</em></li>'
+ '<li class="failures"><a href="#">failures:</a> <em>0</em></li>'
+ '<li class="duration">duration: <em>0</em>s</li>'
+ '</ul>';
/**
* Initialize a new `HTML` reporter.
*
* @param {Runner} runner
* @api public
*/
function HTML(runner, root) {
Base.call(this, runner);
var self = this
, stats = this.stats
, total = runner.total
, stat = fragment(statsTemplate)
, items = stat.getElementsByTagName('li')
, passes = items[1].getElementsByTagName('em')[0]
, passesLink = items[1].getElementsByTagName('a')[0]
, failures = items[2].getElementsByTagName('em')[0]
, failuresLink = items[2].getElementsByTagName('a')[0]
, duration = items[3].getElementsByTagName('em')[0]
, canvas = stat.getElementsByTagName('canvas')[0]
, report = fragment('<ul id="mocha-report"></ul>')
, stack = [report]
, progress
, ctx
root = root || document.getElementById('mocha');
if (canvas.getContext) {
var ratio = window.devicePixelRatio || 1;
canvas.style.width = canvas.width;
canvas.style.height = canvas.height;
canvas.width *= ratio;
canvas.height *= ratio;
ctx = canvas.getContext('2d');
ctx.scale(ratio, ratio);
progress = new Progress;
}
if (!root) return error('#mocha div missing, add it to your document');
// pass toggle
on(passesLink, 'click', function(){
unhide();
var name = /pass/.test(report.className) ? '' : ' pass';
report.className = report.className.replace(/fail|pass/g, '') + name;
if (report.className.trim()) hideSuitesWithout('test pass');
});
// failure toggle
on(failuresLink, 'click', function(){
unhide();
var name = /fail/.test(report.className) ? '' : ' fail';
report.className = report.className.replace(/fail|pass/g, '') + name;
if (report.className.trim()) hideSuitesWithout('test fail');
});
root.appendChild(stat);
root.appendChild(report);
if (progress) progress.size(40);
runner.on('suite', function(suite){
if (suite.root) return;
// suite
var url = self.suiteURL(suite);
var el = fragment('<li class="suite"><h1><a href="%s">%s</a></h1></li>', url, escape(suite.title));
// container
stack[0].appendChild(el);
stack.unshift(document.createElement('ul'));
el.appendChild(stack[0]);
});
runner.on('suite end', function(suite){
if (suite.root) return;
stack.shift();
});
runner.on('fail', function(test, err){
if ('hook' == test.type) runner.emit('test end', test);
});
runner.on('test end', function(test){
// TODO: add to stats
var percent = stats.tests / this.total * 100 | 0;
if (progress) progress.update(percent).draw(ctx);
// update stats
var ms = new Date - stats.start;
text(passes, stats.passes);
text(failures, stats.failures);
text(duration, (ms / 1000).toFixed(2));
// test
if ('passed' == test.state) {
var url = self.testURL(test);
var el = fragment('<li class="test pass %e"><h2>%e<span class="duration">%ems</span> <a href="%s" class="replay">‣</a></h2></li>', test.speed, test.title, test.duration, url);
} else if (test.pending) {
var el = fragment('<li class="test pass pending"><h2>%e</h2></li>', test.title);
} else {
var el = fragment('<li class="test fail"><h2>%e <a href="?grep=%e" class="replay">‣</a></h2></li>', test.title, encodeURIComponent(test.fullTitle()));
var str = test.err.stack || test.err.toString();
// FF / Opera do not add the message
if (!~str.indexOf(test.err.message)) {
str = test.err.message + '\n' + str;
}
// <=IE7 stringifies to [Object Error]. Since it can be overloaded, we
// check for the result of the stringifying.
if ('[object Error]' == str) str = test.err.message;
// Safari doesn't give you a stack. Let's at least provide a source line.
if (!test.err.stack && test.err.sourceURL && test.err.line !== undefined) {
str += "\n(" + test.err.sourceURL + ":" + test.err.line + ")";
}
el.appendChild(fragment('<pre class="error">%e</pre>', str));
}
// toggle code
// TODO: defer
if (!test.pending) {
var h2 = el.getElementsByTagName('h2')[0];
on(h2, 'click', function(){
pre.style.display = 'none' == pre.style.display
? 'block'
: 'none';
});
var pre = fragment('<pre><code>%e</code></pre>', utils.clean(test.fn.toString()));
el.appendChild(pre);
pre.style.display = 'none';
}
// Don't call .appendChild if #mocha-report was already .shift()'ed off the stack.
if (stack[0]) stack[0].appendChild(el);
});
}
/**
* Provide suite URL
*
* @param {Object} [suite]
*/
HTML.prototype.suiteURL = function(suite){
return '?grep=' + encodeURIComponent(suite.fullTitle());
};
/**
* Provide test URL
*
* @param {Object} [test]
*/
HTML.prototype.testURL = function(test){
return '?grep=' + encodeURIComponent(test.fullTitle());
};
/**
* Display error `msg`.
*/
function error(msg) {
document.body.appendChild(fragment('<div id="mocha-error">%s</div>', msg));
}
/**
* Return a DOM fragment from `html`.
*/
function fragment(html) {
var args = arguments
, div = document.createElement('div')
, i = 1;
div.innerHTML = html.replace(/%([se])/g, function(_, type){
switch (type) {
case 's': return String(args[i++]);
case 'e': return escape(args[i++]);
}
});
return div.firstChild;
}
/**
* Check for suites that do not have elements
* with `classname`, and hide them.
*/
function hideSuitesWithout(classname) {
var suites = document.getElementsByClassName('suite');
for (var i = 0; i < suites.length; i++) {
var els = suites[i].getElementsByClassName(classname);
if (0 == els.length) suites[i].className += ' hidden';
}
}
/**
* Unhide .hidden suites.
*/
function unhide() {
var els = document.getElementsByClassName('suite hidden');
for (var i = 0; i < els.length; ++i) {
els[i].className = els[i].className.replace('suite hidden', 'suite');
}
}
/**
* Set `el` text to `str`.
*/
function text(el, str) {
if (el.textContent) {
el.textContent = str;
} else {
el.innerText = str;
}
}
/**
* Listen on `event` with callback `fn`.
*/
function on(el, event, fn) {
if (el.addEventListener) {
el.addEventListener(event, fn, false);
} else {
el.attachEvent('on' + event, fn);
}
}
}); // module: reporters/html.js
require.register("reporters/index.js", function(module, exports, require){
exports.Base = require('./base');
exports.Dot = require('./dot');
exports.Doc = require('./doc');
exports.TAP = require('./tap');
exports.JSON = require('./json');
exports.HTML = require('./html');
exports.List = require('./list');
exports.Min = require('./min');
exports.Spec = require('./spec');
exports.Nyan = require('./nyan');
exports.XUnit = require('./xunit');
exports.Markdown = require('./markdown');
exports.Progress = require('./progress');
exports.Landing = require('./landing');
exports.JSONCov = require('./json-cov');
exports.HTMLCov = require('./html-cov');
exports.JSONStream = require('./json-stream');
}); // module: reporters/index.js
require.register("reporters/json-cov.js", function(module, exports, require){
/**
* Module dependencies.
*/
var Base = require('./base');
/**
* Expose `JSONCov`.
*/
exports = module.exports = JSONCov;
/**
* Initialize a new `JsCoverage` reporter.
*
* @param {Runner} runner
* @param {Boolean} output
* @api public
*/
function JSONCov(runner, output) {
var self = this
, output = 1 == arguments.length ? true : output;
Base.call(this, runner);
var tests = []
, failures = []
, passes = [];
runner.on('test end', function(test){
tests.push(test);
});
runner.on('pass', function(test){
passes.push(test);
});
runner.on('fail', function(test){
failures.push(test);
});
runner.on('end', function(){
var cov = global._$jscoverage || {};
var result = self.cov = map(cov);
result.stats = self.stats;
result.tests = tests.map(clean);
result.failures = failures.map(clean);
result.passes = passes.map(clean);
if (!output) return;
process.stdout.write(JSON.stringify(result, null, 2 ));
});
}
/**
* Map jscoverage data to a JSON structure
* suitable for reporting.
*
* @param {Object} cov
* @return {Object}
* @api private
*/
function map(cov) {
var ret = {
instrumentation: 'node-jscoverage'
, sloc: 0
, hits: 0
, misses: 0
, coverage: 0
, files: []
};
for (var filename in cov) {
var data = coverage(filename, cov[filename]);
ret.files.push(data);
ret.hits += data.hits;
ret.misses += data.misses;
ret.sloc += data.sloc;
}
ret.files.sort(function(a, b) {
return a.filename.localeCompare(b.filename);
});
if (ret.sloc > 0) {
ret.coverage = (ret.hits / ret.sloc) * 100;
}
return ret;
};
/**
* Map jscoverage data for a single source file
* to a JSON structure suitable for reporting.
*
* @param {String} filename name of the source file
* @param {Object} data jscoverage coverage data
* @return {Object}
* @api private
*/
function coverage(filename, data) {
var ret = {
filename: filename,
coverage: 0,
hits: 0,
misses: 0,
sloc: 0,
source: {}
};
data.source.forEach(function(line, num){
num++;
if (data[num] === 0) {
ret.misses++;
ret.sloc++;
} else if (data[num] !== undefined) {
ret.hits++;
ret.sloc++;
}
ret.source[num] = {
source: line
, coverage: data[num] === undefined
? ''
: data[num]
};
});
ret.coverage = ret.hits / ret.sloc * 100;
return ret;
}
/**
* Return a plain-object representation of `test`
* free of cyclic properties etc.
*
* @param {Object} test
* @return {Object}
* @api private
*/
function clean(test) {
return {
title: test.title
, fullTitle: test.fullTitle()
, duration: test.duration
}
}
}); // module: reporters/json-cov.js
require.register("reporters/json-stream.js", function(module, exports, require){
/**
* Module dependencies.
*/
var Base = require('./base')
, color = Base.color;
/**
* Expose `List`.
*/
exports = module.exports = List;
/**
* Initialize a new `List` test reporter.
*
* @param {Runner} runner
* @api public
*/
function List(runner) {
Base.call(this, runner);
var self = this
, stats = this.stats
, total = runner.total;
runner.on('start', function(){
console.log(JSON.stringify(['start', { total: total }]));
});
runner.on('pass', function(test){
console.log(JSON.stringify(['pass', clean(test)]));
});
runner.on('fail', function(test, err){
console.log(JSON.stringify(['fail', clean(test)]));
});
runner.on('end', function(){
process.stdout.write(JSON.stringify(['end', self.stats]));
});
}
/**
* Return a plain-object representation of `test`
* free of cyclic properties etc.
*
* @param {Object} test
* @return {Object}
* @api private
*/
function clean(test) {
return {
title: test.title
, fullTitle: test.fullTitle()
, duration: test.duration
}
}
}); // module: reporters/json-stream.js
require.register("reporters/json.js", function(module, exports, require){
/**
* Module dependencies.
*/
var Base = require('./base')
, cursor = Base.cursor
, color = Base.color;
/**
* Expose `JSON`.
*/
exports = module.exports = JSONReporter;
/**
* Initialize a new `JSON` reporter.
*
* @param {Runner} runner
* @api public
*/
function JSONReporter(runner) {
var self = this;
Base.call(this, runner);
var tests = []
, failures = []
, passes = [];
runner.on('test end', function(test){
tests.push(test);
});
runner.on('pass', function(test){
passes.push(test);
});
runner.on('fail', function(test){
failures.push(test);
});
runner.on('end', function(){
var obj = {
stats: self.stats
, tests: tests.map(clean)
, failures: failures.map(clean)
, passes: passes.map(clean)
};
process.stdout.write(JSON.stringify(obj, null, 2));
});
}
/**
* Return a plain-object representation of `test`
* free of cyclic properties etc.
*
* @param {Object} test
* @return {Object}
* @api private
*/
function clean(test) {
return {
title: test.title
, fullTitle: test.fullTitle()
, duration: test.duration
}
}
}); // module: reporters/json.js
require.register("reporters/landing.js", function(module, exports, require){
/**
* Module dependencies.
*/
var Base = require('./base')
, cursor = Base.cursor
, color = Base.color;
/**
* Expose `Landing`.
*/
exports = module.exports = Landing;
/**
* Airplane color.
*/
Base.colors.plane = 0;
/**
* Airplane crash color.
*/
Base.colors['plane crash'] = 31;
/**
* Runway color.
*/
Base.colors.runway = 90;
/**
* Initialize a new `Landing` reporter.
*
* @param {Runner} runner
* @api public
*/
function Landing(runner) {
Base.call(this, runner);
var self = this
, stats = this.stats
, width = Base.window.width * .75 | 0
, total = runner.total
, stream = process.stdout
, plane = color('plane', '✈')
, crashed = -1
, n = 0;
function runway() {
var buf = Array(width).join('-');
return ' ' + color('runway', buf);
}
runner.on('start', function(){
stream.write('\n ');
cursor.hide();
});
runner.on('test end', function(test){
// check if the plane crashed
var col = -1 == crashed
? width * ++n / total | 0
: crashed;
// show the crash
if ('failed' == test.state) {
plane = color('plane crash', '✈');
crashed = col;
}
// render landing strip
stream.write('\u001b[4F\n\n');
stream.write(runway());
stream.write('\n ');
stream.write(color('runway', Array(col).join('⋅')));
stream.write(plane)
stream.write(color('runway', Array(width - col).join('⋅') + '\n'));
stream.write(runway());
stream.write('\u001b[0m');
});
runner.on('end', function(){
cursor.show();
console.log();
self.epilogue();
});
}
/**
* Inherit from `Base.prototype`.
*/
function F(){};
F.prototype = Base.prototype;
Landing.prototype = new F;
Landing.prototype.constructor = Landing;
}); // module: reporters/landing.js
require.register("reporters/list.js", function(module, exports, require){
/**
* Module dependencies.
*/
var Base = require('./base')
, cursor = Base.cursor
, color = Base.color;
/**
* Expose `List`.
*/
exports = module.exports = List;
/**
* Initialize a new `List` test reporter.
*
* @param {Runner} runner
* @api public
*/
function List(runner) {
Base.call(this, runner);
var self = this
, stats = this.stats
, n = 0;
runner.on('start', function(){
console.log();
});
runner.on('test', function(test){
process.stdout.write(color('pass', ' ' + test.fullTitle() + ': '));
});
runner.on('pending', function(test){
var fmt = color('checkmark', ' -')
+ color('pending', ' %s');
console.log(fmt, test.fullTitle());
});
runner.on('pass', function(test){
var fmt = color('checkmark', ' '+Base.symbols.dot)
+ color('pass', ' %s: ')
+ color(test.speed, '%dms');
cursor.CR();
console.log(fmt, test.fullTitle(), test.duration);
});
runner.on('fail', function(test, err){
cursor.CR();
console.log(color('fail', ' %d) %s'), ++n, test.fullTitle());
});
runner.on('end', self.epilogue.bind(self));
}
/**
* Inherit from `Base.prototype`.
*/
function F(){};
F.prototype = Base.prototype;
List.prototype = new F;
List.prototype.constructor = List;
}); // module: reporters/list.js
require.register("reporters/markdown.js", function(module, exports, require){
/**
* Module dependencies.
*/
var Base = require('./base')
, utils = require('../utils');
/**
* Expose `Markdown`.
*/
exports = module.exports = Markdown;
/**
* Initialize a new `Markdown` reporter.
*
* @param {Runner} runner
* @api public
*/
function Markdown(runner) {
Base.call(this, runner);
var self = this
, stats = this.stats
, level = 0
, buf = '';
function title(str) {
return Array(level).join('#') + ' ' + str;
}
function indent() {
return Array(level).join(' ');
}
function mapTOC(suite, obj) {
var ret = obj;
obj = obj[suite.title] = obj[suite.title] || { suite: suite };
suite.suites.forEach(function(suite){
mapTOC(suite, obj);
});
return ret;
}
function stringifyTOC(obj, level) {
++level;
var buf = '';
var link;
for (var key in obj) {
if ('suite' == key) continue;
if (key) link = ' - [' + key + '](#' + utils.slug(obj[key].suite.fullTitle()) + ')\n';
if (key) buf += Array(level).join(' ') + link;
buf += stringifyTOC(obj[key], level);
}
--level;
return buf;
}
function generateTOC(suite) {
var obj = mapTOC(suite, {});
return stringifyTOC(obj, 0);
}
generateTOC(runner.suite);
runner.on('suite', function(suite){
++level;
var slug = utils.slug(suite.fullTitle());
buf += '<a name="' + slug + '"></a>' + '\n';
buf += title(suite.title) + '\n';
});
runner.on('suite end', function(suite){
--level;
});
runner.on('pass', function(test){
var code = utils.clean(test.fn.toString());
buf += test.title + '.\n';
buf += '\n```js\n';
buf += code + '\n';
buf += '```\n\n';
});
runner.on('end', function(){
process.stdout.write('# TOC\n');
process.stdout.write(generateTOC(runner.suite));
process.stdout.write(buf);
});
}
}); // module: reporters/markdown.js
require.register("reporters/min.js", function(module, exports, require){
/**
* Module dependencies.
*/
var Base = require('./base');
/**
* Expose `Min`.
*/
exports = module.exports = Min;
/**
* Initialize a new `Min` minimal test reporter (best used with --watch).
*
* @param {Runner} runner
* @api public
*/
function Min(runner) {
Base.call(this, runner);
runner.on('start', function(){
// clear screen
process.stdout.write('\u001b[2J');
// set cursor position
process.stdout.write('\u001b[1;3H');
});
runner.on('end', this.epilogue.bind(this));
}
/**
* Inherit from `Base.prototype`.
*/
function F(){};
F.prototype = Base.prototype;
Min.prototype = new F;
Min.prototype.constructor = Min;
}); // module: reporters/min.js
require.register("reporters/nyan.js", function(module, exports, require){
/**
* Module dependencies.
*/
var Base = require('./base')
, color = Base.color;
/**
* Expose `Dot`.
*/
exports = module.exports = NyanCat;
/**
* Initialize a new `Dot` matrix test reporter.
*
* @param {Runner} runner
* @api public
*/
function NyanCat(runner) {
Base.call(this, runner);
var self = this
, stats = this.stats
, width = Base.window.width * .75 | 0
, rainbowColors = this.rainbowColors = self.generateColors()
, colorIndex = this.colorIndex = 0
, numerOfLines = this.numberOfLines = 4
, trajectories = this.trajectories = [[], [], [], []]
, nyanCatWidth = this.nyanCatWidth = 11
, trajectoryWidthMax = this.trajectoryWidthMax = (width - nyanCatWidth)
, scoreboardWidth = this.scoreboardWidth = 5
, tick = this.tick = 0
, n = 0;
runner.on('start', function(){
Base.cursor.hide();
self.draw();
});
runner.on('pending', function(test){
self.draw();
});
runner.on('pass', function(test){
self.draw();
});
runner.on('fail', function(test, err){
self.draw();
});
runner.on('end', function(){
Base.cursor.show();
for (var i = 0; i < self.numberOfLines; i++) write('\n');
self.epilogue();
});
}
/**
* Draw the nyan cat
*
* @api private
*/
NyanCat.prototype.draw = function(){
this.appendRainbow();
this.drawScoreboard();
this.drawRainbow();
this.drawNyanCat();
this.tick = !this.tick;
};
/**
* Draw the "scoreboard" showing the number
* of passes, failures and pending tests.
*
* @api private
*/
NyanCat.prototype.drawScoreboard = function(){
var stats = this.stats;
var colors = Base.colors;
function draw(color, n) {
write(' ');
write('\u001b[' + color + 'm' + n + '\u001b[0m');
write('\n');
}
draw(colors.green, stats.passes);
draw(colors.fail, stats.failures);
draw(colors.pending, stats.pending);
write('\n');
this.cursorUp(this.numberOfLines);
};
/**
* Append the rainbow.
*
* @api private
*/
NyanCat.prototype.appendRainbow = function(){
var segment = this.tick ? '_' : '-';
var rainbowified = this.rainbowify(segment);
for (var index = 0; index < this.numberOfLines; index++) {
var trajectory = this.trajectories[index];
if (trajectory.length >= this.trajectoryWidthMax) trajectory.shift();
trajectory.push(rainbowified);
}
};
/**
* Draw the rainbow.
*
* @api private
*/
NyanCat.prototype.drawRainbow = function(){
var self = this;
this.trajectories.forEach(function(line, index) {
write('\u001b[' + self.scoreboardWidth + 'C');
write(line.join(''));
write('\n');
});
this.cursorUp(this.numberOfLines);
};
/**
* Draw the nyan cat
*
* @api private
*/
NyanCat.prototype.drawNyanCat = function() {
var self = this;
var startWidth = this.scoreboardWidth + this.trajectories[0].length;
var color = '\u001b[' + startWidth + 'C';
var padding = '';
write(color);
write('_,------,');
write('\n');
write(color);
padding = self.tick ? ' ' : ' ';
write('_|' + padding + '/\\_/\\ ');
write('\n');
write(color);
padding = self.tick ? '_' : '__';
var tail = self.tick ? '~' : '^';
var face;
write(tail + '|' + padding + this.face() + ' ');
write('\n');
write(color);
padding = self.tick ? ' ' : ' ';
write(padding + '"" "" ');
write('\n');
this.cursorUp(this.numberOfLines);
};
/**
* Draw nyan cat face.
*
* @return {String}
* @api private
*/
NyanCat.prototype.face = function() {
var stats = this.stats;
if (stats.failures) {
return '( x .x)';
} else if (stats.pending) {
return '( o .o)';
} else if(stats.passes) {
return '( ^ .^)';
} else {
return '( - .-)';
}
}
/**
* Move cursor up `n`.
*
* @param {Number} n
* @api private
*/
NyanCat.prototype.cursorUp = function(n) {
write('\u001b[' + n + 'A');
};
/**
* Move cursor down `n`.
*
* @param {Number} n
* @api private
*/
NyanCat.prototype.cursorDown = function(n) {
write('\u001b[' + n + 'B');
};
/**
* Generate rainbow colors.
*
* @return {Array}
* @api private
*/
NyanCat.prototype.generateColors = function(){
var colors = [];
for (var i = 0; i < (6 * 7); i++) {
var pi3 = Math.floor(Math.PI / 3);
var n = (i * (1.0 / 6));
var r = Math.floor(3 * Math.sin(n) + 3);
var g = Math.floor(3 * Math.sin(n + 2 * pi3) + 3);
var b = Math.floor(3 * Math.sin(n + 4 * pi3) + 3);
colors.push(36 * r + 6 * g + b + 16);
}
return colors;
};
/**
* Apply rainbow to the given `str`.
*
* @param {String} str
* @return {String}
* @api private
*/
NyanCat.prototype.rainbowify = function(str){
var color = this.rainbowColors[this.colorIndex % this.rainbowColors.length];
this.colorIndex += 1;
return '\u001b[38;5;' + color + 'm' + str + '\u001b[0m';
};
/**
* Stdout helper.
*/
function write(string) {
process.stdout.write(string);
}
/**
* Inherit from `Base.prototype`.
*/
function F(){};
F.prototype = Base.prototype;
NyanCat.prototype = new F;
NyanCat.prototype.constructor = NyanCat;
}); // module: reporters/nyan.js
require.register("reporters/progress.js", function(module, exports, require){
/**
* Module dependencies.
*/
var Base = require('./base')
, cursor = Base.cursor
, color = Base.color;
/**
* Expose `Progress`.
*/
exports = module.exports = Progress;
/**
* General progress bar color.
*/
Base.colors.progress = 90;
/**
* Initialize a new `Progress` bar test reporter.
*
* @param {Runner} runner
* @param {Object} options
* @api public
*/
function Progress(runner, options) {
Base.call(this, runner);
var self = this
, options = options || {}
, stats = this.stats
, width = Base.window.width * .50 | 0
, total = runner.total
, complete = 0
, max = Math.max;
// default chars
options.open = options.open || '[';
options.complete = options.complete || '▬';
options.incomplete = options.incomplete || Base.symbols.dot;
options.close = options.close || ']';
options.verbose = false;
// tests started
runner.on('start', function(){
console.log();
cursor.hide();
});
// tests complete
runner.on('test end', function(){
complete++;
var incomplete = total - complete
, percent = complete / total
, n = width * percent | 0
, i = width - n;
cursor.CR();
process.stdout.write('\u001b[J');
process.stdout.write(color('progress', ' ' + options.open));
process.stdout.write(Array(n).join(options.complete));
process.stdout.write(Array(i).join(options.incomplete));
process.stdout.write(color('progress', options.close));
if (options.verbose) {
process.stdout.write(color('progress', ' ' + complete + ' of ' + total));
}
});
// tests are complete, output some stats
// and the failures if any
runner.on('end', function(){
cursor.show();
console.log();
self.epilogue();
});
}
/**
* Inherit from `Base.prototype`.
*/
function F(){};
F.prototype = Base.prototype;
Progress.prototype = new F;
Progress.prototype.constructor = Progress;
}); // module: reporters/progress.js
require.register("reporters/spec.js", function(module, exports, require){
/**
* Module dependencies.
*/
var Base = require('./base')
, cursor = Base.cursor
, color = Base.color;
/**
* Expose `Spec`.
*/
exports = module.exports = Spec;
/**
* Initialize a new `Spec` test reporter.
*
* @param {Runner} runner
* @api public
*/
function Spec(runner) {
Base.call(this, runner);
var self = this
, stats = this.stats
, indents = 0
, n = 0;
function indent() {
return Array(indents).join(' ')
}
runner.on('start', function(){
console.log();
});
runner.on('suite', function(suite){
++indents;
console.log(color('suite', '%s%s'), indent(), suite.title);
});
runner.on('suite end', function(suite){
--indents;
if (1 == indents) console.log();
});
runner.on('test', function(test){
process.stdout.write(indent() + color('pass', ' ◦ ' + test.title + ': '));
});
runner.on('pending', function(test){
var fmt = indent() + color('pending', ' - %s');
console.log(fmt, test.title);
});
runner.on('pass', function(test){
if ('fast' == test.speed) {
var fmt = indent()
+ color('checkmark', ' ' + Base.symbols.ok)
+ color('pass', ' %s ');
cursor.CR();
console.log(fmt, test.title);
} else {
var fmt = indent()
+ color('checkmark', ' ' + Base.symbols.ok)
+ color('pass', ' %s ')
+ color(test.speed, '(%dms)');
cursor.CR();
console.log(fmt, test.title, test.duration);
}
});
runner.on('fail', function(test, err){
cursor.CR();
console.log(indent() + color('fail', ' %d) %s'), ++n, test.title);
});
runner.on('end', self.epilogue.bind(self));
}
/**
* Inherit from `Base.prototype`.
*/
function F(){};
F.prototype = Base.prototype;
Spec.prototype = new F;
Spec.prototype.constructor = Spec;
}); // module: reporters/spec.js
require.register("reporters/tap.js", function(module, exports, require){
/**
* Module dependencies.
*/
var Base = require('./base')
, cursor = Base.cursor
, color = Base.color;
/**
* Expose `TAP`.
*/
exports = module.exports = TAP;
/**
* Initialize a new `TAP` reporter.
*
* @param {Runner} runner
* @api public
*/
function TAP(runner) {
Base.call(this, runner);
var self = this
, stats = this.stats
, n = 1
, passes = 0
, failures = 0;
runner.on('start', function(){
var total = runner.grepTotal(runner.suite);
console.log('%d..%d', 1, total);
});
runner.on('test end', function(){
++n;
});
runner.on('pending', function(test){
console.log('ok %d %s # SKIP -', n, title(test));
});
runner.on('pass', function(test){
passes++;
console.log('ok %d %s', n, title(test));
});
runner.on('fail', function(test, err){
failures++;
console.log('not ok %d %s', n, title(test));
if (err.stack) console.log(err.stack.replace(/^/gm, ' '));
});
runner.on('end', function(){
console.log('# tests ' + (passes + failures));
console.log('# pass ' + passes);
console.log('# fail ' + failures);
});
}
/**
* Return a TAP-safe title of `test`
*
* @param {Object} test
* @return {String}
* @api private
*/
function title(test) {
return test.fullTitle().replace(/#/g, '');
}
}); // module: reporters/tap.js
require.register("reporters/xunit.js", function(module, exports, require){
/**
* Module dependencies.
*/
var Base = require('./base')
, utils = require('../utils')
, escape = utils.escape;
/**
* Save timer references to avoid Sinon interfering (see GH-237).
*/
var Date = global.Date
, setTimeout = global.setTimeout
, setInterval = global.setInterval
, clearTimeout = global.clearTimeout
, clearInterval = global.clearInterval;
/**
* Expose `XUnit`.
*/
exports = module.exports = XUnit;
/**
* Initialize a new `XUnit` reporter.
*
* @param {Runner} runner
* @api public
*/
function XUnit(runner) {
Base.call(this, runner);
var stats = this.stats
, tests = []
, self = this;
runner.on('pass', function(test){
tests.push(test);
});
runner.on('fail', function(test){
tests.push(test);
});
runner.on('end', function(){
console.log(tag('testsuite', {
name: 'Mocha Tests'
, tests: stats.tests
, failures: stats.failures
, errors: stats.failures
, skipped: stats.tests - stats.failures - stats.passes
, timestamp: (new Date).toUTCString()
, time: (stats.duration / 1000) || 0
}, false));
tests.forEach(test);
console.log('</testsuite>');
});
}
/**
* Inherit from `Base.prototype`.
*/
function F(){};
F.prototype = Base.prototype;
XUnit.prototype = new F;
XUnit.prototype.constructor = XUnit;
/**
* Output tag for the given `test.`
*/
function test(test) {
var attrs = {
classname: test.parent.fullTitle()
, name: test.title
, time: test.duration / 1000
};
if ('failed' == test.state) {
var err = test.err;
attrs.message = escape(err.message);
console.log(tag('testcase', attrs, false, tag('failure', attrs, false, cdata(err.stack))));
} else if (test.pending) {
console.log(tag('testcase', attrs, false, tag('skipped', {}, true)));
} else {
console.log(tag('testcase', attrs, true) );
}
}
/**
* HTML tag helper.
*/
function tag(name, attrs, close, content) {
var end = close ? '/>' : '>'
, pairs = []
, tag;
for (var key in attrs) {
pairs.push(key + '="' + escape(attrs[key]) + '"');
}
tag = '<' + name + (pairs.length ? ' ' + pairs.join(' ') : '') + end;
if (content) tag += content + '</' + name + end;
return tag;
}
/**
* Return cdata escaped CDATA `str`.
*/
function cdata(str) {
return '<![CDATA[' + escape(str) + ']]>';
}
}); // module: reporters/xunit.js
require.register("runnable.js", function(module, exports, require){
/**
* Module dependencies.
*/
var EventEmitter = require('browser/events').EventEmitter
, debug = require('browser/debug')('mocha:runnable')
, milliseconds = require('./ms');
/**
* Save timer references to avoid Sinon interfering (see GH-237).
*/
var Date = global.Date
, setTimeout = global.setTimeout
, setInterval = global.setInterval
, clearTimeout = global.clearTimeout
, clearInterval = global.clearInterval;
/**
* Object#toString().
*/
var toString = Object.prototype.toString;
/**
* Expose `Runnable`.
*/
module.exports = Runnable;
/**
* Initialize a new `Runnable` with the given `title` and callback `fn`.
*
* @param {String} title
* @param {Function} fn
* @api private
*/
function Runnable(title, fn) {
this.title = title;
this.fn = fn;
this.async = fn && fn.length;
this.sync = ! this.async;
this._timeout = 2000;
this._slow = 75;
this.timedOut = false;
}
/**
* Inherit from `EventEmitter.prototype`.
*/
function F(){};
F.prototype = EventEmitter.prototype;
Runnable.prototype = new F;
Runnable.prototype.constructor = Runnable;
/**
* Set & get timeout `ms`.
*
* @param {Number|String} ms
* @return {Runnable|Number} ms or self
* @api private
*/
Runnable.prototype.timeout = function(ms){
if (0 == arguments.length) return this._timeout;
if ('string' == typeof ms) ms = milliseconds(ms);
debug('timeout %d', ms);
this._timeout = ms;
if (this.timer) this.resetTimeout();
return this;
};
/**
* Set & get slow `ms`.
*
* @param {Number|String} ms
* @return {Runnable|Number} ms or self
* @api private
*/
Runnable.prototype.slow = function(ms){
if (0 === arguments.length) return this._slow;
if ('string' == typeof ms) ms = milliseconds(ms);
debug('timeout %d', ms);
this._slow = ms;
return this;
};
/**
* Return the full title generated by recursively
* concatenating the parent's full title.
*
* @return {String}
* @api public
*/
Runnable.prototype.fullTitle = function(){
return this.parent.fullTitle() + ' ' + this.title;
};
/**
* Clear the timeout.
*
* @api private
*/
Runnable.prototype.clearTimeout = function(){
clearTimeout(this.timer);
};
/**
* Inspect the runnable void of private properties.
*
* @return {String}
* @api private
*/
Runnable.prototype.inspect = function(){
return JSON.stringify(this, function(key, val){
if ('_' == key[0]) return;
if ('parent' == key) return '#<Suite>';
if ('ctx' == key) return '#<Context>';
return val;
}, 2);
};
/**
* Reset the timeout.
*
* @api private
*/
Runnable.prototype.resetTimeout = function(){
var self = this;
var ms = this.timeout() || 1e9;
this.clearTimeout();
this.timer = setTimeout(function(){
self.callback(new Error('timeout of ' + ms + 'ms exceeded'));
self.timedOut = true;
}, ms);
};
/**
* Run the test and invoke `fn(err)`.
*
* @param {Function} fn
* @api private
*/
Runnable.prototype.run = function(fn){
var self = this
, ms = this.timeout()
, start = new Date
, ctx = this.ctx
, finished
, emitted;
if (ctx) ctx.runnable(this);
// timeout
if (this.async) {
if (ms) {
this.timer = setTimeout(function(){
done(new Error('timeout of ' + ms + 'ms exceeded'));
self.timedOut = true;
}, ms);
}
}
// called multiple times
function multiple(err) {
if (emitted) return;
emitted = true;
self.emit('error', err || new Error('done() called multiple times'));
}
// finished
function done(err) {
if (self.timedOut) return;
if (finished) return multiple(err);
self.clearTimeout();
self.duration = new Date - start;
finished = true;
fn(err);
}
// for .resetTimeout()
this.callback = done;
// async
if (this.async) {
try {
this.fn.call(ctx, function(err){
if (err instanceof Error || toString.call(err) === "[object Error]") return done(err);
if (null != err) return done(new Error('done() invoked with non-Error: ' + err));
done();
});
} catch (err) {
done(err);
}
return;
}
if (this.asyncOnly) {
return done(new Error('--async-only option in use without declaring `done()`'));
}
// sync
try {
if (!this.pending) this.fn.call(ctx);
this.duration = new Date - start;
fn();
} catch (err) {
fn(err);
}
};
}); // module: runnable.js
require.register("runner.js", function(module, exports, require){
/**
* Module dependencies.
*/
var EventEmitter = require('browser/events').EventEmitter
, debug = require('browser/debug')('mocha:runner')
, Test = require('./test')
, utils = require('./utils')
, filter = utils.filter
, keys = utils.keys;
/**
* Non-enumerable globals.
*/
var globals = [
'setTimeout',
'clearTimeout',
'setInterval',
'clearInterval',
'XMLHttpRequest',
'Date'
];
/**
* Expose `Runner`.
*/
module.exports = Runner;
/**
* Initialize a `Runner` for the given `suite`.
*
* Events:
*
* - `start` execution started
* - `end` execution complete
* - `suite` (suite) test suite execution started
* - `suite end` (suite) all tests (and sub-suites) have finished
* - `test` (test) test execution started
* - `test end` (test) test completed
* - `hook` (hook) hook execution started
* - `hook end` (hook) hook complete
* - `pass` (test) test passed
* - `fail` (test, err) test failed
* - `pending` (test) test pending
*
* @api public
*/
function Runner(suite) {
var self = this;
this._globals = [];
this.suite = suite;
this.total = suite.total();
this.failures = 0;
this.on('test end', function(test){ self.checkGlobals(test); });
this.on('hook end', function(hook){ self.checkGlobals(hook); });
this.grep(/.*/);
this.globals(this.globalProps().concat(['errno']));
}
/**
* Wrapper for setImmediate, process.nextTick, or browser polyfill.
*
* @param {Function} fn
* @api private
*/
Runner.immediately = global.setImmediate || process.nextTick;
/**
* Inherit from `EventEmitter.prototype`.
*/
function F(){};
F.prototype = EventEmitter.prototype;
Runner.prototype = new F;
Runner.prototype.constructor = Runner;
/**
* Run tests with full titles matching `re`. Updates runner.total
* with number of tests matched.
*
* @param {RegExp} re
* @param {Boolean} invert
* @return {Runner} for chaining
* @api public
*/
Runner.prototype.grep = function(re, invert){
debug('grep %s', re);
this._grep = re;
this._invert = invert;
this.total = this.grepTotal(this.suite);
return this;
};
/**
* Returns the number of tests matching the grep search for the
* given suite.
*
* @param {Suite} suite
* @return {Number}
* @api public
*/
Runner.prototype.grepTotal = function(suite) {
var self = this;
var total = 0;
suite.eachTest(function(test){
var match = self._grep.test(test.fullTitle());
if (self._invert) match = !match;
if (match) total++;
});
return total;
};
/**
* Return a list of global properties.
*
* @return {Array}
* @api private
*/
Runner.prototype.globalProps = function() {
var props = utils.keys(global);
// non-enumerables
for (var i = 0; i < globals.length; ++i) {
if (~utils.indexOf(props, globals[i])) continue;
props.push(globals[i]);
}
return props;
};
/**
* Allow the given `arr` of globals.
*
* @param {Array} arr
* @return {Runner} for chaining
* @api public
*/
Runner.prototype.globals = function(arr){
if (0 == arguments.length) return this._globals;
debug('globals %j', arr);
utils.forEach(arr, function(arr){
this._globals.push(arr);
}, this);
return this;
};
/**
* Check for global variable leaks.
*
* @api private
*/
Runner.prototype.checkGlobals = function(test){
if (this.ignoreLeaks) return;
var ok = this._globals;
var globals = this.globalProps();
var isNode = process.kill;
var leaks;
// check length - 2 ('errno' and 'location' globals)
if (isNode && 1 == ok.length - globals.length) return;
else if (2 == ok.length - globals.length) return;
if(this.prevGlobalsLength == globals.length) return;
this.prevGlobalsLength = globals.length;
leaks = filterLeaks(ok, globals);
this._globals = this._globals.concat(leaks);
if (leaks.length > 1) {
this.fail(test, new Error('global leaks detected: ' + leaks.join(', ') + ''));
} else if (leaks.length) {
this.fail(test, new Error('global leak detected: ' + leaks[0]));
}
};
/**
* Fail the given `test`.
*
* @param {Test} test
* @param {Error} err
* @api private
*/
Runner.prototype.fail = function(test, err){
++this.failures;
test.state = 'failed';
if ('string' == typeof err) {
err = new Error('the string "' + err + '" was thrown, throw an Error :)');
}
this.emit('fail', test, err);
};
/**
* Fail the given `hook` with `err`.
*
* Hook failures (currently) hard-end due
* to that fact that a failing hook will
* surely cause subsequent tests to fail,
* causing jumbled reporting.
*
* @param {Hook} hook
* @param {Error} err
* @api private
*/
Runner.prototype.failHook = function(hook, err){
this.fail(hook, err);
this.emit('end');
};
/**
* Run hook `name` callbacks and then invoke `fn()`.
*
* @param {String} name
* @param {Function} function
* @api private
*/
Runner.prototype.hook = function(name, fn){
var suite = this.suite
, hooks = suite['_' + name]
, self = this
, timer;
function next(i) {
var hook = hooks[i];
if (!hook) return fn();
if (self.failures && suite.bail()) return fn();
self.currentRunnable = hook;
hook.ctx.currentTest = self.test;
self.emit('hook', hook);
hook.on('error', function(err){
self.failHook(hook, err);
});
hook.run(function(err){
hook.removeAllListeners('error');
var testError = hook.error();
if (testError) self.fail(self.test, testError);
if (err) return self.failHook(hook, err);
self.emit('hook end', hook);
delete hook.ctx.currentTest;
next(++i);
});
}
Runner.immediately(function(){
next(0);
});
};
/**
* Run hook `name` for the given array of `suites`
* in order, and callback `fn(err)`.
*
* @param {String} name
* @param {Array} suites
* @param {Function} fn
* @api private
*/
Runner.prototype.hooks = function(name, suites, fn){
var self = this
, orig = this.suite;
function next(suite) {
self.suite = suite;
if (!suite) {
self.suite = orig;
return fn();
}
self.hook(name, function(err){
if (err) {
self.suite = orig;
return fn(err);
}
next(suites.pop());
});
}
next(suites.pop());
};
/**
* Run hooks from the top level down.
*
* @param {String} name
* @param {Function} fn
* @api private
*/
Runner.prototype.hookUp = function(name, fn){
var suites = [this.suite].concat(this.parents()).reverse();
this.hooks(name, suites, fn);
};
/**
* Run hooks from the bottom up.
*
* @param {String} name
* @param {Function} fn
* @api private
*/
Runner.prototype.hookDown = function(name, fn){
var suites = [this.suite].concat(this.parents());
this.hooks(name, suites, fn);
};
/**
* Return an array of parent Suites from
* closest to furthest.
*
* @return {Array}
* @api private
*/
Runner.prototype.parents = function(){
var suite = this.suite
, suites = [];
while (suite = suite.parent) suites.push(suite);
return suites;
};
/**
* Run the current test and callback `fn(err)`.
*
* @param {Function} fn
* @api private
*/
Runner.prototype.runTest = function(fn){
var test = this.test
, self = this;
if (this.asyncOnly) test.asyncOnly = true;
try {
test.on('error', function(err){
self.fail(test, err);
});
test.run(fn);
} catch (err) {
fn(err);
}
};
/**
* Run tests in the given `suite` and invoke
* the callback `fn()` when complete.
*
* @param {Suite} suite
* @param {Function} fn
* @api private
*/
Runner.prototype.runTests = function(suite, fn){
var self = this
, tests = suite.tests.slice()
, test;
function next(err) {
// if we bail after first err
if (self.failures && suite._bail) return fn();
// next test
test = tests.shift();
// all done
if (!test) return fn();
// grep
var match = self._grep.test(test.fullTitle());
if (self._invert) match = !match;
if (!match) return next();
// pending
if (test.pending) {
self.emit('pending', test);
self.emit('test end', test);
return next();
}
// execute test and hook(s)
self.emit('test', self.test = test);
self.hookDown('beforeEach', function(){
self.currentRunnable = self.test;
self.runTest(function(err){
test = self.test;
if (err) {
self.fail(test, err);
self.emit('test end', test);
return self.hookUp('afterEach', next);
}
test.state = 'passed';
self.emit('pass', test);
self.emit('test end', test);
self.hookUp('afterEach', next);
});
});
}
this.next = next;
next();
};
/**
* Run the given `suite` and invoke the
* callback `fn()` when complete.
*
* @param {Suite} suite
* @param {Function} fn
* @api private
*/
Runner.prototype.runSuite = function(suite, fn){
var total = this.grepTotal(suite)
, self = this
, i = 0;
debug('run suite %s', suite.fullTitle());
if (!total) return fn();
this.emit('suite', this.suite = suite);
function next() {
var curr = suite.suites[i++];
if (!curr) return done();
self.runSuite(curr, next);
}
function done() {
self.suite = suite;
self.hook('afterAll', function(){
self.emit('suite end', suite);
fn();
});
}
this.hook('beforeAll', function(){
self.runTests(suite, next);
});
};
/**
* Handle uncaught exceptions.
*
* @param {Error} err
* @api private
*/
Runner.prototype.uncaught = function(err){
debug('uncaught exception %s', err.message);
var runnable = this.currentRunnable;
if (!runnable || 'failed' == runnable.state) return;
runnable.clearTimeout();
err.uncaught = true;
this.fail(runnable, err);
// recover from test
if ('test' == runnable.type) {
this.emit('test end', runnable);
this.hookUp('afterEach', this.next);
return;
}
// bail on hooks
this.emit('end');
};
/**
* Run the root suite and invoke `fn(failures)`
* on completion.
*
* @param {Function} fn
* @return {Runner} for chaining
* @api public
*/
Runner.prototype.run = function(fn){
var self = this
, fn = fn || function(){};
function uncaught(err){
self.uncaught(err);
}
debug('start');
// callback
this.on('end', function(){
debug('end');
process.removeListener('uncaughtException', uncaught);
fn(self.failures);
});
// run suites
this.emit('start');
this.runSuite(this.suite, function(){
debug('finished running');
self.emit('end');
});
// uncaught exception
process.on('uncaughtException', uncaught);
return this;
};
/**
* Filter leaks with the given globals flagged as `ok`.
*
* @param {Array} ok
* @param {Array} globals
* @return {Array}
* @api private
*/
function filterLeaks(ok, globals) {
return filter(globals, function(key){
// Firefox and Chrome exposes iframes as index inside the window object
if (/^d+/.test(key)) return false;
// in firefox
// if runner runs in an iframe, this iframe's window.getInterface method not init at first
// it is assigned in some seconds
if (global.navigator && /^getInterface/.test(key)) return false;
// an iframe could be approached by window[iframeIndex]
// in ie6,7,8 and opera, iframeIndex is enumerable, this could cause leak
if (global.navigator && /^\d+/.test(key)) return false;
// Opera and IE expose global variables for HTML element IDs (issue #243)
if (/^mocha-/.test(key)) return false;
var matched = filter(ok, function(ok){
if (~ok.indexOf('*')) return 0 == key.indexOf(ok.split('*')[0]);
return key == ok;
});
return matched.length == 0 && (!global.navigator || 'onerror' !== key);
});
}
}); // module: runner.js
require.register("suite.js", function(module, exports, require){
/**
* Module dependencies.
*/
var EventEmitter = require('browser/events').EventEmitter
, debug = require('browser/debug')('mocha:suite')
, milliseconds = require('./ms')
, utils = require('./utils')
, Hook = require('./hook');
/**
* Expose `Suite`.
*/
exports = module.exports = Suite;
/**
* Create a new `Suite` with the given `title`
* and parent `Suite`. When a suite with the
* same title is already present, that suite
* is returned to provide nicer reporter
* and more flexible meta-testing.
*
* @param {Suite} parent
* @param {String} title
* @return {Suite}
* @api public
*/
exports.create = function(parent, title){
var suite = new Suite(title, parent.ctx);
suite.parent = parent;
if (parent.pending) suite.pending = true;
title = suite.fullTitle();
parent.addSuite(suite);
return suite;
};
/**
* Initialize a new `Suite` with the given
* `title` and `ctx`.
*
* @param {String} title
* @param {Context} ctx
* @api private
*/
function Suite(title, ctx) {
this.title = title;
this.ctx = ctx;
this.suites = [];
this.tests = [];
this.pending = false;
this._beforeEach = [];
this._beforeAll = [];
this._afterEach = [];
this._afterAll = [];
this.root = !title;
this._timeout = 2000;
this._slow = 75;
this._bail = false;
}
/**
* Inherit from `EventEmitter.prototype`.
*/
function F(){};
F.prototype = EventEmitter.prototype;
Suite.prototype = new F;
Suite.prototype.constructor = Suite;
/**
* Return a clone of this `Suite`.
*
* @return {Suite}
* @api private
*/
Suite.prototype.clone = function(){
var suite = new Suite(this.title);
debug('clone');
suite.ctx = this.ctx;
suite.timeout(this.timeout());
suite.slow(this.slow());
suite.bail(this.bail());
return suite;
};
/**
* Set timeout `ms` or short-hand such as "2s".
*
* @param {Number|String} ms
* @return {Suite|Number} for chaining
* @api private
*/
Suite.prototype.timeout = function(ms){
if (0 == arguments.length) return this._timeout;
if ('string' == typeof ms) ms = milliseconds(ms);
debug('timeout %d', ms);
this._timeout = parseInt(ms, 10);
return this;
};
/**
* Set slow `ms` or short-hand such as "2s".
*
* @param {Number|String} ms
* @return {Suite|Number} for chaining
* @api private
*/
Suite.prototype.slow = function(ms){
if (0 === arguments.length) return this._slow;
if ('string' == typeof ms) ms = milliseconds(ms);
debug('slow %d', ms);
this._slow = ms;
return this;
};
/**
* Sets whether to bail after first error.
*
* @parma {Boolean} bail
* @return {Suite|Number} for chaining
* @api private
*/
Suite.prototype.bail = function(bail){
if (0 == arguments.length) return this._bail;
debug('bail %s', bail);
this._bail = bail;
return this;
};
/**
* Run `fn(test[, done])` before running tests.
*
* @param {Function} fn
* @return {Suite} for chaining
* @api private
*/
Suite.prototype.beforeAll = function(fn){
if (this.pending) return this;
var hook = new Hook('"before all" hook', fn);
hook.parent = this;
hook.timeout(this.timeout());
hook.slow(this.slow());
hook.ctx = this.ctx;
this._beforeAll.push(hook);
this.emit('beforeAll', hook);
return this;
};
/**
* Run `fn(test[, done])` after running tests.
*
* @param {Function} fn
* @return {Suite} for chaining
* @api private
*/
Suite.prototype.afterAll = function(fn){
if (this.pending) return this;
var hook = new Hook('"after all" hook', fn);
hook.parent = this;
hook.timeout(this.timeout());
hook.slow(this.slow());
hook.ctx = this.ctx;
this._afterAll.push(hook);
this.emit('afterAll', hook);
return this;
};
/**
* Run `fn(test[, done])` before each test case.
*
* @param {Function} fn
* @return {Suite} for chaining
* @api private
*/
Suite.prototype.beforeEach = function(fn){
if (this.pending) return this;
var hook = new Hook('"before each" hook', fn);
hook.parent = this;
hook.timeout(this.timeout());
hook.slow(this.slow());
hook.ctx = this.ctx;
this._beforeEach.push(hook);
this.emit('beforeEach', hook);
return this;
};
/**
* Run `fn(test[, done])` after each test case.
*
* @param {Function} fn
* @return {Suite} for chaining
* @api private
*/
Suite.prototype.afterEach = function(fn){
if (this.pending) return this;
var hook = new Hook('"after each" hook', fn);
hook.parent = this;
hook.timeout(this.timeout());
hook.slow(this.slow());
hook.ctx = this.ctx;
this._afterEach.push(hook);
this.emit('afterEach', hook);
return this;
};
/**
* Add a test `suite`.
*
* @param {Suite} suite
* @return {Suite} for chaining
* @api private
*/
Suite.prototype.addSuite = function(suite){
suite.parent = this;
suite.timeout(this.timeout());
suite.slow(this.slow());
suite.bail(this.bail());
this.suites.push(suite);
this.emit('suite', suite);
return this;
};
/**
* Add a `test` to this suite.
*
* @param {Test} test
* @return {Suite} for chaining
* @api private
*/
Suite.prototype.addTest = function(test){
test.parent = this;
test.timeout(this.timeout());
test.slow(this.slow());
test.ctx = this.ctx;
this.tests.push(test);
this.emit('test', test);
return this;
};
/**
* Return the full title generated by recursively
* concatenating the parent's full title.
*
* @return {String}
* @api public
*/
Suite.prototype.fullTitle = function(){
if (this.parent) {
var full = this.parent.fullTitle();
if (full) return full + ' ' + this.title;
}
return this.title;
};
/**
* Return the total number of tests.
*
* @return {Number}
* @api public
*/
Suite.prototype.total = function(){
return utils.reduce(this.suites, function(sum, suite){
return sum + suite.total();
}, 0) + this.tests.length;
};
/**
* Iterates through each suite recursively to find
* all tests. Applies a function in the format
* `fn(test)`.
*
* @param {Function} fn
* @return {Suite}
* @api private
*/
Suite.prototype.eachTest = function(fn){
utils.forEach(this.tests, fn);
utils.forEach(this.suites, function(suite){
suite.eachTest(fn);
});
return this;
};
}); // module: suite.js
require.register("test.js", function(module, exports, require){
/**
* Module dependencies.
*/
var Runnable = require('./runnable');
/**
* Expose `Test`.
*/
module.exports = Test;
/**
* Initialize a new `Test` with the given `title` and callback `fn`.
*
* @param {String} title
* @param {Function} fn
* @api private
*/
function Test(title, fn) {
Runnable.call(this, title, fn);
this.pending = !fn;
this.type = 'test';
}
/**
* Inherit from `Runnable.prototype`.
*/
function F(){};
F.prototype = Runnable.prototype;
Test.prototype = new F;
Test.prototype.constructor = Test;
}); // module: test.js
require.register("utils.js", function(module, exports, require){
/**
* Module dependencies.
*/
var fs = require('browser/fs')
, path = require('browser/path')
, join = path.join
, debug = require('browser/debug')('mocha:watch');
/**
* Ignored directories.
*/
var ignore = ['node_modules', '.git'];
/**
* Escape special characters in the given string of html.
*
* @param {String} html
* @return {String}
* @api private
*/
exports.escape = function(html){
return String(html)
.replace(/&/g, '&amp;')
.replace(/"/g, '&quot;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;');
};
/**
* Array#forEach (<=IE8)
*
* @param {Array} array
* @param {Function} fn
* @param {Object} scope
* @api private
*/
exports.forEach = function(arr, fn, scope){
for (var i = 0, l = arr.length; i < l; i++)
fn.call(scope, arr[i], i);
};
/**
* Array#indexOf (<=IE8)
*
* @parma {Array} arr
* @param {Object} obj to find index of
* @param {Number} start
* @api private
*/
exports.indexOf = function(arr, obj, start){
for (var i = start || 0, l = arr.length; i < l; i++) {
if (arr[i] === obj)
return i;
}
return -1;
};
/**
* Array#reduce (<=IE8)
*
* @param {Array} array
* @param {Function} fn
* @param {Object} initial value
* @api private
*/
exports.reduce = function(arr, fn, val){
var rval = val;
for (var i = 0, l = arr.length; i < l; i++) {
rval = fn(rval, arr[i], i, arr);
}
return rval;
};
/**
* Array#filter (<=IE8)
*
* @param {Array} array
* @param {Function} fn
* @api private
*/
exports.filter = function(arr, fn){
var ret = [];
for (var i = 0, l = arr.length; i < l; i++) {
var val = arr[i];
if (fn(val, i, arr)) ret.push(val);
}
return ret;
};
/**
* Object.keys (<=IE8)
*
* @param {Object} obj
* @return {Array} keys
* @api private
*/
exports.keys = Object.keys || function(obj) {
var keys = []
, has = Object.prototype.hasOwnProperty // for `window` on <=IE8
for (var key in obj) {
if (has.call(obj, key)) {
keys.push(key);
}
}
return keys;
};
/**
* Watch the given `files` for changes
* and invoke `fn(file)` on modification.
*
* @param {Array} files
* @param {Function} fn
* @api private
*/
exports.watch = function(files, fn){
var options = { interval: 100 };
files.forEach(function(file){
debug('file %s', file);
fs.watchFile(file, options, function(curr, prev){
if (prev.mtime < curr.mtime) fn(file);
});
});
};
/**
* Ignored files.
*/
function ignored(path){
return !~ignore.indexOf(path);
}
/**
* Lookup files in the given `dir`.
*
* @return {Array}
* @api private
*/
exports.files = function(dir, ret){
ret = ret || [];
fs.readdirSync(dir)
.filter(ignored)
.forEach(function(path){
path = join(dir, path);
if (fs.statSync(path).isDirectory()) {
exports.files(path, ret);
} else if (path.match(/\.(js|coffee|litcoffee|coffee.md)$/)) {
ret.push(path);
}
});
return ret;
};
/**
* Compute a slug from the given `str`.
*
* @param {String} str
* @return {String}
* @api private
*/
exports.slug = function(str){
return str
.toLowerCase()
.replace(/ +/g, '-')
.replace(/[^-\w]/g, '');
};
/**
* Strip the function definition from `str`,
* and re-indent for pre whitespace.
*/
exports.clean = function(str) {
str = str
.replace(/^function *\(.*\) *{/, '')
.replace(/\s+\}$/, '');
var whitespace = str.match(/^\n?(\s*)/)[1]
, re = new RegExp('^' + whitespace, 'gm');
str = str.replace(re, '');
return exports.trim(str);
};
/**
* Escape regular expression characters in `str`.
*
* @param {String} str
* @return {String}
* @api private
*/
exports.escapeRegexp = function(str){
return str.replace(/[-\\^$*+?.()|[\]{}]/g, "\\$&");
};
/**
* Trim the given `str`.
*
* @param {String} str
* @return {String}
* @api private
*/
exports.trim = function(str){
return str.replace(/^\s+|\s+$/g, '');
};
/**
* Parse the given `qs`.
*
* @param {String} qs
* @return {Object}
* @api private
*/
exports.parseQuery = function(qs){
return exports.reduce(qs.replace('?', '').split('&'), function(obj, pair){
var i = pair.indexOf('=')
, key = pair.slice(0, i)
, val = pair.slice(++i);
obj[key] = decodeURIComponent(val);
return obj;
}, {});
};
/**
* Highlight the given string of `js`.
*
* @param {String} js
* @return {String}
* @api private
*/
function highlight(js) {
return js
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/\/\/(.*)/gm, '<span class="comment">//$1</span>')
.replace(/('.*?')/gm, '<span class="string">$1</span>')
.replace(/(\d+\.\d+)/gm, '<span class="number">$1</span>')
.replace(/(\d+)/gm, '<span class="number">$1</span>')
.replace(/\bnew *(\w+)/gm, '<span class="keyword">new</span> <span class="init">$1</span>')
.replace(/\b(function|new|throw|return|var|if|else)\b/gm, '<span class="keyword">$1</span>')
}
/**
* Highlight the contents of tag `name`.
*
* @param {String} name
* @api private
*/
exports.highlightTags = function(name) {
var code = document.getElementsByTagName(name);
for (var i = 0, len = code.length; i < len; ++i) {
code[i].innerHTML = highlight(code[i].innerHTML);
}
};
}); // module: utils.js
// The global object is "self" in Web Workers.
global = (function() { return this; })();
/**
* Save timer references to avoid Sinon interfering (see GH-237).
*/
var Date = global.Date;
var setTimeout = global.setTimeout;
var setInterval = global.setInterval;
var clearTimeout = global.clearTimeout;
var clearInterval = global.clearInterval;
/**
* Node shims.
*
* These are meant only to allow
* mocha.js to run untouched, not
* to allow running node code in
* the browser.
*/
var process = {};
process.exit = function(status){};
process.stdout = {};
/**
* Remove uncaughtException listener.
*/
process.removeListener = function(e){
if ('uncaughtException' == e) {
global.onerror = function() {};
}
};
/**
* Implements uncaughtException listener.
*/
process.on = function(e, fn){
if ('uncaughtException' == e) {
global.onerror = function(err, url, line){
fn(new Error(err + ' (' + url + ':' + line + ')'));
};
}
};
/**
* Expose mocha.
*/
var Mocha = global.Mocha = require('mocha'),
mocha = global.mocha = new Mocha({ reporter: 'html' });
var immediateQueue = []
, immediateTimeout;
function timeslice() {
var immediateStart = new Date().getTime();
while (immediateQueue.length && (new Date().getTime() - immediateStart) < 100) {
immediateQueue.shift()();
}
if (immediateQueue.length) {
immediateTimeout = setTimeout(timeslice, 0);
} else {
immediateTimeout = null;
}
}
/**
* High-performance override of Runner.immediately.
*/
Mocha.Runner.immediately = function(callback) {
immediateQueue.push(callback);
if (!immediateTimeout) {
immediateTimeout = setTimeout(timeslice, 0);
}
};
/**
* Override ui to ensure that the ui functions are initialized.
* Normally this would happen in Mocha.prototype.loadFiles.
*/
mocha.ui = function(ui){
Mocha.prototype.ui.call(this, ui);
this.suite.emit('pre-require', global, null, this);
return this;
};
/**
* Setup mocha with the given setting options.
*/
mocha.setup = function(opts){
if ('string' == typeof opts) opts = { ui: opts };
for (var opt in opts) this[opt](opts[opt]);
return this;
};
/**
* Run mocha, returning the Runner.
*/
mocha.run = function(fn){
var options = mocha.options;
mocha.globals('location');
var query = Mocha.utils.parseQuery(global.location.search || '');
if (query.grep) mocha.grep(query.grep);
if (query.invert) mocha.invert();
return Mocha.prototype.run.call(mocha, function(){
// The DOM Document is not available in Web Workers.
if (global.document) {
Mocha.utils.highlightTags('code');
}
if (fn) fn();
});
};
/**
* Expose the process shim.
*/
Mocha.process = process;
})();
(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(require,module,exports){
'use strict';
var utils = require('./utils');
function wrapError(callback) {
// provide more helpful error message
return function (err, res) {
if (err) {
if (err.name === 'unknown_error') {
err.message = (err.message || '') +
' Unknown error! Did you remember to enable CORS?';
}
}
return callback(err, res);
};
}
exports.signup = utils.toPromise(function (username, password, opts, callback) {
var db = this;
if (typeof callback === 'undefined') {
callback = typeof opts === 'undefined' ? (typeof password === 'undefined' ?
username : password) : opts;
opts = {};
}
if (['http', 'https'].indexOf(db.type()) === -1) {
return callback(new AuthError('This plugin only works for the http/https adapter. ' +
'So you should use new PouchDB("http://mysite.com:5984/mydb") instead.'));
} else if (!username) {
return callback(new AuthError('You must provide a username'));
} else if (!password) {
return callback(new AuthError('You must provide a password'));
}
var userId = 'org.couchdb.user:' + username;
var user = {
name : username,
password : password,
roles : opts.roles || [],
type : 'user',
_id : userId
};
var reservedWords = ['name', 'password', 'roles', 'type', 'salt', 'metadata'];
if (opts.metadata) {
for (var key in opts.metadata) {
if (opts.hasOwnProperty(key)) {
if (reservedWords.indexOf(key) !== -1 || key.startsWith('_')) {
return callback(new AuthError('cannot use reserved word in metadata: "' + key + '"'));
}
}
}
user = utils.extend(true, user, opts.metadata);
}
var url = utils.getUsersUrl(db) + '/' + encodeURIComponent(userId);
var ajaxOpts = utils.extend(true, {
method : 'PUT',
url : url,
body : user
}, opts.ajax || {});
utils.ajax(ajaxOpts, wrapError(callback));
});
exports.signUp = exports.signup;
exports.login = utils.toPromise(function (username, password, opts, callback) {
var db = this;
if (typeof callback === 'undefined') {
callback = opts;
opts = {};
}
if (['http', 'https'].indexOf(db.type()) === -1) {
return callback(new AuthError('this plugin only works for the http/https adapter'));
}
if (!username) {
return callback(new AuthError('you must provide a username'));
} else if (!password) {
return callback(new AuthError('you must provide a password'));
}
var ajaxOpts = utils.extend(true, {
method : 'POST',
url : utils.getSessionUrl(db),
body : {name : username, password : password}
}, opts.ajax || {});
utils.ajax(ajaxOpts, wrapError(callback));
});
exports.logIn = exports.login;
exports.logout = utils.toPromise(function (opts, callback) {
var db = this;
if (typeof callback === 'undefined') {
callback = opts;
opts = {};
}
var ajaxOpts = utils.extend(true, {
method : 'DELETE',
url : utils.getSessionUrl(db)
}, opts.ajax || {});
utils.ajax(ajaxOpts, wrapError(callback));
});
exports.logOut = exports.logout;
exports.getSession = utils.toPromise(function (opts, callback) {
var db = this;
if (typeof callback === 'undefined') {
callback = opts;
opts = {};
}
var url = utils.getSessionUrl(db);
var ajaxOpts = utils.extend(true, {
method : 'GET',
url : url
}, opts.ajax || {});
utils.ajax(ajaxOpts, wrapError(callback));
});
exports.getUser = utils.toPromise(function (username, opts, callback) {
var db = this;
if (typeof callback === 'undefined') {
callback = typeof opts === 'undefined' ? username : opts;
opts = {};
}
if (!username) {
return callback(new AuthError('you must provide a username'));
}
var url = utils.getUsersUrl(db);
var ajaxOpts = utils.extend(true, {
method : 'GET',
url : url + '/' + encodeURIComponent('org.couchdb.user:' + username)
}, opts.ajax || {});
utils.ajax(ajaxOpts, wrapError(callback));
});
exports.changePassword = utils.toPromise(function (username, password, opts, callback) {
var db = this;
if (typeof callback === 'undefined') {
callback = typeof opts === 'undefined' ? (typeof password === 'undefined' ?
username : password) : opts;
opts = {};
}
if (['http', 'https'].indexOf(db.type()) === -1) {
return callback(new AuthError('This plugin only works for the http/https adapter. ' +
'So you should use new PouchDB("http://mysite.com:5984/mydb") instead.'));
} else if (!username) {
return callback(new AuthError('You must provide a username'));
} else if (!password) {
return callback(new AuthError('You must provide a password'));
}
return db.getUser(username, opts, function (error, user) {
if (error) {
return callback(error);
}
user.password = password;
var url = utils.getUsersUrl(db) + '/' + encodeURIComponent(user._id);
var ajaxOpts = utils.extend(true, {
method : 'PUT',
url : url,
body : user
}, opts.ajax || {});
utils.ajax(ajaxOpts, wrapError(callback));
});
});
function AuthError(message) {
this.status = 400;
this.name = 'authentication_error';
this.message = message;
this.error = true;
try {
Error.captureStackTrace(this, AuthError);
} catch (e) {}
}
utils.inherits(AuthError, Error);
if (typeof window !== 'undefined' && window.PouchDB) {
window.PouchDB.plugin(exports);
}
},{"./utils":2}],2:[function(require,module,exports){
(function (process){
'use strict';
var Promise = require('pouchdb/extras/promise');
function getBaseUrl(db) {
return db.getUrl().replace(/\/[^\/]+\/?$/, '');
}
exports.getUsersUrl = function (db) {
return getBaseUrl(db) + '/_users';
};
exports.getSessionUrl = function (db) {
return getBaseUrl(db) + '/_session';
};
exports.once = function (fun) {
var called = false;
return exports.getArguments(function (args) {
if (called) {
console.trace();
throw new Error('once called more than once');
} else {
called = true;
fun.apply(this, args);
}
});
};
exports.getArguments = function (fun) {
return function () {
var len = arguments.length;
var args = new Array(len);
var i = -1;
while (++i < len) {
args[i] = arguments[i];
}
return fun.call(this, args);
};
};
exports.toPromise = function (func) {
//create the function we will be returning
return exports.getArguments(function (args) {
var self = this;
var tempCB = (typeof args[args.length - 1] === 'function') ? args.pop() : false;
// if the last argument is a function, assume its a callback
var usedCB;
if (tempCB) {
// if it was a callback, create a new callback which calls it,
// but do so async so we don't trap any errors
usedCB = function (err, resp) {
process.nextTick(function () {
tempCB(err, resp);
});
};
}
var promise = new Promise(function (fulfill, reject) {
try {
var callback = exports.once(function (err, mesg) {
if (err) {
reject(err);
} else {
fulfill(mesg);
}
});
// create a callback for this invocation
// apply the function in the orig context
args.push(callback);
func.apply(self, args);
} catch (e) {
reject(e);
}
});
// if there is a callback, call it back
if (usedCB) {
promise.then(function (result) {
usedCB(null, result);
}, usedCB);
}
promise.cancel = function () {
return this;
};
return promise;
});
};
exports.inherits = require('inherits');
exports.extend = require('pouchdb-extend');
exports.ajax = require('pouchdb/extras/ajax');
exports.clone = function (obj) {
return exports.extend(true, {}, obj);
};
exports.uuid = require('./uuid');
exports.Promise = Promise;
}).call(this,require("/Users/nlawson/workspace-node/pouchdb-authentication/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js"))
},{"./uuid":3,"/Users/nlawson/workspace-node/pouchdb-authentication/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js":46,"inherits":79,"pouchdb-extend":99,"pouchdb/extras/ajax":100,"pouchdb/extras/promise":101}],3:[function(require,module,exports){
"use strict";
// BEGIN Math.uuid.js
/*!
Math.uuid.js (v1.4)
http://www.broofa.com
mailto:robert@broofa.com
Copyright (c) 2010 Robert Kieffer
Dual licensed under the MIT and GPL licenses.
*/
/*
* Generate a random uuid.
*
* USAGE: Math.uuid(length, radix)
* length - the desired number of characters
* radix - the number of allowable values for each character.
*
* EXAMPLES:
* // No arguments - returns RFC4122, version 4 ID
* >>> Math.uuid()
* "92329D39-6F5C-4520-ABFC-AAB64544E172"
*
* // One argument - returns ID of the specified length
* >>> Math.uuid(15) // 15 character ID (default base=62)
* "VcydxgltxrVZSTV"
*
* // Two arguments - returns ID of the specified length, and radix.
* // (Radix must be <= 62)
* >>> Math.uuid(8, 2) // 8 character ID (base=2)
* "01001010"
* >>> Math.uuid(8, 10) // 8 character ID (base=10)
* "47473046"
* >>> Math.uuid(8, 16) // 8 character ID (base=16)
* "098F4D35"
*/
var chars = (
'0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ' +
'abcdefghijklmnopqrstuvwxyz'
).split('');
function getValue(radix) {
return 0 | Math.random() * radix;
}
function uuid(len, radix) {
radix = radix || chars.length;
var out = '';
var i = -1;
if (len) {
// Compact form
while (++i < len) {
out += chars[getValue(radix)];
}
return out;
}
// rfc4122, version 4 form
// Fill in random data. At i==19 set the high bits of clock sequence as
// per rfc4122, sec. 4.1.5
while (++i < 36) {
switch (i) {
case 8:
case 13:
case 18:
case 23:
out += '-';
break;
case 19:
out += chars[(getValue(16) & 0x3) | 0x8];
break;
default:
out += chars[getValue(16)];
}
}
return out;
}
module.exports = uuid;
},{}],4:[function(require,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 = require("./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":36}],5:[function(require,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 = require("./schedule.js");
var Queue = require("./queue.js");
var errorObj = require("./util.js").errorObj;
var tryCatch1 = require("./util.js").tryCatch1;
var process = require("./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":18,"./queue.js":29,"./schedule.js":32,"./util.js":40}],6:[function(require,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 = require("./promise.js")();
module.exports = Promise;
},{"./promise.js":22}],7:[function(require,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
);
};
};
},{}],8:[function(require,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 = require("./errors.js");
var async = require("./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":5,"./errors.js":12}],9:[function(require,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 = require("./util.js").inherits;
var defineProperty = require("./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":14,"./util.js":40}],10:[function(require,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 = require("./util.js");
var errors = require("./errors.js");
var tryCatch1 = util.tryCatch1;
var errorObj = util.errorObj;
var keys = require("./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":12,"./es5.js":14,"./util.js":40}],11:[function(require,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 = require("./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":40}],12:[function(require,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 = require("./global.js");
var Objectfreeze = require("./es5.js").freeze;
var util = require("./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":14,"./global.js":18,"./util.js":40}],13:[function(require,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 = require('./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":12}],14:[function(require,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;
var ObjectKeys = function ObjectKeys(o) {
var ret = [];
for (var key in o) {
if (has.call(o, key)) {
ret.push(key);
}
}
return ret;
}
var ObjectDefineProperty = function ObjectDefineProperty(o, key, desc) {
o[key] = desc.value;
return o;
}
var ObjectFreeze = function ObjectFreeze(obj) {
return obj;
}
var ObjectGetPrototypeOf = function ObjectGetPrototypeOf(obj) {
try {
return Object(obj).constructor.prototype;
}
catch (e) {
return proto;
}
}
var ArrayIsArray = 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
};
}
},{}],15:[function(require,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 = require("./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":40}],16:[function(require,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 = require("./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":40}],17:[function(require,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 = require("./promise_spawn.js")(Promise, INTERNAL);
var errors = require("./errors.js");
var TypeError = errors.TypeError;
var deprecated = require("./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":12,"./promise_spawn.js":25,"./util.js":40}],18:[function(require,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 : {})
},{}],19:[function(require,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 = require("./util.js");
var canAttach = require("./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":12,"./util.js":40}],20:[function(require,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 = require("./util.js");
var async = require("./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":5,"./util.js":40}],21:[function(require,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 = require("./util.js");
var async = require("./async.js");
var errors = require("./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":5,"./errors.js":12,"./util.js":40}],22:[function(require,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 = require("./global.js");
var util = require("./util.js");
var async = require("./async.js");
var errors = require("./errors.js");
var INTERNAL = function(){};
var APPLY = {};
var NEXT_FILTER = {e: null};
var PromiseArray = require("./promise_array.js")(Promise, INTERNAL);
var CapturedTrace = require("./captured_trace.js")();
var CatchFilter = require("./catch_filter.js")(NEXT_FILTER);
var PromiseResolver = require("./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 = require("./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;
require("./finally.js")(Promise, NEXT_FILTER);
require("./direct_resolve.js")(Promise);
require("./thenables.js")(Promise, INTERNAL);
require("./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);
require('./timers.js')(Promise,INTERNAL);
require('./any.js')(Promise,Promise$_CreatePromiseArray,PromiseArray);
require('./race.js')(Promise,INTERNAL);
require('./call_get.js')(Promise);
require('./filter.js')(Promise,Promise$_CreatePromiseArray,PromiseArray,apiRejection);
require('./generators.js')(Promise,apiRejection,INTERNAL);
require('./map.js')(Promise,PromiseArray,INTERNAL,apiRejection);
require('./nodeify.js')(Promise);
require('./promisify.js')(Promise,INTERNAL);
require('./props.js')(Promise,PromiseArray);
require('./reduce.js')(Promise,Promise$_CreatePromiseArray,PromiseArray,apiRejection,INTERNAL);
require('./settle.js')(Promise,Promise$_CreatePromiseArray,PromiseArray);
require('./some.js')(Promise,Promise$_CreatePromiseArray,PromiseArray,apiRejection);
require('./progress.js')(Promise,isPromiseArrayProxy);
require('./cancel.js')(Promise,INTERNAL);
Promise.prototype = Promise.prototype;
return Promise;
};
}).call(this,require("/Users/nlawson/workspace-node/pouchdb-authentication/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js"))
},{"./any.js":4,"./async.js":5,"./call_get.js":7,"./cancel.js":8,"./captured_trace.js":9,"./catch_filter.js":10,"./direct_resolve.js":11,"./errors.js":12,"./errors_api_rejection":13,"./filter.js":15,"./finally.js":16,"./generators.js":17,"./global.js":18,"./map.js":19,"./nodeify.js":20,"./progress.js":21,"./promise_array.js":23,"./promise_resolver.js":24,"./promisify.js":26,"./props.js":28,"./race.js":30,"./reduce.js":31,"./settle.js":33,"./some.js":35,"./synchronous_inspection.js":37,"./thenables.js":38,"./timers.js":39,"./util.js":40,"/Users/nlawson/workspace-node/pouchdb-authentication/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js":46}],23:[function(require,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 = require("./errors.js").canAttach;
var util = require("./util.js");
var async = require("./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":5,"./errors.js":12,"./util.js":40}],24:[function(require,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 = require("./util.js");
var maybeWrapAsError = util.maybeWrapAsError;
var errors = require("./errors.js");
var TimeoutError = errors.TimeoutError;
var RejectionError = errors.RejectionError;
var async = require("./async.js");
var haveGetters = util.haveGetters;
var es5 = require("./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 === void 0) || (promise._tryFollow === void 0)) {
throw new TypeError("Illegal invocation, resolver resolve/reject must be called within a resolver context. Consider using the promise constructor instead.");
}
if (promise._tryFollow(value)) {
return;
}
async.invoke(promise._fulfill, promise, value);
};
PromiseResolver.prototype.reject = function PromiseResolver$reject(reason) {
var promise = this.promise;
if ((promise === void 0) || (promise._attachExtraTrace === void 0)) {
throw new TypeError("Illegal invocation, resolver resolve/reject must be called within a resolver context. Consider using the promise constructor instead.");
}
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":5,"./errors.js":12,"./es5.js":14,"./util.js":40}],25:[function(require,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 = require("./errors.js");
var TypeError = errors.TypeError;
var util = require("./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":12,"./util.js":40}],26:[function(require,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 = require("./util.js");
var es5 = require("./es5.js");
var nodebackForPromise = require("./promise_resolver.js")
._nodebackForPromise;
var withAppended = util.withAppended;
var maybeWrapAsError = util.maybeWrapAsError;
var canEvaluate = util.canEvaluate;
var deprecated = util.deprecated;
var TypeError = require("./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;
}
var rident = /^[a-z$_][a-z$_0-9]*$/i;
function propertyAccess(id) {
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;";
}
if (!rident.test(callbackName)) {
callbackName = "promisified";
}
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":12,"./es5.js":14,"./promise_resolver.js":24,"./util.js":40}],27:[function(require,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 = require("./util.js");
var inherits = util.inherits;
var es5 = require("./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":14,"./util.js":40}],28:[function(require,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 = require("./properties_promise_array.js")(
Promise, PromiseArray);
var util = require("./util.js");
var apiRejection = require("./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":13,"./properties_promise_array.js":27,"./util.js":40}],29:[function(require,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;
},{}],30:[function(require,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 = require("./errors_api_rejection.js")(Promise);
var isArray = require("./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":13,"./util.js":40}],31:[function(require,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);
};
};
},{}],32:[function(require,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 = require("./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,require("/Users/nlawson/workspace-node/pouchdb-authentication/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js"))
},{"./global.js":18,"/Users/nlawson/workspace-node/pouchdb-authentication/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js":46}],33:[function(require,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 = require("./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":34}],34:[function(require,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 = require("./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":40}],35:[function(require,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 = require("./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":36}],36:[function(require,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 = require("./util.js");
var RangeError = require("./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":12,"./util.js":40}],37:[function(require,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;
};
},{}],38:[function(require,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 = require("./util.js");
var canAttach = require("./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":12,"./util.js":40}],39:[function(require,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 = require("./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 = require("./util.js");
var errors = require("./errors.js");
var apiRejection = require("./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":12,"./errors_api_rejection":13,"./global.js":18,"./util.js":40}],40:[function(require,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 = require("./global.js");
var es5 = require("./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":14,"./global.js":18}],41:[function(require,module,exports){
},{}],42:[function(require,module,exports){
/*!
* The buffer module from node.js, for the browser.
*
* @author Feross Aboukhadijeh <feross@feross.org> <http://feross.org>
* @license MIT
*/
var base64 = require('base64-js')
var ieee754 = require('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":43,"ieee754":44}],43:[function(require,module,exports){
var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
;(function (exports) {
'use strict';
var Arr = (typeof Uint8Array !== 'undefined')
? Uint8Array
: Array
var PLUS = '+'.charCodeAt(0)
var SLASH = '/'.charCodeAt(0)
var NUMBER = '0'.charCodeAt(0)
var LOWER = 'a'.charCodeAt(0)
var UPPER = 'A'.charCodeAt(0)
var PLUS_URL_SAFE = '-'.charCodeAt(0)
var SLASH_URL_SAFE = '_'.charCodeAt(0)
function decode (elt) {
var code = elt.charCodeAt(0)
if (code === PLUS ||
code === PLUS_URL_SAFE)
return 62 // '+'
if (code === SLASH ||
code === SLASH_URL_SAFE)
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
}
exports.toByteArray = b64ToByteArray
exports.fromByteArray = uint8ToBase64
}(typeof exports === 'undefined' ? (this.base64js = {}) : exports))
},{}],44:[function(require,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
}
},{}],45:[function(require,module,exports){
// 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.
function EventEmitter() {
this._events = this._events || {};
this._maxListeners = this._maxListeners || undefined;
}
module.exports = EventEmitter;
// Backwards-compat with node 0.10.x
EventEmitter.EventEmitter = EventEmitter;
EventEmitter.prototype._events = undefined;
EventEmitter.prototype._maxListeners = undefined;
// By default EventEmitters will print a warning if more than 10 listeners are
// added to it. This is a useful default which helps finding memory leaks.
EventEmitter.defaultMaxListeners = 10;
// Obviously not all Emitters should be limited to 10. This function allows
// that to be increased. Set to zero for unlimited.
EventEmitter.prototype.setMaxListeners = function(n) {
if (!isNumber(n) || n < 0 || isNaN(n))
throw TypeError('n must be a positive number');
this._maxListeners = n;
return this;
};
EventEmitter.prototype.emit = function(type) {
var er, handler, len, args, i, listeners;
if (!this._events)
this._events = {};
// If there is no 'error' event listener then throw.
if (type === 'error') {
if (!this._events.error ||
(isObject(this._events.error) && !this._events.error.length)) {
er = arguments[1];
if (er instanceof Error) {
throw er; // Unhandled 'error' event
}
throw TypeError('Uncaught, unspecified "error" event.');
}
}
handler = this._events[type];
if (isUndefined(handler))
return false;
if (isFunction(handler)) {
switch (arguments.length) {
// fast cases
case 1:
handler.call(this);
break;
case 2:
handler.call(this, arguments[1]);
break;
case 3:
handler.call(this, arguments[1], arguments[2]);
break;
// slower
default:
len = arguments.length;
args = new Array(len - 1);
for (i = 1; i < len; i++)
args[i - 1] = arguments[i];
handler.apply(this, args);
}
} else if (isObject(handler)) {
len = arguments.length;
args = new Array(len - 1);
for (i = 1; i < len; i++)
args[i - 1] = arguments[i];
listeners = handler.slice();
len = listeners.length;
for (i = 0; i < len; i++)
listeners[i].apply(this, args);
}
return true;
};
EventEmitter.prototype.addListener = function(type, listener) {
var m;
if (!isFunction(listener))
throw TypeError('listener must be a function');
if (!this._events)
this._events = {};
// To avoid recursion in the case that type === "newListener"! Before
// adding it to the listeners, first emit "newListener".
if (this._events.newListener)
this.emit('newListener', type,
isFunction(listener.listener) ?
listener.listener : listener);
if (!this._events[type])
// Optimize the case of one listener. Don't need the extra array object.
this._events[type] = listener;
else if (isObject(this._events[type]))
// If we've already got an array, just append.
this._events[type].push(listener);
else
// Adding the second element, need to change to array.
this._events[type] = [this._events[type], listener];
// Check for listener leak
if (isObject(this._events[type]) && !this._events[type].warned) {
var m;
if (!isUndefined(this._maxListeners)) {
m = this._maxListeners;
} else {
m = EventEmitter.defaultMaxListeners;
}
if (m && m > 0 && this._events[type].length > m) {
this._events[type].warned = true;
console.error('(node) warning: possible EventEmitter memory ' +
'leak detected. %d listeners added. ' +
'Use emitter.setMaxListeners() to increase limit.',
this._events[type].length);
if (typeof console.trace === 'function') {
// not supported in IE 10
console.trace();
}
}
}
return this;
};
EventEmitter.prototype.on = EventEmitter.prototype.addListener;
EventEmitter.prototype.once = function(type, listener) {
if (!isFunction(listener))
throw TypeError('listener must be a function');
var fired = false;
function g() {
this.removeListener(type, g);
if (!fired) {
fired = true;
listener.apply(this, arguments);
}
}
g.listener = listener;
this.on(type, g);
return this;
};
// emits a 'removeListener' event iff the listener was removed
EventEmitter.prototype.removeListener = function(type, listener) {
var list, position, length, i;
if (!isFunction(listener))
throw TypeError('listener must be a function');
if (!this._events || !this._events[type])
return this;
list = this._events[type];
length = list.length;
position = -1;
if (list === listener ||
(isFunction(list.listener) && list.listener === listener)) {
delete this._events[type];
if (this._events.removeListener)
this.emit('removeListener', type, listener);
} else if (isObject(list)) {
for (i = length; i-- > 0;) {
if (list[i] === listener ||
(list[i].listener && list[i].listener === listener)) {
position = i;
break;
}
}
if (position < 0)
return this;
if (list.length === 1) {
list.length = 0;
delete this._events[type];
} else {
list.splice(position, 1);
}
if (this._events.removeListener)
this.emit('removeListener', type, listener);
}
return this;
};
EventEmitter.prototype.removeAllListeners = function(type) {
var key, listeners;
if (!this._events)
return this;
// not listening for removeListener, no need to emit
if (!this._events.removeListener) {
if (arguments.length === 0)
this._events = {};
else if (this._events[type])
delete this._events[type];
return this;
}
// emit removeListener for all listeners on all events
if (arguments.length === 0) {
for (key in this._events) {
if (key === 'removeListener') continue;
this.removeAllListeners(key);
}
this.removeAllListeners('removeListener');
this._events = {};
return this;
}
listeners = this._events[type];
if (isFunction(listeners)) {
this.removeListener(type, listeners);
} else {
// LIFO order
while (listeners.length)
this.removeListener(type, listeners[listeners.length - 1]);
}
delete this._events[type];
return this;
};
EventEmitter.prototype.listeners = function(type) {
var ret;
if (!this._events || !this._events[type])
ret = [];
else if (isFunction(this._events[type]))
ret = [this._events[type]];
else
ret = this._events[type].slice();
return ret;
};
EventEmitter.listenerCount = function(emitter, type) {
var ret;
if (!emitter._events || !emitter._events[type])
ret = 0;
else if (isFunction(emitter._events[type]))
ret = 1;
else
ret = emitter._events[type].length;
return ret;
};
function isFunction(arg) {
return typeof arg === 'function';
}
function isNumber(arg) {
return typeof arg === 'number';
}
function isObject(arg) {
return typeof arg === 'object' && arg !== null;
}
function isUndefined(arg) {
return arg === void 0;
}
},{}],46:[function(require,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');
};
},{}],47:[function(require,module,exports){
(function (process){
// 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.
// resolves . and .. elements in a path array with directory names there
// must be no slashes, empty elements, or device names (c:\) in the array
// (so also no leading and trailing slashes - it does not distinguish
// relative and absolute paths)
function normalizeArray(parts, allowAboveRoot) {
// if the path tries to go above the root, `up` ends up > 0
var up = 0;
for (var i = parts.length - 1; i >= 0; i--) {
var last = parts[i];
if (last === '.') {
parts.splice(i, 1);
} else if (last === '..') {
parts.splice(i, 1);
up++;
} else if (up) {
parts.splice(i, 1);
up--;
}
}
// if the path is allowed to go above the root, restore leading ..s
if (allowAboveRoot) {
for (; up--; up) {
parts.unshift('..');
}
}
return parts;
}
// Split a filename into [root, dir, basename, ext], unix version
// 'root' is just a slash, or nothing.
var splitPathRe =
/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;
var splitPath = function(filename) {
return splitPathRe.exec(filename).slice(1);
};
// path.resolve([from ...], to)
// posix version
exports.resolve = function() {
var resolvedPath = '',
resolvedAbsolute = false;
for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {
var path = (i >= 0) ? arguments[i] : process.cwd();
// Skip empty and invalid entries
if (typeof path !== 'string') {
throw new TypeError('Arguments to path.resolve must be strings');
} else if (!path) {
continue;
}
resolvedPath = path + '/' + resolvedPath;
resolvedAbsolute = path.charAt(0) === '/';
}
// At this point the path should be resolved to a full absolute path, but
// handle relative paths to be safe (might happen when process.cwd() fails)
// Normalize the path
resolvedPath = normalizeArray(filter(resolvedPath.split('/'), function(p) {
return !!p;
}), !resolvedAbsolute).join('/');
return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';
};
// path.normalize(path)
// posix version
exports.normalize = function(path) {
var isAbsolute = exports.isAbsolute(path),
trailingSlash = substr(path, -1) === '/';
// Normalize the path
path = normalizeArray(filter(path.split('/'), function(p) {
return !!p;
}), !isAbsolute).join('/');
if (!path && !isAbsolute) {
path = '.';
}
if (path && trailingSlash) {
path += '/';
}
return (isAbsolute ? '/' : '') + path;
};
// posix version
exports.isAbsolute = function(path) {
return path.charAt(0) === '/';
};
// posix version
exports.join = function() {
var paths = Array.prototype.slice.call(arguments, 0);
return exports.normalize(filter(paths, function(p, index) {
if (typeof p !== 'string') {
throw new TypeError('Arguments to path.join must be strings');
}
return p;
}).join('/'));
};
// path.relative(from, to)
// posix version
exports.relative = function(from, to) {
from = exports.resolve(from).substr(1);
to = exports.resolve(to).substr(1);
function trim(arr) {
var start = 0;
for (; start < arr.length; start++) {
if (arr[start] !== '') break;
}
var end = arr.length - 1;
for (; end >= 0; end--) {
if (arr[end] !== '') break;
}
if (start > end) return [];
return arr.slice(start, end - start + 1);
}
var fromParts = trim(from.split('/'));
var toParts = trim(to.split('/'));
var length = Math.min(fromParts.length, toParts.length);
var samePartsLength = length;
for (var i = 0; i < length; i++) {
if (fromParts[i] !== toParts[i]) {
samePartsLength = i;
break;
}
}
var outputParts = [];
for (var i = samePartsLength; i < fromParts.length; i++) {
outputParts.push('..');
}
outputParts = outputParts.concat(toParts.slice(samePartsLength));
return outputParts.join('/');
};
exports.sep = '/';
exports.delimiter = ':';
exports.dirname = function(path) {
var result = splitPath(path),
root = result[0],
dir = result[1];
if (!root && !dir) {
// No dirname whatsoever
return '.';
}
if (dir) {
// It has a dirname, strip trailing slash
dir = dir.substr(0, dir.length - 1);
}
return root + dir;
};
exports.basename = function(path, ext) {
var f = splitPath(path)[2];
// TODO: make this comparison case-insensitive on windows?
if (ext && f.substr(-1 * ext.length) === ext) {
f = f.substr(0, f.length - ext.length);
}
return f;
};
exports.extname = function(path) {
return splitPath(path)[3];
};
function filter (xs, f) {
if (xs.filter) return xs.filter(f);
var res = [];
for (var i = 0; i < xs.length; i++) {
if (f(xs[i], i, xs)) res.push(xs[i]);
}
return res;
}
// String.prototype.substr - negative index don't work in IE8
var substr = 'ab'.substr(-1) === 'b'
? function (str, start, len) { return str.substr(start, len) }
: function (str, start, len) {
if (start < 0) start = str.length + start;
return str.substr(start, len);
}
;
}).call(this,require("/Users/nlawson/workspace-node/pouchdb-authentication/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js"))
},{"/Users/nlawson/workspace-node/pouchdb-authentication/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js":46}],48:[function(require,module,exports){
(function () {
"use strict";
// Module systems magic dance.
if (typeof require === "function" && typeof exports === "object" && typeof module === "object") {
// NodeJS
module.exports = chaiAsPromised;
} else if (typeof define === "function" && define.amd) {
// AMD
define(function () {
return chaiAsPromised;
});
} else {
/*global self: false */
// Other environment (usually <script> tag): plug in to global chai instance directly.
chai.use(chaiAsPromised);
// Expose as a property of the global object so that consumers can configure the `transferPromiseness` property.
self.chaiAsPromised = chaiAsPromised;
}
chaiAsPromised.transferPromiseness = function (assertion, promise) {
assertion.then = promise.then.bind(promise);
};
function chaiAsPromised(chai, utils) {
var Assertion = chai.Assertion;
var assert = chai.assert;
function isJQueryPromise(thenable) {
return typeof thenable.always === "function" &&
typeof thenable.done === "function" &&
typeof thenable.fail === "function" &&
typeof thenable.pipe === "function" &&
typeof thenable.progress === "function" &&
typeof thenable.state === "function";
}
function assertIsAboutPromise(assertion) {
if (typeof assertion._obj.then !== "function") {
throw new TypeError(utils.inspect(assertion._obj) + " is not a thenable.");
}
if (isJQueryPromise(assertion._obj)) {
throw new TypeError("Chai as Promised is incompatible with jQuery's thenables, sorry! Please use a " +
"Promises/A+ compatible library (see http://promisesaplus.com/).");
}
}
function method(name, asserter) {
utils.addMethod(Assertion.prototype, name, function () {
assertIsAboutPromise(this);
return asserter.apply(this, arguments);
});
}
function property(name, asserter) {
utils.addProperty(Assertion.prototype, name, function () {
assertIsAboutPromise(this);
return asserter.apply(this, arguments);
});
}
function doNotify(promise, done) {
promise.then(function () { done(); }, done);
}
// These are for clarity and to bypass Chai refusing to allow `undefined` as actual when used with `assert`.
function assertIfNegated(assertion, message, extra) {
assertion.assert(true, null, message, extra.expected, extra.actual);
}
function assertIfNotNegated(assertion, message, extra) {
assertion.assert(false, message, null, extra.expected, extra.actual);
}
function getBasePromise(assertion) {
// We need to chain subsequent asserters on top of ones in the chain already (consider
// `eventually.have.property("foo").that.equals("bar")`), only running them after the existing ones pass.
// So the first base-promise is `assertion._obj`, but after that we use the assertions themselves, i.e.
// previously derived promises, to chain off of.
return typeof assertion.then === "function" ? assertion : assertion._obj;
}
// Grab these first, before we modify `Assertion.prototype`.
var propertyNames = Object.getOwnPropertyNames(Assertion.prototype);
var propertyDescs = {};
propertyNames.forEach(function (name) {
propertyDescs[name] = Object.getOwnPropertyDescriptor(Assertion.prototype, name);
});
property("fulfilled", function () {
var that = this;
var derivedPromise = getBasePromise(that).then(
function (value) {
that._obj = value;
assertIfNegated(that,
"expected promise not to be fulfilled but it was fulfilled with #{act}",
{ actual: value });
return value;
},
function (reason) {
assertIfNotNegated(that,
"expected promise to be fulfilled but it was rejected with #{act}",
{ actual: reason });
}
);
chaiAsPromised.transferPromiseness(that, derivedPromise);
});
property("rejected", function () {
var that = this;
var derivedPromise = getBasePromise(that).then(
function (value) {
that._obj = value;
assertIfNotNegated(that,
"expected promise to be rejected but it was fulfilled with #{act}",
{ actual: value });
return value;
},
function (reason) {
assertIfNegated(that,
"expected promise not to be rejected but it was rejected with #{act}",
{ actual: reason });
// Return the reason, transforming this into a fulfillment, to allow further assertions, e.g.
// `promise.should.be.rejected.and.eventually.equal("reason")`.
return reason;
}
);
chaiAsPromised.transferPromiseness(that, derivedPromise);
});
method("rejectedWith", function (Constructor, message) {
var desiredReason = null;
var constructorName = null;
if (Constructor instanceof RegExp || typeof Constructor === "string") {
message = Constructor;
Constructor = null;
} else if (Constructor && Constructor instanceof Error) {
desiredReason = Constructor;
Constructor = null;
message = null;
} else if (typeof Constructor === "function") {
constructorName = (new Constructor()).name;
} else {
Constructor = null;
}
var that = this;
var derivedPromise = getBasePromise(that).then(
function (value) {
var assertionMessage = null;
var expected = null;
if (Constructor) {
assertionMessage = "expected promise to be rejected with #{exp} but it was fulfilled with " +
"#{act}";
expected = constructorName;
} else if (message) {
var verb = message instanceof RegExp ? "matching" : "including";
assertionMessage = "expected promise to be rejected with an error " + verb + " #{exp} but it " +
"was fulfilled with #{act}";
expected = message;
} else if (desiredReason) {
assertionMessage = "expected promise to be rejected with #{exp} but it was fulfilled with " +
"#{act}";
expected = desiredReason;
}
that._obj = value;
assertIfNotNegated(that, assertionMessage, { expected: expected, actual: value });
},
function (reason) {
if (Constructor) {
that.assert(reason instanceof Constructor,
"expected promise to be rejected with #{exp} but it was rejected with #{act}",
"expected promise not to be rejected with #{exp} but it was rejected with #{act}",
constructorName,
reason);
}
var reasonMessage = utils.type(reason) === "object" && "message" in reason ?
reason.message :
"" + reason;
if (message && reasonMessage !== null && reasonMessage !== undefined) {
if (message instanceof RegExp) {
that.assert(message.test(reasonMessage),
"expected promise to be rejected with an error matching #{exp} but got #{act}",
"expected promise not to be rejected with an error matching #{exp}",
message,
reasonMessage);
}
if (typeof message === "string") {
that.assert(reasonMessage.indexOf(message) !== -1,
"expected promise to be rejected with an error including #{exp} but got #{act}",
"expected promise not to be rejected with an error including #{exp}",
message,
reasonMessage);
}
}
if (desiredReason) {
that.assert(reason === desiredReason,
"expected promise to be rejected with #{exp} but it was rejected with #{act}",
"expected promise not to be rejected with #{exp}",
desiredReason,
reason);
}
}
);
chaiAsPromised.transferPromiseness(that, derivedPromise);
});
property("eventually", function () {
utils.flag(this, "eventually", true);
});
method("notify", function (done) {
doNotify(getBasePromise(this), done);
});
method("become", function (value) {
return this.eventually.deep.equal(value);
});
////////
// `eventually`
// We need to be careful not to trigger any getters, thus `Object.getOwnPropertyDescriptor` usage.
var methodNames = propertyNames.filter(function (name) {
return name !== "assert" && typeof propertyDescs[name].value === "function";
});
methodNames.forEach(function (methodName) {
Assertion.overwriteMethod(methodName, function (originalMethod) {
return function () {
doAsserterAsyncAndAddThen(originalMethod, this, arguments);
};
});
});
var getterNames = propertyNames.filter(function (name) {
return name !== "_obj" && typeof propertyDescs[name].get === "function";
});
getterNames.forEach(function (getterName) {
var propertyDesc = propertyDescs[getterName];
// Chainable methods are things like `an`, which can work both for `.should.be.an.instanceOf` and as
// `should.be.an("object")`. We need to handle those specially.
var isChainableMethod = false;
try {
isChainableMethod = typeof propertyDesc.get.call({}) === "function";
} catch (e) { }
if (isChainableMethod) {
Assertion.addChainableMethod(
getterName,
function () {
var assertion = this;
function originalMethod() {
return propertyDesc.get.call(assertion).apply(assertion, arguments);
}
doAsserterAsyncAndAddThen(originalMethod, this, arguments);
},
function () {
var originalGetter = propertyDesc.get;
doAsserterAsyncAndAddThen(originalGetter, this);
}
);
} else {
Assertion.overwriteProperty(getterName, function (originalGetter) {
return function () {
doAsserterAsyncAndAddThen(originalGetter, this);
};
});
}
});
function doAsserterAsyncAndAddThen(asserter, assertion, args) {
// Since we're intercepting all methods/properties, we need to just pass through if they don't want
// `eventually`, or if we've already fulfilled the promise (see below).
if (!utils.flag(assertion, "eventually")) {
return asserter.apply(assertion, args);
}
var derivedPromise = getBasePromise(assertion).then(function (value) {
// Set up the environment for the asserter to actually run: `_obj` should be the fulfillment value, and
// now that we have the value, we're no longer in "eventually" mode, so we won't run any of this code,
// just the base Chai code that we get to via the short-circuit above.
assertion._obj = value;
utils.flag(assertion, "eventually", false);
asserter.apply(assertion, args);
// Because asserters, for example `property`, can change the value of `_obj` (i.e. change the "object"
// flag), we need to communicate this value change to subsequent chained asserters. Since we build a
// promise chain paralleling the asserter chain, we can use it to communicate such changes.
return assertion._obj;
});
chaiAsPromised.transferPromiseness(assertion, derivedPromise);
}
///////
// Now use the `Assertion` framework to build an `assert` interface.
var originalAssertMethods = Object.getOwnPropertyNames(assert).filter(function (propName) {
return typeof assert[propName] === "function";
});
assert.isFulfilled = function (promise, message) {
return (new Assertion(promise, message)).to.be.fulfilled;
};
assert.isRejected = function (promise, toTestAgainst, message) {
if (typeof toTestAgainst === "string") {
message = toTestAgainst;
toTestAgainst = undefined;
}
var assertion = (new Assertion(promise, message));
return toTestAgainst !== undefined ? assertion.to.be.rejectedWith(toTestAgainst) : assertion.to.be.rejected;
};
assert.becomes = function (promise, value, message) {
return assert.eventually.deepEqual(promise, value, message);
};
assert.doesNotBecome = function (promise, value, message) {
return assert.eventually.notDeepEqual(promise, value, message);
};
assert.eventually = {};
originalAssertMethods.forEach(function (assertMethodName) {
assert.eventually[assertMethodName] = function (promise) {
var otherArgs = Array.prototype.slice.call(arguments, 1);
var customRejectionHandler;
var message = arguments[assert[assertMethodName].length - 1];
if (typeof message === "string") {
customRejectionHandler = function (reason) {
throw new chai.AssertionError(message + "\n\nOriginal reason: " + utils.inspect(reason));
};
}
var returnedPromise = promise.then(
function (fulfillmentValue) {
return assert[assertMethodName].apply(assert, [fulfillmentValue].concat(otherArgs));
},
customRejectionHandler
);
returnedPromise.notify = function (done) {
doNotify(returnedPromise, done);
};
return returnedPromise;
};
});
}
}());
},{}],49:[function(require,module,exports){
module.exports = require('./lib/chai');
},{"./lib/chai":50}],50:[function(require,module,exports){
/*!
* chai
* Copyright(c) 2011-2013 Jake Luer <jake@alogicalparadox.com>
* MIT Licensed
*/
var used = []
, exports = module.exports = {};
/*!
* Chai version
*/
exports.version = '1.8.1';
/*!
* Assertion Error
*/
exports.AssertionError = require('assertion-error');
/*!
* Utils for plugins (not exported)
*/
var util = require('./chai/utils');
/**
* # .use(function)
*
* Provides a way to extend the internals of Chai
*
* @param {Function}
* @returns {this} for chaining
* @api public
*/
exports.use = function (fn) {
if (!~used.indexOf(fn)) {
fn(this, util);
used.push(fn);
}
return this;
};
/*!
* Primary `Assertion` prototype
*/
var assertion = require('./chai/assertion');
exports.use(assertion);
/*!
* Core Assertions
*/
var core = require('./chai/core/assertions');
exports.use(core);
/*!
* Expect interface
*/
var expect = require('./chai/interface/expect');
exports.use(expect);
/*!
* Should interface
*/
var should = require('./chai/interface/should');
exports.use(should);
/*!
* Assert interface
*/
var assert = require('./chai/interface/assert');
exports.use(assert);
},{"./chai/assertion":51,"./chai/core/assertions":52,"./chai/interface/assert":53,"./chai/interface/expect":54,"./chai/interface/should":55,"./chai/utils":66,"assertion-error":74}],51:[function(require,module,exports){
/*!
* chai
* http://chaijs.com
* Copyright(c) 2011-2013 Jake Luer <jake@alogicalparadox.com>
* MIT Licensed
*/
module.exports = function (_chai, util) {
/*!
* Module dependencies.
*/
var AssertionError = _chai.AssertionError
, flag = util.flag;
/*!
* Module export.
*/
_chai.Assertion = Assertion;
/*!
* Assertion Constructor
*
* Creates object for chaining.
*
* @api private
*/
function Assertion (obj, msg, stack) {
flag(this, 'ssfi', stack || arguments.callee);
flag(this, 'object', obj);
flag(this, 'message', msg);
}
/*!
* ### Assertion.includeStack
*
* User configurable property, influences whether stack trace
* is included in Assertion error message. Default of false
* suppresses stack trace in the error message
*
* Assertion.includeStack = true; // enable stack on error
*
* @api public
*/
Assertion.includeStack = false;
/*!
* ### Assertion.showDiff
*
* User configurable property, influences whether or not
* the `showDiff` flag should be included in the thrown
* AssertionErrors. `false` will always be `false`; `true`
* will be true when the assertion has requested a diff
* be shown.
*
* @api public
*/
Assertion.showDiff = true;
Assertion.addProperty = function (name, fn) {
util.addProperty(this.prototype, name, fn);
};
Assertion.addMethod = function (name, fn) {
util.addMethod(this.prototype, name, fn);
};
Assertion.addChainableMethod = function (name, fn, chainingBehavior) {
util.addChainableMethod(this.prototype, name, fn, chainingBehavior);
};
Assertion.overwriteProperty = function (name, fn) {
util.overwriteProperty(this.prototype, name, fn);
};
Assertion.overwriteMethod = function (name, fn) {
util.overwriteMethod(this.prototype, name, fn);
};
/*!
* ### .assert(expression, message, negateMessage, expected, actual)
*
* Executes an expression and check expectations. Throws AssertionError for reporting if test doesn't pass.
*
* @name assert
* @param {Philosophical} expression to be tested
* @param {String} message to display if fails
* @param {String} negatedMessage to display if negated expression fails
* @param {Mixed} expected value (remember to check for negation)
* @param {Mixed} actual (optional) will default to `this.obj`
* @api private
*/
Assertion.prototype.assert = function (expr, msg, negateMsg, expected, _actual, showDiff) {
var ok = util.test(this, arguments);
if (true !== showDiff) showDiff = false;
if (true !== Assertion.showDiff) showDiff = false;
if (!ok) {
var msg = util.getMessage(this, arguments)
, actual = util.getActual(this, arguments);
throw new AssertionError(msg, {
actual: actual
, expected: expected
, showDiff: showDiff
}, (Assertion.includeStack) ? this.assert : flag(this, 'ssfi'));
}
};
/*!
* ### ._obj
*
* Quick reference to stored `actual` value for plugin developers.
*
* @api private
*/
Object.defineProperty(Assertion.prototype, '_obj',
{ get: function () {
return flag(this, 'object');
}
, set: function (val) {
flag(this, 'object', val);
}
});
};
},{}],52:[function(require,module,exports){
/*!
* chai
* http://chaijs.com
* Copyright(c) 2011-2013 Jake Luer <jake@alogicalparadox.com>
* MIT Licensed
*/
module.exports = function (chai, _) {
var Assertion = chai.Assertion
, toString = Object.prototype.toString
, flag = _.flag;
/**
* ### Language Chains
*
* The following are provide as chainable getters to
* improve the readability of your assertions. They
* do not provide an testing capability unless they
* have been overwritten by a plugin.
*
* **Chains**
*
* - to
* - be
* - been
* - is
* - that
* - and
* - have
* - with
* - at
* - of
* - same
*
* @name language chains
* @api public
*/
[ 'to', 'be', 'been'
, 'is', 'and', 'have'
, 'with', 'that', 'at'
, 'of', 'same' ].forEach(function (chain) {
Assertion.addProperty(chain, function () {
return this;
});
});
/**
* ### .not
*
* Negates any of assertions following in the chain.
*
* expect(foo).to.not.equal('bar');
* expect(goodFn).to.not.throw(Error);
* expect({ foo: 'baz' }).to.have.property('foo')
* .and.not.equal('bar');
*
* @name not
* @api public
*/
Assertion.addProperty('not', function () {
flag(this, 'negate', true);
});
/**
* ### .deep
*
* Sets the `deep` flag, later used by the `equal` and
* `property` assertions.
*
* expect(foo).to.deep.equal({ bar: 'baz' });
* expect({ foo: { bar: { baz: 'quux' } } })
* .to.have.deep.property('foo.bar.baz', 'quux');
*
* @name deep
* @api public
*/
Assertion.addProperty('deep', function () {
flag(this, 'deep', true);
});
/**
* ### .a(type)
*
* The `a` and `an` assertions are aliases that can be
* used either as language chains or to assert a value's
* type.
*
* // typeof
* expect('test').to.be.a('string');
* expect({ foo: 'bar' }).to.be.an('object');
* expect(null).to.be.a('null');
* expect(undefined).to.be.an('undefined');
*
* // language chain
* expect(foo).to.be.an.instanceof(Foo);
*
* @name a
* @alias an
* @param {String} type
* @param {String} message _optional_
* @api public
*/
function an (type, msg) {
if (msg) flag(this, 'message', msg);
type = type.toLowerCase();
var obj = flag(this, 'object')
, article = ~[ 'a', 'e', 'i', 'o', 'u' ].indexOf(type.charAt(0)) ? 'an ' : 'a ';
this.assert(
type === _.type(obj)
, 'expected #{this} to be ' + article + type
, 'expected #{this} not to be ' + article + type
);
}
Assertion.addChainableMethod('an', an);
Assertion.addChainableMethod('a', an);
/**
* ### .include(value)
*
* The `include` and `contain` assertions can be used as either property
* based language chains or as methods to assert the inclusion of an object
* in an array or a substring in a string. When used as language chains,
* they toggle the `contain` flag for the `keys` assertion.
*
* expect([1,2,3]).to.include(2);
* expect('foobar').to.contain('foo');
* expect({ foo: 'bar', hello: 'universe' }).to.include.keys('foo');
*
* @name include
* @alias contain
* @param {Object|String|Number} obj
* @param {String} message _optional_
* @api public
*/
function includeChainingBehavior () {
flag(this, 'contains', true);
}
function include (val, msg) {
if (msg) flag(this, 'message', msg);
var obj = flag(this, 'object')
this.assert(
~obj.indexOf(val)
, 'expected #{this} to include ' + _.inspect(val)
, 'expected #{this} to not include ' + _.inspect(val));
}
Assertion.addChainableMethod('include', include, includeChainingBehavior);
Assertion.addChainableMethod('contain', include, includeChainingBehavior);
/**
* ### .ok
*
* Asserts that the target is truthy.
*
* expect('everthing').to.be.ok;
* expect(1).to.be.ok;
* expect(false).to.not.be.ok;
* expect(undefined).to.not.be.ok;
* expect(null).to.not.be.ok;
*
* @name ok
* @api public
*/
Assertion.addProperty('ok', function () {
this.assert(
flag(this, 'object')
, 'expected #{this} to be truthy'
, 'expected #{this} to be falsy');
});
/**
* ### .true
*
* Asserts that the target is `true`.
*
* expect(true).to.be.true;
* expect(1).to.not.be.true;
*
* @name true
* @api public
*/
Assertion.addProperty('true', function () {
this.assert(
true === flag(this, 'object')
, 'expected #{this} to be true'
, 'expected #{this} to be false'
, this.negate ? false : true
);
});
/**
* ### .false
*
* Asserts that the target is `false`.
*
* expect(false).to.be.false;
* expect(0).to.not.be.false;
*
* @name false
* @api public
*/
Assertion.addProperty('false', function () {
this.assert(
false === flag(this, 'object')
, 'expected #{this} to be false'
, 'expected #{this} to be true'
, this.negate ? true : false
);
});
/**
* ### .null
*
* Asserts that the target is `null`.
*
* expect(null).to.be.null;
* expect(undefined).not.to.be.null;
*
* @name null
* @api public
*/
Assertion.addProperty('null', function () {
this.assert(
null === flag(this, 'object')
, 'expected #{this} to be null'
, 'expected #{this} not to be null'
);
});
/**
* ### .undefined
*
* Asserts that the target is `undefined`.
*
* expect(undefined).to.be.undefined;
* expect(null).to.not.be.undefined;
*
* @name undefined
* @api public
*/
Assertion.addProperty('undefined', function () {
this.assert(
undefined === flag(this, 'object')
, 'expected #{this} to be undefined'
, 'expected #{this} not to be undefined'
);
});
/**
* ### .exist
*
* Asserts that the target is neither `null` nor `undefined`.
*
* var foo = 'hi'
* , bar = null
* , baz;
*
* expect(foo).to.exist;
* expect(bar).to.not.exist;
* expect(baz).to.not.exist;
*
* @name exist
* @api public
*/
Assertion.addProperty('exist', function () {
this.assert(
null != flag(this, 'object')
, 'expected #{this} to exist'
, 'expected #{this} to not exist'
);
});
/**
* ### .empty
*
* Asserts that the target's length is `0`. For arrays, it checks
* the `length` property. For objects, it gets the count of
* enumerable keys.
*
* expect([]).to.be.empty;
* expect('').to.be.empty;
* expect({}).to.be.empty;
*
* @name empty
* @api public
*/
Assertion.addProperty('empty', function () {
var obj = flag(this, 'object')
, expected = obj;
if (Array.isArray(obj) || 'string' === typeof object) {
expected = obj.length;
} else if (typeof obj === 'object') {
expected = Object.keys(obj).length;
}
this.assert(
!expected
, 'expected #{this} to be empty'
, 'expected #{this} not to be empty'
);
});
/**
* ### .arguments
*
* Asserts that the target is an arguments object.
*
* function test () {
* expect(arguments).to.be.arguments;
* }
*
* @name arguments
* @alias Arguments
* @api public
*/
function checkArguments () {
var obj = flag(this, 'object')
, type = Object.prototype.toString.call(obj);
this.assert(
'[object Arguments]' === type
, 'expected #{this} to be arguments but got ' + type
, 'expected #{this} to not be arguments'
);
}
Assertion.addProperty('arguments', checkArguments);
Assertion.addProperty('Arguments', checkArguments);
/**
* ### .equal(value)
*
* Asserts that the target is strictly equal (`===`) to `value`.
* Alternately, if the `deep` flag is set, asserts that
* the target is deeply equal to `value`.
*
* expect('hello').to.equal('hello');
* expect(42).to.equal(42);
* expect(1).to.not.equal(true);
* expect({ foo: 'bar' }).to.not.equal({ foo: 'bar' });
* expect({ foo: 'bar' }).to.deep.equal({ foo: 'bar' });
*
* @name equal
* @alias equals
* @alias eq
* @alias deep.equal
* @param {Mixed} value
* @param {String} message _optional_
* @api public
*/
function assertEqual (val, msg) {
if (msg) flag(this, 'message', msg);
var obj = flag(this, 'object');
if (flag(this, 'deep')) {
return this.eql(val);
} else {
this.assert(
val === obj
, 'expected #{this} to equal #{exp}'
, 'expected #{this} to not equal #{exp}'
, val
, this._obj
, true
);
}
}
Assertion.addMethod('equal', assertEqual);
Assertion.addMethod('equals', assertEqual);
Assertion.addMethod('eq', assertEqual);
/**
* ### .eql(value)
*
* Asserts that the target is deeply equal to `value`.
*
* expect({ foo: 'bar' }).to.eql({ foo: 'bar' });
* expect([ 1, 2, 3 ]).to.eql([ 1, 2, 3 ]);
*
* @name eql
* @alias eqls
* @param {Mixed} value
* @param {String} message _optional_
* @api public
*/
function assertEql(obj, msg) {
if (msg) flag(this, 'message', msg);
this.assert(
_.eql(obj, flag(this, 'object'))
, 'expected #{this} to deeply equal #{exp}'
, 'expected #{this} to not deeply equal #{exp}'
, obj
, this._obj
, true
);
}
Assertion.addMethod('eql', assertEql);
Assertion.addMethod('eqls', assertEql);
/**
* ### .above(value)
*
* Asserts that the target is greater than `value`.
*
* expect(10).to.be.above(5);
*
* Can also be used in conjunction with `length` to
* assert a minimum length. The benefit being a
* more informative error message than if the length
* was supplied directly.
*
* expect('foo').to.have.length.above(2);
* expect([ 1, 2, 3 ]).to.have.length.above(2);
*
* @name above
* @alias gt
* @alias greaterThan
* @param {Number} value
* @param {String} message _optional_
* @api public
*/
function assertAbove (n, msg) {
if (msg) flag(this, 'message', msg);
var obj = flag(this, 'object');
if (flag(this, 'doLength')) {
new Assertion(obj, msg).to.have.property('length');
var len = obj.length;
this.assert(
len > n
, 'expected #{this} to have a length above #{exp} but got #{act}'
, 'expected #{this} to not have a length above #{exp}'
, n
, len
);
} else {
this.assert(
obj > n
, 'expected #{this} to be above ' + n
, 'expected #{this} to be at most ' + n
);
}
}
Assertion.addMethod('above', assertAbove);
Assertion.addMethod('gt', assertAbove);
Assertion.addMethod('greaterThan', assertAbove);
/**
* ### .least(value)
*
* Asserts that the target is greater than or equal to `value`.
*
* expect(10).to.be.at.least(10);
*
* Can also be used in conjunction with `length` to
* assert a minimum length. The benefit being a
* more informative error message than if the length
* was supplied directly.
*
* expect('foo').to.have.length.of.at.least(2);
* expect([ 1, 2, 3 ]).to.have.length.of.at.least(3);
*
* @name least
* @alias gte
* @param {Number} value
* @param {String} message _optional_
* @api public
*/
function assertLeast (n, msg) {
if (msg) flag(this, 'message', msg);
var obj = flag(this, 'object');
if (flag(this, 'doLength')) {
new Assertion(obj, msg).to.have.property('length');
var len = obj.length;
this.assert(
len >= n
, 'expected #{this} to have a length at least #{exp} but got #{act}'
, 'expected #{this} to have a length below #{exp}'
, n
, len
);
} else {
this.assert(
obj >= n
, 'expected #{this} to be at least ' + n
, 'expected #{this} to be below ' + n
);
}
}
Assertion.addMethod('least', assertLeast);
Assertion.addMethod('gte', assertLeast);
/**
* ### .below(value)
*
* Asserts that the target is less than `value`.
*
* expect(5).to.be.below(10);
*
* Can also be used in conjunction with `length` to
* assert a maximum length. The benefit being a
* more informative error message than if the length
* was supplied directly.
*
* expect('foo').to.have.length.below(4);
* expect([ 1, 2, 3 ]).to.have.length.below(4);
*
* @name below
* @alias lt
* @alias lessThan
* @param {Number} value
* @param {String} message _optional_
* @api public
*/
function assertBelow (n, msg) {
if (msg) flag(this, 'message', msg);
var obj = flag(this, 'object');
if (flag(this, 'doLength')) {
new Assertion(obj, msg).to.have.property('length');
var len = obj.length;
this.assert(
len < n
, 'expected #{this} to have a length below #{exp} but got #{act}'
, 'expected #{this} to not have a length below #{exp}'
, n
, len
);
} else {
this.assert(
obj < n
, 'expected #{this} to be below ' + n
, 'expected #{this} to be at least ' + n
);
}
}
Assertion.addMethod('below', assertBelow);
Assertion.addMethod('lt', assertBelow);
Assertion.addMethod('lessThan', assertBelow);
/**
* ### .most(value)
*
* Asserts that the target is less than or equal to `value`.
*
* expect(5).to.be.at.most(5);
*
* Can also be used in conjunction with `length` to
* assert a maximum length. The benefit being a
* more informative error message than if the length
* was supplied directly.
*
* expect('foo').to.have.length.of.at.most(4);
* expect([ 1, 2, 3 ]).to.have.length.of.at.most(3);
*
* @name most
* @alias lte
* @param {Number} value
* @param {String} message _optional_
* @api public
*/
function assertMost (n, msg) {
if (msg) flag(this, 'message', msg);
var obj = flag(this, 'object');
if (flag(this, 'doLength')) {
new Assertion(obj, msg).to.have.property('length');
var len = obj.length;
this.assert(
len <= n
, 'expected #{this} to have a length at most #{exp} but got #{act}'
, 'expected #{this} to have a length above #{exp}'
, n
, len
);
} else {
this.assert(
obj <= n
, 'expected #{this} to be at most ' + n
, 'expected #{this} to be above ' + n
);
}
}
Assertion.addMethod('most', assertMost);
Assertion.addMethod('lte', assertMost);
/**
* ### .within(start, finish)
*
* Asserts that the target is within a range.
*
* expect(7).to.be.within(5,10);
*
* Can also be used in conjunction with `length` to
* assert a length range. The benefit being a
* more informative error message than if the length
* was supplied directly.
*
* expect('foo').to.have.length.within(2,4);
* expect([ 1, 2, 3 ]).to.have.length.within(2,4);
*
* @name within
* @param {Number} start lowerbound inclusive
* @param {Number} finish upperbound inclusive
* @param {String} message _optional_
* @api public
*/
Assertion.addMethod('within', function (start, finish, msg) {
if (msg) flag(this, 'message', msg);
var obj = flag(this, 'object')
, range = start + '..' + finish;
if (flag(this, 'doLength')) {
new Assertion(obj, msg).to.have.property('length');
var len = obj.length;
this.assert(
len >= start && len <= finish
, 'expected #{this} to have a length within ' + range
, 'expected #{this} to not have a length within ' + range
);
} else {
this.assert(
obj >= start && obj <= finish
, 'expected #{this} to be within ' + range
, 'expected #{this} to not be within ' + range
);
}
});
/**
* ### .instanceof(constructor)
*
* Asserts that the target is an instance of `constructor`.
*
* var Tea = function (name) { this.name = name; }
* , Chai = new Tea('chai');
*
* expect(Chai).to.be.an.instanceof(Tea);
* expect([ 1, 2, 3 ]).to.be.instanceof(Array);
*
* @name instanceof
* @param {Constructor} constructor
* @param {String} message _optional_
* @alias instanceOf
* @api public
*/
function assertInstanceOf (constructor, msg) {
if (msg) flag(this, 'message', msg);
var name = _.getName(constructor);
this.assert(
flag(this, 'object') instanceof constructor
, 'expected #{this} to be an instance of ' + name
, 'expected #{this} to not be an instance of ' + name
);
};
Assertion.addMethod('instanceof', assertInstanceOf);
Assertion.addMethod('instanceOf', assertInstanceOf);
/**
* ### .property(name, [value])
*
* Asserts that the target has a property `name`, optionally asserting that
* the value of that property is strictly equal to `value`.
* If the `deep` flag is set, you can use dot- and bracket-notation for deep
* references into objects and arrays.
*
* // simple referencing
* var obj = { foo: 'bar' };
* expect(obj).to.have.property('foo');
* expect(obj).to.have.property('foo', 'bar');
*
* // deep referencing
* var deepObj = {
* green: { tea: 'matcha' }
* , teas: [ 'chai', 'matcha', { tea: 'konacha' } ]
* };
* expect(deepObj).to.have.deep.property('green.tea', 'matcha');
* expect(deepObj).to.have.deep.property('teas[1]', 'matcha');
* expect(deepObj).to.have.deep.property('teas[2].tea', 'konacha');
*
* You can also use an array as the starting point of a `deep.property`
* assertion, or traverse nested arrays.
*
* var arr = [
* [ 'chai', 'matcha', 'konacha' ]
* , [ { tea: 'chai' }
* , { tea: 'matcha' }
* , { tea: 'konacha' } ]
* ];
*
* expect(arr).to.have.deep.property('[0][1]', 'matcha');
* expect(arr).to.have.deep.property('[1][2].tea', 'konacha');
*
* Furthermore, `property` changes the subject of the assertion
* to be the value of that property from the original object. This
* permits for further chainable assertions on that property.
*
* expect(obj).to.have.property('foo')
* .that.is.a('string');
* expect(deepObj).to.have.property('green')
* .that.is.an('object')
* .that.deep.equals({ tea: 'matcha' });
* expect(deepObj).to.have.property('teas')
* .that.is.an('array')
* .with.deep.property('[2]')
* .that.deep.equals({ tea: 'konacha' });
*
* @name property
* @alias deep.property
* @param {String} name
* @param {Mixed} value (optional)
* @param {String} message _optional_
* @returns value of property for chaining
* @api public
*/
Assertion.addMethod('property', function (name, val, msg) {
if (msg) flag(this, 'message', msg);
var descriptor = flag(this, 'deep') ? 'deep property ' : 'property '
, negate = flag(this, 'negate')
, obj = flag(this, 'object')
, value = flag(this, 'deep')
? _.getPathValue(name, obj)
: obj[name];
if (negate && undefined !== val) {
if (undefined === value) {
msg = (msg != null) ? msg + ': ' : '';
throw new Error(msg + _.inspect(obj) + ' has no ' + descriptor + _.inspect(name));
}
} else {
this.assert(
undefined !== value
, 'expected #{this} to have a ' + descriptor + _.inspect(name)
, 'expected #{this} to not have ' + descriptor + _.inspect(name));
}
if (undefined !== val) {
this.assert(
val === value
, 'expected #{this} to have a ' + descriptor + _.inspect(name) + ' of #{exp}, but got #{act}'
, 'expected #{this} to not have a ' + descriptor + _.inspect(name) + ' of #{act}'
, val
, value
);
}
flag(this, 'object', value);
});
/**
* ### .ownProperty(name)
*
* Asserts that the target has an own property `name`.
*
* expect('test').to.have.ownProperty('length');
*
* @name ownProperty
* @alias haveOwnProperty
* @param {String} name
* @param {String} message _optional_
* @api public
*/
function assertOwnProperty (name, msg) {
if (msg) flag(this, 'message', msg);
var obj = flag(this, 'object');
this.assert(
obj.hasOwnProperty(name)
, 'expected #{this} to have own property ' + _.inspect(name)
, 'expected #{this} to not have own property ' + _.inspect(name)
);
}
Assertion.addMethod('ownProperty', assertOwnProperty);
Assertion.addMethod('haveOwnProperty', assertOwnProperty);
/**
* ### .length(value)
*
* Asserts that the target's `length` property has
* the expected value.
*
* expect([ 1, 2, 3]).to.have.length(3);
* expect('foobar').to.have.length(6);
*
* Can also be used as a chain precursor to a value
* comparison for the length property.
*
* expect('foo').to.have.length.above(2);
* expect([ 1, 2, 3 ]).to.have.length.above(2);
* expect('foo').to.have.length.below(4);
* expect([ 1, 2, 3 ]).to.have.length.below(4);
* expect('foo').to.have.length.within(2,4);
* expect([ 1, 2, 3 ]).to.have.length.within(2,4);
*
* @name length
* @alias lengthOf
* @param {Number} length
* @param {String} message _optional_
* @api public
*/
function assertLengthChain () {
flag(this, 'doLength', true);
}
function assertLength (n, msg) {
if (msg) flag(this, 'message', msg);
var obj = flag(this, 'object');
new Assertion(obj, msg).to.have.property('length');
var len = obj.length;
this.assert(
len == n
, 'expected #{this} to have a length of #{exp} but got #{act}'
, 'expected #{this} to not have a length of #{act}'
, n
, len
);
}
Assertion.addChainableMethod('length', assertLength, assertLengthChain);
Assertion.addMethod('lengthOf', assertLength, assertLengthChain);
/**
* ### .match(regexp)
*
* Asserts that the target matches a regular expression.
*
* expect('foobar').to.match(/^foo/);
*
* @name match
* @param {RegExp} RegularExpression
* @param {String} message _optional_
* @api public
*/
Assertion.addMethod('match', function (re, msg) {
if (msg) flag(this, 'message', msg);
var obj = flag(this, 'object');
this.assert(
re.exec(obj)
, 'expected #{this} to match ' + re
, 'expected #{this} not to match ' + re
);
});
/**
* ### .string(string)
*
* Asserts that the string target contains another string.
*
* expect('foobar').to.have.string('bar');
*
* @name string
* @param {String} string
* @param {String} message _optional_
* @api public
*/
Assertion.addMethod('string', function (str, msg) {
if (msg) flag(this, 'message', msg);
var obj = flag(this, 'object');
new Assertion(obj, msg).is.a('string');
this.assert(
~obj.indexOf(str)
, 'expected #{this} to contain ' + _.inspect(str)
, 'expected #{this} to not contain ' + _.inspect(str)
);
});
/**
* ### .keys(key1, [key2], [...])
*
* Asserts that the target has exactly the given keys, or
* asserts the inclusion of some keys when using the
* `include` or `contain` modifiers.
*
* expect({ foo: 1, bar: 2 }).to.have.keys(['foo', 'bar']);
* expect({ foo: 1, bar: 2, baz: 3 }).to.contain.keys('foo', 'bar');
*
* @name keys
* @alias key
* @param {String...|Array} keys
* @api public
*/
function assertKeys (keys) {
var obj = flag(this, 'object')
, str
, ok = true;
keys = keys instanceof Array
? keys
: Array.prototype.slice.call(arguments);
if (!keys.length) throw new Error('keys required');
var actual = Object.keys(obj)
, len = keys.length;
// Inclusion
ok = keys.every(function(key){
return ~actual.indexOf(key);
});
// Strict
if (!flag(this, 'negate') && !flag(this, 'contains')) {
ok = ok && keys.length == actual.length;
}
// Key string
if (len > 1) {
keys = keys.map(function(key){
return _.inspect(key);
});
var last = keys.pop();
str = keys.join(', ') + ', and ' + last;
} else {
str = _.inspect(keys[0]);
}
// Form
str = (len > 1 ? 'keys ' : 'key ') + str;
// Have / include
str = (flag(this, 'contains') ? 'contain ' : 'have ') + str;
// Assertion
this.assert(
ok
, 'expected #{this} to ' + str
, 'expected #{this} to not ' + str
);
}
Assertion.addMethod('keys', assertKeys);
Assertion.addMethod('key', assertKeys);
/**
* ### .throw(constructor)
*
* Asserts that the function target will throw a specific error, or specific type of error
* (as determined using `instanceof`), optionally with a RegExp or string inclusion test
* for the error's message.
*
* var err = new ReferenceError('This is a bad function.');
* var fn = function () { throw err; }
* expect(fn).to.throw(ReferenceError);
* expect(fn).to.throw(Error);
* expect(fn).to.throw(/bad function/);
* expect(fn).to.not.throw('good function');
* expect(fn).to.throw(ReferenceError, /bad function/);
* expect(fn).to.throw(err);
* expect(fn).to.not.throw(new RangeError('Out of range.'));
*
* Please note that when a throw expectation is negated, it will check each
* parameter independently, starting with error constructor type. The appropriate way
* to check for the existence of a type of error but for a message that does not match
* is to use `and`.
*
* expect(fn).to.throw(ReferenceError)
* .and.not.throw(/good function/);
*
* @name throw
* @alias throws
* @alias Throw
* @param {ErrorConstructor} constructor
* @param {String|RegExp} expected error message
* @param {String} message _optional_
* @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types
* @api public
*/
function assertThrows (constructor, errMsg, msg) {
if (msg) flag(this, 'message', msg);
var obj = flag(this, 'object');
new Assertion(obj, msg).is.a('function');
var thrown = false
, desiredError = null
, name = null
, thrownError = null;
if (arguments.length === 0) {
errMsg = null;
constructor = null;
} else if (constructor && (constructor instanceof RegExp || 'string' === typeof constructor)) {
errMsg = constructor;
constructor = null;
} else if (constructor && constructor instanceof Error) {
desiredError = constructor;
constructor = null;
errMsg = null;
} else if (typeof constructor === 'function') {
name = (new constructor()).name;
} else {
constructor = null;
}
try {
obj();
} catch (err) {
// first, check desired error
if (desiredError) {
this.assert(
err === desiredError
, 'expected #{this} to throw #{exp} but #{act} was thrown'
, 'expected #{this} to not throw #{exp}'
, desiredError
, err
);
return this;
}
// next, check constructor
if (constructor) {
this.assert(
err instanceof constructor
, 'expected #{this} to throw #{exp} but #{act} was thrown'
, 'expected #{this} to not throw #{exp} but #{act} was thrown'
, name
, err
);
if (!errMsg) return this;
}
// next, check message
var message = 'object' === _.type(err) && "message" in err
? err.message
: '' + err;
if ((message != null) && errMsg && errMsg instanceof RegExp) {
this.assert(
errMsg.exec(message)
, 'expected #{this} to throw error matching #{exp} but got #{act}'
, 'expected #{this} to throw error not matching #{exp}'
, errMsg
, message
);
return this;
} else if ((message != null) && errMsg && 'string' === typeof errMsg) {
this.assert(
~message.indexOf(errMsg)
, 'expected #{this} to throw error including #{exp} but got #{act}'
, 'expected #{this} to throw error not including #{act}'
, errMsg
, message
);
return this;
} else {
thrown = true;
thrownError = err;
}
}
var actuallyGot = ''
, expectedThrown = name !== null
? name
: desiredError
? '#{exp}' //_.inspect(desiredError)
: 'an error';
if (thrown) {
actuallyGot = ' but #{act} was thrown'
}
this.assert(
thrown === true
, 'expected #{this} to throw ' + expectedThrown + actuallyGot
, 'expected #{this} to not throw ' + expectedThrown + actuallyGot
, desiredError
, thrownError
);
};
Assertion.addMethod('throw', assertThrows);
Assertion.addMethod('throws', assertThrows);
Assertion.addMethod('Throw', assertThrows);
/**
* ### .respondTo(method)
*
* Asserts that the object or class target will respond to a method.
*
* Klass.prototype.bar = function(){};
* expect(Klass).to.respondTo('bar');
* expect(obj).to.respondTo('bar');
*
* To check if a constructor will respond to a static function,
* set the `itself` flag.
*
* Klass.baz = function(){};
* expect(Klass).itself.to.respondTo('baz');
*
* @name respondTo
* @param {String} method
* @param {String} message _optional_
* @api public
*/
Assertion.addMethod('respondTo', function (method, msg) {
if (msg) flag(this, 'message', msg);
var obj = flag(this, 'object')
, itself = flag(this, 'itself')
, context = ('function' === _.type(obj) && !itself)
? obj.prototype[method]
: obj[method];
this.assert(
'function' === typeof context
, 'expected #{this} to respond to ' + _.inspect(method)
, 'expected #{this} to not respond to ' + _.inspect(method)
);
});
/**
* ### .itself
*
* Sets the `itself` flag, later used by the `respondTo` assertion.
*
* function Foo() {}
* Foo.bar = function() {}
* Foo.prototype.baz = function() {}
*
* expect(Foo).itself.to.respondTo('bar');
* expect(Foo).itself.not.to.respondTo('baz');
*
* @name itself
* @api public
*/
Assertion.addProperty('itself', function () {
flag(this, 'itself', true);
});
/**
* ### .satisfy(method)
*
* Asserts that the target passes a given truth test.
*
* expect(1).to.satisfy(function(num) { return num > 0; });
*
* @name satisfy
* @param {Function} matcher
* @param {String} message _optional_
* @api public
*/
Assertion.addMethod('satisfy', function (matcher, msg) {
if (msg) flag(this, 'message', msg);
var obj = flag(this, 'object');
this.assert(
matcher(obj)
, 'expected #{this} to satisfy ' + _.objDisplay(matcher)
, 'expected #{this} to not satisfy' + _.objDisplay(matcher)
, this.negate ? false : true
, matcher(obj)
);
});
/**
* ### .closeTo(expected, delta)
*
* Asserts that the target is equal `expected`, to within a +/- `delta` range.
*
* expect(1.5).to.be.closeTo(1, 0.5);
*
* @name closeTo
* @param {Number} expected
* @param {Number} delta
* @param {String} message _optional_
* @api public
*/
Assertion.addMethod('closeTo', function (expected, delta, msg) {
if (msg) flag(this, 'message', msg);
var obj = flag(this, 'object');
this.assert(
Math.abs(obj - expected) <= delta
, 'expected #{this} to be close to ' + expected + ' +/- ' + delta
, 'expected #{this} not to be close to ' + expected + ' +/- ' + delta
);
});
function isSubsetOf(subset, superset) {
return subset.every(function(elem) {
return superset.indexOf(elem) !== -1;
})
}
/**
* ### .members(set)
*
* Asserts that the target is a superset of `set`,
* or that the target and `set` have the same members.
*
* expect([1, 2, 3]).to.include.members([3, 2]);
* expect([1, 2, 3]).to.not.include.members([3, 2, 8]);
*
* expect([4, 2]).to.have.members([2, 4]);
* expect([5, 2]).to.not.have.members([5, 2, 1]);
*
* @name members
* @param {Array} set
* @param {String} message _optional_
* @api public
*/
Assertion.addMethod('members', function (subset, msg) {
if (msg) flag(this, 'message', msg);
var obj = flag(this, 'object');
new Assertion(obj).to.be.an('array');
new Assertion(subset).to.be.an('array');
if (flag(this, 'contains')) {
return this.assert(
isSubsetOf(subset, obj)
, 'expected #{this} to be a superset of #{act}'
, 'expected #{this} to not be a superset of #{act}'
, obj
, subset
);
}
this.assert(
isSubsetOf(obj, subset) && isSubsetOf(subset, obj)
, 'expected #{this} to have the same members as #{act}'
, 'expected #{this} to not have the same members as #{act}'
, obj
, subset
);
});
};
},{}],53:[function(require,module,exports){
/*!
* chai
* Copyright(c) 2011-2013 Jake Luer <jake@alogicalparadox.com>
* MIT Licensed
*/
module.exports = function (chai, util) {
/*!
* Chai dependencies.
*/
var Assertion = chai.Assertion
, flag = util.flag;
/*!
* Module export.
*/
/**
* ### assert(expression, message)
*
* Write your own test expressions.
*
* assert('foo' !== 'bar', 'foo is not bar');
* assert(Array.isArray([]), 'empty arrays are arrays');
*
* @param {Mixed} expression to test for truthiness
* @param {String} message to display on error
* @name assert
* @api public
*/
var assert = chai.assert = function (express, errmsg) {
var test = new Assertion(null);
test.assert(
express
, errmsg
, '[ negation message unavailable ]'
);
};
/**
* ### .fail(actual, expected, [message], [operator])
*
* Throw a failure. Node.js `assert` module-compatible.
*
* @name fail
* @param {Mixed} actual
* @param {Mixed} expected
* @param {String} message
* @param {String} operator
* @api public
*/
assert.fail = function (actual, expected, message, operator) {
throw new chai.AssertionError({
actual: actual
, expected: expected
, message: message
, operator: operator
, stackStartFunction: assert.fail
});
};
/**
* ### .ok(object, [message])
*
* Asserts that `object` is truthy.
*
* assert.ok('everything', 'everything is ok');
* assert.ok(false, 'this will fail');
*
* @name ok
* @param {Mixed} object to test
* @param {String} message
* @api public
*/
assert.ok = function (val, msg) {
new Assertion(val, msg).is.ok;
};
/**
* ### .notOk(object, [message])
*
* Asserts that `object` is falsy.
*
* assert.notOk('everything', 'this will fail');
* assert.notOk(false, 'this will pass');
*
* @name notOk
* @param {Mixed} object to test
* @param {String} message
* @api public
*/
assert.notOk = function (val, msg) {
new Assertion(val, msg).is.not.ok;
};
/**
* ### .equal(actual, expected, [message])
*
* Asserts non-strict equality (`==`) of `actual` and `expected`.
*
* assert.equal(3, '3', '== coerces values to strings');
*
* @name equal
* @param {Mixed} actual
* @param {Mixed} expected
* @param {String} message
* @api public
*/
assert.equal = function (act, exp, msg) {
var test = new Assertion(act, msg);
test.assert(
exp == flag(test, 'object')
, 'expected #{this} to equal #{exp}'
, 'expected #{this} to not equal #{act}'
, exp
, act
);
};
/**
* ### .notEqual(actual, expected, [message])
*
* Asserts non-strict inequality (`!=`) of `actual` and `expected`.
*
* assert.notEqual(3, 4, 'these numbers are not equal');
*
* @name notEqual
* @param {Mixed} actual
* @param {Mixed} expected
* @param {String} message
* @api public
*/
assert.notEqual = function (act, exp, msg) {
var test = new Assertion(act, msg);
test.assert(
exp != flag(test, 'object')
, 'expected #{this} to not equal #{exp}'
, 'expected #{this} to equal #{act}'
, exp
, act
);
};
/**
* ### .strictEqual(actual, expected, [message])
*
* Asserts strict equality (`===`) of `actual` and `expected`.
*
* assert.strictEqual(true, true, 'these booleans are strictly equal');
*
* @name strictEqual
* @param {Mixed} actual
* @param {Mixed} expected
* @param {String} message
* @api public
*/
assert.strictEqual = function (act, exp, msg) {
new Assertion(act, msg).to.equal(exp);
};
/**
* ### .notStrictEqual(actual, expected, [message])
*
* Asserts strict inequality (`!==`) of `actual` and `expected`.
*
* assert.notStrictEqual(3, '3', 'no coercion for strict equality');
*
* @name notStrictEqual
* @param {Mixed} actual
* @param {Mixed} expected
* @param {String} message
* @api public
*/
assert.notStrictEqual = function (act, exp, msg) {
new Assertion(act, msg).to.not.equal(exp);
};
/**
* ### .deepEqual(actual, expected, [message])
*
* Asserts that `actual` is deeply equal to `expected`.
*
* assert.deepEqual({ tea: 'green' }, { tea: 'green' });
*
* @name deepEqual
* @param {Mixed} actual
* @param {Mixed} expected
* @param {String} message
* @api public
*/
assert.deepEqual = function (act, exp, msg) {
new Assertion(act, msg).to.eql(exp);
};
/**
* ### .notDeepEqual(actual, expected, [message])
*
* Assert that `actual` is not deeply equal to `expected`.
*
* assert.notDeepEqual({ tea: 'green' }, { tea: 'jasmine' });
*
* @name notDeepEqual
* @param {Mixed} actual
* @param {Mixed} expected
* @param {String} message
* @api public
*/
assert.notDeepEqual = function (act, exp, msg) {
new Assertion(act, msg).to.not.eql(exp);
};
/**
* ### .isTrue(value, [message])
*
* Asserts that `value` is true.
*
* var teaServed = true;
* assert.isTrue(teaServed, 'the tea has been served');
*
* @name isTrue
* @param {Mixed} value
* @param {String} message
* @api public
*/
assert.isTrue = function (val, msg) {
new Assertion(val, msg).is['true'];
};
/**
* ### .isFalse(value, [message])
*
* Asserts that `value` is false.
*
* var teaServed = false;
* assert.isFalse(teaServed, 'no tea yet? hmm...');
*
* @name isFalse
* @param {Mixed} value
* @param {String} message
* @api public
*/
assert.isFalse = function (val, msg) {
new Assertion(val, msg).is['false'];
};
/**
* ### .isNull(value, [message])
*
* Asserts that `value` is null.
*
* assert.isNull(err, 'there was no error');
*
* @name isNull
* @param {Mixed} value
* @param {String} message
* @api public
*/
assert.isNull = function (val, msg) {
new Assertion(val, msg).to.equal(null);
};
/**
* ### .isNotNull(value, [message])
*
* Asserts that `value` is not null.
*
* var tea = 'tasty chai';
* assert.isNotNull(tea, 'great, time for tea!');
*
* @name isNotNull
* @param {Mixed} value
* @param {String} message
* @api public
*/
assert.isNotNull = function (val, msg) {
new Assertion(val, msg).to.not.equal(null);
};
/**
* ### .isUndefined(value, [message])
*
* Asserts that `value` is `undefined`.
*
* var tea;
* assert.isUndefined(tea, 'no tea defined');
*
* @name isUndefined
* @param {Mixed} value
* @param {String} message
* @api public
*/
assert.isUndefined = function (val, msg) {
new Assertion(val, msg).to.equal(undefined);
};
/**
* ### .isDefined(value, [message])
*
* Asserts that `value` is not `undefined`.
*
* var tea = 'cup of chai';
* assert.isDefined(tea, 'tea has been defined');
*
* @name isDefined
* @param {Mixed} value
* @param {String} message
* @api public
*/
assert.isDefined = function (val, msg) {
new Assertion(val, msg).to.not.equal(undefined);
};
/**
* ### .isFunction(value, [message])
*
* Asserts that `value` is a function.
*
* function serveTea() { return 'cup of tea'; };
* assert.isFunction(serveTea, 'great, we can have tea now');
*
* @name isFunction
* @param {Mixed} value
* @param {String} message
* @api public
*/
assert.isFunction = function (val, msg) {
new Assertion(val, msg).to.be.a('function');
};
/**
* ### .isNotFunction(value, [message])
*
* Asserts that `value` is _not_ a function.
*
* var serveTea = [ 'heat', 'pour', 'sip' ];
* assert.isNotFunction(serveTea, 'great, we have listed the steps');
*
* @name isNotFunction
* @param {Mixed} value
* @param {String} message
* @api public
*/
assert.isNotFunction = function (val, msg) {
new Assertion(val, msg).to.not.be.a('function');
};
/**
* ### .isObject(value, [message])
*
* Asserts that `value` is an object (as revealed by
* `Object.prototype.toString`).
*
* var selection = { name: 'Chai', serve: 'with spices' };
* assert.isObject(selection, 'tea selection is an object');
*
* @name isObject
* @param {Mixed} value
* @param {String} message
* @api public
*/
assert.isObject = function (val, msg) {
new Assertion(val, msg).to.be.a('object');
};
/**
* ### .isNotObject(value, [message])
*
* Asserts that `value` is _not_ an object.
*
* var selection = 'chai'
* assert.isObject(selection, 'tea selection is not an object');
* assert.isObject(null, 'null is not an object');
*
* @name isNotObject
* @param {Mixed} value
* @param {String} message
* @api public
*/
assert.isNotObject = function (val, msg) {
new Assertion(val, msg).to.not.be.a('object');
};
/**
* ### .isArray(value, [message])
*
* Asserts that `value` is an array.
*
* var menu = [ 'green', 'chai', 'oolong' ];
* assert.isArray(menu, 'what kind of tea do we want?');
*
* @name isArray
* @param {Mixed} value
* @param {String} message
* @api public
*/
assert.isArray = function (val, msg) {
new Assertion(val, msg).to.be.an('array');
};
/**
* ### .isNotArray(value, [message])
*
* Asserts that `value` is _not_ an array.
*
* var menu = 'green|chai|oolong';
* assert.isNotArray(menu, 'what kind of tea do we want?');
*
* @name isNotArray
* @param {Mixed} value
* @param {String} message
* @api public
*/
assert.isNotArray = function (val, msg) {
new Assertion(val, msg).to.not.be.an('array');
};
/**
* ### .isString(value, [message])
*
* Asserts that `value` is a string.
*
* var teaOrder = 'chai';
* assert.isString(teaOrder, 'order placed');
*
* @name isString
* @param {Mixed} value
* @param {String} message
* @api public
*/
assert.isString = function (val, msg) {
new Assertion(val, msg).to.be.a('string');
};
/**
* ### .isNotString(value, [message])
*
* Asserts that `value` is _not_ a string.
*
* var teaOrder = 4;
* assert.isNotString(teaOrder, 'order placed');
*
* @name isNotString
* @param {Mixed} value
* @param {String} message
* @api public
*/
assert.isNotString = function (val, msg) {
new Assertion(val, msg).to.not.be.a('string');
};
/**
* ### .isNumber(value, [message])
*
* Asserts that `value` is a number.
*
* var cups = 2;
* assert.isNumber(cups, 'how many cups');
*
* @name isNumber
* @param {Number} value
* @param {String} message
* @api public
*/
assert.isNumber = function (val, msg) {
new Assertion(val, msg).to.be.a('number');
};
/**
* ### .isNotNumber(value, [message])
*
* Asserts that `value` is _not_ a number.
*
* var cups = '2 cups please';
* assert.isNotNumber(cups, 'how many cups');
*
* @name isNotNumber
* @param {Mixed} value
* @param {String} message
* @api public
*/
assert.isNotNumber = function (val, msg) {
new Assertion(val, msg).to.not.be.a('number');
};
/**
* ### .isBoolean(value, [message])
*
* Asserts that `value` is a boolean.
*
* var teaReady = true
* , teaServed = false;
*
* assert.isBoolean(teaReady, 'is the tea ready');
* assert.isBoolean(teaServed, 'has tea been served');
*
* @name isBoolean
* @param {Mixed} value
* @param {String} message
* @api public
*/
assert.isBoolean = function (val, msg) {
new Assertion(val, msg).to.be.a('boolean');
};
/**
* ### .isNotBoolean(value, [message])
*
* Asserts that `value` is _not_ a boolean.
*
* var teaReady = 'yep'
* , teaServed = 'nope';
*
* assert.isNotBoolean(teaReady, 'is the tea ready');
* assert.isNotBoolean(teaServed, 'has tea been served');
*
* @name isNotBoolean
* @param {Mixed} value
* @param {String} message
* @api public
*/
assert.isNotBoolean = function (val, msg) {
new Assertion(val, msg).to.not.be.a('boolean');
};
/**
* ### .typeOf(value, name, [message])
*
* Asserts that `value`'s type is `name`, as determined by
* `Object.prototype.toString`.
*
* assert.typeOf({ tea: 'chai' }, 'object', 'we have an object');
* assert.typeOf(['chai', 'jasmine'], 'array', 'we have an array');
* assert.typeOf('tea', 'string', 'we have a string');
* assert.typeOf(/tea/, 'regexp', 'we have a regular expression');
* assert.typeOf(null, 'null', 'we have a null');
* assert.typeOf(undefined, 'undefined', 'we have an undefined');
*
* @name typeOf
* @param {Mixed} value
* @param {String} name
* @param {String} message
* @api public
*/
assert.typeOf = function (val, type, msg) {
new Assertion(val, msg).to.be.a(type);
};
/**
* ### .notTypeOf(value, name, [message])
*
* Asserts that `value`'s type is _not_ `name`, as determined by
* `Object.prototype.toString`.
*
* assert.notTypeOf('tea', 'number', 'strings are not numbers');
*
* @name notTypeOf
* @param {Mixed} value
* @param {String} typeof name
* @param {String} message
* @api public
*/
assert.notTypeOf = function (val, type, msg) {
new Assertion(val, msg).to.not.be.a(type);
};
/**
* ### .instanceOf(object, constructor, [message])
*
* Asserts that `value` is an instance of `constructor`.
*
* var Tea = function (name) { this.name = name; }
* , chai = new Tea('chai');
*
* assert.instanceOf(chai, Tea, 'chai is an instance of tea');
*
* @name instanceOf
* @param {Object} object
* @param {Constructor} constructor
* @param {String} message
* @api public
*/
assert.instanceOf = function (val, type, msg) {
new Assertion(val, msg).to.be.instanceOf(type);
};
/**
* ### .notInstanceOf(object, constructor, [message])
*
* Asserts `value` is not an instance of `constructor`.
*
* var Tea = function (name) { this.name = name; }
* , chai = new String('chai');
*
* assert.notInstanceOf(chai, Tea, 'chai is not an instance of tea');
*
* @name notInstanceOf
* @param {Object} object
* @param {Constructor} constructor
* @param {String} message
* @api public
*/
assert.notInstanceOf = function (val, type, msg) {
new Assertion(val, msg).to.not.be.instanceOf(type);
};
/**
* ### .include(haystack, needle, [message])
*
* Asserts that `haystack` includes `needle`. Works
* for strings and arrays.
*
* assert.include('foobar', 'bar', 'foobar contains string "bar"');
* assert.include([ 1, 2, 3 ], 3, 'array contains value');
*
* @name include
* @param {Array|String} haystack
* @param {Mixed} needle
* @param {String} message
* @api public
*/
assert.include = function (exp, inc, msg) {
var obj = new Assertion(exp, msg);
if (Array.isArray(exp)) {
obj.to.include(inc);
} else if ('string' === typeof exp) {
obj.to.contain.string(inc);
} else {
throw new chai.AssertionError(
'expected an array or string'
, null
, assert.include
);
}
};
/**
* ### .notInclude(haystack, needle, [message])
*
* Asserts that `haystack` does not include `needle`. Works
* for strings and arrays.
*i
* assert.notInclude('foobar', 'baz', 'string not include substring');
* assert.notInclude([ 1, 2, 3 ], 4, 'array not include contain value');
*
* @name notInclude
* @param {Array|String} haystack
* @param {Mixed} needle
* @param {String} message
* @api public
*/
assert.notInclude = function (exp, inc, msg) {
var obj = new Assertion(exp, msg);
if (Array.isArray(exp)) {
obj.to.not.include(inc);
} else if ('string' === typeof exp) {
obj.to.not.contain.string(inc);
} else {
throw new chai.AssertionError(
'expected an array or string'
, null
, assert.notInclude
);
}
};
/**
* ### .match(value, regexp, [message])
*
* Asserts that `value` matches the regular expression `regexp`.
*
* assert.match('foobar', /^foo/, 'regexp matches');
*
* @name match
* @param {Mixed} value
* @param {RegExp} regexp
* @param {String} message
* @api public
*/
assert.match = function (exp, re, msg) {
new Assertion(exp, msg).to.match(re);
};
/**
* ### .notMatch(value, regexp, [message])
*
* Asserts that `value` does not match the regular expression `regexp`.
*
* assert.notMatch('foobar', /^foo/, 'regexp does not match');
*
* @name notMatch
* @param {Mixed} value
* @param {RegExp} regexp
* @param {String} message
* @api public
*/
assert.notMatch = function (exp, re, msg) {
new Assertion(exp, msg).to.not.match(re);
};
/**
* ### .property(object, property, [message])
*
* Asserts that `object` has a property named by `property`.
*
* assert.property({ tea: { green: 'matcha' }}, 'tea');
*
* @name property
* @param {Object} object
* @param {String} property
* @param {String} message
* @api public
*/
assert.property = function (obj, prop, msg) {
new Assertion(obj, msg).to.have.property(prop);
};
/**
* ### .notProperty(object, property, [message])
*
* Asserts that `object` does _not_ have a property named by `property`.
*
* assert.notProperty({ tea: { green: 'matcha' }}, 'coffee');
*
* @name notProperty
* @param {Object} object
* @param {String} property
* @param {String} message
* @api public
*/
assert.notProperty = function (obj, prop, msg) {
new Assertion(obj, msg).to.not.have.property(prop);
};
/**
* ### .deepProperty(object, property, [message])
*
* Asserts that `object` has a property named by `property`, which can be a
* string using dot- and bracket-notation for deep reference.
*
* assert.deepProperty({ tea: { green: 'matcha' }}, 'tea.green');
*
* @name deepProperty
* @param {Object} object
* @param {String} property
* @param {String} message
* @api public
*/
assert.deepProperty = function (obj, prop, msg) {
new Assertion(obj, msg).to.have.deep.property(prop);
};
/**
* ### .notDeepProperty(object, property, [message])
*
* Asserts that `object` does _not_ have a property named by `property`, which
* can be a string using dot- and bracket-notation for deep reference.
*
* assert.notDeepProperty({ tea: { green: 'matcha' }}, 'tea.oolong');
*
* @name notDeepProperty
* @param {Object} object
* @param {String} property
* @param {String} message
* @api public
*/
assert.notDeepProperty = function (obj, prop, msg) {
new Assertion(obj, msg).to.not.have.deep.property(prop);
};
/**
* ### .propertyVal(object, property, value, [message])
*
* Asserts that `object` has a property named by `property` with value given
* by `value`.
*
* assert.propertyVal({ tea: 'is good' }, 'tea', 'is good');
*
* @name propertyVal
* @param {Object} object
* @param {String} property
* @param {Mixed} value
* @param {String} message
* @api public
*/
assert.propertyVal = function (obj, prop, val, msg) {
new Assertion(obj, msg).to.have.property(prop, val);
};
/**
* ### .propertyNotVal(object, property, value, [message])
*
* Asserts that `object` has a property named by `property`, but with a value
* different from that given by `value`.
*
* assert.propertyNotVal({ tea: 'is good' }, 'tea', 'is bad');
*
* @name propertyNotVal
* @param {Object} object
* @param {String} property
* @param {Mixed} value
* @param {String} message
* @api public
*/
assert.propertyNotVal = function (obj, prop, val, msg) {
new Assertion(obj, msg).to.not.have.property(prop, val);
};
/**
* ### .deepPropertyVal(object, property, value, [message])
*
* Asserts that `object` has a property named by `property` with value given
* by `value`. `property` can use dot- and bracket-notation for deep
* reference.
*
* assert.deepPropertyVal({ tea: { green: 'matcha' }}, 'tea.green', 'matcha');
*
* @name deepPropertyVal
* @param {Object} object
* @param {String} property
* @param {Mixed} value
* @param {String} message
* @api public
*/
assert.deepPropertyVal = function (obj, prop, val, msg) {
new Assertion(obj, msg).to.have.deep.property(prop, val);
};
/**
* ### .deepPropertyNotVal(object, property, value, [message])
*
* Asserts that `object` has a property named by `property`, but with a value
* different from that given by `value`. `property` can use dot- and
* bracket-notation for deep reference.
*
* assert.deepPropertyNotVal({ tea: { green: 'matcha' }}, 'tea.green', 'konacha');
*
* @name deepPropertyNotVal
* @param {Object} object
* @param {String} property
* @param {Mixed} value
* @param {String} message
* @api public
*/
assert.deepPropertyNotVal = function (obj, prop, val, msg) {
new Assertion(obj, msg).to.not.have.deep.property(prop, val);
};
/**
* ### .lengthOf(object, length, [message])
*
* Asserts that `object` has a `length` property with the expected value.
*
* assert.lengthOf([1,2,3], 3, 'array has length of 3');
* assert.lengthOf('foobar', 5, 'string has length of 6');
*
* @name lengthOf
* @param {Mixed} object
* @param {Number} length
* @param {String} message
* @api public
*/
assert.lengthOf = function (exp, len, msg) {
new Assertion(exp, msg).to.have.length(len);
};
/**
* ### .throws(function, [constructor/string/regexp], [string/regexp], [message])
*
* Asserts that `function` will throw an error that is an instance of
* `constructor`, or alternately that it will throw an error with message
* matching `regexp`.
*
* assert.throw(fn, 'function throws a reference error');
* assert.throw(fn, /function throws a reference error/);
* assert.throw(fn, ReferenceError);
* assert.throw(fn, ReferenceError, 'function throws a reference error');
* assert.throw(fn, ReferenceError, /function throws a reference error/);
*
* @name throws
* @alias throw
* @alias Throw
* @param {Function} function
* @param {ErrorConstructor} constructor
* @param {RegExp} regexp
* @param {String} message
* @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types
* @api public
*/
assert.Throw = function (fn, errt, errs, msg) {
if ('string' === typeof errt || errt instanceof RegExp) {
errs = errt;
errt = null;
}
new Assertion(fn, msg).to.Throw(errt, errs);
};
/**
* ### .doesNotThrow(function, [constructor/regexp], [message])
*
* Asserts that `function` will _not_ throw an error that is an instance of
* `constructor`, or alternately that it will not throw an error with message
* matching `regexp`.
*
* assert.doesNotThrow(fn, Error, 'function does not throw');
*
* @name doesNotThrow
* @param {Function} function
* @param {ErrorConstructor} constructor
* @param {RegExp} regexp
* @param {String} message
* @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types
* @api public
*/
assert.doesNotThrow = function (fn, type, msg) {
if ('string' === typeof type) {
msg = type;
type = null;
}
new Assertion(fn, msg).to.not.Throw(type);
};
/**
* ### .operator(val1, operator, val2, [message])
*
* Compares two values using `operator`.
*
* assert.operator(1, '<', 2, 'everything is ok');
* assert.operator(1, '>', 2, 'this will fail');
*
* @name operator
* @param {Mixed} val1
* @param {String} operator
* @param {Mixed} val2
* @param {String} message
* @api public
*/
assert.operator = function (val, operator, val2, msg) {
if (!~['==', '===', '>', '>=', '<', '<=', '!=', '!=='].indexOf(operator)) {
throw new Error('Invalid operator "' + operator + '"');
}
var test = new Assertion(eval(val + operator + val2), msg);
test.assert(
true === flag(test, 'object')
, 'expected ' + util.inspect(val) + ' to be ' + operator + ' ' + util.inspect(val2)
, 'expected ' + util.inspect(val) + ' to not be ' + operator + ' ' + util.inspect(val2) );
};
/**
* ### .closeTo(actual, expected, delta, [message])
*
* Asserts that the target is equal `expected`, to within a +/- `delta` range.
*
* assert.closeTo(1.5, 1, 0.5, 'numbers are close');
*
* @name closeTo
* @param {Number} actual
* @param {Number} expected
* @param {Number} delta
* @param {String} message
* @api public
*/
assert.closeTo = function (act, exp, delta, msg) {
new Assertion(act, msg).to.be.closeTo(exp, delta);
};
/**
* ### .sameMembers(set1, set2, [message])
*
* Asserts that `set1` and `set2` have the same members.
* Order is not taken into account.
*
* assert.sameMembers([ 1, 2, 3 ], [ 2, 1, 3 ], 'same members');
*
* @name sameMembers
* @param {Array} superset
* @param {Array} subset
* @param {String} message
* @api public
*/
assert.sameMembers = function (set1, set2, msg) {
new Assertion(set1, msg).to.have.same.members(set2);
}
/**
* ### .includeMembers(superset, subset, [message])
*
* Asserts that `subset` is included in `superset`.
* Order is not taken into account.
*
* assert.includeMembers([ 1, 2, 3 ], [ 2, 1 ], 'include members');
*
* @name includeMembers
* @param {Array} superset
* @param {Array} subset
* @param {String} message
* @api public
*/
assert.includeMembers = function (superset, subset, msg) {
new Assertion(superset, msg).to.include.members(subset);
}
/*!
* Undocumented / untested
*/
assert.ifError = function (val, msg) {
new Assertion(val, msg).to.not.be.ok;
};
/*!
* Aliases.
*/
(function alias(name, as){
assert[as] = assert[name];
return alias;
})
('Throw', 'throw')
('Throw', 'throws');
};
},{}],54:[function(require,module,exports){
/*!
* chai
* Copyright(c) 2011-2013 Jake Luer <jake@alogicalparadox.com>
* MIT Licensed
*/
module.exports = function (chai, util) {
chai.expect = function (val, message) {
return new chai.Assertion(val, message);
};
};
},{}],55:[function(require,module,exports){
/*!
* chai
* Copyright(c) 2011-2013 Jake Luer <jake@alogicalparadox.com>
* MIT Licensed
*/
module.exports = function (chai, util) {
var Assertion = chai.Assertion;
function loadShould () {
// modify Object.prototype to have `should`
Object.defineProperty(Object.prototype, 'should',
{
set: function (value) {
// See https://github.com/chaijs/chai/issues/86: this makes
// `whatever.should = someValue` actually set `someValue`, which is
// especially useful for `global.should = require('chai').should()`.
//
// Note that we have to use [[DefineProperty]] instead of [[Put]]
// since otherwise we would trigger this very setter!
Object.defineProperty(this, 'should', {
value: value,
enumerable: true,
configurable: true,
writable: true
});
}
, get: function(){
if (this instanceof String || this instanceof Number) {
return new Assertion(this.constructor(this));
} else if (this instanceof Boolean) {
return new Assertion(this == true);
}
return new Assertion(this);
}
, configurable: true
});
var should = {};
should.equal = function (val1, val2, msg) {
new Assertion(val1, msg).to.equal(val2);
};
should.Throw = function (fn, errt, errs, msg) {
new Assertion(fn, msg).to.Throw(errt, errs);
};
should.exist = function (val, msg) {
new Assertion(val, msg).to.exist;
}
// negation
should.not = {}
should.not.equal = function (val1, val2, msg) {
new Assertion(val1, msg).to.not.equal(val2);
};
should.not.Throw = function (fn, errt, errs, msg) {
new Assertion(fn, msg).to.not.Throw(errt, errs);
};
should.not.exist = function (val, msg) {
new Assertion(val, msg).to.not.exist;
}
should['throw'] = should['Throw'];
should.not['throw'] = should.not['Throw'];
return should;
};
chai.should = loadShould;
chai.Should = loadShould;
};
},{}],56:[function(require,module,exports){
/*!
* Chai - addChainingMethod utility
* Copyright(c) 2012-2013 Jake Luer <jake@alogicalparadox.com>
* MIT Licensed
*/
/*!
* Module dependencies
*/
var transferFlags = require('./transferFlags');
/*!
* Module variables
*/
// Check whether `__proto__` is supported
var hasProtoSupport = '__proto__' in Object;
// Without `__proto__` support, this module will need to add properties to a function.
// However, some Function.prototype methods cannot be overwritten,
// and there seems no easy cross-platform way to detect them (@see chaijs/chai/issues/69).
var excludeNames = /^(?:length|name|arguments|caller)$/;
// Cache `Function` properties
var call = Function.prototype.call,
apply = Function.prototype.apply;
/**
* ### addChainableMethod (ctx, name, method, chainingBehavior)
*
* Adds a method to an object, such that the method can also be chained.
*
* utils.addChainableMethod(chai.Assertion.prototype, 'foo', function (str) {
* var obj = utils.flag(this, 'object');
* new chai.Assertion(obj).to.be.equal(str);
* });
*
* Can also be accessed directly from `chai.Assertion`.
*
* chai.Assertion.addChainableMethod('foo', fn, chainingBehavior);
*
* The result can then be used as both a method assertion, executing both `method` and
* `chainingBehavior`, or as a language chain, which only executes `chainingBehavior`.
*
* expect(fooStr).to.be.foo('bar');
* expect(fooStr).to.be.foo.equal('foo');
*
* @param {Object} ctx object to which the method is added
* @param {String} name of method to add
* @param {Function} method function to be used for `name`, when called
* @param {Function} chainingBehavior function to be called every time the property is accessed
* @name addChainableMethod
* @api public
*/
module.exports = function (ctx, name, method, chainingBehavior) {
if (typeof chainingBehavior !== 'function')
chainingBehavior = function () { };
Object.defineProperty(ctx, name,
{ get: function () {
chainingBehavior.call(this);
var assert = function () {
var result = method.apply(this, arguments);
return result === undefined ? this : result;
};
// Use `__proto__` if available
if (hasProtoSupport) {
// Inherit all properties from the object by replacing the `Function` prototype
var prototype = assert.__proto__ = Object.create(this);
// Restore the `call` and `apply` methods from `Function`
prototype.call = call;
prototype.apply = apply;
}
// Otherwise, redefine all properties (slow!)
else {
var asserterNames = Object.getOwnPropertyNames(ctx);
asserterNames.forEach(function (asserterName) {
if (!excludeNames.test(asserterName)) {
var pd = Object.getOwnPropertyDescriptor(ctx, asserterName);
Object.defineProperty(assert, asserterName, pd);
}
});
}
transferFlags(this, assert);
return assert;
}
, configurable: true
});
};
},{"./transferFlags":72}],57:[function(require,module,exports){
/*!
* Chai - addMethod utility
* Copyright(c) 2012-2013 Jake Luer <jake@alogicalparadox.com>
* MIT Licensed
*/
/**
* ### .addMethod (ctx, name, method)
*
* Adds a method to the prototype of an object.
*
* utils.addMethod(chai.Assertion.prototype, 'foo', function (str) {
* var obj = utils.flag(this, 'object');
* new chai.Assertion(obj).to.be.equal(str);
* });
*
* Can also be accessed directly from `chai.Assertion`.
*
* chai.Assertion.addMethod('foo', fn);
*
* Then can be used as any other assertion.
*
* expect(fooStr).to.be.foo('bar');
*
* @param {Object} ctx object to which the method is added
* @param {String} name of method to add
* @param {Function} method function to be used for name
* @name addMethod
* @api public
*/
module.exports = function (ctx, name, method) {
ctx[name] = function () {
var result = method.apply(this, arguments);
return result === undefined ? this : result;
};
};
},{}],58:[function(require,module,exports){
/*!
* Chai - addProperty utility
* Copyright(c) 2012-2013 Jake Luer <jake@alogicalparadox.com>
* MIT Licensed
*/
/**
* ### addProperty (ctx, name, getter)
*
* Adds a property to the prototype of an object.
*
* utils.addProperty(chai.Assertion.prototype, 'foo', function () {
* var obj = utils.flag(this, 'object');
* new chai.Assertion(obj).to.be.instanceof(Foo);
* });
*
* Can also be accessed directly from `chai.Assertion`.
*
* chai.Assertion.addProperty('foo', fn);
*
* Then can be used as any other assertion.
*
* expect(myFoo).to.be.foo;
*
* @param {Object} ctx object to which the property is added
* @param {String} name of property to add
* @param {Function} getter function to be used for name
* @name addProperty
* @api public
*/
module.exports = function (ctx, name, getter) {
Object.defineProperty(ctx, name,
{ get: function () {
var result = getter.call(this);
return result === undefined ? this : result;
}
, configurable: true
});
};
},{}],59:[function(require,module,exports){
/*!
* Chai - flag utility
* Copyright(c) 2012-2013 Jake Luer <jake@alogicalparadox.com>
* MIT Licensed
*/
/**
* ### flag(object ,key, [value])
*
* Get or set a flag value on an object. If a
* value is provided it will be set, else it will
* return the currently set value or `undefined` if
* the value is not set.
*
* utils.flag(this, 'foo', 'bar'); // setter
* utils.flag(this, 'foo'); // getter, returns `bar`
*
* @param {Object} object (constructed Assertion
* @param {String} key
* @param {Mixed} value (optional)
* @name flag
* @api private
*/
module.exports = function (obj, key, value) {
var flags = obj.__flags || (obj.__flags = Object.create(null));
if (arguments.length === 3) {
flags[key] = value;
} else {
return flags[key];
}
};
},{}],60:[function(require,module,exports){
/*!
* Chai - getActual utility
* Copyright(c) 2012-2013 Jake Luer <jake@alogicalparadox.com>
* MIT Licensed
*/
/**
* # getActual(object, [actual])
*
* Returns the `actual` value for an Assertion
*
* @param {Object} object (constructed Assertion)
* @param {Arguments} chai.Assertion.prototype.assert arguments
*/
module.exports = function (obj, args) {
var actual = args[4];
return 'undefined' !== typeof actual ? actual : obj._obj;
};
},{}],61:[function(require,module,exports){
/*!
* Chai - getEnumerableProperties utility
* Copyright(c) 2012-2013 Jake Luer <jake@alogicalparadox.com>
* MIT Licensed
*/
/**
* ### .getEnumerableProperties(object)
*
* This allows the retrieval of enumerable property names of an object,
* inherited or not.
*
* @param {Object} object
* @returns {Array}
* @name getEnumerableProperties
* @api public
*/
module.exports = function getEnumerableProperties(object) {
var result = [];
for (var name in object) {
result.push(name);
}
return result;
};
},{}],62:[function(require,module,exports){
/*!
* Chai - message composition utility
* Copyright(c) 2012-2013 Jake Luer <jake@alogicalparadox.com>
* MIT Licensed
*/
/*!
* Module dependancies
*/
var flag = require('./flag')
, getActual = require('./getActual')
, inspect = require('./inspect')
, objDisplay = require('./objDisplay');
/**
* ### .getMessage(object, message, negateMessage)
*
* Construct the error message based on flags
* and template tags. Template tags will return
* a stringified inspection of the object referenced.
*
* Message template tags:
* - `#{this}` current asserted object
* - `#{act}` actual value
* - `#{exp}` expected value
*
* @param {Object} object (constructed Assertion)
* @param {Arguments} chai.Assertion.prototype.assert arguments
* @name getMessage
* @api public
*/
module.exports = function (obj, args) {
var negate = flag(obj, 'negate')
, val = flag(obj, 'object')
, expected = args[3]
, actual = getActual(obj, args)
, msg = negate ? args[2] : args[1]
, flagMsg = flag(obj, 'message');
msg = msg || '';
msg = msg
.replace(/#{this}/g, objDisplay(val))
.replace(/#{act}/g, objDisplay(actual))
.replace(/#{exp}/g, objDisplay(expected));
return flagMsg ? flagMsg + ': ' + msg : msg;
};
},{"./flag":59,"./getActual":60,"./inspect":67,"./objDisplay":68}],63:[function(require,module,exports){
/*!
* Chai - getName utility
* Copyright(c) 2012-2013 Jake Luer <jake@alogicalparadox.com>
* MIT Licensed
*/
/**
* # getName(func)
*
* Gets the name of a function, in a cross-browser way.
*
* @param {Function} a function (usually a constructor)
*/
module.exports = function (func) {
if (func.name) return func.name;
var match = /^\s?function ([^(]*)\(/.exec(func);
return match && match[1] ? match[1] : "";
};
},{}],64:[function(require,module,exports){
/*!
* Chai - getPathValue utility
* Copyright(c) 2012-2013 Jake Luer <jake@alogicalparadox.com>
* @see https://github.com/logicalparadox/filtr
* MIT Licensed
*/
/**
* ### .getPathValue(path, object)
*
* This allows the retrieval of values in an
* object given a string path.
*
* var obj = {
* prop1: {
* arr: ['a', 'b', 'c']
* , str: 'Hello'
* }
* , prop2: {
* arr: [ { nested: 'Universe' } ]
* , str: 'Hello again!'
* }
* }
*
* The following would be the results.
*
* getPathValue('prop1.str', obj); // Hello
* getPathValue('prop1.att[2]', obj); // b
* getPathValue('prop2.arr[0].nested', obj); // Universe
*
* @param {String} path
* @param {Object} object
* @returns {Object} value or `undefined`
* @name getPathValue
* @api public
*/
var getPathValue = module.exports = function (path, obj) {
var parsed = parsePath(path);
return _getPathValue(parsed, obj);
};
/*!
* ## parsePath(path)
*
* Helper function used to parse string object
* paths. Use in conjunction with `_getPathValue`.
*
* var parsed = parsePath('myobject.property.subprop');
*
* ### Paths:
*
* * Can be as near infinitely deep and nested
* * Arrays are also valid using the formal `myobject.document[3].property`.
*
* @param {String} path
* @returns {Object} parsed
* @api private
*/
function parsePath (path) {
var str = path.replace(/\[/g, '.[')
, parts = str.match(/(\\\.|[^.]+?)+/g);
return parts.map(function (value) {
var re = /\[(\d+)\]$/
, mArr = re.exec(value)
if (mArr) return { i: parseFloat(mArr[1]) };
else return { p: value };
});
};
/*!
* ## _getPathValue(parsed, obj)
*
* Helper companion function for `.parsePath` that returns
* the value located at the parsed address.
*
* var value = getPathValue(parsed, obj);
*
* @param {Object} parsed definition from `parsePath`.
* @param {Object} object to search against
* @returns {Object|Undefined} value
* @api private
*/
function _getPathValue (parsed, obj) {
var tmp = obj
, res;
for (var i = 0, l = parsed.length; i < l; i++) {
var part = parsed[i];
if (tmp) {
if ('undefined' !== typeof part.p)
tmp = tmp[part.p];
else if ('undefined' !== typeof part.i)
tmp = tmp[part.i];
if (i == (l - 1)) res = tmp;
} else {
res = undefined;
}
}
return res;
};
},{}],65:[function(require,module,exports){
/*!
* Chai - getProperties utility
* Copyright(c) 2012-2013 Jake Luer <jake@alogicalparadox.com>
* MIT Licensed
*/
/**
* ### .getProperties(object)
*
* This allows the retrieval of property names of an object, enumerable or not,
* inherited or not.
*
* @param {Object} object
* @returns {Array}
* @name getProperties
* @api public
*/
module.exports = function getProperties(object) {
var result = Object.getOwnPropertyNames(subject);
function addProperty(property) {
if (result.indexOf(property) === -1) {
result.push(property);
}
}
var proto = Object.getPrototypeOf(subject);
while (proto !== null) {
Object.getOwnPropertyNames(proto).forEach(addProperty);
proto = Object.getPrototypeOf(proto);
}
return result;
};
},{}],66:[function(require,module,exports){
/*!
* chai
* Copyright(c) 2011 Jake Luer <jake@alogicalparadox.com>
* MIT Licensed
*/
/*!
* Main exports
*/
var exports = module.exports = {};
/*!
* test utility
*/
exports.test = require('./test');
/*!
* type utility
*/
exports.type = require('./type');
/*!
* message utility
*/
exports.getMessage = require('./getMessage');
/*!
* actual utility
*/
exports.getActual = require('./getActual');
/*!
* Inspect util
*/
exports.inspect = require('./inspect');
/*!
* Object Display util
*/
exports.objDisplay = require('./objDisplay');
/*!
* Flag utility
*/
exports.flag = require('./flag');
/*!
* Flag transferring utility
*/
exports.transferFlags = require('./transferFlags');
/*!
* Deep equal utility
*/
exports.eql = require('deep-eql');
/*!
* Deep path value
*/
exports.getPathValue = require('./getPathValue');
/*!
* Function name
*/
exports.getName = require('./getName');
/*!
* add Property
*/
exports.addProperty = require('./addProperty');
/*!
* add Method
*/
exports.addMethod = require('./addMethod');
/*!
* overwrite Property
*/
exports.overwriteProperty = require('./overwriteProperty');
/*!
* overwrite Method
*/
exports.overwriteMethod = require('./overwriteMethod');
/*!
* Add a chainable method
*/
exports.addChainableMethod = require('./addChainableMethod');
},{"./addChainableMethod":56,"./addMethod":57,"./addProperty":58,"./flag":59,"./getActual":60,"./getMessage":62,"./getName":63,"./getPathValue":64,"./inspect":67,"./objDisplay":68,"./overwriteMethod":69,"./overwriteProperty":70,"./test":71,"./transferFlags":72,"./type":73,"deep-eql":75}],67:[function(require,module,exports){
// This is (almost) directly from Node.js utils
// https://github.com/joyent/node/blob/f8c335d0caf47f16d31413f89aa28eda3878e3aa/lib/util.js
var getName = require('./getName');
var getProperties = require('./getProperties');
var getEnumerableProperties = require('./getEnumerableProperties');
module.exports = inspect;
/**
* 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 {Boolean} showHidden Flag that shows hidden (not enumerable)
* properties of objects.
* @param {Number} depth Depth in which to descend in object. Default is 2.
* @param {Boolean} colors Flag to turn on ANSI escape codes to color the
* output. Default is false (no coloring).
*/
function inspect(obj, showHidden, depth, colors) {
var ctx = {
showHidden: showHidden,
seen: [],
stylize: function (str) { return str; }
};
return formatValue(ctx, obj, (typeof depth === 'undefined' ? 2 : depth));
}
// https://gist.github.com/1044128/
var getOuterHTML = function(element) {
if ('outerHTML' in element) return element.outerHTML;
var ns = "http://www.w3.org/1999/xhtml";
var container = document.createElementNS(ns, '_');
var elemProto = (window.HTMLElement || window.Element).prototype;
var xmlSerializer = new XMLSerializer();
var html;
if (document.xmlVersion) {
return xmlSerializer.serializeToString(element);
} else {
container.appendChild(element.cloneNode(false));
html = container.innerHTML.replace('><', '>' + element.innerHTML + '<');
container.innerHTML = '';
return html;
}
};
// Returns true if object is a DOM element.
var isDOMElement = function (object) {
if (typeof HTMLElement === 'object') {
return object instanceof HTMLElement;
} else {
return object &&
typeof object === 'object' &&
object.nodeType === 1 &&
typeof object.nodeName === 'string';
}
};
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 (value && typeof value.inspect === 'function' &&
// 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);
if (typeof ret !== 'string') {
ret = formatValue(ctx, ret, recurseTimes);
}
return ret;
}
// Primitive types cannot have properties
var primitive = formatPrimitive(ctx, value);
if (primitive) {
return primitive;
}
// If it's DOM elem, get outer HTML.
if (isDOMElement(value)) {
return getOuterHTML(value);
}
// Look up the keys of the object.
var visibleKeys = getEnumerableProperties(value);
var keys = ctx.showHidden ? getProperties(value) : visibleKeys;
// Some type of object without properties can be shortcutted.
// In IE, errors have a single `stack` property, or if they are vanilla `Error`,
// a `stack` plus `description` property; ignore those for consistency.
if (keys.length === 0 || (isError(value) && (
(keys.length === 1 && keys[0] === 'stack') ||
(keys.length === 2 && keys[0] === 'description' && keys[1] === 'stack')
))) {
if (typeof value === 'function') {
var name = getName(value);
var nameSuffix = name ? ': ' + name : '';
return ctx.stylize('[Function' + nameSuffix + ']', 'special');
}
if (isRegExp(value)) {
return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
}
if (isDate(value)) {
return ctx.stylize(Date.prototype.toUTCString.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 (typeof value === 'function') {
var name = getName(value);
var nameSuffix = name ? ': ' + name : '';
base = ' [Function' + nameSuffix + ']';
}
// 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)) {
return 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) {
switch (typeof value) {
case 'undefined':
return ctx.stylize('undefined', 'undefined');
case 'string':
var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
.replace(/'/g, "\\'")
.replace(/\\"/g, '"') + '\'';
return ctx.stylize(simple, 'string');
case 'number':
return ctx.stylize('' + value, 'number');
case 'boolean':
return ctx.stylize('' + value, 'boolean');
}
// For some reason typeof null is "object", so special case here.
if (value === null) {
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 (Object.prototype.hasOwnProperty.call(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;
if (value.__lookupGetter__) {
if (value.__lookupGetter__(key)) {
if (value.__lookupSetter__(key)) {
str = ctx.stylize('[Getter/Setter]', 'special');
} else {
str = ctx.stylize('[Getter]', 'special');
}
} else {
if (value.__lookupSetter__(key)) {
str = ctx.stylize('[Setter]', 'special');
}
}
}
if (visibleKeys.indexOf(key) < 0) {
name = '[' + key + ']';
}
if (!str) {
if (ctx.seen.indexOf(value[key]) < 0) {
if (recurseTimes === null) {
str = formatValue(ctx, value[key], null);
} else {
str = formatValue(ctx, value[key], 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 (typeof name === 'undefined') {
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.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];
}
function isArray(ar) {
return Array.isArray(ar) ||
(typeof ar === 'object' && objectToString(ar) === '[object Array]');
}
function isRegExp(re) {
return typeof re === 'object' && objectToString(re) === '[object RegExp]';
}
function isDate(d) {
return typeof d === 'object' && objectToString(d) === '[object Date]';
}
function isError(e) {
return typeof e === 'object' && objectToString(e) === '[object Error]';
}
function objectToString(o) {
return Object.prototype.toString.call(o);
}
},{"./getEnumerableProperties":61,"./getName":63,"./getProperties":65}],68:[function(require,module,exports){
/*!
* Chai - flag utility
* Copyright(c) 2012-2013 Jake Luer <jake@alogicalparadox.com>
* MIT Licensed
*/
/*!
* Module dependancies
*/
var inspect = require('./inspect');
/**
* ### .objDisplay (object)
*
* Determines if an object or an array matches
* criteria to be inspected in-line for error
* messages or should be truncated.
*
* @param {Mixed} javascript object to inspect
* @name objDisplay
* @api public
*/
module.exports = function (obj) {
var str = inspect(obj)
, type = Object.prototype.toString.call(obj);
if (str.length >= 40) {
if (type === '[object Function]') {
return !obj.name || obj.name === ''
? '[Function]'
: '[Function: ' + obj.name + ']';
} else if (type === '[object Array]') {
return '[ Array(' + obj.length + ') ]';
} else if (type === '[object Object]') {
var keys = Object.keys(obj)
, kstr = keys.length > 2
? keys.splice(0, 2).join(', ') + ', ...'
: keys.join(', ');
return '{ Object (' + kstr + ') }';
} else {
return str;
}
} else {
return str;
}
};
},{"./inspect":67}],69:[function(require,module,exports){
/*!
* Chai - overwriteMethod utility
* Copyright(c) 2012-2013 Jake Luer <jake@alogicalparadox.com>
* MIT Licensed
*/
/**
* ### overwriteMethod (ctx, name, fn)
*
* Overwites an already existing method and provides
* access to previous function. Must return function
* to be used for name.
*
* utils.overwriteMethod(chai.Assertion.prototype, 'equal', function (_super) {
* return function (str) {
* var obj = utils.flag(this, 'object');
* if (obj instanceof Foo) {
* new chai.Assertion(obj.value).to.equal(str);
* } else {
* _super.apply(this, arguments);
* }
* }
* });
*
* Can also be accessed directly from `chai.Assertion`.
*
* chai.Assertion.overwriteMethod('foo', fn);
*
* Then can be used as any other assertion.
*
* expect(myFoo).to.equal('bar');
*
* @param {Object} ctx object whose method is to be overwritten
* @param {String} name of method to overwrite
* @param {Function} method function that returns a function to be used for name
* @name overwriteMethod
* @api public
*/
module.exports = function (ctx, name, method) {
var _method = ctx[name]
, _super = function () { return this; };
if (_method && 'function' === typeof _method)
_super = _method;
ctx[name] = function () {
var result = method(_super).apply(this, arguments);
return result === undefined ? this : result;
}
};
},{}],70:[function(require,module,exports){
/*!
* Chai - overwriteProperty utility
* Copyright(c) 2012-2013 Jake Luer <jake@alogicalparadox.com>
* MIT Licensed
*/
/**
* ### overwriteProperty (ctx, name, fn)
*
* Overwites an already existing property getter and provides
* access to previous value. Must return function to use as getter.
*
* utils.overwriteProperty(chai.Assertion.prototype, 'ok', function (_super) {
* return function () {
* var obj = utils.flag(this, 'object');
* if (obj instanceof Foo) {
* new chai.Assertion(obj.name).to.equal('bar');
* } else {
* _super.call(this);
* }
* }
* });
*
*
* Can also be accessed directly from `chai.Assertion`.
*
* chai.Assertion.overwriteProperty('foo', fn);
*
* Then can be used as any other assertion.
*
* expect(myFoo).to.be.ok;
*
* @param {Object} ctx object whose property is to be overwritten
* @param {String} name of property to overwrite
* @param {Function} getter function that returns a getter function to be used for name
* @name overwriteProperty
* @api public
*/
module.exports = function (ctx, name, getter) {
var _get = Object.getOwnPropertyDescriptor(ctx, name)
, _super = function () {};
if (_get && 'function' === typeof _get.get)
_super = _get.get
Object.defineProperty(ctx, name,
{ get: function () {
var result = getter(_super).call(this);
return result === undefined ? this : result;
}
, configurable: true
});
};
},{}],71:[function(require,module,exports){
/*!
* Chai - test utility
* Copyright(c) 2012-2013 Jake Luer <jake@alogicalparadox.com>
* MIT Licensed
*/
/*!
* Module dependancies
*/
var flag = require('./flag');
/**
* # test(object, expression)
*
* Test and object for expression.
*
* @param {Object} object (constructed Assertion)
* @param {Arguments} chai.Assertion.prototype.assert arguments
*/
module.exports = function (obj, args) {
var negate = flag(obj, 'negate')
, expr = args[0];
return negate ? !expr : expr;
};
},{"./flag":59}],72:[function(require,module,exports){
/*!
* Chai - transferFlags utility
* Copyright(c) 2012-2013 Jake Luer <jake@alogicalparadox.com>
* MIT Licensed
*/
/**
* ### transferFlags(assertion, object, includeAll = true)
*
* Transfer all the flags for `assertion` to `object`. If
* `includeAll` is set to `false`, then the base Chai
* assertion flags (namely `object`, `ssfi`, and `message`)
* will not be transferred.
*
*
* var newAssertion = new Assertion();
* utils.transferFlags(assertion, newAssertion);
*
* var anotherAsseriton = new Assertion(myObj);
* utils.transferFlags(assertion, anotherAssertion, false);
*
* @param {Assertion} assertion the assertion to transfer the flags from
* @param {Object} object the object to transfer the flags too; usually a new assertion
* @param {Boolean} includeAll
* @name getAllFlags
* @api private
*/
module.exports = function (assertion, object, includeAll) {
var flags = assertion.__flags || (assertion.__flags = Object.create(null));
if (!object.__flags) {
object.__flags = Object.create(null);
}
includeAll = arguments.length === 3 ? includeAll : true;
for (var flag in flags) {
if (includeAll ||
(flag !== 'object' && flag !== 'ssfi' && flag != 'message')) {
object.__flags[flag] = flags[flag];
}
}
};
},{}],73:[function(require,module,exports){
/*!
* Chai - type utility
* Copyright(c) 2012-2013 Jake Luer <jake@alogicalparadox.com>
* MIT Licensed
*/
/*!
* Detectable javascript natives
*/
var natives = {
'[object Arguments]': 'arguments'
, '[object Array]': 'array'
, '[object Date]': 'date'
, '[object Function]': 'function'
, '[object Number]': 'number'
, '[object RegExp]': 'regexp'
, '[object String]': 'string'
};
/**
* ### type(object)
*
* Better implementation of `typeof` detection that can
* be used cross-browser. Handles the inconsistencies of
* Array, `null`, and `undefined` detection.
*
* utils.type({}) // 'object'
* utils.type(null) // `null'
* utils.type(undefined) // `undefined`
* utils.type([]) // `array`
*
* @param {Mixed} object to detect type of
* @name type
* @api private
*/
module.exports = function (obj) {
var str = Object.prototype.toString.call(obj);
if (natives[str]) return natives[str];
if (obj === null) return 'null';
if (obj === undefined) return 'undefined';
if (obj === Object(obj)) return 'object';
return typeof obj;
};
},{}],74:[function(require,module,exports){
/*!
* assertion-error
* Copyright(c) 2013 Jake Luer <jake@qualiancy.com>
* MIT Licensed
*/
/*!
* Return a function that will copy properties from
* one object to another excluding any originally
* listed. Returned function will create a new `{}`.
*
* @param {String} excluded properties ...
* @return {Function}
*/
function exclude () {
var excludes = [].slice.call(arguments);
function excludeProps (res, obj) {
Object.keys(obj).forEach(function (key) {
if (!~excludes.indexOf(key)) res[key] = obj[key];
});
}
return function extendExclude () {
var args = [].slice.call(arguments)
, i = 0
, res = {};
for (; i < args.length; i++) {
excludeProps(res, args[i]);
}
return res;
};
};
/*!
* Primary Exports
*/
module.exports = AssertionError;
/**
* ### AssertionError
*
* An extension of the JavaScript `Error` constructor for
* assertion and validation scenarios.
*
* @param {String} message
* @param {Object} properties to include (optional)
* @param {callee} start stack function (optional)
*/
function AssertionError (message, _props, ssf) {
var extend = exclude('name', 'message', 'stack', 'constructor', 'toJSON')
, props = extend(_props || {});
// default values
this.message = message || 'Unspecified AssertionError';
this.showDiff = false;
// copy from properties
for (var key in props) {
this[key] = props[key];
}
// capture stack trace
ssf = ssf || arguments.callee;
if (ssf && Error.captureStackTrace) {
Error.captureStackTrace(this, ssf);
}
}
/*!
* Inherit from Error.prototype
*/
AssertionError.prototype = Object.create(Error.prototype);
/*!
* Statically set name
*/
AssertionError.prototype.name = 'AssertionError';
/*!
* Ensure correct constructor
*/
AssertionError.prototype.constructor = AssertionError;
/**
* Allow errors to be converted to JSON for static transfer.
*
* @param {Boolean} include stack (default: `true`)
* @return {Object} object that can be `JSON.stringify`
*/
AssertionError.prototype.toJSON = function (stack) {
var extend = exclude('constructor', 'toJSON', 'stack')
, props = extend({ name: this.name }, this);
// include stack if exists and not turned off
if (false !== stack && this.stack) {
props.stack = this.stack;
}
return props;
};
},{}],75:[function(require,module,exports){
module.exports = require('./lib/eql');
},{"./lib/eql":76}],76:[function(require,module,exports){
/*!
* deep-eql
* Copyright(c) 2013 Jake Luer <jake@alogicalparadox.com>
* MIT Licensed
*/
/*!
* Module dependencies
*/
var type = require('type-detect');
/*!
* Buffer.isBuffer browser shim
*/
var Buffer;
try { Buffer = require('buffer').Buffer; }
catch(ex) {
Buffer = {};
Buffer.isBuffer = function() { return false; }
}
/*!
* Primary Export
*/
module.exports = deepEqual;
/**
* Assert super-strict (egal) equality between
* two objects of any type.
*
* @param {Mixed} a
* @param {Mixed} b
* @param {Array} memoised (optional)
* @return {Boolean} equal match
*/
function deepEqual(a, b, m) {
if (sameValue(a, b)) {
return true;
} else if ('date' === type(a)) {
return dateEqual(a, b);
} else if ('regexp' === type(a)) {
return regexpEqual(a, b);
} else if (Buffer.isBuffer(a)) {
return bufferEqual(a, b);
} else if ('arguments' === type(a)) {
return argumentsEqual(a, b, m);
} else if (!typeEqual(a, b)) {
return false;
} else if (('object' !== type(a) && 'object' !== type(b))
&& ('array' !== type(a) && 'array' !== type(b))) {
return sameValue(a, b);
} else {
return objectEqual(a, b, m);
}
}
/*!
* Strict (egal) equality test. Ensures that NaN always
* equals NaN and `-0` does not equal `+0`.
*
* @param {Mixed} a
* @param {Mixed} b
* @return {Boolean} equal match
*/
function sameValue(a, b) {
if (a === b) return a !== 0 || 1 / a === 1 / b;
return a !== a && b !== b;
}
/*!
* Compare the types of two given objects and
* return if they are equal. Note that an Array
* has a type of `array` (not `object`) and arguments
* have a type of `arguments` (not `array`/`object`).
*
* @param {Mixed} a
* @param {Mixed} b
* @return {Boolean} result
*/
function typeEqual(a, b) {
return type(a) === type(b);
}
/*!
* Compare two Date objects by asserting that
* the time values are equal using `saveValue`.
*
* @param {Date} a
* @param {Date} b
* @return {Boolean} result
*/
function dateEqual(a, b) {
if ('date' !== type(b)) return false;
return sameValue(a.getTime(), b.getTime());
}
/*!
* Compare two regular expressions by converting them
* to string and checking for `sameValue`.
*
* @param {RegExp} a
* @param {RegExp} b
* @return {Boolean} result
*/
function regexpEqual(a, b) {
if ('regexp' !== type(b)) return false;
return sameValue(a.toString(), b.toString());
}
/*!
* Assert deep equality of two `arguments` objects.
* Unfortunately, these must be sliced to arrays
* prior to test to ensure no bad behavior.
*
* @param {Arguments} a
* @param {Arguments} b
* @param {Array} memoize (optional)
* @return {Boolean} result
*/
function argumentsEqual(a, b, m) {
if ('arguments' !== type(b)) return false;
a = [].slice.call(a);
b = [].slice.call(b);
return deepEqual(a, b, m);
}
/*!
* Get enumerable properties of a given object.
*
* @param {Object} a
* @return {Array} property names
*/
function enumerable(a) {
var res = [];
for (var key in a) res.push(key);
return res;
}
/*!
* Simple equality for flat iterable objects
* such as Arrays or Node.js buffers.
*
* @param {Iterable} a
* @param {Iterable} b
* @return {Boolean} result
*/
function iterableEqual(a, b) {
if (a.length !== b.length) return false;
var i = 0;
var match = true;
for (; i < a.length; i++) {
if (a[i] !== b[i]) {
match = false;
break;
}
}
return match;
}
/*!
* Extension to `iterableEqual` specifically
* for Node.js Buffers.
*
* @param {Buffer} a
* @param {Mixed} b
* @return {Boolean} result
*/
function bufferEqual(a, b) {
if (!Buffer.isBuffer(b)) return false;
return iterableEqual(a, b);
}
/*!
* Block for `objectEqual` ensuring non-existing
* values don't get in.
*
* @param {Mixed} object
* @return {Boolean} result
*/
function isValue(a) {
return a !== null && a !== undefined;
}
/*!
* Recursively check the equality of two objects.
* Once basic sameness has been established it will
* defer to `deepEqual` for each enumerable key
* in the object.
*
* @param {Mixed} a
* @param {Mixed} b
* @return {Boolean} result
*/
function objectEqual(a, b, m) {
if (!isValue(a) || !isValue(b)) {
return false;
}
if (a.prototype !== b.prototype) {
return false;
}
var i;
if (m) {
for (i = 0; i < m.length; i++) {
if ((m[i][0] === a && m[i][1] === b)
|| (m[i][0] === b && m[i][1] === a)) {
return true;
}
}
} else {
m = [];
}
try {
var ka = enumerable(a);
var kb = enumerable(b);
} catch (ex) {
return false;
}
ka.sort();
kb.sort();
if (!iterableEqual(ka, kb)) {
return false;
}
m.push([ a, b ]);
var key;
for (i = ka.length - 1; i >= 0; i--) {
key = ka[i];
if (!deepEqual(a[key], b[key], m)) {
return false;
}
}
return true;
}
},{"buffer":42,"type-detect":77}],77:[function(require,module,exports){
module.exports = require('./lib/type');
},{"./lib/type":78}],78:[function(require,module,exports){
/*!
* type-detect
* Copyright(c) 2013 jake luer <jake@alogicalparadox.com>
* MIT Licensed
*/
/*!
* Primary Exports
*/
var exports = module.exports = getType;
/*!
* Detectable javascript natives
*/
var natives = {
'[object Array]': 'array'
, '[object RegExp]': 'regexp'
, '[object Function]': 'function'
, '[object Arguments]': 'arguments'
, '[object Date]': 'date'
};
/**
* ### typeOf (obj)
*
* Use several different techniques to determine
* the type of object being tested.
*
*
* @param {Mixed} object
* @return {String} object type
* @api public
*/
function getType (obj) {
var str = Object.prototype.toString.call(obj);
if (natives[str]) return natives[str];
if (obj === null) return 'null';
if (obj === undefined) return 'undefined';
if (obj === Object(obj)) return 'object';
return typeof obj;
}
exports.Library = Library;
/**
* ### Library
*
* Create a repository for custom type detection.
*
* ```js
* var lib = new type.Library;
* ```
*
*/
function Library () {
this.tests = {};
}
/**
* #### .of (obj)
*
* Expose replacement `typeof` detection to the library.
*
* ```js
* if ('string' === lib.of('hello world')) {
* // ...
* }
* ```
*
* @param {Mixed} object to test
* @return {String} type
*/
Library.prototype.of = getType;
/**
* #### .define (type, test)
*
* Add a test to for the `.test()` assertion.
*
* Can be defined as a regular expression:
*
* ```js
* lib.define('int', /^[0-9]+$/);
* ```
*
* ... or as a function:
*
* ```js
* lib.define('bln', function (obj) {
* if ('boolean' === lib.of(obj)) return true;
* var blns = [ 'yes', 'no', 'true', 'false', 1, 0 ];
* if ('string' === lib.of(obj)) obj = obj.toLowerCase();
* return !! ~blns.indexOf(obj);
* });
* ```
*
* @param {String} type
* @param {RegExp|Function} test
* @api public
*/
Library.prototype.define = function (type, test) {
if (arguments.length === 1) return this.tests[type];
this.tests[type] = test;
return this;
};
/**
* #### .test (obj, test)
*
* Assert that an object is of type. Will first
* check natives, and if that does not pass it will
* use the user defined custom tests.
*
* ```js
* assert(lib.test('1', 'int'));
* assert(lib.test('yes', 'bln'));
* ```
*
* @param {Mixed} object
* @param {String} type
* @return {Boolean} result
* @api public
*/
Library.prototype.test = function (obj, type) {
if (type === getType(obj)) return true;
var test = this.tests[type];
if (test && 'regexp' === getType(test)) {
return test.test(obj);
} else if (test && 'function' === getType(test)) {
return test(obj);
} else {
throw new ReferenceError('Type test "' + type + '" not defined or invalid.');
}
};
},{}],79:[function(require,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
}
}
},{}],80:[function(require,module,exports){
'use strict';
module.exports = INTERNAL;
function INTERNAL() {}
},{}],81:[function(require,module,exports){
'use strict';
var Promise = require('./promise');
var reject = require('./reject');
var resolve = require('./resolve');
var INTERNAL = require('./INTERNAL');
var handlers = require('./handlers');
module.exports = all;
function all(iterable) {
if (Object.prototype.toString.call(iterable) !== '[object Array]') {
return reject(new TypeError('must be an array'));
}
var len = iterable.length;
var called = false;
if (!len) {
return resolve([]);
}
var values = new Array(len);
var resolved = 0;
var i = -1;
var promise = new Promise(INTERNAL);
while (++i < len) {
allResolver(iterable[i], i);
}
return promise;
function allResolver(value, i) {
resolve(value).then(resolveFromAll, function (error) {
if (!called) {
called = true;
handlers.reject(promise, error);
}
});
function resolveFromAll(outValue) {
values[i] = outValue;
if (++resolved === len & !called) {
called = true;
handlers.resolve(promise, values);
}
}
}
}
},{"./INTERNAL":80,"./handlers":82,"./promise":84,"./reject":87,"./resolve":88}],82:[function(require,module,exports){
'use strict';
var tryCatch = require('./tryCatch');
var resolveThenable = require('./resolveThenable');
var states = require('./states');
exports.resolve = function (self, value) {
var result = tryCatch(getThen, value);
if (result.status === 'error') {
return exports.reject(self, result.value);
}
var thenable = result.value;
if (thenable) {
resolveThenable.safely(self, thenable);
} else {
self.state = states.FULFILLED;
self.outcome = value;
var i = -1;
var len = self.queue.length;
while (++i < len) {
self.queue[i].callFulfilled(value);
}
}
return self;
};
exports.reject = function (self, error) {
self.state = states.REJECTED;
self.outcome = error;
var i = -1;
var len = self.queue.length;
while (++i < len) {
self.queue[i].callRejected(error);
}
return self;
};
function getThen(obj) {
// Make sure we only access the accessor once as required by the spec
var then = obj && obj.then;
if (obj && typeof obj === 'object' && typeof then === 'function') {
return function appyThen() {
then.apply(obj, arguments);
};
}
}
},{"./resolveThenable":89,"./states":90,"./tryCatch":91}],83:[function(require,module,exports){
module.exports = exports = require('./promise');
exports.resolve = require('./resolve');
exports.reject = require('./reject');
exports.all = require('./all');
exports.race = require('./race');
},{"./all":81,"./promise":84,"./race":86,"./reject":87,"./resolve":88}],84:[function(require,module,exports){
'use strict';
var unwrap = require('./unwrap');
var INTERNAL = require('./INTERNAL');
var resolveThenable = require('./resolveThenable');
var states = require('./states');
var QueueItem = require('./queueItem');
module.exports = Promise;
function Promise(resolver) {
if (!(this instanceof Promise)) {
return new Promise(resolver);
}
if (typeof resolver !== 'function') {
throw new TypeError('resolver must be a function');
}
this.state = states.PENDING;
this.queue = [];
this.outcome = void 0;
if (resolver !== INTERNAL) {
resolveThenable.safely(this, resolver);
}
}
Promise.prototype['catch'] = function (onRejected) {
return this.then(null, onRejected);
};
Promise.prototype.then = function (onFulfilled, onRejected) {
if (typeof onFulfilled !== 'function' && this.state === states.FULFILLED ||
typeof onRejected !== 'function' && this.state === states.REJECTED) {
return this;
}
var promise = new Promise(INTERNAL);
if (this.state !== states.PENDING) {
var resolver = this.state === states.FULFILLED ? onFulfilled: onRejected;
unwrap(promise, resolver, this.outcome);
} else {
this.queue.push(new QueueItem(promise, onFulfilled, onRejected));
}
return promise;
};
},{"./INTERNAL":80,"./queueItem":85,"./resolveThenable":89,"./states":90,"./unwrap":92}],85:[function(require,module,exports){
'use strict';
var handlers = require('./handlers');
var unwrap = require('./unwrap');
module.exports = QueueItem;
function QueueItem(promise, onFulfilled, onRejected) {
this.promise = promise;
if (typeof onFulfilled === 'function') {
this.onFulfilled = onFulfilled;
this.callFulfilled = this.otherCallFulfilled;
}
if (typeof onRejected === 'function') {
this.onRejected = onRejected;
this.callRejected = this.otherCallRejected;
}
}
QueueItem.prototype.callFulfilled = function (value) {
handlers.resolve(this.promise, value);
};
QueueItem.prototype.otherCallFulfilled = function (value) {
unwrap(this.promise, this.onFulfilled, value);
};
QueueItem.prototype.callRejected = function (value) {
handlers.reject(this.promise, value);
};
QueueItem.prototype.otherCallRejected = function (value) {
unwrap(this.promise, this.onRejected, value);
};
},{"./handlers":82,"./unwrap":92}],86:[function(require,module,exports){
'use strict';
var Promise = require('./promise');
var reject = require('./reject');
var resolve = require('./resolve');
var INTERNAL = require('./INTERNAL');
var handlers = require('./handlers');
module.exports = race;
function race(iterable) {
if (Object.prototype.toString.call(iterable) !== '[object Array]') {
return reject(new TypeError('must be an array'));
}
var len = iterable.length;
var called = false;
if (!len) {
return resolve([]);
}
var resolved = 0;
var i = -1;
var promise = new Promise(INTERNAL);
while (++i < len) {
resolver(iterable[i]);
}
return promise;
function resolver(value) {
resolve(value).then(function (response) {
if (!called) {
called = true;
handlers.resolve(promise, response);
}
}, function (error) {
if (!called) {
called = true;
handlers.reject(promise, error);
}
});
}
}
},{"./INTERNAL":80,"./handlers":82,"./promise":84,"./reject":87,"./resolve":88}],87:[function(require,module,exports){
'use strict';
var Promise = require('./promise');
var INTERNAL = require('./INTERNAL');
var handlers = require('./handlers');
module.exports = reject;
function reject(reason) {
var promise = new Promise(INTERNAL);
return handlers.reject(promise, reason);
}
},{"./INTERNAL":80,"./handlers":82,"./promise":84}],88:[function(require,module,exports){
'use strict';
var Promise = require('./promise');
var INTERNAL = require('./INTERNAL');
var handlers = require('./handlers');
module.exports = resolve;
var FALSE = handlers.resolve(new Promise(INTERNAL), false);
var NULL = handlers.resolve(new Promise(INTERNAL), null);
var UNDEFINED = handlers.resolve(new Promise(INTERNAL), void 0);
var ZERO = handlers.resolve(new Promise(INTERNAL), 0);
var EMPTYSTRING = handlers.resolve(new Promise(INTERNAL), '');
function resolve(value) {
if (value) {
if (value instanceof Promise) {
return value;
}
return handlers.resolve(new Promise(INTERNAL), value);
}
var valueType = typeof value;
switch (valueType) {
case 'boolean':
return FALSE;
case 'undefined':
return UNDEFINED;
case 'object':
return NULL;
case 'number':
return ZERO;
case 'string':
return EMPTYSTRING;
}
}
},{"./INTERNAL":80,"./handlers":82,"./promise":84}],89:[function(require,module,exports){
'use strict';
var handlers = require('./handlers');
var tryCatch = require('./tryCatch');
function safelyResolveThenable(self, thenable) {
// Either fulfill, reject or reject with error
var called = false;
function onError(value) {
if (called) {
return;
}
called = true;
handlers.reject(self, value);
}
function onSuccess(value) {
if (called) {
return;
}
called = true;
handlers.resolve(self, value);
}
function tryToUnwrap() {
thenable(onSuccess, onError);
}
var result = tryCatch(tryToUnwrap);
if (result.status === 'error') {
onError(result.value);
}
}
exports.safely = safelyResolveThenable;
},{"./handlers":82,"./tryCatch":91}],90:[function(require,module,exports){
// Lazy man's symbols for states
exports.REJECTED = ['REJECTED'];
exports.FULFILLED = ['FULFILLED'];
exports.PENDING = ['PENDING'];
},{}],91:[function(require,module,exports){
'use strict';
module.exports = tryCatch;
function tryCatch(func, value) {
var out = {};
try {
out.value = func(value);
out.status = 'success';
} catch (e) {
out.status = 'error';
out.value = e;
}
return out;
}
},{}],92:[function(require,module,exports){
'use strict';
var immediate = require('immediate');
var handlers = require('./handlers');
module.exports = unwrap;
function unwrap(promise, func, value) {
immediate(function () {
var returnValue;
try {
returnValue = func(value);
} catch (e) {
return handlers.reject(promise, e);
}
if (returnValue === promise) {
handlers.reject(promise, new TypeError('Cannot resolve promise with itself'));
} else {
handlers.resolve(promise, returnValue);
}
});
}
},{"./handlers":82,"immediate":93}],93:[function(require,module,exports){
'use strict';
var types = [
require('./nextTick'),
require('./mutation.js'),
require('./messageChannel'),
require('./stateChange'),
require('./timeout')
];
var draining;
var currentQueue;
var queueIndex = -1;
var queue = [];
function cleanUpNextTick() {
draining = false;
if (currentQueue && currentQueue.length) {
queue = currentQueue.concat(queue);
} else {
queueIndex = -1;
}
if (queue.length) {
nextTick();
}
}
//named nextTick for less confusing stack traces
function nextTick() {
draining = true;
var len = queue.length;
var timeout = setTimeout(cleanUpNextTick);
while (len) {
currentQueue = queue;
queue = [];
while (++queueIndex < len) {
currentQueue[queueIndex]();
}
queueIndex = -1;
len = queue.length;
}
queueIndex = -1;
draining = false;
clearTimeout(timeout);
}
var scheduleDrain;
var i = -1;
var len = types.length;
while (++ i < len) {
if (types[i] && types[i].test && types[i].test()) {
scheduleDrain = types[i].install(nextTick);
break;
}
}
module.exports = immediate;
function immediate(task) {
if (queue.push(task) === 1 && !draining) {
scheduleDrain();
}
}
},{"./messageChannel":94,"./mutation.js":95,"./nextTick":41,"./stateChange":96,"./timeout":97}],94:[function(require,module,exports){
(function (global){
'use strict';
exports.test = function () {
if (global.setImmediate) {
// we can only get here in IE10
// which doesn't handel postMessage well
return false;
}
return typeof global.MessageChannel !== 'undefined';
};
exports.install = function (func) {
var channel = new global.MessageChannel();
channel.port1.onmessage = func;
return function () {
channel.port2.postMessage(0);
};
};
}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{}],95:[function(require,module,exports){
(function (global){
'use strict';
//based off rsvp https://github.com/tildeio/rsvp.js
//license https://github.com/tildeio/rsvp.js/blob/master/LICENSE
//https://github.com/tildeio/rsvp.js/blob/master/lib/rsvp/asap.js
var Mutation = global.MutationObserver || global.WebKitMutationObserver;
exports.test = function () {
return Mutation;
};
exports.install = function (handle) {
var called = 0;
var observer = new Mutation(handle);
var element = global.document.createTextNode('');
observer.observe(element, {
characterData: true
});
return function () {
element.data = (called = ++called % 2);
};
};
}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{}],96:[function(require,module,exports){
(function (global){
'use strict';
exports.test = function () {
return 'document' in global && 'onreadystatechange' in global.document.createElement('script');
};
exports.install = function (handle) {
return function () {
// Create a <script> element; its readystatechange event will be fired asynchronously once it is inserted
// into the document. Do so, thus queuing up the task. Remember to clean up once it's been called.
var scriptEl = global.document.createElement('script');
scriptEl.onreadystatechange = function () {
handle();
scriptEl.onreadystatechange = null;
scriptEl.parentNode.removeChild(scriptEl);
scriptEl = null;
};
global.document.documentElement.appendChild(scriptEl);
return handle;
};
};
}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{}],97:[function(require,module,exports){
'use strict';
exports.test = function () {
return true;
};
exports.install = function (t) {
return function () {
setTimeout(t, 0);
};
};
},{}],98:[function(require,module,exports){
(function (process){
(function (mochaAsPromised) {
"use strict";
function findNodeJSMocha(moduleToTest, suffix, accumulator) {
if (accumulator === undefined) {
accumulator = [];
}
if (moduleToTest.id.indexOf(suffix, moduleToTest.id.length - suffix.length) !== -1 && moduleToTest.exports) {
accumulator.push(moduleToTest.exports);
}
moduleToTest.children.forEach(function (child) {
findNodeJSMocha(child, suffix, accumulator);
});
return accumulator;
}
// Module systems magic dance.
if (typeof require === "function" && typeof exports === "object" && typeof module === "object") {
// Node.js: plug in automatically, if no argument is provided. This is a good idea since one can run Mocha tests
// using the Mocha test runner from either a locally-installed package, or from a globally-installed one.
// In the latter case, naively plugging in `require("mocha")` would end up duck-punching the wrong instance,
// so we provide this shortcut to auto-detect which Mocha package needs to be duck-punched.
module.exports = function (mochaModules) {
if (mochaModules === undefined) {
if (typeof process === "object" && Object.prototype.toString.call(process) === "[object process]") {
// We're in *real* Node.js, not in a browserify-like environment. Do automatic detection logic.
// Funky syntax prevents Browserify from detecting the require, since it's needed for Node.js-only
// stuff.
var path = (require)("path");
var suffix = path.join("mocha", "lib", "mocha.js");
mochaModules = findNodeJSMocha(require.main, suffix);
if (mochaModules === undefined) {
throw new Error("Attempted to automatically plug in to Mocha, but could not detect a " +
"running Mocha module.");
}
} else if (typeof Mocha !== "undefined") {
// We're in a browserify-like emulation environment. Try the `Mocha` global.
mochaModules = [Mocha];
} else {
throw new Error("Attempted to automatically plug in to Mocha, but could not detect the " +
"environment. Plug in manually by passing the running Mocha module.");
}
}
mochaModules.forEach(mochaAsPromised);
};
} else if (typeof define === "function" && define.amd) {
// AMD
define(function () {
return mochaAsPromised;
});
} else {
// Other environment (usually <script> tag): plug in global `Mocha` directly and automatically.
mochaAsPromised(Mocha);
}
}((function () {
"use strict";
function getThen(x) {
if ((typeof x === "object" || typeof x === "function") && x !== null) {
var then = x.then;
if (typeof then === "function") {
return then;
}
}
}
return function mochaAsPromised(mocha) {
if (mocha._mochaAsPromisedLoadedAlready) {
return;
}
mocha._mochaAsPromisedLoadedAlready = true;
// Soooo this is an awesome hack.
// Here's the idea: Mocha `Runnable` instances have a `fn` property, representing the test to run. Async tests
// in Mocha are done with `fn`s that take a `done` callback, and call it with either nothing (success) or an
// error (failure). We want to add another paradigm for async tests: `fn`s that take no arguments, but return a
// promise. Promise fulfillment corresponds to success, and rejection to failure.
// To do this, we translate promise-returning `fn`s into callback-calling ones. So Mocha never sees the promisey
// functions, but instead sees a wrapper around them that we provide. The only trick is, how and when to insert
// this wrapper into a Mocha `Runnable`?
// We accomplish this by intercepting all [[Put]]s to the `fn` property of *any* `Runnable`. That is, we define
// a setter for `fn` on `Runnable.prototype` (!). So when Mocha sets the `fn` property of a runnable inside the
// `Runnable` constructor (i.e. `this.fn = fn`), it is immediately translated into a wrapped version, which is
// then stored as a `_wrappedFn` instance property. Finally we define a getter for `fn` on `Runnable.prototype`
// as well, so that any retrievals of the `fn` property (e.g. in `Runnable.prototype.run`) return the wrapped
// version we've stored.
// We also need to override the `async` property, since the Mocha constructor sets it by looking at the `fn`
// passed in, and not at the `this.fn` property we have control over. We just give it a getter that performs the
// same logic as the Mocha constructor, and a no-op setter (so that it silently ignores Mocha's attempts to set
// it).
// ISN'T THIS COOL!?
Object.defineProperties(mocha.Runnable.prototype, {
fn: {
configurable: true,
enumerable: true,
get: function () {
return this._wrappedFn;
},
set: function (fn) {
this._wrappedFn = function (done) {
// Run the original `fn`, passing along `done` for the case in which it's callback-asynchronous.
// Make sure to forward the `this` context, since you can set variables and stuff on it to share
// within a suite.
var retVal = fn.call(this, done);
var then = getThen(retVal);
if (then) {
// If we get a promise back...
then.call(
retVal,
function () {
// On fulfillment, ignore the fulfillment value and call `done()` with no arguments.
done();
},
function (reason) {
// On rejection, make sure there's a rejection reason, then call `done` with it.
if (reason === null || reason === undefined) {
reason = new Error("Promise rejected with no rejection reason.");
}
done(reason);
}
);
} else if (fn.length === 0) {
// If `fn` is synchronous (i.e. didn't have a `done` parameter and didn't return a promise),
// call `done` now. (If it's callback-asynchronous, `fn` will call `done` eventually since
// we passed it in above.)
done();
}
};
this._wrappedFn.toString = function () {
return fn.toString();
};
}
},
async: {
configurable: true,
enumerable: true,
get: function () {
return typeof this._wrappedFn === "function";
},
set: function () {
// Ignore Mocha trying to set this; it doesn't know the whole picture.
}
}
});
};
}())));
}).call(this,require("/Users/nlawson/workspace-node/pouchdb-authentication/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js"))
},{"/Users/nlawson/workspace-node/pouchdb-authentication/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js":46,"path":47}],99:[function(require,module,exports){
"use strict";
// Extends method
// (taken from http://code.jquery.com/jquery-1.9.0.js)
// Populate the class2type map
var class2type = {};
var types = [
"Boolean", "Number", "String", "Function", "Array",
"Date", "RegExp", "Object", "Error"
];
for (var i = 0; i < types.length; i++) {
var typename = types[i];
class2type["[object " + typename + "]"] = typename.toLowerCase();
}
var core_toString = class2type.toString;
var core_hasOwn = class2type.hasOwnProperty;
function type(obj) {
if (obj === null) {
return String(obj);
}
return typeof obj === "object" || typeof obj === "function" ?
class2type[core_toString.call(obj)] || "object" :
typeof obj;
}
function isWindow(obj) {
return obj !== null && obj === obj.window;
}
function isPlainObject(obj) {
// Must be an Object.
// Because of IE, we also have to check the presence of
// the constructor property.
// Make sure that DOM nodes and window objects don't pass through, as well
if (!obj || type(obj) !== "object" || obj.nodeType || isWindow(obj)) {
return false;
}
try {
// Not own constructor property must be Object
if (obj.constructor &&
!core_hasOwn.call(obj, "constructor") &&
!core_hasOwn.call(obj.constructor.prototype, "isPrototypeOf")) {
return false;
}
} catch ( e ) {
// IE8,9 Will throw exceptions on certain host objects #9897
return false;
}
// Own properties are enumerated firstly, so to speed up,
// if last one is own, then all properties are own.
var key;
for (key in obj) {}
return key === undefined || core_hasOwn.call(obj, key);
}
function isFunction(obj) {
return type(obj) === "function";
}
var isArray = Array.isArray || function (obj) {
return type(obj) === "array";
};
function extend() {
// originally extend() was recursive, but this ended up giving us
// "call stack exceeded", so it's been unrolled to use a literal stack
// (see https://github.com/pouchdb/pouchdb/issues/2543)
var stack = [];
var i = -1;
var len = arguments.length;
var args = new Array(len);
while (++i < len) {
args[i] = arguments[i];
}
var container = {};
stack.push({args: args, result: {container: container, key: 'key'}});
var next;
while ((next = stack.pop())) {
extendInner(stack, next.args, next.result);
}
return container.key;
}
function extendInner(stack, args, result) {
var options, name, src, copy, copyIsArray, clone,
target = args[0] || {},
i = 1,
length = args.length,
deep = false,
numericStringRegex = /\d+/,
optionsIsArray;
// Handle a deep copy situation
if (typeof target === "boolean") {
deep = target;
target = args[1] || {};
// skip the boolean and the target
i = 2;
}
// Handle case when target is a string or something (possible in deep copy)
if (typeof target !== "object" && !isFunction(target)) {
target = {};
}
// extend jQuery itself if only one argument is passed
if (length === i) {
/* jshint validthis: true */
target = this;
--i;
}
for (; i < length; i++) {
// Only deal with non-null/undefined values
if ((options = args[i]) != null) {
optionsIsArray = isArray(options);
// Extend the base object
for (name in options) {
//if (options.hasOwnProperty(name)) {
if (!(name in Object.prototype)) {
if (optionsIsArray && !numericStringRegex.test(name)) {
continue;
}
src = target[name];
copy = options[name];
// Prevent never-ending loop
if (target === copy) {
continue;
}
// Recurse if we're merging plain objects or arrays
if (deep && copy && (isPlainObject(copy) ||
(copyIsArray = isArray(copy)))) {
if (copyIsArray) {
copyIsArray = false;
clone = src && isArray(src) ? src : [];
} else {
clone = src && isPlainObject(src) ? src : {};
}
// Never move original objects, clone them
stack.push({
args: [deep, clone, copy],
result: {
container: target,
key: name
}
});
// Don't bring in undefined values
} else if (copy !== undefined) {
if (!(isArray(options) && isFunction(copy))) {
target[name] = copy;
}
}
}
}
}
}
// "Return" the modified object by setting the key
// on the given container
result.container[result.key] = target;
}
module.exports = extend;
},{}],100:[function(require,module,exports){
'use strict';
// allow external plugins to require('pouchdb/extras/ajax')
module.exports = require('../lib/deps/ajax');
},{"../lib/deps/ajax":117}],101:[function(require,module,exports){
'use strict';
// allow external plugins to require('pouchdb/extras/promise')
module.exports = require('../lib/deps/promise');
},{"../lib/deps/promise":126}],102:[function(require,module,exports){
"use strict";
var utils = require('./utils');
var merge = require('./merge');
var errors = require('./deps/errors');
var EventEmitter = require('events').EventEmitter;
var upsert = require('./deps/upsert');
var Changes = require('./changes');
var Promise = utils.Promise;
/*
* A generic pouch adapter
*/
// returns first element of arr satisfying callback predicate
function arrayFirst(arr, callback) {
for (var i = 0; i < arr.length; i++) {
if (callback(arr[i], i) === true) {
return arr[i];
}
}
return false;
}
// Wrapper for functions that call the bulkdocs api with a single doc,
// if the first result is an error, return an error
function yankError(callback) {
return function (err, results) {
if (err || (results[0] && results[0].error)) {
callback(err || results[0]);
} else {
callback(null, results.length ? results[0] : results);
}
};
}
// for every node in a revision tree computes its distance from the closest
// leaf
function computeHeight(revs) {
var height = {};
var edges = [];
merge.traverseRevTree(revs, function (isLeaf, pos, id, prnt) {
var rev = pos + "-" + id;
if (isLeaf) {
height[rev] = 0;
}
if (prnt !== undefined) {
edges.push({from: prnt, to: rev});
}
return rev;
});
edges.reverse();
edges.forEach(function (edge) {
if (height[edge.from] === undefined) {
height[edge.from] = 1 + height[edge.to];
} else {
height[edge.from] = Math.min(height[edge.from], 1 + height[edge.to]);
}
});
return height;
}
function allDocsKeysQuery(api, opts, callback) {
var keys = ('limit' in opts) ?
opts.keys.slice(opts.skip, opts.limit + opts.skip) :
(opts.skip > 0) ? opts.keys.slice(opts.skip) : opts.keys;
if (opts.descending) {
keys.reverse();
}
if (!keys.length) {
return api._allDocs({limit: 0}, callback);
}
var finalResults = {
offset: opts.skip
};
return Promise.all(keys.map(function (key) {
var subOpts = utils.extend(true, {key: key, deleted: 'ok'}, opts);
['limit', 'skip', 'keys'].forEach(function (optKey) {
delete subOpts[optKey];
});
return new Promise(function (resolve, reject) {
api._allDocs(subOpts, function (err, res) {
if (err) {
return reject(err);
}
finalResults.total_rows = res.total_rows;
resolve(res.rows[0] || {key: key, error: 'not_found'});
});
});
})).then(function (results) {
finalResults.rows = results;
return finalResults;
});
}
utils.inherits(AbstractPouchDB, EventEmitter);
module.exports = AbstractPouchDB;
function AbstractPouchDB() {
EventEmitter.call(this);
}
AbstractPouchDB.prototype.post =
utils.adapterFun('post', function (doc, opts, callback) {
if (typeof opts === 'function') {
callback = opts;
opts = {};
}
if (typeof doc !== 'object' || Array.isArray(doc)) {
return callback(errors.error(errors.NOT_AN_OBJECT));
}
this.bulkDocs({docs: [doc]}, opts, yankError(callback));
});
AbstractPouchDB.prototype.put =
utils.adapterFun('put', utils.getArguments(function (args) {
var temp, temptype, opts, callback;
var doc = args.shift();
var id = '_id' in doc;
if (typeof doc !== 'object' || Array.isArray(doc)) {
callback = args.pop();
return callback(errors.error(errors.NOT_AN_OBJECT));
}
doc = utils.clone(doc);
while (true) {
temp = args.shift();
temptype = typeof temp;
if (temptype === "string" && !id) {
doc._id = temp;
id = true;
} else if (temptype === "string" && id && !('_rev' in doc)) {
doc._rev = temp;
} else if (temptype === "object") {
opts = temp;
} else if (temptype === "function") {
callback = temp;
}
if (!args.length) {
break;
}
}
opts = opts || {};
var error = utils.invalidIdError(doc._id);
if (error) {
return callback(error);
}
if (utils.isLocalId(doc._id) && typeof this._putLocal === 'function') {
if (doc._deleted) {
return this._removeLocal(doc, callback);
} else {
return this._putLocal(doc, callback);
}
}
this.bulkDocs({docs: [doc]}, opts, yankError(callback));
}));
AbstractPouchDB.prototype.putAttachment =
utils.adapterFun('putAttachment', function (docId, attachmentId, rev,
blob, type, callback) {
var api = this;
if (typeof type === 'function') {
callback = type;
type = blob;
blob = rev;
rev = null;
}
if (typeof type === 'undefined') {
type = blob;
blob = rev;
rev = null;
}
function createAttachment(doc) {
doc._attachments = doc._attachments || {};
doc._attachments[attachmentId] = {
content_type: type,
data: blob
};
return api.put(doc);
}
return api.get(docId).then(function (doc) {
if (doc._rev !== rev) {
throw errors.error(errors.REV_CONFLICT);
}
return createAttachment(doc);
}, function (err) {
// create new doc
if (err.reason === errors.MISSING_DOC.message) {
return createAttachment({_id: docId});
} else {
throw err;
}
});
});
AbstractPouchDB.prototype.removeAttachment =
utils.adapterFun('removeAttachment', function (docId, attachmentId, rev,
callback) {
var self = this;
self.get(docId, function (err, obj) {
if (err) {
callback(err);
return;
}
if (obj._rev !== rev) {
callback(errors.error(errors.REV_CONFLICT));
return;
}
if (!obj._attachments) {
return callback();
}
delete obj._attachments[attachmentId];
if (Object.keys(obj._attachments).length === 0) {
delete obj._attachments;
}
self.put(obj, callback);
});
});
AbstractPouchDB.prototype.remove =
utils.adapterFun('remove', function (docOrId, optsOrRev, opts, callback) {
var doc;
if (typeof optsOrRev === 'string') {
// id, rev, opts, callback style
doc = {
_id: docOrId,
_rev: optsOrRev
};
if (typeof opts === 'function') {
callback = opts;
opts = {};
}
} else {
// doc, opts, callback style
doc = docOrId;
if (typeof optsOrRev === 'function') {
callback = optsOrRev;
opts = {};
} else {
callback = opts;
opts = optsOrRev;
}
}
opts = utils.clone(opts || {});
opts.was_delete = true;
var newDoc = {_id: doc._id, _rev: (doc._rev || opts.rev)};
newDoc._deleted = true;
if (utils.isLocalId(newDoc._id) && typeof this._removeLocal === 'function') {
return this._removeLocal(doc, callback);
}
this.bulkDocs({docs: [newDoc]}, opts, yankError(callback));
});
AbstractPouchDB.prototype.revsDiff =
utils.adapterFun('revsDiff', function (req, opts, callback) {
if (typeof opts === 'function') {
callback = opts;
opts = {};
}
opts = utils.clone(opts);
var ids = Object.keys(req);
if (!ids.length) {
return callback(null, {});
}
var count = 0;
var missing = new utils.Map();
function addToMissing(id, revId) {
if (!missing.has(id)) {
missing.set(id, {missing: []});
}
missing.get(id).missing.push(revId);
}
function processDoc(id, rev_tree) {
// Is this fast enough? Maybe we should switch to a set simulated by a map
var missingForId = req[id].slice(0);
merge.traverseRevTree(rev_tree, function (isLeaf, pos, revHash, ctx,
opts) {
var rev = pos + '-' + revHash;
var idx = missingForId.indexOf(rev);
if (idx === -1) {
return;
}
missingForId.splice(idx, 1);
if (opts.status !== 'available') {
addToMissing(id, rev);
}
});
// Traversing the tree is synchronous, so now `missingForId` contains
// revisions that were not found in the tree
missingForId.forEach(function (rev) {
addToMissing(id, rev);
});
}
ids.map(function (id) {
this._getRevisionTree(id, function (err, rev_tree) {
if (err && err.status === 404 && err.message === 'missing') {
missing.set(id, {missing: req[id]});
} else if (err) {
return callback(err);
} else {
processDoc(id, rev_tree);
}
if (++count === ids.length) {
// convert LazyMap to object
var missingObj = {};
missing.forEach(function (value, key) {
missingObj[key] = value;
});
return callback(null, missingObj);
}
});
}, this);
});
// compact one document and fire callback
// by compacting we mean removing all revisions which
// are further from the leaf in revision tree than max_height
AbstractPouchDB.prototype.compactDocument =
utils.adapterFun('compactDocument', function (docId, maxHeight, callback) {
var self = this;
this._getRevisionTree(docId, function (err, revTree) {
if (err) {
return callback(err);
}
var height = computeHeight(revTree);
var candidates = [];
var revs = [];
Object.keys(height).forEach(function (rev) {
if (height[rev] > maxHeight) {
candidates.push(rev);
}
});
merge.traverseRevTree(revTree, function (isLeaf, pos, revHash, ctx, opts) {
var rev = pos + '-' + revHash;
if (opts.status === 'available' && candidates.indexOf(rev) !== -1) {
revs.push(rev);
}
});
self._doCompaction(docId, revs, callback);
});
});
// compact the whole database using single document
// compaction
AbstractPouchDB.prototype.compact =
utils.adapterFun('compact', function (opts, callback) {
if (typeof opts === 'function') {
callback = opts;
opts = {};
}
var self = this;
opts = utils.clone(opts || {});
self.get('_local/compaction').catch(function () {
return false;
}).then(function (doc) {
if (typeof self._compact === 'function') {
if (doc && doc.last_seq) {
opts.last_seq = doc.last_seq;
}
return self._compact(opts, callback);
}
});
});
AbstractPouchDB.prototype._compact = function (opts, callback) {
var self = this;
var changesOpts = {
returnDocs: false,
last_seq: opts.last_seq || 0
};
var promises = [];
function onChange(row) {
promises.push(self.compactDocument(row.id, 0));
}
function onComplete(resp) {
var lastSeq = resp.last_seq;
Promise.all(promises).then(function () {
return upsert(self, '_local/compaction', function deltaFunc(doc) {
if (!doc.last_seq || doc.last_seq < lastSeq) {
doc.last_seq = lastSeq;
return doc;
}
return false; // somebody else got here first, don't update
});
}).then(function () {
callback(null, {ok: true});
}).catch(callback);
}
self.changes(changesOpts)
.on('change', onChange)
.on('complete', onComplete)
.on('error', callback);
};
/* Begin api wrappers. Specific functionality to storage belongs in the
_[method] */
AbstractPouchDB.prototype.get =
utils.adapterFun('get', function (id, opts, callback) {
if (typeof opts === 'function') {
callback = opts;
opts = {};
}
if (typeof id !== 'string') {
return callback(errors.error(errors.INVALID_ID));
}
if (utils.isLocalId(id) && typeof this._getLocal === 'function') {
return this._getLocal(id, callback);
}
var leaves = [], self = this;
function finishOpenRevs() {
var result = [];
var count = leaves.length;
if (!count) {
return callback(null, result);
}
// order with open_revs is unspecified
leaves.forEach(function (leaf) {
self.get(id, {
rev: leaf,
revs: opts.revs,
attachments: opts.attachments
}, function (err, doc) {
if (!err) {
result.push({ok: doc});
} else {
result.push({missing: leaf});
}
count--;
if (!count) {
callback(null, result);
}
});
});
}
if (opts.open_revs) {
if (opts.open_revs === "all") {
this._getRevisionTree(id, function (err, rev_tree) {
if (err) {
return callback(err);
}
leaves = merge.collectLeaves(rev_tree).map(function (leaf) {
return leaf.rev;
});
finishOpenRevs();
});
} else {
if (Array.isArray(opts.open_revs)) {
leaves = opts.open_revs;
for (var i = 0; i < leaves.length; i++) {
var l = leaves[i];
// looks like it's the only thing couchdb checks
if (!(typeof(l) === "string" && /^\d+-/.test(l))) {
return callback(errors.error(errors.INVALID_REV));
}
}
finishOpenRevs();
} else {
return callback(errors.error(errors.UNKNOWN_ERROR,
'function_clause'));
}
}
return; // open_revs does not like other options
}
return this._get(id, opts, function (err, result) {
opts = utils.clone(opts);
if (err) {
return callback(err);
}
var doc = result.doc;
var metadata = result.metadata;
var ctx = result.ctx;
if (opts.conflicts) {
var conflicts = merge.collectConflicts(metadata);
if (conflicts.length) {
doc._conflicts = conflicts;
}
}
if (utils.isDeleted(metadata, doc._rev)) {
doc._deleted = true;
}
if (opts.revs || opts.revs_info) {
var paths = merge.rootToLeaf(metadata.rev_tree);
var path = arrayFirst(paths, function (arr) {
return arr.ids.map(function (x) { return x.id; })
.indexOf(doc._rev.split('-')[1]) !== -1;
});
var indexOfRev = path.ids.map(function (x) {return x.id; })
.indexOf(doc._rev.split('-')[1]) + 1;
var howMany = path.ids.length - indexOfRev;
path.ids.splice(indexOfRev, howMany);
path.ids.reverse();
if (opts.revs) {
doc._revisions = {
start: (path.pos + path.ids.length) - 1,
ids: path.ids.map(function (rev) {
return rev.id;
})
};
}
if (opts.revs_info) {
var pos = path.pos + path.ids.length;
doc._revs_info = path.ids.map(function (rev) {
pos--;
return {
rev: pos + '-' + rev.id,
status: rev.opts.status
};
});
}
}
if (opts.local_seq) {
utils.info('The "local_seq" option is deprecated and will be removed');
doc._local_seq = result.metadata.seq;
}
if (opts.attachments && doc._attachments) {
var attachments = doc._attachments;
var count = Object.keys(attachments).length;
if (count === 0) {
return callback(null, doc);
}
Object.keys(attachments).forEach(function (key) {
this._getAttachment(attachments[key],
{encode: true, ctx: ctx}, function (err, data) {
var att = doc._attachments[key];
att.data = data;
delete att.stub;
delete att.length;
if (!--count) {
callback(null, doc);
}
});
}, self);
} else {
if (doc._attachments) {
for (var key in doc._attachments) {
if (doc._attachments.hasOwnProperty(key)) {
doc._attachments[key].stub = true;
}
}
}
callback(null, doc);
}
});
});
AbstractPouchDB.prototype.getAttachment =
utils.adapterFun('getAttachment', function (docId, attachmentId, opts,
callback) {
var self = this;
if (opts instanceof Function) {
callback = opts;
opts = {};
}
opts = utils.clone(opts);
this._get(docId, opts, function (err, res) {
if (err) {
return callback(err);
}
if (res.doc._attachments && res.doc._attachments[attachmentId]) {
opts.ctx = res.ctx;
self._getAttachment(res.doc._attachments[attachmentId], opts, callback);
} else {
return callback(errors.error(errors.MISSING_DOC));
}
});
});
AbstractPouchDB.prototype.allDocs =
utils.adapterFun('allDocs', function (opts, callback) {
if (typeof opts === 'function') {
callback = opts;
opts = {};
}
opts = utils.clone(opts);
opts.skip = typeof opts.skip !== 'undefined' ? opts.skip : 0;
if ('keys' in opts) {
if (!Array.isArray(opts.keys)) {
return callback(new TypeError('options.keys must be an array'));
}
var incompatibleOpt =
['startkey', 'endkey', 'key'].filter(function (incompatibleOpt) {
return incompatibleOpt in opts;
})[0];
if (incompatibleOpt) {
callback(errors.error(errors.QUERY_PARSE_ERROR,
'Query parameter `' + incompatibleOpt +
'` is not compatible with multi-get'
));
return;
}
if (this.type() !== 'http') {
return allDocsKeysQuery(this, opts, callback);
}
}
return this._allDocs(opts, callback);
});
AbstractPouchDB.prototype.changes = function (opts, callback) {
if (typeof opts === 'function') {
callback = opts;
opts = {};
}
return new Changes(this, opts, callback);
};
AbstractPouchDB.prototype.close =
utils.adapterFun('close', function (callback) {
this._closed = true;
return this._close(callback);
});
AbstractPouchDB.prototype.info = utils.adapterFun('info', function (callback) {
var self = this;
this._info(function (err, info) {
if (err) {
return callback(err);
}
// assume we know better than the adapter, unless it informs us
info.db_name = info.db_name || self._db_name;
info.auto_compaction = !!(self.auto_compaction && self.type() !== 'http');
callback(null, info);
});
});
AbstractPouchDB.prototype.id = utils.adapterFun('id', function (callback) {
return this._id(callback);
});
AbstractPouchDB.prototype.type = function () {
return (typeof this._type === 'function') ? this._type() : this.adapter;
};
AbstractPouchDB.prototype.bulkDocs =
utils.adapterFun('bulkDocs', function (req, opts, callback) {
if (typeof opts === 'function') {
callback = opts;
opts = {};
}
opts = utils.clone(opts);
if (Array.isArray(req)) {
req = {
docs: req
};
}
if (!req || !req.docs || !Array.isArray(req.docs)) {
return callback(errors.error(errors.MISSING_BULK_DOCS));
}
for (var i = 0; i < req.docs.length; ++i) {
if (typeof req.docs[i] !== 'object' || Array.isArray(req.docs[i])) {
return callback(errors.error(errors.NOT_AN_OBJECT));
}
}
req = utils.clone(req);
if (!('new_edits' in opts)) {
if ('new_edits' in req) {
opts.new_edits = req.new_edits;
} else {
opts.new_edits = true;
}
}
if (!opts.new_edits && this.type() !== 'http') {
// ensure revisions of the same doc are sorted, so that
// the local adapter processes them correctly (#2935)
req.docs.sort(function (a, b) {
var idCompare = utils.compare(a._id, b._id);
if (idCompare !== 0) {
return idCompare;
}
var aStart = a._revisions ? a._revisions.start : 0;
var bStart = b._revisions ? b._revisions.start : 0;
return utils.compare(aStart, bStart);
});
}
req.docs.forEach(function (doc) {
if (doc._deleted) {
delete doc._attachments; // ignore atts for deleted docs
}
});
return this._bulkDocs(req, opts, function (err, res) {
if (err) {
return callback(err);
}
if (!opts.new_edits) {
// this is what couch does when new_edits is false
res = res.filter(function (x) {
return x.error;
});
}
callback(null, res);
});
});
AbstractPouchDB.prototype.registerDependentDatabase =
utils.adapterFun('registerDependentDatabase', function (dependentDb,
callback) {
var depDB = new this.constructor(dependentDb, this.__opts);
function diffFun(doc) {
doc.dependentDbs = doc.dependentDbs || {};
if (doc.dependentDbs[dependentDb]) {
return false; // no update required
}
doc.dependentDbs[dependentDb] = true;
return doc;
}
upsert(this, '_local/_pouch_dependentDbs', diffFun, function (err) {
if (err) {
return callback(err);
}
return callback(null, {db: depDB});
});
});
AbstractPouchDB.prototype.destroy =
utils.adapterFun('destroy', function (callback) {
var self = this;
var usePrefix = 'use_prefix' in self ? self.use_prefix : true;
function destroyDb() {
// call destroy method of the particular adaptor
self._destroy(function (err, resp) {
if (err) {
return callback(err);
}
self.emit('destroyed');
callback(null, resp || { 'ok': true });
});
}
self.get('_local/_pouch_dependentDbs', function (err, localDoc) {
if (err) {
if (err.status !== 404) {
return callback(err);
} else { // no dependencies
return destroyDb();
}
}
var dependentDbs = localDoc.dependentDbs;
var PouchDB = self.constructor;
var deletedMap = Object.keys(dependentDbs).map(function (name) {
var trueName = usePrefix ?
name.replace(new RegExp('^' + PouchDB.prefix), '') : name;
return new PouchDB(trueName, self.__opts).destroy();
});
Promise.all(deletedMap).then(destroyDb, function (error) {
callback(error);
});
});
});
},{"./changes":114,"./deps/errors":120,"./deps/upsert":128,"./merge":133,"./utils":138,"events":45}],103:[function(require,module,exports){
(function (process){
"use strict";
var CHANGES_BATCH_SIZE = 25;
// according to http://stackoverflow.com/a/417184/680742,
// the de factor URL length limit is 2000 characters.
// but since most of our measurements don't take the full
// URL into account, we fudge it a bit.
// TODO: we could measure the full URL to enforce exactly 2000 chars
var MAX_URL_LENGTH = 1800;
var utils = require('../../utils');
var errors = require('../../deps/errors');
var log = require('debug')('pouchdb:http');
var isBrowser = typeof process === 'undefined' || process.browser;
var buffer = require('../../deps/buffer');
function encodeDocId(id) {
if (/^_design/.test(id)) {
return '_design/' + encodeURIComponent(id.slice(8));
}
if (/^_local/.test(id)) {
return '_local/' + encodeURIComponent(id.slice(7));
}
return encodeURIComponent(id);
}
function preprocessAttachments(doc) {
if (!doc._attachments || !Object.keys(doc._attachments)) {
return utils.Promise.resolve();
}
return utils.Promise.all(Object.keys(doc._attachments).map(function (key) {
var attachment = doc._attachments[key];
if (attachment.data && typeof attachment.data !== 'string') {
if (isBrowser) {
return new utils.Promise(function (resolve) {
utils.readAsBinaryString(attachment.data, function (binary) {
attachment.data = utils.btoa(binary);
resolve();
});
});
} else {
attachment.data = attachment.data.toString('base64');
}
}
}));
}
// Get all the information you possibly can about the URI given by name and
// return it as a suitable object.
function getHost(name, opts) {
// If the given name contains "http:"
if (/http(s?):/.test(name)) {
// Prase the URI into all its little bits
var uri = utils.parseUri(name);
// Store the fact that it is a remote URI
uri.remote = true;
// Store the user and password as a separate auth object
if (uri.user || uri.password) {
uri.auth = {username: uri.user, password: uri.password};
}
// Split the path part of the URI into parts using '/' as the delimiter
// after removing any leading '/' and any trailing '/'
var parts = uri.path.replace(/(^\/|\/$)/g, '').split('/');
// Store the first part as the database name and remove it from the parts
// array
uri.db = parts.pop();
// Restore the path by joining all the remaining parts (all the parts
// except for the database name) with '/'s
uri.path = parts.join('/');
opts = opts || {};
opts = utils.clone(opts);
uri.headers = opts.headers || (opts.ajax && opts.ajax.headers) || {};
if (opts.auth || uri.auth) {
var nAuth = opts.auth || uri.auth;
var token = utils.btoa(nAuth.username + ':' + nAuth.password);
uri.headers.Authorization = 'Basic ' + token;
}
if (opts.headers) {
uri.headers = opts.headers;
}
return uri;
}
// If the given name does not contain 'http:' then return a very basic object
// with no host, the current path, the given name as the database name and no
// username/password
return {host: '', path: '/', db: name, auth: false};
}
// Generate a URL with the host data given by opts and the given path
function genDBUrl(opts, path) {
return genUrl(opts, opts.db + '/' + path);
}
// Generate a URL with the host data given by opts and the given path
function genUrl(opts, path) {
if (opts.remote) {
// If the host already has a path, then we need to have a path delimiter
// Otherwise, the path delimiter is the empty string
var pathDel = !opts.path ? '' : '/';
// If the host already has a path, then we need to have a path delimiter
// Otherwise, the path delimiter is the empty string
return opts.protocol + '://' + opts.host + ':' + opts.port + '/' +
opts.path + pathDel + path;
}
return '/' + path;
}
// Implements the PouchDB API for dealing with CouchDB instances over HTTP
function HttpPouch(opts, callback) {
// The functions that will be publicly available for HttpPouch
var api = this;
api.getHost = opts.getHost ? opts.getHost : getHost;
// Parse the URI given by opts.name into an easy-to-use object
var host = api.getHost(opts.name, opts);
// Generate the database URL based on the host
var dbUrl = genDBUrl(host, '');
api.getUrl = function () {return dbUrl; };
api.getHeaders = function () {return utils.clone(host.headers); };
var ajaxOpts = opts.ajax || {};
opts = utils.clone(opts);
function ajax(options, callback) {
var reqOpts = utils.extend(true, utils.clone(ajaxOpts), options);
log(reqOpts.method + ' ' + reqOpts.url);
return utils.ajax(reqOpts, callback);
}
// Create a new CouchDB database based on the given opts
var createDB = function () {
ajax({headers: host.headers, method: 'PUT', url: dbUrl}, function (err) {
// If we get an "Unauthorized" error
if (err && err.status === 401) {
// Test if the database already exists
ajax({headers: host.headers, method: 'HEAD', url: dbUrl},
function (err) {
// If there is still an error
if (err) {
// Give the error to the callback to deal with
callback(err);
} else {
// Continue as if there had been no errors
callback(null, api);
}
});
// If there were no errros or if the only error is "Precondition Failed"
// (note: "Precondition Failed" occurs when we try to create a database
// that already exists)
} else if (!err || err.status === 412) {
// Continue as if there had been no errors
callback(null, api);
} else {
callback(err);
}
});
};
if (!opts.skipSetup) {
ajax({headers: host.headers, method: 'GET', url: dbUrl}, function (err) {
//check if the db exists
if (err) {
if (err.status === 404) {
utils.explain404(
'PouchDB is just detecting if the remote DB exists.');
//if it doesn't, create it
createDB();
} else {
callback(err);
}
} else {
//go do stuff with the db
callback(null, api);
}
});
}
api.type = function () {
return 'http';
};
api.id = utils.adapterFun('id', function (callback) {
ajax({
headers: host.headers,
method: 'GET',
url: genUrl(host, '')
}, function (err, result) {
var uuid = (result && result.uuid) ?
result.uuid + host.db : genDBUrl(host, '');
callback(null, uuid);
});
});
api.request = utils.adapterFun('request', function (options, callback) {
options.headers = host.headers;
options.url = genDBUrl(host, options.url);
ajax(options, callback);
});
// Sends a POST request to the host calling the couchdb _compact function
// version: The version of CouchDB it is running
api.compact = utils.adapterFun('compact', function (opts, callback) {
if (typeof opts === 'function') {
callback = opts;
opts = {};
}
opts = utils.clone(opts);
ajax({
headers: host.headers,
url: genDBUrl(host, '_compact'),
method: 'POST'
}, function () {
function ping() {
api.info(function (err, res) {
if (!res.compact_running) {
callback(null, {ok: true});
} else {
setTimeout(ping, opts.interval || 200);
}
});
}
// Ping the http if it's finished compaction
if (typeof callback === "function") {
ping();
}
});
});
// Calls GET on the host, which gets back a JSON string containing
// couchdb: A welcome string
// version: The version of CouchDB it is running
api._info = function (callback) {
ajax({
headers: host.headers,
method: 'GET',
url: genDBUrl(host, '')
}, function (err, res) {
if (err) {
callback(err);
} else {
res.host = genDBUrl(host, '');
callback(null, res);
}
});
};
// Get the document with the given id from the database given by host.
// The id could be solely the _id in the database, or it may be a
// _design/ID or _local/ID path
api.get = utils.adapterFun('get', function (id, opts, callback) {
// If no options were given, set the callback to the second parameter
if (typeof opts === 'function') {
callback = opts;
opts = {};
}
opts = utils.clone(opts);
if (opts.auto_encode === undefined) {
opts.auto_encode = true;
}
// List of parameters to add to the GET request
var params = [];
// If it exists, add the opts.revs value to the list of parameters.
// If revs=true then the resulting JSON will include a field
// _revisions containing an array of the revision IDs.
if (opts.revs) {
params.push('revs=true');
}
// If it exists, add the opts.revs_info value to the list of parameters.
// If revs_info=true then the resulting JSON will include the field
// _revs_info containing an array of objects in which each object
// representing an available revision.
if (opts.revs_info) {
params.push('revs_info=true');
}
if (opts.local_seq) {
params.push('local_seq=true');
}
// If it exists, add the opts.open_revs value to the list of parameters.
// If open_revs=all then the resulting JSON will include all the leaf
// revisions. If open_revs=["rev1", "rev2",...] then the resulting JSON
// will contain an array of objects containing data of all revisions
if (opts.open_revs) {
if (opts.open_revs !== "all") {
opts.open_revs = JSON.stringify(opts.open_revs);
}
params.push('open_revs=' + opts.open_revs);
}
// If it exists, add the opts.attachments value to the list of parameters.
// If attachments=true the resulting JSON will include the base64-encoded
// contents in the "data" property of each attachment.
if (opts.attachments) {
params.push('attachments=true');
}
// If it exists, add the opts.rev value to the list of parameters.
// If rev is given a revision number then get the specified revision.
if (opts.rev) {
params.push('rev=' + opts.rev);
}
// If it exists, add the opts.conflicts value to the list of parameters.
// If conflicts=true then the resulting JSON will include the field
// _conflicts containing all the conflicting revisions.
if (opts.conflicts) {
params.push('conflicts=' + opts.conflicts);
}
// Format the list of parameters into a valid URI query string
params = params.join('&');
params = params === '' ? '' : '?' + params;
if (opts.auto_encode) {
id = encodeDocId(id);
}
// Set the options for the ajax call
var options = {
headers: host.headers,
method: 'GET',
url: genDBUrl(host, id + params)
};
var getRequestAjaxOpts = opts.ajax || {};
utils.extend(true, options, getRequestAjaxOpts);
// If the given id contains at least one '/' and the part before the '/'
// is NOT "_design" and is NOT "_local"
// OR
// If the given id contains at least two '/' and the part before the first
// '/' is "_design".
// TODO This second condition seems strange since if parts[0] === '_design'
// then we already know that parts[0] !== '_local'.
var parts = id.split('/');
if ((parts.length > 1 && parts[0] !== '_design' && parts[0] !== '_local') ||
(parts.length > 2 && parts[0] === '_design' && parts[0] !== '_local')) {
// Binary is expected back from the server
options.binary = true;
}
// Get the document
ajax(options, function (err, doc, xhr) {
// If the document does not exist, send an error to the callback
if (err) {
return callback(err);
}
// Send the document to the callback
callback(null, doc, xhr);
});
});
// Delete the document given by doc from the database given by host.
api.remove = utils.adapterFun('remove',
function (docOrId, optsOrRev, opts, callback) {
var doc;
if (typeof optsOrRev === 'string') {
// id, rev, opts, callback style
doc = {
_id: docOrId,
_rev: optsOrRev
};
if (typeof opts === 'function') {
callback = opts;
opts = {};
}
} else {
// doc, opts, callback style
doc = docOrId;
if (typeof optsOrRev === 'function') {
callback = optsOrRev;
opts = {};
} else {
callback = opts;
opts = optsOrRev;
}
}
var rev = (doc._rev || opts.rev);
// Delete the document
ajax({
headers: host.headers,
method: 'DELETE',
url: genDBUrl(host, encodeDocId(doc._id)) + '?rev=' + rev
}, callback);
});
function encodeAttachmentId(attachmentId) {
return attachmentId.split("/").map(encodeURIComponent).join("/");
}
// Get the attachment
api.getAttachment =
utils.adapterFun('getAttachment', function (docId, attachmentId, opts,
callback) {
if (typeof opts === 'function') {
callback = opts;
opts = {};
}
opts = utils.clone(opts);
if (opts.auto_encode === undefined) {
opts.auto_encode = true;
}
if (opts.auto_encode) {
docId = encodeDocId(docId);
}
opts.auto_encode = false;
api.get(docId + '/' + encodeAttachmentId(attachmentId), opts, callback);
});
// Remove the attachment given by the id and rev
api.removeAttachment =
utils.adapterFun('removeAttachment', function (docId, attachmentId, rev,
callback) {
var url = genDBUrl(host, encodeDocId(docId) + '/' +
encodeAttachmentId(attachmentId)) + '?rev=' + rev;
ajax({
headers: host.headers,
method: 'DELETE',
url: url
}, callback);
});
// Add the attachment given by blob and its contentType property
// to the document with the given id, the revision given by rev, and
// add it to the database given by host.
api.putAttachment =
utils.adapterFun('putAttachment', function (docId, attachmentId, rev, blob,
type, callback) {
if (typeof type === 'function') {
callback = type;
type = blob;
blob = rev;
rev = null;
}
if (typeof type === 'undefined') {
type = blob;
blob = rev;
rev = null;
}
var id = encodeDocId(docId) + '/' + encodeAttachmentId(attachmentId);
var url = genDBUrl(host, id);
if (rev) {
url += '?rev=' + rev;
}
if (typeof blob === 'string') {
var binary;
try {
binary = utils.atob(blob);
} catch (err) {
// it's not base64-encoded, so throw error
return callback(errors.error(errors.BAD_ARG,
'Attachments need to be base64 encoded'));
}
if (isBrowser) {
blob = utils.createBlob([utils.fixBinary(binary)], {type: type});
} else {
blob = binary ? new buffer(binary, 'binary') : '';
}
}
var opts = {
headers: utils.clone(host.headers),
method: 'PUT',
url: url,
processData: false,
body: blob,
timeout: 60000
};
opts.headers['Content-Type'] = type;
// Add the attachment
ajax(opts, callback);
});
// Add the document given by doc (in JSON string format) to the database
// given by host. This fails if the doc has no _id field.
api.put = utils.adapterFun('put', utils.getArguments(function (args) {
var temp, temptype, opts;
var doc = args.shift();
var id = '_id' in doc;
var callback = args.pop();
if (typeof doc !== 'object' || Array.isArray(doc)) {
return callback(errors.error(errors.NOT_AN_OBJECT));
}
doc = utils.clone(doc);
preprocessAttachments(doc).then(function () {
while (true) {
temp = args.shift();
temptype = typeof temp;
if (temptype === "string" && !id) {
doc._id = temp;
id = true;
} else if (temptype === "string" && id && !('_rev' in doc)) {
doc._rev = temp;
} else if (temptype === "object") {
opts = utils.clone(temp);
}
if (!args.length) {
break;
}
}
opts = opts || {};
var error = utils.invalidIdError(doc._id);
if (error) {
throw error;
}
// List of parameter to add to the PUT request
var params = [];
// If it exists, add the opts.new_edits value to the list of parameters.
// If new_edits = false then the database will NOT assign this document a
// new revision number
if (opts && typeof opts.new_edits !== 'undefined') {
params.push('new_edits=' + opts.new_edits);
}
// Format the list of parameters into a valid URI query string
params = params.join('&');
if (params !== '') {
params = '?' + params;
}
// Add the document
ajax({
headers: host.headers,
method: 'PUT',
url: genDBUrl(host, encodeDocId(doc._id)) + params,
body: doc
}, function (err, res) {
if (err) {
return callback(err);
}
res.ok = true;
callback(null, res);
});
}).catch(callback);
}));
// Add the document given by doc (in JSON string format) to the database
// given by host. This does not assume that doc is a new document
// (i.e. does not have a _id or a _rev field.)
api.post = utils.adapterFun('post', function (doc, opts, callback) {
// If no options were given, set the callback to be the second parameter
if (typeof opts === 'function') {
callback = opts;
opts = {};
}
opts = utils.clone(opts);
if (typeof doc !== 'object') {
return callback(errors.error(errors.NOT_AN_OBJECT));
}
if (! ("_id" in doc)) {
doc._id = utils.uuid();
}
api.put(doc, opts, function (err, res) {
if (err) {
return callback(err);
}
res.ok = true;
callback(null, res);
});
});
// Update/create multiple documents given by req in the database
// given by host.
api._bulkDocs = function (req, opts, callback) {
// If opts.new_edits exists add it to the document data to be
// send to the database.
// If new_edits=false then it prevents the database from creating
// new revision numbers for the documents. Instead it just uses
// the old ones. This is used in database replication.
if (typeof opts.new_edits !== 'undefined') {
req.new_edits = opts.new_edits;
}
utils.Promise.all(req.docs.map(preprocessAttachments)).then(function () {
// Update/create the documents
ajax({
headers: host.headers,
method: 'POST',
url: genDBUrl(host, '_bulk_docs'),
body: req
}, function (err, results) {
if (err) {
return callback(err);
}
results.forEach(function (result) {
result.ok = true; // smooths out cloudant not adding this
});
callback(null, results);
});
}).catch(callback);
};
// Get a listing of the documents in the database given
// by host and ordered by increasing id.
api.allDocs = utils.adapterFun('allDocs', function (opts, callback) {
if (typeof opts === 'function') {
callback = opts;
opts = {};
}
opts = utils.clone(opts);
// List of parameters to add to the GET request
var params = [];
var body;
var method = 'GET';
if (opts.conflicts) {
params.push('conflicts=true');
}
// If opts.descending is truthy add it to params
if (opts.descending) {
params.push('descending=true');
}
// If opts.include_docs exists, add the include_docs value to the
// list of parameters.
// If include_docs=true then include the associated document with each
// result.
if (opts.include_docs) {
params.push('include_docs=true');
}
if (opts.attachments) {
// added in CouchDB 1.6.0
params.push('attachments=true');
}
if (opts.key) {
params.push('key=' + encodeURIComponent(JSON.stringify(opts.key)));
}
// If opts.startkey exists, add the startkey value to the list of
// parameters.
// If startkey is given then the returned list of documents will
// start with the document whose id is startkey.
if (opts.startkey) {
params.push('startkey=' +
encodeURIComponent(JSON.stringify(opts.startkey)));
}
// If opts.endkey exists, add the endkey value to the list of parameters.
// If endkey is given then the returned list of docuemnts will
// end with the document whose id is endkey.
if (opts.endkey) {
params.push('endkey=' + encodeURIComponent(JSON.stringify(opts.endkey)));
}
if (typeof opts.inclusive_end !== 'undefined') {
params.push('inclusive_end=' + !!opts.inclusive_end);
}
// If opts.limit exists, add the limit value to the parameter list.
if (typeof opts.limit !== 'undefined') {
params.push('limit=' + opts.limit);
}
if (typeof opts.skip !== 'undefined') {
params.push('skip=' + opts.skip);
}
// Format the list of parameters into a valid URI query string
params = params.join('&');
if (params !== '') {
params = '?' + params;
}
if (typeof opts.keys !== 'undefined') {
var keysAsString =
'keys=' + encodeURIComponent(JSON.stringify(opts.keys));
if (keysAsString.length + params.length + 1 <= MAX_URL_LENGTH) {
// If the keys are short enough, do a GET. we do this to work around
// Safari not understanding 304s on POSTs (see issue #1239)
params += (params.indexOf('?') !== -1 ? '&' : '?') + keysAsString;
} else {
// If keys are too long, issue a POST request to circumvent GET
// query string limits
// see http://wiki.apache.org/couchdb/HTTP_view_API#Querying_Options
method = 'POST';
body = JSON.stringify({keys: opts.keys});
}
}
// Get the document listing
ajax({
headers: host.headers,
method: method,
url: genDBUrl(host, '_all_docs' + params),
body: body
}, callback);
});
// Get a list of changes made to documents in the database given by host.
// TODO According to the README, there should be two other methods here,
// api.changes.addListener and api.changes.removeListener.
api._changes = function (opts) {
// We internally page the results of a changes request, this means
// if there is a large set of changes to be returned we can start
// processing them quicker instead of waiting on the entire
// set of changes to return and attempting to process them at once
var batchSize = 'batch_size' in opts ? opts.batch_size : CHANGES_BATCH_SIZE;
opts = utils.clone(opts);
opts.timeout = opts.timeout || 30 * 1000;
// We give a 5 second buffer for CouchDB changes to respond with
// an ok timeout
var params = { timeout: opts.timeout - (5 * 1000) };
var limit = (typeof opts.limit !== 'undefined') ? opts.limit : false;
if (limit === 0) {
limit = 1;
}
var returnDocs;
if ('returnDocs' in opts) {
returnDocs = opts.returnDocs;
} else {
returnDocs = true;
}
//
var leftToFetch = limit;
if (opts.style) {
params.style = opts.style;
}
if (opts.include_docs || opts.filter && typeof opts.filter === 'function') {
params.include_docs = true;
}
if (opts.attachments) {
params.attachments = true;
}
if (opts.continuous) {
params.feed = 'longpoll';
}
if (opts.conflicts) {
params.conflicts = true;
}
if (opts.descending) {
params.descending = true;
}
if (opts.filter && typeof opts.filter === 'string') {
params.filter = opts.filter;
if (opts.filter === '_view' &&
opts.view &&
typeof opts.view === 'string') {
params.view = opts.view;
}
}
// If opts.query_params exists, pass it through to the changes request.
// These parameters may be used by the filter on the source database.
if (opts.query_params && typeof opts.query_params === 'object') {
for (var param_name in opts.query_params) {
if (opts.query_params.hasOwnProperty(param_name)) {
params[param_name] = opts.query_params[param_name];
}
}
}
var method = 'GET';
var body;
if (opts.doc_ids) {
// set this automagically for the user; it's annoying that couchdb
// requires both a "filter" and a "doc_ids" param.
params.filter = '_doc_ids';
var docIdsJson = JSON.stringify(opts.doc_ids);
if (docIdsJson.length < MAX_URL_LENGTH) {
params.doc_ids = docIdsJson;
} else {
// anything greater than ~2000 is unsafe for gets, so
// use POST instead
method = 'POST';
body = {doc_ids: opts.doc_ids };
}
}
if (opts.continuous && api._useSSE) {
return api.sse(opts, params, returnDocs);
}
var xhr;
var lastFetchedSeq;
// Get all the changes starting wtih the one immediately after the
// sequence number given by since.
var fetch = function (since, callback) {
if (opts.aborted) {
return;
}
params.since = since;
if (typeof params.since === "object") {
params.since = JSON.stringify(params.since);
}
if (opts.descending) {
if (limit) {
params.limit = leftToFetch;
}
} else {
params.limit = (!limit || leftToFetch > batchSize) ?
batchSize : leftToFetch;
}
var paramStr = '?' + Object.keys(params).map(function (k) {
return k + '=' + params[k];
}).join('&');
// Set the options for the ajax call
var xhrOpts = {
headers: host.headers,
method: method,
url: genDBUrl(host, '_changes' + paramStr),
// _changes can take a long time to generate, especially when filtered
timeout: opts.timeout,
body: body
};
lastFetchedSeq = since;
if (opts.aborted) {
return;
}
// Get the changes
xhr = ajax(xhrOpts, callback);
};
// If opts.since exists, get all the changes from the sequence
// number given by opts.since. Otherwise, get all the changes
// from the sequence number 0.
var fetchTimeout = 10;
var fetchRetryCount = 0;
var results = {results: []};
var fetched = function (err, res) {
if (opts.aborted) {
return;
}
var raw_results_length = 0;
// If the result of the ajax call (res) contains changes (res.results)
if (res && res.results) {
raw_results_length = res.results.length;
results.last_seq = res.last_seq;
// For each change
var req = {};
req.query = opts.query_params;
res.results = res.results.filter(function (c) {
leftToFetch--;
var ret = utils.filterChange(opts)(c);
if (ret) {
if (returnDocs) {
results.results.push(c);
}
utils.call(opts.onChange, c);
}
return ret;
});
} else if (err) {
// In case of an error, stop listening for changes and call
// opts.complete
opts.aborted = true;
utils.call(opts.complete, err);
return;
}
// The changes feed may have timed out with no results
// if so reuse last update sequence
if (res && res.last_seq) {
lastFetchedSeq = res.last_seq;
}
var finished = (limit && leftToFetch <= 0) ||
(res && raw_results_length < batchSize) ||
(opts.descending);
if ((opts.continuous && !(limit && leftToFetch <= 0)) || !finished) {
// Increase retry delay exponentially as long as errors persist
if (err) {
fetchRetryCount += 1;
} else {
fetchRetryCount = 0;
}
var timeoutMultiplier = 1 << fetchRetryCount;
var retryWait = fetchTimeout * timeoutMultiplier;
var maximumWait = opts.maximumWait || 30000;
if (retryWait > maximumWait) {
utils.call(opts.complete, err || errors.error(errors.UNKNOWN_ERROR));
return;
}
// Queue a call to fetch again with the newest sequence number
setTimeout(function () { fetch(lastFetchedSeq, fetched); }, retryWait);
} else {
// We're done, call the callback
utils.call(opts.complete, null, results);
}
};
fetch(opts.since || 0, fetched);
// Return a method to cancel this method from processing any more
return {
cancel: function () {
opts.aborted = true;
if (xhr) {
xhr.abort();
}
}
};
};
api.sse = function (opts, params, returnDocs) {
params.feed = 'eventsource';
params.since = opts.since || 0;
params.limit = opts.limit;
delete params.timeout;
var paramStr = '?' + Object.keys(params).map(function (k) {
return k + '=' + params[k];
}).join('&');
var url = genDBUrl(host, '_changes' + paramStr);
var source = new EventSource(url);
var results = {
results: [],
last_seq: false
};
var dispatched = false;
var open = false;
source.addEventListener('message', msgHandler, false);
source.onopen = function () {
open = true;
};
source.onerror = errHandler;
return {
cancel: function () {
if (dispatched) {
return dispatched.cancel();
}
source.removeEventListener('message', msgHandler, false);
source.close();
}
};
function msgHandler(e) {
var data = JSON.parse(e.data);
if (returnDocs) {
results.results.push(data);
}
results.last_seq = data.seq;
utils.call(opts.onChange, data);
}
function errHandler(err) {
source.removeEventListener('message', msgHandler, false);
if (open === false) {
// errored before it opened
// likely doesn't support EventSource
api._useSSE = false;
dispatched = api._changes(opts);
return;
}
source.close();
utils.call(opts.complete, err);
}
};
api._useSSE = false;
// Currently disabled due to failing chrome tests in saucelabs
// api._useSSE = typeof global.EventSource === 'function';
// Given a set of document/revision IDs (given by req), tets the subset of
// those that do NOT correspond to revisions stored in the database.
// See http://wiki.apache.org/couchdb/HttpPostRevsDiff
api.revsDiff = utils.adapterFun('revsDiff', function (req, opts, callback) {
// If no options were given, set the callback to be the second parameter
if (typeof opts === 'function') {
callback = opts;
opts = {};
}
// Get the missing document/revision IDs
ajax({
headers: host.headers,
method: 'POST',
url: genDBUrl(host, '_revs_diff'),
body: JSON.stringify(req)
}, callback);
});
api._close = function (callback) {
callback();
};
api._destroy = function (callback) {
ajax({
url: genDBUrl(host, ''),
method: 'DELETE',
headers: host.headers
}, function (err, resp) {
if (err) {
api.emit('error', err);
callback(err);
} else {
api.emit('destroyed');
api.constructor.emit('destroyed', opts.name);
callback(null, resp);
}
});
};
}
// HttpPouch is a valid adapter.
HttpPouch.valid = function () {
return true;
};
module.exports = HttpPouch;
}).call(this,require("/Users/nlawson/workspace-node/pouchdb-authentication/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js"))
},{"../../deps/buffer":119,"../../deps/errors":120,"../../utils":138,"/Users/nlawson/workspace-node/pouchdb-authentication/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js":46,"debug":141}],104:[function(require,module,exports){
'use strict';
var merge = require('../../merge');
var errors = require('../../deps/errors');
var idbUtils = require('./idb-utils');
var idbConstants = require('./idb-constants');
var ATTACH_STORE = idbConstants.ATTACH_STORE;
var BY_SEQ_STORE = idbConstants.BY_SEQ_STORE;
var DOC_STORE = idbConstants.DOC_STORE;
var decodeDoc = idbUtils.decodeDoc;
var decodeMetadata = idbUtils.decodeMetadata;
var fetchAttachmentsIfNecessary = idbUtils.fetchAttachmentsIfNecessary;
var postProcessAttachments = idbUtils.postProcessAttachments;
var openTransactionSafely = idbUtils.openTransactionSafely;
function createKeyRange(start, end, inclusiveEnd, key, descending) {
try {
if (start && end) {
if (descending) {
return IDBKeyRange.bound(end, start, !inclusiveEnd, false);
} else {
return IDBKeyRange.bound(start, end, false, !inclusiveEnd);
}
} else if (start) {
if (descending) {
return IDBKeyRange.upperBound(start);
} else {
return IDBKeyRange.lowerBound(start);
}
} else if (end) {
if (descending) {
return IDBKeyRange.lowerBound(end, !inclusiveEnd);
} else {
return IDBKeyRange.upperBound(end, !inclusiveEnd);
}
} else if (key) {
return IDBKeyRange.only(key);
}
} catch (e) {
return {error: e};
}
return null;
}
function handleKeyRangeError(api, opts, err, callback) {
if (err.name === "DataError" && err.code === 0) {
// data error, start is less than end
return callback(null, {
total_rows: api._meta.docCount,
offset: opts.skip,
rows: []
});
}
callback(errors.error(errors.IDB_ERROR, err.name, err.message));
}
function idbAllDocs(opts, api, idb, callback) {
function allDocsQuery(opts, callback) {
var start = 'startkey' in opts ? opts.startkey : false;
var end = 'endkey' in opts ? opts.endkey : false;
var key = 'key' in opts ? opts.key : false;
var skip = opts.skip || 0;
var limit = typeof opts.limit === 'number' ? opts.limit : -1;
var inclusiveEnd = opts.inclusive_end !== false;
var descending = 'descending' in opts && opts.descending ? 'prev' : null;
var keyRange = createKeyRange(start, end, inclusiveEnd, key, descending);
if (keyRange && keyRange.error) {
return handleKeyRangeError(api, opts, keyRange.error, callback);
}
var stores = [DOC_STORE, BY_SEQ_STORE];
if (opts.attachments) {
stores.push(ATTACH_STORE);
}
var txnResult = openTransactionSafely(idb, stores, 'readonly');
if (txnResult.error) {
return callback(txnResult.error);
}
var txn = txnResult.txn;
var docStore = txn.objectStore(DOC_STORE);
var seqStore = txn.objectStore(BY_SEQ_STORE);
var cursor = descending ?
docStore.openCursor(keyRange, descending) :
docStore.openCursor(keyRange);
var docIdRevIndex = seqStore.index('_doc_id_rev');
var results = [];
var docCount = 0;
// if the user specifies include_docs=true, then we don't
// want to block the main cursor while we're fetching the doc
function fetchDocAsynchronously(metadata, row, winningRev) {
var key = metadata.id + "::" + winningRev;
docIdRevIndex.get(key).onsuccess = function onGetDoc(e) {
row.doc = decodeDoc(e.target.result);
if (opts.conflicts) {
row.doc._conflicts = merge.collectConflicts(metadata);
}
fetchAttachmentsIfNecessary(row.doc, opts, txn);
};
}
function allDocsInner(cursor, winningRev, metadata) {
var row = {
id: metadata.id,
key: metadata.id,
value: {
rev: winningRev
}
};
var deleted = metadata.deleted;
if (opts.deleted === 'ok') {
results.push(row);
// deleted docs are okay with "keys" requests
if (deleted) {
row.value.deleted = true;
row.doc = null;
} else if (opts.include_docs) {
fetchDocAsynchronously(metadata, row, winningRev);
}
} else if (!deleted && skip-- <= 0) {
results.push(row);
if (opts.include_docs) {
fetchDocAsynchronously(metadata, row, winningRev);
}
if (--limit === 0) {
return;
}
}
cursor.continue();
}
function onGetCursor(e) {
docCount = api._meta.docCount; // do this within the txn for consistency
var cursor = e.target.result;
if (!cursor) {
return;
}
var metadata = decodeMetadata(cursor.value);
var winningRev = metadata.winningRev;
allDocsInner(cursor, winningRev, metadata);
}
function onResultsReady() {
callback(null, {
total_rows: docCount,
offset: opts.skip,
rows: results
});
}
function onTxnComplete() {
if (opts.attachments) {
postProcessAttachments(results).then(onResultsReady);
} else {
onResultsReady();
}
}
txn.oncomplete = onTxnComplete;
cursor.onsuccess = onGetCursor;
}
function allDocs(opts, callback) {
if (opts.limit === 0) {
return callback(null, {
total_rows: api._meta.docCount,
offset: opts.skip,
rows: []
});
}
allDocsQuery(opts, callback);
}
allDocs(opts, callback);
}
module.exports = idbAllDocs;
},{"../../deps/errors":120,"../../merge":133,"./idb-constants":107,"./idb-utils":108}],105:[function(require,module,exports){
'use strict';
var utils = require('../../utils');
var idbConstants = require('./idb-constants');
var DETECT_BLOB_SUPPORT_STORE = idbConstants.DETECT_BLOB_SUPPORT_STORE;
//
// Detect blob support. Chrome didn't support it until version 38.
// In version 37 they had a broken version where PNGs (and possibly
// other binary types) aren't stored correctly, because when you fetch
// them, the content type is always null.
//
// Furthermore, they have some outstanding bugs where blobs occasionally
// are read by FileReader as null, or by ajax as 404s.
//
// Sadly we use the 404 bug to detect the FileReader bug, so if they
// get fixed independently and released in different versions of Chrome,
// then the bug could come back. So it's worthwhile to watch these issues:
// 404 bug: https://code.google.com/p/chromium/issues/detail?id=447916
// FileReader bug: https://code.google.com/p/chromium/issues/detail?id=447836
//
function checkBlobSupport(txn, idb) {
return new utils.Promise(function (resolve, reject) {
var blob = utils.createBlob([''], {type: 'image/png'});
txn.objectStore(DETECT_BLOB_SUPPORT_STORE).put(blob, 'key');
txn.oncomplete = function () {
// have to do it in a separate transaction, else the correct
// content type is always returned
var blobTxn = idb.transaction([DETECT_BLOB_SUPPORT_STORE],
'readwrite');
var getBlobReq = blobTxn.objectStore(
DETECT_BLOB_SUPPORT_STORE).get('key');
getBlobReq.onerror = reject;
getBlobReq.onsuccess = function (e) {
var storedBlob = e.target.result;
var url = URL.createObjectURL(storedBlob);
utils.ajax({
url: url,
cache: true,
binary: true
}, function (err, res) {
if (err && err.status === 405) {
// firefox won't let us do that. but firefox doesn't
// have the blob type bug that Chrome does, so that's ok
resolve(true);
} else {
resolve(!!(res && res.type === 'image/png'));
if (err && err.status === 404) {
utils.explain404('PouchDB is just detecting blob URL support.');
}
}
URL.revokeObjectURL(url);
});
};
};
}).catch(function () {
return false; // error, so assume unsupported
});
}
module.exports = checkBlobSupport;
},{"../../utils":138,"./idb-constants":107}],106:[function(require,module,exports){
'use strict';
var utils = require('../../utils');
var errors = require('../../deps/errors');
var idbUtils = require('./idb-utils');
var idbConstants = require('./idb-constants');
var ATTACH_AND_SEQ_STORE = idbConstants.ATTACH_AND_SEQ_STORE;
var ATTACH_STORE = idbConstants.ATTACH_STORE;
var BY_SEQ_STORE = idbConstants.BY_SEQ_STORE;
var DOC_STORE = idbConstants.DOC_STORE;
var LOCAL_STORE = idbConstants.LOCAL_STORE;
var META_STORE = idbConstants.META_STORE;
var compactRevs = idbUtils.compactRevs;
var decodeMetadata = idbUtils.decodeMetadata;
var encodeMetadata = idbUtils.encodeMetadata;
var idbError = idbUtils.idbError;
var openTransactionSafely = idbUtils.openTransactionSafely;
function idbBulkDocs(req, opts, api, idb, Changes, callback) {
var docInfos = req.docs;
var txn;
var docStore;
var bySeqStore;
var attachStore;
var attachAndSeqStore;
var docInfoError;
var docCountDelta = 0;
for (var i = 0, len = docInfos.length; i < len; i++) {
var doc = docInfos[i];
if (doc._id && utils.isLocalId(doc._id)) {
continue;
}
doc = docInfos[i] = utils.parseDoc(doc, opts.new_edits);
if (doc.error && !docInfoError) {
docInfoError = doc;
}
}
if (docInfoError) {
return callback(docInfoError);
}
var results = new Array(docInfos.length);
var fetchedDocs = new utils.Map();
var preconditionErrored = false;
var blobType = api._meta.blobSupport ? 'blob' : 'base64';
utils.preprocessAttachments(docInfos, blobType, function (err) {
if (err) {
return callback(err);
}
startTransaction();
});
function startTransaction() {
var stores = [
DOC_STORE, BY_SEQ_STORE,
ATTACH_STORE, META_STORE,
LOCAL_STORE, ATTACH_AND_SEQ_STORE
];
var txnResult = openTransactionSafely(idb, stores, 'readwrite');
if (txnResult.error) {
return callback(txnResult.error);
}
txn = txnResult.txn;
txn.onerror = idbError(callback);
txn.ontimeout = idbError(callback);
txn.oncomplete = complete;
docStore = txn.objectStore(DOC_STORE);
bySeqStore = txn.objectStore(BY_SEQ_STORE);
attachStore = txn.objectStore(ATTACH_STORE);
attachAndSeqStore = txn.objectStore(ATTACH_AND_SEQ_STORE);
verifyAttachments(function (err) {
if (err) {
preconditionErrored = true;
return callback(err);
}
fetchExistingDocs();
});
}
function processDocs() {
utils.processDocs(docInfos, api, fetchedDocs, txn, results,
writeDoc, opts);
}
function fetchExistingDocs() {
if (!docInfos.length) {
return;
}
var numFetched = 0;
function checkDone() {
if (++numFetched === docInfos.length) {
processDocs();
}
}
function readMetadata(event) {
var metadata = decodeMetadata(event.target.result);
if (metadata) {
fetchedDocs.set(metadata.id, metadata);
}
checkDone();
}
for (var i = 0, len = docInfos.length; i < len; i++) {
var docInfo = docInfos[i];
if (docInfo._id && utils.isLocalId(docInfo._id)) {
checkDone(); // skip local docs
continue;
}
var req = docStore.get(docInfo.metadata.id);
req.onsuccess = readMetadata;
}
}
function complete() {
if (preconditionErrored) {
return;
}
Changes.notify(api._meta.name);
api._meta.docCount += docCountDelta;
callback(null, results);
}
function verifyAttachment(digest, callback) {
var req = attachStore.get(digest);
req.onsuccess = function (e) {
if (!e.target.result) {
var err = errors.error(errors.MISSING_STUB,
'unknown stub attachment with digest ' +
digest);
err.status = 412;
callback(err);
} else {
callback();
}
};
}
function verifyAttachments(finish) {
var digests = [];
docInfos.forEach(function (docInfo) {
if (docInfo.data && docInfo.data._attachments) {
Object.keys(docInfo.data._attachments).forEach(function (filename) {
var att = docInfo.data._attachments[filename];
if (att.stub) {
digests.push(att.digest);
}
});
}
});
if (!digests.length) {
return finish();
}
var numDone = 0;
var err;
function checkDone() {
if (++numDone === digests.length) {
finish(err);
}
}
digests.forEach(function (digest) {
verifyAttachment(digest, function (attErr) {
if (attErr && !err) {
err = attErr;
}
checkDone();
});
});
}
function writeDoc(docInfo, winningRev, winningRevIsDeleted, newRevIsDeleted,
isUpdate, delta, resultsIdx, callback) {
docCountDelta += delta;
var doc = docInfo.data;
doc._id = docInfo.metadata.id;
doc._rev = docInfo.metadata.rev;
if (newRevIsDeleted) {
doc._deleted = true;
}
var hasAttachments = doc._attachments &&
Object.keys(doc._attachments).length;
if (hasAttachments) {
return writeAttachments(docInfo, winningRev, winningRevIsDeleted,
isUpdate, resultsIdx, callback);
}
finishDoc(docInfo, winningRev, winningRevIsDeleted,
isUpdate, resultsIdx, callback);
}
function autoCompact(docInfo) {
var revsToDelete = utils.compactTree(docInfo.metadata);
compactRevs(revsToDelete, docInfo.metadata.id, txn);
}
function finishDoc(docInfo, winningRev, winningRevIsDeleted,
isUpdate, resultsIdx, callback) {
var doc = docInfo.data;
var metadata = docInfo.metadata;
doc._doc_id_rev = metadata.id + '::' + metadata.rev;
delete doc._id;
delete doc._rev;
function afterPutDoc(e) {
if (isUpdate && api.auto_compaction) {
autoCompact(docInfo);
}
metadata.seq = e.target.result;
// Current _rev is calculated from _rev_tree on read
delete metadata.rev;
var metadataToStore = encodeMetadata(metadata, winningRev,
winningRevIsDeleted);
var metaDataReq = docStore.put(metadataToStore);
metaDataReq.onsuccess = afterPutMetadata;
}
function afterPutDocError(e) {
// ConstraintError, need to update, not put (see #1638 for details)
e.preventDefault(); // avoid transaction abort
e.stopPropagation(); // avoid transaction onerror
var index = bySeqStore.index('_doc_id_rev');
var getKeyReq = index.getKey(doc._doc_id_rev);
getKeyReq.onsuccess = function (e) {
var putReq = bySeqStore.put(doc, e.target.result);
putReq.onsuccess = afterPutDoc;
};
}
function afterPutMetadata() {
results[resultsIdx] = {
ok: true,
id: metadata.id,
rev: winningRev
};
fetchedDocs.set(docInfo.metadata.id, docInfo.metadata);
insertAttachmentMappings(docInfo, metadata.seq, callback);
}
var putReq = bySeqStore.put(doc);
putReq.onsuccess = afterPutDoc;
putReq.onerror = afterPutDocError;
}
function writeAttachments(docInfo, winningRev, winningRevIsDeleted,
isUpdate, resultsIdx, callback) {
var doc = docInfo.data;
var numDone = 0;
var attachments = Object.keys(doc._attachments);
function collectResults() {
if (numDone === attachments.length) {
finishDoc(docInfo, winningRev, winningRevIsDeleted,
isUpdate, resultsIdx, callback);
}
}
function attachmentSaved() {
numDone++;
collectResults();
}
attachments.forEach(function (key) {
var att = docInfo.data._attachments[key];
if (!att.stub) {
var data = att.data;
delete att.data;
var digest = att.digest;
saveAttachment(digest, data, attachmentSaved);
} else {
numDone++;
collectResults();
}
});
}
// map seqs to attachment digests, which
// we will need later during compaction
function insertAttachmentMappings(docInfo, seq, callback) {
var attsAdded = 0;
var attsToAdd = Object.keys(docInfo.data._attachments || {});
if (!attsToAdd.length) {
return callback();
}
function checkDone() {
if (++attsAdded === attsToAdd.length) {
callback();
}
}
function add(att) {
var digest = docInfo.data._attachments[att].digest;
var req = attachAndSeqStore.put({
seq: seq,
digestSeq: digest + '::' + seq
});
req.onsuccess = checkDone;
req.onerror = function (e) {
// this callback is for a constaint error, which we ignore
// because this docid/rev has already been associated with
// the digest (e.g. when new_edits == false)
e.preventDefault(); // avoid transaction abort
e.stopPropagation(); // avoid transaction onerror
checkDone();
};
}
for (var i = 0; i < attsToAdd.length; i++) {
add(attsToAdd[i]); // do in parallel
}
}
function saveAttachment(digest, data, callback) {
var getKeyReq = attachStore.count(digest);
getKeyReq.onsuccess = function(e) {
var count = e.target.result;
if (count) {
return callback(); // already exists
}
var newAtt = {
digest: digest,
body: data
};
var putReq = attachStore.put(newAtt);
putReq.onsuccess = callback;
};
}
}
module.exports = idbBulkDocs;
},{"../../deps/errors":120,"../../utils":138,"./idb-constants":107,"./idb-utils":108}],107:[function(require,module,exports){
'use strict';
// IndexedDB requires a versioned database structure, so we use the
// version here to manage migrations.
exports.ADAPTER_VERSION = 5;
// The object stores created for each database
// DOC_STORE stores the document meta data, its revision history and state
// Keyed by document id
exports. DOC_STORE = 'document-store';
// BY_SEQ_STORE stores a particular version of a document, keyed by its
// sequence id
exports.BY_SEQ_STORE = 'by-sequence';
// Where we store attachments
exports.ATTACH_STORE = 'attach-store';
// Where we store many-to-many relations
// between attachment digests and seqs
exports.ATTACH_AND_SEQ_STORE = 'attach-seq-store';
// Where we store database-wide meta data in a single record
// keyed by id: META_STORE
exports.META_STORE = 'meta-store';
// Where we store local documents
exports.LOCAL_STORE = 'local-store';
// Where we detect blob support
exports.DETECT_BLOB_SUPPORT_STORE = 'detect-blob-support';
},{}],108:[function(require,module,exports){
(function (process){
'use strict';
var errors = require('../../deps/errors');
var utils = require('../../utils');
var constants = require('./idb-constants');
function tryCode(fun, that, args) {
try {
fun.apply(that, args);
} catch (err) { // shouldn't happen
if (typeof PouchDB !== 'undefined') {
PouchDB.emit('error', err);
}
}
}
exports.taskQueue = {
running: false,
queue: []
};
exports.applyNext = function () {
if (exports.taskQueue.running || !exports.taskQueue.queue.length) {
return;
}
exports.taskQueue.running = true;
var item = exports.taskQueue.queue.shift();
item.action(function (err, res) {
tryCode(item.callback, this, [err, res]);
exports.taskQueue.running = false;
process.nextTick(exports.applyNext);
});
};
exports.idbError = function (callback) {
return function (event) {
var message = (event.target && event.target.error &&
event.target.error.name) || event.target;
callback(errors.error(errors.IDB_ERROR, message, event.type));
};
};
// Unfortunately, the metadata has to be stringified
// when it is put into the database, because otherwise
// IndexedDB can throw errors for deeply-nested objects.
// Originally we just used JSON.parse/JSON.stringify; now
// we use this custom vuvuzela library that avoids recursion.
// If we could do it all over again, we'd probably use a
// format for the revision trees other than JSON.
exports.encodeMetadata = function (metadata, winningRev, deleted) {
return {
data: utils.safeJsonStringify(metadata),
winningRev: winningRev,
deletedOrLocal: deleted ? '1' : '0',
seq: metadata.seq, // highest seq for this doc
id: metadata.id
};
};
exports.decodeMetadata = function (storedObject) {
if (!storedObject) {
return null;
}
var metadata = utils.safeJsonParse(storedObject.data);
metadata.winningRev = storedObject.winningRev;
metadata.deleted = storedObject.deletedOrLocal === '1';
metadata.seq = storedObject.seq;
return metadata;
};
// read the doc back out from the database. we don't store the
// _id or _rev because we already have _doc_id_rev.
exports.decodeDoc = function (doc) {
if (!doc) {
return doc;
}
var idx = utils.lastIndexOf(doc._doc_id_rev, ':');
doc._id = doc._doc_id_rev.substring(0, idx - 1);
doc._rev = doc._doc_id_rev.substring(idx + 1);
delete doc._doc_id_rev;
return doc;
};
// Read a blob from the database, encoding as necessary
// and translating from base64 if the IDB doesn't support
// native Blobs
exports.readBlobData = function (body, type, encode, callback) {
if (encode) {
if (!body) {
callback('');
} else if (typeof body !== 'string') { // we have blob support
utils.readAsBinaryString(body, function (binary) {
callback(utils.btoa(binary));
});
} else { // no blob support
callback(body);
}
} else {
if (!body) {
callback(utils.createBlob([''], {type: type}));
} else if (typeof body !== 'string') { // we have blob support
callback(body);
} else { // no blob support
body = utils.fixBinary(atob(body));
callback(utils.createBlob([body], {type: type}));
}
}
};
exports.fetchAttachmentsIfNecessary = function (doc, opts, txn, cb) {
var attachments = Object.keys(doc._attachments || {});
if (!attachments.length) {
return cb && cb();
}
var numDone = 0;
function checkDone() {
if (++numDone === attachments.length && cb) {
cb();
}
}
function fetchAttachment(doc, att) {
var attObj = doc._attachments[att];
var digest = attObj.digest;
var req = txn.objectStore(constants.ATTACH_STORE).get(digest);
req.onsuccess = function (e) {
attObj.body = e.target.result.body;
checkDone();
};
}
attachments.forEach(function (att) {
if (opts.attachments && opts.include_docs) {
fetchAttachment(doc, att);
} else {
doc._attachments[att].stub = true;
checkDone();
}
});
};
// IDB-specific postprocessing necessary because
// we don't know whether we stored a true Blob or
// a base64-encoded string, and if it's a Blob it
// needs to be read outside of the transaction context
exports.postProcessAttachments = function (results) {
return utils.Promise.all(results.map(function (row) {
if (row.doc && row.doc._attachments) {
var attNames = Object.keys(row.doc._attachments);
return utils.Promise.all(attNames.map(function (att) {
var attObj = row.doc._attachments[att];
if (!('body' in attObj)) { // already processed
return;
}
var body = attObj.body;
var type = attObj.content_type;
return new utils.Promise(function (resolve) {
exports.readBlobData(body, type, true, function (base64) {
row.doc._attachments[att] = utils.extend(
utils.pick(attObj, ['digest', 'content_type']),
{data: base64}
);
resolve();
});
});
}));
}
}));
};
exports.compactRevs = function (revs, docId, txn) {
var possiblyOrphanedDigests = [];
var seqStore = txn.objectStore(constants.BY_SEQ_STORE);
var attStore = txn.objectStore(constants.ATTACH_STORE);
var attAndSeqStore = txn.objectStore(constants.ATTACH_AND_SEQ_STORE);
var count = revs.length;
function checkDone() {
count--;
if (!count) { // done processing all revs
deleteOrphanedAttachments();
}
}
function deleteOrphanedAttachments() {
if (!possiblyOrphanedDigests.length) {
return;
}
possiblyOrphanedDigests.forEach(function (digest) {
var countReq = attAndSeqStore.index('digestSeq').count(
IDBKeyRange.bound(
digest + '::', digest + '::\uffff', false, false));
countReq.onsuccess = function (e) {
var count = e.target.result;
if (!count) {
// orphaned
attStore.delete(digest);
}
};
});
}
revs.forEach(function (rev) {
var index = seqStore.index('_doc_id_rev');
var key = docId + "::" + rev;
index.getKey(key).onsuccess = function (e) {
var seq = e.target.result;
if (typeof seq !== 'number') {
return checkDone();
}
seqStore.delete(seq);
var cursor = attAndSeqStore.index('seq')
.openCursor(IDBKeyRange.only(seq));
cursor.onsuccess = function (event) {
var cursor = event.target.result;
if (cursor) {
var digest = cursor.value.digestSeq.split('::')[0];
possiblyOrphanedDigests.push(digest);
attAndSeqStore.delete(cursor.primaryKey);
cursor.continue();
} else { // done
checkDone();
}
};
};
});
};
exports.openTransactionSafely = function (idb, stores, mode) {
try {
return {
txn: idb.transaction(stores, mode)
};
} catch (err) {
return {
error: err
};
}
};
}).call(this,require("/Users/nlawson/workspace-node/pouchdb-authentication/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js"))
},{"../../deps/errors":120,"../../utils":138,"./idb-constants":107,"/Users/nlawson/workspace-node/pouchdb-authentication/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js":46}],109:[function(require,module,exports){
(function (process){
'use strict';
var utils = require('../../utils');
var merge = require('../../merge');
var errors = require('../../deps/errors');
var idbUtils = require('./idb-utils');
var idbConstants = require('./idb-constants');
var idbBulkDocs = require('./idb-bulk-docs');
var idbAllDocs = require('./idb-all-docs');
var checkBlobSupport = require('./idb-blob-support');
var ADAPTER_VERSION = idbConstants.ADAPTER_VERSION;
var ATTACH_AND_SEQ_STORE = idbConstants.ATTACH_AND_SEQ_STORE;
var ATTACH_STORE = idbConstants.ATTACH_STORE;
var BY_SEQ_STORE = idbConstants.BY_SEQ_STORE;
var DETECT_BLOB_SUPPORT_STORE = idbConstants.DETECT_BLOB_SUPPORT_STORE;
var DOC_STORE = idbConstants.DOC_STORE;
var LOCAL_STORE = idbConstants.LOCAL_STORE;
var META_STORE = idbConstants.META_STORE;
var applyNext = idbUtils.applyNext;
var compactRevs = idbUtils.compactRevs;
var decodeDoc = idbUtils.decodeDoc;
var decodeMetadata = idbUtils.decodeMetadata;
var encodeMetadata = idbUtils.encodeMetadata;
var fetchAttachmentsIfNecessary = idbUtils.fetchAttachmentsIfNecessary;
var idbError = idbUtils.idbError;
var postProcessAttachments = idbUtils.postProcessAttachments;
var readBlobData = idbUtils.readBlobData;
var taskQueue = idbUtils.taskQueue;
var openTransactionSafely = idbUtils.openTransactionSafely;
var cachedDBs = {};
var blobSupportPromise;
function IdbPouch(opts, callback) {
var api = this;
taskQueue.queue.push({
action: function (thisCallback) {
init(api, opts, thisCallback);
},
callback: callback
});
applyNext();
}
function init(api, opts, callback) {
var dbName = opts.name;
var idb = null;
api._meta = null;
// called when creating a fresh new database
function createSchema(db) {
var docStore = db.createObjectStore(DOC_STORE, {keyPath : 'id'});
db.createObjectStore(BY_SEQ_STORE, {autoIncrement: true})
.createIndex('_doc_id_rev', '_doc_id_rev', {unique: true});
db.createObjectStore(ATTACH_STORE, {keyPath: 'digest'});
db.createObjectStore(META_STORE, {keyPath: 'id', autoIncrement: false});
db.createObjectStore(DETECT_BLOB_SUPPORT_STORE);
// added in v2
docStore.createIndex('deletedOrLocal', 'deletedOrLocal', {unique : false});
// added in v3
db.createObjectStore(LOCAL_STORE, {keyPath: '_id'});
// added in v4
var attAndSeqStore = db.createObjectStore(ATTACH_AND_SEQ_STORE,
{autoIncrement: true});
attAndSeqStore.createIndex('seq', 'seq');
attAndSeqStore.createIndex('digestSeq', 'digestSeq', {unique: true});
}
// migration to version 2
// unfortunately "deletedOrLocal" is a misnomer now that we no longer
// store local docs in the main doc-store, but whaddyagonnado
function addDeletedOrLocalIndex(txn, callback) {
var docStore = txn.objectStore(DOC_STORE);
docStore.createIndex('deletedOrLocal', 'deletedOrLocal', {unique : false});
docStore.openCursor().onsuccess = function (event) {
var cursor = event.target.result;
if (cursor) {
var metadata = cursor.value;
var deleted = utils.isDeleted(metadata);
metadata.deletedOrLocal = deleted ? "1" : "0";
docStore.put(metadata);
cursor.continue();
} else {
callback();
}
};
}
// migration to version 3 (part 1)
function createLocalStoreSchema(db) {
db.createObjectStore(LOCAL_STORE, {keyPath: '_id'})
.createIndex('_doc_id_rev', '_doc_id_rev', {unique: true});
}
// migration to version 3 (part 2)
function migrateLocalStore(txn, cb) {
var localStore = txn.objectStore(LOCAL_STORE);
var docStore = txn.objectStore(DOC_STORE);
var seqStore = txn.objectStore(BY_SEQ_STORE);
var cursor = docStore.openCursor();
cursor.onsuccess = function (event) {
var cursor = event.target.result;
if (cursor) {
var metadata = cursor.value;
var docId = metadata.id;
var local = utils.isLocalId(docId);
var rev = merge.winningRev(metadata);
if (local) {
var docIdRev = docId + "::" + rev;
// remove all seq entries
// associated with this docId
var start = docId + "::";
var end = docId + "::~";
var index = seqStore.index('_doc_id_rev');
var range = IDBKeyRange.bound(start, end, false, false);
var seqCursor = index.openCursor(range);
seqCursor.onsuccess = function (e) {
seqCursor = e.target.result;
if (!seqCursor) {
// done
docStore.delete(cursor.primaryKey);
cursor.continue();
} else {
var data = seqCursor.value;
if (data._doc_id_rev === docIdRev) {
localStore.put(data);
}
seqStore.delete(seqCursor.primaryKey);
seqCursor.continue();
}
};
} else {
cursor.continue();
}
} else if (cb) {
cb();
}
};
}
// migration to version 4 (part 1)
function addAttachAndSeqStore(db) {
var attAndSeqStore = db.createObjectStore(ATTACH_AND_SEQ_STORE,
{autoIncrement: true});
attAndSeqStore.createIndex('seq', 'seq');
attAndSeqStore.createIndex('digestSeq', 'digestSeq', {unique: true});
}
// migration to version 4 (part 2)
function migrateAttsAndSeqs(txn, callback) {
var seqStore = txn.objectStore(BY_SEQ_STORE);
var attStore = txn.objectStore(ATTACH_STORE);
var attAndSeqStore = txn.objectStore(ATTACH_AND_SEQ_STORE);
// need to actually populate the table. this is the expensive part,
// so as an optimization, check first that this database even
// contains attachments
var req = attStore.count();
req.onsuccess = function (e) {
var count = e.target.result;
if (!count) {
return callback(); // done
}
seqStore.openCursor().onsuccess = function (e) {
var cursor = e.target.result;
if (!cursor) {
return callback(); // done
}
var doc = cursor.value;
var seq = cursor.primaryKey;
var atts = Object.keys(doc._attachments || {});
var digestMap = {};
for (var j = 0; j < atts.length; j++) {
var att = doc._attachments[atts[j]];
digestMap[att.digest] = true; // uniq digests, just in case
}
var digests = Object.keys(digestMap);
for (j = 0; j < digests.length; j++) {
var digest = digests[j];
attAndSeqStore.put({
seq: seq,
digestSeq: digest + '::' + seq
});
}
cursor.continue();
};
};
}
// migration to version 5
// Instead of relying on on-the-fly migration of metadata,
// this brings the doc-store to its modern form:
// - metadata.winningrev
// - metadata.seq
// - stringify the metadata when storing it
function migrateMetadata(txn) {
function decodeMetadataCompat(storedObject) {
if (!storedObject.data) {
// old format, when we didn't store it stringified
storedObject.deleted = storedObject.deletedOrLocal === '1';
return storedObject;
}
return decodeMetadata(storedObject);
}
// ensure that every metadata has a winningRev and seq,
// which was previously created on-the-fly but better to migrate
var bySeqStore = txn.objectStore(BY_SEQ_STORE);
var docStore = txn.objectStore(DOC_STORE);
var cursor = docStore.openCursor();
cursor.onsuccess = function (e) {
var cursor = e.target.result;
if (!cursor) {
return; // done
}
var metadata = decodeMetadataCompat(cursor.value);
metadata.winningRev = metadata.winningRev || merge.winningRev(metadata);
function fetchMetadataSeq() {
// metadata.seq was added post-3.2.0, so if it's missing,
// we need to fetch it manually
var start = metadata.id + '::';
var end = metadata.id + '::\uffff';
var req = bySeqStore.index('_doc_id_rev').openCursor(
IDBKeyRange.bound(start, end));
var metadataSeq = 0;
req.onsuccess = function (e) {
var cursor = e.target.result;
if (!cursor) {
metadata.seq = metadataSeq;
return onGetMetadataSeq();
}
var seq = cursor.primaryKey;
if (seq > metadataSeq) {
metadataSeq = seq;
}
cursor.continue();
};
}
function onGetMetadataSeq() {
var metadataToStore = encodeMetadata(metadata,
metadata.winningRev, metadata.deleted);
var req = docStore.put(metadataToStore);
req.onsuccess = function () {
cursor.continue();
};
}
if (metadata.seq) {
return onGetMetadataSeq();
}
fetchMetadataSeq();
};
}
api.type = function () {
return 'idb';
};
api._id = utils.toPromise(function (callback) {
callback(null, api._meta.instanceId);
});
api._bulkDocs = function idb_bulkDocs(req, opts, callback) {
idbBulkDocs(req, opts, api, idb, IdbPouch.Changes, callback);
};
// First we look up the metadata in the ids database, then we fetch the
// current revision(s) from the by sequence store
api._get = function idb_get(id, opts, callback) {
var doc;
var metadata;
var err;
var txn;
opts = utils.clone(opts);
if (opts.ctx) {
txn = opts.ctx;
} else {
var txnResult = openTransactionSafely(idb,
[DOC_STORE, BY_SEQ_STORE, ATTACH_STORE], 'readonly');
if (txnResult.error) {
return callback(txnResult.error);
}
txn = txnResult.txn;
}
function finish() {
callback(err, {doc: doc, metadata: metadata, ctx: txn});
}
txn.objectStore(DOC_STORE).get(id).onsuccess = function (e) {
metadata = decodeMetadata(e.target.result);
// we can determine the result here if:
// 1. there is no such document
// 2. the document is deleted and we don't ask about specific rev
// When we ask with opts.rev we expect the answer to be either
// doc (possibly with _deleted=true) or missing error
if (!metadata) {
err = errors.error(errors.MISSING_DOC, 'missing');
return finish();
}
if (utils.isDeleted(metadata) && !opts.rev) {
err = errors.error(errors.MISSING_DOC, "deleted");
return finish();
}
var objectStore = txn.objectStore(BY_SEQ_STORE);
var rev = opts.rev || metadata.winningRev;
var key = metadata.id + '::' + rev;
objectStore.index('_doc_id_rev').get(key).onsuccess = function (e) {
doc = e.target.result;
if (doc) {
doc = decodeDoc(doc);
}
if (!doc) {
err = errors.error(errors.MISSING_DOC, 'missing');
return finish();
}
finish();
};
};
};
api._getAttachment = function (attachment, opts, callback) {
var txn;
opts = utils.clone(opts);
if (opts.ctx) {
txn = opts.ctx;
} else {
var txnResult = openTransactionSafely(idb,
[DOC_STORE, BY_SEQ_STORE, ATTACH_STORE], 'readonly');
if (txnResult.error) {
return callback(txnResult.error);
}
txn = txnResult.txn;
}
var digest = attachment.digest;
var type = attachment.content_type;
txn.objectStore(ATTACH_STORE).get(digest).onsuccess = function (e) {
var body = e.target.result.body;
readBlobData(body, type, opts.encode, function (blobData) {
callback(null, blobData);
});
};
};
api._info = function idb_info(callback) {
if (idb === null || !cachedDBs[dbName]) {
var error = new Error('db isn\'t open');
error.id = 'idbNull';
return callback(error);
}
var updateSeq;
var docCount;
var txnResult = openTransactionSafely(idb, [BY_SEQ_STORE], 'readonly');
if (txnResult.error) {
return callback(txnResult.error);
}
var txn = txnResult.txn;
var cursor = txn.objectStore(BY_SEQ_STORE).openCursor(null, 'prev');
cursor.onsuccess = function (event) {
var cursor = event.target.result;
updateSeq = cursor ? cursor.key : 0;
// count within the same txn for consistency
docCount = api._meta.docCount;
};
txn.oncomplete = function () {
callback(null, {
doc_count: docCount,
update_seq: updateSeq,
// for debugging
idb_attachment_format: (api._meta.blobSupport ? 'binary' : 'base64')
});
};
};
api._allDocs = function idb_allDocs(opts, callback) {
idbAllDocs(opts, api, idb, callback);
};
api._changes = function (opts) {
opts = utils.clone(opts);
if (opts.continuous) {
var id = dbName + ':' + utils.uuid();
IdbPouch.Changes.addListener(dbName, id, api, opts);
IdbPouch.Changes.notify(dbName);
return {
cancel: function () {
IdbPouch.Changes.removeListener(dbName, id);
}
};
}
var docIds = opts.doc_ids && new utils.Set(opts.doc_ids);
var descending = opts.descending ? 'prev' : null;
opts.since = opts.since || 0;
var lastSeq = opts.since;
var limit = 'limit' in opts ? opts.limit : -1;
if (limit === 0) {
limit = 1; // per CouchDB _changes spec
}
var returnDocs;
if ('returnDocs' in opts) {
returnDocs = opts.returnDocs;
} else {
returnDocs = true;
}
var results = [];
var numResults = 0;
var filter = utils.filterChange(opts);
var docIdsToMetadata = new utils.Map();
var txn;
var bySeqStore;
var docStore;
function onGetCursor(cursor) {
var doc = decodeDoc(cursor.value);
var seq = cursor.key;
if (docIds && !docIds.has(doc._id)) {
return cursor.continue();
}
var metadata;
function onGetMetadata() {
if (metadata.seq !== seq) {
// some other seq is later
return cursor.continue();
}
lastSeq = seq;
if (metadata.winningRev === doc._rev) {
return onGetWinningDoc(doc);
}
fetchWinningDoc();
}
function fetchWinningDoc() {
var docIdRev = doc._id + '::' + metadata.winningRev;
var req = bySeqStore.index('_doc_id_rev').openCursor(
IDBKeyRange.bound(docIdRev, docIdRev + '\uffff'));
req.onsuccess = function (e) {
onGetWinningDoc(decodeDoc(e.target.result.value));
};
}
function onGetWinningDoc(winningDoc) {
var change = opts.processChange(winningDoc, metadata, opts);
change.seq = metadata.seq;
if (filter(change)) {
numResults++;
if (returnDocs) {
results.push(change);
}
// process the attachment immediately
// for the benefit of live listeners
if (opts.attachments && opts.include_docs) {
fetchAttachmentsIfNecessary(winningDoc, opts, txn, function () {
postProcessAttachments([change]).then(function () {
opts.onChange(change);
});
});
} else {
opts.onChange(change);
}
}
if (numResults !== limit) {
cursor.continue();
}
}
metadata = docIdsToMetadata.get(doc._id);
if (metadata) { // cached
return onGetMetadata();
}
// metadata not cached, have to go fetch it
docStore.get(doc._id).onsuccess = function (event) {
metadata = decodeMetadata(event.target.result);
docIdsToMetadata.set(doc._id, metadata);
onGetMetadata();
};
}
function onsuccess(event) {
var cursor = event.target.result;
if (!cursor) {
return;
}
onGetCursor(cursor);
}
function fetchChanges() {
var objectStores = [DOC_STORE, BY_SEQ_STORE];
if (opts.attachments) {
objectStores.push(ATTACH_STORE);
}
var txnResult = openTransactionSafely(idb, objectStores, 'readonly');
if (txnResult.error) {
return opts.complete(txnResult.error);
}
txn = txnResult.txn;
txn.onerror = idbError(opts.complete);
txn.oncomplete = onTxnComplete;
bySeqStore = txn.objectStore(BY_SEQ_STORE);
docStore = txn.objectStore(DOC_STORE);
var req;
if (descending) {
req = bySeqStore.openCursor(
null, descending);
} else {
req = bySeqStore.openCursor(
IDBKeyRange.lowerBound(opts.since, true));
}
req.onsuccess = onsuccess;
}
fetchChanges();
function onTxnComplete() {
function finish() {
opts.complete(null, {
results: results,
last_seq: lastSeq
});
}
if (!opts.continuous && opts.attachments) {
// cannot guarantee that postProcessing was already done,
// so do it again
postProcessAttachments(results).then(finish);
} else {
finish();
}
}
};
api._close = function (callback) {
if (idb === null) {
return callback(errors.error(errors.NOT_OPEN));
}
// https://developer.mozilla.org/en-US/docs/IndexedDB/IDBDatabase#close
// "Returns immediately and closes the connection in a separate thread..."
idb.close();
delete cachedDBs[dbName];
idb = null;
callback();
};
api._getRevisionTree = function (docId, callback) {
var txnResult = openTransactionSafely(idb, [DOC_STORE], 'readonly');
if (txnResult.error) {
return callback(txnResult.error);
}
var txn = txnResult.txn;
var req = txn.objectStore(DOC_STORE).get(docId);
req.onsuccess = function (event) {
var doc = decodeMetadata(event.target.result);
if (!doc) {
callback(errors.error(errors.MISSING_DOC));
} else {
callback(null, doc.rev_tree);
}
};
};
// This function removes revisions of document docId
// which are listed in revs and sets this document
// revision to to rev_tree
api._doCompaction = function (docId, revs, callback) {
var stores = [
DOC_STORE,
BY_SEQ_STORE,
ATTACH_STORE,
ATTACH_AND_SEQ_STORE
];
var txnResult = openTransactionSafely(idb, stores, 'readwrite');
if (txnResult.error) {
return callback(txnResult.error);
}
var txn = txnResult.txn;
var docStore = txn.objectStore(DOC_STORE);
docStore.get(docId).onsuccess = function (event) {
var metadata = decodeMetadata(event.target.result);
merge.traverseRevTree(metadata.rev_tree, function (isLeaf, pos,
revHash, ctx, opts) {
var rev = pos + '-' + revHash;
if (revs.indexOf(rev) !== -1) {
opts.status = 'missing';
}
});
compactRevs(revs, docId, txn);
var winningRev = metadata.winningRev;
var deleted = metadata.deleted;
txn.objectStore(DOC_STORE).put(
encodeMetadata(metadata, winningRev, deleted));
};
txn.onerror = idbError(callback);
txn.oncomplete = function () {
utils.call(callback);
};
};
api._getLocal = function (id, callback) {
var txnResult = openTransactionSafely(idb, [LOCAL_STORE], 'readonly');
if (txnResult.error) {
return callback(txnResult.error);
}
var tx = txnResult.txn;
var req = tx.objectStore(LOCAL_STORE).get(id);
req.onerror = idbError(callback);
req.onsuccess = function (e) {
var doc = e.target.result;
if (!doc) {
callback(errors.error(errors.MISSING_DOC));
} else {
delete doc['_doc_id_rev']; // for backwards compat
callback(null, doc);
}
};
};
api._putLocal = function (doc, opts, callback) {
if (typeof opts === 'function') {
callback = opts;
opts = {};
}
delete doc._revisions; // ignore this, trust the rev
var oldRev = doc._rev;
var id = doc._id;
if (!oldRev) {
doc._rev = '0-1';
} else {
doc._rev = '0-' + (parseInt(oldRev.split('-')[1], 10) + 1);
}
var tx = opts.ctx;
var ret;
if (!tx) {
var txnResult = openTransactionSafely(idb, [LOCAL_STORE], 'readwrite');
if (txnResult.error) {
return callback(txnResult.error);
}
tx = txnResult.txn;
tx.onerror = idbError(callback);
tx.oncomplete = function () {
if (ret) {
callback(null, ret);
}
};
}
var oStore = tx.objectStore(LOCAL_STORE);
var req;
if (oldRev) {
req = oStore.get(id);
req.onsuccess = function (e) {
var oldDoc = e.target.result;
if (!oldDoc || oldDoc._rev !== oldRev) {
callback(errors.error(errors.REV_CONFLICT));
} else { // update
var req = oStore.put(doc);
req.onsuccess = function () {
ret = {ok: true, id: doc._id, rev: doc._rev};
if (opts.ctx) { // return immediately
callback(null, ret);
}
};
}
};
} else { // new doc
req = oStore.add(doc);
req.onerror = function (e) {
// constraint error, already exists
callback(errors.error(errors.REV_CONFLICT));
e.preventDefault(); // avoid transaction abort
e.stopPropagation(); // avoid transaction onerror
};
req.onsuccess = function () {
ret = {ok: true, id: doc._id, rev: doc._rev};
if (opts.ctx) { // return immediately
callback(null, ret);
}
};
}
};
api._removeLocal = function (doc, callback) {
var txnResult = openTransactionSafely(idb, [LOCAL_STORE], 'readwrite');
if (txnResult.error) {
return callback(txnResult.error);
}
var tx = txnResult.txn;
var ret;
tx.oncomplete = function () {
if (ret) {
callback(null, ret);
}
};
var id = doc._id;
var oStore = tx.objectStore(LOCAL_STORE);
var req = oStore.get(id);
req.onerror = idbError(callback);
req.onsuccess = function (e) {
var oldDoc = e.target.result;
if (!oldDoc || oldDoc._rev !== doc._rev) {
callback(errors.error(errors.MISSING_DOC));
} else {
oStore.delete(id);
ret = {ok: true, id: id, rev: '0-0'};
}
};
};
api._destroy = function (callback) {
IdbPouch.Changes.removeAllListeners(dbName);
//Close open request for "dbName" database to fix ie delay.
if (IdbPouch.openReqList[dbName] && IdbPouch.openReqList[dbName].result) {
IdbPouch.openReqList[dbName].result.close();
delete cachedDBs[dbName];
}
var req = indexedDB.deleteDatabase(dbName);
req.onsuccess = function () {
//Remove open request from the list.
if (IdbPouch.openReqList[dbName]) {
IdbPouch.openReqList[dbName] = null;
}
if (utils.hasLocalStorage() && (dbName in localStorage)) {
delete localStorage[dbName];
}
callback(null, { 'ok': true });
};
req.onerror = idbError(callback);
};
var cached = cachedDBs[dbName];
if (cached) {
idb = cached.idb;
api._meta = cached.global;
process.nextTick(function () {
callback(null, api);
});
return;
}
var req = indexedDB.open(dbName, ADAPTER_VERSION);
if (!('openReqList' in IdbPouch)) {
IdbPouch.openReqList = {};
}
IdbPouch.openReqList[dbName] = req;
req.onupgradeneeded = function (e) {
var db = e.target.result;
if (e.oldVersion < 1) {
return createSchema(db); // new db, initial schema
}
// do migrations
var txn = e.currentTarget.transaction;
// these migrations have to be done in this function, before
// control is returned to the event loop, because IndexedDB
if (e.oldVersion < 3) {
createLocalStoreSchema(db); // v2 -> v3
}
if (e.oldVersion < 4) {
addAttachAndSeqStore(db); // v3 -> v4
}
var migrations = [
addDeletedOrLocalIndex, // v1 -> v2
migrateLocalStore, // v2 -> v3
migrateAttsAndSeqs, // v3 -> v4
migrateMetadata // v4 -> v5
];
var i = e.oldVersion;
function next() {
var migration = migrations[i - 1];
i++;
if (migration) {
migration(txn, next);
}
}
next();
};
req.onsuccess = function (e) {
idb = e.target.result;
idb.onversionchange = function () {
idb.close();
delete cachedDBs[dbName];
};
idb.onabort = function () {
idb.close();
delete cachedDBs[dbName];
};
var txn = idb.transaction([
META_STORE,
DETECT_BLOB_SUPPORT_STORE,
DOC_STORE
], 'readwrite');
var req = txn.objectStore(META_STORE).get(META_STORE);
var blobSupport = null;
var docCount = null;
var instanceId = null;
req.onsuccess = function (e) {
var checkSetupComplete = function () {
if (blobSupport === null || docCount === null ||
instanceId === null) {
return;
} else {
api._meta = {
name: dbName,
instanceId: instanceId,
blobSupport: blobSupport,
docCount: docCount
};
cachedDBs[dbName] = {
idb: idb,
global: api._meta
};
callback(null, api);
}
};
//
// fetch/store the id
//
var meta = e.target.result || {id: META_STORE};
if (dbName + '_id' in meta) {
instanceId = meta[dbName + '_id'];
checkSetupComplete();
} else {
instanceId = utils.uuid();
meta[dbName + '_id'] = instanceId;
txn.objectStore(META_STORE).put(meta).onsuccess = function () {
checkSetupComplete();
};
}
//
// check blob support
//
if (!blobSupportPromise) {
// make sure blob support is only checked once
blobSupportPromise = checkBlobSupport(txn, idb);
}
blobSupportPromise.then(function (val) {
blobSupport = val;
checkSetupComplete();
});
//
// count docs
//
var index = txn.objectStore(DOC_STORE).index('deletedOrLocal');
index.count(IDBKeyRange.only('0')).onsuccess = function (e) {
docCount = e.target.result;
checkSetupComplete();
};
};
};
req.onerror = idbError(callback);
}
IdbPouch.valid = function () {
// Issue #2533, we finally gave up on doing bug
// detection instead of browser sniffing. Safari brought us
// to our knees.
var isSafari = typeof openDatabase !== 'undefined' &&
/(Safari|iPhone|iPad|iPod)/.test(navigator.userAgent) &&
!/Chrome/.test(navigator.userAgent) &&
!/BlackBerry/.test(navigator.platform);
// some outdated implementations of IDB that appear on Samsung
// and HTC Android devices <4.4 are missing IDBKeyRange
return !isSafari && typeof indexedDB !== 'undefined' &&
typeof IDBKeyRange !== 'undefined';
};
IdbPouch.Changes = new utils.Changes();
module.exports = IdbPouch;
}).call(this,require("/Users/nlawson/workspace-node/pouchdb-authentication/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js"))
},{"../../deps/errors":120,"../../merge":133,"../../utils":138,"./idb-all-docs":104,"./idb-blob-support":105,"./idb-bulk-docs":106,"./idb-constants":107,"./idb-utils":108,"/Users/nlawson/workspace-node/pouchdb-authentication/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js":46}],110:[function(require,module,exports){
'use strict';
var utils = require('../../utils');
var errors = require('../../deps/errors');
var websqlUtils = require('./websql-utils');
var websqlConstants = require('./websql-constants');
var DOC_STORE = websqlConstants.DOC_STORE;
var BY_SEQ_STORE = websqlConstants.BY_SEQ_STORE;
var ATTACH_STORE = websqlConstants.ATTACH_STORE;
var ATTACH_AND_SEQ_STORE = websqlConstants.ATTACH_AND_SEQ_STORE;
var select = websqlUtils.select;
var stringifyDoc = websqlUtils.stringifyDoc;
var compactRevs = websqlUtils.compactRevs;
var unknownError = websqlUtils.unknownError;
function websqlBulkDocs(req, opts, api, db, Changes, callback) {
var newEdits = opts.new_edits;
var userDocs = req.docs;
// Parse the docs, give them a sequence number for the result
var docInfos = userDocs.map(function (doc) {
if (doc._id && utils.isLocalId(doc._id)) {
return doc;
}
var newDoc = utils.parseDoc(doc, newEdits);
return newDoc;
});
var docInfoErrors = docInfos.filter(function (docInfo) {
return docInfo.error;
});
if (docInfoErrors.length) {
return callback(docInfoErrors[0]);
}
var tx;
var results = new Array(docInfos.length);
var fetchedDocs = new utils.Map();
var preconditionErrored;
function complete() {
if (preconditionErrored) {
return callback(preconditionErrored);
}
Changes.notify(api._name);
api._docCount = -1; // invalidate
callback(null, results);
}
function verifyAttachment(digest, callback) {
var sql = 'SELECT count(*) as cnt FROM ' + ATTACH_STORE +
' WHERE digest=?';
tx.executeSql(sql, [digest], function (tx, result) {
if (result.rows.item(0).cnt === 0) {
var err = errors.error(errors.MISSING_STUB,
'unknown stub attachment with digest ' +
digest);
callback(err);
} else {
callback();
}
});
}
function verifyAttachments(finish) {
var digests = [];
docInfos.forEach(function (docInfo) {
if (docInfo.data && docInfo.data._attachments) {
Object.keys(docInfo.data._attachments).forEach(function (filename) {
var att = docInfo.data._attachments[filename];
if (att.stub) {
digests.push(att.digest);
}
});
}
});
if (!digests.length) {
return finish();
}
var numDone = 0;
var err;
function checkDone() {
if (++numDone === digests.length) {
finish(err);
}
}
digests.forEach(function (digest) {
verifyAttachment(digest, function (attErr) {
if (attErr && !err) {
err = attErr;
}
checkDone();
});
});
}
function writeDoc(docInfo, winningRev, winningRevIsDeleted, newRevIsDeleted,
isUpdate, delta, resultsIdx, callback) {
function finish() {
var data = docInfo.data;
var deletedInt = newRevIsDeleted ? 1 : 0;
var id = data._id;
var rev = data._rev;
var json = stringifyDoc(data);
var sql = 'INSERT INTO ' + BY_SEQ_STORE +
' (doc_id, rev, json, deleted) VALUES (?, ?, ?, ?);';
var sqlArgs = [id, rev, json, deletedInt];
// map seqs to attachment digests, which
// we will need later during compaction
function insertAttachmentMappings(seq, callback) {
var attsAdded = 0;
var attsToAdd = Object.keys(data._attachments || {});
if (!attsToAdd.length) {
return callback();
}
function checkDone() {
if (++attsAdded === attsToAdd.length) {
callback();
}
return false; // ack handling a constraint error
}
function add(att) {
var sql = 'INSERT INTO ' + ATTACH_AND_SEQ_STORE +
' (digest, seq) VALUES (?,?)';
var sqlArgs = [data._attachments[att].digest, seq];
tx.executeSql(sql, sqlArgs, checkDone, checkDone);
// second callback is for a constaint error, which we ignore
// because this docid/rev has already been associated with
// the digest (e.g. when new_edits == false)
}
for (var i = 0; i < attsToAdd.length; i++) {
add(attsToAdd[i]); // do in parallel
}
}
tx.executeSql(sql, sqlArgs, function (tx, result) {
var seq = result.insertId;
insertAttachmentMappings(seq, function () {
dataWritten(tx, seq);
});
}, function () {
// constraint error, recover by updating instead (see #1638)
var fetchSql = select('seq', BY_SEQ_STORE, null,
'doc_id=? AND rev=?');
tx.executeSql(fetchSql, [id, rev], function (tx, res) {
var seq = res.rows.item(0).seq;
var sql = 'UPDATE ' + BY_SEQ_STORE +
' SET json=?, deleted=? WHERE doc_id=? AND rev=?;';
var sqlArgs = [json, deletedInt, id, rev];
tx.executeSql(sql, sqlArgs, function (tx) {
insertAttachmentMappings(seq, function () {
dataWritten(tx, seq);
});
});
});
return false; // ack that we've handled the error
});
}
function collectResults(attachmentErr) {
if (!err) {
if (attachmentErr) {
err = attachmentErr;
callback(err);
} else if (recv === attachments.length) {
finish();
}
}
}
var err = null;
var recv = 0;
docInfo.data._id = docInfo.metadata.id;
docInfo.data._rev = docInfo.metadata.rev;
var attachments = Object.keys(docInfo.data._attachments || {});
if (newRevIsDeleted) {
docInfo.data._deleted = true;
}
function attachmentSaved(err) {
recv++;
collectResults(err);
}
attachments.forEach(function (key) {
var att = docInfo.data._attachments[key];
if (!att.stub) {
var data = att.data;
delete att.data;
var digest = att.digest;
saveAttachment(digest, data, attachmentSaved);
} else {
recv++;
collectResults();
}
});
if (!attachments.length) {
finish();
}
function autoCompact() {
if (!isUpdate || !api.auto_compaction) {
return; // nothing to do
}
var id = docInfo.metadata.id;
var revsToDelete = utils.compactTree(docInfo.metadata);
compactRevs(revsToDelete, id, tx);
}
function dataWritten(tx, seq) {
autoCompact();
docInfo.metadata.seq = seq;
delete docInfo.metadata.rev;
var sql = isUpdate ?
'UPDATE ' + DOC_STORE +
' SET json=?, max_seq=?, winningseq=' +
'(SELECT seq FROM ' + BY_SEQ_STORE +
' WHERE doc_id=' + DOC_STORE + '.id AND rev=?) WHERE id=?'
: 'INSERT INTO ' + DOC_STORE +
' (id, winningseq, max_seq, json) VALUES (?,?,?,?);';
var metadataStr = utils.safeJsonStringify(docInfo.metadata);
var id = docInfo.metadata.id;
var params = isUpdate ?
[metadataStr, seq, winningRev, id] :
[id, seq, seq, metadataStr];
tx.executeSql(sql, params, function () {
results[resultsIdx] = {
ok: true,
id: docInfo.metadata.id,
rev: winningRev
};
fetchedDocs.set(id, docInfo.metadata);
callback();
});
}
}
function processDocs() {
utils.processDocs(docInfos, api, fetchedDocs,
tx, results, writeDoc, opts);
}
function fetchExistingDocs(callback) {
if (!docInfos.length) {
return callback();
}
var numFetched = 0;
function checkDone() {
if (++numFetched === docInfos.length) {
callback();
}
}
docInfos.forEach(function (docInfo) {
if (docInfo._id && utils.isLocalId(docInfo._id)) {
return checkDone(); // skip local docs
}
var id = docInfo.metadata.id;
tx.executeSql('SELECT json FROM ' + DOC_STORE +
' WHERE id = ?', [id], function (tx, result) {
if (result.rows.length) {
var metadata = utils.safeJsonParse(result.rows.item(0).json);
fetchedDocs.set(id, metadata);
}
checkDone();
});
});
}
function saveAttachment(digest, data, callback) {
var sql = 'SELECT digest FROM ' + ATTACH_STORE + ' WHERE digest=?';
tx.executeSql(sql, [digest], function (tx, result) {
if (result.rows.length) { // attachment already exists
return callback();
}
// we could just insert before selecting and catch the error,
// but my hunch is that it's cheaper not to serialize the blob
// from JS to C if we don't have to (TODO: confirm this)
sql = 'INSERT INTO ' + ATTACH_STORE +
' (digest, body, escaped) VALUES (?,?,1)';
tx.executeSql(sql, [digest, websqlUtils.escapeBlob(data)], function () {
callback();
}, function () {
// ignore constaint errors, means it already exists
callback();
return false; // ack we handled the error
});
});
}
utils.preprocessAttachments(docInfos, 'binary', function (err) {
if (err) {
return callback(err);
}
db.transaction(function (txn) {
tx = txn;
verifyAttachments(function (err) {
if (err) {
preconditionErrored = err;
} else {
fetchExistingDocs(processDocs);
}
});
}, unknownError(callback), complete);
});
}
module.exports = websqlBulkDocs;
},{"../../deps/errors":120,"../../utils":138,"./websql-constants":111,"./websql-utils":112}],111:[function(require,module,exports){
'use strict';
function quote(str) {
return "'" + str + "'";
}
exports.ADAPTER_VERSION = 7; // used to manage migrations
// The object stores created for each database
// DOC_STORE stores the document meta data, its revision history and state
exports.DOC_STORE = quote('document-store');
// BY_SEQ_STORE stores a particular version of a document, keyed by its
// sequence id
exports.BY_SEQ_STORE = quote('by-sequence');
// Where we store attachments
exports.ATTACH_STORE = quote('attach-store');
exports.LOCAL_STORE = quote('local-store');
exports.META_STORE = quote('metadata-store');
// where we store many-to-many relations between attachment
// digests and seqs
exports.ATTACH_AND_SEQ_STORE = quote('attach-seq-store');
},{}],112:[function(require,module,exports){
'use strict';
var utils = require('../../utils');
var errors = require('../../deps/errors');
var websqlConstants = require('./websql-constants');
var BY_SEQ_STORE = websqlConstants.BY_SEQ_STORE;
var ATTACH_STORE = websqlConstants.ATTACH_STORE;
var ATTACH_AND_SEQ_STORE = websqlConstants.ATTACH_AND_SEQ_STORE;
// escapeBlob and unescapeBlob are workarounds for a websql bug:
// https://code.google.com/p/chromium/issues/detail?id=422690
// https://bugs.webkit.org/show_bug.cgi?id=137637
// The goal is to never actually insert the \u0000 character
// in the database.
function escapeBlob(str) {
return str
.replace(/\u0002/g, '\u0002\u0002')
.replace(/\u0001/g, '\u0001\u0002')
.replace(/\u0000/g, '\u0001\u0001');
}
function unescapeBlob(str) {
return str
.replace(/\u0001\u0001/g, '\u0000')
.replace(/\u0001\u0002/g, '\u0001')
.replace(/\u0002\u0002/g, '\u0002');
}
function stringifyDoc(doc) {
// don't bother storing the id/rev. it uses lots of space,
// in persistent map/reduce especially
delete doc._id;
delete doc._rev;
return JSON.stringify(doc);
}
function unstringifyDoc(doc, id, rev) {
doc = JSON.parse(doc);
doc._id = id;
doc._rev = rev;
return doc;
}
// question mark groups IN queries, e.g. 3 -> '(?,?,?)'
function qMarks(num) {
var s = '(';
while (num--) {
s += '?';
if (num) {
s += ',';
}
}
return s + ')';
}
function select(selector, table, joiner, where, orderBy) {
return 'SELECT ' + selector + ' FROM ' +
(typeof table === 'string' ? table : table.join(' JOIN ')) +
(joiner ? (' ON ' + joiner) : '') +
(where ? (' WHERE ' +
(typeof where === 'string' ? where : where.join(' AND '))) : '') +
(orderBy ? (' ORDER BY ' + orderBy) : '');
}
function compactRevs(revs, docId, tx) {
if (!revs.length) {
return;
}
var numDone = 0;
var seqs = [];
function checkDone() {
if (++numDone === revs.length) { // done
deleteOrphans();
}
}
function deleteOrphans() {
// find orphaned attachment digests
if (!seqs.length) {
return;
}
var sql = 'SELECT DISTINCT digest AS digest FROM ' +
ATTACH_AND_SEQ_STORE + ' WHERE seq IN ' + qMarks(seqs.length);
tx.executeSql(sql, seqs, function (tx, res) {
var digestsToCheck = [];
for (var i = 0; i < res.rows.length; i++) {
digestsToCheck.push(res.rows.item(i).digest);
}
if (!digestsToCheck.length) {
return;
}
var sql = 'DELETE FROM ' + ATTACH_AND_SEQ_STORE +
' WHERE seq IN (' +
seqs.map(function () { return '?'; }).join(',') +
')';
tx.executeSql(sql, seqs, function (tx) {
var sql = 'SELECT digest FROM ' + ATTACH_AND_SEQ_STORE +
' WHERE digest IN (' +
digestsToCheck.map(function () { return '?'; }).join(',') +
')';
tx.executeSql(sql, digestsToCheck, function (tx, res) {
var nonOrphanedDigests = new utils.Set();
for (var i = 0; i < res.rows.length; i++) {
nonOrphanedDigests.add(res.rows.item(i).digest);
}
digestsToCheck.forEach(function (digest) {
if (nonOrphanedDigests.has(digest)) {
return;
}
tx.executeSql(
'DELETE FROM ' + ATTACH_AND_SEQ_STORE + ' WHERE digest=?',
[digest]);
tx.executeSql(
'DELETE FROM ' + ATTACH_STORE + ' WHERE digest=?', [digest]);
});
});
});
});
}
// update by-seq and attach stores in parallel
revs.forEach(function (rev) {
var sql = 'SELECT seq FROM ' + BY_SEQ_STORE +
' WHERE doc_id=? AND rev=?';
tx.executeSql(sql, [docId, rev], function (tx, res) {
if (!res.rows.length) { // already deleted
return checkDone();
}
var seq = res.rows.item(0).seq;
seqs.push(seq);
tx.executeSql(
'DELETE FROM ' + BY_SEQ_STORE + ' WHERE seq=?', [seq], checkDone);
});
});
}
function unknownError(callback) {
return function (event) {
// event may actually be a SQLError object, so report is as such
var errorNameMatch = event && event.constructor.toString()
.match(/function ([^\(]+)/);
var errorName = (errorNameMatch && errorNameMatch[1]) || event.type;
var errorReason = event.target || event.message;
callback(errors.error(errors.WSQ_ERROR, errorReason, errorName));
};
}
function getSize(opts) {
if ('size' in opts) {
// triggers immediate popup in iOS, fixes #2347
// e.g. 5000001 asks for 5 MB, 10000001 asks for 10 MB,
return opts.size * 1000000;
}
// In iOS, doesn't matter as long as it's <= 5000000.
// Except that if you request too much, our tests fail
// because of the native "do you accept?" popup.
// In Android <=4.3, this value is actually used as an
// honest-to-god ceiling for data, so we need to
// set it to a decently high number.
var isAndroid = /Android/.test(window.navigator.userAgent);
return isAndroid ? 5000000 : 1; // in PhantomJS, if you use 0 it will crash
}
function createOpenDBFunction() {
if (typeof sqlitePlugin !== 'undefined') {
// The SQLite Plugin started deviating pretty heavily from the
// standard openDatabase() function, as they started adding more features.
// It's better to just use their "new" format and pass in a big ol'
// options object.
return sqlitePlugin.openDatabase.bind(sqlitePlugin);
}
if (typeof openDatabase !== 'undefined') {
return function openDB(opts) {
// Traditional WebSQL API
return openDatabase(opts.name, opts.version, opts.description, opts.size);
};
}
}
var cachedDatabases = {};
function openDB(opts) {
var openDBFunction = createOpenDBFunction();
var db = cachedDatabases[opts.name];
if (!db) {
db = cachedDatabases[opts.name] = openDBFunction(opts);
db._sqlitePlugin = typeof sqlitePlugin !== 'undefined';
}
return db;
}
function valid() {
// SQLitePlugin leaks this global object, which we can use
// to detect if it's installed or not. The benefit is that it's
// declared immediately, before the 'deviceready' event has fired.
return typeof openDatabase !== 'undefined' ||
typeof SQLitePlugin !== 'undefined';
}
module.exports = {
escapeBlob: escapeBlob,
unescapeBlob: unescapeBlob,
stringifyDoc: stringifyDoc,
unstringifyDoc: unstringifyDoc,
qMarks: qMarks,
select: select,
compactRevs: compactRevs,
unknownError: unknownError,
getSize: getSize,
openDB: openDB,
valid: valid
};
},{"../../deps/errors":120,"../../utils":138,"./websql-constants":111}],113:[function(require,module,exports){
'use strict';
var utils = require('../../utils');
var merge = require('../../merge');
var errors = require('../../deps/errors');
var parseHexString = require('../../deps/parse-hex');
var websqlConstants = require('./websql-constants');
var websqlUtils = require('./websql-utils');
var websqlBulkDocs = require('./websql-bulk-docs');
var ADAPTER_VERSION = websqlConstants.ADAPTER_VERSION;
var DOC_STORE = websqlConstants.DOC_STORE;
var BY_SEQ_STORE = websqlConstants.BY_SEQ_STORE;
var ATTACH_STORE = websqlConstants.ATTACH_STORE;
var LOCAL_STORE = websqlConstants.LOCAL_STORE;
var META_STORE = websqlConstants.META_STORE;
var ATTACH_AND_SEQ_STORE = websqlConstants.ATTACH_AND_SEQ_STORE;
var qMarks = websqlUtils.qMarks;
var stringifyDoc = websqlUtils.stringifyDoc;
var unstringifyDoc = websqlUtils.unstringifyDoc;
var select = websqlUtils.select;
var compactRevs = websqlUtils.compactRevs;
var unknownError = websqlUtils.unknownError;
var getSize = websqlUtils.getSize;
var openDB = websqlUtils.openDB;
function fetchAttachmentsIfNecessary(doc, opts, api, txn, cb) {
var attachments = Object.keys(doc._attachments || {});
if (!attachments.length) {
return cb && cb();
}
var numDone = 0;
function checkDone() {
if (++numDone === attachments.length && cb) {
cb();
}
}
function fetchAttachment(doc, att) {
var attObj = doc._attachments[att];
var attOpts = {encode: true, ctx: txn};
api._getAttachment(attObj, attOpts, function (_, base64) {
doc._attachments[att] = utils.extend(
utils.pick(attObj, ['digest', 'content_type']),
{ data: base64 }
);
checkDone();
});
}
attachments.forEach(function (att) {
if (opts.attachments && opts.include_docs) {
fetchAttachment(doc, att);
} else {
doc._attachments[att].stub = true;
checkDone();
}
});
}
var POUCH_VERSION = 1;
// these indexes cover the ground for most allDocs queries
var BY_SEQ_STORE_DELETED_INDEX_SQL =
'CREATE INDEX IF NOT EXISTS \'by-seq-deleted-idx\' ON ' +
BY_SEQ_STORE + ' (seq, deleted)';
var BY_SEQ_STORE_DOC_ID_REV_INDEX_SQL =
'CREATE UNIQUE INDEX IF NOT EXISTS \'by-seq-doc-id-rev\' ON ' +
BY_SEQ_STORE + ' (doc_id, rev)';
var DOC_STORE_WINNINGSEQ_INDEX_SQL =
'CREATE INDEX IF NOT EXISTS \'doc-winningseq-idx\' ON ' +
DOC_STORE + ' (winningseq)';
var ATTACH_AND_SEQ_STORE_SEQ_INDEX_SQL =
'CREATE INDEX IF NOT EXISTS \'attach-seq-seq-idx\' ON ' +
ATTACH_AND_SEQ_STORE + ' (seq)';
var ATTACH_AND_SEQ_STORE_ATTACH_INDEX_SQL =
'CREATE UNIQUE INDEX IF NOT EXISTS \'attach-seq-digest-idx\' ON ' +
ATTACH_AND_SEQ_STORE + ' (digest, seq)';
var DOC_STORE_AND_BY_SEQ_JOINER = BY_SEQ_STORE +
'.seq = ' + DOC_STORE + '.winningseq';
var SELECT_DOCS = BY_SEQ_STORE + '.seq AS seq, ' +
BY_SEQ_STORE + '.deleted AS deleted, ' +
BY_SEQ_STORE + '.json AS data, ' +
BY_SEQ_STORE + '.rev AS rev, ' +
DOC_STORE + '.json AS metadata';
function WebSqlPouch(opts, callback) {
var api = this;
var instanceId = null;
var size = getSize(opts);
var idRequests = [];
var encoding;
api._docCount = -1; // cache sqlite count(*) for performance
api._name = opts.name;
var db = openDB({
name: api._name,
version: POUCH_VERSION,
description: api._name,
size: size,
location: opts.location,
createFromLocation: opts.createFromLocation
});
if (!db) {
return callback(errors.error(errors.UNKNOWN_ERROR));
} else if (typeof db.readTransaction !== 'function') {
// doesn't exist in sqlite plugin
db.readTransaction = db.transaction;
}
function dbCreated() {
// note the db name in case the browser upgrades to idb
if (utils.hasLocalStorage()) {
window.localStorage['_pouch__websqldb_' + api._name] = true;
}
callback(null, api);
}
// In this migration, we added the 'deleted' and 'local' columns to the
// by-seq and doc store tables.
// To preserve existing user data, we re-process all the existing JSON
// and add these values.
// Called migration2 because it corresponds to adapter version (db_version) #2
function runMigration2(tx, callback) {
// index used for the join in the allDocs query
tx.executeSql(DOC_STORE_WINNINGSEQ_INDEX_SQL);
tx.executeSql('ALTER TABLE ' + BY_SEQ_STORE +
' ADD COLUMN deleted TINYINT(1) DEFAULT 0', [], function () {
tx.executeSql(BY_SEQ_STORE_DELETED_INDEX_SQL);
tx.executeSql('ALTER TABLE ' + DOC_STORE +
' ADD COLUMN local TINYINT(1) DEFAULT 0', [], function () {
tx.executeSql('CREATE INDEX IF NOT EXISTS \'doc-store-local-idx\' ON ' +
DOC_STORE + ' (local, id)');
var sql = 'SELECT ' + DOC_STORE + '.winningseq AS seq, ' + DOC_STORE +
'.json AS metadata FROM ' + BY_SEQ_STORE + ' JOIN ' + DOC_STORE +
' ON ' + BY_SEQ_STORE + '.seq = ' + DOC_STORE + '.winningseq';
tx.executeSql(sql, [], function (tx, result) {
var deleted = [];
var local = [];
for (var i = 0; i < result.rows.length; i++) {
var item = result.rows.item(i);
var seq = item.seq;
var metadata = JSON.parse(item.metadata);
if (utils.isDeleted(metadata)) {
deleted.push(seq);
}
if (utils.isLocalId(metadata.id)) {
local.push(metadata.id);
}
}
tx.executeSql('UPDATE ' + DOC_STORE + 'SET local = 1 WHERE id IN ' +
qMarks(local.length), local, function () {
tx.executeSql('UPDATE ' + BY_SEQ_STORE +
' SET deleted = 1 WHERE seq IN ' +
qMarks(deleted.length), deleted, callback);
});
});
});
});
}
// in this migration, we make all the local docs unversioned
function runMigration3(tx, callback) {
var local = 'CREATE TABLE IF NOT EXISTS ' + LOCAL_STORE +
' (id UNIQUE, rev, json)';
tx.executeSql(local, [], function () {
var sql = 'SELECT ' + DOC_STORE + '.id AS id, ' +
BY_SEQ_STORE + '.json AS data ' +
'FROM ' + BY_SEQ_STORE + ' JOIN ' +
DOC_STORE + ' ON ' + BY_SEQ_STORE + '.seq = ' +
DOC_STORE + '.winningseq WHERE local = 1';
tx.executeSql(sql, [], function (tx, res) {
var rows = [];
for (var i = 0; i < res.rows.length; i++) {
rows.push(res.rows.item(i));
}
function doNext() {
if (!rows.length) {
return callback(tx);
}
var row = rows.shift();
var rev = JSON.parse(row.data)._rev;
tx.executeSql('INSERT INTO ' + LOCAL_STORE +
' (id, rev, json) VALUES (?,?,?)',
[row.id, rev, row.data], function (tx) {
tx.executeSql('DELETE FROM ' + DOC_STORE + ' WHERE id=?',
[row.id], function (tx) {
tx.executeSql('DELETE FROM ' + BY_SEQ_STORE + ' WHERE seq=?',
[row.seq], function () {
doNext();
});
});
});
}
doNext();
});
});
}
// in this migration, we remove doc_id_rev and just use rev
function runMigration4(tx, callback) {
function updateRows(rows) {
function doNext() {
if (!rows.length) {
return callback(tx);
}
var row = rows.shift();
var doc_id_rev = parseHexString(row.hex, encoding);
var idx = doc_id_rev.lastIndexOf('::');
var doc_id = doc_id_rev.substring(0, idx);
var rev = doc_id_rev.substring(idx + 2);
var sql = 'UPDATE ' + BY_SEQ_STORE +
' SET doc_id=?, rev=? WHERE doc_id_rev=?';
tx.executeSql(sql, [doc_id, rev, doc_id_rev], function () {
doNext();
});
}
doNext();
}
var sql = 'ALTER TABLE ' + BY_SEQ_STORE + ' ADD COLUMN doc_id';
tx.executeSql(sql, [], function (tx) {
var sql = 'ALTER TABLE ' + BY_SEQ_STORE + ' ADD COLUMN rev';
tx.executeSql(sql, [], function (tx) {
tx.executeSql(BY_SEQ_STORE_DOC_ID_REV_INDEX_SQL, [], function (tx) {
var sql = 'SELECT hex(doc_id_rev) as hex FROM ' + BY_SEQ_STORE;
tx.executeSql(sql, [], function (tx, res) {
var rows = [];
for (var i = 0; i < res.rows.length; i++) {
rows.push(res.rows.item(i));
}
updateRows(rows);
});
});
});
});
}
// in this migration, we add the attach_and_seq table
// for issue #2818
function runMigration5(tx, callback) {
function migrateAttsAndSeqs(tx) {
// need to actually populate the table. this is the expensive part,
// so as an optimization, check first that this database even
// contains attachments
var sql = 'SELECT COUNT(*) AS cnt FROM ' + ATTACH_STORE;
tx.executeSql(sql, [], function (tx, res) {
var count = res.rows.item(0).cnt;
if (!count) {
return callback(tx);
}
var offset = 0;
var pageSize = 10;
function nextPage() {
var sql = select(
SELECT_DOCS + ', ' + DOC_STORE + '.id AS id',
[DOC_STORE, BY_SEQ_STORE],
DOC_STORE_AND_BY_SEQ_JOINER,
null,
DOC_STORE + '.id '
);
sql += ' LIMIT ' + pageSize + ' OFFSET ' + offset;
offset += pageSize;
tx.executeSql(sql, [], function (tx, res) {
if (!res.rows.length) {
return callback(tx);
}
var digestSeqs = {};
function addDigestSeq(digest, seq) {
// uniq digest/seq pairs, just in case there are dups
var seqs = digestSeqs[digest] = (digestSeqs[digest] || []);
if (seqs.indexOf(seq) === -1) {
seqs.push(seq);
}
}
for (var i = 0; i < res.rows.length; i++) {
var row = res.rows.item(i);
var doc = unstringifyDoc(row.data, row.id, row.rev);
var atts = Object.keys(doc._attachments || {});
for (var j = 0; j < atts.length; j++) {
var att = doc._attachments[atts[j]];
addDigestSeq(att.digest, row.seq);
}
}
var digestSeqPairs = [];
Object.keys(digestSeqs).forEach(function (digest) {
var seqs = digestSeqs[digest];
seqs.forEach(function (seq) {
digestSeqPairs.push([digest, seq]);
});
});
if (!digestSeqPairs.length) {
return nextPage();
}
var numDone = 0;
digestSeqPairs.forEach(function (pair) {
var sql = 'INSERT INTO ' + ATTACH_AND_SEQ_STORE +
' (digest, seq) VALUES (?,?)';
tx.executeSql(sql, pair, function () {
if (++numDone === digestSeqPairs.length) {
nextPage();
}
});
});
});
}
nextPage();
});
}
var attachAndRev = 'CREATE TABLE IF NOT EXISTS ' +
ATTACH_AND_SEQ_STORE + ' (digest, seq INTEGER)';
tx.executeSql(attachAndRev, [], function (tx) {
tx.executeSql(
ATTACH_AND_SEQ_STORE_ATTACH_INDEX_SQL, [], function (tx) {
tx.executeSql(
ATTACH_AND_SEQ_STORE_SEQ_INDEX_SQL, [],
migrateAttsAndSeqs);
});
});
}
// in this migration, we use escapeBlob() and unescapeBlob()
// instead of reading out the binary as HEX, which is slow
function runMigration6(tx, callback) {
var sql = 'ALTER TABLE ' + ATTACH_STORE +
' ADD COLUMN escaped TINYINT(1) DEFAULT 0';
tx.executeSql(sql, [], callback);
}
// issue #3136, in this migration we need a "latest seq" as well
// as the "winning seq" in the doc store
function runMigration7(tx, callback) {
var sql = 'ALTER TABLE ' + DOC_STORE +
' ADD COLUMN max_seq INTEGER';
tx.executeSql(sql, [], function (tx) {
var sql = 'UPDATE ' + DOC_STORE + ' SET max_seq=(SELECT MAX(seq) FROM ' +
BY_SEQ_STORE + ' WHERE doc_id=id)';
tx.executeSql(sql, [], function (tx) {
// add unique index after filling, else we'll get a constraint
// error when we do the ALTER TABLE
var sql =
'CREATE UNIQUE INDEX IF NOT EXISTS \'doc-max-seq-idx\' ON ' +
DOC_STORE + ' (max_seq)';
tx.executeSql(sql, [], callback);
});
});
}
function checkEncoding(tx, cb) {
// UTF-8 on chrome/android, UTF-16 on safari < 7.1
tx.executeSql('SELECT HEX("a") AS hex', [], function (tx, res) {
var hex = res.rows.item(0).hex;
encoding = hex.length === 2 ? 'UTF-8' : 'UTF-16';
cb();
}
);
}
function onGetInstanceId() {
while (idRequests.length > 0) {
var idCallback = idRequests.pop();
idCallback(null, instanceId);
}
}
function onGetVersion(tx, dbVersion) {
if (dbVersion === 0) {
// initial schema
var meta = 'CREATE TABLE IF NOT EXISTS ' + META_STORE +
' (dbid, db_version INTEGER)';
var attach = 'CREATE TABLE IF NOT EXISTS ' + ATTACH_STORE +
' (digest UNIQUE, escaped TINYINT(1), body BLOB)';
var attachAndRev = 'CREATE TABLE IF NOT EXISTS ' +
ATTACH_AND_SEQ_STORE + ' (digest, seq INTEGER)';
// TODO: migrate winningseq to INTEGER
var doc = 'CREATE TABLE IF NOT EXISTS ' + DOC_STORE +
' (id unique, json, winningseq, max_seq INTEGER UNIQUE)';
var seq = 'CREATE TABLE IF NOT EXISTS ' + BY_SEQ_STORE +
' (seq INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, ' +
'json, deleted TINYINT(1), doc_id, rev)';
var local = 'CREATE TABLE IF NOT EXISTS ' + LOCAL_STORE +
' (id UNIQUE, rev, json)';
// creates
tx.executeSql(attach);
tx.executeSql(local);
tx.executeSql(attachAndRev, [], function () {
tx.executeSql(ATTACH_AND_SEQ_STORE_SEQ_INDEX_SQL);
tx.executeSql(ATTACH_AND_SEQ_STORE_ATTACH_INDEX_SQL);
});
tx.executeSql(doc, [], function () {
tx.executeSql(DOC_STORE_WINNINGSEQ_INDEX_SQL);
tx.executeSql(seq, [], function () {
tx.executeSql(BY_SEQ_STORE_DELETED_INDEX_SQL);
tx.executeSql(BY_SEQ_STORE_DOC_ID_REV_INDEX_SQL);
tx.executeSql(meta, [], function () {
// mark the db version, and new dbid
var initSeq = 'INSERT INTO ' + META_STORE +
' (db_version, dbid) VALUES (?,?)';
instanceId = utils.uuid();
var initSeqArgs = [ADAPTER_VERSION, instanceId];
tx.executeSql(initSeq, initSeqArgs, function () {
onGetInstanceId();
});
});
});
});
} else { // version > 0
var setupDone = function () {
var migrated = dbVersion < ADAPTER_VERSION;
if (migrated) {
// update the db version within this transaction
tx.executeSql('UPDATE ' + META_STORE + ' SET db_version = ' +
ADAPTER_VERSION);
}
// notify db.id() callers
var sql = 'SELECT dbid FROM ' + META_STORE;
tx.executeSql(sql, [], function (tx, result) {
instanceId = result.rows.item(0).dbid;
onGetInstanceId();
});
};
// would love to use promises here, but then websql
// ends the transaction early
var tasks = [
runMigration2,
runMigration3,
runMigration4,
runMigration5,
runMigration6,
runMigration7,
setupDone
];
// run each migration sequentially
var i = dbVersion;
var nextMigration = function (tx) {
tasks[i - 1](tx, nextMigration);
i++;
};
nextMigration(tx);
}
}
function setup() {
db.transaction(function (tx) {
// first check the encoding
checkEncoding(tx, function () {
// then get the version
fetchVersion(tx);
});
}, unknownError(callback), dbCreated);
}
function fetchVersion(tx) {
var sql = 'SELECT sql FROM sqlite_master WHERE tbl_name = ' + META_STORE;
tx.executeSql(sql, [], function (tx, result) {
if (!result.rows.length) {
// database hasn't even been created yet (version 0)
onGetVersion(tx, 0);
} else if (!/db_version/.test(result.rows.item(0).sql)) {
// table was created, but without the new db_version column,
// so add it.
tx.executeSql('ALTER TABLE ' + META_STORE +
' ADD COLUMN db_version INTEGER', [], function () {
// before version 2, this column didn't even exist
onGetVersion(tx, 1);
});
} else { // column exists, we can safely get it
tx.executeSql('SELECT db_version FROM ' + META_STORE,
[], function (tx, result) {
var dbVersion = result.rows.item(0).db_version;
onGetVersion(tx, dbVersion);
});
}
});
}
if (utils.isCordova()) {
//to wait until custom api is made in pouch.adapters before doing setup
window.addEventListener(api._name + '_pouch', function cordova_init() {
window.removeEventListener(api._name + '_pouch', cordova_init, false);
setup();
}, false);
} else {
setup();
}
api.type = function () {
return 'websql';
};
api._id = utils.toPromise(function (callback) {
callback(null, instanceId);
});
api._info = function (callback) {
db.readTransaction(function (tx) {
countDocs(tx, function (docCount) {
var sql = 'SELECT MAX(seq) AS seq FROM ' + BY_SEQ_STORE;
tx.executeSql(sql, [], function (tx, res) {
var updateSeq = res.rows.item(0).seq || 0;
callback(null, {
doc_count: docCount,
update_seq: updateSeq,
// for debugging
sqlite_plugin: db._sqlitePlugin,
websql_encoding: encoding
});
});
});
}, unknownError(callback));
};
api._bulkDocs = function (req, opts, callback) {
websqlBulkDocs(req, opts, api, db, WebSqlPouch.Changes, callback);
};
api._get = function (id, opts, callback) {
opts = utils.clone(opts);
var doc;
var metadata;
var err;
if (!opts.ctx) {
db.readTransaction(function (txn) {
opts.ctx = txn;
api._get(id, opts, callback);
});
return;
}
var tx = opts.ctx;
function finish() {
callback(err, {doc: doc, metadata: metadata, ctx: tx});
}
var sql;
var sqlArgs;
if (opts.rev) {
sql = select(
SELECT_DOCS,
[DOC_STORE, BY_SEQ_STORE],
DOC_STORE + '.id=' + BY_SEQ_STORE + '.doc_id',
[BY_SEQ_STORE + '.doc_id=?', BY_SEQ_STORE + '.rev=?']);
sqlArgs = [id, opts.rev];
} else {
sql = select(
SELECT_DOCS,
[DOC_STORE, BY_SEQ_STORE],
DOC_STORE_AND_BY_SEQ_JOINER,
DOC_STORE + '.id=?');
sqlArgs = [id];
}
tx.executeSql(sql, sqlArgs, function (a, results) {
if (!results.rows.length) {
err = errors.error(errors.MISSING_DOC, 'missing');
return finish();
}
var item = results.rows.item(0);
metadata = utils.safeJsonParse(item.metadata);
if (item.deleted && !opts.rev) {
err = errors.error(errors.MISSING_DOC, 'deleted');
return finish();
}
doc = unstringifyDoc(item.data, metadata.id, item.rev);
finish();
});
};
function countDocs(tx, callback) {
if (api._docCount !== -1) {
return callback(api._docCount);
}
// count the total rows
var sql = select(
'COUNT(' + DOC_STORE + '.id) AS \'num\'',
[DOC_STORE, BY_SEQ_STORE],
DOC_STORE_AND_BY_SEQ_JOINER,
BY_SEQ_STORE + '.deleted=0');
tx.executeSql(sql, [], function (tx, result) {
api._docCount = result.rows.item(0).num;
callback(api._docCount);
});
}
api._allDocs = function (opts, callback) {
var results = [];
var totalRows;
var start = 'startkey' in opts ? opts.startkey : false;
var end = 'endkey' in opts ? opts.endkey : false;
var key = 'key' in opts ? opts.key : false;
var descending = 'descending' in opts ? opts.descending : false;
var limit = 'limit' in opts ? opts.limit : -1;
var offset = 'skip' in opts ? opts.skip : 0;
var inclusiveEnd = opts.inclusive_end !== false;
var sqlArgs = [];
var criteria = [];
if (key !== false) {
criteria.push(DOC_STORE + '.id = ?');
sqlArgs.push(key);
} else if (start !== false || end !== false) {
if (start !== false) {
criteria.push(DOC_STORE + '.id ' + (descending ? '<=' : '>=') + ' ?');
sqlArgs.push(start);
}
if (end !== false) {
var comparator = descending ? '>' : '<';
if (inclusiveEnd) {
comparator += '=';
}
criteria.push(DOC_STORE + '.id ' + comparator + ' ?');
sqlArgs.push(end);
}
if (key !== false) {
criteria.push(DOC_STORE + '.id = ?');
sqlArgs.push(key);
}
}
if (opts.deleted !== 'ok') {
// report deleted if keys are specified
criteria.push(BY_SEQ_STORE + '.deleted = 0');
}
db.readTransaction(function (tx) {
// first count up the total rows
countDocs(tx, function (count) {
totalRows = count;
if (limit === 0) {
return;
}
// then actually fetch the documents
var sql = select(
SELECT_DOCS,
[DOC_STORE, BY_SEQ_STORE],
DOC_STORE_AND_BY_SEQ_JOINER,
criteria,
DOC_STORE + '.id ' + (descending ? 'DESC' : 'ASC')
);
sql += ' LIMIT ' + limit + ' OFFSET ' + offset;
tx.executeSql(sql, sqlArgs, function (tx, result) {
for (var i = 0, l = result.rows.length; i < l; i++) {
var item = result.rows.item(i);
var metadata = utils.safeJsonParse(item.metadata);
var id = metadata.id;
var data = unstringifyDoc(item.data, id, item.rev);
var winningRev = data._rev;
var doc = {
id: id,
key: id,
value: {rev: winningRev}
};
if (opts.include_docs) {
doc.doc = data;
doc.doc._rev = winningRev;
if (opts.conflicts) {
doc.doc._conflicts = merge.collectConflicts(metadata);
}
fetchAttachmentsIfNecessary(doc.doc, opts, api, tx);
}
if (item.deleted) {
if (opts.deleted === 'ok') {
doc.value.deleted = true;
doc.doc = null;
} else {
continue;
}
}
results.push(doc);
}
});
});
}, unknownError(callback), function () {
callback(null, {
total_rows: totalRows,
offset: opts.skip,
rows: results
});
});
};
api._changes = function (opts) {
opts = utils.clone(opts);
if (opts.continuous) {
var id = api._name + ':' + utils.uuid();
WebSqlPouch.Changes.addListener(api._name, id, api, opts);
WebSqlPouch.Changes.notify(api._name);
return {
cancel: function () {
WebSqlPouch.Changes.removeListener(api._name, id);
}
};
}
var descending = opts.descending;
// Ignore the `since` parameter when `descending` is true
opts.since = opts.since && !descending ? opts.since : 0;
var limit = 'limit' in opts ? opts.limit : -1;
if (limit === 0) {
limit = 1; // per CouchDB _changes spec
}
var returnDocs;
if ('returnDocs' in opts) {
returnDocs = opts.returnDocs;
} else {
returnDocs = true;
}
var results = [];
var numResults = 0;
function fetchChanges() {
var selectStmt =
DOC_STORE + '.json AS metadata, ' +
DOC_STORE + '.max_seq AS maxSeq, ' +
BY_SEQ_STORE + '.json AS winningDoc, ' +
BY_SEQ_STORE + '.rev AS winningRev ';
var from = DOC_STORE + ' JOIN ' + BY_SEQ_STORE;
var joiner = DOC_STORE + '.id=' + BY_SEQ_STORE + '.doc_id' +
' AND ' + DOC_STORE + '.winningseq=' + BY_SEQ_STORE + '.seq';
var criteria = ['maxSeq > ?'];
var sqlArgs = [opts.since];
if (opts.doc_ids) {
criteria.push(DOC_STORE + '.id IN ' + qMarks(opts.doc_ids.length));
sqlArgs = sqlArgs.concat(opts.doc_ids);
}
var orderBy = 'maxSeq ' + (descending ? 'DESC' : 'ASC');
var sql = select(selectStmt, from, joiner, criteria, orderBy);
var filter = utils.filterChange(opts);
if (!opts.view && !opts.filter) {
// we can just limit in the query
sql += ' LIMIT ' + limit;
}
var lastSeq = opts.since || 0;
db.readTransaction(function (tx) {
tx.executeSql(sql, sqlArgs, function (tx, result) {
function reportChange(change) {
return function () {
opts.onChange(change);
};
}
for (var i = 0, l = result.rows.length; i < l; i++) {
var item = result.rows.item(i);
var metadata = utils.safeJsonParse(item.metadata);
lastSeq = item.maxSeq;
var doc = unstringifyDoc(item.winningDoc, metadata.id,
item.winningRev);
var change = opts.processChange(doc, metadata, opts);
change.seq = item.maxSeq;
if (filter(change)) {
numResults++;
if (returnDocs) {
results.push(change);
}
// process the attachment immediately
// for the benefit of live listeners
if (opts.attachments && opts.include_docs) {
fetchAttachmentsIfNecessary(doc, opts, api, tx,
reportChange(change));
} else {
reportChange(change)();
}
}
if (numResults === limit) {
break;
}
}
});
}, unknownError(opts.complete), function () {
if (!opts.continuous) {
opts.complete(null, {
results: results,
last_seq: lastSeq
});
}
});
}
fetchChanges();
};
api._close = function (callback) {
//WebSQL databases do not need to be closed
callback();
};
api._getAttachment = function (attachment, opts, callback) {
var res;
var tx = opts.ctx;
var digest = attachment.digest;
var type = attachment.content_type;
var sql = 'SELECT escaped, ' +
'CASE WHEN escaped = 1 THEN body ELSE HEX(body) END AS body FROM ' +
ATTACH_STORE + ' WHERE digest=?';
tx.executeSql(sql, [digest], function (tx, result) {
// websql has a bug where \u0000 causes early truncation in strings
// and blobs. to work around this, we used to use the hex() function,
// but that's not performant. after migration 6, we remove \u0000
// and add it back in afterwards
var item = result.rows.item(0);
var data = item.escaped ? websqlUtils.unescapeBlob(item.body) :
parseHexString(item.body, encoding);
if (opts.encode) {
res = btoa(data);
} else {
data = utils.fixBinary(data);
res = utils.createBlob([data], {type: type});
}
callback(null, res);
});
};
api._getRevisionTree = function (docId, callback) {
db.readTransaction(function (tx) {
var sql = 'SELECT json AS metadata FROM ' + DOC_STORE + ' WHERE id = ?';
tx.executeSql(sql, [docId], function (tx, result) {
if (!result.rows.length) {
callback(errors.error(errors.MISSING_DOC));
} else {
var data = utils.safeJsonParse(result.rows.item(0).metadata);
callback(null, data.rev_tree);
}
});
});
};
api._doCompaction = function (docId, revs, callback) {
if (!revs.length) {
return callback();
}
db.transaction(function (tx) {
// update doc store
var sql = 'SELECT json AS metadata FROM ' + DOC_STORE + ' WHERE id = ?';
tx.executeSql(sql, [docId], function (tx, result) {
var metadata = utils.safeJsonParse(result.rows.item(0).metadata);
merge.traverseRevTree(metadata.rev_tree, function (isLeaf, pos,
revHash, ctx, opts) {
var rev = pos + '-' + revHash;
if (revs.indexOf(rev) !== -1) {
opts.status = 'missing';
}
});
var sql = 'UPDATE ' + DOC_STORE + ' SET json = ? WHERE id = ?';
tx.executeSql(sql, [utils.safeJsonStringify(metadata), docId]);
});
compactRevs(revs, docId, tx);
}, unknownError(callback), function () {
callback();
});
};
api._getLocal = function (id, callback) {
db.readTransaction(function (tx) {
var sql = 'SELECT json, rev FROM ' + LOCAL_STORE + ' WHERE id=?';
tx.executeSql(sql, [id], function (tx, res) {
if (res.rows.length) {
var item = res.rows.item(0);
var doc = unstringifyDoc(item.json, id, item.rev);
callback(null, doc);
} else {
callback(errors.error(errors.MISSING_DOC));
}
});
});
};
api._putLocal = function (doc, opts, callback) {
if (typeof opts === 'function') {
callback = opts;
opts = {};
}
delete doc._revisions; // ignore this, trust the rev
var oldRev = doc._rev;
var id = doc._id;
var newRev;
if (!oldRev) {
newRev = doc._rev = '0-1';
} else {
newRev = doc._rev = '0-' + (parseInt(oldRev.split('-')[1], 10) + 1);
}
var json = stringifyDoc(doc);
var ret;
function putLocal(tx) {
var sql;
var values;
if (oldRev) {
sql = 'UPDATE ' + LOCAL_STORE + ' SET rev=?, json=? ' +
'WHERE id=? AND rev=?';
values = [newRev, json, id, oldRev];
} else {
sql = 'INSERT INTO ' + LOCAL_STORE + ' (id, rev, json) VALUES (?,?,?)';
values = [id, newRev, json];
}
tx.executeSql(sql, values, function (tx, res) {
if (res.rowsAffected) {
ret = {ok: true, id: id, rev: newRev};
if (opts.ctx) { // return immediately
callback(null, ret);
}
} else {
callback(errors.error(errors.REV_CONFLICT));
}
}, function () {
callback(errors.error(errors.REV_CONFLICT));
return false; // ack that we handled the error
});
}
if (opts.ctx) {
putLocal(opts.ctx);
} else {
db.transaction(function (tx) {
putLocal(tx);
}, unknownError(callback), function () {
if (ret) {
callback(null, ret);
}
});
}
};
api._removeLocal = function (doc, callback) {
var ret;
db.transaction(function (tx) {
var sql = 'DELETE FROM ' + LOCAL_STORE + ' WHERE id=? AND rev=?';
var params = [doc._id, doc._rev];
tx.executeSql(sql, params, function (tx, res) {
if (!res.rowsAffected) {
return callback(errors.error(errors.MISSING_DOC));
}
ret = {ok: true, id: doc._id, rev: '0-0'};
});
}, unknownError(callback), function () {
if (ret) {
callback(null, ret);
}
});
};
api._destroy = function (callback) {
WebSqlPouch.Changes.removeAllListeners(api._name);
db.transaction(function (tx) {
var stores = [DOC_STORE, BY_SEQ_STORE, ATTACH_STORE, META_STORE,
LOCAL_STORE, ATTACH_AND_SEQ_STORE];
stores.forEach(function (store) {
tx.executeSql('DROP TABLE IF EXISTS ' + store, []);
});
}, unknownError(callback), function () {
if (utils.hasLocalStorage()) {
delete window.localStorage['_pouch__websqldb_' + api._name];
delete window.localStorage[api._name];
}
callback(null, {'ok': true});
});
};
}
WebSqlPouch.valid = websqlUtils.valid;
WebSqlPouch.Changes = new utils.Changes();
module.exports = WebSqlPouch;
},{"../../deps/errors":120,"../../deps/parse-hex":124,"../../merge":133,"../../utils":138,"./websql-bulk-docs":110,"./websql-constants":111,"./websql-utils":112}],114:[function(require,module,exports){
'use strict';
var utils = require('./utils');
var merge = require('./merge');
var errors = require('./deps/errors');
var EE = require('events').EventEmitter;
var evalFilter = require('./evalFilter');
var evalView = require('./evalView');
module.exports = Changes;
utils.inherits(Changes, EE);
function Changes(db, opts, callback) {
EE.call(this);
var self = this;
this.db = db;
opts = opts ? utils.clone(opts) : {};
var oldComplete = callback || opts.complete || function () {};
var complete = opts.complete = utils.once(function (err, resp) {
if (err) {
self.emit('error', err);
} else {
self.emit('complete', resp);
}
self.removeAllListeners();
db.removeListener('destroyed', onDestroy);
});
if (oldComplete) {
self.on('complete', function (resp) {
oldComplete(null, resp);
});
self.on('error', function (err) {
oldComplete(err);
});
}
var oldOnChange = opts.onChange;
if (oldOnChange) {
self.on('change', oldOnChange);
}
function onDestroy() {
self.cancel();
}
db.once('destroyed', onDestroy);
opts.onChange = function (change) {
if (opts.isCancelled) {
return;
}
self.emit('change', change);
if (self.startSeq && self.startSeq <= change.seq) {
self.emit('uptodate');
self.startSeq = false;
}
if (change.deleted) {
self.emit('delete', change);
} else if (change.changes.length === 1 &&
change.changes[0].rev.slice(0, 2) === '1-') {
self.emit('create', change);
} else {
self.emit('update', change);
}
};
var promise = new utils.Promise(function (fulfill, reject) {
opts.complete = function (err, res) {
if (err) {
reject(err);
} else {
fulfill(res);
}
};
});
self.once('cancel', function () {
if (oldOnChange) {
self.removeListener('change', oldOnChange);
}
opts.complete(null, {status: 'cancelled'});
});
this.then = promise.then.bind(promise);
this['catch'] = promise['catch'].bind(promise);
this.then(function (result) {
complete(null, result);
}, complete);
if (!db.taskqueue.isReady) {
db.taskqueue.addTask(function () {
if (self.isCancelled) {
self.emit('cancel');
} else {
self.doChanges(opts);
}
});
} else {
self.doChanges(opts);
}
}
Changes.prototype.cancel = function () {
this.isCancelled = true;
if (this.db.taskqueue.isReady) {
this.emit('cancel');
}
};
function processChange(doc, metadata, opts) {
var changeList = [{rev: doc._rev}];
if (opts.style === 'all_docs') {
changeList = merge.collectLeaves(metadata.rev_tree)
.map(function (x) { return {rev: x.rev}; });
}
var change = {
id: metadata.id,
changes: changeList,
doc: doc
};
if (utils.isDeleted(metadata, doc._rev)) {
change.deleted = true;
}
if (opts.conflicts) {
change.doc._conflicts = merge.collectConflicts(metadata);
if (!change.doc._conflicts.length) {
delete change.doc._conflicts;
}
}
return change;
}
Changes.prototype.doChanges = function (opts) {
var self = this;
var callback = opts.complete;
opts = utils.clone(opts);
if ('live' in opts && !('continuous' in opts)) {
opts.continuous = opts.live;
}
opts.processChange = processChange;
if (opts.since === 'latest') {
opts.since = 'now';
}
if (!opts.since) {
opts.since = 0;
}
if (opts.since === 'now') {
this.db.info().then(function (info) {
if (self.isCancelled) {
callback(null, {status: 'cancelled'});
return;
}
opts.since = info.update_seq;
self.doChanges(opts);
}, callback);
return;
}
if (opts.continuous && opts.since !== 'now') {
this.db.info().then(function (info) {
self.startSeq = info.update_seq;
}, function (err) {
if (err.id === 'idbNull') {
//db closed before this returned
//thats ok
return;
}
throw err;
});
}
if (this.db.type() !== 'http' &&
opts.filter && typeof opts.filter === 'string' &&
!opts.doc_ids) {
return this.filterChanges(opts);
}
if (!('descending' in opts)) {
opts.descending = false;
}
// 0 and 1 should return 1 document
opts.limit = opts.limit === 0 ? 1 : opts.limit;
opts.complete = callback;
var newPromise = this.db._changes(opts);
if (newPromise && typeof newPromise.cancel === 'function') {
var cancel = self.cancel;
self.cancel = utils.getArguments(function (args) {
newPromise.cancel();
cancel.apply(this, args);
});
}
};
Changes.prototype.filterChanges = function (opts) {
var self = this;
var callback = opts.complete;
if (opts.filter === '_view') {
if (!opts.view || typeof opts.view !== 'string') {
var err = errors.error(errors.BAD_REQUEST,
'`view` filter parameter is not provided.');
callback(err);
return;
}
// fetch a view from a design doc, make it behave like a filter
var viewName = opts.view.split('/');
this.db.get('_design/' + viewName[0], function (err, ddoc) {
if (self.isCancelled) {
callback(null, {status: 'cancelled'});
return;
}
if (err) {
callback(errors.generateErrorFromResponse(err));
return;
}
if (ddoc && ddoc.views && ddoc.views[viewName[1]]) {
var filter = evalView(ddoc.views[viewName[1]].map);
opts.filter = filter;
self.doChanges(opts);
return;
}
var msg = ddoc.views ? 'missing json key: ' + viewName[1] :
'missing json key: views';
if (!err) {
err = errors.error(errors.MISSING_DOC, msg);
}
callback(err);
return;
});
} else {
// fetch a filter from a design doc
var filterName = opts.filter.split('/');
this.db.get('_design/' + filterName[0], function (err, ddoc) {
if (self.isCancelled) {
callback(null, {status: 'cancelled'});
return;
}
if (err) {
callback(errors.generateErrorFromResponse(err));
return;
}
if (ddoc && ddoc.filters && ddoc.filters[filterName[1]]) {
var filter = evalFilter(ddoc.filters[filterName[1]]);
opts.filter = filter;
self.doChanges(opts);
return;
} else {
var msg = (ddoc && ddoc.filters) ? 'missing json key: ' + filterName[1]
: 'missing json key: filters';
if (!err) {
err = errors.error(errors.MISSING_DOC, msg);
}
callback(err);
return;
}
});
}
};
},{"./deps/errors":120,"./evalFilter":130,"./evalView":131,"./merge":133,"./utils":138,"events":45}],115:[function(require,module,exports){
'use strict';
var Promise = require('./deps/promise');
var explain404 = require('./deps/explain404');
var pouchCollate = require('pouchdb-collate');
var collate = pouchCollate.collate;
function updateCheckpoint(db, id, checkpoint, returnValue) {
return db.get(id).catch(function (err) {
if (err.status === 404) {
if (db.type() === 'http') {
explain404(
'PouchDB is just checking if a remote checkpoint exists.');
}
return {_id: id};
}
throw err;
}).then(function (doc) {
if (returnValue.cancelled) {
return;
}
doc.last_seq = checkpoint;
return db.put(doc).catch(function (err) {
if (err.status === 409) {
// retry; someone is trying to write a checkpoint simultaneously
return updateCheckpoint(db, id, checkpoint, returnValue);
}
throw err;
});
});
}
function Checkpointer(src, target, id, returnValue) {
this.src = src;
this.target = target;
this.id = id;
this.returnValue = returnValue;
}
Checkpointer.prototype.writeCheckpoint = function (checkpoint) {
var self = this;
return this.updateTarget(checkpoint).then(function () {
return self.updateSource(checkpoint);
});
};
Checkpointer.prototype.updateTarget = function (checkpoint) {
return updateCheckpoint(this.target, this.id, checkpoint, this.returnValue);
};
Checkpointer.prototype.updateSource = function (checkpoint) {
var self = this;
if (this.readOnlySource) {
return Promise.resolve(true);
}
return updateCheckpoint(this.src, this.id, checkpoint, this.returnValue)
.catch(function (err) {
var isForbidden = typeof err.status === 'number' &&
Math.floor(err.status / 100) === 4;
if (isForbidden) {
self.readOnlySource = true;
return true;
}
throw err;
});
};
Checkpointer.prototype.getCheckpoint = function () {
var self = this;
return self.target.get(self.id).then(function (targetDoc) {
return self.src.get(self.id).then(function (sourceDoc) {
if (collate(targetDoc.last_seq, sourceDoc.last_seq) === 0) {
return sourceDoc.last_seq;
}
return 0;
}, function (err) {
if (err.status === 404 && targetDoc.last_seq) {
return self.src.put({
_id: self.id,
last_seq: 0
}).then(function () {
return 0;
}, function (err) {
if (err.status === 401) {
self.readOnlySource = true;
return targetDoc.last_seq;
}
return 0;
});
}
throw err;
});
}).catch(function (err) {
if (err.status !== 404) {
throw err;
}
return 0;
});
};
module.exports = Checkpointer;
},{"./deps/explain404":121,"./deps/promise":126,"pouchdb-collate":144}],116:[function(require,module,exports){
(function (process,global){
/*globals cordova */
"use strict";
var Adapter = require('./adapter');
var utils = require('./utils');
var TaskQueue = require('./taskqueue');
var Promise = utils.Promise;
function defaultCallback(err) {
if (err && global.debug) {
console.error(err);
}
}
utils.inherits(PouchDB, Adapter);
function PouchDB(name, opts, callback) {
if (!(this instanceof PouchDB)) {
return new PouchDB(name, opts, callback);
}
var self = this;
if (typeof opts === 'function' || typeof opts === 'undefined') {
callback = opts;
opts = {};
}
if (name && typeof name === 'object') {
opts = name;
name = undefined;
}
if (typeof callback === 'undefined') {
callback = defaultCallback;
}
name = name || opts.name;
opts = opts ? utils.clone(opts) : {};
// if name was specified via opts, ignore for the sake of dependentDbs
delete opts.name;
this.__opts = opts;
var oldCB = callback;
self.auto_compaction = opts.auto_compaction;
self.prefix = PouchDB.prefix;
Adapter.call(self);
self.taskqueue = new TaskQueue();
var promise = new Promise(function (fulfill, reject) {
callback = function (err, resp) {
if (err) {
return reject(err);
}
delete resp.then;
fulfill(resp);
};
opts = utils.clone(opts);
var originalName = opts.name || name;
var backend, error;
(function () {
try {
if (typeof originalName !== 'string') {
error = new Error('Missing/invalid DB name');
error.code = 400;
throw error;
}
backend = PouchDB.parseAdapter(originalName, opts);
opts.originalName = originalName;
opts.name = backend.name;
if (opts.prefix && backend.adapter !== 'http' &&
backend.adapter !== 'https') {
opts.name = opts.prefix + opts.name;
}
opts.adapter = opts.adapter || backend.adapter;
self._adapter = opts.adapter;
self._db_name = originalName;
if (!PouchDB.adapters[opts.adapter]) {
error = new Error('Adapter is missing');
error.code = 404;
throw error;
}
if (!PouchDB.adapters[opts.adapter].valid()) {
error = new Error('Invalid Adapter');
error.code = 404;
throw error;
}
} catch (err) {
self.taskqueue.fail(err);
self.changes = utils.toPromise(function (opts) {
if (opts.complete) {
opts.complete(err);
}
});
}
}());
if (error) {
return reject(error); // constructor error, see above
}
self.adapter = opts.adapter;
// needs access to PouchDB;
self.replicate = {};
self.replicate.from = function (url, opts, callback) {
return self.constructor.replicate(url, self, opts, callback);
};
self.replicate.to = function (url, opts, callback) {
return self.constructor.replicate(self, url, opts, callback);
};
self.sync = function (dbName, opts, callback) {
return self.constructor.sync(self, dbName, opts, callback);
};
self.replicate.sync = self.sync;
PouchDB.adapters[opts.adapter].call(self, opts, function (err) {
if (err) {
if (callback) {
self.taskqueue.fail(err);
callback(err);
}
return;
}
function destructionListener() {
PouchDB.emit('destroyed', opts.originalName);
//so we don't have to sift through all dbnames
PouchDB.emit(opts.originalName, 'destroyed');
self.removeListener('destroyed', destructionListener);
}
self.on('destroyed', destructionListener);
self.emit('created', self);
PouchDB.emit('created', opts.originalName);
self.taskqueue.ready(self);
callback(null, self);
});
if (opts.skipSetup) {
self.taskqueue.ready(self);
process.nextTick(function () {
callback(null, self);
});
}
if (utils.isCordova()) {
//to inform websql adapter that we can use api
cordova.fireWindowEvent(opts.name + "_pouch", {});
}
});
promise.then(function (resp) {
oldCB(null, resp);
}, oldCB);
self.then = promise.then.bind(promise);
self.catch = promise.catch.bind(promise);
}
PouchDB.debug = require('debug');
module.exports = PouchDB;
}).call(this,require("/Users/nlawson/workspace-node/pouchdb-authentication/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js"),typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"./adapter":102,"./taskqueue":137,"./utils":138,"/Users/nlawson/workspace-node/pouchdb-authentication/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js":46,"debug":141}],117:[function(require,module,exports){
(function (process){
"use strict";
var request = require('request');
var buffer = require('./buffer');
var errors = require('./errors');
var utils = require('../utils');
function ajax(options, adapterCallback) {
var requestCompleted = false;
var callback = utils.getArguments(function (args) {
if (requestCompleted) {
return;
}
adapterCallback.apply(this, args);
requestCompleted = true;
});
if (typeof options === "function") {
callback = options;
options = {};
}
options = utils.clone(options);
var defaultOptions = {
method : "GET",
headers: {},
json: true,
processData: true,
timeout: 10000,
cache: false
};
options = utils.extend(true, defaultOptions, options);
function onSuccess(obj, resp, cb) {
if (!options.binary && !options.json && options.processData &&
typeof obj !== 'string') {
obj = JSON.stringify(obj);
} else if (!options.binary && options.json && typeof obj === 'string') {
try {
obj = JSON.parse(obj);
} catch (e) {
// Probably a malformed JSON from server
return cb(e);
}
}
if (Array.isArray(obj)) {
obj = obj.map(function (v) {
if (v.error || v.missing) {
return errors.generateErrorFromResponse(v);
} else {
return v;
}
});
}
cb(null, obj, resp);
}
function onError(err, cb) {
var errParsed, errObj;
if (err.code && err.status) {
var err2 = new Error(err.message || err.code);
err2.status = err.status;
return cb(err2);
}
try {
errParsed = JSON.parse(err.responseText);
//would prefer not to have a try/catch clause
errObj = errors.generateErrorFromResponse(errParsed);
} catch (e) {
errObj = errors.generateErrorFromResponse(err);
}
cb(errObj);
}
if (options.json) {
if (!options.binary) {
options.headers.Accept = 'application/json';
}
options.headers['Content-Type'] = options.headers['Content-Type'] ||
'application/json';
}
if (options.binary) {
options.encoding = null;
options.json = false;
}
if (!options.processData) {
options.json = false;
}
function defaultBody(data) {
if (process.browser) {
return '';
}
return new buffer('', 'binary');
}
return request(options, function (err, response, body) {
if (err) {
err.status = response ? response.statusCode : 400;
return onError(err, callback);
}
var error;
var content_type = response.headers && response.headers['content-type'];
var data = body || defaultBody();
// CouchDB doesn't always return the right content-type for JSON data, so
// we check for ^{ and }$ (ignoring leading/trailing whitespace)
if (!options.binary && (options.json || !options.processData) &&
typeof data !== 'object' &&
(/json/.test(content_type) ||
(/^[\s]*\{/.test(data) && /\}[\s]*$/.test(data)))) {
data = JSON.parse(data);
}
if (response.statusCode >= 200 && response.statusCode < 300) {
onSuccess(data, response, callback);
} else {
if (options.binary) {
data = JSON.parse(data.toString());
}
error = errors.generateErrorFromResponse(data);
error.status = response.statusCode;
callback(error);
}
});
}
module.exports = ajax;
}).call(this,require("/Users/nlawson/workspace-node/pouchdb-authentication/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js"))
},{"../utils":138,"./buffer":119,"./errors":120,"/Users/nlawson/workspace-node/pouchdb-authentication/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js":46,"request":127}],118:[function(require,module,exports){
(function (global){
"use strict";
//Abstracts constructing a Blob object, so it also works in older
//browsers that don't support the native Blob constructor. (i.e.
//old QtWebKit versions, at least).
function createBlob(parts, properties) {
parts = parts || [];
properties = properties || {};
try {
return new Blob(parts, properties);
} catch (e) {
if (e.name !== "TypeError") {
throw e;
}
var BlobBuilder = global.BlobBuilder ||
global.MSBlobBuilder ||
global.MozBlobBuilder ||
global.WebKitBlobBuilder;
var builder = new BlobBuilder();
for (var i = 0; i < parts.length; i += 1) {
builder.append(parts[i]);
}
return builder.getBlob(properties.type);
}
}
module.exports = createBlob;
}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{}],119:[function(require,module,exports){
// hey guess what, we don't need this in the browser
module.exports = {};
},{}],120:[function(require,module,exports){
"use strict";
var inherits = require('inherits');
inherits(PouchError, Error);
function PouchError(opts) {
Error.call(opts.reason);
this.status = opts.status;
this.name = opts.error;
this.message = opts.reason;
this.error = true;
}
PouchError.prototype.toString = function () {
return JSON.stringify({
status: this.status,
name: this.name,
message: this.message
});
};
exports.UNAUTHORIZED = new PouchError({
status: 401,
error: 'unauthorized',
reason: "Name or password is incorrect."
});
exports.MISSING_BULK_DOCS = new PouchError({
status: 400,
error: 'bad_request',
reason: "Missing JSON list of 'docs'"
});
exports.MISSING_DOC = new PouchError({
status: 404,
error: 'not_found',
reason: 'missing'
});
exports.REV_CONFLICT = new PouchError({
status: 409,
error: 'conflict',
reason: 'Document update conflict'
});
exports.INVALID_ID = new PouchError({
status: 400,
error: 'invalid_id',
reason: '_id field must contain a string'
});
exports.MISSING_ID = new PouchError({
status: 412,
error: 'missing_id',
reason: '_id is required for puts'
});
exports.RESERVED_ID = new PouchError({
status: 400,
error: 'bad_request',
reason: 'Only reserved document ids may start with underscore.'
});
exports.NOT_OPEN = new PouchError({
status: 412,
error: 'precondition_failed',
reason: 'Database not open'
});
exports.UNKNOWN_ERROR = new PouchError({
status: 500,
error: 'unknown_error',
reason: 'Database encountered an unknown error'
});
exports.BAD_ARG = new PouchError({
status: 500,
error: 'badarg',
reason: 'Some query argument is invalid'
});
exports.INVALID_REQUEST = new PouchError({
status: 400,
error: 'invalid_request',
reason: 'Request was invalid'
});
exports.QUERY_PARSE_ERROR = new PouchError({
status: 400,
error: 'query_parse_error',
reason: 'Some query parameter is invalid'
});
exports.DOC_VALIDATION = new PouchError({
status: 500,
error: 'doc_validation',
reason: 'Bad special document member'
});
exports.BAD_REQUEST = new PouchError({
status: 400,
error: 'bad_request',
reason: 'Something wrong with the request'
});
exports.NOT_AN_OBJECT = new PouchError({
status: 400,
error: 'bad_request',
reason: 'Document must be a JSON object'
});
exports.DB_MISSING = new PouchError({
status: 404,
error: 'not_found',
reason: 'Database not found'
});
exports.IDB_ERROR = new PouchError({
status: 500,
error: 'indexed_db_went_bad',
reason: 'unknown'
});
exports.WSQ_ERROR = new PouchError({
status: 500,
error: 'web_sql_went_bad',
reason: 'unknown'
});
exports.LDB_ERROR = new PouchError({
status: 500,
error: 'levelDB_went_went_bad',
reason: 'unknown'
});
exports.FORBIDDEN = new PouchError({
status: 403,
error: 'forbidden',
reason: 'Forbidden by design doc validate_doc_update function'
});
exports.INVALID_REV = new PouchError({
status: 400,
error: 'bad_request',
reason: 'Invalid rev format'
});
exports.FILE_EXISTS = new PouchError({
status: 412,
error: 'file_exists',
reason: 'The database could not be created, the file already exists.'
});
exports.MISSING_STUB = new PouchError({
status: 412,
error: 'missing_stub'
});
exports.error = function (error, reason, name) {
function CustomPouchError(reason) {
// inherit error properties from our parent error manually
// so as to allow proper JSON parsing.
/* jshint ignore:start */
for (var p in error) {
if (typeof error[p] !== 'function') {
this[p] = error[p];
}
}
/* jshint ignore:end */
if (name !== undefined) {
this.name = name;
}
if (reason !== undefined) {
this.reason = reason;
}
}
CustomPouchError.prototype = PouchError.prototype;
return new CustomPouchError(reason);
};
// Find one of the errors defined above based on the value
// of the specified property.
// If reason is provided prefer the error matching that reason.
// This is for differentiating between errors with the same name and status,
// eg, bad_request.
exports.getErrorTypeByProp = function (prop, value, reason) {
var errors = exports;
var keys = Object.keys(errors).filter(function (key) {
var error = errors[key];
return typeof error !== 'function' && error[prop] === value;
});
var key = reason && keys.filter(function (key) {
var error = errors[key];
return error.message === reason;
})[0] || keys[0];
return (key) ? errors[key] : null;
};
exports.generateErrorFromResponse = function (res) {
var error, errName, errType, errMsg, errReason;
var errors = exports;
errName = (res.error === true && typeof res.name === 'string') ?
res.name :
res.error;
errReason = res.reason;
errType = errors.getErrorTypeByProp('name', errName, errReason);
if (res.missing ||
errReason === 'missing' ||
errReason === 'deleted' ||
errName === 'not_found') {
errType = errors.MISSING_DOC;
} else if (errName === 'doc_validation') {
// doc validation needs special treatment since
// res.reason depends on the validation error.
// see utils.js
errType = errors.DOC_VALIDATION;
errMsg = errReason;
} else if (errName === 'bad_request' && errType.message !== errReason) {
// if bad_request error already found based on reason don't override.
// attachment errors.
if (errReason.indexOf('unknown stub attachment') === 0) {
errType = errors.MISSING_STUB;
errMsg = errReason;
} else {
errType = errors.BAD_REQUEST;
}
}
// fallback to error by statys or unknown error.
if (!errType) {
errType = errors.getErrorTypeByProp('status', res.status, errReason) ||
errors.UNKNOWN_ERROR;
}
error = errors.error(errType, errReason, errName);
// Keep custom message.
if (errMsg) {
error.message = errMsg;
}
// Keep helpful response data in our error messages.
if (res.id) {
error.id = res.id;
}
if (res.status) {
error.status = res.status;
}
if (res.statusText) {
error.name = res.statusText;
}
if (res.missing) {
error.missing = res.missing;
}
return error;
};
},{"inherits":79}],121:[function(require,module,exports){
(function (process,global){
'use strict';
// designed to give info to browser users, who are disturbed
// when they see 404s in the console
function explain404(str) {
if (process.browser && 'console' in global && 'info' in console) {
console.info('The above 404 is totally normal. ' + str);
}
}
module.exports = explain404;
}).call(this,require("/Users/nlawson/workspace-node/pouchdb-authentication/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js"),typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"/Users/nlawson/workspace-node/pouchdb-authentication/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js":46}],122:[function(require,module,exports){
(function (process,global){
'use strict';
var crypto = require('crypto');
var Md5 = require('spark-md5');
var setImmediateShim = global.setImmediate || global.setTimeout;
var MD5_CHUNK_SIZE = 32768;
// convert a 64-bit int to a binary string
function intToString(int) {
var bytes = [
(int & 0xff),
((int >>> 8) & 0xff),
((int >>> 16) & 0xff),
((int >>> 24) & 0xff)
];
return bytes.map(function (byte) {
return String.fromCharCode(byte);
}).join('');
}
// convert an array of 64-bit ints into
// a base64-encoded string
function rawToBase64(raw) {
var res = '';
for (var i = 0; i < raw.length; i++) {
res += intToString(raw[i]);
}
return btoa(res);
}
function appendBuffer(buffer, data, start, end) {
if (start > 0 || end < data.byteLength) {
// only create a subarray if we really need to
data = new Uint8Array(data, start,
Math.min(end, data.byteLength) - start);
}
buffer.append(data);
}
function appendString(buffer, data, start, end) {
if (start > 0 || end < data.length) {
// only create a substring if we really need to
data = data.substring(start, end);
}
buffer.appendBinary(data);
}
module.exports = function (data, callback) {
if (!process.browser) {
var base64 = crypto.createHash('md5').update(data).digest('base64');
callback(null, base64);
return;
}
var inputIsString = typeof data === 'string';
var len = inputIsString ? data.length : data.byteLength;
var chunkSize = Math.min(MD5_CHUNK_SIZE, len);
var chunks = Math.ceil(len / chunkSize);
var currentChunk = 0;
var buffer = inputIsString ? new Md5() : new Md5.ArrayBuffer();
var append = inputIsString ? appendString : appendBuffer;
function loadNextChunk() {
var start = currentChunk * chunkSize;
var end = start + chunkSize;
currentChunk++;
if (currentChunk < chunks) {
append(buffer, data, start, end);
setImmediateShim(loadNextChunk);
} else {
append(buffer, data, start, end);
var raw = buffer.end(true);
var base64 = rawToBase64(raw);
callback(null, base64);
buffer.destroy();
}
}
loadNextChunk();
};
}).call(this,require("/Users/nlawson/workspace-node/pouchdb-authentication/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js"),typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"/Users/nlawson/workspace-node/pouchdb-authentication/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js":46,"crypto":41,"spark-md5":154}],123:[function(require,module,exports){
'use strict';
var errors = require('./errors');
var uuid = require('./uuid');
function toObject(array) {
return array.reduce(function (obj, item) {
obj[item] = true;
return obj;
}, {});
}
// List of top level reserved words for doc
var reservedWords = toObject([
'_id',
'_rev',
'_attachments',
'_deleted',
'_revisions',
'_revs_info',
'_conflicts',
'_deleted_conflicts',
'_local_seq',
'_rev_tree',
//replication documents
'_replication_id',
'_replication_state',
'_replication_state_time',
'_replication_state_reason',
'_replication_stats',
// Specific to Couchbase Sync Gateway
'_removed'
]);
// List of reserved words that should end up the document
var dataWords = toObject([
'_attachments',
//replication documents
'_replication_id',
'_replication_state',
'_replication_state_time',
'_replication_state_reason',
'_replication_stats'
]);
// Determine id an ID is valid
// - invalid IDs begin with an underescore that does not begin '_design' or
// '_local'
// - any other string value is a valid id
// Returns the specific error object for each case
exports.invalidIdError = function (id) {
var err;
if (!id) {
err = errors.error(errors.MISSING_ID);
} else if (typeof id !== 'string') {
err = errors.error(errors.INVALID_ID);
} else if (/^_/.test(id) && !(/^_(design|local)/).test(id)) {
err = errors.error(errors.RESERVED_ID);
}
if (err) {
throw err;
}
};
function parseRevisionInfo(rev) {
if (!/^\d+\-./.test(rev)) {
return errors.error(errors.INVALID_REV);
}
var idx = rev.indexOf('-');
var left = rev.substring(0, idx);
var right = rev.substring(idx + 1);
return {
prefix: parseInt(left, 10),
id: right
};
}
function makeRevTreeFromRevisions(revisions, opts) {
var pos = revisions.start - revisions.ids.length + 1;
var revisionIds = revisions.ids;
var ids = [revisionIds[0], opts, []];
for (var i = 1, len = revisionIds.length; i < len; i++) {
ids = [revisionIds[i], {status: 'missing'}, [ids]];
}
return [{
pos: pos,
ids: ids
}];
}
// Preprocess documents, parse their revisions, assign an id and a
// revision for new writes that are missing them, etc
exports.parseDoc = function (doc, newEdits) {
var nRevNum;
var newRevId;
var revInfo;
var opts = {status: 'available'};
if (doc._deleted) {
opts.deleted = true;
}
if (newEdits) {
if (!doc._id) {
doc._id = uuid();
}
newRevId = uuid(32, 16).toLowerCase();
if (doc._rev) {
revInfo = parseRevisionInfo(doc._rev);
if (revInfo.error) {
return revInfo;
}
doc._rev_tree = [{
pos: revInfo.prefix,
ids: [revInfo.id, {status: 'missing'}, [[newRevId, opts, []]]]
}];
nRevNum = revInfo.prefix + 1;
} else {
doc._rev_tree = [{
pos: 1,
ids : [newRevId, opts, []]
}];
nRevNum = 1;
}
} else {
if (doc._revisions) {
doc._rev_tree = makeRevTreeFromRevisions(doc._revisions, opts);
nRevNum = doc._revisions.start;
newRevId = doc._revisions.ids[0];
}
if (!doc._rev_tree) {
revInfo = parseRevisionInfo(doc._rev);
if (revInfo.error) {
return revInfo;
}
nRevNum = revInfo.prefix;
newRevId = revInfo.id;
doc._rev_tree = [{
pos: nRevNum,
ids: [newRevId, opts, []]
}];
}
}
exports.invalidIdError(doc._id);
doc._rev = nRevNum + '-' + newRevId;
var result = {metadata : {}, data : {}};
for (var key in doc) {
if (doc.hasOwnProperty(key)) {
var specialKey = key[0] === '_';
if (specialKey && !reservedWords[key]) {
var error = errors.error(errors.DOC_VALIDATION, key);
error.message = errors.DOC_VALIDATION.message + ': ' + key;
throw error;
} else if (specialKey && !dataWords[key]) {
result.metadata[key.slice(1)] = doc[key];
} else {
result.data[key] = doc[key];
}
}
}
return result;
};
},{"./errors":120,"./uuid":129}],124:[function(require,module,exports){
'use strict';
//
// Parsing hex strings. Yeah.
//
// So basically we need this because of a bug in WebSQL:
// https://code.google.com/p/chromium/issues/detail?id=422690
// https://bugs.webkit.org/show_bug.cgi?id=137637
//
// UTF-8 and UTF-16 are provided as separate functions
// for meager performance improvements
//
function decodeUtf8(str) {
return decodeURIComponent(window.escape(str));
}
function hexToInt(charCode) {
// '0'-'9' is 48-57
// 'A'-'F' is 65-70
// SQLite will only give us uppercase hex
return charCode < 65 ? (charCode - 48) : (charCode - 55);
}
// Example:
// pragma encoding=utf8;
// select hex('A');
// returns '41'
function parseHexUtf8(str, start, end) {
var result = '';
while (start < end) {
result += String.fromCharCode(
(hexToInt(str.charCodeAt(start++)) << 4) |
hexToInt(str.charCodeAt(start++)));
}
return result;
}
// Example:
// pragma encoding=utf16;
// select hex('A');
// returns '4100'
// notice that the 00 comes after the 41 (i.e. it's swizzled)
function parseHexUtf16(str, start, end) {
var result = '';
while (start < end) {
// UTF-16, so swizzle the bytes
result += String.fromCharCode(
(hexToInt(str.charCodeAt(start + 2)) << 12) |
(hexToInt(str.charCodeAt(start + 3)) << 8) |
(hexToInt(str.charCodeAt(start)) << 4) |
hexToInt(str.charCodeAt(start + 1)));
start += 4;
}
return result;
}
function parseHexString(str, encoding) {
if (encoding === 'UTF-8') {
return decodeUtf8(parseHexUtf8(str, 0, str.length));
} else {
return parseHexUtf16(str, 0, str.length);
}
}
module.exports = parseHexString;
},{}],125:[function(require,module,exports){
'use strict';
// originally parseUri 1.2.2, now patched by us
// (c) Steven Levithan <stevenlevithan.com>
// MIT License
var options = {
strictMode: false,
key: ["source", "protocol", "authority", "userInfo", "user", "password",
"host", "port", "relative", "path", "directory", "file", "query",
"anchor"],
q: {
name: "queryKey",
parser: /(?:^|&)([^&=]*)=?([^&]*)/g
},
parser: {
/* jshint maxlen: false */
strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,
loose: /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/
}
};
function parseUri(str) {
var o = options;
var m = o.parser[o.strictMode ? "strict" : "loose"].exec(str);
var uri = {};
var i = 14;
while (i--) {
var key = o.key[i];
var value = m[i] || "";
var encoded = ['user', 'password'].indexOf(key) !== -1;
uri[key] = encoded ? decodeURIComponent(value) : value;
}
uri[o.q.name] = {};
uri[o.key[12]].replace(o.q.parser, function ($0, $1, $2) {
if ($1) {
uri[o.q.name][$1] = $2;
}
});
return uri;
}
module.exports = parseUri;
},{}],126:[function(require,module,exports){
'use strict';
if (typeof Promise === 'function') {
module.exports = Promise;
} else {
module.exports = require('bluebird');
}
},{"bluebird":83}],127:[function(require,module,exports){
/* global fetch */
/* global Headers */
'use strict';
var createBlob = require('./blob.js');
var utils = require('../utils');
function wrappedFetch() {
var wrappedPromise = {};
var promise = new utils.Promise(function(resolve, reject) {
wrappedPromise.resolve = resolve;
wrappedPromise.reject = reject;
});
var args = new Array(arguments.length);
for (var i = 0; i < args.length; i++) {
args[i] = arguments[i];
}
wrappedPromise.then = promise.then.bind(promise);
wrappedPromise.catch = promise.catch.bind(promise);
wrappedPromise.promise = promise;
fetch.apply(null, args).then(function(response) {
wrappedPromise.resolve(response);
}, function(error) {
wrappedPromise.reject(error);
}).catch(function(error) {
wrappedPromise.catch(error);
});
return wrappedPromise;
}
function fetchRequest(options, callback) {
var wrappedPromise, timer, fetchResponse;
var headers = new Headers();
var fetchOptions = {
method: options.method,
credentials: 'include',
headers: headers
};
if (options.json) {
headers.set('Accept', 'application/json');
headers.set('Content-Type', options.headers['Content-Type'] ||
'application/json');
}
if (options.body && (options.body instanceof Blob)) {
utils.readAsBinaryString(options.body, function(binary) {
fetchOptions.body = utils.fixBinary(binary);
});
} else if (options.body &&
options.processData &&
typeof options.body !== 'string') {
fetchOptions.body = JSON.stringify(options.body);
} else if ('body' in options) {
fetchOptions.body = options.body;
} else {
fetchOptions.body = null;
}
Object.keys(options.headers).forEach(function(key) {
if (options.headers.hasOwnProperty(key)) {
headers.set(key, options.headers[key]);
}
});
wrappedPromise = wrappedFetch(options.url, fetchOptions);
if (options.timeout > 0) {
timer = setTimeout(function() {
wrappedPromise.reject(new Error('Load timeout for resource: ' +
options.url));
}, options.timeout);
}
wrappedPromise.promise.then(function(response) {
var result;
fetchResponse = response;
if (options.timeout > 0) {
clearTimeout(timer);
}
if (response.status >= 200 && response.status < 300) {
return options.binary ? response.blob() : response.text();
}
return result.json();
}).then(function(result) {
if (fetchResponse.status >= 200 && fetchResponse.status < 300) {
callback(null, fetchResponse, result);
} else {
callback(result, fetchResponse);
}
}).catch(function(error) {
callback(error, fetchResponse);
});
return {abort: wrappedPromise.reject};
}
function xhRequest(options, callback) {
var xhr, timer, hasUpload;
var abortReq = function () {
xhr.abort();
};
if (options.xhr) {
xhr = new options.xhr();
} else {
xhr = new XMLHttpRequest();
}
// cache-buster, specifically designed to work around IE's aggressive caching
// see http://www.dashbay.com/2011/05/internet-explorer-caches-ajax/
if (options.method === 'GET' && !options.cache) {
var hasArgs = options.url.indexOf('?') !== -1;
options.url += (hasArgs ? '&' : '?') + '_nonce=' + Date.now();
}
xhr.open(options.method, options.url);
xhr.withCredentials = true;
if (options.method === 'GET') {
delete options.headers['Content-Type'];
} else if (options.json) {
options.headers.Accept = 'application/json';
options.headers['Content-Type'] = options.headers['Content-Type'] ||
'application/json';
if (options.body &&
options.processData &&
typeof options.body !== "string") {
options.body = JSON.stringify(options.body);
}
}
if (options.binary) {
xhr.responseType = 'arraybuffer';
}
if (!('body' in options)) {
options.body = null;
}
for (var key in options.headers) {
if (options.headers.hasOwnProperty(key)) {
xhr.setRequestHeader(key, options.headers[key]);
}
}
if (options.timeout > 0) {
timer = setTimeout(abortReq, options.timeout);
xhr.onprogress = function () {
clearTimeout(timer);
timer = setTimeout(abortReq, options.timeout);
};
if (typeof hasUpload === 'undefined') {
// IE throws an error if you try to access it directly
hasUpload = Object.keys(xhr).indexOf('upload') !== -1 &&
typeof xhr.upload !== 'undefined';
}
if (hasUpload) { // does not exist in ie9
xhr.upload.onprogress = xhr.onprogress;
}
}
xhr.onreadystatechange = function () {
if (xhr.readyState !== 4) {
return;
}
var response = {
statusCode: xhr.status
};
if (xhr.status >= 200 && xhr.status < 300) {
var data;
if (options.binary) {
data = createBlob([xhr.response || ''], {
type: xhr.getResponseHeader('Content-Type')
});
} else {
data = xhr.responseText;
}
callback(null, response, data);
} else {
var err = {};
try {
err = JSON.parse(xhr.response);
} catch(e) {}
callback(err, response);
}
};
if (options.body && (options.body instanceof Blob)) {
utils.readAsBinaryString(options.body, function (binary) {
xhr.send(utils.fixBinary(binary));
});
} else {
xhr.send(options.body);
}
return {abort: abortReq};
}
module.exports = function(options, callback) {
if (typeof XMLHttpRequest === 'undefined' && !options.xhr) {
return fetchRequest(options, callback);
} else {
return xhRequest(options, callback);
}
};
},{"../utils":138,"./blob.js":118}],128:[function(require,module,exports){
'use strict';
var upsert = require('pouchdb-upsert').upsert;
module.exports = function (db, doc, diffFun, cb) {
return upsert.call(db, doc, diffFun, cb);
};
},{"pouchdb-upsert":153}],129:[function(require,module,exports){
module.exports=require(3)
},{}],130:[function(require,module,exports){
'use strict';
module.exports = evalFilter;
function evalFilter(input) {
/*jshint evil: true */
return eval([
'(function () { return ',
input,
' })()'
].join(''));
}
},{}],131:[function(require,module,exports){
'use strict';
module.exports = evalView;
function evalView(input) {
/*jshint evil: true */
return eval([
'(function () {',
' return function (doc) {',
' var emitted = false;',
' var emit = function (a, b) {',
' emitted = true;',
' };',
' var view = ' + input + ';',
' view(doc);',
' if (emitted) {',
' return true;',
' }',
' }',
'})()'
].join('\n'));
}
},{}],132:[function(require,module,exports){
(function (process){
"use strict";
var PouchDB = require('./setup');
module.exports = PouchDB;
PouchDB.ajax = require('./deps/ajax');
PouchDB.utils = require('./utils');
PouchDB.Errors = require('./deps/errors');
PouchDB.replicate = require('./replicate').replicate;
PouchDB.sync = require('./sync');
PouchDB.version = require('./version');
var httpAdapter = require('./adapters/http/http');
PouchDB.adapter('http', httpAdapter);
PouchDB.adapter('https', httpAdapter);
PouchDB.adapter('idb', require('./adapters/idb/idb'), true);
PouchDB.adapter('websql', require('./adapters/websql/websql'), true);
PouchDB.plugin(require('pouchdb-mapreduce'));
if (!process.browser) {
var ldbAdapter = require('./adapters/leveldb/leveldb');
PouchDB.adapter('leveldb', ldbAdapter, true);
}
}).call(this,require("/Users/nlawson/workspace-node/pouchdb-authentication/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js"))
},{"./adapters/http/http":103,"./adapters/idb/idb":109,"./adapters/leveldb/leveldb":41,"./adapters/websql/websql":113,"./deps/ajax":117,"./deps/errors":120,"./replicate":134,"./setup":135,"./sync":136,"./utils":138,"./version":139,"/Users/nlawson/workspace-node/pouchdb-authentication/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js":46,"pouchdb-mapreduce":149}],133:[function(require,module,exports){
'use strict';
var extend = require('pouchdb-extend');
// for a better overview of what this is doing, read:
// https://github.com/apache/couchdb/blob/master/src/couchdb/couch_key_tree.erl
//
// But for a quick intro, CouchDB uses a revision tree to store a documents
// history, A -> B -> C, when a document has conflicts, that is a branch in the
// tree, A -> (B1 | B2 -> C), We store these as a nested array in the format
//
// KeyTree = [Path ... ]
// Path = {pos: position_from_root, ids: Tree}
// Tree = [Key, Opts, [Tree, ...]], in particular single node: [Key, []]
// classic binary search
function binarySearch(arr, item, comparator) {
var low = 0;
var high = arr.length;
var mid;
while (low < high) {
mid = (low + high) >>> 1;
if (comparator(arr[mid], item) < 0) {
low = mid + 1;
} else {
high = mid;
}
}
return low;
}
// assuming the arr is sorted, insert the item in the proper place
function insertSorted(arr, item, comparator) {
var idx = binarySearch(arr, item, comparator);
arr.splice(idx, 0, item);
}
// Turn a path as a flat array into a tree with a single branch
function pathToTree(path) {
var doc = path.shift();
var root = [doc.id, doc.opts, []];
var leaf = root;
var nleaf;
while (path.length) {
doc = path.shift();
nleaf = [doc.id, doc.opts, []];
leaf[2].push(nleaf);
leaf = nleaf;
}
return root;
}
// compare the IDs of two trees
function compareTree(a, b) {
return a[0] < b[0] ? -1 : 1;
}
// Merge two trees together
// The roots of tree1 and tree2 must be the same revision
function mergeTree(in_tree1, in_tree2) {
var queue = [{tree1: in_tree1, tree2: in_tree2}];
var conflicts = false;
while (queue.length > 0) {
var item = queue.pop();
var tree1 = item.tree1;
var tree2 = item.tree2;
if (tree1[1].status || tree2[1].status) {
tree1[1].status =
(tree1[1].status === 'available' ||
tree2[1].status === 'available') ? 'available' : 'missing';
}
for (var i = 0; i < tree2[2].length; i++) {
if (!tree1[2][0]) {
conflicts = 'new_leaf';
tree1[2][0] = tree2[2][i];
continue;
}
var merged = false;
for (var j = 0; j < tree1[2].length; j++) {
if (tree1[2][j][0] === tree2[2][i][0]) {
queue.push({tree1: tree1[2][j], tree2: tree2[2][i]});
merged = true;
}
}
if (!merged) {
conflicts = 'new_branch';
insertSorted(tree1[2], tree2[2][i], compareTree);
}
}
}
return {conflicts: conflicts, tree: in_tree1};
}
function doMerge(tree, path, dontExpand) {
var restree = [];
var conflicts = false;
var merged = false;
var res;
if (!tree.length) {
return {tree: [path], conflicts: 'new_leaf'};
}
tree.forEach(function (branch) {
if (branch.pos === path.pos && branch.ids[0] === path.ids[0]) {
// Paths start at the same position and have the same root, so they need
// merged
res = mergeTree(branch.ids, path.ids);
restree.push({pos: branch.pos, ids: res.tree});
conflicts = conflicts || res.conflicts;
merged = true;
} else if (dontExpand !== true) {
// The paths start at a different position, take the earliest path and
// traverse up until it as at the same point from root as the path we
// want to merge. If the keys match we return the longer path with the
// other merged After stemming we dont want to expand the trees
var t1 = branch.pos < path.pos ? branch : path;
var t2 = branch.pos < path.pos ? path : branch;
var diff = t2.pos - t1.pos;
var candidateParents = [];
var trees = [];
trees.push({ids: t1.ids, diff: diff, parent: null, parentIdx: null});
while (trees.length > 0) {
var item = trees.pop();
if (item.diff === 0) {
if (item.ids[0] === t2.ids[0]) {
candidateParents.push(item);
}
continue;
}
if (!item.ids) {
continue;
}
/*jshint loopfunc:true */
item.ids[2].forEach(function (el, idx) {
trees.push(
{ids: el, diff: item.diff - 1, parent: item.ids, parentIdx: idx});
});
}
var el = candidateParents[0];
if (!el) {
restree.push(branch);
} else {
res = mergeTree(el.ids, t2.ids);
el.parent[2][el.parentIdx] = res.tree;
restree.push({pos: t1.pos, ids: t1.ids});
conflicts = conflicts || res.conflicts;
merged = true;
}
} else {
restree.push(branch);
}
});
// We didnt find
if (!merged) {
restree.push(path);
}
restree.sort(function (a, b) {
return a.pos - b.pos;
});
return {
tree: restree,
conflicts: conflicts || 'internal_node'
};
}
// To ensure we dont grow the revision tree infinitely, we stem old revisions
function stem(tree, depth) {
// First we break out the tree into a complete list of root to leaf paths,
// we cut off the start of the path and generate a new set of flat trees
var stemmedPaths = PouchMerge.rootToLeaf(tree).map(function (path) {
var stemmed = path.ids.slice(-depth);
return {
pos: path.pos + (path.ids.length - stemmed.length),
ids: pathToTree(stemmed)
};
});
// Then we remerge all those flat trees together, ensuring that we dont
// connect trees that would go beyond the depth limit
return stemmedPaths.reduce(function (prev, current) {
return doMerge(prev, current, true).tree;
}, [stemmedPaths.shift()]);
}
var PouchMerge = {};
PouchMerge.merge = function (tree, path, depth) {
// Ugh, nicer way to not modify arguments in place?
tree = extend(true, [], tree);
path = extend(true, {}, path);
var newTree = doMerge(tree, path);
return {
tree: stem(newTree.tree, depth),
conflicts: newTree.conflicts
};
};
// We fetch all leafs of the revision tree, and sort them based on tree length
// and whether they were deleted, undeleted documents with the longest revision
// tree (most edits) win
// The final sort algorithm is slightly documented in a sidebar here:
// http://guide.couchdb.org/draft/conflicts.html
PouchMerge.winningRev = function (metadata) {
var leafs = [];
PouchMerge.traverseRevTree(metadata.rev_tree,
function (isLeaf, pos, id, something, opts) {
if (isLeaf) {
leafs.push({pos: pos, id: id, deleted: !!opts.deleted});
}
});
leafs.sort(function (a, b) {
if (a.deleted !== b.deleted) {
return a.deleted > b.deleted ? 1 : -1;
}
if (a.pos !== b.pos) {
return b.pos - a.pos;
}
return a.id < b.id ? 1 : -1;
});
return leafs[0].pos + '-' + leafs[0].id;
};
// Pretty much all below can be combined into a higher order function to
// traverse revisions
// The return value from the callback will be passed as context to all
// children of that node
PouchMerge.traverseRevTree = function (revs, callback) {
var toVisit = revs.slice();
var node;
while ((node = toVisit.pop())) {
var pos = node.pos;
var tree = node.ids;
var branches = tree[2];
var newCtx =
callback(branches.length === 0, pos, tree[0], node.ctx, tree[1]);
for (var i = 0, len = branches.length; i < len; i++) {
toVisit.push({pos: pos + 1, ids: branches[i], ctx: newCtx});
}
}
};
PouchMerge.collectLeaves = function (revs) {
var leaves = [];
PouchMerge.traverseRevTree(revs, function (isLeaf, pos, id, acc, opts) {
if (isLeaf) {
leaves.push({rev: pos + "-" + id, pos: pos, opts: opts});
}
});
leaves.sort(function (a, b) {
return b.pos - a.pos;
});
leaves.forEach(function (leaf) { delete leaf.pos; });
return leaves;
};
// returns revs of all conflicts that is leaves such that
// 1. are not deleted and
// 2. are different than winning revision
PouchMerge.collectConflicts = function (metadata) {
var win = PouchMerge.winningRev(metadata);
var leaves = PouchMerge.collectLeaves(metadata.rev_tree);
var conflicts = [];
leaves.forEach(function (leaf) {
if (leaf.rev !== win && !leaf.opts.deleted) {
conflicts.push(leaf.rev);
}
});
return conflicts;
};
PouchMerge.rootToLeaf = function (tree) {
var paths = [];
PouchMerge.traverseRevTree(tree, function (isLeaf, pos, id, history, opts) {
history = history ? history.slice(0) : [];
history.push({id: id, opts: opts});
if (isLeaf) {
var rootPos = pos + 1 - history.length;
paths.unshift({pos: rootPos, ids: history});
}
return history;
});
return paths;
};
module.exports = PouchMerge;
},{"pouchdb-extend":99}],134:[function(require,module,exports){
'use strict';
var utils = require('./utils');
var EE = require('events').EventEmitter;
var Checkpointer = require('./checkpointer');
var MAX_SIMULTANEOUS_REVS = 50;
var RETRY_DEFAULT = false;
function randomNumber(min, max) {
min = parseInt(min, 10);
max = parseInt(max, 10);
if (min !== min) {
min = 0;
}
if (max !== max || max <= min) {
max = (min || 1) << 1; //doubling
} else {
max = max + 1;
}
var ratio = Math.random();
var range = max - min;
return ~~(range * ratio + min); // ~~ coerces to an int, but fast.
}
function defaultBackOff(min) {
var max = 0;
if (!min) {
max = 2000;
}
return randomNumber(min, max);
}
function backOff(repId, src, target, opts, returnValue, result, error) {
if (opts.retry === false) {
returnValue.emit('error', error);
returnValue.removeAllListeners();
return;
}
opts.default_back_off = opts.default_back_off || 0;
opts.retries = opts.retries || 0;
if (typeof opts.back_off_function !== 'function') {
opts.back_off_function = defaultBackOff;
}
opts.retries++;
if (opts.max_retries && opts.retries > opts.max_retries) {
returnValue.emit('error', new Error('tried ' +
opts.retries + ' times but replication failed'));
returnValue.removeAllListeners();
return;
}
returnValue.emit('requestError', error);
if (returnValue.state === 'active') {
returnValue.emit('paused', error);
returnValue.state = 'stopped';
returnValue.once('active', function () {
opts.current_back_off = opts.default_back_off;
});
}
opts.current_back_off = opts.current_back_off || opts.default_back_off;
opts.current_back_off = opts.back_off_function(opts.current_back_off);
setTimeout(function () {
replicate(repId, src, target, opts, returnValue);
}, opts.current_back_off);
}
// We create a basic promise so the caller can cancel the replication possibly
// before we have actually started listening to changes etc
utils.inherits(Replication, EE);
function Replication() {
EE.call(this);
this.cancelled = false;
this.state = 'pending';
var self = this;
var promise = new utils.Promise(function (fulfill, reject) {
self.once('complete', fulfill);
self.once('error', reject);
});
self.then = function (resolve, reject) {
return promise.then(resolve, reject);
};
self.catch = function (reject) {
return promise.catch(reject);
};
// As we allow error handling via "error" event as well,
// put a stub in here so that rejecting never throws UnhandledError.
self.catch(function () {});
}
Replication.prototype.cancel = function () {
this.cancelled = true;
this.state = 'cancelled';
this.emit('cancel');
};
Replication.prototype.ready = function (src, target) {
var self = this;
function onDestroy() {
self.cancel();
}
src.once('destroyed', onDestroy);
target.once('destroyed', onDestroy);
function cleanup() {
src.removeListener('destroyed', onDestroy);
target.removeListener('destroyed', onDestroy);
}
this.then(cleanup, cleanup);
};
// TODO: check CouchDB's replication id generation
// Generate a unique id particular to this replication
function genReplicationId(src, target, opts) {
var filterFun = opts.filter ? opts.filter.toString() : '';
return src.id().then(function (src_id) {
return target.id().then(function (target_id) {
var queryData = src_id + target_id + filterFun +
JSON.stringify(opts.query_params) + opts.doc_ids;
return utils.MD5(queryData).then(function (md5) {
// can't use straight-up md5 alphabet, because
// the char '/' is interpreted as being for attachments,
// and + is also not url-safe
md5 = md5.replace(/\//g, '.').replace(/\+/g, '_');
return '_local/' + md5;
});
});
});
}
function replicate(repId, src, target, opts, returnValue, result) {
var batches = []; // list of batches to be processed
var currentBatch; // the batch currently being processed
var pendingBatch = {
seq: 0,
changes: [],
docs: []
}; // next batch, not yet ready to be processed
var writingCheckpoint = false; // true while checkpoint is being written
var changesCompleted = false; // true when all changes received
var replicationCompleted = false; // true when replication has completed
var last_seq = 0;
var continuous = opts.continuous || opts.live || false;
var batch_size = opts.batch_size || 100;
var batches_limit = opts.batches_limit || 10;
var changesPending = false; // true while src.changes is running
var doc_ids = opts.doc_ids;
var state = {
cancelled: false
};
var checkpointer = new Checkpointer(src, target, repId, state);
var allErrors = [];
var changedDocs = [];
result = result || {
ok: true,
start_time: new Date(),
docs_read: 0,
docs_written: 0,
doc_write_failures: 0,
errors: []
};
var changesOpts = {};
returnValue.ready(src, target);
function writeDocs() {
if (currentBatch.docs.length === 0) {
return;
}
var docs = currentBatch.docs;
return target.bulkDocs({docs: docs, new_edits: false}).then(function (res) {
if (state.cancelled) {
completeReplication();
throw new Error('cancelled');
}
var errors = [];
var errorsById = {};
res.forEach(function (res) {
if (res.error) {
result.doc_write_failures++;
errors.push(res);
errorsById[res.id] = res;
}
});
allErrors = allErrors.concat(errors);
result.docs_written += currentBatch.docs.length - errors.length;
var non403s = errors.filter(function (error) {
return error.name !== 'unauthorized' && error.name !== 'forbidden';
});
changedDocs = [];
docs.forEach(function(doc) {
var error = errorsById[doc._id];
if (error) {
returnValue.emit('denied', utils.clone(error));
} else {
changedDocs.push(doc);
}
});
if (non403s.length > 0) {
var error = new Error('bulkDocs error');
error.other_errors = errors;
abortReplication('target.bulkDocs failed to write docs', error);
throw new Error('bulkWrite partial failure');
}
}, function (err) {
result.doc_write_failures += docs.length;
throw err;
});
}
function processDiffDoc(id) {
var diffs = currentBatch.diffs;
var allMissing = diffs[id].missing;
// avoid url too long error by batching
var missingBatches = [];
for (var i = 0; i < allMissing.length; i += MAX_SIMULTANEOUS_REVS) {
missingBatches.push(allMissing.slice(i, Math.min(allMissing.length,
i + MAX_SIMULTANEOUS_REVS)));
}
return utils.Promise.all(missingBatches.map(function (missing) {
var opts = {
revs: true,
open_revs: missing,
attachments: true
};
return src.get(id, opts).then(function (docs) {
docs.forEach(function (doc) {
if (state.cancelled) {
return completeReplication();
}
if (doc.ok) {
result.docs_read++;
currentBatch.pendingRevs++;
currentBatch.docs.push(doc.ok);
}
});
delete diffs[id];
});
}));
}
function getAllDocs() {
var diffKeys = Object.keys(currentBatch.diffs);
return utils.Promise.all(diffKeys.map(processDiffDoc));
}
function getRevisionOneDocs() {
// filter out the generation 1 docs and get them
// leaving the non-generation one docs to be got otherwise
var ids = Object.keys(currentBatch.diffs).filter(function (id) {
var missing = currentBatch.diffs[id].missing;
return missing.length === 1 && missing[0].slice(0, 2) === '1-';
});
if (!ids.length) { // nothing to fetch
return utils.Promise.resolve();
}
return src.allDocs({
keys: ids,
include_docs: true
}).then(function (res) {
if (state.cancelled) {
completeReplication();
throw (new Error('cancelled'));
}
res.rows.forEach(function (row) {
if (row.doc && !row.deleted &&
row.value.rev.slice(0, 2) === '1-' && (
!row.doc._attachments ||
Object.keys(row.doc._attachments).length === 0
)
) {
result.docs_read++;
currentBatch.pendingRevs++;
currentBatch.docs.push(row.doc);
delete currentBatch.diffs[row.id];
}
});
});
}
function getDocs() {
return getRevisionOneDocs().then(getAllDocs);
}
function finishBatch() {
writingCheckpoint = true;
return checkpointer.writeCheckpoint(currentBatch.seq).then(function () {
writingCheckpoint = false;
if (state.cancelled) {
completeReplication();
throw new Error('cancelled');
}
result.last_seq = last_seq = currentBatch.seq;
var outResult = utils.clone(result);
outResult.docs = changedDocs;
returnValue.emit('change', outResult);
currentBatch = undefined;
getChanges();
}).catch(function (err) {
writingCheckpoint = false;
abortReplication('writeCheckpoint completed with error', err);
throw err;
});
}
function getDiffs() {
var diff = {};
currentBatch.changes.forEach(function (change) {
// Couchbase Sync Gateway emits these, but we can ignore them
if (change.id === "_user/") {
return;
}
diff[change.id] = change.changes.map(function (x) {
return x.rev;
});
});
return target.revsDiff(diff).then(function (diffs) {
if (state.cancelled) {
completeReplication();
throw new Error('cancelled');
}
// currentBatch.diffs elements are deleted as the documents are written
currentBatch.diffs = diffs;
currentBatch.pendingRevs = 0;
});
}
function startNextBatch() {
if (state.cancelled || currentBatch) {
return;
}
if (batches.length === 0) {
processPendingBatch(true);
return;
}
currentBatch = batches.shift();
getDiffs()
.then(getDocs)
.then(writeDocs)
.then(finishBatch)
.then(startNextBatch)
.catch(function (err) {
abortReplication('batch processing terminated with error', err);
});
}
function processPendingBatch(immediate) {
if (pendingBatch.changes.length === 0) {
if (batches.length === 0 && !currentBatch) {
if ((continuous && changesOpts.live) || changesCompleted) {
returnValue.state = 'pending';
returnValue.emit('paused');
returnValue.emit('uptodate', result);
}
if (changesCompleted) {
completeReplication();
}
}
return;
}
if (
immediate ||
changesCompleted ||
pendingBatch.changes.length >= batch_size
) {
batches.push(pendingBatch);
pendingBatch = {
seq: 0,
changes: [],
docs: []
};
if (returnValue.state === 'pending' || returnValue.state === 'stopped') {
returnValue.state = 'active';
returnValue.emit('active');
}
startNextBatch();
}
}
function abortReplication(reason, err) {
if (replicationCompleted) {
return;
}
if (!err.message) {
err.message = reason;
}
result.ok = false;
result.status = 'aborting';
result.errors.push(err);
allErrors = allErrors.concat(err);
batches = [];
pendingBatch = {
seq: 0,
changes: [],
docs: []
};
completeReplication();
}
function completeReplication() {
if (replicationCompleted) {
return;
}
if (state.cancelled) {
result.status = 'cancelled';
if (writingCheckpoint) {
return;
}
}
result.status = result.status || 'complete';
result.end_time = new Date();
result.last_seq = last_seq;
replicationCompleted = state.cancelled = true;
var non403s = allErrors.filter(function (error) {
return error.name !== 'unauthorized' && error.name !== 'forbidden';
});
if (non403s.length > 0) {
var error = allErrors.pop();
if (allErrors.length > 0) {
error.other_errors = allErrors;
}
error.result = result;
backOff(repId, src, target, opts, returnValue, result, error);
} else {
result.errors = allErrors;
returnValue.emit('complete', result);
returnValue.removeAllListeners();
}
}
function onChange(change) {
if (state.cancelled) {
return completeReplication();
}
var filter = utils.filterChange(opts)(change);
if (!filter) {
return;
}
if (
pendingBatch.changes.length === 0 &&
batches.length === 0 &&
!currentBatch
) {
returnValue.emit('outofdate', result);
}
pendingBatch.seq = change.seq;
pendingBatch.changes.push(change);
processPendingBatch(batches.length === 0);
}
function onChangesComplete(changes) {
changesPending = false;
if (state.cancelled) {
return completeReplication();
}
// if no results were returned then we're done,
// else fetch more
if (changes.results.length > 0) {
changesOpts.since = changes.last_seq;
getChanges();
} else {
if (continuous) {
changesOpts.live = true;
getChanges();
} else {
changesCompleted = true;
}
}
processPendingBatch(true);
}
function onChangesError(err) {
changesPending = false;
if (state.cancelled) {
return completeReplication();
}
abortReplication('changes rejected', err);
}
function getChanges() {
if (!(
!changesPending &&
!changesCompleted &&
batches.length < batches_limit
)) {
return;
}
changesPending = true;
function abortChanges() {
changes.cancel();
}
function removeListener() {
returnValue.removeListener('cancel', abortChanges);
}
returnValue.once('cancel', abortChanges);
var changes = src.changes(changesOpts)
.on('change', onChange);
changes.then(removeListener, removeListener);
changes.then(onChangesComplete)
.catch(onChangesError);
}
function startChanges() {
checkpointer.getCheckpoint().then(function (checkpoint) {
last_seq = checkpoint;
changesOpts = {
since: last_seq,
limit: batch_size,
batch_size: batch_size,
style: 'all_docs',
doc_ids: doc_ids,
returnDocs: true // required so we know when we're done
};
if (opts.filter) {
if (typeof opts.filter !== 'string') {
// required for the client-side filter in onChange
changesOpts.include_docs = true;
} else { // ddoc filter
changesOpts.filter = opts.filter;
}
}
if (opts.query_params) {
changesOpts.query_params = opts.query_params;
}
if (opts.view) {
changesOpts.view = opts.view;
}
getChanges();
}).catch(function (err) {
abortReplication('getCheckpoint rejected with ', err);
});
}
if (returnValue.cancelled) { // cancelled immediately
completeReplication();
return;
}
returnValue.once('cancel', completeReplication);
if (typeof opts.onChange === 'function') {
returnValue.on('change', opts.onChange);
}
if (typeof opts.complete === 'function') {
returnValue.once('error', opts.complete);
returnValue.once('complete', function (result) {
opts.complete(null, result);
});
}
if (typeof opts.since === 'undefined') {
startChanges();
} else {
writingCheckpoint = true;
checkpointer.writeCheckpoint(opts.since).then(function () {
writingCheckpoint = false;
if (state.cancelled) {
completeReplication();
return;
}
last_seq = opts.since;
startChanges();
}).catch(function (err) {
writingCheckpoint = false;
abortReplication('writeCheckpoint completed with error', err);
throw err;
});
}
}
exports.toPouch = toPouch;
function toPouch(db, opts) {
var PouchConstructor = opts.PouchConstructor;
if (typeof db === 'string') {
return new PouchConstructor(db, opts);
} else if (db.then) {
return db;
} else {
return utils.Promise.resolve(db);
}
}
exports.replicate = replicateWrapper;
function replicateWrapper(src, target, opts, callback) {
if (typeof opts === 'function') {
callback = opts;
opts = {};
}
if (typeof opts === 'undefined') {
opts = {};
}
if (!opts.complete) {
opts.complete = callback || function () {};
}
opts = utils.clone(opts);
opts.continuous = opts.continuous || opts.live;
opts.retry = ('retry' in opts) ? opts.retry : RETRY_DEFAULT;
/*jshint validthis:true */
opts.PouchConstructor = opts.PouchConstructor || this;
var replicateRet = new Replication(opts);
toPouch(src, opts).then(function (src) {
return toPouch(target, opts).then(function (target) {
return genReplicationId(src, target, opts).then(function (repId) {
replicate(repId, src, target, opts, replicateRet);
});
});
}).catch(function (err) {
replicateRet.emit('error', err);
opts.complete(err);
});
return replicateRet;
}
},{"./checkpointer":115,"./utils":138,"events":45}],135:[function(require,module,exports){
"use strict";
var PouchDB = require("./constructor");
var utils = require('./utils');
var EventEmitter = require('events').EventEmitter;
PouchDB.adapters = {};
PouchDB.preferredAdapters = [];
PouchDB.prefix = '_pouch_';
var eventEmitter = new EventEmitter();
var eventEmitterMethods = [
'on',
'addListener',
'emit',
'listeners',
'once',
'removeAllListeners',
'removeListener',
'setMaxListeners'
];
eventEmitterMethods.forEach(function (method) {
PouchDB[method] = eventEmitter[method].bind(eventEmitter);
});
PouchDB.setMaxListeners(0);
PouchDB.parseAdapter = function (name, opts) {
var match = name.match(/([a-z\-]*):\/\/(.*)/);
var adapter, adapterName;
if (match) {
// the http adapter expects the fully qualified name
name = /http(s?)/.test(match[1]) ? match[1] + '://' + match[2] : match[2];
adapter = match[1];
if (!PouchDB.adapters[adapter].valid()) {
throw 'Invalid adapter';
}
return {name: name, adapter: match[1]};
}
// check for browsers that have been upgraded from websql-only to websql+idb
var skipIdb = 'idb' in PouchDB.adapters && 'websql' in PouchDB.adapters &&
utils.hasLocalStorage() &&
localStorage['_pouch__websqldb_' + PouchDB.prefix + name];
if (opts.adapter) {
adapterName = opts.adapter;
} else if (typeof opts !== 'undefined' && opts.db) {
adapterName = 'leveldb';
} else { // automatically determine adapter
for (var i = 0; i < PouchDB.preferredAdapters.length; ++i) {
adapterName = PouchDB.preferredAdapters[i];
if (adapterName in PouchDB.adapters) {
if (skipIdb && adapterName === 'idb') {
// log it, because this can be confusing during development
console.log('PouchDB is downgrading "' + name + '" to WebSQL to' +
' avoid data loss, because it was already opened with WebSQL.');
continue; // keep using websql to avoid user data loss
}
break;
}
}
}
adapter = PouchDB.adapters[adapterName];
// if adapter is invalid, then an error will be thrown later
var usePrefix = (adapter && 'use_prefix' in adapter) ?
adapter.use_prefix : true;
return {
name: usePrefix ? (PouchDB.prefix + name) : name,
adapter: adapterName
};
};
PouchDB.destroy = utils.toPromise(function (name, opts, callback) {
console.log('PouchDB.destroy() is deprecated and will be removed. ' +
'Please use db.destroy() instead.');
if (typeof opts === 'function' || typeof opts === 'undefined') {
callback = opts;
opts = {};
}
if (name && typeof name === 'object') {
opts = name;
name = undefined;
}
new PouchDB(name, opts, function (err, db) {
if (err) {
return callback(err);
}
db.destroy(callback);
});
});
PouchDB.adapter = function (id, obj, addToPreferredAdapters) {
if (obj.valid()) {
PouchDB.adapters[id] = obj;
if (addToPreferredAdapters) {
PouchDB.preferredAdapters.push(id);
}
}
};
PouchDB.plugin = function (obj) {
Object.keys(obj).forEach(function (id) {
PouchDB.prototype[id] = obj[id];
});
};
PouchDB.defaults = function (defaultOpts) {
function PouchAlt(name, opts, callback) {
if (typeof opts === 'function' || typeof opts === 'undefined') {
callback = opts;
opts = {};
}
if (name && typeof name === 'object') {
opts = name;
name = undefined;
}
opts = utils.extend(true, {}, defaultOpts, opts);
PouchDB.call(this, name, opts, callback);
}
utils.inherits(PouchAlt, PouchDB);
PouchAlt.destroy = utils.toPromise(function (name, opts, callback) {
if (typeof opts === 'function' || typeof opts === 'undefined') {
callback = opts;
opts = {};
}
if (name && typeof name === 'object') {
opts = name;
name = undefined;
}
opts = utils.extend(true, {}, defaultOpts, opts);
return PouchDB.destroy(name, opts, callback);
});
eventEmitterMethods.forEach(function (method) {
PouchAlt[method] = eventEmitter[method].bind(eventEmitter);
});
PouchAlt.setMaxListeners(0);
PouchAlt.preferredAdapters = PouchDB.preferredAdapters.slice();
Object.keys(PouchDB).forEach(function (key) {
if (!(key in PouchAlt)) {
PouchAlt[key] = PouchDB[key];
}
});
return PouchAlt;
};
module.exports = PouchDB;
},{"./constructor":116,"./utils":138,"events":45}],136:[function(require,module,exports){
'use strict';
var utils = require('./utils');
var replication = require('./replicate');
var replicate = replication.replicate;
var EE = require('events').EventEmitter;
utils.inherits(Sync, EE);
module.exports = sync;
function sync(src, target, opts, callback) {
if (typeof opts === 'function') {
callback = opts;
opts = {};
}
if (typeof opts === 'undefined') {
opts = {};
}
opts = utils.clone(opts);
/*jshint validthis:true */
opts.PouchConstructor = opts.PouchConstructor || this;
src = replication.toPouch(src, opts);
target = replication.toPouch(target, opts);
return new Sync(src, target, opts, callback);
}
function Sync(src, target, opts, callback) {
var self = this;
this.canceled = false;
var onChange, complete;
if ('onChange' in opts) {
onChange = opts.onChange;
delete opts.onChange;
}
if (typeof callback === 'function' && !opts.complete) {
complete = callback;
} else if ('complete' in opts) {
complete = opts.complete;
delete opts.complete;
}
this.push = replicate(src, target, opts);
this.pull = replicate(target, src, opts);
var emittedCancel = false;
function onCancel(data) {
if (!emittedCancel) {
emittedCancel = true;
self.emit('cancel', data);
}
}
function pullChange(change) {
self.emit('change', {
direction: 'pull',
change: change
});
}
function pushChange(change) {
self.emit('change', {
direction: 'push',
change: change
});
}
function pushDenied(doc) {
self.emit('denied', {
direction: 'push',
doc: doc
});
}
function pullDenied(doc) {
self.emit('denied', {
direction: 'pull',
doc: doc
});
}
var listeners = {};
var removed = {};
function removeAll(type) { // type is 'push' or 'pull'
return function (event, func) {
var isChange = event === 'change' &&
(func === pullChange || func === pushChange);
var isCancel = event === 'cancel' && func === onCancel;
var isOtherEvent = event in listeners && func === listeners[event];
if (isChange || isCancel || isOtherEvent) {
if (!(event in removed)) {
removed[event] = {};
}
removed[event][type] = true;
if (Object.keys(removed[event]).length === 2) {
// both push and pull have asked to be removed
self.removeAllListeners(event);
}
}
};
}
if (opts.live) {
this.push.on('complete', self.pull.cancel.bind(self.pull));
this.pull.on('complete', self.push.cancel.bind(self.push));
}
this.on('newListener', function (event) {
if (event === 'change') {
self.pull.on('change', pullChange);
self.push.on('change', pushChange);
} else if (event === 'denied') {
self.pull.on('denied', pullDenied);
self.push.on('denied', pushDenied);
} else if (event === 'cancel') {
self.pull.on('cancel', onCancel);
self.push.on('cancel', onCancel);
} else if (event !== 'error' &&
event !== 'removeListener' &&
event !== 'complete' && !(event in listeners)) {
listeners[event] = function (e) {
self.emit(event, e);
};
self.pull.on(event, listeners[event]);
self.push.on(event, listeners[event]);
}
});
this.on('removeListener', function (event) {
if (event === 'change') {
self.pull.removeListener('change', pullChange);
self.push.removeListener('change', pushChange);
} else if (event === 'cancel') {
self.pull.removeListener('cancel', onCancel);
self.push.removeListener('cancel', onCancel);
} else if (event in listeners) {
if (typeof listeners[event] === 'function') {
self.pull.removeListener(event, listeners[event]);
self.push.removeListener(event, listeners[event]);
delete listeners[event];
}
}
});
this.pull.on('removeListener', removeAll('pull'));
this.push.on('removeListener', removeAll('push'));
var promise = utils.Promise.all([
this.push,
this.pull
]).then(function (resp) {
var out = {
push: resp[0],
pull: resp[1]
};
self.emit('complete', out);
if (complete) {
complete(null, out);
}
self.removeAllListeners();
return out;
}, function (err) {
self.cancel();
self.emit('error', err);
if (complete) {
complete(err);
}
self.removeAllListeners();
throw err;
});
this.then = function (success, err) {
return promise.then(success, err);
};
this.catch = function (err) {
return promise.catch(err);
};
}
Sync.prototype.cancel = function () {
if (!this.canceled) {
this.canceled = true;
this.push.cancel();
this.pull.cancel();
}
};
},{"./replicate":134,"./utils":138,"events":45}],137:[function(require,module,exports){
'use strict';
module.exports = TaskQueue;
function TaskQueue() {
this.isReady = false;
this.failed = false;
this.queue = [];
}
TaskQueue.prototype.execute = function () {
var d, func;
if (this.failed) {
while ((d = this.queue.shift())) {
if (typeof d === 'function') {
d(this.failed);
continue;
}
func = d.parameters[d.parameters.length - 1];
if (typeof func === 'function') {
func(this.failed);
} else if (d.name === 'changes' && typeof func.complete === 'function') {
func.complete(this.failed);
}
}
} else if (this.isReady) {
while ((d = this.queue.shift())) {
if (typeof d === 'function') {
d();
} else {
d.task = this.db[d.name].apply(this.db, d.parameters);
}
}
}
};
TaskQueue.prototype.fail = function (err) {
this.failed = err;
this.execute();
};
TaskQueue.prototype.ready = function (db) {
if (this.failed) {
return false;
} else if (arguments.length === 0) {
return this.isReady;
}
this.isReady = db ? true: false;
this.db = db;
this.execute();
};
TaskQueue.prototype.addTask = function (name, parameters) {
if (typeof name === 'function') {
this.queue.push(name);
if (this.failed) {
this.execute();
}
} else {
var task = { name: name, parameters: parameters };
this.queue.push(task);
if (this.failed) {
this.execute();
}
return task;
}
};
},{}],138:[function(require,module,exports){
(function (process){
/*jshint strict: false */
/*global chrome */
var merge = require('./merge');
exports.extend = require('pouchdb-extend');
exports.ajax = require('./deps/ajax');
exports.createBlob = require('./deps/blob');
exports.uuid = require('./deps/uuid');
exports.getArguments = require('argsarray');
var buffer = require('./deps/buffer');
var errors = require('./deps/errors');
var EventEmitter = require('events').EventEmitter;
var collections = require('pouchdb-collections');
exports.Map = collections.Map;
exports.Set = collections.Set;
var parseDoc = require('./deps/parse-doc');
var Promise = require('./deps/promise');
exports.Promise = Promise;
exports.lastIndexOf = function (str, char) {
for (var i = str.length - 1; i >= 0; i--) {
if (str.charAt(i) === char) {
return i;
}
}
return -1;
};
exports.clone = function (obj) {
return exports.extend(true, {}, obj);
};
// like underscore/lodash _.pick()
exports.pick = function (obj, arr) {
var res = {};
for (var i = 0, len = arr.length; i < len; i++) {
var prop = arr[i];
res[prop] = obj[prop];
}
return res;
};
exports.inherits = require('inherits');
function isChromeApp() {
return (typeof chrome !== "undefined" &&
typeof chrome.storage !== "undefined" &&
typeof chrome.storage.local !== "undefined");
}
// Pretty dumb name for a function, just wraps callback calls so we dont
// to if (callback) callback() everywhere
exports.call = exports.getArguments(function (args) {
if (!args.length) {
return;
}
var fun = args.shift();
if (typeof fun === 'function') {
fun.apply(this, args);
}
});
exports.isLocalId = function (id) {
return (/^_local/).test(id);
};
// check if a specific revision of a doc has been deleted
// - metadata: the metadata object from the doc store
// - rev: (optional) the revision to check. defaults to winning revision
exports.isDeleted = function (metadata, rev) {
if (!rev) {
rev = merge.winningRev(metadata);
}
var dashIndex = rev.indexOf('-');
if (dashIndex !== -1) {
rev = rev.substring(dashIndex + 1);
}
var deleted = false;
merge.traverseRevTree(metadata.rev_tree,
function (isLeaf, pos, id, acc, opts) {
if (id === rev) {
deleted = !!opts.deleted;
}
});
return deleted;
};
exports.revExists = function (metadata, rev) {
var found = false;
merge.traverseRevTree(metadata.rev_tree, function (leaf, pos, id) {
if ((pos + '-' + id) === rev) {
found = true;
}
});
return found;
};
exports.filterChange = function filterChange(opts) {
var req = {};
var hasFilter = opts.filter && typeof opts.filter === 'function';
req.query = opts.query_params;
return function filter(change) {
if (!change.doc) {
// CSG sends events on the changes feed that don't have documents,
// this hack makes a whole lot of existing code robust.
change.doc = {};
}
if (opts.filter && hasFilter && !opts.filter.call(this, change.doc, req)) {
return false;
}
if (!opts.include_docs) {
delete change.doc;
} else if (!opts.attachments) {
for (var att in change.doc._attachments) {
if (change.doc._attachments.hasOwnProperty(att)) {
change.doc._attachments[att].stub = true;
}
}
}
return true;
};
};
exports.parseDoc = parseDoc.parseDoc;
exports.invalidIdError = parseDoc.invalidIdError;
exports.isCordova = function () {
return (typeof cordova !== "undefined" ||
typeof PhoneGap !== "undefined" ||
typeof phonegap !== "undefined");
};
exports.hasLocalStorage = function () {
if (isChromeApp()) {
return false;
}
try {
return localStorage;
} catch (e) {
return false;
}
};
exports.Changes = Changes;
exports.inherits(Changes, EventEmitter);
function Changes() {
if (!(this instanceof Changes)) {
return new Changes();
}
var self = this;
EventEmitter.call(this);
this.isChrome = isChromeApp();
this.listeners = {};
this.hasLocal = false;
if (!this.isChrome) {
this.hasLocal = exports.hasLocalStorage();
}
if (this.isChrome) {
chrome.storage.onChanged.addListener(function (e) {
// make sure it's event addressed to us
if (e.db_name != null) {
//object only has oldValue, newValue members
self.emit(e.dbName.newValue);
}
});
} else if (this.hasLocal) {
if (typeof addEventListener !== 'undefined') {
addEventListener("storage", function (e) {
self.emit(e.key);
});
} else { // old IE
window.attachEvent("storage", function (e) {
self.emit(e.key);
});
}
}
}
Changes.prototype.addListener = function (dbName, id, db, opts) {
if (this.listeners[id]) {
return;
}
var self = this;
var inprogress = false;
function eventFunction() {
if (!self.listeners[id]) {
return;
}
if (inprogress) {
inprogress = 'waiting';
return;
}
inprogress = true;
db.changes({
style: opts.style,
include_docs: opts.include_docs,
attachments: opts.attachments,
conflicts: opts.conflicts,
continuous: false,
descending: false,
filter: opts.filter,
doc_ids: opts.doc_ids,
view: opts.view,
since: opts.since,
query_params: opts.query_params
}).on('change', function (c) {
if (c.seq > opts.since && !opts.cancelled) {
opts.since = c.seq;
exports.call(opts.onChange, c);
}
}).on('complete', function () {
if (inprogress === 'waiting') {
process.nextTick(function () {
self.notify(dbName);
});
}
inprogress = false;
}).on('error', function () {
inprogress = false;
});
}
this.listeners[id] = eventFunction;
this.on(dbName, eventFunction);
};
Changes.prototype.removeListener = function (dbName, id) {
if (!(id in this.listeners)) {
return;
}
EventEmitter.prototype.removeListener.call(this, dbName,
this.listeners[id]);
};
Changes.prototype.notifyLocalWindows = function (dbName) {
//do a useless change on a storage thing
//in order to get other windows's listeners to activate
if (this.isChrome) {
chrome.storage.local.set({dbName: dbName});
} else if (this.hasLocal) {
localStorage[dbName] = (localStorage[dbName] === "a") ? "b" : "a";
}
};
Changes.prototype.notify = function (dbName) {
this.emit(dbName);
this.notifyLocalWindows(dbName);
};
if (typeof atob === 'function') {
exports.atob = function (str) {
return atob(str);
};
} else {
exports.atob = function (str) {
var base64 = new buffer(str, 'base64');
// Node.js will just skip the characters it can't encode instead of
// throwing and exception
if (base64.toString('base64') !== str) {
throw ("Cannot base64 encode full string");
}
return base64.toString('binary');
};
}
if (typeof btoa === 'function') {
exports.btoa = function (str) {
return btoa(str);
};
} else {
exports.btoa = function (str) {
return new buffer(str, 'binary').toString('base64');
};
}
// From http://stackoverflow.com/questions/14967647/ (continues on next line)
// encode-decode-image-with-base64-breaks-image (2013-04-21)
exports.fixBinary = function (bin) {
if (!process.browser) {
// don't need to do this in Node
return bin;
}
var length = bin.length;
var buf = new ArrayBuffer(length);
var arr = new Uint8Array(buf);
for (var i = 0; i < length; i++) {
arr[i] = bin.charCodeAt(i);
}
return buf;
};
// shim for browsers that don't support it
exports.readAsBinaryString = function (blob, callback) {
var reader = new FileReader();
var hasBinaryString = typeof reader.readAsBinaryString === 'function';
reader.onloadend = function (e) {
var result = e.target.result || '';
if (hasBinaryString) {
return callback(result);
}
callback(exports.arrayBufferToBinaryString(result));
};
if (hasBinaryString) {
reader.readAsBinaryString(blob);
} else {
reader.readAsArrayBuffer(blob);
}
};
// simplified API. universal browser support is assumed
exports.readAsArrayBuffer = function (blob, callback) {
var reader = new FileReader();
reader.onloadend = function (e) {
var result = e.target.result || new ArrayBuffer(0);
callback(result);
};
reader.readAsArrayBuffer(blob);
};
exports.once = function (fun) {
var called = false;
return exports.getArguments(function (args) {
if (called) {
throw new Error('once called more than once');
} else {
called = true;
fun.apply(this, args);
}
});
};
exports.toPromise = function (func) {
//create the function we will be returning
return exports.getArguments(function (args) {
var self = this;
var tempCB =
(typeof args[args.length - 1] === 'function') ? args.pop() : false;
// if the last argument is a function, assume its a callback
var usedCB;
if (tempCB) {
// if it was a callback, create a new callback which calls it,
// but do so async so we don't trap any errors
usedCB = function (err, resp) {
process.nextTick(function () {
tempCB(err, resp);
});
};
}
var promise = new Promise(function (fulfill, reject) {
var resp;
try {
var callback = exports.once(function (err, mesg) {
if (err) {
reject(err);
} else {
fulfill(mesg);
}
});
// create a callback for this invocation
// apply the function in the orig context
args.push(callback);
resp = func.apply(self, args);
if (resp && typeof resp.then === 'function') {
fulfill(resp);
}
} catch (e) {
reject(e);
}
});
// if there is a callback, call it back
if (usedCB) {
promise.then(function (result) {
usedCB(null, result);
}, usedCB);
}
promise.cancel = function () {
return this;
};
return promise;
});
};
exports.adapterFun = function (name, callback) {
var log = require('debug')('pouchdb:api');
function logApiCall(self, name, args) {
if (!log.enabled) {
return;
}
var logArgs = [self._db_name, name];
for (var i = 0; i < args.length - 1; i++) {
logArgs.push(args[i]);
}
log.apply(null, logArgs);
// override the callback itself to log the response
var origCallback = args[args.length - 1];
args[args.length - 1] = function (err, res) {
var responseArgs = [self._db_name, name];
responseArgs = responseArgs.concat(
err ? ['error', err] : ['success', res]
);
log.apply(null, responseArgs);
origCallback(err, res);
};
}
return exports.toPromise(exports.getArguments(function (args) {
if (this._closed) {
return Promise.reject(new Error('database is closed'));
}
var self = this;
logApiCall(self, name, args);
if (!this.taskqueue.isReady) {
return new Promise(function (fulfill, reject) {
self.taskqueue.addTask(function (failed) {
if (failed) {
reject(failed);
} else {
fulfill(self[name].apply(self, args));
}
});
});
}
return callback.apply(this, args);
}));
};
//Can't find original post, but this is close
//http://stackoverflow.com/questions/6965107/ (continues on next line)
//converting-between-strings-and-arraybuffers
exports.arrayBufferToBinaryString = function (buffer) {
var binary = "";
var bytes = new Uint8Array(buffer);
var length = bytes.byteLength;
for (var i = 0; i < length; i++) {
binary += String.fromCharCode(bytes[i]);
}
return binary;
};
exports.cancellableFun = function (fun, self, opts) {
opts = opts ? exports.clone(true, {}, opts) : {};
var emitter = new EventEmitter();
var oldComplete = opts.complete || function () { };
var complete = opts.complete = exports.once(function (err, resp) {
if (err) {
oldComplete(err);
} else {
emitter.emit('end', resp);
oldComplete(null, resp);
}
emitter.removeAllListeners();
});
var oldOnChange = opts.onChange || function () {};
var lastChange = 0;
self.on('destroyed', function () {
emitter.removeAllListeners();
});
opts.onChange = function (change) {
oldOnChange(change);
if (change.seq <= lastChange) {
return;
}
lastChange = change.seq;
emitter.emit('change', change);
if (change.deleted) {
emitter.emit('delete', change);
} else if (change.changes.length === 1 &&
change.changes[0].rev.slice(0, 1) === '1-') {
emitter.emit('create', change);
} else {
emitter.emit('update', change);
}
};
var promise = new Promise(function (fulfill, reject) {
opts.complete = function (err, res) {
if (err) {
reject(err);
} else {
fulfill(res);
}
};
});
promise.then(function (result) {
complete(null, result);
}, complete);
// this needs to be overwridden by caller, dont fire complete until
// the task is ready
promise.cancel = function () {
promise.isCancelled = true;
if (self.taskqueue.isReady) {
opts.complete(null, {status: 'cancelled'});
}
};
if (!self.taskqueue.isReady) {
self.taskqueue.addTask(function () {
if (promise.isCancelled) {
opts.complete(null, {status: 'cancelled'});
} else {
fun(self, opts, promise);
}
});
} else {
fun(self, opts, promise);
}
promise.on = emitter.on.bind(emitter);
promise.once = emitter.once.bind(emitter);
promise.addListener = emitter.addListener.bind(emitter);
promise.removeListener = emitter.removeListener.bind(emitter);
promise.removeAllListeners = emitter.removeAllListeners.bind(emitter);
promise.setMaxListeners = emitter.setMaxListeners.bind(emitter);
promise.listeners = emitter.listeners.bind(emitter);
promise.emit = emitter.emit.bind(emitter);
return promise;
};
exports.MD5 = exports.toPromise(require('./deps/md5'));
exports.explain404 = require('./deps/explain404');
exports.info = function (str) {
if (typeof console !== 'undefined' && 'info' in console) {
console.info(str);
}
};
exports.parseUri = require('./deps/parse-uri');
exports.compare = function (left, right) {
return left < right ? -1 : left > right ? 1 : 0;
};
exports.updateDoc = function updateDoc(prev, docInfo, results,
i, cb, writeDoc, newEdits) {
if (exports.revExists(prev, docInfo.metadata.rev)) {
results[i] = docInfo;
return cb();
}
// TODO: some of these can be pre-calculated, but it's safer to just
// call merge.winningRev() and exports.isDeleted() all over again
var previousWinningRev = merge.winningRev(prev);
var previouslyDeleted = exports.isDeleted(prev, previousWinningRev);
var deleted = exports.isDeleted(docInfo.metadata);
var isRoot = /^1-/.test(docInfo.metadata.rev);
if (previouslyDeleted && !deleted && newEdits && isRoot) {
var newDoc = docInfo.data;
newDoc._rev = previousWinningRev;
newDoc._id = docInfo.metadata.id;
docInfo = exports.parseDoc(newDoc, newEdits);
}
var merged = merge.merge(prev.rev_tree, docInfo.metadata.rev_tree[0], 1000);
var inConflict = newEdits && (((previouslyDeleted && deleted) ||
(!previouslyDeleted && merged.conflicts !== 'new_leaf') ||
(previouslyDeleted && !deleted && merged.conflicts === 'new_branch')));
if (inConflict) {
var err = errors.error(errors.REV_CONFLICT);
results[i] = err;
return cb();
}
var newRev = docInfo.metadata.rev;
docInfo.metadata.rev_tree = merged.tree;
if (prev.rev_map) {
docInfo.metadata.rev_map = prev.rev_map; // used by leveldb
}
// recalculate
var winningRev = merge.winningRev(docInfo.metadata);
var winningRevIsDeleted = exports.isDeleted(docInfo.metadata, winningRev);
// calculate the total number of documents that were added/removed,
// from the perspective of total_rows/doc_count
var delta = (previouslyDeleted === winningRevIsDeleted) ? 0 :
previouslyDeleted < winningRevIsDeleted ? -1 : 1;
var newRevIsDeleted = exports.isDeleted(docInfo.metadata, newRev);
writeDoc(docInfo, winningRev, winningRevIsDeleted, newRevIsDeleted,
true, delta, i, cb);
};
exports.processDocs = function processDocs(docInfos, api, fetchedDocs,
tx, results, writeDoc, opts,
overallCallback) {
if (!docInfos.length) {
return;
}
function insertDoc(docInfo, resultsIdx, callback) {
// Cant insert new deleted documents
var winningRev = merge.winningRev(docInfo.metadata);
var deleted = exports.isDeleted(docInfo.metadata, winningRev);
if ('was_delete' in opts && deleted) {
results[resultsIdx] = errors.error(errors.MISSING_DOC, 'deleted');
return callback();
}
var delta = deleted ? 0 : 1;
writeDoc(docInfo, winningRev, deleted, deleted, false,
delta, resultsIdx, callback);
}
var newEdits = opts.new_edits;
var idsToDocs = new exports.Map();
var docsDone = 0;
var docsToDo = docInfos.length;
function checkAllDocsDone() {
if (++docsDone === docsToDo && overallCallback) {
overallCallback();
}
}
docInfos.forEach(function (currentDoc, resultsIdx) {
if (currentDoc._id && exports.isLocalId(currentDoc._id)) {
api[currentDoc._deleted ? '_removeLocal' : '_putLocal'](
currentDoc, {ctx: tx}, function (err) {
if (err) {
results[resultsIdx] = err;
} else {
results[resultsIdx] = {ok: true};
}
checkAllDocsDone();
});
return;
}
var id = currentDoc.metadata.id;
if (idsToDocs.has(id)) {
docsToDo--; // duplicate
idsToDocs.get(id).push([currentDoc, resultsIdx]);
} else {
idsToDocs.set(id, [[currentDoc, resultsIdx]]);
}
});
// in the case of new_edits, the user can provide multiple docs
// with the same id. these need to be processed sequentially
idsToDocs.forEach(function (docs, id) {
var numDone = 0;
function docWritten() {
if (++numDone < docs.length) {
nextDoc();
} else {
checkAllDocsDone();
}
}
function nextDoc() {
var value = docs[numDone];
var currentDoc = value[0];
var resultsIdx = value[1];
if (fetchedDocs.has(id)) {
exports.updateDoc(fetchedDocs.get(id), currentDoc, results,
resultsIdx, docWritten, writeDoc, newEdits);
} else {
insertDoc(currentDoc, resultsIdx, docWritten);
}
}
nextDoc();
});
};
exports.preprocessAttachments = function preprocessAttachments(
docInfos, blobType, callback) {
if (!docInfos.length) {
return callback();
}
var docv = 0;
function parseBase64(data) {
try {
return exports.atob(data);
} catch (e) {
var err = errors.error(errors.BAD_ARG,
'Attachments need to be base64 encoded');
return {error: err};
}
}
function preprocessAttachment(att, callback) {
if (att.stub) {
return callback();
}
if (typeof att.data === 'string') {
// input is a base64 string
var asBinary = parseBase64(att.data);
if (asBinary.error) {
return callback(asBinary.error);
}
att.length = asBinary.length;
if (blobType === 'blob') {
att.data = exports.createBlob([exports.fixBinary(asBinary)],
{type: att.content_type});
} else if (blobType === 'base64') {
att.data = exports.btoa(asBinary);
} else { // binary
att.data = asBinary;
}
exports.MD5(asBinary).then(function (result) {
att.digest = 'md5-' + result;
callback();
});
} else { // input is a blob
exports.readAsArrayBuffer(att.data, function (buff) {
if (blobType === 'binary') {
att.data = exports.arrayBufferToBinaryString(buff);
} else if (blobType === 'base64') {
att.data = exports.btoa(exports.arrayBufferToBinaryString(buff));
}
exports.MD5(buff).then(function (result) {
att.digest = 'md5-' + result;
att.length = buff.byteLength;
callback();
});
});
}
}
var overallErr;
docInfos.forEach(function (docInfo) {
var attachments = docInfo.data && docInfo.data._attachments ?
Object.keys(docInfo.data._attachments) : [];
var recv = 0;
if (!attachments.length) {
return done();
}
function processedAttachment(err) {
overallErr = err;
recv++;
if (recv === attachments.length) {
done();
}
}
for (var key in docInfo.data._attachments) {
if (docInfo.data._attachments.hasOwnProperty(key)) {
preprocessAttachment(docInfo.data._attachments[key],
processedAttachment);
}
}
});
function done() {
docv++;
if (docInfos.length === docv) {
if (overallErr) {
callback(overallErr);
} else {
callback();
}
}
}
};
// compact a tree by marking its non-leafs as missing,
// and return a list of revs to delete
exports.compactTree = function compactTree(metadata) {
var revs = [];
merge.traverseRevTree(metadata.rev_tree, function (isLeaf, pos,
revHash, ctx, opts) {
if (opts.status === 'available' && !isLeaf) {
revs.push(pos + '-' + revHash);
opts.status = 'missing';
}
});
return revs;
};
var vuvuzela = require('vuvuzela');
exports.safeJsonParse = function safeJsonParse(str) {
try {
return JSON.parse(str);
} catch (e) {
return vuvuzela.parse(str);
}
};
exports.safeJsonStringify = function safeJsonStringify(json) {
try {
return JSON.stringify(json);
} catch (e) {
return vuvuzela.stringify(json);
}
};
}).call(this,require("/Users/nlawson/workspace-node/pouchdb-authentication/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js"))
},{"./deps/ajax":117,"./deps/blob":118,"./deps/buffer":119,"./deps/errors":120,"./deps/explain404":121,"./deps/md5":122,"./deps/parse-doc":123,"./deps/parse-uri":125,"./deps/promise":126,"./deps/uuid":129,"./merge":133,"/Users/nlawson/workspace-node/pouchdb-authentication/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js":46,"argsarray":140,"debug":141,"events":45,"inherits":79,"pouchdb-collections":146,"pouchdb-extend":99,"vuvuzela":155}],139:[function(require,module,exports){
module.exports = "3.5.0";
},{}],140:[function(require,module,exports){
'use strict';
module.exports = argsArray;
function argsArray(fun) {
return function () {
var len = arguments.length;
if (len) {
var args = [];
var i = -1;
while (++i < len) {
args[i] = arguments[i];
}
return fun.call(this, args);
} else {
return fun.call(this, []);
}
};
}
},{}],141:[function(require,module,exports){
/**
* This is the web browser implementation of `debug()`.
*
* Expose `debug()` as the module.
*/
exports = module.exports = require('./debug');
exports.log = log;
exports.formatArgs = formatArgs;
exports.save = save;
exports.load = load;
exports.useColors = useColors;
exports.storage = 'undefined' != typeof chrome
&& 'undefined' != typeof chrome.storage
? chrome.storage.local
: localstorage();
/**
* Colors.
*/
exports.colors = [
'lightseagreen',
'forestgreen',
'goldenrod',
'dodgerblue',
'darkorchid',
'crimson'
];
/**
* Currently only WebKit-based Web Inspectors, Firefox >= v31,
* and the Firebug extension (any Firefox version) are known
* to support "%c" CSS customizations.
*
* TODO: add a `localStorage` variable to explicitly enable/disable colors
*/
function useColors() {
// is webkit? http://stackoverflow.com/a/16459606/376773
return ('WebkitAppearance' in document.documentElement.style) ||
// is firebug? http://stackoverflow.com/a/398120/376773
(window.console && (console.firebug || (console.exception && console.table))) ||
// is firefox >= v31?
// https://developer.mozilla.org/en-US/docs/Tools/Web_Console#Styling_messages
(navigator.userAgent.toLowerCase().match(/firefox\/(\d+)/) && parseInt(RegExp.$1, 10) >= 31);
}
/**
* Map %j to `JSON.stringify()`, since no Web Inspectors do that by default.
*/
exports.formatters.j = function(v) {
return JSON.stringify(v);
};
/**
* Colorize log arguments if enabled.
*
* @api public
*/
function formatArgs() {
var args = arguments;
var useColors = this.useColors;
args[0] = (useColors ? '%c' : '')
+ this.namespace
+ (useColors ? ' %c' : ' ')
+ args[0]
+ (useColors ? '%c ' : ' ')
+ '+' + exports.humanize(this.diff);
if (!useColors) return args;
var c = 'color: ' + this.color;
args = [args[0], c, 'color: inherit'].concat(Array.prototype.slice.call(args, 1));
// the final "%c" is somewhat tricky, because there could be other
// arguments passed either before or after the %c, so we need to
// figure out the correct index to insert the CSS into
var index = 0;
var lastC = 0;
args[0].replace(/%[a-z%]/g, function(match) {
if ('%%' === match) return;
index++;
if ('%c' === match) {
// we only are interested in the *last* %c
// (the user may have provided their own)
lastC = index;
}
});
args.splice(lastC, 0, c);
return args;
}
/**
* Invokes `console.log()` when available.
* No-op when `console.log` is not a "function".
*
* @api public
*/
function log() {
// this hackery is required for IE8/9, where
// the `console.log` function doesn't have 'apply'
return 'object' === typeof console
&& console.log
&& Function.prototype.apply.call(console.log, console, arguments);
}
/**
* Save `namespaces`.
*
* @param {String} namespaces
* @api private
*/
function save(namespaces) {
try {
if (null == namespaces) {
exports.storage.removeItem('debug');
} else {
exports.storage.debug = namespaces;
}
} catch(e) {}
}
/**
* Load `namespaces`.
*
* @return {String} returns the previously persisted debug modes
* @api private
*/
function load() {
var r;
try {
r = exports.storage.debug;
} catch(e) {}
return r;
}
/**
* Enable namespaces listed in `localStorage.debug` initially.
*/
exports.enable(load());
/**
* Localstorage attempts to return the localstorage.
*
* This is necessary because safari throws
* when a user disables cookies/localstorage
* and you attempt to access it.
*
* @return {LocalStorage}
* @api private
*/
function localstorage(){
try {
return window.localStorage;
} catch (e) {}
}
},{"./debug":142}],142:[function(require,module,exports){
/**
* This is the common logic for both the Node.js and web browser
* implementations of `debug()`.
*
* Expose `debug()` as the module.
*/
exports = module.exports = debug;
exports.coerce = coerce;
exports.disable = disable;
exports.enable = enable;
exports.enabled = enabled;
exports.humanize = require('ms');
/**
* The currently active debug mode names, and names to skip.
*/
exports.names = [];
exports.skips = [];
/**
* Map of special "%n" handling functions, for the debug "format" argument.
*
* Valid key names are a single, lowercased letter, i.e. "n".
*/
exports.formatters = {};
/**
* Previously assigned color.
*/
var prevColor = 0;
/**
* Previous log timestamp.
*/
var prevTime;
/**
* Select a color.
*
* @return {Number}
* @api private
*/
function selectColor() {
return exports.colors[prevColor++ % exports.colors.length];
}
/**
* Create a debugger with the given `namespace`.
*
* @param {String} namespace
* @return {Function}
* @api public
*/
function debug(namespace) {
// define the `disabled` version
function disabled() {
}
disabled.enabled = false;
// define the `enabled` version
function enabled() {
var self = enabled;
// set `diff` timestamp
var curr = +new Date();
var ms = curr - (prevTime || curr);
self.diff = ms;
self.prev = prevTime;
self.curr = curr;
prevTime = curr;
// add the `color` if not set
if (null == self.useColors) self.useColors = exports.useColors();
if (null == self.color && self.useColors) self.color = selectColor();
var args = Array.prototype.slice.call(arguments);
args[0] = exports.coerce(args[0]);
if ('string' !== typeof args[0]) {
// anything else let's inspect with %o
args = ['%o'].concat(args);
}
// apply any `formatters` transformations
var index = 0;
args[0] = args[0].replace(/%([a-z%])/g, function(match, format) {
// if we encounter an escaped % then don't increase the array index
if (match === '%%') return match;
index++;
var formatter = exports.formatters[format];
if ('function' === typeof formatter) {
var val = args[index];
match = formatter.call(self, val);
// now we need to remove `args[index]` since it's inlined in the `format`
args.splice(index, 1);
index--;
}
return match;
});
if ('function' === typeof exports.formatArgs) {
args = exports.formatArgs.apply(self, args);
}
var logFn = enabled.log || exports.log || console.log.bind(console);
logFn.apply(self, args);
}
enabled.enabled = true;
var fn = exports.enabled(namespace) ? enabled : disabled;
fn.namespace = namespace;
return fn;
}
/**
* Enables a debug mode by namespaces. This can include modes
* separated by a colon and wildcards.
*
* @param {String} namespaces
* @api public
*/
function enable(namespaces) {
exports.save(namespaces);
var split = (namespaces || '').split(/[\s,]+/);
var len = split.length;
for (var i = 0; i < len; i++) {
if (!split[i]) continue; // ignore empty strings
namespaces = split[i].replace(/\*/g, '.*?');
if (namespaces[0] === '-') {
exports.skips.push(new RegExp('^' + namespaces.substr(1) + '$'));
} else {
exports.names.push(new RegExp('^' + namespaces + '$'));
}
}
}
/**
* Disable debug output.
*
* @api public
*/
function disable() {
exports.enable('');
}
/**
* Returns true if the given mode name is enabled, false otherwise.
*
* @param {String} name
* @return {Boolean}
* @api public
*/
function enabled(name) {
var i, len;
for (i = 0, len = exports.skips.length; i < len; i++) {
if (exports.skips[i].test(name)) {
return false;
}
}
for (i = 0, len = exports.names.length; i < len; i++) {
if (exports.names[i].test(name)) {
return true;
}
}
return false;
}
/**
* Coerce `val`.
*
* @param {Mixed} val
* @return {Mixed}
* @api private
*/
function coerce(val) {
if (val instanceof Error) return val.stack || val.message;
return val;
}
},{"ms":143}],143:[function(require,module,exports){
/**
* Helpers.
*/
var s = 1000;
var m = s * 60;
var h = m * 60;
var d = h * 24;
var y = d * 365.25;
/**
* Parse or format the given `val`.
*
* Options:
*
* - `long` verbose formatting [false]
*
* @param {String|Number} val
* @param {Object} options
* @return {String|Number}
* @api public
*/
module.exports = function(val, options){
options = options || {};
if ('string' == typeof val) return parse(val);
return options.long
? long(val)
: short(val);
};
/**
* Parse the given `str` and return milliseconds.
*
* @param {String} str
* @return {Number}
* @api private
*/
function parse(str) {
str = '' + str;
if (str.length > 10000) return;
var match = /^((?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|years?|yrs?|y)?$/i.exec(str);
if (!match) return;
var n = parseFloat(match[1]);
var type = (match[2] || 'ms').toLowerCase();
switch (type) {
case 'years':
case 'year':
case 'yrs':
case 'yr':
case 'y':
return n * y;
case 'days':
case 'day':
case 'd':
return n * d;
case 'hours':
case 'hour':
case 'hrs':
case 'hr':
case 'h':
return n * h;
case 'minutes':
case 'minute':
case 'mins':
case 'min':
case 'm':
return n * m;
case 'seconds':
case 'second':
case 'secs':
case 'sec':
case 's':
return n * s;
case 'milliseconds':
case 'millisecond':
case 'msecs':
case 'msec':
case 'ms':
return n;
}
}
/**
* Short format for `ms`.
*
* @param {Number} ms
* @return {String}
* @api private
*/
function short(ms) {
if (ms >= d) return Math.round(ms / d) + 'd';
if (ms >= h) return Math.round(ms / h) + 'h';
if (ms >= m) return Math.round(ms / m) + 'm';
if (ms >= s) return Math.round(ms / s) + 's';
return ms + 'ms';
}
/**
* Long format for `ms`.
*
* @param {Number} ms
* @return {String}
* @api private
*/
function long(ms) {
return plural(ms, d, 'day')
|| plural(ms, h, 'hour')
|| plural(ms, m, 'minute')
|| plural(ms, s, 'second')
|| ms + ' ms';
}
/**
* Pluralization helper.
*/
function plural(ms, n, name) {
if (ms < n) return;
if (ms < n * 1.5) return Math.floor(ms / n) + ' ' + name;
return Math.ceil(ms / n) + ' ' + name + 's';
}
},{}],144:[function(require,module,exports){
'use strict';
var MIN_MAGNITUDE = -324; // verified by -Number.MIN_VALUE
var MAGNITUDE_DIGITS = 3; // ditto
var SEP = ''; // set to '_' for easier debugging
var utils = require('./utils');
exports.collate = function (a, b) {
if (a === b) {
return 0;
}
a = exports.normalizeKey(a);
b = exports.normalizeKey(b);
var ai = collationIndex(a);
var bi = collationIndex(b);
if ((ai - bi) !== 0) {
return ai - bi;
}
if (a === null) {
return 0;
}
switch (typeof a) {
case 'number':
return a - b;
case 'boolean':
return a === b ? 0 : (a < b ? -1 : 1);
case 'string':
return stringCollate(a, b);
}
return Array.isArray(a) ? arrayCollate(a, b) : objectCollate(a, b);
};
// couch considers null/NaN/Infinity/-Infinity === undefined,
// for the purposes of mapreduce indexes. also, dates get stringified.
exports.normalizeKey = function (key) {
switch (typeof key) {
case 'undefined':
return null;
case 'number':
if (key === Infinity || key === -Infinity || isNaN(key)) {
return null;
}
return key;
case 'object':
var origKey = key;
if (Array.isArray(key)) {
var len = key.length;
key = new Array(len);
for (var i = 0; i < len; i++) {
key[i] = exports.normalizeKey(origKey[i]);
}
} else if (key instanceof Date) {
return key.toJSON();
} else if (key !== null) { // generic object
key = {};
for (var k in origKey) {
if (origKey.hasOwnProperty(k)) {
var val = origKey[k];
if (typeof val !== 'undefined') {
key[k] = exports.normalizeKey(val);
}
}
}
}
}
return key;
};
function indexify(key) {
if (key !== null) {
switch (typeof key) {
case 'boolean':
return key ? 1 : 0;
case 'number':
return numToIndexableString(key);
case 'string':
// We've to be sure that key does not contain \u0000
// Do order-preserving replacements:
// 0 -> 1, 1
// 1 -> 1, 2
// 2 -> 2, 2
return key
.replace(/\u0002/g, '\u0002\u0002')
.replace(/\u0001/g, '\u0001\u0002')
.replace(/\u0000/g, '\u0001\u0001');
case 'object':
var isArray = Array.isArray(key);
var arr = isArray ? key : Object.keys(key);
var i = -1;
var len = arr.length;
var result = '';
if (isArray) {
while (++i < len) {
result += exports.toIndexableString(arr[i]);
}
} else {
while (++i < len) {
var objKey = arr[i];
result += exports.toIndexableString(objKey) +
exports.toIndexableString(key[objKey]);
}
}
return result;
}
}
return '';
}
// convert the given key to a string that would be appropriate
// for lexical sorting, e.g. within a database, where the
// sorting is the same given by the collate() function.
exports.toIndexableString = function (key) {
var zero = '\u0000';
key = exports.normalizeKey(key);
return collationIndex(key) + SEP + indexify(key) + zero;
};
function parseNumber(str, i) {
var originalIdx = i;
var num;
var zero = str[i] === '1';
if (zero) {
num = 0;
i++;
} else {
var neg = str[i] === '0';
i++;
var numAsString = '';
var magAsString = str.substring(i, i + MAGNITUDE_DIGITS);
var magnitude = parseInt(magAsString, 10) + MIN_MAGNITUDE;
if (neg) {
magnitude = -magnitude;
}
i += MAGNITUDE_DIGITS;
while (true) {
var ch = str[i];
if (ch === '\u0000') {
break;
} else {
numAsString += ch;
}
i++;
}
numAsString = numAsString.split('.');
if (numAsString.length === 1) {
num = parseInt(numAsString, 10);
} else {
num = parseFloat(numAsString[0] + '.' + numAsString[1]);
}
if (neg) {
num = num - 10;
}
if (magnitude !== 0) {
// parseFloat is more reliable than pow due to rounding errors
// e.g. Number.MAX_VALUE would return Infinity if we did
// num * Math.pow(10, magnitude);
num = parseFloat(num + 'e' + magnitude);
}
}
return {num: num, length : i - originalIdx};
}
// move up the stack while parsing
// this function moved outside of parseIndexableString for performance
function pop(stack, metaStack) {
var obj = stack.pop();
if (metaStack.length) {
var lastMetaElement = metaStack[metaStack.length - 1];
if (obj === lastMetaElement.element) {
// popping a meta-element, e.g. an object whose value is another object
metaStack.pop();
lastMetaElement = metaStack[metaStack.length - 1];
}
var element = lastMetaElement.element;
var lastElementIndex = lastMetaElement.index;
if (Array.isArray(element)) {
element.push(obj);
} else if (lastElementIndex === stack.length - 2) { // obj with key+value
var key = stack.pop();
element[key] = obj;
} else {
stack.push(obj); // obj with key only
}
}
}
exports.parseIndexableString = function (str) {
var stack = [];
var metaStack = []; // stack for arrays and objects
var i = 0;
while (true) {
var collationIndex = str[i++];
if (collationIndex === '\u0000') {
if (stack.length === 1) {
return stack.pop();
} else {
pop(stack, metaStack);
continue;
}
}
switch (collationIndex) {
case '1':
stack.push(null);
break;
case '2':
stack.push(str[i] === '1');
i++;
break;
case '3':
var parsedNum = parseNumber(str, i);
stack.push(parsedNum.num);
i += parsedNum.length;
break;
case '4':
var parsedStr = '';
while (true) {
var ch = str[i];
if (ch === '\u0000') {
break;
}
parsedStr += ch;
i++;
}
// perform the reverse of the order-preserving replacement
// algorithm (see above)
parsedStr = parsedStr.replace(/\u0001\u0001/g, '\u0000')
.replace(/\u0001\u0002/g, '\u0001')
.replace(/\u0002\u0002/g, '\u0002');
stack.push(parsedStr);
break;
case '5':
var arrayElement = { element: [], index: stack.length };
stack.push(arrayElement.element);
metaStack.push(arrayElement);
break;
case '6':
var objElement = { element: {}, index: stack.length };
stack.push(objElement.element);
metaStack.push(objElement);
break;
default:
throw new Error(
'bad collationIndex or unexpectedly reached end of input: ' + collationIndex);
}
}
};
function arrayCollate(a, b) {
var len = Math.min(a.length, b.length);
for (var i = 0; i < len; i++) {
var sort = exports.collate(a[i], b[i]);
if (sort !== 0) {
return sort;
}
}
return (a.length === b.length) ? 0 :
(a.length > b.length) ? 1 : -1;
}
function stringCollate(a, b) {
// See: https://github.com/daleharvey/pouchdb/issues/40
// This is incompatible with the CouchDB implementation, but its the
// best we can do for now
return (a === b) ? 0 : ((a > b) ? 1 : -1);
}
function objectCollate(a, b) {
var ak = Object.keys(a), bk = Object.keys(b);
var len = Math.min(ak.length, bk.length);
for (var i = 0; i < len; i++) {
// First sort the keys
var sort = exports.collate(ak[i], bk[i]);
if (sort !== 0) {
return sort;
}
// if the keys are equal sort the values
sort = exports.collate(a[ak[i]], b[bk[i]]);
if (sort !== 0) {
return sort;
}
}
return (ak.length === bk.length) ? 0 :
(ak.length > bk.length) ? 1 : -1;
}
// The collation is defined by erlangs ordered terms
// the atoms null, true, false come first, then numbers, strings,
// arrays, then objects
// null/undefined/NaN/Infinity/-Infinity are all considered null
function collationIndex(x) {
var id = ['boolean', 'number', 'string', 'object'];
var idx = id.indexOf(typeof x);
//false if -1 otherwise true, but fast!!!!1
if (~idx) {
if (x === null) {
return 1;
}
if (Array.isArray(x)) {
return 5;
}
return idx < 3 ? (idx + 2) : (idx + 3);
}
if (Array.isArray(x)) {
return 5;
}
}
// conversion:
// x yyy zz...zz
// x = 0 for negative, 1 for 0, 2 for positive
// y = exponent (for negative numbers negated) moved so that it's >= 0
// z = mantisse
function numToIndexableString(num) {
if (num === 0) {
return '1';
}
// convert number to exponential format for easier and
// more succinct string sorting
var expFormat = num.toExponential().split(/e\+?/);
var magnitude = parseInt(expFormat[1], 10);
var neg = num < 0;
var result = neg ? '0' : '2';
// first sort by magnitude
// it's easier if all magnitudes are positive
var magForComparison = ((neg ? -magnitude : magnitude) - MIN_MAGNITUDE);
var magString = utils.padLeft((magForComparison).toString(), '0', MAGNITUDE_DIGITS);
result += SEP + magString;
// then sort by the factor
var factor = Math.abs(parseFloat(expFormat[0])); // [1..10)
if (neg) { // for negative reverse ordering
factor = 10 - factor;
}
var factorStr = factor.toFixed(20);
// strip zeros from the end
factorStr = factorStr.replace(/\.?0+$/, '');
result += SEP + factorStr;
return result;
}
},{"./utils":145}],145:[function(require,module,exports){
'use strict';
function pad(str, padWith, upToLength) {
var padding = '';
var targetLength = upToLength - str.length;
while (padding.length < targetLength) {
padding += padWith;
}
return padding;
}
exports.padLeft = function (str, padWith, upToLength) {
var padding = pad(str, padWith, upToLength);
return padding + str;
};
exports.padRight = function (str, padWith, upToLength) {
var padding = pad(str, padWith, upToLength);
return str + padding;
};
exports.stringLexCompare = function (a, b) {
var aLen = a.length;
var bLen = b.length;
var i;
for (i = 0; i < aLen; i++) {
if (i === bLen) {
// b is shorter substring of a
return 1;
}
var aChar = a.charAt(i);
var bChar = b.charAt(i);
if (aChar !== bChar) {
return aChar < bChar ? -1 : 1;
}
}
if (aLen < bLen) {
// a is shorter substring of b
return -1;
}
return 0;
};
/*
* returns the decimal form for the given integer, i.e. writes
* out all the digits (in base-10) instead of using scientific notation
*/
exports.intToDecimalForm = function (int) {
var isNeg = int < 0;
var result = '';
do {
var remainder = isNeg ? -Math.ceil(int % 10) : Math.floor(int % 10);
result = remainder + result;
int = isNeg ? Math.ceil(int / 10) : Math.floor(int / 10);
} while (int);
if (isNeg && result !== '0') {
result = '-' + result;
}
return result;
};
},{}],146:[function(require,module,exports){
'use strict';
exports.Map = LazyMap; // TODO: use ES6 map
exports.Set = LazySet; // TODO: use ES6 set
// based on https://github.com/montagejs/collections
function LazyMap() {
this.store = {};
}
LazyMap.prototype.mangle = function (key) {
if (typeof key !== "string") {
throw new TypeError("key must be a string but Got " + key);
}
return '$' + key;
};
LazyMap.prototype.unmangle = function (key) {
return key.substring(1);
};
LazyMap.prototype.get = function (key) {
var mangled = this.mangle(key);
if (mangled in this.store) {
return this.store[mangled];
} else {
return void 0;
}
};
LazyMap.prototype.set = function (key, value) {
var mangled = this.mangle(key);
this.store[mangled] = value;
return true;
};
LazyMap.prototype.has = function (key) {
var mangled = this.mangle(key);
return mangled in this.store;
};
LazyMap.prototype.delete = function (key) {
var mangled = this.mangle(key);
if (mangled in this.store) {
delete this.store[mangled];
return true;
}
return false;
};
LazyMap.prototype.forEach = function (cb) {
var self = this;
var keys = Object.keys(self.store);
keys.forEach(function (key) {
var value = self.store[key];
key = self.unmangle(key);
cb(value, key);
});
};
function LazySet(array) {
this.store = new LazyMap();
// init with an array
if (array && Array.isArray(array)) {
for (var i = 0, len = array.length; i < len; i++) {
this.add(array[i]);
}
}
}
LazySet.prototype.add = function (key) {
return this.store.set(key, true);
};
LazySet.prototype.has = function (key) {
return this.store.has(key);
};
LazySet.prototype.delete = function (key) {
return this.store.delete(key);
};
},{}],147:[function(require,module,exports){
'use strict';
var upsert = require('./upsert');
var utils = require('./utils');
var Promise = utils.Promise;
module.exports = function (opts) {
var sourceDB = opts.db;
var viewName = opts.viewName;
var mapFun = opts.map;
var reduceFun = opts.reduce;
var temporary = opts.temporary;
// the "undefined" part is for backwards compatibility
var viewSignature = mapFun.toString() + (reduceFun && reduceFun.toString()) +
'undefined';
if (!temporary && sourceDB._cachedViews) {
var cachedView = sourceDB._cachedViews[viewSignature];
if (cachedView) {
return Promise.resolve(cachedView);
}
}
return sourceDB.info().then(function (info) {
var depDbName = info.db_name + '-mrview-' +
(temporary ? 'temp' : utils.MD5(viewSignature));
// save the view name in the source PouchDB so it can be cleaned up if necessary
// (e.g. when the _design doc is deleted, remove all associated view data)
function diffFunction(doc) {
doc.views = doc.views || {};
var fullViewName = viewName;
if (fullViewName.indexOf('/') === -1) {
fullViewName = viewName + '/' + viewName;
}
var depDbs = doc.views[fullViewName] = doc.views[fullViewName] || {};
/* istanbul ignore if */
if (depDbs[depDbName]) {
return; // no update necessary
}
depDbs[depDbName] = true;
return doc;
}
return upsert(sourceDB, '_local/mrviews', diffFunction).then(function () {
return sourceDB.registerDependentDatabase(depDbName).then(function (res) {
var db = res.db;
db.auto_compaction = true;
var view = {
name: depDbName,
db: db,
sourceDB: sourceDB,
adapter: sourceDB.adapter,
mapFun: mapFun,
reduceFun: reduceFun
};
return view.db.get('_local/lastSeq')["catch"](function (err) {
/* istanbul ignore if */
if (err.status !== 404) {
throw err;
}
}).then(function (lastSeqDoc) {
view.seq = lastSeqDoc ? lastSeqDoc.seq : 0;
if (!temporary) {
sourceDB._cachedViews = sourceDB._cachedViews || {};
sourceDB._cachedViews[viewSignature] = view;
view.db.on('destroyed', function () {
delete sourceDB._cachedViews[viewSignature];
});
}
return view;
});
});
});
});
};
},{"./upsert":151,"./utils":152}],148:[function(require,module,exports){
'use strict';
module.exports = function (func, emit, sum, log, isArray, toJSON) {
/*jshint evil:true,unused:false */
return eval("'use strict'; (" + func.replace(/;\s*$/, "") + ");");
};
},{}],149:[function(require,module,exports){
(function (process){
'use strict';
var pouchCollate = require('pouchdb-collate');
var TaskQueue = require('./taskqueue');
var collate = pouchCollate.collate;
var toIndexableString = pouchCollate.toIndexableString;
var normalizeKey = pouchCollate.normalizeKey;
var createView = require('./create-view');
var evalFunc = require('./evalfunc');
var log;
/* istanbul ignore else */
if ((typeof console !== 'undefined') && (typeof console.log === 'function')) {
log = Function.prototype.bind.call(console.log, console);
} else {
log = function () {};
}
var utils = require('./utils');
var Promise = utils.Promise;
var persistentQueues = {};
var tempViewQueue = new TaskQueue();
var CHANGES_BATCH_SIZE = 50;
function parseViewName(name) {
// can be either 'ddocname/viewname' or just 'viewname'
// (where the ddoc name is the same)
return name.indexOf('/') === -1 ? [name, name] : name.split('/');
}
function isGenOne(changes) {
// only return true if the current change is 1-
// and there are no other leafs
return changes.length === 1 && /^1-/.test(changes[0].rev);
}
function emitError(db, e) {
try {
db.emit('error', e);
} catch (err) {
console.error(
'The user\'s map/reduce function threw an uncaught error.\n' +
'You can debug this error by doing:\n' +
'myDatabase.on(\'error\', function (err) { debugger; });\n' +
'Please double-check your map/reduce function.');
console.error(e);
}
}
function tryCode(db, fun, args) {
// emit an event if there was an error thrown by a map/reduce function.
// putting try/catches in a single function also avoids deoptimizations.
try {
return {
output : fun.apply(null, args)
};
} catch (e) {
emitError(db, e);
return {error: e};
}
}
function sortByKeyThenValue(x, y) {
var keyCompare = collate(x.key, y.key);
return keyCompare !== 0 ? keyCompare : collate(x.value, y.value);
}
function sliceResults(results, limit, skip) {
skip = skip || 0;
if (typeof limit === 'number') {
return results.slice(skip, limit + skip);
} else if (skip > 0) {
return results.slice(skip);
}
return results;
}
function rowToDocId(row) {
var val = row.value;
// Users can explicitly specify a joined doc _id, or it
// defaults to the doc _id that emitted the key/value.
var docId = (val && typeof val === 'object' && val._id) || row.id;
return docId;
}
function createBuiltInError(name) {
var message = 'builtin ' + name +
' function requires map values to be numbers' +
' or number arrays';
return new BuiltInError(message);
}
function sum(values) {
var result = 0;
for (var i = 0, len = values.length; i < len; i++) {
var num = values[i];
if (typeof num !== 'number') {
if (Array.isArray(num)) {
// lists of numbers are also allowed, sum them separately
result = typeof result === 'number' ? [result] : result;
for (var j = 0, jLen = num.length; j < jLen; j++) {
var jNum = num[j];
if (typeof jNum !== 'number') {
throw createBuiltInError('_sum');
} else if (typeof result[j] === 'undefined') {
result.push(jNum);
} else {
result[j] += jNum;
}
}
} else { // not array/number
throw createBuiltInError('_sum');
}
} else if (typeof result === 'number') {
result += num;
} else { // add number to array
result[0] += num;
}
}
return result;
}
var builtInReduce = {
_sum: function (keys, values) {
return sum(values);
},
_count: function (keys, values) {
return values.length;
},
_stats: function (keys, values) {
// no need to implement rereduce=true, because Pouch
// will never call it
function sumsqr(values) {
var _sumsqr = 0;
for (var i = 0, len = values.length; i < len; i++) {
var num = values[i];
_sumsqr += (num * num);
}
return _sumsqr;
}
return {
sum : sum(values),
min : Math.min.apply(null, values),
max : Math.max.apply(null, values),
count : values.length,
sumsqr : sumsqr(values)
};
}
};
function addHttpParam(paramName, opts, params, asJson) {
// add an http param from opts to params, optionally json-encoded
var val = opts[paramName];
if (typeof val !== 'undefined') {
if (asJson) {
val = encodeURIComponent(JSON.stringify(val));
}
params.push(paramName + '=' + val);
}
}
function checkQueryParseError(options, fun) {
var startkeyName = options.descending ? 'endkey' : 'startkey';
var endkeyName = options.descending ? 'startkey' : 'endkey';
if (typeof options[startkeyName] !== 'undefined' &&
typeof options[endkeyName] !== 'undefined' &&
collate(options[startkeyName], options[endkeyName]) > 0) {
throw new QueryParseError('No rows can match your key range, reverse your ' +
'start_key and end_key or set {descending : true}');
} else if (fun.reduce && options.reduce !== false) {
if (options.include_docs) {
throw new QueryParseError('{include_docs:true} is invalid for reduce');
} else if (options.keys && options.keys.length > 1 &&
!options.group && !options.group_level) {
throw new QueryParseError('Multi-key fetches for reduce views must use {group: true}');
}
}
if (options.group_level) {
if (typeof options.group_level !== 'number') {
throw new QueryParseError('Invalid value for integer: "' + options.group_level + '"');
}
if (options.group_level < 0) {
throw new QueryParseError('Invalid value for positive integer: ' +
'"' + options.group_level + '"');
}
}
}
function httpQuery(db, fun, opts) {
// List of parameters to add to the PUT request
var params = [];
var body;
var method = 'GET';
// If opts.reduce exists and is defined, then add it to the list
// of parameters.
// If reduce=false then the results are that of only the map function
// not the final result of map and reduce.
addHttpParam('reduce', opts, params);
addHttpParam('include_docs', opts, params);
addHttpParam('attachments', opts, params);
addHttpParam('limit', opts, params);
addHttpParam('descending', opts, params);
addHttpParam('group', opts, params);
addHttpParam('group_level', opts, params);
addHttpParam('skip', opts, params);
addHttpParam('stale', opts, params);
addHttpParam('conflicts', opts, params);
addHttpParam('startkey', opts, params, true);
addHttpParam('endkey', opts, params, true);
addHttpParam('inclusive_end', opts, params);
addHttpParam('key', opts, params, true);
// Format the list of parameters into a valid URI query string
params = params.join('&');
params = params === '' ? '' : '?' + params;
// If keys are supplied, issue a POST request to circumvent GET query string limits
// see http://wiki.apache.org/couchdb/HTTP_view_API#Querying_Options
if (typeof opts.keys !== 'undefined') {
var MAX_URL_LENGTH = 2000;
// according to http://stackoverflow.com/a/417184/680742,
// the de facto URL length limit is 2000 characters
var keysAsString =
'keys=' + encodeURIComponent(JSON.stringify(opts.keys));
if (keysAsString.length + params.length + 1 <= MAX_URL_LENGTH) {
// If the keys are short enough, do a GET. we do this to work around
// Safari not understanding 304s on POSTs (see pouchdb/pouchdb#1239)
params += (params[0] === '?' ? '&' : '?') + keysAsString;
} else {
method = 'POST';
if (typeof fun === 'string') {
body = JSON.stringify({keys: opts.keys});
} else { // fun is {map : mapfun}, so append to this
fun.keys = opts.keys;
}
}
}
// We are referencing a query defined in the design doc
if (typeof fun === 'string') {
var parts = parseViewName(fun);
return db.request({
method: method,
url: '_design/' + parts[0] + '/_view/' + parts[1] + params,
body: body
});
}
// We are using a temporary view, terrible for performance but good for testing
body = body || {};
Object.keys(fun).forEach(function (key) {
if (Array.isArray(fun[key])) {
body[key] = fun[key];
} else {
body[key] = fun[key].toString();
}
});
return db.request({
method: 'POST',
url: '_temp_view' + params,
body: body
});
}
function defaultsTo(value) {
return function (reason) {
/* istanbul ignore else */
if (reason.status === 404) {
return value;
} else {
throw reason;
}
};
}
// returns a promise for a list of docs to update, based on the input docId.
// the order doesn't matter, because post-3.2.0, bulkDocs
// is an atomic operation in all three adapters.
function getDocsToPersist(docId, view, docIdsToChangesAndEmits) {
var metaDocId = '_local/doc_' + docId;
var defaultMetaDoc = {_id: metaDocId, keys: []};
var docData = docIdsToChangesAndEmits[docId];
var indexableKeysToKeyValues = docData.indexableKeysToKeyValues;
var changes = docData.changes;
function getMetaDoc() {
if (isGenOne(changes)) {
// generation 1, so we can safely assume initial state
// for performance reasons (avoids unnecessary GETs)
return Promise.resolve(defaultMetaDoc);
}
return view.db.get(metaDocId)["catch"](defaultsTo(defaultMetaDoc));
}
function getKeyValueDocs(metaDoc) {
if (!metaDoc.keys.length) {
// no keys, no need for a lookup
return Promise.resolve({rows: []});
}
return view.db.allDocs({
keys: metaDoc.keys,
include_docs: true
});
}
function processKvDocs(metaDoc, kvDocsRes) {
var kvDocs = [];
var oldKeysMap = {};
for (var i = 0, len = kvDocsRes.rows.length; i < len; i++) {
var row = kvDocsRes.rows[i];
var doc = row.doc;
if (!doc) { // deleted
continue;
}
kvDocs.push(doc);
oldKeysMap[doc._id] = true;
doc._deleted = !indexableKeysToKeyValues[doc._id];
if (!doc._deleted) {
var keyValue = indexableKeysToKeyValues[doc._id];
if ('value' in keyValue) {
doc.value = keyValue.value;
}
}
}
var newKeys = Object.keys(indexableKeysToKeyValues);
newKeys.forEach(function (key) {
if (!oldKeysMap[key]) {
// new doc
var kvDoc = {
_id: key
};
var keyValue = indexableKeysToKeyValues[key];
if ('value' in keyValue) {
kvDoc.value = keyValue.value;
}
kvDocs.push(kvDoc);
}
});
metaDoc.keys = utils.uniq(newKeys.concat(metaDoc.keys));
kvDocs.push(metaDoc);
return kvDocs;
}
return getMetaDoc().then(function (metaDoc) {
return getKeyValueDocs(metaDoc).then(function (kvDocsRes) {
return processKvDocs(metaDoc, kvDocsRes);
});
});
}
// updates all emitted key/value docs and metaDocs in the mrview database
// for the given batch of documents from the source database
function saveKeyValues(view, docIdsToChangesAndEmits, seq) {
var seqDocId = '_local/lastSeq';
return view.db.get(seqDocId)[
"catch"](defaultsTo({_id: seqDocId, seq: 0}))
.then(function (lastSeqDoc) {
var docIds = Object.keys(docIdsToChangesAndEmits);
return Promise.all(docIds.map(function (docId) {
return getDocsToPersist(docId, view, docIdsToChangesAndEmits);
})).then(function (listOfDocsToPersist) {
var docsToPersist = utils.flatten(listOfDocsToPersist);
lastSeqDoc.seq = seq;
docsToPersist.push(lastSeqDoc);
// write all docs in a single operation, update the seq once
return view.db.bulkDocs({docs : docsToPersist});
});
});
}
function getQueue(view) {
var viewName = typeof view === 'string' ? view : view.name;
var queue = persistentQueues[viewName];
if (!queue) {
queue = persistentQueues[viewName] = new TaskQueue();
}
return queue;
}
function updateView(view) {
return utils.sequentialize(getQueue(view), function () {
return updateViewInQueue(view);
})();
}
function updateViewInQueue(view) {
// bind the emit function once
var mapResults;
var doc;
function emit(key, value) {
var output = {id: doc._id, key: normalizeKey(key)};
// Don't explicitly store the value unless it's defined and non-null.
// This saves on storage space, because often people don't use it.
if (typeof value !== 'undefined' && value !== null) {
output.value = normalizeKey(value);
}
mapResults.push(output);
}
var mapFun;
// for temp_views one can use emit(doc, emit), see #38
if (typeof view.mapFun === "function" && view.mapFun.length === 2) {
var origMap = view.mapFun;
mapFun = function (doc) {
return origMap(doc, emit);
};
} else {
mapFun = evalFunc(view.mapFun.toString(), emit, sum, log, Array.isArray, JSON.parse);
}
var currentSeq = view.seq || 0;
function processChange(docIdsToChangesAndEmits, seq) {
return function () {
return saveKeyValues(view, docIdsToChangesAndEmits, seq);
};
}
var queue = new TaskQueue();
// TODO(neojski): https://github.com/daleharvey/pouchdb/issues/1521
return new Promise(function (resolve, reject) {
function complete() {
queue.finish().then(function () {
view.seq = currentSeq;
resolve();
});
}
function processNextBatch() {
view.sourceDB.changes({
conflicts: true,
include_docs: true,
style: 'all_docs',
since: currentSeq,
limit: CHANGES_BATCH_SIZE
}).on('complete', function (response) {
var results = response.results;
if (!results.length) {
return complete();
}
var docIdsToChangesAndEmits = {};
for (var i = 0, l = results.length; i < l; i++) {
var change = results[i];
if (change.doc._id[0] !== '_') {
mapResults = [];
doc = change.doc;
if (!doc._deleted) {
tryCode(view.sourceDB, mapFun, [doc]);
}
mapResults.sort(sortByKeyThenValue);
var indexableKeysToKeyValues = {};
var lastKey;
for (var j = 0, jl = mapResults.length; j < jl; j++) {
var obj = mapResults[j];
var complexKey = [obj.key, obj.id];
if (collate(obj.key, lastKey) === 0) {
complexKey.push(j); // dup key+id, so make it unique
}
var indexableKey = toIndexableString(complexKey);
indexableKeysToKeyValues[indexableKey] = obj;
lastKey = obj.key;
}
docIdsToChangesAndEmits[change.doc._id] = {
indexableKeysToKeyValues: indexableKeysToKeyValues,
changes: change.changes
};
}
currentSeq = change.seq;
}
queue.add(processChange(docIdsToChangesAndEmits, currentSeq));
if (results.length < CHANGES_BATCH_SIZE) {
return complete();
}
return processNextBatch();
}).on('error', onError);
/* istanbul ignore next */
function onError(err) {
reject(err);
}
}
processNextBatch();
});
}
function reduceView(view, results, options) {
if (options.group_level === 0) {
delete options.group_level;
}
var shouldGroup = options.group || options.group_level;
var reduceFun;
if (builtInReduce[view.reduceFun]) {
reduceFun = builtInReduce[view.reduceFun];
} else {
reduceFun = evalFunc(
view.reduceFun.toString(), null, sum, log, Array.isArray, JSON.parse);
}
var groups = [];
var lvl = options.group_level;
results.forEach(function (e) {
var last = groups[groups.length - 1];
var key = shouldGroup ? e.key : null;
// only set group_level for array keys
if (shouldGroup && Array.isArray(key) && typeof lvl === 'number') {
key = key.length > lvl ? key.slice(0, lvl) : key;
}
if (last && collate(last.key[0][0], key) === 0) {
last.key.push([key, e.id]);
last.value.push(e.value);
return;
}
groups.push({key: [
[key, e.id]
], value: [e.value]});
});
for (var i = 0, len = groups.length; i < len; i++) {
var e = groups[i];
var reduceTry = tryCode(view.sourceDB, reduceFun, [e.key, e.value, false]);
if (reduceTry.error && reduceTry.error instanceof BuiltInError) {
// CouchDB returns an error if a built-in errors out
throw reduceTry.error;
}
// CouchDB just sets the value to null if a non-built-in errors out
e.value = reduceTry.error ? null : reduceTry.output;
e.key = e.key[0][0];
}
// no total_rows/offset when reducing
return {rows: sliceResults(groups, options.limit, options.skip)};
}
function queryView(view, opts) {
return utils.sequentialize(getQueue(view), function () {
return queryViewInQueue(view, opts);
})();
}
function queryViewInQueue(view, opts) {
var totalRows;
var shouldReduce = view.reduceFun && opts.reduce !== false;
var skip = opts.skip || 0;
if (typeof opts.keys !== 'undefined' && !opts.keys.length) {
// equivalent query
opts.limit = 0;
delete opts.keys;
}
function fetchFromView(viewOpts) {
viewOpts.include_docs = true;
return view.db.allDocs(viewOpts).then(function (res) {
totalRows = res.total_rows;
return res.rows.map(function (result) {
// implicit migration - in older versions of PouchDB,
// we explicitly stored the doc as {id: ..., key: ..., value: ...}
// this is tested in a migration test
/* istanbul ignore next */
if ('value' in result.doc && typeof result.doc.value === 'object' &&
result.doc.value !== null) {
var keys = Object.keys(result.doc.value).sort();
// this detection method is not perfect, but it's unlikely the user
// emitted a value which was an object with these 3 exact keys
var expectedKeys = ['id', 'key', 'value'];
if (!(keys < expectedKeys || keys > expectedKeys)) {
return result.doc.value;
}
}
var parsedKeyAndDocId = pouchCollate.parseIndexableString(result.doc._id);
return {
key: parsedKeyAndDocId[0],
id: parsedKeyAndDocId[1],
value: ('value' in result.doc ? result.doc.value : null)
};
});
});
}
function onMapResultsReady(rows) {
var finalResults;
if (shouldReduce) {
finalResults = reduceView(view, rows, opts);
} else {
finalResults = {
total_rows: totalRows,
offset: skip,
rows: rows
};
}
if (opts.include_docs) {
var docIds = utils.uniq(rows.map(rowToDocId));
return view.sourceDB.allDocs({
keys: docIds,
include_docs: true,
conflicts: opts.conflicts,
attachments: opts.attachments
}).then(function (allDocsRes) {
var docIdsToDocs = {};
allDocsRes.rows.forEach(function (row) {
if (row.doc) {
docIdsToDocs['$' + row.id] = row.doc;
}
});
rows.forEach(function (row) {
var docId = rowToDocId(row);
var doc = docIdsToDocs['$' + docId];
if (doc) {
row.doc = doc;
}
});
return finalResults;
});
} else {
return finalResults;
}
}
var flatten = function (array) {
return array.reduce(function (prev, cur) {
return prev.concat(cur);
});
};
if (typeof opts.keys !== 'undefined') {
var keys = opts.keys;
var fetchPromises = keys.map(function (key) {
var viewOpts = {
startkey : toIndexableString([key]),
endkey : toIndexableString([key, {}])
};
return fetchFromView(viewOpts);
});
return Promise.all(fetchPromises).then(flatten).then(onMapResultsReady);
} else { // normal query, no 'keys'
var viewOpts = {
descending : opts.descending
};
if (typeof opts.startkey !== 'undefined') {
viewOpts.startkey = opts.descending ?
toIndexableString([opts.startkey, {}]) :
toIndexableString([opts.startkey]);
}
if (typeof opts.endkey !== 'undefined') {
var inclusiveEnd = opts.inclusive_end !== false;
if (opts.descending) {
inclusiveEnd = !inclusiveEnd;
}
viewOpts.endkey = toIndexableString(inclusiveEnd ? [opts.endkey, {}] : [opts.endkey]);
}
if (typeof opts.key !== 'undefined') {
var keyStart = toIndexableString([opts.key]);
var keyEnd = toIndexableString([opts.key, {}]);
if (viewOpts.descending) {
viewOpts.endkey = keyStart;
viewOpts.startkey = keyEnd;
} else {
viewOpts.startkey = keyStart;
viewOpts.endkey = keyEnd;
}
}
if (!shouldReduce) {
if (typeof opts.limit === 'number') {
viewOpts.limit = opts.limit;
}
viewOpts.skip = skip;
}
return fetchFromView(viewOpts).then(onMapResultsReady);
}
}
function httpViewCleanup(db) {
return db.request({
method: 'POST',
url: '_view_cleanup'
});
}
function localViewCleanup(db) {
return db.get('_local/mrviews').then(function (metaDoc) {
var docsToViews = {};
Object.keys(metaDoc.views).forEach(function (fullViewName) {
var parts = parseViewName(fullViewName);
var designDocName = '_design/' + parts[0];
var viewName = parts[1];
docsToViews[designDocName] = docsToViews[designDocName] || {};
docsToViews[designDocName][viewName] = true;
});
var opts = {
keys : Object.keys(docsToViews),
include_docs : true
};
return db.allDocs(opts).then(function (res) {
var viewsToStatus = {};
res.rows.forEach(function (row) {
var ddocName = row.key.substring(8);
Object.keys(docsToViews[row.key]).forEach(function (viewName) {
var fullViewName = ddocName + '/' + viewName;
/* istanbul ignore if */
if (!metaDoc.views[fullViewName]) {
// new format, without slashes, to support PouchDB 2.2.0
// migration test in pouchdb's browser.migration.js verifies this
fullViewName = viewName;
}
var viewDBNames = Object.keys(metaDoc.views[fullViewName]);
// design doc deleted, or view function nonexistent
var statusIsGood = row.doc && row.doc.views && row.doc.views[viewName];
viewDBNames.forEach(function (viewDBName) {
viewsToStatus[viewDBName] = viewsToStatus[viewDBName] || statusIsGood;
});
});
});
var dbsToDelete = Object.keys(viewsToStatus).filter(function (viewDBName) {
return !viewsToStatus[viewDBName];
});
var destroyPromises = dbsToDelete.map(function (viewDBName) {
return utils.sequentialize(getQueue(viewDBName), function () {
return new db.constructor(viewDBName, db.__opts).destroy();
})();
});
return Promise.all(destroyPromises).then(function () {
return {ok: true};
});
});
}, defaultsTo({ok: true}));
}
exports.viewCleanup = utils.callbackify(function () {
var db = this;
if (db.type() === 'http') {
return httpViewCleanup(db);
}
return localViewCleanup(db);
});
function queryPromised(db, fun, opts) {
if (db.type() === 'http') {
return httpQuery(db, fun, opts);
}
if (typeof fun !== 'string') {
// temp_view
checkQueryParseError(opts, fun);
var createViewOpts = {
db : db,
viewName : 'temp_view/temp_view',
map : fun.map,
reduce : fun.reduce,
temporary : true
};
tempViewQueue.add(function () {
return createView(createViewOpts).then(function (view) {
function cleanup() {
return view.db.destroy();
}
return utils.fin(updateView(view).then(function () {
return queryView(view, opts);
}), cleanup);
});
});
return tempViewQueue.finish();
} else {
// persistent view
var fullViewName = fun;
var parts = parseViewName(fullViewName);
var designDocName = parts[0];
var viewName = parts[1];
return db.get('_design/' + designDocName).then(function (doc) {
var fun = doc.views && doc.views[viewName];
if (!fun || typeof fun.map !== 'string') {
throw new NotFoundError('ddoc ' + designDocName + ' has no view named ' +
viewName);
}
checkQueryParseError(opts, fun);
var createViewOpts = {
db : db,
viewName : fullViewName,
map : fun.map,
reduce : fun.reduce
};
return createView(createViewOpts).then(function (view) {
if (opts.stale === 'ok' || opts.stale === 'update_after') {
if (opts.stale === 'update_after') {
process.nextTick(function () {
updateView(view);
});
}
return queryView(view, opts);
} else { // stale not ok
return updateView(view).then(function () {
return queryView(view, opts);
});
}
});
});
}
}
exports.query = function (fun, opts, callback) {
if (typeof opts === 'function') {
callback = opts;
opts = {};
}
opts = utils.extend(true, {}, opts);
if (typeof fun === 'function') {
fun = {map : fun};
}
var db = this;
var promise = Promise.resolve().then(function () {
return queryPromised(db, fun, opts);
});
utils.promisedCallback(promise, callback);
return promise;
};
function QueryParseError(message) {
this.status = 400;
this.name = 'query_parse_error';
this.message = message;
this.error = true;
try {
Error.captureStackTrace(this, QueryParseError);
} catch (e) {}
}
utils.inherits(QueryParseError, Error);
function NotFoundError(message) {
this.status = 404;
this.name = 'not_found';
this.message = message;
this.error = true;
try {
Error.captureStackTrace(this, NotFoundError);
} catch (e) {}
}
utils.inherits(NotFoundError, Error);
function BuiltInError(message) {
this.status = 500;
this.name = 'invalid_value';
this.message = message;
this.error = true;
try {
Error.captureStackTrace(this, BuiltInError);
} catch (e) {}
}
utils.inherits(BuiltInError, Error);
}).call(this,require("/Users/nlawson/workspace-node/pouchdb-authentication/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js"))
},{"./create-view":147,"./evalfunc":148,"./taskqueue":150,"./utils":152,"/Users/nlawson/workspace-node/pouchdb-authentication/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js":46,"pouchdb-collate":144}],150:[function(require,module,exports){
'use strict';
/*
* Simple task queue to sequentialize actions. Assumes callbacks will eventually fire (once).
*/
var Promise = require('./utils').Promise;
function TaskQueue() {
this.promise = new Promise(function (fulfill) {fulfill(); });
}
TaskQueue.prototype.add = function (promiseFactory) {
this.promise = this.promise["catch"](function () {
// just recover
}).then(function () {
return promiseFactory();
});
return this.promise;
};
TaskQueue.prototype.finish = function () {
return this.promise;
};
module.exports = TaskQueue;
},{"./utils":152}],151:[function(require,module,exports){
'use strict';
var upsert = require('pouchdb-upsert').upsert;
module.exports = function (db, doc, diffFun) {
return upsert.apply(db, [doc, diffFun]);
};
},{"pouchdb-upsert":153}],152:[function(require,module,exports){
(function (process,global){
'use strict';
/* istanbul ignore if */
if (typeof global.Promise === 'function') {
exports.Promise = global.Promise;
} else {
exports.Promise = require('lie');
}
exports.inherits = require('inherits');
exports.extend = require('pouchdb-extend');
var argsarray = require('argsarray');
exports.promisedCallback = function (promise, callback) {
if (callback) {
promise.then(function (res) {
process.nextTick(function () {
callback(null, res);
});
}, function (reason) {
process.nextTick(function () {
callback(reason);
});
});
}
return promise;
};
exports.callbackify = function (fun) {
return argsarray(function (args) {
var cb = args.pop();
var promise = fun.apply(this, args);
if (typeof cb === 'function') {
exports.promisedCallback(promise, cb);
}
return promise;
});
};
// Promise finally util similar to Q.finally
exports.fin = function (promise, cb) {
return promise.then(function (res) {
var promise2 = cb();
if (typeof promise2.then === 'function') {
return promise2.then(function () {
return res;
});
}
return res;
}, function (reason) {
var promise2 = cb();
if (typeof promise2.then === 'function') {
return promise2.then(function () {
throw reason;
});
}
throw reason;
});
};
exports.sequentialize = function (queue, promiseFactory) {
return function () {
var args = arguments;
var that = this;
return queue.add(function () {
return promiseFactory.apply(that, args);
});
};
};
exports.flatten = function (arrs) {
var res = [];
for (var i = 0, len = arrs.length; i < len; i++) {
res = res.concat(arrs[i]);
}
return res;
};
// uniq an array of strings, order not guaranteed
// similar to underscore/lodash _.uniq
exports.uniq = function (arr) {
var map = {};
for (var i = 0, len = arr.length; i < len; i++) {
map['$' + arr[i]] = true;
}
var keys = Object.keys(map);
var output = new Array(keys.length);
for (i = 0, len = keys.length; i < len; i++) {
output[i] = keys[i].substring(1);
}
return output;
};
var crypto = require('crypto');
var Md5 = require('spark-md5');
exports.MD5 = function (string) {
/* istanbul ignore else */
if (!process.browser) {
return crypto.createHash('md5').update(string).digest('hex');
} else {
return Md5.hash(string);
}
};
}).call(this,require("/Users/nlawson/workspace-node/pouchdb-authentication/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js"),typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"/Users/nlawson/workspace-node/pouchdb-authentication/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js":46,"argsarray":140,"crypto":41,"inherits":79,"lie":83,"pouchdb-extend":99,"spark-md5":154}],153:[function(require,module,exports){
(function (global){
'use strict';
var PouchPromise;
/* istanbul ignore next */
if (typeof window !== 'undefined' && window.PouchDB) {
PouchPromise = window.PouchDB.utils.Promise;
} else {
PouchPromise = typeof global.Promise === 'function' ? global.Promise : require('lie');
}
// this is essentially the "update sugar" function from daleharvey/pouchdb#1388
// the diffFun tells us what delta to apply to the doc. it either returns
// the doc, or false if it doesn't need to do an update after all
function upsertInner(db, docId, diffFun) {
return new PouchPromise(function (fulfill, reject) {
if (typeof docId !== 'string') {
return reject(new Error('doc id is required'));
}
db.get(docId, function (err, doc) {
if (err) {
/* istanbul ignore next */
if (err.status !== 404) {
return reject(err);
}
doc = {};
}
// the user might change the _rev, so save it for posterity
var docRev = doc._rev;
var newDoc = diffFun(doc);
if (!newDoc) {
// if the diffFun returns falsy, we short-circuit as
// an optimization
return fulfill({updated: false, rev: docRev});
}
// users aren't allowed to modify these values,
// so reset them here
newDoc._id = docId;
newDoc._rev = docRev;
fulfill(tryAndPut(db, newDoc, diffFun));
});
});
}
function tryAndPut(db, doc, diffFun) {
return db.put(doc).then(function (res) {
return {
updated: true,
rev: res.rev
};
}, function (err) {
/* istanbul ignore next */
if (err.status !== 409) {
throw err;
}
return upsertInner(db, doc._id, diffFun);
});
}
exports.upsert = function upsert(docId, diffFun, cb) {
var db = this;
var promise = upsertInner(db, docId, diffFun);
if (typeof cb !== 'function') {
return promise;
}
promise.then(function (resp) {
cb(null, resp);
}, cb);
};
exports.putIfNotExists = function putIfNotExists(docId, doc, cb) {
var db = this;
if (typeof docId !== 'string') {
cb = doc;
doc = docId;
docId = doc._id;
}
var diffFun = function (existingDoc) {
if (existingDoc._rev) {
return false; // do nothing
}
return doc;
};
var promise = upsertInner(db, docId, diffFun);
if (typeof cb !== 'function') {
return promise;
}
promise.then(function (resp) {
cb(null, resp);
}, cb);
};
/* istanbul ignore next */
if (typeof window !== 'undefined' && window.PouchDB) {
window.PouchDB.plugin(exports);
}
}).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"lie":83}],154:[function(require,module,exports){
/*jshint bitwise:false*/
/*global unescape*/
(function (factory) {
if (typeof exports === 'object') {
// Node/CommonJS
module.exports = factory();
} else if (typeof define === 'function' && define.amd) {
// AMD
define(factory);
} else {
// Browser globals (with support for web workers)
var glob;
try {
glob = window;
} catch (e) {
glob = self;
}
glob.SparkMD5 = factory();
}
}(function (undefined) {
'use strict';
////////////////////////////////////////////////////////////////////////////
/*
* Fastest md5 implementation around (JKM md5)
* Credits: Joseph Myers
*
* @see http://www.myersdaily.org/joseph/javascript/md5-text.html
* @see http://jsperf.com/md5-shootout/7
*/
/* this function is much faster,
so if possible we use it. Some IEs
are the only ones I know of that
need the idiotic second function,
generated by an if clause. */
var add32 = function (a, b) {
return (a + b) & 0xFFFFFFFF;
},
cmn = function (q, a, b, x, s, t) {
a = add32(add32(a, q), add32(x, t));
return add32((a << s) | (a >>> (32 - s)), b);
},
ff = function (a, b, c, d, x, s, t) {
return cmn((b & c) | ((~b) & d), a, b, x, s, t);
},
gg = function (a, b, c, d, x, s, t) {
return cmn((b & d) | (c & (~d)), a, b, x, s, t);
},
hh = function (a, b, c, d, x, s, t) {
return cmn(b ^ c ^ d, a, b, x, s, t);
},
ii = function (a, b, c, d, x, s, t) {
return cmn(c ^ (b | (~d)), a, b, x, s, t);
},
md5cycle = function (x, k) {
var a = x[0],
b = x[1],
c = x[2],
d = x[3];
a = ff(a, b, c, d, k[0], 7, -680876936);
d = ff(d, a, b, c, k[1], 12, -389564586);
c = ff(c, d, a, b, k[2], 17, 606105819);
b = ff(b, c, d, a, k[3], 22, -1044525330);
a = ff(a, b, c, d, k[4], 7, -176418897);
d = ff(d, a, b, c, k[5], 12, 1200080426);
c = ff(c, d, a, b, k[6], 17, -1473231341);
b = ff(b, c, d, a, k[7], 22, -45705983);
a = ff(a, b, c, d, k[8], 7, 1770035416);
d = ff(d, a, b, c, k[9], 12, -1958414417);
c = ff(c, d, a, b, k[10], 17, -42063);
b = ff(b, c, d, a, k[11], 22, -1990404162);
a = ff(a, b, c, d, k[12], 7, 1804603682);
d = ff(d, a, b, c, k[13], 12, -40341101);
c = ff(c, d, a, b, k[14], 17, -1502002290);
b = ff(b, c, d, a, k[15], 22, 1236535329);
a = gg(a, b, c, d, k[1], 5, -165796510);
d = gg(d, a, b, c, k[6], 9, -1069501632);
c = gg(c, d, a, b, k[11], 14, 643717713);
b = gg(b, c, d, a, k[0], 20, -373897302);
a = gg(a, b, c, d, k[5], 5, -701558691);
d = gg(d, a, b, c, k[10], 9, 38016083);
c = gg(c, d, a, b, k[15], 14, -660478335);
b = gg(b, c, d, a, k[4], 20, -405537848);
a = gg(a, b, c, d, k[9], 5, 568446438);
d = gg(d, a, b, c, k[14], 9, -1019803690);
c = gg(c, d, a, b, k[3], 14, -187363961);
b = gg(b, c, d, a, k[8], 20, 1163531501);
a = gg(a, b, c, d, k[13], 5, -1444681467);
d = gg(d, a, b, c, k[2], 9, -51403784);
c = gg(c, d, a, b, k[7], 14, 1735328473);
b = gg(b, c, d, a, k[12], 20, -1926607734);
a = hh(a, b, c, d, k[5], 4, -378558);
d = hh(d, a, b, c, k[8], 11, -2022574463);
c = hh(c, d, a, b, k[11], 16, 1839030562);
b = hh(b, c, d, a, k[14], 23, -35309556);
a = hh(a, b, c, d, k[1], 4, -1530992060);
d = hh(d, a, b, c, k[4], 11, 1272893353);
c = hh(c, d, a, b, k[7], 16, -155497632);
b = hh(b, c, d, a, k[10], 23, -1094730640);
a = hh(a, b, c, d, k[13], 4, 681279174);
d = hh(d, a, b, c, k[0], 11, -358537222);
c = hh(c, d, a, b, k[3], 16, -722521979);
b = hh(b, c, d, a, k[6], 23, 76029189);
a = hh(a, b, c, d, k[9], 4, -640364487);
d = hh(d, a, b, c, k[12], 11, -421815835);
c = hh(c, d, a, b, k[15], 16, 530742520);
b = hh(b, c, d, a, k[2], 23, -995338651);
a = ii(a, b, c, d, k[0], 6, -198630844);
d = ii(d, a, b, c, k[7], 10, 1126891415);
c = ii(c, d, a, b, k[14], 15, -1416354905);
b = ii(b, c, d, a, k[5], 21, -57434055);
a = ii(a, b, c, d, k[12], 6, 1700485571);
d = ii(d, a, b, c, k[3], 10, -1894986606);
c = ii(c, d, a, b, k[10], 15, -1051523);
b = ii(b, c, d, a, k[1], 21, -2054922799);
a = ii(a, b, c, d, k[8], 6, 1873313359);
d = ii(d, a, b, c, k[15], 10, -30611744);
c = ii(c, d, a, b, k[6], 15, -1560198380);
b = ii(b, c, d, a, k[13], 21, 1309151649);
a = ii(a, b, c, d, k[4], 6, -145523070);
d = ii(d, a, b, c, k[11], 10, -1120210379);
c = ii(c, d, a, b, k[2], 15, 718787259);
b = ii(b, c, d, a, k[9], 21, -343485551);
x[0] = add32(a, x[0]);
x[1] = add32(b, x[1]);
x[2] = add32(c, x[2]);
x[3] = add32(d, x[3]);
},
/* there needs to be support for Unicode here,
* unless we pretend that we can redefine the MD-5
* algorithm for multi-byte characters (perhaps
* by adding every four 16-bit characters and
* shortening the sum to 32 bits). Otherwise
* I suggest performing MD-5 as if every character
* was two bytes--e.g., 0040 0025 = @%--but then
* how will an ordinary MD-5 sum be matched?
* There is no way to standardize text to something
* like UTF-8 before transformation; speed cost is
* utterly prohibitive. The JavaScript standard
* itself needs to look at this: it should start
* providing access to strings as preformed UTF-8
* 8-bit unsigned value arrays.
*/
md5blk = function (s) {
var md5blks = [],
i; /* Andy King said do it this way. */
for (i = 0; i < 64; i += 4) {
md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << 24);
}
return md5blks;
},
md5blk_array = function (a) {
var md5blks = [],
i; /* Andy King said do it this way. */
for (i = 0; i < 64; i += 4) {
md5blks[i >> 2] = a[i] + (a[i + 1] << 8) + (a[i + 2] << 16) + (a[i + 3] << 24);
}
return md5blks;
},
md51 = function (s) {
var n = s.length,
state = [1732584193, -271733879, -1732584194, 271733878],
i,
length,
tail,
tmp,
lo,
hi;
for (i = 64; i <= n; i += 64) {
md5cycle(state, md5blk(s.substring(i - 64, i)));
}
s = s.substring(i - 64);
length = s.length;
tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
for (i = 0; i < length; i += 1) {
tail[i >> 2] |= s.charCodeAt(i) << ((i % 4) << 3);
}
tail[i >> 2] |= 0x80 << ((i % 4) << 3);
if (i > 55) {
md5cycle(state, tail);
for (i = 0; i < 16; i += 1) {
tail[i] = 0;
}
}
// Beware that the final length might not fit in 32 bits so we take care of that
tmp = n * 8;
tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);
lo = parseInt(tmp[2], 16);
hi = parseInt(tmp[1], 16) || 0;
tail[14] = lo;
tail[15] = hi;
md5cycle(state, tail);
return state;
},
md51_array = function (a) {
var n = a.length,
state = [1732584193, -271733879, -1732584194, 271733878],
i,
length,
tail,
tmp,
lo,
hi;
for (i = 64; i <= n; i += 64) {
md5cycle(state, md5blk_array(a.subarray(i - 64, i)));
}
// Not sure if it is a bug, however IE10 will always produce a sub array of length 1
// containing the last element of the parent array if the sub array specified starts
// beyond the length of the parent array - weird.
// https://connect.microsoft.com/IE/feedback/details/771452/typed-array-subarray-issue
a = (i - 64) < n ? a.subarray(i - 64) : new Uint8Array(0);
length = a.length;
tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
for (i = 0; i < length; i += 1) {
tail[i >> 2] |= a[i] << ((i % 4) << 3);
}
tail[i >> 2] |= 0x80 << ((i % 4) << 3);
if (i > 55) {
md5cycle(state, tail);
for (i = 0; i < 16; i += 1) {
tail[i] = 0;
}
}
// Beware that the final length might not fit in 32 bits so we take care of that
tmp = n * 8;
tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);
lo = parseInt(tmp[2], 16);
hi = parseInt(tmp[1], 16) || 0;
tail[14] = lo;
tail[15] = hi;
md5cycle(state, tail);
return state;
},
hex_chr = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'],
rhex = function (n) {
var s = '',
j;
for (j = 0; j < 4; j += 1) {
s += hex_chr[(n >> (j * 8 + 4)) & 0x0F] + hex_chr[(n >> (j * 8)) & 0x0F];
}
return s;
},
hex = function (x) {
var i;
for (i = 0; i < x.length; i += 1) {
x[i] = rhex(x[i]);
}
return x.join('');
},
md5 = function (s) {
return hex(md51(s));
},
////////////////////////////////////////////////////////////////////////////
/**
* SparkMD5 OOP implementation.
*
* Use this class to perform an incremental md5, otherwise use the
* static methods instead.
*/
SparkMD5 = function () {
// call reset to init the instance
this.reset();
};
// In some cases the fast add32 function cannot be used..
if (md5('hello') !== '5d41402abc4b2a76b9719d911017c592') {
add32 = function (x, y) {
var lsw = (x & 0xFFFF) + (y & 0xFFFF),
msw = (x >> 16) + (y >> 16) + (lsw >> 16);
return (msw << 16) | (lsw & 0xFFFF);
};
}
/**
* Appends a string.
* A conversion will be applied if an utf8 string is detected.
*
* @param {String} str The string to be appended
*
* @return {SparkMD5} The instance itself
*/
SparkMD5.prototype.append = function (str) {
// converts the string to utf8 bytes if necessary
if (/[\u0080-\uFFFF]/.test(str)) {
str = unescape(encodeURIComponent(str));
}
// then append as binary
this.appendBinary(str);
return this;
};
/**
* Appends a binary string.
*
* @param {String} contents The binary string to be appended
*
* @return {SparkMD5} The instance itself
*/
SparkMD5.prototype.appendBinary = function (contents) {
this._buff += contents;
this._length += contents.length;
var length = this._buff.length,
i;
for (i = 64; i <= length; i += 64) {
md5cycle(this._state, md5blk(this._buff.substring(i - 64, i)));
}
this._buff = this._buff.substr(i - 64);
return this;
};
/**
* Finishes the incremental computation, reseting the internal state and
* returning the result.
* Use the raw parameter to obtain the raw result instead of the hex one.
*
* @param {Boolean} raw True to get the raw result, false to get the hex result
*
* @return {String|Array} The result
*/
SparkMD5.prototype.end = function (raw) {
var buff = this._buff,
length = buff.length,
i,
tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
ret;
for (i = 0; i < length; i += 1) {
tail[i >> 2] |= buff.charCodeAt(i) << ((i % 4) << 3);
}
this._finish(tail, length);
ret = !!raw ? this._state : hex(this._state);
this.reset();
return ret;
};
/**
* Finish the final calculation based on the tail.
*
* @param {Array} tail The tail (will be modified)
* @param {Number} length The length of the remaining buffer
*/
SparkMD5.prototype._finish = function (tail, length) {
var i = length,
tmp,
lo,
hi;
tail[i >> 2] |= 0x80 << ((i % 4) << 3);
if (i > 55) {
md5cycle(this._state, tail);
for (i = 0; i < 16; i += 1) {
tail[i] = 0;
}
}
// Do the final computation based on the tail and length
// Beware that the final length may not fit in 32 bits so we take care of that
tmp = this._length * 8;
tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);
lo = parseInt(tmp[2], 16);
hi = parseInt(tmp[1], 16) || 0;
tail[14] = lo;
tail[15] = hi;
md5cycle(this._state, tail);
};
/**
* Resets the internal state of the computation.
*
* @return {SparkMD5} The instance itself
*/
SparkMD5.prototype.reset = function () {
this._buff = "";
this._length = 0;
this._state = [1732584193, -271733879, -1732584194, 271733878];
return this;
};
/**
* Releases memory used by the incremental buffer and other aditional
* resources. If you plan to use the instance again, use reset instead.
*/
SparkMD5.prototype.destroy = function () {
delete this._state;
delete this._buff;
delete this._length;
};
/**
* Performs the md5 hash on a string.
* A conversion will be applied if utf8 string is detected.
*
* @param {String} str The string
* @param {Boolean} raw True to get the raw result, false to get the hex result
*
* @return {String|Array} The result
*/
SparkMD5.hash = function (str, raw) {
// converts the string to utf8 bytes if necessary
if (/[\u0080-\uFFFF]/.test(str)) {
str = unescape(encodeURIComponent(str));
}
var hash = md51(str);
return !!raw ? hash : hex(hash);
};
/**
* Performs the md5 hash on a binary string.
*
* @param {String} content The binary string
* @param {Boolean} raw True to get the raw result, false to get the hex result
*
* @return {String|Array} The result
*/
SparkMD5.hashBinary = function (content, raw) {
var hash = md51(content);
return !!raw ? hash : hex(hash);
};
/**
* SparkMD5 OOP implementation for array buffers.
*
* Use this class to perform an incremental md5 ONLY for array buffers.
*/
SparkMD5.ArrayBuffer = function () {
// call reset to init the instance
this.reset();
};
////////////////////////////////////////////////////////////////////////////
/**
* Appends an array buffer.
*
* @param {ArrayBuffer} arr The array to be appended
*
* @return {SparkMD5.ArrayBuffer} The instance itself
*/
SparkMD5.ArrayBuffer.prototype.append = function (arr) {
// TODO: we could avoid the concatenation here but the algorithm would be more complex
// if you find yourself needing extra performance, please make a PR.
var buff = this._concatArrayBuffer(this._buff, arr),
length = buff.length,
i;
this._length += arr.byteLength;
for (i = 64; i <= length; i += 64) {
md5cycle(this._state, md5blk_array(buff.subarray(i - 64, i)));
}
// Avoids IE10 weirdness (documented above)
this._buff = (i - 64) < length ? buff.subarray(i - 64) : new Uint8Array(0);
return this;
};
/**
* Finishes the incremental computation, reseting the internal state and
* returning the result.
* Use the raw parameter to obtain the raw result instead of the hex one.
*
* @param {Boolean} raw True to get the raw result, false to get the hex result
*
* @return {String|Array} The result
*/
SparkMD5.ArrayBuffer.prototype.end = function (raw) {
var buff = this._buff,
length = buff.length,
tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
i,
ret;
for (i = 0; i < length; i += 1) {
tail[i >> 2] |= buff[i] << ((i % 4) << 3);
}
this._finish(tail, length);
ret = !!raw ? this._state : hex(this._state);
this.reset();
return ret;
};
SparkMD5.ArrayBuffer.prototype._finish = SparkMD5.prototype._finish;
/**
* Resets the internal state of the computation.
*
* @return {SparkMD5.ArrayBuffer} The instance itself
*/
SparkMD5.ArrayBuffer.prototype.reset = function () {
this._buff = new Uint8Array(0);
this._length = 0;
this._state = [1732584193, -271733879, -1732584194, 271733878];
return this;
};
/**
* Releases memory used by the incremental buffer and other aditional
* resources. If you plan to use the instance again, use reset instead.
*/
SparkMD5.ArrayBuffer.prototype.destroy = SparkMD5.prototype.destroy;
/**
* Concats two array buffers, returning a new one.
*
* @param {ArrayBuffer} first The first array buffer
* @param {ArrayBuffer} second The second array buffer
*
* @return {ArrayBuffer} The new array buffer
*/
SparkMD5.ArrayBuffer.prototype._concatArrayBuffer = function (first, second) {
var firstLength = first.length,
result = new Uint8Array(firstLength + second.byteLength);
result.set(first);
result.set(new Uint8Array(second), firstLength);
return result;
};
/**
* Performs the md5 hash on an array buffer.
*
* @param {ArrayBuffer} arr The array buffer
* @param {Boolean} raw True to get the raw result, false to get the hex result
*
* @return {String|Array} The result
*/
SparkMD5.ArrayBuffer.hash = function (arr, raw) {
var hash = md51_array(new Uint8Array(arr));
return !!raw ? hash : hex(hash);
};
return SparkMD5;
}));
},{}],155:[function(require,module,exports){
'use strict';
/**
* Stringify/parse functions that don't operate
* recursively, so they avoid call stack exceeded
* errors.
*/
exports.stringify = function stringify(input) {
var queue = [];
queue.push({obj: input});
var res = '';
var next, obj, prefix, val, i, arrayPrefix, keys, k, key, value, objPrefix;
while ((next = queue.pop())) {
obj = next.obj;
prefix = next.prefix || '';
val = next.val || '';
res += prefix;
if (val) {
res += val;
} else if (typeof obj !== 'object') {
res += typeof obj === 'undefined' ? null : JSON.stringify(obj);
} else if (obj === null) {
res += 'null';
} else if (Array.isArray(obj)) {
queue.push({val: ']'});
for (i = obj.length - 1; i >= 0; i--) {
arrayPrefix = i === 0 ? '' : ',';
queue.push({obj: obj[i], prefix: arrayPrefix});
}
queue.push({val: '['});
} else { // object
keys = [];
for (k in obj) {
if (obj.hasOwnProperty(k)) {
keys.push(k);
}
}
queue.push({val: '}'});
for (i = keys.length - 1; i >= 0; i--) {
key = keys[i];
value = obj[key];
objPrefix = (i > 0 ? ',' : '');
objPrefix += JSON.stringify(key) + ':';
queue.push({obj: value, prefix: objPrefix});
}
queue.push({val: '{'});
}
}
return res;
};
// Convenience function for the parse function.
// This pop function is basically copied from
// pouchCollate.parseIndexableString
function pop(obj, stack, metaStack) {
var lastMetaElement = metaStack[metaStack.length - 1];
if (obj === lastMetaElement.element) {
// popping a meta-element, e.g. an object whose value is another object
metaStack.pop();
lastMetaElement = metaStack[metaStack.length - 1];
}
var element = lastMetaElement.element;
var lastElementIndex = lastMetaElement.index;
if (Array.isArray(element)) {
element.push(obj);
} else if (lastElementIndex === stack.length - 2) { // obj with key+value
var key = stack.pop();
element[key] = obj;
} else {
stack.push(obj); // obj with key only
}
}
exports.parse = function (str) {
var stack = [];
var metaStack = []; // stack for arrays and objects
var i = 0;
var collationIndex,parsedNum,numChar;
var parsedString,lastCh,numConsecutiveSlashes,ch;
var arrayElement, objElement;
while (true) {
collationIndex = str[i++];
if (collationIndex === '}' ||
collationIndex === ']' ||
typeof collationIndex === 'undefined') {
if (stack.length === 1) {
return stack.pop();
} else {
pop(stack.pop(), stack, metaStack);
continue;
}
}
switch (collationIndex) {
case ' ':
case '\t':
case '\n':
case ':':
case ',':
break;
case 'n':
i += 3; // 'ull'
pop(null, stack, metaStack);
break;
case 't':
i += 3; // 'rue'
pop(true, stack, metaStack);
break;
case 'f':
i += 4; // 'alse'
pop(false, stack, metaStack);
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case '-':
parsedNum = '';
i--;
while (true) {
numChar = str[i++];
if (/[\d\.\-e\+]/.test(numChar)) {
parsedNum += numChar;
} else {
i--;
break;
}
}
pop(parseFloat(parsedNum), stack, metaStack);
break;
case '"':
parsedString = '';
lastCh = void 0;
numConsecutiveSlashes = 0;
while (true) {
ch = str[i++];
if (ch !== '"' || (lastCh === '\\' &&
numConsecutiveSlashes % 2 === 1)) {
parsedString += ch;
lastCh = ch;
if (lastCh === '\\') {
numConsecutiveSlashes++;
} else {
numConsecutiveSlashes = 0;
}
} else {
break;
}
}
pop(JSON.parse('"' + parsedString + '"'), stack, metaStack);
break;
case '[':
arrayElement = { element: [], index: stack.length };
stack.push(arrayElement.element);
metaStack.push(arrayElement);
break;
case '{':
objElement = { element: {}, index: stack.length };
stack.push(objElement.element);
metaStack.push(objElement);
break;
default:
throw new Error(
'unexpectedly reached end of input: ' + collationIndex);
}
}
};
},{}],156:[function(require,module,exports){
(function (process){
/*jshint expr:true */
/* global sum */
'use strict';
var PouchDB = require('pouchdb');
var Authentication = require('../lib');
PouchDB.plugin(Authentication);
var utils = require('../lib/utils');
var chai = require('chai');
var should = chai.should();
require('mocha-as-promised')();
chai.use(require('chai-as-promised'));
var Promise = require('bluebird');
var all = Promise.all;
if (process.browser) {
process.env.TEST_DB = 'http://localhost:2022/testdb';
}
var dbs = process.env.TEST_DB;
if (!dbs) {
console.error('No db name specified');
process.exit(1);
}
dbs.split(',').forEach(function (db) {
var dbType = /^http/.test(db) ? 'http' : 'local';
describe(dbType, function () {
tests(db);
});
});
var users = ['batman', 'superman', 'green_lantern', 'robin', 'aquaman', 'spiderman'];
function tests(dbName) {
describe('authentication', function () {
var db;
beforeEach(function () {
db = new PouchDB(dbName);
return db;
});
afterEach(function () {
return db.logout().then(function () {
return PouchDB.destroy(dbName).then(function () {
var usersUrl = utils.getUsersUrl(db);
return new PouchDB(usersUrl).then(function (usersDb) {
// remove the fake users, hopefully we're in the admin party
return usersDb.allDocs({
include_docs : true,
keys : users.map(function (user) {
return 'org.couchdb.user:' + user;
})
}).then(function (res) {
var rows = res.rows.filter(function (row) {
return row.doc;
});
var docs = rows.map(function (row) {
row.doc._deleted = true;
return row.doc;
});
return usersDb.bulkDocs({docs : docs});
});
});
});
});
});
it('Test signup', function () {
return db.signup('batman', 'brucewayne').then(function (res) {
console.log(res);
res.ok.should.equal(true);
res.id.should.equal('org.couchdb.user:batman');
});
});
it('Test signup conflict', function () {
return db.signup('superman', 'clarkkent').then(function (res) {
res.ok.should.equal(true);
return db.signup('superman', 'notclarkkent').then(function (res) {
should.not.exist(res);
}).catch(function (err) {
err.name.should.equal('conflict');
});
});
});
it('Test bad signup args', function () {
return db.signup().catch(function (err) {
should.exist(err);
});
});
it('Test bad signup args 2', function () {
return db.signup('green_lantern').catch(function (err) {
should.exist(err);
});
});
it('Test login/logout', function () {
return db.signup('aquaman', 'sleeps_with_fishes').then(function (res) {
return db.getSession();
}).then(function (res) {
should.equal(res.userCtx.name, null);
return db.login('aquaman', 'sleeps_with_fishes');
}).then(function (res) {
res.ok.should.equal(true);
return db.getSession();
}).then(function (res) {
res.userCtx.name.should.equal('aquaman');
return db.logout();
}).then(function () {
return db.getSession();
}).then(function (res) {
should.equal(res.userCtx.name, null);
});
});
it('Test metadata', function () {
var metadata = {alias : 'boywonder', profession : 'acrobat'};
var opts = {metadata : metadata};
return db.signup('robin', 'dickgrayson', opts).then(function (res) {
res.ok.should.equal(true);
return db.login('robin', 'dickgrayson');
}).then(function () {
return db.getUser('robin');
}).then(function (user) {
console.log(user);
user.name.should.equal('robin');
user.alias.should.equal('boywonder');
user.profession.should.equal('acrobat');
});
});
it('Test wrong user for getUser', function () {
return db.signup('robin', 'dickgrayson').then(function (res) {
return db.signup('aquaman', 'sleeps_with_fishes');
}).then(function () {
return db.login('robin', 'dickgrayson');
}).then(function () {
return db.getUser('robin');
}).then(function (res) {
res.name.should.equal('robin');
return db.getUser('aquaman').then(function (res) {
should.not.exist(res);
}).catch(function (err) {
err.name.should.equal('not_found');
return db.login('aquaman', 'sleeps_with_fishes').then(function () {
return db.getUser('aquaman').then(function (res) {
res.name.should.equal('aquaman');
return db.getSession();
}).then(function (res) {
res.userCtx.name.should.equal('aquaman');
return db.getUser('robin').then(function (res) {
should.not.exist(res);
}).catch(function (err) {
err.name.should.equal('not_found');
});
});
});
});
});
});
it('Test change password', function () {
return db.signup('spiderman', 'will-forget').then(function (res) {
return db.changePassword('spiderman', 'will-remember').then(function (res) {
res.ok.should.equal(true);
}).then(function () {
return db.login('spiderman', 'will-remember');
}).then(function (res) {
res.ok.should.equal(true);
});
});
});
});
}
}).call(this,require("/Users/nlawson/workspace-node/pouchdb-authentication/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js"))
},{"../lib":1,"../lib/utils":2,"/Users/nlawson/workspace-node/pouchdb-authentication/node_modules/browserify/node_modules/insert-module-globals/node_modules/process/browser.js":46,"bluebird":6,"chai":49,"chai-as-promised":48,"mocha-as-promised":98,"pouchdb":132}]},{},[156])
/*jshint expr:true */
/* global sum */
'use strict';
var PouchDB = require('pouchdb');
var Authentication = require('../lib');
PouchDB.plugin(Authentication);
var utils = require('../lib/utils');
var chai = require('chai');
var should = chai.should();
require('mocha-as-promised')();
chai.use(require('chai-as-promised'));
var Promise = require('bluebird');
var all = Promise.all;
if (process.browser) {
process.env.TEST_DB = 'http://localhost:2022/testdb';
}
var dbs = process.env.TEST_DB;
if (!dbs) {
console.error('No db name specified');
process.exit(1);
}
dbs.split(',').forEach(function (db) {
var dbType = /^http/.test(db) ? 'http' : 'local';
describe(dbType, function () {
tests(db);
});
});
var users = ['batman', 'superman', 'green_lantern', 'robin', 'aquaman', 'spiderman'];
function tests(dbName) {
describe('authentication', function () {
var db;
beforeEach(function () {
db = new PouchDB(dbName);
return db;
});
afterEach(function () {
return db.logout().then(function () {
return PouchDB.destroy(dbName).then(function () {
var usersUrl = utils.getUsersUrl(db);
return new PouchDB(usersUrl).then(function (usersDb) {
// remove the fake users, hopefully we're in the admin party
return usersDb.allDocs({
include_docs : true,
keys : users.map(function (user) {
return 'org.couchdb.user:' + user;
})
}).then(function (res) {
var rows = res.rows.filter(function (row) {
return row.doc;
});
var docs = rows.map(function (row) {
row.doc._deleted = true;
return row.doc;
});
return usersDb.bulkDocs({docs : docs});
});
});
});
});
});
it('Test signup', function () {
return db.signup('batman', 'brucewayne').then(function (res) {
console.log(res);
res.ok.should.equal(true);
res.id.should.equal('org.couchdb.user:batman');
});
});
it('Test signup conflict', function () {
return db.signup('superman', 'clarkkent').then(function (res) {
res.ok.should.equal(true);
return db.signup('superman', 'notclarkkent').then(function (res) {
should.not.exist(res);
}).catch(function (err) {
err.name.should.equal('conflict');
});
});
});
it('Test bad signup args', function () {
return db.signup().catch(function (err) {
should.exist(err);
});
});
it('Test bad signup args 2', function () {
return db.signup('green_lantern').catch(function (err) {
should.exist(err);
});
});
it('Test login/logout', function () {
return db.signup('aquaman', 'sleeps_with_fishes').then(function (res) {
return db.getSession();
}).then(function (res) {
should.equal(res.userCtx.name, null);
return db.login('aquaman', 'sleeps_with_fishes');
}).then(function (res) {
res.ok.should.equal(true);
return db.getSession();
}).then(function (res) {
res.userCtx.name.should.equal('aquaman');
return db.logout();
}).then(function () {
return db.getSession();
}).then(function (res) {
should.equal(res.userCtx.name, null);
});
});
it('Test metadata', function () {
var metadata = {alias : 'boywonder', profession : 'acrobat'};
var opts = {metadata : metadata};
return db.signup('robin', 'dickgrayson', opts).then(function (res) {
res.ok.should.equal(true);
return db.login('robin', 'dickgrayson');
}).then(function () {
return db.getUser('robin');
}).then(function (user) {
console.log(user);
user.name.should.equal('robin');
user.alias.should.equal('boywonder');
user.profession.should.equal('acrobat');
});
});
it('Test wrong user for getUser', function () {
return db.signup('robin', 'dickgrayson').then(function (res) {
return db.signup('aquaman', 'sleeps_with_fishes');
}).then(function () {
return db.login('robin', 'dickgrayson');
}).then(function () {
return db.getUser('robin');
}).then(function (res) {
res.name.should.equal('robin');
return db.getUser('aquaman').then(function (res) {
should.not.exist(res);
}).catch(function (err) {
err.name.should.equal('not_found');
return db.login('aquaman', 'sleeps_with_fishes').then(function () {
return db.getUser('aquaman').then(function (res) {
res.name.should.equal('aquaman');
return db.getSession();
}).then(function (res) {
res.userCtx.name.should.equal('aquaman');
return db.getUser('robin').then(function (res) {
should.not.exist(res);
}).catch(function (err) {
err.name.should.equal('not_found');
});
});
});
});
});
});
it('Test change password', function () {
return db.signup('spiderman', 'will-forget').then(function (res) {
return db.changePassword('spiderman', 'will-remember').then(function (res) {
res.ok.should.equal(true);
}).then(function () {
return db.login('spiderman', 'will-remember');
}).then(function (res) {
res.ok.should.equal(true);
});
});
});
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment