<commit_before>//
// Module Dependencies
//
var util       = require('util');
var hapi       = require('hapi');
var intel      = require('intel');
var utils      = require('nails-utils');
var model      = require('model');
var Agenda     = require('agenda');
var Registry   = require('./Registry');
var confidence = require('confidence');

//
// Shortcuts
//
var is         = utils.is;
var pkg        = utils.loadPackage;
var cyan       = utils.chalk.cyan;
var red        = utils.chalk.red;
var assert     = utils.assert;
var resolve    = utils.path.resolve;
var basename   = utils.path.basename;
var defaults   = utils.applyToDefaults;

//
// App Constructor
//
var Nails = function(opts) {

  // Apply default options
  opts = defaults({
    env:    process.env.NODE_ENV ? process.env.NODE_ENV.toLowerCase() : 'development',
    base:   process.cwd(),
    plugins: [],
    pack:   {
      cache:  {
        engine:    'catbox-memory',
        partition: 'app'
      }
    }
  }, opts || {});

  // Common properties
  this.options = opts;
  this.base    = opts.base;
  this.env     = opts.env;
  this.pkg     = pkg(this.base);
  this.name    = opts.name    || this.pkg.name;
  this.version = opts.version || this.pkg.version;

  // Common utilities
  this.hapi    = hapi;
  this.utils   = utils;
  this.logger  = intel;

  // Initialize
  this.log.info('Application: %s %s', cyan(this.name), cyan('v' + this.version));
  this.log.info('Environment: %s\n', cyan(this.env));
  this.init();
};

//
// Prototype Methods
//
Nails.prototype.log      = new utils.DummyLogger();
Nails.prototype.Registry = Registry;
Nails.prototype.model    = model;
Nails.prototype.task     = new Agenda();
Nails.prototype.service  = new Registry('Service');
Nails.prototype.config   = new confidence.Store();

//
// Option helper - Access `this.options` using dot notation
//
Nails.prototype.option = function(chain) {
  return utils.reach(this.options, chain);
};

//
// Initialize
//
Nails.prototype.init = function() {
  var self = this;
  var conf = this.config;
  var opt  = this.option.bind(this);

  //
  // Init: Config Files
  //
  var configFiles = opt('config');
  if(!is.array(configFiles)) configFiles = [configFiles];

  configFiles.forEach(self.loadConfig, self);

  //
  // Init: Logger
  //
  var logConfig = conf.get('/logging', { env: self.env });
  var messages = this.log.getLogs();

  if(logConfig && logConfig.handlers) {
    // Resolve file paths
    var handlers = logConfig.handlers;

    Object.keys(handlers)
      .filter(function(handler) {
        return handlers[handler].class === 'intel/handlers/file' && handlers[handler].file;
      })
      .forEach(function(handler) {
        handlers[handler].file = resolve(self.base, handlers[handler].file);
       });

    this.logger.config(logConfig);
    this.log = this.logger.getLogger('app');

    messages.forEach(function(msg) {
      self.log[msg.level].apply(self.log, msg.args);
    });
  }
  else {
    this.log = this.logger.getLogger('app');

    messages.forEach(function(msg) {
      self.log[msg.level].apply(self.log, msg.args);
    });
  }

  //
  // Init: Cache
  //
  this.options.pack.cache = conf.get('/cache', { env: self.env }) || opt('pack.cache');

  //
  // Init: Hapi.Pack
  //
  this.pack = new hapi.Pack(opt('pack'));
  this.pack.app = this;

  //
  // Init: Servers
  //
  var servers = opt('servers') || conf.get('/servers') || [];

  servers.forEach(function(serverConfig) {
    serverConfig = defaults({
      host: '0.0.0.0',
      port: '3000',
      options: {}
    }, serverConfig);

    self.server(serverConfig.port, serverConfig.host, serverConfig.options);
  });

  //

  //
  // Init: Framework Plugins
  //
  var plugins = {
    'hapi-navigation': {}
  };

  var sessions = conf.get('/sessions');
  if(sessions) plugins.yar = sessions;

  this.pack.require(plugins, function(err) {
    if(err) throw err;
  });

  //
  // Init: App Plugins
  //
  var appPlugins = opt('plugins');

  if(!is.array.empty(appPlugins)) {
    appPlugins.forEach(function(pattern) {
      self.plugin(pattern, {});
    });
  }

  //
  // Init: Tasks
  //
  var tasks    = opt('tasks');
  var mongoURL = conf.get('/databases/mongodb/url', { env: this.env });

  if(tasks && mongoURL) {
    var taskLogger = self.logger.getLogger('app.task');

    this.task
      .database(mongoURL, 'tasks')
      .processEvery('10 seconds')
      .maxConcurrency(20)
      .defaultConcurrency(5)
      .on('start', function(job) {
        taskLogger.info('Starting: %s', cyan(job.attrs.name));
      })
      .on('success', function(job) {
        taskLogger.info('Complete: %s', cyan(job.attrs.name));
      })
      .on('fail', function(err, job) {
        taskLogger.warn('Failed: %s', red(job.attrs.name));
        if(err) taskLogger.error(err);
      });

    if(!is.array(tasks)) tasks = [tasks];
    tasks.forEach(self.loadTasks, self);
  }
  else delete this.task;

  console.log();
};

//
// Load Plugins
//
Nails.prototype.plugin = function usePlugin(pattern, options) {
  assert(is.string(pattern), 'Missing glob pattern');
  options = options || {};

  var self  = this;
  var found = [];

  utils.finder({
    pattern: pattern,
    cwd: this.base
  }, function(file, total) {
      var plugin = require(file);

      assert(is.string(plugin.name),     'Invalid Plugin: Missing exports.name');
      assert(is.defined(plugin.version), 'Invalid Plugin: Missing exports.version');
      assert(is.fn(plugin.register),     'Invalid Plugin: Missing exports.register()');

      var single = total === 1;

      // Register
      self.pack.register(plugin, single ? options : options[plugin.name] || {}, function(err) {
        if(err) throw err;
        found.push(plugin.name);
      });
  });

  if(found.length) self.log.info('Loaded plugins: ' + cyan(found.join(', ')));
};

//
// Load Configuration Files
//
Nails.prototype.loadConfig = function loadConfig(pattern) {
  var obj  = this.config.get('/');
  var found = [];

  utils.finder({
    pattern: pattern,
    cwd: this.base
  }, function(file, total) {
      var ext  = utils.path.extname(file);
      var name = basename(file, ext);

      obj[name] = require(file);
      found.push(name);
  });

  this.log.info('Loaded configs: ' + cyan('%s'), found.join(', '));
  this.config.load(obj);

  return this;
};

//
// Load Tasks
//
Nails.prototype.loadTasks = function loadTasks(pattern) {
  var self  = this;
  var found = [];

  utils.finder({
    pattern: pattern,
    cwd: this.base
  }, function(file) {
       var task = require(file);

       // Exposes app and a custom logger on the task object
       // Not sure if this is a good idea..
       task.app = self;
       task.log = self.logger.getLogger('app.task');

       assert(is.string(task.name), 'Invalid Task: Missing exports.name');
       assert(is.fn(task.run),      'Invalid Task: Missing exports.run()');

       self.task.define(task.name, task.options || {}, task.run);
       found.push(task.name);
  });

  this.log.info('Loaded tasks:   ' + cyan('%s'), found.join(', '));

  return this;
};

//
// Require a plugin
//
Nails.prototype.require = function requirePlugin(names, options, callback) {
  var self = this;

  if(Array.isArray(names) && typeof options === 'function') {
    callback = options;
    options = {};
  }
  options = options || {};

  if(Array.isArray(names)) {

    names = names.map(function(name) {
      return resolve(this.base, 'node_modules', name);
    });

    this.pack.require(names, function(err) {
      if(err) throw err;

      names.forEach(function(name) {
        self.log.info('Loaded plugin: ' + cyan(basename(name)));
      });

      if(callback) return callback(err);
    });
  }
  else {
    names = resolve(this.base, 'node_modules', names);
    this.pack.require(names, options, function(err) {
      if(err) throw err;

      self.log.info('Loaded plugin: ' + cyan(basename(names)));

      if(callback) return callback(err);
    });
  }
  return this;
};

//
// Create a server
//
Nails.prototype.server = function createServer(host, port, options) {
  var self   = this;
  var logger = this.logger.getLogger('app.request');
  var server = this.pack.server.apply(this.pack, Array.prototype.slice.call(arguments));

  server.on('log', function(event, tags) {
    var data;
    var level = 'info';
    if (tags.debug) level = 'debug';
    if (tags.info)  level = 'info';
    if (tags.warn)  level = 'warn';
    if (tags.error) level = 'error';

    data = util.format(event.data);

    self.log[level](data);
  });

  server.on('request', function(request, event, tags) {
     if (tags.error && util.isError(event.data)) {
      var err = event.data;

      if (err.isBoom && err.output.statusCode < 500) {
        logger.warn(
          utils.chalk.yellow.bold('%d') + utils.chalk.bold(' %s ') + utils.chalk.red('%s'),
          err.output.statusCode,
          request.method.toUpperCase(),
          err.message
        );
      }
      else {
        logger.error(utils.chalk.red('%s'), err);
      }
    }

  });

  // response logging
  server.on('response', function(request) {

    var access = {
      ip: request.info.remoteAddress,
      time: new Date(),
      method: request.method.toUpperCase(),
      url: request.url.path,
      agent: request.headers['user-agent'],
      referer: request.headers.referer || request.headers.referrer || '-',
      http_ver: request.raw.req.httpVersion,
      length: request.response.headers['content-length'],
      status: request.response.statusCode,
      color: 'green',
      response_time: new Date().getTime() - request.info.received
    };

    if (access.status >= 500) access.color = 'red';
    else if (access.status >= 400) access.color = 'yellow';
    else if (access.status >= 300) access.color = 'cyan';

    logger.info(
      utils.chalk[access.color].bold('%d') + utils.chalk.bold(' %s ') + utils.chalk.grey('%s') + utils.chalk.magenta(' (%s, %dms)'),
      access.status,
      access.method,
      access.url,
      access.ip,
      access.response_time
    );
  });

  return server;
};

//
// Start all servers
//
Nails.prototype.start = function startServers(callback) {
  var self = this;

  this.pack.start(function() {

    // Log started servers
    self.pack._servers.forEach(function(s) {
      var info = s.info.uri;
      if(s.settings && Array.isArray(s.settings.labels)) {
        info = cyan(info) + ' (' + utils.chalk.magenta(s.settings.labels.join(', ')) + ')';
      }
      self.log.info('Started web server: ' + info);
    });

    // Start task scheduler
    if(self.task) {
      var tLog = self.logger.getLogger('app.task');

      // Purge old tasks without definitions
      self.task.purge(function(err, num) {
        if(err) tLog.error(err);
        if(num) tLog.info('Purged %i old jobs', cyan(num));

        // Start scheduler after 0-5 seconds
        // So all servers don't run at the same time
        setTimeout(function() {
          self.task.start();
          self.log.info('Started task scheduler');
        }, utils.random(0, 5000));

        if(callback) callback();
        return this;
      });
    }
    else {
      if(callback) callback();
      return this;
    }
  });
};

//
// Stop all servers
//
Nails.prototype.stop = function stopServers(options, callback) {
  var self = this;

  if(typeof options === 'function') {
    callback = options;
    options = {};
  }

  options = defaults({
    timeout: 30 * 1000
  }, options);

  if(this.task) {
    this.task.stop();
    this.log.info('Stopped task scheduler');
  }

  this.pack.stop(options, function() {
    self.log.info('Stopped all servers');
    if(callback) return callback();
    else return self;
  });
};

//
// createApplication - Returns a new Nails instance
//
module.exports = function createApplication(options) {
  return new Nails(options);
};

exports.utils = utils;
<commit_msg>Formatting<commit_after>//
// Module Dependencies
//
var utils      = require('nails-utils');
var util       = require('util');
var hapi       = require('hapi');
var intel      = require('intel');
var model      = require('model');
var Agenda     = require('agenda');
var Registry   = require('./Registry');
var confidence = require('confidence');

