<commit_before>var url = require('url');
var npmPackage = require('../package.json');

module.exports.create = function (pages) {
    var har = {
        'log': {
            'version': '1.2',
            'creator': {
                'name': 'Chrome HAR Capturer',
                'version': npmPackage.version,
            },
            'pages': [],
            'entries': []
        }
    };
    pages.forEach(function (page) {
        if (!page.isFailed()) {
            var pageHar = fromPage(page);
            har.log.pages.push(pageHar.info);
            Array.prototype.push.apply(har.log.entries, pageHar.entries);
        }
    });
    return har;
};

function fromPage(page) {
    // page timings
    var startedDateTime = new Date(page.originalRequestMs).toISOString();
    var onContentLoad = page.domContentEventFiredMs - page.originalRequestMs;
    var onLoad = page.loadEventFiredMs - page.originalRequestMs;
    // entries
    var entries = [];
    for (var requestId in page.objects) {
        var object = page.objects[requestId];
        // skip incomplete entries, those that have no timing information (since
        // it's optional) or data URI requests
        if (!object.responseMessage || !object.responseFinishedMs ||
            !object.responseMessage.response.timing ||
            object.requestMessage.request.url.match('^data:')) {
            continue;
        }
        // check for redirections
        var redirectUrl = '';
        if (object.requestMessage.redirectResponse) {
            redirectUrl = object.requestMessage.redirectResponse.url;
        }
        // process headers
        var requestHeaders = convertHeaders(object.requestMessage.request.headers);
        var responseHeaders = convertHeaders(object.responseMessage.response.headers);
        // add status line length (12 = "HTTP/1.x" + "  " + "\r\n")
        requestHeaders.size += (object.requestMessage.request.method.length +
                                object.requestMessage.request.url.length + 12);
        responseHeaders.size += (object.responseMessage.response.status.toString().length +
                                 object.responseMessage.response.statusText.length + 12);
        // query string
        var queryString = convertQueryString(object.requestMessage.request.url);
        // object timings
        // - timing.requestTime: seconds
        // - timing.*Start/End: milliseconds from the above
        var timing = object.responseMessage.response.timing;
        timing.requestTime *= 1000; // to ms
        var dnsTime = timingDelta(timing.dnsStart, timing.dnsEnd);
        var connectTime = timingDelta(timing.connectStart, timing.connectEnd);
        var proxyTime = timingDelta(timing.proxyStart, timing.proxyEnd);
        var sendTime = timingDelta(timing.sendStart, timing.sendEnd);
        var sslTime = timingDelta(timing.sslStart, timing.sslEnd);
        // computed timings
        var waitTime = timing.receiveHeadersEnd - timing.sendEnd;
        var receiveTime = object.responseFinishedMs - (timing.requestTime + timing.receiveHeadersEnd);
        var totalTime = dnsTime + connectTime + sendTime + waitTime + receiveTime + sslTime;
        // fill entry
        entries.push({
            'pageref': page.id.toString(),
            'startedDateTime': new Date(timing.requestTime).toISOString(),
            'time': totalTime,
            'request': {
                'method': object.requestMessage.request.method,
                'url': object.requestMessage.request.url,
                'httpVersion': 'HTTP/1.1', // TODO
                'cookies': [], // TODO
                'headers': requestHeaders.pairs,
                'queryString': queryString,
                'headersSize': requestHeaders.size,
                'bodySize': object.requestMessage.request.headers['Content-Length'] || -1,
            },
            'response': {
                'status': object.responseMessage.response.status,
                'statusText': object.responseMessage.response.statusText,
                'httpVersion': 'HTTP/1.1', // TODO
                'cookies': [], // TODO
                'headers': responseHeaders.pairs,
                'redirectURL': redirectUrl,
                'headersSize': responseHeaders.size,
                'bodySize': object.encodedResponseLength,
                'content': {
                    'size': object.responseLength,
                    'mimeType': object.responseMessage.response.mimeType,
                    'compression': object.responseLength - object.encodedResponseLength // TODO sometimes negative
                }
            },
            'cache': {},
            'timings': {
                'blocked': -1, // TODO
                'dns': dnsTime,
                'connect': object.responseMessage.response.connectionReused ? -1 : connectTime,
                'send': sendTime,
                'wait': waitTime,
                'receive': receiveTime,
                'ssl': sslTime
            }
        });
    }
    // outcome
    return {
        'info': {
            'startedDateTime': startedDateTime,
            'id': page.id.toString(),
            'title': page.url,
            'pageTimings': {
                'onContentLoad': onContentLoad,
                'onLoad': onLoad
            }
        },
        'entries': entries
    };
}

function timingDelta(start, end) {
    return start != -1 && end != -1 ? (end - start) : 0;
}

function convertQueryString(fullUrl) {
    var query = url.parse(fullUrl, true).query;
    var pairs = [];
    for (var name in query) {
        var value = query[name];
        pairs.push({'name': name, 'value': value.toString()});
    }
    return pairs;
}

function convertHeaders(headers) {
    headersObject = {'pairs': [], 'size': undefined};
    if (Object.keys(headers).length) {
        headersObject.size = 2; // trailing "\r\n"
        for (var name in headers) {
            var value = headers[name];
            headersObject.pairs.push({'name': name, 'value': value});
            headersObject.size += name.length + value.length + 4; // ": " + "\r\n"
        }
    }
    return headersObject;
}
<commit_msg>Add remote IP address and connection id to entries<commit_after>var url = require('url');
var npmPackage = require('../package.json');

module.exports.create = function (pages) {
    var har = {
        'log': {
            'version': '1.2',
            'creator': {
                'name': 'Chrome HAR Capturer',
                'version': npmPackage.version,
            },
            'pages': [],
            'entries': []
        }
    };
    pages.forEach(function (page) {
        if (!page.isFailed()) {
            var pageHar = fromPage(page);
            har.log.pages.push(pageHar.info);
            Array.prototype.push.apply(har.log.entries, pageHar.entries);
        }
    });
    return har;
};

function fromPage(page) {
    // page timings
    var startedDateTime = new Date(page.originalRequestMs).toISOString();
    var onContentLoad = page.domContentEventFiredMs - page.originalRequestMs;
    var onLoad = page.loadEventFiredMs - page.originalRequestMs;
    // entries
    var entries = [];
    for (var requestId in page.objects) {
        var object = page.objects[requestId];
        // skip incomplete entries, those that have no timing information (since
        // it's optional) or data URI requests
        if (!object.responseMessage || !object.responseFinishedMs ||
            !object.responseMessage.response.timing ||
            object.requestMessage.request.url.match('^data:')) {
            continue;
        }
        // check for redirections
        var redirectUrl = '';
        if (object.requestMessage.redirectResponse) {
            redirectUrl = object.requestMessage.redirectResponse.url;
        }
        // process headers
        var requestHeaders = convertHeaders(object.requestMessage.request.headers);
        var responseHeaders = convertHeaders(object.responseMessage.response.headers);
        // add status line length (12 = "HTTP/1.x" + "  " + "\r\n")
        requestHeaders.size += (object.requestMessage.request.method.length +
                                object.requestMessage.request.url.length + 12);
        responseHeaders.size += (object.responseMessage.response.status.toString().length +
                                 object.responseMessage.response.statusText.length + 12);
        // query string
        var queryString = convertQueryString(object.requestMessage.request.url);
        // object timings
        // - timing.requestTime: seconds
        // - timing.*Start/End: milliseconds from the above
        var timing = object.responseMessage.response.timing;
        timing.requestTime *= 1000; // to ms
        var dnsTime = timingDelta(timing.dnsStart, timing.dnsEnd);
        var connectTime = timingDelta(timing.connectStart, timing.connectEnd);
        var proxyTime = timingDelta(timing.proxyStart, timing.proxyEnd);
        var sendTime = timingDelta(timing.sendStart, timing.sendEnd);
        var sslTime = timingDelta(timing.sslStart, timing.sslEnd);
        // computed timings
        var waitTime = timing.receiveHeadersEnd - timing.sendEnd;
        var receiveTime = object.responseFinishedMs - (timing.requestTime + timing.receiveHeadersEnd);
        var totalTime = dnsTime + connectTime + sendTime + waitTime + receiveTime + sslTime;
        // connection information
        var serverIPAddress = object.responseMessage.response.remoteIPAddress;
        var connection = object.responseMessage.response.connectionId;
        // fill entry
        entries.push({
            'pageref': page.id.toString(),
            'startedDateTime': new Date(timing.requestTime).toISOString(),
            'time': totalTime,
            'request': {
                'method': object.requestMessage.request.method,
                'url': object.requestMessage.request.url,
                'httpVersion': 'HTTP/1.1', // TODO
                'cookies': [], // TODO
                'headers': requestHeaders.pairs,
                'queryString': queryString,
                'headersSize': requestHeaders.size,
                'bodySize': object.requestMessage.request.headers['Content-Length'] || -1,
            },
            'response': {
                'status': object.responseMessage.response.status,
                'statusText': object.responseMessage.response.statusText,
                'httpVersion': 'HTTP/1.1', // TODO
                'cookies': [], // TODO
                'headers': responseHeaders.pairs,
                'redirectURL': redirectUrl,
                'headersSize': responseHeaders.size,
                'bodySize': object.encodedResponseLength,
                'content': {
                    'size': object.responseLength,
                    'mimeType': object.responseMessage.response.mimeType,
                    'compression': object.responseLength - object.encodedResponseLength // TODO sometimes negative
                }
            },
            'cache': {},
            'timings': {
                'blocked': -1, // TODO
                'dns': dnsTime,
                'connect': object.responseMessage.response.connectionReused ? -1 : connectTime,
                'send': sendTime,
                'wait': waitTime,
                'receive': receiveTime,
                'ssl': sslTime
            },
            'serverIPAddress': serverIPAddress,
            'connection': connection.toString()
        });
    }
    // outcome
    return {
        'info': {
            'startedDateTime': startedDateTime,
            'id': page.id.toString(),
            'title': page.url,
            'pageTimings': {
                'onContentLoad': onContentLoad,
                'onLoad': onLoad
            }
        },
        'entries': entries
    };
}

function timingDelta(start, end) {
    return start != -1 && end != -1 ? (end - start) : 0;
}

function convertQueryString(fullUrl) {
    var query = url.parse(fullUrl, true).query;
    var pairs = [];
    for (var name in query) {
        var value = query[name];
        pairs.push({'name': name, 'value': value.toString()});
    }
    return pairs;
}

