<commit_before>/*global window, require, console */
/*
 * panel.js
 *
 * Copyright (c) 2014 James G Jenner
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

// "use strict"

var node = false;

if (typeof module == "undefined") {
  var module = function () {};
  var exports = this.panel = {};
  module.exports = exports;
}
if (typeof require != "undefined") {
  var uuid = require('node-uuid');
}

module.exports = Panel;

Panel.KEY = 'Panel';

Panel.ICON_USER_DEFINED = 'userDefined';
Panel.ICON_FONT_AWESOME = 'fontAwesom';
Panel.ICON_GLYPHICON = 'glyphicon';
Panel.ICON_OPEN_ICONIC = 'openIconic';
Panel.ICON_ENTYPO = 'entypo';

Panel.DEFAULT_NAME = 'Panel Name';
Panel.DEFAULT_WIDTH = 1;
Panel.DEFAULT_ROW = 0;
Panel.DEFAULT_COLUMN = 1;
Panel.DEFAULT_ICON_TYPE = Panel.ICON_FONT_AWESOME;
Panel.DEFAULT_ICON_NAME = 'fa-group';

Panel.MESSAGE_ADD_PANEL = 'addPanel';
Panel.MESSAGE_DELETE_PANEL = 'deletePanel';
Panel.MESSAGE_UPDATE_PANEL = 'updatePanel';
Panel.MESSAGE_GET_PANELS = 'getPanels';
Panel.MESSAGE_PANELS = 'panels';

Panel.MESSAGE_MOVE_PANEL_UP = 'movePanelUp';
Panel.MESSAGE_MOVE_PANEL_DOWN = 'movePanelDown';
Panel.MESSAGE_MOVE_PANEL_RIGHT = 'movePanelRight';
Panel.MESSAGE_MOVE_PANEL_LEFT = 'movePanelLeft';

function Panel(options) {
  options = options || {};

  var uuidV1 = ((options.uuidV1 !== null && options.uuidV1 !== undefined) ? options.uuidV1 : false);

  this.id = ((options.id !== null && options.id !== undefined) ? options.id : uuidV1 ? uuid.v1() : uuid.v4());
  this.name = ((options.name !== null && options.name !== undefined) ? options.name : Panel.DEFAULT_NAME);
  this.column = ((options.column !== null && options.column !== undefined) ? options.column : Panel.DEFAULT_COLUMN);
  this.width = ((options.width !== null && options.width !== undefined) ? options.width : Panel.DEFAULT_WIDTH);
  this.row = ((options.row !== null && options.row !== undefined) ? options.row : Panel.DEFAULT_ROW);
  this.iconName = ((options.iconName !== null && options.iconName !== undefined) ? options.iconName : Panel.DEFAULT_ICON_NAME);
  this.iconType = ((options.iconType !== null && options.iconType !== undefined) ? options.iconType : Panel.DEFAULT_ICON_TYPE);
}

/*
 * merge
 */
Panel.merge = function (d1, d2) {
  mergeAttribute(d1, d2, 'name');
  mergeAttribute(d1, d2, 'column');
  mergeAttribute(d1, d2, 'width');
  // TODO: sort out management of row value
  // mergeAttribute(d1, d2, 'row');
  mergeAttribute(d1, d2, 'iconName');
  mergeAttribute(d1, d2, 'iconType');
};

function mergeAttribute(object, modifiedObject, attribute) {
  object[attribute] = ((modifiedObject[attribute] !== null && modifiedObject[attribute] !== undefined) ? modifiedObject[attribute] : object[attribute]);
}<commit_msg>New msg type MESSAGE_MOVE_PANEL<commit_after>/*global window, require, console */
/*
 * panel.js
 *
 * Copyright (c) 2014 James G Jenner
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

// "use strict"

var node = false;

if (typeof module == "undefined") {
  var module = function () {};
  var exports = this.panel = {};
  module.exports = exports;
}
if (typeof require != "undefined") {
  var uuid = require('node-uuid');
}

module.exports = Panel;

Panel.KEY = 'Panel';

Panel.ICON_USER_DEFINED = 'userDefined';
Panel.ICON_FONT_AWESOME = 'fontAwesom';
Panel.ICON_GLYPHICON = 'glyphicon';
Panel.ICON_OPEN_ICONIC = 'openIconic';
Panel.ICON_ENTYPO = 'entypo';

Panel.DEFAULT_NAME = 'Panel Name';
Panel.DEFAULT_WIDTH = 1;
Panel.DEFAULT_ROW = 0;
Panel.DEFAULT_COLUMN = 1;
Panel.DEFAULT_ICON_TYPE = Panel.ICON_FONT_AWESOME;
Panel.DEFAULT_ICON_NAME = 'fa-group';

Panel.MESSAGE_ADD_PANEL = 'addPanel';
Panel.MESSAGE_DELETE_PANEL = 'deletePanel';
Panel.MESSAGE_UPDATE_PANEL = 'updatePanel';
Panel.MESSAGE_GET_PANELS = 'getPanels';
Panel.MESSAGE_PANELS = 'panels';

Panel.MESSAGE_MOVE_PANEL = 'movePanel';

Panel.MESSAGE_MOVE_PANEL_UP = 'movePanelUp';
Panel.MESSAGE_MOVE_PANEL_DOWN = 'movePanelDown';
Panel.MESSAGE_MOVE_PANEL_RIGHT = 'movePanelRight';
Panel.MESSAGE_MOVE_PANEL_LEFT = 'movePanelLeft';

function Panel(options) {
  options = options || {};

  var uuidV1 = ((options.uuidV1 !== null && options.uuidV1 !== undefined) ? options.uuidV1 : false);

  this.id = ((options.id !== null && options.id !== undefined) ? options.id : uuidV1 ? uuid.v1() : uuid.v4());
  this.name = ((options.name !== null && options.name !== undefined) ? options.name : Panel.DEFAULT_NAME);
  this.column = ((options.column !== null && options.column !== undefined) ? options.column : Panel.DEFAULT_COLUMN);
  this.width = ((options.width !== null && options.width !== undefined) ? options.width : Panel.DEFAULT_WIDTH);
  this.row = ((options.row !== null && options.row !== undefined) ? options.row : Panel.DEFAULT_ROW);
  this.iconName = ((options.iconName !== null && options.iconName !== undefined) ? options.iconName : Panel.DEFAULT_ICON_NAME);
  this.iconType = ((options.iconType !== null && options.iconType !== undefined) ? options.iconType : Panel.DEFAULT_ICON_TYPE);
}

/*
 * merge
 */
Panel.merge = function (d1, d2) {
  mergeAttribute(d1, d2, 'name');
  mergeAttribute(d1, d2, 'column');
  mergeAttribute(d1, d2, 'width');
  // TODO: sort out management of row value
  // mergeAttribute(d1, d2, 'row');
  mergeAttribute(d1, d2, 'iconName');
  mergeAttribute(d1, d2, 'iconType');
};

function mergeAttribute(object, modifiedObject, attribute) {
  object[attribute] = ((modifiedObject[attribute] !== null && modifiedObject[attribute] !== undefined) ? modifiedObject[attribute] : object[attribute]);
}<|endoftext|>


<commit_before>// Load in the EventEmitter
var spawn = require('child_process').spawn,
    EventEmitter = require('events').EventEmitter,
    nimble = require('nimble');

/**
 * Spawn for a single child. Always guarantees only one child exists
 * @see child_process.spawn
 * @param {String} cmd Command to run
 * @param {String[]} [args] Array of arguments to pass with cmd
 * @param {Object} [options] Options to pass to `spawn` and for ourselves
 * @param {Mixed} [options.killSignal] Signal to pass to `kill` executions
 */
var CHILDREN = [];
function SingleChild(cmd, args, options) {
  // If there are arguments, fallback options
  if (Array.isArray(args)) {
    options = options || {};
  } else {
  // Otherwise, fallback args
    options = args || {};
    args = [];
  }

  // Save arguments to starting/restarting
  this.cmd = cmd;
  this.args = args;
  this.options = options || {};

  // Save the child for self killing
  CHILDREN.push(this);

  // Call the EventEmitter constructor
  EventEmitter.call(this);
}
var SingleChildProto = {
  start: function (cb) {
    // Emit a start and proxy to restart
    return this.restart.apply(this, arguments);
  },
  /**
   * Stop the currently running child and start a new one
   * @param {Function} [cb] Error-first callback that returns *before* the child starts
   * @callback {Error|Null} err Error if there was one
   * @callback {ChildProcess} child Child that was started. Generated by node's ChildProcess#spawn
   */
  restart: function (cb) {
    // Stop the child
    var that = this;
    this.stop(function killedChild (code) {
      // Spawn a new child and emit start events
      that.emit('starting');
      var child = spawn(that.cmd, that.args, that.options);
      that.child = child;
      that.emit('started', child);

      // If the child leaves
      child.on('exit', function (code, signal) {
        // Unset the child
        that.child = null;

        // Emit an exit event
        that.emit('exited', code, signal);
      });

      // Callback with the child
      // DEV: It is important this runs before the child starts
      // so .stdout, .stderr hooks can be attached
      if (cb) {
        cb(null, child);
      }
    });
  },
  stop: function (cb) {
    // Emit a stop and proxy a SIGINT to kill
    return this.kill({signal: 'SIGINT'}, cb);
  },
  /**
   * Stop the currently running program
   * @param {Object} [options] Options for the kill action
   * @param {Mixed} [options.signal] Signal to use when killing
   * @param {Function} [cb] Callback to run when process has been killed.
   *     Receives same params as node's ChildProcess#exit event
   */
  kill: function (options, cb) {
    // Fallback options
    if (!cb) {
      cb = options;
      options = {};
    }

    // If there is no child, callback shortly
    var child = this.child;
    if (!child) {
      if (cb) {
        process.nextTick(cb);
      }
      return;
    }

    // Emit a killing event
    this.emit('killing', child);

    // Grab the signal and send it
    child.kill(options.signal || this.options.killSignal);

    // When we leave, callback with the exit code
    var that = this;
    child.on('exit', function cleanupChild (code, signal) {
      // Unset the child
      that.child = null;

      // Emit a killed event
      that.emit('killed', code, signal);

      // Callback with info
      if (cb) {
        cb(code, signal);
      }
    });
  }
};
SingleChild.prototype = SingleChildProto;

// Duck-punch EventEmitter methods
var EventProto = EventEmitter.prototype,
    key;
for (key in EventProto) {
  SingleChildProto[key] = EventProto[key];
}

console.log('hiii');

// When the process is leaving, kill all the children
function slaughterChildren () {
console.log('killing time');
  nimble.each(CHILDREN, function killChild (child, cb) {
    child.kill(function (err) {
      cb();
    });
  }, function leaveGracefully (err) {
    process.exit(0);
  });
}
// TODO: This is probably overkill
process.on('SIGINT', slaughterChildren);
process.on('SIGHUP', slaughterChildren);
process.on('SIGTERM', slaughterChildren);
process.on('SIGUSR2', slaughterChildren);
process.on('exit', slaughterChildren);

