<commit_before>var controllerDir;

// Get js-controller directory to load libs
function getControllerDir(isSilent) {
    var fs = require('fs');
    // Find the js-controller location
    var controllerDir = __dirname.replace(/\\/g, '/');
    controllerDir = controllerDir.split('/');
    if (controllerDir[controllerDir.length - 3] == 'adapter') {
        controllerDir.splice(controllerDir.length - 3, 3);
        controllerDir = controllerDir.join('/');
    } else if (controllerDir[controllerDir.length - 3] == 'node_modules') {
        controllerDir.splice(controllerDir.length - 3, 3);
        controllerDir = controllerDir.join('/');
        if (fs.existsSync(controllerDir + '/node_modules/iobroker.js-controller')) {
            controllerDir += '/node_modules/iobroker.js-controller';
        } else if (fs.existsSync(controllerDir + '/node_modules/ioBroker.js-controller')) {
            controllerDir += '/node_modules/ioBroker.js-controller';
        } else if (!fs.existsSync(controllerDir + '/controller.js')) {
            if (!isSilent) {
                console.log('Cannot find js-controller');
                process.exit(10);
            } else {
                process.exit();
            }
        }
    } else {
        if (!isSilent) {
            console.log('Cannot find js-controller');
            process.exit(10);
        } else {
            process.exit();
        }
    }
    return controllerDir;
}

// Read controller configuration file
function getConfig() {
    return JSON.parse(fs.readFileSync(controllerDir + '/conf/iobroker.json'));
}
controllerDir = getControllerDir(typeof process != 'undefined' && process.argv && process.argv.indexOf('--silent') != -1);

exports.controllerDir = controllerDir;
exports.getConfig = getConfig;
exports.adapter = require(controllerDir + '/lib/adapter.js');<commit_msg>update utils<commit_after>var controllerDir;

// Get js-controller directory to load libs
function getControllerDir(isInstall) {
    var fs = require('fs');
    // Find the js-controller location
    var controllerDir = __dirname.replace(/\\/g, '/');
    controllerDir = controllerDir.split('/');
    if (controllerDir[controllerDir.length - 3] == 'adapter') {
        controllerDir.splice(controllerDir.length - 3, 3);
        controllerDir = controllerDir.join('/');
    } else if (controllerDir[controllerDir.length - 3] == 'node_modules') {
        controllerDir.splice(controllerDir.length - 3, 3);
        controllerDir = controllerDir.join('/');
        if (fs.existsSync(controllerDir + '/node_modules/iobroker.js-controller')) {
            controllerDir += '/node_modules/iobroker.js-controller';
        } else if (fs.existsSync(controllerDir + '/node_modules/ioBroker.js-controller')) {
            controllerDir += '/node_modules/ioBroker.js-controller';
        } else if (!fs.existsSync(controllerDir + '/controller.js')) {
            if (!isInstall) {
                console.log('Cannot find js-controller');
                process.exit(10);
            } else {
                process.exit();
            }
        }
    } else {
        if (!isInstall) {
            console.log('Cannot find js-controller');
            process.exit(10);
        } else {
            process.exit();
        }
    }
    return controllerDir;
}

// Read controller configuration file
function getConfig() {
    return JSON.parse(fs.readFileSync(controllerDir + '/conf/iobroker.json'));
}
controllerDir = getControllerDir(typeof process != 'undefined' && process.argv && process.argv.indexOf('--install') != -1);

exports.controllerDir = controllerDir;
exports.getConfig =     getConfig;
exports.adapter =       require(controllerDir + '/lib/adapter.js');<|endoftext|>


<commit_before>var utils = {};
var random_string_chars = ['a','b','c','d','e','f','g','h','i','j',
                           'k','l','m','n','o','p','q','r','s','t',
                           'u','v','w','x','y','z',
                           '0','1','2','3','4','5','6','7','8','9','_'];
utils.random_string = function(letters, max) {
    max = max || random_string_chars.length;
    var i, ret = [];
    for(i=0; i < letters; i++) {
        ret.push( random_string_chars[Math.floor(Math.random() * max)] );
    }
    return ret.join('');
};
utils.random_number = function(max) {
    return Math.floor(Math.random() * max);
};
utils.random_number_string = function(max) {
    var s = ''+utils.random_number(max);
    var t = (''+(max - 1)).length;
    while (s.length < t) {s = '0' + s;}
    return s;
};

utils.attachMessage = function(listener) {
    utils.attachEvent('message', listener);
};
utils.attachEvent = function(event, listener) {
    if (typeof _window.addEventListener !== 'undefined') {
        _window.addEventListener(event, listener, false);
    } else {
        // IE quirks.
        // According to: http://stevesouders.com/misc/test-postmessage.php
        // the message gets delivered only to 'document', not 'window'.
	_document.attachEvent("on" + event, listener);
        // I get 'window' for ie8.
	_window.attachEvent("on" + event, listener);
    }
};

utils.detachMessage = function(listener) {
    utils.detachEvent('message', listener);
};
utils.detachEvent = function(event, listener) {
    if (typeof _window.addEventListener !== 'undefined') {
        _window.removeEventListener(event, listener, false);
    } else {
        _document.detachEvent("on" + event, listener);
	_window.detachEvent("on" + event, listener);
    }
};

// Assuming that url looks like: http://asdasd:111/asd
utils.getOrigin = function(url) {
    url += '/';
    var parts = url.split('/').slice(0, 3);
    return parts.join('/');
};

utils.objectExtend = function(dst, src) {
    for(var k in src) {
        if (src.hasOwnProperty(k)) {
            dst[k] = src[k];
        }
    }
    return dst;
};

// Try to clear some headers, in order to save bandwidth. For
// reference see:
//   http://blog.mibbit.com/?p=143
//   http://code.google.com/p/browsersec/wiki/Part2#Same-origin_policy_for_XMLHttpRequest
var xhrDefaultHeaders = {
    "User-Agent": '',
    "Accept": '',
    "Accept-Language": '',
    "Content-Type": "T"
};

if (navigator &&
    (navigator.userAgent.indexOf('Chrome')!= -1 ||
     navigator.userAgent.indexOf('Safari') != -1)) {
    delete xhrDefaultHeaders['User-Agent'];
}

// References:
//   http://ajaxian.com/archives/100-line-ajax-wrapper
//   http://msdn.microsoft.com/en-us/library/cc288060(v=VS.85).aspx
utils.createXDR = function(method, url, payload, callback) {
    var mock_xhr = {status: null, responseText:'', readyState:1};
    var xdr = new XDomainRequest();
    // IE caches even POSTs
    url += ((url.indexOf('?') === -1) ? '?' : '&') + 't='+utils.random_string(8);
    var cleanup = function() {
        if (xdr) {
            onerror = xdr.onerror = xdr.ontimeout = xdr.onprogress =
                xdr.onload = null;
            try {
                xdr.abort();
            } catch (x) {}
            xdr = callback = null;
        }
    };
    var onerror = xdr.ontimeout = xdr.onerror = function() {
        mock_xhr.status = 500;
        mock_xhr.readyState = 4;
        callback(mock_xhr);
        cleanup();
    };
    xdr.onload = function() {
        mock_xhr.status = 200;
        mock_xhr.readyState = 4;
        mock_xhr.responseText = xdr.responseText;
        callback(mock_xhr);
        cleanup();
    };
    xdr.onprogress = function() {
        mock_xhr.status = 200;
        mock_xhr.readyState = 3;
        mock_xhr.responseText = xdr.responseText;
        callback(mock_xhr);
    };
    try {
        // Fails with AccessDenied if port number is bogus
        xdr.open(method, url);
        xdr.send(payload);
    } catch (x) {
        utils.delay(onerror);
    }
    return function (abort_reason) {
        if (callback) {
            callback(mock_xhr, null, abort_reason);
            cleanup();
        }
    };
};

utils.createXHR = function(method, url, payload, callback) {
    var xhr;
    if (_window.ActiveXObject) {
        // IE caches POSTs
        url += ((url.indexOf('?') === -1) ? '?' : '&') + 't='+(+new Date);
        try {
            xhr = new ActiveXObject('Microsoft.XMLHTTP');
        } catch(x) {}
    }
    if (!xhr) {
        xhr = new XMLHttpRequest();
    }
    xhr.open(method, url, true);

    for (var k in xhrDefaultHeaders) {
        try {
            xhr.setRequestHeader(k, xhrDefaultHeaders[k]);
        } catch(x) {
            delete xhrDefaultHeaders[k];
        }
    }
    if ('withCredentials' in xhr) {
        // Set cookies on CORS, please.
        xhr.withCredentials = "true";
    }

    var cleanup = function() {
        if (xhr) {
            // IE needs this field to be a function
            try {
                xhr.onreadystatechange = null;
            } catch (x) {
                xhr.onreadystatechange = function(){};
            }
            // Explorer tends to keep connection open, even after the
            // tab gets closed: http://bugs.jquery.com/ticket/5280
            try {
                xhr.abort();
            } catch(e) {};
            utils.detachEvent('unload', cleanup);
        }
        callback = xhr = null;
    };

    xhr.onreadystatechange = function (e) {
        if (xhr && callback) {
            callback(xhr, e);
            if (xhr && xhr.readyState === 4) {
                cleanup();
            }
        }
    };
    xhr.send(payload);
    utils.attachEvent('unload', cleanup);
    return function (abort_reason) {
        if (callback) {
            callback(xhr, null, abort_reason);
            cleanup();
        }
    };
};

var WPrefix = '_jp';

utils.polluteGlobalNamespace = function() {
    if (!(WPrefix in _window)) {
        _window[WPrefix] = {};
    }
};

utils.createIframe = function (iframe_url, error_callback) {
    var iframe = _document.createElement('iframe');
    var tref;
    var unattach = function() {
        clearTimeout(tref);
        // Explorer had problems with that.
        try {iframe.onload = null;} catch (x) {}
        iframe.onerror = null;
    };
    var cleanup = function() {
        if (iframe) {
            unattach();
            iframe.parentNode.removeChild(iframe);
            iframe.src = "about:blank";
            iframe = null;
            utils.detachEvent('unload', cleanup);
        }
    };
    var onerror = function(r) {
        if (iframe) {
            cleanup();
            error_callback(r);
        }
    };
    iframe.src = iframe_url;
    iframe.style.display = 'none';
    iframe.style.position = 'absolute';
    iframe.onerror = function(){onerror('onerror');};
    iframe.onload = function() {
        // `onload` is triggered before scripts on the iframe are
        // executed. Give it few seconds to actually load stuff.
        clearTimeout(tref);
        tref = setTimeout(function(){onerror('onload timeout');}, 2000);
    };
    _document.body.appendChild(iframe);
    tref = setTimeout(function(){onerror('timeout');}, 5000);
    utils.attachEvent('unload', cleanup);
    return {
        iframe: iframe,
        cleanup: cleanup,
        loaded: unattach
    };
};

utils.createHtmlfile = function (iframe_url, error_callback) {
    var doc = new ActiveXObject('htmlfile');
    var tref;
    var iframe;
    var unattach = function() {
        clearTimeout(tref);
    };
    var cleanup = function() {
        if (doc) {
            unattach();
            utils.detachEvent('unload', cleanup);
            try {
                iframe.src = "about:blank";
            } catch (x) {}
            iframe.parentNode.removeChild(iframe);
            iframe = doc = null;
            CollectGarbage();
        }
    };
    var onerror = function(r)  {
        if (doc) {
            cleanup();
            error_callback(r);
        }
    };

    doc.open();
    doc.write('');
    doc.close();
    doc.parentWindow[WPrefix] = _window[WPrefix];
    var c = doc.createElement('div');
    doc.body.appendChild(c);
    iframe = doc.createElement('iframe');
    c.appendChild(iframe);
    iframe.src = iframe_url;
    tref = setTimeout(function(){onerror('timeout');}, 5000);
    utils.attachEvent('unload', cleanup);
    return {
        iframe: iframe,
        cleanup: cleanup,
        loaded: unattach
    };
};