function convertHeaders(headers) {
    headersObject = {'pairs': [], 'size': undefined};
    if (Object.keys(headers).length) {
        headersObject.size = 2; // trailing "\r\n"
        for (var name in headers) {
            var value = headers[name];
            headersObject.pairs.push({'name': name, 'value': value});
            headersObject.size += name.length + value.length + 4; // ": " + "\r\n"
        }
    }
    return headersObject;
}
<|endoftext|>


<commit_before>//----------------------------------------------------------------------------------------------------------------------
// This is the main database logic. It implements a thin wrapper around a plain object, as well as logic for persisting
// to disk.
//
// @module jdb.js
//----------------------------------------------------------------------------------------------------------------------

var path = require('path');
var util = require('util');
var EventEmitter = require('events').EventEmitter;

var _ = require('lodash');
var uuid = require('node-uuid');
var Promise = require('bluebird');

var fs = Promise.promisifyAll(require('fs'));

//----------------------------------------------------------------------------------------------------------------------

function JDB(name, options)
{
    EventEmitter.call(this);

    // We disable warnings about max listeners.
    this.setMaxListeners(0);

    this.values = {};

    this._name = name;
    this._dirty = false;
    this._writing = false;
    this._lastWritten = Date.now();

    this.options = _.defaults(options || {}, {
        writeToDisk: true,
        loadFromDisk: true,
        rootPath: "./",
        writeDelay: 0,
        prettyPrint: true,
        idFunc: uuid.v4
    });

    // Optionally load this database from disk
    if(this.options.loadFromDisk)
    {
        this._loadFromDisk();
    } // end if

    // Register for the sync event
    this.on('sync', this.sync.bind(this));
} // end JDB

util.inherits(JDB, EventEmitter);

Object.defineProperties(JDB.prototype, {
    name: {
        get: function()
        {
            return this._name;
        }
    },
    rootPath: {
        get: function()
        {
            if(!this._rootPath)
            {
                this._rootPath = path.resolve(this.options.rootPath);
            } // end if

            return this._rootPath;
        }
    },
    path: {
        get:function()
        {
            return path.join(this.rootPath, this._name) + '.json';
        }
    }
}); // end properties

//----------------------------------------------------------------------------------------------------------------------
// Private functions
//----------------------------------------------------------------------------------------------------------------------

JDB.prototype._loadFromDisk = function()
{
    if(fs.existsSync(this.path))
    {
        var jsonStr = fs.readFileSync(this.path);

        try
        {
            this.values = JSON.parse(jsonStr);
        }
        catch(ex)
        {
            // Wrap the exception in a more friendly one.
            var error = new Error("Failed to parse on disk json file.");
            error.innerException = ex;

            // Throw the error
            throw error;
        } // end try/catch
    } // end if
}; // end loadFromDisk

JDB.prototype._writeToDisk = function()
{
    var self = this;

    if(this.options.writeToDisk && this._dirty && !this._writing)
    {
        // We're definitely going to schedule a write, so we flag it.
        this._writing = true;

        // We calculate how many milliseconds are left before we can next write, and take the max of that and 0.
        // This means that if it's been `writeDelay` or more milliseconds since we last wrote, we'll write on
        // the next tick.
        var timeout = Math.max((this._lastWritten + this.options.writeDelay) - Date.now(), 0);

        return Promise.delay(timeout)
            .then(function()
            {
                self._dirty = false;

                // If we're set to pretty print, we use a 4 space indent, otherwise, undefined.
                // See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#space_argument
                var indent = self.options.prettyPrint ? 4 : undefined;

                // Build our json string
                var jsonStr = JSON.stringify(self.values, null, indent);

                return fs.writeFileAsync(self.path, jsonStr);
            })
            .then(function()
            {
                self._writing = false;

                // Check to see if the db has been marked dirty since we started our write.
                if(self._dirty)
                {
                    return self._writeToDisk();
                } // end if
            });
    }
    else
    {
        // Writing to disk is disabled, we're not dirty, or we're currently writing; resolve the promise.
        return Promise.resolve();
    } // end if
}; // end _writeToDisk

//----------------------------------------------------------------------------------------------------------------------
// Public API
//----------------------------------------------------------------------------------------------------------------------

JDB.prototype.get = function(key)
{
    return Promise.resolve(this.values[key]);
}; // end get

JDB.prototype.store = function(name, value)
{
    if(!value)
    {
        value = name;
        name = undefined;
    } // end if

    if(name === undefined && this.options.pk)
    {
        name = value[this.options.pk];
    } // end if

    if(name === undefined)
    {
        name = this.options.idFunc(value);
    } // end if

    this.values[name] = value;

    // Schedule a sync
    this.emit('sync');

    return Promise.resolve(name);
}; // end store

JDB.prototype.merge = function(key, partial)
{
    var val = this.values[key] || {};
    _.merge(val, partial);

    this.values[key] = val;

    // Schedule a sync
    this.emit('sync');

    return Promise.resolve(val);
}; // end merge

JDB.prototype.filter = function(filter)
{
    return Promise.resolve(_.pick(this.values, _.createCallback(filter)));
}; // end filter

JDB.prototype.remove = function(filter)
{
    var self = this;
    if(_.isString(filter) || _.isArray(filter))
    {
        self.values = _.omit(this.values, filter);
    }
    else
    {
        self.values = _.omit(this.values, _.createCallback(filter));
    } // end if

    // Schedule a sync
    this.emit('sync');

    return Promise.resolve();
}; // end remove

JDB.prototype.sync = function()
{
    this._dirty = true;
    return this._writeToDisk();
}; // end sync

//----------------------------------------------------------------------------------------------------------------------

module.exports = JDB;

//----------------------------------------------------------------------------------------------------------------------
<commit_msg>Make rootPath if it doesn't exist, and ensure that it's a directory.<commit_after>//----------------------------------------------------------------------------------------------------------------------
// This is the main database logic. It implements a thin wrapper around a plain object, as well as logic for persisting
// to disk.
//
// @module jdb.js
//----------------------------------------------------------------------------------------------------------------------

var path = require('path');
var util = require('util');
var EventEmitter = require('events').EventEmitter;

var _ = require('lodash');
var uuid = require('node-uuid');
var Promise = require('bluebird');

var fs = Promise.promisifyAll(require('fs'));
var mkdirp = Promise.promisify(require('mkdirp'));

var errors = require('./errors');

//----------------------------------------------------------------------------------------------------------------------

function JDB(name, options)
{
    EventEmitter.call(this);

    // We disable warnings about max listeners.
    this.setMaxListeners(0);

    this.values = {};

    this._name = name;
    this._dirty = false;
    this._writing = false;
    this._lastWritten = Date.now();

    this.options = _.defaults(options || {}, {
        writeToDisk: true,
        loadFromDisk: true,
        rootPath: "./",
        writeDelay: 0,
        prettyPrint: true,
        idFunc: uuid.v4
    });

    // Optionally load this database from disk
    if(this.options.loadFromDisk)
    {
        this._loadFromDisk();
    } // end if

    // Register for the sync event
    this.on('sync', this.sync.bind(this));
} // end JDB

util.inherits(JDB, EventEmitter);

Object.defineProperties(JDB.prototype, {
    name: {
        get: function()
        {
            return this._name;
        }
    },
    rootPath: {
        get: function()
        {
            if(!this._rootPath)
            {
                this._rootPath = path.resolve(this.options.rootPath);
            } // end if

            return this._rootPath;
        }
    },
    path: {
        get:function()
        {
            return path.join(this.rootPath, this._name) + '.json';
        }
    }
}); // end properties

//----------------------------------------------------------------------------------------------------------------------
// Private functions
//----------------------------------------------------------------------------------------------------------------------

JDB.prototype._loadFromDisk = function()
{
    if(fs.existsSync(this.path))
    {
        var jsonStr = fs.readFileSync(this.path);

        try
        {
            this.values = JSON.parse(jsonStr);
        }
        catch(ex)
        {
            // Wrap the exception in a more friendly one.
            var error = new Error("Failed to parse on disk json file.");
            error.innerException = ex;

            // Throw the error
            throw error;
        } // end try/catch
    } // end if
}; // end loadFromDisk

JDB.prototype._writeToDisk = function()
{
    var self = this;

    if(this.options.writeToDisk && this._dirty && !this._writing)
    {
        // We're definitely going to schedule a write, so we flag it.
        this._writing = true;

        // We calculate how many milliseconds are left before we can next write, and take the max of that and 0.
        // This means that if it's been `writeDelay` or more milliseconds since we last wrote, we'll write on
        // the next tick.
        var timeout = Math.max((this._lastWritten + this.options.writeDelay) - Date.now(), 0);

        return Promise.delay(timeout)
            .then(function()
            {
                return fs.statAsync(self.rootPath);
            })
            .then(function(stats)
            {
                if(!stats.isDirectory())
                {
                    throw new errors.WriteError("Root path " + JSON.stringify(self.rootPath) + " is not a directory!");
                } // end if
            })
            .catch(function(error) { return error.code == 'ENOENT'; }, function()
            {
                return mkdirp(self.rootPath);
            })
            .then(function()
            {
                self._dirty = false;

                // If we're set to pretty print, we use a 4 space indent, otherwise, undefined.
                // See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#space_argument
                var indent = self.options.prettyPrint ? 4 : undefined;

                // Build our json string
                var jsonStr = JSON.stringify(self.values, null, indent);

                return fs.writeFileAsync(self.path, jsonStr);
            })
            .then(function()
            {
                self._writing = false;

                // Check to see if the db has been marked dirty since we started our write.
                if(self._dirty)
                {
                    return self._writeToDisk();
                } // end if
            })
            .catch(function(error) { return !(error instanceof errors.WriteError); }, function(error)
            {
                // Wrap any errors in a WriteError so the message says that writing the DB failed.
                throw new errors.WriteError(error.message).causedBy(error);
            });
    }
    else
    {
        // Writing to disk is disabled, we're not dirty, or we're currently writing; resolve the promise.
        return Promise.resolve();
    } // end if
}; // end _writeToDisk

//----------------------------------------------------------------------------------------------------------------------
// Public API
//----------------------------------------------------------------------------------------------------------------------

JDB.prototype.get = function(key)
{
    return Promise.resolve(this.values[key]);
}; // end get

JDB.prototype.store = function(name, value)
{
    if(!value)
    {
        value = name;
        name = undefined;
    } // end if

    if(name === undefined && this.options.pk)
    {
        name = value[this.options.pk];
    } // end if

    if(name === undefined)
    {
        name = this.options.idFunc(value);
    } // end if

    this.values[name] = value;

    // Schedule a sync
    this.emit('sync');

    return Promise.resolve(name);
}; // end store

