<commit_before>/**
 * @file Manages Streaming APIs
 * @author Shinichi Tomita <shinichi.tomita@gmail.com>
 */

'use strict';

var events = require('events'),
    inherits = require('inherits'),
    Faye   = require('faye');

/**
 * Streaming API topic class
 *
 * @class Streaming~Topic
 * @param {Streaming} steaming - Streaming API object
 * @param {String} name - Topic name
 */
var Topic = module.exports = function(streaming, name) {
  this._streaming = streaming;
  this.name = name;
};

/**
 * @typedef {Object} Streaming~StreamingMessage
 * @prop {Object} event
 * @prop {Object} event.type - Event type
 * @prop {Record} sobject - Record information
 */
/**
 * Subscribe listener to topic
 *
 * @method Streaming~Topic#subscribe
 * @param {Callback.<Streaming~StreamingMesasge>} listener - Streaming message listener
 * @returns {Streaming~Topic}
 */
Topic.prototype.subscribe = function(listener) {
  this._streaming.subscribe(this.name, listener);
  return this;
};

/**
 * Unsubscribe listener from topic
 *
 * @method Streaming~Topic#unsubscribe
 * @param {Callback.<Streaming~StreamingMesasge>} listener - Streaming message listener
 * @returns {Streaming~Topic}
 */
Topic.prototype.unsubscribe = function(listener) {
  this._streaming.unsubscribe(this.name, listener);
  return this;
};

/*--------------------------------------------*/

/**
 * Streaming API class
 *
 * @class
 * @extends events.EventEmitter
 * @param {Connection} conn - Connection object
 */
var Streaming = function(conn) {
  this._conn = conn;
};

inherits(Streaming, events.EventEmitter);

/** @private **/
Streaming.prototype._createClient = function() {
  var endpointUrl = [ this._conn.instanceUrl, "cometd", this._conn.version ].join('/');
  var fayeClient = new Faye.Client(endpointUrl, {});
  fayeClient.setHeader('Authorization', 'OAuth '+this._conn.accessToken);
  return fayeClient;
};

/**
 * Get named topic
 *
 * @param {String} name - Topic name
 * @returns {Streaming~Topic}
 */
Streaming.prototype.topic = function(name) {
  this._topics = this._topics || {};
  var topic = this._topics[name] =
    this._topics[name] || new Topic(this, name);
  return topic;
};

/**
 * Subscribe topic
 *
 * @param {String} name - Topic name
 * @param {Callback.<Streaming~StreamingMessage>} listener - Streaming message listener
 * @returns {Streaming}
 */
Streaming.prototype.subscribe = function(name, listener) {
  if (!this._fayeClient) {
    if (Faye.Transport.NodeHttp) {
      Faye.Transport.NodeHttp.prototype.batching = false; // prevent streaming API server error
    }
    this._fayeClient = this._createClient();
  }
  this._fayeClient.subscribe("/topic/"+name, listener);
  return this;
};

/**
 * Unsubscribe topic
 *
 * @param {String} name - Topic name
 * @param {Callback.<Streaming~StreamingMessage>} listener - Streaming message listener
 * @returns {Streaming}
 */
Streaming.prototype.unsubscribe = function(name, listener) {
  if (this._fayeClient) {
    this._fayeClient.unsubscribe("/topic/"+name, listener);
  }
  return this;
};

module.exports = Streaming;
<commit_msg>Return subscription object<commit_after>/**
 * @file Manages Streaming APIs
 * @author Shinichi Tomita <shinichi.tomita@gmail.com>
 */

'use strict';

var events = require('events'),
    inherits = require('inherits'),
    Faye   = require('faye');

/**
 * Streaming API topic class
 *
 * @class Streaming~Topic
 * @param {Streaming} steaming - Streaming API object
 * @param {String} name - Topic name
 */
var Topic = module.exports = function(streaming, name) {
  this._streaming = streaming;
  this.name = name;
};

/**
 * @typedef {Object} Streaming~StreamingMessage
 * @prop {Object} event
 * @prop {Object} event.type - Event type
 * @prop {Record} sobject - Record information
 */
/**
 * Subscribe listener to topic
 *
 * @method Streaming~Topic#subscribe
 * @param {Callback.<Streaming~StreamingMesasge>} listener - Streaming message listener
 * @returns {Subscription} - Faye subscription object
 */
Topic.prototype.subscribe = function(listener) {
  return this._streaming.subscribe(this.name, listener);
};

/**
 * Unsubscribe listener from topic
 *
 * @method Streaming~Topic#unsubscribe
 * @param {Callback.<Streaming~StreamingMesasge>} listener - Streaming message listener
 * @returns {Streaming~Topic}
 */
Topic.prototype.unsubscribe = function(listener) {
  this._streaming.unsubscribe(this.name, listener);
  return this;
};

/*--------------------------------------------*/

/**
 * Streaming API class
 *
 * @class
 * @extends events.EventEmitter
 * @param {Connection} conn - Connection object
 */
var Streaming = function(conn) {
  this._conn = conn;
};

inherits(Streaming, events.EventEmitter);

/** @private **/
Streaming.prototype._createClient = function() {
  var endpointUrl = [ this._conn.instanceUrl, "cometd", this._conn.version ].join('/');
  var fayeClient = new Faye.Client(endpointUrl, {});
  fayeClient.setHeader('Authorization', 'OAuth '+this._conn.accessToken);
  return fayeClient;
};

/**
 * Get named topic
 *
 * @param {String} name - Topic name
 * @returns {Streaming~Topic}
 */
Streaming.prototype.topic = function(name) {
  this._topics = this._topics || {};
  var topic = this._topics[name] =
    this._topics[name] || new Topic(this, name);
  return topic;
};

/**
 * Subscribe topic
 *
 * @param {String} name - Topic name
 * @param {Callback.<Streaming~StreamingMessage>} listener - Streaming message listener
 * @returns {Subscription} - Faye subscription object
 */
Streaming.prototype.subscribe = function(name, listener) {
  if (!this._fayeClient) {
    if (Faye.Transport.NodeHttp) {
      Faye.Transport.NodeHttp.prototype.batching = false; // prevent streaming API server error
    }
    this._fayeClient = this._createClient();
  }
  return this._fayeClient.subscribe("/topic/"+name, listener);
};

/**
 * Unsubscribe topic
 *
 * @param {String} name - Topic name
 * @param {Callback.<Streaming~StreamingMessage>} listener - Streaming message listener
 * @returns {Streaming}
 */
Streaming.prototype.unsubscribe = function(name, listener) {
  if (this._fayeClient) {
    this._fayeClient.unsubscribe("/topic/"+name, listener);
  }
  return this;
};

module.exports = Streaming;
<|endoftext|>


<commit_before>var convert = require('color-convert');
var EventEmitter = require('events');
var merge = require('merge');
var util = require('util');
var workerproxy = require('workerproxy');

var ResourceLoader = require('./resourceloader');

module.exports = AssetsManager;

function AssetsManager(opt_options) {
  EventEmitter.call(this);

  var options = {
    workerPath: __dirname + '/../worker.js'
  };

  Object.seal(options);
  merge(options, opt_options);
  Object.freeze(options);

  this.options = options;

  var worker = new Worker(options.workerPath);
  this.api = workerproxy(worker, {timeCalls: true});

  this._emitting = {};
  // TODO: Make a more generic cache?
  this._framesCache = Object.create(null);
  this._imageCache = Object.create(null);
}
util.inherits(AssetsManager, EventEmitter);

/**
 * Indexes a directory. All files in the directory will be reachable through
 * the assets database after this completes. All .pak/.modpak files will also
 * be loaded into the index.
 *
 * The virtual path argument is a prefix for the entries in the directory.
 */
AssetsManager.prototype.addDirectory = function (path, dirEntry, callback) {
  var self = this;

  var pending = 1;
  var decrementPending = function () {
    pending--;
    if (!pending) {
      callback(null);
    }
  };

  var reader = dirEntry.createReader();
  var next = function () {
    reader.readEntries(function (entries) {
      if (!entries.length) {
        process.nextTick(decrementPending);
        return;
      }

      entries.forEach(function (entry) {
        if (entry.name[0] == '.') return;

        var entryPath = path + '/' + entry.name;

        if (entry.isDirectory) {
          pending++;
          self.addDirectory(entryPath, entry, decrementPending);
        } else {
          pending++;
          entry.file(function (file) {
            self.addFile(entryPath, file, decrementPending);
          }, decrementPending);
        }
      });
      next();
    });
  };
  next();
};

AssetsManager.prototype.addFile = function (path, file, callback) {
  this.api.addFile(path, file, callback);
};

AssetsManager.prototype.addRoot = function (dirEntry, callback) {
  this.addDirectory('', dirEntry, callback);
};

AssetsManager.prototype.emitOncePerTick = function (event) {
  if (this._emitting[event]) return;
  this._emitting[event] = true;

  var self = this, args = Array.prototype.slice.call(arguments);
  process.nextTick(function () {
    self.emit.apply(self, args);
    delete self._emitting[event];
  });
};

AssetsManager.prototype.getBlobURL = function (path, callback) {
  this.api.getBlobURL(path, callback);
};

AssetsManager.prototype.getFrames = function (imagePath) {
  var dotOffset = imagePath.lastIndexOf('.');
  var path = imagePath.substr(0, dotOffset) + '.frames';

  if (path in this._framesCache) return this._framesCache[path];
  this._framesCache[path] = null;

  var self = this;
  this.api.getJSON(path, function (err, frames) {
    if (err) {
      console.error(err.stack);
      return;
    }

    self._framesCache[path] = frames;
  });

  return null;
};

/**
 * Gets the image for the specified path. This function is synchronous, but may
 * depend on asynchronous operations. If the image is not immediately available
 * this function will return null. Once more images are available, an "images"
 * event will be emitted.
 */
