<commit_before>const Writable = require('stream').Writable;

function isBlankNode (string) {
    return string.indexOf('_:') === 0;
}

module.exports = (scope, event, args) => {
    return new Writable({
        objectMode: true,
        write: (triple, enc, done) => {

            let subject = triple[0] || triple.subject;
            let predicate = triple[1] || triple.predicate;
            let object = triple[2] || triple.object;

            switch (predicate) {

                case 'http://schema.jillix.net/vocab/onEnd':
                    event.e = object;
                    break;

                case 'http://schema.jillix.net/vocab/onError':
                    event.r = object;
                    break;

                case 'http://schema.jillix.net/vocab/module':
                    event.module(subject, object);
                    break;

                case 'http://schema.jillix.net/vocab/roles':
                    event.instance(subject, 'role', object);
                    break;

                case 'http://schema.jillix.net/vocab/args':

                    try {
                        object = JSON.parse(object.slice(1, -1));
                    } catch (error) {
                        event.emit('error', error);
                        break;
                    }

                    if (isBlankNode(subject)) {
                        event.handler(subject, 'args', object);
                        break;
                    }

                    event.instance(subject, 'args', object);
                    break;

                case 'http://schema.jillix.net/vocab/sequence':

                    if (isBlankNode(subject)) {
                        event.handler(subject, 'next', object);
                        break;
                    }

                    event.handler(object, 'first', true);
                    break;

                case 'http://schema.jillix.net/vocab/instance':
                    event.handler(subject, 'instance', object);
                    break;

                case 'http://schema.jillix.net/vocab/dataHandler':
                    event.handler(subject, 'data', object.split('#')[1]);
                    break;

                case 'http://schema.jillix.net/vocab/streamHandler':
                    event.handler(subject, 'stream', object.split('#')[1]);
                    break;

                case 'http://schema.jillix.net/vocab/emit':
                    event.handler(subject, 'emit', object);
                    break;

                default:
                    console.log('[Parser] Unknown triple:', predicate);
            }

            done();
        }
    });
};
<commit_msg>use Module and Instance loaders<commit_after>const Writable = require('stream').Writable;
const Module = require('./Module');
const Instance = require('./Instance');

function isBlankNode (string) {
    return string.indexOf('_:') === 0;
}

module.exports = (scope, event, args) => {
    return new Writable({
        objectMode: true,
        write: (triple, enc, done) => {

            let subject = triple[0] || triple.subject;
            let predicate = triple[1] || triple.predicate;
            let object = triple[2] || triple.object;

            switch (predicate) {

                case 'http://schema.jillix.net/vocab/onEnd':
                    event.set('e', object);
                    break;

                case 'http://schema.jillix.net/vocab/onError':
                    event.set('r', object);
                    break;

                case 'http://schema.jillix.net/vocab/module':
                    Module(scope, args, object, (error, module) => {

                        if (error) {
                            return event.error(error);
                        }

                        Instance(scope, args, subject, 'module', module);
                    });
                    break;

                case 'http://schema.jillix.net/vocab/roles':
                    Instance(scope, args, subject, (error, instance) => {

                        if (error) {
                            return event.error(error);
                        }

                        instance.role(object);
                    });
                    break;

                case 'http://schema.jillix.net/vocab/args':

                    try {
                        object = JSON.parse(object.slice(1, -1));
                    } catch (error) {
                        event.error(error);
                        break;
                    }

                    if (isBlankNode(subject)) {
                        event.handler(subject, 'args', object);
                        break;
                    }

                    Instance(scope, args, subject, (error, instance) => {

                        if (error) {
                            return event.error(error);
                        }

                        instance.args(object);
                    });
                    break;

                case 'http://schema.jillix.net/vocab/sequence':

                    if (isBlankNode(subject)) {
                        event.handler(subject, 'next', object);
                        break;
                    }

                    event.handler(object, 'first', true);
                    break;

                case 'http://schema.jillix.net/vocab/instance':
                    ++event.load;
                    Instance(scope, args, object, (error, instance) => {

                        if (error) {
                            return event.error(error);
                        }

                        event.handler(subject, 'instance', instance);
                        event.done(event);
                    });
                    break;

                case 'http://schema.jillix.net/vocab/dataHandler':
                    event.handler(subject, 'data', object.split('#')[1]);
                    break;

                case 'http://schema.jillix.net/vocab/streamHandler':
                    event.handler(subject, 'stream', object.split('#')[1]);
                    break;

                case 'http://schema.jillix.net/vocab/emit':
                    ++event.load;
                    event.handler(subject, 'emit', object);
                    event.done(event);
                    break;

                default:
                    console.log('[Parser] Unknown triple:', predicate);
            }

            done();
        }
    });
};
<|endoftext|>


<commit_before>(function($, $$) {

var _ = Mavo.Locale = $.Class({
	constructor: function(lang, phrases) {
		this.lang = lang;
		this.phrases = {};
		this.extend(phrases);
	},

	get fallback() {
		// TODO should we fallback to other dialects? I.e. should en-US fallback to en-GB if en didn't exist?
		if (_.all[this.baseLang]) {
			return _.all[this.baseLang];
		}

		if (this !== _.default) {
			return _.default;
		}
	},

	extend: function(phrases) {
		$.extend(this.phrases, phrases);
	},

	phrase: function(id, vars) {
		var key = id.toLowerCase();
		var phrase = this.phrases[key];

		if (phrase === undefined && this.fallback) {
			phrase = this.fallback.phrase(key);
		}

		if (phrase === undefined) {
			// Everything failed, use id
			phrase = Mavo.Functions.readable(key);
		}
		else if (vars) {
			var keys = Mavo.matches(phrase, /\{\w+(?=\})/g).map(v => v.slice(1));
			Mavo.Functions.unique(keys).forEach(name => {
				if (name in vars) {
					phrase = phrase.replace(RegExp(`{${name}}`, "gi"), vars[name]);
				}
			});
		}

		return phrase;
	},

	live: {
		lang: function(lang) {
			this.baseLang = _.getBaseLang(lang);

			if (lang == this.baseLang) {
				this.baseLang = null;
			}
		}
	},

	static: {
		all: {},

		/**
		 * Register new locale or extend existing locale
		 */
		register: function(lang, phrases) {
			if (_.all[lang]) {
				_.all[lang].extend(phrases);
			}
			else {
				_.all[lang] = new _(lang, phrases);
			}
		},

		// Get locale for a given language, use its base as fallback
		match: function(lang = "") {
			return _.all[lang] || _.all[_.getBaseLang(lang)];
		},

		// Get locale for a given language, use its base as fallback, and the default locale if nothing exists
		get: function(lang) {
			return _.match(lang) || _.default;
		},

		getBaseLang: function(lang) {
			return lang.split("-")[0];
		},

		lazy: {
			default: () => {
				return _.match(Mavo.locale) || _.all.en;
			}
		}
	}
});

/**
 * Use phrase
 */
Mavo.prototype._ = function(id, vars) {
	return this.locale && id? this.locale.phrase(id, vars) : id;
};

$.ready().then(() => {
	$$("datalist.mv-phrases[lang]").forEach(datalist => {
		var phrases = $$("option", datalist).reduce((o, option) => {
			o[option.value] = option.textContent.trim();
			return o;
		}, {});

		Mavo.Locale.register(datalist.lang, phrases);
	});
});

})(Bliss, Bliss.$);
<commit_msg>Do not capitalize id if no translation is found, just replace hyphens<commit_after>(function($, $$) {

var _ = Mavo.Locale = $.Class({
	constructor: function(lang, phrases) {
		this.lang = lang;
		this.phrases = {};
		this.extend(phrases);
	},

	get fallback() {
		// TODO should we fallback to other dialects? I.e. should en-US fallback to en-GB if en didn't exist?
		if (_.all[this.baseLang]) {
			return _.all[this.baseLang];
		}

		if (this !== _.default) {
			return _.default;
		}
	},

	extend: function(phrases) {
		$.extend(this.phrases, phrases);
	},

	phrase: function(id, vars) {
		var key = id.toLowerCase();
		var phrase = this.phrases[key];

		if (phrase === undefined && this.fallback) {
			phrase = this.fallback.phrase(key);
		}

		if (phrase === undefined) {
			// Everything failed, use id
			phrase = key.replace(/\b-\b/g, " ");
		}
		else if (vars) {
			var keys = Mavo.matches(phrase, /\{\w+(?=\})/g).map(v => v.slice(1));
			Mavo.Functions.unique(keys).forEach(name => {
				if (name in vars) {
					phrase = phrase.replace(RegExp(`{${name}}`, "gi"), vars[name]);
				}
			});
		}

		return phrase;
	},

	live: {
		lang: function(lang) {
			this.baseLang = _.getBaseLang(lang);

			if (lang == this.baseLang) {
				this.baseLang = null;
			}
		}
	},

	static: {
		all: {},

		/**
		 * Register new locale or extend existing locale
		 */
		register: function(lang, phrases) {
			if (_.all[lang]) {
				_.all[lang].extend(phrases);
			}
			else {
				_.all[lang] = new _(lang, phrases);
			}
		},

		// Get locale for a given language, use its base as fallback
		match: function(lang = "") {
			return _.all[lang] || _.all[_.getBaseLang(lang)];
		},

		// Get locale for a given language, use its base as fallback, and the default locale if nothing exists
		get: function(lang) {
			return _.match(lang) || _.default;
		},

		getBaseLang: function(lang) {
			return lang.split("-")[0];
		},

		lazy: {
			default: () => {
				return _.match(Mavo.locale) || _.all.en;
			}
		}
	}
});

/**
 * Use phrase
 */
Mavo.prototype._ = function(id, vars) {
	return this.locale && id? this.locale.phrase(id, vars) : id;
};

$.ready().then(() => {
	$$("datalist.mv-phrases[lang]").forEach(datalist => {
		var phrases = $$("option", datalist).reduce((o, option) => {
			o[option.value] = option.textContent.trim();
			return o;
		}, {});

		Mavo.Locale.register(datalist.lang, phrases);
	});
});

})(Bliss, Bliss.$);
<|endoftext|>


<commit_before>const { is } = require('./utils');
const errors = require('./errors');
const chalk = require('chalk');

// Special chars.
let chevron = '\xBB';
let checkmark = '\u2713';
let octopus = '\uD83D\uDC19'; // jshint ignore:line
// Helpers.
let br = str => `[${str}]`; // Wrap in brackets.

export default class Logger {
  constructor(verbose = false, debug = false) {
    this.verbose = verbose;
    this._debug = debug;
    this._times = [];
  }

  /**
   * Log arguments into stderr if the verbose mode is enabled.
   */
  log(...args) {
    if (this.verbose) {
      console.error(chalk.green(chevron), ...args);
    }
  }

  info(...args) {
    return this.log(...args);
  }

  /**
   * Always log arguments as warning into stderr.
   */
  warn(...args) {
    chalkHack(() =>
      console.error(chalk.yellow(chevron), br('WARNING'), ...args)
    );
  }

  /**
   * Always log arguments as error into stderr.
   */
  error(...args) {
    chalkHack(() =>
      console.error(chalk.red(chevron), br('ERROR'), ...args)
    );
  }

  /**
   * Init a new timer.
   * @param {String} label
   */
  time(label) {
    this._times[label] = Date.now();
  }

  /**
   * End timer and log result.
   * @param {String} label
   * @param {String} format
   */
  timeEnd(label, format) {
    let time = this._times[label];
    if (!time) {
      throw new Error(`No such label: ${label}`);
    }

    let duration = Date.now() - time;
    console.error(`${chalk.green(checkmark)} ${format}`, label, duration);
  }

