<commit_before>// ==========================================================================
// Project:  Ember Metal
// Copyright: ©2011 Strobe Inc. and contributors.
// License:   Licensed under MIT license (see license.js)
// ==========================================================================

require('ember-metal/core');
require('ember-metal/platform');
require('ember-metal/utils');
require('ember-metal/properties');

Ember.warn("Computed properties will soon be cacheable by default. To enable this in your app, set `ENV.CP_DEFAULT_CACHEABLE = true`.", Ember.CP_DEFAULT_CACHEABLE);

var get = Ember.get,
    getPath = Ember.getPath,
    meta = Ember.meta,
    guidFor = Ember.guidFor,
    USE_ACCESSORS = Ember.USE_ACCESSORS,
    a_slice = [].slice,
    o_create = Ember.create,
    o_defineProperty = Ember.platform.defineProperty;

// ..........................................................
// DEPENDENT KEYS
//

// data structure:
//  meta.deps = {
//   'depKey': {
//     'keyName': count,
//     __emberproto__: SRC_OBJ [to detect clones]
//     },
//   __emberproto__: SRC_OBJ
//  }

/**
  @private

  This function returns a map of unique dependencies for a
  given object and key.
*/
function uniqDeps(obj, depKey) {
  var m = meta(obj), deps = m.deps, ret;

  // If the current object has no dependencies...
  if (!deps) {
    // initialize the dependencies with a pointer back to
    // the current object
    deps = m.deps = { __emberproto__: obj };
  } else if (deps.__emberproto__ !== obj) {
    // otherwise if the dependencies are inherited from the
    // object's superclass, clone the deps
    deps = m.deps = o_create(deps);
    deps.__emberproto__ = obj;
  }

  ret = deps[depKey];

  if (!ret) {
    // if there are no dependencies yet for a the given key
    // create a new empty list of dependencies for the key
    ret = deps[depKey] = { __emberproto__: obj };
  } else if (ret.__emberproto__ !== obj) {
    // otherwise if the dependency list is inherited from
    // a superclass, clone the hash
    ret = deps[depKey] = o_create(ret);
    ret.__emberproto__ = obj;
  }

  return ret;
}

/**
  @private

  This method allows us to register that a particular
  property depends on another property.
*/
function addDependentKey(obj, keyName, depKey) {
  var deps = uniqDeps(obj, depKey);

  // Increment the number of times depKey depends on
  // keyName.
  deps[keyName] = (deps[keyName] || 0) + 1;

  // Watch the depKey
  Ember.watch(obj, depKey);
}

/**
  @private

  This method removes a dependency.
*/
function removeDependentKey(obj, keyName, depKey) {
  var deps = uniqDeps(obj, depKey);

  // Decrement the number of times depKey depends
  // on keyName.
  deps[keyName] = (deps[keyName] || 0) - 1;

  // Unwatch the depKey
  Ember.unwatch(obj, depKey);
}

/** @private */
function addDependentKeys(desc, obj, keyName) {
  // the descriptor has a list of dependent keys, so
  // add all of its dependent keys.
  var keys = desc._dependentKeys,
      len  = keys ? keys.length : 0;

  for(var idx=0; idx<len; idx++) {
    addDependentKey(obj, keyName, keys[idx]);
  }
}

// ..........................................................
// COMPUTED PROPERTY
//

/** @private */
function ComputedProperty(func, opts) {
  this.func = func;
  this._cacheable = (opts && opts.cacheable !== undefined) ? opts.cacheable : Ember.CP_DEFAULT_CACHEABLE;
  this._dependentKeys = opts && opts.dependentKeys;
}

/**
  @constructor
*/
Ember.ComputedProperty = ComputedProperty;
ComputedProperty.prototype = new Ember.Descriptor();

var CP_DESC = {
  configurable: true,
  enumerable:   true,
  get: function() { return undefined; }, // for when use_accessors is false.
  set: Ember.Descriptor.MUST_USE_SETTER  // for when use_accessors is false
};

/** @private */
function mkCpGetter(keyName, desc) {
  var cacheable = desc._cacheable,
      func     = desc.func;

  if (cacheable) {
    return function() {
      var ret, cache = meta(this).cache;
      if (keyName in cache) { return cache[keyName]; }
      ret = cache[keyName] = func.call(this, keyName);
      return ret;
    };
  } else {
    return function() {
      return func.call(this, keyName);
    };
  }
}

/** @private */
function mkCpSetter(keyName, desc) {
  var cacheable = desc._cacheable,
      func      = desc.func;

  return function(value) {
    var m = meta(this, cacheable),
        watched = m.source === this && m.watching[keyName] > 0,
        oldSuspended = desc._suspended,
        ret;

    desc._suspended = this;

    if (watched) { Ember.propertyWillChange(this, keyName); }
    if (cacheable) delete m.cache[keyName];
    ret = func.call(this, keyName, value);
    if (cacheable) { m.cache[keyName] = ret; }
    if (watched) { Ember.propertyDidChange(this, keyName); }
    desc._suspended = oldSuspended;
    return ret;
  };
}

/**
  @extends Ember.ComputedProperty
  @private
*/
var ComputedPropertyPrototype = ComputedProperty.prototype;

/**
  Call on a computed property to set it into cacheable mode.  When in this
  mode the computed property will automatically cache the return value of
  your function until one of the dependent keys changes.

      MyApp.president = Ember.Object.create({
        fullName: function() {
          return this.get('firstName') + ' ' + this.get('lastName');

          // After calculating the value of this function, Ember.js will
          // return that value without re-executing this function until
          // one of the dependent properties change.
        }.property('firstName', 'lastName').cacheable()
      });

  Properties are cacheable by default.

  @name Ember.ComputedProperty.cacheable
  @param {Boolean} aFlag optional set to false to disable caching
  @returns {Ember.ComputedProperty} receiver
*/
ComputedPropertyPrototype.cacheable = function(aFlag) {
  this._cacheable = aFlag !== false;
  return this;
};

/**
  Call on a computed property to set it into non-cached mode.  When in this
  mode the computed property will not automatically cache the return value.

      MyApp.outsideService = Ember.Object.create({
        value: function() {
          return OutsideService.getValue();
        }.property().volatile()
      });

  @name Ember.ComputedProperty.volatile
  @returns {Ember.ComputedProperty} receiver
*/
ComputedPropertyPrototype.volatile = function() {
  return this.cacheable(false);
};

/**
  Sets the dependent keys on this computed property.  Pass any number of
  arguments containing key paths that this computed property depends on.

      MyApp.president = Ember.Object.create({
        fullName: Ember.computed(function() {
          return this.get('firstName') + ' ' + this.get('lastName');

          // Tell Ember.js that this computed property depends on firstName
          // and lastName
        }).property('firstName', 'lastName')
      });

  @name Ember.ComputedProperty.property
  @param {String} path... zero or more property paths
  @returns {Ember.ComputedProperty} receiver
*/
ComputedPropertyPrototype.property = function() {
  this._dependentKeys = a_slice.call(arguments);
  return this;
};

/**
  In some cases, you may want to annotate computed properties with additional
  metadata about how they function or what values they operate on. For example,
  computed property functions may close over variables that are then no longer
  available for introspection.

  You can pass a hash of these values to a computed property like this:

      person: function() {
        var personId = this.get('personId');
        return App.Person.create({ id: personId });
      }.property().meta({ type: App.Person })

  The hash that you pass to the `meta()` function will be saved on the
  computed property descriptor under the `_meta` key. Ember runtime
  exposes a public API for retrieving these values from classes,
  via the `metaForProperty()` function.

  @name Ember.ComputedProperty.meta
  @param {Hash} metadata
  @returns {Ember.ComputedProperty} property descriptor instance
*/

ComputedPropertyPrototype.meta = function(meta) {
  this._meta = meta;
  return this;
};

/** @private - impl descriptor API */
ComputedPropertyPrototype.setup = function(obj, keyName, value) {
  CP_DESC.get = mkCpGetter(keyName, this);
  CP_DESC.set = mkCpSetter(keyName, this);
  o_defineProperty(obj, keyName, CP_DESC);
  CP_DESC.get = CP_DESC.set = null;
  addDependentKeys(this, obj, keyName);
};

/** @private - impl descriptor API */
ComputedPropertyPrototype.teardown = function(obj, keyName) {
  var keys = this._dependentKeys,
      len  = keys ? keys.length : 0;

  for(var idx=0; idx < len; idx++) {
    removeDependentKey(obj, keyName, keys[idx]);
  }

  if (this._cacheable) { delete meta(obj).cache[keyName]; }

  return null; // no value to restore
};

/** @private - impl descriptor API */
ComputedPropertyPrototype.didChange = function(obj, keyName) {
  if (this._cacheable && this._suspended !== obj) {
    delete meta(obj).cache[keyName];
  }
};

/** @private - impl descriptor API */
ComputedPropertyPrototype.get = function(obj, keyName) {
  var ret, cache;

  if (this._cacheable) {
    cache = meta(obj).cache;
    if (keyName in cache) { return cache[keyName]; }
    ret = cache[keyName] = this.func.call(obj, keyName);
  } else {
    ret = this.func.call(obj, keyName);
  }
  return ret;
};

/** @private - impl descriptor API */
ComputedPropertyPrototype.set = function(obj, keyName, value) {
  var cacheable = this._cacheable,
      m = meta(obj, cacheable),
      watched = m.source === obj && m.watching[keyName] > 0,
      oldSuspended = this._suspended,
      ret;

  this._suspended = obj;

  if (watched) { Ember.propertyWillChange(obj, keyName); }
  if (cacheable) delete m.cache[keyName];
  ret = this.func.call(obj, keyName, value);
  if (cacheable) { m.cache[keyName] = ret; }
  if (watched) { Ember.propertyDidChange(obj, keyName); }
  this._suspended = oldSuspended;
  return ret;
};

ComputedPropertyPrototype.val = function(obj, keyName) {
  return meta(obj, false).values[keyName];
};

if (!Ember.platform.hasPropertyAccessors) {
  ComputedPropertyPrototype.setup = function(obj, keyName, value) {
    obj[keyName] = undefined; // so it shows up in key iteration
    addDependentKeys(this, obj, keyName);
  };

} else if (!USE_ACCESSORS) {
  ComputedPropertyPrototype.setup = function(obj, keyName) {
    // throw exception if not using Ember.get() and Ember.set() when supported
    o_defineProperty(obj, keyName, CP_DESC);
    addDependentKeys(this, obj, keyName);
  };
}

/**
  This helper returns a new property descriptor that wraps the passed
  computed property function.  You can use this helper to define properties
  with mixins or via Ember.defineProperty().

  The function you pass will be used to both get and set property values.
  The function should accept two parameters, key and value.  If value is not
  undefined you should set the value first.  In either case return the
  current value of the property.

  @param {Function} func
    The computed property function.

  @returns {Ember.ComputedProperty} property descriptor instance
*/
Ember.computed = function(func) {
  var args;

  if (arguments.length > 1) {
    args = a_slice.call(arguments, 0, -1);
    func = a_slice.call(arguments, -1)[0];
  }

  var cp = new ComputedProperty(func);

  if (args) {
    cp.property.apply(cp, args);
  }

  return cp;
};