utils.closeFrame = function (code, reason) {
    return 'c'+JSON.stringify([code, reason]);
};

utils.userSetCode = function (code) {
    return code === 1000 || (code >= 3000 && code <= 4999);
};

utils.log = function() {
    if (_window.console && console.log && console.log.apply) {
        console.log.apply(console, arguments);
    }
};

utils.bind = function(fun, that) {
    if (fun.bind) {
        return fun.bind(that);
    } else {
        return function() {
            return fun.apply(that, arguments);
        };
    }
};

utils.amendUrl = function(url) {
    var dl = _document.location;
    if (!url) {
        throw new Error('Wrong url for SockJS');
    }
    //  '//abc' --> 'http://abc'
    if (url.indexOf('//') === 0) {
        url = dl.protocol + url;
    }
    // '/abc' --> 'http://localhost:80/abc'
    if (url.indexOf('/') === 0) {
        url = dl.protocol + '//' + dl.host + url;
    }
    // strip trailing slashes
    url = url.replace(/[/]+$/,'');
    return url;
};

// IE doesn't support [].indexOf.
utils.arrIndexOf = function(arr, obj){
	for(var i=0; i < arr.length; i++){
		if(arr[i] === obj){
			return i;
		}
	}
    return -1;
};

utils.delay = function(t, fun) {
    if(typeof t === 'function') {
        fun = t;
        t = 0;
    }
    return setTimeout(fun, t);
};<commit_msg>Use more standard 'text/plain' rather than custom 't' type for xhr<commit_after>var utils = {};
var random_string_chars = ['a','b','c','d','e','f','g','h','i','j',
                           'k','l','m','n','o','p','q','r','s','t',
                           'u','v','w','x','y','z',
                           '0','1','2','3','4','5','6','7','8','9','_'];
utils.random_string = function(letters, max) {
    max = max || random_string_chars.length;
    var i, ret = [];
    for(i=0; i < letters; i++) {
        ret.push( random_string_chars[Math.floor(Math.random() * max)] );
    }
    return ret.join('');
};
utils.random_number = function(max) {
    return Math.floor(Math.random() * max);
};
utils.random_number_string = function(max) {
    var s = ''+utils.random_number(max);
    var t = (''+(max - 1)).length;
    while (s.length < t) {s = '0' + s;}
    return s;
};

utils.attachMessage = function(listener) {
    utils.attachEvent('message', listener);
};
utils.attachEvent = function(event, listener) {
    if (typeof _window.addEventListener !== 'undefined') {
        _window.addEventListener(event, listener, false);
    } else {
        // IE quirks.
        // According to: http://stevesouders.com/misc/test-postmessage.php
        // the message gets delivered only to 'document', not 'window'.
	_document.attachEvent("on" + event, listener);
        // I get 'window' for ie8.
	_window.attachEvent("on" + event, listener);
    }
};

utils.detachMessage = function(listener) {
    utils.detachEvent('message', listener);
};
utils.detachEvent = function(event, listener) {
    if (typeof _window.addEventListener !== 'undefined') {
        _window.removeEventListener(event, listener, false);
    } else {
        _document.detachEvent("on" + event, listener);
	_window.detachEvent("on" + event, listener);
    }
};

// Assuming that url looks like: http://asdasd:111/asd
utils.getOrigin = function(url) {
    url += '/';
    var parts = url.split('/').slice(0, 3);
    return parts.join('/');
};

utils.objectExtend = function(dst, src) {
    for(var k in src) {
        if (src.hasOwnProperty(k)) {
            dst[k] = src[k];
        }
    }
    return dst;
};

// Try to clear some headers, in order to save bandwidth. For
// reference see:
//   http://blog.mibbit.com/?p=143
//   http://code.google.com/p/browsersec/wiki/Part2#Same-origin_policy_for_XMLHttpRequest
var xhrDefaultHeaders = {
    "User-Agent": '',
    "Accept": '',
    "Accept-Language": '',
    "Content-Type": "text/plain;charset=UTF-8"
};

if (navigator &&
    (navigator.userAgent.indexOf('Chrome')!= -1 ||
     navigator.userAgent.indexOf('Safari') != -1)) {
    delete xhrDefaultHeaders['User-Agent'];
}

// References:
//   http://ajaxian.com/archives/100-line-ajax-wrapper
//   http://msdn.microsoft.com/en-us/library/cc288060(v=VS.85).aspx
utils.createXDR = function(method, url, payload, callback) {
    var mock_xhr = {status: null, responseText:'', readyState:1};
    var xdr = new XDomainRequest();
    // IE caches even POSTs
    url += ((url.indexOf('?') === -1) ? '?' : '&') + 't='+utils.random_string(8);
    var cleanup = function() {
        if (xdr) {
            onerror = xdr.onerror = xdr.ontimeout = xdr.onprogress =
                xdr.onload = null;
            try {
                xdr.abort();
            } catch (x) {}
            xdr = callback = null;
        }
    };
    var onerror = xdr.ontimeout = xdr.onerror = function() {
        mock_xhr.status = 500;
        mock_xhr.readyState = 4;
        callback(mock_xhr);
        cleanup();
    };
    xdr.onload = function() {
        mock_xhr.status = 200;
        mock_xhr.readyState = 4;
        mock_xhr.responseText = xdr.responseText;
        callback(mock_xhr);
        cleanup();
    };
    xdr.onprogress = function() {
        mock_xhr.status = 200;
        mock_xhr.readyState = 3;
        mock_xhr.responseText = xdr.responseText;
        callback(mock_xhr);
    };
    try {
        // Fails with AccessDenied if port number is bogus
        xdr.open(method, url);
        xdr.send(payload);
    } catch (x) {
        utils.delay(onerror);
    }
    return function (abort_reason) {
        if (callback) {
            callback(mock_xhr, null, abort_reason);
            cleanup();
        }
    };
};

utils.createXHR = function(method, url, payload, callback) {
    var xhr;
    if (_window.ActiveXObject) {
        // IE caches POSTs
        url += ((url.indexOf('?') === -1) ? '?' : '&') + 't='+(+new Date);
        try {
            xhr = new ActiveXObject('Microsoft.XMLHTTP');
        } catch(x) {}
    }
    if (!xhr) {
        xhr = new XMLHttpRequest();
    }
    xhr.open(method, url, true);

    for (var k in xhrDefaultHeaders) {
        try {
            xhr.setRequestHeader(k, xhrDefaultHeaders[k]);
        } catch(x) {
            delete xhrDefaultHeaders[k];
        }
    }
    if ('withCredentials' in xhr) {
        // Set cookies on CORS, please.
        xhr.withCredentials = "true";
    }

    var cleanup = function() {
        if (xhr) {
            // IE needs this field to be a function
            try {
                xhr.onreadystatechange = null;
            } catch (x) {
                xhr.onreadystatechange = function(){};
            }
            // Explorer tends to keep connection open, even after the
            // tab gets closed: http://bugs.jquery.com/ticket/5280
            try {
                xhr.abort();
            } catch(e) {};
            utils.detachEvent('unload', cleanup);
        }
        callback = xhr = null;
    };

    xhr.onreadystatechange = function (e) {
        if (xhr && callback) {
            callback(xhr, e);
            if (xhr && xhr.readyState === 4) {
                cleanup();
            }
        }
    };
    xhr.send(payload);
    utils.attachEvent('unload', cleanup);
    return function (abort_reason) {
        if (callback) {
            callback(xhr, null, abort_reason);
            cleanup();
        }
    };
};

var WPrefix = '_jp';

utils.polluteGlobalNamespace = function() {
    if (!(WPrefix in _window)) {
        _window[WPrefix] = {};
    }
};

utils.createIframe = function (iframe_url, error_callback) {
    var iframe = _document.createElement('iframe');
    var tref;
    var unattach = function() {
        clearTimeout(tref);
        // Explorer had problems with that.
        try {iframe.onload = null;} catch (x) {}
        iframe.onerror = null;
    };
    var cleanup = function() {
        if (iframe) {
            unattach();
            iframe.parentNode.removeChild(iframe);
            iframe.src = "about:blank";
            iframe = null;
            utils.detachEvent('unload', cleanup);
        }
    };
    var onerror = function(r) {
        if (iframe) {
            cleanup();
            error_callback(r);
        }
    };
    iframe.src = iframe_url;
    iframe.style.display = 'none';
    iframe.style.position = 'absolute';
    iframe.onerror = function(){onerror('onerror');};
    iframe.onload = function() {
        // `onload` is triggered before scripts on the iframe are
        // executed. Give it few seconds to actually load stuff.
        clearTimeout(tref);
        tref = setTimeout(function(){onerror('onload timeout');}, 2000);
    };
    _document.body.appendChild(iframe);
    tref = setTimeout(function(){onerror('timeout');}, 5000);
    utils.attachEvent('unload', cleanup);
    return {
        iframe: iframe,
        cleanup: cleanup,
        loaded: unattach
    };
};

utils.createHtmlfile = function (iframe_url, error_callback) {
    var doc = new ActiveXObject('htmlfile');
    var tref;
    var iframe;
    var unattach = function() {
        clearTimeout(tref);
    };
    var cleanup = function() {
        if (doc) {
            unattach();
            utils.detachEvent('unload', cleanup);
            try {
                iframe.src = "about:blank";
            } catch (x) {}
            iframe.parentNode.removeChild(iframe);
            iframe = doc = null;
            CollectGarbage();
        }
    };
    var onerror = function(r)  {
        if (doc) {
            cleanup();
            error_callback(r);
        }
    };

    doc.open();
    doc.write('');
    doc.close();
    doc.parentWindow[WPrefix] = _window[WPrefix];
    var c = doc.createElement('div');
    doc.body.appendChild(c);
    iframe = doc.createElement('iframe');
    c.appendChild(iframe);
    iframe.src = iframe_url;
    tref = setTimeout(function(){onerror('timeout');}, 5000);
    utils.attachEvent('unload', cleanup);
    return {
        iframe: iframe,
        cleanup: cleanup,
        loaded: unattach
    };
};

utils.closeFrame = function (code, reason) {
    return 'c'+JSON.stringify([code, reason]);
};

utils.userSetCode = function (code) {
    return code === 1000 || (code >= 3000 && code <= 4999);
};

utils.log = function() {
    if (_window.console && console.log && console.log.apply) {
        console.log.apply(console, arguments);
    }
};

utils.bind = function(fun, that) {
    if (fun.bind) {
        return fun.bind(that);
    } else {
        return function() {
            return fun.apply(that, arguments);
        };
    }
};

utils.amendUrl = function(url) {
    var dl = _document.location;
    if (!url) {
        throw new Error('Wrong url for SockJS');
    }
    //  '//abc' --> 'http://abc'
    if (url.indexOf('//') === 0) {
        url = dl.protocol + url;
    }
    // '/abc' --> 'http://localhost:80/abc'
    if (url.indexOf('/') === 0) {
        url = dl.protocol + '//' + dl.host + url;
    }
    // strip trailing slashes
    url = url.replace(/[/]+$/,'');
    return url;
};