  /**
   * Log arguments into stderr if debug mode is enabled (will call all
   * argument functions to allow "lazy" arguments).
   */
  debug(...args) {
    if (this._debug) {
      chalkHack(() => {
        console.error(chalk.grey(br('DEBUG'), ...args.map(f => {
          if (f instanceof Function) {
            return f();
          }

          return f;
        })));
      });
    }
  }
}

export var empty = {
  log: () => {},
  warn: () => {},
  error: () => {},
  debug: () => {},
};

/**
 * Checks if given object looks like a logger.
 *
 * If the `debug` function is missing (like for the `console` object),
 * it will be set to an empty function in a newly returned object.
 *
 * If any other method is missing, an exception is thrown.
 *
 * @param {Object} logger
 * @return {Logger}
 * @throws {SassDocError}
 */
export function checkLogger(logger) {
  const methods = ['log', 'warn', 'error']
    .filter(x => !(x in logger) || !is.function(logger[x]));

  if (methods.length) {
    const missing = `"${methods.join('", "')}"`;
    const s = methods.length > 1 ? 's' : '';

    throw new errors.SassDocError(`Invalid logger, missing ${missing} method${s}`);
  }

  if ('debug' in logger) {
    return logger;
  }

  return {
    log: logger.log,
    warn: logger.warn,
    error: logger.error,
    debug: empty.debug,
  };
}

/**
 * Chalk don't allow us to create a new instance with our own `enabled`
 * value (internal functions always reference the global export). Here
 * we want to enable it if stderr is a TTY, but it's not acceptable to
 * modify the global context for this purpose.
 *
 * So this hack will set `chalk.enabled` for the time of the synchronous
 * callback execution, then reset it to whatever was its default value.
 */
function chalkHack(cb) {
  let enabled = chalk.enabled;
  chalk.enabled = process.stderr.isTTY;
  cb();
  chalk.enabled = enabled;
}
<commit_msg>Don't print final success message on non verbose mode<commit_after>const { is } = require('./utils');
const errors = require('./errors');
const chalk = require('chalk');

// Special chars.
let chevron = '\xBB';
let checkmark = '\u2713';
let octopus = '\uD83D\uDC19'; // jshint ignore:line
// Helpers.
let br = str => `[${str}]`; // Wrap in brackets.

export default class Logger {
  constructor(verbose = false, debug = false) {
    this.verbose = verbose;
    this._debug = debug;
    this._times = [];
  }

  /**
   * Log arguments into stderr if the verbose mode is enabled.
   */
  log(...args) {
    if (this.verbose) {
      console.error(chalk.green(chevron), ...args);
    }
  }

  info(...args) {
    return this.log(...args);
  }

  /**
   * Always log arguments as warning into stderr.
   */
  warn(...args) {
    chalkHack(() =>
      console.error(chalk.yellow(chevron), br('WARNING'), ...args)
    );
  }

  /**
   * Always log arguments as error into stderr.
   */
  error(...args) {
    chalkHack(() =>
      console.error(chalk.red(chevron), br('ERROR'), ...args)
    );
  }

  /**
   * Init a new timer.
   * @param {String} label
   */
  time(label) {
    this._times[label] = Date.now();
  }

  /**
   * End timer and log result.
   * @param {String} label
   * @param {String} format
   */
  timeEnd(label, format) {
    if (!this.verbose) {
      return;
    }

    let time = this._times[label];
    if (!time) {
      throw new Error(`No such label: ${label}`);
    }

    let duration = Date.now() - time;
    console.error(`${chalk.green(checkmark)} ${format}`, label, duration);
  }

  /**
   * Log arguments into stderr if debug mode is enabled (will call all
   * argument functions to allow "lazy" arguments).
   */
  debug(...args) {
    if (this._debug) {
      chalkHack(() => {
        console.error(chalk.grey(br('DEBUG'), ...args.map(f => {
          if (f instanceof Function) {
            return f();
          }

          return f;
        })));
      });
    }
  }
}

export var empty = {
  log: () => {},
  warn: () => {},
  error: () => {},
  debug: () => {},
};

/**
 * Checks if given object looks like a logger.
 *
 * If the `debug` function is missing (like for the `console` object),
 * it will be set to an empty function in a newly returned object.
 *
 * If any other method is missing, an exception is thrown.
 *
 * @param {Object} logger
 * @return {Logger}
 * @throws {SassDocError}
 */
export function checkLogger(logger) {
  const methods = ['log', 'warn', 'error']
    .filter(x => !(x in logger) || !is.function(logger[x]));

  if (methods.length) {
    const missing = `"${methods.join('", "')}"`;
    const s = methods.length > 1 ? 's' : '';

    throw new errors.SassDocError(`Invalid logger, missing ${missing} method${s}`);
  }

  if ('debug' in logger) {
    return logger;
  }

  return {
    log: logger.log,
    warn: logger.warn,
    error: logger.error,
    debug: empty.debug,
  };
}

/**
 * Chalk don't allow us to create a new instance with our own `enabled`
 * value (internal functions always reference the global export). Here
 * we want to enable it if stderr is a TTY, but it's not acceptable to
 * modify the global context for this purpose.
 *
 * So this hack will set `chalk.enabled` for the time of the synchronous
 * callback execution, then reset it to whatever was its default value.
 */
function chalkHack(cb) {
  let enabled = chalk.enabled;
  chalk.enabled = process.stderr.isTTY;
  cb();
  chalk.enabled = enabled;
}
<|endoftext|>


<commit_before>const winston = require('winston');

const { printf, timestamp, combine } = winston.format;

const chatFormat = printf((info) =>
    `${info.timestamp} [${info.level}]: ChatId ${info.chatId}. "${
        info.message
    }"`);

const logger = winston.createLogger({
    level: 'info',
    format: combine(timestamp(), chatFormat),
    transports: [
        new winston.transports.File({ filename: 'error.log', level: 'info' })
    ]
});

module.exports = { logger };
<commit_msg>Allow pass random objects to logger<commit_after>const winston = require('winston');

const { printf, timestamp, combine } = winston.format;

const chatFormat = printf((info) =>
    info.chatId
        ? `${info.timestamp} [${info.level}]: ChatId ${info.chatId}. "${info.message}"`
        : JSON.stringify(info)
);

const logger = winston.createLogger({
    level: 'info',
    format: combine(timestamp(), chatFormat),
    transports: [
        new winston.transports.File({ filename: 'error.log', level: 'info' })
    ]
});

module.exports = { logger };
<|endoftext|>


<commit_before>/**
 * @module logger
 * @summary: Provides a logger instance.
 *
 * @description:
 *
 * Author: m0ser
 * Created On: 2015-10-28.
 * @license Apache-2.0
 */

 var _ = require('lodash'),
   p = require('bluebird'),
   Promise = p