/**
  Returns the cached value for a property, if one exists.
  This can be useful for peeking at the value of a computed
  property that is generated lazily, without accidentally causing
  it to be created.

  @param {Object} obj the object whose property you want to check
  @param {String} key the name of the property whose cached value you want
                      to return

*/
Ember.cacheFor = function(obj, key) {
  var cache = meta(obj, false).cache;

  if (cache && key in cache) {
    return cache[key];
  }
};

Ember.computed.not = function(dependentKey) {
  return Ember.computed(dependentKey, function(key) {
    return !getPath(this, dependentKey);
  }).cacheable();
};

Ember.computed.empty = function(dependentKey) {
  return Ember.computed(dependentKey, function(key) {
    var val = getPath(this, dependentKey);
    return val === undefined || val === null || val === '' || (Ember.isArray(val) && get(val, 'length') === 0);
  }).cacheable();
};

Ember.computed.bool = function(dependentKey) {
  return Ember.computed(dependentKey, function(key) {
    return !!getPath(this, dependentKey);
  }).cacheable();
};
<commit_msg>Fix failing ObjectProxy spec in Chrome<commit_after>// ==========================================================================
// Project:  Ember Metal
// Copyright: ©2011 Strobe Inc. and contributors.
// License:   Licensed under MIT license (see license.js)
// ==========================================================================

require('ember-metal/core');
require('ember-metal/platform');
require('ember-metal/utils');
require('ember-metal/properties');

Ember.warn("Computed properties will soon be cacheable by default. To enable this in your app, set `ENV.CP_DEFAULT_CACHEABLE = true`.", Ember.CP_DEFAULT_CACHEABLE);

var get = Ember.get,
    getPath = Ember.getPath,
    meta = Ember.meta,
    guidFor = Ember.guidFor,
    USE_ACCESSORS = Ember.USE_ACCESSORS,
    a_slice = [].slice,
    o_create = Ember.create,
    o_defineProperty = Ember.platform.defineProperty;

// ..........................................................
// DEPENDENT KEYS
//

// data structure:
//  meta.deps = {
//   'depKey': {
//     'keyName': count,
//     __emberproto__: SRC_OBJ [to detect clones]
//     },
//   __emberproto__: SRC_OBJ
//  }

/**
  @private

  This function returns a map of unique dependencies for a
  given object and key.
*/
function uniqDeps(obj, depKey) {
  var m = meta(obj), deps = m.deps, ret;

  // If the current object has no dependencies...
  if (!deps) {
    // initialize the dependencies with a pointer back to
    // the current object
    deps = m.deps = { __emberproto__: obj };
  } else if (deps.__emberproto__ !== obj) {
    // otherwise if the dependencies are inherited from the
    // object's superclass, clone the deps
    deps = m.deps = o_create(deps);
    deps.__emberproto__ = obj;
  }

  ret = deps[depKey];

  if (!ret) {
    // if there are no dependencies yet for a the given key
    // create a new empty list of dependencies for the key
    ret = deps[depKey] = { __emberproto__: obj };
  } else if (ret.__emberproto__ !== obj) {
    // otherwise if the dependency list is inherited from
    // a superclass, clone the hash
    ret = deps[depKey] = o_create(ret);
    ret.__emberproto__ = obj;
  }

  return ret;
}

/**
  @private

  This method allows us to register that a particular
  property depends on another property.
*/
function addDependentKey(obj, keyName, depKey) {
  var deps = uniqDeps(obj, depKey);

  // Increment the number of times depKey depends on
  // keyName.
  deps[keyName] = (deps[keyName] || 0) + 1;

  // Watch the depKey
  Ember.watch(obj, depKey);
}

/**
  @private

  This method removes a dependency.
*/
function removeDependentKey(obj, keyName, depKey) {
  var deps = uniqDeps(obj, depKey);

  // Decrement the number of times depKey depends
  // on keyName.
  deps[keyName] = (deps[keyName] || 0) - 1;

  // Unwatch the depKey
  Ember.unwatch(obj, depKey);
}

/** @private */
function addDependentKeys(desc, obj, keyName) {
  // the descriptor has a list of dependent keys, so
  // add all of its dependent keys.
  var keys = desc._dependentKeys,
      len  = keys ? keys.length : 0;

  for(var idx=0; idx<len; idx++) {
    addDependentKey(obj, keyName, keys[idx]);
  }
}

// ..........................................................
// COMPUTED PROPERTY
//

/** @private */
function ComputedProperty(func, opts) {
  this.func = func;
  this._cacheable = (opts && opts.cacheable !== undefined) ? opts.cacheable : Ember.CP_DEFAULT_CACHEABLE;
  this._dependentKeys = opts && opts.dependentKeys;
}

/**
  @constructor
*/
Ember.ComputedProperty = ComputedProperty;
ComputedProperty.prototype = new Ember.Descriptor();

var CP_DESC = {
  configurable: true,
  enumerable:   true,
  writable:     true,
  get: function() { return undefined; }, // for when use_accessors is false.
  set: Ember.Descriptor.MUST_USE_SETTER  // for when use_accessors is false
};

/** @private */
function mkCpGetter(keyName, desc) {
  var cacheable = desc._cacheable,
      func     = desc.func;

  if (cacheable) {
    return function() {
      var ret, cache = meta(this).cache;
      if (keyName in cache) { return cache[keyName]; }
      ret = cache[keyName] = func.call(this, keyName);
      return ret;
    };
  } else {
    return function() {
      return func.call(this, keyName);
    };
  }
}

/** @private */
function mkCpSetter(keyName, desc) {
  var cacheable = desc._cacheable,
      func      = desc.func;

  return function(value) {
    var m = meta(this, cacheable),
        watched = m.source === this && m.watching[keyName] > 0,
        oldSuspended = desc._suspended,
        ret;

    desc._suspended = this;

    if (watched) { Ember.propertyWillChange(this, keyName); }
    if (cacheable) delete m.cache[keyName];
    ret = func.call(this, keyName, value);
    if (cacheable) { m.cache[keyName] = ret; }
    if (watched) { Ember.propertyDidChange(this, keyName); }
    desc._suspended = oldSuspended;
    return ret;
  };
}

/**
  @extends Ember.ComputedProperty
  @private
*/
var ComputedPropertyPrototype = ComputedProperty.prototype;

/**
  Call on a computed property to set it into cacheable mode.  When in this
  mode the computed property will automatically cache the return value of
  your function until one of the dependent keys changes.

      MyApp.president = Ember.Object.create({
        fullName: function() {
          return this.get('firstName') + ' ' + this.get('lastName');

          // After calculating the value of this function, Ember.js will
          // return that value without re-executing this function until
          // one of the dependent properties change.
        }.property('firstName', 'lastName').cacheable()
      });

  Properties are cacheable by default.

  @name Ember.ComputedProperty.cacheable
  @param {Boolean} aFlag optional set to false to disable caching
  @returns {Ember.ComputedProperty} receiver
*/
ComputedPropertyPrototype.cacheable = function(aFlag) {
  this._cacheable = aFlag !== false;
  return this;
};

/**
  Call on a computed property to set it into non-cached mode.  When in this
  mode the computed property will not automatically cache the return value.

      MyApp.outsideService = Ember.Object.create({
        value: function() {
          return OutsideService.getValue();
        }.property().volatile()
      });

  @name Ember.ComputedProperty.volatile
  @returns {Ember.ComputedProperty} receiver
*/
ComputedPropertyPrototype.volatile = function() {
  return this.cacheable(false);
};

/**
  Sets the dependent keys on this computed property.  Pass any number of
  arguments containing key paths that this computed property depends on.

      MyApp.president = Ember.Object.create({
        fullName: Ember.computed(function() {
          return this.get('firstName') + ' ' + this.get('lastName');

          // Tell Ember.js that this computed property depends on firstName
          // and lastName
        }).property('firstName', 'lastName')
      });

  @name Ember.ComputedProperty.property
  @param {String} path... zero or more property paths
  @returns {Ember.ComputedProperty} receiver
*/
ComputedPropertyPrototype.property = function() {
  this._dependentKeys = a_slice.call(arguments);
  return this;
};

/**
  In some cases, you may want to annotate computed properties with additional
  metadata about how they function or what values they operate on. For example,
  computed property functions may close over variables that are then no longer
  available for introspection.

  You can pass a hash of these values to a computed property like this:

      person: function() {
        var personId = this.get('personId');
        return App.Person.create({ id: personId });
      }.property().meta({ type: App.Person })

  The hash that you pass to the `meta()` function will be saved on the
  computed property descriptor under the `_meta` key. Ember runtime
  exposes a public API for retrieving these values from classes,
  via the `metaForProperty()` function.

  @name Ember.ComputedProperty.meta
  @param {Hash} metadata
  @returns {Ember.ComputedProperty} property descriptor instance
*/

ComputedPropertyPrototype.meta = function(meta) {
  this._meta = meta;
  return this;
};

/** @private - impl descriptor API */
ComputedPropertyPrototype.setup = function(obj, keyName, value) {
  CP_DESC.get = mkCpGetter(keyName, this);
  CP_DESC.set = mkCpSetter(keyName, this);
  o_defineProperty(obj, keyName, CP_DESC);
  CP_DESC.get = CP_DESC.set = null;
  addDependentKeys(this, obj, keyName);
};

/** @private - impl descriptor API */
ComputedPropertyPrototype.teardown = function(obj, keyName) {
  var keys = this._dependentKeys,
      len  = keys ? keys.length : 0;

  for(var idx=0; idx < len; idx++) {
    removeDependentKey(obj, keyName, keys[idx]);
  }

  if (this._cacheable) { delete meta(obj).cache[keyName]; }

  return null; // no value to restore
};

/** @private - impl descriptor API */
ComputedPropertyPrototype.didChange = function(obj, keyName) {
  if (this._cacheable && this._suspended !== obj) {
    delete meta(obj).cache[keyName];
  }
};

/** @private - impl descriptor API */
ComputedPropertyPrototype.get = function(obj, keyName) {
  var ret, cache;

  if (this._cacheable) {
    cache = meta(obj).cache;
    if (keyName in cache) { return cache[keyName]; }
    ret = cache[keyName] = this.func.call(obj, keyName);
  } else {
    ret = this.func.call(obj, keyName);
  }
  return ret;
};

/** @private - impl descriptor API */
ComputedPropertyPrototype.set = function(obj, keyName, value) {
  var cacheable = this._cacheable,
      m = meta(obj, cacheable),
      watched = m.source === obj && m.watching[keyName] > 0,
      oldSuspended = this._suspended,
      ret;

  this._suspended = obj;

  if (watched) { Ember.propertyWillChange(obj, keyName); }
  if (cacheable) delete m.cache[keyName];
  ret = this.func.call(obj, keyName, value);
  if (cacheable) { m.cache[keyName] = ret; }
  if (watched) { Ember.propertyDidChange(obj, keyName); }
  this._suspended = oldSuspended;
  return ret;
};

ComputedPropertyPrototype.val = function(obj, keyName) {
  return meta(obj, false).values[keyName];
};