JDB.prototype.merge = function(key, partial)
{
    var val = this.values[key] || {};
    _.merge(val, partial);

    this.values[key] = val;

    // Schedule a sync
    this.emit('sync');

    return Promise.resolve(val);
}; // end merge

JDB.prototype.filter = function(filter)
{
    return Promise.resolve(_.pick(this.values, _.createCallback(filter)));
}; // end filter

JDB.prototype.remove = function(filter)
{
    var self = this;
    if(_.isString(filter) || _.isArray(filter))
    {
        self.values = _.omit(this.values, filter);
    }
    else
    {
        self.values = _.omit(this.values, _.createCallback(filter));
    } // end if

    // Schedule a sync
    this.emit('sync');

    return Promise.resolve();
}; // end remove

JDB.prototype.sync = function()
{
    this._dirty = true;
    return this._writeToDisk();
}; // end sync

//----------------------------------------------------------------------------------------------------------------------

module.exports = JDB;

//----------------------------------------------------------------------------------------------------------------------
<|endoftext|>


<commit_before>/** @license MIT License (c) copyright 2010-2014 original author or authors */
/** @author Brian Cavalier */
/** @author John Hann */

exports.compare = compare;
exports.reduce = reduce;

var REMOVE, RIGHT, ADD, DOWN, SKIP;

exports.REMOVE = REMOVE = RIGHT = -1;
exports.ADD    = ADD    = DOWN  =  1;
exports.EQUAL  = SKIP   = 0;

var skip = { value: 1, type: SKIP };

/**
 * Create an lcs comparison matrix describing the differences
 * between two array-like sequences
 * @param {array} a array-like
 * @param {array} b array-like
 * @returns {object} lcs descriptor, suitable for passing to reduce()
 */
function compare(a, b) {
	var cols = a.length;
	var rows = b.length;

	var prefix = findPrefix(a, b);
	var suffix = prefix < cols && prefix < rows
		? findSuffix(a, b, prefix)
		: 0;

	var remove = suffix + prefix - 1;
	cols -= remove;
	rows -= remove;
	var matrix = createMatrix(cols, rows);

	for (var j = cols - 1; j >= 0; --j) {
		for (var i = rows - 1; i >= 0; --i) {
			matrix[i][j] = backtrack(matrix, a, b, prefix, j, i);
		}
	}

	return {
		prefix: prefix,
		matrix: matrix,
		suffix: suffix
	};
}

/**
 * Reduce a set of lcs changes previously created using compare
 * @param {function(result:*, type:number, i:number, j:number)} f
 *  reducer function, where:
 *  - result is the current reduce value,
 *  - type is the type of change: ADD, REMOVE, or EQUAL
 *  - i is the index of the change location in b
 *  - j is the index of the change location in a
 * @param {*} r initial value
 * @param {object} lcs results returned by compare()
 * @returns {*} the final reduced value
 */
function reduce(f, r, lcs) {
	var i, j, k, op;

	var m = lcs.matrix;

	// Reduce shared prefix
	var l = lcs.prefix;
	for(i = 0;i < l; ++i) {
		r = f(r, SKIP, i, i);
	}

	// Reduce longest change span
	k = i;
	l = m.length;
	i = 0;
	j = 0;
	while(i < l) {
		op = m[i][j].type;
		r = f(r, op, i+k, j+k);

		switch(op) {
			case SKIP:  ++i; ++j; break;
			case RIGHT: ++j; break;
			case DOWN:  ++i; break;
		}
	}

	// Reduce shared suffix
	i += k;
	j += k;
	l = lcs.suffix;
	for(k = 0;k < l; ++k) {
		r = f(r, SKIP, i+k, j+k);
	}

	return r;
}

function findPrefix(a, b) {
	var i = 0;
	var l = Math.min(a.length, b.length);
	while(i < l && a[i] === b[i]) {
		++i;
	}
	return i;
}

function findSuffix(a, b) {
	var al = a.length - 1;
	var bl = b.length - 1;
	var l = Math.min(al, bl);
	var i = 0;
	while(i < l && a[al-i] === b[bl-i]) {
		++i;
	}
	return i;
}

function backtrack(matrix, a, b, start, j, i) {
	if (a[j+start] === b[i+start]) {
		return { value: matrix[i + 1][j + 1].value, type: SKIP };
	}
	if (matrix[i][j + 1].value < matrix[i + 1][j].value) {
		return { value: matrix[i][j + 1].value + 1, type: RIGHT };
	}

	return { value: matrix[i + 1][j].value + 1, type: DOWN };
}

function createMatrix (cols, rows) {
	var m = [], i, j, lastrow;

	// Fill the last row
	lastrow = m[rows] = [];
	for (j = 0; j<cols; ++j) {
		lastrow[j] = { value: cols - j, type: RIGHT };
	}

	// Fill the last col
	for (i = 0; i<rows; ++i) {
		m[i] = [];
		m[i][cols] = { value: rows - i, type: DOWN };
	}

	// Fill the last cell
	m[rows][cols] = { value: 0, type: SKIP };

	return m;
}
<commit_msg>Remove unused var. Fix jsdoc<commit_after>/** @license MIT License (c) copyright 2010-2014 original author or authors */
/** @author Brian Cavalier */
/** @author John Hann */

exports.compare = compare;
exports.reduce = reduce;

var REMOVE, RIGHT, ADD, DOWN, SKIP;

exports.REMOVE = REMOVE = RIGHT = -1;
exports.ADD    = ADD    = DOWN  =  1;
exports.EQUAL  = SKIP   = 0;

/**
 * Create an lcs comparison matrix describing the differences
 * between two array-like sequences
 * @param {array} a array-like
 * @param {array} b array-like
 * @returns {object} lcs descriptor, suitable for passing to reduce()
 */
function compare(a, b) {
	var cols = a.length;
	var rows = b.length;

	var prefix = findPrefix(a, b);
	var suffix = prefix < cols && prefix < rows
		? findSuffix(a, b, prefix)
		: 0;

	var remove = suffix + prefix - 1;
	cols -= remove;
	rows -= remove;
	var matrix = createMatrix(cols, rows);

	for (var j = cols - 1; j >= 0; --j) {
		for (var i = rows - 1; i >= 0; --i) {
			matrix[i][j] = backtrack(matrix, a, b, prefix, j, i);
		}
	}

	return {
		prefix: prefix,
		matrix: matrix,
		suffix: suffix
	};
}

/**
 * Reduce a set of lcs changes previously created using compare
 * @param {function(result:*, type:number, i:number, j:number)} f
 *  reducer function, where:
 *  - result is the current reduce value,
 *  - type is the type of change: ADD, REMOVE, or SKIP
 *  - i is the index of the change location in b
 *  - j is the index of the change location in a
 * @param {*} r initial value
 * @param {object} lcs results returned by compare()
 * @returns {*} the final reduced value
 */
function reduce(f, r, lcs) {
	var i, j, k, op;

	var m = lcs.matrix;

	// Reduce shared prefix
	var l = lcs.prefix;
	for(i = 0;i < l; ++i) {
		r = f(r, SKIP, i, i);
	}

	// Reduce longest change span
	k = i;
	l = m.length;
	i = 0;
	j = 0;
	while(i < l) {
		op = m[i][j].type;
		r = f(r, op, i+k, j+k);

		switch(op) {
			case SKIP:  ++i; ++j; break;
			case RIGHT: ++j; break;
			case DOWN:  ++i; break;
		}
	}

	// Reduce shared suffix
	i += k;
	j += k;
	l = lcs.suffix;
	for(k = 0;k < l; ++k) {
		r = f(r, SKIP, i+k, j+k);
	}

	return r;
}

function findPrefix(a, b) {
	var i = 0;
	var l = Math.min(a.length, b.length);
	while(i < l && a[i] === b[i]) {
		++i;
	}
	return i;
}

function findSuffix(a, b) {
	var al = a.length - 1;
	var bl = b.length - 1;
	var l = Math.min(al, bl);
	var i = 0;
	while(i < l && a[al-i] === b[bl-i]) {
		++i;
	}
	return i;
}

function backtrack(matrix, a, b, start, j, i) {
	if (a[j+start] === b[i+start]) {
		return { value: matrix[i + 1][j + 1].value, type: SKIP };
	}
	if (matrix[i][j + 1].value < matrix[i + 1][j].value) {
		return { value: matrix[i][j + 1].value + 1, type: RIGHT };
	}

	return { value: matrix[i + 1][j].value + 1, type: DOWN };
}

function createMatrix (cols, rows) {
	var m = [], i, j, lastrow;

	// Fill the last row
	lastrow = m[rows] = [];
	for (j = 0; j<cols; ++j) {
		lastrow[j] = { value: cols - j, type: RIGHT };
	}

	// Fill the last col
	for (i = 0; i<rows; ++i) {
		m[i] = [];
		m[i][cols] = { value: rows - i, type: DOWN };
	}

	// Fill the last cell
	m[rows][cols] = { value: 0, type: SKIP };

	return m;
}
<|endoftext|>


<commit_before>'use strict';

var utils = require('./utils');

Array.prototype.$_where = function(queryOrFunction) {

    if (utils.isFunction(queryOrFunction)) {
        return this.filter(queryOrFunction);
    }
    else {
        return utils.performSearch(Array.prototype.filter.bind(this), queryOrFunction);
    }
};

Array.prototype.$_orderBy = function(orderByKeys) {

    var keys = Object.keys(orderByKeys);
    var numKeys = keys.length;

    // convert asc/desc strings into 1/-1
    for (var i = 0; i < numKeys; i++) {
        var key = keys[i];
        var direction = orderByKeys[key];

        if (direction === 'asc' || direction === 'ascending') {
            orderByKeys[key] = 1;
        }
        else if (direction === 'desc' || direction === 'descending') {
            orderByKeys[key] = -1;
        }
    }

    return this.sort(function(item1, item2) {

        for (var i = 0; i < numKeys; i++) {
            var key = keys[i];
            var direction = orderByKeys[key];

            if (item1[key] === item2[key]) {
                continue;
            }
            else if (item1[key] > item2[key]) {
                return direction < 0 ? -1 : 1;
            }
            else if (item1[key] < item2[key]) {
                return direction < 0 ? 1 : -1;
            }
        }

        return 0;
    });
};

Array.prototype.$_select = function(selectList) {

    var keys = Object.keys(selectList || {});
    var numKeys = keys.length;

    return this.map(function(item) {
        var obj = {};

        for (var i = 0; i < numKeys; i++) {
            var key = keys[i];
            obj[key] = item[key];
        }

        return obj;
    });
};