var _plugins, _observers = {}
module.exports = function(config, deps) {
  var m = post.bind(null,'info'),
		_context = deps.context || {},
    log = deps.log,
		_ringBuff = deps.ringBuff,
		_plugins = deps.plugins || _plugins

	// TODO: figure why this is here.
  _context = _.defaults(_context, {
    observers: {},
    chain: config.module || ''
  })

  m.context = function(contextInfo) {
		if (config.debug && !config.silent) console.log('Logger: Creating context...', contextInfo)
		if (contextInfo.opts) {
			if (contextInfo.opts.isModule) {
				// must clone the config to avoid isModule flag from permeating.
				// Not sure a better way to handle this.  isModule is set by libraries
				// when they are created with a logger instance.
				config = _.cloneDeep(config)
				config.isModule = true
			}
		}

    contextInfo.chain = _context.chain
    if (contextInfo.module) {
      contextInfo.chain = contextInfo.module.name
    } else {
      contextInfo.chain += '.'+contextInfo.name
    }

    var newLogger = module.exports(config, {
         log: log.child({chain: contextInfo.chain}),
         context: _.extend(new Context(_context), contextInfo),
				 ringBuff: deps.ringBuff
       })

    newLogger.parent = m
    return newLogger
  }

  m.module = function(moduleName, args, opts) {
    return m.context({module: {
      name: moduleName,
      args: args,
			opts: opts
    }})
  }

  m.debug = post.bind(m, 'debug')
  m.info = post.bind(m,'info')
  m.fatal = post.bind(m, 'fatal')
  m.error = post.bind(m, 'error')
  m.logError = post.bind(m, 'error')
  m.warn = post.bind(m, 'warn')
  m.log = post.bind(m, 'info')
  m.trace = post.bind(m,'trace')

  // difference between method and goal: a method can fail and be recovered from.
  // a goal is something that is not recovered from and should never fail.  You
  // always want to be alerted if a goal fails, because if a goal fails, your
  // application is not doing its job.
  m.method = createGoal.bind(m, 'method')
  m.goal = createGoal.bind(m, 'goal')

	// TODO: coming soon...  The ability to query the log.
  m.query = function() { throw new Error('log.query() unsupported')}
	//	m.query = _plugins['loggly'] ? _plugins['loggly'].query : function() {
	//    throw new Error('log.query() not available.  Load a plugin that supports it.')
	//  }

  function createGoal(type, goalName, params, opts) {
    opts = opts || {}
    opts.type = type
    var newGoalInstance = new Goal(goalName, params, opts)
    m.log('Starting '+goalName, {params: params}, {custom: {goalId: newGoalInstance.goalId}})
    var newGoal = m.context({
      goalInstance: newGoalInstance,
      name: goalName
    })

    return newGoal
  }

	m.report = function(err, prev, details) {
		if (!(err instanceof Error)) {
      console.log('ErrorReport:', err)
      if (config.env != 'prod' && config.env != 'production')
        throw new Error('ASSERT:report:InvalidParam "err"')
    }
		if (prev && !(prev instanceof Error)) {
			details = prev
		}
    details = details || {}

    err.prev = prev
		err.details = details
    var type = typeof err
    if (type != 'Error' || type != 'error' || type != 'object') err.type

		var errorDetails = err.message.split(':')
		if (errorDetails.length == 3) {
			err.category = errorDetails[0]
			err.activity = errorDetails[1]
			err.message = errorDetails[2]
		}
    // depending on how many colons are used in the error message,
    // we can remain backward compatible with previous error formats by
    // checking how many colons there are.
		if (errorDetails.length == 4) {
			err.category = errorDetails[0]
			err.activity = errorDetails[1]
			err.code = errorDetails[2]
      err.message = errorDetails[3]
		}
		if (!err.code)
		  err.code = details.code || err.type || err.message

    err.timestamp = Date.now()
    err.goalId = _context.goalInstance && _context.goalInstance.goalId
    err.goalName = _context.goalInstance && _context.goalInstance.name

    m.log('ErrorDetails', details)
    m.log('ErrorReport', err)

		if (err.category == 'USER') m.warn(err.message, err, {custom: details.custom})
		else m.error(err.message, err, {custom: details.custom})

		return err
	}

  m.failSuppressed = function (error) {
		m.report(error)
    var result = {err: error}

    if (_context && _context.goalInstance) {
      var goalReport = result.goalReport = _context.goalInstance.report("FAILED")
      m.error('Failed '+goalReport.goalName+'.', {
        goalId: goalReport.goalId,
        name: goalReport.goalName,
        codeName: goalReport.codeName,
				err: error
      }, {tags: 'GOAL-COMPLETE,GOAL-FAILED', custom: {goalReport: goalReport, goalDuration: goalReport.duration}})
    }

		return error
  }

  m.fail = function(err) {
    throw m.failSuppressed(err)
  }

  m.rejectWithCode = function(code) {
    return function(err) {
      throw m.report(err, {code: code})
    }
  }

  m.pass = m.result = function(result) {
    if (_context && _context.goalInstance) {
      var goalReport = _context.goalInstance.report('SUCCEEDED', result)
      m.log('Finished '+goalReport.goalName+'.', {
        goalId: goalReport.goalId,
        name: goalReport.goalName,
        goalName: goalReport.codeName
      }, {
        tags: 'GOAL-COMPLETE',
        custom: {goalReport: goalReport, goalDuration: goalReport.duration},
        priority: _context.goalInstance.priority || 10
      })
    } else {
      m.log('Result: ', _context)
    }

    return result
  }

  /**
   * Checks for any event handlers that match this event label and runs them
   * all.
   *
   * @param  {string} eventLabel The label for the event.
   * @param  {type} details    description
   * @param  {type} options    description
   * @return {type}            description
   */
  m.processEventHandlers = function(eventLabel, details, options) {
    var event = {
      eventName: eventLabel,
      handled: false
    }

    if (_context.observers[eventLabel]) {
      return p.map(_context.observers[eventLabel], function(cb) {
        if (!event.handled) return cb(event, details);
      }, {concurrency: 1})
    } else if (m.parent) {
      return m.parent.processEventHandlers(eventLabel, details, options)
    } else if (_observers[eventLabel]) {
      return p.map(_observers[eventLabel], function(cb) {
        if (!event.handled) return cb(event, details);
      }, {concurrency: 1})
    }

    return p.resolve()
  }

  m.addEventHandler = function(eventLabel, handler) {
    _context.observers[eventLabel] = _context.observers[eventLabel] || []
    _context.observers[eventLabel].push(handler)

    _observers[eventLabel] = _observers[eventLabel] || []
    _observers[eventLabel].push(handler)

		return function() {
			m.removeEventHandler(eventLabel, handler)
		}
  }

  m.removeEventHandler = function(eventLabel, handler) {
    //console.log(_observers[eventLabel].length, _context.observers[eventLabel].length)

    if (_observers[eventLabel]) {
      _.pull(_observers[eventLabel], handler)
    }
    if (_context.observers[eventLabel]) {
      _.pull(_context.observers[eventLabel], handler)
    }

    //console.log('Removed event handlers', _observers[eventLabel].length, 		_context.observers[eventLabel].length)
  }

  m.timestamp = function (kind) {
		if (!kind) return Date.now()
    else if (kind=='epoch') return Date.now()/1000
    else if (kind=='epochmill') return Date.now()
		else if (kind=='iso') return new Date().toISOString()
		throw new Error('log.timestamp(kind) says "kind" is invalid.')
  }

	// create aliases
  m.on = m.addEventHandler
	m.errorReport = m.report

	function flushLogBuffer() {
		var count = _ringBuff.length
		if (count == 0) return
    while(count--) {
			var args = _ringBuff.shift()
			args[3] = args[3] || {}
			args[3].priority = 11
			post.apply(m, args)
    }
  }

  function post(level, msg, details, options) {
    if (config.silent) return p.resolve()

    options = options || {}
    if (!_.isObject(options)) {
      details.options = options
      options = {}
    }

    if (!log[level]) {
      log.error({msg:'Invalid log level',
								 arg: level,
								 err: new Error('Invalid log level.')})
      level = 'info'
    }

		if (!config.debug && config.ringBufferSize && (!options.priority || options.priority < 10)) {
			if (level == 'warn') {} // continue logging as normal.
			else if (level == 'error' || level == 'fatal') flushLogBuffer()
			else {
				// preserve the original time that the event was logged.
				options.time = new Date()

				_ringBuff.enqueue([level,msg,details,options])
				return p.resolve(false)
			}
		}

    // hide goal complete messages if not in debug mode and ringBuffer is enabled.
    if (config.plugins && config.ringBufferSize && options.priority && options.priority>=10) {
      if (level != 'error' && level != 'fatal' && level != 'warn') level = 'debug'
    }

		// make library logs always trace.  priority < 11 allows ringbuffer output
		// to retain its original level output since the dump should contain
		// trace level details anyways.
		if (config.isModule && (!options.priority || options.priority < 11)) {
			if (level != 'error' && level != 'fatal') level = 'trace'
		}

    var goal = (_context && _context.goalInstance) || {}
    var logObject = {
        _id: parseInt(_.uniqueId()),
        _tags: goal.tags ? options.tags + ',' + goal.tags : options.tags,
        _goalId: goal.goalId
      }

    if (details instanceof Error) {
      logObject.err = details
    } else if (_.isObject(details) && details.err) {
      logObject.err = details.err
      //details.err = undefined
      logObject.details = details
    } else if (_.isObject(details)) {
      logObject.details = details
    } else if (details) {
      logObject.details = {details: details}
    }

    if (logObject.details) delete logObject.details.err
		if (options.timestamp) logObject.timestamp = options.timestamp
		if (options.time) logObject.time = options.time
    if (_.isObject(options.custom)) {
      logObject = _.merge(logObject,options.custom)
    }

    var sourceInfo
    if (options.source) {
      function getErrorObject(){
        try { throw Error('') } catch(err) { return err; }
      }
      var err = getErrorObject();
      var caller_line = err.stack.split("\n")[4];
      var index = caller_line.indexOf("at ");
      var clean = caller_line.slice(index+2, caller_line.length);
      sourceInfo = clean
    }

    if (!config.isNotBrowser && console) {
      if (!console[level]) console[level] = console.log
      if (sourceInfo) console[level]('[%s] %s:', _context.chain, logObject.msg || msg, logObject.details, sourceInfo)
      else console[level]('[%s] %s:', _context.chain, logObject.msg || msg, logObject.details)
      return
    }

    if (_.size(logObject) > 0) {
      try {
        log[level](logObject, msg)
      }
      catch (ex) {
				console.log(ex)
        console.log('Logger: exception occurred.  Attempting again using safe stringify...')
        if (ex instanceof TypeError) {
          var stringify = require('json-stringify-safe')
          log[level](JSON.parse(stringify(logObject)), msg)
        }
        else throw ex
      }
    }
    else
      log[level](msg)

    return m.processEventHandlers(msg, details, options)
  }

  return m
}

function Context(ctx) {
  this.__parentContext = ctx
}

function Goal(name, goalDetails, opts) {
  opts = opts || {}
  this.goalContext = goalDetails || {};
  this.goalId = this.goalContext.goalId
  this.type = opts.type

  // TODO: if this is in the context of another goal, set the parentGoalId to track subgoals.

  if (!this.goalContext.goalId) {
    this.goalId = _.uniqueId()
  }

  this.name = name;
  this.creationTimeMS = Date.now()
  this.tags = opts.tags
  this.priority = opts.priority || 1
}

String.prototype.toUnderscore = function(){
	return this.replace(/([A-Z])/g, function($1){return "_"+$1.toLowerCase();});
}

Goal.prototype.report = function (status, result) {
  var report = {
    goalId: this.goalId,
    goalName: this.name,
    codeName: this.name.replace('()','').toUnderscore().toUpperCase(),
    context: this.goalContext,
    duration: Date.now() - this.creationTimeMS,
    result: result,
    type: this.type,
    status: status
  }
  return report
}

  // bluebird deprecated the defer() method, and I'm not sure how to
  // refactor the code to use the new method so I"ll jsut add my own
  // version of defer() for now.
  function defer() {
    var resolve, reject;
    var promise = new Promise(function() {
      resolve = arguments[0]
      reject = arguments[1]
    });
    return {
      resolve: resolve,
      reject: reject,
      promise: promise
    }
  }
<commit_msg>log.report details logged.<commit_after>/**
 * @module logger
 * @summary: Provides a logger instance.
 *
 * @description:
 *
 * Author: m0ser
 * Created On: 2015-10-28.
 * @license Apache-2.0
 */

 var _ = require('lodash'),
   p = require('bluebird'),
   Promise = p

