asana-phrase
Version:
Random error phrase generator used by Asana
1,493 lines (1,300 loc) • 45.8 kB
JavaScript
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.AsanaPhrase = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
var Factory = require('./lib/factory');
var Dictionary = require('./lib/dictionary');
var NumberRange = require('./lib/number_range');
var WordGenerator = require('./lib/word_generator');
var dictionaries = require('./lib/dictionaries');
/**
* The default 32-bit phrase generator, which creates fun and easy-to-remember
* phrases consisting of, in order:
* * One of 32 numbers, from 2-33 [5 bits]
* * One of 128 adjectives [7 bits]
* * One of 128 subjects (mostly animals, for extra cuteness) [7 bits]
* * One of 128 verbs [7 bits]
* * One of 64 adverbs [6 bits]
*
* So a random phrase is something like:
* "23 glossy ants march happily"
*
* Dividing the phrase into distinct parts of speech with an obvious pattern
* and constraints makes memorization easier. Restricting the dictionary space
* to as few syllables as possible (in most cases one- or two-syllable words)
* makes recitation of the complete phrase simpler. The result is a phrase
* that, while taking up more bytes to render digitally, theoretically takes up
* significantly less cognitive space than an 8-digit hex string or even a
* 6-digit alphanumeric code. This is an experiment. :)
*/
var default32BitFactory = new Factory([
new NumberRange(5, 2),
new Dictionary(dictionaries.adjectives),
new Dictionary(dictionaries.subjects),
new Dictionary(dictionaries.verbs),
new Dictionary(dictionaries.adverbs)
]);
module.exports = {
default32BitFactory: function() {
return default32BitFactory;
},
Factory: Factory,
WordGenerator: WordGenerator,
Dictionary: Dictionary,
NumberRange: NumberRange,
dictionaries: dictionaries
};
},{"./lib/dictionaries":3,"./lib/dictionary":4,"./lib/factory":5,"./lib/number_range":6,"./lib/word_generator":7}],2:[function(require,module,exports){
var assert = require('assert');
/**
* @returns {Function} A function that, when called, returns a random 1 or 0
* with equal probability up until `len` digits.
*/
function randomBitGen(len) {
assert.equal(typeof(len), 'number');
var remaining = len;
return function() {
if (remaining > 0) {
remaining--;
return Math.random() >= 0.5 ? 1 : 0;
} else {
return null;
}
};
}
/**
* @param value {number}
* @returns {Function} A function that, when called, returns the bits of the
* integer `value`, starting from least to most significant.
*/
function intBitGen(value) {
assert.equal(typeof(value), 'number');
assert.equal(value, Math.floor(value), 'value is not an integer');
assert(value < Math.pow(2, 53), 'value too large to be integer');
var returnedAny = false;
var remaining = value;
return function() {
if (remaining > 0 || !returnedAny) {
var bit = remaining % 2;
remaining >>= 1;
returnedAny = true;
return bit;
} else {
return null;
}
};
}
/**
* @param value {string}
* @returns {Function} A function that, when called, returns the bits of the
* hex string `value`, starting from least to most significant.
*/
function hexBitGen(value) {
assert.equal(typeof(value), 'string');
assert(/^[0-9a-fA-F]+$/.test(value), 'value is not a hex number');
var returnedAny = false;
var remaining = value;
var offset = 0;
var nibble = 0;
return function() {
if (offset++ % 4 === 0 && remaining.length > 0) {
nibble = parseInt(remaining.substr(-1), 16);
remaining = remaining.substr(0, remaining.length - 1);
}
if (nibble > 0 || remaining.length > 0 || !returnedAny) {
var bit = nibble % 2;
nibble >>= 1;
returnedAny = true;
return bit;
} else {
return null;
}
};
}
/**
* @param value {string}
* @returns {Function} A function that, when called, returns the bits of the
* binary digit string `value` (e.g. "10010110"), starting from least
* to most significant.
*/
function binaryDigitBitGen(value) {
assert.equal(typeof(value), 'string');
assert(/^[01]+$/.test(value), 'value is not a string of binary digits');
var returnedAny = false;
var remaining = value;
return function() {
var bit = 0;
if (remaining) {
bit = remaining.charCodeAt(remaining.length - 1) - 48;
remaining = remaining.substr(0, remaining.length - 1);
returnedAny = true;
return bit;
} else if (!returnedAny) {
returnedAny = true;
return 0;
} else {
return null;
}
};
}
module.exports = {
random: randomBitGen,
int: intBitGen,
hex: hexBitGen,
binaryDigit: binaryDigitBitGen
};
},{"assert":8}],3:[function(require,module,exports){
// Dictionaries of words to use as parts of phrases.
// These are all chosen to be short words (1-2 syllables), to keep the
// resulting phrases short.
var subjects = [
'aardvarks', 'alpacas', 'ants', 'apes', 'baboons', 'badgers', 'bats',
'bears', 'beavers', 'bees', 'birds', 'bison', 'bobcats', 'bullfrogs',
'bulls', 'bunnies', 'buzzards', 'camels', 'catfish', 'cats', 'cattle',
'cheetahs', 'chickens', 'chipmunks', 'cobras', 'cougars', 'crabs',
'crickets', 'crows', 'deer', 'dogs', 'dolphins', 'donkeys', 'doves',
'ducks', 'eagles', 'eels', 'elephants', 'elk', 'emus', 'ewoks', 'falcons',
'ferrets', 'fish', 'fleas', 'flies', 'foxes', 'frogs', 'gazelle', 'geese',
'gerbils', 'giraffes', 'goats', 'goblins', 'gorillas', 'groundhogs',
'hawks', 'hippos',
'hogs', 'horses', 'hounds', 'jackals', 'jaguars', 'kittens', 'klingons',
'lambs', 'leeches', 'lemmings', 'leopards', 'ligers', 'lions', 'lizards',
'llamas', 'lobsters', 'marmots', 'mice', 'monkeys', 'moose', 'mules',
'newts', 'orcs', 'otters', 'owls', 'oysters', 'pandas', 'peacocks',
'penguins', 'pidgeons', 'pigs', 'pumas', 'puppies', 'quails', 'rabbits',
'raccoons', 'rats', 'reindeer', 'rhinos', 'roosters', 'salmon', 'seals',
'sharks', 'sheep', 'shrimp', 'skunks', 'slugs', 'snails', 'snakes',
'spiders', 'squid', 'squirrels', 'starfish', 'stingrays', 'swans', 'tigers',
'toads', 'trout', 'tuna', 'turkeys', 'turtles', 'urchins', 'vipers',
'vultures', 'warthogs', 'whales', 'wolves', 'woodchucks', 'yaks', 'zebras'
];
var adjectives = [
'awful', 'bad', 'bashful', 'berserk', 'big', 'bizarre', 'black', 'blue',
'boring', 'brawny', 'bright', 'bumpy', 'burly', 'cagey', 'cheerful',
'chilly', 'chubby', 'classy', 'clumsy', 'cold', 'crazy', 'creepy', 'cuddly',
'dashing', 'dirty', 'dizzy', 'drunk', 'dry', 'dull', 'dusty', 'eager',
'evil', 'fancy', 'fast', 'fat', 'faulty', 'fearless', 'filthy', 'foamy',
'friendly', 'funny', 'gentle', 'giant', 'glossy', 'good', 'goofy', 'great',
'greedy', 'green', 'groovy', 'grumpy', 'guilty', 'hairy', 'handsome',
'happy', 'healthy', 'heavy', 'helpful', 'high', 'huge', 'hungry', 'icky',
'itchy', 'jazzy', 'jealous', 'jolly', 'jumpy', 'kind', 'large', 'lazy',
'lean', 'little', 'lively', 'lucky', 'macho', 'magenta', 'magic', 'massive',
'meek', 'mighty', 'mindless', 'nasty', 'needy', 'new', 'nice', 'noisy',
'odd', 'old', 'orange', 'pretty', 'prickly', 'proud', 'puffy', 'purple',
'quick', 'quiet', 'rabid', 'rebel', 'red', 'righteous', 'round', 'sad',
'sassy', 'scary', 'sedate', 'shallow', 'short', 'silly', 'skillful',
'skinny', 'sloppy', 'slow', 'small', 'smelly', 'sneaky', 'snobby',
'strange', 'tacky', 'tall', 'tan', 'tough', 'tricky', 'ugly', 'wicked',
'wise', 'yellow', 'young', 'zany'
];
var verbs = [
'agree', 'applaud', 'argue', 'arise', 'arrive', 'attack', 'awaken', 'bake',
'bathe', 'beg', 'behave', 'bite', 'blink', 'blush', 'bounce', 'breathe',
'burrow', 'buzz', 'charge', 'chat', 'cheer', 'chuckle', 'chew', 'clap',
'cry', 'dance', 'dig', 'dive', 'drink', 'eat', 'feed', 'fight', 'flap',
'flee', 'float', 'fly', 'gather', 'glow', 'grunt', 'hang', 'hide', 'howl',
'hunt', 'itch', 'jog', 'joke', 'jostle', 'jump', 'kick', 'kneel', 'knit',
'krump', 'laugh', 'leap', 'leave', 'look', 'lope', 'march', 'mix', 'moan',
'nuzzle', 'observe', 'plan', 'play', 'plead', 'point', 'pray', 'punch',
'push', 'race', 'rejoice', 'relax', 'retire', 'return', 'roar', 'rub',
'rumble', 'run', 'rush', 'sail', 'scare', 'scrape', 'scratch', 'scream',
'scrub', 'search', 'shake', 'shiver', 'shrink', 'shrug', 'sigh', 'sing',
'sit', 'skip', 'slap', 'sleep', 'slide', 'slip', 'smash', 'snore', 'spar',
'speak', 'spit', 'stand', 'stare', 'step', 'sting', 'stomp', 'stretch',
'strike', 'study', 'stumble', 'swim', 'talk', 'think', 'tickle', 'travel',
'trot', 'twist', 'wait', 'walk', 'wander', 'watch', 'wave', 'whine',
'whisper', 'work', 'wriggle'
];
var adverbs = [
'ably', 'always', 'angrily', 'badly', 'blindly', 'boldly', 'bravely',
'briefly', 'brightly', 'busily', 'calmly', 'clearly', 'cruelly', 'daily',
'easily', 'equally', 'exactly', 'fast', 'fiercely', 'fondly', 'gently',
'gladly', 'greedily', 'happily', 'hastily', 'honestly', 'hourly',
'hungrily', 'joyously', 'justly', 'kindly', 'lazily', 'loosely', 'loudly',
'madly', 'merrily', 'monthly', 'neatly', 'often', 'poorly', 'promptly',
'quickly', 'quietly', 'rarely', 'roughly', 'rudely', 'sadly', 'safely',
'sharply', 'shyly', 'slowly', 'smoothly', 'softly', 'soon', 'sternly',
'swiftly', 'tensely', 'tightly', 'too', 'warmly', 'weakly', 'well',
'wildly', 'yearly'
];
module.exports = {
subjects: subjects,
adjectives: adjectives,
verbs: verbs,
adverbs: adverbs
};
},{}],4:[function(require,module,exports){
var WordGenerator = require('./word_generator');
var assert = require('assert');
var util = require('util');
/**
* A word generator that draws from a dictionary of words.
*
* @param words {String[]} List of words the dictionary should draw on.
* The length must be an even power of two.
* @constructor
*/
function Dictionary(words) {
var size = words.length;
this._numBits = 0;
for (var x = size; x > 1; x = x >> 1) {
if (x % 2 === 1) {
throw new Error('Dictionary size is not an even power of two: ' + size);
}
this._numBits++;
}
assert.equal(words.length, this.size());
this._words = words;
}
util.inherits(Dictionary, WordGenerator);
Dictionary.prototype.numBits = function() {
return this._numBits;
};
Dictionary.prototype.word = function(num) {
assert.equal(typeof(num), 'number');
assert(num >= 0);
assert(num < this.size());
return '' + this._words[num];
};
module.exports = Dictionary;
},{"./word_generator":7,"assert":8,"util":12}],5:[function(require,module,exports){
var assert = require('assert');
var bitGenerator = require('./bit_generator');
var WordGenerator = require('./word_generator');
/**
* @param generators {WordGenerator[]}
* @constructor
*/
function Factory(generators) {
var bits = 0;
generators.forEach(function(generator) {
assert(generator instanceof WordGenerator);
bits += generator.numBits();
});
assert(bits > 0);
this.generators = generators;
this._numBits = bits;
}
/**
* @returns {string[]} An array of words randomly chosen from amongst
* `numPossiblePhrases` possibilities.
*/
Factory.prototype.randomPhrase = function() {
return this.phraseFromBits(bitGenerator.random(this._numBits));
};
/**
* @param num {number}
* @returns {string[]} An array of words chosen to correspond to the integer
* supplied in `num`.
*/
Factory.prototype.phraseFromInt = function(num) {
return this.phraseFromBits(bitGenerator.int(num));
};
/**
* @param value {string}
* @returns {string[]} An array of words chosen to correspond to the hex
* value supplied.
*/
Factory.prototype.phraseFromHex = function(value) {
return this.phraseFromBits(bitGenerator.hex(value));
};
/**
* @param bitGen {function} A function that when called, returns a 1 or 0
* starting from least to most significant bit
* @returns {string[]} The specific phrase (array of words) corresponding to
* the number built up from the bit stream.
*/
Factory.prototype.phraseFromBits = function(bitGen) {
assert.equal(typeof(bitGen), 'function');
var words = [];
this.generators.forEach(function(generator) {
// Shift off the number of bits the generator expects and use it
// to generate the next word in the phrase. We can't use regular bit-shift
// ops though because those cast to 32-bit and we want to preserve more
// bits than that.
var numBits = generator.numBits();
var wordIndex = 0;
for (var i = 0; i < numBits; i++) {
var bit = bitGen() || 0;
wordIndex += (bit << i);
console.log(bit, wordIndex);
}
words.push(generator.word(wordIndex));
});
return words;
};
/**
* @returns {number} The total number of possible phrases this could return.
*/
Factory.prototype.numPossiblePhrases = function() {
return Math.pow(2, this._numBits); // left-shift would truncate to 32-bit int
};
module.exports = Factory;
},{"./bit_generator":2,"./word_generator":7,"assert":8}],6:[function(require,module,exports){
var WordGenerator = require('./word_generator');
var assert = require('assert');
var util = require('util');
/**
* A word generator that generates a number.
*
* @param numBits {number} Generate numbers with this many bits in depth.
* @param offset {number} Offset all generated numbers by this amount.
* @constructor
*/
function NumberRange(numBits, offset) {
this._numBits = numBits;
this._offset = offset || 0;
}
util.inherits(NumberRange, WordGenerator);
NumberRange.prototype.numBits = function() {
return this._numBits;
};
NumberRange.prototype.word = function(num) {
assert.equal(typeof(num), 'number');
assert(num >= 0);
assert(num < this.size());
return '' + (num + this._offset);
};
module.exports = NumberRange;
},{"./word_generator":7,"assert":8,"util":12}],7:[function(require,module,exports){
function WordGenerator() {}
/**
* @return {Number} Number of bits of information this generator makes.
*/
WordGenerator.prototype.numBits = function() {
throw new Error('not implemented');
};
/**
* @param num {Number} An integer, 0 <= number < 2^numBits
* @return {String} The word for the given number
*/
WordGenerator.prototype.word = function() {
throw new Error('not implemented');
};
/**
* @returns {number} Number of values this generator can make.
*/
WordGenerator.prototype.size = function() {
return 1 << this.numBits();
};
module.exports = WordGenerator;
},{}],8:[function(require,module,exports){
// http://wiki.commonjs.org/wiki/Unit_Testing/1.0
//
// THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8!
//
// Originally from narwhal.js (http://narwhaljs.org)
// Copyright (c) 2009 Thomas Robinson <280north.com>
//
// 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 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.
// when used in node, this will actually load the util module we depend on
// versus loading the builtin util module as happens otherwise
// this is a bug in node module loading as far as I am concerned
var util = require('util/');
var pSlice = Array.prototype.slice;
var hasOwn = Object.prototype.hasOwnProperty;
// 1. The assert module provides functions that throw
// AssertionError's when particular conditions are not met. The
// assert module must conform to the following interface.
var assert = module.exports = ok;
// 2. The AssertionError is defined in assert.
// new assert.AssertionError({ message: message,
// actual: actual,
// expected: expected })
assert.AssertionError = function AssertionError(options) {
this.name = 'AssertionError';
this.actual = options.actual;
this.expected = options.expected;
this.operator = options.operator;
if (options.message) {
this.message = options.message;
this.generatedMessage = false;
} else {
this.message = getMessage(this);
this.generatedMessage = true;
}
var stackStartFunction = options.stackStartFunction || fail;
if (Error.captureStackTrace) {
Error.captureStackTrace(this, stackStartFunction);
}
else {
// non v8 browsers so we can have a stacktrace
var err = new Error();
if (err.stack) {
var out = err.stack;
// try to strip useless frames
var fn_name = stackStartFunction.name;
var idx = out.indexOf('\n' + fn_name);
if (idx >= 0) {
// once we have located the function frame
// we need to strip out everything before it (and its line)
var next_line = out.indexOf('\n', idx + 1);
out = out.substring(next_line + 1);
}
this.stack = out;
}
}
};
// assert.AssertionError instanceof Error
util.inherits(assert.AssertionError, Error);
function replacer(key, value) {
if (util.isUndefined(value)) {
return '' + value;
}
if (util.isNumber(value) && !isFinite(value)) {
return value.toString();
}
if (util.isFunction(value) || util.isRegExp(value)) {
return value.toString();
}
return value;
}
function truncate(s, n) {
if (util.isString(s)) {
return s.length < n ? s : s.slice(0, n);
} else {
return s;
}
}
function getMessage(self) {
return truncate(JSON.stringify(self.actual, replacer), 128) + ' ' +
self.operator + ' ' +
truncate(JSON.stringify(self.expected, replacer), 128);
}
// At present only the three keys mentioned above are used and
// understood by the spec. Implementations or sub modules can pass
// other keys to the AssertionError's constructor - they will be
// ignored.
// 3. All of the following functions must throw an AssertionError
// when a corresponding condition is not met, with a message that
// may be undefined if not provided. All assertion methods provide
// both the actual and expected values to the assertion error for
// display purposes.
function fail(actual, expected, message, operator, stackStartFunction) {
throw new assert.AssertionError({
message: message,
actual: actual,
expected: expected,
operator: operator,
stackStartFunction: stackStartFunction
});
}
// EXTENSION! allows for well behaved errors defined elsewhere.
assert.fail = fail;
// 4. Pure assertion tests whether a value is truthy, as determined
// by !!guard.
// assert.ok(guard, message_opt);
// This statement is equivalent to assert.equal(true, !!guard,
// message_opt);. To test strictly for the value true, use
// assert.strictEqual(true, guard, message_opt);.
function ok(value, message) {
if (!value) fail(value, true, message, '==', assert.ok);
}
assert.ok = ok;
// 5. The equality assertion tests shallow, coercive equality with
// ==.
// assert.equal(actual, expected, message_opt);
assert.equal = function equal(actual, expected, message) {
if (actual != expected) fail(actual, expected, message, '==', assert.equal);
};
// 6. The non-equality assertion tests for whether two objects are not equal
// with != assert.notEqual(actual, expected, message_opt);
assert.notEqual = function notEqual(actual, expected, message) {
if (actual == expected) {
fail(actual, expected, message, '!=', assert.notEqual);
}
};
// 7. The equivalence assertion tests a deep equality relation.
// assert.deepEqual(actual, expected, message_opt);
assert.deepEqual = function deepEqual(actual, expected, message) {
if (!_deepEqual(actual, expected)) {
fail(actual, expected, message, 'deepEqual', assert.deepEqual);
}
};
function _deepEqual(actual, expected) {
// 7.1. All identical values are equivalent, as determined by ===.
if (actual === expected) {
return true;
} else if (util.isBuffer(actual) && util.isBuffer(expected)) {
if (actual.length != expected.length) return false;
for (var i = 0; i < actual.length; i++) {
if (actual[i] !== expected[i]) return false;
}
return true;
// 7.2. If the expected value is a Date object, the actual value is
// equivalent if it is also a Date object that refers to the same time.
} else if (util.isDate(actual) && util.isDate(expected)) {
return actual.getTime() === expected.getTime();
// 7.3 If the expected value is a RegExp object, the actual value is
// equivalent if it is also a RegExp object with the same source and
// properties (`global`, `multiline`, `lastIndex`, `ignoreCase`).
} else if (util.isRegExp(actual) && util.isRegExp(expected)) {
return actual.source === expected.source &&
actual.global === expected.global &&
actual.multiline === expected.multiline &&
actual.lastIndex === expected.lastIndex &&
actual.ignoreCase === expected.ignoreCase;
// 7.4. Other pairs that do not both pass typeof value == 'object',
// equivalence is determined by ==.
} else if (!util.isObject(actual) && !util.isObject(expected)) {
return actual == expected;
// 7.5 For all other Object pairs, including Array objects, equivalence is
// determined by having the same number of owned properties (as verified
// with Object.prototype.hasOwnProperty.call), the same set of keys
// (although not necessarily the same order), equivalent values for every
// corresponding key, and an identical 'prototype' property. Note: this
// accounts for both named and indexed properties on Arrays.
} else {
return objEquiv(actual, expected);
}
}
function isArguments(object) {
return Object.prototype.toString.call(object) == '[object Arguments]';
}
function objEquiv(a, b) {
if (util.isNullOrUndefined(a) || util.isNullOrUndefined(b))
return false;
// an identical 'prototype' property.
if (a.prototype !== b.prototype) return false;
// if one is a primitive, the other must be same
if (util.isPrimitive(a) || util.isPrimitive(b)) {
return a === b;
}
var aIsArgs = isArguments(a),
bIsArgs = isArguments(b);
if ((aIsArgs && !bIsArgs) || (!aIsArgs && bIsArgs))
return false;
if (aIsArgs) {
a = pSlice.call(a);
b = pSlice.call(b);
return _deepEqual(a, b);
}
var ka = objectKeys(a),
kb = objectKeys(b),
key, i;
// having the same number of owned properties (keys incorporates
// hasOwnProperty)
if (ka.length != kb.length)
return false;
//the same set of keys (although not necessarily the same order),
ka.sort();
kb.sort();
//~~~cheap key test
for (i = ka.length - 1; i >= 0; i--) {
if (ka[i] != kb[i])
return false;
}
//equivalent values for every corresponding key, and
//~~~possibly expensive deep test
for (i = ka.length - 1; i >= 0; i--) {
key = ka[i];
if (!_deepEqual(a[key], b[key])) return false;
}
return true;
}
// 8. The non-equivalence assertion tests for any deep inequality.
// assert.notDeepEqual(actual, expected, message_opt);
assert.notDeepEqual = function notDeepEqual(actual, expected, message) {
if (_deepEqual(actual, expected)) {
fail(actual, expected, message, 'notDeepEqual', assert.notDeepEqual);
}
};
// 9. The strict equality assertion tests strict equality, as determined by ===.
// assert.strictEqual(actual, expected, message_opt);
assert.strictEqual = function strictEqual(actual, expected, message) {
if (actual !== expected) {
fail(actual, expected, message, '===', assert.strictEqual);
}
};
// 10. The strict non-equality assertion tests for strict inequality, as
// determined by !==. assert.notStrictEqual(actual, expected, message_opt);
assert.notStrictEqual = function notStrictEqual(actual, expected, message) {
if (actual === expected) {
fail(actual, expected, message, '!==', assert.notStrictEqual);
}
};
function expectedException(actual, expected) {
if (!actual || !expected) {
return false;
}
if (Object.prototype.toString.call(expected) == '[object RegExp]') {
return expected.test(actual);
} else if (actual instanceof expected) {
return true;
} else if (expected.call({}, actual) === true) {
return true;
}
return false;
}
function _throws(shouldThrow, block, expected, message) {
var actual;
if (util.isString(expected)) {
message = expected;
expected = null;
}
try {
block();
} catch (e) {
actual = e;
}
message = (expected && expected.name ? ' (' + expected.name + ').' : '.') +
(message ? ' ' + message : '.');
if (shouldThrow && !actual) {
fail(actual, expected, 'Missing expected exception' + message);
}
if (!shouldThrow && expectedException(actual, expected)) {
fail(actual, expected, 'Got unwanted exception' + message);
}
if ((shouldThrow && actual && expected &&
!expectedException(actual, expected)) || (!shouldThrow && actual)) {
throw actual;
}
}
// 11. Expected to throw an error:
// assert.throws(block, Error_opt, message_opt);
assert.throws = function(block, /*optional*/error, /*optional*/message) {
_throws.apply(this, [true].concat(pSlice.call(arguments)));
};
// EXTENSION! This is annoying to write outside this module.
assert.doesNotThrow = function(block, /*optional*/message) {
_throws.apply(this, [false].concat(pSlice.call(arguments)));
};
assert.ifError = function(err) { if (err) {throw err;}};
var objectKeys = Object.keys || function (obj) {
var keys = [];
for (var key in obj) {
if (hasOwn.call(obj, key)) keys.push(key);
}
return keys;
};
},{"util/":12}],9:[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
}
}
},{}],10:[function(require,module,exports){
// shim for using process in browser
var process = module.exports = {};
var queue = [];
var draining = false;
var currentQueue;
var queueIndex = -1;
function cleanUpNextTick() {
draining = false;
if (currentQueue.length) {
queue = currentQueue.concat(queue);
} else {
queueIndex = -1;
}
if (queue.length) {
drainQueue();
}
}
function drainQueue() {
if (draining) {
return;
}
var timeout = setTimeout(cleanUpNextTick);
draining = true;
var len = queue.length;
while(len) {
currentQueue = queue;
queue = [];
while (++queueIndex < len) {
currentQueue[queueIndex].run();
}
queueIndex = -1;
len = queue.length;
}
currentQueue = null;
draining = false;
clearTimeout(timeout);
}
process.nextTick = function (fun) {
var args = new Array(arguments.length - 1);
if (arguments.length > 1) {
for (var i = 1; i < arguments.length; i++) {
args[i - 1] = arguments[i];
}
}
queue.push(new Item(fun, args));
if (queue.length === 1 && !draining) {
setTimeout(drainQueue, 0);
}
};
// v8 likes predictible objects
function Item(fun, array) {
this.fun = fun;
this.array = array;
}
Item.prototype.run = function () {
this.fun.apply(null, this.array);
};
process.title = 'browser';
process.browser = true;
process.env = {};
process.argv = [];
process.version = ''; // empty string to avoid regexp issues
process.versions = {};
function noop() {}
process.on = noop;
process.addListener = noop;
process.once = noop;
process.off = noop;
process.removeListener = noop;
process.removeAllListeners = 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');
};
process.umask = function() { return 0; };
},{}],11:[function(require,module,exports){
module.exports = function isBuffer(arg) {
return arg && typeof arg === 'object'
&& typeof arg.copy === 'function'
&& typeof arg.fill === 'function'
&& typeof arg.readUInt8 === 'function';
}
},{}],12:[function(require,module,exports){
(function (process,global){
// Copyright Joyent, Inc. and other Node contributors.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
var formatRegExp = /%[sdj%]/g;
exports.format = function(f) {
if (!isString(f)) {
var objects = [];
for (var i = 0; i < arguments.length; i++) {
objects.push(inspect(arguments[i]));
}
return objects.join(' ');
}
var i = 1;
var args = arguments;
var len = args.length;
var str = String(f).replace(formatRegExp, function(x) {
if (x === '%%') return '%';
if (i >= len) return x;
switch (x) {
case '%s': return String(args[i++]);
case '%d': return Number(args[i++]);
case '%j':
try {
return JSON.stringify(args[i++]);
} catch (_) {
return '[Circular]';
}
default:
return x;
}
});
for (var x = args[i]; i < len; x = args[++i]) {
if (isNull(x) || !isObject(x)) {
str += ' ' + x;
} else {
str += ' ' + inspect(x);
}
}
return str;
};
// Mark that a method should not be used.
// Returns a modified function which warns once by default.
// If --no-deprecation is set, then it is a no-op.
exports.deprecate = function(fn, msg) {
// Allow for deprecating things in the process of starting up.
if (isUndefined(global.process)) {
return function() {
return exports.deprecate(fn, msg).apply(this, arguments);
};
}
if (process.noDeprecation === true) {
return fn;
}
var warned = false;
function deprecated() {
if (!warned) {
if (process.throwDeprecation) {
throw new Error(msg);
} else if (process.traceDeprecation) {
console.trace(msg);
} else {
console.error(msg);
}
warned = true;
}
return fn.apply(this, arguments);
}
return deprecated;
};
var debugs = {};
var debugEnviron;
exports.debuglog = function(set) {
if (isUndefined(debugEnviron))
debugEnviron = process.env.NODE_DEBUG || '';
set = set.toUpperCase();
if (!debugs[set]) {
if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) {
var pid = process.pid;
debugs[set] = function() {
var msg = exports.format.apply(exports, arguments);
console.error('%s %d: %s', set, pid, msg);
};
} else {
debugs[set] = function() {};
}
}
return debugs[set];
};
/**
* Echos the value of a value. Trys to print the value out
* in the best way possible given the different types.
*
* @param {Object} obj The object to print out.
* @param {Object} opts Optional options object that alters the output.
*/
/* legacy: obj, showHidden, depth, colors*/
function inspect(obj, opts) {
// default options
var ctx = {
seen: [],
stylize: stylizeNoColor
};
// legacy...
if (arguments.length >= 3) ctx.depth = arguments[2];
if (arguments.length >= 4) ctx.colors = arguments[3];
if (isBoolean(opts)) {
// legacy...
ctx.showHidden = opts;
} else if (opts) {
// got an "options" object
exports._extend(ctx, opts);
}
// set default options
if (isUndefined(ctx.showHidden)) ctx.showHidden = false;
if (isUndefined(ctx.depth)) ctx.depth = 2;
if (isUndefined(ctx.colors)) ctx.colors = false;
if (isUndefined(ctx.customInspect)) ctx.customInspect = true;
if (ctx.colors) ctx.stylize = stylizeWithColor;
return formatValue(ctx, obj, ctx.depth);
}
exports.inspect = inspect;
// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics
inspect.colors = {
'bold' : [1, 22],
'italic' : [3, 23],
'underline' : [4, 24],
'inverse' : [7, 27],
'white' : [37, 39],
'grey' : [90, 39],
'black' : [30, 39],
'blue' : [34, 39],
'cyan' : [36, 39],
'green' : [32, 39],
'magenta' : [35, 39],
'red' : [31, 39],
'yellow' : [33, 39]
};
// Don't use 'blue' not visible on cmd.exe
inspect.styles = {
'special': 'cyan',
'number': 'yellow',
'boolean': 'yellow',
'undefined': 'grey',
'null': 'bold',
'string': 'green',
'date': 'magenta',
// "name": intentionally not styling
'regexp': 'red'
};
function stylizeWithColor(str, styleType) {
var style = inspect.styles[styleType];
if (style) {
return '\u001b[' + inspect.colors[style][0] + 'm' + str +
'\u001b[' + inspect.colors[style][1] + 'm';
} else {
return str;
}
}
function stylizeNoColor(str, styleType) {
return str;
}
function arrayToHash(array) {
var hash = {};
array.forEach(function(val, idx) {
hash[val] = true;
});
return hash;
}
function formatValue(ctx, value, recurseTimes) {
// Provide a hook for user-specified inspect functions.
// Check that value is an object with an inspect function on it
if (ctx.customInspect &&
value &&
isFunction(value.inspect) &&
// Filter out the util module, it's inspect function is special
value.inspect !== exports.inspect &&
// Also filter out any prototype objects using the circular check.
!(value.constructor && value.constructor.prototype === value)) {
var ret = value.inspect(recurseTimes, ctx);
if (!isString(ret)) {
ret = formatValue(ctx, ret, recurseTimes);
}
return ret;
}
// Primitive types cannot have properties
var primitive = formatPrimitive(ctx, value);
if (primitive) {
return primitive;
}
// Look up the keys of the object.
var keys = Object.keys(value);
var visibleKeys = arrayToHash(keys);
if (ctx.showHidden) {
keys = Object.getOwnPropertyNames(value);
}
// IE doesn't make error fields non-enumerable
// http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx
if (isError(value)
&& (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) {
return formatError(value);
}
// Some type of object without properties can be shortcutted.
if (keys.length === 0) {
if (isFunction(value)) {
var name = value.name ? ': ' + value.name : '';
return ctx.stylize('[Function' + name + ']', 'special');
}
if (isRegExp(value)) {
return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
}
if (isDate(value)) {
return ctx.stylize(Date.prototype.toString.call(value), 'date');
}
if (isError(value)) {
return formatError(value);
}
}
var base = '', array = false, braces = ['{', '}'];
// Make Array say that they are Array
if (isArray(value)) {
array = true;
braces = ['[', ']'];
}
// Make functions say that they are functions
if (isFunction(value)) {
var n = value.name ? ': ' + value.name : '';
base = ' [Function' + n + ']';
}
// Make RegExps say that they are RegExps
if (isRegExp(value)) {
base = ' ' + RegExp.prototype.toString.call(value);
}
// Make dates with properties first say the date
if (isDate(value)) {
base = ' ' + Date.prototype.toUTCString.call(value);
}
// Make error with message first say the error
if (isError(value)) {
base = ' ' + formatError(value);
}
if (keys.length === 0 && (!array || value.length == 0)) {
return braces[0] + base + braces[1];
}
if (recurseTimes < 0) {
if (isRegExp(value)) {
return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
} else {
return ctx.stylize('[Object]', 'special');
}
}
ctx.seen.push(value);
var output;
if (array) {
output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);
} else {
output = keys.map(function(key) {
return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);
});
}
ctx.seen.pop();
return reduceToSingleString(output, base, braces);
}
function formatPrimitive(ctx, value) {
if (isUndefined(value))
return ctx.stylize('undefined', 'undefined');
if (isString(value)) {
var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
.replace(/'/g, "\\'")
.replace(/\\"/g, '"') + '\'';
return ctx.stylize(simple, 'string');
}
if (isNumber(value))
return ctx.stylize('' + value, 'number');
if (isBoolean(value))
return ctx.stylize('' + value, 'boolean');
// For some reason typeof null is "object", so special case here.
if (isNull(value))
return ctx.stylize('null', 'null');
}
function formatError(value) {
return '[' + Error.prototype.toString.call(value) + ']';
}
function formatArray(ctx, value, recurseTimes, visibleKeys, keys) {
var output = [];
for (var i = 0, l = value.length; i < l; ++i) {
if (hasOwnProperty(value, String(i))) {
output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
String(i), true));
} else {
output.push('');
}
}
keys.forEach(function(key) {
if (!key.match(/^\d+$/)) {
output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
key, true));
}
});
return output;
}
function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {
var name, str, desc;
desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] };
if (desc.get) {
if (desc.set) {
str = ctx.stylize('[Getter/Setter]', 'special');
} else {
str = ctx.stylize('[Getter]', 'special');
}
} else {
if (desc.set) {
str = ctx.stylize('[Setter]', 'special');
}
}
if (!hasOwnProperty(visibleKeys, key)) {
name = '[' + key + ']';
}
if (!str) {
if (ctx.seen.indexOf(desc.value) < 0) {
if (isNull(recurseTimes)) {
str = formatValue(ctx, desc.value, null);
} else {
str = formatValue(ctx, desc.value, recurseTimes - 1);
}
if (str.indexOf('\n') > -1) {
if (array) {
str = str.split('\n').map(function(line) {
return ' ' + line;
}).join('\n').substr(2);
} else {
str = '\n' + str.split('\n').map(function(line) {
return ' ' + line;
}).join('\n');
}
}
} else {
str = ctx.stylize('[Circular]', 'special');
}
}
if (isUndefined(name)) {
if (array && key.match(/^\d+$/)) {
return str;
}
name = JSON.stringify('' + key);
if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
name = name.substr(1, name.length - 2);
name = ctx.stylize(name, 'name');
} else {
name = name.replace(/'/g, "\\'")
.replace(/\\"/g, '"')
.replace(/(^"|"$)/g, "'");
name = ctx.stylize(name, 'string');
}
}
return name + ': ' + str;
}
function reduceToSingleString(output, base, braces) {
var numLinesEst = 0;
var length = output.reduce(function(prev, cur) {
numLinesEst++;
if (cur.indexOf('\n') >= 0) numLinesEst++;
return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1;
}, 0);
if (length > 60) {
return braces[0] +
(base === '' ? '' : base + '\n ') +
' ' +
output.join(',\n ') +
' ' +
braces[1];
}
return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
}
// NOTE: These type checking functions intentionally don't use `instanceof`
// because it is fragile and can be easily faked with `Object.create()`.
function isArray(ar) {
return Array.isArray(ar);
}
exports.isArray = isArray;
function isBoolean(arg) {
return typeof arg === 'boolean';
}
exports.isBoolean = isBoolean;
function isNull(arg) {
return arg === null;
}
exports.isNull = isNull;
function isNullOrUndefined(arg) {
return arg == null;
}
exports.isNullOrUndefined = isNullOrUndefined;
function isNumber(arg) {
return typeof arg === 'number';
}
exports.isNumber = isNumber;
function isString(arg) {
return typeof arg === 'string';
}
exports.isString = isString;
function isSymbol(arg) {
return typeof arg === 'symbol';
}
exports.isSymbol = isSymbol;
function isUndefined(arg) {
return arg === void 0;
}
exports.isUndefined = isUndefined;
function isRegExp(re) {
return isObject(re) && objectToString(re) === '[object RegExp]';
}
exports.isRegExp = isRegExp;
function isObject(arg) {
return typeof arg === 'object' && arg !== null;
}
exports.isObject = isObject;
function isDate(d) {
return isObject(d) && objectToString(d) === '[object Date]';
}
exports.isDate = isDate;
function isError(e) {
return isObject(e) &&
(objectToString(e) === '[object Error]' || e instanceof Error);
}
exports.isError = isError;
function isFunction(arg) {
return typeof arg === 'function';
}
exports.isFunction = isFunction;
function isPrimitive(arg) {
return arg === null ||
typeof arg === 'boolean' ||
typeof arg === 'number' ||
typeof arg === 'string' ||
typeof arg === 'symbol' || // ES6 symbol
typeof arg === 'undefined';
}
exports.isPrimitive = isPrimitive;
exports.isBuffer = require('./support/isBuffer');
function objectToString(o) {
return Object.prototype.toString.call(o);
}
function pad(n) {
return n < 10 ? '0' + n.toString(10) : n.toString(10);
}
var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep',
'Oct', 'Nov', 'Dec'];
// 26 Feb 16:19:34
function timestamp() {
var d = new Date();
var time = [pad(d.getHours()),
pad(d.getMinutes()),
pad(d.getSeconds())].join(':');
return [d.getDate(), months[d.getMonth()], time].join(' ');
}
// log is just a thin wrapper to console.log that prepends a timestamp
exports.log = function() {
console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments));
};
/**
* Inherit the prototype methods from one constructor into another.
*
* The Function.prototype.inherits from lang.js rewritten as a standalone
* function (not on Function.prototype). NOTE: If this file is to be loaded
* during bootstrapping this function needs to be rewritten using some native
* functions as prototype setup using normal JavaScript does not work as
* expected during bootstrapping (see mirror.js in r114903).
*
* @param {function} ctor Constructor function which needs to inherit the
* prototype.
* @param {function} superCtor Constructor function to inherit prototype from.
*/
exports.inherits = require('inherits');
exports._extend = function(origin, add) {
// Don't do anything if add isn't an object
if (!add || !isObject(add)) return origin;
var keys = Object.keys(add);
var i = keys.length;
while (i--) {
origin[keys[i]] = add[keys[i]];
}
return origin;
};
function hasOwnProperty(obj, prop) {
return Object.prototype.hasOwnProperty.call(obj, prop);
}
}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
},{"./support/isBuffer":11,"_process":10,"inherits":9}]},{},[1])(1)
});