Array.prototype.$_first = function(queryOrFunction) {

    var items = this;

    if (queryOrFunction) {
        items = utils.performSearch(Array.prototype.filter.bind(items), queryOrFunction);
    }

    return items.length > 0 ? items[0] : null;
};

Array.prototype.$_last = function(queryOrFunction) {

    var items = this;

    if (queryOrFunction) {
        items = utils.performSearch(Array.prototype.filter.bind(items), queryOrFunction);
    }

    return items.length > 0 ? items[items.length - 1] : null;
};

Array.prototype.$_any = function(queryOrFunction) {

    if (queryOrFunction) {
        if (utils.isFunction(queryOrFunction)) {
            return this.some(queryOrFunction)
        }
        else {
            return utils.performSearch(Array.prototype.some.bind(this), queryOrFunction);
        }
    }
    else {
        return this.length > 0;
    }
};

Array.prototype.$_all = function(queryOrFunction) {

    if (queryOrFunction) {
        if (utils.isFunction(queryOrFunction)) {
            return this.every(queryOrFunction);
        }
        else {
            return utils.performSearch(Array.prototype.every.bind(this), queryOrFunction);
        }
    }
    else {
        return this.length > 0;
    }
};

Array.prototype.$_skip = function(skipCount) {

    if (this.length > skipCount) {
        return this.slice(skipCount);
    }
    else {
        return [];
    }
};

Array.prototype.$_take = function(takeAmount) {

    if (this.length > takeAmount) {
        return this.slice(0, takeAmount);
    }
    else {
        return this;
    }
};

Array.prototype.$_count = function(queryOrFunction) {

    if (queryOrFunction) {
        return utils.performSearch(Array.prototype.filter.bind(this), queryOrFunction).length;
    }
    else {
        return this.length;
    }
};

Array.prototype.$_sum = function(keyOrFunction) {

    var numItems = this.length;
    if (numItems === 0) return null;

    if (utils.isFunction(keyOrFunction)) {
        var total = 0;

        for (var i = 0; i < numItems; i++) {
            var value = keyOrFunction(this[i]);
            total += value ? value : 0;
        }

        return total;
    }
    else {
        var total = 0;

        for (var i = 0; i < numItems; i++) {
            var item = this[i];
            var value = item[keyOrFunction];
            total += value ? value : 0;
        }

        return total;
    }
};

Array.prototype.$_min = function(keyOrFunction) {
    var numItems = this.length;
    if (numItems === 0) return null;

    var values = utils.getAggregateValues(this, keyOrFunction);

    var min = values[0];
    var numValues = values.length;

    for (var i = 0; i < numValues; i++) {
        var value = values[i];
        if (value < min) {
            min = value;
        }
    }

    return min;
};

Array.prototype.$_max = function(keyOrFunction) {
    var numItems = this.length;
    if (numItems === 0) return null;

    var values = utils.getAggregateValues(this, keyOrFunction);

    var max = values[0];
    var numValues = values.length;

    for (var i = 0; i < numValues; i++) {
        var value = values[i];
        if (value > max) {
            max = value;
        }
    }

    return max;
};

Array.prototype.$_average = function(key) {
    if (this.length === 0) return null;

    var total = this.$_sum(key);
    return total / this.length;
};<commit_msg>first, last and count functions now support function searches<commit_after>'use strict';

var utils = require('./utils');

Array.prototype.$_where = function(queryOrFunction) {

    if (utils.isFunction(queryOrFunction)) {
        return this.filter(queryOrFunction);
    }
    else {
        return utils.performSearch(Array.prototype.filter.bind(this), queryOrFunction);
    }
};

Array.prototype.$_orderBy = function(orderByKeys) {

    var keys = Object.keys(orderByKeys);
    var numKeys = keys.length;

    // convert asc/desc strings into 1/-1
    for (var i = 0; i < numKeys; i++) {
        var key = keys[i];
        var direction = orderByKeys[key];

        if (direction === 'asc' || direction === 'ascending') {
            orderByKeys[key] = 1;
        }
        else if (direction === 'desc' || direction === 'descending') {
            orderByKeys[key] = -1;
        }
    }

    return this.sort(function(item1, item2) {

        for (var i = 0; i < numKeys; i++) {
            var key = keys[i];
            var direction = orderByKeys[key];

            if (item1[key] === item2[key]) {
                continue;
            }
            else if (item1[key] > item2[key]) {
                return direction < 0 ? -1 : 1;
            }
            else if (item1[key] < item2[key]) {
                return direction < 0 ? 1 : -1;
            }
        }

        return 0;
    });
};

Array.prototype.$_select = function(selectList) {

    var keys = Object.keys(selectList || {});
    var numKeys = keys.length;

    return this.map(function(item) {
        var obj = {};

        for (var i = 0; i < numKeys; i++) {
            var key = keys[i];
            obj[key] = item[key];
        }

        return obj;
    });
};

Array.prototype.$_first = function(queryOrFunction) {

    var items = this;

    if (queryOrFunction) {
        items = items.$_where(queryOrFunction);
    }

    return items.length > 0 ? items[0] : null;
};

Array.prototype.$_last = function(queryOrFunction) {

    var items = this;

    if (queryOrFunction) {
        items = items.$_where(queryOrFunction);
    }

    return items.length > 0 ? items[items.length - 1] : null;
};

Array.prototype.$_any = function(queryOrFunction) {

    if (queryOrFunction) {
        if (utils.isFunction(queryOrFunction)) {
            return this.some(queryOrFunction)
        }
        else {
            return utils.performSearch(Array.prototype.some.bind(this), queryOrFunction);
        }
    }
    else {
        return this.length > 0;
    }
};

Array.prototype.$_all = function(queryOrFunction) {

    if (queryOrFunction) {
        if (utils.isFunction(queryOrFunction)) {
            return this.every(queryOrFunction);
        }
        else {
            return utils.performSearch(Array.prototype.every.bind(this), queryOrFunction);
        }
    }
    else {
        return this.length > 0;
    }
};

Array.prototype.$_skip = function(skipCount) {

    if (this.length > skipCount) {
        return this.slice(skipCount);
    }
    else {
        return [];
    }
};

Array.prototype.$_take = function(takeAmount) {

    if (this.length > takeAmount) {
        return this.slice(0, takeAmount);
    }
    else {
        return this;
    }
};

Array.prototype.$_count = function(queryOrFunction) {

    if (queryOrFunction) {
        return this.$_where(queryOrFunction).length;
    }
    else {
        return this.length;
    }
};

Array.prototype.$_sum = function(keyOrFunction) {

    var numItems = this.length;
    if (numItems === 0) return null;

    if (utils.isFunction(keyOrFunction)) {
        var total = 0;

        for (var i = 0; i < numItems; i++) {
            var value = keyOrFunction(this[i]);
            total += value ? value : 0;
        }

        return total;
    }
    else {
        var total = 0;

        for (var i = 0; i < numItems; i++) {
            var item = this[i];
            var value = item[keyOrFunction];
            total += value ? value : 0;
        }

        return total;
    }
};

Array.prototype.$_min = function(keyOrFunction) {
    var numItems = this.length;
    if (numItems === 0) return null;

    var values = utils.getAggregateValues(this, keyOrFunction);

    var min = values[0];
    var numValues = values.length;

    for (var i = 0; i < numValues; i++) {
        var value = values[i];
        if (value < min) {
            min = value;
        }
    }

    return min;
};

Array.prototype.$_max = function(keyOrFunction) {
    var numItems = this.length;
    if (numItems === 0) return null;

    var values = utils.getAggregateValues(this, keyOrFunction);

    var max = values[0];
    var numValues = values.length;

    for (var i = 0; i < numValues; i++) {
        var value = values[i];
        if (value > max) {
            max = value;
        }
    }

    return max;
};

Array.prototype.$_average = function(key) {
    if (this.length === 0) return null;

    var total = this.$_sum(key);
    return total / this.length;
};<|endoftext|>


<commit_before>'use strict';
let colors = require("colors/safe");

let ErrorMap = {
    unique_id: "id must be unique",
    empty_id: "Id can not be empty",
    pattern_null: 'Pattern cannot be null',
    no_handle_found: 'No handle found',
    no_transport_found: 'No transport found'
};

function error(type, client) {

    let err = new Error();
    err.type = type;
    err.message = ErrorMap[type];
    err.error = true;
    console.log(colors.red(JSON.stringify(err)));
    if (client == 1)
        process.exit(1);
    return err;

}

module.exports = {
    error: error,
    ErrorMap: ErrorMap
}
<commit_msg>Update log.js<commit_after>/* Copyright (c) 2016 Devis, MIT License */
'use strict';
let colors = require("colors/safe");

let ErrorMap = {
    unique_id: "id must be unique",
    empty_id: "Id can not be empty",
    pattern_null: 'Pattern cannot be null',
    no_handle_found: 'No handle found',
    no_transport_found: 'No transport found'
};

function error(type, client) {

    let err = new Error();
    err.type = type;
    err.message = ErrorMap[type];
    err.error = true;
    console.log(colors.red(JSON.stringify(err)));
    if (client == 1)
        process.exit(1);
    return err;

}

module.exports = {
    error: error,
    ErrorMap: ErrorMap
}
<|endoftext|>


<commit_before>var winston = require('winston');
var ENV = process.env.NODE_ENV;

function getLogger(module) {
  var path = module.filename.split('/').slice(-2).join('/');

  return new winston.Logger({
    transports: [
      new winston.transports.Console({
        colorize: true,
        level: ENV == 'development' ? 'debug' : 'error',
        label: path
      })
    ]
  });
}

module.exports = getLogger;<commit_msg>Now we are showing full path to file where we called logger<commit_after>var winston = require('winston');
var ENV = process.env.NODE_ENV;
var rootDir = process.cwd().split('/').slice(-1)[0];

function getLogger(module) {
  var path = module.filename.split('/');
  path = path.slice(path.indexOf(rootDir) - path.length + 1).join('/');

  return new winston.Logger({
    transports: [
      new winston.transports.Console({
        colorize: true,
        level: ENV == 'development' ? 'debug' : 'error',
        label: path
      })
    ]
  });
}

module.exports = getLogger;<|endoftext|>


<commit_before>/**
 * Copyright (c) 2013 Yahoo! Inc.  All rights reserved.
 * Copyrights licensed under the MIT License.
 * See the accompanying LICENSE file for terms.
 */

var log = require('npmlog');

// cust config
log.addLevel('debug', 999, {fg: 'grey'}, 'debug');
//log.level = 'debug';