var _plugins, _observers = {}
module.exports = function(config, deps) {
  var m = post.bind(null,'info'),
		_context = deps.context || {},
    log = deps.log,
		_ringBuff = deps.ringBuff,
		_plugins = deps.plugins || _plugins

	// TODO: figure why this is here.
  _context = _.defaults(_context, {
    observers: {},
    chain: config.module || ''
  })

  m.context = function(contextInfo) {
		if (config.debug && !config.silent) console.log('Logger: Creating context...', contextInfo)
		if (contextInfo.opts) {
			if (contextInfo.opts.isModule) {
				// must clone the config to avoid isModule flag from permeating.
				// Not sure a better way to handle this.  isModule is set by libraries
				// when they are created with a logger instance.
				config = _.cloneDeep(config)
				config.isModule = true
			}
		}

    contextInfo.chain = _context.chain
    if (contextInfo.module) {
      contextInfo.chain = contextInfo.module.name
    } else {
      contextInfo.chain += '.'+contextInfo.name
    }

    var newLogger = module.exports(config, {
         log: log.child({chain: contextInfo.chain}),
         context: _.extend(new Context(_context), contextInfo),
				 ringBuff: deps.ringBuff
       })

    newLogger.parent = m
    return newLogger
  }

  m.module = function(moduleName, args, opts) {
    return m.context({module: {
      name: moduleName,
      args: args,
			opts: opts
    }})
  }

  m.debug = post.bind(m, 'debug')
  m.info = post.bind(m,'info')
  m.fatal = post.bind(m, 'fatal')
  m.error = post.bind(m, 'error')
  m.logError = post.bind(m, 'error')
  m.warn = post.bind(m, 'warn')
  m.log = post.bind(m, 'info')
  m.trace = post.bind(m,'trace')

  // difference between method and goal: a method can fail and be recovered from.
  // a goal is something that is not recovered from and should never fail.  You
  // always want to be alerted if a goal fails, because if a goal fails, your
  // application is not doing its job.
  m.method = createGoal.bind(m, 'method')
  m.goal = createGoal.bind(m, 'goal')

	// TODO: coming soon...  The ability to query the log.
  m.query = function() { throw new Error('log.query() unsupported')}
	//	m.query = _plugins['loggly'] ? _plugins['loggly'].query : function() {
	//    throw new Error('log.query() not available.  Load a plugin that supports it.')
	//  }

  function createGoal(type, goalName, params, opts) {
    opts = opts || {}
    opts.type = type
    var newGoalInstance = new Goal(goalName, params, opts)
    m.log('Starting '+goalName, {params: params}, {custom: {goalId: newGoalInstance.goalId}})
    var newGoal = m.context({
      goalInstance: newGoalInstance,
      name: goalName
    })

    return newGoal
  }

	m.report = function(err, prev, details) {
		if (!(err instanceof Error)) {
      console.log('ErrorReport:', err)
      if (config.env != 'prod' && config.env != 'production')
        throw new Error('ASSERT:report:InvalidParam "err"')
    }
		if (prev && !(prev instanceof Error)) {
			details = prev
		}
    if (details)
      console.log('ErrDetails:', details)

    details = details || {}

    err.prev = prev
		err.details = details
    var type = typeof err
    if (type != 'Error' || type != 'error' || type != 'object') err.type

		var errorDetails = err.message.split(':')
		if (errorDetails.length == 3) {
			err.category = errorDetails[0]
			err.activity = errorDetails[1]
			err.message = errorDetails[2]
		}
    // depending on how many colons are used in the error message,
    // we can remain backward compatible with previous error formats by
    // checking how many colons there are.
		if (errorDetails.length == 4) {
			err.category = errorDetails[0]
			err.activity = errorDetails[1]
			err.code = errorDetails[2]
      err.message = errorDetails[3]
		}
		if (!err.code)
		  err.code = details.code || err.type || err.message

    err.timestamp = Date.now()
    err.goalId = _context.goalInstance && _context.goalInstance.goalId
    err.goalName = _context.goalInstance && _context.goalInstance.name

    m.log('ErrorDetails', details)
    m.log('ErrorReport', err)

		if (err.category == 'USER') m.warn(err.message, err, {custom: details.custom})
		else m.error(err.message, err, {custom: details.custom})

		return err
	}

  m.failSuppressed = function (error) {
		m.report(error)
    var result = {err: error}

    if (_context && _context.goalInstance) {
      var goalReport = result.goalReport = _context.goalInstance.report("FAILED")
      m.error('Failed '+goalReport.goalName+'.', {
        goalId: goalReport.goalId,
        name: goalReport.goalName,
        codeName: goalReport.codeName,
				err: error
      }, {tags: 'GOAL-COMPLETE,GOAL-FAILED', custom: {goalReport: goalReport, goalDuration: goalReport.duration}})
    }

		return error
  }

  m.fail = function(err) {
    throw m.failSuppressed(err)
  }

  m.rejectWithCode = function(code) {
    return function(err) {
      throw m.report(err, {code: code})
    }
  }

  m.pass = m.result = function(result) {
    if (_context && _context.goalInstance) {
      var goalReport = _context.goalInstance.report('SUCCEEDED', result)
      m.log('Finished '+goalReport.goalName+'.', {
        goalId: goalReport.goalId,
        name: goalReport.goalName,
        goalName: goalReport.codeName
      }, {
        tags: 'GOAL-COMPLETE',
        custom: {goalReport: goalReport, goalDuration: goalReport.duration},
        priority: _context.goalInstance.priority || 10
      })
    } else {
      m.log('Result: ', _context)
    }

    return result
  }

  /**
   * Checks for any event handlers that match this event label and runs them
   * all.
   *
   * @param  {string} eventLabel The label for the event.
   * @param  {type} details    description
   * @param  {type} options    description
   * @return {type}            description
   */
  m.processEventHandlers = function(eventLabel, details, options) {
    var event = {
      eventName: eventLabel,
      handled: false
    }

    if (_context.observers[eventLabel]) {
      return p.map(_context.observers[eventLabel], function(cb) {
        if (!event.handled) return cb(event, details);
      }, {concurrency: 1})
    } else if (m.parent) {
      return m.parent.processEventHandlers(eventLabel, details, options)
    } else if (_observers[eventLabel]) {
      return p.map(_observers[eventLabel], function(cb) {
        if (!event.handled) return cb(event, details);
      }, {concurrency: 1})
    }

    return p.resolve()
  }

  m.addEventHandler = function(eventLabel, handler) {
    _context.observers[eventLabel] = _context.observers[eventLabel] || []
    _context.observers[eventLabel].push(handler)

    _observers[eventLabel] = _observers[eventLabel] || []
    _observers[eventLabel].push(handler)

		return function() {
			m.removeEventHandler(eventLabel, handler)
		}
  }

  m.removeEventHandler = function(eventLabel, handler) {
    //console.log(_observers[eventLabel].length, _context.observers[eventLabel].length)

    if (_observers[eventLabel]) {
      _.pull(_observers[eventLabel], handler)
    }
    if (_context.observers[eventLabel]) {
      _.pull(_context.observers[eventLabel], handler)
    }

    //console.log('Removed event handlers', _observers[eventLabel].length, 		_context.observers[eventLabel].length)
  }

  m.timestamp = function (kind) {
		if (!kind) return Date.now()
    else if (kind=='epoch') return Date.now()/1000
    else if (kind=='epochmill') return Date.now()
		else if (kind=='iso') return new Date().toISOString()
		throw new Error('log.timestamp(kind) says "kind" is invalid.')
  }

	// create aliases
  m.on = m.addEventHandler
	m.errorReport = m.report

	function flushLogBuffer() {
		var count = _ringBuff.length
		if (count == 0) return
    while(count--) {
			var args = _ringBuff.shift()
			args[3] = args[3] || {}
			args[3].priority = 11
			post.apply(m, args)
    }
  }

  function post(level, msg, details, options) {
    if (config.silent) return p.resolve()

    options = options || {}
    if (!_.isObject(options)) {
      details.options = options
      options = {}
    }

    if (!log[level]) {
      log.error({msg:'Invalid log level',
								 arg: level,
								 err: new Error('Invalid log level.')})
      level = 'info'
    }

		if (!config.debug && config.ringBufferSize && (!options.priority || options.priority < 10)) {
			if (level == 'warn') {} // continue logging as normal.
			else if (level == 'error' || level == 'fatal') flushLogBuffer()
			else {
				// preserve the original time that the event was logged.
				options.time = new Date()

				_ringBuff.enqueue([level,msg,details,options])
				return p.resolve(false)
			}
		}

    // hide goal complete messages if not in debug mode and ringBuffer is enabled.
    if (config.plugins && config.ringBufferSize && options.priority && options.priority>=10) {
      if (level != 'error' && level != 'fatal' && level != 'warn') level = 'debug'
    }

		// make library logs always trace.  priority < 11 allows ringbuffer output
		// to retain its original level output since the dump should contain
		// trace level details anyways.
		if (config.isModule && (!options.priority || options.priority < 11)) {
			if (level != 'error' && level != 'fatal') level = 'trace'
		}

    var goal = (_context && _context.goalInstance) || {}
    var logObject = {
        _id: parseInt(_.uniqueId()),
        _tags: goal.tags ? options.tags + ',' + goal.tags : options.tags,
        _goalId: goal.goalId
      }

    if (details instanceof Error) {
      logObject.err = details
    } else if (_.isObject(details) && details.err) {
      logObject.err = details.err
      //details.err = undefined
      logObject.details = details
    } else if (_.isObject(details)) {
      logObject.details = details
    } else if (details) {
      logObject.details = {details: details}
    }

    if (logObject.details) delete logObject.details.err
		if (options.timestamp) logObject.timestamp = options.timestamp
		if (options.time) logObject.time = options.time
    if (_.isObject(options.custom)) {
      logObject = _.merge(logObject,options.custom)
    }

    var sourceInfo
    if (options.source) {
      function getErrorObject(){
        try { throw Error('') } catch(err) { return err; }
      }
      var err = getErrorObject();
      var caller_line = err.stack.split("\n")[4];
      var index = caller_line.indexOf("at ");
      var clean = caller_line.slice(index+2, caller_line.length);
      sourceInfo = clean
    }

    if (!config.isNotBrowser && console) {
      if (!console[level]) console[level] = console.log
      if (sourceInfo) console[level]('[%s] %s:', _context.chain, logObject.msg || msg, logObject.details, sourceInfo)
      else console[level]('[%s] %s:', _context.chain, logObject.msg || msg, logObject.details)
      return
    }

    if (_.size(logObject) > 0) {
      try {
        log[level](logObject, msg)
      }
      catch (ex) {
				console.log(ex)
        console.log('Logger: exception occurred.  Attempting again using safe stringify...')
        if (ex instanceof TypeError) {
          var stringify = require('json-stringify-safe')
          log[level](JSON.parse(stringify(logObject)), msg)
        }
        else throw ex
      }
    }
    else
      log[level](msg)

    return m.processEventHandlers(msg, details, options)
  }

  return m
}

function Context(ctx) {
  this.__parentContext = ctx
}

function Goal(name, goalDetails, opts) {
  opts = opts || {}
  this.goalContext = goalDetails || {};
  this.goalId = this.goalContext.goalId
  this.type = opts.type

  // TODO: if this is in the context of another goal, set the parentGoalId to track subgoals.

  if (!this.goalContext.goalId) {
    this.goalId = _.uniqueId()
  }

  this.name = name;
  this.creationTimeMS = Date.now()
  this.tags = opts.tags
  this.priority = opts.priority || 1
}

String.prototype.toUnderscore = function(){
	return this.replace(/([A-Z])/g, function($1){return "_"+$1.toLowerCase();});
}

Goal.prototype.report = function (status, result) {
  var report = {
    goalId: this.goalId,
    goalName: this.name,
    codeName: this.name.replace('()','').toUnderscore().toUpperCase(),
    context: this.goalContext,
    duration: Date.now() - this.creationTimeMS,
    result: result,
    type: this.type,
    status: status
  }
  return report
}

  // bluebird deprecated the defer() method, and I'm not sure how to
  // refactor the code to use the new method so I"ll jsut add my own
  // version of defer() for now.
  function defer() {
    var resolve, reject;
    var promise = new Promise(function() {
      resolve = arguments[0]
      reject = arguments[1]
    });
    return {
      resolve: resolve,
      reject: reject,
      promise: promise
    }
  }
<|endoftext|>


<commit_before>/* eslint-disable no-console */
const chalk = require('chalk')
const cheerio = require('cheerio')
const logSymbols = require('log-symbols')
const escapeGoat = require('escape-goat')

exports.blank = () => {
  console.log('')
}

const tab = (msg, count = 1) => {
  const tabs = []

  for (let i = 0; i < count; i++) {
    tabs.push('    ')
  }

  return `${tabs.join('')}${msg}`
}

exports.tab = tab

exports.underline = msg => {
  console.log(tab(`${chalk.underline.white(msg)}`))
}

exports.title = msg => {
  console.info(tab(chalk.bgBlue(`-------- ${msg} --------`)))
}

exports.info = msg => {
  console.info(tab(`${logSymbols.info} ${chalk.cyan(msg)}`))
}

exports.error = data => {
  const isObject = typeof data === 'object'
  const message = isObject ? `${data.message}` : data

  console.error(tab(`${logSymbols.error} ${message}`))

  if (isObject && data.snippet) {
    console.info(tab(`${logSymbols.info} ${data.snippet}`))
  }
}

// Error log for theme-check
exports.error2 = data => {
  const $ = cheerio.load(data.message)
  $('strong').each((i, el) => {
    $(el).replaceWith(() => chalk.magenta(escapeGoat.unescape($(el).text())))
  })

  $('a').each((i, el) => {
    $(el).replaceWith(() => chalk.underline.blue($(el).attr('href')))
  })

  $('pre').each((i, el) => {
    $(el).replaceWith(() => chalk.underline.gray($(el).text()))
  })

  const message = escapeGoat.unescape($('body').html())
  console.error(tab(`${logSymbols[data.type]} ${message}`))
}

exports.done = msg => {
  console.log(tab(`${logSymbols.success} ${chalk.green(msg)}`))
}
<commit_msg>replace: pre with tab and new line<commit_after>/* eslint-disable no-console */
const chalk = require('chalk')
const cheerio = require('cheerio')
const logSymbols = require('log-symbols')
const escapeGoat = require('escape-goat')

exports.blank = () => {
  console.log('')
}

const tab = (msg, count = 1) => {
  const tabs = []

  for (let i = 0; i < count; i++) {
    tabs.push('    ')
  }

  return `${tabs.join('')}${msg}`
}

exports.tab = tab

exports.underline = msg => {
  console.log(tab(`${chalk.underline.white(msg)}`))
}

exports.title = msg => {
  console.info(tab(chalk.bgBlue(`-------- ${msg} --------`)))
}

exports.info = msg => {
  console.info(tab(`${logSymbols.info} ${chalk.cyan(msg)}`))
}