//
// Utility Shortcuts
//
var is         = utils.is;
var pkg        = utils.loadPackage;
var cyan       = utils.chalk.cyan;
var red        = utils.chalk.red;
var assert     = utils.assert;
var resolve    = utils.path.resolve;
var basename   = utils.path.basename;
var defaults   = utils.applyToDefaults;

//
// App Constructor
//
var Nails = function(opts) {

  // Apply default options
  opts = defaults({
    env:    process.env.NODE_ENV ? process.env.NODE_ENV.toLowerCase() : 'development',
    base:   process.cwd(),
    plugins: [],
    pack:   {
      cache:  {
        engine:    'catbox-memory',
        partition: 'app'
      }
    }
  }, opts || {});

  // Define properties
  this.options = opts;
  this.base    = opts.base;
  this.env     = opts.env;
  this.pkg     = pkg(this.base);
  this.name    = opts.name    || this.pkg.name;
  this.version = opts.version || this.pkg.version;

  // Expose Hapi and some common methods
  this.hapi    = hapi;
  this.utils   = utils;
  this.logger  = intel;

  // Initialize
  this.log.info('Application: %s %s', cyan(this.name), cyan('v' + this.version));
  this.log.info('Environment: %s\n', cyan(this.env));
  this.init();
};

//
// Prototype Methods
//
Nails.prototype.Registry = Registry;
Nails.prototype.model    = model;
Nails.prototype.log      = new utils.DummyLogger();
Nails.prototype.task     = new Agenda();
Nails.prototype.service  = new Registry('Service');
Nails.prototype.config   = new confidence.Store();

//
// Option helper - Access `this.options` using dot notation
//
Nails.prototype.option = function(chain) {
  return utils.reach(this.options, chain);
};

//
// Initialize
//
Nails.prototype.init = function() {
  var self = this;
  var conf = this.config;
  var opt  = this.option.bind(this);

  //
  // Init: Config Files
  //
  var configFiles = opt('config');
  if(!is.array(configFiles)) configFiles = [configFiles];

  configFiles.forEach(self.loadConfig, self);

  //
  // Init: Logger
  //
  var logConfig = conf.get('/logging', { env: self.env });
  var messages = this.log.getLogs();

  if(logConfig && logConfig.handlers) {
    // Resolve file paths
    var handlers = logConfig.handlers;

    Object.keys(handlers)
      .filter(function(handler) {
        return handlers[handler].class === 'intel/handlers/file' && handlers[handler].file;
      })
      .forEach(function(handler) {
        handlers[handler].file = resolve(self.base, handlers[handler].file);
       });

    this.logger.config(logConfig);
    this.log = this.logger.getLogger('app');

    messages.forEach(function(msg) {
      self.log[msg.level].apply(self.log, msg.args);
    });
  }
  else {
    this.log = this.logger.getLogger('app');

    messages.forEach(function(msg) {
      self.log[msg.level].apply(self.log, msg.args);
    });
  }

  //
  // Init: Cache
  //
  this.options.pack.cache = conf.get('/cache', { env: self.env }) || opt('pack.cache');

  //
  // Init: Hapi.Pack
  //
  this.pack = new hapi.Pack(opt('pack'));
  this.pack.app = this;

  //
  // Init: Servers
  //
  var servers = opt('servers') || conf.get('/servers') || [];

  servers.forEach(function(serverConfig) {
    serverConfig = defaults({
      host: '0.0.0.0',
      port: '3000',
      options: {}
    }, serverConfig);

    self.server(serverConfig.port, serverConfig.host, serverConfig.options);
  });

  //
  // Init: Required Hapi Plugins
  //
  var plugins = {
    'hapi-navigation': {}
  };

  var sessions = conf.get('/sessions');
  if(sessions) plugins.yar = sessions;

  this.pack.require(plugins, function(err) {
    if(err) throw err;
  });

  //
  // Init: App Hapi Plugins
  //
  var appPlugins = opt('plugins');

  if(!is.array.empty(appPlugins)) {
    appPlugins.forEach(function(pattern) {
      self.plugin(pattern, {});
    });
  }

  //
  // Init: Tasks
  //
  var tasks    = opt('tasks');
  var mongoURL = conf.get('/databases/mongodb/url', { env: this.env });

  if(tasks && mongoURL) {
    var taskLogger = self.logger.getLogger('app.task');

    this.task
      .database(mongoURL, 'tasks')
      .processEvery('10 seconds')
      .maxConcurrency(20)
      .defaultConcurrency(5)
      .on('start', function(job) {
        taskLogger.info('Starting: %s', cyan(job.attrs.name));
      })
      .on('success', function(job) {
        taskLogger.info('Complete: %s', cyan(job.attrs.name));
      })
      .on('fail', function(err, job) {
        taskLogger.warn('Failed: %s', red(job.attrs.name));
        if(err) taskLogger.error(err);
      });

    if(!is.array(tasks)) tasks = [tasks];
    tasks.forEach(self.loadTasks, self);
  }
  else delete this.task;

  console.log();
};

//
// Load Configuration Files
//
Nails.prototype.loadConfig = function loadConfig(pattern) {
  var obj  = this.config.get('/');
  var found = [];

  utils.finder({
    pattern: pattern,
    cwd: this.base
  }, function(file, total) {
      var ext  = utils.path.extname(file);
      var name = basename(file, ext);

      obj[name] = require(file);
      found.push(name);
  });

  this.log.info('Loaded configs: ' + cyan('%s'), found.join(', '));
  this.config.load(obj);

  return this;
};

//
// Load Tasks
//
Nails.prototype.loadTasks = function loadTasks(pattern) {
  var self  = this;
  var found = [];

  utils.finder({
    pattern: pattern,
    cwd: this.base
  }, function(file) {
       var task = require(file);

       // Exposes app and a custom logger on the task object
       // Not sure if this is a good idea..
       task.app = self;
       task.log = self.logger.getLogger('app.task');

       assert(is.string(task.name), 'Invalid Task: Missing exports.name');
       assert(is.fn(task.run),      'Invalid Task: Missing exports.run()');

       self.task.define(task.name, task.options || {}, task.run);
       found.push(task.name);
  });

  this.log.info('Loaded tasks:   ' + cyan('%s'), found.join(', '));

  return this;
};

//
// Load Hapi Plugins
//
Nails.prototype.plugin = function usePlugin(pattern, options) {
  assert(is.string(pattern), 'Missing glob pattern');
  options = options || {};

  var self  = this;
  var found = [];

  utils.finder({
    pattern: pattern,
    cwd: this.base
  }, function(file, total) {
      var plugin = require(file);
      var single = total === 1;

      assert(is.string(plugin.name),     'Invalid Plugin: Missing exports.name');
      assert(is.defined(plugin.version), 'Invalid Plugin: Missing exports.version');
      assert(is.fn(plugin.register),     'Invalid Plugin: Missing exports.register()');

      // Register
      self.pack.register(plugin, single ? options : options[plugin.name] || {}, function(err) {
        if(err) throw err;
        found.push(plugin.name);
      });
  });

  if(found.length) self.log.info('Loaded plugins: ' + cyan(found.join(', ')));
};

//
// Require a Hapi plugin
//
Nails.prototype.require = function requirePlugin(names, options, callback) {
  var self = this;
  var isArray = Array.isArray(names);

  if(typeof options === 'function') {
    callback = options;
    options = {};
  }
  options = options || {};

  if(isArray) {
    names = names.map(function(name) {
      return resolve(this.base, 'node_modules', name);
    });

    this.pack.require(names, function(err) {
      if(err) throw err;

      names.forEach(function(name) {
        self.log.info('Loaded plugin: ' + cyan(basename(name)));
      });

      if(callback) return callback(err);
    });
  }
  else {
    names = resolve(this.base, 'node_modules', names);
    this.pack.require(names, options, function(err) {
      if(err) throw err;

      self.log.info('Loaded plugin: ' + cyan(basename(names)));

      if(callback) return callback(err);
    });
  }
  return this;
};

//
// Create a server
//
Nails.prototype.server = function createServer(host, port, options) {
  var self   = this;
  var logger = this.logger.getLogger('app.request');
  var server = this.pack.server.apply(this.pack, Array.prototype.slice.call(arguments));

  // Handle Hapi log events
  server.on('log', function(event, tags) {
    var level = 'info';
    if (tags.debug) level = 'debug';
    if (tags.info)  level = 'info';
    if (tags.warn)  level = 'warn';
    if (tags.error) level = 'error';

    self.log[level](util.format(event.data));
  });

  // Log Hapi request errors
  server.on('request', function(request, event, tags) {
    if (tags.error && util.isError(event.data)) {
      var err = event.data;

      if (err.isBoom && err.output.statusCode < 500) {
        logger.warn(
          utils.chalk.yellow.bold('%d') + utils.chalk.bold(' %s ') + utils.chalk.red('%s'),
          err.output.statusCode,
          request.method.toUpperCase(),
          err.message
        );
      }
      else {
        logger.error(utils.chalk.red('%s'), err);
      }
    }
  });

  // Log Hapi requests
  server.on('response', function(request) {

    var access = {
      ip            : request.info.remoteAddress,
      time          : new Date(),
      method        : request.method.toUpperCase(),
      url           : request.url.path,
      agent         : request.headers['user-agent'],
      referer       : request.headers.referer || request.headers.referrer || '-',
      http_ver      : request.raw.req.httpVersion,
      length        : request.response.headers['content-length'],
      status        : request.response.statusCode,
      color         : 'green',
      response_time : new Date().getTime() - request.info.received
    };

    if      (access.status >= 500) access.color = 'red';
    else if (access.status >= 400) access.color = 'yellow';
    else if (access.status >= 300) access.color = 'cyan';

    logger.info(
      utils.chalk[access.color].bold('%d') + utils.chalk.bold(' %s ') + utils.chalk.grey('%s') + utils.chalk.magenta(' (%s, %dms)'),
      access.status,
      access.method,
      access.url,
      access.ip,
      access.response_time
    );
  });

  return server;
};

//
// Start all servers
//
Nails.prototype.start = function startServers(callback) {
  var self = this;

  this.pack.start(function() {

    // Log started servers
    self.pack._servers.forEach(function(s) {
      var info = s.info.uri;
      if(s.settings && Array.isArray(s.settings.labels)) {
        info = cyan(info) + ' (' + utils.chalk.magenta(s.settings.labels.join(', ')) + ')';
      }
      self.log.info('Started web server: ' + info);
    });

    // Start task scheduler
    if(self.task) {
      var tLog = self.logger.getLogger('app.task');

      // Purge old tasks without definitions
      self.task.purge(function(err, num) {
        if(err) tLog.error(err);
        if(num) tLog.info('Purged %i old jobs', cyan(num));

        // Start scheduler after 0-5 seconds
        // Helps to prevent multiple servers checking at the same time
        setTimeout(function() {
          self.task.start();
          self.log.info('Started task scheduler');
        }, utils.random(0, 5000));

        if(callback) callback();
        return this;
      });
    }
    else {
      if(callback) callback();
      return this;
    }
  });
};

//
// Stop all servers
//
Nails.prototype.stop = function stopServers(options, callback) {
  var self = this;

  if(typeof options === 'function') {
    callback = options;
    options = {};
  }

  options = defaults({
    timeout: 30 * 1000
  }, options);

  if(this.task) {
    this.task.stop();
    this.log.info('Stopped task scheduler');
  }

  this.pack.stop(options, function() {
    self.log.info('Stopped all servers');
    if(callback) return callback();
    else return self;
  });
};

//
// createApplication - Returns a new Nails instance
//
module.exports = function createApplication(options) {
  return new Nails(options);
};

exports.utils = utils;
<|endoftext|>