// monkey patch npmlog…
log.heading = '';
log.headingStyle.fg = 'blue';
log.disp.verbose = 'verbose';
log.disp.error = 'err!';
log.disp.warn = 'warn';
log.style.error.bold = true;

// no bg colors
log.headingStyle.bg =
log.style.verbose.bg =
log.style.warn.bg =
log.style.error.bg =
log.style.http.bg = null;

// disable prefixing
Object.keys(log.levels).forEach(function(level) {
	log[level] = log[level].bind(log, '');
});

module.exports = log;
<commit_msg>warn is yellow<commit_after>/**
 * Copyright (c) 2013 Yahoo! Inc.  All rights reserved.
 * Copyrights licensed under the MIT License.
 * See the accompanying LICENSE file for terms.
 */

var log = require('npmlog');

// cust config
log.addLevel('debug', 999, {fg: 'grey'}, 'debug');
//log.level = 'debug';

// monkey patch npmlog…
log.heading = '';
log.headingStyle.fg = 'blue';
log.disp.verbose = 'verbose';
log.disp.error = 'err!';
log.disp.warn = 'warn';
log.style.error.bold = true;
log.style.warn.fg = 'yellow';

// no bg colors
log.headingStyle.bg =
log.style.verbose.bg =
log.style.warn.bg =
log.style.error.bg =
log.style.http.bg = null;

// disable prefixing
Object.keys(log.levels).forEach(function(level) {
	log[level] = log[level].bind(log, '');
});

module.exports = log;
<|endoftext|>