exports.error = data => {
  const isObject = typeof data === 'object'
  const message = isObject ? `${data.message}` : data

  console.error(tab(`${logSymbols.error} ${message}`))

  if (isObject && data.snippet) {
    console.info(tab(`${logSymbols.info} ${data.snippet}`))
  }
}

// Error log for theme-check
exports.error2 = data => {
  const $ = cheerio.load(data.message)
  $('strong').each((i, el) => {
    $(el).replaceWith(() => chalk.magenta(escapeGoat.unescape($(el).text())))
  })

  $('a').each((i, el) => {
    $(el).replaceWith(() => chalk.underline.blue($(el).attr('href')))
  })

  $('pre').each((i, el) => {
    $(el).replaceWith(() => {
      const text = escapeGoat.unescape($(el).text())
      return '\n' + tab(chalk.underline.gray(text))
    })
  })

  const message = escapeGoat.unescape($('body').html())
  console.error(tab(`${logSymbols[data.type]} ${message}`))
}

exports.done = msg => {
  console.log(tab(`${logSymbols.success} ${chalk.green(msg)}`))
}
<|endoftext|>


<commit_before>import { console } from "./globals";

/**
 * Returns a function that proxies to the given method name on the globals
 * console object. The proxy will also detect if the console doesn't exist and
 * will appropriately no-op. This allows support for IE9, which doesn't have a
 * console if the developer tools are not open.
 */
function consoleProxy( method ) {
	return function( ...args ) {
		if ( console ) {
			console[ method ]( ...args );
		}
	};
}

export default {
	warn: consoleProxy( "warn" )
};
<commit_msg>Logger: Simplify Logger.warn() internals<commit_after>import { console } from "./globals";

// Detect if the console doesn't exist and no-op in that case.
// This allows support for IE 9, which doesn't have a console
// object if the developer tools are not open.

export default {
	warn: console ? console.warn.bind( console ) : function() {}
};
<|endoftext|>


<commit_before>/*jshint esversion: 6 */
"use strict";

const assert = require('assert');

const defs    = require('./defs.js');
const ldebug  = require('./ldebug.js');
const lobject = require('./lobject.js');
const lstring = require('./lstring.js');
const lstate  = require('./lstate.js');
const CT      = defs.constant_types;

/* used to prevent conflicts with lightuserdata keys */
let lightuserdata_hashes = new WeakMap();
const get_lightuserdata_hash = function(v) {
    let hash = lightuserdata_hashes.get(v);
    if (!hash) {
        hash = Symbol("lightuserdata");
        lightuserdata_hashes.set(v, hash);
    }
    return hash;
};

const table_hash = function(L, key) {
    switch(key.type) {
    case CT.LUA_TNIL:
        return ldebug.luaG_runerror(L, defs.to_luastring("table index is nil", true));
    case CT.LUA_TNUMFLT:
        if (isNaN(key.value))
            return ldebug.luaG_runerror(L, defs.to_luastring("table index is NaN", true));
        /* fall through */
    case CT.LUA_TBOOLEAN:
    case CT.LUA_TNUMINT:
    case CT.LUA_TTABLE:
    case CT.LUA_TLCL:
    case CT.LUA_TLCF:
    case CT.LUA_TCCL:
    case CT.LUA_TUSERDATA:
    case CT.LUA_TTHREAD:
        return key.value;
    case CT.LUA_TSHRSTR:
    case CT.LUA_TLNGSTR:
        return lstring.luaS_hashlongstr(key.tsvalue());
    case CT.LUA_TLIGHTUSERDATA:
        let v = key.value;
        switch(typeof v) {
        case "string":
            /* possible conflict with LUA_TSTRING.
               prefix this string with "*" so they don't clash */
            return "*" + v;
        case "number":
            /* possible conflict with LUA_TNUMBER.
               turn into string and prefix with "#" to avoid clash with other strings */
            return "#" + v;
        case "boolean":
            /* possible conflict with LUA_TBOOLEAN. use strings ?true and ?false instead */
            return v?"?true":"?false";
        case "function":
            /* possible conflict with LUA_TLCF.
               indirect via a weakmap */
            return get_lightuserdata_hash(v);
        case "object":
            /* v shouldn't be a CClosure, LClosure, Table or Userdata from this state as they're never exposed
               the only exposed internal type is a lua_State */
            if (v instanceof lstate.lua_State && v.l_G === L.l_G) {
                /* indirect via a weakmap */
                return get_lightuserdata_hash(v);
            }
            /* fall through */
        default:
            return v;
        }
    default:
        throw new Error("unknown key type: " + key.type);
    }
};

class Table {
    constructor(L) {
        this.id = L.l_G.id_counter++;
        this.strong = new Map();
        this.dead_strong = new Map();
        this.dead_weak = void 0; /* initialised when needed */
        this.f = void 0; /* first entry */
        this.l = void 0; /* last entry */
        this.metatable = null;
        this.flags = ~0;
    }
}

const invalidateTMcache = function(t) {
    t.flags = 0;
};

const add = function(t, hash, key, value) {
    t.dead_strong.clear();
    t.dead_weak = void 0;
    let prev = null;
    let entry = {
        key: key,
        value: value,
        p: prev = t.l,
        n: void 0
    };
    if (!t.f) t.f = entry;
    if (prev) prev.n = entry;
    t.strong.set(hash, entry);
    t.l = entry;
};

const is_valid_weakmap_key = function(k) {
    return typeof k === 'object' ? k !== null : typeof k === 'function';
};

/* Move out of 'strong' part and into 'dead' part. */
const mark_dead = function(t, hash) {
    let e = t.strong.get(hash);
    if (e) {
        e.key.setdeadvalue();
        e.value = void 0;
        let next = e.n;
        let prev = e.p;
        e.p = void 0; /* no need to know previous item any more */
        if(prev) prev.n = next;
        if(next) next.p = prev;
        if(t.f === e) t.f = next;
        if(t.l === e) t.l = prev;
        t.strong.delete(hash);
        if (is_valid_weakmap_key(hash)) {
            if (!t.dead_weak) t.dead_weak = new WeakMap();
            t.dead_weak.set(hash, e);
        } else {
            /* can't be used as key in weakmap */
            t.dead_strong.set(hash, e);
        }
    }
};

const luaH_new = function(L) {
    return new Table(L);
};

const getgeneric = function(t, hash) {
    let v = t.strong.get(hash);
    return v ? v.value : lobject.luaO_nilobject;
};

const luaH_getint = function(t, key) {
    assert(typeof key == "number" && (key|0) === key);
    return getgeneric(t, key);
};

const luaH_getstr = function(t, key) {
    assert(key instanceof lstring.TString);
    return getgeneric(t, lstring.luaS_hashlongstr(key));
};

const luaH_get = function(L, t, key) {
    assert(key instanceof lobject.TValue);
    if (key.ttisnil() || (key.ttisfloat() && isNaN(key.value)))
        return lobject.luaO_nilobject;
    return getgeneric(t, table_hash(L, key));
};

const setgeneric = function(t, hash, key) {
    let v = t.strong.get(hash);
    if (v)
        return v.value;

    let tv = new lobject.TValue(CT.LUA_TNIL, null);
    add(t, hash, key, tv);
    return tv;
};

const luaH_setint = function(t, key, value) {
    assert(typeof key == "number" && (key|0) === key && value instanceof lobject.TValue);
    let hash = key; /* table_hash known result */
    if (value.ttisnil()) {
        mark_dead(t, hash);
        return;
    }
    let v = t.strong.get(hash);
    if (v) {
        let tv = v.value;
        tv.setfrom(value);
    } else {
        let k = new lobject.TValue(CT.LUA_TNUMINT, key);
        let v = new lobject.TValue(value.type, value.value);
        add(t, hash, k, v);
    }
};

const luaH_set = function(L, t, key) {
    assert(key instanceof lobject.TValue);
    let hash = table_hash(L, key);
    return setgeneric(t, hash, new lobject.TValue(key.type, key.value));
};

const luaH_delete = function(L, t, key) {
    assert(key instanceof lobject.TValue);
    let hash = table_hash(L, key);
    return mark_dead(t, hash);
};

/*
** Try to find a boundary in table 't'. A 'boundary' is an integer index
** such that t[i] is non-nil and t[i+1] is nil (and 0 if t[1] is nil).
*/
const luaH_getn = function(t) {
    let i = 0;
    let j = t.strong.size + 1; /* use known size of Map to bound search */
    /* now do a binary search between them */
    while (j - i > 1) {
        let m = Math.floor((i+j)/2);
        if (luaH_getint(t, m).ttisnil()) j = m;
        else i = m;
    }
    return i;
};

const luaH_next = function(L, table, keyI) {
    let keyO = L.stack[keyI];

    let entry;
    if (keyO.type === CT.LUA_TNIL) {
        entry = table.f;
        if (!entry)
            return false;
    } else {
        /* First find current key */
        let hash = table_hash(L, keyO);
        /* Look in main part of table */
        entry = table.strong.get(hash);
        if (entry) {
            entry = entry.n;
            if (!entry)
                return false;
        } else {
            /* Try dead keys */
            entry = (table.dead_weak && table.dead_weak.get(hash)) || table.dead_strong.get(hash);
            if (!entry)
                /* item not in table */
                return ldebug.luaG_runerror(L, defs.to_luastring("invalid key to 'next'"));
            /* Iterate until either out of keys, or until finding a non-dead key */
            do {
                entry = entry.n;
                if (!entry)
                    return false;
            } while (entry.key.ttisdeadkey());
        }
    }
    L.stack[keyI] = new lobject.TValue(entry.key.type, entry.key.value);
    L.stack[keyI+1] = new lobject.TValue(entry.value.type, entry.value.value);
    return true;
};

module.exports.invalidateTMcache = invalidateTMcache;
module.exports.luaH_delete  = luaH_delete;
module.exports.luaH_get     = luaH_get;
module.exports.luaH_getint  = luaH_getint;
module.exports.luaH_getn    = luaH_getn;
module.exports.luaH_getstr  = luaH_getstr;
module.exports.luaH_set     = luaH_set;
module.exports.luaH_setint  = luaH_setint;
module.exports.luaH_new     = luaH_new;
module.exports.luaH_next    = luaH_next;
<commit_msg>src/ltable.js: Convert float keys that fit in an integer to integers<commit_after>/*jshint esversion: 6 */
"use strict";

const assert = require('assert');

const defs    = require('./defs.js');
const ldebug  = require('./ldebug.js');
const lobject = require('./lobject.js');
const lstring = require('./lstring.js');
const lstate  = require('./lstate.js');
const CT      = defs.constant_types;

/* used to prevent conflicts with lightuserdata keys */
let lightuserdata_hashes = new WeakMap();
const get_lightuserdata_hash = function(v) {
    let hash = lightuserdata_hashes.get(v);
    if (!hash) {
        hash = Symbol("lightuserdata");
        lightuserdata_hashes.set(v, hash);
    }
    return hash;
};