// IE doesn't support [].indexOf.
utils.arrIndexOf = function(arr, obj){
	for(var i=0; i < arr.length; i++){
		if(arr[i] === obj){
			return i;
		}
	}
    return -1;
};

utils.delay = function(t, fun) {
    if(typeof t === 'function') {
        fun = t;
        t = 0;
    }
    return setTimeout(fun, t);
};<|endoftext|>


<commit_before>/* eslint-disable no-proto */
/* global Deno */

const canSetPrototype =
  Object.setPrototypeOf || { __proto__: [] } instanceof Array;
const greedyIntervalPacker = require('greedy-interval-packer');

const setPrototypeOf =
  Object.setPrototypeOf ||
  function setPrototypeOf(obj, proto) {
    obj.__proto__ = proto;
    return obj;
  };
/* eslint-enable no-proto */

const utils = (module.exports = {
  objectIs:
    Object.is ||
    ((a, b) => {
      // Polyfill from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is
      if (a === 0 && b === 0) {
        return 1 / a === 1 / b;
      }
      // eslint-disable-next-line no-self-compare
      if (a !== a) {
        // eslint-disable-next-line no-self-compare
        return b !== b;
      }
      return a === b;
    }),

  checkObjectEqualityUsingType(a, b, type, isEqual) {
    if (a === b) {
      return true;
    }

    if (b.constructor !== a.constructor) {
      return false;
    }

    const actualKeys = type
      .getKeys(a)
      .filter(key => typeof type.valueForKey(a, key) !== 'undefined');
    const expectedKeys = type
      .getKeys(b)
      .filter(key => typeof type.valueForKey(b, key) !== 'undefined');

    // having the same number of owned properties (keys incorporates hasOwnProperty)
    if (actualKeys.length !== expectedKeys.length) {
      return false;
    }

    // the same set of keys (although not necessarily the same order),
    actualKeys.sort(type.keyComparator);
    expectedKeys.sort(type.keyComparator);
    // cheap key test
    for (let i = 0; i < actualKeys.length; i += 1) {
      if (actualKeys[i] !== expectedKeys[i]) {
        return false;
      }
    }

    // equivalent values for every corresponding key, and
    // possibly expensive deep test
    for (let j = 0; j < actualKeys.length; j += 1) {
      const key = actualKeys[j];
      if (!isEqual(type.valueForKey(a, key), type.valueForKey(b, key))) {
        return false;
      }
    }
    return true;
  },

  duplicateArrayLikeUsingType(obj, type) {
    const keys = type.getKeys(obj);

    let numericalKeyLength = keys.length;
    if (!type.numericalPropertiesOnly) {
      let nonNumericalKeyLength = 0;
      // find non-numerical keys in reverse order to keep iteration minimal
      for (let i = keys.length - 1; i > -1; i -= 1) {
        const key = keys[i];
        if (typeof key === 'symbol' || !utils.numericalRegExp.test(key)) {
          nonNumericalKeyLength += 1;
        } else {
          break;
        }
      }
      // remove non-numerical keys to ensure the copy is sized correctly
      numericalKeyLength -= nonNumericalKeyLength;
    }

    const arr = new Array(numericalKeyLength);

    keys.forEach(function(key, index) {
      const isNonNumericKey = index >= numericalKeyLength;
      if (isNonNumericKey && !type.hasKey(obj, key)) {
        // do not add non-numerical keys that are not actually attached
        // to the array-like to ensure they will be treated as "missing"
        return;
      }
      arr[key] = type.hasKey(obj, key) ? type.valueForKey(obj, key) : undefined;
    });

    return arr;
  },

  isArray(ar) {
    return Object.prototype.toString.call(ar) === '[object Array]';
  },

  isPromise(obj) {
    return obj && typeof obj.then === 'function';
  },

  isRegExp(re) {
    return Object.prototype.toString.call(re) === '[object RegExp]';
  },

  isError(err) {
    return (
      typeof err === 'object' &&
      (Object.prototype.toString.call(err) === '[object Error]' ||
        err instanceof Error)
    );
  },

  extend(target) {
    for (let i = 1; i < arguments.length; i += 1) {
      const source = arguments[i];
      if (source) {
        Object.keys(source).forEach(key => {
          target[key] = source[key];
        });
      }
    }
    return target;
  },

  findFirst(arr, predicate) {
    for (let i = 0; i < arr.length; i += 1) {
      if (predicate(arr[i])) {
        return arr[i];
      }
    }
    return null;
  },

  leftPad(str, width, ch = ' ') {
    while (str.length < width) {
      str = ch + str;
    }
    return str;
  },

  escapeRegExpMetaChars(str) {
    return str.replace(/[[\]{}()*+?.\\^$|]/g, '\\$&');
  },

  escapeChar(ch) {
    if (ch === '\t') {
      return '\\t';
    } else if (ch === '\r') {
      return '\\r';
    } else {
      const charCode = ch.charCodeAt(0);
      const hexChars = charCode.toString(16).toUpperCase();
      if (charCode < 256) {
        return `\\x${utils.leftPad(hexChars, 2, '0')}`;
      } else {
        return `\\u${utils.leftPad(hexChars, 4, '0')}`;
      }
    }
  },

  getFunctionName(f) {
    if (typeof f.name === 'string') {
      return f.name;
    }
    const matchFunctionName = Function.prototype.toString
      .call(f)
      .match(/function ([^(]+)/);
    if (matchFunctionName) {
      return matchFunctionName[1];
    }

    if (f === Object) {
      return 'Object';
    }
    if (f === Function) {
      return 'Function';
    }
    return '';
  },

  wrapConstructorNameAroundOutput(output, obj) {
    const constructor = obj.constructor;
    const constructorName =
      constructor &&
      constructor !== Object &&
      utils.getFunctionName(constructor);
    if (constructorName && constructorName !== 'Object') {
      return output
        .clone()
        .text(`${constructorName}(`)
        .append(output)
        .text(')');
    } else {
      return output;
    }
  },

  setPrototypeOfOrExtend: canSetPrototype
    ? setPrototypeOf
    : function extend(target, source) {
        for (const prop in source) {
          if (Object.prototype.hasOwnProperty.call(source, prop)) {
            target[prop] = source[prop];
          }
        }
        return target;
      },

  uniqueStringsAndSymbols(...args) {
    // [filterFn], item1, item2...
    let filterFn;
    if (typeof args[0] === 'function') {
      filterFn = args[0];
    }
    const index = {};
    const uniqueStringsAndSymbols = [];

    function visit(item) {
      if (Array.isArray(item)) {
        item.forEach(visit);
      } else if (
        !Object.prototype.hasOwnProperty.call(index, item) &&
        (!filterFn || filterFn(item))
      ) {
        index[item] = true;
        uniqueStringsAndSymbols.push(item);
      }
    }

    for (let i = filterFn ? 1 : 0; i < args.length; i += 1) {
      visit(args[i]);
    }
    return uniqueStringsAndSymbols;
  },

  uniqueNonNumericalStringsAndSymbols(...args) {
    // ...
    return utils.uniqueStringsAndSymbols(
      stringOrSymbol =>
        typeof stringOrSymbol === 'symbol' ||
        !utils.numericalRegExp.test(stringOrSymbol),
      Array.prototype.slice.call(args)
    );
  },

  forwardFlags(testDescriptionString, flags) {
    return testDescriptionString
      .replace(/\[(!?)([^\]]+)\] ?/g, (match, negate, flag) =>
        Boolean(flags[flag]) !== Boolean(negate) ? `${flag} ` : ''
      )
      .trim();
  },

  numericalRegExp: /^(?:0|[1-9][0-9]*)$/,

  packArrows(changes) {
    const moveSourceAndTargetByActualIndex = {};
    changes.forEach((diffItem, index) => {
      if (diffItem.type === 'moveSource') {
        diffItem.changeIndex = index;
        (moveSourceAndTargetByActualIndex[diffItem.actualIndex] =
          moveSourceAndTargetByActualIndex[diffItem.actualIndex] ||
          {}).source = diffItem;
      } else if (diffItem.type === 'moveTarget') {
        diffItem.changeIndex = index;
        (moveSourceAndTargetByActualIndex[diffItem.actualIndex] =
          moveSourceAndTargetByActualIndex[diffItem.actualIndex] ||
          {}).target = diffItem;
      }
    });
    const moveIndices = Object.keys(moveSourceAndTargetByActualIndex);
    if (moveIndices.length > 0) {
      const arrowSpecs = [];
      moveIndices
        .sort(
          (
            a,
            b // Order by distance between change indices descending
          ) =>
            Math.abs(
              moveSourceAndTargetByActualIndex[b].source.changeIndex -
                moveSourceAndTargetByActualIndex[b].target.changeIndex
            ) -
            Math.abs(
              moveSourceAndTargetByActualIndex[a].source.changeIndex -
                moveSourceAndTargetByActualIndex[a].target.changeIndex
            )
        )
        .forEach((actualIndex, i, keys) => {
          const moveSourceAndMoveTarget =
            moveSourceAndTargetByActualIndex[actualIndex];
          const firstChangeIndex = Math.min(
            moveSourceAndMoveTarget.source.changeIndex,
            moveSourceAndMoveTarget.target.changeIndex
          );
          const lastChangeIndex = Math.max(
            moveSourceAndMoveTarget.source.changeIndex,
            moveSourceAndMoveTarget.target.changeIndex
          );

          arrowSpecs.push({
            start: firstChangeIndex,
            end: lastChangeIndex,
            direction:
              moveSourceAndMoveTarget.source.changeIndex <
              moveSourceAndMoveTarget.target.changeIndex
                ? 'down'
                : 'up'
          });
        });

      const packing = greedyIntervalPacker(arrowSpecs);
      while (packing.length > 3) {
        // The arrow packing takes up too many lanes. Turn the moveSource/moveTarget items into inserts and removes
        packing.shift().forEach(({ direction, start, end }) => {
          changes[direction === 'up' ? start : end].type = 'insert';
          changes[direction === 'up' ? end : start].type = 'remove';
        });
      }
      return packing;
    }
  },

  truncateSubjectStringForBegin(subject, value) {
    var contextLength = value.length + 25;
    if (subject.length <= contextLength) {
      return null;
    }
    var truncationIndex = subject.indexOf(' ', value.length + 1);
    if (truncationIndex > -1 && truncationIndex < contextLength) {
      return subject.substring(0, truncationIndex);
    } else {
      return subject.substring(0, contextLength);
    }
  },

  truncateSubjectStringForEnd(subject, value) {
    var contextLength = subject.length - value.length - 25;
    if (contextLength <= 0) {
      return null;
    }
    var truncationIndex = subject.lastIndexOf(' ', value.length + 1);
    if (truncationIndex > -1 && truncationIndex >= contextLength) {
      return subject.substring(truncationIndex + 1, subject.length);
    } else {
      return subject.substring(contextLength, subject.length);
    }
  },

  getEnv(varName) {
    if (typeof Deno === 'object' && Deno.permissions().env) {
      return Deno.env()[varName];
    } else if (typeof process === 'object' && process.env) {
      return process.env[varName];
    }
  }
});
<commit_msg>Try to avoid querying Deno.permissions<commit_after>/* eslint-disable no-proto */
/* global Deno */

const canSetPrototype =
  Object.setPrototypeOf || { __proto__: [] } instanceof Array;
const greedyIntervalPacker = require('greedy-interval-packer');