AssetsManager.prototype.getImage = function (path) {
  // Example path: "/directory/image.png?hueshift=60?fade=ffffff=0.1"
  if (path in this._imageCache) return this._imageCache[path];

  var self = this;

  // Extract image operations.
  var ops = path.split('?');
  // Get the plain path to the image file.
  var filePath = ops.shift();

  // If the image is not in the cache, load it and trigger an "images" event
  // when it's done.
  if (!(filePath in this._imageCache)) {
    this._imageCache[filePath] = null;

    this.getBlobURL(filePath, function (err, url) {
      if (err) {
        console.warn('Failed to load %s (%s)', filePath, err.message);
        return;
      }

      var image = new Image();
      image.src = url;
      image.onload = function () {
        self._imageCache[filePath] = image;
        self.emitOncePerTick('images');
      };
    });
  }

  var image = this._imageCache[filePath];
  if (!image) return null;

  // Apply operations (such as hue shift) on the image.
  var canvas = document.createElement('canvas');
  canvas.width = image.width;
  canvas.height = image.height;

  // Parse all the operations to be applied to the image.
  // TODO: addmask, brightness, fade, replace, saturation
  var hue = 0, flipEveryX = 0;
  for (var i = 0; i < ops.length; i++) {
    var op = ops[i].split(/[=;]/);
    switch (op[0]) {
      // This operation doesn't exist in Starbound, but is helpful for us.
      case 'flipgridx':
        flipEveryX = parseInt(op[1]);
        if (image.width % flipEveryX) {
          throw new Error(image.width + ' not divisible by ' + flipEveryX + ' (' + path + ')');
        }
        break;
      case 'hueshift':
        hue = parseFloat(op[1]);
        break;
      default:
        console.warn('Unsupported image operation:', op);
    }
  }

  var context = canvas.getContext('2d');

  if (flipEveryX) {
    context.save();
    context.scale(-1, 1);
    for (var x = 0; x < image.width; x += flipEveryX) {
      var flippedX = -(x + flipEveryX), dw = flipEveryX, dh = image.height;
      context.drawImage(image, x, 0, dw, dh, flippedX, 0, dw, dh);
    }
    context.restore();
  } else {
    context.drawImage(image, 0, 0);
  }

  if (hue) {
    var imageData = context.getImageData(0, 0, image.width, image.height),
        data = imageData.data;
    for (var i = 0; i < data.length; i += 4) {
      hsv = convert.rgb2hsv(data[i], data[i + 1], data[i + 2]);

      hsv[0] += hue;
      if (hsv[0] < 0) hsv[0] += 360
      else if (hsv[0] >= 360) hsv[0] -= 360;

      rgb = convert.hsv2rgb(hsv);

      data[i] = rgb[0];
      data[i + 1] = rgb[1];
      data[i + 2] = rgb[2];
    }
    context.putImageData(imageData, 0, 0);
  }

  // Create a new object for the modified image and cache it.
  image = new Image();
  image.onload = function () {
    self._imageCache[path] = image;
  };
  image.src = canvas.toDataURL();

  return null;
};

AssetsManager.prototype.getResourceLoader = function (extension) {
  return new ResourceLoader(this, extension);
};

AssetsManager.prototype.getResourcePath = function (resource, path) {
  if (path[0] == '/') return path;
  var base = resource.__path__;
  return base.substr(0, base.lastIndexOf('/') + 1) + path;
};

AssetsManager.prototype.getTileImage = function (resource, field, opt_hueShift) {
  path = this.getResourcePath(resource, resource[field]);

  // Add hueshift image operation if needed.
  if (opt_hueShift) {
    path += '?hueshift=' + (opt_hueShift / 255 * 360);
  }

  return this.getImage(path);
};

AssetsManager.prototype.loadResources = function (extension, callback) {
  var self = this;
  this.api.loadResources(extension, function (err, resources) {
    callback(err, resources);
    if (!err) {
      self.emitOncePerTick('resources');
    }
  });
};
<commit_msg>Don't generate same image more than once<commit_after>var convert = require('color-convert');
var EventEmitter = require('events');
var merge = require('merge');
var util = require('util');
var workerproxy = require('workerproxy');

var ResourceLoader = require('./resourceloader');

module.exports = AssetsManager;

function AssetsManager(opt_options) {
  EventEmitter.call(this);

  var options = {
    workerPath: __dirname + '/../worker.js'
  };

  Object.seal(options);
  merge(options, opt_options);
  Object.freeze(options);

  this.options = options;

  var worker = new Worker(options.workerPath);
  this.api = workerproxy(worker, {timeCalls: true});

  this._emitting = {};
  // TODO: Make a more generic cache?
  this._framesCache = Object.create(null);
  this._imageCache = Object.create(null);
}
util.inherits(AssetsManager, EventEmitter);

/**
 * Indexes a directory. All files in the directory will be reachable through
 * the assets database after this completes. All .pak/.modpak files will also
 * be loaded into the index.
 *
 * The virtual path argument is a prefix for the entries in the directory.
 */
AssetsManager.prototype.addDirectory = function (path, dirEntry, callback) {
  var self = this;

  var pending = 1;
  var decrementPending = function () {
    pending--;
    if (!pending) {
      callback(null);
    }
  };

  var reader = dirEntry.createReader();
  var next = function () {
    reader.readEntries(function (entries) {
      if (!entries.length) {
        process.nextTick(decrementPending);
        return;
      }

      entries.forEach(function (entry) {
        if (entry.name[0] == '.') return;

        var entryPath = path + '/' + entry.name;

        if (entry.isDirectory) {
          pending++;
          self.addDirectory(entryPath, entry, decrementPending);
        } else {
          pending++;
          entry.file(function (file) {
            self.addFile(entryPath, file, decrementPending);
          }, decrementPending);
        }
      });
      next();
    });
  };
  next();
};

AssetsManager.prototype.addFile = function (path, file, callback) {
  this.api.addFile(path, file, callback);
};

AssetsManager.prototype.addRoot = function (dirEntry, callback) {
  this.addDirectory('', dirEntry, callback);
};

AssetsManager.prototype.emitOncePerTick = function (event) {
  if (this._emitting[event]) return;
  this._emitting[event] = true;

  var self = this, args = Array.prototype.slice.call(arguments);
  process.nextTick(function () {
    self.emit.apply(self, args);
    delete self._emitting[event];
  });
};

AssetsManager.prototype.getBlobURL = function (path, callback) {
  this.api.getBlobURL(path, callback);
};

AssetsManager.prototype.getFrames = function (imagePath) {
  var dotOffset = imagePath.lastIndexOf('.');
  var path = imagePath.substr(0, dotOffset) + '.frames';

  if (path in this._framesCache) return this._framesCache[path];
  this._framesCache[path] = null;

  var self = this;
  this.api.getJSON(path, function (err, frames) {
    if (err) {
      console.error(err.stack);
      return;
    }

    self._framesCache[path] = frames;
  });

  return null;
};

/**
 * Gets the image for the specified path. This function is synchronous, but may
 * depend on asynchronous operations. If the image is not immediately available
 * this function will return null. Once more images are available, an "images"
 * event will be emitted.
 */
AssetsManager.prototype.getImage = function (path) {
  // Example path: "/directory/image.png?hueshift=60?fade=ffffff=0.1"
  if (path in this._imageCache) return this._imageCache[path];

  var self = this;

  // Extract image operations.
  var ops = path.split('?');
  // Get the plain path to the image file.
  var filePath = ops.shift();

  // If the image is not in the cache, load it and trigger an "images" event
  // when it's done.
  if (!(filePath in this._imageCache)) {
    this._imageCache[filePath] = null;

    this.getBlobURL(filePath, function (err, url) {
      if (err) {
        console.warn('Failed to load %s (%s)', filePath, err.message);
        return;
      }

      var image = new Image();
      image.src = url;
      image.onload = function () {
        self._imageCache[filePath] = image;
        self.emitOncePerTick('images');
      };
    });
  }

  var image = this._imageCache[filePath];
  if (!image) return null;

  // Apply operations (such as hue shift) on the image.
  var canvas = document.createElement('canvas');
  canvas.width = image.width;
  canvas.height = image.height;

  // Parse all the operations to be applied to the image.
  // TODO: addmask, brightness, fade, replace, saturation
  var hue = 0, flipEveryX = 0;
  for (var i = 0; i < ops.length; i++) {
    var op = ops[i].split(/[=;]/);
    switch (op[0]) {
      // This operation doesn't exist in Starbound, but is helpful for us.
      case 'flipgridx':
        flipEveryX = parseInt(op[1]);
        if (image.width % flipEveryX) {
          throw new Error(image.width + ' not divisible by ' + flipEveryX + ' (' + path + ')');
        }
        break;
      case 'hueshift':
        hue = parseFloat(op[1]);
        break;
      default:
        console.warn('Unsupported image operation:', op);
    }
  }

  var context = canvas.getContext('2d');

  if (flipEveryX) {
    context.save();
    context.scale(-1, 1);
    for (var x = 0; x < image.width; x += flipEveryX) {
      var flippedX = -(x + flipEveryX), dw = flipEveryX, dh = image.height;
      context.drawImage(image, x, 0, dw, dh, flippedX, 0, dw, dh);
    }
    context.restore();
  } else {
    context.drawImage(image, 0, 0);
  }

  if (hue) {
    var imageData = context.getImageData(0, 0, image.width, image.height),
        data = imageData.data;
    for (var i = 0; i < data.length; i += 4) {
      hsv = convert.rgb2hsv(data[i], data[i + 1], data[i + 2]);

      hsv[0] += hue;
      if (hsv[0] < 0) hsv[0] += 360
      else if (hsv[0] >= 360) hsv[0] -= 360;

      rgb = convert.hsv2rgb(hsv);

      data[i] = rgb[0];
      data[i + 1] = rgb[1];
      data[i + 2] = rgb[2];
    }
    context.putImageData(imageData, 0, 0);
  }

  self._imageCache[path] = null;

  // Create a new object for the modified image and cache it.
  image = new Image();
  image.onload = function () {
    self._imageCache[path] = image;
  };
  image.src = canvas.toDataURL();

  return null;
};