const table_hash = function(L, key) {
    switch(key.type) {
    case CT.LUA_TNIL:
        return ldebug.luaG_runerror(L, defs.to_luastring("table index is nil", true));
    case CT.LUA_TNUMFLT:
        if (isNaN(key.value))
            return ldebug.luaG_runerror(L, defs.to_luastring("table index is NaN", true));
        /* fall through */
    case CT.LUA_TNUMINT: /* takes advantage of floats and integers being same in JS */
    case CT.LUA_TBOOLEAN:
    case CT.LUA_TTABLE:
    case CT.LUA_TLCL:
    case CT.LUA_TLCF:
    case CT.LUA_TCCL:
    case CT.LUA_TUSERDATA:
    case CT.LUA_TTHREAD:
        return key.value;
    case CT.LUA_TSHRSTR:
    case CT.LUA_TLNGSTR:
        return lstring.luaS_hashlongstr(key.tsvalue());
    case CT.LUA_TLIGHTUSERDATA:
        let v = key.value;
        switch(typeof v) {
        case "string":
            /* possible conflict with LUA_TSTRING.
               prefix this string with "*" so they don't clash */
            return "*" + v;
        case "number":
            /* possible conflict with LUA_TNUMBER.
               turn into string and prefix with "#" to avoid clash with other strings */
            return "#" + v;
        case "boolean":
            /* possible conflict with LUA_TBOOLEAN. use strings ?true and ?false instead */
            return v?"?true":"?false";
        case "function":
            /* possible conflict with LUA_TLCF.
               indirect via a weakmap */
            return get_lightuserdata_hash(v);
        case "object":
            /* v shouldn't be a CClosure, LClosure, Table or Userdata from this state as they're never exposed
               the only exposed internal type is a lua_State */
            if (v instanceof lstate.lua_State && v.l_G === L.l_G) {
                /* indirect via a weakmap */
                return get_lightuserdata_hash(v);
            }
            /* fall through */
        default:
            return v;
        }
    default:
        throw new Error("unknown key type: " + key.type);
    }
};

class Table {
    constructor(L) {
        this.id = L.l_G.id_counter++;
        this.strong = new Map();
        this.dead_strong = new Map();
        this.dead_weak = void 0; /* initialised when needed */
        this.f = void 0; /* first entry */
        this.l = void 0; /* last entry */
        this.metatable = null;
        this.flags = ~0;
    }
}

const invalidateTMcache = function(t) {
    t.flags = 0;
};

const add = function(t, hash, key, value) {
    t.dead_strong.clear();
    t.dead_weak = void 0;
    let prev = null;
    let entry = {
        key: key,
        value: value,
        p: prev = t.l,
        n: void 0
    };
    if (!t.f) t.f = entry;
    if (prev) prev.n = entry;
    t.strong.set(hash, entry);
    t.l = entry;
};

const is_valid_weakmap_key = function(k) {
    return typeof k === 'object' ? k !== null : typeof k === 'function';
};

/* Move out of 'strong' part and into 'dead' part. */
const mark_dead = function(t, hash) {
    let e = t.strong.get(hash);
    if (e) {
        e.key.setdeadvalue();
        e.value = void 0;
        let next = e.n;
        let prev = e.p;
        e.p = void 0; /* no need to know previous item any more */
        if(prev) prev.n = next;
        if(next) next.p = prev;
        if(t.f === e) t.f = next;
        if(t.l === e) t.l = prev;
        t.strong.delete(hash);
        if (is_valid_weakmap_key(hash)) {
            if (!t.dead_weak) t.dead_weak = new WeakMap();
            t.dead_weak.set(hash, e);
        } else {
            /* can't be used as key in weakmap */
            t.dead_strong.set(hash, e);
        }
    }
};

const luaH_new = function(L) {
    return new Table(L);
};

const getgeneric = function(t, hash) {
    let v = t.strong.get(hash);
    return v ? v.value : lobject.luaO_nilobject;
};

const luaH_getint = function(t, key) {
    assert(typeof key == "number" && (key|0) === key);
    return getgeneric(t, key);
};

const luaH_getstr = function(t, key) {
    assert(key instanceof lstring.TString);
    return getgeneric(t, lstring.luaS_hashlongstr(key));
};

const luaH_get = function(L, t, key) {
    assert(key instanceof lobject.TValue);
    if (key.ttisnil() || (key.ttisfloat() && isNaN(key.value)))
        return lobject.luaO_nilobject;
    return getgeneric(t, table_hash(L, key));
};

const setgeneric = function(t, hash, key) {
    let v = t.strong.get(hash);
    if (v)
        return v.value;

    let kv = key.value;
    if ((key.ttisfloat() && (kv|0) === kv)) { /* does index fit in an integer? */
        /* insert it as an integer */
        key = new lobject.TValue(CT.LUA_TNUMINT, kv);
    } else {
        key = new lobject.TValue(key.type, kv);
    }
    let tv = new lobject.TValue(CT.LUA_TNIL, null);
    add(t, hash, key, tv);
    return tv;
};

const luaH_setint = function(t, key, value) {
    assert(typeof key == "number" && (key|0) === key && value instanceof lobject.TValue);
    let hash = key; /* table_hash known result */
    if (value.ttisnil()) {
        mark_dead(t, hash);
        return;
    }
    let v = t.strong.get(hash);
    if (v) {
        let tv = v.value;
        tv.setfrom(value);
    } else {
        let k = new lobject.TValue(CT.LUA_TNUMINT, key);
        let v = new lobject.TValue(value.type, value.value);
        add(t, hash, k, v);
    }
};

const luaH_set = function(L, t, key) {
    assert(key instanceof lobject.TValue);
    let hash = table_hash(L, key);
    return setgeneric(t, hash, key);
};

const luaH_delete = function(L, t, key) {
    assert(key instanceof lobject.TValue);
    let hash = table_hash(L, key);
    return mark_dead(t, hash);
};

/*
** Try to find a boundary in table 't'. A 'boundary' is an integer index
** such that t[i] is non-nil and t[i+1] is nil (and 0 if t[1] is nil).
*/
const luaH_getn = function(t) {
    let i = 0;
    let j = t.strong.size + 1; /* use known size of Map to bound search */
    /* now do a binary search between them */
    while (j - i > 1) {
        let m = Math.floor((i+j)/2);
        if (luaH_getint(t, m).ttisnil()) j = m;
        else i = m;
    }
    return i;
};

const luaH_next = function(L, table, keyI) {
    let keyO = L.stack[keyI];

    let entry;
    if (keyO.type === CT.LUA_TNIL) {
        entry = table.f;
        if (!entry)
            return false;
    } else {
        /* First find current key */
        let hash = table_hash(L, keyO);
        /* Look in main part of table */
        entry = table.strong.get(hash);
        if (entry) {
            entry = entry.n;
            if (!entry)
                return false;
        } else {
            /* Try dead keys */
            entry = (table.dead_weak && table.dead_weak.get(hash)) || table.dead_strong.get(hash);
            if (!entry)
                /* item not in table */
                return ldebug.luaG_runerror(L, defs.to_luastring("invalid key to 'next'"));
            /* Iterate until either out of keys, or until finding a non-dead key */
            do {
                entry = entry.n;
                if (!entry)
                    return false;
            } while (entry.key.ttisdeadkey());
        }
    }
    L.stack[keyI] = new lobject.TValue(entry.key.type, entry.key.value);
    L.stack[keyI+1] = new lobject.TValue(entry.value.type, entry.value.value);
    return true;
};

module.exports.invalidateTMcache = invalidateTMcache;
module.exports.luaH_delete  = luaH_delete;
module.exports.luaH_get     = luaH_get;
module.exports.luaH_getint  = luaH_getint;
module.exports.luaH_getn    = luaH_getn;
module.exports.luaH_getstr  = luaH_getstr;
module.exports.luaH_set     = luaH_set;
module.exports.luaH_setint  = luaH_setint;
module.exports.luaH_new     = luaH_new;
module.exports.luaH_next    = luaH_next;
<|endoftext|>


<commit_before>/*jshint esversion: 6 */
"use strict";

const assert = require('assert');

const defs    = require('./defs.js');
const ldebug  = require('./ldebug.js');
const lobject = require('./lobject.js');
const lstring = require('./lstring.js');
const CT      = defs.constant_types;

const table_hash = function(key) {
    switch(key.type) {
    case CT.LUA_TBOOLEAN:
    case CT.LUA_TLIGHTUSERDATA: /* XXX: if user pushes conflicting lightuserdata then the table will do odd things */
    case CT.LUA_TNUMFLT:
    case CT.LUA_TNUMINT:
    case CT.LUA_TTABLE:
    case CT.LUA_TLCL:
    case CT.LUA_TLCF:
    case CT.LUA_TCCL:
    case CT.LUA_TUSERDATA:
    case CT.LUA_TTHREAD:
        return key.value;
    case CT.LUA_TSHRSTR:
    case CT.LUA_TLNGSTR:
        return lstring.luaS_hashlongstr(key.tsvalue());
    default:
        throw new Error("unknown key type: " + key.type);
    }
};

class Table {
    constructor(L) {
        this.id = L.l_G.id_counter++;
        this.strong = new Map();
        this.dead_strong = new Map();
        this.dead_weak = void 0; /* initialised when needed */
        this.f = void 0; /* first entry */
        this.l = void 0; /* last entry */
        this.metatable = null;
    }
}

const add = function(t, hash, key, value) {
    t.dead_strong.clear();
    t.dead_weak = void 0;
    let prev;
    let entry = {
        key: key,
        value: value,
        p: prev = t.l,
        n: void 0
    };
    if (!t.f) t.f = entry;
    if (prev) prev.n = entry;
    t.strong.set(hash, entry);
    t.l = entry;
};

const is_valid_weakmap_key = function(k) {
    return typeof k === 'object' ? k !== null : typeof k === 'function';
};

/* Move out of 'strong' part and into 'dead' part. */
const mark_dead = function(t, hash) {
    let e = t.strong.get(hash);
    if (e) {
        e.key.setdeadvalue();
        e.value = void 0;
        let next = e.n;
        let prev = e.p;
        e.p = void 0; /* no need to know previous item any more */
        if(prev) prev.n = next;
        if(next) next.p = prev;
        if(t.f === e) t.f = next;
        if(t.l === e) t.l = prev;
        t.strong.delete(hash);
        if (is_valid_weakmap_key(hash)) {
            if (!t.dead_weak) t.dead_weak = new WeakMap();
            t.dead_weak.set(hash, e);
        } else {
            /* can't be used as key in weakmap */
            t.dead_strong.set(hash, e);
        }
    }
};

const luaH_new = function(L) {
    return new Table(L);
};

const getgeneric = function(t, hash) {
    let v = t.strong.get(hash);
    return v ? v.value : lobject.luaO_nilobject;
};

const luaH_getint = function(t, key) {
    assert(typeof key == "number" && (key|0) === key);
    return getgeneric(t, key);
};

const luaH_getstr = function(t, key) {
    assert(key instanceof lstring.TString);
    return getgeneric(t, lstring.luaS_hashlongstr(key));
};

const luaH_get = function(t, key) {
    assert(key instanceof lobject.TValue);
    if (key.ttisnil())
        return lobject.luaO_nilobject;
    return getgeneric(t, table_hash(key));
};

const setgeneric = function(t, hash, key) {
    let v = t.strong.get(hash);
    if (v)
        return v.value;

    let tv = new lobject.TValue(CT.LUA_TNIL, null);
    add(t, hash, key, tv);
    return tv;
};

const luaH_setint = function(t, key, value) {
    assert(typeof key == "number" && (key|0) === key && value instanceof lobject.TValue);
    let hash = key; /* table_hash known result */
    if (value.ttisnil()) {
        mark_dead(t, hash);
        return;
    }
    let v = t.strong.get(hash);
    if (v) {
        let tv = v.value;
        tv.setfrom(value);
    } else {
        let k = new lobject.TValue(CT.LUA_TNUMINT, key);
        let v = new lobject.TValue(value.type, value.value);
        add(t, hash, k, v);
    }
};

const luaH_set = function(t, key) {
    assert(key instanceof lobject.TValue);
    let hash = table_hash(key);
    return setgeneric(t, hash, new lobject.TValue(key.type, key.value));
};