const setPrototypeOf =
  Object.setPrototypeOf ||
  function setPrototypeOf(obj, proto) {
    obj.__proto__ = proto;
    return obj;
  };
/* eslint-enable no-proto */

const utils = (module.exports = {
  objectIs:
    Object.is ||
    ((a, b) => {
      // Polyfill from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is
      if (a === 0 && b === 0) {
        return 1 / a === 1 / b;
      }
      // eslint-disable-next-line no-self-compare
      if (a !== a) {
        // eslint-disable-next-line no-self-compare
        return b !== b;
      }
      return a === b;
    }),

  checkObjectEqualityUsingType(a, b, type, isEqual) {
    if (a === b) {
      return true;
    }

    if (b.constructor !== a.constructor) {
      return false;
    }

    const actualKeys = type
      .getKeys(a)
      .filter(key => typeof type.valueForKey(a, key) !== 'undefined');
    const expectedKeys = type
      .getKeys(b)
      .filter(key => typeof type.valueForKey(b, key) !== 'undefined');

    // having the same number of owned properties (keys incorporates hasOwnProperty)
    if (actualKeys.length !== expectedKeys.length) {
      return false;
    }

    // the same set of keys (although not necessarily the same order),
    actualKeys.sort(type.keyComparator);
    expectedKeys.sort(type.keyComparator);
    // cheap key test
    for (let i = 0; i < actualKeys.length; i += 1) {
      if (actualKeys[i] !== expectedKeys[i]) {
        return false;
      }
    }

    // equivalent values for every corresponding key, and
    // possibly expensive deep test
    for (let j = 0; j < actualKeys.length; j += 1) {
      const key = actualKeys[j];
      if (!isEqual(type.valueForKey(a, key), type.valueForKey(b, key))) {
        return false;
      }
    }
    return true;
  },

  duplicateArrayLikeUsingType(obj, type) {
    const keys = type.getKeys(obj);

    let numericalKeyLength = keys.length;
    if (!type.numericalPropertiesOnly) {
      let nonNumericalKeyLength = 0;
      // find non-numerical keys in reverse order to keep iteration minimal
      for (let i = keys.length - 1; i > -1; i -= 1) {
        const key = keys[i];
        if (typeof key === 'symbol' || !utils.numericalRegExp.test(key)) {
          nonNumericalKeyLength += 1;
        } else {
          break;
        }
      }
      // remove non-numerical keys to ensure the copy is sized correctly
      numericalKeyLength -= nonNumericalKeyLength;
    }

    const arr = new Array(numericalKeyLength);

    keys.forEach(function(key, index) {
      const isNonNumericKey = index >= numericalKeyLength;
      if (isNonNumericKey && !type.hasKey(obj, key)) {
        // do not add non-numerical keys that are not actually attached
        // to the array-like to ensure they will be treated as "missing"
        return;
      }
      arr[key] = type.hasKey(obj, key) ? type.valueForKey(obj, key) : undefined;
    });

    return arr;
  },

  isArray(ar) {
    return Object.prototype.toString.call(ar) === '[object Array]';
  },

  isPromise(obj) {
    return obj && typeof obj.then === 'function';
  },

  isRegExp(re) {
    return Object.prototype.toString.call(re) === '[object RegExp]';
  },

  isError(err) {
    return (
      typeof err === 'object' &&
      (Object.prototype.toString.call(err) === '[object Error]' ||
        err instanceof Error)
    );
  },

  extend(target) {
    for (let i = 1; i < arguments.length; i += 1) {
      const source = arguments[i];
      if (source) {
        Object.keys(source).forEach(key => {
          target[key] = source[key];
        });
      }
    }
    return target;
  },

  findFirst(arr, predicate) {
    for (let i = 0; i < arr.length; i += 1) {
      if (predicate(arr[i])) {
        return arr[i];
      }
    }
    return null;
  },

  leftPad(str, width, ch = ' ') {
    while (str.length < width) {
      str = ch + str;
    }
    return str;
  },

  escapeRegExpMetaChars(str) {
    return str.replace(/[[\]{}()*+?.\\^$|]/g, '\\$&');
  },

  escapeChar(ch) {
    if (ch === '\t') {
      return '\\t';
    } else if (ch === '\r') {
      return '\\r';
    } else {
      const charCode = ch.charCodeAt(0);
      const hexChars = charCode.toString(16).toUpperCase();
      if (charCode < 256) {
        return `\\x${utils.leftPad(hexChars, 2, '0')}`;
      } else {
        return `\\u${utils.leftPad(hexChars, 4, '0')}`;
      }
    }
  },

  getFunctionName(f) {
    if (typeof f.name === 'string') {
      return f.name;
    }
    const matchFunctionName = Function.prototype.toString
      .call(f)
      .match(/function ([^(]+)/);
    if (matchFunctionName) {
      return matchFunctionName[1];
    }

    if (f === Object) {
      return 'Object';
    }
    if (f === Function) {
      return 'Function';
    }
    return '';
  },

  wrapConstructorNameAroundOutput(output, obj) {
    const constructor = obj.constructor;
    const constructorName =
      constructor &&
      constructor !== Object &&
      utils.getFunctionName(constructor);
    if (constructorName && constructorName !== 'Object') {
      return output
        .clone()
        .text(`${constructorName}(`)
        .append(output)
        .text(')');
    } else {
      return output;
    }
  },

  setPrototypeOfOrExtend: canSetPrototype
    ? setPrototypeOf
    : function extend(target, source) {
        for (const prop in source) {
          if (Object.prototype.hasOwnProperty.call(source, prop)) {
            target[prop] = source[prop];
          }
        }
        return target;
      },

  uniqueStringsAndSymbols(...args) {
    // [filterFn], item1, item2...
    let filterFn;
    if (typeof args[0] === 'function') {
      filterFn = args[0];
    }
    const index = {};
    const uniqueStringsAndSymbols = [];

    function visit(item) {
      if (Array.isArray(item)) {
        item.forEach(visit);
      } else if (
        !Object.prototype.hasOwnProperty.call(index, item) &&
        (!filterFn || filterFn(item))
      ) {
        index[item] = true;
        uniqueStringsAndSymbols.push(item);
      }
    }

    for (let i = filterFn ? 1 : 0; i < args.length; i += 1) {
      visit(args[i]);
    }
    return uniqueStringsAndSymbols;
  },

  uniqueNonNumericalStringsAndSymbols(...args) {
    // ...
    return utils.uniqueStringsAndSymbols(
      stringOrSymbol =>
        typeof stringOrSymbol === 'symbol' ||
        !utils.numericalRegExp.test(stringOrSymbol),
      Array.prototype.slice.call(args)
    );
  },

  forwardFlags(testDescriptionString, flags) {
    return testDescriptionString
      .replace(/\[(!?)([^\]]+)\] ?/g, (match, negate, flag) =>
        Boolean(flags[flag]) !== Boolean(negate) ? `${flag} ` : ''
      )
      .trim();
  },

  numericalRegExp: /^(?:0|[1-9][0-9]*)$/,

  packArrows(changes) {
    const moveSourceAndTargetByActualIndex = {};
    changes.forEach((diffItem, index) => {
      if (diffItem.type === 'moveSource') {
        diffItem.changeIndex = index;
        (moveSourceAndTargetByActualIndex[diffItem.actualIndex] =
          moveSourceAndTargetByActualIndex[diffItem.actualIndex] ||
          {}).source = diffItem;
      } else if (diffItem.type === 'moveTarget') {
        diffItem.changeIndex = index;
        (moveSourceAndTargetByActualIndex[diffItem.actualIndex] =
          moveSourceAndTargetByActualIndex[diffItem.actualIndex] ||
          {}).target = diffItem;
      }
    });
    const moveIndices = Object.keys(moveSourceAndTargetByActualIndex);
    if (moveIndices.length > 0) {
      const arrowSpecs = [];
      moveIndices
        .sort(
          (
            a,
            b // Order by distance between change indices descending
          ) =>
            Math.abs(
              moveSourceAndTargetByActualIndex[b].source.changeIndex -
                moveSourceAndTargetByActualIndex[b].target.changeIndex
            ) -
            Math.abs(
              moveSourceAndTargetByActualIndex[a].source.changeIndex -
                moveSourceAndTargetByActualIndex[a].target.changeIndex
            )
        )
        .forEach((actualIndex, i, keys) => {
          const moveSourceAndMoveTarget =
            moveSourceAndTargetByActualIndex[actualIndex];
          const firstChangeIndex = Math.min(
            moveSourceAndMoveTarget.source.changeIndex,
            moveSourceAndMoveTarget.target.changeIndex
          );
          const lastChangeIndex = Math.max(
            moveSourceAndMoveTarget.source.changeIndex,
            moveSourceAndMoveTarget.target.changeIndex
          );

          arrowSpecs.push({
            start: firstChangeIndex,
            end: lastChangeIndex,
            direction:
              moveSourceAndMoveTarget.source.changeIndex <
              moveSourceAndMoveTarget.target.changeIndex
                ? 'down'
                : 'up'
          });
        });

      const packing = greedyIntervalPacker(arrowSpecs);
      while (packing.length > 3) {
        // The arrow packing takes up too many lanes. Turn the moveSource/moveTarget items into inserts and removes
        packing.shift().forEach(({ direction, start, end }) => {
          changes[direction === 'up' ? start : end].type = 'insert';
          changes[direction === 'up' ? end : start].type = 'remove';
        });
      }
      return packing;
    }
  },

  truncateSubjectStringForBegin(subject, value) {
    var contextLength = value.length + 25;
    if (subject.length <= contextLength) {
      return null;
    }
    var truncationIndex = subject.indexOf(' ', value.length + 1);
    if (truncationIndex > -1 && truncationIndex < contextLength) {
      return subject.substring(0, truncationIndex);
    } else {
      return subject.substring(0, contextLength);
    }
  },

  truncateSubjectStringForEnd(subject, value) {
    var contextLength = subject.length - value.length - 25;
    if (contextLength <= 0) {
      return null;
    }
    var truncationIndex = subject.lastIndexOf(' ', value.length + 1);
    if (truncationIndex > -1 && truncationIndex >= contextLength) {
      return subject.substring(truncationIndex + 1, subject.length);
    } else {
      return subject.substring(contextLength, subject.length);
    }
  },

  getEnv(varName) {
    if (typeof Deno === 'object') {
      try {
        return Deno.env()[varName];
      } catch (err) {
        // Probably a permissions error because we don't have permission to read the environment variables
        // Unfortunately the whole permissions API is async now:
        // https://github.com/denoland/deno/pull/3200/files
        // ... so we can't detect whether we do have access
      }
    } else if (typeof process === 'object' && process.env) {
      return process.env[varName];
    }
  }
});
<|endoftext|>


<commit_before>
/*!
 * Module dependencies.
 */

var mongodb = require('mongodb')
  , ReadPref = mongodb.ReadPreference
  , ObjectId = mongodb.ObjectID

/**
 * Object clone with Mongoose natives support.
 *
 * Creates a minimal data Object.
 * It does not clone empty Arrays, empty Objects, and undefined values.
 * This makes the data payload sent to MongoDB as minimal as possible.
 *
 * @param {Object} obj the object to clone
 * @param {Object} options
 * @return {Object} the cloned object
 * @api private
 */