<commit_before>export default [
    {
        props: [
            {
                name: 'v-model',
                description: 'Binding value',
                type: 'String, Number',
                values: '—',
                default: '—'
            },
            {
                name: 'type',
                description: 'Type (color) of the control, optional',
                type: 'String',
                values: `is-white, is-black, is-light,
                    is-dark, is-primary, is-info, is-success,
                    is-warning, is-danger,
                    and any other colors you've set in the $colors list on Sass`,
                default: 'is-primary'
            },
            {
                name: 'size',
                description: 'Vertical size of input, optional',
                type: 'String',
                values: 'is-small, is-medium, is-large',
                default: '—'
            },
            {
                name: 'expanded',
                description: 'Makes input full width when inside a grouped or addon field',
                type: 'Boolean',
                values: '—',
                default: 'false'
            },
            {
                name: 'loading',
                description: 'Add the loading state to the input',
                type: 'Boolean',
                values: '—',
                default: 'false'
            },
            {
                name: 'editable',
                description: 'Editable input',
                type: 'Boolean',
                values: '—',
                default: 'true'
            },
            {
                name: 'min',
                description: 'Minimum allowed value',
                type: 'Number, String',
                values: '—',
                default: '—'
            },
            {
                name: 'max',
                description: 'Maximum allowed value',
                type: 'Number, String',
                values: '—',
                default: '—'
            },
            {
                name: 'step',
                description: 'Incremental number step',
                type: 'Number, String',
                values: '—',
                default: '—'
            },
            {
                name: 'controls-rounded',
                description: 'Show rounded controls',
                type: 'Boolean',
                values: '—',
                default: 'false'
            },
            {
                name: 'controls-position',
                description: 'Position of controls',
                type: 'String',
                values: 'compact<compact>',
                default: '—'
            },
            {
                name: 'Any native attribute',
                description: '—',
                type: '—',
                values: '—',
                default: '—'
            }
        ],
        events: [
            {
                name: 'input',
                description: 'Triggers when value is changed',
                parameters: 'value: String|Number'
            },
            {
                name: 'focus',
                description: 'Triggers when input has received focus',
                parameters: 'event: $event'
            },
            {
                name: 'blur',
                description: 'Triggers when input has lost focus',
                parameters: 'event: $event'
            },
            {
                name: '[any].native',
                description: 'Listen to any native event, e.g. click.native',
                parameters: 'event: $event'
            }
        ],
        methods: [
            {
                name: 'checkHtml5Validity',
                description: 'Check validation of HTML5 (add the message and type/color), also updates the isValid property',
                return: 'isValid: Boolean'
            },
            {
                name: 'focus',
                description: 'Set focus (internally uses the native .select() method)',
                return: '—'
            }
        ]
    }
]
<commit_msg>adds icon-pack property on numberinput docs (#1870)<commit_after>export default [
    {
        props: [
            {
                name: 'v-model',
                description: 'Binding value',
                type: 'String, Number',
                values: '—',
                default: '—'
            },
            {
                name: 'type',
                description: 'Type (color) of the control, optional',
                type: 'String',
                values: `is-white, is-black, is-light,
                    is-dark, is-primary, is-info, is-success,
                    is-warning, is-danger,
                    and any other colors you've set in the $colors list on Sass`,
                default: 'is-primary'
            },
            {
                name: 'size',
                description: 'Vertical size of input, optional',
                type: 'String',
                values: 'is-small, is-medium, is-large',
                default: '—'
            },
            {
                name: 'expanded',
                description: 'Makes input full width when inside a grouped or addon field',
                type: 'Boolean',
                values: '—',
                default: 'false'
            },
            {
                name: 'loading',
                description: 'Add the loading state to the input',
                type: 'Boolean',
                values: '—',
                default: 'false'
            },
            {
                name: 'editable',
                description: 'Editable input',
                type: 'Boolean',
                values: '—',
                default: 'true'
            },
            {
                name: 'icon-pack',
                description: 'Icon pack to use',
                type: 'String',
                values: 'mdi, fa, fas, far, fab, fad, fal',
                default: 'mdi'
            },
            {
                name: 'min',
                description: 'Minimum allowed value',
                type: 'Number, String',
                values: '—',
                default: '—'
            },
            {
                name: 'max',
                description: 'Maximum allowed value',
                type: 'Number, String',
                values: '—',
                default: '—'
            },
            {
                name: 'step',
                description: 'Incremental number step',
                type: 'Number, String',
                values: '—',
                default: '—'
            },
            {
                name: 'controls-rounded',
                description: 'Show rounded controls',
                type: 'Boolean',
                values: '—',
                default: 'false'
            },
            {
                name: 'controls-position',
                description: 'Position of controls',
                type: 'String',
                values: 'compact<compact>',
                default: '—'
            },
            {
                name: 'Any native attribute',
                description: '—',
                type: '—',
                values: '—',
                default: '—'
            }
        ],
        events: [
            {
                name: 'input',
                description: 'Triggers when value is changed',
                parameters: 'value: String|Number'
            },
            {
                name: 'focus',
                description: 'Triggers when input has received focus',
                parameters: 'event: $event'
            },
            {
                name: 'blur',
                description: 'Triggers when input has lost focus',
                parameters: 'event: $event'
            },
            {
                name: '[any].native',
                description: 'Listen to any native event, e.g. click.native',
                parameters: 'event: $event'
            }
        ],
        methods: [
            {
                name: 'checkHtml5Validity',
                description: 'Check validation of HTML5 (add the message and type/color), also updates the isValid property',
                return: 'isValid: Boolean'
            },
            {
                name: 'focus',
                description: 'Set focus (internally uses the native .select() method)',
                return: '—'
            }
        ]
    }
]
<|endoftext|>


<commit_before>// WARNING: DO NOT INSERT COMMENTS OR ANYTHING
// Line numbers matter to this test!

QUnit.module(module.id);

function nextTick(_){
	(function(cb) {
		setTimeout(function(){
			cb();
		}, 0);
	})(~_);
}

function failAsync(_, code){
	throw new Error(code);
}

function failSync(_, code){
	(function fail(dummy){ // dummy to defeat CoffeeScript compat rule
		throw new Error(code);
	})(0);
}

var fail;

function A(_, code){
	if (code == 1)
		fail(_, code);
	if (code == 2)
		fail(_, code);
	nextTick(_);
	if (code == 3)
		fail(_, code);
	for (var i = 0; i < 6; i++) {
		if (code == i)
			fail(_, code);
		nextTick(_);
	}
	if (code == 6)
		fail(_, code);
	nextTick(_);
	B(_, code);
	nextTick(_);
	return "END";
}

function B(_, code){
	if (code == 7)
		fail(_, code);
	C(_, code);
	nextTick(_);
	C(_, code);
	D(_, code);
}

function C(_, code){
	if (code == 8)
		fail(_, code);
}

function D(_, code){
	if (code == 9)
		fail(_, code);
}

function E(_, code){
	try {
		fail(_, code);
	}
	catch (ex) {
		if (code % 3 == 1)
			fail(_, code);
		else if (code % 3 == 2)
			A(_, code);
		else
			return "OK " + code;
	}
}

function F(_, code){
	var f1 = A(!_, code);
	var f2 = A(!_, code + 1);
	return f1(_) + " & " + f2(_);
}

function G(_, code){
	if (code == 5)
		fail(_, code);
	return "" + code;
}

function H(_, code){
	if (code % 2 == 0)
		nextTick(_);
	return G(_, code);
}

function I(_, code){
	var s = "";
	for (var i = 0; i < code; i++)
		s += H(_, i);
	return s;
}

function T(_, fn, code, failFn){
	fail = failFn;
	var s = "{"
	try {
		return fn(_, code);
	}
	catch (ex) {
		var s = ex.stack;
		s = s.split('\n').filter(function(l) { return l.indexOf('<<<') < 0 && l.indexOf('exports.invoke') < 0; }).map(function(l){
			var m = /^\s+at (\w+).*:(\d+)\:[^:]+$/.exec(l);
			if (m)
				return m[1] + ":" + m[2];
			return l;
		}).join('/');
		var end = s.indexOf('/T:');
		return end < 0 ? s + "-- end frame missing" : s.substring(0, end);
	}
}

function stackEqual(got, expect) {
	if (typeof T_ === 'function' && T_.gstreamlineFunction) { got = got.substring(0, 25); expect = expect.substring(0, 25); }
	strictEqual(got, expect, expect);
}
// safari hack
var rawStack = new Error().stack ? function(raw) {
	return raw;
} : function() {
	return "raw stack unavailable";
}

asyncTest("stacks", 20, function(_) {
	stackEqual(T(_, A, 1, failAsync), rawStack("Error: 1/failAsync:15") + "/A:28");
	stackEqual(T(_, A, 1, failSync), rawStack("Error: 1/fail:20/failSync:21") + "/A:28");
	stackEqual(T(_, A, 2, failAsync), rawStack("Error: 2/failAsync:15") + "/A:30");
	stackEqual(T(_, A, 2, failSync), rawStack("Error: 2/fail:20/failSync:21") + "/A:30");
	stackEqual(T(_, A, 3, failAsync), rawStack("Error: 3/failAsync:15") + "/A:33");
	stackEqual(T(_, A, 3, failSync), rawStack("Error: 3/fail:20/failSync:21") + "/A:33");
	stackEqual(T(_, A, 4, failAsync), rawStack("Error: 4/failAsync:15") + "/A:36");
	stackEqual(T(_, A, 4, failSync), rawStack("Error: 4/fail:20/failSync:21") + "/A:36");
	stackEqual(T(_, A, 5, failAsync), rawStack("Error: 5/failAsync:15") + "/A:36");
	stackEqual(T(_, A, 5, failSync), rawStack("Error: 5/fail:20/failSync:21") + "/A:36");
	stackEqual(T(_, A, 6, failAsync), rawStack("Error: 6/failAsync:15") + "/A:40");
	stackEqual(T(_, A, 6, failSync), rawStack("Error: 6/fail:20/failSync:21") + "/A:40");
	stackEqual(T(_, A, 7, failAsync), rawStack("Error: 7/failAsync:15") + "/B:49/A:42");
	stackEqual(T(_, A, 7, failSync), rawStack("Error: 7/fail:20/failSync:21") + "/B:49/A:42");
	stackEqual(T(_, A, 8, failAsync), rawStack("Error: 8/failAsync:15") + "/C:58/B:50/A:42");
	stackEqual(T(_, A, 8, failSync), rawStack("Error: 8/fail:20/failSync:21") + "/C:58/B:50/A:42");
	stackEqual(T(_, A, 9, failAsync), rawStack("Error: 9/failAsync:15") + "/D:63/B:53/A:42");
	stackEqual(T(_, A, 9, failSync), rawStack("Error: 9/fail:20/failSync:21") + "/D:63/B:53/A:42");
	stackEqual(T(_, A, 10, failAsync), "END");
	stackEqual(T(_, A, 10, failSync), "END");
	start();
})

asyncTest("catch", 20, function(_) {
	stackEqual(T(_, E, 1, failAsync), rawStack("Error: 1/failAsync:15") + "/E:72");
	stackEqual(T(_, E, 1, failSync), rawStack("Error: 1/fail:20/failSync:21") + "/E:72");
	stackEqual(T(_, E, 2, failAsync), rawStack("Error: 2/failAsync:15") + "/A:30/E:74");
	stackEqual(T(_, E, 2, failSync), rawStack("Error: 2/fail:20/failSync:21") + "/A:30/E:74");
	stackEqual(T(_, E, 3, failAsync), "OK 3");
	stackEqual(T(_, E, 3, failSync), "OK 3");
	stackEqual(T(_, E, 4, failAsync), rawStack("Error: 4/failAsync:15") + "/E:72");
	stackEqual(T(_, E, 4, failSync), rawStack("Error: 4/fail:20/failSync:21") + "/E:72");
	stackEqual(T(_, E, 5, failAsync), rawStack("Error: 5/failAsync:15") + "/A:36/E:74");
	stackEqual(T(_, E, 5, failSync), rawStack("Error: 5/fail:20/failSync:21") + "/A:36/E:74");
	stackEqual(T(_, E, 6, failAsync), "OK 6");
	stackEqual(T(_, E, 6, failSync), "OK 6");
	stackEqual(T(_, E, 7, failAsync), rawStack("Error: 7/failAsync:15") + "/E:72");
	stackEqual(T(_, E, 7, failSync), rawStack("Error: 7/fail:20/failSync:21") + "/E:72");
	stackEqual(T(_, E, 8, failAsync), rawStack("Error: 8/failAsync:15") + "/C:58/B:50/A:42/E:74");
	stackEqual(T(_, E, 8, failSync), rawStack("Error: 8/fail:20/failSync:21") + "/C:58/B:50/A:42/E:74");
	stackEqual(T(_, E, 9, failAsync), "OK 9");
	stackEqual(T(_, E, 9, failSync), "OK 9");
	stackEqual(T(_, E, 10, failAsync), rawStack("Error: 10/failAsync:15") + "/E:72");
	stackEqual(T(_, E, 10, failSync), rawStack("Error: 10/fail:20/failSync:21") + "/E:72");
	start();
})