<commit_before>(function (JSUS) {

    /**
     *
     *    OBJ: functions working with js objects.
     *
     *
     */

    function OBJ(){};

    /**
     * Checks for deep equality between two objects,
     * string or primitive types.
     *
     * All nested properties are checked, and if they differ
     * in at least one returns FALSE, otherwise TRUE.
     *
     */
    OBJ.equals = function (o1, o2) {
        if (!o1 || !o2) return false;

        // Check whether arguments are not objects
        if ( typeof o1 in {number:'',string:''}) {
            if ( typeof o2 in {number:'',string:''}) {
                return (o1 === o2);
            }
            return false;
        } else if ( typeof o2 in {number:'',string:''}) {
            return false;
        }

        for (var p in o1) {
            if (o1.hasOwnProperty(p)) {

                if ('undefined' === typeof o2[p] && 'undefined' !== typeof o1[p]) return false;

                switch (typeof o1[p]) {
                    case 'object':
                        if (!OBJ.equals(o1[p],o2[p])) return false;

                    case 'function':
                        if (o1[p].toString() !== o2[p].toString()) return false;

                    default:
                        if (o1[p] !== o2[p]) return false;
              }
          }
      }

      // Check whether o2 has extra properties
      // TODO: improve, some properties have already been checked!
      for (p in o2) {
          if (o2.hasOwnProperty(p)) {
              if ('undefined' === typeof o1[p] && 'undefined' !== typeof o2[p])
                  return false;
          }
      }

      return true;
    };

    /**
     * Returns TRUE if an object has no properties,
     * FALSE otherwise.
     *
     */
    OBJ.isEmpty = function (o) {
        for (var key in o) {
            if (o.hasOwnProperty(key)) {
            	return false;
            }
        }

        return true;
    };

    /**
     * Returns the number of own properties, prototype
     * chain excluded, stored in the object / list.
     *
     */
    OBJ.getListSize = OBJ.getOwnPropertiesSize = function (list) {
        var n = 0;
        for (var key in list) {
            if (list.hasOwnProperty(key)) {
                n++;
            }
        }
        return n;
    };

    /**
     * Explodes an object into an array of keys and values,
     * according to the specified parameters.
     * A fixed level of recursion can be set.
     *
     * @api private
     *
     */
    OBJ._obj2Array = function(obj, keyed, level, cur_level) {
        if ('object' !== typeof obj) return [obj];

        if (level) {
            var cur_level = ('undefined' !== typeof cur_level) ? cur_level : 1;
            if (cur_level > level) return [obj];
            cur_level = cur_level + 1;
        }

        var result = [];
        for (var key in obj) {
            if (obj.hasOwnProperty(key)) {
                if ( 'object' === typeof obj[key] ) {
                    result = result.concat(OBJ._obj2Array(obj[key], keyed, level, cur_level));
                } else {
                    if (keyed) result.push(key);
                    result.push(obj[key]);
                }

            }
        }
        return result;
    };

    /**
     * Recursively put the values of the properties of an object into
     * an array and returns it. The level of recursion can be set with the
     * parameter level, by default recursion has no limit. That means that
     * the whole object gets totally unfolded into an array.
     *
     * @see OBJ._obj2Array
     * @see OBJ._obj2KeyedArray
     *
     */
    OBJ.obj2Array = function (obj, level) {
        return OBJ._obj2Array(obj, false, level);
    };

    /**
     * Creates an array containing all keys and values of an object and
     * returns it.
     *
     * @see OBJ.obj2Array
     *
     */
    OBJ.obj2KeyedArray = OBJ.obj2KeyArray = function (obj, level) {
        return OBJ._obj2Array(obj, true, level);
    };

    /**
     * Scans an object an returns all the keys of the properties,
     * into an array. Nested objects are also evaluated.
     *
     */
    OBJ.objGetAllKeys = function (obj) {
        var result = [];
        for (var key in obj) {
           if (obj.hasOwnProperty(key)) {
               result.push(key);
               if ('object' === typeof obj[key]) {
                   result = result.concat(OBJ.objGetAllKeys(obj[key]));
               }
           }
        }
        return result;
    };

    /**
     * Creates an array of key:value objects.
     *
     */
    OBJ.implodeObj = function (obj) {
        //console.log(obj);
        var result = [];
        for (var key in obj) {
            if (obj.hasOwnProperty(key)) {
                var o = {};
                o[key] = obj[key];
                result.push(o);
                //console.log(o);
            }
        }
        return result;
    };

 /**
  * Creates a perfect copy of the object passed as parameter.
  *
  */
 OBJ.clone = function (obj) {
     if (!obj) return;
     if ('number' === typeof obj) return obj;
     if ('string' === typeof obj) return obj;
     if (obj === NaN) return obj;
     if (obj === Infinity) return obj;

     var clone = {};
     for (var i in obj) {

    	// It is not NULL and it is an object
     	var value = (obj[i] && 'object' === typeof obj[i]) 	? OBJ.clone(obj[i])
					 								 		: obj[i];

         if (obj.hasOwnProperty(i)) {
         	clone[i] = value;
         }
         else {

        	 // Does not work
//         	if ('undefined' === typeof clone.prototype) {
//         		Object.defineProperty(clone, 'prototype', {
//         			value: {},
//         			writable: true,
//           		  	configurable: true,
//           		});
//         	}

         	Object.defineProperty(clone, i, {
         		 value: value,
         		 writable: true,
         		 configurable: true,
         	});

         }
     }
     return clone;
 };

    /**
     * Performs a *left* join on the keys of two objects. In case keys overlaps
     * the values from obj2 are taken.
     *
     */
    OBJ.join = function (obj1, obj2) {
        var clone = OBJ.clone(obj1);
        if (!obj2) return clone;
        for (var i in clone) {
            if (clone.hasOwnProperty(i)) {
                if ('undefined' !== typeof obj2[i]) {
                    if ( 'object' === typeof obj2[i] ) {
                        clone[i] = OBJ.join(clone[i], obj2[i]);
                    } else {
                        clone[i] = obj2[i];
                    }
                }
            }
        }
        return clone;
    };

    /**
     * Merges two objects in one. In case keys overlaps the values from
     * obj2 are taken.
     *
     * Returns a new object, the original ones are not modified.
     *
     */
    OBJ.merge = function (obj1, obj2) {
    	// Checking before starting the algorithm
    	if (!obj1 && !obj2) return false;
    	if (!obj1) return OBJ.clone(obj2);
    	if (!obj2) return OBJ.clone(obj1);

        var clone = OBJ.clone(obj1);
        if (!obj2) return clone;
        for (var i in obj2) {
            if (obj2.hasOwnProperty(i)) {
            	// it is an object and it is not NULL
                if ( obj2[i] && 'object' === typeof obj2[i] ) {
                    clone[i] = OBJ.merge(obj1[i],obj2[i]);
                } else {
                    clone[i] = obj2[i];
                }
            }
        }
        return clone;
    };

    /**
     * Appends / merges the values of the properties of obj2 into a
     * a new property called 'key' of obj1.
     *
     * Returns a new object, the original ones are not modified.
     *
     * This method is useful when we want to merge into a larger
     * configuration (e.g. min, max, value) object another one that
     * contains just the values for one of the properties (e.g. value).
     *
     * @see OBJ.merge
     *
     */
    OBJ.mergeOnKey = function (obj1, obj2, key) {
        var clone = OBJ.clone(obj1);
        if (!obj2 || !key) return clone;
        for (var i in obj2) {
            if (obj2.hasOwnProperty(i)) {
                if (!clone[i] || 'object' === typeof clone[i]) {
                	clone[i] = {};
                }
                clone[i][key] = obj2[i];
            }
        }
        return clone;
    };

    /**
     * Creates a copy of an object containing only the
     * properties passed as second parameter.
     *
     * The parameter select can be an array of strings,
     * or the name of a property.
     *
     */
    OBJ.subobj = function (o, select) {
        if (!o) return false;
        var out = {};
        if (!select) return out;
        if (!(select instanceof Array)) select = [select];
        for (var i=0; i<select.length;i++) {
            var key = select[i];
            if ('undefined' !== typeof o[key]) {
                out[key] = o[key];
            }
        }
        return out;
    };

    /**
     * Sets the value of a nested property of an object,
     * and returns it.
     *
     * If the object is not passed a new one is created.
     * If the nested property is not existing, a new one
     * is created.
     *
     * The original object is modified.
     *
     */
    OBJ.setNestedValue = function (str, value, obj) {
        var obj = obj || {};
        var keys = str.split('.');
        if (keys.length === 1) {
            obj[str] = value;
            return obj;
        }
        var k = keys.shift();
        obj[k] = OBJ.setNestedValue(keys.join('.'), value, obj[k]);
        return obj;
    };

    /**
     * Returns the value of a property of an object, as defined
     * by the input string. The string can contains '.', and in that
     * case the method looks for nested objects.
     *
     * Returns undefined if the nested key is not found.
     *
     */
    OBJ.getNestedValue = function (str, obj) {
        if (!obj) return;
        var keys = str.split('.');
        if (keys.length === 1) {
            return obj[str];
        }
        var k = keys.shift();
        return OBJ.getNestedValue(keys.join('.'), obj[k]);
    };

    JSUS.extend(OBJ);

})('undefined' !== typeof JSUS ? JSUS : module.parent.exports.JSUS);<commit_msg>Added JSUS.lengthnode<commit_after>(function (JSUS) {

    /**
     *
     *    OBJ: functions working with js objects.
     *
     *
     */

    function OBJ(){};

    /**
     * Checks for deep equality between two objects,
     * string or primitive types.
     *
     * All nested properties are checked, and if they differ
     * in at least one returns FALSE, otherwise TRUE.
     *
     */
    OBJ.equals = function (o1, o2) {
        if (!o1 || !o2) return false;

        // Check whether arguments are not objects
        if ( typeof o1 in {number:'',string:''}) {
            if ( typeof o2 in {number:'',string:''}) {
                return (o1 === o2);
            }
            return false;
        } else if ( typeof o2 in {number:'',string:''}) {
            return false;
        }

        for (var p in o1) {
            if (o1.hasOwnProperty(p)) {

                if ('undefined' === typeof o2[p] && 'undefined' !== typeof o1[p]) return false;

                switch (typeof o1[p]) {
                    case 'object':
                        if (!OBJ.equals(o1[p],o2[p])) return false;

                    case 'function':
                        if (o1[p].toString() !== o2[p].toString()) return false;

                    default:
                        if (o1[p] !== o2[p]) return false;
              }
          }
      }

      // Check whether o2 has extra properties
      // TODO: improve, some properties have already been checked!
      for (p in o2) {
          if (o2.hasOwnProperty(p)) {
              if ('undefined' === typeof o1[p] && 'undefined' !== typeof o2[p])
                  return false;
          }
      }

      return true;
    };

    /**
     * Returns TRUE if an object has no properties,
     * FALSE otherwise.
     *
     */
    OBJ.isEmpty = function (o) {
        for (var key in o) {
            if (o.hasOwnProperty(key)) {
            	return false;
            }
        }

        return true;
    };

    /**
     * @deprecated
     * @see OBJ.length();
     */
    OBJ.getListSize = OBJ.getOwnPropertiesSize = function (o) {
    	return OBJ.length(o);
    };

    /**
     * Returns the number of own properties of an object.
     * Prototype chain properties are excluded.
     *
     */
    OBJ.length = function (obj) {
    	if (!obj) return 0;
        var n = 0;
        for (var key in list) {
            if (list.hasOwnProperty(key)) {
                n++;
            }
        }
        return n;
    };

    /**
     * Explodes an object into an array of keys and values,
     * according to the specified parameters.
     * A fixed level of recursion can be set.
     *
     * @api private
     *
     */
    OBJ._obj2Array = function(obj, keyed, level, cur_level) {
        if ('object' !== typeof obj) return [obj];

        if (level) {
            var cur_level = ('undefined' !== typeof cur_level) ? cur_level : 1;
            if (cur_level > level) return [obj];
            cur_level = cur_level + 1;
        }

        var result = [];
        for (var key in obj) {
            if (obj.hasOwnProperty(key)) {
                if ( 'object' === typeof obj[key] ) {
                    result = result.concat(OBJ._obj2Array(obj[key], keyed, level, cur_level));
                } else {
                    if (keyed) result.push(key);
                    result.push(obj[key]);
                }

            }
        }
        return result;
    };

    /**
     * Recursively put the values of the properties of an object into
     * an array and returns it. The level of recursion can be set with the
     * parameter level, by default recursion has no limit. That means that
     * the whole object gets totally unfolded into an array.
     *
     * @see OBJ._obj2Array
     * @see OBJ._obj2KeyedArray
     *
     */
    OBJ.obj2Array = function (obj, level) {
        return OBJ._obj2Array(obj, false, level);
    };

    /**
     * Creates an array containing all keys and values of an object and
     * returns it.
     *
     * @see OBJ.obj2Array
     *
     */
    OBJ.obj2KeyedArray = OBJ.obj2KeyArray = function (obj, level) {
        return OBJ._obj2Array(obj, true, level);
    };

    /**
     * Scans an object an returns all the keys of the properties,
     * into an array. Nested objects are also evaluated.
     *
     */
    OBJ.objGetAllKeys = function (obj) {
        var result = [];
        for (var key in obj) {
           if (obj.hasOwnProperty(key)) {
               result.push(key);
               if ('object' === typeof obj[key]) {
                   result = result.concat(OBJ.objGetAllKeys(obj[key]));
               }
           }
        }
        return result;
    };

    /**
     * Creates an array of key:value objects.
     *
     */
    OBJ.implodeObj = function (obj) {
        //console.log(obj);
        var result = [];
        for (var key in obj) {
            if (obj.hasOwnProperty(key)) {
                var o = {};
                o[key] = obj[key];
                result.push(o);
                //console.log(o);
            }
        }
        return result;
    };

 /**
  * Creates a perfect copy of the object passed as parameter.
  *
  */
 OBJ.clone = function (obj) {
     if (!obj) return;
     if ('number' === typeof obj) return obj;
     if ('string' === typeof obj) return obj;
     if (obj === NaN) return obj;
     if (obj === Infinity) return obj;

     var clone = {};
     for (var i in obj) {

    	// It is not NULL and it is an object
     	var value = (obj[i] && 'object' === typeof obj[i]) 	? OBJ.clone(obj[i])
					 								 		: obj[i];

         if (obj.hasOwnProperty(i)) {
         	clone[i] = value;
         }
         else {

        	 // Does not work
//         	if ('undefined' === typeof clone.prototype) {
//         		Object.defineProperty(clone, 'prototype', {
//         			value: {},
//         			writable: true,
//           		  	configurable: true,
//           		});
//         	}

         	Object.defineProperty(clone, i, {
         		 value: value,
         		 writable: true,
         		 configurable: true,
         	});

         }
     }
     return clone;
 };

    /**
     * Performs a *left* join on the keys of two objects. In case keys overlaps
     * the values from obj2 are taken.
     *
     */
    OBJ.join = function (obj1, obj2) {
        var clone = OBJ.clone(obj1);
        if (!obj2) return clone;
        for (var i in clone) {
            if (clone.hasOwnProperty(i)) {
                if ('undefined' !== typeof obj2[i]) {
                    if ( 'object' === typeof obj2[i] ) {
                        clone[i] = OBJ.join(clone[i], obj2[i]);
                    } else {
                        clone[i] = obj2[i];
                    }
                }
            }
        }
        return clone;
    };

    /**
     * Merges two objects in one. In case keys overlaps the values from
     * obj2 are taken.
     *
     * Returns a new object, the original ones are not modified.
     *
     */
    OBJ.merge = function (obj1, obj2) {
    	// Checking before starting the algorithm
    	if (!obj1 && !obj2) return false;
    	if (!obj1) return OBJ.clone(obj2);
    	if (!obj2) return OBJ.clone(obj1);

        var clone = OBJ.clone(obj1);
        if (!obj2) return clone;
        for (var i in obj2) {
            if (obj2.hasOwnProperty(i)) {
            	// it is an object and it is not NULL
                if ( obj2[i] && 'object' === typeof obj2[i] ) {
                    clone[i] = OBJ.merge(obj1[i],obj2[i]);
                } else {
                    clone[i] = obj2[i];
                }
            }
        }
        return clone;
    };

    /**
     * Appends / merges the values of the properties of obj2 into a
     * a new property called 'key' of obj1.
     *
     * Returns a new object, the original ones are not modified.
     *
     * This method is useful when we want to merge into a larger
     * configuration (e.g. min, max, value) object another one that
     * contains just the values for one of the properties (e.g. value).
     *
     * @see OBJ.merge
     *
     */
    OBJ.mergeOnKey = function (obj1, obj2, key) {
        var clone = OBJ.clone(obj1);
        if (!obj2 || !key) return clone;
        for (var i in obj2) {
            if (obj2.hasOwnProperty(i)) {
                if (!clone[i] || 'object' === typeof clone[i]) {
                	clone[i] = {};
                }
                clone[i][key] = obj2[i];
            }
        }
        return clone;
    };

    /**
     * Creates a copy of an object containing only the
     * properties passed as second parameter.
     *
     * The parameter select can be an array of strings,
     * or the name of a property.
     *
     */
    OBJ.subobj = function (o, select) {
        if (!o) return false;
        var out = {};
        if (!select) return out;
        if (!(select instanceof Array)) select = [select];
        for (var i=0; i<select.length;i++) {
            var key = select[i];
            if ('undefined' !== typeof o[key]) {
                out[key] = o[key];
            }
        }
        return out;
    };

    /**
     * Sets the value of a nested property of an object,
     * and returns it.
     *
     * If the object is not passed a new one is created.
     * If the nested property is not existing, a new one
     * is created.
     *
     * The original object is modified.
     *
     */
    OBJ.setNestedValue = function (str, value, obj) {
        var obj = obj || {};
        var keys = str.split('.');
        if (keys.length === 1) {
            obj[str] = value;
            return obj;
        }
        var k = keys.shift();
        obj[k] = OBJ.setNestedValue(keys.join('.'), value, obj[k]);
        return obj;
    };

    /**
     * Returns the value of a property of an object, as defined
     * by the input string. The string can contains '.', and in that
     * case the method looks for nested objects.
     *
     * Returns undefined if the nested key is not found.
     *
     */
    OBJ.getNestedValue = function (str, obj) {
        if (!obj) return;
        var keys = str.split('.');
        if (keys.length === 1) {
            return obj[str];
        }
        var k = keys.shift();
        return OBJ.getNestedValue(keys.join('.'), obj[k]);
    };

    JSUS.extend(OBJ);

})('undefined' !== typeof JSUS ? JSUS : module.parent.exports.JSUS);<|endoftext|>