exports.clone = function clone (obj, options) {
  if (obj === undefined || obj === null)
    return obj;

  if (Array.isArray(obj))
    return exports.cloneArray(obj, options);

  if ('Object' === obj.constructor.name)
    return exports.cloneObject(obj, options);

  if ('Date' === obj.constructor.name || 'Function' === obj.constructor.name)
    return new obj.constructor(+obj);

  if ('RegExp' === obj.constructor.name)
    return new RegExp(obj.source);

  if (obj instanceof ObjectId)
    return new ObjectId(obj.id);

  if (obj.valueOf)
    return obj.valueOf();
};
var clone = exports.clone;

/*!
 * ignore
 */

var cloneObject = exports.cloneObject = function cloneObject (obj, options) {
  var retainKeyOrder = options && options.retainKeyOrder
    , minimize = options && options.minimize
    , ret = {}
    , hasKeys
    , keys
    , val
    , k
    , i

  if (retainKeyOrder) {
    for (k in obj) {
      val = clone(obj[k], options);

      if (!minimize || ('undefined' !== typeof val)) {
        hasKeys || (hasKeys = true);
        ret[k] = val;
      }
    }
  } else {
    // faster

    keys = Object.keys(obj);
    i = keys.length;

    while (i--) {
      k = keys[i];
      val = clone(obj[k], options);

      if (!minimize || ('undefined' !== typeof val)) {
        if (!hasKeys) hasKeys = true;
        ret[k] = val;
      }
    }
  }

  return minimize
    ? hasKeys && ret
    : ret;
};

var cloneArray = exports.cloneArray = function cloneArray (arr, options) {
  var ret = [];
  for (var i = 0, l = arr.length; i < l; i++)
    ret.push(clone(arr[i], options));
  return ret;
};

/**
 * process.nextTick helper.
 *
 * Wraps the given `callback` in a try/catch. If an error is
 * caught it will be thrown on nextTick.
 *
 * node-mongodb-native had a habit of state corruption when
 * an error was immediately thrown from within a collection
 * method (find, update, etc) callback.
 *
 * @param {Function} [callback]
 * @api private
 */

var tick = exports.tick = function tick (callback) {
  if ('function' !== typeof callback) return;
  return function () {
    try {
      callback.apply(this, arguments);
    } catch (err) {
      // only nextTick on err to get out of
      // the event loop and avoid state corruption.
      process.nextTick(function () {
        throw err;
      });
    }
  }
}

/**
 * Merges `from` into `to` without overwriting existing properties.
 *
 * @param {Object} to
 * @param {Object} from
 * @api private
 */

var merge = exports.merge = function merge (to, from) {
  var keys = Object.keys(from)
    , i = keys.length
    , key

  while (i--) {
    key = keys[i];
    if ('undefined' === typeof to[key]) {
      to[key] = from[key];
    } else {
      if (exports.isObject(from[key])) {
        merge(to[key], from[key]);
      } else {
        to[key] = from[key];
      }
    }
  }
}

/**
 * Read pref helper (mongo 2.2 drivers support this)
 *
 * Allows using aliases instead of full preference names:
 *
 *     p   primary
 *     pp  primaryPreferred
 *     s   secondary
 *     sp  secondaryPreferred
 *     n   nearest
 *
 * @param {String|Array} pref
 * @param {Array} [tags]
 */

exports.readPref = function readPref (pref, tags) {
  if (Array.isArray(pref)) {
    tags = pref[1];
    pref = pref[0];
  }

  switch (pref) {
    case 'p':
      pref = 'primary';
      break;
    case 'pp':
      pref = 'primaryPrefered';
      break;
    case 's':
      pref = 'secondary';
      break;
    case 'sp':
      pref = 'secondaryPrefered';
      break;
    case 'n':
      pref = 'nearest';
      break;
  }

  return new ReadPref(pref, tags);
}

/**
 * Object.prototype.toString.call helper
 */

var toString = Object.prototype.toString;
exports.toString = function (arg) {
  return toString.call(arg);
}

/**
 * Determines if `arg` is an object.
 *
 * @param {Object|Array|String|Function|RegExp|any} arg
 * @return {Boolean}
 */

exports.isObject = function (arg) {
  return '[object Object]' == exports.toString(arg);
}

/**
 * Determines if `arg` is an array.
 *
 * @param {Object}
 * @return {Boolean}
 * @see nodejs utils
 */

exports.isArray = function (arg) {
  return Array.isArray(arg) ||
    'object' == typeof arg && '[object Array]' == exports.toString(arg);
}

/**
 * Object.keys helper
 */

exports.keys = Object.keys || function (obj) {
  var keys = [];
  for (var k in obj) if (obj.hasOwnProperty(k)) {
    keys.push(k);
  }
  return keys;
}
<commit_msg>callbacks always fire on next turn of loop<commit_after>
/*!
 * Module dependencies.
 */

var mongodb = require('mongodb')
  , ReadPref = mongodb.ReadPreference
  , ObjectId = mongodb.ObjectID

/**
 * Object clone with Mongoose natives support.
 *
 * Creates a minimal data Object.
 * It does not clone empty Arrays, empty Objects, and undefined values.
 * This makes the data payload sent to MongoDB as minimal as possible.
 *
 * @param {Object} obj the object to clone
 * @param {Object} options
 * @return {Object} the cloned object
 * @api private
 */

exports.clone = function clone (obj, options) {
  if (obj === undefined || obj === null)
    return obj;

  if (Array.isArray(obj))
    return exports.cloneArray(obj, options);

  if ('Object' === obj.constructor.name)
    return exports.cloneObject(obj, options);

  if ('Date' === obj.constructor.name || 'Function' === obj.constructor.name)
    return new obj.constructor(+obj);

  if ('RegExp' === obj.constructor.name)
    return new RegExp(obj.source);

  if (obj instanceof ObjectId)
    return new ObjectId(obj.id);

  if (obj.valueOf)
    return obj.valueOf();
};
var clone = exports.clone;

/*!
 * ignore
 */

var cloneObject = exports.cloneObject = function cloneObject (obj, options) {
  var retainKeyOrder = options && options.retainKeyOrder
    , minimize = options && options.minimize
    , ret = {}
    , hasKeys
    , keys
    , val
    , k
    , i

  if (retainKeyOrder) {
    for (k in obj) {
      val = clone(obj[k], options);

      if (!minimize || ('undefined' !== typeof val)) {
        hasKeys || (hasKeys = true);
        ret[k] = val;
      }
    }
  } else {
    // faster

    keys = Object.keys(obj);
    i = keys.length;

    while (i--) {
      k = keys[i];
      val = clone(obj[k], options);

      if (!minimize || ('undefined' !== typeof val)) {
        if (!hasKeys) hasKeys = true;
        ret[k] = val;
      }
    }
  }

  return minimize
    ? hasKeys && ret
    : ret;
};

var cloneArray = exports.cloneArray = function cloneArray (arr, options) {
  var ret = [];
  for (var i = 0, l = arr.length; i < l; i++)
    ret.push(clone(arr[i], options));
  return ret;
};

var later = 'function' == typeof setImmediate
  ? setImmediate
  : process.nextTick;

/**
 * process.nextTick helper.
 *
 * Wraps the given `callback` in a try/catch. If an error is
 * caught it will be thrown on nextTick.
 *
 * node-mongodb-native had a habit of state corruption when
 * an error was immediately thrown from within a collection
 * method (find, update, etc) callback.
 *
 * @param {Function} [callback]
 * @api private
 */

var tick = exports.tick = function tick (callback) {
  if ('function' !== typeof callback) return;
  return function () {
    // callbacks should always be fired on the next
    // turn of the event loop. A side benefit is
    // errors thrown from executing the callback
    // will not cause drivers state to be corrupted
    // which has historically been a problem.
    var args = arguments;
    later(function(){
      callback.apply(this, args);
    });
  }
}

/**
 * Merges `from` into `to` without overwriting existing properties.
 *
 * @param {Object} to
 * @param {Object} from
 * @api private
 */

var merge = exports.merge = function merge (to, from) {
  var keys = Object.keys(from)
    , i = keys.length
    , key

  while (i--) {
    key = keys[i];
    if ('undefined' === typeof to[key]) {
      to[key] = from[key];
    } else {
      if (exports.isObject(from[key])) {
        merge(to[key], from[key]);
      } else {
        to[key] = from[key];
      }
    }
  }
}

/**
 * Read pref helper (mongo 2.2 drivers support this)
 *
 * Allows using aliases instead of full preference names:
 *
 *     p   primary
 *     pp  primaryPreferred
 *     s   secondary
 *     sp  secondaryPreferred
 *     n   nearest
 *
 * @param {String|Array} pref
 * @param {Array} [tags]
 */

exports.readPref = function readPref (pref, tags) {
  if (Array.isArray(pref)) {
    tags = pref[1];
    pref = pref[0];
  }

  switch (pref) {
    case 'p':
      pref = 'primary';
      break;
    case 'pp':
      pref = 'primaryPrefered';
      break;
    case 's':
      pref = 'secondary';
      break;
    case 'sp':
      pref = 'secondaryPrefered';
      break;
    case 'n':
      pref = 'nearest';
      break;
  }

  return new ReadPref(pref, tags);
}

/**
 * Object.prototype.toString.call helper
 */

var toString = Object.prototype.toString;
exports.toString = function (arg) {
  return toString.call(arg);
}

/**
 * Determines if `arg` is an object.
 *
 * @param {Object|Array|String|Function|RegExp|any} arg
 * @return {Boolean}
 */

exports.isObject = function (arg) {
  return '[object Object]' == exports.toString(arg);
}

/**
 * Determines if `arg` is an array.
 *
 * @param {Object}
 * @return {Boolean}
 * @see nodejs utils
 */

exports.isArray = function (arg) {
  return Array.isArray(arg) ||
    'object' == typeof arg && '[object Array]' == exports.toString(arg);
}

/**
 * Object.keys helper
 */

exports.keys = Object.keys || function (obj) {
  var keys = [];
  for (var k in obj) if (obj.hasOwnProperty(k)) {
    keys.push(k);
  }
  return keys;
}
<|endoftext|>


<commit_before>// Load modules

// Declare internals

var internals = {};

exports.arrayToObject = function (source) {

    var obj = {};
    for (var i = 0, il = source.length; i < il; ++i) {
        if (typeof source[i] !== 'undefined') {

            obj[i] = source[i];
        }
    }

    return obj;
};

exports.merge = function (target, source) {

    if (!source) {
        return target;
    }

    if (Array.isArray(source)) {
        for (var i = 0, il = source.length; i < il; ++i) {
            if (typeof source[i] !== 'undefined') {
                if (typeof target[i] === 'object') {
                    target[i] = exports.merge(target[i], source[i]);
                }
                else {
                    target[i] = source[i];
                }
            }
        }

        return target;
    }

    if (Array.isArray(target)) {
        if (typeof source !== 'object') {
            target.push(source);
            return target;
        }
        else {
            target = exports.arrayToObject(target);
        }
    }

    var keys = Object.keys(source);
    for (var k = 0, kl = keys.length; k < kl; ++k) {
        var key = keys[k];
        var value = source[key];

        if (value &&
            typeof value === 'object') {

            if (!target[key]) {
                target[key] = value;
            }
            else {
                target[key] = exports.merge(target[key], value);
            }
        }
        else {
            target[key] = value;
        }
    }

    return target;
};

exports.decode = function (str) {

    try {
        return decodeURIComponent(str.replace(/\+/g, ' '));
    } catch (e) {
        return str;
    }
};