asyncTest("futures", 20, function(_) {
	stackEqual(T(_, F, 1, failAsync), rawStack("Error: 1/failAsync:15") + "/A:28/F:83");
	stackEqual(T(_, F, 1, failSync), rawStack("Error: 1/fail:20/failSync:21") + "/A:28/F:83");
	stackEqual(T(_, F, 2, failAsync), rawStack("Error: 2/failAsync:15") + "/A:30/F:83");
	stackEqual(T(_, F, 2, failSync), rawStack("Error: 2/fail:20/failSync:21") + "/A:30/F:83");
	stackEqual(T(_, F, 3, failAsync), rawStack("Error: 3/failAsync:15") + "/A:33/F:83");
	stackEqual(T(_, F, 3, failSync), rawStack("Error: 3/fail:20/failSync:21") + "/A:33/F:83");
	stackEqual(T(_, F, 4, failAsync), rawStack("Error: 4/failAsync:15") + "/A:36/F:83");
	stackEqual(T(_, F, 4, failSync), rawStack("Error: 4/fail:20/failSync:21") + "/A:36/F:83");
	stackEqual(T(_, F, 5, failAsync), rawStack("Error: 5/failAsync:15") + "/A:36/F:83");
	stackEqual(T(_, F, 5, failSync), rawStack("Error: 5/fail:20/failSync:21") + "/A:36/F:83");
	stackEqual(T(_, F, 6, failAsync), rawStack("Error: 6/failAsync:15") + "/A:40/F:83");
	stackEqual(T(_, F, 6, failSync), rawStack("Error: 6/fail:20/failSync:21") + "/A:40/F:83");
	stackEqual(T(_, F, 7, failAsync), rawStack("Error: 7/failAsync:15") + "/B:49/A:42/F:83");
	stackEqual(T(_, F, 7, failSync), rawStack("Error: 7/fail:20/failSync:21") + "/B:49/A:42/F:83");
	stackEqual(T(_, F, 8, failAsync), rawStack("Error: 8/failAsync:15") + "/C:58/B:50/A:42/F:83");
	stackEqual(T(_, F, 8, failSync), rawStack("Error: 8/fail:20/failSync:21") + "/C:58/B:50/A:42/F:83");
	stackEqual(T(_, F, 9, failAsync), rawStack("Error: 9/failAsync:15") + "/D:63/B:53/A:42/F:83");
	stackEqual(T(_, F, 9, failSync), rawStack("Error: 9/fail:20/failSync:21") + "/D:63/B:53/A:42/F:83");
	stackEqual(T(_, F, 10, failAsync), "END & END");
	stackEqual(T(_, F, 10, failSync), "END & END");
	start();
})

asyncTest("loop", 8, function(_) {
	stackEqual(T(_, I, 4, failAsync), "0123");
	stackEqual(T(_, I, 4, failSync), "0123");
	stackEqual(T(_, I, 5, failAsync), "01234");
	stackEqual(T(_, I, 5, failSync), "01234");
	stackEqual(T(_, I, 6, failAsync), rawStack("Error: 5/failAsync:15") + "/G:88/H:95/I:101");
	stackEqual(T(_, I, 6, failSync), rawStack("Error: 5/fail:20/failSync:21") + "/G:88/H:95/I:101");
	stackEqual(T(_, I, 7, failAsync), rawStack("Error: 5/failAsync:15") + "/G:88/H:95/I:101");
	stackEqual(T(_, I, 7, failSync), rawStack("Error: 5/fail:20/failSync:21") + "/G:88/H:95/I:101");
	start();
})
<commit_msg>small code simplification in stack-test<commit_after>// WARNING: DO NOT INSERT COMMENTS OR ANYTHING
// Line numbers matter to this test!

QUnit.module(module.id);

var nextTick = _(function(cb) {
	setTimeout(function(){
		cb();
	}, 0);
}, 0);

function failAsync(_, code){
	throw new Error(code);
}

function failSync(_, code){
	(function fail(dummy){ // dummy to defeat CoffeeScript compat rule
		throw new Error(code);
	})(0);
}

var fail;

function A(_, code){
	if (code == 1)
		fail(_, code);
	if (code == 2)
		fail(_, code);
	nextTick(_);
	if (code == 3)
		fail(_, code);
	for (var i = 0; i < 6; i++) {
		if (code == i)
			fail(_, code);
		nextTick(_);
	}
	if (code == 6)
		fail(_, code);
	nextTick(_);
	B(_, code);
	nextTick(_);
	return "END";
}

function B(_, code){
	if (code == 7)
		fail(_, code);
	C(_, code);
	nextTick(_);
	C(_, code);
	D(_, code);
}

function C(_, code){
	if (code == 8)
		fail(_, code);
}

function D(_, code){
	if (code == 9)
		fail(_, code);
}

function E(_, code){
	try {
		fail(_, code);
	}
	catch (ex) {
		if (code % 3 == 1)
			fail(_, code);
		else if (code % 3 == 2)
			A(_, code);
		else
			return "OK " + code;
	}
}

function F(_, code){
	var f1 = A(!_, code);
	var f2 = A(!_, code + 1);
	return f1(_) + " & " + f2(_);
}

function G(_, code){
	if (code == 5)
		fail(_, code);
	return "" + code;
}

function H(_, code){
	if (code % 2 == 0)
		nextTick(_);
	return G(_, code);
}

function I(_, code){
	var s = "";
	for (var i = 0; i < code; i++)
		s += H(_, i);
	return s;
}

function T(_, fn, code, failFn){
	fail = failFn;
	var s = "{"
	try {
		return fn(_, code);
	}
	catch (ex) {
		var s = ex.stack;
		s = s.split('\n').filter(function(l) { return l.indexOf('<<<') < 0 && l.indexOf('exports.invoke') < 0; }).map(function(l){
			var m = /^\s+at (\w+).*:(\d+)\:[^:]+$/.exec(l);
			if (m)
				return m[1] + ":" + m[2];
			return l;
		}).join('/');
		var end = s.indexOf('/T:');
		return end < 0 ? s + "-- end frame missing" : s.substring(0, end);
	}
}

function stackEqual(got, expect) {
	if (typeof T_ === 'function' && T_.gstreamlineFunction) { got = got.substring(0, 25); expect = expect.substring(0, 25); }
	strictEqual(got, expect, expect);
}
// safari hack
var rawStack = new Error().stack ? function(raw) {
	return raw;
} : function() {
	return "raw stack unavailable";
}

asyncTest("stacks", 20, function(_) {
	stackEqual(T(_, A, 1, failAsync), rawStack("Error: 1/failAsync:15") + "/A:28");
	stackEqual(T(_, A, 1, failSync), rawStack("Error: 1/fail:20/failSync:21") + "/A:28");
	stackEqual(T(_, A, 2, failAsync), rawStack("Error: 2/failAsync:15") + "/A:30");
	stackEqual(T(_, A, 2, failSync), rawStack("Error: 2/fail:20/failSync:21") + "/A:30");
	stackEqual(T(_, A, 3, failAsync), rawStack("Error: 3/failAsync:15") + "/A:33");
	stackEqual(T(_, A, 3, failSync), rawStack("Error: 3/fail:20/failSync:21") + "/A:33");
	stackEqual(T(_, A, 4, failAsync), rawStack("Error: 4/failAsync:15") + "/A:36");
	stackEqual(T(_, A, 4, failSync), rawStack("Error: 4/fail:20/failSync:21") + "/A:36");
	stackEqual(T(_, A, 5, failAsync), rawStack("Error: 5/failAsync:15") + "/A:36");
	stackEqual(T(_, A, 5, failSync), rawStack("Error: 5/fail:20/failSync:21") + "/A:36");
	stackEqual(T(_, A, 6, failAsync), rawStack("Error: 6/failAsync:15") + "/A:40");
	stackEqual(T(_, A, 6, failSync), rawStack("Error: 6/fail:20/failSync:21") + "/A:40");
	stackEqual(T(_, A, 7, failAsync), rawStack("Error: 7/failAsync:15") + "/B:49/A:42");
	stackEqual(T(_, A, 7, failSync), rawStack("Error: 7/fail:20/failSync:21") + "/B:49/A:42");
	stackEqual(T(_, A, 8, failAsync), rawStack("Error: 8/failAsync:15") + "/C:58/B:50/A:42");
	stackEqual(T(_, A, 8, failSync), rawStack("Error: 8/fail:20/failSync:21") + "/C:58/B:50/A:42");
	stackEqual(T(_, A, 9, failAsync), rawStack("Error: 9/failAsync:15") + "/D:63/B:53/A:42");
	stackEqual(T(_, A, 9, failSync), rawStack("Error: 9/fail:20/failSync:21") + "/D:63/B:53/A:42");
	stackEqual(T(_, A, 10, failAsync), "END");
	stackEqual(T(_, A, 10, failSync), "END");
	start();
})

asyncTest("catch", 20, function(_) {
	stackEqual(T(_, E, 1, failAsync), rawStack("Error: 1/failAsync:15") + "/E:72");
	stackEqual(T(_, E, 1, failSync), rawStack("Error: 1/fail:20/failSync:21") + "/E:72");
	stackEqual(T(_, E, 2, failAsync), rawStack("Error: 2/failAsync:15") + "/A:30/E:74");
	stackEqual(T(_, E, 2, failSync), rawStack("Error: 2/fail:20/failSync:21") + "/A:30/E:74");
	stackEqual(T(_, E, 3, failAsync), "OK 3");
	stackEqual(T(_, E, 3, failSync), "OK 3");
	stackEqual(T(_, E, 4, failAsync), rawStack("Error: 4/failAsync:15") + "/E:72");
	stackEqual(T(_, E, 4, failSync), rawStack("Error: 4/fail:20/failSync:21") + "/E:72");
	stackEqual(T(_, E, 5, failAsync), rawStack("Error: 5/failAsync:15") + "/A:36/E:74");
	stackEqual(T(_, E, 5, failSync), rawStack("Error: 5/fail:20/failSync:21") + "/A:36/E:74");
	stackEqual(T(_, E, 6, failAsync), "OK 6");
	stackEqual(T(_, E, 6, failSync), "OK 6");
	stackEqual(T(_, E, 7, failAsync), rawStack("Error: 7/failAsync:15") + "/E:72");
	stackEqual(T(_, E, 7, failSync), rawStack("Error: 7/fail:20/failSync:21") + "/E:72");
	stackEqual(T(_, E, 8, failAsync), rawStack("Error: 8/failAsync:15") + "/C:58/B:50/A:42/E:74");
	stackEqual(T(_, E, 8, failSync), rawStack("Error: 8/fail:20/failSync:21") + "/C:58/B:50/A:42/E:74");
	stackEqual(T(_, E, 9, failAsync), "OK 9");
	stackEqual(T(_, E, 9, failSync), "OK 9");
	stackEqual(T(_, E, 10, failAsync), rawStack("Error: 10/failAsync:15") + "/E:72");
	stackEqual(T(_, E, 10, failSync), rawStack("Error: 10/fail:20/failSync:21") + "/E:72");
	start();
})