if (!Ember.platform.hasPropertyAccessors) {
  ComputedPropertyPrototype.setup = function(obj, keyName, value) {
    obj[keyName] = undefined; // so it shows up in key iteration
    addDependentKeys(this, obj, keyName);
  };

} else if (!USE_ACCESSORS) {
  ComputedPropertyPrototype.setup = function(obj, keyName) {
    // throw exception if not using Ember.get() and Ember.set() when supported
    o_defineProperty(obj, keyName, CP_DESC);
    addDependentKeys(this, obj, keyName);
  };
}

/**
  This helper returns a new property descriptor that wraps the passed
  computed property function.  You can use this helper to define properties
  with mixins or via Ember.defineProperty().

  The function you pass will be used to both get and set property values.
  The function should accept two parameters, key and value.  If value is not
  undefined you should set the value first.  In either case return the
  current value of the property.

  @param {Function} func
    The computed property function.

  @returns {Ember.ComputedProperty} property descriptor instance
*/
Ember.computed = function(func) {
  var args;

  if (arguments.length > 1) {
    args = a_slice.call(arguments, 0, -1);
    func = a_slice.call(arguments, -1)[0];
  }

  var cp = new ComputedProperty(func);

  if (args) {
    cp.property.apply(cp, args);
  }

  return cp;
};

/**
  Returns the cached value for a property, if one exists.
  This can be useful for peeking at the value of a computed
  property that is generated lazily, without accidentally causing
  it to be created.

  @param {Object} obj the object whose property you want to check
  @param {String} key the name of the property whose cached value you want
                      to return

*/
Ember.cacheFor = function(obj, key) {
  var cache = meta(obj, false).cache;

  if (cache && key in cache) {
    return cache[key];
  }
};

Ember.computed.not = function(dependentKey) {
  return Ember.computed(dependentKey, function(key) {
    return !getPath(this, dependentKey);
  }).cacheable();
};

Ember.computed.empty = function(dependentKey) {
  return Ember.computed(dependentKey, function(key) {
    var val = getPath(this, dependentKey);
    return val === undefined || val === null || val === '' || (Ember.isArray(val) && get(val, 'length') === 0);
  }).cacheable();
};

Ember.computed.bool = function(dependentKey) {
  return Ember.computed(dependentKey, function(key) {
    return !!getPath(this, dependentKey);
  }).cacheable();
};
<|endoftext|>


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

var Agent = require('superagent').agent;
var methods = require('methods');
var http = require('http');
var Test = require('./test');

/**
 * Expose `Agent`.
 */

module.exports = TestAgent;

/**
 * Initialize a new `TestAgent`.
 *
 * @param {Function|Server} app
 * @param {Object} options
 * @api public
 */

function TestAgent(app, options) {
  if (!(this instanceof TestAgent)) return new TestAgent(app, options);
  if (typeof app === 'function') app = http.createServer(app);  // eslint-disable-line no-param-reassign
  if (options) this._ca = options.ca;
  Agent.call(this);
  this.app = app;
}

/**
 * Inherits from `Agent.prototype`.
 */

TestAgent.prototype.__proto__ = Agent.prototype;

// override HTTP verb methods
methods.forEach(function(method) {
  TestAgent.prototype[method] = function(url, fn) {   // eslint-disable-line no-unused-vars
    var req = new Test(this.app, method.toUpperCase(), url);
    req.ca(this._ca);

    req.on('response', this._saveCookies.bind(this));
    req.on('redirect', this._saveCookies.bind(this));
    req.on('redirect', this._attachCookies.bind(this, req));
    this._attachCookies(req);

    return req;
  };
});