exports.compact = function (obj, refs) {

    if (typeof obj !== 'object' ||
        obj === null) {

        return obj;
    }

    refs = refs || [];
    var lookup = refs.indexOf(obj);
    if (lookup !== -1) {
        return refs[lookup];
    }

    refs.push(obj);

    if (Array.isArray(obj)) {
        var compacted = [];

        for (var i = 0, l = obj.length; i < l; ++i) {
            if (typeof obj[i] !== 'undefined') {
                compacted.push(obj[i]);
            }
        }

        return compacted;
    }

    var keys = Object.keys(obj);
    for (var i = 0, il = keys.length; i < il; ++i) {
        var key = keys[i];
        obj[key] = exports.compact(obj[key], refs);
    }

    return obj;
};

exports.isRegExp = function (obj) {
    return Object.prototype.toString.call(obj) === '[object RegExp]';
};

exports.isBuffer = function (obj) {

    if (obj === null ||
        obj === undefined) {

        return false;
    }

    return obj.constructor &&
        obj.constructor.isBuffer &&
        obj.constructor.isBuffer(obj);
};
<commit_msg>better undefined check<commit_after>// Load modules

// Declare internals

var internals = {};

exports.arrayToObject = function (source) {

    var obj = {};
    for (var i = 0, il = source.length; i < il; ++i) {
        if (typeof source[i] !== 'undefined') {

            obj[i] = source[i];
        }
    }

    return obj;
};

exports.merge = function (target, source) {

    if (!source) {
        return target;
    }

    if (Array.isArray(source)) {
        for (var i = 0, il = source.length; i < il; ++i) {
            if (typeof source[i] !== 'undefined') {
                if (typeof target[i] === 'object') {
                    target[i] = exports.merge(target[i], source[i]);
                }
                else {
                    target[i] = source[i];
                }
            }
        }

        return target;
    }

    if (Array.isArray(target)) {
        if (typeof source !== 'object') {
            target.push(source);
            return target;
        }
        else {
            target = exports.arrayToObject(target);
        }
    }

    var keys = Object.keys(source);
    for (var k = 0, kl = keys.length; k < kl; ++k) {
        var key = keys[k];
        var value = source[key];

        if (value &&
            typeof value === 'object') {

            if (!target[key]) {
                target[key] = value;
            }
            else {
                target[key] = exports.merge(target[key], value);
            }
        }
        else {
            target[key] = value;
        }
    }

    return target;
};

exports.decode = function (str) {

    try {
        return decodeURIComponent(str.replace(/\+/g, ' '));
    } catch (e) {
        return str;
    }
};

exports.compact = function (obj, refs) {

    if (typeof obj !== 'object' ||
        obj === null) {

        return obj;
    }

    refs = refs || [];
    var lookup = refs.indexOf(obj);
    if (lookup !== -1) {
        return refs[lookup];
    }

    refs.push(obj);

    if (Array.isArray(obj)) {
        var compacted = [];

        for (var i = 0, l = obj.length; i < l; ++i) {
            if (typeof obj[i] !== 'undefined') {
                compacted.push(obj[i]);
            }
        }

        return compacted;
    }

    var keys = Object.keys(obj);
    for (var i = 0, il = keys.length; i < il; ++i) {
        var key = keys[i];
        obj[key] = exports.compact(obj[key], refs);
    }

    return obj;
};

exports.isRegExp = function (obj) {
    return Object.prototype.toString.call(obj) === '[object RegExp]';
};

exports.isBuffer = function (obj) {

    if (obj === null ||
        typeof obj === 'undefined') {

        return false;
    }

    return obj.constructor &&
        obj.constructor.isBuffer &&
        obj.constructor.isBuffer(obj);
};
<|endoftext|>


<commit_before>
var filter = require('./ansi')
  , crypto = require('crypto')
  , _ = require('underscore')

module.exports =
  { gravatar: gravatar
  , sanitizeProject: sanitizeProject
  , sanitizeBranch: sanitizeBranch
  , sanitizeUser: sanitizeUser
  , timeFromId: timeFromId
  , defaultSchema: defaultSchema
  , validateAgainstSchema: validateAgainstSchema
  , mergePlugins: mergePlugins
  , mergeConfigs: mergeConfigs
  , findBranch: findBranch
  }

function findBranch(branches, name) {
  var foundBranch = false
  branches.some(function (branch) {
    var regEx = new RegExp('^' + branch.name.replace(/\*/g, '.*') + '$')
    if (regEx.test(name)) {
      foundBranch = branch
      return true
    }
  })
  return foundBranch
}

// merge plugins from the DB with ones from strider.json. The latter overrides the former
function mergePlugins(branch, sjson) {
  if (!branch) return sjson
  if (!sjson) return branch
  // if strict_plugins is not turned on, we merge each plugin config instead of overwriting.
  var plugins = []
    , pdict = {}
    , plugin
    , i
  for (i=0; i<sjson.length; i++) {
    plugins.push(sjson[i])
    pdict[sjson[i].id] = true
  }
  for (i=0; i<branch.length; i++) {
    if (!pdict[branch[i].id]) plugins.push(branch[i])
  }
  return plugins
}

function mergeConfigs(branch, sjson) {
  var config = _.extend({}, branch, sjson)
  if (!sjson.merge_plugins) return config
  config.plugins = mergePlugins(branch.plugins, sjson.plugins)
  return config
}

function validateVal(val, schema) {
  if (schema === String) return val + ''
  if (schema === Number) {
    val = parseFloat(schema)
    return isNaN(val) ? 0 : val
  }
  if (schema === Boolean) return !!val
  if (Array.isArray(schema)) {
    var ret = []
    if (!Array.isArray(val)) return []
    for (var i=0; i<val.length; i++) {
      ret.push(validateVal(val[i], schema[0]))
    }
    return ret
  }
  if (schema.type && !schema.type.type) {
    val = validateVal(val, schema.type)
    if (schema.enum && schema.enum.indexOf(val) === -1) {
      return
    }
    return val
  }
  if ('object' !== typeof schema) return
  if ('object' !== typeof val) return {}
  // if schema is {}, it's unchecked.
  if (Object.keys(schema).length === 0) return val
  return validateAgainstSchema(val, schema)
}

function defaultVal(val) {
  if (val === String) return ''
  if (val === Number) return 0
  if (val === Boolean) return false
  if (!val) return null
  if (Array.isArray(val)) return []
  if (val.type && !val.type.type) {
    if (val.default) return val.default
    if (val.enum) return val.enum[0]
    return defaultVal(val.type)
  }
  if ('object' === typeof val) return defaultSchema(val)
  return null
}

function defaultSchema(schema) {
  var data = {}
    , val
  for (var key in schema) {
    data[key] = defaultVal(schema[key])
  }
  return data
}

function validateAgainstSchema(obj, schema) {
  var data = {}
  for (var key in obj) {
    if (!schema[key]) continue;
    data[key] = validateVal(obj[key], schema[key])
  }
  return data;
}

function timeFromId(id) {
  return new Date(parseInt(id.toString().substring(0, 8), 16) * 1000)
}

function sanitizeBranch(branch) {
  var plugins = []
  for (var i=0; i<branch.plugins; i++) {
    plugins.push({id: branch.plugins[i].id, enabled: branch.plugins[i].enabled})
  }
  return {
    plugins: plugins,
    public: branch.public,
    active: branch.active,
    deploy_on_green: branch.deploy_on_green,
    runner: {
      id: branch.runner && branch.runner.id
    }
  }
}

function sanitizeUser(user) {
  for (var i=0; i<user.accounts.length; i++) {
    delete user.accounts[i].cache
  }
  return user
}

function sanitizeProject(project) {
  return {
    _id: project._id,
    name: project.name,
    branches: project.branches.map(sanitizeBranch),
    public: project.public,
    display_url: project.display_url,
    display_name : project.display_name,
    provider: {
      id: project.provider.id
    }
  }
}

function gravatar(email) {
  var hash = crypto.createHash('md5').update(email.toLowerCase()).digest("hex")
  return 'https://secure.gravatar.com/avatar/' + hash + '?d=identicon';
}
<commit_msg>When trying to find a branch, ensure branch name is set before using it<commit_after>
var filter = require('./ansi')
  , crypto = require('crypto')
  , _ = require('underscore')

module.exports =
  { gravatar: gravatar
  , sanitizeProject: sanitizeProject
  , sanitizeBranch: sanitizeBranch
  , sanitizeUser: sanitizeUser
  , timeFromId: timeFromId
  , defaultSchema: defaultSchema
  , validateAgainstSchema: validateAgainstSchema
  , mergePlugins: mergePlugins
  , mergeConfigs: mergeConfigs
  , findBranch: findBranch
  }

function findBranch(branches, name) {
  var foundBranch = false
  branches.some(function (branch) {
    if (branch.name) {
      var regEx = new RegExp('^' + branch.name.replace(/\*/g, '.*') + '$')
      if (regEx.test(name)) {
        foundBranch = branch
        return true
      }
    }
  })
  return foundBranch
}

// merge plugins from the DB with ones from strider.json. The latter overrides the former
function mergePlugins(branch, sjson) {
  if (!branch) return sjson
  if (!sjson) return branch
  // if strict_plugins is not turned on, we merge each plugin config instead of overwriting.
  var plugins = []
    , pdict = {}
    , plugin
    , i
  for (i=0; i<sjson.length; i++) {
    plugins.push(sjson[i])
    pdict[sjson[i].id] = true
  }
  for (i=0; i<branch.length; i++) {
    if (!pdict[branch[i].id]) plugins.push(branch[i])
  }
  return plugins
}

function mergeConfigs(branch, sjson) {
  var config = _.extend({}, branch, sjson)
  if (!sjson.merge_plugins) return config
  config.plugins = mergePlugins(branch.plugins, sjson.plugins)
  return config
}

function validateVal(val, schema) {
  if (schema === String) return val + ''
  if (schema === Number) {
    val = parseFloat(schema)
    return isNaN(val) ? 0 : val
  }
  if (schema === Boolean) return !!val
  if (Array.isArray(schema)) {
    var ret = []
    if (!Array.isArray(val)) return []
    for (var i=0; i<val.length; i++) {
      ret.push(validateVal(val[i], schema[0]))
    }
    return ret
  }
  if (schema.type && !schema.type.type) {
    val = validateVal(val, schema.type)
    if (schema.enum && schema.enum.indexOf(val) === -1) {
      return
    }
    return val
  }
  if ('object' !== typeof schema) return
  if ('object' !== typeof val) return {}
  // if schema is {}, it's unchecked.
  if (Object.keys(schema).length === 0) return val
  return validateAgainstSchema(val, schema)
}

function defaultVal(val) {
  if (val === String) return ''
  if (val === Number) return 0
  if (val === Boolean) return false
  if (!val) return null
  if (Array.isArray(val)) return []
  if (val.type && !val.type.type) {
    if (val.default) return val.default
    if (val.enum) return val.enum[0]
    return defaultVal(val.type)
  }
  if ('object' === typeof val) return defaultSchema(val)
  return null
}

function defaultSchema(schema) {
  var data = {}
    , val
  for (var key in schema) {
    data[key] = defaultVal(schema[key])
  }
  return data
}

function validateAgainstSchema(obj, schema) {
  var data = {}
  for (var key in obj) {
    if (!schema[key]) continue;
    data[key] = validateVal(obj[key], schema[key])
  }
  return data;
}

function timeFromId(id) {
  return new Date(parseInt(id.toString().substring(0, 8), 16) * 1000)
}