asyncTest("futures", 20, function(_) {
	stackEqual(T(_, F, 1, failAsync), rawStack("Error: 1/failAsync:15") + "/A:28/F:83");
	stackEqual(T(_, F, 1, failSync), rawStack("Error: 1/fail:20/failSync:21") + "/A:28/F:83");
	stackEqual(T(_, F, 2, failAsync), rawStack("Error: 2/failAsync:15") + "/A:30/F:83");
	stackEqual(T(_, F, 2, failSync), rawStack("Error: 2/fail:20/failSync:21") + "/A:30/F:83");
	stackEqual(T(_, F, 3, failAsync), rawStack("Error: 3/failAsync:15") + "/A:33/F:83");
	stackEqual(T(_, F, 3, failSync), rawStack("Error: 3/fail:20/failSync:21") + "/A:33/F:83");
	stackEqual(T(_, F, 4, failAsync), rawStack("Error: 4/failAsync:15") + "/A:36/F:83");
	stackEqual(T(_, F, 4, failSync), rawStack("Error: 4/fail:20/failSync:21") + "/A:36/F:83");
	stackEqual(T(_, F, 5, failAsync), rawStack("Error: 5/failAsync:15") + "/A:36/F:83");
	stackEqual(T(_, F, 5, failSync), rawStack("Error: 5/fail:20/failSync:21") + "/A:36/F:83");
	stackEqual(T(_, F, 6, failAsync), rawStack("Error: 6/failAsync:15") + "/A:40/F:83");
	stackEqual(T(_, F, 6, failSync), rawStack("Error: 6/fail:20/failSync:21") + "/A:40/F:83");
	stackEqual(T(_, F, 7, failAsync), rawStack("Error: 7/failAsync:15") + "/B:49/A:42/F:83");
	stackEqual(T(_, F, 7, failSync), rawStack("Error: 7/fail:20/failSync:21") + "/B:49/A:42/F:83");
	stackEqual(T(_, F, 8, failAsync), rawStack("Error: 8/failAsync:15") + "/C:58/B:50/A:42/F:83");
	stackEqual(T(_, F, 8, failSync), rawStack("Error: 8/fail:20/failSync:21") + "/C:58/B:50/A:42/F:83");
	stackEqual(T(_, F, 9, failAsync), rawStack("Error: 9/failAsync:15") + "/D:63/B:53/A:42/F:83");
	stackEqual(T(_, F, 9, failSync), rawStack("Error: 9/fail:20/failSync:21") + "/D:63/B:53/A:42/F:83");
	stackEqual(T(_, F, 10, failAsync), "END & END");
	stackEqual(T(_, F, 10, failSync), "END & END");
	start();
})

asyncTest("loop", 8, function(_) {
	stackEqual(T(_, I, 4, failAsync), "0123");
	stackEqual(T(_, I, 4, failSync), "0123");
	stackEqual(T(_, I, 5, failAsync), "01234");
	stackEqual(T(_, I, 5, failSync), "01234");
	stackEqual(T(_, I, 6, failAsync), rawStack("Error: 5/failAsync:15") + "/G:88/H:95/I:101");
	stackEqual(T(_, I, 6, failSync), rawStack("Error: 5/fail:20/failSync:21") + "/G:88/H:95/I:101");
	stackEqual(T(_, I, 7, failAsync), rawStack("Error: 5/failAsync:15") + "/G:88/H:95/I:101");
	stackEqual(T(_, I, 7, failSync), rawStack("Error: 5/fail:20/failSync:21") + "/G:88/H:95/I:101");
	start();
})
<|endoftext|>


<commit_before>"use strict";

var https = require('https');
var http = require('http');
var Step = require('step');
var SmtpapiHeaders = require('./smtpapi_headers');
var FileHandler = require('./file_handler');
var _ = require('underscore');

/**
 * Class to handle storing the properties relative to an email.
 *
 * @param  {Object}          params
 * @param  {string|array}    params.to       The to address(es) of the email
 * @param  {string|array}    params.fromname The display name of the email recipients
 * @param  {string}          params.from     The from address of the email
 * @param  {string}          params.fromname The display name of the email sender
 * @param  {SmtpapiHeaders}  params.smtpapi  The SendGrid x-smtpapi headers object
 * @param  {string}          params.subject  The subject of the email
 * @param  {string}          params.text     The text/plain content of an email
 * @param  {string}          params.html     The text/html content of an email
 * @param  {string|array}    params.bcc      The bcc address(es) of the email
 * @param  {Date}            params.date     The date of the email
 * @param  {object}          params.headers  The custom headers on an email
 */
function Email(params) {

  params = params || {};

  this.to      = params.to      || [];
  this.from    = params.from    || '';
  this.smtpapi = params.smtpapi || new SmtpapiHeaders();
  this.subject = params.subject || '';
  this.text    = params.text    || '';
  this.html    = params.html    || '';
  this.bcc     = params.bcc     || [];
  this.replyto = params.replyto || '';
  this.date    = params.date    || new Date();
  this.headers = params.headers || {};

  if(params.toname != null) {
    this.toname = params.toname;
  }
  if(params.fromname != null) {
    this.fromname = params.fromname;
  }
  // auto handle calling the constructor for the file handler
  this.files = [];
  if (params.files) {
    params.files.forEach(function(file) {
      this.files.push(new FileHandler(file));
    }, this);
  }
}

/**
 * Validates an email. This is used before sending, but
 * can still be invoked programatically
 *
 * @return  {Boolean}  The result of the validation
 */
Email.prototype.validate = function() {
  //TODO: add validation
};

/**
 * This method sets the headers on an email, if the value passed in is an object.
 *
 * @param  {object}  val  An object of custom headers
 */
Email.prototype.setHeaders = function(val) {
  if (_.isObject(val)) {
    this.headers = val;
  }
};

/**
 * This method will add a header, or multiple headers, to an email.
 *
 * @param  {object}  val  An object of custom headers
 */
Email.prototype.addHeaders = function(val) {
  if (_.isObject(val)) {
    _.extend(this.headers, val);
  }
};

/**
 * This method is a proxy for adding a to address to the SmtpapiHeaders
 *
 * @see SmtpapiHeaders.addTo
 */
Email.prototype.addTo = function(to) {
  this.smtpapi.addTo(to);
};

/**
 * This method is a proxy for the add sub val on the SmtpapiHeaders
 *
 * @see SmtpapiHeaders.addSubVal
 */
Email.prototype.addSubVal = function(key, val) {
  this.smtpapi.addSubVal(key, val);
};

/**
 * This method is a proxy for setting unique args on the SmtpapiHeaders
 *
 * @see SmtpapiHeaders.setUniqueArgs
 */
Email.prototype.setUniqueArgs = function(val) {
  this.smtpapi.setUniqueArgs(val);
};

/**
 * This method is a proxy for adding unique args on the SmtpapiHeaders
 *
 * @see SmtpapiHeaders.addUniqueArgs
 */
Email.prototype.addUniqueArgs = function (val) {
  this.smtpapi.addUniqueArgs(val);
};

/**
 * This method is a proxy for setting categories on the SmtpapiHeaders
 *
 * @see SmtpapiHeaders.setCategory
 */
Email.prototype.setCategory = function(val) {
  this.smtpapi.setCategory(val);
};

/**
 * This method is a proxy for adding categories on the SmtpapiHeaders
 *
 * @see SmtpapiHeaders.addCategory
 */
Email.prototype.addCategory = function(val) {
  this.smtpapi.addCategory(val);
};

/**
 * This method is a proxy for setting sections on the SmtpapiHeaders
 *
 * @see SmtpapiHeaders.setSection
 */
Email.prototype.setSection = function(val) {
  this.smtpapi.setSection(val);
};

/**
 * This method is a proxy for adding sections on the SmtpapiHeaders
 *
 * @see SmtpapiHeaders.addSection
 */
Email.prototype.addSection = function(val) {
  this.smtpapi.addSection(val);
};

/**
 * This method is a proxy for adding a filter setting on the SmtpapiHeaders
 *
 * @see SmtpapiHeaders.addFilterSetting
 */
Email.prototype.addFilterSetting = function(filter, setting, val) {
  this.smtpapi.addFilterSetting(filter, setting, val);
};

/**
 * This method is a proxy for setting a filter setting on the SmtpapiHeaders
 *
 * @see SmtpapiHeaders.setFilterSetting
 */
Email.prototype.setFilterSetting = function(filters) {
  this.smtpapi.setFilterSetting(filters);
};

/**
 * This method adds a file to the email object as an attachment
 * It uses the FileHandler object.
 *
 * @param  {object}  file_object  The file object
 *
 * @see FileHandler
 */
Email.prototype.addFile = function(file_object) {
  this.files.push(new FileHandler(file_object));
};

/**
 * This method is used to process files. It uses step.js to asychronously load the contents of each file.
 *
 * @param  {function}  callback  The callback to call when the method returns
 */
Email.prototype.processFiles = function(callback) {
  var self = this;

  function handleFiles() {
    for(var i in self.files) {
      self.files[i].loadContent(this.parallel());
    }
  };

  function finish(err, messages) {
    if (err) {
      callback(false, messages);
    } else {
      callback(true);
    }
  };

  Step(handleFiles, finish);
};

/**
 * This method returns the email object is a format to be consumed by the SendGrid.send
 * using the web api
 *
 * @see SendGrid.send
 */
Email.prototype.toWebFormat = function() {
  var data = {
    to: this.to,
    from: this.from,
    'x-smtpapi': this.smtpapi.toJson(),
    subject: this.subject,
    text: this.text,
    html: this.html,
    bcc: this.bcc,
    replyto: this.replyto,
    headers: JSON.stringify(this.headers)
  };

  if (this.fromname != null) {
    data.fromname = this.fromname;
  }
  if (this.toname != null) {
    data.toname = this.toname;
  }
  this.updateMissingTo(data);

  return data;
};

/**
 * This method returns the email object is a format to be consumed by the SendGrid.smtp
 * using the smtp api
 *
 * @see SendGrid.smtp
 */
Email.prototype.toSmtpFormat = function() {
  var data = {
    to: this.to,
    sender: this.from,
    subject: this.subject,
    body: this.text,
    html: this.html,
    reply_to: this.replyto,
    headers: this.headers
  };
  data.headers['x-smtpapi'] = this.smtpapi.toJson();

  if (_.size(this.files) > 0) {
    var attachments = [];
    _(this.files).each(function(file) {
      attachments.push({filename: file.filename, contents: file.content});
    });
    data.attachments = attachments;
  }

  this.updateMissingTo(data);

  return data;
};

/**
 * There needs to be at least 1 to address, or else the mail won't send.
 * This method modifies the data that will be sent via either Rest or SMTP.
 *
 * @param  {object}  data  The data parameter to send via Rest or SMTP
 */
Email.prototype.updateMissingTo = function(data) {
  if (_.isEmpty(data.to) && this.smtpapi.to && !_.isEmpty(this.smtpapi.to)) {
    data.to = this.from;
  }
};

/**
 * This method is used to show if there are files on this email object
 *
 * @return boolean
 */
Email.prototype.hasFiles = function() {
  return _(this.files).size() > 0;
};

// export the object as the only object in this module
module.exports = Email;
<commit_msg>Fixed typo in function header<commit_after>"use strict";

var https = require('https');
var http = require('http');
var Step = require('step');
var SmtpapiHeaders = require('./smtpapi_headers');
var FileHandler = require('./file_handler');
var _ = require('underscore');

/**
 * Class to handle storing the properties relative to an email.
 *
 * @param  {Object}          params
 * @param  {string|array}    params.to       The to address(es) of the email
 * @param  {string|array}    params.toname   The display name of the email recipients
 * @param  {string}          params.from     The from address of the email
 * @param  {string}          params.fromname The display name of the email sender
 * @param  {SmtpapiHeaders}  params.smtpapi  The SendGrid x-smtpapi headers object
 * @param  {string}          params.subject  The subject of the email
 * @param  {string}          params.text     The text/plain content of an email
 * @param  {string}          params.html     The text/html content of an email
 * @param  {string|array}    params.bcc      The bcc address(es) of the email
 * @param  {Date}            params.date     The date of the email
 * @param  {object}          params.headers  The custom headers on an email
 */