AssetsManager.prototype.getResourceLoader = function (extension) {
  return new ResourceLoader(this, extension);
};

AssetsManager.prototype.getResourcePath = function (resource, path) {
  if (path[0] == '/') return path;
  var base = resource.__path__;
  return base.substr(0, base.lastIndexOf('/') + 1) + path;
};

AssetsManager.prototype.getTileImage = function (resource, field, opt_hueShift) {
  path = this.getResourcePath(resource, resource[field]);

  // Add hueshift image operation if needed.
  if (opt_hueShift) {
    path += '?hueshift=' + (opt_hueShift / 255 * 360);
  }

  return this.getImage(path);
};

AssetsManager.prototype.loadResources = function (extension, callback) {
  var self = this;
  this.api.loadResources(extension, function (err, resources) {
    callback(err, resources);
    if (!err) {
      self.emitOncePerTick('resources');
    }
  });
};
<|endoftext|>


<commit_before>exports.BattleScripts = {
                  this.modData('Learnsets', 'masquerain').learnset.hurricane = ['5L100'];
};
<commit_msg>add final learnsets [HOLY FUCK THAT TOOK HOURS]<commit_after>exports.BattleScripts = {
        init: function() {
                  this.modData('Learnsets', 'fennekin').learnset.thunderbolt = ['6M'];
                  this.modData('Learnsets', 'fennekin').learnset.thunder = ['6M'];
                  this.modData('Learnsets', 'fennekin').learnset.calmmind = ['6M'];
                  this.modData('Learnsets', 'fennekin').learnset.batonpass = ['6T'];

                  this.modData('Learnsets', 'froakie').learnset.nightdaze = ['6E'];
                  this.modData('Learnsets', 'froakie').learnset.pursuit = ['6E'];

                  this.modData('Learnsets', 'chesnaught').learnset.powerwhip = ['6L100'];
                  this.modData('Learnsets', 'chesnaught').learnset.machpunch = ['6L100'];
                  this.modData('Learnsets', 'chespin').learnset.drainpunch = ['6E'];
                  this.modData('Learnsets', 'chesnaught').learnset.icepunch = ['6L100'];
                  this.modData('Learnsets', 'chesnaught').learnset.shadowpunch = ['6L100'];
                  this.modData('Learnsets', 'chesnaught').learnset.crosschop = ['6L100'];
                  this.modData('Learnsets', 'chespin').learnset.stealthrock = ['6E'];
                  this.modData('Learnsets', 'chespin').learnset.spikysheild = ['6E'];

                  this.modData('Learnsets', 'flabebe').learnset.perishsong = ['6E'];
                  this.modData('Learnsets', 'flabebe').learnset.recover = ['6E'];
                  this.modData('Learnsets', 'flabebe').learnset.quiverdance = ['6E'];
                  this.modData('Learnsets', 'flabebe').learnset.thunderwave = ['6L1'];
                  this.modData('Learnsets', 'florges').learnset.thunder = ['6M'];
                  this.modData('Learnsets', 'flabebe').learnset.trickroom = ['6E'];
                  this.modData('Learnsets', 'flabebe').learnset.sleeppowder = ['6E'];

                  this.modData('Learnsets', 'heliolisk').learnset.earthpower = ['6L100'];
                  this.modData('Learnsets', 'heliolisk').learnset.flamethrower = ['6M'];
                  this.modData('Learnsets', 'helioptile').learnset.earthpower = ['6E'];

                  this.modData('Learnsets', 'talonflame').learnset.superpower = ['6L100'];
                  this.modData('Learnsets', 'fletchling').learnset.flareblitz = ['6T'];
                  this.modData('Learnsets', 'fletchling').learnset.bravebird = ['6T'];

                  this.modData('Learnsets', 'vivillon').learnset.focusblast = ['6M'];
                  this.modData('Learnsets', 'vivillon').learnset.moonblast = ['6L100'];
                  this.modData('Learnsets', 'vivillon').learnset.dazzlinggleam = ['6M'];

                  this.modData('Learnsets', 'gogoat').learnset.swordsdance = ['6M'];

                  this.modData('Learnsets', 'pyroar').learnset.boomburst = ['6M'];

                  this.modData('Learnsets', 'pangoro').learnset.closecombat = ['6L100'];
                  this.modData('Learnsets', 'pangoro').learnset.pursuit = ['6L100'];
                  this.modData('Learnsets', 'pangoro').learnset.suckerpunch = ['6L100'];
                  this.modData('Learnsets', 'pangoro').learnset.drainpunch = ['6L100'];
                  this.modData('Learnsets', 'pangoro').learnset.icepunch = ['6L100'];
                  this.modData('Learnsets', 'pangoro').learnset.machpunch = ['6L100'];

                  this.modData('Learnsets', 'meowstic').learnset.willowisp = ['6L100'];
                  this.modData('Learnsets', 'meowstic').learnset.recover = ['6L100'];
                  this.modData('Learnsets', 'meowstic').learnset.nastyplot = ['6L100'];
                  this.modData('Learnsets', 'meowstic').learnset.aurasphere = ['6L100'];

                  this.modData('Learnsets', 'meowsticf').learnset.extremespeed = ['6L100'];
                  this.modData('Learnsets', 'meowsticf').learnset.triattack = ['6L100'];
                  this.modData('Learnsets', 'meowsticf').learnset.focusblast = ['6L100'];

                  this.modData('Learnsets', 'espurr').learnset.batonpass = ['6E'];

                  this.modData('Learnsets', 'honedge').learnset.kingssheild = ['6E'];
                  this.modData('Learnsets', 'honedge').learnset.stealthrock = ['6E'];
                  this.modData('Learnsets', 'honedge').learnset.bulletpunch = ['6E'];
                  this.modData('Learnsets', 'honedge').learnset.phantomforce = ['6E'];
                  this.modData('Learnsets', 'doublade').learnset.willowisp = ['6L100'];
                  this.modData('Learnsets', 'doublade').learnset.secretsword = ['6L100'];

                  this.modData('Learnsets', 'furfrou').learnset.milkdrink = ['6L100'];

                  this.modData('Learnsets', 'malamar').learnset.partingshot = ['6L100'];
                  this.modData('Learnsets', 'malamar').learnset.nightdaze = ['6L100'];
                  this.modData('Learnsets', 'malamar').learnset.focusblast = ['6M'];

                  this.modData('Learnsets', 'barbaracle').learnset.iceshard = ['6L100'];
                  this.modData('Learnsets', 'barbaracle').learnset.aquajet = ['6L100'];

                  this.modData('Learnsets', 'goodra').learnset.recover = ['6T'];
                  this.modData('Learnsets', 'goodra').learnset.aurasphere = ['6L100'];

                  this.modData('Learnsets', 'clawitzer').learnset.megahorn = ['6L100'];
                  this.modData('Learnsets', 'clawitzer').learnset.shellsmash = ['6L100'];
                  this.modData('Learnsets', 'clawitzer').learnset.bugbuzz = ['6L100'];
                  this.modData('Learnsets', 'clawitzer').learnset.xscissor = ['6L100'];

                  this.modData('Learnsets', 'dragalge').learnset.thunderwave = ['6M'];

                  this.modData('Learnsets', 'latias').learnset.moonblast = ['6L100'];
                  this.modData('Learnsets', 'latias').learnset.dazzlinggleam = ['6M'];
                  this.modData('Learnsets', 'latias').learnset.batonpass = ['6T'];

                  this.modData('Learnsets', 'garchomp').learnset.rockpolish = ['6M'];
                  this.modData('Learnsets', 'garchomp').learnset.crosschop = ['6L100'];

                  this.modData('Learnsets', 'regirock').learnset.recover = ['6L100'];

                  this.modData('Learnsets', 'registeel').learnset.recover = ['6L100'];

                  this.modData('Learnsets', 'regice').learnset.recover = ['6L100'];

                  this.modData('Learnsets', 'latios').learnset.uturn = ['6M'];

                  this.modData('Learnsets', 'flygon').learnset.quiverdance = ['6L100'];
                  this.modData('Learnsets', 'flygon').learnset.bulkup = ['6L100'];
                  this.modData('Learnsets', 'flygon').learnset.bugbuzz = ['6L100'];

                  this.modData('Learnsets', 'mew').learnset.playrough = ['6L100'];
                  this.modData('Learnsets', 'mew').learnset.moonblast = ['6L100'];
                  this.modData('Learnsets', 'mew').learnset.recover = ['6L100'];
                  this.modData('Learnsets', 'mew').learnset.psytrike = ['6L100'];

                  this.modData('Learnsets', 'celebi').learnset.playrough = ['6L100'];
                  this.modData('Learnsets', 'celebi').learnset.moonblast = ['6L100'];
                  this.modData('Learnsets', 'celebi').learnset.seedflare = ['6L100'];

                  this.modData('Learnsets', 'jirachi').learnset.playrough = ['6L100'];
                  this.modData('Learnsets', 'jirachi').learnset.moonblast = ['6L100'];
                  this.modData('Learnsets', 'jirachi').learnset.bulletpunch = ['6L100'];

                  this.modData('Learnsets', 'victini').learnset.playrough = ['6L100'];
                  this.modData('Learnsets', 'victini').learnset.moonblast = ['6L100'];

                  this.modData('Learnsets', 'manaphy').learnset.playrough = ['6L100'];
                  this.modData('Learnsets', 'manaphy').learnset.moonblast = ['6L100'];

                  this.modData('Learnsets', 'shaymin').learnset.boomburst = ['6L100'];

                  this.modData('Learnsets', 'meloetta').learnset.psytrike = ['6L100'];
                  this.modData('Learnsets', 'meloetta').learnset.boomburst = ['6L100'];
                  this.modData('Learnsets', 'meloetta').learnset.phantomforce = ['6L100'];
                  this.modData('Learnsets', 'meloetta').learnset.swordsdance = ['6M'];

                  this.modData('Learnsets', 'arceus').learnset.playrough = ['6L100'];
                  this.modData('Learnsets', 'arceus').learnset.moonblast = ['6L100'];

                  this.modData('Learnsets', 'bulbasaur').learnset.healorder = ['6E'];

                  this.modData('Learnsets', 'pinsir').learnset.megahorn = ['6L100'];

                  this.modData('Learnsets', 'scizor').learnset.megahorn = ['6L100'];

                  this.modData('Learnsets', 'heracross').learnset.icepunch = ['6100'];
                  this.modData('Learnsets', 'heracross').learnset.firepunch = ['6100'];
                  this.modData('Learnsets', 'heracross').learnset.thunderpunch = ['6L100'];

                  this.modData('Learnsets', 'gyarados').learnset.suckerpunch = ['6L100'];
                  this.modData('Learnsets', 'gyarados').learnset.crunch = ['6L100'];

                  this.modData('Learnsets', 'yveltal').learnset.bravebird = ['6L100'];
                  this.modData('Learnsets', 'yveltal').learnset.pursuit = ['6L100'];

                  this.modData('Learnsets', 'xerneas').learnset.grassknot = ['6L100'];
                  this.modData('Learnsets', 'xerneas').learnset.leafstorm = ['6L100'];
                  this.modData('Learnsets', 'xerneas').learnset.gigadrain = ['6M'];
                  this.modData('Learnsets', 'xerneas').learnset.recover = ['6T'];
                  //move tutors

                  //brave bird
                  this.modData('Learnsets', 'charizard').learnset.bravebird = ['6T'];
                  this.modData('Learnsets', 'landorus').learnset.bravebird = ['6T'];
                  this.modData('Learnsets', 'gliscor').learnset.bravebird = ['6T'];
                  this.modData('Learnsets', 'aerodactyl').learnset.bravebird = ['6T'];
                  this.modData('Learnsets', 'archeops').learnset.bravebird = ['6T'];
                  this.modData('Learnsets', 'scyther').learnset.bravebird = ['6T'];
                  this.modData('Learnsets', 'dragonite').learnset.bravebird = ['6T'];
                  this.modData('Learnsets', 'gyarados').learnset.bravebird = ['6T'];
                  this.modData('Learnsets', 'noivern').learnset.bravebird = ['6T'];
                  this.modData('Learnsets', 'rayquaza').learnset.bravebird = ['6T'];
                  this.modData('Learnsets', 'hawlucha').learnset.bravebird = ['6T'];

                  //CC
                  this.modData('Learnsets', 'pinsir').learnset.closecombat = ['6T'];
                  this.modData('Learnsets', 'chesnaught').learnset.closecombat = ['6T'];

                  //rapid spin
                  this.modData('Learnsets', 'chespin').learnset.rapidspin = ['6T'];
                  this.modData('Learnsets', 'shaymin').learnset.rapidspin = ['6T'];

                  //recover
                  this.modData('Learnsets', 'dragalge').learnset.recover = ['6T'];
};
<|endoftext|>


<commit_before>import { NodeComponent, Tooltip } from 'substance'
import { getColumnLabel } from './sheetHelpers'
const DEFAULT_COLUMN_WIDTH = 100

class SheetColumnHeader extends NodeComponent {
  didMount() {
    const cell = this.props.node
    cell.on('issue:changed', this.rerender, this)
  }

  dispose() {
    const cell = this.props.node
    cell.off(this)
  }

  render($$) {
    const colIdx = this.props.colIdx
    const node = this.props.node
    const issueManager = this.context.issueManager

    let th = $$('th')
      .attr('data-col', colIdx)
      .addClass('sc-column-header')

    let cellIssues = issueManager.getColumnIssues(node.id)
    if(cellIssues.length > 0) {
      th.addClass('sm-issue sm-error')
    }

    let columnHeader = $$('div').addClass('se-column-title').append(
      $$('div').addClass('se-column-label').text(getColumnLabel(colIdx)),
      this.renderColumnName($$),
      this.renderColumnType($$)
    )

    th.append(
      columnHeader
    ).css({ width: this.getWidth() })

    return th
  }

  getWidth() {
    return this.props.node.attr('width') || DEFAULT_COLUMN_WIDTH
  }

  renderIcon($$, icon) {
    let iconEl = this.context.iconProvider.renderIcon($$, icon)
    return iconEl
  }

  renderColumnName($$) {
    const node = this.props.node
    let name = node.attr('name')
    if (!name) return

    let el = $$('div').addClass('se-column-name')
      .text(String(name))

    return el
  }

  renderColumnType($$) {
    // TODO: here we should discuss how to deal with units
    // we could introduce an extra type for different units
    // but IMO it is semantically more appropriate to have units
    // for number types, such as km, ms, MW
    // In that case we could rather display the unit than the type
    // 'km' instead of number
    // alternatively, we could introduce an extra row with the units
    const node = this.props.node
    let coltype = node.attr('type')
    if(!coltype) return

    let el = $$('div').addClass('se-column-type').append(
      this.renderIcon($$, coltype + '-cell-type'),
      $$(Tooltip, {
        text: this.getLabel(coltype)
      })
    )

    return el
  }
}

export default SheetColumnHeader
<commit_msg>Fix header rerendering bug.<commit_after>import { NodeComponent, Tooltip } from 'substance'
import { getColumnLabel } from './sheetHelpers'
const DEFAULT_COLUMN_WIDTH = 100

class SheetColumnHeader extends NodeComponent {
  didMount() {
    super.didMount()
    const cell = this.props.node
    cell.on('issue:changed', this.rerender, this)
  }

  dispose() {
    super.dispose()
    const cell = this.props.node
    cell.off(this)
  }

  render($$) {
    const colIdx = this.props.colIdx
    const node = this.props.node
    const issueManager = this.context.issueManager

    let th = $$('th')
      .attr('data-col', colIdx)
      .addClass('sc-column-header')

    let cellIssues = issueManager.getColumnIssues(node.id)
    if(cellIssues.length > 0) {
      th.addClass('sm-issue sm-error')
    }

    let columnHeader = $$('div').addClass('se-column-title').append(
      $$('div').addClass('se-column-label').text(getColumnLabel(colIdx)),
      this.renderColumnName($$),
      this.renderColumnType($$)
    )

    th.append(
      columnHeader
    ).css({ width: this.getWidth() })

    return th
  }

  getWidth() {
    return this.props.node.attr('width') || DEFAULT_COLUMN_WIDTH
  }

  renderIcon($$, icon) {
    let iconEl = this.context.iconProvider.renderIcon($$, icon)
    return iconEl
  }

  renderColumnName($$) {
    const node = this.props.node
    let name = node.attr('name')
    if (!name) return

    let el = $$('div').addClass('se-column-name')
      .text(String(name))

    return el
  }

  renderColumnType($$) {
    // TODO: here we should discuss how to deal with units
    // we could introduce an extra type for different units
    // but IMO it is semantically more appropriate to have units
    // for number types, such as km, ms, MW
    // In that case we could rather display the unit than the type
    // 'km' instead of number
    // alternatively, we could introduce an extra row with the units
    const node = this.props.node
    let coltype = node.attr('type')
    if(!coltype) return

    let el = $$('div').addClass('se-column-type').append(
      this.renderIcon($$, coltype + '-cell-type'),
      $$(Tooltip, {
        text: this.getLabel(coltype)
      })
    )

    return el
  }
}

export default SheetColumnHeader
<|endoftext|>


<commit_before>import debugModule from "debug";
const debug = debugModule("debugger:solidity:selectors");

import { createSelectorTree, createLeaf } from "reselect-tree";
import SolidityUtils from "truffle-solidity-utils";
import CodeUtils from "truffle-code-utils";

import context from "lib/context/selectors";
import evm from "lib/evm/selectors";

let solidity = createSelectorTree({
  /**
   * solidity.current
   */
  current: {

    /**
     * solidity.current.functionDepth
     */
    functionDepth: (state) => state.solidity.functionDepth,

    /**
     * solidity.current.instructions
     */
    instructions: createLeaf(
      [context.current], (context) => {
        debug("context: %o", context);
        let instructions = CodeUtils.parseCode(context.binary);

        let sourceMap = context.sourceMap;
        if (!sourceMap) {
          // Let's create a source map to use since none exists. This source map
          // maps just as many ranges as there are instructions, and ensures every
          // instruction is marked as "jumping out". This will ensure all
          // available debugger commands step one instruction at a time.
          //
          // This is kindof a hack; perhaps this should be broken out into separate
          // context types. TODO
          sourceMap = "";
          for (var i = 0; i < instructions.length; i++) {
            sourceMap += i + ":" + i + ":1:o;";
          }
        }

        var lineAndColumnMapping = SolidityUtils.getCharacterOffsetToLineAndColumnMapping(context.source || "");
        var humanReadableSourceMap = SolidityUtils.getHumanReadableSourceMap(sourceMap);

        instructions.forEach(function(instruction, instructionIndex) {
          var sourceMapInstruction = humanReadableSourceMap[instructionIndex];

          instruction.index = instructionIndex;

          if (sourceMapInstruction) {
            instruction.jump = sourceMapInstruction.jump;
            instruction.start = sourceMapInstruction.start;
            instruction.length = sourceMapInstruction.length;
            instruction.range = {
              start: lineAndColumnMapping[sourceMapInstruction.start],
              end: lineAndColumnMapping[sourceMapInstruction.start + sourceMapInstruction.length]
            }
          }
        });
        debug("instructions: %O", instructions.filter((i) => i.jump != "-"));

        return instructions;
      }
    ),

    /**
     * solidity.current.instructionAtProgramCounter
     */
    instructionAtProgramCounter: createLeaf(
      ["./instructions"],

      (instructions) => {
        let map = [];
        instructions.forEach(function(instruction) {
          map[instruction.pc] = instruction;
        });
        return map;
      }
    )
  },

  /**
   * solidity.next
   */
  next: {

    /**
     * solidity.next.instruction
     */
    instruction: createLeaf(
      ["../current/instructionAtProgramCounter", evm.next.step.programCounter],

      (map, pc) => map[pc]
    ),

    /**
     * solidity.next.sourceRange
     */
    sourceRange: createLeaf(
      ["./instruction"],

      (instruction) => {
        return {
          start: instruction.start,
          length: instruction.length,
          lines: instruction.range
        };
      }
    ),

    /**
     * solidity.next.isMultiline
     */
    isMultiline: createLeaf(
      ["./sourceRange"],

      ( {lines} ) => lines.start.line != lines.end.line
    ),

    /**
     * solidity.next.willJump
     */
    willJump: createLeaf([evm.next.step.isJump], (isJump) => isJump),

    /**
     * solidity.next.jumpDirection
     */
    jumpDirection: createLeaf(
      ["./instruction"], (i) => i.jump
    )
  }
});

export default solidity;
<commit_msg>Include file index in instructions table<commit_after>import debugModule from "debug";
const debug = debugModule("debugger:solidity:selectors");

import { createSelectorTree, createLeaf } from "reselect-tree";
import SolidityUtils from "truffle-solidity-utils";
import CodeUtils from "truffle-code-utils";

import context from "lib/context/selectors";
import evm from "lib/evm/selectors";

let solidity = createSelectorTree({
  /**
   * solidity.current
   */
  current: {

    /**
     * solidity.current.functionDepth
     */
    functionDepth: (state) => state.solidity.functionDepth,

    /**
     * solidity.current.instructions
     */
    instructions: createLeaf(
      [context.current], (context) => {
        debug("context: %o", context);
        let instructions = CodeUtils.parseCode(context.binary);

        let sourceMap = context.sourceMap;
        if (!sourceMap) {
          // Let's create a source map to use since none exists. This source map
          // maps just as many ranges as there are instructions, and ensures every
          // instruction is marked as "jumping out". This will ensure all
          // available debugger commands step one instruction at a time.
          //
          // This is kindof a hack; perhaps this should be broken out into separate
          // context types. TODO
          sourceMap = "";
          for (var i = 0; i < instructions.length; i++) {
            sourceMap += i + ":" + i + ":1:o;";
          }
        }

        var lineAndColumnMapping = SolidityUtils.getCharacterOffsetToLineAndColumnMapping(context.source || "");
        var humanReadableSourceMap = SolidityUtils.getHumanReadableSourceMap(sourceMap);

        instructions.forEach(function(instruction, instructionIndex) {
          var sourceMapInstruction = humanReadableSourceMap[instructionIndex];

          instruction.index = instructionIndex;

          if (sourceMapInstruction) {
            instruction.jump = sourceMapInstruction.jump;
            instruction.start = sourceMapInstruction.start;
            instruction.length = sourceMapInstruction.length;
            instruction.file = sourceMapInstruction.file;
            instruction.range = {
              start: lineAndColumnMapping[sourceMapInstruction.start],
              end: lineAndColumnMapping[sourceMapInstruction.start + sourceMapInstruction.length]
            }
          }
        });
        debug("instructions: %O", instructions.filter((i) => i.jump != "-"));

        return instructions;
      }
    ),

    /**
     * solidity.current.instructionAtProgramCounter
     */
    instructionAtProgramCounter: createLeaf(
      ["./instructions"],

      (instructions) => {
        let map = [];
        instructions.forEach(function(instruction) {
          map[instruction.pc] = instruction;
        });
        return map;
      }
    )
  },

  /**
   * solidity.next
   */
  next: {

    /**
     * solidity.next.instruction
     */
    instruction: createLeaf(
      ["../current/instructionAtProgramCounter", evm.next.step.programCounter],

      (map, pc) => map[pc]
    ),

    /**
     * solidity.next.sourceRange
     */
    sourceRange: createLeaf(
      ["./instruction"],

      (instruction) => {
        return {
          start: instruction.start,
          length: instruction.length,
          lines: instruction.range
        };
      }
    ),

    /**
     * solidity.next.isMultiline
     */
    isMultiline: createLeaf(
      ["./sourceRange"],

      ( {lines} ) => lines.start.line != lines.end.line
    ),

    /**
     * solidity.next.willJump
     */
    willJump: createLeaf([evm.next.step.isJump], (isJump) => isJump),

    /**
     * solidity.next.jumpDirection
     */
    jumpDirection: createLeaf(
      ["./instruction"], (i) => i.jump
    )
  }
});

export default solidity;
<|endoftext|>


<commit_before>/* eslint-disable global-require */

module.exports = function createOpts(
  env,
  react,
  { presets: otherPresets, plugins: otherPlugins } = {}
) {
  const production = !env.endsWith('-dev');

  if (!production) {
    env = env.slice(0, -4);
  }

  if (env === 'doc') {
    return {
      presets: [
        'jsdoc',
        react && 'babel-preset-pob-react',
        require.resolve('babel-preset-stage-1'),
      ].filter(Boolean),
      plugins: [
        'add-jsdoc-annotations',
        require.resolve('babel-plugin-transform-flow-strip-types'),
      ],
    };
  }

  let transpilationPreset;
  let browser;

  switch (env) {
    case 'es5':
      throw new Error('use olderNode instead.');

    case 'node7':
      transpilationPreset = ['latest-node', { target: 7.6 }];
      browser = false;
      break;

    case 'node6':
      transpilationPreset = ['latest-node', { target: 6.5 }];
      browser = false;
      break;

    case 'older-node':
      transpilationPreset = 'latest';
      browser = false;
      break;

    case 'webpack-node7':
      transpilationPreset = ['latest-node', { target: 7.6, modules: false }];
      browser = false;
      break;

    case 'webpack':
      transpilationPreset = ['latest', { es2015: { modules: false } }];
      browser = true;
      break;

    case 'webpack-modern-browsers':
      transpilationPreset = ['modern-browsers', { modules: false }];
      browser = true;
      break;

    case 'browsers':
      transpilationPreset = 'latest';
      browser = true;
      break;

    default:
      throw new Error(`Unsupported env ${env}`);
  }

  return {
    // preset order is last to first, so we reverse it for clarity.
    presets: [
      // add react preset with jsx
      react && ['babel-preset-pob-react', { production }],
      // add stage-1 to stage-3 features
      require.resolve('babel-preset-pob-stages'),
      // pob preset: flow, import `src`, export default function name, replacements
      [require.resolve('babel-preset-pob'), {
        production,
        replacements: {
          BROWSER: browser,
          NODEJS: !browser,
          SERVER: !browser,
        },
      }],
      // optimizations: remove dead-code
      require.resolve('babel-preset-babili-optimizations'),
      // discard unused imports (like production-only or node-only imports)
      { plugins: [require.resolve('babel-plugin-discard-module-references')] },
      // transpile for specified target
      transpilationPreset,
    ].reverse().concat(otherPresets || []).filter(Boolean),
    plugins: (otherPlugins || []).filter(Boolean),
  };
};
<commit_msg>feat: module<commit_after>/* eslint-disable global-require */

module.exports = function createOpts(
  env,
  react,
  { presets: otherPresets, plugins: otherPlugins } = {}
) {
  const production = !env.endsWith('-dev');

  if (!production) {
    env = env.slice(0, -4);
  }

  if (env === 'doc') {
    return {
      presets: [
        'jsdoc',
        react && 'babel-preset-pob-react',
        require.resolve('babel-preset-stage-1'),
      ].filter(Boolean),
      plugins: [
        'add-jsdoc-annotations',
        require.resolve('babel-plugin-transform-flow-strip-types'),
      ],
    };
  }

  let transpilationPreset;
  let browser;

  switch (env) {
    case 'es5':
      throw new Error('use olderNode instead.');

    case 'node7':
      transpilationPreset = ['latest-node', { target: 7.6 }];
      browser = false;
      break;

    case 'node6':
      transpilationPreset = ['latest-node', { target: 6.5 }];
      browser = false;
      break;

    case 'older-node':
      transpilationPreset = 'latest';
      browser = false;
      break;

    case 'module-node7':
    case 'webpack-node7':
      transpilationPreset = ['latest-node', { target: 7.6, modules: false }];
      browser = false;
      break;

    case 'module':
    case 'webpack':
      transpilationPreset = ['latest', { es2015: { modules: false } }];
      browser = true;
      break;

    case 'module-modern-browsers':
    case 'webpack-modern-browsers':
      transpilationPreset = ['modern-browsers', { modules: false }];
      browser = true;
      break;

    case 'browsers':
      transpilationPreset = 'latest';
      browser = true;
      break;

    default:
      throw new Error(`Unsupported env ${env}`);
  }

  return {
    // preset order is last to first, so we reverse it for clarity.
    presets: [
      // add react preset with jsx
      react && ['babel-preset-pob-react', { production }],
      // add stage-1 to stage-3 features
      require.resolve('babel-preset-pob-stages'),
      // pob preset: flow, import `src`, export default function name, replacements
      [require.resolve('babel-preset-pob'), {
        production,
        replacements: {
          BROWSER: browser,
          NODEJS: !browser,
          SERVER: !browser,
        },
      }],
      // optimizations: remove dead-code
      require.resolve('babel-preset-babili-optimizations'),
      // discard unused imports (like production-only or node-only imports)
      { plugins: [require.resolve('babel-plugin-discard-module-references')] },
      // transpile for specified target
      transpilationPreset,
    ].reverse().concat(otherPresets || []).filter(Boolean),
    plugins: (otherPlugins || []).filter(Boolean),
  };
};
<|endoftext|>


<commit_before>// *************************************************************************
// Copyright (c) 2014-2017, SUSE LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// 3. Neither the name of SUSE LLC nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
// *************************************************************************
//
// stack.js -- stack enabling targets (dialogs) to be "push"ed and "pop"ped
//
// To initiate a new target (dialog), call stack.push(target)
//
// To return to the previous target (dialog), call stack.pop()
//
// Each target type (dmenu, dform, etc.) needs to have methods for saving
// and restoring the target state. These can range from very simple (dmenu)
// to complicated (dbrowser).
//
"use strict";

define ([
    "jquery",
    "lib",
    "prototypes",
    "target"
], function (
    $,
    lib,
    prototypes,
    target
) {

    var
        // object for storing the stack
        _stack = [],

        // pop a target and its state off the stack
        // ARG1 (optional) - object to be merged into stateObj
        // ARG2 (optional) - boolean, whether to call start() (default: true)
        pop = function (newState, opts) {
            console.log("Entering stack.pop() with new state", newState, "and opts", opts);
            var resultLine,
                stackState,
                stackTarget,
                stackLength;

            opts = lib.objectify(opts);
            opts['logout'] = ('logout' in opts) ? opts.logout : false;
            opts['inputId'] = ('inputId' in opts) ? opts.inputId : null;
            opts['resultLine'] = ('resultLine' in opts) ? opts.resultLine : "&nbsp";
            opts['_start'] = ('_start' in opts) ? opts._start : true;
            opts['_restart'] = ('_restart' in opts) ? opts._restart : false;
            opts['_start'] = opts._restart ? true : opts._start;
            console.log("stack.pop() adjusted opts", opts);

            stackLength = getLength();

            if (stackLength === 1) {
                if (opts.logout) {
                    target.pull('logout').start();
                    return;
                } else {
                    console.log("Refusing to pop last remaining item off the stack");
                    return
                }
            }

            // pop item off the stack, unless called by stack.restart()
            if (opts._restart) {
                console.log("Restarting stack top item.");
            } else {
                _stack.pop();
                console.log("Stack top item popped off and discarded.");
            }
            stackTarget = getTarget();
            stackState = getState();
            console.log("Now, the stack length is " + stackLength +
                        " and the top target is " + stackTarget.name +
                        " and its state is", stackState);
            if (newState && typeof newState === 'object') {
                $.extend(stackState, newState);
                setState(stackState);
            }
            setPush(false);
            if (opts._start) {
                delete opts["_start"];
                delete opts["_restart"];
                stackTarget.start(newState, opts);
            }
        },

        popWithoutStart = function (newState, opts) {
            opts = lib.objectify(opts);
            opts['_start'] = false;
            opts['_restart'] = false;
            pop(newState, opts);
        },

        // push a target and its state onto the stack
        push = function (tgt, obj, opts) {
            console.log("Entering stack.push() with target", tgt, "object", obj, "and opts", opts);
            // console.log("and stack", _stack);
            var flag,
                resultLine,
                xtarget;
            obj = lib.objectify(obj);
            opts = lib.objectify(opts);
            if (typeof tgt === "string") {
                tgt = target.pull(tgt);
            }
            if (typeof tgt !== "object") {
                console.log("ERROR in stack.push() - found no target object");
                return;
            }
            opts['flag'] = ('flag' in opts) ? opts.flag : false;
            opts['xtarget'] = ('xtarget' in opts) ? opts.xtarget : null;
            opts['resultLine'] = ('resultLine' in opts) ? opts.resultLine : null;
            opts['_start'] = ('_start' in opts) ? opts._start : true;
            console.log("stack.push() adjusted opts", opts);
            if (tgt.pushable) {
                _stack.push({
                    "flag": opts.flag,
                    "opts": opts,
                    "push": true,
                    "resultLine": opts.resultLine,
                    "state": obj,
                    "target": tgt,
                    "xtarget": opts.xtarget
                });
            }
            if (opts._start) {
                tgt.start(obj);
            }
        },

        pushWithoutStart = function (newState, opts) {
            if (typeof opts !== 'object') {
                opts = {};
            }
            opts['_start'] = false;
            push(newState, opts);
        },

        restart = function (newState, opts) {
            // does the exact same thing as pop, except it leaves the top
            // item on the stack and restarts it with new state and opts
            if (typeof opts !== 'object') {
                opts = {};
            }
            opts["_start"] = true;
            opts["_restart"] = true;
            pop(newState, opts);
        },

        getFlag = function () {
            return _stack[_stack.length - 1].flag;
        },
        getLength = function () {
            return _stack.length;
        },
        getOpts = function () {
            return _stack[_stack.length - 1].opts;
        },
        getPush = function () {
            return _stack[_stack.length - 1].push;
        },
        getResultLine = function () {
            return _stack[_stack.length - 1].resultLine;
        },
        getStack = function () {
            // returns the entire stack
            return _stack;
        },
        getState = function (offset) {
            // offset -1 for target under top target
            // offset -2 for two targets down, etc.
            if (offset === undefined) {
                offset = 0;
            }
            if (_stack.length === 0) {
                console.log("Ignoring attempt to get target from empty stack");
                return null;
            }
            return _stack[_stack.length - 1].state;
        },
        getTarget = function (offset) {
            // offset -1 for target under top target
            // offset -2 for two targets down, etc.
            if (offset === undefined) {
                offset = 0;
            }
            if (_stack.length === 0) {
                console.log("Ignoring attempt to get target from empty stack");
                return null;
            }
            return _stack[_stack.length + offset - 1].target;
        },
        getXTarget = function () {
            return _stack[_stack.length - 1].xtarget;
        },

        resetStack = function () {
            console.log("Resetting the stack");
            _stack = [];
        },

        setFlag = function () {
            _stack[_stack.length - 1].flag = true;
        },
        setPush = function (newPush) {
            _stack[_stack.length - 1].push = newPush;
        },
        setState = function (newState) {
            _stack[_stack.length - 1].state = newState;
        },
        setTarget = function (newTarget) {
            _stack[_stack.length - 1].target = newTarget;
        },
        setXTarget = function (newXTarget) {
            _stack[_stack.length - 1].xtarget = newXTarget;
        },

        unsetFlag = function () {
            _stack[_stack.length - 1].flag = false;
        },
        unsetPush = function () {
            _stack[_stack.length - 1].push = undefined;
        },
        unsetState = function () {
            _stack[_stack.length - 1].state = undefined;
        },
        unsetTarget = function () {
            _stack[_stack.length - 1].target = undefined;
        },
        unsetXTarget = function () {
            _stack[_stack.length - 1].xtarget = undefined;
        },

        // unwind stack until given target is reached
        // optional object to pass to start()
        unwindToTarget = function (tname, newObj, opts) {
            var i, tgt;
            console.log("Unwinding the stack to target " + tname);
            for (i = _stack.length; i > 0; i -= 1) {
                tgt = _stack[i - 1].target;
                if (tgt.name === tname) {
                   break;
                }
                popWithoutStart(newObj, opts);
            }
            tgt.start(newObj, opts);
        },

        unwindToFlag = function () {
            console.log("Unwinding the stack to flag");
            var flag, i;
            for (i = _stack.length; i > 0; i -= 1) {
                flag = _stack[i - 1].flag;
                if (flag) {
                   break;
                }
                popWithoutStart();
            }
            _stack[_stack.length - 1].target.start();
        },

        unwindToType = function (targetType) {
            var i, tgt;
            console.log("Unwinding stack to nearest target of type " + targetType);
            for (i = _stack.length; i > 0; i -= 1) {
                tgt = _stack[i - 1].target;
                if (tgt.type === targetType) {
                   break;
                }
                popWithoutStart();
            }
            tgt.start();
        },

        // grep stack for a target name (exact match)
        grep = function (tname) {
            var i, retval = false;
            for (i = 0; i < _stack.length; i += 1) {
                if (_stack[i].target.name === tname) {
                    return true;
                }
            }
            return false;
        };

    return {
        "getFlag": getFlag,
        "getLength": getLength,
        "getPush": getPush,
        "getResultLine": getResultLine,
        "getStack": getStack,
        "getState": getState,
        "getTarget": getTarget,
        "getXTarget": getXTarget,
        "grep": grep,
        "pop": pop,
        "popWithoutStart": popWithoutStart,
        "push": push,
        "pushWithoutStart": popWithoutStart,
        "resetStack": resetStack,
        "restart" : restart,
        "setFlag": setFlag,
        "setPush": setPush,
        "setState": setState,
        "setTarget": setTarget,
        "setXTarget": setXTarget,
        "unsetFlag": unsetFlag,
        "unsetPush": unsetPush,
        "unsetState": unsetState,
        "unsetTarget": unsetTarget,
        "unsetXTarget": unsetXTarget,
        "unwindToFlag": unwindToFlag,
        "unwindToTarget": unwindToTarget,
        "unwindToType": unwindToType,
    };

});
<commit_msg>js: core/stack: make unwindTo{Flag,Target} handle opts and respect _start<commit_after>// *************************************************************************
// Copyright (c) 2014-2017, SUSE LLC
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// 3. Neither the name of SUSE LLC nor the names of its contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
// *************************************************************************
//
// stack.js -- stack enabling targets (dialogs) to be "push"ed and "pop"ped
//
// To initiate a new target (dialog), call stack.push(target)
//
// To return to the previous target (dialog), call stack.pop()
//
// Each target type (dmenu, dform, etc.) needs to have methods for saving
// and restoring the target state. These can range from very simple (dmenu)
// to complicated (dbrowser).
//
"use strict";

define ([
    "jquery",
    "lib",
    "prototypes",
    "target"
], function (
    $,
    lib,
    prototypes,
    target
) {

    var
        // object for storing the stack
        _stack = [],

        // pop a target and its state off the stack
        // ARG1 (optional) - object to be merged into stateObj
        // ARG2 (optional) - boolean, whether to call start() (default: true)
        pop = function (newState, opts) {
            console.log("Entering stack.pop() with new state", newState, "and opts", opts);
            var resultLine,
                stackState,
                stackTarget,
                stackLength;

            opts = lib.objectify(opts);
            opts['logout'] = ('logout' in opts) ? opts.logout : false;
            opts['inputId'] = ('inputId' in opts) ? opts.inputId : null;
            opts['resultLine'] = ('resultLine' in opts) ? opts.resultLine : "&nbsp";
            opts['_start'] = ('_start' in opts) ? opts._start : true;
            opts['_restart'] = ('_restart' in opts) ? opts._restart : false;
            opts['_start'] = opts._restart ? true : opts._start;
            console.log("stack.pop() adjusted opts", opts);

            stackLength = getLength();

            if (stackLength === 1) {
                if (opts.logout) {
                    target.pull('logout').start();
                    return;
                } else {
                    console.log("Refusing to pop last remaining item off the stack");
                    return
                }
            }

            // pop item off the stack, unless called by stack.restart()
            if (opts._restart) {
                console.log("Restarting stack top item.");
            } else {
                _stack.pop();
                console.log("Stack top item popped off and discarded.");
            }
            stackTarget = getTarget();
            stackState = getState();
            console.log("Now, the stack length is " + stackLength +
                        " and the top target is " + stackTarget.name +
                        " and its state is", stackState);
            if (newState && typeof newState === 'object') {
                $.extend(stackState, newState);
                setState(stackState);
            }
            setPush(false);
            if (opts._start) {
                delete opts["_start"];
                delete opts["_restart"];
                stackTarget.start(newState, opts);
            }
        },

        popWithoutStart = function (newState, opts) {
            opts = lib.objectify(opts);
            opts['_start'] = false;
            opts['_restart'] = false;
            pop(newState, opts);
        },

        // push a target and its state onto the stack
        push = function (tgt, obj, opts) {
            console.log("Entering stack.push() with target", tgt, "object", obj, "and opts", opts);
            // console.log("and stack", _stack);
            var flag,
                resultLine,
                xtarget;
            obj = lib.objectify(obj);
            opts = lib.objectify(opts);
            if (typeof tgt === "string") {
                tgt = target.pull(tgt);
            }
            if (typeof tgt !== "object") {
                console.log("ERROR in stack.push() - found no target object");
                return;
            }
            opts['flag'] = ('flag' in opts) ? opts.flag : false;
            opts['xtarget'] = ('xtarget' in opts) ? opts.xtarget : null;
            opts['resultLine'] = ('resultLine' in opts) ? opts.resultLine : null;
            opts['_start'] = ('_start' in opts) ? opts._start : true;
            console.log("stack.push() adjusted opts", opts);
            if (tgt.pushable) {
                _stack.push({
                    "flag": opts.flag,
                    "opts": opts,
                    "push": true,
                    "resultLine": opts.resultLine,
                    "state": obj,
                    "target": tgt,
                    "xtarget": opts.xtarget
                });
            }
            if (opts._start) {
                tgt.start(obj);
            }
        },

        pushWithoutStart = function (newState, opts) {
            if (typeof opts !== 'object') {
                opts = {};
            }
            opts['_start'] = false;
            push(newState, opts);
        },

        restart = function (newState, opts) {
            // does the exact same thing as pop, except it leaves the top
            // item on the stack and restarts it with new state and opts
            if (typeof opts !== 'object') {
                opts = {};
            }
            opts["_start"] = true;
            opts["_restart"] = true;
            pop(newState, opts);
        },

        getFlag = function () {
            return _stack[_stack.length - 1].flag;
        },
        getLength = function () {
            return _stack.length;
        },
        getOpts = function () {
            return _stack[_stack.length - 1].opts;
        },
        getPush = function () {
            return _stack[_stack.length - 1].push;
        },
        getResultLine = function () {
            return _stack[_stack.length - 1].resultLine;
        },
        getStack = function () {
            // returns the entire stack
            return _stack;
        },
        getState = function (offset) {
            // offset -1 for target under top target
            // offset -2 for two targets down, etc.
            if (offset === undefined) {
                offset = 0;
            }
            if (_stack.length === 0) {
                console.log("Ignoring attempt to get target from empty stack");
                return null;
            }
            return _stack[_stack.length - 1].state;
        },
        getTarget = function (offset) {
            // offset -1 for target under top target
            // offset -2 for two targets down, etc.
            if (offset === undefined) {
                offset = 0;
            }
            if (_stack.length === 0) {
                console.log("Ignoring attempt to get target from empty stack");
                return null;
            }
            return _stack[_stack.length + offset - 1].target;
        },
        getXTarget = function () {
            return _stack[_stack.length - 1].xtarget;
        },

        resetStack = function () {
            console.log("Resetting the stack");
            _stack = [];
        },

        setFlag = function () {
            _stack[_stack.length - 1].flag = true;
        },
        setPush = function (newPush) {
            _stack[_stack.length - 1].push = newPush;
        },
        setState = function (newState) {
            _stack[_stack.length - 1].state = newState;
        },
        setTarget = function (newTarget) {
            _stack[_stack.length - 1].target = newTarget;
        },
        setXTarget = function (newXTarget) {
            _stack[_stack.length - 1].xtarget = newXTarget;
        },

        unsetFlag = function () {
            _stack[_stack.length - 1].flag = false;
        },
        unsetPush = function () {
            _stack[_stack.length - 1].push = undefined;
        },
        unsetState = function () {
            _stack[_stack.length - 1].state = undefined;
        },
        unsetTarget = function () {
            _stack[_stack.length - 1].target = undefined;
        },
        unsetXTarget = function () {
            _stack[_stack.length - 1].xtarget = undefined;
        },

        // unwind stack until given target is reached
        // optional object to pass to start()
        unwindToTarget = function (tname, newObj, opts) {
            var i, tgt;
            console.log("Unwinding the stack to target " + tname);
            for (i = _stack.length; i > 0; i -= 1) {
                tgt = _stack[i - 1].target;
                console.log("Does " + tgt.name + " equal " + tname + " ?");
                if (tgt.name === tname) {
                   break;
                }
                popWithoutStart(newObj, opts);
            }
            tgt.start(newObj, opts);
        },

        unwindToFlag = function (newObj, opts) {
            console.log("Unwinding the stack to flag");
            var flag, i;
            if (typeof opts !== 'object' || opts === null) {
                opts = {};
            }
            opts['_start'] = ('_start' in opts) ? opts._start : true;
            for (i = _stack.length; i > 0; i -= 1) {
                flag = _stack[i - 1].flag;
                if (flag) {
                   break;
                }
                popWithoutStart(newObj, opts);
            }
            if (opts._start) {
                _stack[_stack.length - 1].target.start();
            }
        },

        unwindToType = function (targetType, opts) {
            var i, tgt;
            console.log("Unwinding stack to nearest target of type " + targetType);
            if (typeof opts !== 'object' || opts === null) {
                opts = {};
            }
            opts['_start'] = ('_start' in opts) ? opts._start : true;
            for (i = _stack.length; i > 0; i -= 1) {
                tgt = _stack[i - 1].target;
                if (tgt.type === targetType) {
                   break;
                }
                popWithoutStart();
            }
            if (opts._start) {
                tgt.start();
            }
        },

        // grep stack for a target name (exact match)
        grep = function (tname) {
            var i, retval = false;
            console.log("Grepping stack for " + tname);
            for (i = 0; i < _stack.length; i += 1) {
                console.log("Does " + _stack[i].target.name + " equal " + tname + " ?");
                if (_stack[i].target.name === tname) {
                    return true;
                }
            }
            return false;
        };

    return {
        "getFlag": getFlag,
        "getLength": getLength,
        "getOpts": getOpts,
        "getPush": getPush,
        "getResultLine": getResultLine,
        "getStack": getStack,
        "getState": getState,
        "getTarget": getTarget,
        "getXTarget": getXTarget,
        "grep": grep,
        "pop": pop,
        "popWithoutStart": popWithoutStart,
        "push": push,
        "pushWithoutStart": popWithoutStart,
        "resetStack": resetStack,
        "restart" : restart,
        "setFlag": setFlag,
        "setPush": setPush,
        "setState": setState,
        "setTarget": setTarget,
        "setXTarget": setXTarget,
        "unsetFlag": unsetFlag,
        "unsetPush": unsetPush,
        "unsetState": unsetState,
        "unsetTarget": unsetTarget,
        "unsetXTarget": unsetXTarget,
        "unwindToFlag": unwindToFlag,
        "unwindToTarget": unwindToTarget,
        "unwindToType": unwindToType,
    };

});
<|endoftext|>


<commit_before>'use strict';

/*

    Exceptions

*/

function AdapterRegistryException(message, context) {
   this.message = message;
   this.name = "AdapterRegistryException";
   this.context = context;
   console.error(context);
}

/*

    Adapter Registry Code

*/

var AdapterRegistry = function () {
    this.adapters = {};
}

AdapterRegistry.prototype.registerAdapter = function (adapter) {
    /*
        Add an adapter to the registry

        adapts -- interface or object prototype that the adapter decorates
        implementsInterface -- the interface that the adapter implements
        adapter -- the prototype of the adapter to instantiate on get
    */
    var adapts = adapter.prototype._adapts,
        implementsInterfaces = adapter.prototype._implements;

    // TODO: Check that the adapter implements the interface
    // TODO: else throw InterfaceNotImplementedError

    // INTEGRITY CHECK: Have we specified what the adapter implements?
    if (!implementsInterfaces || !implementsInterfaces[0].interfaceId) {
        throw new AdapterRegistryException(
            "Registration error: You haven't specified interface that this adapter implements",
            {
                adapter: adapter
            }
        )
    }

    // Register the adapter (interfaces are stored in a list)
    var tmpInterfaceId = implementsInterfaces[0].interfaceId;
    if (typeof this.adapters[tmpInterfaceId] === 'undefined') {
        this.adapters[tmpInterfaceId] = {
            implementsInterface: implementsInterfaces[0],
            interfaceAdapters: [],
            objectAdapters: []
        }
    }

    // INTEGRITY CHECK: Have we specified what the adapter has specified what it adapts?
    if (!adapts) {
        throw new AdapterRegistryException(
            "Registration error: You haven't specified interface or object that this adapter adapts",
            {
                adapter: adapter
            }
        )
    }

    var adapters = this.adapters[tmpInterfaceId];

    if (adapts.interfaceId) {
        // This should be registered as an interface
        adapters.interfaceAdapters.push({
            adapts: adapts,
            adapter: adapter
        });
    } else {
        // This should be registered as an object adaptor
        adapters.objectAdapters.push({
            adapts: adapts,
            adapter: adapter
        });

    }
}

// TODO: implement hasAdapter (returns true or false), look at getAdapter

AdapterRegistry.prototype.getAdapter = function (obj, implementsInterface) {
    /*
        Return an instance of an adapter for the provided object which implements
        the provided interface.
    */
    var adapters = this.adapters[implementsInterface.interfaceId];

    if (adapters) {
        // First check if an object adapter matches
        for (var i = 0, imax = adapters.objectAdapters.length; i < imax; i++) {
            var tmp = adapters.objectAdapters[i];
            // TODO: THIS IS A NOOP right now, there is no interfaceId-property on objects unless they are interfaces
            if (obj.interfaceId === tmp.adapts.interfaceId) {
                // Found the adapter, instansiate and return (adapter should set obj as context on creation)
                var outp = new tmp.adapter(obj);
                return outp;
            }

        }
        // Then check if an interface adapter matches, iterate over each interface implemented by the
        // passed object to find the first match.

        // INTEGRITY CHECK: Throw a useful error if the passed object doesn't have _implements
        if (!(obj._implements && obj._implements.length > 0)) {
            throw new AdapterRegistryException(
                "Context (first param) doesn't have any _implements property, and thus no interfaces to use for look up",
                {
                    context: obj,
                    implements: implementsInterface,
                    registry: this
                }
            )
        };

        // TODO: Should investigate inheritance and overriding here, the use case is that you want to override
        // adapters registered on a general interface in a component with that registered in an application. I
        // need to think about how this works and write the docs first, then tests and then implement it so it
        // is easy to understand and reason about.
        for (var j = 0, jmax = obj._implements.length; j < jmax; j++) {
            var tmpInterface = obj._implements[j];
            for (var i = 0, imax = adapters.interfaceAdapters.length; i < imax; i++) {
                var tmp = adapters.interfaceAdapters[i];
                if (tmpInterface.interfaceId === tmp.adapts.interfaceId) {
                    // Found the adapter, instansiate and return (adapter should set obj as context on creation)
                    var outp = new tmp.adapter(obj);
                    return outp;
                }

            }
        }
    };

    // TODO: Figure out how to throw nice custom errors
    // If we get this far, throws error if no adapter is found
    var adaptsInterfaces = adapters.interfaceAdapters.map(function (adapter) {
        return "[" + adapter.adapts.name + "] " + adapter.adapts.interfaceId;
    });
    var contextInterfaces = obj._implements.map(function (intrfc) {
        return "[" + intrfc.name + "] " + intrfc.interfaceId;
    })

    var message = "No adapter found that was registered for specified object\n "
        + "implements: [" + implementsInterface.name + "] " + implementsInterface.interfaceId + "\n"
        + "adapts: " +  adaptsInterfaces + "\n"
        + "context: " + contextInterfaces;
    console.error(message);
    throw new AdapterRegistryException(
        message,
        {
            context: obj,
            implements: implementsInterface,
            adaptsInterfaces: adapters.interfaceAdapters,
            registry: this
        }
    );
}

module.exports = AdapterRegistry;<commit_msg>Improved error formatting<commit_after>'use strict';

/*

    Exceptions

*/

function AdapterRegistryException(message, context) {
   this.message = message;
   this.name = "AdapterRegistryException";
   this.context = context;
   console.error(context);
}

/*

    Adapter Registry Code

*/

var AdapterRegistry = function () {
    this.adapters = {};
}

AdapterRegistry.prototype.registerAdapter = function (adapter) {
    /*
        Add an adapter to the registry

        adapts -- interface or object prototype that the adapter decorates
        implementsInterface -- the interface that the adapter implements
        adapter -- the prototype of the adapter to instantiate on get
    */
    var adapts = adapter.prototype._adapts,
        implementsInterfaces = adapter.prototype._implements;

    // TODO: Check that the adapter implements the interface
    // TODO: else throw InterfaceNotImplementedError

    // INTEGRITY CHECK: Have we specified what the adapter implements?
    if (!implementsInterfaces || !implementsInterfaces[0].interfaceId) {
        throw new AdapterRegistryException(
            "Registration error: You haven't specified interface that this adapter implements",
            {
                adapter: adapter
            }
        )
    }

    // Register the adapter (interfaces are stored in a list)
    var tmpInterfaceId = implementsInterfaces[0].interfaceId;
    if (typeof this.adapters[tmpInterfaceId] === 'undefined') {
        this.adapters[tmpInterfaceId] = {
            implementsInterface: implementsInterfaces[0],
            interfaceAdapters: [],
            objectAdapters: []
        }
    }

    // INTEGRITY CHECK: Have we specified what the adapter has specified what it adapts?
    if (!adapts) {
        throw new AdapterRegistryException(
            "Registration error: You haven't specified interface or object that this adapter adapts",
            {
                adapter: adapter
            }
        )
    }

    var adapters = this.adapters[tmpInterfaceId];

    if (adapts.interfaceId) {
        // This should be registered as an interface
        adapters.interfaceAdapters.push({
            adapts: adapts,
            adapter: adapter
        });
    } else {
        // This should be registered as an object adaptor
        adapters.objectAdapters.push({
            adapts: adapts,
            adapter: adapter
        });

    }
}

// TODO: implement hasAdapter (returns true or false), look at getAdapter

AdapterRegistry.prototype.getAdapter = function (obj, implementsInterface) {
    /*
        Return an instance of an adapter for the provided object which implements
        the provided interface.
    */
    var adapters = this.adapters[implementsInterface.interfaceId];

    // if we didn't find an adapter for this we throw an error
    if (typeof adapters === 'undefined') {
        var message = "No registered adapter(s) found for: " + implementsInterface.name;
        throw new AdapterRegistryException(message, obj);
    }

    // Ok so we found adapters that implement this interface, let's see if they
    // adapt the provided object.
    if (adapters) {
        // First check if an object adapter matches
        for (var i = 0, imax = adapters.objectAdapters.length; i < imax; i++) {
            var tmp = adapters.objectAdapters[i];
            // TODO: THIS IS A NOOP right now, there is no interfaceId-property on objects unless they are interfaces
            if (obj.interfaceId === tmp.adapts.interfaceId) {
                // Found the adapter, instansiate and return (adapter should set obj as context on creation)
                var outp = new tmp.adapter(obj);
                return outp;
            }

        }
        // Then check if an interface adapter matches, iterate over each interface implemented by the
        // passed object to find the first match.

        // INTEGRITY CHECK: Throw a useful error if the passed object doesn't have _implements
        if (!(obj._implements && obj._implements.length > 0)) {
            throw new AdapterRegistryException(
                "Context (first param) doesn't have any _implements property, and thus no interfaces to use for look up",
                {
                    context: obj,
                    implements: implementsInterface,
                    registry: this
                }
            )
        };

        // TODO: Should investigate inheritance and overriding here, the use case is that you want to override
        // adapters registered on a general interface in a component with that registered in an application. I
        // need to think about how this works and write the docs first, then tests and then implement it so it
        // is easy to understand and reason about.
        for (var j = 0, jmax = obj._implements.length; j < jmax; j++) {
            var tmpInterface = obj._implements[j];
            for (var i = 0, imax = adapters.interfaceAdapters.length; i < imax; i++) {
                var tmp = adapters.interfaceAdapters[i];
                if (tmpInterface.interfaceId === tmp.adapts.interfaceId) {
                    // Found the adapter, instansiate and return (adapter should set obj as context on creation)
                    var outp = new tmp.adapter(obj);
                    return outp;
                }

            }
        }
    };

    // TODO: Figure out how to throw nice custom errors
    // If we get this far, throws error if no adapter is found
    var adaptsInterfaces = adapters.interfaceAdapters.map(function (adapter) {
        return "[" + adapter.adapts.name + "] " + adapter.adapts.interfaceId;
    });
    var contextInterfaces = obj._implements.map(function (intrfc) {
        return "[" + intrfc.name + "] " + intrfc.interfaceId;
    })

    var message = "No registered adapter implementing [" + implementsInterface.name + "] found that adapts: " + (obj._iname || obj);
    throw new AdapterRegistryException(message, obj);
}

module.exports = AdapterRegistry;<|endoftext|>


<commit_before>const Directive = require('./directive')

module.exports = Poison

function Poison(poison) {
  Directive.call(this, poison)

  this.phase = 'incoming'
  this._outPoisonsEnabled = false
}

Poison.prototype = Object.create(Directive.prototype)
<commit_msg>refactor(poison): rename field<commit_after>const Directive = require('./directive')

module.exports = Poison

function Poison(poison) {
  Directive.call(this, poison)

  this.phase = 'incoming'
  this._outgoingEnabled = false
}

Poison.prototype = Object.create(Directive.prototype)
<|endoftext|>