TestAgent.prototype.del = TestAgent.prototype.delete;
<commit_msg>Allow TestAgent pass a cert and key to request (#373)<commit_after>
/**
 * Module dependencies.
 */

var Agent = require('superagent').agent;
var methods = require('methods');
var http = require('http');
var Test = require('./test');

/**
 * Expose `Agent`.
 */

module.exports = TestAgent;

/**
 * Initialize a new `TestAgent`.
 *
 * @param {Function|Server} app
 * @param {Object} options
 * @api public
 */

function TestAgent(app, options) {
  if (!(this instanceof TestAgent)) return new TestAgent(app, options);
  if (typeof app === 'function') app = http.createServer(app);  // eslint-disable-line no-param-reassign
  if (options) {
    this._ca = options.ca;
    this._key = options.key;
    this._cert = options.cert;
  }
  Agent.call(this);
  this.app = app;
}

/**
 * Inherits from `Agent.prototype`.
 */

TestAgent.prototype.__proto__ = Agent.prototype;

// override HTTP verb methods
methods.forEach(function(method) {
  TestAgent.prototype[method] = function(url, fn) {   // eslint-disable-line no-unused-vars
    var req = new Test(this.app, method.toUpperCase(), url);
    req.ca(this._ca);
    req.cert(this._cert);
    req.key(this._key);

    req.on('response', this._saveCookies.bind(this));
    req.on('redirect', this._saveCookies.bind(this));
    req.on('redirect', this._attachCookies.bind(this, req));
    this._attachCookies(req);

    return req;
  };
});

TestAgent.prototype.del = TestAgent.prototype.delete;
<|endoftext|>


<commit_before>var fs = require('fs');
const nodemailer = require('nodemailer');

var ready = false;
var transporter;
var mailOptions;

fs.readFile('credpersonal.json', function(err, data){
    if (err) throw err;

    details = JSON.parse(data);
    transporter = nodemailer.createTransport({
        host: details.server,
        port: details.port,
        secure: details.port == 465, // secure:true for port 465, secure:false for port 587
        requireTLS: details.port == 587, //true for port 587
        auth: {
            user: details.from,
            pass: details.pass
        }
    });

    mailOptions = {
        from: '"RPi Door Sensor" <'+details.server+'>', // sender address
        to: details.to, // list of receivers
        subject: 'Door Status', // Subject line
        text: 'Hello world', // plain text body
        html: 'Hello world' // html body
    };
    ready = true;
});

module.exports = {
    sendMail: function(text){
        if (ready){
            mailOptions.text = "\n"+text;
            mailOptions.html = "\n"+text+"";
            // send mail with defined transport object
            transporter.sendMail(mailOptions, function(error, info) {
                if (error) {
                    return console.log(error);
                }
                console.log(text);
                // console.log('Message %s sent: %s', info.messageId, info.response);
            });
        }
        else{
            console.log("Not ready");
        }
    }
}<commit_msg>Bug fix<commit_after>var fs = require('fs');
const nodemailer = require('nodemailer');

var ready = false;
var transporter;
var mailOptions;

fs.readFile('credpersonal.json', function(err, data){
    if (err) throw err;

    details = JSON.parse(data);
    transporter = nodemailer.createTransport({
        host: details.server,
        port: details.port,
        secure: details.port == 465, // secure:true for port 465, secure:false for port 587
        requireTLS: details.port == 587, //true for port 587
        auth: {
            user: details.from,
            pass: details.pass
        }
    });

    mailOptions = {
        from: '"RPi Door Sensor" <'+details.from+'>', // sender address
        to: details.to, // list of receivers
        subject: 'Door Status', // Subject line
        text: 'Hello world', // plain text body
        html: 'Hello world' // html body
    };
    ready = true;
});

module.exports = {
    sendMail: function(text){
        if (ready){
            mailOptions.text = "\n"+text;
            mailOptions.html = "\n"+text+"";
            // send mail with defined transport object
            transporter.sendMail(mailOptions, function(error, info) {
                if (error) {
                    return console.log(error);
                }
                console.log(text);
                // console.log('Message %s sent: %s', info.messageId, info.response);
            });
        }
        else{
            console.log("Not ready");
        }
    }
}<|endoftext|>


<commit_before>// Module dependencies.
var debug = require('debug')('ruche:download');
var http = require('http');
var https = require('https');
var path = require('path');
var fs = require('fs');
var progress = require('progress');
var colors = require('colors');
var humanize = require('humanize');
var error = require('./error');
var emitter = require('./emitter');

/**
 * Get a file from HTTP request and save it to the local file system.
 * @param {String}   url      The HTTP URL of the file you want
 * @param {String}   dest     Destination file on the file system
 * @param {Object}   options  An object of options: package, port, etc.
 * @fires RucheEmitter#install-package-response
 * @fires RucheEmitter#install-package-chunk
 * @fires RucheEmitter#install-package-dl
 * @fires RucheEmitter#install-package-file
 */
var download = function(url, dest, options) {

  // Open a file stream
  var file = fs.createWriteStream(dest);

  // Make an HTTP request to get the file
  var req = http.get(url, function(res) {
    debug('Start of HTTP response: ' + options.package)
    res.pipe(file);
    file.on('finish', function() {
      file.close(function (data) {
        emitter.emit('install-' + options.package + '-file', data);
        debug('Written to file sytsem: ' + options.package);
      });
    });
  });

  // Capture the HTTP response
  req.on('response', function (res) {
    var contentLength = parseInt(res.headers['content-length'], 10)
    emitter.emit('install-' + options.package + '-response', contentLength);

    res.on('data', function (chunk) {
      emitter.emit('install-' + options.package + '-chunk', chunk);
    });

    res.on('end', function () {
      emitter.emit('install-' + options.package + '-dl');
      debug('End of HTTP response: ' + options.package);
    });
  })

  req.on('error', function(err) {
    fs.unlink(dest);
    error.handle(err);
  });
};

module.exports = download;<commit_msg>Remove useless dependencies<commit_after>// Module dependencies.
var debug = require('debug')('ruche:download');
var http = require('http');
var fs = require('fs');
var error = require('./error');
var emitter = require('./emitter');

/**
 * Get a file from HTTP request and save it to the local file system.
 * @param {String}   url      The HTTP URL of the file you want
 * @param {String}   dest     Destination file on the file system
 * @param {Object}   options  An object of options: package, port, etc.
 * @fires RucheEmitter#install-package-response
 * @fires RucheEmitter#install-package-chunk
 * @fires RucheEmitter#install-package-dl
 * @fires RucheEmitter#install-package-file
 */
var download = function(url, dest, options) {

  // Open a file stream
  var file = fs.createWriteStream(dest);

  // Make an HTTP request to get the file
  var req = http.get(url, function(res) {
    debug('Start of HTTP response: ' + options.package)
    res.pipe(file);
    file.on('finish', function() {
      file.close(function (data) {
        emitter.emit('install-' + options.package + '-file', data);
        debug('Written to file sytsem: ' + options.package);
      });
    });
  });

  // Capture the HTTP response
  req.on('response', function (res) {
    var contentLength = parseInt(res.headers['content-length'], 10)
    emitter.emit('install-' + options.package + '-response', contentLength);

    // When receiving data (chunk by chunk)
    res.on('data', function (chunk) {
      emitter.emit('install-' + options.package + '-chunk', chunk);
    });

    // When response ends
    res.on('end', function () {
      emitter.emit('install-' + options.package + '-dl');
      debug('End of HTTP response: ' + options.package);
    });
  })

  // If there is an error handle it
  req.on('error', function(err) {
    fs.unlink(dest);
    error.handle(err);
  });
};

module.exports = download;<|endoftext|>


<commit_before>require('ember-metal/vendor/backburner');

var Backburner = requireModule('backburner').Backburner,
    backburner = new Backburner(['sync', 'actions', 'destroy'], {
      sync: {
        before: Ember.beginPropertyChanges,
        after: Ember.endPropertyChanges
      }
    }),
    slice = [].slice;

// ..........................................................
// Ember.run - this is ideally the only public API the dev sees
//

/**
  Runs the passed target and method inside of a RunLoop, ensuring any
  deferred actions including bindings and views updates are flushed at the
  end.

  Normally you should not need to invoke this method yourself. However if
  you are implementing raw event handlers when interfacing with other
  libraries or plugins, you should probably wrap all of your code inside this
  call.

  ```javascript
  Ember.run(function(){
    // code to be execute within a RunLoop
  });
  ```

  @class run
  @namespace Ember
  @static
  @constructor
  @param {Object} [target] target of method to call
  @param {Function|String} method Method to invoke.
    May be a function or a string. If you pass a string
    then it will be looked up on the passed target.
  @param {Object} [args*] Any additional arguments you wish to pass to the method.
  @return {Object} return value from invoking the passed function.
*/
Ember.run = function(target, method) {
  var ret;
  try {
    ret = backburner.run.apply(backburner, arguments);
  } catch (e) {
    if (Ember.onerror) {
      Ember.onerror(e);
    } else {
      throw e;
    }
  }
  return ret;
};

Ember.run.backburner = backburner;

var run = Ember.run;

/**
  Begins a new RunLoop. Any deferred actions invoked after the begin will
  be buffered until you invoke a matching call to `Ember.run.end()`. This is
  a lower-level way to use a RunLoop instead of using `Ember.run()`.

  ```javascript
  Ember.run.begin();
  // code to be execute within a RunLoop
  Ember.run.end();
  ```

  @method begin
  @return {void}
*/
Ember.run.begin = function() {
  backburner.begin();
};

/**
  Ends a RunLoop. This must be called sometime after you call
  `Ember.run.begin()` to flush any deferred actions. This is a lower-level way
  to use a RunLoop instead of using `Ember.run()`.

  ```javascript
  Ember.run.begin();
  // code to be execute within a RunLoop
  Ember.run.end();
  ```

  @method end
  @return {void}
*/
Ember.run.end = function() {
  backburner.end();
};

/**
  Array of named queues. This array determines the order in which queues
  are flushed at the end of the RunLoop. You can define your own queues by
  simply adding the queue name to this array. Normally you should not need
  to inspect or modify this property.

  @property queues
  @type Array
  @default ['sync', 'actions', 'destroy']
*/

/**
  Adds the passed target/method and any optional arguments to the named
  queue to be executed at the end of the RunLoop. If you have not already
  started a RunLoop when calling this method one will be started for you
  automatically.

  At the end of a RunLoop, any methods scheduled in this way will be invoked.
  Methods will be invoked in an order matching the named queues defined in
  the `Ember.run.queues` property.

  ```javascript
  Ember.run.schedule('sync', this, function(){
    // this will be executed in the first RunLoop queue, when bindings are synced
    console.log("scheduled on sync queue");
  });

  Ember.run.schedule('actions', this, function(){
    // this will be executed in the 'actions' queue, after bindings have synced.
    console.log("scheduled on actions queue");
  });

  // Note the functions will be run in order based on the run queues order. Output would be:
  //   scheduled on sync queue
  //   scheduled on actions queue
  ```

  @method schedule
  @param {String} queue The name of the queue to schedule against.
    Default queues are 'sync' and 'actions'
  @param {Object} [target] target object to use as the context when invoking a method.
  @param {String|Function} method The method to invoke. If you pass a string it
    will be resolved on the target object at the time the scheduled item is
    invoked allowing you to change the target function.
  @param {Object} [arguments*] Optional arguments to be passed to the queued method.
  @return {void}
*/
Ember.run.schedule = function(queue, target, method) {
  backburner.schedule.apply(backburner, arguments);
};

// Used by global test teardown
Ember.run.hasScheduledTimers = function() {
  return backburner.hasTimers();
};

// Used by global test teardown
Ember.run.cancelTimers = function () {
  backburner.cancelTimers();
};

/**
  Immediately flushes any events scheduled in the 'sync' queue. Bindings
  use this queue so this method is a useful way to immediately force all
  bindings in the application to sync.

  You should call this method anytime you need any changed state to propagate
  throughout the app immediately without repainting the UI (which happens
  in the later 'render' queue added by the `ember-views` package).

  ```javascript
  Ember.run.sync();
  ```

  @method sync
  @return {void}
*/
Ember.run.sync = function() {
  backburner.currentInstance.queues.sync.flush();
};

/**
  Invokes the passed target/method and optional arguments after a specified
  period if time. The last parameter of this method must always be a number
  of milliseconds.

  You should use this method whenever you need to run some action after a
  period of time instead of using `setTimeout()`. This method will ensure that
  items that expire during the same script execution cycle all execute
  together, which is often more efficient than using a real setTimeout.

  ```javascript
  Ember.run.later(myContext, function(){
    // code here will execute within a RunLoop in about 500ms with this == myContext
  }, 500);
  ```

  @method later
  @param {Object} [target] target of method to invoke
  @param {Function|String} method The method to invoke.
    If you pass a string it will be resolved on the
    target at the time the method is invoked.
  @param {Object} [args*] Optional arguments to pass to the timeout.
  @param {Number} wait Number of milliseconds to wait.
  @return {String} a string you can use to cancel the timer in
    {{#crossLink "Ember/run.cancel"}}{{/crossLink}} later.
*/
Ember.run.later = function(target, method) {
  return backburner.later.apply(backburner, arguments);
};

/**
  Schedule a function to run one time during the current RunLoop. This is equivalent
  to calling `scheduleOnce` with the "actions" queue.

  @method once
  @param {Object} [target] The target of the method to invoke.
  @param {Function|String} method The method to invoke.
    If you pass a string it will be resolved on the
    target at the time the method is invoked.
  @param {Object} [args*] Optional arguments to pass to the timeout.
  @return {Object} timer
*/
Ember.run.once = function(target, method) {
  var args = slice.call(arguments);
  args.unshift('actions');
  return backburner.scheduleOnce.apply(backburner, args);
};

/**
  Schedules a function to run one time in a given queue of the current RunLoop.
  Calling this method with the same queue/target/method combination will have
  no effect (past the initial call).

  Note that although you can pass optional arguments these will not be
  considered when looking for duplicates. New arguments will replace previous
  calls.

  ```javascript
  Ember.run(function(){
    var sayHi = function() { console.log('hi'); }
    Ember.run.scheduleOnce('afterRender', myContext, sayHi);
    Ember.run.scheduleOnce('afterRender', myContext, sayHi);
    // doFoo will only be executed once, in the afterRender queue of the RunLoop
  });
  ```

  Also note that passing an anonymous function to `Ember.run.scheduleOnce` will
  not prevent additional calls with an identical anonymous function from
  scheduling the items multiple times, e.g.:

  ```javascript
  function scheduleIt() {
    Ember.run.scheduleOnce('actions', myContext, function() { console.log("Closure"); });
  }
  scheduleIt();
  scheduleIt();
  // "Closure" will print twice, even though we're using `Ember.run.scheduleOnce`,
  // because the function we pass to it is anonymous and won't match the
  // previously scheduled operation.
  ```

  Available queues, and their order, can be found at `Ember.run.queues`

  @method scheduleOnce
  @param {String} [queue] The name of the queue to schedule against. Default queues are 'sync' and 'actions'.
  @param {Object} [target] The target of the method to invoke.
  @param {Function|String} method The method to invoke.
    If you pass a string it will be resolved on the
    target at the time the method is invoked.
  @param {Object} [args*] Optional arguments to pass to the timeout.
  @return {Object} timer
*/
Ember.run.scheduleOnce = function(queue, target, method) {
  return backburner.scheduleOnce.apply(backburner, arguments);
};

/**
  Schedules an item to run from within a separate run loop, after
  control has been returned to the system. This is equivalent to calling
  `Ember.run.later` with a wait time of 1ms.

  ```javascript
  Ember.run.next(myContext, function(){
    // code to be executed in the next run loop, which will be scheduled after the current one
  });
  ```

  Multiple operations scheduled with `Ember.run.next` will coalesce
  into the same later run loop, along with any other operations
  scheduled by `Ember.run.later` that expire right around the same
  time that `Ember.run.next` operations will fire.

  Note that there are often alternatives to using `Ember.run.next`.
  For instance, if you'd like to schedule an operation to happen
  after all DOM element operations have completed within the current
  run loop, you can make use of the `afterRender` run loop queue (added
  by the `ember-views` package, along with the preceding `render` queue
  where all the DOM element operations happen). Example:

  ```javascript
  App.MyCollectionView = Ember.CollectionView.extend({
    didInsertElement: function() {
      Ember.run.scheduleOnce('afterRender', this, 'processChildElements');
    },
    processChildElements: function() {
      // ... do something with collectionView's child view
      // elements after they've finished rendering, which
      // can't be done within the CollectionView's
      // `didInsertElement` hook because that gets run
      // before the child elements have been added to the DOM.
    }
  });
  ```

  One benefit of the above approach compared to using `Ember.run.next` is
  that you will be able to perform DOM/CSS operations before unprocessed
  elements are rendered to the screen, which may prevent flickering or
  other artifacts caused by delaying processing until after rendering.

  The other major benefit to the above approach is that `Ember.run.next`
  introduces an element of non-determinism, which can make things much
  harder to test, due to its reliance on `setTimeout`; it's much harder
  to guarantee the order of scheduled operations when they are scheduled
  outside of the current run loop, i.e. with `Ember.run.next`.

  @method next
  @param {Object} [target] target of method to invoke
  @param {Function|String} method The method to invoke.
    If you pass a string it will be resolved on the
    target at the time the method is invoked.
  @param {Object} [args*] Optional arguments to pass to the timeout.
  @return {Object} timer
*/
Ember.run.next = function() {
  var args = slice.call(arguments);
  args.push(1);
  return backburner.later.apply(backburner, args);
};

/**
  Cancels a scheduled item. Must be a value returned by `Ember.run.later()`,
  `Ember.run.once()`, or `Ember.run.next()`.

  ```javascript
  var runNext = Ember.run.next(myContext, function(){
    // will not be executed
  });
  Ember.run.cancel(runNext);

  var runLater = Ember.run.later(myContext, function(){
    // will not be executed
  }, 500);
  Ember.run.cancel(runLater);

  var runOnce = Ember.run.once(myContext, function(){
    // will not be executed
  });
  Ember.run.cancel(runOnce);
  ```

  @method cancel
  @param {Object} timer Timer object to cancel
  @return {void}
*/
Ember.run.cancel = function(timer) {
  return backburner.cancel(timer);
};
<commit_msg>Set actions as the default run loop queue<commit_after>require('ember-metal/vendor/backburner');

var Backburner = requireModule('backburner').Backburner,
    backburner = new Backburner(['sync', 'actions', 'destroy'], {
      sync: {
        before: Ember.beginPropertyChanges,
        after: Ember.endPropertyChanges
      },
      defaultQueue: 'actions'
    }),
    slice = [].slice;

// ..........................................................
// Ember.run - this is ideally the only public API the dev sees
//

/**
  Runs the passed target and method inside of a RunLoop, ensuring any
  deferred actions including bindings and views updates are flushed at the
  end.

  Normally you should not need to invoke this method yourself. However if
  you are implementing raw event handlers when interfacing with other
  libraries or plugins, you should probably wrap all of your code inside this
  call.

  ```javascript
  Ember.run(function(){
    // code to be execute within a RunLoop
  });
  ```

  @class run
  @namespace Ember
  @static
  @constructor
  @param {Object} [target] target of method to call
  @param {Function|String} method Method to invoke.
    May be a function or a string. If you pass a string
    then it will be looked up on the passed target.
  @param {Object} [args*] Any additional arguments you wish to pass to the method.
  @return {Object} return value from invoking the passed function.
*/
Ember.run = function(target, method) {
  var ret;
  try {
    ret = backburner.run.apply(backburner, arguments);
  } catch (e) {
    if (Ember.onerror) {
      Ember.onerror(e);
    } else {
      throw e;
    }
  }
  return ret;
};

Ember.run.backburner = backburner;

var run = Ember.run;

/**
  Begins a new RunLoop. Any deferred actions invoked after the begin will
  be buffered until you invoke a matching call to `Ember.run.end()`. This is
  a lower-level way to use a RunLoop instead of using `Ember.run()`.

  ```javascript
  Ember.run.begin();
  // code to be execute within a RunLoop
  Ember.run.end();
  ```

  @method begin
  @return {void}
*/
Ember.run.begin = function() {
  backburner.begin();
};

/**
  Ends a RunLoop. This must be called sometime after you call
  `Ember.run.begin()` to flush any deferred actions. This is a lower-level way
  to use a RunLoop instead of using `Ember.run()`.

  ```javascript
  Ember.run.begin();
  // code to be execute within a RunLoop
  Ember.run.end();
  ```

  @method end
  @return {void}
*/
Ember.run.end = function() {
  backburner.end();
};

/**
  Array of named queues. This array determines the order in which queues
  are flushed at the end of the RunLoop. You can define your own queues by
  simply adding the queue name to this array. Normally you should not need
  to inspect or modify this property.

  @property queues
  @type Array
  @default ['sync', 'actions', 'destroy']
*/

/**
  Adds the passed target/method and any optional arguments to the named
  queue to be executed at the end of the RunLoop. If you have not already
  started a RunLoop when calling this method one will be started for you
  automatically.

  At the end of a RunLoop, any methods scheduled in this way will be invoked.
  Methods will be invoked in an order matching the named queues defined in
  the `Ember.run.queues` property.

  ```javascript
  Ember.run.schedule('sync', this, function(){
    // this will be executed in the first RunLoop queue, when bindings are synced
    console.log("scheduled on sync queue");
  });

  Ember.run.schedule('actions', this, function(){
    // this will be executed in the 'actions' queue, after bindings have synced.
    console.log("scheduled on actions queue");
  });

  // Note the functions will be run in order based on the run queues order. Output would be:
  //   scheduled on sync queue
  //   scheduled on actions queue
  ```

  @method schedule
  @param {String} queue The name of the queue to schedule against.
    Default queues are 'sync' and 'actions'
  @param {Object} [target] target object to use as the context when invoking a method.
  @param {String|Function} method The method to invoke. If you pass a string it
    will be resolved on the target object at the time the scheduled item is
    invoked allowing you to change the target function.
  @param {Object} [arguments*] Optional arguments to be passed to the queued method.
  @return {void}
*/
Ember.run.schedule = function(queue, target, method) {
  backburner.schedule.apply(backburner, arguments);
};

// Used by global test teardown
Ember.run.hasScheduledTimers = function() {
  return backburner.hasTimers();
};

// Used by global test teardown
Ember.run.cancelTimers = function () {
  backburner.cancelTimers();
};

/**
  Immediately flushes any events scheduled in the 'sync' queue. Bindings
  use this queue so this method is a useful way to immediately force all
  bindings in the application to sync.

  You should call this method anytime you need any changed state to propagate
  throughout the app immediately without repainting the UI (which happens
  in the later 'render' queue added by the `ember-views` package).

  ```javascript
  Ember.run.sync();
  ```

  @method sync
  @return {void}
*/
Ember.run.sync = function() {
  backburner.currentInstance.queues.sync.flush();
};

/**
  Invokes the passed target/method and optional arguments after a specified
  period if time. The last parameter of this method must always be a number
  of milliseconds.

  You should use this method whenever you need to run some action after a
  period of time instead of using `setTimeout()`. This method will ensure that
  items that expire during the same script execution cycle all execute
  together, which is often more efficient than using a real setTimeout.

  ```javascript
  Ember.run.later(myContext, function(){
    // code here will execute within a RunLoop in about 500ms with this == myContext
  }, 500);
  ```

  @method later
  @param {Object} [target] target of method to invoke
  @param {Function|String} method The method to invoke.
    If you pass a string it will be resolved on the
    target at the time the method is invoked.
  @param {Object} [args*] Optional arguments to pass to the timeout.
  @param {Number} wait Number of milliseconds to wait.
  @return {String} a string you can use to cancel the timer in
    {{#crossLink "Ember/run.cancel"}}{{/crossLink}} later.
*/
Ember.run.later = function(target, method) {
  return backburner.later.apply(backburner, arguments);
};

/**
  Schedule a function to run one time during the current RunLoop. This is equivalent
  to calling `scheduleOnce` with the "actions" queue.

  @method once
  @param {Object} [target] The target of the method to invoke.
  @param {Function|String} method The method to invoke.
    If you pass a string it will be resolved on the
    target at the time the method is invoked.
  @param {Object} [args*] Optional arguments to pass to the timeout.
  @return {Object} timer
*/
Ember.run.once = function(target, method) {
  var args = slice.call(arguments);
  args.unshift('actions');
  return backburner.scheduleOnce.apply(backburner, args);
};

/**
  Schedules a function to run one time in a given queue of the current RunLoop.
  Calling this method with the same queue/target/method combination will have
  no effect (past the initial call).

  Note that although you can pass optional arguments these will not be
  considered when looking for duplicates. New arguments will replace previous
  calls.

  ```javascript
  Ember.run(function(){
    var sayHi = function() { console.log('hi'); }
    Ember.run.scheduleOnce('afterRender', myContext, sayHi);
    Ember.run.scheduleOnce('afterRender', myContext, sayHi);
    // doFoo will only be executed once, in the afterRender queue of the RunLoop
  });
  ```

  Also note that passing an anonymous function to `Ember.run.scheduleOnce` will
  not prevent additional calls with an identical anonymous function from
  scheduling the items multiple times, e.g.:

  ```javascript
  function scheduleIt() {
    Ember.run.scheduleOnce('actions', myContext, function() { console.log("Closure"); });
  }
  scheduleIt();
  scheduleIt();
  // "Closure" will print twice, even though we're using `Ember.run.scheduleOnce`,
  // because the function we pass to it is anonymous and won't match the
  // previously scheduled operation.
  ```

  Available queues, and their order, can be found at `Ember.run.queues`

  @method scheduleOnce
  @param {String} [queue] The name of the queue to schedule against. Default queues are 'sync' and 'actions'.
  @param {Object} [target] The target of the method to invoke.
  @param {Function|String} method The method to invoke.
    If you pass a string it will be resolved on the
    target at the time the method is invoked.
  @param {Object} [args*] Optional arguments to pass to the timeout.
  @return {Object} timer
*/
Ember.run.scheduleOnce = function(queue, target, method) {
  return backburner.scheduleOnce.apply(backburner, arguments);
};

/**
  Schedules an item to run from within a separate run loop, after
  control has been returned to the system. This is equivalent to calling
  `Ember.run.later` with a wait time of 1ms.

  ```javascript
  Ember.run.next(myContext, function(){
    // code to be executed in the next run loop, which will be scheduled after the current one
  });
  ```

  Multiple operations scheduled with `Ember.run.next` will coalesce
  into the same later run loop, along with any other operations
  scheduled by `Ember.run.later` that expire right around the same
  time that `Ember.run.next` operations will fire.

  Note that there are often alternatives to using `Ember.run.next`.
  For instance, if you'd like to schedule an operation to happen
  after all DOM element operations have completed within the current
  run loop, you can make use of the `afterRender` run loop queue (added
  by the `ember-views` package, along with the preceding `render` queue
  where all the DOM element operations happen). Example:

  ```javascript
  App.MyCollectionView = Ember.CollectionView.extend({
    didInsertElement: function() {
      Ember.run.scheduleOnce('afterRender', this, 'processChildElements');
    },
    processChildElements: function() {
      // ... do something with collectionView's child view
      // elements after they've finished rendering, which
      // can't be done within the CollectionView's
      // `didInsertElement` hook because that gets run
      // before the child elements have been added to the DOM.
    }
  });
  ```

  One benefit of the above approach compared to using `Ember.run.next` is
  that you will be able to perform DOM/CSS operations before unprocessed
  elements are rendered to the screen, which may prevent flickering or
  other artifacts caused by delaying processing until after rendering.

  The other major benefit to the above approach is that `Ember.run.next`
  introduces an element of non-determinism, which can make things much
  harder to test, due to its reliance on `setTimeout`; it's much harder
  to guarantee the order of scheduled operations when they are scheduled
  outside of the current run loop, i.e. with `Ember.run.next`.

  @method next
  @param {Object} [target] target of method to invoke
  @param {Function|String} method The method to invoke.
    If you pass a string it will be resolved on the
    target at the time the method is invoked.
  @param {Object} [args*] Optional arguments to pass to the timeout.
  @return {Object} timer
*/
Ember.run.next = function() {
  var args = slice.call(arguments);
  args.push(1);
  return backburner.later.apply(backburner, args);
};

/**
  Cancels a scheduled item. Must be a value returned by `Ember.run.later()`,
  `Ember.run.once()`, or `Ember.run.next()`.

  ```javascript
  var runNext = Ember.run.next(myContext, function(){
    // will not be executed
  });
  Ember.run.cancel(runNext);

  var runLater = Ember.run.later(myContext, function(){
    // will not be executed
  }, 500);
  Ember.run.cancel(runLater);

  var runOnce = Ember.run.once(myContext, function(){
    // will not be executed
  });
  Ember.run.cancel(runOnce);
  ```

  @method cancel
  @param {Object} timer Timer object to cancel
  @return {void}
*/
Ember.run.cancel = function(timer) {
  return backburner.cancel(timer);
};
<|endoftext|>


<commit_before>var sys = require("sys"),
    Connect = require("connect");

//bootstrap jojo (default context object is 'global')
require("../lib/core").bootstrap(/*some custom context object can go here*/);

//TODO: These states have some core functionality which should be moved in the framework
//TODO: make generic configuration file loader for this stuff
jojo.init({
    port: 8088,
    debug: true,
    jojoRoot: "../lib/",
    appRoot: __dirname,
    enableLogging: true,
    logFilePath: "test.log",
    middleware: [

    ],
    states: {
        ready: {
            stateStartup: function(fsm, args) {
                if (jojo.appOptions.enableLogging && !jojo.logger) {
                    jojo.logger = new jojo.logging.logger();
                }
                sys.puts("app is currently waiting on requests");
            },
            request: function(fsm, args) {
                //we got a new request, move to the "processingRequest" state
                return fsm.states.processingRequest;
            }
        },
        processingRequest: {
            stateStartup: function(fsm, args) {
                var req = args.request;
                var res = args.response;

                //basic benchmarking
                req.startTime = (new Date()).getTime();

                if (jojo.logger) {
                    jojo.logger.log("-------------------------------------------------------------------------");
                    jojo.logger.log("processing request: " + req.url);
                }

                req.on("end", function() {
                    fsm.fire("endRequest", {request: req, response: res});
                });

                //start running through the middleware
                args.next();

                //go back and wait for the next request
                return fsm.states.ready;
            }
        },
        global: {
          endRequest: function(fsm, args) {
            //done processing the request, we can go wait for a new one now
            //simple per-request benchmarking
            var req = args.request;
            var newTick = (new Date()).getTime();
            var diff = newTick - req.startTime;
            if (jojo.logger) {
                jojo.logger.log("request took " + diff + " milliseconds");
                jojo.logger.log("-------------------------------------------------------------------------");
                jojo.logger.flush();
            }
          }
        }
    }
});<commit_msg>Changed log file name from test to blog.<commit_after>var sys = require("sys"),
    Connect = require("connect");

//bootstrap jojo (default context object is 'global')
require("../lib/core").bootstrap(/*some custom context object can go here*/);

//TODO: These states have some core functionality which should be moved in the framework
//TODO: make generic configuration file loader for this stuff
jojo.init({
    port: 8088,
    debug: true,
    jojoRoot: "../lib/",
    appRoot: __dirname,
    enableLogging: true,
    logFilePath: "blog.log",
    middleware: [

    ],
    states: {
        ready: {
            stateStartup: function(fsm, args) {
                if (jojo.appOptions.enableLogging && !jojo.logger) {
                    jojo.logger = new jojo.logging.logger();
                }
                sys.puts("app is currently waiting on requests");
            },
            request: function(fsm, args) {
                //we got a new request, move to the "processingRequest" state
                return fsm.states.processingRequest;
            }
        },
        processingRequest: {
            stateStartup: function(fsm, args) {
                var req = args.request;
                var res = args.response;

                //basic benchmarking
                req.startTime = (new Date()).getTime();

                if (jojo.logger) {
                    jojo.logger.log("-------------------------------------------------------------------------");
                    jojo.logger.log("processing request: " + req.url);
                }

                req.on("end", function() {
                    fsm.fire("endRequest", {request: req, response: res});
                });

                //start running through the middleware
                args.next();

                //go back and wait for the next request
                return fsm.states.ready;
            }
        },
        global: {
          endRequest: function(fsm, args) {
            //done processing the request, we can go wait for a new one now
            //simple per-request benchmarking
            var req = args.request;
            var newTick = (new Date()).getTime();
            var diff = newTick - req.startTime;
            if (jojo.logger) {
                jojo.logger.log("request took " + diff + " milliseconds");
                jojo.logger.log("-------------------------------------------------------------------------");
                jojo.logger.flush();
            }
          }
        }
    }
});<|endoftext|>


<commit_before>const express = require('express')
const router = express.Router()
const ms = require('ms')
const apn = require('apn')
const joi = require('joi')
const { validate } = require('../helpers')
const Wc = require('../schemas/wc')
const moment = require('moment');
const ObjectId = require('mongoose').Types.ObjectId;
const Report = require('../schemas/report');

import { Counter } from '../generator/counter';
let counter = new Counter();
counter.notificationFunction = (wcId, count) => {}; // @todo here register call function

router.get('/', (req, res) => {
    const params = req.query
    if ('category' in params) {
        try {
            let objId = new ObjectId(params.category);
            Wc.find({ categoryId: objId }, (err, item) => {
                if (err) {
                    console.error(err);
                }
                res.json({
                    status: 'success',
                    data: item
                });
            });
        } catch (e) {
            res.status(400).json({
                status: 'error',
                message: 'Invalid category'
            });
        }
    } else {
        Wc.find((err, items) => {
            if (err) {
                console.error(err)
            }
            res.json({
                status: 'success',
                data: items
            })
        })
    }
})

router.get('/:wcId', (req, res) => {
    const { wcId } = req.params
    Wc.findById(wcId, 'id categoryId status banner active')
        .then(item => {
            if (!item) {
                return res.status(404).json({
                    status: 'error',
                    message: 'Wc not found'
                });
            }
            return res.json({
                status: 'success',
                data: item
            })
        })
        .catch(() => {
            return res.status(400).json({
                status: 'error',
                message: 'Wrong wc id'
            })
        })
})

const apnProvider = new apn.Provider({
    token: {
        key: process.env.IOS_PATH_TO_P8_FILE,
        keyId: process.env.IOS_KEY_ID,
        teamId: process.env.IOS_TEAM_ID
    },
    production: false
})

const sendNotification = ({ deviceToken, title, _id }) => {
    const notification = new apn.Notification()
    notification.topic = process.env.IOS_BUNDLE_ID
    notification.expiry = ms('1h')
    notification.badge = 1
    notification.sound = 'ping.aiff'
    notification.alert = `WC ${title} is vacant.`
    notification.payload = { id: _id }
    return apnProvider.send(notification, deviceToken)
}

const notifyDevices = ({ wcId }) => {
  return Wc.findById(wcId)
  .then(wc => {
    return Promise.all(wc.deviceTokens.map(deviceToken => {
      return sendNotification(wc)
    }))
  })
}

router.get('/:wcId/notify', (req, res) => {
  const { wcId } = req.params
  notifyDevices({ wcId })
  .then((results) => {
    console.log(results)
    return res.status(200).json(results).end()
  })
  .catch(err => console.log(err))
})

router.post('/:wcId/notify', (req, res) => {
  if ('status' in req.body) {
    counter.dbWrite(req.params.wcId, req.body.status);
    if (req.body.status === false) {
        notifyDevices({ wcId })
            .then((results) => {
                console.log(results)
                return res.status(200).json({
                    status: 'success',
                    data: results
                }).end()
            })
            .catch(err => console.log(err))
    }
  }
})

router.get('/:wcId/last', (req, res) => {
    try {
        if ('from' in req.query) {
            Report.find({
                wcId: new ObjectId(req.params.wcId),
                date: {
                    $gte: moment(req.query.from).toDate()
                }
            })
                .then((items) => {
                    res.json({
                        status: 'success',
                        reports: items || []
                    });
                })
                .catch(() => {
                    return res.status(400).json({
                        status: 'error',
                        message: 'Wrong wc id'
                    })
                });
        } else {
            res.json({
                status: 'success',
                reports: []
            });
        }
    } catch (e) {
        return res.status(400).json({
            status: 'error',
            message: 'Something goes wrong (wcid, date format)'
        })
    }
});

const expSchema = joi.object({
    deviceToken: joi.string().required()
}).required()

router.post('/:wcId/subscribe', validate('body', expSchema), (req, res) => {
  const { deviceToken } = req.body
  console.log('deviceToken', deviceToken);
  const { wcId } = req.params
  if (req.headers['X-Auth-token']) {
    const adminWcId = req.headers['X-Auth-token']
    Wc.find({ token: adminWcId })
    .then(wc => {
      if(!wc) {
        return res.sendStatus(404).end()
      }
      wc.adminDeviceTokens.push(deviceToken)
    })
    .then(() => {
      res.sendStatus(201).end()
    })
    .catch(err => console.log(err))
  } else {
    Wc.findById(wcId)
    .then(wc => {
      if(!wc) {
        return res.sendStatus(404).end()
      }
      wc.deviceTokens.push(deviceToken)
      return wc.save()
    })
    .then(() => {
      return res.sendStatus(204).end()
    })
    .catch(err => {
      console.log(err)
      res.sendStatus(500)
    })
  }
})

router.post('/:wcId/unsubscribe', validate('body', expSchema), (req, res) => {
    const { deviceToken } = req.body
    const { wcId } = req.params
    if (req.headers['X-Auth-token']) {
        const adminWcId = req.headers['X-Auth-token']
        Wc.find({ token: adminWcId })
            .then(wc => {
                if (!wc) {
                    return res.sendStatus(404).end()
                }
                const deviceTokenIndex = wc.adminDeviceTokens.findIndex(deviceToken)
                if (deviceTokenIndex === -1) {
                    return res.sendStatus(404).end()
                }
                wc.adminDeviceTokens = [
                    ...wc.adminDeviceTokens.slice(0, deviceTokenIndex),
                    ...wc.adminDeviceTokens.slice(deviceTokenIndex + 1)
                ]
                return wc.save()
            })
            .then(() => res.sendStatus(201).end())
            .catch(err => {
                console.log(err)
                res.sendStatus(500)
            })
    } else {
        Wc.findById(wcId)
            .then(wc => {
                const deviceTokenIndex = wc.deviceTokens.indexOf(deviceToken)
                if (deviceTokenIndex === -1) {
                    return res.sendStatus(404).end()
                }
                wc.deviceTokens = [
                    ...wc.deviceTokens.slice(0, deviceTokenIndex),
                    ...wc.deviceTokens.slice(deviceTokenIndex + 1)
                ]
                return wc.save()
            })
            .then(() => res.sendStatus(204).end())
            .catch(err => {
                console.log(err)
                res.sendStatus(500)
            })
    }
})

/**
 * Report generator
 */
// const data = require('./data');
// const moment = require('moment');
// router.get('/gen', (req, res) => {
//     for (let item of data) {
//         if (item.status === 'occupied' || item.status === 'vacant') {
//             let report = new Report();
//             report.date = moment(item.date);
//             report.status = item.status === 'occupied' ? true : false;
//             report.wcId = new ObjectId('589e3bf575d52d722a3d2c08');
//             report.save();

//             let report2 = new Report();
//             report2.date = moment(item.date);
//             report2.status = item.status === 'occupied' ? false : true;
//             report2.wcId = new ObjectId('589e3cda75d52d722a3d2cda');
//             report2.save();
//         }
//     }
//     res.json({});
// });

router.put('/:wcId', (req, res) => {
    Wc.findById(req.params.wcId)
        .then(item => {
            if (!item) {
                res.status(404);
                return res.json({
                    status: 'error',
                    message: 'Wc not found'
                });
            }
            if ('banner' in req.body) {
                item.banner = req.body.banner;
            }
            if ('usageCount' in req.body) {
                item.usageCount = req.body.usageCount; // @todo validate in notifications
            }
            if ('inactivity' in req.body) {
                item.inactivity = req.body.inactivity; // @todo validate in notifications
            }

            item.save();

            res.json({
                status: 'success',
                data: item
            });
        })
        .catch(() => {
            return res.status(400).json({
                status: 'error',
                message: 'Wrong wc id'
            })
        });
});

module.exports = router;
<commit_msg>fix pushky<commit_after>const express = require('express')
const router = express.Router()
const ms = require('ms')
const apn = require('apn')
const joi = require('joi')
const { validate } = require('../helpers')
const Wc = require('../schemas/wc')
const moment = require('moment');
const ObjectId = require('mongoose').Types.ObjectId;
const Report = require('../schemas/report');

import { Counter } from '../generator/counter';
let counter = new Counter();
counter.notificationFunction = (wcId, count) => {}; // @todo here register call function

router.get('/', (req, res) => {
    const params = req.query
    if ('category' in params) {
        try {
            let objId = new ObjectId(params.category);
            Wc.find({ categoryId: objId }, (err, item) => {
                if (err) {
                    console.error(err);
                }
                res.json({
                    status: 'success',
                    data: item
                });
            });
        } catch (e) {
            res.status(400).json({
                status: 'error',
                message: 'Invalid category'
            });
        }
    } else {
        Wc.find((err, items) => {
            if (err) {
                console.error(err)
            }
            res.json({
                status: 'success',
                data: items
            })
        })
    }
})

router.get('/:wcId', (req, res) => {
    const { wcId } = req.params
    Wc.findById(wcId, 'id categoryId status banner active')
        .then(item => {
            if (!item) {
                return res.status(404).json({
                    status: 'error',
                    message: 'Wc not found'
                });
            }
            return res.json({
                status: 'success',
                data: item
            })
        })
        .catch(() => {
            return res.status(400).json({
                status: 'error',
                message: 'Wrong wc id'
            })
        })
})

const apnProvider = new apn.Provider({
    token: {
        key: process.env.IOS_PATH_TO_P8_FILE,
        keyId: process.env.IOS_KEY_ID,
        teamId: process.env.IOS_TEAM_ID
    },
    production: false
})

const sendNotification = ({ title, _id }, deviceToken) => {
    console.log(deviceToken, title, _id)
    const notification = new apn.Notification()
    notification.topic = process.env.IOS_BUNDLE_ID
    notification.expiry = ms('1h')
    notification.badge = 1
    notification.sound = 'ping.aiff'
    notification.alert = `WC ${title} is vacant.`
    // notification.payload = { id: _id }
    return apnProvider.send(notification, deviceToken)
}

const notifyDevices = ({ wcId }) => {
  return Wc.findById(wcId)
  .then(wc => {
    const uniqueDeviceTokens = wc.deviceTokens.filter((elem, index, self) => {
      return index == self.indexOf(elem)
    })
    return Promise.all(uniqueDeviceTokens.map(deviceToken => {
      return sendNotification(wc, deviceToken)
    }))
  })
}

router.get('/:wcId/notify', (req, res) => {
  const { wcId } = req.params
  notifyDevices({ wcId })
  .then((results) => {
    console.log(results)
    return res.status(200).json(results).end()
  })
  .catch(err => console.log(err))
})

router.post('/:wcId/notify', (req, res) => {
  if ('status' in req.body) {
    counter.dbWrite(req.params.wcId, req.body.status);
    if (req.body.status === false) {
        notifyDevices({ wcId })
            .then((results) => {
                console.log(results)
                return res.status(200).json({
                    status: 'success',
                    data: results
                }).end()
            })
            .catch(err => console.log(err))
    }
  }
})

router.get('/:wcId/last', (req, res) => {
    try {
        if ('from' in req.query) {
            Report.find({
                wcId: new ObjectId(req.params.wcId),
                date: {
                    $gte: moment(req.query.from).toDate()
                }
            })
                .then((items) => {
                    res.json({
                        status: 'success',
                        reports: items || []
                    });
                })
                .catch(() => {
                    return res.status(400).json({
                        status: 'error',
                        message: 'Wrong wc id'
                    })
                });
        } else {
            res.json({
                status: 'success',
                reports: []
            });
        }
    } catch (e) {
        return res.status(400).json({
            status: 'error',
            message: 'Something goes wrong (wcid, date format)'
        })
    }
});

const expSchema = joi.object({
    deviceToken: joi.string().required()
}).required()

router.post('/:wcId/subscribe', validate('body', expSchema), (req, res) => {
  const { deviceToken } = req.body
  console.log('deviceToken', deviceToken);
  const { wcId } = req.params
  if (req.headers['X-Auth-token']) {
    const adminWcId = req.headers['X-Auth-token']
    Wc.find({ token: adminWcId })
    .then(wc => {
      if(!wc) {
        return res.sendStatus(404).end()
      }
      wc.adminDeviceTokens.push(deviceToken)
    })
    .then(() => {
      res.sendStatus(201).end()
    })
    .catch(err => console.log(err))
  } else {
    Wc.findById(wcId)
    .then(wc => {
      if(!wc) {
        return res.sendStatus(404).end()
      }
      if(wc.deviceTokens.indexOf(deviceToken) === -1) {
        return res.sendStatus(204).end()
      }
      wc.deviceTokens.push(deviceToken)
      return wc.save()
    })
    .then(() => {
      return res.sendStatus(204).end()
    })
    .catch(err => {
      console.log(err)
      res.sendStatus(500)
    })
  }
})

router.post('/:wcId/unsubscribe', validate('body', expSchema), (req, res) => {
    const { deviceToken } = req.body
    const { wcId } = req.params
    if (req.headers['X-Auth-token']) {
        const adminWcId = req.headers['X-Auth-token']
        Wc.find({ token: adminWcId })
            .then(wc => {
                if (!wc) {
                    return res.sendStatus(404).end()
                }
                const deviceTokenIndex = wc.adminDeviceTokens.findIndex(deviceToken)
                if (deviceTokenIndex === -1) {
                    return res.sendStatus(404).end()
                }
                wc.adminDeviceTokens = [
                    ...wc.adminDeviceTokens.slice(0, deviceTokenIndex),
                    ...wc.adminDeviceTokens.slice(deviceTokenIndex + 1)
                ]
                return wc.save()
            })
            .then(() => res.sendStatus(201).end())
            .catch(err => {
                console.log(err)
                res.sendStatus(500)
            })
    } else {
        Wc.findById(wcId)
            .then(wc => {
                const deviceTokenIndex = wc.deviceTokens.indexOf(deviceToken)
                if (deviceTokenIndex === -1) {
                    return res.sendStatus(404).end()
                }
                wc.deviceTokens = [
                    ...wc.deviceTokens.slice(0, deviceTokenIndex),
                    ...wc.deviceTokens.slice(deviceTokenIndex + 1)
                ]
                return wc.save()
            })
            .then(() => res.sendStatus(204).end())
            .catch(err => {
                console.log(err)
                res.sendStatus(500)
            })
    }
})

/**
 * Report generator
 */
// const data = require('./data');
// const moment = require('moment');
// router.get('/gen', (req, res) => {
//     for (let item of data) {
//         if (item.status === 'occupied' || item.status === 'vacant') {
//             let report = new Report();
//             report.date = moment(item.date);
//             report.status = item.status === 'occupied' ? true : false;
//             report.wcId = new ObjectId('589e3bf575d52d722a3d2c08');
//             report.save();

//             let report2 = new Report();
//             report2.date = moment(item.date);
//             report2.status = item.status === 'occupied' ? false : true;
//             report2.wcId = new ObjectId('589e3cda75d52d722a3d2cda');
//             report2.save();
//         }
//     }
//     res.json({});
// });

router.put('/:wcId', (req, res) => {
    Wc.findById(req.params.wcId)
        .then(item => {
            if (!item) {
                res.status(404);
                return res.json({
                    status: 'error',
                    message: 'Wc not found'
                });
            }
            if ('banner' in req.body) {
                item.banner = req.body.banner;
            }
            if ('usageCount' in req.body) {
                item.usageCount = req.body.usageCount; // @todo validate in notifications
            }
            if ('inactivity' in req.body) {
                item.inactivity = req.body.inactivity; // @todo validate in notifications
            }

            item.save();

            res.json({
                status: 'success',
                data: item
            });
        })
        .catch(() => {
            return res.status(400).json({
                status: 'error',
                message: 'Wrong wc id'
            })
        });
});

module.exports = router;
<|endoftext|>


<commit_before>var AWS = require('./core');
var domain = AWS.util.nodeRequire('domain');

/**
 * @!method on(eventName, callback)
 *   Registers an event listener callback for the event given by `eventName`.
 *   Parameters passed to the callback function depend on the individual event
 *   being triggered. See the event documentation for those parameters.
 *
 *   @param eventName [String] the event name to register the listener for
 *   @param callback [Function] the listener callback function
 *   @return [AWS.SequentialExecutor] the same object for chaining
 */
AWS.SequentialExecutor = AWS.util.inherit({

  constructor: function SequentialExecutor() {
    this.domain = domain && domain.active;
    this._events = {};
  },

  /**
   * @api private
   */
  listeners: function listeners(eventName) {
    return this._events[eventName] ? this._events[eventName].slice(0) : [];
  },

  on: function on(eventName, listener) {
    if (this._events[eventName]) {
      this._events[eventName].push(listener);
    } else {
      this._events[eventName] = [listener];
    }
    return this;
  },

  /**
   * @api private
   */
  onAsync: function onAsync(eventName, listener) {
    listener._isAsync = true;
    return this.on(eventName, listener);
  },

  removeListener: function removeListener(eventName, listener) {
    var listeners = this._events[eventName];
    if (listeners) {
      var length = listeners.length;
      var position = -1;
      for (var i = 0; i < length; ++i) {
        if (listeners[i] === listener) {
          position = i;
        }
      }
      if (position > -1) {
        listeners.splice(position, 1);
      }
    }
    return this;
  },

  removeAllListeners: function removeAllListeners(eventName) {
    if (eventName) {
      delete this._events[eventName];
    } else {
      this._events = {};
    }
    return this;
  },

  /**
   * @api private
   */
  emit: function emit(eventName, eventArgs, doneCallback) {
    if (!doneCallback) doneCallback = this.unhandledErrorCallback;
    if (domain && this.domain instanceof domain.Domain)
      this.domain.enter();

    var listeners = this.listeners(eventName);
    var count = listeners.length;
    this.callListeners(listeners, eventArgs, doneCallback);
    return count > 0;
  },

  /**
   * @api private
   */
  callListeners: function callListeners(listeners, args, doneCallback) {
    if (listeners.length === 0) {
      doneCallback.call(this);
      if (domain && this.domain instanceof domain.Domain)
        this.domain.exit();
    } else {
      var listener = listeners.shift();
      if (listener._isAsync) {

        // asynchronous listener
        var self = this;
        var callNextListener = function(err) {
          if (err) {
            doneCallback.call(self, err);
            if (domain && self.domain instanceof domain.Domain)
              self.domain.exit();
          } else {
            self.callListeners(listeners, args, doneCallback);
          }
        };
        listener.apply(this, args.concat([callNextListener]));

      } else {

        // synchronous listener
        try {
          listener.apply(this, args);
          this.callListeners(listeners, args, doneCallback);
        } catch (err) {
          if (err._hardError) throw err;

          doneCallback.call(this, err);
          if (domain && this.domain instanceof domain.Domain)
            this.domain.exit();
        }

      }
    }
  },

  /**
   * Adds or copies a set of listeners from another list of
   * listeners or SequentialExecutor object.
   *
   * @param listeners [map<String,Array<Function>>, AWS.SequentialExecutor]
   *   a list of events and callbacks, or an event emitter object
   *   containing listeners to add to this emitter object.
   * @return [AWS.SequentialExecutor] the emitter object, for chaining.
   * @example Adding listeners from a map of listeners
   *   emitter.addListeners({
   *     event1: [function() { ... }, function() { ... }],
   *     event2: [function() { ... }]
   *   });
   *   emitter.emit('event1'); // emitter has event1
   *   emitter.emit('event2'); // emitter has event2
   * @example Adding listeners from another emitter object
   *   var emitter1 = new AWS.SequentialExecutor();
   *   emitter1.on('event1', function() { ... });
   *   emitter1.on('event2', function() { ... });
   *   var emitter2 = new AWS.SequentialExecutor();
   *   emitter2.addListeners(emitter1);
   *   emitter2.emit('event1'); // emitter2 has event1
   *   emitter2.emit('event2'); // emitter2 has event2
   */
  addListeners: function addListeners(listeners) {
    var self = this;

    // extract listeners if parameter is an SequentialExecutor object
    if (listeners._events) listeners = listeners._events;

    AWS.util.each(listeners, function(event, callbacks) {
      if (typeof callbacks === 'function') callbacks = [callbacks];
      AWS.util.arrayEach(callbacks, function(callback) {
        self.on(event, callback);
      });
    });

    return self;
  },

  /**
   * Registers an event with {on} and saves the callback handle function
   * as a property on the emitter object using a given `name`.
   *
   * @param name [String] the property name to set on this object containing
   *   the callback function handle so that the listener can be removed in
   *   the future.
   * @param (see on)
   * @return (see on)
   * @example Adding a named listener DATA_CALLBACK
   *   var listener = function() { doSomething(); };
   *   emitter.addNamedListener('DATA_CALLBACK', 'data', listener);
   *
   *   // the following prints: true
   *   console.log(emitter.DATA_CALLBACK == listener);
   */
  addNamedListener: function addNamedListener(name, eventName, callback) {
    this[name] = callback;
    this.addListener(eventName, callback);
    return this;
  },

  /**
   * @api private
   */
  addNamedAsyncListener: function addNamedAsyncListener(name, eventName, callback) {
    callback._isAsync = true;
    return this.addNamedListener(name, eventName, callback);
  },

  /**
   * Helper method to add a set of named listeners using
   * {addNamedListener}. The callback contains a parameter
   * with a handle to the `addNamedListener` method.
   *
   * @callback callback function(add)
   *   The callback function is called immediately in order to provide
   *   the `add` function to the block. This simplifies the addition of
   *   a large group of named listeners.
   *   @param add [Function] the {addNamedListener} function to call
   *     when registering listeners.
   * @example Adding a set of named listeners
   *   emitter.addNamedListeners(function(add) {
   *     add('DATA_CALLBACK', 'data', function() { ... });
   *     add('OTHER', 'otherEvent', function() { ... });
   *     add('LAST', 'lastEvent', function() { ... });
   *   });
   *
   *   // these properties are now set:
   *   emitter.DATA_CALLBACK;
   *   emitter.OTHER;
   *   emitter.LAST;
   */
  addNamedListeners: function addNamedListeners(callback) {
    var self = this;
    callback(
      function() {
        self.addNamedListener.apply(self, arguments);
      },
      function() {
        self.addNamedAsyncListener.apply(self, arguments);
      }
    );
    return this;
  },

  /**
   * @api private
   */
  unhandledErrorCallback: function unhandledErrorCallback(err) {
    if (err) {
      if (domain && this.domain instanceof domain.Domain) {
        err.domainEmitter = this;
        err.domain = this.domain;
        err.domainThrown = false;
        this.domain.emit('error', err);
      } else {
        throw err;
      }
    }
  }
});

/**
 * {on} is the prefered method.
 * @api private
 */
AWS.SequentialExecutor.prototype.addListener = AWS.SequentialExecutor.prototype.on;

module.exports = AWS.SequentialExecutor;
<commit_msg>Don't need to throw on hardError anymore<commit_after>var AWS = require('./core');
var domain = AWS.util.nodeRequire('domain');

/**
 * @!method on(eventName, callback)
 *   Registers an event listener callback for the event given by `eventName`.
 *   Parameters passed to the callback function depend on the individual event
 *   being triggered. See the event documentation for those parameters.
 *
 *   @param eventName [String] the event name to register the listener for
 *   @param callback [Function] the listener callback function
 *   @return [AWS.SequentialExecutor] the same object for chaining
 */
AWS.SequentialExecutor = AWS.util.inherit({

  constructor: function SequentialExecutor() {
    this.domain = domain && domain.active;
    this._events = {};
  },

  /**
   * @api private
   */
  listeners: function listeners(eventName) {
    return this._events[eventName] ? this._events[eventName].slice(0) : [];
  },

  on: function on(eventName, listener) {
    if (this._events[eventName]) {
      this._events[eventName].push(listener);
    } else {
      this._events[eventName] = [listener];
    }
    return this;
  },

  /**
   * @api private
   */
  onAsync: function onAsync(eventName, listener) {
    listener._isAsync = true;
    return this.on(eventName, listener);
  },

  removeListener: function removeListener(eventName, listener) {
    var listeners = this._events[eventName];
    if (listeners) {
      var length = listeners.length;
      var position = -1;
      for (var i = 0; i < length; ++i) {
        if (listeners[i] === listener) {
          position = i;
        }
      }
      if (position > -1) {
        listeners.splice(position, 1);
      }
    }
    return this;
  },

  removeAllListeners: function removeAllListeners(eventName) {
    if (eventName) {
      delete this._events[eventName];
    } else {
      this._events = {};
    }
    return this;
  },

  /**
   * @api private
   */
  emit: function emit(eventName, eventArgs, doneCallback) {
    if (!doneCallback) doneCallback = this.unhandledErrorCallback;
    if (domain && this.domain instanceof domain.Domain)
      this.domain.enter();

    var listeners = this.listeners(eventName);
    var count = listeners.length;
    this.callListeners(listeners, eventArgs, doneCallback);
    return count > 0;
  },

  /**
   * @api private
   */
  callListeners: function callListeners(listeners, args, doneCallback) {
    if (listeners.length === 0) {
      doneCallback.call(this);
      if (domain && this.domain instanceof domain.Domain)
        this.domain.exit();
    } else {
      var listener = listeners.shift();
      if (listener._isAsync) {

        // asynchronous listener
        var self = this;
        var callNextListener = function(err) {
          if (err) {
            doneCallback.call(self, err);
            if (domain && self.domain instanceof domain.Domain)
              self.domain.exit();
          } else {
            self.callListeners(listeners, args, doneCallback);
          }
        };
        listener.apply(this, args.concat([callNextListener]));

      } else {

        // synchronous listener
        try {
          listener.apply(this, args);
          this.callListeners(listeners, args, doneCallback);
        } catch (err) {
          doneCallback.call(this, err);
          if (domain && this.domain instanceof domain.Domain)
            this.domain.exit();
        }

      }
    }
  },

  /**
   * Adds or copies a set of listeners from another list of
   * listeners or SequentialExecutor object.
   *
   * @param listeners [map<String,Array<Function>>, AWS.SequentialExecutor]
   *   a list of events and callbacks, or an event emitter object
   *   containing listeners to add to this emitter object.
   * @return [AWS.SequentialExecutor] the emitter object, for chaining.
   * @example Adding listeners from a map of listeners
   *   emitter.addListeners({
   *     event1: [function() { ... }, function() { ... }],
   *     event2: [function() { ... }]
   *   });
   *   emitter.emit('event1'); // emitter has event1
   *   emitter.emit('event2'); // emitter has event2
   * @example Adding listeners from another emitter object
   *   var emitter1 = new AWS.SequentialExecutor();
   *   emitter1.on('event1', function() { ... });
   *   emitter1.on('event2', function() { ... });
   *   var emitter2 = new AWS.SequentialExecutor();
   *   emitter2.addListeners(emitter1);
   *   emitter2.emit('event1'); // emitter2 has event1
   *   emitter2.emit('event2'); // emitter2 has event2
   */
  addListeners: function addListeners(listeners) {
    var self = this;

    // extract listeners if parameter is an SequentialExecutor object
    if (listeners._events) listeners = listeners._events;

    AWS.util.each(listeners, function(event, callbacks) {
      if (typeof callbacks === 'function') callbacks = [callbacks];
      AWS.util.arrayEach(callbacks, function(callback) {
        self.on(event, callback);
      });
    });

    return self;
  },

  /**
   * Registers an event with {on} and saves the callback handle function
   * as a property on the emitter object using a given `name`.
   *
   * @param name [String] the property name to set on this object containing
   *   the callback function handle so that the listener can be removed in
   *   the future.
   * @param (see on)
   * @return (see on)
   * @example Adding a named listener DATA_CALLBACK
   *   var listener = function() { doSomething(); };
   *   emitter.addNamedListener('DATA_CALLBACK', 'data', listener);
   *
   *   // the following prints: true
   *   console.log(emitter.DATA_CALLBACK == listener);
   */
  addNamedListener: function addNamedListener(name, eventName, callback) {
    this[name] = callback;
    this.addListener(eventName, callback);
    return this;
  },

  /**
   * @api private
   */
  addNamedAsyncListener: function addNamedAsyncListener(name, eventName, callback) {
    callback._isAsync = true;
    return this.addNamedListener(name, eventName, callback);
  },

  /**
   * Helper method to add a set of named listeners using
   * {addNamedListener}. The callback contains a parameter
   * with a handle to the `addNamedListener` method.
   *
   * @callback callback function(add)
   *   The callback function is called immediately in order to provide
   *   the `add` function to the block. This simplifies the addition of
   *   a large group of named listeners.
   *   @param add [Function] the {addNamedListener} function to call
   *     when registering listeners.
   * @example Adding a set of named listeners
   *   emitter.addNamedListeners(function(add) {
   *     add('DATA_CALLBACK', 'data', function() { ... });
   *     add('OTHER', 'otherEvent', function() { ... });
   *     add('LAST', 'lastEvent', function() { ... });
   *   });
   *
   *   // these properties are now set:
   *   emitter.DATA_CALLBACK;
   *   emitter.OTHER;
   *   emitter.LAST;
   */
  addNamedListeners: function addNamedListeners(callback) {
    var self = this;
    callback(
      function() {
        self.addNamedListener.apply(self, arguments);
      },
      function() {
        self.addNamedAsyncListener.apply(self, arguments);
      }
    );
    return this;
  },

  /**
   * @api private
   */
  unhandledErrorCallback: function unhandledErrorCallback(err) {
    if (err) {
      if (domain && this.domain instanceof domain.Domain) {
        err.domainEmitter = this;
        err.domain = this.domain;
        err.domainThrown = false;
        this.domain.emit('error', err);
      } else {
        throw err;
      }
    }
  }
});

/**
 * {on} is the prefered method.
 * @api private
 */
AWS.SequentialExecutor.prototype.addListener = AWS.SequentialExecutor.prototype.on;

module.exports = AWS.SequentialExecutor;
<|endoftext|>