function Email(params) {

  params = params || {};

  this.to      = params.to      || [];
  this.from    = params.from    || '';
  this.smtpapi = params.smtpapi || new SmtpapiHeaders();
  this.subject = params.subject || '';
  this.text    = params.text    || '';
  this.html    = params.html    || '';
  this.bcc     = params.bcc     || [];
  this.replyto = params.replyto || '';
  this.date    = params.date    || new Date();
  this.headers = params.headers || {};

  if(params.toname != null) {
    this.toname = params.toname;
  }
  if(params.fromname != null) {
    this.fromname = params.fromname;
  }
  // auto handle calling the constructor for the file handler
  this.files = [];
  if (params.files) {
    params.files.forEach(function(file) {
      this.files.push(new FileHandler(file));
    }, this);
  }
}

/**
 * Validates an email. This is used before sending, but
 * can still be invoked programatically
 *
 * @return  {Boolean}  The result of the validation
 */
Email.prototype.validate = function() {
  //TODO: add validation
};

/**
 * This method sets the headers on an email, if the value passed in is an object.
 *
 * @param  {object}  val  An object of custom headers
 */
Email.prototype.setHeaders = function(val) {
  if (_.isObject(val)) {
    this.headers = val;
  }
};

/**
 * This method will add a header, or multiple headers, to an email.
 *
 * @param  {object}  val  An object of custom headers
 */
Email.prototype.addHeaders = function(val) {
  if (_.isObject(val)) {
    _.extend(this.headers, val);
  }
};

/**
 * This method is a proxy for adding a to address to the SmtpapiHeaders
 *
 * @see SmtpapiHeaders.addTo
 */
Email.prototype.addTo = function(to) {
  this.smtpapi.addTo(to);
};

/**
 * This method is a proxy for the add sub val on the SmtpapiHeaders
 *
 * @see SmtpapiHeaders.addSubVal
 */
Email.prototype.addSubVal = function(key, val) {
  this.smtpapi.addSubVal(key, val);
};

/**
 * This method is a proxy for setting unique args on the SmtpapiHeaders
 *
 * @see SmtpapiHeaders.setUniqueArgs
 */
Email.prototype.setUniqueArgs = function(val) {
  this.smtpapi.setUniqueArgs(val);
};

/**
 * This method is a proxy for adding unique args on the SmtpapiHeaders
 *
 * @see SmtpapiHeaders.addUniqueArgs
 */
Email.prototype.addUniqueArgs = function (val) {
  this.smtpapi.addUniqueArgs(val);
};

/**
 * This method is a proxy for setting categories on the SmtpapiHeaders
 *
 * @see SmtpapiHeaders.setCategory
 */
Email.prototype.setCategory = function(val) {
  this.smtpapi.setCategory(val);
};

/**
 * This method is a proxy for adding categories on the SmtpapiHeaders
 *
 * @see SmtpapiHeaders.addCategory
 */
Email.prototype.addCategory = function(val) {
  this.smtpapi.addCategory(val);
};

/**
 * This method is a proxy for setting sections on the SmtpapiHeaders
 *
 * @see SmtpapiHeaders.setSection
 */
Email.prototype.setSection = function(val) {
  this.smtpapi.setSection(val);
};

/**
 * This method is a proxy for adding sections on the SmtpapiHeaders
 *
 * @see SmtpapiHeaders.addSection
 */
Email.prototype.addSection = function(val) {
  this.smtpapi.addSection(val);
};

/**
 * This method is a proxy for adding a filter setting on the SmtpapiHeaders
 *
 * @see SmtpapiHeaders.addFilterSetting
 */
Email.prototype.addFilterSetting = function(filter, setting, val) {
  this.smtpapi.addFilterSetting(filter, setting, val);
};

/**
 * This method is a proxy for setting a filter setting on the SmtpapiHeaders
 *
 * @see SmtpapiHeaders.setFilterSetting
 */
Email.prototype.setFilterSetting = function(filters) {
  this.smtpapi.setFilterSetting(filters);
};

/**
 * This method adds a file to the email object as an attachment
 * It uses the FileHandler object.
 *
 * @param  {object}  file_object  The file object
 *
 * @see FileHandler
 */
Email.prototype.addFile = function(file_object) {
  this.files.push(new FileHandler(file_object));
};

/**
 * This method is used to process files. It uses step.js to asychronously load the contents of each file.
 *
 * @param  {function}  callback  The callback to call when the method returns
 */
Email.prototype.processFiles = function(callback) {
  var self = this;

  function handleFiles() {
    for(var i in self.files) {
      self.files[i].loadContent(this.parallel());
    }
  };

  function finish(err, messages) {
    if (err) {
      callback(false, messages);
    } else {
      callback(true);
    }
  };

  Step(handleFiles, finish);
};

/**
 * This method returns the email object is a format to be consumed by the SendGrid.send
 * using the web api
 *
 * @see SendGrid.send
 */
Email.prototype.toWebFormat = function() {
  var data = {
    to: this.to,
    from: this.from,
    'x-smtpapi': this.smtpapi.toJson(),
    subject: this.subject,
    text: this.text,
    html: this.html,
    bcc: this.bcc,
    replyto: this.replyto,
    headers: JSON.stringify(this.headers)
  };

  if (this.fromname != null) {
    data.fromname = this.fromname;
  }
  if (this.toname != null) {
    data.toname = this.toname;
  }
  this.updateMissingTo(data);

  return data;
};

/**
 * This method returns the email object is a format to be consumed by the SendGrid.smtp
 * using the smtp api
 *
 * @see SendGrid.smtp
 */
Email.prototype.toSmtpFormat = function() {
  var data = {
    to: this.to,
    sender: this.from,
    subject: this.subject,
    body: this.text,
    html: this.html,
    reply_to: this.replyto,
    headers: this.headers
  };
  data.headers['x-smtpapi'] = this.smtpapi.toJson();

  if (_.size(this.files) > 0) {
    var attachments = [];
    _(this.files).each(function(file) {
      attachments.push({filename: file.filename, contents: file.content});
    });
    data.attachments = attachments;
  }

  this.updateMissingTo(data);

  return data;
};

/**
 * There needs to be at least 1 to address, or else the mail won't send.
 * This method modifies the data that will be sent via either Rest or SMTP.
 *
 * @param  {object}  data  The data parameter to send via Rest or SMTP
 */
Email.prototype.updateMissingTo = function(data) {
  if (_.isEmpty(data.to) && this.smtpapi.to && !_.isEmpty(this.smtpapi.to)) {
    data.to = this.from;
  }
};

/**
 * This method is used to show if there are files on this email object
 *
 * @return boolean
 */
Email.prototype.hasFiles = function() {
  return _(this.files).size() > 0;
};

// export the object as the only object in this module
module.exports = Email;
<|endoftext|>


<commit_before>export { ConcatGather };
export { ConcatGatherPool };

import * as Pool from "../../util/Pool.js";
import * as Recyclable from "../../util/Recyclable.js";
import { ShuffleInfo, ShuffleInfoPool } from "./ChannelShuffler_ShuffleInfo.js";

/**
 * Implement the channel shuffler by tf.concat() and tf.gather().
 *
 * When outputGroupCount is smaller (e.g. 2), this may be faster than concat-reshape-transpose-reshape-split and
 * split-concat because the total operations (and memory access) are smaller.
 *
 * The extra cost is a pre-built channel index look up table (with tensor1d).
 *
 *
 * @member {number[]} concatenatedShape
 *   (Please see ShuffleInfo explanation.)
 *
 * @member {number} outputGroupCount
 *   (Please see ShuffleInfo explanation.)
 *
 * @member {ShuffleInfo} shuffleInfo
 *   The information calculated from concatenatedShape and outputGroupCount.
 *
 * @member {tf.tensor1d[]} shuffledChannelIndicesTensor1dArray
 *   The look up table for tf.gather()'s channel index. This table is composed of tensor1d so should be released
 * by calling disposeResources().
 *
 * @member {number} tensorWeightCountExtracted
 *   The wieght count extracted from inputFloat32Array and used in tensors. Not including Params, because they are not used in
 * tensors. Not including inferenced weights (even if they are used in tensors), because they are not extracted from inputFloat32Array.
 *
 * @member {number} tensorWeightCountTotal
 *   The total wieght count used in tensors. Not including Params, because they are not used in tensors. Including inferenced
 * weights, if they are used in tensors.
 *
 * @member {function} gather
 *   Permute and split the input tensor by gather. It is a function pointer to one of this.gather_XXX().
 *
 * @member {function} concatGather
 *   Concatenate, permute and split the input tensor by concat-gather. It is a function pointer to one of
 * this.concatGather_XXX().
 */
class ConcatGather extends Recyclable.Root {

  /**
   *
   * @param {number[]} concatenatedShape  Used to calculate shuffleInfo.
   * @param {number}   outputGroupCount   Used to calculate shuffleInfo.
   * @exception {Object} If failed (e.g. out of GPU memory).
   *
   * @see ShuffleInfo
   */
  constructor( concatenatedShape, outputGroupCount, ...restArgs ) {
    super( ...restArgs );
    ConcatGather.setAsConstructor.call( this, concatenatedShape, outputGroupCount );
  }

  /**
   *
   * @param {ShuffleInfo} this
   *   The object to be initialized.
   *
   * @param {number[]} concatenatedShape  Used to calculate shuffleInfo.
   * @param {number}   outputGroupCount   Used to calculate shuffleInfo.
   * @exception {Object} If failed (e.g. out of GPU memory).
   *
   * @return {ConcatGather}
   *   Return the this object.
   *
   * @see ShuffleInfo
   */
  static setAsConstructor( concatenatedShape, outputGroupCount ) {

    this.tensorWeightCountExtracted = 0;
    this.tensorWeightCountTotal = 0;

    this.shuffleInfo = ShuffleInfoPool.Singleton.get_or_create_by( concatenatedShape, outputGroupCount );

    // Build shuffled channel index table (as an array of tf.tensor1d).
    //
    // It can be used by algorithm ConcatGather().
    // They should be integers so that can be used as tf.gather()'s index.
    //
    // Not like SplitConcat, the channel indexes will not be sorted here. According to testing, sorted
    // channel seems slow down memory access when using them as tf.gather()'s index list.
    {
      this.shuffledChannelIndicesTensor1dArray
        = tf.tidy( "ChannelShuffler.ConcatGather.init.shuffledChannelIndicesTensor1dArray", () => {
          let channelIndices = tf.range( 0, this.shuffleInfo.totalChannelCount, 1, "int32" );
          return Pool.All.sessionCall( () => {
            let channelIndicesShuffleInfo = ShuffleInfoPool.Singleton.get_or_create_by( channelIndices.shape, outputGroupCount );
            return channelIndicesShuffleInfo.reshapeTransposeReshapeSplit( channelIndices );
          });
        });

      // Calculate total weight count.
      for ( let i = 0; i < this.shuffledChannelIndicesTensor1dArray.length; ++i ) {
        let shuffledChannelIndicesTensor1d = this.shuffledChannelIndicesTensor1dArray[ i ];
        if ( shuffledChannelIndicesTensor1d ) {
          this.tensorWeightCountTotal += shuffledChannelIndicesTensor1d.size;
        }
      }

    // Exception if failed (e.g. out of (GPU) memory).
    }

    this.gather = this.gather_loop;
    this.concatGather = this.concatGather_dispose_finally_call_loop;

    return this;
  }