function sanitizeBranch(branch) {
  var plugins = []
  for (var i=0; i<branch.plugins; i++) {
    plugins.push({id: branch.plugins[i].id, enabled: branch.plugins[i].enabled})
  }
  return {
    plugins: plugins,
    public: branch.public,
    active: branch.active,
    deploy_on_green: branch.deploy_on_green,
    runner: {
      id: branch.runner && branch.runner.id
    }
  }
}

function sanitizeUser(user) {
  for (var i=0; i<user.accounts.length; i++) {
    delete user.accounts[i].cache
  }
  return user
}

function sanitizeProject(project) {
  return {
    _id: project._id,
    name: project.name,
    branches: project.branches.map(sanitizeBranch),
    public: project.public,
    display_url: project.display_url,
    display_name : project.display_name,
    provider: {
      id: project.provider.id
    }
  }
}

function gravatar(email) {
  var hash = crypto.createHash('md5').update(email.toLowerCase()).digest("hex")
  return 'https://secure.gravatar.com/avatar/' + hash + '?d=identicon';
}
<|endoftext|>


<commit_before>'use strict';

var bind = require('./helpers/bind');

/*global toString:true*/

// utils is a library of generic helper functions non-specific to axios

var toString = Object.prototype.toString;

/**
 * Determine if a value is an Array
 *
 * @param {Object} val The value to test
 * @returns {boolean} True if value is an Array, otherwise false
 */
function isArray(val) {
  return toString.call(val) === '[object Array]';
}

/**
 * Determine if a value is an ArrayBuffer
 *
 * @param {Object} val The value to test
 * @returns {boolean} True if value is an ArrayBuffer, otherwise false
 */
function isArrayBuffer(val) {
  return toString.call(val) === '[object ArrayBuffer]';
}

/**
 * Determine if a value is a FormData
 *
 * @param {Object} val The value to test
 * @returns {boolean} True if value is an FormData, otherwise false
 */
function isFormData(val) {
  return (typeof FormData !== 'undefined') && (val instanceof FormData);
}

/**
 * Determine if a value is a view on an ArrayBuffer
 *
 * @param {Object} val The value to test
 * @returns {boolean} True if value is a view on an ArrayBuffer, otherwise false
 */
function isArrayBufferView(val) {
  var result;
  if ((typeof ArrayBuffer !== 'undefined') && (ArrayBuffer.isView)) {
    result = ArrayBuffer.isView(val);
  } else {
    result = (val) && (val.buffer) && (val.buffer instanceof ArrayBuffer);
  }
  return result;
}

/**
 * Determine if a value is a String
 *
 * @param {Object} val The value to test
 * @returns {boolean} True if value is a String, otherwise false
 */
function isString(val) {
  return typeof val === 'string';
}

/**
 * Determine if a value is a Number
 *
 * @param {Object} val The value to test
 * @returns {boolean} True if value is a Number, otherwise false
 */
function isNumber(val) {
  return typeof val === 'number';
}

/**
 * Determine if a value is undefined
 *
 * @param {Object} val The value to test
 * @returns {boolean} True if the value is undefined, otherwise false
 */
function isUndefined(val) {
  return typeof val === 'undefined';
}

/**
 * Determine if a value is an Object
 *
 * @param {Object} val The value to test
 * @returns {boolean} True if value is an Object, otherwise false
 */
function isObject(val) {
  return val !== null && typeof val === 'object';
}

/**
 * Determine if a value is a Date
 *
 * @param {Object} val The value to test
 * @returns {boolean} True if value is a Date, otherwise false
 */
function isDate(val) {
  return toString.call(val) === '[object Date]';
}

/**
 * Determine if a value is a File
 *
 * @param {Object} val The value to test
 * @returns {boolean} True if value is a File, otherwise false
 */
function isFile(val) {
  return toString.call(val) === '[object File]';
}

/**
 * Determine if a value is a Blob
 *
 * @param {Object} val The value to test
 * @returns {boolean} True if value is a Blob, otherwise false
 */
function isBlob(val) {
  return toString.call(val) === '[object Blob]';
}

/**
 * Determine if a value is a Function
 *
 * @param {Object} val The value to test
 * @returns {boolean} True if value is a Function, otherwise false
 */
function isFunction(val) {
  return toString.call(val) === '[object Function]';
}

/**
 * Determine if a value is a Stream
 *
 * @param {Object} val The value to test
 * @returns {boolean} True if value is a Stream, otherwise false
 */
function isStream(val) {
  return isObject(val) && isFunction(val.pipe);
}

/**
 * Determine if a value is a URLSearchParams object
 *
 * @param {Object} val The value to test
 * @returns {boolean} True if value is a URLSearchParams object, otherwise false
 */
function isURLSearchParams(val) {
  return typeof URLSearchParams !== 'undefined' && val instanceof URLSearchParams;
}

/**
 * Trim excess whitespace off the beginning and end of a string
 *
 * @param {String} str The String to trim
 * @returns {String} The String freed of excess whitespace
 */
function trim(str) {
  return str.replace(/^\s*/, '').replace(/\s*$/, '');
}

/**
 * Determine if we're running in a standard browser environment
 *
 * This allows axios to run in a web worker, and react-native.
 * Both environments support XMLHttpRequest, but not fully standard globals.
 * As of react-native 0.13, it can be identified from navigator.product.
 *
 * web workers:
 *  typeof window -> undefined
 *  typeof document -> undefined
 *
 * react-native:
 *  navigator.product -> 'ReactNative'
 */
function isStandardBrowserEnv() {
  if (typeof navigator.product !== 'undefined' && navigator.product === 'ReactNative') {
    return false;
  }
  return (
    typeof window !== 'undefined' &&
    typeof document !== 'undefined'
  );
}

/**
 * Iterate over an Array or an Object invoking a function for each item.
 *
 * If `obj` is an Array callback will be called passing
 * the value, index, and complete array for each item.
 *
 * If 'obj' is an Object callback will be called passing
 * the value, key, and complete object for each property.
 *
 * @param {Object|Array} obj The object to iterate
 * @param {Function} fn The callback to invoke for each item
 */
function forEach(obj, fn) {
  // Don't bother if no value provided
  if (obj === null || typeof obj === 'undefined') {
    return;
  }

  // Force an array if not already something iterable
  if (typeof obj !== 'object' && !isArray(obj)) {
    /*eslint no-param-reassign:0*/
    obj = [obj];
  }

  if (isArray(obj)) {
    // Iterate over array values
    for (var i = 0, l = obj.length; i < l; i++) {
      fn.call(null, obj[i], i, obj);
    }
  } else {
    // Iterate over object keys
    for (var key in obj) {
      if (Object.prototype.hasOwnProperty.call(obj, key)) {
        fn.call(null, obj[key], key, obj);
      }
    }
  }
}

/**
 * Accepts varargs expecting each argument to be an object, then
 * immutably merges the properties of each object and returns result.
 *
 * When multiple objects contain the same key the later object in
 * the arguments list will take precedence.
 *
 * Example:
 *
 * ```js
 * var result = merge({foo: 123}, {foo: 456});
 * console.log(result.foo); // outputs 456
 * ```
 *
 * @param {Object} obj1 Object to merge
 * @returns {Object} Result of all merge properties
 */
function merge(/* obj1, obj2, obj3, ... */) {
  var result = {};
  function assignValue(val, key) {
    if (typeof result[key] === 'object' && typeof val === 'object') {
      result[key] = merge(result[key], val);
    } else {
      result[key] = val;
    }
  }

  for (var i = 0, l = arguments.length; i < l; i++) {
    forEach(arguments[i], assignValue);
  }
  return result;
}

/**
 * Extends object a by mutably adding to it the properties of object b.
 *
 * @param {Object} a The object to be extended
 * @param {Object} b The object to copy properties from
 * @param {Object} thisArg The object to bind function to
 * @return {Object} The resulting value of object a
 */
function extend(a, b, thisArg) {
  forEach(b, function assignValue(val, key) {
    if (thisArg && typeof val === 'function') {
      a[key] = bind(val, thisArg);
    } else {
      a[key] = val;
    }
  });
  return a;
}

module.exports = {
  isArray: isArray,
  isArrayBuffer: isArrayBuffer,
  isFormData: isFormData,
  isArrayBufferView: isArrayBufferView,
  isString: isString,
  isNumber: isNumber,
  isObject: isObject,
  isUndefined: isUndefined,
  isDate: isDate,
  isFile: isFile,
  isBlob: isBlob,
  isFunction: isFunction,
  isStream: isStream,
  isURLSearchParams: isURLSearchParams,
  isStandardBrowserEnv: isStandardBrowserEnv,
  forEach: forEach,
  merge: merge,
  extend: extend,
  trim: trim
};
<commit_msg>Check that navigator is defined<commit_after>'use strict';

var bind = require('./helpers/bind');

/*global toString:true*/

// utils is a library of generic helper functions non-specific to axios

var toString = Object.prototype.toString;

/**
 * Determine if a value is an Array
 *
 * @param {Object} val The value to test
 * @returns {boolean} True if value is an Array, otherwise false
 */
function isArray(val) {
  return toString.call(val) === '[object Array]';
}

/**
 * Determine if a value is an ArrayBuffer
 *
 * @param {Object} val The value to test
 * @returns {boolean} True if value is an ArrayBuffer, otherwise false
 */
function isArrayBuffer(val) {
  return toString.call(val) === '[object ArrayBuffer]';
}

/**
 * Determine if a value is a FormData
 *
 * @param {Object} val The value to test
 * @returns {boolean} True if value is an FormData, otherwise false
 */
function isFormData(val) {
  return (typeof FormData !== 'undefined') && (val instanceof FormData);
}

/**
 * Determine if a value is a view on an ArrayBuffer
 *
 * @param {Object} val The value to test
 * @returns {boolean} True if value is a view on an ArrayBuffer, otherwise false
 */
function isArrayBufferView(val) {
  var result;
  if ((typeof ArrayBuffer !== 'undefined') && (ArrayBuffer.isView)) {
    result = ArrayBuffer.isView(val);
  } else {
    result = (val) && (val.buffer) && (val.buffer instanceof ArrayBuffer);
  }
  return result;
}

/**
 * Determine if a value is a String
 *
 * @param {Object} val The value to test
 * @returns {boolean} True if value is a String, otherwise false
 */
function isString(val) {
  return typeof val === 'string';
}

/**
 * Determine if a value is a Number
 *
 * @param {Object} val The value to test
 * @returns {boolean} True if value is a Number, otherwise false
 */
function isNumber(val) {
  return typeof val === 'number';
}

/**
 * Determine if a value is undefined
 *
 * @param {Object} val The value to test
 * @returns {boolean} True if the value is undefined, otherwise false
 */
function isUndefined(val) {
  return typeof val === 'undefined';
}

/**
 * Determine if a value is an Object
 *
 * @param {Object} val The value to test
 * @returns {boolean} True if value is an Object, otherwise false
 */
function isObject(val) {
  return val !== null && typeof val === 'object';
}

/**
 * Determine if a value is a Date
 *
 * @param {Object} val The value to test
 * @returns {boolean} True if value is a Date, otherwise false
 */
function isDate(val) {
  return toString.call(val) === '[object Date]';
}

/**
 * Determine if a value is a File
 *
 * @param {Object} val The value to test
 * @returns {boolean} True if value is a File, otherwise false
 */
function isFile(val) {
  return toString.call(val) === '[object File]';
}

/**
 * Determine if a value is a Blob
 *
 * @param {Object} val The value to test
 * @returns {boolean} True if value is a Blob, otherwise false
 */
function isBlob(val) {
  return toString.call(val) === '[object Blob]';
}