const luaH_delete = function(t, key) {
    assert(key instanceof lobject.TValue);
    let hash = table_hash(key);
    return mark_dead(t, hash);
};

/*
** Try to find a boundary in table 't'. A 'boundary' is an integer index
** such that t[i] is non-nil and t[i+1] is nil (and 0 if t[1] is nil).
*/
const luaH_getn = function(t) {
    let i = 0;
    let j = t.strong.size + 1; /* use known size of Map to bound search */
    /* now do a binary search between them */
    while (j - i > 1) {
        let m = Math.floor((i+j)/2);
        if (luaH_getint(t, m).ttisnil()) j = m;
        else i = m;
    }
    return i;
};

const luaH_next = function(L, table, keyI) {
    let keyO = L.stack[keyI];

    let entry;
    if (keyO.type === CT.LUA_TNIL) {
        entry = table.f;
        if (!entry)
            return false;
    } else {
        /* First find current key */
        let hash = table_hash(keyO);
        /* Look in main part of table */
        entry = table.strong.get(hash);
        if (entry) {
            entry = entry.n;
            if (!entry)
                return false;
        } else {
            /* Try dead keys */
            entry = table.dead_weak.get(hash) || table.dead_strong.get(hash);
            if (!entry)
                /* item not in table */
                return ldebug.luaG_runerror(L, defs.to_luastring("invalid key to 'next'"));
            /* Iterate until either out of keys, or until finding a non-dead key */
            do {
                entry = entry.n;
                if (!entry)
                    return false;
            } while (entry.key.ttisdeadkey());
        }
    }
    L.stack[keyI] = new lobject.TValue(entry.key.type, entry.key.value);
    L.stack[keyI+1] = new lobject.TValue(entry.value.type, entry.value.value);
    return true;
};

module.exports.luaH_delete  = luaH_delete;
module.exports.luaH_get     = luaH_get;
module.exports.luaH_getint  = luaH_getint;
module.exports.luaH_getn    = luaH_getn;
module.exports.luaH_getstr  = luaH_getstr;
module.exports.luaH_set     = luaH_set;
module.exports.luaH_setint  = luaH_setint;
module.exports.luaH_new     = luaH_new;
module.exports.luaH_next    = luaH_next;
<commit_msg>If not initialized, is removed by babili<commit_after>/*jshint esversion: 6 */
"use strict";

const assert = require('assert');

const defs    = require('./defs.js');
const ldebug  = require('./ldebug.js');
const lobject = require('./lobject.js');
const lstring = require('./lstring.js');
const CT      = defs.constant_types;

const table_hash = function(key) {
    switch(key.type) {
    case CT.LUA_TBOOLEAN:
    case CT.LUA_TLIGHTUSERDATA: /* XXX: if user pushes conflicting lightuserdata then the table will do odd things */
    case CT.LUA_TNUMFLT:
    case CT.LUA_TNUMINT:
    case CT.LUA_TTABLE:
    case CT.LUA_TLCL:
    case CT.LUA_TLCF:
    case CT.LUA_TCCL:
    case CT.LUA_TUSERDATA:
    case CT.LUA_TTHREAD:
        return key.value;
    case CT.LUA_TSHRSTR:
    case CT.LUA_TLNGSTR:
        return lstring.luaS_hashlongstr(key.tsvalue());
    default:
        throw new Error("unknown key type: " + key.type);
    }
};

class Table {
    constructor(L) {
        this.id = L.l_G.id_counter++;
        this.strong = new Map();
        this.dead_strong = new Map();
        this.dead_weak = void 0; /* initialised when needed */
        this.f = void 0; /* first entry */
        this.l = void 0; /* last entry */
        this.metatable = null;
    }
}

const add = function(t, hash, key, value) {
    t.dead_strong.clear();
    t.dead_weak = void 0;
    let prev = null;
    let entry = {
        key: key,
        value: value,
        p: prev = t.l,
        n: void 0
    };
    if (!t.f) t.f = entry;
    if (prev) prev.n = entry;
    t.strong.set(hash, entry);
    t.l = entry;
};

const is_valid_weakmap_key = function(k) {
    return typeof k === 'object' ? k !== null : typeof k === 'function';
};

/* Move out of 'strong' part and into 'dead' part. */
const mark_dead = function(t, hash) {
    let e = t.strong.get(hash);
    if (e) {
        e.key.setdeadvalue();
        e.value = void 0;
        let next = e.n;
        let prev = e.p;
        e.p = void 0; /* no need to know previous item any more */
        if(prev) prev.n = next;
        if(next) next.p = prev;
        if(t.f === e) t.f = next;
        if(t.l === e) t.l = prev;
        t.strong.delete(hash);
        if (is_valid_weakmap_key(hash)) {
            if (!t.dead_weak) t.dead_weak = new WeakMap();
            t.dead_weak.set(hash, e);
        } else {
            /* can't be used as key in weakmap */
            t.dead_strong.set(hash, e);
        }
    }
};

const luaH_new = function(L) {
    return new Table(L);
};

const getgeneric = function(t, hash) {
    let v = t.strong.get(hash);
    return v ? v.value : lobject.luaO_nilobject;
};

const luaH_getint = function(t, key) {
    assert(typeof key == "number" && (key|0) === key);
    return getgeneric(t, key);
};

const luaH_getstr = function(t, key) {
    assert(key instanceof lstring.TString);
    return getgeneric(t, lstring.luaS_hashlongstr(key));
};

const luaH_get = function(t, key) {
    assert(key instanceof lobject.TValue);
    if (key.ttisnil())
        return lobject.luaO_nilobject;
    return getgeneric(t, table_hash(key));
};

const setgeneric = function(t, hash, key) {
    let v = t.strong.get(hash);
    if (v)
        return v.value;

    let tv = new lobject.TValue(CT.LUA_TNIL, null);
    add(t, hash, key, tv);
    return tv;
};

const luaH_setint = function(t, key, value) {
    assert(typeof key == "number" && (key|0) === key && value instanceof lobject.TValue);
    let hash = key; /* table_hash known result */
    if (value.ttisnil()) {
        mark_dead(t, hash);
        return;
    }
    let v = t.strong.get(hash);
    if (v) {
        let tv = v.value;
        tv.setfrom(value);
    } else {
        let k = new lobject.TValue(CT.LUA_TNUMINT, key);
        let v = new lobject.TValue(value.type, value.value);
        add(t, hash, k, v);
    }
};

const luaH_set = function(t, key) {
    assert(key instanceof lobject.TValue);
    let hash = table_hash(key);
    return setgeneric(t, hash, new lobject.TValue(key.type, key.value));
};

const luaH_delete = function(t, key) {
    assert(key instanceof lobject.TValue);
    let hash = table_hash(key);
    return mark_dead(t, hash);
};

/*
** Try to find a boundary in table 't'. A 'boundary' is an integer index
** such that t[i] is non-nil and t[i+1] is nil (and 0 if t[1] is nil).
*/
const luaH_getn = function(t) {
    let i = 0;
    let j = t.strong.size + 1; /* use known size of Map to bound search */
    /* now do a binary search between them */
    while (j - i > 1) {
        let m = Math.floor((i+j)/2);
        if (luaH_getint(t, m).ttisnil()) j = m;
        else i = m;
    }
    return i;
};

const luaH_next = function(L, table, keyI) {
    let keyO = L.stack[keyI];

    let entry;
    if (keyO.type === CT.LUA_TNIL) {
        entry = table.f;
        if (!entry)
            return false;
    } else {
        /* First find current key */
        let hash = table_hash(keyO);
        /* Look in main part of table */
        entry = table.strong.get(hash);
        if (entry) {
            entry = entry.n;
            if (!entry)
                return false;
        } else {
            /* Try dead keys */
            entry = table.dead_weak.get(hash) || table.dead_strong.get(hash);
            if (!entry)
                /* item not in table */
                return ldebug.luaG_runerror(L, defs.to_luastring("invalid key to 'next'"));
            /* Iterate until either out of keys, or until finding a non-dead key */
            do {
                entry = entry.n;
                if (!entry)
                    return false;
            } while (entry.key.ttisdeadkey());
        }
    }
    L.stack[keyI] = new lobject.TValue(entry.key.type, entry.key.value);
    L.stack[keyI+1] = new lobject.TValue(entry.value.type, entry.value.value);
    return true;
};

module.exports.luaH_delete  = luaH_delete;
module.exports.luaH_get     = luaH_get;
module.exports.luaH_getint  = luaH_getint;
module.exports.luaH_getn    = luaH_getn;
module.exports.luaH_getstr  = luaH_getstr;
module.exports.luaH_set     = luaH_set;
module.exports.luaH_setint  = luaH_setint;
module.exports.luaH_new     = luaH_new;
module.exports.luaH_next    = luaH_next;
<|endoftext|>


<commit_before>'use strict';

const bytes = require('bytes');

// Returns the main numerical limits of the engine.
// Some of those limits cannot be changed by the user.
const getLimits = function ({
  runOpts: {
    pagesize,
    maxpayload = MAX_URL_LENGTH,
  } = {},
} = {}) {
  const maxpayloadA = bytes.parse(maxpayload);

  return {
    // Max number of top-level models returned in a response
    // Default: 100
    pagesize,
    // Max size of request payloads, in bytes.
    // Can use 'KB', 'MB', 'GB' OR 'TB'.
    // Default: '1MB'
    maxpayload: maxpayloadA,
    // Max size of an attribute's value, in bytes.
    maxAttrValueSize: 2e3,

    // Max URL length
    // Since URL can contain GraphQL query, it should not be less than
    // `maxpayload`
    maxUrlLength: Math.max(MAX_URL_LENGTH, maxpayloadA),
    // Max level of nesting in query string, e.g. ?var.subvar.subvar2=val
    maxQueryStringDepth: 10,
    // Max length of arrays in query string, e.g. ?var[50]=val
    maxQueryStringLength: 100,

    // How long the request can run, in milliseconds
    requestTimeout: 5e3,
    // When event listeners fail, they are retried with an ever increasing delay
    // This is the upper limit
    // This is 3 minutes, in milliseconds
    maxEventDelay: 18e4,

    // Enforced during schema validation:
    //  - max number of attributes per model: 50
    //  - max model|attribute name length: 200
  };
};

const MAX_URL_LENGTH = 2e3;

module.exports = {
  getLimits,
};
<commit_msg>Improve runOpts.pagesize 0<commit_after>'use strict';

const bytes = require('bytes');

// Returns the main numerical limits of the engine.
// Some of those limits cannot be changed by the user.
const getLimits = function ({
  runOpts: {
    pagesize,
    maxpayload = MAX_URL_LENGTH,
  } = {},
} = {}) {
  const maxpayloadA = bytes.parse(maxpayload);

  // `pagesize` `0` disables pagination
  const pagesizeA = pagesize === 0 ? Infinity : pagesize;

  return {
    // Max number of top-level models returned in a response
    // Default: 100
    pagesize: pagesizeA,
    // Max size of request payloads, in bytes.
    // Can use 'KB', 'MB', 'GB' OR 'TB'.
    // Default: '1MB'
    maxpayload: maxpayloadA,
    // Max size of an attribute's value, in bytes.
    maxAttrValueSize: 2e3,

    // Max URL length
    // Since URL can contain GraphQL query, it should not be less than
    // `maxpayload`
    maxUrlLength: Math.max(MAX_URL_LENGTH, maxpayloadA),
    // Max level of nesting in query string, e.g. ?var.subvar.subvar2=val
    maxQueryStringDepth: 10,
    // Max length of arrays in query string, e.g. ?var[50]=val
    maxQueryStringLength: 100,

    // How long the request can run, in milliseconds
    requestTimeout: 5e3,
    // When event listeners fail, they are retried with an ever increasing delay
    // This is the upper limit
    // This is 3 minutes, in milliseconds
    maxEventDelay: 18e4,

    // Enforced during schema validation:
    //  - max number of attributes per model: 50
    //  - max model|attribute name length: 200
  };
};