  /**
   * Release tf.tensor.
   *
   * Sub-class should override this method (and call super.disposeResources() before return).
   */
  disposeResources() {
    this.concatGather = null;
    this.gather = null;

    this.tensorWeightCountTotal = 0;
    this.tensorWeightCountExtracted = 0;

    if ( this.shuffledChannelIndicesTensor1dArray ) {
      for ( let i = 0; i < this.shuffledChannelIndicesTensor1dArray.length; ++i ) {
        tf.dispose( this.shuffledChannelIndicesTensor1dArray[ i ] );
        this.shuffledChannelIndicesTensor1dArray[ i ] = null;
      }

//!!! (2022/06/25 Remarked) Now only Recyclable.Array could be recycled.
//      // Note: This array is generated by tensorflow.js (i.e. not by Pool.Array). Although it could be recycled by Pool.Array,
//      //       however, this could result in more and more array being cumulated (and then out of memory). So do not recycle it.
//      //
//      //Pool.Array.Singleton.recycle( this.shuffledChannelIndicesTensor1dArray );

      this.shuffledChannelIndicesTensor1dArray = null;
    }

    if ( this.shuffleInfo ) {
      this.shuffleInfo.disposeResources_and_recycleToPool();
      this.shuffleInfo = null;
    }

    //super.disposeResources();
  }

//!!! (2022/06/25 Remarked) Inherits from Recyclable.Base instead.
//   /**
//    * After calling this method, this object should be viewed as disposed and should not be operated again.
//    *
//    * Sub-class should override this method for recycling to its pool (and NEVER call super.disposeResources_and_recycleToPool()).
//    */
//   disposeResources_and_recycleToPool() {
//     this.disposeResources();
//     ConcatGatherPool.Singleton.recycle( this );
//   }

  get concatenatedShape() {
    return this.shuffleInfo.concatenatedShape;
  }

  get outputGroupCount() {
    return this.shuffleInfo.outputGroupCount;
  }

  /**
   * Permute and split the input tensor by gather.
   *
   * @param {tf.tensor} concatenatedTensor
   *   An single tensor (not array) to be processed. It should conform to this.shuffleInfo.concatenatedShape.
   *
   * @return {tf.tensor[]}
   *   An array of shuffled tensors. Their total channel count is the same as concatenated tensorArray, but their
   * last dimensions are shuffled.
   */
  gather_loop( concatenatedTensor ) {
    let shuffledSplitedTensorArray = new Array( this.shuffledChannelIndicesTensor1dArray.length );
    for ( let i = 0; i < shuffledSplitedTensorArray.length; ++i ) {
      // shuffle and split by gather (one operation achieves two operations).
      shuffledSplitedTensorArray[ i ] = concatenatedTensor.gather( this.shuffledChannelIndicesTensor1dArray[ i ], this.shuffleInfo.lastAxisId );
    }
    return shuffledSplitedTensorArray;
  }

  /**
   * Concatenate, permute and split the input tensor by concat-gather.
   *
   * @param {tf.tensor[]} tensorArray
   *   An array of tensors to be processed. It should conform to this.concatenatedShape.
   *
   * @return {tf.tensor[]}
   *   An array of shuffled tensors. Their total channel count is the same as concatenated tensorArray, but their
   * last dimensions are shuffled.
   */
  concatGather_dispose_finally_call_loop( tensorArray ) {
    let concatenatedTensor = tf.concat( tensorArray, this.shuffleInfo.lastAxisId );

    try {
      return this.gather_loop( concatenatedTensor );

    } finally {
      concatenatedTensor.dispose();
    }
  }
}

/**
 * Providing ChannelShuffler.ConcatGather
 *
 */
class ConcatGatherPool extends Pool.Root {

  constructor() {
    super( "ChannelShuffler.ConcatGatherPool", ConcatGather, ConcatGather.setAsConstructor );
  }

}

/**
 * Used as default ChannelShuffler.ConcatGather provider for conforming to Recyclable interface.
 */
ConcatGather.Pool = new ConcatGatherPool();
<commit_msg>Update ChannelShuffler_ConcatGather.js<commit_after>export { ConcatGather };
export { ConcatGatherPool };

import * as Pool from "../../util/Pool.js";
import * as Recyclable from "../../util/Recyclable.js";
import { ShuffleInfo, ShuffleInfoPool } from "./ChannelShuffler_ShuffleInfo.js";

/**
 * Implement the channel shuffler by tf.concat() and tf.gather().
 *
 * When outputGroupCount is smaller (e.g. 2), this may be faster than concat-reshape-transpose-reshape-split and
 * split-concat because the total operations (and memory access) are smaller.
 *
 * The extra cost is a pre-built channel index look up table (with tensor1d).
 *
 *
 * @member {number[]} concatenatedShape
 *   (Please see ShuffleInfo explanation.)
 *
 * @member {number} outputGroupCount
 *   (Please see ShuffleInfo explanation.)
 *
 * @member {ShuffleInfo} shuffleInfo
 *   The information calculated from concatenatedShape and outputGroupCount.
 *
 * @member {tf.tensor1d[]} shuffledChannelIndicesTensor1dArray
 *   The look up table for tf.gather()'s channel index. This table is composed of tensor1d so should be released
 * by calling disposeResources().
 *
 * @member {number} tensorWeightCountExtracted
 *   The wieght count extracted from inputFloat32Array and used in tensors. Not including Params, because they are not used in
 * tensors. Not including inferenced weights (even if they are used in tensors), because they are not extracted from inputFloat32Array.
 *
 * @member {number} tensorWeightCountTotal
 *   The total wieght count used in tensors. Not including Params, because they are not used in tensors. Including inferenced
 * weights, if they are used in tensors.
 *
 * @member {function} gather
 *   Permute and split the input tensor by gather. It is a function pointer to one of this.gather_XXX().
 *
 * @member {function} concatGather
 *   Concatenate, permute and split the input tensor by concat-gather. It is a function pointer to one of
 * this.concatGather_XXX().
 */
class ConcatGather extends Recyclable.Root {

  /**
   *
   * @param {number[]} concatenatedShape  Used to calculate shuffleInfo.
   * @param {number}   outputGroupCount   Used to calculate shuffleInfo.
   * @exception {Object} If failed (e.g. out of GPU memory).
   *
   * @see ShuffleInfo
   */
  constructor( concatenatedShape, outputGroupCount, ...restArgs ) {
    super( ...restArgs );
    ConcatGather.setAsConstructor.call( this, concatenatedShape, outputGroupCount );
  }

  /**
   *
   * @param {ShuffleInfo} this
   *   The object to be initialized.
   *
   * @param {number[]} concatenatedShape  Used to calculate shuffleInfo.
   * @param {number}   outputGroupCount   Used to calculate shuffleInfo.
   * @exception {Object} If failed (e.g. out of GPU memory).
   *
   * @return {ConcatGather}
   *   Return the this object.
   *
   * @see ShuffleInfo
   */
  static setAsConstructor( concatenatedShape, outputGroupCount ) {

    this.tensorWeightCountExtracted = 0;
    this.tensorWeightCountTotal = 0;

    this.shuffleInfo = ShuffleInfo.Pool.get_or_create_by( concatenatedShape, outputGroupCount );

    // Build shuffled channel index table (as an array of tf.tensor1d).
    //
    // It can be used by algorithm ConcatGather().
    // They should be integers so that can be used as tf.gather()'s index.
    //
    // Not like SplitConcat, the channel indexes will not be sorted here. According to testing, sorted
    // channel seems slow down memory access when using them as tf.gather()'s index list.
    {
      this.shuffledChannelIndicesTensor1dArray
        = tf.tidy( "ChannelShuffler.ConcatGather.init.shuffledChannelIndicesTensor1dArray", () => {
          let channelIndices = tf.range( 0, this.shuffleInfo.totalChannelCount, 1, "int32" );
          return Pool.All.sessionCall( () => {
            let channelIndicesShuffleInfo = ShuffleInfo.Pool.get_or_create_by( channelIndices.shape, outputGroupCount );
            return channelIndicesShuffleInfo.reshapeTransposeReshapeSplit( channelIndices );
          });
        });

      // Calculate total weight count.
      for ( let i = 0; i < this.shuffledChannelIndicesTensor1dArray.length; ++i ) {
        let shuffledChannelIndicesTensor1d = this.shuffledChannelIndicesTensor1dArray[ i ];
        if ( shuffledChannelIndicesTensor1d ) {
          this.tensorWeightCountTotal += shuffledChannelIndicesTensor1d.size;
        }
      }

    // Exception if failed (e.g. out of (GPU) memory).
    }

    this.gather = this.gather_loop;
    this.concatGather = this.concatGather_dispose_finally_call_loop;

    return this;
  }

  /**
   * Release tf.tensor.
   *
   * Sub-class should override this method (and call super.disposeResources() before return).
   */
  disposeResources() {
    this.concatGather = null;
    this.gather = null;

    this.tensorWeightCountTotal = 0;
    this.tensorWeightCountExtracted = 0;

    if ( this.shuffledChannelIndicesTensor1dArray ) {
      for ( let i = 0; i < this.shuffledChannelIndicesTensor1dArray.length; ++i ) {
        tf.dispose( this.shuffledChannelIndicesTensor1dArray[ i ] );
        this.shuffledChannelIndicesTensor1dArray[ i ] = null;
      }

//!!! (2022/06/25 Remarked) Now only Recyclable.Array could be recycled.
//      // Note: This array is generated by tensorflow.js (i.e. not by Pool.Array). Although it could be recycled by Pool.Array,
//      //       however, this could result in more and more array being cumulated (and then out of memory). So do not recycle it.
//      //
//      //Pool.Array.Singleton.recycle( this.shuffledChannelIndicesTensor1dArray );

      this.shuffledChannelIndicesTensor1dArray = null;
    }

    if ( this.shuffleInfo ) {
      this.shuffleInfo.disposeResources_and_recycleToPool();
      this.shuffleInfo = null;
    }

    //super.disposeResources();
  }

//!!! (2022/06/25 Remarked) Inherits from Recyclable.Base instead.
//   /**
//    * After calling this method, this object should be viewed as disposed and should not be operated again.
//    *
//    * Sub-class should override this method for recycling to its pool (and NEVER call super.disposeResources_and_recycleToPool()).
//    */
//   disposeResources_and_recycleToPool() {
//     this.disposeResources();
//     ConcatGatherPool.Singleton.recycle( this );
//   }

  get concatenatedShape() {
    return this.shuffleInfo.concatenatedShape;
  }

  get outputGroupCount() {
    return this.shuffleInfo.outputGroupCount;
  }

  /**
   * Permute and split the input tensor by gather.
   *
   * @param {tf.tensor} concatenatedTensor
   *   An single tensor (not array) to be processed. It should conform to this.shuffleInfo.concatenatedShape.
   *
   * @return {tf.tensor[]}
   *   An array of shuffled tensors. Their total channel count is the same as concatenated tensorArray, but their
   * last dimensions are shuffled.
   */
  gather_loop( concatenatedTensor ) {
    let shuffledSplitedTensorArray = new Array( this.shuffledChannelIndicesTensor1dArray.length );
    for ( let i = 0; i < shuffledSplitedTensorArray.length; ++i ) {
      // shuffle and split by gather (one operation achieves two operations).
      shuffledSplitedTensorArray[ i ] = concatenatedTensor.gather( this.shuffledChannelIndicesTensor1dArray[ i ], this.shuffleInfo.lastAxisId );
    }
    return shuffledSplitedTensorArray;
  }

  /**
   * Concatenate, permute and split the input tensor by concat-gather.
   *
   * @param {tf.tensor[]} tensorArray
   *   An array of tensors to be processed. It should conform to this.concatenatedShape.
   *
   * @return {tf.tensor[]}
   *   An array of shuffled tensors. Their total channel count is the same as concatenated tensorArray, but their
   * last dimensions are shuffled.
   */
  concatGather_dispose_finally_call_loop( tensorArray ) {
    let concatenatedTensor = tf.concat( tensorArray, this.shuffleInfo.lastAxisId );

    try {
      return this.gather_loop( concatenatedTensor );

    } finally {
      concatenatedTensor.dispose();
    }
  }
}