/**
 * Determine if a value is a Function
 *
 * @param {Object} val The value to test
 * @returns {boolean} True if value is a Function, otherwise false
 */
function isFunction(val) {
  return toString.call(val) === '[object Function]';
}

/**
 * Determine if a value is a Stream
 *
 * @param {Object} val The value to test
 * @returns {boolean} True if value is a Stream, otherwise false
 */
function isStream(val) {
  return isObject(val) && isFunction(val.pipe);
}

/**
 * Determine if a value is a URLSearchParams object
 *
 * @param {Object} val The value to test
 * @returns {boolean} True if value is a URLSearchParams object, otherwise false
 */
function isURLSearchParams(val) {
  return typeof URLSearchParams !== 'undefined' && val instanceof URLSearchParams;
}

/**
 * Trim excess whitespace off the beginning and end of a string
 *
 * @param {String} str The String to trim
 * @returns {String} The String freed of excess whitespace
 */
function trim(str) {
  return str.replace(/^\s*/, '').replace(/\s*$/, '');
}

/**
 * Determine if we're running in a standard browser environment
 *
 * This allows axios to run in a web worker, and react-native.
 * Both environments support XMLHttpRequest, but not fully standard globals.
 *
 * web workers:
 *  typeof window -> undefined
 *  typeof document -> undefined
 *
 * react-native:
 *  navigator.product -> 'ReactNative'
 */
function isStandardBrowserEnv() {
  if (typeof navigator !== 'undefined' && navigator.product === 'ReactNative') {
    return false;
  }
  return (
    typeof window !== 'undefined' &&
    typeof document !== 'undefined'
  );
}

/**
 * Iterate over an Array or an Object invoking a function for each item.
 *
 * If `obj` is an Array callback will be called passing
 * the value, index, and complete array for each item.
 *
 * If 'obj' is an Object callback will be called passing
 * the value, key, and complete object for each property.
 *
 * @param {Object|Array} obj The object to iterate
 * @param {Function} fn The callback to invoke for each item
 */
function forEach(obj, fn) {
  // Don't bother if no value provided
  if (obj === null || typeof obj === 'undefined') {
    return;
  }

  // Force an array if not already something iterable
  if (typeof obj !== 'object' && !isArray(obj)) {
    /*eslint no-param-reassign:0*/
    obj = [obj];
  }

  if (isArray(obj)) {
    // Iterate over array values
    for (var i = 0, l = obj.length; i < l; i++) {
      fn.call(null, obj[i], i, obj);
    }
  } else {
    // Iterate over object keys
    for (var key in obj) {
      if (Object.prototype.hasOwnProperty.call(obj, key)) {
        fn.call(null, obj[key], key, obj);
      }
    }
  }
}

/**
 * Accepts varargs expecting each argument to be an object, then
 * immutably merges the properties of each object and returns result.
 *
 * When multiple objects contain the same key the later object in
 * the arguments list will take precedence.
 *
 * Example:
 *
 * ```js
 * var result = merge({foo: 123}, {foo: 456});
 * console.log(result.foo); // outputs 456
 * ```
 *
 * @param {Object} obj1 Object to merge
 * @returns {Object} Result of all merge properties
 */
function merge(/* obj1, obj2, obj3, ... */) {
  var result = {};
  function assignValue(val, key) {
    if (typeof result[key] === 'object' && typeof val === 'object') {
      result[key] = merge(result[key], val);
    } else {
      result[key] = val;
    }
  }

  for (var i = 0, l = arguments.length; i < l; i++) {
    forEach(arguments[i], assignValue);
  }
  return result;
}

/**
 * Extends object a by mutably adding to it the properties of object b.
 *
 * @param {Object} a The object to be extended
 * @param {Object} b The object to copy properties from
 * @param {Object} thisArg The object to bind function to
 * @return {Object} The resulting value of object a
 */
function extend(a, b, thisArg) {
  forEach(b, function assignValue(val, key) {
    if (thisArg && typeof val === 'function') {
      a[key] = bind(val, thisArg);
    } else {
      a[key] = val;
    }
  });
  return a;
}

module.exports = {
  isArray: isArray,
  isArrayBuffer: isArrayBuffer,
  isFormData: isFormData,
  isArrayBufferView: isArrayBufferView,
  isString: isString,
  isNumber: isNumber,
  isObject: isObject,
  isUndefined: isUndefined,
  isDate: isDate,
  isFile: isFile,
  isBlob: isBlob,
  isFunction: isFunction,
  isStream: isStream,
  isURLSearchParams: isURLSearchParams,
  isStandardBrowserEnv: isStandardBrowserEnv,
  forEach: forEach,
  merge: merge,
  extend: extend,
  trim: trim
};
<|endoftext|>


<commit_before>var path = require("path");

var classToType = {};

var classNames = "Boolean Number String Function Array Date RegExp".split(" ");
for (var i = 0; i < classNames.length; i++) {
    var name = classNames[i];
    classToType["[object " + name + "]"] = name.toLowerCase();
}

var Utils = {

    typeOf:  function(obj) {
        if (obj === undefined || obj === null) {
            return String(obj);
        }
        myClass = Object.prototype.toString.call(obj);
        if (myClass in classToType) {
            return classToType[myClass];
        }
        return "object";
    },

    checkOwnProperty: function (obj, key) {
        return Object.prototype.hasOwnProperty.call(obj, key);
    },

    getPackageVersion:  function(packageJSONPath) {
        try {
            var packageInfo = require(packageJSONPath);
            return packageInfo.version;
        } catch (e) {
            return null;
        }
    },

    fullPath:  function(unknownPath) {
        return path.resolve(__dirname, unknownPath);
    },

    cloneObject:  function(obj, options) {
        if (!options) {
            options = {};
        }
        if (!(obj && Utils.typeOf(obj) === "object")) {
            return obj;
        }
        var except = options.except || [];
        var alreadyCloned = options.alreadyCloned || [];
        var copy = {};
        Object.keys(obj).forEach(function (key) {
            var val = obj[key];
            if (Utils.checkOwnProperty(obj, key) && except.indexOf(key) === -1) {
                if (Utils.typeOf(val) === "object") {
                    if (alreadyCloned.indexOf(val) === -1) {
                        alreadyCloned.push(val);
                        copy[key] = Utils.cloneObject(val, {
                            alreadyCloned: alreadyCloned
                        });
                    }
                } else {
                    copy[key] = val;
                }
            }
        });
        return copy;
    },

    mergeObjects:  function(dest, source, options) {
        if (!options) {
            options = {};
        }
        if (!(dest && Utils.typeOf(dest) === "object" && source && Utils.typeOf(source) === "object")) {
            return dest;
        }
        var alreadyMerged = options.alreadyMerged || [];

        Object.keys(source).forEach(function (key) {
            if (Utils.checkOwnProperty(source, key)) {
                val = source[key];
                if (Utils.typeOf(val) === "object" && dest[key]) {
                    if (alreadyMerged.indexOf(val) === -1) {
                        alreadyMerged.push(val);
                        Utils.mergeObjects(dest[key], val, {
                            alreadyMerged: alreadyMerged
                        });
                    }
                } else {
                    dest[key] = source[key];
                }
            }
        });
        return dest;
    },

    filterObject:  function(object, filters, options) {
        if (!options) {
            options = {};
        }
        if (Utils.typeOf(object) !== "object") {
            return;
        }
        if (Utils.typeOf(filters) !== "array") {
            return;
        }
        alreadyFiltered = options.alreadyFiltered || [];
        Object.keys(object).forEach(function (key) {
            if (Utils.checkOwnProperty(object, key)) {
                return filters.forEach(function(filter) {
                    if (key.indexOf(filter) !== -1) {
                        object[key] = "[FILTERED]";
                    } else if (Utils.typeOf(object[key]) === "object" && alreadyFiltered.indexOf(object[key]) === -1) {
                        alreadyFiltered.push(object[key]);
                        Utils.filterObject(object[key], filters, {
                            alreadyFiltered: alreadyFiltered
                        });
                    }
                });
            }
        });
    }
};

module.exports = Utils;
<commit_msg>Fixed global variables (caused by previous coffee script) that are throwing errors when trying to use the library<commit_after>var path = require("path");

var classToType = {};

var classNames = "Boolean Number String Function Array Date RegExp".split(" ");
for (var i = 0; i < classNames.length; i++) {
    var name = classNames[i];
    classToType["[object " + name + "]"] = name.toLowerCase();
}

var Utils = {

    typeOf:  function(obj) {
        if (obj === undefined || obj === null) {
            return String(obj);
        }
        var myClass = Object.prototype.toString.call(obj);
        if (myClass in classToType) {
            return classToType[myClass];
        }
        return "object";
    },

    checkOwnProperty: function (obj, key) {
        return Object.prototype.hasOwnProperty.call(obj, key);
    },

    getPackageVersion:  function(packageJSONPath) {
        try {
            var packageInfo = require(packageJSONPath);
            return packageInfo.version;
        } catch (e) {
            return null;
        }
    },

    fullPath:  function(unknownPath) {
        return path.resolve(__dirname, unknownPath);
    },

    cloneObject:  function(obj, options) {
        if (!options) {
            options = {};
        }
        if (!(obj && Utils.typeOf(obj) === "object")) {
            return obj;
        }
        var except = options.except || [];
        var alreadyCloned = options.alreadyCloned || [];
        var copy = {};
        Object.keys(obj).forEach(function (key) {
            var val = obj[key];
            if (Utils.checkOwnProperty(obj, key) && except.indexOf(key) === -1) {
                if (Utils.typeOf(val) === "object") {
                    if (alreadyCloned.indexOf(val) === -1) {
                        alreadyCloned.push(val);
                        copy[key] = Utils.cloneObject(val, {
                            alreadyCloned: alreadyCloned
                        });
                    }
                } else {
                    copy[key] = val;
                }
            }
        });
        return copy;
    },

    mergeObjects:  function(dest, source, options) {
        if (!options) {
            options = {};
        }
        if (!(dest && Utils.typeOf(dest) === "object" && source && Utils.typeOf(source) === "object")) {
            return dest;
        }
        var alreadyMerged = options.alreadyMerged || [];

        Object.keys(source).forEach(function (key) {
            if (Utils.checkOwnProperty(source, key)) {
                var val = source[key];
                if (Utils.typeOf(val) === "object" && dest[key]) {
                    if (alreadyMerged.indexOf(val) === -1) {
                        alreadyMerged.push(val);
                        Utils.mergeObjects(dest[key], val, {
                            alreadyMerged: alreadyMerged
                        });
                    }
                } else {
                    dest[key] = source[key];
                }
            }
        });
        return dest;
    },

    filterObject:  function(object, filters, options) {
        if (!options) {
            options = {};
        }
        if (Utils.typeOf(object) !== "object") {
            return;
        }
        if (Utils.typeOf(filters) !== "array") {
            return;
        }
        var alreadyFiltered = options.alreadyFiltered || [];
        Object.keys(object).forEach(function (key) {
            if (Utils.checkOwnProperty(object, key)) {
                return filters.forEach(function(filter) {
                    if (key.indexOf(filter) !== -1) {
                        object[key] = "[FILTERED]";
                    } else if (Utils.typeOf(object[key]) === "object" && alreadyFiltered.indexOf(object[key]) === -1) {
                        alreadyFiltered.push(object[key]);
                        Utils.filterObject(object[key], filters, {
                            alreadyFiltered: alreadyFiltered
                        });
                    }
                });
            }
        });
    }
};

module.exports = Utils;
<|endoftext|>