const MAX_URL_LENGTH = 2e3;

module.exports = {
  getLimits,
};
<|endoftext|>


<commit_before>Threesixty.prototype.load = function(options){
  //overwrite loader
  this.renderMeta = {};

  //catch options if present
  options = options || {};

  var _defaults = {
    //specifies how many rotations per row
    rows: 1,
    //loop horrizontaly
    loopX: true,
    //loop vertically
    loopY: false,
    //animation speed while in play modus
    speed: 1,
    //animation easing while interacting
    easing: 0.5,
    //turn to false when only preloading.
    renderAfterLoad: true,
    //auto start after ready status 1 (when first row is loaded)
    startOnStatus: 1,
    //startRow (first loaded row)
    startRow: -1,

    normal: {
      //urls to the sequence images
      sources: [],
      width: 640,
      height: 480
    },

    HD: {
      //urls to the sequence images.
      sources: [],
      width: 1280,
      height: 960
    }
  };

  //fill blank mandatory default properties
  for (var d in _defaults) {
    options[d] = options[d] || _defaults[d];
  }

  //validate type of properties
  var p = this;
  for (var key in _defaults) {
    if(typeof(_defaults[key])==typeof(options[key])){
      p.renderMeta[key] = options[key];
    } else {
      console.warn('Threesixty: load option ' + key + ' must be of type ' + typeof(_defaults[key]));
    }
  }

  if(this.renderMeta.renderAfterLoad){
    this.layout();
  }

  this.frames = [];

  var sources = this.renderMeta.normal.sources;
  var rowsCount = this.renderMeta.rows;
  var perRow = Math.floor(sources.length / rowsCount);

  for (var i = 0; i < this.renderMeta.rows; i++) {
    this.frames.push([]);
    for (var j = perRow - 1; j >= 0; j--) {
       this.frames[i].push(null);
    }
  };

  if(this.renderMeta.startRow==-1){
    this.renderMeta.startRow = Math.floor(rowsCount/2);
  }

  var that = this;
  this.loadRow({
    row:that.renderMeta.startRow,
    render:true,
    onFrame:function(e){
      var perc = e.frame / perRow;
      var loaderwidth = perc*that.width;

      that._$loader.width(loaderwidth);
    },
    onComplete:function(e){
      that._$loader.width(0);
      that.ready = 1;
      if(rowsCount>1){
        if(that.renderMeta.startOnStatus==1) {
          that.renderer();
        }
        loadAllFrames(e);
      } else {
        that.renderer();
      }
    }
  });

  function loadAllFrames(event){
    var rowLoaded = 0;

    var loadOtherRow = function(){
        that.loadRow({
          row: rowLoaded,
          render:false,
          onFrame: function(e){
            var perc =  (e.frame + (perRow*e.row)) / (perRow*rowsCount);
            var loaderwidth = perc*that.width;
            that._$loader.width(loaderwidth);
          },
          onComplete: function(){
            if(rowLoaded<rowsCount-1){

              rowLoaded++;
              loadOtherRow();
            } else {
              that.ready = 2;
              that._$loader.width(0);

              if(that.renderMeta.startOnStatus==2) {
                that.renderer();
              }
            }
          }
        });
    }

    loadOtherRow();
  }
}

Threesixty.prototype.loadRow = function(options){
  var sources = this.renderMeta.normal.sources;
  var rowsCount = this.renderMeta.rows;
  var perRow = Math.floor(sources.length / rowsCount);

  var startIndex = options.row * perRow;
  var endIndex = startIndex + perRow-1;
  var currentLoad = startIndex;

  var needsLoading = false;
  for (var i = perRow -1; i >= 0; i--) {
    var slot = this.frames[options.row][i];
    if(slot === null){
      needsLoading = true;
    }
  };

  var that = this;
  if(needsLoading==true){
    var normal = that.renderMeta.normal;
    var HD = that.renderMeta.HD;
    var preload = function() {
      var asset = document.createElement("img");
      asset.onload = function() {
        var rowID = options.row;
        var rowFrame = currentLoad - (perRow*rowID);

        if(that.frames[rowID][rowFrame]==null){
          that.frames[rowID][rowFrame] = this;
        }

        currentLoad++;

        if(options.render==true){

          that._context.globalAlpha = 1;
          that._context.clearRect( 0, 0, that.width, that.height );
          that._context.drawImage(this, 0, 0, normal.width, normal.height, 0, 0, that._canvas.width, that._canvas.height);

          if(currentLoad <= endIndex) {
            that._context.globalAlpha = 0.5;

            that._context.beginPath();
            that._context.rect(0,0,that._canvas.width,that._canvas.height);
            that._context.fillStyle = '#000000';
            that._context.fill();
          }
        }

        if(currentLoad > endIndex) {
          //loading finished!

          if(options.hasOwnProperty('onComplete')) {
            var rowFrame = currentLoad - (perRow*rowID) -1;
            options.onComplete({row:options.row,frame:rowFrame});
          }

          currentLoad = undefined;
        } else {
          //loading unfinished.
          if(options.hasOwnProperty('onFrame')) {
            var rowFrame = currentLoad - (perRow*rowID) - 1;
            options.onFrame({row:options.row,frame:rowFrame});
          }

          preload();
        }
      }

      // Set asset-to-load source path.
      asset.src = sources[currentLoad];
    }

    //next frame
    preload();
  } else {
    if(that.renderMeta.startRow!==options.row){
      console.warn('Threesixty: loader row ' + options.row + ' is already loaded.');
    }
    if(options.hasOwnProperty('onComplete')) {
      options.onComplete({row:options.row,frame:perRow -1});
    }
  }
}
<commit_msg>add render meta<commit_after>Threesixty.prototype.load = function(options){
  //overwrite loader
  this.renderMeta = {};

  //catch options if present
  options = options || {};

  var _defaults = {
    //specifies how many rotations per row
    rows: 1,
    //loop horrizontaly
    loopX: true,
    //loop vertically
    loopY: false,
    //animation speed while in play modus
    speed: 1,
    //animation easing while interacting
    easing: 0.5,
    //turn to false when only preloading.
    renderAfterLoad: true,
    //auto start after ready status 1 (when first row is loaded)
    startOnStatus: 1,
    //startRow (first loaded row)
    startRow: -1,

    normal: {
      //urls to the sequence images
      sources: [],
      width: 640,
      height: 480
    },

    HD: {
      //urls to the sequence images.
      sources: [],
      width: 1280,
      height: 960
    }
  };

  //fill blank mandatory default properties
  for (var d in _defaults) {
    options[d] = options[d] || _defaults[d];
  }

  //validate type of properties
  var p = this;
  for (var key in _defaults) {
    if(typeof(_defaults[key])==typeof(options[key])){
      p.renderMeta[key] = options[key];
    } else {
      console.warn('Threesixty: load option ' + key + ' must be of type ' + typeof(_defaults[key]));
    }
  }

  if(this.renderMeta.renderAfterLoad){
    this.layout();
  }

  this.frames = [];

  var sources = this.renderMeta.normal.sources;
  var rowsCount = this.renderMeta.rows;
  var perRow = Math.floor(sources.length / rowsCount);

  this.renderMeta.perRow = perRow;

  for (var i = 0; i < this.renderMeta.rows; i++) {
    this.frames.push([]);
    for (var j = perRow - 1; j >= 0; j--) {
       this.frames[i].push(null);
    }
  };

  if(this.renderMeta.startRow==-1){
    this.renderMeta.startRow = Math.floor(rowsCount/2);
  }

  var that = this;
  this.loadRow({
    row:that.renderMeta.startRow,
    render:true,
    onFrame:function(e){
      var perc = e.frame / perRow;
      var loaderwidth = perc*that.width;

      that._$loader.width(loaderwidth);
    },
    onComplete:function(e){
      that._$loader.width(0);
      that.ready = 1;
      if(rowsCount>1){
        if(that.renderMeta.startOnStatus==1) {
          that.renderer();
        }
        loadAllFrames(e);
      } else {
        that.renderer();
      }
    }
  });

  function loadAllFrames(event){
    var rowLoaded = 0;

    var loadOtherRow = function(){
        that.loadRow({
          row: rowLoaded,
          render:false,
          onFrame: function(e){
            var perc =  (e.frame + (perRow*e.row)) / (perRow*rowsCount);
            var loaderwidth = perc*that.width;
            that._$loader.width(loaderwidth);
          },
          onComplete: function(){
            if(rowLoaded<rowsCount-1){

              rowLoaded++;
              loadOtherRow();
            } else {
              that.ready = 2;
              that._$loader.width(0);

              if(that.renderMeta.startOnStatus==2) {
                that.renderer();
              }
            }
          }
        });
    }

    loadOtherRow();
  }
}

Threesixty.prototype.loadRow = function(options){
  var sources = this.renderMeta.normal.sources;
  var rowsCount = this.renderMeta.rows;
  var perRow = Math.floor(sources.length / rowsCount);

  var startIndex = options.row * perRow;
  var endIndex = startIndex + perRow-1;
  var currentLoad = startIndex;

  var needsLoading = false;
  for (var i = perRow -1; i >= 0; i--) {
    var slot = this.frames[options.row][i];
    if(slot === null){
      needsLoading = true;
    }
  };

  var that = this;
  if(needsLoading==true){
    var normal = that.renderMeta.normal;
    var HD = that.renderMeta.HD;
    var preload = function() {
      var asset = document.createElement("img");
      asset.onload = function() {
        var rowID = options.row;
        var rowFrame = currentLoad - (perRow*rowID);

        if(that.frames[rowID][rowFrame]==null){
          that.frames[rowID][rowFrame] = this;
        }

        currentLoad++;

        if(options.render==true){

          that._context.globalAlpha = 1;
          that._context.clearRect( 0, 0, that.width, that.height );
          that._context.drawImage(this, 0, 0, normal.width, normal.height, 0, 0, that._canvas.width, that._canvas.height);

          if(currentLoad <= endIndex) {
            that._context.globalAlpha = 0.8;

            that._context.beginPath();
            that._context.rect(0,0,that._canvas.width,that._canvas.height);
            that._context.fillStyle = '#000000';
            that._context.fill();
          }
        }

        if(currentLoad > endIndex) {
          //loading finished!

          if(options.hasOwnProperty('onComplete')) {
            var rowFrame = currentLoad - (perRow*rowID) -1;
            options.onComplete({row:options.row,frame:rowFrame});
          }

          currentLoad = undefined;
        } else {
          //loading unfinished.
          if(options.hasOwnProperty('onFrame')) {
            var rowFrame = currentLoad - (perRow*rowID) - 1;
            options.onFrame({row:options.row,frame:rowFrame});
          }

          preload();
        }
      }

      // Set asset-to-load source path.
      asset.src = sources[currentLoad];
    }

    //next frame
    preload();
  } else {
    if(that.renderMeta.startRow!==options.row){
      console.warn('Threesixty: loader row ' + options.row + ' is already loaded.');
    }
    if(options.hasOwnProperty('onComplete')) {
      options.onComplete({row:options.row,frame:perRow -1});
    }
  }
}
<|endoftext|>