/**
 * Providing ChannelShuffler.ConcatGather
 *
 */
class ConcatGatherPool extends Pool.Root {

  constructor() {
    super( "ChannelShuffler.ConcatGatherPool", ConcatGather, ConcatGather.setAsConstructor );
  }

}

/**
 * Used as default ChannelShuffler.ConcatGather provider for conforming to Recyclable interface.
 */
ConcatGather.Pool = new ConcatGatherPool();
<|endoftext|>


<commit_before>"use strict";

class gswaEffects {
	constructor( fns ) {
		this.ctx = null;
		this._getChanInput = fns.getChanInput;
		this._getChanOutput = fns.getChanOutput;
		this._wafxs = new Map();
		this.gsdata = new GSDataEffects( {
			dataCallbacks: {
				toggleFx: this._toggleFx.bind( this ),
				removeFx: this._removeFx.bind( this ),
				changeFxData: this._changeFxData.bind( this ),
			},
		} );
		Object.seal( this );
	}

	// .........................................................................
	setContext( ctx ) {
		this.ctx = ctx;
		this._wafxs.forEach( fx => fx.setContext( ctx ) );
	}
	setBPM( bpm ) {
		this._wafxs.forEach( fx => fx.setBPM && fx.setBPM( bpm ) );
	}
	change( obj ) {
		this.gsdata.change( obj );
	}
	clear() {
		this.gsdata.clear();
	}

	// .........................................................................
	_toggleFx( id, b ) {
		if ( !b ) {
			this._removeFx( id );
		} else if ( !this._wafxs.has( id ) ) {
			this._addFx( id, this.gsdata.data[ id ] );
		}
	}
	_addFx( id, fx ) {
		const wafx = new ( gswaEffects.fxsMap.get( fx.type ) )(),
			chanIn = this._getChanInput( fx.dest ),
			chanOut = this._getChanOutput( fx.dest );

		this._wafxs.set( id, wafx );
		wafx.setContext( this.ctx );
		chanIn.disconnect(); // still work to do here
		chanIn.connect( wafx.input );
		wafx.output.connect( chanOut );
	}
	_changeFxData( id, fxData ) {
		this._wafxs.get( id ).change( fxData );
	}
	_removeFx( id ) {
		const wafx = this._wafxs.get( id );

		wafx.output.disconnect();
		this._wafxs.delete( id );
	}
}

gswaEffects.fxsMap = new Map();
Object.freeze( gswaEffects );
<commit_msg>gswaEffects: liveChangeFxProp<commit_after>"use strict";

class gswaEffects {
	constructor( fns ) {
		this.ctx = null;
		this._getChanInput = fns.getChanInput;
		this._getChanOutput = fns.getChanOutput;
		this._wafxs = new Map();
		this.gsdata = new GSDataEffects( {
			dataCallbacks: {
				toggleFx: this._toggleFx.bind( this ),
				removeFx: this._removeFx.bind( this ),
				changeFxData: this._changeFxData.bind( this ),
			},
		} );
		Object.seal( this );
	}

	// .........................................................................
	setContext( ctx ) {
		this.ctx = ctx;
		this._wafxs.forEach( fx => fx.setContext( ctx ) );
	}
	setBPM( bpm ) {
		this._wafxs.forEach( fx => fx.setBPM && fx.setBPM( bpm ) );
	}
	change( obj ) {
		this.gsdata.change( obj );
	}
	clear() {
		this.gsdata.clear();
	}
	liveChangeFxProp( id, prop, val ) {
		this._wafxs.get( id ).liveChange( prop, val );
	}

	// .........................................................................
	_toggleFx( id, b ) {
		if ( !b ) {
			this._removeFx( id );
		} else if ( !this._wafxs.has( id ) ) {
			this._addFx( id, this.gsdata.data[ id ] );
		}
	}
	_addFx( id, fx ) {
		const wafx = new ( gswaEffects.fxsMap.get( fx.type ) )(),
			chanIn = this._getChanInput( fx.dest ),
			chanOut = this._getChanOutput( fx.dest );

		this._wafxs.set( id, wafx );
		wafx.setContext( this.ctx );
		chanIn.disconnect(); // still work to do here
		chanIn.connect( wafx.input );
		wafx.output.connect( chanOut );
	}
	_changeFxData( id, fxData ) {
		this._wafxs.get( id ).change( fxData );
	}
	_removeFx( id ) {
		const wafx = this._wafxs.get( id );

		wafx.output.disconnect();
		this._wafxs.delete( id );
	}
}

gswaEffects.fxsMap = new Map();
Object.freeze( gswaEffects );
<|endoftext|>


<commit_before>const WINNING_COUNT = 4;

const DecideGameWinner = (board) => {
  if (horizontalCheck(board).isGameOver || verticalCheck(board).isGameOver) {
    return true
  }
}

const horizontalCheck = (board) => {
  var rowIndex, columnIndex, redCount = 0, blueCount = 0;
  let winnerObj = {};
  // Loop through all rows
  for (rowIndex = 0; rowIndex < board.length; rowIndex++) {

    // Loop through all the columns
    for (columnIndex = 0; columnIndex < board[rowIndex].length; columnIndex++) {
      if (board[rowIndex][columnIndex] === 'red') {
        redCount ++;
        blueCount = 0
      } else if (board[rowIndex][columnIndex] === 'blue') {
        blueCount ++;
        redCount = 0;
      }

      if (redCount === WINNING_COUNT) {
        winnerObj.isGameOver = true;
        winnerObj.winner = 'red';
        break;
      }

      if (blueCount === WINNING_COUNT) {
        winnerObj.isGameOver = true;
        winnerObj.winner = 'blue';
        break;
      }
    }

    redCount = 0;
    blueCount = 0
  }

  return winnerObj
}

const verticalCheck = (board) => {
  var rowIndex, columnIndex, redCount = 0, blueCount = 0;
  let winnerObj = {};
  // Loop through all columns
  for (columnIndex = 0; columnIndex < board[0].length; columnIndex++) {

    // Loop through all the row cells
    for (rowIndex = 0; rowIndex < board.length; rowIndex++) {
      if (board[rowIndex][columnIndex] === 'red') {
        // Increase Respective count and set other color count to 0 as cells have to be continuos
        redCount ++;
        blueCount = 0;
      } else if (board[rowIndex][columnIndex] === 'blue') {
        blueCount ++;
        redCount = 0;
      }

      if (redCount === WINNING_COUNT) {
        winnerObj.isGameOver = true;
        winnerObj.winner = 'red';
        break;
      }

      if (blueCount === WINNING_COUNT) {
        winnerObj.isGameOver = true;
        winnerObj.winner = 'blue';
        break;
      }
    }

    redCount = 0;
    blueCount = 0
  }

  return winnerObj

}

const diagonalCheck = (board) => {
  var rowIndex, columnIndex, redCount = 0, blueCount = 0;
  let winnerObj = {};
  const rowLength = board.length;
  const columnLength = board[0].length;

  var maxLength = Math.max(rowLength, columnLength);

  var temp;

  for (var k = 0; k <= 2 * (maxLength - 1); ++k) {
      temp = [];
      for (var y = columnLength - 1; y >= 0; --y) {
          var x = k - y;
          if (x >= 0 && x < rowLength) {
              console.log(board[x][y])
          }
      }
  }

}

export default DecideGameWinner;<commit_msg>top left diagonal logic<commit_after>const WINNING_COUNT = 4;

const DecideGameWinner = (board) => {
  if (horizontalCheck(board).isGameOver || verticalCheck(board).isGameOver || topLeftDiagonalCheck(board).isGameOver) {
    return true
  }
}

const horizontalCheck = (board) => {
  var rowIndex, columnIndex, redCount = 0, blueCount = 0;
  let winnerObj = {};
  // Loop through all rows
  for (rowIndex = 0; rowIndex < board.length; rowIndex++) {

    // Loop through all the columns
    for (columnIndex = 0; columnIndex < board[rowIndex].length; columnIndex++) {
      if (board[rowIndex][columnIndex] === 'red') {
        redCount ++;
        blueCount = 0
      } else if (board[rowIndex][columnIndex] === 'blue') {
        blueCount ++;
        redCount = 0;
      }

      if (redCount === WINNING_COUNT) {
        winnerObj.isGameOver = true;
        winnerObj.winner = 'red';
        break;
      }

      if (blueCount === WINNING_COUNT) {
        winnerObj.isGameOver = true;
        winnerObj.winner = 'blue';
        break;
      }
    }

    redCount = 0;
    blueCount = 0
  }

  return winnerObj
}

const verticalCheck = (board) => {
  var rowIndex, columnIndex, redCount = 0, blueCount = 0;
  let winnerObj = {};
  // Loop through all columns
  for (columnIndex = 0; columnIndex < board[0].length; columnIndex++) {

    // Loop through all the row cells
    for (rowIndex = 0; rowIndex < board.length; rowIndex++) {
      if (board[rowIndex][columnIndex] === 'red') {
        // Increase Respective count and set other color count to 0 as cells have to be continuos
        redCount ++;
        blueCount = 0;
      } else if (board[rowIndex][columnIndex] === 'blue') {
        blueCount ++;
        redCount = 0;
      }

      if (redCount === WINNING_COUNT) {
        winnerObj.isGameOver = true;
        winnerObj.winner = 'red';
        break;
      }

      if (blueCount === WINNING_COUNT) {
        winnerObj.isGameOver = true;
        winnerObj.winner = 'blue';
        break;
      }
    }

    redCount = 0;
    blueCount = 0
  }

  return winnerObj

}

const topLeftDiagonalCheck = (board) => {
  var redCount = 0, blueCount = 0;
  let winnerObj = {};
  const rowLength = board.length;
  const columnLength = board[0].length;

  /*
  * Really Terrible algo complexity.. :(
  */
  var maxLength = Math.max(columnLength, rowLength);
  for (var k = 0; k <= 2 * (maxLength - 1); ++k) {
      for (var y = rowLength - 1; y >= 0; --y) {
          var x = k - y;
          if (x >= 0 && x < columnLength) {
            if (board[y][x] === 'red') {
              redCount ++;
              blueCount = 0;
            } else if (board[y][x] === 'blue') {
              blueCount ++;
              redCount = 0;
            }

            if (redCount === WINNING_COUNT) {
              winnerObj.isGameOver = true;
              winnerObj.winner = 'red';
              break;
            }

            if (blueCount === WINNING_COUNT) {
              winnerObj.isGameOver = true;
              winnerObj.winner = 'blue';
              break;
            }
          }
      }

      redCount = 0;
      blueCount = 0;
  }

  return winnerObj;

}

export default DecideGameWinner;<|endoftext|>


<commit_before>importPackage(Packages.java.lang);
importPackage(Packages.de.fhhannover.inform.trust.ironvas);

/* The 'filter'-Method gets called by ironvas, if it returns
 * false for the given vulnerability the vulnerability is
 * discarded from further processing.
 */
function filter(vulnerability) {
	//return true; // default process all vulnerability
	return filterByThreatLevel(vulnerability);
}

//*****************************************************************************

function filterByThreatLevel(vulnerability) {
	var minLevel = ThreatLevel.Low;

	if (vulnerability.getThreat().compareTo(minLevel) < 0) {
		return false;
	}
	else {
		return true;
	}
}

<commit_msg>ironvas: change default vulnerability filter<commit_after>importPackage(Packages.java.lang);
importPackage(Packages.de.fhhannover.inform.trust.ironvas);

/* The 'filter'-Method gets called by ironvas, if it returns
 * false for the given vulnerability the vulnerability is
 * discarded from further processing.
 */
function filter(vulnerability) {
	return true; // default process all vulnerability
	//return filterByThreatLevel(vulnerability);
}

//*****************************************************************************

function filterByThreatLevel(vulnerability) {
	var minLevel = ThreatLevel.Low;

	if (vulnerability.getThreat().compareTo(minLevel) < 0) {
		return false;
	}
	else {
		return true;
	}
}

<|endoftext|>