<commit_before>"use strict";

var utils = require("../utils");
var log = require("npmlog");

var msgsRecv = 0;

module.exports = function(defaultFuncs, api, ctx) {
  var shouldStop = false;
  var currentlyRunning = null;
  var stopListening = function() {
    shouldStop = true;
    if(currentlyRunning) {
      clearTimeout(currentlyRunning);
    }
  };

  var prev = Date.now();
  var tmpPrev = Date.now();
  var lastSync = Date.now();

  var form = {
    'channel' : 'p_' + ctx.userID,
    'seq' : '0',
    'partition' : '-2',
    'clientid' : ctx.clientID,
    'viewer_uid' : ctx.userID,
    'uid' : ctx.userID,
    'state' : 'active',
    'idle' : 0,
    'cap' : '8',
    'msgs_recv':msgsRecv
  };

  var globalCallback = null;

  /**
   * Get an object maybe representing an event. Handles events it wants to handle
   * and returns true if it did handle an event (and called the globalCallback).
   * Returns false otherwise.
   */
  function handleMessagingEvents(event) {
    switch (event.event) {
      case 'read_receipt':
        globalCallback(null, utils.formatReadReceipt(event));
        return true;
      default:
        return false;
    }
  }

  function listen() {
    if(shouldStop || !ctx.loggedIn) {
      return;
    }

    form.idle = ~~(Date.now() / 1000) - prev;
    prev = ~~(Date.now() / 1000);
    var presence = utils.generatePresence(ctx.userID);
    ctx.jar.setCookie("presence=" + presence + "; path=/; domain=.facebook.com; secure", "https://www.facebook.com");
    utils.get("https://0-edge-chat.facebook.com/pull", ctx.jar, form)
    .then(utils.parseAndCheckLogin(ctx.jar, defaultFuncs))
    .then(function(resData) {
      var now = Date.now();
      log.info("Got answer in ", now - tmpPrev);
      tmpPrev = now;

      if(resData && resData.t === "lb") {
        form.sticky_token = resData.lb_info.sticky;
        form.sticky_pool = resData.lb_info.pool;
      }

      if(resData && resData.t === 'fullReload') {
        form.seq = resData.seq;
        delete form.sticky_pool;
        delete form.sticky_token;
        var form4 = {
          'lastSync' : ~~(lastSync/1000),
        };
        defaultFuncs.get("https://www.facebook.com/notifications/sync/", ctx.jar, form4)
        .then(utils.saveCookies(ctx.jar))
        .then(function() {
          lastSync = Date.now();
          var form = {
            'client' : 'mercury',
            'folders[0]': 'inbox',
            'last_action_timestamp' : ~~(Date.now() - 60)
          };
          defaultFuncs.post("https://www.facebook.com/ajax/mercury/thread_sync.php", ctx.jar, form)
          .then(function() {
            currentlyRunning = setTimeout(listen, 1000);
          });
        });
        return;
      }

      if(resData.ms) {
        msgsRecv += resData.ms.length;
        var atLeastOne = false;
        resData.ms.sort(function(a, b) {
          return a.timestamp - b.timestamp;
        }).forEach(function parsePackets(v) {
          switch (v.type) {
            // TODO: 'ttyp' was used before. It changed to 'typ'. We're keeping
            // both for now but we should remove 'ttyp' at some point.
            case 'ttyp':
            case 'typ':
              if(!ctx.globalOptions.listenEvents ||
                (!ctx.globalOptions.selfListen && v.from.toString() === ctx.userID)) {
                return;
              }

              return globalCallback(null, utils.formatTyp(v));
              break;
            case 'buddylist_overlay':
              // TODO: what happens when you're logged in as a page?
              if(!ctx.globalOptions.updatePresence) {
                return;
              }

              // There should be only one key inside overlay
              Object.keys(v.overlay).map(function(userID) {
                var formattedPresence = utils.formatPresence(v.overlay[userID], userID);
                if(!shouldStop && ctx.loggedIn) {
                  return globalCallback(null, formattedPresence);
                }
              });
              break;
            case 'mercury':
              if(ctx.globalOptions.pageID || !ctx.globalOptions.listenEvents){
               return;
              }

              v.actions.map(function(v2) {
                var formattedEvent = utils.formatEvent(v2);
                if(!ctx.globalOptions.selfListen && formattedEvent.author.toString() === ctx.userID) {
                  return;
                }

                if (!shouldStop && ctx.loggedIn) {
                  return globalCallback(null, formattedEvent);
                }
              });
              break;
            case 'messaging':
              if (ctx.globalOptions.listenEvents && handleMessagingEvents(v)) {
                // globalCallback got called if handleMessagingEvents returned true
                return;
              }

              if(ctx.globalOptions.pageID ||
                v.event !== "deliver" ||
                (!ctx.globalOptions.selfListen && v.message.sender_fbid.toString() === ctx.userID)) {
                return;
              }

              atLeastOne = true;
              var message = utils.formatMessage(v);

              // The participants array is caped at 5, we need to query more to
              // get them.
              if(message.participantIDs.length >= 5) {
                // Either the thread has a name, and we can "search" for it
                // or it doesn't, then we can simply use getThreadList to
                // retrieve the participants array.
                if (message.threadName.length > 0) {
                  api.searchForThread(message.threadName, function(err, res) {
                    if (err) {
                      return globalCallback(err);
                    }

                    var firstThread = res.filter(function(v) {
                      return v.threadID === message.threadID;
                    })[0];
                    if (!firstThread) {
                      return globalCallback({error: "Couldn't retrieve thread participants for thread with name " + message.threadName + " and ID " + message.threadID});
                    }

                    message.participantIDs = firstThread.participants;
                    api.getUserInfo(firstThread.participants, function(err, firstThread) {
                      if (err) {
                        throw err;
                      }

                      message.participantsInfo = Object.keys(firstThread).map(function(key) {
                        return firstThread[key];
                      });
                      // Rename this?
                      message.participantNames = message.participantsInfo.map(function(v) {
                        return v.name;
                      });
                      return globalCallback(null, message);
                    });
                  });
                } else {
                  // This assumes that you didn't receive > 20 messages at the
                  // same time, on different chats. Otherwise the thread won't
                  // be part of the first 20 and this first search will fail.
                  // TODO: Make more getThreadList until you've searched through
                  // all threads.
                  api.getThreadList(0, 20, function(err, res) {
                    if (err) {
                      return globalCallback(err);
                    }
                    var firstThread = res.filter(function(v) {
                      return v.threadID === message.threadID;
                    })[0];

                    if (!firstThread) {
                      return globalCallback({error: "Couldn't retrieve thread participants for thread with name " + message.threadName + " and ID " + message.threadID + "."});
                    }

                    message.participantIDs = firstThread.participants;

                    api.getUserInfo(firstThread.participants, function(err, firstThread) {
                      if (err) {
                        throw err;
                      }

                      message.participantsInfo = Object.keys(firstThread).map(function(key) {
                        return firstThread[key];
                      });
                      // Rename this?
                      message.participantNames = message.participantsInfo.map(function(v) {
                        return v.name;
                      });
                      return globalCallback(null, message);
                    });
                  });
                }
                return;
              }

              if (!shouldStop && ctx.loggedIn) {
                return globalCallback(null, message);
              }
              break;
            case 'pages_messaging':
              if(!ctx.globalOptions.pageID ||
                v.event !== "deliver" ||
                (!ctx.globalOptions.selfListen && (v.message.sender_fbid.toString() === ctx.userID ||
                                                   v.message.sender_fbid.toString() === ctx.globalOptions.pageID)) ||
                v.realtime_viewer_fbid.toString() !== ctx.globalOptions.pageID) {
                return;
              }

              atLeastOne = true;
              if (!shouldStop && ctx.loggedIn) {
                return globalCallback(null, utils.formatMessage(v));
              }
              break;
          }
        });

        if(atLeastOne) {
          // Send deliveryReceipt notification to the server
          var formDeliveryReceipt = {};

          resData.ms.filter(function(v) {
            return v.message && v.message.mid && v.message.sender_fbid.toString() !== ctx.userID;
          }).forEach(function(val, i) {
            formDeliveryReceipt["[" + i + "]"] = val.message.mid;
          });

          // If there's at least one, we do the post request
          if(formDeliveryReceipt["[0]"]) {
            defaultFuncs.post("https://www.facebook.com/ajax/mercury/delivery_receipts.php", ctx.jar, formDeliveryReceipt);
          }
        }
      }

      if(resData.seq) {
        form.seq = resData.seq;
      }
      if(resData.tr) {
        form.traceid = resData.tr;
      }
      currentlyRunning = setTimeout(listen, Math.random() * 200 + 50);

    })
    .catch(function(err) {
      log.error("ERROR in listen --> ", err);
      globalCallback(err);
      currentlyRunning = setTimeout(listen, Math.random() * 200 + 50);
    });
  }

  return function(callback) {
    globalCallback = callback;

    if (!currentlyRunning) {
      currentlyRunning = setTimeout(listen, Math.random() * 200 + 50, callback);
    }

    return stopListening;
  };
};
<commit_msg>Real fix for participants in message obj. Fix #141.<commit_after>"use strict";

var utils = require("../utils");
var log = require("npmlog");

var msgsRecv = 0;