<commit_before>define(["Tone/core/Tone", "Tone/core/Buffer", "Tone/source/Source", "Tone/core/Gain",
	"Tone/core/AudioNode"], function(Tone){

	/**
	 *  @class Wrapper around the native fire-and-forget OscillatorNode. Adds the
	 *     ability to reschedule the stop method. ***[Tone.Oscillator](Oscillator) is better
	 *     for most use-cases***
	 *  @extends {Tone.AudioNode}
	 *  @param  {AudioBuffer|Tone.Buffer}  buffer   The buffer to play
	 *  @param  {Function}  onload  The callback to invoke when the
	 *                               buffer is done playing.
	 */
	Tone.OscillatorNode = function(){

		var options = Tone.defaults(arguments, ["frequency", "type"], Tone.OscillatorNode);
		Tone.AudioNode.call(this, options);

		/**
		 *  The callback to invoke after the
		 *  buffer source is done playing.
		 *  @type  {Function}
		 */
		this.onended = options.onended;

		/**
		 *  The oscillator start time
		 *  @type  {Number}
		 *  @private
		 */
		this._startTime = -1;

		/**
		 *  The oscillator stop time
		 *  @type  {Number}
		 *  @private
		 */
		this._stopTime = -1;

		/**
		 *  The gain node which envelopes the OscillatorNode
		 *  @type  {Tone.Gain}
		 *  @private
		 */
		this._gainNode = this.output = new Tone.Gain();
		this._gainNode.gain.setValueAtTime(0, this.context.currentTime);

		/**
		 *  The oscillator
		 *  @type  {OscillatorNode}
		 *  @private
		 */
		this._oscillator = this.context.createOscillator();
		this._oscillator.connect(this._gainNode);
		this.type = options.type;

		/**
		 *  The frequency of the oscillator
		 *  @type {Frequency}
		 *  @signal
		 */
		this.frequency = new Tone.Param(this._oscillator.frequency, Tone.Type.Frequency);
		this.frequency.value = options.frequency;

		/**
		 *  The detune of the oscillator
		 *  @type {Frequency}
		 *  @signal
		 */
		this.detune = new Tone.Param(this._oscillator.detune, Tone.Type.Cents);
		this.detune.value = options.detune;

		/**
		 *  The value that the buffer ramps to
		 *  @type {Gain}
		 *  @private
		 */
		this._gain = 1;
	};

	Tone.extend(Tone.OscillatorNode, Tone.AudioNode);

	/**
	 *  The defaults
	 *  @const
	 *  @type  {Object}
	 */
	Tone.OscillatorNode.defaults = {
		"frequency" : 440,
		"detune" : 0,
		"type" : "sine",
		"onended" : Tone.noOp
	};

	/**
	 *  Returns the playback state of the oscillator, either "started" or "stopped".
	 *  @type {Tone.State}
	 *  @readOnly
	 *  @memberOf Tone.OscillatorNode#
	 *  @name state
	 */
	Object.defineProperty(Tone.OscillatorNode.prototype, "state", {
		get : function(){
			return this.getStateAtTime(this.now());
		}
	});

	/**
	 *  Get the playback state at the given time
	 *  @param  {Time}  time  The time to test the state at
	 *  @return  {Tone.State}  The playback state.
	 */
	Tone.OscillatorNode.prototype.getStateAtTime = function(time){
		time = this.toSeconds(time);
		if (this._startTime !== -1 && time >= this._startTime && (this._stopTime === -1 || time <= this._stopTime)){
			return Tone.State.Started;
		} else {
			return Tone.State.Stopped;
		}
	};

	/**
     * Start the oscillator node at the given time
     * @param  {Time=} time When to start the oscillator
     * @return {OscillatorNode}      this
     */
	Tone.OscillatorNode.prototype.start = function(time){
		if (this._startTime === -1){
			this._startTime = this.toSeconds(time);
			this._oscillator.start(this._startTime);
			var now = this.context.currentTime;
			this._gainNode.gain.cancelScheduledValues(now);
			this._gainNode.gain.setValueAtTime(0, now);
			this._gainNode.gain.setValueAtTime(1, this._startTime);
		} else {
			throw new Error("cannot call OscillatorNode.start more than once");
		}
		return this;
	};

	/**
     * Sets an arbitrary custom periodic waveform given a PeriodicWave.
     * @param  {PeriodicWave} periodicWave PeriodicWave should be created with context.createPeriodicWave
     * @return {OscillatorNode} this
     */
	Tone.OscillatorNode.prototype.setPeriodicWave = function(periodicWave){
		this._oscillator.setPeriodicWave(periodicWave);
		return this;
	};

	/**
     * Stop the oscillator node at the given time
     * @param  {Time=} time When to stop the oscillator
     * @return {OscillatorNode}      this
     */
	Tone.OscillatorNode.prototype.stop = function(time){
		//cancel the previous stop
		this.cancelStop();
		//reschedule it
		this._stopTime = this.toSeconds(time);
		this._gainNode.gain.setValueAtTime(0, this._stopTime);
		this.context.clearTimeout(this._timeout);
		this._timeout = this.context.setTimeout(function(){
			this._oscillator.stop(this.now());
			this.onended();
		}.bind(this), this._stopTime - this.now());
		return this;
	};

	/**
	 *  Cancel a scheduled stop event
	 *  @return  {Tone.OscillatorNode}  this
	 */
	Tone.OscillatorNode.prototype.cancelStop = function(){
		if (this._startTime !== -1){
			//cancel the stop envelope
			this._gainNode.gain.cancelScheduledValues(this._startTime + this.sampleTime);
			this._gainNode.gain.setValueAtTime(1, Math.max(this.now(), this._startTime));
			this.context.clearTimeout(this._timeout);
			this._stopTime = -1;
		}
		return this;
	};

	/**
	 * The oscillator type. Either 'sine', 'sawtooth', 'square', or 'triangle'
	 * @memberOf Tone.OscillatorNode#
	 * @type {Time}
	 * @name type
	 */
	Object.defineProperty(Tone.OscillatorNode.prototype, "type", {
		get : function(){
			return this._oscillator.type;
		},
		set : function(type){
			this._oscillator.type = type;
		}
	});

	/**
	 *  Clean up.
	 *  @return  {Tone.OscillatorNode}  this
	 */
	Tone.OscillatorNode.prototype.dispose = function(){
		this.context.clearTimeout(this._timeout);
		Tone.AudioNode.prototype.dispose.call(this);
		this.onended = null;
		this._oscillator.disconnect();
		this._oscillator = null;
		this._gainNode.dispose();
		this._gainNode = null;
		this.frequency.dispose();
		this.frequency = null;
		this.detune.dispose();
		this.detune = null;
		return this;
	};

	return Tone.OscillatorNode;
});
<commit_msg>handles start/stop/restart better in many situations<commit_after>define(["Tone/core/Tone", "Tone/core/Buffer", "Tone/source/Source", "Tone/core/Gain",
	"Tone/core/AudioNode"], function(Tone){

	/**
	 *  @class Wrapper around the native fire-and-forget OscillatorNode. Adds the
	 *     ability to reschedule the stop method. ***[Tone.Oscillator](Oscillator) is better
	 *     for most use-cases***
	 *  @extends {Tone.AudioNode}
	 *  @param  {AudioBuffer|Tone.Buffer}  buffer   The buffer to play
	 *  @param  {Function}  onload  The callback to invoke when the
	 *                               buffer is done playing.
	 */
	Tone.OscillatorNode = function(){

		var options = Tone.defaults(arguments, ["frequency", "type"], Tone.OscillatorNode);
		Tone.AudioNode.call(this, options);

		/**
		 *  The callback to invoke after the
		 *  buffer source is done playing.
		 *  @type  {Function}
		 */
		this.onended = options.onended;

		/**
		 *  The oscillator start time
		 *  @type  {Number}
		 *  @private
		 */
		this._startTime = -1;

		/**
		 *  The oscillator stop time
		 *  @type  {Number}
		 *  @private
		 */
		this._stopTime = -1;

		/**
		 *  The gain node which envelopes the OscillatorNode
		 *  @type  {Tone.Gain}
		 *  @private
		 */
		this._gainNode = this.output = new Tone.Gain(0);

		/**
		 *  The oscillator
		 *  @type  {OscillatorNode}
		 *  @private
		 */
		this._oscillator = this.context.createOscillator();
		this._oscillator.connect(this._gainNode);
		this.type = options.type;

		/**
		 *  The frequency of the oscillator
		 *  @type {Frequency}
		 *  @signal
		 */
		this.frequency = new Tone.Param({
			param : this._oscillator.frequency,
			units : Tone.Type.Frequency,
			value : options.frequency
		});

		/**
		 *  The detune of the oscillator
		 *  @type {Frequency}
		 *  @signal
		 */
		this.detune = new Tone.Param({
			param : this._oscillator.detune,
			units : Tone.Type.Cents,
			value : options.detune
		});

		/**
		 *  The value that the buffer ramps to
		 *  @type {Gain}
		 *  @private
		 */
		this._gain = 1;
	};

	Tone.extend(Tone.OscillatorNode, Tone.AudioNode);

	/**
	 *  The defaults
	 *  @const
	 *  @type  {Object}
	 */
	Tone.OscillatorNode.defaults = {
		"frequency" : 440,
		"detune" : 0,
		"type" : "sine",
		"onended" : Tone.noOp
	};

	/**
	 *  Returns the playback state of the oscillator, either "started" or "stopped".
	 *  @type {Tone.State}
	 *  @readOnly
	 *  @memberOf Tone.OscillatorNode#
	 *  @name state
	 */
	Object.defineProperty(Tone.OscillatorNode.prototype, "state", {
		get : function(){
			return this.getStateAtTime(this.now());
		}
	});

	/**
	 *  Get the playback state at the given time
	 *  @param  {Time}  time  The time to test the state at
	 *  @return  {Tone.State}  The playback state.
	 */
	Tone.OscillatorNode.prototype.getStateAtTime = function(time){
		time = this.toSeconds(time);
		if (this._startTime !== -1 && time >= this._startTime && (this._stopTime === -1 || time <= this._stopTime)){
			return Tone.State.Started;
		} else {
			return Tone.State.Stopped;
		}
	};

	/**
     * Start the oscillator node at the given time
     * @param  {Time=} time When to start the oscillator
     * @return {OscillatorNode}      this
     */
	Tone.OscillatorNode.prototype.start = function(time){
		this.log("start", time);
		if (this._startTime === -1){
			this._startTime = this.toSeconds(time);
			this._oscillator.start(this._startTime);
			this._gainNode.gain.setValueAtTime(1, this._startTime);
		} else {
			throw new Error("cannot call OscillatorNode.start more than once");
		}
		return this;
	};

	/**
     * Sets an arbitrary custom periodic waveform given a PeriodicWave.
     * @param  {PeriodicWave} periodicWave PeriodicWave should be created with context.createPeriodicWave
     * @return {OscillatorNode} this
     */
	Tone.OscillatorNode.prototype.setPeriodicWave = function(periodicWave){
		this._oscillator.setPeriodicWave(periodicWave);
		return this;
	};

	/**
     * Stop the oscillator node at the given time
     * @param  {Time=} time When to stop the oscillator
     * @return {OscillatorNode}      this
     */
	Tone.OscillatorNode.prototype.stop = function(time){
		this.log("stop", time);
		this.assert(this._startTime !== -1, "'start' must be called before 'stop'");
		//cancel the previous stop
		this.cancelStop();
		//reschedule it
		this._stopTime = this.toSeconds(time);
		if (this._stopTime > this._startTime){
			this._gainNode.gain.setValueAtTime(0, this._stopTime);
			this.context.clearTimeout(this._timeout);
			this._timeout = this.context.setTimeout(function(){
				this._oscillator.stop(this.now());
				this.onended();
			}.bind(this), this._stopTime - this.context.currentTime);
		} else {
			//cancel the stop envelope
			this._gainNode.gain.cancelScheduledValues(this._startTime);
		}
		return this;
	};

	/**
	 *  Cancel a scheduled stop event
	 *  @return  {Tone.OscillatorNode}  this
	 */
	Tone.OscillatorNode.prototype.cancelStop = function(){
		if (this._startTime !== -1){
			//cancel the stop envelope
			this._gainNode.gain.cancelScheduledValues(this._startTime+this.sampleTime);
			this.context.clearTimeout(this._timeout);
			this._stopTime = -1;
		}
		return this;
	};

	/**
	 * The oscillator type. Either 'sine', 'sawtooth', 'square', or 'triangle'
	 * @memberOf Tone.OscillatorNode#
	 * @type {Time}
	 * @name type
	 */
	Object.defineProperty(Tone.OscillatorNode.prototype, "type", {
		get : function(){
			return this._oscillator.type;
		},
		set : function(type){
			this._oscillator.type = type;
		}
	});

	/**
	 *  Clean up.
	 *  @return  {Tone.OscillatorNode}  this
	 */
	Tone.OscillatorNode.prototype.dispose = function(){
		this.context.clearTimeout(this._timeout);
		Tone.AudioNode.prototype.dispose.call(this);
		this.onended = null;
		this._oscillator.disconnect();
		this._oscillator = null;
		this._gainNode.dispose();
		this._gainNode = null;
		this.frequency.dispose();
		this.frequency = null;
		this.detune.dispose();
		this.detune = null;
		return this;
	};

	return Tone.OscillatorNode;
});
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2015 Dickson Tam
 *
 * 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() {

   var pad = function(width, opts) {

     opts = opts || {}
     opts.filler = (opts.filler == null)? ' ' : opts.filler;
     opts.location = opts.location || 'tail';

     width = (width == null)? 16 : width;

     if (this.length > 0) {
       if (opts.location == 'tail') {
         return this + pad.call('', width - this.length, opts);
       } else if (opts.location == 'head') {
         return pad.call('', width - this.length, opts) + this;
       }
     }

     if (width < 0) return this;

     var padding = "";

     for (var i=0; i < width; i++) {
        padding += opts.filler.substr(i % opts.filler.length, 1);
     }

     padding = padding.substr(0, width);

     return padding;
   }

   if (typeof module !== 'undefined' && module && module.exports) { // Node.js & CommonJS
     module.exports = pad;
   } else { // Browser
     String.prototype.pad = pad;
   }

 })();