// Export the child
module.exports = SingleChild;<commit_msg>Confused about the timings of things =(<commit_after>// Load in the EventEmitter
var spawn = require('child_process').spawn,
    EventEmitter = require('events').EventEmitter,
    nimble = require('nimble');

/**
 * Spawn for a single child. Always guarantees only one child exists
 * @see child_process.spawn
 * @param {String} cmd Command to run
 * @param {String[]} [args] Array of arguments to pass with cmd
 * @param {Object} [options] Options to pass to `spawn` and for ourselves
 * @param {Mixed} [options.killSignal] Signal to pass to `kill` executions
 */
var CHILDREN = [];
function SingleChild(cmd, args, options) {
  // If there are arguments, fallback options
  if (Array.isArray(args)) {
    options = options || {};
  } else {
  // Otherwise, fallback args
    options = args || {};
    args = [];
  }

  // Save arguments to starting/restarting
  this.cmd = cmd;
  this.args = args;
  this.options = options || {};

  // Save the child for self killing
  CHILDREN.push(this);
console.log('children', CHILDREN, CHILDREN.length);

  // Call the EventEmitter constructor
  EventEmitter.call(this);
}
var SingleChildProto = {
  start: function (cb) {
    // Emit a start and proxy to restart
    return this.restart.apply(this, arguments);
  },
  /**
   * Stop the currently running child and start a new one
   * @param {Function} [cb] Error-first callback that returns *before* the child starts
   * @callback {Error|Null} err Error if there was one
   * @callback {ChildProcess} child Child that was started. Generated by node's ChildProcess#spawn
   */
  restart: function (cb) {
    // Stop the child
    var that = this;
    this.stop(function killedChild (code) {
      // Spawn a new child and emit start events
      that.emit('starting');
      var child = spawn(that.cmd, that.args, that.options);
      that.child = child;
      that.emit('started', child);

      // If the child leaves
      child.on('exit', function (code, signal) {
        // Unset the child
        that.child = null;

        // Emit an exit event
        that.emit('exited', code, signal);
      });

      // Callback with the child
      // DEV: It is important this runs before the child starts
      // so .stdout, .stderr hooks can be attached
      if (cb) {
        cb(null, child);
      }
    });
  },
  stop: function (cb) {
    // Emit a stop and proxy a SIGINT to kill
    return this.kill({signal: 'SIGINT'}, cb);
  },
  /**
   * Stop the currently running program
   * @param {Object} [options] Options for the kill action
   * @param {Mixed} [options.signal] Signal to use when killing
   * @param {Function} [cb] Callback to run when process has been killed.
   *     Receives same params as node's ChildProcess#exit event
   */
  kill: function (options, cb) {
    // Fallback options
    if (!cb) {
      cb = options;
      options = {};
    }

    // If there is no child, callback shortly
    var child = this.child;
    if (!child) {
      if (cb) {
        process.nextTick(cb);
      }
      return;
    }

    // Emit a killing event
    this.emit('killing', child);

    // Grab the signal and send it
    child.kill(options.signal || this.options.killSignal);

    // When we leave, callback with the exit code
    var that = this;
    child.on('exit', function cleanupChild (code, signal) {
      // Unset the child
      that.child = null;

      // Emit a killed event
      that.emit('killed', code, signal);

      // Callback with info
      if (cb) {
        cb(code, signal);
      }
    });
  }
};
SingleChild.prototype = SingleChildProto;

// Duck-punch EventEmitter methods
var EventProto = EventEmitter.prototype,
    key;
for (key in EventProto) {
  SingleChildProto[key] = EventProto[key];
}

console.log('hiii');

// When the process is leaving, kill all the children
function slaughterChildren () {
console.log('killing time', CHILDREN.length);
  nimble.each(CHILDREN, function killChild (child, cb) {
    console.log('abc', child.pid);
    // TODO: Try out taskkill https://github.com/remy/nodemon/blob/master/nodemon.js#L405
    child.kill(function (err) {
      cb();
    });
  }, function leaveGracefully (err) {
    process.exit(0);
  });
}
// TODO: This is probably overkill
// process.on('SIGINT', slaughterChildren);
// process.on('SIGHUP', slaughterChildren);
// process.on('SIGTERM', slaughterChildren);
// process.on('SIGUSR2', slaughterChildren);
process.on('exit', slaughterChildren);

// Export the child
module.exports = SingleChild;<|endoftext|>


<commit_before>"use strict";

window.AudioContext = window.AudioContext || window.webkitAudioContext;

/**
 * Loads sound files and lets you know when they're all available. An instance of SoundLoader is available as {@link Splat.Game#sounds}.
 * This implementation uses the Web Audio API, and if that is not available it automatically falls back to the HTML5 <audio> tag.
 * @constructor
 */
function SoundLoader() {
	/**
	 * The key-value object that stores named sounds.
	 * @member {object}
	 * @private
	 */
	this.sounds = {};
	/**
	 * The total number of sounds to be loaded.
	 * @member {number}
	 * @private
	 */
	this.totalSounds = 0;
	/**
	 * The number of sounds that have loaded completely.
	 * @member {number}
	 * @private
	 */
	this.loadedSounds = 0;
	/**
	 * A flag signifying if sounds are muted and should not be played.
	 * This only stops new sounds from being played, and doesn't actually mute the volume.
	 * Patches appreciated.
	 * @member {boolean}
	 * @private
	 */
	this.muted = false;
	/**
	 * A key-value object that stores named looping sounds.
	 * @member {object}
	 * @private
	 */
	this.looping = {};

	/**
	 * The Web Audio API AudioContext
	 * @member {external:AudioContext}
	 * @private
	 */
	this.context = new window.AudioContext();

	this.gainNode = this.context.createGain();
	this.gainNode.connect(this.context.destination);
	this.volume = this.gainNode.gain.value;
}
/**
 * Load an audio file.
 * @param {string} name The name you want to use when you {@link SoundLoader#play} the sound.
 * @param {string} path The path of the sound file.
 */
SoundLoader.prototype.load = function(name, path) {
	var self = this;

	if (this.totalSounds === 0) {
		// safari on iOS mutes sounds until they're played in response to user input
		// play a dummy sound on first touch
		var firstTouchHandler = function() {
			window.removeEventListener("click", firstTouchHandler);
			window.removeEventListener("keydown", firstTouchHandler);
			window.removeEventListener("touchstart", firstTouchHandler);

			var source = self.context.createOscillator();
			source.connect(self.gainNode);
			source.start(0);
			source.stop(0);

			if (self.firstPlay) {
				self.play(self.firstPlay, self.firstPlayLoop);
			} else {
				self.firstPlay = "workaround";
			}
		};
		window.addEventListener("click", firstTouchHandler);
		window.addEventListener("keydown", firstTouchHandler);
		window.addEventListener("touchstart", firstTouchHandler);
	}

	this.totalSounds++;

	var request = new XMLHttpRequest();
	request.open("GET", path, true);
	request.responseType = "arraybuffer";
	request.addEventListener("readystatechange", function() {
		if (request.readyState !== 4) {
			return;
		}
		if (request.status !== 200 && request.status !== 0) {
			console.error("Error loading sound " + path);
			return;
		}
		self.context.decodeAudioData(request.response, function(buffer) {
			self.sounds[name] = buffer;
			self.loadedSounds++;
		}, function(err) {
			console.error("Error decoding audio data for " + path + ": " + err);
		});
	});
	request.addEventListener("error", function() {
		console.error("Error loading sound " + path);
	});
	try {
		request.send();
	} catch (e) {
		console.error("Error loading sound", path, e);
	}
};
/**
 * Test if all sounds have loaded.
 * @returns {boolean}
 */
SoundLoader.prototype.allLoaded = function() {
	return this.totalSounds === this.loadedSounds;
};
/**
 * Play a sound.
 * @param {string} name The name given to the sound during {@link SoundLoader#load}
 * @param {boolean} [loop=false] A flag denoting whether the sound should be looped. To stop a looped sound use {@link SoundLoader#stop}.
 */
SoundLoader.prototype.play = function(name, loop) {
	if (loop && this.looping[name]) {
		return;
	}
	if (!this.firstPlay) {
		// let the iOS user input workaround handle it
		this.firstPlay = name;
		this.firstPlayLoop = loop;
		return;
	}
	var snd = this.sounds[name];
	if (snd === undefined) {
		console.error("Unknown sound: " + name);
	}
	var source = this.context.createBufferSource();
	source.buffer = snd;
	source.connect(this.gainNode);
	if (loop) {
		source.loop = true;
		this.looping[name] = source;
	}
	source.start(0);
};
/**
 * Stop playing a sound. This currently only stops playing a sound that was looped earlier, and doesn't stop a sound mid-play. Patches welcome.
 * @param {string} name The name given to the sound during {@link SoundLoader#load}
 */
SoundLoader.prototype.stop = function(name) {
	if (!this.looping[name]) {
		return;
	}
	this.looping[name].stop();
	delete this.looping[name];
};
SoundLoader.prototype.mute = function() {
	this.gainNode.gain.value = 0;
	this.muted = true;
};
SoundLoader.prototype.unmute = function() {
	this.gainNode.gain.value = this.volume;
	this.muted = false;
};
SoundLoader.prototype.setVolume = function(gain) {
	this.volume = gain;
	this.gainNode.gain  = gain;
	this.muted = false;
};
SoundLoader.prototype.isMuted = function() {
	return this.muted;
};

function AudioTagSoundLoader() {
	this.sounds = {};
	this.totalSounds = 0;
	this.loadedSounds = 0;
	this.muted = false;
	this.looping = {};
	this.volume = new Audio().volume;
}
AudioTagSoundLoader.prototype.load = function(name, path) {
	this.totalSounds++;

	var audio = new Audio();
	var self = this;
	audio.addEventListener("error", function() {
		console.error("Error loading sound " + path);
	});
	audio.addEventListener("canplaythrough", function() {
		self.sounds[name] = audio;
		self.loadedSounds++;
	});
	audio.volume = this.volume;
	audio.src = path;
	audio.load();
};
AudioTagSoundLoader.prototype.allLoaded = function() {
	return this.totalSounds === this.loadedSounds;
};
AudioTagSoundLoader.prototype.play = function(name, loop) {
	if (loop && this.looping[name]) {
		return;
	}
	if (this.muted) {
		return;
	}
	var snd = this.sounds[name];
	if (snd === undefined) {
		console.error("Unknown sound: " + name);
	}
	if (loop) {
		snd.loop = true;
		this.looping[name] = snd;
	}
	snd.play();
};
AudioTagSoundLoader.prototype.stop = function(name) {
	var snd = this.looping[name];
	if (!snd) {
		return;
	}
	snd.loop = false;
	snd.pause();
	snd.currentTime = 0;
	delete this.looping[name];
};
function setAudioTagVolume(sounds, gain) {
	for (var name in sounds) {
		if (sounds.hasOwnProperty(name)) {
			sounds[name].volume = gain;
		}
	}
}
AudioTagSoundLoader.prototype.mute = function() {
	setAudioTagVolume(this.sounds, 0);
	this.muted = true;
};
AudioTagSoundLoader.prototype.unmute = function() {
	setAudioTagVolume(this.sounds, this.volume);
	this.muted = false;
};
AudioTagSoundLoader.prototype.setVolume = function(gain) {
	this.volume = gain;
	setAudioTagVolume(this.sounds, gain);
	this.muted = false;
};
AudioTagSoundLoader.prototype.isMuted = function() {
	return this.muted;
};

function FakeSoundLoader() {}
FakeSoundLoader.prototype.load = function() {};
FakeSoundLoader.prototype.allLoaded = function() { return true; };
FakeSoundLoader.prototype.play = function() {};

if (window.AudioContext) {
	module.exports = SoundLoader;
} else if (window.Audio) {
	module.exports = AudioTagSoundLoader;
} else {
	console.log("This browser doesn't support the Web Audio API or the HTML5 audio tag.");
	module.exports = FakeSoundLoader;
}<commit_msg>Implement mute when no audio is supported<commit_after>"use strict";

window.AudioContext = window.AudioContext || window.webkitAudioContext;

/**
 * Loads sound files and lets you know when they're all available. An instance of SoundLoader is available as {@link Splat.Game#sounds}.
 * This implementation uses the Web Audio API, and if that is not available it automatically falls back to the HTML5 <audio> tag.
 * @constructor
 */
function SoundLoader() {
	/**
	 * The key-value object that stores named sounds.
	 * @member {object}
	 * @private
	 */
	this.sounds = {};
	/**
	 * The total number of sounds to be loaded.
	 * @member {number}
	 * @private
	 */
	this.totalSounds = 0;
	/**
	 * The number of sounds that have loaded completely.
	 * @member {number}
	 * @private
	 */
	this.loadedSounds = 0;
	/**
	 * A flag signifying if sounds are muted and should not be played.
	 * This only stops new sounds from being played, and doesn't actually mute the volume.
	 * Patches appreciated.
	 * @member {boolean}
	 * @private
	 */
	this.muted = false;
	/**
	 * A key-value object that stores named looping sounds.
	 * @member {object}
	 * @private
	 */
	this.looping = {};

	/**
	 * The Web Audio API AudioContext
	 * @member {external:AudioContext}
	 * @private
	 */
	this.context = new window.AudioContext();

	this.gainNode = this.context.createGain();
	this.gainNode.connect(this.context.destination);
	this.volume = this.gainNode.gain.value;
}
/**
 * Load an audio file.
 * @param {string} name The name you want to use when you {@link SoundLoader#play} the sound.
 * @param {string} path The path of the sound file.
 */
SoundLoader.prototype.load = function(name, path) {
	var self = this;

	if (this.totalSounds === 0) {
		// safari on iOS mutes sounds until they're played in response to user input
		// play a dummy sound on first touch
		var firstTouchHandler = function() {
			window.removeEventListener("click", firstTouchHandler);
			window.removeEventListener("keydown", firstTouchHandler);
			window.removeEventListener("touchstart", firstTouchHandler);

			var source = self.context.createOscillator();
			source.connect(self.gainNode);
			source.start(0);
			source.stop(0);

			if (self.firstPlay) {
				self.play(self.firstPlay, self.firstPlayLoop);
			} else {
				self.firstPlay = "workaround";
			}
		};
		window.addEventListener("click", firstTouchHandler);
		window.addEventListener("keydown", firstTouchHandler);
		window.addEventListener("touchstart", firstTouchHandler);
	}

	this.totalSounds++;

	var request = new XMLHttpRequest();
	request.open("GET", path, true);
	request.responseType = "arraybuffer";
	request.addEventListener("readystatechange", function() {
		if (request.readyState !== 4) {
			return;
		}
		if (request.status !== 200 && request.status !== 0) {
			console.error("Error loading sound " + path);
			return;
		}
		self.context.decodeAudioData(request.response, function(buffer) {
			self.sounds[name] = buffer;
			self.loadedSounds++;
		}, function(err) {
			console.error("Error decoding audio data for " + path + ": " + err);
		});
	});
	request.addEventListener("error", function() {
		console.error("Error loading sound " + path);
	});
	try {
		request.send();
	} catch (e) {
		console.error("Error loading sound", path, e);
	}
};
/**
 * Test if all sounds have loaded.
 * @returns {boolean}
 */
SoundLoader.prototype.allLoaded = function() {
	return this.totalSounds === this.loadedSounds;
};
/**
 * Play a sound.
 * @param {string} name The name given to the sound during {@link SoundLoader#load}
 * @param {boolean} [loop=false] A flag denoting whether the sound should be looped. To stop a looped sound use {@link SoundLoader#stop}.
 */
SoundLoader.prototype.play = function(name, loop) {
	if (loop && this.looping[name]) {
		return;
	}
	if (!this.firstPlay) {
		// let the iOS user input workaround handle it
		this.firstPlay = name;
		this.firstPlayLoop = loop;
		return;
	}
	var snd = this.sounds[name];
	if (snd === undefined) {
		console.error("Unknown sound: " + name);
	}
	var source = this.context.createBufferSource();
	source.buffer = snd;
	source.connect(this.gainNode);
	if (loop) {
		source.loop = true;
		this.looping[name] = source;
	}
	source.start(0);
};
/**
 * Stop playing a sound. This currently only stops playing a sound that was looped earlier, and doesn't stop a sound mid-play. Patches welcome.
 * @param {string} name The name given to the sound during {@link SoundLoader#load}
 */
SoundLoader.prototype.stop = function(name) {
	if (!this.looping[name]) {
		return;
	}
	this.looping[name].stop();
	delete this.looping[name];
};
SoundLoader.prototype.mute = function() {
	this.gainNode.gain.value = 0;
	this.muted = true;
};
SoundLoader.prototype.unmute = function() {
	this.gainNode.gain.value = this.volume;
	this.muted = false;
};
SoundLoader.prototype.setVolume = function(gain) {
	this.volume = gain;
	this.gainNode.gain  = gain;
	this.muted = false;
};
SoundLoader.prototype.isMuted = function() {
	return this.muted;
};

function AudioTagSoundLoader() {
	this.sounds = {};
	this.totalSounds = 0;
	this.loadedSounds = 0;
	this.muted = false;
	this.looping = {};
	this.volume = new Audio().volume;
}
AudioTagSoundLoader.prototype.load = function(name, path) {
	this.totalSounds++;

	var audio = new Audio();
	var self = this;
	audio.addEventListener("error", function() {
		console.error("Error loading sound " + path);
	});
	audio.addEventListener("canplaythrough", function() {
		self.sounds[name] = audio;
		self.loadedSounds++;
	});
	audio.volume = this.volume;
	audio.src = path;
	audio.load();
};
AudioTagSoundLoader.prototype.allLoaded = function() {
	return this.totalSounds === this.loadedSounds;
};
AudioTagSoundLoader.prototype.play = function(name, loop) {
	if (loop && this.looping[name]) {
		return;
	}
	if (this.muted) {
		return;
	}
	var snd = this.sounds[name];
	if (snd === undefined) {
		console.error("Unknown sound: " + name);
	}
	if (loop) {
		snd.loop = true;
		this.looping[name] = snd;
	}
	snd.play();
};
AudioTagSoundLoader.prototype.stop = function(name) {
	var snd = this.looping[name];
	if (!snd) {
		return;
	}
	snd.loop = false;
	snd.pause();
	snd.currentTime = 0;
	delete this.looping[name];
};
function setAudioTagVolume(sounds, gain) {
	for (var name in sounds) {
		if (sounds.hasOwnProperty(name)) {
			sounds[name].volume = gain;
		}
	}
}
AudioTagSoundLoader.prototype.mute = function() {
	setAudioTagVolume(this.sounds, 0);
	this.muted = true;
};
AudioTagSoundLoader.prototype.unmute = function() {
	setAudioTagVolume(this.sounds, this.volume);
	this.muted = false;
};
AudioTagSoundLoader.prototype.setVolume = function(gain) {
	this.volume = gain;
	setAudioTagVolume(this.sounds, gain);
	this.muted = false;
};
AudioTagSoundLoader.prototype.isMuted = function() {
	return this.muted;
};

function FakeSoundLoader() {}
FakeSoundLoader.prototype.load = function() {};
FakeSoundLoader.prototype.allLoaded = function() { return true; };
FakeSoundLoader.prototype.play = function() {};
FakeSoundLoader.prototype.stop = function() {};
FakeSoundLoader.prototype.mute = function() {};
FakeSoundLoader.prototype.unmute = function() {};
FakeSoundLoader.prototype.setVolume = function() {};
FakeSoundLoader.prototype.isMuted = function() {
	return true;
};

if (window.AudioContext) {
	module.exports = SoundLoader;
} else if (window.Audio) {
	module.exports = AudioTagSoundLoader;
} else {
	console.log("This browser doesn't support the Web Audio API or the HTML5 audio tag.");
	module.exports = FakeSoundLoader;
}<|endoftext|>


<commit_before>'use babel';

/* @flow */
import * as fs from 'fs';
import * as path from 'path';
import _ from 'lodash';
import os from 'os';
import { BufferedProcess } from 'atom';
/* flow-include
import type { TextEditor } from 'atom'
*/

export function run(textEditor/* :TextEditor*/) {
  return new Promise((resolve) => {
    let processOutput = `\u001b[1mTester Jest\u001b[0m${os.EOL}`;
    const fileName = textEditor.getPath();
    let outputFilePath = fileName;
    const projectPath = atom.project.relativizePath(fileName)[0];
    let cwd = projectPath;
    if (!(cwd)) {
      cwd = path.dirname(fileName);
    }
    const fileModified = textEditor.isModified();
    if (fileModified) {
      const outputDir = `${atom.getConfigDirPath()}/tester-jest`;
      if (!fs.existsSync(outputDir)) {
        fs.mkdir(outputDir);
      }
      outputFilePath = `${outputDir}/${path.basename(fileName)}`;
      fs.writeFileSync(outputFilePath, textEditor.getText());
    }
    function parseReporterOutput(outputString) {
      let output = '';
      const messages = [];
      _.forEach(_.split(outputString, os.EOL), (line) => {
        try {
          const summary = JSON.parse(line);
          console.log('outputEvent', summary);
          if (_.has(summary, 'testResults[0].assertionResults') && summary.testResults[0].assertionResults.length > 0) {
            _.forEach(summary.testResults[0].assertionResults, (testResult) => {
              messages.push({
                state: testResult.status,
                title: testResult.title,
                error: _.get(testResult, 'failureMessages[0]'),
                duration: summary.testResults[0].endTime - summary.testResults[0].startTime,
                lineNumber: 1,
                filePath: outputFilePath,
              });
            });
          }
          // messages.push(outputEvent);
        } catch (e) {
          output += line.toString() + os.EOL;
        }
      });
      return { messages, output };
    }
    const args = ['--json', outputFilePath];
    const options = { cwd };
    const jestBinary = atom.config.get('tester-jest.binaryPath');
    const command = jestBinary !== '' ? jestBinary : `${atom.packages.resolvePackagePath('tester-jest')}/node_modules/.bin/jest`;
    processOutput += `\u001b[1mcommand:\u001b[0m ${command} ${args.join(' ')}${os.EOL}`;
    processOutput += `\u001b[1mcwd:\u001b[0m ${cwd}${os.EOL}`;
    const stdout = data => processOutput += data;
    const stderr = data => processOutput += data;
    const exit = () => resolve(parseReporterOutput(processOutput));
    const process = new BufferedProcess({ command, args, options, stdout, stderr, exit });

    process.onWillThrowError((errorObject) => {
      atom.notifications.addError('Tester is unable to locate the jest command. Please ensure process.env.PATH can access jest.');
      console.error('Tester Jest: ', errorObject);
    });
  });
}
<commit_msg>use parser<commit_after>'use babel';

/* @flow */
import * as fs from 'fs';
import * as path from 'path';
import _ from 'lodash';
import os from 'os';
import { BufferedProcess } from 'atom';
import { parse } from 'jest-editor-support';
/* flow-include
import type { TextEditor } from 'atom'
*/

export function run(textEditor/* :TextEditor*/) {
  return new Promise((resolve) => {
    let processOutput = `\u001b[1mTester Jest\u001b[0m${os.EOL}`;
    const fileName = textEditor.getPath();
    let outputFilePath = fileName;
    const projectPath = atom.project.relativizePath(fileName)[0];
    let cwd = projectPath;
    if (!(cwd)) {
      cwd = path.dirname(fileName);
    }
    const fileModified = textEditor.isModified();
    if (fileModified) {
      const outputDir = `${atom.getConfigDirPath()}/tester-jest`;
      if (!fs.existsSync(outputDir)) {
        fs.mkdir(outputDir);
      }
      outputFilePath = `${outputDir}/${path.basename(fileName)}`;
      fs.writeFileSync(outputFilePath, textEditor.getText());
    }
    function parseReporterOutput(outputString) {
      let output = '';
      const messages = [];
      _.forEach(_.split(outputString, os.EOL), (line) => {
        try {
          const summary = JSON.parse(line);
          console.log('outputEvent', summary);
          if (_.has(summary, 'testResults[0].assertionResults') && summary.testResults[0].assertionResults.length > 0) {
            const parseJest = parse(outputFilePath);
            console.log('parseJest', parseJest);
            _.forEach(summary.testResults[0].assertionResults, (testResult) => {
              messages.push({
                state: testResult.status,
                title: testResult.title,
                error: _.get(testResult, 'failureMessages[0]'),
                duration: summary.testResults[0].endTime - summary.testResults[0].startTime,
                lineNumber: 1,
                filePath: outputFilePath,
              });
            });
          }
          // messages.push(outputEvent);
        } catch (e) {
          output += line.toString() + os.EOL;
        }
      });
      return { messages, output };
    }
    const args = ['--json', outputFilePath];
    const options = { cwd };
    const jestBinary = atom.config.get('tester-jest.binaryPath');
    const command = jestBinary !== '' ? jestBinary : `${atom.packages.resolvePackagePath('tester-jest')}/node_modules/.bin/jest`;
    processOutput += `\u001b[1mcommand:\u001b[0m ${command} ${args.join(' ')}${os.EOL}`;
    processOutput += `\u001b[1mcwd:\u001b[0m ${cwd}${os.EOL}`;
    const stdout = data => processOutput += data;
    const stderr = data => processOutput += data;
    const exit = () => resolve(parseReporterOutput(processOutput));
    const process = new BufferedProcess({ command, args, options, stdout, stderr, exit });

    process.onWillThrowError((errorObject) => {
      atom.notifications.addError('Tester is unable to locate the jest command. Please ensure process.env.PATH can access jest.');
      console.error('Tester Jest: ', errorObject);
    });
  });
}
<|endoftext|>


<commit_before>var path = require('path');
var bindings = require('../build/Release/spellchecker.node');

Spellchecker = bindings.Spellchecker;

var defaultSpellcheck = null;
var ensureDefaultSpellCheck = function() {
  if (defaultSpellcheck) return;

  defaultSpellcheck = new Spellchecker();
  defaultSpellcheck.setDictionary('en_US', path.join(__dirname, '..', 'vendor', 'hunspell_dictionaries'));
};

var isMisspelled = function(word) {
  ensureDefaultSpellCheck();

  return defaultSpellcheck.isMisspelled(word);
};

var getCorrectionsForMisspelling = function(word) {
  ensureDefaultSpellCheck();

  return defaultSpellcheck.getCorrectionsForMisspelling(word);
};

module.exports = {
  isMisspelled: isMisspelled,
  getCorrectionsForMisspelling: getCorrectionsForMisspelling,
  Spellchecker: Spellchecker
};
<commit_msg>Ensure arguments get marshaled correctly<commit_after>var path = require('path');
var bindings = require('../build/Release/spellchecker.node');

Spellchecker = bindings.Spellchecker;

var defaultSpellcheck = null;
var ensureDefaultSpellCheck = function() {
  if (defaultSpellcheck) return;

  defaultSpellcheck = new Spellchecker();
  defaultSpellcheck.setDictionary('en_US', path.join(__dirname, '..', 'vendor', 'hunspell_dictionaries'));
};

var isMisspelled = function() {
  ensureDefaultSpellCheck();

  return defaultSpellcheck.isMisspelled.apply(defaultSpellcheck, arguments);
};

var getCorrectionsForMisspelling = function() {
  ensureDefaultSpellCheck();

  return defaultSpellcheck.getCorrectionsForMisspelling.apply(defaultSpellcheck, arguments);
};

module.exports = {
  isMisspelled: isMisspelled,
  getCorrectionsForMisspelling: getCorrectionsForMisspelling,
  Spellchecker: Spellchecker
};
<|endoftext|>


<commit_before>/**
 * Created by vedi on 14/04/17.
 */

'use strict';

const Bb = require('bluebird');
const Client = require('ftp');
const path = require('path');
const mime = require('mime-types');

let client = new Client();
client = Bb.promisifyAll(client);

const utils = require('../utils');

const requireOptions = utils.requireOptions;

class FtpStorage {

  /**
   * @param options
   * @param options.uploadPath The remote path on ftp server
   *
   * ftp connection options:
   *
   * @param {string} options.host The hostname or IP address of the FTP server. Default: 'localhost'
   * @param {number} options.port The port of the FTP server. Default: 21
   * @param {(boolean|string)} options.secure Set to true for both control and data connection
   * encryption, 'control' for control connection encryption only, or 'implicit' for implicitly
   * encrypted control connection (this mode is deprecated in modern times, but usually uses port
   * 990) Default: false
   * @param {object} options.secureOptions Additional options to be passed to tls.connect().
   * Default: (none)
   * @param {string} options.user Username for authentication. Default: 'anonymous'
   * @param {string} options.password Password for authentication. Default: 'anonymous@'
   * @param {number} options.connTimeout How long (in milliseconds) to wait for the control
   * connection to be established. Default: 10000
   * @param {number} options.pasvTimeout How long (in milliseconds) to wait for a PASV data
   * connection to be established. Default: 10000
   * @param {number} options.keepalive How often (in milliseconds) to send a 'dummy' (NOOP)
   *  command to keep the connection alive. Default: 10000
   */
  initialize(options) {
    requireOptions(options, ['host']);
    this.options = options;
  }

  _connect(scope) {
    return new Bb((resolve, reject) => {
      let serverMessage;
      client.once('greeting', (msg) => {
        serverMessage = msg;
      });
      client.once('ready', () => resolve(serverMessage));
      client.once('error', err => reject(err));
      client.connect(Object.assign({}, this.options, scope.ftpOptions));
    });
  }

  getStream(fileMeta, scope) {
    const vals = {};
    const fileName = fileMeta;
    return this
      ._connect(scope)
      .then(() => client.sizeAsync(this._fullRemoteFileName(fileName)))
      .then((size) => {
        vals.size = size;
        return client.getAsync(fileName);
      })
      .then((stream) => {
        stream.once('close', () => { client.end(); });
        return {
          contentType: mime.lookup(fileName),
          contentLength: vals.size,
          stream,
        };
      })
      .catch((e) => {
        client.end();
        throw e;
      });
  }

  _fullRemoteFileName(fileName) {
    if (this.options.uploadPath) {
      return path.join(this.options.uploadPath, fileName);
    } else {
      return fileName;
    }
  }

  putFile(frompath, scope) {
    const fullRemoteFileName = this._fullRemoteFileName(path.basename(frompath));
    return this
      ._connect(scope)
      .then(() => Bb.fromCallback((callback) => {
        client.put(frompath, fullRemoteFileName, callback);
      }))
      .then(() => fullRemoteFileName)
      .finally(() => {
        client.end();
      });
  }

  replaceFile(fileMeta, fromPath, options, scope) {
    const prevRemotePath = this._fullRemoteFileName(fileMeta.fileName);
    const newRemotePath = this._fullRemoteFileName(path.basename(fromPath));
    return Bb
      .try(() => {
        if (prevRemotePath !== newRemotePath) {
          return this.deleteFile(prevRemotePath, scope);
        }
      })
      .then(() => this.putFile(fromPath, options, scope));
  }

  deleteFile(fileMeta, scope) {
    const fileName = fileMeta;
    return this
      ._connect(scope)
      .then(() => Bb.fromCallback((callback) => {
        client.delete(this._fullRemoteFileName(fileName), callback);
      }))
      .finally(() => {
        client.end();
      });
  }
}

module.exports = new FtpStorage();
<commit_msg>fix uploadPath for FTP<commit_after>/**
 * Created by vedi on 14/04/17.
 */

'use strict';

const Bb = require('bluebird');
const Client = require('ftp');
const path = require('path');
const mime = require('mime-types');

let client = new Client();
client = Bb.promisifyAll(client);

const utils = require('../utils');

const requireOptions = utils.requireOptions;

class FtpStorage {

  /**
   * @param {Object} options
   * @param {string} options.uploadPath the remote path on ftp server
   * @param {string} options.separator='/' string used on the FTP server for path concatination.
   *
   * ftp connection options:
   *
   * @param {string} options.host The hostname or IP address of the FTP server. Default: 'localhost'
   * @param {number} options.port The port of the FTP server. Default: 21
   * @param {(boolean|string)} options.secure Set to true for both control and data connection
   * encryption, 'control' for control connection encryption only, or 'implicit' for implicitly
   * encrypted control connection (this mode is deprecated in modern times, but usually uses port
   * 990) Default: false
   * @param {object} options.secureOptions Additional options to be passed to tls.connect().
   * Default: (none)
   * @param {string} options.user Username for authentication. Default: 'anonymous'
   * @param {string} options.password Password for authentication. Default: 'anonymous@'
   * @param {number} options.connTimeout How long (in milliseconds) to wait for the control
   * connection to be established. Default: 10000
   * @param {number} options.pasvTimeout How long (in milliseconds) to wait for a PASV data
   * connection to be established. Default: 10000
   * @param {number} options.keepalive How often (in milliseconds) to send a 'dummy' (NOOP)
   *  command to keep the connection alive. Default: 10000
   */
  initialize(options) {
    requireOptions(options, ['host']);
    this.options = options;
  }

  _connect(scope) {
    return new Bb((resolve, reject) => {
      let serverMessage;
      client.once('greeting', (msg) => {
        serverMessage = msg;
      });
      client.once('ready', () => resolve(serverMessage));
      client.once('error', err => reject(err));
      client.connect(Object.assign({}, this.options, scope.ftpOptions));
    });
  }

  getStream(fileMeta, scope) {
    const vals = {};
    const fileName = fileMeta;
    return this
      ._connect(scope)
      .then(() => client.sizeAsync(this._fullRemoteFileName(fileName)))
      .then((size) => {
        vals.size = size;
        return client.getAsync(fileName);
      })
      .then((stream) => {
        stream.once('close', () => { client.end(); });
        return {
          contentType: mime.lookup(fileName),
          contentLength: vals.size,
          stream,
        };
      })
      .catch((e) => {
        client.end();
        throw e;
      });
  }

  _fullRemoteFileName(fileName) {
    const { options: { uploadPath, separator = '/' } } = this;
    if (uploadPath) {
      return `${uploadPath}${separator}${fileName}`;
    } else {
      return fileName;
    }
  }

  putFile(fromPath, scope) {
    const fileName = path.basename(fromPath);
    const fullRemoteFileName = this._fullRemoteFileName(fileName);
    return this
      ._connect(scope)
      .then(() => Bb.fromCallback((callback) => {
        client.put(fromPath, fullRemoteFileName, callback);
      }))
      .then(() => fileName)
      .finally(() => {
        client.end();
      });
  }

  replaceFile(fileMeta, fromPath, options, scope) {
    const prevRemotePath = this._fullRemoteFileName(fileMeta.fileName);
    const newRemotePath = this._fullRemoteFileName(path.basename(fromPath));
    return Bb
      .try(() => {
        if (prevRemotePath !== newRemotePath) {
          return this.deleteFile(prevRemotePath, scope);
        }
      })
      .then(() => this.putFile(fromPath, options, scope));
  }

  deleteFile(fileMeta, scope) {
    const fileName = fileMeta;
    return this
      ._connect(scope)
      .then(() => Bb.fromCallback((callback) => {
        client.delete(this._fullRemoteFileName(fileName), callback);
      }))
      .finally(() => {
        client.end();
      });
  }
}

module.exports = new FtpStorage();
<|endoftext|>


<commit_before>
var AST      = require('../ast'),
    types    = require('../types'),
    Scope    = require('../typesystem/scope'),
    LLVM     = require('../../../llvm2'),
    Builtins = require('./llvm/builtins'),
    slots    = require('./llvm/slots')

// Unbox the slots module
var Slots         = slots.Slots,
    ConstantSlots = slots.ConstantSlots

var Int8Type    = LLVM.Types.Int8Type,
    Int32Type   = LLVM.Types.Int32Type,
    VoidType    = LLVM.Types.VoidType,
    Int8PtrType = LLVM.Types.pointerType(LLVM.Types.Int8Type)

var Int32Zero = LLVM.Library.LLVMConstInt(Int32Type, 0, true)

AST.Root.prototype.emitToFile = function (outFile) {
  var ctx = {}
  ctx.module       = new LLVM.Module('test')
  ctx.builder      = new LLVM.Builder()
  ctx.pass_manager = new LLVM.FunctionPassManager(ctx.module)
  ctx.funcs        = {}
  // Slots for global values (eg. builtins)
  ctx.globalSlots  = new ConstantSlots()
  // Maps sets of Slots to their associated Scope by the scope's ID
  ctx.slotsMap     = {}
  // Add the root scope to the slots map
  var rootScope = this.scope.parent
  if (!rootScope.isRoot) { throw new Error("Couldn't find root scope") }
  ctx.slotsMap[rootScope.id] = ctx.globalSlots

  // Set up the main function
  var mainType  = new LLVM.FunctionType(VoidType, [], false),
      mainFunc  = ctx.module.addFunction('main', mainType),
      mainEntry = mainFunc.appendBasicBlock('entry')

  // Add the builtins
  Builtins.compile(ctx, mainEntry, this)
  // Compile ourselves in the main entry function
  this.buildMain(ctx, mainEntry)

  ctx.module.dump()
  ctx.module.writeBitcodeToFile(outFile)
}

AST.Root.prototype.buildMain = function (ctx, mainEntry) {
  // Setup the entry into the function
  ctx.builder.positionAtEnd(mainEntry)
  compileBlock(ctx, this, mainEntry)

  // var str = ctx.builder.buildGlobalStringPtr("Hello world!\n", 'greeting')
  // ctx.builder.buildCall(ctx.funcs.puts, [str], '')
  ctx.builder.buildRetVoid()
}

function compileBlock (ctx, block, entry) {
  // Bunch of pre-conditions to make sure we got sane arguments
  if (!(block.statements instanceof Array)) {
    throw new Error('Missing statements in block')
  }
  if (!(block.scope instanceof Scope)) {
    throw new Error('Missing block\'s scope')
  }
  if (!entry) {
    throw new Error('Missing entry point for block')
  }

  // Set up slots for each local
  var scopeLocals = block.scope.locals,
      slots       = new Slots()
  Object.keys(scopeLocals).forEach(function (name) {
    slots.buildAlloc(ctx, name)
  })
  // Add the slots to the map of slots in the context
  ctx.slotsMap[block.scope.id] = slots
  // Set up a new context just for this block
  var blockCtx = new BlockContext(ctx, block, slots)

  var statements = block.statements
  for (var i = 0; i < statements.length; i++) {
    var stmt = statements[i]
    stmt.compile(ctx, blockCtx)
  }
}

function assertInstanceOf (value, type, message) {
  if (!(value instanceof type)) {
    if (!message) {
      message = 'Incorrect type; expected '+type.name+', got '+value.constructor.name
    }
    throw new Error(message)
  }
}

function BlockContext (ctx, block, slots) {
  this.ctx   = ctx
  this.block = block
  this.slots = slots
}

AST.Assignment.prototype.compile = function (ctx, blockCtx) {
  if (this.type === 'var' || this.type === 'let') {
    return this.compileNamed(ctx, blockCtx)
  }
  throw new Error('Cannot compile assignment type: '+this.type)
}

AST.Assignment.prototype.compileNamed = function (ctx, blockCtx) {
  // Get a value pointer from the rvalue
  var rvalue = this.rvalue.compileToValue(ctx, blockCtx)
  assertInstanceOf(rvalue, Buffer, 'Received non-Buffer from Node#compilerToValue')
  // Get the slot pointer
  blockCtx.slots.buildSet(ctx, this.lvalue.name, rvalue)
}

AST.Literal.prototype.compileToValue = function (ctx, blockCtx) {
  var instance = this.type
  switch (instance.type.constructor) {
    case types.String:
      var stringValue = this.value
      // Build a constant with our string value and return that
      var val = ctx.builder.buildGlobalStringPtr(stringValue, '')
      return val
    default:
      var name = instance.type.constructor.name
      throw new Error('AST.Literal#compileToValue: Cannot handle instance type: '+name)
  }
}

function checkScopePathForClosureOverreach (scopePath) {
  // Figure out the first (outermost) and last (innermost) indices of the closures
  var firstClosingIdx = -1,
      lastClosingIdx  = -1
  for (var i = 0; i < scopePath.length; i++) {
    var s = scopePath[i]
    if (s.isClosing) {
      // If the first closing index has been set then we know we're the first
      // one found
      if (firstClosingIdx === -1) { firstClosingIdx = i }
      // Push back the last closing index if we found another one
      if (i > lastClosingIdx) { lastClosingIdx = i }
    }
  }
  // If the closing indices don't match then we know we've busted through closures
  if (firstClosingIdx !== lastClosingIdx) {
    throw new Error('Too many closures')
  }
  // If the first closing index isn't the outermost one then we've busted
  // beyond a closure
  if (firstClosingIdx > 0) {
    throw new Error('Accessing variable beyond closure')
  }
}

function computeScopePath (blockCtx, outermostScope) {
  var scope = blockCtx.block.scope,
      path  = []
  while (true) {
    path.unshift(scope)
    // Stop building the scope path if we encountered the outermost scope
    if (scope === outermostScope) {
      break
    }
    // Otherwise go to the parent scope
    scope = scope.parent
    if (!scope) {
      throw new Error('Ran out of scopes!')
    }
  }
  return path
}

AST.Chain.prototype.compileToValue = function (ctx, blockCtx) {
  // Keep tracking of the scope of the beginning of the chain
  var outermostScope = null
  var itemType = blockCtx.block.scope.get(this.name, function (scope, type) {
    outermostScope = scope
  })

  // Outermost scope will be the first in `scopePath`; innermost scope
  // will be the last in `scopePath`.
  var scopePath = computeScopePath(blockCtx, outermostScope)

  // Sanity-check the `scopePath` to make sure it's outermost scope is the
  // same as the one we got from the Scope class' scope resolver.
  if (scopePath[0] !== outermostScope) {
    throw new Error('Invalid scope path: first scope does not match outermost scope')
  }

  // Check this scope path to make sure we didn't bust any closures
  checkScopePathForClosureOverreach(scopePath)

  // Look up the Slots for the scope that the head of our chain belongs to
  var slots = ctx.slotsMap[outermostScope.id]
  if (!slots) {
    throw new Error("Couldn't find slots for scope #"+outermostScope.id)
  }
  var itemValue = slots.buildGet(ctx, this.name)

  // Handle the tail
  for (var i = 0; i < this.tail.length; i++) {
    var item = this.tail[i]
    switch (item.constructor) {
    case AST.Property:
      assertInstanceOf(itemType, types.Instance)
      // Look up the type of the instance and get the native struct for it
      var type         = itemType.type,
          nativeObject = type.getNativeObject(),
          propertyName = item.name
      // Get the pointer to the property value
      var ptr = nativeObject.buildStructGEPForProperty(ctx, itemValue, propertyName)
      // Update the type and value
      itemType = type.getTypeOfProperty(propertyName)
      itemValue = ctx.builder.buildLoad(ptr, propertyName)
      break
    case AST.Call:
      assertInstanceOf(itemType, types.Function)
      // Compile all the args into values
      var argValues = item.args.map(function (arg) {
        return arg.compileToValue(ctx, blockCtx)
      })
      itemType  = new types.Instance(itemType.ret)
      itemValue = ctx.builder.buildCall(itemValue, argValues, '')
      break
    default:
      throw new Error("Cannot handle item type: "+item.constructor.name)
    }
  }
  return itemValue
}

AST.Chain.prototype.compile = function (ctx, blockCtx) {
  this.compileToValue(ctx, blockCtx)
}

<commit_msg>Setup proper class for LLVM compilation contexts<commit_after>
var AST      = require('../ast'),
    types    = require('../types'),
    Scope    = require('../typesystem/scope'),
    LLVM     = require('../../../llvm2'),
    Builtins = require('./llvm/builtins'),
    slots    = require('./llvm/slots')

// Unbox the slots module
var Slots         = slots.Slots,
    ConstantSlots = slots.ConstantSlots

var Int8Type    = LLVM.Types.Int8Type,
    Int32Type   = LLVM.Types.Int32Type,
    VoidType    = LLVM.Types.VoidType,
    Int8PtrType = LLVM.Types.pointerType(LLVM.Types.Int8Type)

var Int32Zero = LLVM.Library.LLVMConstInt(Int32Type, 0, true)

function Context () {}

AST.Root.prototype.emitToFile = function (outFile) {
  var ctx = new Context()
  ctx.module       = new LLVM.Module('test')
  ctx.builder      = new LLVM.Builder()
  ctx.pass_manager = new LLVM.FunctionPassManager(ctx.module)
  ctx.funcs        = {}
  // Slots for global values (eg. builtins)
  ctx.globalSlots  = new ConstantSlots()
  // Maps sets of Slots to their associated Scope by the scope's ID
  ctx.slotsMap     = {}
  // Add the root scope to the slots map
  var rootScope = this.scope.parent
  if (!rootScope.isRoot) { throw new Error("Couldn't find root scope") }
  ctx.slotsMap[rootScope.id] = ctx.globalSlots

  // Set up the main function
  var mainType  = new LLVM.FunctionType(VoidType, [], false),
      mainFunc  = ctx.module.addFunction('main', mainType),
      mainEntry = mainFunc.appendBasicBlock('entry')

  // Add the builtins
  Builtins.compile(ctx, mainEntry, this)
  // Compile ourselves in the main entry function
  this.buildMain(ctx, mainEntry)

  ctx.module.dump()
  ctx.module.writeBitcodeToFile(outFile)
}

AST.Root.prototype.buildMain = function (ctx, mainEntry) {
  // Setup the entry into the function
  ctx.builder.positionAtEnd(mainEntry)
  compileBlock(ctx, this, mainEntry)

  // var str = ctx.builder.buildGlobalStringPtr("Hello world!\n", 'greeting')
  // ctx.builder.buildCall(ctx.funcs.puts, [str], '')
  ctx.builder.buildRetVoid()
}

function compileBlock (ctx, block, entry) {
  // Bunch of pre-conditions to make sure we got sane arguments
  if (!(block.statements instanceof Array)) {
    throw new Error('Missing statements in block')
  }
  if (!(block.scope instanceof Scope)) {
    throw new Error('Missing block\'s scope')
  }
  if (!entry) {
    throw new Error('Missing entry point for block')
  }

  // Set up slots for each local
  var scopeLocals = block.scope.locals,
      slots       = new Slots()
  Object.keys(scopeLocals).forEach(function (name) {
    slots.buildAlloc(ctx, name)
  })
  // Add the slots to the map of slots in the context
  ctx.slotsMap[block.scope.id] = slots
  // Set up a new context just for this block
  var blockCtx = new BlockContext(ctx, block, slots)

  var statements = block.statements
  for (var i = 0; i < statements.length; i++) {
    var stmt = statements[i]
    stmt.compile(ctx, blockCtx)
  }
}

function assertInstanceOf (value, type, message) {
  if (!(value instanceof type)) {
    if (!message) {
      message = 'Incorrect type; expected '+type.name+', got '+value.constructor.name
    }
    throw new Error(message)
  }
}

function BlockContext (ctx, block, slots) {
  this.ctx   = ctx
  this.block = block
  this.slots = slots
}

AST.Assignment.prototype.compile = function (ctx, blockCtx) {
  if (this.type === 'var' || this.type === 'let') {
    return this.compileNamed(ctx, blockCtx)
  }
  throw new Error('Cannot compile assignment type: '+this.type)
}

AST.Assignment.prototype.compileNamed = function (ctx, blockCtx) {
  // Get a value pointer from the rvalue
  var rvalue = this.rvalue.compileToValue(ctx, blockCtx)
  assertInstanceOf(rvalue, Buffer, 'Received non-Buffer from Node#compilerToValue')
  // Get the slot pointer
  blockCtx.slots.buildSet(ctx, this.lvalue.name, rvalue)
}

AST.Literal.prototype.compileToValue = function (ctx, blockCtx) {
  var instance = this.type
  switch (instance.type.constructor) {
    case types.String:
      var stringValue = this.value
      // Build a constant with our string value and return that
      var val = ctx.builder.buildGlobalStringPtr(stringValue, '')
      return val
    default:
      var name = instance.type.constructor.name
      throw new Error('AST.Literal#compileToValue: Cannot handle instance type: '+name)
  }
}

function checkScopePathForClosureOverreach (scopePath) {
  // Figure out the first (outermost) and last (innermost) indices of the closures
  var firstClosingIdx = -1,
      lastClosingIdx  = -1
  for (var i = 0; i < scopePath.length; i++) {
    var s = scopePath[i]
    if (s.isClosing) {
      // If the first closing index has been set then we know we're the first
      // one found
      if (firstClosingIdx === -1) { firstClosingIdx = i }
      // Push back the last closing index if we found another one
      if (i > lastClosingIdx) { lastClosingIdx = i }
    }
  }
  // If the closing indices don't match then we know we've busted through closures
  if (firstClosingIdx !== lastClosingIdx) {
    throw new Error('Too many closures')
  }
  // If the first closing index isn't the outermost one then we've busted
  // beyond a closure
  if (firstClosingIdx > 0) {
    throw new Error('Accessing variable beyond closure')
  }
}

function computeScopePath (blockCtx, outermostScope) {
  var scope = blockCtx.block.scope,
      path  = []
  while (true) {
    path.unshift(scope)
    // Stop building the scope path if we encountered the outermost scope
    if (scope === outermostScope) {
      break
    }
    // Otherwise go to the parent scope
    scope = scope.parent
    if (!scope) {
      throw new Error('Ran out of scopes!')
    }
  }
  return path
}

AST.Chain.prototype.compileToValue = function (ctx, blockCtx) {
  // Keep tracking of the scope of the beginning of the chain
  var outermostScope = null
  var itemType = blockCtx.block.scope.get(this.name, function (scope, type) {
    outermostScope = scope
  })

  // Outermost scope will be the first in `scopePath`; innermost scope
  // will be the last in `scopePath`.
  var scopePath = computeScopePath(blockCtx, outermostScope)

  // Sanity-check the `scopePath` to make sure it's outermost scope is the
  // same as the one we got from the Scope class' scope resolver.
  if (scopePath[0] !== outermostScope) {
    throw new Error('Invalid scope path: first scope does not match outermost scope')
  }

  // Check this scope path to make sure we didn't bust any closures
  checkScopePathForClosureOverreach(scopePath)

  // Look up the Slots for the scope that the head of our chain belongs to
  var slots = ctx.slotsMap[outermostScope.id]
  if (!slots) {
    throw new Error("Couldn't find slots for scope #"+outermostScope.id)
  }
  var itemValue = slots.buildGet(ctx, this.name)

  // Handle the tail
  for (var i = 0; i < this.tail.length; i++) {
    var item = this.tail[i]
    switch (item.constructor) {
    case AST.Property:
      assertInstanceOf(itemType, types.Instance)
      // Look up the type of the instance and get the native struct for it
      var type         = itemType.type,
          nativeObject = type.getNativeObject(),
          propertyName = item.name
      // Get the pointer to the property value
      var ptr = nativeObject.buildStructGEPForProperty(ctx, itemValue, propertyName)
      // Update the type and value
      itemType = type.getTypeOfProperty(propertyName)
      itemValue = ctx.builder.buildLoad(ptr, propertyName)
      break
    case AST.Call:
      assertInstanceOf(itemType, types.Function)
      // Compile all the args into values
      var argValues = item.args.map(function (arg) {
        return arg.compileToValue(ctx, blockCtx)
      })
      itemType  = new types.Instance(itemType.ret)
      itemValue = ctx.builder.buildCall(itemValue, argValues, '')
      break
    default:
      throw new Error("Cannot handle item type: "+item.constructor.name)
    }
  }
  return itemValue
}

AST.Chain.prototype.compile = function (ctx, blockCtx) {
  this.compileToValue(ctx, blockCtx)
}

<|endoftext|>


<commit_before>var BufferedSender = function() {};
BufferedSender.prototype.send_constructor = function(sender) {
    var that = this;
    that.send_buffer = [];
    that.sender = sender;
};
BufferedSender.prototype.doSend = function(message) {
    var that = this;
    that.send_buffer.push(message);
    if (typeof that.send_stop === 'undefined') {
        that.send_schedule();
    }
};

BufferedSender.prototype.send_schedule = function() {
    var that = this;
    if (that.send_buffer.length > 0) {
        var payload = '[' + that.send_buffer.join(',') + ']';
        that.send_stop = that.sender(that.trans_url,
                                     payload,
                                     function() {
                                         that.send_stop = undefined;
                                         that.send_schedule();
                                     });
        that.send_buffer = [];
    }
};

BufferedSender.prototype.send_destructor = function() {
    var that = this;
    if (that._send_stop) {
        that._send_stop();
    }
    that._send_stop = null;
};

var jsonPGenericSender = function(url, payload, callback) {
    var that = this;
    if (!('_send_form' in that)) {
        var form = that._send_form = _document.createElement('form');
        var area = that._send_area = _document.createElement('textarea');
        area.name = 'd';
        form.style.display = 'none';
        form.style.position = 'absolute';
        form.method = 'POST';
        form.enctype = 'application/x-www-form-urlencoded';
        form.acceptCharset = "UTF-8";
        form.appendChild(area);
        _document.body.appendChild(form);
    }
    var form = that._send_form;
    var area = that._send_area;
    var id = 'a' + utils.random_string(8);
    form.target = id;
    form.action = url + '/jsonp_send?i=' + id;

    var iframe;
    try {
        // ie6 dynamic iframes with target="" support (thanks Chris Lambacher)
        iframe = _document.createElement('<iframe name="'+ id +'">');
    } catch(x) {
        iframe = _document.createElement('iframe');
        iframe.name = id;
    }
    iframe.id = id;
    form.appendChild(iframe);
    iframe.style.display = 'none';

    area.value = payload;
    form.submit();

    var completed = function(e) {
        if (!iframe.onerror) return;
        iframe.onreadystatechange = iframe.onerror = iframe.onload = null;
        // Opera mini doesn't like if we GC iframe
        // immediately, thus this timeout.
        setTimeout(function() {
                       iframe.parentNode.removeChild(iframe);
                       iframe = null;
                   }, 500);
        area.value = null;
        callback();
    };
    iframe.onerror = iframe.onload = completed;
    iframe.onreadystatechange = function(e) {
        if (iframe.readyState == 'complete') completed();
    };
    return completed;
};

var ajaxSender = function(url, payload, callback) {
    var orsc = function (xhr, e, abort_reason) {
        if(xhr.readyState === 4 || abort_reason) {
            callback(xhr.status, abort_reason);
        }
    };
    return utils.createXHR('POST', url + '/xhr_send', payload, orsc);
};

var xdrSender = function(url, payload, callback) {
    var orsc = function (xhr, e, abort_reason) {
        if(xhr.readyState === 4 || abort_reason) {
            callback(xhr.status, abort_reason);
        }
    };
    var fun = window.XDomainRequest ? utils.createXDR : utils.createXHR;
    return fun('POST', url + '/xhr_send', payload, orsc);
};

<commit_msg>Delay sending messages by 25 ms, in order to make tests more stable.<commit_after>var BufferedSender = function() {};
BufferedSender.prototype.send_constructor = function(sender) {
    var that = this;
    that.send_buffer = [];
    that.sender = sender;
};
BufferedSender.prototype.doSend = function(message) {
    var that = this;
    that.send_buffer.push(message);
    if (!that.send_stop) {
        that.send_schedule();
    }
};

// For polling transports in a situation when in the message callback,
// new message is being send. If the sending connection was started
// before receiving one, it is possible to saturate the network and
// timeout due to the lack of receiving socket. To avoid that we delay
// sending messages by some small time, in order to let receiving
// connection be started beforehand. This is only a halfmeasure and
// does not fix the big problem, but it does make the tests go more
// stable on slow networks.
BufferedSender.prototype.send_schedule_wait = function() {
    var that = this;
    var tref;
    that.send_stop = function() {
        that.send_stop = null;
        clearTimeout(tref);
    };
    tref = utils.delay(25, function() {
        that.send_stop = null;
        that.send_schedule();
    });
};

BufferedSender.prototype.send_schedule = function() {
    var that = this;
    if (that.send_buffer.length > 0) {
        var payload = '[' + that.send_buffer.join(',') + ']';
        that.send_stop = that.sender(that.trans_url,
                                     payload,
                                     function() {
                                         that.send_stop = null;
                                         that.send_schedule_wait();
                                     });
        that.send_buffer = [];
    }
};

BufferedSender.prototype.send_destructor = function() {
    var that = this;
    if (that._send_stop) {
        that._send_stop();
    }
    that._send_stop = null;
};

var jsonPGenericSender = function(url, payload, callback) {
    var that = this;
    if (!('_send_form' in that)) {
        var form = that._send_form = _document.createElement('form');
        var area = that._send_area = _document.createElement('textarea');
        area.name = 'd';
        form.style.display = 'none';
        form.style.position = 'absolute';
        form.method = 'POST';
        form.enctype = 'application/x-www-form-urlencoded';
        form.acceptCharset = "UTF-8";
        form.appendChild(area);
        _document.body.appendChild(form);
    }
    var form = that._send_form;
    var area = that._send_area;
    var id = 'a' + utils.random_string(8);
    form.target = id;
    form.action = url + '/jsonp_send?i=' + id;

    var iframe;
    try {
        // ie6 dynamic iframes with target="" support (thanks Chris Lambacher)
        iframe = _document.createElement('<iframe name="'+ id +'">');
    } catch(x) {
        iframe = _document.createElement('iframe');
        iframe.name = id;
    }
    iframe.id = id;
    form.appendChild(iframe);
    iframe.style.display = 'none';

    area.value = payload;
    form.submit();

    var completed = function(e) {
        if (!iframe.onerror) return;
        iframe.onreadystatechange = iframe.onerror = iframe.onload = null;
        // Opera mini doesn't like if we GC iframe
        // immediately, thus this timeout.
        setTimeout(function() {
                       iframe.parentNode.removeChild(iframe);
                       iframe = null;
                   }, 500);
        area.value = null;
        callback();
    };
    iframe.onerror = iframe.onload = completed;
    iframe.onreadystatechange = function(e) {
        if (iframe.readyState == 'complete') completed();
    };
    return completed;
};

var ajaxSender = function(url, payload, callback) {
    var orsc = function (xhr, e, abort_reason) {
        if(xhr.readyState === 4 || abort_reason) {
            callback(xhr.status, abort_reason);
        }
    };
    return utils.createXHR('POST', url + '/xhr_send', payload, orsc);
};

var xdrSender = function(url, payload, callback) {
    var orsc = function (xhr, e, abort_reason) {
        if(xhr.readyState === 4 || abort_reason) {
            callback(xhr.status, abort_reason);
        }
    };
    var fun = window.XDomainRequest ? utils.createXDR : utils.createXHR;
    return fun('POST', url + '/xhr_send', payload, orsc);
};

<|endoftext|>


<commit_before>'use strict';

var bitcore = require('bitcore-lib-dash');
var _ = bitcore.deps._;
var $ = bitcore.util.preconditions;
var Common = require('./common');
var async = require('async');

var MAXINT = 0xffffffff; // Math.pow(2, 32) - 1;

function TxController(node) {
  this.node = node;
  this.common = new Common({log: this.node.log});
}

TxController.prototype.show = function(req, res) {
  if (req.transaction) {
    res.jsonp(req.transaction);
  }
};

/**
 * Find transaction by hash ...
 */
TxController.prototype.transaction = function(req, res, next) {
  var self = this;
  var txid = req.params.txid;

  this.node.getDetailedTransaction(txid, function(err, transaction) {
    if (err && err.code === -5) {
      return self.common.handleErrors(null, res);
    } else if(err) {
      return self.common.handleErrors(err, res);
    }

    self.transformTransaction(transaction, function(err, transformedTransaction) {
      if (err) {
        return self.common.handleErrors(err, res);
      }
      req.transaction = transformedTransaction;
      next();
    });

  });
};

TxController.prototype.transformTransaction = function(transaction, options, callback) {
  if (_.isFunction(options)) {
    callback = options;
    options = {};
  }
  $.checkArgument(_.isFunction(callback));

  var confirmations = 0;
  if(transaction.height >= 0) {
    confirmations = this.node.services.bitcoind.height - transaction.height + 1;
  }

  var transformed = {
    txid: transaction.hash,
    version: transaction.version,
    locktime: transaction.locktime
  };

  if(transaction.coinbase) {
    transformed.vin = [
      {
        coinbase: transaction.inputs[0].script,
        sequence: transaction.inputs[0].sequence,
        n: 0
      }
    ];
  } else {
    transformed.vin = transaction.inputs.map(this.transformInput.bind(this, options));
  }

  transformed.vout = transaction.outputs.map(this.transformOutput.bind(this, options));

  transformed.blockhash = transaction.blockHash;
  transformed.blockheight = transaction.height;
  transformed.confirmations = confirmations;
  // TODO consider mempool txs with receivedTime?
  var time = transaction.blockTimestamp ? transaction.blockTimestamp : Math.round(Date.now() / 1000);
  transformed.time = time;
  if (transformed.confirmations) {
    transformed.blocktime = transformed.time;
  }

  if(transaction.coinbase) {
    transformed.isCoinBase = true;
  }

  transformed.valueOut = transaction.outputSatoshis / 1e8;
  transformed.size = transaction.hex.length / 2; // in bytes
  if (!transaction.coinbase) {
    transformed.valueIn = transaction.inputSatoshis / 1e8;
    transformed.fees = transaction.feeSatoshis / 1e8;
  }

  transformed.txlock = transaction.txlock;

  callback(null, transformed);
};

TxController.prototype.transformInput = function(options, input, index) {
  // Input scripts are validated and can be assumed to be valid
  var transformed = {
    txid: input.prevTxId,
    vout: input.outputIndex,
    sequence: input.sequence,
    n: index
  };

  if (!options.noScriptSig) {
    transformed.scriptSig = {
      hex: input.script
    };
    if (!options.noAsm) {
      transformed.scriptSig.asm = input.scriptAsm;
    }
  }

  transformed.addr = input.address;
  transformed.valueSat = input.satoshis;
  transformed.value = input.satoshis / 1e8;
  transformed.doubleSpentTxID = null; // TODO
  //transformed.isConfirmed = null; // TODO
  //transformed.confirmations = null; // TODO
  //transformed.unconfirmedInput = null; // TODO

  return transformed;
};

TxController.prototype.transformOutput = function(options, output, index) {
  var transformed = {
    value: (output.satoshis / 1e8).toFixed(8),
    n: index,
    scriptPubKey: {
      hex: output.script
    }
  };

  if (!options.noAsm) {
    transformed.scriptPubKey.asm = output.scriptAsm;
  }

  if (!options.noSpent) {
    transformed.spentTxId = output.spentTxId || null;
    transformed.spentIndex = _.isUndefined(output.spentIndex) ? null : output.spentIndex;
    transformed.spentHeight = output.spentHeight || null;
  }

  if (output.address) {
    transformed.scriptPubKey.addresses = [output.address];
    var address = bitcore.Address(output.address); //TODO return type from bitcore-node
    transformed.scriptPubKey.type = address.type;
  }
  return transformed;
};

TxController.prototype.transformInvTransaction = function(transaction) {
  var self = this;

  var valueOut = 0;
  var vout = [];
  for (var i = 0; i < transaction.outputs.length; i++) {
    var output = transaction.outputs[i];
    valueOut += output.satoshis;
    if (output.script) {
      var address = output.script.toAddress(self.node.network);
      if (address) {
        var obj = {};
        obj[address.toString()] = output.satoshis;
        vout.push(obj);
      }
    }
  }

  var isRBF = _.any(_.pluck(transaction.inputs, 'sequenceNumber'), function(seq) {
    return seq < MAXINT - 1;
  });

  var transformed = {
    txid: transaction.hash,
    valueOut: valueOut / 1e8,
    vout: vout,
    isRBF: isRBF,
    txlock: false
  };

  return transformed;
};

TxController.prototype.rawTransaction = function(req, res, next) {
  var self = this;
  var txid = req.params.txid;

  this.node.getTransaction(txid, function(err, transaction) {
    if (err && err.code === -5) {
      return self.common.handleErrors(null, res);
    } else if(err) {
      return self.common.handleErrors(err, res);
    }

    req.rawTransaction = {
      'rawtx': transaction.toBuffer().toString('hex')
    };

    next();
  });
};

TxController.prototype.showRaw = function(req, res) {
  if (req.rawTransaction) {
    res.jsonp(req.rawTransaction);
  }
};

TxController.prototype.list = function(req, res) {
  var self = this;

  var blockHash = req.query.block;
  var address = req.query.address;
  var page = parseInt(req.query.pageNum) || 0;
  var pageLength = 10;
  var pagesTotal = 1;

  if(blockHash) {
    self.node.getBlockOverview(blockHash, function(err, block) {
      if(err && err.code === -5) {
        return self.common.handleErrors(null, res);
      } else if(err) {
        return self.common.handleErrors(err, res);
      }

      var totalTxs = block.txids.length;
      var txids;

      if(!_.isUndefined(page)) {
        var start = page * pageLength;
        txids = block.txids.slice(start, start + pageLength);
        pagesTotal = Math.ceil(totalTxs / pageLength);
      } else {
        txids = block.txids;
      }

      async.mapSeries(txids, function(txid, next) {
        self.node.getDetailedTransaction(txid, function(err, transaction) {
          if (err) {
            return next(err);
          }
          self.transformTransaction(transaction, next);
        });
      }, function(err, transformed) {
        if(err) {
          return self.common.handleErrors(err, res);
        }

        res.jsonp({
          pagesTotal: pagesTotal,
          txs: transformed
        });
      });

    });
  } else if(address) {
    var options = {
      from: page * pageLength,
      to: (page + 1) * pageLength
    };

    self.node.getAddressHistory(address, options, function(err, result) {
      if(err) {
        return self.common.handleErrors(err, res);
      }

      var txs = result.items.map(function(info) {
        return info.tx;
      }).filter(function(value, index, self) {
        return self.indexOf(value) === index;
      });

      async.map(
        txs,
        function(tx, next) {
          self.transformTransaction(tx, next);
        },
        function(err, transformed) {
          if (err) {
            return self.common.handleErrors(err, res);
          }
          res.jsonp({
            pagesTotal: Math.ceil(result.totalCount / pageLength),
            txs: transformed
          });
        }
      );
    });
  } else {
    return self.common.handleErrors(new Error('Block hash or address expected'), res);
  }
};

TxController.prototype.send = function(req, res) {
  var self = this;
  this.node.sendTransaction(req.body.rawtx, function(err, txid) {
    if(err) {
      // TODO handle specific errors
      return self.common.handleErrors(err, res);
    }

    res.json({'txid': txid});
  });
};
//Handler for InstantSend
TxController.prototype.sendix = function(req, res) {
	var self = this;
	if(_.isUndefined(req.body.rawtx)){
		return self.common.handleErrors({
			message:"Missing parameter (expected 'rawtx' a string)",
			code:1
		}, res);
	}
	var options = {allowAbsurdFees: false, isInstasend: true};
	this.node.sendTransaction(req.body.rawtx, options, function(err, txid) {
		if(err) {
			// TODO handle specific errors
			return self.common.handleErrors(err, res);
		}
		res.json({'txid': txid});
	});
};
module.exports = TxController;
<commit_msg>Fix : Reflect new options isInstantSend name.<commit_after>'use strict';

var bitcore = require('bitcore-lib-dash');
var _ = bitcore.deps._;
var $ = bitcore.util.preconditions;
var Common = require('./common');
var async = require('async');

var MAXINT = 0xffffffff; // Math.pow(2, 32) - 1;

function TxController(node) {
  this.node = node;
  this.common = new Common({log: this.node.log});
}

TxController.prototype.show = function(req, res) {
  if (req.transaction) {
    res.jsonp(req.transaction);
  }
};

/**
 * Find transaction by hash ...
 */
TxController.prototype.transaction = function(req, res, next) {
  var self = this;
  var txid = req.params.txid;

  this.node.getDetailedTransaction(txid, function(err, transaction) {
    if (err && err.code === -5) {
      return self.common.handleErrors(null, res);
    } else if(err) {
      return self.common.handleErrors(err, res);
    }

    self.transformTransaction(transaction, function(err, transformedTransaction) {
      if (err) {
        return self.common.handleErrors(err, res);
      }
      req.transaction = transformedTransaction;
      next();
    });

  });
};

TxController.prototype.transformTransaction = function(transaction, options, callback) {
  if (_.isFunction(options)) {
    callback = options;
    options = {};
  }
  $.checkArgument(_.isFunction(callback));

  var confirmations = 0;
  if(transaction.height >= 0) {
    confirmations = this.node.services.bitcoind.height - transaction.height + 1;
  }

  var transformed = {
    txid: transaction.hash,
    version: transaction.version,
    locktime: transaction.locktime
  };

  if(transaction.coinbase) {
    transformed.vin = [
      {
        coinbase: transaction.inputs[0].script,
        sequence: transaction.inputs[0].sequence,
        n: 0
      }
    ];
  } else {
    transformed.vin = transaction.inputs.map(this.transformInput.bind(this, options));
  }

  transformed.vout = transaction.outputs.map(this.transformOutput.bind(this, options));

  transformed.blockhash = transaction.blockHash;
  transformed.blockheight = transaction.height;
  transformed.confirmations = confirmations;
  // TODO consider mempool txs with receivedTime?
  var time = transaction.blockTimestamp ? transaction.blockTimestamp : Math.round(Date.now() / 1000);
  transformed.time = time;
  if (transformed.confirmations) {
    transformed.blocktime = transformed.time;
  }

  if(transaction.coinbase) {
    transformed.isCoinBase = true;
  }

  transformed.valueOut = transaction.outputSatoshis / 1e8;
  transformed.size = transaction.hex.length / 2; // in bytes
  if (!transaction.coinbase) {
    transformed.valueIn = transaction.inputSatoshis / 1e8;
    transformed.fees = transaction.feeSatoshis / 1e8;
  }

  transformed.txlock = transaction.txlock;

  callback(null, transformed);
};

TxController.prototype.transformInput = function(options, input, index) {
  // Input scripts are validated and can be assumed to be valid
  var transformed = {
    txid: input.prevTxId,
    vout: input.outputIndex,
    sequence: input.sequence,
    n: index
  };

  if (!options.noScriptSig) {
    transformed.scriptSig = {
      hex: input.script
    };
    if (!options.noAsm) {
      transformed.scriptSig.asm = input.scriptAsm;
    }
  }

  transformed.addr = input.address;
  transformed.valueSat = input.satoshis;
  transformed.value = input.satoshis / 1e8;
  transformed.doubleSpentTxID = null; // TODO
  //transformed.isConfirmed = null; // TODO
  //transformed.confirmations = null; // TODO
  //transformed.unconfirmedInput = null; // TODO

  return transformed;
};

TxController.prototype.transformOutput = function(options, output, index) {
  var transformed = {
    value: (output.satoshis / 1e8).toFixed(8),
    n: index,
    scriptPubKey: {
      hex: output.script
    }
  };

  if (!options.noAsm) {
    transformed.scriptPubKey.asm = output.scriptAsm;
  }

  if (!options.noSpent) {
    transformed.spentTxId = output.spentTxId || null;
    transformed.spentIndex = _.isUndefined(output.spentIndex) ? null : output.spentIndex;
    transformed.spentHeight = output.spentHeight || null;
  }

  if (output.address) {
    transformed.scriptPubKey.addresses = [output.address];
    var address = bitcore.Address(output.address); //TODO return type from bitcore-node
    transformed.scriptPubKey.type = address.type;
  }
  return transformed;
};

TxController.prototype.transformInvTransaction = function(transaction) {
  var self = this;

  var valueOut = 0;
  var vout = [];
  for (var i = 0; i < transaction.outputs.length; i++) {
    var output = transaction.outputs[i];
    valueOut += output.satoshis;
    if (output.script) {
      var address = output.script.toAddress(self.node.network);
      if (address) {
        var obj = {};
        obj[address.toString()] = output.satoshis;
        vout.push(obj);
      }
    }
  }

  var isRBF = _.any(_.pluck(transaction.inputs, 'sequenceNumber'), function(seq) {
    return seq < MAXINT - 1;
  });

  var transformed = {
    txid: transaction.hash,
    valueOut: valueOut / 1e8,
    vout: vout,
    isRBF: isRBF,
    txlock: false
  };

  return transformed;
};

TxController.prototype.rawTransaction = function(req, res, next) {
  var self = this;
  var txid = req.params.txid;

  this.node.getTransaction(txid, function(err, transaction) {
    if (err && err.code === -5) {
      return self.common.handleErrors(null, res);
    } else if(err) {
      return self.common.handleErrors(err, res);
    }

    req.rawTransaction = {
      'rawtx': transaction.toBuffer().toString('hex')
    };

    next();
  });
};

TxController.prototype.showRaw = function(req, res) {
  if (req.rawTransaction) {
    res.jsonp(req.rawTransaction);
  }
};

TxController.prototype.list = function(req, res) {
  var self = this;

  var blockHash = req.query.block;
  var address = req.query.address;
  var page = parseInt(req.query.pageNum) || 0;
  var pageLength = 10;
  var pagesTotal = 1;

  if(blockHash) {
    self.node.getBlockOverview(blockHash, function(err, block) {
      if(err && err.code === -5) {
        return self.common.handleErrors(null, res);
      } else if(err) {
        return self.common.handleErrors(err, res);
      }

      var totalTxs = block.txids.length;
      var txids;

      if(!_.isUndefined(page)) {
        var start = page * pageLength;
        txids = block.txids.slice(start, start + pageLength);
        pagesTotal = Math.ceil(totalTxs / pageLength);
      } else {
        txids = block.txids;
      }

      async.mapSeries(txids, function(txid, next) {
        self.node.getDetailedTransaction(txid, function(err, transaction) {
          if (err) {
            return next(err);
          }
          self.transformTransaction(transaction, next);
        });
      }, function(err, transformed) {
        if(err) {
          return self.common.handleErrors(err, res);
        }

        res.jsonp({
          pagesTotal: pagesTotal,
          txs: transformed
        });
      });

    });
  } else if(address) {
    var options = {
      from: page * pageLength,
      to: (page + 1) * pageLength
    };

    self.node.getAddressHistory(address, options, function(err, result) {
      if(err) {
        return self.common.handleErrors(err, res);
      }

      var txs = result.items.map(function(info) {
        return info.tx;
      }).filter(function(value, index, self) {
        return self.indexOf(value) === index;
      });

      async.map(
        txs,
        function(tx, next) {
          self.transformTransaction(tx, next);
        },
        function(err, transformed) {
          if (err) {
            return self.common.handleErrors(err, res);
          }
          res.jsonp({
            pagesTotal: Math.ceil(result.totalCount / pageLength),
            txs: transformed
          });
        }
      );
    });
  } else {
    return self.common.handleErrors(new Error('Block hash or address expected'), res);
  }
};

TxController.prototype.send = function(req, res) {
  var self = this;
  this.node.sendTransaction(req.body.rawtx, function(err, txid) {
    if(err) {
      // TODO handle specific errors
      return self.common.handleErrors(err, res);
    }

    res.json({'txid': txid});
  });
};
//Handler for InstantSend
TxController.prototype.sendix = function(req, res) {
	var self = this;
	if(_.isUndefined(req.body.rawtx)){
		return self.common.handleErrors({
			message:"Missing parameter (expected 'rawtx' a string)",
			code:1
		}, res);
	}
	var options = {allowAbsurdFees: false, isInstantSend: true};
	this.node.sendTransaction(req.body.rawtx, options, function(err, txid) {
		if(err) {
			// TODO handle specific errors
			return self.common.handleErrors(err, res);
		}
		res.json({'txid': txid});
	});
};
module.exports = TxController;
<|endoftext|>