module.exports = function(defaultFuncs, api, ctx) {
  var shouldStop = false;
  var currentlyRunning = null;
  var stopListening = function() {
    shouldStop = true;
    if(currentlyRunning) {
      clearTimeout(currentlyRunning);
    }
  };

  var prev = Date.now();
  var tmpPrev = Date.now();
  var lastSync = Date.now();

  var form = {
    'channel' : 'p_' + ctx.userID,
    'seq' : '0',
    'partition' : '-2',
    'clientid' : ctx.clientID,
    'viewer_uid' : ctx.userID,
    'uid' : ctx.userID,
    'state' : 'active',
    'idle' : 0,
    'cap' : '8',
    'msgs_recv':msgsRecv
  };

  var globalCallback = null;

  /**
   * Get an object maybe representing an event. Handles events it wants to handle
   * and returns true if it did handle an event (and called the globalCallback).
   * Returns false otherwise.
   */
  function handleMessagingEvents(event) {
    switch (event.event) {
      case 'read_receipt':
        globalCallback(null, utils.formatReadReceipt(event));
        return true;
      default:
        return false;
    }
  }

  function listen() {
    if(shouldStop || !ctx.loggedIn) {
      return;
    }

    form.idle = ~~(Date.now() / 1000) - prev;
    prev = ~~(Date.now() / 1000);
    var presence = utils.generatePresence(ctx.userID);
    ctx.jar.setCookie("presence=" + presence + "; path=/; domain=.facebook.com; secure", "https://www.facebook.com");
    utils.get("https://0-edge-chat.facebook.com/pull", ctx.jar, form)
    .then(utils.parseAndCheckLogin(ctx.jar, defaultFuncs))
    .then(function(resData) {
      var now = Date.now();
      log.info("Got answer in ", now - tmpPrev);
      tmpPrev = now;

      if(resData && resData.t === "lb") {
        form.sticky_token = resData.lb_info.sticky;
        form.sticky_pool = resData.lb_info.pool;
      }

      if(resData && resData.t === 'fullReload') {
        form.seq = resData.seq;
        delete form.sticky_pool;
        delete form.sticky_token;
        var form4 = {
          'lastSync' : ~~(lastSync/1000),
        };
        defaultFuncs.get("https://www.facebook.com/notifications/sync/", ctx.jar, form4)
        .then(utils.saveCookies(ctx.jar))
        .then(function() {
          lastSync = Date.now();
          var form = {
            'client' : 'mercury',
            'folders[0]': 'inbox',
            'last_action_timestamp' : ~~(Date.now() - 60)
          };
          defaultFuncs.post("https://www.facebook.com/ajax/mercury/thread_sync.php", ctx.jar, form)
          .then(function() {
            currentlyRunning = setTimeout(listen, 1000);
          });
        });
        return;
      }

      if(resData.ms) {
        msgsRecv += resData.ms.length;
        var atLeastOne = false;
        resData.ms.sort(function(a, b) {
          return a.timestamp - b.timestamp;
        }).forEach(function parsePackets(v) {
          switch (v.type) {
            // TODO: 'ttyp' was used before. It changed to 'typ'. We're keeping
            // both for now but we should remove 'ttyp' at some point.
            case 'ttyp':
            case 'typ':
              if(!ctx.globalOptions.listenEvents ||
                (!ctx.globalOptions.selfListen && v.from.toString() === ctx.userID)) {
                return;
              }

              return globalCallback(null, utils.formatTyp(v));
              break;
            case 'buddylist_overlay':
              // TODO: what happens when you're logged in as a page?
              if(!ctx.globalOptions.updatePresence) {
                return;
              }

              // There should be only one key inside overlay
              Object.keys(v.overlay).map(function(userID) {
                var formattedPresence = utils.formatPresence(v.overlay[userID], userID);
                if(!shouldStop && ctx.loggedIn) {
                  return globalCallback(null, formattedPresence);
                }
              });
              break;
            case 'mercury':
              if(ctx.globalOptions.pageID || !ctx.globalOptions.listenEvents){
               return;
              }

              v.actions.map(function(v2) {
                var formattedEvent = utils.formatEvent(v2);
                if(!ctx.globalOptions.selfListen && formattedEvent.author.toString() === ctx.userID) {
                  return;
                }

                if (!shouldStop && ctx.loggedIn) {
                  return globalCallback(null, formattedEvent);
                }
              });
              break;
            case 'messaging':
              if (ctx.globalOptions.listenEvents && handleMessagingEvents(v)) {
                // globalCallback got called if handleMessagingEvents returned true
                return;
              }

              if(ctx.globalOptions.pageID ||
                v.event !== "deliver" ||
                (!ctx.globalOptions.selfListen && v.message.sender_fbid.toString() === ctx.userID)) {
                return;
              }

              atLeastOne = true;
              var message = utils.formatMessage(v);

              // The participants array is caped at 5, we need to query more to
              // get them.
              if(message.participantIDs.length >= 5) {
                // Either the thread has a name, and we can "search" for it
                // or it doesn't, then we can simply make a get request to get
                // the message page focused on a specific thread and parse the
                // html returned
                if (message.threadName.length > 0) {
                  api.searchForThread(message.threadName, function(err, res) {
                    if (err) {
                      return globalCallback(err);
                    }

                    var firstThread = res.filter(function(v) {
                      return v.threadID === message.threadID;
                    })[0];
                    if (!firstThread) {
                      return globalCallback({error: "Couldn't retrieve thread participants for thread with name " + message.threadName + " and ID " + message.threadID});
                    }

                    message.participantIDs = firstThread.participants;
                    api.getUserInfo(firstThread.participants, function(err, firstThread) {
                      if (err) {
                        throw err;
                      }

                      message.participantsInfo = Object.keys(firstThread).map(function(key) {
                        return firstThread[key];
                      });
                      // Rename this?
                      message.participantNames = message.participantsInfo.map(function(v) {
                        return v.name;
                      });
                      return globalCallback(null, message);
                    });
                  });
                } else {
                  defaultFuncs.get("https://www.facebook.com/messages/search/conversation-" + message.threadID, ctx.jar)
                    .then(function(res) {
                      if (res.statusCode !== 200) {
                        throw {error: "listen: couldn't get participantNames."};
                      }
                      // FB will send the first 20 thread information directly
                      // merged inside the html. This is an attempt at retrieving
                      // that information in only 2 (guaranteed) queries.
                      // ---------- Very Hacky Part Starts -----------------
                      // Add "]" at the end for the 2nd utils.getFrom
                      // because this utils.getFrom will slurp the end token
                      var almostParticipants = utils.getFrom(res.body, "\"thread_fbid\":\"" + message.threadID + "\",\"other_user_fbid\"", "]") + "]";
                      var stringParticipants = utils.getFrom(almostParticipants, "[", "]");
                      var participantIDs = stringParticipants.split(",").map(function(v) {
                        return v.replace("fbid:", "").replace(/\"/g, "");
                      });
                      // ---------- Very Hacky Part Ends -----------------
                      message.participantIDs = participantIDs;
                      api.getUserInfo(participantIDs, function(err, firstThread) {
                        if (err) {
                          throw err;
                        }

                        message.participantsInfo = Object.keys(firstThread).map(function(key) {
                          return firstThread[key];
                        });
                        // Rename this?
                        message.participantNames = message.participantsInfo.map(function(v) {
                          return v.name;
                        });
                        return globalCallback(null, message);
                      });
                    });
                }
                return;
              }

              if (!shouldStop && ctx.loggedIn) {
                return globalCallback(null, message);
              }
              break;
            case 'pages_messaging':
              if(!ctx.globalOptions.pageID ||
                v.event !== "deliver" ||
                (!ctx.globalOptions.selfListen && (v.message.sender_fbid.toString() === ctx.userID ||
                                                   v.message.sender_fbid.toString() === ctx.globalOptions.pageID)) ||
                v.realtime_viewer_fbid.toString() !== ctx.globalOptions.pageID) {
                return;
              }

              atLeastOne = true;
              if (!shouldStop && ctx.loggedIn) {
                return globalCallback(null, utils.formatMessage(v));
              }
              break;
          }
        });

        if(atLeastOne) {
          // Send deliveryReceipt notification to the server
          var formDeliveryReceipt = {};

          resData.ms.filter(function(v) {
            return v.message && v.message.mid && v.message.sender_fbid.toString() !== ctx.userID;
          }).forEach(function(val, i) {
            formDeliveryReceipt["[" + i + "]"] = val.message.mid;
          });

          // If there's at least one, we do the post request
          if(formDeliveryReceipt["[0]"]) {
            defaultFuncs.post("https://www.facebook.com/ajax/mercury/delivery_receipts.php", ctx.jar, formDeliveryReceipt);
          }
        }
      }

      if(resData.seq) {
        form.seq = resData.seq;
      }
      if(resData.tr) {
        form.traceid = resData.tr;
      }
      currentlyRunning = setTimeout(listen, Math.random() * 200 + 50);

    })
    .catch(function(err) {
      log.error("ERROR in listen --> ", err);
      globalCallback(err);
      currentlyRunning = setTimeout(listen, Math.random() * 200 + 50);
    });
  }

  return function(callback) {
    globalCallback = callback;

    if (!currentlyRunning) {
      currentlyRunning = setTimeout(listen, Math.random() * 200 + 50, callback);
    }

    return stopListening;
  };
};
<|endoftext|>


<commit_before>'use strict';

function setFrame(sprite, key) {

}

function setAnimations(sprite, key) {
	sprite.loadTexture(key);
	var sheet = PATH_MAP.spritesheets[key];
	if (sheet && sheet.animations) {
		var aname;
		for (aname in sheet.animations) {
			var anim = sheet.animations[aname];
			sprite.animations.add(aname, anim.frames, anim.fps, anim.loop);
		}
	}
}

module.exports = {
	setFrame: setFrame,
	setAnimations: setAnimations
};
<commit_msg>Remove unused code<commit_after>'use strict';

function setAnimations(sprite, key) {
	sprite.loadTexture(key);
	var sheet = PATH_MAP.spritesheets[key];
	if (sheet && sheet.animations) {
		var aname;
		for (aname in sheet.animations) {
			var anim = sheet.animations[aname];
			sprite.animations.add(aname, anim.frames, anim.fps, anim.loop);
		}
	}
}

module.exports = {
	setAnimations: setAnimations
};
<|endoftext|>


<commit_before>Crafty.extend({
	/**@
	* #Crafty.assets
	* @category Assets
	* An object containing every asset used in the current Crafty game.
	* The key is the URL and the value is the `Audio` or `Image` object.
    *
	* If loading an asset, check that it is in this object first to avoid loading twice.
	* @example
	* ~~~
	* var isLoaded = !!Crafty.assets["images/sprite.png"];
	* ~~~
	*/
	assets: {},

	/**@
	* #Crafty.loader
	* @category Assets
	* @sign public void Crafty.load(Array assets, Function onLoad[, Function onProgress, Function onError])
	* @param assets - Array of assets to load (accepts sounds and images)
	* @param onLoad - Callback when the assets are loaded
	* @param onProgress - Callback when an asset is loaded. Contains information about assets loaded
	* @param onError - Callback when an asset fails to load
	* Preloader for all assets. Takes an array of URLs and
	* adds them to the `Crafty.assets` object.
	*
	* The `onProgress` function will be passed on object with information about
	* the progress including how many assets loaded, total of all the assets to
	* load and a percentage of the progress.
    *
	* `onError` will be passed with the asset that couldn't load.
	*
	* @example
	* ~~~
	* Crafty.load(["images/sprite.png", "sounds/jump.mp3"],
	*     function() {
	*         //when loaded
	*         Crafty.scene("main"); //go to main scene
	*     },
	*
	*     function(e) {
	*		  //progress
	*     },
	*
	*     function(e) {
	*	      //uh oh, error loading
	*     }
	* );
	* ~~~
	* @see Crafty.assets
	*/
	load: function (data, oncomplete, onprogress, onerror) {
		var i = 0, l = data.length, current, obj, total = l, j = 0, ext;
		for (; i < l; ++i) {
			current = data[i];
			ext = current.substr(current.lastIndexOf('.') + 1).toLowerCase();

			if (Crafty.support.audio && (ext === "mp3" || ext === "wav" || ext === "ogg" || ext === "mp4")) {
				obj = new Audio(current);
				//Chrome doesn't trigger onload on audio, see http://code.google.com/p/chromium/issues/detail?id=77794
				if (navigator.userAgent.indexOf('Chrome') != -1) j++;
			} else if (ext === "jpg" || ext === "jpeg" || ext === "gif" || ext === "png") {
				obj = new Image();
				obj.src = current;
			} else {
				total--;
				continue; //skip if not applicable
			}

			//add to global asset collection
			this.assets[current] = obj;

			obj.onload = function () {
				++j;

				//if progress callback, give information of assets loaded, total and percent
				if (onprogress) {
					onprogress.call(this, { loaded: j, total: total, percent: (j / total * 100) });
				}
				if (j === total) {
					if (oncomplete) oncomplete();
				}
			};

			//if there is an error, pass it in the callback (this will be the object that didn't load)
			obj.onerror = function () {
				if (onerror) {
					onerror.call(this, { loaded: j, total: total, percent: (j / total * 100) });
				} else {
					j++;
					if (j === total) {
						if (oncomplete) oncomplete();
					}
				}
			};
		}
	},
	/**@
	* #Crafty.modules
	* @category Assets
	* @sign public void Crafty.modules(Object moduleMap[, Function onLoad])
	* @param modules - Map of name:version pairs for modules to load
	* @param onLoad - Callback when the modules are loaded
	* Browse the selection of modules on crafty-modules.com
	* Downloads and executes the javascript in the specified modules.
	*
    *
	* @example
	* ~~~
	* Crafty.modules({ moveto: 'DEV' }, function () {
	*     //module is ready
	*     Crafty.e("MoveTo, 2D, DOM");
	* });
	* ~~~
	*/
	modules: function (moduleMap, oncomplete) {
		/*!
		  * $script.js Async loader & dependency manager
		  * https://github.com/ded/script.js
		  * (c) Dustin Diaz, Jacob Thornton 2011
		  * License: MIT
		  */
		var $script = (function () {
			var win = this, doc = document
			, head = doc.getElementsByTagName('head')[0]
			, validBase = /^https?:\/\//
			, old = win.$script, list = {}, ids = {}, delay = {}, scriptpath
			, scripts = {}, s = 'string', f = false
			, push = 'push', domContentLoaded = 'DOMContentLoaded', readyState = 'readyState'
			, addEventListener = 'addEventListener', onreadystatechange = 'onreadystatechange'

			function every(ar, fn, i) {
				for (i = 0, j = ar.length; i < j; ++i) if (!fn(ar[i])) return f
				return 1
			}
			function each(ar, fn) {
				every(ar, function (el) {
					return !fn(el)
				})
			}

			if (!doc[readyState] && doc[addEventListener]) {
				doc[addEventListener](domContentLoaded, function fn() {
					doc.removeEventListener(domContentLoaded, fn, f)
					doc[readyState] = 'complete'
				}, f)
				doc[readyState] = 'loading'
			}

			function $script(paths, idOrDone, optDone) {
				paths = paths[push] ? paths : [paths]
				var idOrDoneIsDone = idOrDone && idOrDone.call
				, done = idOrDoneIsDone ? idOrDone : optDone
				, id = idOrDoneIsDone ? paths.join('') : idOrDone
				, queue = paths.length
				function loopFn(item) {
					return item.call ? item() : list[item]
				}
				function callback() {
					if (!--queue) {
						list[id] = 1
						done && done()
						for (var dset in delay) {
							every(dset.split('|'), loopFn) && !each(delay[dset], loopFn) && (delay[dset] = [])
						}
					}
				}
				setTimeout(function () {
					each(paths, function (path) {
						if (scripts[path]) {
							id && (ids[id] = 1)
							return scripts[path] == 2 && callback()
						}
						scripts[path] = 1
						id && (ids[id] = 1)
						create(!validBase.test(path) && scriptpath ? scriptpath + path + '.js' : path, callback)
					})
				}, 0)
				return $script
			}

			function create(path, fn) {
				var el = doc.createElement('script')
				, loaded = f
				el.onload = el.onerror = el[onreadystatechange] = function () {
					if ((el[readyState] && !(/^c|loade/.test(el[readyState]))) || loaded) return;
					el.onload = el[onreadystatechange] = null
					loaded = 1
					scripts[path] = 2
					fn()
				}
				el.async = 1
				el.src = path
				head.insertBefore(el, head.firstChild)
			}

			$script.get = create

			$script.order = function (scripts, id, done) {
				(function callback(s) {
					s = scripts.shift()
					if (!scripts.length) $script(s, id, done)
					else $script(s, callback)
				}())
			}

			$script.path = function (p) {
				scriptpath = p
			}
			$script.ready = function (deps, ready, req) {
				deps = deps[push] ? deps : [deps]
				var missing = [];
				!each(deps, function (dep) {
					list[dep] || missing[push](dep);
				}) && every(deps, function (dep) { return list[dep] }) ?
				ready() : !function (key) {
					delay[key] = delay[key] || []
					delay[key][push](ready)
					req && req(missing)
				}(deps.join('|'))
				return $script
			}

			$script.noConflict = function () {
				win.$script = old;
				return this
			}

			return $script
		})();

		var modules = [];
		for (var i in moduleMap) {
			if (i.indexOf("http://") != -1)
				modules.push(i)
			else
				modules.push('http://cdn.crafty-modules.com/' + i.toLowerCase() + '-' + moduleMap[i] + '.js');
		}
		$script(modules, function () {
			if (oncomplete) oncomplete();
		});
	}
});<commit_msg>support form other repositories in loader<commit_after>Crafty.extend({
	/**@
	* #Crafty.assets
	* @category Assets
	* An object containing every asset used in the current Crafty game.
	* The key is the URL and the value is the `Audio` or `Image` object.
    *
	* If loading an asset, check that it is in this object first to avoid loading twice.
	* @example
	* ~~~
	* var isLoaded = !!Crafty.assets["images/sprite.png"];
	* ~~~
	*/
	assets: {},

	/**@
	* #Crafty.loader
	* @category Assets
	* @sign public void Crafty.load(Array assets, Function onLoad[, Function onProgress, Function onError])
	* @param assets - Array of assets to load (accepts sounds and images)
	* @param onLoad - Callback when the assets are loaded
	* @param onProgress - Callback when an asset is loaded. Contains information about assets loaded
	* @param onError - Callback when an asset fails to load
	* Preloader for all assets. Takes an array of URLs and
	* adds them to the `Crafty.assets` object.
	*
	* The `onProgress` function will be passed on object with information about
	* the progress including how many assets loaded, total of all the assets to
	* load and a percentage of the progress.
    *
	* `onError` will be passed with the asset that couldn't load.
	*
	* @example
	* ~~~
	* Crafty.load(["images/sprite.png", "sounds/jump.mp3"],
	*     function() {
	*         //when loaded
	*         Crafty.scene("main"); //go to main scene
	*     },
	*
	*     function(e) {
	*		  //progress
	*     },
	*
	*     function(e) {
	*	      //uh oh, error loading
	*     }
	* );
	* ~~~
	* @see Crafty.assets
	*/
	load: function (data, oncomplete, onprogress, onerror) {
		var i = 0, l = data.length, current, obj, total = l, j = 0, ext;
		for (; i < l; ++i) {
			current = data[i];
			ext = current.substr(current.lastIndexOf('.') + 1).toLowerCase();

			if (Crafty.support.audio && (ext === "mp3" || ext === "wav" || ext === "ogg" || ext === "mp4")) {
				obj = new Audio(current);
				//Chrome doesn't trigger onload on audio, see http://code.google.com/p/chromium/issues/detail?id=77794
				if (navigator.userAgent.indexOf('Chrome') != -1) j++;
			} else if (ext === "jpg" || ext === "jpeg" || ext === "gif" || ext === "png") {
				obj = new Image();
				obj.src = current;
			} else {
				total--;
				continue; //skip if not applicable
			}

			//add to global asset collection
			this.assets[current] = obj;

			obj.onload = function () {
				++j;

				//if progress callback, give information of assets loaded, total and percent
				if (onprogress) {
					onprogress.call(this, { loaded: j, total: total, percent: (j / total * 100) });
				}
				if (j === total) {
					if (oncomplete) oncomplete();
				}
			};

			//if there is an error, pass it in the callback (this will be the object that didn't load)
			obj.onerror = function () {
				if (onerror) {
					onerror.call(this, { loaded: j, total: total, percent: (j / total * 100) });
				} else {
					j++;
					if (j === total) {
						if (oncomplete) oncomplete();
					}
				}
			};
		}
	},
	/**@
	* #Crafty.modules
	* @category Assets
	* @sign public void Crafty.modules(Object moduleMap[, Function onLoad])
	* @param modules - Map of name:version pairs for modules to load
	* @param onLoad - Callback when the modules are loaded
	* Browse the selection of modules on crafty repositories.
	* Downloads and executes the javascript in the specified modules.
	*
	* Available repositories:
	* 	- http://cdn.crafty-modules.com
	* 	- http://craftycomponents.com
    *
	* @example
	* ~~~
	* Crafty.modules('http://example.com', { moveto: 'DEV' }, function () {
	*     //module is ready
	*     Crafty.e("MoveTo, 2D, DOM");
	* });
	* ~~~
	*
	*/
	modules: function (modulesRepository, moduleMap, oncomplete) {
		/*!
		  * $script.js Async loader & dependency manager
		  * https://github.com/ded/script.js
		  * (c) Dustin Diaz, Jacob Thornton 2011
		  * License: MIT
		  */
		var $script = (function () {
			var win = this, doc = document
			, head = doc.getElementsByTagName('head')[0]
			, validBase = /^https?:\/\//
			, old = win.$script, list = {}, ids = {}, delay = {}, scriptpath
			, scripts = {}, s = 'string', f = false
			, push = 'push', domContentLoaded = 'DOMContentLoaded', readyState = 'readyState'
			, addEventListener = 'addEventListener', onreadystatechange = 'onreadystatechange'

			function every(ar, fn, i) {
				for (i = 0, j = ar.length; i < j; ++i) if (!fn(ar[i])) return f
				return 1
			}
			function each(ar, fn) {
				every(ar, function (el) {
					return !fn(el)
				})
			}

			if (!doc[readyState] && doc[addEventListener]) {
				doc[addEventListener](domContentLoaded, function fn() {
					doc.removeEventListener(domContentLoaded, fn, f)
					doc[readyState] = 'complete'
				}, f)
				doc[readyState] = 'loading'
			}

			function $script(paths, idOrDone, optDone) {
				paths = paths[push] ? paths : [paths]
				var idOrDoneIsDone = idOrDone && idOrDone.call
				, done = idOrDoneIsDone ? idOrDone : optDone
				, id = idOrDoneIsDone ? paths.join('') : idOrDone
				, queue = paths.length
				function loopFn(item) {
					return item.call ? item() : list[item]
				}
				function callback() {
					if (!--queue) {
						list[id] = 1
						done && done()
						for (var dset in delay) {
							every(dset.split('|'), loopFn) && !each(delay[dset], loopFn) && (delay[dset] = [])
						}
					}
				}
				setTimeout(function () {
					each(paths, function (path) {
						if (scripts[path]) {
							id && (ids[id] = 1)
							return scripts[path] == 2 && callback()
						}
						scripts[path] = 1
						id && (ids[id] = 1)
						create(!validBase.test(path) && scriptpath ? scriptpath + path + '.js' : path, callback)
					})
				}, 0)
				return $script
			}

			function create(path, fn) {
				var el = doc.createElement('script')
				, loaded = f
				el.onload = el.onerror = el[onreadystatechange] = function () {
					if ((el[readyState] && !(/^c|loade/.test(el[readyState]))) || loaded) return;
					el.onload = el[onreadystatechange] = null
					loaded = 1
					scripts[path] = 2
					fn()
				}
				el.async = 1
				el.src = path
				head.insertBefore(el, head.firstChild)
			}

			$script.get = create

			$script.order = function (scripts, id, done) {
				(function callback(s) {
					s = scripts.shift()
					if (!scripts.length) $script(s, id, done)
					else $script(s, callback)
				}())
			}

			$script.path = function (p) {
				scriptpath = p
			}
			$script.ready = function (deps, ready, req) {
				deps = deps[push] ? deps : [deps]
				var missing = [];
				!each(deps, function (dep) {
					list[dep] || missing[push](dep);
				}) && every(deps, function (dep) { return list[dep] }) ?
				ready() : !function (key) {
					delay[key] = delay[key] || []
					delay[key][push](ready)
					req && req(missing)
				}(deps.join('|'))
				return $script
			}

			$script.noConflict = function () {
				win.$script = old;
				return this
			}

			return $script
		})();

		var modules = [];
		for (var i in moduleMap) {
			if (i.indexOf("http://") != -1)
				modules.push(i)
			else
				modules.push(modulesRepository + '/' + i.toLowerCase() + '-' + moduleMap[i] + '.js');
		}

		$script(modules, function () {
			if (oncomplete) oncomplete();
		});
	}
});<|endoftext|>


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

const assert               = require('assert');

const defs                 = require('./defs.js');
const lobject              = require('./lobject.js');
const ldo                  = require('./ldo.js');
const lapi                 = require('./lapi.js');
const ltable               = require('./ltable.js');
const lfunc                = require('./lfunc.js');
const ltm                  = require('./ltm.js');
const CT                   = defs.constant_types;
const TS                   = defs.thread_status;
const LUA_NUMTAGS          = defs.LUA_NUMTAGS;

const BASIC_STACK_SIZE = 2 * defs.LUA_MINSTACK;

class CallInfo {

    constructor(funcOff, func, top, base, previous, next) {
        this.func = func;
        this.funcOff = funcOff;
        this.top = top;
        this.previous = previous;
        this.next = next;
        this.pcOff = 0;

        /* only for Lua functions */
        this.l_base = base; /* base for this function */
        this.l_savedpc = [];
        /* only for JS functions */
        this.c_k = null;  /* continuation in case of yields */
        this.c_old_errfunc = null;
        this.c_ctx = null;  /* context info. in case of yields */

        this.nresults = 0;
        this.callstatus = 0;
    }

}

class lua_State {

    constructor() {
        this.id = null;
        this.base_ci = new CallInfo(); // Will be populated later
        this.top = 0;
        this.ci = null;
        this.ciOff = null;
        this.stack = [];
        this.openupval = null;
        this.status = TS.LUA_OK;
        this.next = null;
        this.errorJmp = null;
        this.nny = 1;
        this.errfunc = 0;
    }

}

class global_State {

    constructor(L) {
        this.id_counter = 0; /* used to give objects unique ids */

        this.mainthread = L;
        this.l_registry = new lobject.TValue(CT.LUA_TNIL, null);
        this.panic = null;
        this.version = null;
        this.tmname = new Array(ltm.TMS.TM_N);
        this.mt = new Array(LUA_NUMTAGS);
    }

}

const luaE_extendCI = function(L) {
    let ci = new CallInfo();
    L.ci.next = ci;
    ci.previous = L.ci;
    ci.next = null;
    L.ci = ci;
    L.ciOff++;
    return ci;
};

const luaE_freeCI = function(L) {
    let ci = L.ci;
    ci.next = null;
};

const stack_init = function(L1, L) {
    L1.stack = new Array(BASIC_STACK_SIZE); // TODO: for now we don't care about the stack size
    L1.top = 0;
    let ci = L1.base_ci;
    ci.next = ci.previous = null;
    ci.callstatus = 0;
    ci.func = L1.stack[L1.top];
    ci.funcOff = L1.top;
    L1.stack[L1.top++] = new lobject.TValue(CT.LUA_TNIL, null);
    ci.top = L1.top + defs.LUA_MINSTACK;
    L1.ci = ci;
};

const freestack = function(L) {
    L.ci = L.base_ci;
    luaE_freeCI(L);
    L.stack = null;
};

/*
** Create registry table and its predefined values
*/
const init_registry = function(L, g) {
    let registry = ltable.luaH_new(L);
    g.l_registry.sethvalue(registry);
    ltable.luaH_setint(registry, defs.LUA_RIDX_MAINTHREAD, new lobject.TValue(CT.LUA_TTHREAD, L));
    ltable.luaH_setint(registry, defs.LUA_RIDX_GLOBALS, new lobject.TValue(CT.LUA_TTABLE, ltable.luaH_new(L)));
};

/*
** open parts of the state that may cause memory-allocation errors.
** ('g->version' !== NULL flags that the state was completely build)
*/
const f_luaopen = function(L) {
    let g = L.l_G;
    stack_init(L, L);
    init_registry(L, g);
    ltm.luaT_init(L);
    g.version = lapi.lua_version(null);
};

const preinit_thread = function(L, g) {
    L.id = g.id_counter++;
    L.l_G = g;
    L.stack = null;
    L.ci = null;
    L.nci = 0;
    L.errorJmp = null;
    L.nCcalls = 0;
    L.hook = null;
    L.hookmask = 0;
    L.basehookcount = 0;
    L.allowhook = 1;
    L.hookcount = L.basehookcount;
    L.openupval = null;
    L.nny = 1;
    L.status = TS.LUA_OK;
    L.errfunc = 0;
};

const lua_newthread = function(L) {
    let g = L.l_G;
    let L1 = new lua_State();
    L.stack[L.top++] = new lobject.TValue(CT.LUA_TTHREAD, L1);
    assert(L.top <= L.ci.top, "stack overflow");
    preinit_thread(L1, g);
    L1.hookmask = L.hookmask;
    L1.basehookcount = L.basehookcount;
    L1.hook = L.hook;
    L1.hookcount = L1.basehookcount;
    stack_init(L1, L);
    return L1;
};

const luaE_freethread = function(L, L1) {
    lfunc.luaF_close(L1, L1.stack);
    freestack(L1);
};

const lua_newstate = function() {
    let L = new lua_State();
    let g = new global_State(L);

    preinit_thread(L, g);

    if (ldo.luaD_rawrunprotected(L, f_luaopen, null) !== TS.LUA_OK) {
        L = null;
    }

    return L;
};

const close_state = function(L) {
    lfunc.luaF_close(L, L.stack);  /* close all upvalues for this thread */
    freestack(L);
};

const lua_close = function(L) {
    L = L.l_G.mainthread;  /* only the main thread can be closed */
    close_state(L);
};

module.exports.lua_State       = lua_State;
module.exports.CallInfo        = CallInfo;
module.exports.CIST_OAH        = (1<<0);  /* original value of 'allowhook' */
module.exports.CIST_LUA        = (1<<1);  /* call is running a Lua function */
module.exports.CIST_HOOKED     = (1<<2);  /* call is running a debug hook */
module.exports.CIST_FRESH      = (1<<3);  /* call is running on a fresh invocation of luaV_execute */
module.exports.CIST_YPCALL     = (1<<4);  /* call is a yieldable protected call */
module.exports.CIST_TAIL       = (1<<5);  /* call was tail called */
module.exports.CIST_HOOKYIELD  = (1<<6);  /* last hook called yielded */
module.exports.CIST_LEQ        = (1<<7);  /* using __lt for __le */
module.exports.CIST_FIN        = (1<<8);   /* call is running a finalizer */
module.exports.lua_close       = lua_close;
module.exports.lua_newstate    = lua_newstate;
module.exports.lua_newthread   = lua_newthread;
module.exports.luaE_extendCI   = luaE_extendCI;
module.exports.luaE_freeCI     = luaE_freeCI;
module.exports.luaE_freethread = luaE_freethread;
<commit_msg>src/lstate.js: Remove (unused) CallInfo constructor arguments<commit_after>/*jshint esversion: 6 */
"use strict";

const assert               = require('assert');

const defs                 = require('./defs.js');
const lobject              = require('./lobject.js');
const ldo                  = require('./ldo.js');
const lapi                 = require('./lapi.js');
const ltable               = require('./ltable.js');
const lfunc                = require('./lfunc.js');
const ltm                  = require('./ltm.js');
const CT                   = defs.constant_types;
const TS                   = defs.thread_status;
const LUA_NUMTAGS          = defs.LUA_NUMTAGS;

const BASIC_STACK_SIZE = 2 * defs.LUA_MINSTACK;

class CallInfo {

    constructor() {
        this.func = null;
        this.funcOff = NaN;
        this.top = NaN;
        this.previous = null;
        this.next = null;

        /* only for Lua functions */
        this.l_base = NaN; /* base for this function */
        this.l_savedpc = null;
        this.pcOff = NaN; /* offset into l_savedpc */
        /* only for JS functions */
        this.c_k = null;  /* continuation in case of yields */
        this.c_old_errfunc = null;
        this.c_ctx = null;  /* context info. in case of yields */

        this.nresults = NaN;
        this.callstatus = NaN;
    }

}

class lua_State {

    constructor() {
        this.id = null;
        this.base_ci = new CallInfo(); // Will be populated later
        this.top = 0;
        this.ci = null;
        this.ciOff = null;
        this.stack = [];
        this.openupval = null;
        this.status = TS.LUA_OK;
        this.next = null;
        this.errorJmp = null;
        this.nny = 1;
        this.errfunc = 0;
    }

}

class global_State {

    constructor(L) {
        this.id_counter = 0; /* used to give objects unique ids */

        this.mainthread = L;
        this.l_registry = new lobject.TValue(CT.LUA_TNIL, null);
        this.panic = null;
        this.version = null;
        this.tmname = new Array(ltm.TMS.TM_N);
        this.mt = new Array(LUA_NUMTAGS);
    }

}

const luaE_extendCI = function(L) {
    let ci = new CallInfo();
    L.ci.next = ci;
    ci.previous = L.ci;
    ci.next = null;
    L.ci = ci;
    L.ciOff++;
    return ci;
};

const luaE_freeCI = function(L) {
    let ci = L.ci;
    ci.next = null;
};

const stack_init = function(L1, L) {
    L1.stack = new Array(BASIC_STACK_SIZE); // TODO: for now we don't care about the stack size
    L1.top = 0;
    let ci = L1.base_ci;
    ci.next = ci.previous = null;
    ci.callstatus = 0;
    ci.func = L1.stack[L1.top];
    ci.funcOff = L1.top;
    L1.stack[L1.top++] = new lobject.TValue(CT.LUA_TNIL, null);
    ci.top = L1.top + defs.LUA_MINSTACK;
    L1.ci = ci;
};

const freestack = function(L) {
    L.ci = L.base_ci;
    luaE_freeCI(L);
    L.stack = null;
};

/*
** Create registry table and its predefined values
*/
const init_registry = function(L, g) {
    let registry = ltable.luaH_new(L);
    g.l_registry.sethvalue(registry);
    ltable.luaH_setint(registry, defs.LUA_RIDX_MAINTHREAD, new lobject.TValue(CT.LUA_TTHREAD, L));
    ltable.luaH_setint(registry, defs.LUA_RIDX_GLOBALS, new lobject.TValue(CT.LUA_TTABLE, ltable.luaH_new(L)));
};

/*
** open parts of the state that may cause memory-allocation errors.
** ('g->version' !== NULL flags that the state was completely build)
*/
const f_luaopen = function(L) {
    let g = L.l_G;
    stack_init(L, L);
    init_registry(L, g);
    ltm.luaT_init(L);
    g.version = lapi.lua_version(null);
};

const preinit_thread = function(L, g) {
    L.id = g.id_counter++;
    L.l_G = g;
    L.stack = null;
    L.ci = null;
    L.nci = 0;
    L.errorJmp = null;
    L.nCcalls = 0;
    L.hook = null;
    L.hookmask = 0;
    L.basehookcount = 0;
    L.allowhook = 1;
    L.hookcount = L.basehookcount;
    L.openupval = null;
    L.nny = 1;
    L.status = TS.LUA_OK;
    L.errfunc = 0;
};

const lua_newthread = function(L) {
    let g = L.l_G;
    let L1 = new lua_State();
    L.stack[L.top++] = new lobject.TValue(CT.LUA_TTHREAD, L1);
    assert(L.top <= L.ci.top, "stack overflow");
    preinit_thread(L1, g);
    L1.hookmask = L.hookmask;
    L1.basehookcount = L.basehookcount;
    L1.hook = L.hook;
    L1.hookcount = L1.basehookcount;
    stack_init(L1, L);
    return L1;
};

const luaE_freethread = function(L, L1) {
    lfunc.luaF_close(L1, L1.stack);
    freestack(L1);
};

const lua_newstate = function() {
    let L = new lua_State();
    let g = new global_State(L);

    preinit_thread(L, g);

    if (ldo.luaD_rawrunprotected(L, f_luaopen, null) !== TS.LUA_OK) {
        L = null;
    }

    return L;
};

const close_state = function(L) {
    lfunc.luaF_close(L, L.stack);  /* close all upvalues for this thread */
    freestack(L);
};

const lua_close = function(L) {
    L = L.l_G.mainthread;  /* only the main thread can be closed */
    close_state(L);
};

module.exports.lua_State       = lua_State;
module.exports.CallInfo        = CallInfo;
module.exports.CIST_OAH        = (1<<0);  /* original value of 'allowhook' */
module.exports.CIST_LUA        = (1<<1);  /* call is running a Lua function */
module.exports.CIST_HOOKED     = (1<<2);  /* call is running a debug hook */
module.exports.CIST_FRESH      = (1<<3);  /* call is running on a fresh invocation of luaV_execute */
module.exports.CIST_YPCALL     = (1<<4);  /* call is a yieldable protected call */
module.exports.CIST_TAIL       = (1<<5);  /* call was tail called */
module.exports.CIST_HOOKYIELD  = (1<<6);  /* last hook called yielded */
module.exports.CIST_LEQ        = (1<<7);  /* using __lt for __le */
module.exports.CIST_FIN        = (1<<8);   /* call is running a finalizer */
module.exports.lua_close       = lua_close;
module.exports.lua_newstate    = lua_newstate;
module.exports.lua_newthread   = lua_newthread;
module.exports.luaE_extendCI   = luaE_extendCI;
module.exports.luaE_freeCI     = luaE_freeCI;
module.exports.luaE_freethread = luaE_freethread;
<|endoftext|>


<commit_before>import assign from 'object-assign';
import {broadcast} from './event-bus';
import {promisedTimeout} from './utils';
import {passthrough, createPipeline} from './pipelines';
import {vdomToDocument, createEmptyDocument} from './render/document';

let hasModal = false;

const RENDERING_ANIMATION = 500;

export function render(template) {
	return createPipeline()
		.pipe(parseDocument(template))
		.pipe(passthrough(payload => {
			const {
				route,
				redirect,
				navigation = {},
				parsedDocument: document,
			} = payload;

			let {document: renderedDocument} = payload;

			const {menuBar, menuItem} = navigation;
			const prevRouteDocument = renderedDocument ? renderedDocument.prevRouteDocument : navigationDocument.documents.slice(-1)[0];

			document.route = route;
			document.prevRouteDocument = prevRouteDocument;

			if (prevRouteDocument === renderedDocument) {
				document.prevRouteDocument = null;
			}

			if (hasModal) removeModal();

			if (redirect && prevRouteDocument) {
				renderedDocument = prevRouteDocument;
			}

			if (menuBar && menuItem) {
				const menuItemDocument = menuBar.getDocument(menuItem);

				if (menuItemDocument !== document) {
					setTimeout(() => menuBar.setDocument(document, menuItem), RENDERING_ANIMATION);
				}
			} else if (renderedDocument) {
				navigationDocument.replaceDocument(document, renderedDocument);
			} else {
				navigationDocument.pushDocument(document);
			}

			return {document, redirect: false};
		}))
		.pipe(passthrough(() => promisedTimeout(RENDERING_ANIMATION)));
}

export function renderModal(template) {
	return createPipeline()
		.pipe(passthrough(() => {
			if (!hasModal) return;
			removeModal();
			return promisedTimeout(RENDERING_ANIMATION);
		}))
		.pipe(parseDocument(template))
		.pipe(passthrough(({parsedDocument: document, route}) => {
			hasModal = true;
			document.modal = true;
			document.route = route || (navigationDocument.documents.pop() || {}).route;
			navigationDocument.presentModal(document);
		}));
}

export function parseDocument(template) {
	return createPipeline().pipe(passthrough(payload => ({
		parsedDocument: createDocument(template, payload),
	})));
}

export function removeModal() {
	hasModal = false;
	navigationDocument.dismissModal(true);
}

function createDocument(template, payload) {
	if (typeof(template) === 'string') {
		throw `String templates aren't supported. Use jsx templates.`
	}

	if (typeof(template) === 'function') {
		template = template(payload);
	}

	if (typeof(template) === 'object' && template) {
		return vdomToDocument(template, payload);
	}

	return createEmptyDocument();
}
<commit_msg>Updated animation speed value for tvos 11<commit_after>import assign from 'object-assign';
import {broadcast} from './event-bus';
import {promisedTimeout} from './utils';
import {passthrough, createPipeline} from './pipelines';
import {vdomToDocument, createEmptyDocument} from './render/document';

let hasModal = false;

const RENDERING_ANIMATION = 600;

export function render(template) {
	return createPipeline()
		.pipe(parseDocument(template))
		.pipe(passthrough(payload => {
			const {
				route,
				redirect,
				navigation = {},
				parsedDocument: document,
			} = payload;

			let {document: renderedDocument} = payload;

			const {menuBar, menuItem} = navigation;
			const prevRouteDocument = renderedDocument ? renderedDocument.prevRouteDocument : navigationDocument.documents.slice(-1)[0];

			document.route = route;
			document.prevRouteDocument = prevRouteDocument;

			if (prevRouteDocument === renderedDocument) {
				document.prevRouteDocument = null;
			}

			if (hasModal) removeModal();

			if (redirect && prevRouteDocument) {
				renderedDocument = prevRouteDocument;
			}

			if (menuBar && menuItem) {
				const menuItemDocument = menuBar.getDocument(menuItem);

				if (menuItemDocument !== document) {
					setTimeout(() => menuBar.setDocument(document, menuItem), RENDERING_ANIMATION);
				}
			} else if (renderedDocument) {
				navigationDocument.replaceDocument(document, renderedDocument);
			} else {
				navigationDocument.pushDocument(document);
			}

			return {document, redirect: false};
		}))
		.pipe(passthrough(() => promisedTimeout(RENDERING_ANIMATION)));
}

export function renderModal(template) {
	return createPipeline()
		.pipe(passthrough(() => {
			if (!hasModal) return;
			removeModal();
			return promisedTimeout(RENDERING_ANIMATION);
		}))
		.pipe(parseDocument(template))
		.pipe(passthrough(({parsedDocument: document, route}) => {
			hasModal = true;
			document.modal = true;
			document.route = route || (navigationDocument.documents.pop() || {}).route;
			navigationDocument.presentModal(document);
		}));
}

export function parseDocument(template) {
	return createPipeline().pipe(passthrough(payload => ({
		parsedDocument: createDocument(template, payload),
	})));
}

export function removeModal() {
	hasModal = false;
	navigationDocument.dismissModal(true);
}

function createDocument(template, payload) {
	if (typeof(template) === 'string') {
		throw `String templates aren't supported. Use jsx templates.`
	}

	if (typeof(template) === 'function') {
		template = template(payload);
	}

	if (typeof(template) === 'object' && template) {
		return vdomToDocument(template, payload);
	}

	return createEmptyDocument();
}
<|endoftext|>


<commit_before>var coffeeify = require('coffeeify');
var derby = require('derby');
var express = require('express');
var redis = require('redis');
var session = require('express-session');
var RedisStore = require('connect-redis')(session);
var highway = require('racer-highway');
var liveDbMongo = require('livedb-mongo');
var parseUrl = require('url').parse;
var passport = require("d-passport");
derby.use(require('racer-bundle'));

exports.setup = setup;

function setup(app, options, cb) {
  var redisClient;
  if (process.env.REDIS_HOST) {
    redisClient = redis.createClient(process.env.REDIS_PORT, process.env.REDIS_HOST);
    redisClient.auth(process.env.REDIS_PASSWORD);
  } else if (process.env.OPENREDIS_URL) {
    var redisUrl = parseUrl(process.env.OPENREDIS_URL);
    redisClient = redis.createClient(redisUrl.port, redisUrl.hostname);
    redisClient.auth(redisUrl.auth.split(":")[1]);
  } else {
    redisClient = redis.createClient();
  }
  // redisClient.select(1);

  var mongoUrl = process.env.MONGO_URL || process.env.MONGOHQ_URL;
  if(!mongoUrl) {
    mongoUrl = "mongodb://" + (process.env.MONGO_HOST || "localhost") + ":" + (process.env.MONGO_PORT || 27017) + "/" + (process.env.MONGO_DB || "derby-app");
  }
  // The store creates models and syncs data
  var store = derby.createStore({
    db: liveDbMongo(mongoUrl + '?auto_reconnect', {safe: true})
  , redis: redisClient
  });

  var options = {
      "site": {
          "domain": "https://d-passport.herokuapp.com",
          "name": "d-passport-example",
          "email": "admin@d-passport.herokuapp.com"
      },
      "smtp": {
          "host": "smtp.mailgun.org",
          "port": "587",
          "user": "postmaster@app31228337.mailgun.org",
          "pass": "03b3c777fe8a8de5b34e6458be476aa8"
      }
  }

  passport.configure(options)
  passport.store(store)

  store.on('bundle', function(browserify) {
    // Add support for directly requiring coffeescript in browserify bundles
    browserify.transform({global: true}, coffeeify);

    // HACK: In order to use non-complied coffee node modules, we register it
    // as a global transform. However, the coffeeify transform needs to happen
    // before the include-globals transform that browserify hard adds as the
    // first trasform. This moves the first transform to the end as a total
    // hack to get around this
    var pack = browserify.pack;
    browserify.pack = function(opts) {
      var detectTransform = opts.globalTransform.shift();
      opts.globalTransform.push(detectTransform);
      return pack.apply(this, arguments);
    };
  });

  var publicDir = __dirname + '/../public';

  var handlers = highway(store);

  var expressApp = express()
    .use(express.favicon())
    // Gzip dynamically rendered content
    .use(express.compress())
    .use(express.static(publicDir))

  expressApp
    // Adds req.getModel method
    .use(store.modelMiddleware())
    .use(express.cookieParser())
    .use(express.session({
      secret: process.env.SESSION_SECRET || 'YOUR SECRET HERE'
    , store: new RedisStore({
        host: process.env.REDIS_HOST || "localhost",
        port: process.env.REDIS_PORT || 6379,
        pass: process.env.REDIS_PASSWORD || null
      })
    }))
    .use(express.bodyParser())
    .use(passport.middleware(expressApp))
    .use(handlers.middleware)
    .use(createUserId)

  if (options && options.static) {
    if(Array.isArray(options.static)) {
      for(var i = 0; i < options.static.length; i++) {
        var o = options.static[i];
        expressApp.use(o.route, express.static(o.dir));
      }
    } else {
      expressApp.use(express.static(options.static));
    }
  }

  expressApp
    // Creates an express middleware from the app's routes
    .use(app.router())
    .use(expressApp.router)
    .use(errorMiddleware)

  expressApp.all('*', function(req, res, next) {
    next('404: ' + req.url);
  });

  app.writeScripts(store, publicDir, {extensions: ['.coffee']}, function(err) {
    cb(err, expressApp, handlers.upgrade);
  });
}

function createUserId(req, res, next) {
  var model = req.getModel();
  if (req.session) {
    var userId = req.session.userId;
    if (!userId) userId = req.session.userId = model.id();
    model.set('_session.userId', userId);
  }
  next();
}

var errorApp = derby.createApp();
errorApp.loadViews(__dirname + '/../views/error');
errorApp.loadStyles(__dirname + '/../styles/error');

function errorMiddleware(err, req, res, next) {
  if (!err) return next();

  var message = err.message || err.toString();
  var status = parseInt(message);
  status = ((status >= 400) && (status < 600)) ? status : 500;

  if (status < 500) {
    console.log(err.message || err);
  } else {
    console.log(err.stack || err);
  }

  var page = errorApp.createPage(req, res, next);
  page.renderStatic(status, status.toString());
}
<commit_msg>Update server.js<commit_after>var coffeeify = require('coffeeify');
var derby = require('derby');
var express = require('express');
var redis = require('redis');
var session = require('express-session');
var RedisStore = require('connect-redis')(session);
var highway = require('racer-highway');
var liveDbMongo = require('livedb-mongo');
var parseUrl = require('url').parse;
var passport = require("d-passport");
derby.use(require('racer-bundle'));

exports.setup = setup;

function setup(app, options, cb) {
  var redisClient;
  if (process.env.REDIS_HOST) {
    redisClient = redis.createClient(process.env.REDIS_PORT, process.env.REDIS_HOST);
    redisClient.auth(process.env.REDIS_PASSWORD);
  } else if (process.env.OPENREDIS_URL) {
    var redisUrl = parseUrl(process.env.OPENREDIS_URL);
    redisClient = redis.createClient(redisUrl.port, redisUrl.hostname);
    redisClient.auth(redisUrl.auth.split(":")[1]);
  } else {
    redisClient = redis.createClient();
  }
  // redisClient.select(1);

  var mongoUrl = process.env.MONGO_URL || process.env.MONGOHQ_URL;
  if(!mongoUrl) {
    mongoUrl = "mongodb://" + (process.env.MONGO_HOST || "localhost") + ":" + (process.env.MONGO_PORT || 27017) + "/" + (process.env.MONGO_DB || "derby-app");
  }
  // The store creates models and syncs data
  var store = derby.createStore({
    db: liveDbMongo(mongoUrl + '?auto_reconnect', {safe: true})
  , redis: redisClient
  });

  var options = {
      "site": {
          "domain": "https://d-passport.herokuapp.com",
          "name": "d-passport-example",
          "email": "admin@d-passport.herokuapp.com"
      },
      "smtp": {
          "host": "smtp.mailgun.org",
          "port": "587",
          "user": "postmaster@app31228337.mailgun.org",
          "pass": "secret"
      }
  }

  passport.configure(options)
  passport.store(store)

  store.on('bundle', function(browserify) {
    // Add support for directly requiring coffeescript in browserify bundles
    browserify.transform({global: true}, coffeeify);

    // HACK: In order to use non-complied coffee node modules, we register it
    // as a global transform. However, the coffeeify transform needs to happen
    // before the include-globals transform that browserify hard adds as the
    // first trasform. This moves the first transform to the end as a total
    // hack to get around this
    var pack = browserify.pack;
    browserify.pack = function(opts) {
      var detectTransform = opts.globalTransform.shift();
      opts.globalTransform.push(detectTransform);
      return pack.apply(this, arguments);
    };
  });

  var publicDir = __dirname + '/../public';

  var handlers = highway(store);

  var expressApp = express()
    .use(express.favicon())
    // Gzip dynamically rendered content
    .use(express.compress())
    .use(express.static(publicDir))

  expressApp
    // Adds req.getModel method
    .use(store.modelMiddleware())
    .use(express.cookieParser())
    .use(express.session({
      secret: process.env.SESSION_SECRET || 'YOUR SECRET HERE'
    , store: new RedisStore({
        host: process.env.REDIS_HOST || "localhost",
        port: process.env.REDIS_PORT || 6379,
        pass: process.env.REDIS_PASSWORD || null
      })
    }))
    .use(express.bodyParser())
    .use(passport.middleware(expressApp))
    .use(handlers.middleware)
    .use(createUserId)

  if (options && options.static) {
    if(Array.isArray(options.static)) {
      for(var i = 0; i < options.static.length; i++) {
        var o = options.static[i];
        expressApp.use(o.route, express.static(o.dir));
      }
    } else {
      expressApp.use(express.static(options.static));
    }
  }

  expressApp
    // Creates an express middleware from the app's routes
    .use(app.router())
    .use(expressApp.router)
    .use(errorMiddleware)

  expressApp.all('*', function(req, res, next) {
    next('404: ' + req.url);
  });

  app.writeScripts(store, publicDir, {extensions: ['.coffee']}, function(err) {
    cb(err, expressApp, handlers.upgrade);
  });
}

function createUserId(req, res, next) {
  var model = req.getModel();
  if (req.session) {
    var userId = req.session.userId;
    if (!userId) userId = req.session.userId = model.id();
    model.set('_session.userId', userId);
  }
  next();
}

var errorApp = derby.createApp();
errorApp.loadViews(__dirname + '/../views/error');
errorApp.loadStyles(__dirname + '/../styles/error');

function errorMiddleware(err, req, res, next) {
  if (!err) return next();

  var message = err.message || err.toString();
  var status = parseInt(message);
  status = ((status >= 400) && (status < 600)) ? status : 500;

  if (status < 500) {
    console.log(err.message || err);
  } else {
    console.log(err.stack || err);
  }

  var page = errorApp.createPage(req, res, next);
  page.renderStatic(status, status.toString());
}
<|endoftext|>


<commit_before>import koa from 'koa'
import serve from 'koa-static'
import koaRouter from 'koa-router'
import cors from 'kcors'
import translate from 'google-translate-api'
import proverbs from './proverbs'

const app = new koa()
const router = koaRouter()

app.use(cors())
app.use(serve('public'))

const randomIncludeMin = () => Math.floor(Math.random() * proverbs.length)

router.get('/api/proverbs', (ctx, next) => {
  ctx.body = proverbs[randomIncludeMin()]
})

router.get('/api/translate', async (ctx, next) => {
  if (!ctx.query.word) {
    ctx.body = 'Error: you need to specify a word to translate.'
    return
  }
  const translation = await translate(ctx.query.word, {
    from: 'en',
    to: 'mi'
  })
  ctx.body = translation.text
})

app
  .use(router.routes())
  .use(router.allowedMethods())

export default app
<commit_msg>Alternative endpoint name<commit_after>import koa from 'koa'
import serve from 'koa-static'
import koaRouter from 'koa-router'
import cors from 'kcors'
import translate from 'google-translate-api'
import proverbs from './proverbs'

const app = new koa()
const router = koaRouter()

app.use(cors())
app.use(serve('public'))

const randomIncludeMin = () => Math.floor(Math.random() * proverbs.length)

router.get('/api/proverbs', (ctx, next) => {
  ctx.body = proverbs[randomIncludeMin()]
})

router.get('/api/whakatauki', (ctx, next) => {
  ctx.body = proverbs[randomIncludeMin()]
})

router.get('/api/translate', async (ctx, next) => {
  if (!ctx.query.word) {
    ctx.body = 'Error: you need to specify a word to translate.'
    return
  }
  const translation = await translate(ctx.query.word, {
    from: 'en',
    to: 'mi'
  })
  ctx.body = translation.text
})

app
  .use(router.routes())
  .use(router.allowedMethods())

export default app
<|endoftext|>


<commit_before>var Promise = require('promise');
var Config = require('./config.json');
var http = require('http');
var express = require('express');
var bodyParser = require('body-parser');
var request = require('request');
var io = require('socket.io');
var proxy = require('http-proxy-middleware');
var url = require('url');

var app = express();

module.exports = {
	proxies: {},
	launch: function (port, conman) {
		server = http.createServer(app);
		var installingApps = [];
		io = io(server);

		app.enable('trust proxy');
		app.set('views', 'src/www');
		app.set('view engine', 'pug');
		app.use(express.static('src/www'));

		app.use(bodyParser.urlencoded({extended: false}));

		app.use((req, res, next) => {
			var firstPart = req.path.split('/')[1];
			if (firstPart in this.proxies) {
				var proxyURL = url.format({
					protocol: req.protocol,
					hostname: req.hostname,
					port: this.proxies[firstPart],
					pathname: req.baseUrl + req.path.substring(firstPart.length + 1),
					query: req.query
				});

				console.log("[Proxy] " + req.method + ": " + req.url + " => " + proxyURL);
				return req
					.pipe(request(proxyURL))
					.on('error', (e) => {
						console.log(e);
					})
					.pipe(res)
					.on('error', (e) => {
						console.log(e);
					});
			}
			next();
		});

		app.get('/', (req, res) => {
			res.render('index')
		});
		app.get('/slayer', (req, res) => {
			res.render('slayer')
		});

		app.get('/manifest', (req, res) => {
			request.post({'url': Config.storeUrl + '/app/get/', 'form': {'name': req.query.name}}, (err, data) => {
				if (err) {
					//do nothing
					return;
				}

				res.json(JSON.parse(data.body));
			});
		});

		app.get('/list-containers', (req, res) => {
			conman.listContainers()
				.then((containers) => {
					for (var installingApp of installingApps) {
						var appName = '/' + installingApp;
						var found = false;
						for (var installedApp of containers) {
							if (installedApp.Names.indexOf(appName) != -1) {
								found = true;
							}
						}
						if (!found) {
							containers.push({Names: [appName], State: "installing"});
						}
					}
					res.json(containers);
				});
			//.catch()
		});

		app.get('/list-store', (req, res) => {
			request('https://' + Config.registryUrl + '/v2/_catalog', (error, response, body) => {
				if (error) {
					res.json(error);
					return
				}
				var repositories = JSON.parse(body).repositories;
				var repocount = repositories.length;
				var manifests = [];

				repositories.map((repo) => {
					request.post({'url': Config.storeUrl + '/app/get/', 'form': {'name': repo}}, (err, data) => {

						if (err) {
							//do nothing
							return;
						}

						body = JSON.parse(data.body);
						if (typeof body.error == 'undefined' || body.error != 23) {
							manifests.push(body);
						}
						repocount--;
						if (repocount <= 0) {
							res.json(manifests);
						}
					});
				});

			});
		});

		app.post('/pull-app', (req, res) => {
			conman.pullImage(Config.registryUrl + req.body.name + ':' + req.body.tag)
				.then((err, data) => {
					if (err) {
						return;
					}
					stream.pipe(data)
				});
		});

		app.post('/install', (req, res) => {
			var sla = JSON.parse(req.body.sla);
			var name = sla.name;
			console.log(JSON.stringify(installingApps));
			repoTag = name;
			installingApps.push(name);

			io.emit('docker-create', repoTag);
			conman.launchContainer(repoTag, sla)
				.then((info) => {
					console.log("CONTAINER CREATED", info);
					var index = installingApps.indexOf(name);
					if (index != -1) {
						installingApps.splice(index, 1)
					}
					this.proxies[info.name] = info.port;
					res.json(info);
				});
		});

		app.post('/restart', (req, res) => {
			console.log("Restarting " + req.body.id);
			conman.getContainer(req.body.id)
				.then((cont) => {
					return conman.stopContainer(cont)
				})
				.then((cont) => {
					return conman.startContainer(cont)
				})
				.then((data) => {
					console.log("Restarted " + JSON.stringify(data));
					console.log("Restarted " + data.id);
					this.proxies[data.name] = data.port;
					res.json(data);
				})
				.catch((err)=> {
					res.json(err);
				})
		});

		app.post('/uninstall', (req, res) => {
			console.log("Uninstalling " + req.body.id);
			conman.getContainer(req.body.id)
				.then((cont)=> {
					return conman.stopContainer(cont)
				})
				.then((cont)=> {
					return conman.removeContainer(cont)
				})
				.then((data)=> {
					console.log("Uninstalled " + data.id);
					res.json(data);
				})
				.catch((err)=> {
					res.json(err)
				});

		});

		io.on('connection', (socket) => {

			var emitter = conman.getDockerEmitter();

			emitter.on("connect", () => {
				socket.emit('docker-connect');
			});
			emitter.on("disconnect", () => {
				socket.emit('docker-disconnect');
			});
			emitter.on("_message", (message) => {
				socket.emit('docker-_message', message);
			});
			emitter.on("create", (message) => {
				socket.emit('docker-create', message);
			});
			emitter.on("start", (message) => {
				socket.emit('docker-star', message);
			});
			emitter.on("start", (message) => {
				socket.emit('docker-stop', message);
			});
			emitter.on("die", (message) => {
				socket.emit('docker-die', message);
			});
			emitter.on("destroy", (message) => {
				socket.emit('docker-destroy', message);
			});
			emitter.start();

		});

		server.listen(port);
	}
};
<commit_msg>Remove unused requires<commit_after>var Config = require('./config.json');
var http = require('http');
var express = require('express');
var bodyParser = require('body-parser');
var request = require('request');
var io = require('socket.io');
var url = require('url');

var app = express();

module.exports = {
	proxies: {},
	launch: function (port, conman) {
		var server = http.createServer(app);
		var installingApps = [];
		io = io(server);

		app.enable('trust proxy');
		app.set('views', 'src/www');
		app.set('view engine', 'pug');
		app.use(express.static('src/www'));

		app.use(bodyParser.urlencoded({extended: false}));

		app.use((req, res, next) => {
			var firstPart = req.path.split('/')[1];
			if (firstPart in this.proxies) {
				var proxyURL = url.format({
					protocol: req.protocol,
					hostname: req.hostname,
					port: this.proxies[firstPart],
					pathname: req.baseUrl + req.path.substring(firstPart.length + 1),
					query: req.query
				});

				console.log("[Proxy] " + req.method + ": " + req.url + " => " + proxyURL);
				return req
					.pipe(request(proxyURL))
					.on('error', (e) => {
						console.log(e);
					})
					.pipe(res)
					.on('error', (e) => {
						console.log(e);
					});
			}
			next();
		});

		app.get('/', (req, res) => {
			res.render('index')
		});
		app.get('/slayer', (req, res) => {
			res.render('slayer')
		});

		app.get('/manifest', (req, res) => {
			request.post({'url': Config.storeUrl + '/app/get/', 'form': {'name': req.query.name}}, (err, data) => {
				if (err) {
					//do nothing
					return;
				}

				res.json(JSON.parse(data.body));
			});
		});

		app.get('/list-containers', (req, res) => {
			conman.listContainers()
				.then((containers) => {
					for (var installingApp of installingApps) {
						var appName = '/' + installingApp;
						var found = false;
						for (var installedApp of containers) {
							if (installedApp.Names.indexOf(appName) != -1) {
								found = true;
							}
						}
						if (!found) {
							containers.push({Names: [appName], State: "installing"});
						}
					}
					res.json(containers);
				});
			//.catch()
		});

		app.get('/list-store', (req, res) => {
			request('https://' + Config.registryUrl + '/v2/_catalog', (error, response, body) => {
				if (error) {
					res.json(error);
					return
				}
				var repositories = JSON.parse(body).repositories;
				var repocount = repositories.length;
				var manifests = [];

				repositories.map((repo) => {
					request.post({'url': Config.storeUrl + '/app/get/', 'form': {'name': repo}}, (err, data) => {

						if (err) {
							//do nothing
							return;
						}

						body = JSON.parse(data.body);
						if (typeof body.error == 'undefined' || body.error != 23) {
							manifests.push(body);
						}
						repocount--;
						if (repocount <= 0) {
							res.json(manifests);
						}
					});
				});

			});
		});

		app.post('/pull-app', (req, res) => {
			conman.pullImage(Config.registryUrl + req.body.name + ':' + req.body.tag)
				.then((err, data) => {
					if (err) {
						return;
					}
					stream.pipe(data)
				});
		});

		app.post('/install', (req, res) => {
			var sla = JSON.parse(req.body.sla);
			var name = sla.name;
			console.log(JSON.stringify(installingApps));
			repoTag = name;
			installingApps.push(name);

			io.emit('docker-create', repoTag);
			conman.launchContainer(repoTag, sla)
				.then((info) => {
					console.log("CONTAINER CREATED", info);
					var index = installingApps.indexOf(name);
					if (index != -1) {
						installingApps.splice(index, 1)
					}
					this.proxies[info.name] = info.port;
					res.json(info);
				});
		});

		app.post('/restart', (req, res) => {
			console.log("Restarting " + req.body.id);
			conman.getContainer(req.body.id)
				.then((cont) => {
					return conman.stopContainer(cont)
				})
				.then((cont) => {
					return conman.startContainer(cont)
				})
				.then((data) => {
					console.log("Restarted " + data.id);

					res.json(data);
				})
				.catch((err)=> {
					res.json(err);
				})
		});

		app.post('/uninstall', (req, res) => {
			console.log("Uninstalling " + req.body.id);
			conman.getContainer(req.body.id)
				.then((cont)=> {
					return conman.stopContainer(cont)
				})
				.then((cont)=> {
					return conman.removeContainer(cont)
				})
				.then((data)=> {
					console.log("Uninstalled " + data.id);
					res.json(data);
				})
				.catch((err)=> {
					res.json(err)
				});

		});

		io.on('connection', (socket) => {

			var emitter = conman.getDockerEmitter();

			emitter.on("connect", () => {
				socket.emit('docker-connect');
			});
			emitter.on("disconnect", () => {
				socket.emit('docker-disconnect');
			});
			emitter.on("_message", (message) => {
				socket.emit('docker-_message', message);
			});
			emitter.on("create", (message) => {
				socket.emit('docker-create', message);
			});
			emitter.on("start", (message) => {
				socket.emit('docker-star', message);
			});
			emitter.on("start", (message) => {
				socket.emit('docker-stop', message);
			});
			emitter.on("die", (message) => {
				socket.emit('docker-die', message);
			});
			emitter.on("destroy", (message) => {
				socket.emit('docker-destroy', message);
			});
			emitter.start();

		});

		server.listen(port);
	}
};
<|endoftext|>


<commit_before>/*global _:false, extendFunction: false, historicalConsole: false, wrapInTryCatch: false*/

function exceptionalException(message) {
  'use strict';

  // alias:
  var ee = exceptionalException;
  ee.confirmDialogMessage || (ee.confirmDialogMessage = 'We were not able to report an error to our servers. Please email us so we can fix it.');
  ee.domain || (
    ee.domain = location.hostname.split('.'),
    ee.domain = '@' + ee.domain[ee.domain.length - 2] + '.' + ee.domain[ee.domain.length - 1]
  );
  ee.mailtoParams.subject || (ee.mailtoParams.subject = 'Automated error report failed, here\'s a manual one');
  ee.mailtoParams.body    || (ee.mailtoParams.body    = 'I found X javascript errors, they are listed below:');
  function stringifyHash(hash) {
    var result = '';
    for (var key in hash) {
      result += key + ': ' + hash[key];
    }
    return result;
  }
  ee.stringifyHash || (ee.stringifyHash = stringifyHash);

  if (ee.emailErrors !== false) {

    ee.emailErrors = confirm(ee.confirmDialogMessage);

    if (ee.emailErrors) {

      if (!_.isString(message)) {

        //ensure stack property is computed
        message.stack;
        message = ee.stringifyHash(message); //
      }

      ee.mailtoParams.subject && (ee.mailtoParams.body += '\n\n' + message) || (
        ee.mailtoParams.body = ''
      );
      //que of sorts? -setTimeout without runloop, or at very end of runloop stuff..?

      //wait 200 milliseconds in case any other exceptionalExceptions come in
      setTimeout(function(){
        location.href = 'mailto:unrecordedJavaScriptError' + ee.domain + ',support@' + ee.domain + '?' +

      }, 200);
    }
  }
}

function wrapInTryCatch(func) {
  function wrappedFunction() {
    try {
      return func.apply(this, Array.prototype.slice.call(arguments) );
    } catch (generalUncaughtException) { // base try catch block.

      // in the event of an uncaught exception, try to send the exception to onuncaughtException
      try {
        onuncaughtException(generalUncaughtException);

      } catch (exceptionCallingOnUncaughtException) {
        // however, if there's a problem with THAT........

        // First check if it's even defined:
        if (typeof onuncaughtException === 'undefined') {

          // Prompt to define accordingly:
          if (typeof console !== 'undefined' && console.warn) {
            console.warn('You should define an onuncaughtException handler for exceptions, SON.');
          } else if (typeof confirm !== 'undefined' && wrapInTryCatch.defineDialogs !== false) {
            wrapInTryCatch.defineDialogs = confirm('Please define an uncaughtException handler');
          }
          throw e; // will hit window.onerror.
                   // We could also manually call window.onerror with the same arguments each time so it can be programmed against

        } else { // apparently `onuncaughtException` IS DEFINED...
          if (Object.prototype.toString.call(onuncaughtException) != '[object Function]') {
            exceptionalException(new TypeError('onuncaughtException is not a function'));
          } else {
            exceptionalException(exceptionCallingOnUncaughtException);
          }
        }

      } // for catch exceptionCallingOnUncaughtException
    } // for catch generalUncaughtException
  }
  return wrappedFunction;
}

(function shieldJS(global) {
  'use strict';

  // IE < 9 doesn't support .call/.apply on setInterval/setTimeout, but it
  // also only supports 2 argument and doesn't care what "this" is, so we
  // can just call the original function directly.
  function applyPatch(irrelevantThis, args) {
    return this(args[0], args[1]);
  }
  if (!setTimeout.apply) {
    setTimeout.apply = applyPatch;
  }
  if (!setInterval.apply) {
    setInterval.apply = applyPatch;
  }

/**

## The main `shield` function does a few things:

1. Wraps a callback in a try/catch block:

```
shield(function(){
    //your program
})();
```

2. Optionally include a `console` param to use our historicalConsole

```
shield(function(console){
})();
```

For documentation regarding keeping a console history, see
github.com/devinrhode2/historicalConsole.js

3. Modify global api functions so their callbacks are also wrapped in a try/catch block:

```
shield('$');
shield('$, $.fn.on, $.fn.ready

//Now errors in these callbacks will be caught, and there's no need for a try/catch block:
$(function(){})
$('#foo').on('click', function(){})
$(document).ready(function(){})
```

4. Use it for easier try/catch blocks. Instead of:

```
var func = function() {
    //your function
};

// add shield:
var func = shield(function(){
    //no need for a try/catch block now, shield has it taken care of
});
```

### Do not invoke with `new`

@class shield
@constructor shield
@type Function
@param apiFn {String || Function} A string must represent a global function like `'$'`, or a space/comma-space seperated list like `'$, $.fn.ready'`

  Pass in a function, and it will be shieled and returned. `shield`'ing means this function and callbacks
  passed as parameters to it will have all exceptions sent to onuncaughtError, or shield subscribers. (example 4)
@param {String} [promises] Space or comma-space separated list of promise functions to shield (like $.ajax().done)
@return {Function} A function that will have all uncaught exceptions sent to your shield.js subscribers, or onuncaughtException if you overwrote the function. You shield.unsubscribe(shield.report)
*/
  function shield(apiFn, promises) {
    if (_.isString(apiFn)) {
      if (apiFn.indexOf(' ') > -1) {
        apiFn.replace(/\,/g, ''); //allow '$, $.fn.on, $.fn.ready'
        apiFn = apiFn.split(' ');
      }
    }
    if (_.isArray(apiFn)) {
      _.each(apiFn, function(api){
        shield(api);
      });
      return;
    }
    return wrapInTryCatch(extendFunction(apiFn, function(args, prevFunc) {
      apiFn = null;//garbage collected

      //if function.length (number of listed parameters) is 1, and there are no args, then this is
      //shield(function(console){})()
      //ie, prevFunc expects 1 arg (length) but received none when called
      if (prevFunc.length === 1 && args.length === 0) {

        //verify a 'console' param
        var prevFnString = prevFunc.toString();
        var firstParen = prevFnString.indexOf('(');
        var secondParen = prevFnString.indexOf(')', firstParen);
        if (prevFnString.substring(firstParen, secondParen).indexOf('console') > -1 && typeof historicalConsole !== 'undefined') {
          //historicalConsole takes in a function and returns one that will receive the first arg as the console.
          //The second arg is a unique identifier to use another scope's historical console object
          //options.url is probably a deent unique identifier.
          //We could ask the user to name the app (shield.options.appName('thing')
          return historicalConsole(prevFunc/*, options.url*/);
        } else {
          return prevFunc;
        }
      } else {
        //instead of just doing apiFn.apply, we interate through args
        //and if an arg is a function then we wrap then we swap that fn for callback in a try/catch
        var length = args.length;
        //before executing the overriden function, transform each function arg to have a try/catch wrapper
        //I'd prefer to keep the while/length style iteration here for performance, since this can be rather important
        var arg;
        while (arg = args[--length]) {
          if (_.isFunction(arg)) {
            arg = wrapInTryCatch(arg);
          }
        }

        //now we apply the modified arguments:
        var ret = prevFunc.apply(this, args);
        if (promises) {
          promises = promises.split(' ');
          var promise;
          while(promise = promises.pop()) {
            ret[promise] = shield(ret[promise]);
          }
        }
        return ret;
      }
    }));
  }

  /**
   * @method normalize
   * @param error {Error} an
   */
  function shield_normalize(error, callback) {
    if (callback == null) {
      // do synchronous normalization
      return {stack: []};
    }
  }

  /**
   * @method report
   * @param arg {Error || Object || String}
   * @constructor
   */
  function shield_report(/* arg */) {
    //If object or string AND it has no stack property, add one by doing .stack = (new Error('force-added stack')).stack
    shield.normalize(function(/* jsonErrorReport */) {
      //send to subscribers
      //if no subscribers.. then throw an error or alert?
      //If we were to throw in this situation, I would call that an exceptionalException, and call that function above
    });
    return;
  }
  return shield.wrapInTryCatch(extendFunction(apiFn, function(args, prevFunc) {
    apiFn = null;//garbage collected

  /**
   * Export shield out to another variable, e.g., `myModule.shield = shield.noConflict();`
   *
   * @method noConflict
   * @namespace shield
   * @return {Function} the currently defined window.shield (now defined to the previous
       window.shield, which may or may not be defined)
   */
  var oldShield = window.shield;
  function shield_noConflict() {
    window.shield = oldShield;
    return shield;
  }

  //assiging one static object to the prototype instead of property by property is faster in V8
  //performance is the same in other browsers, except FF which is way faster than everyone else
  //and therefore doesn't matter as much. http://jsperf.com/props-or-proto-on-fns
  shield.prototype = {
    report: shield_report,
    normalize: shield_normalize,
    noConflict: shield_noConflict
  };

  window.shield = shield;
})(this);<commit_msg>yaaaaaa trick ya<commit_after>/*global _:false, extendFunction: false, historicalConsole: false, wrapInTryCatch: false*/

function exceptionalException(message) {
  'use strict';

  // alias:
  var ee = exceptionalException;
  ee.confirmDialogMessage || (ee.confirmDialogMessage = 'We were not able to report an error to our servers. Please email us so we can fix it.');
  ee.domain || (
    ee.domain = location.hostname.split('.'),
    ee.domain = '@' + ee.domain[ee.domain.length - 2] + '.' + ee.domain[ee.domain.length - 1]
  );
  ee.mailtoParams.subject || (ee.mailtoParams.subject = 'Automated error report failed, here\'s a manual one');
  ee.mailtoParams.body    || (ee.mailtoParams.body    = 'I found X javascript errors, they are listed below:');
  function stringifyHash(hash) {
    var result = '';
    for (var key in hash) {
      result += key + ': ' + hash[key];
    }
    return result;
  }
  ee.stringifyHash || (ee.stringifyHash = stringifyHash);

  if (ee.emailErrors !== false) {

    ee.emailErrors = confirm(ee.confirmDialogMessage);

    if (ee.emailErrors) {

      if (!_.isString(message)) {

        //ensure stack property is computed
        message.stack;
        message = ee.stringifyHash(message); //
      }

      ee.mailtoParams.subject && (ee.mailtoParams.body += '\n\n' + message) || (
        ee.mailtoParams.body = ''
      );
      //que of sorts? -setTimeout without runloop, or at very end of runloop stuff..?

      location.href = 'mailto:unrecordedJavaScriptError' + ee.domain + ',support@' + ee.domain + '?' + (function(){
        for (var param in ee.mailtoParams) {
          if (ee.mailtoParams.hasOwnProperty(param)) {

          }
        }
      })();
    }
  }
}

function wrapInTryCatch(func) {
  function wrappedFunction() {
    try {
      return func.apply(this, Array.prototype.slice.call(arguments) );
    } catch (generalUncaughtException) { // base try catch block.

      // in the event of an uncaught exception, try to send the exception to onuncaughtException
      try {
        onuncaughtException(generalUncaughtException);

      } catch (exceptionCallingOnUncaughtException) {
        // however, if there's a problem with THAT........

        // First check if it's even defined:
        if (typeof onuncaughtException === 'undefined') {

          // Prompt to define accordingly:
          if (typeof console !== 'undefined' && console.warn) {
            console.warn('You should define an onuncaughtException handler for exceptions, SON.');
          } else if (typeof confirm !== 'undefined' && wrapInTryCatch.defineDialogs !== false) {
            wrapInTryCatch.defineDialogs = confirm('Please define an uncaughtException handler');
          }
          throw e; // will hit window.onerror.
                   // We could also manually call window.onerror with the same arguments each time so it can be programmed against

        } else { // apparently `onuncaughtException` IS DEFINED...
          if (Object.prototype.toString.call(onuncaughtException) != '[object Function]') {
            exceptionalException(new TypeError('onuncaughtException is not a function'));
          } else {
            exceptionalException(exceptionCallingOnUncaughtException);
          }
        }

      } // for catch exceptionCallingOnUncaughtException
    } // for catch generalUncaughtException
  }
  return wrappedFunction;
}

(function shieldJS(global) {
  'use strict';

  // IE < 9 doesn't support .call/.apply on setInterval/setTimeout, but it
  // also only supports 2 argument and doesn't care what "this" is, so we
  // can just call the original function directly.
  function applyPatch(irrelevantThis, args) {
    return this(args[0], args[1]);
  }
  if (!setTimeout.apply) {
    setTimeout.apply = applyPatch;
  }
  if (!setInterval.apply) {
    setInterval.apply = applyPatch;
  }

/**

## The main `shield` function does a few things:

1. Wraps a callback in a try/catch block:

```
shield(function(){
    //your program
})();
```

2. Optionally include a `console` param to use our historicalConsole

```
shield(function(console){
})();
```

For documentation regarding keeping a console history, see
github.com/devinrhode2/historicalConsole.js

3. Modify global api functions so their callbacks are also wrapped in a try/catch block:

```
shield('$');
shield('$, $.fn.on, $.fn.ready

//Now errors in these callbacks will be caught, and there's no need for a try/catch block:
$(function(){})
$('#foo').on('click', function(){})
$(document).ready(function(){})
```

4. Use it for easier try/catch blocks. Instead of:

```
var func = function() {
    //your function
};

// add shield:
var func = shield(function(){
    //no need for a try/catch block now, shield has it taken care of
});
```

### Do not invoke with `new`

@class shield
@constructor shield
@type Function
@param apiFn {String || Function} A string must represent a global function like `'$'`, or a space/comma-space seperated list like `'$, $.fn.ready'`

  Pass in a function, and it will be shieled and returned. `shield`'ing means this function and callbacks
  passed as parameters to it will have all exceptions sent to onuncaughtError, or shield subscribers. (example 4)
@param {String} [promises] Space or comma-space separated list of promise functions to shield (like $.ajax().done)
@return {Function} A function that will have all uncaught exceptions sent to your shield.js subscribers, or onuncaughtException if you overwrote the function. You shield.unsubscribe(shield.report)
*/
  function shield(apiFn, promises) {
    if (_.isString(apiFn)) {
      if (apiFn.indexOf(' ') > -1) {
        apiFn.replace(/\,/g, ''); //allow '$, $.fn.on, $.fn.ready'
        apiFn = apiFn.split(' ');
      }
    }
    if (_.isArray(apiFn)) {
      _.each(apiFn, function(api){
        shield(api);
      });
      return;
    }
    return wrapInTryCatch(extendFunction(apiFn, function(args, prevFunc) {
      apiFn = null;//garbage collected

      //if function.length (number of listed parameters) is 1, and there are no args, then this is
      //shield(function(console){})()
      //ie, prevFunc expects 1 arg (length) but received none when called
      if (prevFunc.length === 1 && args.length === 0) {

        //verify a 'console' param
        var prevFnString = prevFunc.toString();
        var firstParen = prevFnString.indexOf('(');
        var secondParen = prevFnString.indexOf(')', firstParen);
        if (prevFnString.substring(firstParen, secondParen).indexOf('console') > -1 && typeof historicalConsole !== 'undefined') {
          //historicalConsole takes in a function and returns one that will receive the first arg as the console.
          //The second arg is a unique identifier to use another scope's historical console object
          //options.url is probably a deent unique identifier.
          //We could ask the user to name the app (shield.options.appName('thing')
          return historicalConsole(prevFunc/*, options.url*/);
        } else {
          return prevFunc;
        }
      } else {
        //instead of just doing apiFn.apply, we interate through args
        //and if an arg is a function then we wrap then we swap that fn for callback in a try/catch
        var length = args.length;
        //before executing the overriden function, transform each function arg to have a try/catch wrapper
        //I'd prefer to keep the while/length style iteration here for performance, since this can be rather important
        var arg;
        while (arg = args[--length]) {
          if (_.isFunction(arg)) {
            arg = wrapInTryCatch(arg);
          }
        }

        //now we apply the modified arguments:
        var ret = prevFunc.apply(this, args);
        if (promises) {
          promises = promises.split(' ');
          var promise;
          while(promise = promises.pop()) {
            ret[promise] = shield(ret[promise]);
          }
        }
        return ret;
      }
    }));
  }

  /**
   * @method normalize
   * @param error {Error} an
   */
  function shield_normalize(error, callback) {
    if (callback == null) {
      // do synchronous normalization
      return {stack: []};
    }
  }

  /**
   * @method report
   * @param arg {Error || Object || String}
   * @constructor
   */
  function shield_report(/* arg */) {
    //If object or string AND it has no stack property, add one by doing .stack = (new Error('force-added stack')).stack
    shield.normalize(function(/* jsonErrorReport */) {
      //send to subscribers
      //if no subscribers.. then throw an error or alert?
      //If we were to throw in this situation, I would call that an exceptionalException, and call that function above
    });
    return;
  }
  return shield.wrapInTryCatch(extendFunction(apiFn, function(args, prevFunc) {
    apiFn = null;//garbage collected

  /**
   * Export shield out to another variable, e.g., `myModule.shield = shield.noConflict();`
   *
   * @method noConflict
   * @namespace shield
   * @return {Function} the currently defined window.shield (now defined to the previous
       window.shield, which may or may not be defined)
   */
  var oldShield = window.shield;
  function shield_noConflict() {
    window.shield = oldShield;
    return shield;
  }

  //assiging one static object to the prototype instead of property by property is faster in V8
  //performance is the same in other browsers, except FF which is way faster than everyone else
  //and therefore doesn't matter as much. http://jsperf.com/props-or-proto-on-fns
  shield.prototype = {
    report: shield_report,
    normalize: shield_normalize,
    noConflict: shield_noConflict
  };

  window.shield = shield;
})(this);<|endoftext|>