<commit_msg>Removed unnecessary call.<commit_after>/*
 * Copyright (c) 2015 Dickson Tam
 *
 * 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() {

   var pad = function(width, opts) {

     opts = opts || {}
     opts.filler = (opts.filler == null)? ' ' : opts.filler;
     opts.location = opts.location || 'tail';

     width = (width == null)? 16 : width;

     if (this.length > 0) {
       if (opts.location == 'tail') {
         return this + pad.call('', width - this.length, opts);
       } else if (opts.location == 'head') {
         return pad.call('', width - this.length, opts) + this;
       }
     }

     if (width < 0) return this;

     var padding = "";

     for (var i=0; i < width; i++) {
        padding += opts.filler.substr(i % opts.filler.length, 1);
     }

     return padding;
   }

   if (typeof module !== 'undefined' && module && module.exports) { // Node.js & CommonJS
     module.exports = pad;
   } else { // Browser
     String.prototype.pad = pad;
   }

 })();
<|endoftext|>


<commit_before>'use strict';

const BPromise = require('bluebird');
const commandLineArgs = require('command-line-args');
const jsonfile = require('jsonfile');
const knex = require('knex');
const args = require('./args');

let cli = commandLineArgs(args);
let options = cli.parse();

if (Object.keys(options).length === 0 || options.help) {
  displayUsage();
  exit(0);
}

if (!options.file || !options.file.exists) {
  console.error('You must provide a valid JSON file to open with -f or --file');
  exit(1);
}

if (!options.connection) {
  console.error('You must provide a connection string for PostgreSQL with -c or --connection');
  exit(1);
}

if (!options.table) {
  console.error('You must specify a destination table for the data using -t or --table');
  exit(1);
}

let json;

try {
  let json = jsonfile.readFileSync(options.file.filename);
} catch(ex) {
  console.error(`There was a problem reading ${options.file.filename}:\n`, ex.toString());
  exit(1);
}

let pg = knex({
  client: 'pg',
  connection: options.connection
});

pg.transaction((trx) => {
  return BPromise.map(json, (row) => {
    return trx.insert(row)
    .into(options.table);
  })
  .then(trx.commit)
  .catch(trx.rollback);
})
.then((inserts) => {
  console.info(`${inserts.length} rows imported into the table ${options.table}.`);
  exit(0);
})
.catch((error) => {
  console.error(`There was an error importing into ${options.table}. The transaction was reversed. Details: \n\n`, error.toString());
  exit(1)
});

function displayUsage() {
  console.info(cli.getUsage({
    title: 'pg-json-import',
    description: 'Import data from a JSON file into a PG table',
    synopsis: [
      '$ pji [bold]{--file} [underline]{filename.json} [bold]{-c} [underline]{postgresql://localhost:5432/mydb} [bold]{-t} [underline]{tablename}',
      '$ pji [bold]{--file} [underline]{filename.json} [bold]{--database} [underline]{dbname} [bold]{--table} [underline]{tablename}',
      '$ pji [bold]{--file} [underline]{filename.json} [bold]{--host} [underline]{host} [bold]{--port} [underline]{port} [bold]{--database} [underline]{dbname} [bold]{--table} [underline]{tablename}'
    ]
  }));
}

function exit(code) {
  process.exit(code);
}
<commit_msg>Fix an oops<commit_after>'use strict';

const BPromise = require('bluebird');
const commandLineArgs = require('command-line-args');
const jsonfile = require('jsonfile');
const knex = require('knex');
const args = require('./args');

let cli = commandLineArgs(args);
let options = cli.parse();

if (Object.keys(options).length === 0 || options.help) {
  displayUsage();
  exit(0);
}

if (!options.file || !options.file.exists) {
  console.error('You must provide a valid JSON file to open with -f or --file');
  exit(1);
}

if (!options.connection) {
  console.error('You must provide a connection string for PostgreSQL with -c or --connection');
  exit(1);
}

if (!options.table) {
  console.error('You must specify a destination table for the data using -t or --table');
  exit(1);
}

let json;

try {
  json = jsonfile.readFileSync(options.file.filename);
} catch(ex) {
  console.error(`There was a problem reading ${options.file.filename}:\n`, ex.toString());
  exit(1);
}

let pg = knex({
  client: 'pg',
  connection: options.connection
});

pg.transaction((trx) => {
  return BPromise.map(json, (row) => {
    return trx.insert(row)
    .into(options.table);
  })
  .then(trx.commit)
  .catch(trx.rollback);
})
.then((inserts) => {
  console.info(`${inserts.length} rows imported into the table ${options.table}.`);
  exit(0);
})
.catch((error) => {
  console.error(`There was an error importing into ${options.table}. The transaction was reversed. Details: \n\n`, error.toString());
  exit(1)
});

function displayUsage() {
  console.info(cli.getUsage({
    title: 'pg-json-import',
    description: 'Import data from a JSON file into a PG table',
    synopsis: [
      '$ pji [bold]{--file} [underline]{filename.json} [bold]{-c} [underline]{postgresql://localhost:5432/mydb} [bold]{-t} [underline]{tablename}',
      '$ pji [bold]{--file} [underline]{filename.json} [bold]{--database} [underline]{dbname} [bold]{--table} [underline]{tablename}',
      '$ pji [bold]{--file} [underline]{filename.json} [bold]{--host} [underline]{host} [bold]{--port} [underline]{port} [bold]{--database} [underline]{dbname} [bold]{--table} [underline]{tablename}'
    ]
  }));
}

function exit(code) {
  process.exit(code);
}
<|endoftext|>


<commit_before>(function()
{
    var prototype = Seed.prototype(Gio.FileInputStream);

    prototype.get_contents = function()
    {
	    var stream = Gio.DataInputStream._new(this);
	    var line = stream.read_until("", 0);
	    return line;
    }

    Gio.simple_write = function(file, name)
    {
	    var file = Gio.file_new_for_path(file);
	    var fstream = file.replace();
	    var dstream = Gio.DataOutputStream._new(fstream);

	    dstream.put_string(name);
	    fstream.close();
    }

    Gio.simple_read = function(name)
    {
	    var file = Gio.file_new_for_path(name);
	    var fstream = file.read();
	    var dstream = Gio.DataInputStream._new(fstream);
	    var line = dstream.read_until("", 0);
	    fstream.close();
	    return line;
    }
}).apply();
<commit_msg>Make Gio.simple_read and Gio.simple_write verify that files are regular  files or symlinks.<commit_after>(function()
{
    var prototype = Seed.prototype(Gio.FileInputStream);

    prototype.get_contents = function()
    {
	    var stream = Gio.DataInputStream._new(this);
	    var line = stream.read_until("", 0);
	    return line;
    }

    Gio.simple_write = function(file, name)
    {
	    var file = Gio.file_new_for_path(file);
	    var info = file.query_info("standard::type");
	    var type = info.get_file_type();
	    if ((type != Gio.FileType.regular)
		&& (type != Gio.FileType.symbolic_link))
		return;
	    var fstream = file.replace();
	    var dstream = Gio.DataOutputStream._new(fstream);

	    dstream.put_string(name);
	    fstream.close();
    }

    Gio.simple_read = function(name)
    {
	    var file = Gio.file_new_for_path(name);
	    var info = file.query_info("standard::type");
	    var type = info.get_file_type();
	    if ((type != Gio.FileType.regular)
		&& (type != Gio.FileType.symbolic_link))
		return null;
	    var fstream = file.read();
	    var dstream = Gio.DataInputStream._new(fstream);
	    var line = dstream.read_until("", 0);
	    fstream.close();
	    return line;
    }
}).apply();
<|endoftext|>