<commit_before>"use strict";

// Separate scope to work around bug 673569
(function() {

const Cu = Components.utils;
const Cc = Components.classes;
const Ci = Components.interfaces;

function dumpln(s) { dump(s + "\n"); }

// content script for e10s support

// This is a frame script, so it may be running in a content process.
// In any event, it is targeted at a specific "tab", so we listen for
// the DOMWindowCreated event to be notified about content windows
// being created in this context.

function DOMFuzzHelperManager() {
  addEventListener("DOMWindowCreated", this, false);
}

DOMFuzzHelperManager.prototype = {
  handleEvent: function handleEvent(aEvent) {
    var window = aEvent.target.defaultView;
    window.wrappedJSObject.fuzzPriv = makeDOMFuzzHelper(window);
    window.addEventListener("load", maybeInjectScript, false);
  }
};

var domfuzzhelpermanager = new DOMFuzzHelperManager();

/*****************************
 * FUZZPRIV OBJECT INJECTION *
 *****************************/

// Create deeply fresh objects so windows don't influence each other.

function makeDOMFuzzHelper(aWindow) {
  dumpln("DOMFuzzHelper created");

  return {
      toString: function() { return "[DOMFuzzHelper]"; },

      quitApplication: function() {
        sendAsyncMessage('DOMFuzzHelper.quitApplication', {});
      },

      quitApplicationSoon: function() {
        sendAsyncMessage('DOMFuzzHelper.quitApplicationSoon', {});
      },

      closeTabThenQuit: function () {
        // Somehow async messages get lost in close().
        sendSyncMessage('DOMFuzzHelper.quitApplicationSoon', {});

        // This frame-script stops running immediately after close().
        content.close();
      },

      quitWithLeakCheck: function () {
        sendAsyncMessage('DOMFuzzHelper.quitWithLeakCheck', {});
      },

      setGCZeal: function(zeal) {
        sendSyncMessage("DOMFuzzHelper.setGCZeal", {'zeal' : zeal});
      },

      runSoon: runSoon.bind(this),

      enableAccessibility: enableAccessibility.bind(this),

      GC: function() { Cu.forceGC(); },

      CC: cycleCollect(aWindow),

      MP: sendMemoryPressureNotification.bind(this),

      fontList: fontList.bind(this),

      reftestList: reftestList.bind(this),

      printToFile: printToFile(aWindow),

      openAboutMemory: function() {
        sendAsyncMessage('DOMFuzzHelper.openAboutMemory', {});
      },

      cssPropertyDatabase: cssPropertyDatabase.bind(this),

      comparePixels: comparePixels(aWindow),

      __exposedProps__: {
        'toString': 'r',
        'quitApplication': 'r',
        'quitApplicationSoon': 'r',
        'closeTabThenQuit': 'r',
        'quitWithLeakCheck': 'r',
        'setGCZeal': 'r',
        'runSoon': 'r',
        'enableAccessibility': 'r',
        'GC': 'r',
        'CC': 'r',
        'MP': 'r',
        'fontList': 'r',
        'printToFile': 'r',
        'openAboutMemory': 'r',
        'reftestList': 'r',
        'cssPropertyDatabase': 'r',
        'comparePixels': 'r'
      }
  };
};

/***********************************************
 * MISC PRIVILEGED FUNCTIONS - CONTENT PROCESS *
 ***********************************************/

function runSoon(f)
{
  var tm = Cc["@mozilla.org/thread-manager;1"]
             .getService(Ci.nsIThreadManager);

  tm.mainThread.dispatch({
    run: function() {
      f();
    }
  }, Ci.nsIThread.DISPATCH_NORMAL);
}

function enableAccessibility()
{
  try {
    Components.classes["@mozilla.org/accessibilityService;1"]
      .getService(Components.interfaces.nsIAccessibleRetrieval);
    dump("Enabled accessibility!\n");
  } catch(e) {
    dump("Couldn't enable accessibility: " + e + "\n");
  }
}

function sendMemoryPressureNotification()
{
  var os = Components.classes["@mozilla.org/observer-service;1"]
           .getService(Components.interfaces.nsIObserverService);
  os.notifyObservers(null, "memory-pressure", "heap-minimize");
}

function cycleCollect(window)
{
  return function cycleCollectInner() {
    window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
          .getInterface(Components.interfaces.nsIDOMWindowUtils)
          .cycleCollect();
  }
}

function comparePixels(aWindow)
{
  return function comparePixels2() {
    var w = aWindow.innerWidth;
    var h = aWindow.innerHeight;
    dumpln(w + " x " + h);

    var canvas1 = aWindow.document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
    canvas1.setAttribute("width", w);
    canvas1.setAttribute("height", h);

    var canvas2 = aWindow.document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
    canvas2.setAttribute("width", w);
    canvas2.setAttribute("height", h);

    function drawInto(canvas)
    {
      var ctx = canvas.getContext("2d");
      ctx.drawWindow(aWindow,
                     aWindow.scrollX,
                     aWindow.scrollY,
                     w,
                     h,
                     "rgb(255,255,255)",
                     ctx.DRAWWINDOW_DRAW_CARET |
                     ctx.DRAWWINDOW_USE_WIDGET_LAYERS);
    }

    drawInto(canvas1);
    return function comparePixels3() {
      drawInto(canvas2);
      var wu = aWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
      var o = {};
      var n = wu.compareCanvases(canvas1, canvas2, o);
      if (n == 0) { return ""; }
      return (
        n + " pixel" + (n == 1 ? "" : "s") + " differ (max channel difference: " + o.value + ")\n" +
        "Before:\n" + canvas1.toDataURL() + "\n" +
        "After:\n" + canvas2.toDataURL() + "\n"
      );
    }
  }
}

/*
function setZoomLevel(window)
{
  return function setZoomLevelInner(textOrFull, factor) {
    var viewer = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
                       .getInterface(Components.interfaces.nsIWebNavigation)
                       .QueryInterface(Components.interfaces.nsIDocShell)
                       .contentViewer
                       .QueryInterface(Components.interfaces.nsIMarkupDocumentViewer);

    if (textOrFull == "text")
      viewer.textZoom = +factor;
    else if (textOrFull == "full")
      viewer.fullZoom = +factor;
  }
}
*/

function printToFile(window)
{
  // Oddly asynchronous, at least on Linux.

  // Linux: works for PDF and PS.
  // Windows: works for PDF at least. Text may be invisible (bug 653336).
  // Mac: tested, printToFile is ignored and it goes to a printer!
  var xulRuntime = Components.classes["@mozilla.org/xre/app-info;1"]
                             .getService(Components.interfaces.nsIXULRuntime);
  if (xulRuntime.OS != "Linux" && xulRuntime.OS != "WINNT") return function() { };

  var fired = false;

  return function printToFileInner(showHeaders, showBGColor, showBGImages, ps) {
    runSoon(function() {
        // Don't print more than once, it gets messy fast.
        if (fired) { return false; }
        fired = true;

        ps = ps && xulRuntime.OS != "WINNT"; // Windows gets confused when trying to print to ps, and tosses up a *.xps filepicker outside the Firefox process!?

        // Based on https://addons.mozilla.org/en-US/firefox/addon/5971/ by pavlov (Stuart Parmenter) and bho

        var webBrowserPrint = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
        .getInterface(Components.interfaces.nsIWebBrowserPrint);

        var nsIPrintSettings = Components.interfaces.nsIPrintSettings;

        var PSSVC = Components.classes["@mozilla.org/gfx/printsettings-service;1"]
        .getService(Components.interfaces.nsIPrintSettingsService);

        var printSettings = PSSVC.newPrintSettings;

        var file = profileDirectory();
        file.append(ps ? "fuzzout.ps" : "fuzzout.pdf");
        dumpln("Printing to: " + file.path);

        printSettings.printToFile = true;
        printSettings.toFileName  = file.path;
        printSettings.printSilent = true;
        printSettings.outputFormat = ps ? nsIPrintSettings.kOutputFormatPS : nsIPrintSettings.kOutputFormatPDF;
        printSettings.printBGColors   = !!showBGColor;
        printSettings.printBGImages   = !!showBGImages;
        if (!showHeaders) {
            printSettings.footerStrCenter = '';
            printSettings.footerStrLeft   = '';
            printSettings.footerStrRight  = '';
            printSettings.headerStrCenter = '';
            printSettings.headerStrLeft   = '';
            printSettings.headerStrRight  = '';
        }

        webBrowserPrint.print(printSettings, null);
    });
  }
}

function cycleCollect()
{
  return function cycleCollectInner() {
      try {
        content.QueryInterface(Ci.nsIInterfaceRequestor)
              .getInterface(Ci.nsIDOMWindowUtils)
              .cycleCollect();
      }

      catch(e) {
        dumpln("cycle collect failed " + e);
      }
  }
}

function fontList()
{
    return Components.classes["@mozilla.org/gfx/fontenumerator;1"]
            .createInstance(Components.interfaces.nsIFontEnumerator)
            .EnumerateAllFonts({})
            .join("\n");
}

function reftestList()
{
  var dir = extensionLocation().parent;
  dir.append("automation");
  return readFile(indir(dir, "urls-reftests"));
}

function cssPropertyDatabase()
{
  var fn = sendSyncMessage('DOMFuzzHelper.getBinDirectory', {})[0];
  var f = Components.classes["@mozilla.org/file/local;1"]
                    .createInstance(Components.interfaces.nsILocalFile);
  f.initWithPath(fn);
  while (f.leafName != "dist") {
    f = f.parent;
  }
  f = f.parent;
  f.append("tests");
  f.append("reftest");
  f.append("tests");
  f.append("layout");
  f.append("style");
  f.append("test");
  f.append("property_database.js");
  return readFile(f);
}

/**********************
 * FILESYSTEM HELPERS *
 **********************/

function profileDirectory()
{
  var fn = sendSyncMessage('DOMFuzzHelper.getProfileDirectory', {})[0];
  var d = Components.classes["@mozilla.org/file/local;1"]
                    .createInstance(Components.interfaces.nsILocalFile);
  d.initWithPath(fn);
  return d;
}

function extensionLocation()
{
  var d = profileDirectory();
  d.append("extensions");
  d.append("domfuzz@squarefree.com");

  var extensionLocation = readFile(d).replace(/\s*$/, "");

  var f = Components.classes["@mozilla.org/file/local;1"]
                    .createInstance(Components.interfaces.nsILocalFile);
  f.initWithPath(extensionLocation);
  return f;
}

// readFile function from logan
// http://www.gozer.org/mozilla/userChrome.js/scripts/userScripts.uc.js
// |file| must be an nsIFile.
// Returns the contents of the file as a string.
function readFile(file)
{
  var content = '';

  var stream = Components.classes['@mozilla.org/network/file-input-stream;1']
                    .createInstance(Components.interfaces.nsIFileInputStream);
  stream.init(file, 0x01, 0, 0);

  var script = Components.classes['@mozilla.org/scriptableinputstream;1']
              .createInstance(Components.interfaces.nsIScriptableInputStream);
  script.init(stream);

  if (stream.available()) {
    var data = script.read(4096);

    while (data.length > 0) {
      content += data;
      data = script.read(4096);
    }
  }

  stream.close();
  script.close();

  return content;
}

function indir(dir, filename)
{
  var d = dir.clone();
  d.append(filename);
  return d;
}

/*************************
 * FUZZ SCRIPT INJECTION *
 *************************/

function maybeInjectScript(event)
{
  var doc = event.originalTarget;
  if (doc.nodeName != "#document")
    return;

  var hash = doc.location.hash;

  var r = hash.split(",");

  if (r[0] != "#squarefree-af") {
    return;
  }
  if (!(/^[a-zA-Z0-9\-.]*$/.test(r[1]))) {
    dump("Sketchy fuzzer filename!\n");
    return;
  }

  var dir = extensionLocation().parent;
  dir.append("fuzzers");

  var scriptToInject =
    readFile(indir(dir, "fuzz.js")) + "\n"
  + readFile(indir(dir, r[1])) + "\n"
  + readFile(indir(dir, "fuzz-finish-auto.js")) + "\n"
  + "document.getElementById('fuzz1').parentNode.removeChild(document.getElementById('fuzz1'));\n"
  + "fuzzSettings = [" + r.slice(2).join(",") + "];\n"
  + "setTimeout(fuzzOnload, 400);\n";

  var insertionPoint = doc.getElementsByTagName("head")[0] || doc.documentElement;

  if (!insertionPoint)
    return;

  var script = doc.createElementNS("http://www.w3.org/1999/xhtml", "script");
  script.setAttribute("id", "fuzz1");
  script.setAttribute("type", "text/javascript");
  script.textContent = scriptToInject;
  insertionPoint.appendChild(script);
}

})();<commit_msg>Improve GC testing<commit_after>"use strict";

// Separate scope to work around bug 673569
(function() {

const Cu = Components.utils;
const Cc = Components.classes;
const Ci = Components.interfaces;

function dumpln(s) { dump(s + "\n"); }

// content script for e10s support

// This is a frame script, so it may be running in a content process.
// In any event, it is targeted at a specific "tab", so we listen for
// the DOMWindowCreated event to be notified about content windows
// being created in this context.

function DOMFuzzHelperManager() {
  addEventListener("DOMWindowCreated", this, false);
}

DOMFuzzHelperManager.prototype = {
  handleEvent: function handleEvent(aEvent) {
    var window = aEvent.target.defaultView;
    window.wrappedJSObject.fuzzPriv = makeDOMFuzzHelper(window);
    window.addEventListener("load", maybeInjectScript, false);
  }
};

var domfuzzhelpermanager = new DOMFuzzHelperManager();

/*****************************
 * FUZZPRIV OBJECT INJECTION *
 *****************************/

// Create deeply fresh objects so windows don't influence each other.

function makeDOMFuzzHelper(aWindow) {
  dumpln("DOMFuzzHelper created");

  return {
      toString: function() { return "[DOMFuzzHelper]"; },

      quitApplication: function() {
        sendAsyncMessage('DOMFuzzHelper.quitApplication', {});
      },

      quitApplicationSoon: function() {
        sendAsyncMessage('DOMFuzzHelper.quitApplicationSoon', {});
      },

      closeTabThenQuit: function () {
        // Somehow async messages get lost in close().
        sendSyncMessage('DOMFuzzHelper.quitApplicationSoon', {});

        // This frame-script stops running immediately after close().
        content.close();
      },

      quitWithLeakCheck: function () {
        sendAsyncMessage('DOMFuzzHelper.quitWithLeakCheck', {});
      },

      setGCZeal: function(zeal) {
        sendSyncMessage("DOMFuzzHelper.setGCZeal", {'zeal' : zeal});
      },

      runSoon: runSoon.bind(this),

      enableAccessibility: enableAccessibility.bind(this),

      GC: function() { Cu.forceGC(); },

      CC: cycleCollect(aWindow),

      MP: sendMemoryPressureNotification.bind(this),

      forceShrinkingGC: function() { Cu.forceShrinkingGC(); },

      schedulePreciseGC: function() { Cu.schedulePreciseGC(function() { dumpln("precise GC complete"); }); },

      schedulePreciseShrinkingGC: function() { Cu.schedulePreciseShrinkingGC(function() { dumpln("precise shrinking GC complete"); }); },

      fontList: fontList.bind(this),

      reftestList: reftestList.bind(this),

      printToFile: printToFile(aWindow),

      openAboutMemory: function() {
        sendAsyncMessage('DOMFuzzHelper.openAboutMemory', {});
      },

      cssPropertyDatabase: cssPropertyDatabase.bind(this),

      comparePixels: comparePixels(aWindow),

      __exposedProps__: {
        'toString': 'r',
        'quitApplication': 'r',
        'quitApplicationSoon': 'r',
        'closeTabThenQuit': 'r',
        'quitWithLeakCheck': 'r',
        'setGCZeal': 'r',
        'runSoon': 'r',
        'enableAccessibility': 'r',
        'GC': 'r',
        'CC': 'r',
        'MP': 'r',
        'forceShrinkingGC': 'r',
        'schedulePreciseGC': 'r',
        'schedulePreciseShrinkingGC': 'r',
        'fontList': 'r',
        'printToFile': 'r',
        'openAboutMemory': 'r',
        'reftestList': 'r',
        'cssPropertyDatabase': 'r',
        'comparePixels': 'r'
      }
  };
};

/***********************************************
 * MISC PRIVILEGED FUNCTIONS - CONTENT PROCESS *
 ***********************************************/

function runSoon(f)
{
  var tm = Cc["@mozilla.org/thread-manager;1"]
             .getService(Ci.nsIThreadManager);

  tm.mainThread.dispatch({
    run: function() {
      f();
    }
  }, Ci.nsIThread.DISPATCH_NORMAL);
}

function enableAccessibility()
{
  try {
    Components.classes["@mozilla.org/accessibilityService;1"]
      .getService(Components.interfaces.nsIAccessibleRetrieval);
    dump("Enabled accessibility!\n");
  } catch(e) {
    dump("Couldn't enable accessibility: " + e + "\n");
  }
}

function sendMemoryPressureNotification()
{
  var os = Components.classes["@mozilla.org/observer-service;1"]
           .getService(Components.interfaces.nsIObserverService);
  os.notifyObservers(null, "memory-pressure", "heap-minimize");
}

function cycleCollect(window)
{
  return function cycleCollectInner() {
    window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
          .getInterface(Components.interfaces.nsIDOMWindowUtils)
          .cycleCollect();
  }
}

function comparePixels(aWindow)
{
  return function comparePixels2() {
    var w = aWindow.innerWidth;
    var h = aWindow.innerHeight;
    dumpln(w + " x " + h);

    var canvas1 = aWindow.document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
    canvas1.setAttribute("width", w);
    canvas1.setAttribute("height", h);

    var canvas2 = aWindow.document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
    canvas2.setAttribute("width", w);
    canvas2.setAttribute("height", h);

    function drawInto(canvas)
    {
      var ctx = canvas.getContext("2d");
      ctx.drawWindow(aWindow,
                     aWindow.scrollX,
                     aWindow.scrollY,
                     w,
                     h,
                     "rgb(255,255,255)",
                     ctx.DRAWWINDOW_DRAW_CARET |
                     ctx.DRAWWINDOW_USE_WIDGET_LAYERS);
    }

    drawInto(canvas1);
    return function comparePixels3() {
      drawInto(canvas2);
      var wu = aWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
      var o = {};
      var n = wu.compareCanvases(canvas1, canvas2, o);
      if (n == 0) { return ""; }
      return (
        n + " pixel" + (n == 1 ? "" : "s") + " differ (max channel difference: " + o.value + ")\n" +
        "Before:\n" + canvas1.toDataURL() + "\n" +
        "After:\n" + canvas2.toDataURL() + "\n"
      );
    }
  }
}

/*
function setZoomLevel(window)
{
  return function setZoomLevelInner(textOrFull, factor) {
    var viewer = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
                       .getInterface(Components.interfaces.nsIWebNavigation)
                       .QueryInterface(Components.interfaces.nsIDocShell)
                       .contentViewer
                       .QueryInterface(Components.interfaces.nsIMarkupDocumentViewer);

    if (textOrFull == "text")
      viewer.textZoom = +factor;
    else if (textOrFull == "full")
      viewer.fullZoom = +factor;
  }
}
*/

function printToFile(window)
{
  // Oddly asynchronous, at least on Linux.

  // Linux: works for PDF and PS.
  // Windows: works for PDF at least. Text may be invisible (bug 653336).
  // Mac: tested, printToFile is ignored and it goes to a printer!
  var xulRuntime = Components.classes["@mozilla.org/xre/app-info;1"]
                             .getService(Components.interfaces.nsIXULRuntime);
  if (xulRuntime.OS != "Linux" && xulRuntime.OS != "WINNT") return function() { };

  var fired = false;

  return function printToFileInner(showHeaders, showBGColor, showBGImages, ps) {
    runSoon(function() {
        // Don't print more than once, it gets messy fast.
        if (fired) { return false; }
        fired = true;

        ps = ps && xulRuntime.OS != "WINNT"; // Windows gets confused when trying to print to ps, and tosses up a *.xps filepicker outside the Firefox process!?

        // Based on https://addons.mozilla.org/en-US/firefox/addon/5971/ by pavlov (Stuart Parmenter) and bho

        var webBrowserPrint = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
        .getInterface(Components.interfaces.nsIWebBrowserPrint);

        var nsIPrintSettings = Components.interfaces.nsIPrintSettings;

        var PSSVC = Components.classes["@mozilla.org/gfx/printsettings-service;1"]
        .getService(Components.interfaces.nsIPrintSettingsService);

        var printSettings = PSSVC.newPrintSettings;

        var file = profileDirectory();
        file.append(ps ? "fuzzout.ps" : "fuzzout.pdf");
        dumpln("Printing to: " + file.path);

        printSettings.printToFile = true;
        printSettings.toFileName  = file.path;
        printSettings.printSilent = true;
        printSettings.outputFormat = ps ? nsIPrintSettings.kOutputFormatPS : nsIPrintSettings.kOutputFormatPDF;
        printSettings.printBGColors   = !!showBGColor;
        printSettings.printBGImages   = !!showBGImages;
        if (!showHeaders) {
            printSettings.footerStrCenter = '';
            printSettings.footerStrLeft   = '';
            printSettings.footerStrRight  = '';
            printSettings.headerStrCenter = '';
            printSettings.headerStrLeft   = '';
            printSettings.headerStrRight  = '';
        }

        webBrowserPrint.print(printSettings, null);
    });
  }
}

function cycleCollect()
{
  return function cycleCollectInner() {
      try {
        content.QueryInterface(Ci.nsIInterfaceRequestor)
              .getInterface(Ci.nsIDOMWindowUtils)
              .cycleCollect();
      }

      catch(e) {
        dumpln("cycle collect failed " + e);
      }
  }
}

function fontList()
{
    return Components.classes["@mozilla.org/gfx/fontenumerator;1"]
            .createInstance(Components.interfaces.nsIFontEnumerator)
            .EnumerateAllFonts({})
            .join("\n");
}

function reftestList()
{
  var dir = extensionLocation().parent;
  dir.append("automation");
  return readFile(indir(dir, "urls-reftests"));
}

function cssPropertyDatabase()
{
  var fn = sendSyncMessage('DOMFuzzHelper.getBinDirectory', {})[0];
  var f = Components.classes["@mozilla.org/file/local;1"]
                    .createInstance(Components.interfaces.nsILocalFile);
  f.initWithPath(fn);
  while (f.leafName != "dist") {
    f = f.parent;
  }
  f = f.parent;
  f.append("tests");
  f.append("reftest");
  f.append("tests");
  f.append("layout");
  f.append("style");
  f.append("test");
  f.append("property_database.js");
  return readFile(f);
}

/**********************
 * FILESYSTEM HELPERS *
 **********************/

function profileDirectory()
{
  var fn = sendSyncMessage('DOMFuzzHelper.getProfileDirectory', {})[0];
  var d = Components.classes["@mozilla.org/file/local;1"]
                    .createInstance(Components.interfaces.nsILocalFile);
  d.initWithPath(fn);
  return d;
}

function extensionLocation()
{
  var d = profileDirectory();
  d.append("extensions");
  d.append("domfuzz@squarefree.com");

  var extensionLocation = readFile(d).replace(/\s*$/, "");

  var f = Components.classes["@mozilla.org/file/local;1"]
                    .createInstance(Components.interfaces.nsILocalFile);
  f.initWithPath(extensionLocation);
  return f;
}

// readFile function from logan
// http://www.gozer.org/mozilla/userChrome.js/scripts/userScripts.uc.js
// |file| must be an nsIFile.
// Returns the contents of the file as a string.
function readFile(file)
{
  var content = '';

  var stream = Components.classes['@mozilla.org/network/file-input-stream;1']
                    .createInstance(Components.interfaces.nsIFileInputStream);
  stream.init(file, 0x01, 0, 0);

  var script = Components.classes['@mozilla.org/scriptableinputstream;1']
              .createInstance(Components.interfaces.nsIScriptableInputStream);
  script.init(stream);

  if (stream.available()) {
    var data = script.read(4096);

    while (data.length > 0) {
      content += data;
      data = script.read(4096);
    }
  }

  stream.close();
  script.close();

  return content;
}

function indir(dir, filename)
{
  var d = dir.clone();
  d.append(filename);
  return d;
}

/*************************
 * FUZZ SCRIPT INJECTION *
 *************************/

function maybeInjectScript(event)
{
  var doc = event.originalTarget;
  if (doc.nodeName != "#document")
    return;

  var hash = doc.location.hash;

  var r = hash.split(",");

  if (r[0] != "#squarefree-af") {
    return;
  }
  if (!(/^[a-zA-Z0-9\-.]*$/.test(r[1]))) {
    dump("Sketchy fuzzer filename!\n");
    return;
  }

  var dir = extensionLocation().parent;
  dir.append("fuzzers");

  var scriptToInject =
    readFile(indir(dir, "fuzz.js")) + "\n"
  + readFile(indir(dir, r[1])) + "\n"
  + readFile(indir(dir, "fuzz-finish-auto.js")) + "\n"
  + "document.getElementById('fuzz1').parentNode.removeChild(document.getElementById('fuzz1'));\n"
  + "fuzzSettings = [" + r.slice(2).join(",") + "];\n"
  + "setTimeout(fuzzOnload, 400);\n";

  var insertionPoint = doc.getElementsByTagName("head")[0] || doc.documentElement;

  if (!insertionPoint)
    return;

  var script = doc.createElementNS("http://www.w3.org/1999/xhtml", "script");
  script.setAttribute("id", "fuzz1");
  script.setAttribute("type", "text/javascript");
  script.textContent = scriptToInject;
  insertionPoint.appendChild(script);
}

})();<|endoftext|>


<commit_before>#pragma strict

var explosion : Transform ;

function Update () {

  transform.position.x += 0.1 ;
  transform.Rotate(1 , 1 , 1) ;

  if(transform.position.x > 19.4)
  {
    Destroy(gameObject) ;
  }
}

var SE : AudioClip ;

function OnCollisionEnter () {
  Instantiate(explosion , transform.position , transform.rotation) ;
  if((col.gameObject.CompareTag('Bolt'))
  {
    Destroy(gameObject) ;
  }
  AudioSource.PlayClipAtPoint(SE , transform.position) ;
}
<commit_msg>Update Enemy_Script_Left.js<commit_after>#pragma strict

var explosion : Transform ;

function Update () {

  transform.position.x += 0.1 ;
  transform.Rotate(1 , 1 , 1) ;

  if(transform.position.x > 19.4)
  {
    Destroy(gameObject) ;
  }
}

var SE : AudioClip ;

function OnCollisionEnter () {
  if((col.gameObject.CompareTag('Bolt'))
  {
    Instantiate(explosion , transform.position , transform.rotation) ;
    Destroy(gameObject) ;
    AudioSource.PlayClipAtPoint(SE , transform.position) ;
  }
}
<|endoftext|>


<commit_before>// Load modules

var Events = require('events');
var Hoek = require('hoek');
var Wreck = require('wreck');

// Declare internals

var internals = {
    headers: {
        'Content-Type': 'application/json',
        'Accept': 'application/json'
    }
};

module.exports = internals.Commander = function (url) {

    Hoek.assert(this.constructor === internals.Commander, 'must be constructed with new');
    Hoek.assert(url, 'URL parameter is required');

    Events.EventEmitter.call(this);

    this._url = url;
    this._poll();
};

Hoek.inherits(internals.Commander, Events.EventEmitter);

internals.Commander.prototype.registerRadio = function (callback) {

    Wreck.post(this._url + '/radio', { headers: internals.headers }, function (err, res, payload) {

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

        return callback(null, payload.id || payload.radioId);
    });
};

internals.Commander.prototype.updateRadio = function (radioId, data, callback) {

    var stringified = JSON.stringify(data);
    Wreck.put(this._url + '/radio/' + radioId, { payload: stringified, headers: internals.headers }, function (err, res, payload) {

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

        return callback(null, payload);
    });
};

internals.Commander.prototype.updateSensor = function (radioId, sensorId, data, callback) {

    var stringified = JSON.stringify(data);
    Wreck.put(this._url + '/radio/' + radioId + '/sensor/' + sensorId, { payload: stringified, headers: internals.headers }, function (err, res, payload) {

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

        return callback(null, payload);
    });
};

internals.Commander.prototype.createReading = function (radioId, sensorId, data, callback) {

    var stringified = JSON.stringify(data);
    Wreck.post(this._url + '/radio/' + radioId + '/sensor/' + sensorId + '/reading', { payload: stringified, headers: internals.headers }, function (err, res, payload) {

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

        return callback(null, payload);
    });
};

internals.Commander.prototype.log = function (message, callback) {

    var stringified = JSON.stringify(message);
    Wreck.post(this._url + '/log', { payload: stringified, headers: internals.headers }, function (err, res, payload) {

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

        return callback(null, payload);
    });
};

internals.Commander.prototype._checkForCommand = function (callback) {

    Wreck.get(this._url + '/command', { headers: internals.headers }, function (err, res, payload) {

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

        if (res.statusCode !== 200) {
            return callback();
        }

        var command = payload;
        if (payload && typeof payload === 'string') {
            try {
                command = JSON.parse(payload);
            }
            catch (err) {
                return callback();
            }
        }

        if (command instanceof Error) {
            return callback(command);
        }

        return callback(null, (!command || command.length === 0) ? null : command);
    });
};

internals.Commander.prototype._poll = function () {

    var self = this;

    setTimeout(function () {

        self._checkForCommand(function (err, command) {

            if (err) {
                self.emit('error', err);
            }
            else if (command) {
                self.emit('command', command);
            }

            self._poll();
        });
    }, 5000);
};<commit_msg>Fixing commands<commit_after>// Load modules

var Events = require('events');
var Hoek = require('hoek');
var Wreck = require('wreck');

// Declare internals

var internals = {
    headers: {
        'Content-Type': 'application/json',
        'Accept': 'application/json'
    }
};

module.exports = internals.Commander = function (url) {

    Hoek.assert(this.constructor === internals.Commander, 'must be constructed with new');
    Hoek.assert(url, 'URL parameter is required');

    Events.EventEmitter.call(this);

    this._url = url;
    this._poll();
};

Hoek.inherits(internals.Commander, Events.EventEmitter);

internals.Commander.prototype.registerRadio = function (callback) {

    Wreck.post(this._url + '/radio', { headers: internals.headers }, function (err, res, payload) {

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

        return callback(null, payload.id || payload.radioId);
    });
};

internals.Commander.prototype.updateRadio = function (radioId, data, callback) {

    var stringified = JSON.stringify(data);
    Wreck.put(this._url + '/radio/' + radioId, { payload: stringified, headers: internals.headers }, function (err, res, payload) {

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

        return callback(null, payload);
    });
};

internals.Commander.prototype.updateSensor = function (radioId, sensorId, data, callback) {

    var stringified = JSON.stringify(data);
    Wreck.put(this._url + '/radio/' + radioId + '/sensor/' + sensorId, { payload: stringified, headers: internals.headers }, function (err, res, payload) {

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

        return callback(null, payload);
    });
};

internals.Commander.prototype.createReading = function (radioId, sensorId, data, callback) {

    var stringified = JSON.stringify(data);
    Wreck.post(this._url + '/radio/' + radioId + '/sensor/' + sensorId + '/reading', { payload: stringified, headers: internals.headers }, function (err, res, payload) {

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

        return callback(null, payload);
    });
};

internals.Commander.prototype.log = function (message, callback) {

    var stringified = JSON.stringify(message);
    Wreck.post(this._url + '/log', { payload: stringified, headers: internals.headers }, function (err, res, payload) {

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

        return callback(null, payload);
    });
};

internals.Commander.prototype._checkForCommand = function (callback) {

    Wreck.get(this._url + '/command', { headers: internals.headers }, function (err, res, payload) {

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

        if (res.statusCode !== 200) {
            return callback();
        }

        var command = payload;
        if (payload && typeof payload === 'string') {
            try {
                command = JSON.parse(payload);
            }
            catch (err) {
                return callback();
            }
        }

        if (command instanceof Error) {
            return callback(command);
        }

        return callback(null, (!command || command.length === 0) ? null : command);
    });
};

internals.Commander.prototype._poll = function () {

    var self = this;

    setTimeout(function () {

        self._checkForCommand(function (err, command) {

            if (err) {
                self.emit('error', err);
            }
            else if (command && Object.keys(command).length) {
                self.emit('command', command);
            }

            self._poll();
        });
    }, 5000);
};<|endoftext|>


<commit_before>var fs = require('fs')

var pkg = JSON.parse(fs.readFileSync(__dirname + '/../package.json').toString())

exports.VERSION = pkg.version

exports.DEFAULT_PORT = process.env.PORT || 9876
exports.DEFAULT_HOSTNAME = process.env.IP || 'localhost'

// log levels
exports.LOG_DISABLE = 'OFF'
exports.LOG_ERROR = 'ERROR'
exports.LOG_WARN = 'WARN'
exports.LOG_INFO = 'INFO'
exports.LOG_DEBUG = 'DEBUG'

// Default patterns for the pattern layout.
exports.COLOR_PATTERN = '%[%p [%c]: %]%m'
exports.NO_COLOR_PATTERN = '%p [%c]: %m'

// Default console appender
exports.CONSOLE_APPENDER = {
  type: 'console',
  layout: {
    type: 'pattern',
    pattern: exports.COLOR_PATTERN
  }
}

exports.EXIT_CODE = '\x1FEXIT'
<commit_msg>feat(logger): Add date/time stamp to log output<commit_after>var fs = require('fs')

var pkg = JSON.parse(fs.readFileSync(__dirname + '/../package.json').toString())

exports.VERSION = pkg.version

exports.DEFAULT_PORT = process.env.PORT || 9876
exports.DEFAULT_HOSTNAME = process.env.IP || 'localhost'

// log levels
exports.LOG_DISABLE = 'OFF'
exports.LOG_ERROR = 'ERROR'
exports.LOG_WARN = 'WARN'
exports.LOG_INFO = 'INFO'
exports.LOG_DEBUG = 'DEBUG'

// Default patterns for the pattern layout.
exports.COLOR_PATTERN = '%[%d{DATE}:%p [%c]: %]%m'
exports.NO_COLOR_PATTERN = '%d{DATE}:%p [%c]: %m'

// Default console appender
exports.CONSOLE_APPENDER = {
  type: 'console',
  layout: {
    type: 'pattern',
    pattern: exports.COLOR_PATTERN
  }
}

exports.EXIT_CODE = '\x1FEXIT'
<|endoftext|>


<commit_before>const Dog = require('./dog');

const toby = new Dog('Toby')

console.log(toby.bark());
<commit_msg>Adding missing semicolon.<commit_after>const Dog = require('./dog');

const toby = new Dog('Toby');

console.log(toby.bark());
<|endoftext|>


<commit_before>'use strict';

import chai from 'chai';
import {DI} from '../lib.compiled/DI';
import Bottle from 'bottlejs';
import {MissingServiceException} from '../lib.compiled/Exception/MissingServiceException';
import Core from 'deep-core';

class FactoryClass {
  constructor() {
    this.name = 'FactoryClass';
  }
}

class ServiceClass {
  constructor() {
    this.name = 'ServiceClass';
  }
}

suite('DI', function() {
  let di = new DI();

  test('Class DI exists in DI', function() {
    chai.expect(typeof DI).to.equal('function');
  });

  test('Check constructor sets _bottle', function() {
    chai.assert.instanceOf(di._bottle, Bottle, 'this._bottle is an instance of Bottle');
  });

  test('Check get method throws "MissingServiceException" exception for invalid service or parameter', function() {
    let error = null;
    try {
      di.get('invalidValue');
    } catch (e) {
      error = e;
    }

    chai.expect(error).to.be.not.equal(null);
    chai.expect(error).to.be.an.instanceof(MissingServiceException);
  });

  test('Check addService method throws "Core.Exception.InvalidArgumentException" exception for invalid service', function() {
    let error = null;
    try {
      di.addService('serviceName', 'invalidService');
    } catch (e) {
      error = e;
    }

    chai.expect(error).to.be.not.equal(null);
    chai.expect(error).to.be.an.instanceof(Core.Exception.InvalidArgumentException);
  });

  test('Check addService method adds an instantiated service into container', function() {
    let service = {
      name: 'serviceName',
      value: {
        data: 'testServiceObject',
      },
    };
    di.addService(service.name, service.value);
    chai.expect(di.get(service.name)).to.be.eql(service.value);
  });

  test('Check addParameter method adds a parameter into container', function() {
    let parameter = {
      name: 'parameterName',
      value: 'parameterValue',
    };
    di.addParameter(parameter.name, parameter.value);
  });

  test('Check register method registers a service to container', function() {
    let dependencies = ['dep1', 'dep2', 'dep3'];
    chai.expect(di.register('testServiceWithDeps', ServiceClass, dependencies)).
      to.be.equal(undefined);
  });

  test('Check factory method creates a service', function() {
    chai.expect(di.factory('testService', FactoryClass)).to.be.equal(undefined);
  });
});<commit_msg>Refactor factory/register unit tests<commit_after>'use strict';

import chai from 'chai';
import {DI} from '../lib.compiled/DI';
import Bottle from 'bottlejs';
import {MissingServiceException} from '../lib.compiled/Exception/MissingServiceException';
import Core from 'deep-core';

class FactoryClass {
  constructor() {
    this.name = 'FactoryClass';
  }
}

class ServiceClass {
  constructor(firstDependencyArg, secondDependencyArg, thirdDependencyArg) {
    this.name = 'ServiceClass';
  }
}

function factoryFunction() {
  return new FactoryClass();
}

suite('DI', function() {
  let di = new DI();

  test('Class DI exists in DI', function() {
    chai.expect(typeof DI).to.equal('function');
  });

  test('Check constructor sets _bottle', function() {
    chai.assert.instanceOf(di._bottle, Bottle, 'this._bottle is an instance of Bottle');
  });

  test('Check get method throws "MissingServiceException" exception for invalid service or parameter', function() {
    let error = null;
    try {
      di.get('invalidValue');
    } catch (e) {
      error = e;
    }

    chai.expect(error).to.be.not.equal(null);
    chai.expect(error).to.be.an.instanceof(MissingServiceException);
  });

  test('Check addService method throws "Core.Exception.InvalidArgumentException" exception for invalid service', function() {
    let error = null;
    try {
      di.addService('serviceName', 'invalidService');
    } catch (e) {
      error = e;
    }

    chai.expect(error).to.be.not.equal(null);
    chai.expect(error).to.be.an.instanceof(Core.Exception.InvalidArgumentException);
  });

  test('Check addService method adds an instantiated service into container', function() {
    let service = {
      name: 'serviceName',
      value: {
        data: 'testServiceObject',
      },
    };
    di.addService(service.name, service.value);
    chai.expect(di.get(service.name)).to.be.eql(service.value);
  });

  test('Check addParameter method adds a parameter into container', function() {
    let parameter = {
      name: 'parameterName',
      value: 'parameterValue',
    };
    di.addParameter(parameter.name, parameter.value);
  });

  test('Check register method registers a service to container', function() {
    let expectedResult = new ServiceClass('dep1', 'dep2', 'dep3');
    chai.expect(di.register('testServiceWithDeps', ServiceClass, ['dep1', 'dep2', 'dep3'])).
      to.be.equal(undefined);
    let actualResult = di.get('testServiceWithDeps');
    chai.expect(actualResult).to.be.eql(expectedResult);
    chai.assert.instanceOf(actualResult, ServiceClass, 'result is an instance of ServiceClass');
  });

  test('Check factory method creates a service', function() {
    let expectedResult = factoryFunction();
    chai.expect(di.factory('testFactory', factoryFunction)).to.be.equal(undefined);
    let actualResult = di.get('testFactory');
    chai.expect(actualResult).to.be.eql(expectedResult);
    chai.assert.instanceOf(actualResult, FactoryClass, 'result is an instance of FactoryClass');
  });
});<|endoftext|>


<commit_before>import path from 'path'
import fs from 'fs'
import glob from 'glob'
import _ from 'lodash'
import Promise from 'bluebird'
import EventEmitter2 from 'eventemitter2'
import mkdirp from 'mkdirp'

export default class FlowProvider extends EventEmitter2 {
  constructor({ logger, botfile, projectLocation }) {
    super({
      wildcard: true,
      maxListeners: 100
    })

    this.logger = logger
    this.botfile = botfile
    this.projectLocation = projectLocation
  }

  async loadAll() {
    const relDir = this.botfile.flowsDir || './flows'
    const flowsDir = path.resolve(this.projectLocation, relDir)

    if (!fs.existsSync(flowsDir)) {
      return []
    }

    const searchOptions = { cwd: flowsDir }

    const flowFiles = await Promise.fromCallback(callback => glob('**/*.flow.json', searchOptions, callback))

    const flows = []

    flowFiles.forEach(file => {
      const filePath = path.resolve(flowsDir, './' + file)
      const flow = JSON.parse(fs.readFileSync(filePath))

      flow.name = file // e.g. 'login.flow.json' or 'shapes/circle.flow.json'

      const schemaError = this._validateSchema(flow)
      if (schemaError) {
        return this.logger.warn(schemaError)
      }

      const uiEqPath = path.resolve(flowsDir, './' + file.replace(/\.flow/g, '.ui'))
      let uiEq = {}

      if (fs.existsSync(uiEqPath)) {
        uiEq = JSON.parse(fs.readFileSync(uiEqPath))
      }

      Object.assign(flow, { links: uiEq.links })

      // Take position from UI files or create default position
      const unplacedNodes = []
      flow.nodes.forEach(node => {
        const uiNode = _.find(uiEq.nodes, { id: node.id }) || {}

        Object.assign(node, uiNode.position)

        if (_.isNil(node.x) || _.isNil(node.y)) {
          unplacedNodes.push(node)
        }
      })

      const unplacedY = (_.maxBy(flow.nodes, 'y') || { y: 0 }).y + 250
      let unplacedX = 50

      unplacedNodes.forEach(node => {
        node.y = unplacedY
        node.x = unplacedX
        unplacedX += 250
      })

      return flows.push({
        location: file,
        version: flow.version,
        name: flow.name,
        nodes: _.filter(flow.nodes, node => !!node),
        catchAll: flow.catchAll,
        startNode: flow.startNode,
        links: flow.links
      })
    })

    return flows
  }

  async saveFlows(flows) {
    const flowsToSave = await Promise.mapSeries(flows, flow => this._prepareSaveFlow(flow))

    for (let { flowPath, uiPath, flowContent, uiContent } of flowsToSave) {
      if (flowPath.includes('/')) {
        mkdirp.sync(path.dirname(flowPath))
      }

      fs.writeFileSync(flowPath, JSON.stringify(flowContent, null, 2))
      fs.writeFileSync(uiPath, JSON.stringify(uiContent, null, 2))
    }

    const flowsDir = path.resolve(this.projectLocation, this.botfile.flowsDir || './flows')

    const searchOptions = { cwd: flowsDir }
    const flowFiles = await Promise.fromCallback(callback => glob('**/*.flow.json', searchOptions, callback))

    flowFiles
      .map(fileName => path.resolve(flowsDir, './' + fileName))
      .filter(filePath => !flowsToSave.find(flow => flow.flowPath === filePath || flow.uiPath === filePath))
      .map(filePath => fs.unlinkSync(filePath))

    this.emit('flowsChanged')
  }

  async _prepareSaveFlow(flow) {
    flow = Object.assign({}, flow, {
      version: '0.1'
    })

    const schemaError = this._validateSchema(flow)
    if (schemaError) {
      throw new Error(schemaError)
    }

    const uiContent = {
      nodes: flow.nodes.map(node => ({
        id: node.id,
        position: node.position
      })),
      links: flow.links
    }

    const flowContent = {
      version: flow.version,
      startNode: flow.startNode,
      catchAll: flow.catchAll,
      nodes: flow.nodes
    }

    flowContent.nodes.forEach(node => delete node['position'])

    const relDir = this.botfile.flowsDir || './flows'
    const flowPath = path.resolve(this.projectLocation, relDir, './' + flow.location)
    const uiPath = flowPath.replace(/\.flow\.json/i, '.ui.json')

    return { flowPath, uiPath, flowContent, uiContent }
  }

  _validateSchema(flow) {
    const errorPrefix = `[Flow] Error loading "${flow.location}"`

    if (!flow || !_.isObjectLike(flow)) {
      return errorPrefix + ', invalid JSON flow schema'
    }

    if (!flow.version || !_.isString(flow.version)) {
      return errorPrefix + ', expected valid version but found none'
    }

    if (!flow.version.startsWith('0.')) {
      return errorPrefix + ', unsupported `version` of the schema "' + flow.version + '"'
    }

    if (!_.isString(flow.startNode)) {
      return errorPrefix + ', expected valid `startNode`'
    }

    if (!_.isArray(flow.nodes)) {
      return errorPrefix + ', expected `nodes` to be an array of nodes'
    }

    if (!_.find(flow.nodes, { name: flow.startNode })) {
      return errorPrefix + ', expected `startNode` to point to an existing flow node'
    }

    if (flow.catchAll) {
      if (flow.catchAll.onEnter) {
        return errorPrefix + ', catchAll does not support "onEnter"'
      }

      if (flow.catchAll.onReceive) {
        if (_.isString(flow.catchAll.onReceive)) {
          flow.catchAll.onReceive = [flow.catchAll.onReceive]
        }
      }

      if (flow.catchAll.next) {
        if (_.isString(flow.catchAll.next)) {
          flow.catchAll.next = [flow.catchAll.next]
        }
      }
    }

    const errs =
      flow.nodes &&
      flow.nodes.map(node => {
        // TODO Better node validation

        // TODO Validate that connections are valid
        // TODO Validate that conditions are valid

        if (!_.isString(node.id) || node.id.length <= 3) {
          return errorPrefix + ', expected all nodes to have a valid id'
        }

        if (_.isString(node.onEnter)) {
          node.onEnter = [node.onEnter]
        }

        if (_.isString(node.onReceive)) {
          node.onReceive = [node.onReceive]
        }

        if (_.isString(node.next)) {
          node.next = [node.next]
        }
      })

    return _.first(errs, e => !!e)
  }
}
<commit_msg>Removed "x", "y" and "lastModified" properties from the .flow.json files<commit_after>import path from 'path'
import fs from 'fs'
import glob from 'glob'
import _ from 'lodash'
import Promise from 'bluebird'
import EventEmitter2 from 'eventemitter2'
import mkdirp from 'mkdirp'

export default class FlowProvider extends EventEmitter2 {
  constructor({ logger, botfile, projectLocation }) {
    super({
      wildcard: true,
      maxListeners: 100
    })

    this.logger = logger
    this.botfile = botfile
    this.projectLocation = projectLocation
  }

  async loadAll() {
    const relDir = this.botfile.flowsDir || './flows'
    const flowsDir = path.resolve(this.projectLocation, relDir)

    if (!fs.existsSync(flowsDir)) {
      return []
    }

    const searchOptions = { cwd: flowsDir }

    const flowFiles = await Promise.fromCallback(callback => glob('**/*.flow.json', searchOptions, callback))

    const flows = []

    flowFiles.forEach(file => {
      const filePath = path.resolve(flowsDir, './' + file)
      const flow = JSON.parse(fs.readFileSync(filePath))

      flow.name = file // e.g. 'login.flow.json' or 'shapes/circle.flow.json'

      const schemaError = this._validateSchema(flow)
      if (schemaError) {
        return this.logger.warn(schemaError)
      }

      const uiEqPath = path.resolve(flowsDir, './' + file.replace(/\.flow/g, '.ui'))
      let uiEq = {}

      if (fs.existsSync(uiEqPath)) {
        uiEq = JSON.parse(fs.readFileSync(uiEqPath))
      }

      Object.assign(flow, { links: uiEq.links })

      // Take position from UI files or create default position
      const unplacedNodes = []
      flow.nodes.forEach(node => {
        const uiNode = _.find(uiEq.nodes, { id: node.id }) || {}

        Object.assign(node, uiNode.position)

        if (_.isNil(node.x) || _.isNil(node.y)) {
          unplacedNodes.push(node)
        }
      })

      const unplacedY = (_.maxBy(flow.nodes, 'y') || { y: 0 }).y + 250
      let unplacedX = 50

      unplacedNodes.forEach(node => {
        node.y = unplacedY
        node.x = unplacedX
        unplacedX += 250
      })

      return flows.push({
        location: file,
        version: flow.version,
        name: flow.name,
        nodes: _.filter(flow.nodes, node => !!node),
        catchAll: flow.catchAll,
        startNode: flow.startNode,
        links: flow.links
      })
    })

    return flows
  }

  async saveFlows(flows) {
    const flowsToSave = await Promise.mapSeries(flows, flow => this._prepareSaveFlow(flow))

    for (let { flowPath, uiPath, flowContent, uiContent } of flowsToSave) {
      if (flowPath.includes('/')) {
        mkdirp.sync(path.dirname(flowPath))
      }

      fs.writeFileSync(flowPath, JSON.stringify(flowContent, null, 2))
      fs.writeFileSync(uiPath, JSON.stringify(uiContent, null, 2))
    }

    const flowsDir = path.resolve(this.projectLocation, this.botfile.flowsDir || './flows')

    const searchOptions = { cwd: flowsDir }
    const flowFiles = await Promise.fromCallback(callback => glob('**/*.flow.json', searchOptions, callback))

    flowFiles
      .map(fileName => path.resolve(flowsDir, './' + fileName))
      .filter(filePath => !flowsToSave.find(flow => flow.flowPath === filePath || flow.uiPath === filePath))
      .map(filePath => fs.unlinkSync(filePath))

    this.emit('flowsChanged')
  }

  async _prepareSaveFlow(flow) {
    flow = Object.assign({}, flow, {
      version: '0.1'
    })

    const schemaError = this._validateSchema(flow)
    if (schemaError) {
      throw new Error(schemaError)
    }

    // What goes in the ui.json file
    const uiContent = {
      nodes: flow.nodes.map(node => ({
        id: node.id,
        position: { x: node.x, y: node.y }
      })),
      links: flow.links
    }

    // What goes in the .flow.json file
    const flowContent = {
      version: flow.version,
      startNode: flow.startNode,
      catchAll: flow.catchAll,
      nodes: flow.nodes
    }

    flowContent.nodes.forEach(node => {
      // We remove properties that don't belong in the .flow.json file
      delete node['x']
      delete node['y']
      delete node['lastModified']
    })

    const relDir = this.botfile.flowsDir || './flows'
    const flowPath = path.resolve(this.projectLocation, relDir, './' + flow.location)
    const uiPath = flowPath.replace(/\.flow\.json/i, '.ui.json')

    return { flowPath, uiPath, flowContent, uiContent }
  }

  _validateSchema(flow) {
    const errorPrefix = `[Flow] Error loading "${flow.location}"`

    if (!flow || !_.isObjectLike(flow)) {
      return errorPrefix + ', invalid JSON flow schema'
    }

    if (!flow.version || !_.isString(flow.version)) {
      return errorPrefix + ', expected valid version but found none'
    }

    if (!flow.version.startsWith('0.')) {
      return errorPrefix + ', unsupported `version` of the schema "' + flow.version + '"'
    }

    if (!_.isString(flow.startNode)) {
      return errorPrefix + ', expected valid `startNode`'
    }

    if (!_.isArray(flow.nodes)) {
      return errorPrefix + ', expected `nodes` to be an array of nodes'
    }

    if (!_.find(flow.nodes, { name: flow.startNode })) {
      return errorPrefix + ', expected `startNode` to point to an existing flow node'
    }

    if (flow.catchAll) {
      if (flow.catchAll.onEnter) {
        return errorPrefix + ', catchAll does not support "onEnter"'
      }

      if (flow.catchAll.onReceive) {
        if (_.isString(flow.catchAll.onReceive)) {
          flow.catchAll.onReceive = [flow.catchAll.onReceive]
        }
      }

      if (flow.catchAll.next) {
        if (_.isString(flow.catchAll.next)) {
          flow.catchAll.next = [flow.catchAll.next]
        }
      }
    }

    const errs =
      flow.nodes &&
      flow.nodes.map(node => {
        // TODO Better node validation

        // TODO Validate that connections are valid
        // TODO Validate that conditions are valid

        if (!_.isString(node.id) || node.id.length <= 3) {
          return errorPrefix + ', expected all nodes to have a valid id'
        }

        if (_.isString(node.onEnter)) {
          node.onEnter = [node.onEnter]
        }

        if (_.isString(node.onReceive)) {
          node.onReceive = [node.onReceive]
        }

        if (_.isString(node.next)) {
          node.next = [node.next]
        }
      })

    return _.first(errs, e => !!e)
  }
}
<|endoftext|>


<commit_before>//Because Browserify encapsulates every module, use strict won't apply to the global scope and break everything
'use strict';

//Require necessary modules
var Utils = require('./utils.js'),
    TextLog = require('./textlog.js'),
    Camera = require('./camera.js'),
    Map = require('../tilemap/map.js'),
    PlayerFactory = require('../factories/playerfactory.js'),
    Vector2 = require('../geometry/vector2.js'),
    Container = require('../ui/container.js'),
    InteractionManager = require('../ui/interactionmanager.js'),
    TextLogElement = require('../ui/custom/textlog.js'),
    Group = require('../gameobjects/group.js'),
    Combat = require('../gameobjects/systems/combat.js'),
    LightMap = require('../gameobjects/systems/lightmap.js'),
    Movement = require('../gameobjects/systems/movement.js'),
    Open = require('../gameobjects/systems/open.js'),
    PathFinding = require('../gameobjects/systems/pathfinding.js'),
    Render = require('../gameobjects/systems/render.js'),
    MapFactory = require('../tilemap/mapfactory.js'),
    MapDecorator = require('../tilemap/mapdecorator.js'),
    Scheduler = require('../time/scheduler.js'),
    Keyboard = require('../input/keyboard.js');

/**
 * Game Constructor
 *
 * @class Game
 * @classdesc The heart of this roguelike game! In here we provide access to
 * all the other objects and function, and we handle the startup of the game
 *
 * @param {Object} userSettings - The settings that the user provides
 */
var Game = function(userSettings) {

	/**
	 * @property {Boolean} isInitialized - Boolean to see if the game is already initialized
	 */
	this.isInitialized = false;

	/**
	 * @property {Boolean} isActive - Boolean to see if the game is currently active
	 */
	this.isActive = false;

	/**
	 * @property {Map} map - Reference to the current map
	 */
	this.map = null;

	/**
	 * @property {MapFactory} mapFactory - The mapFactory is responsible for creating rooms and corridors on this map
	 */
	this.mapFactory = null;

	/**
	 * @property {MapDecorator} mapDecorator - The mapDecorator is responsible for decorating the map with props and enemies
	 */
	this.mapDecorator = null;

	/**
	 * @property {Keyboard} keyboard - Reference to the keyboard object
	 */
	this.keyboard = null;

	/**
	 * @property {Scheduler} scheduler - Reference to the scheduler object
	 */
	this.scheduler = null;

	/**
	 * @property {Object} staticSystems - An object with all the static systems
	 */
	this.staticSystems = {};

	/**
	 * @property {Array} dynamicSystems - An array with all the current systems that need to be looped
	 */
	this.dynamicSystems = [];

	/**
	 * @property {Camera} camera - Reference to the camera
	 */
	this.camera = null;

	/**
	 * @property {Container} UI - Reference to the global UI container
	 */
	this.UI = null;

	/**
	 * @property {InteractionManager} interactionmanager - Reference to the interactionmanager
	 */
	this.interactionmanager = null;

	/**
	 * @property {TextLog} textLog - Reference to the TextLog object
	 */
	this.textLog = null;

	/**
	 * @property {Entity} player - Reference to the player object
	 */
	this.player = null;

	/**
	 * @property {Object} settings - The default settings
	 */
	this.settings = {
		canvas: null,
		cameraBounds: false,
		debug: false
	};

	//Extend the default settings with those of the user
	this.settings = Utils.extend(this.settings, userSettings);

	//Initialize itself
	this.initialize();

};

Game.prototype = {

	/**
	 * Initialize the game, create all objects
	 * @protected
	 */
	initialize: function() {

		//Check if the game is already initialized
		if(this.isInitialized) {
			return;
		}

		//Create a new keyboard
		this.keyboard = new Keyboard();

		//Create a new scheduler
		this.scheduler = new Scheduler();

		//Initialize the map
		this.initializeMap();

		//Create the camera object
		this.camera = new Camera(this, {x: 0, y: 0});

		//Get the start position of the player
		var playerPosition = new Vector2(this.map.entrance.x, this.map.entrance.y);

		//Associative array with every control that this entity uses
		var playerControls = {
			"left": 65,
			"right":68,
			"up":87,
			"down":83
		};

		//Create the player entity
		this.player = PlayerFactory.newPlayerWarrior(this, playerPosition, playerControls);

		//Initialize the player
		this.initializePlayer();

		//Initialize the movement system
		this.staticSystems.movementSystem = new Movement(this);

		//Initialize the movement system
		this.staticSystems.pathfindingSystem = new PathFinding(this);

		//Initialize the combat system
		this.staticSystems.combatSystem = new Combat(this);

		//Initialize the open system
		this.staticSystems.openSystem = new Open(this);

		//Add all systems to the game that need to be looped
		this.dynamicSystems.push(new LightMap(this));
		this.dynamicSystems.push(new Render(this));

		//Create a new text log
		this.textLog = new TextLog();

		//Add another string to the message
		var textLogMessage = "You enter the basement and look around";

		//Add the message to the textlog
		this.textLog.addMessage(textLogMessage);

		//Create a new interaction manager
		this.interactionmanager = new InteractionManager(this.settings.canvas);

		//Initialize the UI
		this.initializeUI();

		//Update the game for the first time
		this.update();

		//The game is fully initialized!
		this.isInitialized = true;

		//Make the game active for the first time
		this.isActive = true;

	},

	/**
	 * Creates and populates a new map
	 * @protected
	 */
	initializeMap: function() {

		//Initialize the map
		this.map = new Map(this);

		//Create the map factory
		this.mapFactory = new MapFactory(this);

		//Create the map decorator
		this.mapDecorator = new MapDecorator(this);

		//Add a new entity group to the map
		this.map.entities = new Group(this);

		//Generate rooms for this map
		this.mapFactory.generateRooms();

		this.mapDecorator.decorateMap();

	},

	/**
	 * Initializes and adds the player to the game
	 * @protected
	 */
	initializePlayer: function() {

		//Get the start position of the player from the map
		var startPosition = new Vector2(this.map.entrance.x, this.map.entrance.y);

		//Set the player's start position
		var playerPosition = this.player.getComponent("position");
		playerPosition.position = startPosition;

		//Restore the player's health
		var playerHealth = this.player.getComponent("health");
		playerHealth.health = playerHealth.maxHealth;

		//Add the player to the entities list of the current map
		this.map.entities.addEntity(this.player);

		//Get the tile that the player is going to spawn on
		var startingTile = this.map.tiles[startPosition.x][startPosition.y];

		//Add the player to the tile it spawns on
		startingTile.addEntity(this.player);

		//Add the player to the scheduler
		this.scheduler.add(this.player, true);

		//Let the camera follow the player entity
		this.camera.follow(this.player, this.settings.canvas.width / 2, this.settings.canvas.height / 2);

	},

	/**
	 * Creates all UI objects and adds them to the global UI container
	 * @protected
	 */
	initializeUI: function() {

		//Create the global UI container
		this.UI = new Container(
			new Vector2(0, 0)
		);

		var textLog = new TextLogElement(
			new Vector2(15, 15),
			this
		);

		this.UI.addElement(textLog);

		this.interactionmanager.elements.push(textLog);

	},

	/**
	 * All the functions that need to be executed every time the game updates
	 * Basically the game loop
	 * @protected
	 */
	update: function() {

		//If the game is not currently active, restart
		if(this.isInitialized && !this.isActive) {

			this.restart();

		}

		//Request a new animation frame and call the update function again
		requestAnimationFrame(this.update.bind(this));

		//While the scheduler is locked, continue ticking
		while(!this.scheduler.lockCount) {

			//Let the scheduler handle the next entity
			this.scheduler.tick();

		}

		//Loop through each dynamic system
		for(var s = 0; s < this.dynamicSystems.length; s++) {

			//Update the current system
			this.dynamicSystems[s].update();

		}

	},

	/**
	 * Restarts the game with a fresh map and player
	 * @protected
	 */
	restart: function() {

		//Clear events from the scheduler
		this.scheduler.clear();

		//Initialize map and player
		this.initializeMap();
		this.initializePlayer();

		//Initialize the pathfinding system with the new game map
		this.staticSystems.pathfindingSystem.game = this;
		this.staticSystems.pathfindingSystem.initialize();

		//Make game active
		this.isActive = true;

	}

};

//Export the Browserify module
module.exports = Game;
<commit_msg>Code that creates the bottom bar and adds all slots to it.<commit_after>//Because Browserify encapsulates every module, use strict won't apply to the global scope and break everything
'use strict';

//Require necessary modules
var Utils = require('./utils.js'),
    TextLog = require('./textlog.js'),
    Camera = require('./camera.js'),
    Map = require('../tilemap/map.js'),
    PlayerFactory = require('../factories/playerfactory.js'),
    Vector2 = require('../geometry/vector2.js'),
    Container = require('../ui/container.js'),
    InteractionManager = require('../ui/interactionmanager.js'),
    TextLogElement = require('../ui/custom/textlog.js'),
    ImageElement = require('../ui/elements/imageelement.js'),
    TextElement = require('../ui/elements/textelement.js'),
    Group = require('../gameobjects/group.js'),
    Combat = require('../gameobjects/systems/combat.js'),
    LightMap = require('../gameobjects/systems/lightmap.js'),
    Movement = require('../gameobjects/systems/movement.js'),
    Open = require('../gameobjects/systems/open.js'),
    PathFinding = require('../gameobjects/systems/pathfinding.js'),
    Render = require('../gameobjects/systems/render.js'),
    MapFactory = require('../tilemap/mapfactory.js'),
    MapDecorator = require('../tilemap/mapdecorator.js'),
    Scheduler = require('../time/scheduler.js'),
    Keyboard = require('../input/keyboard.js');

/**
 * Game Constructor
 *
 * @class Game
 * @classdesc The heart of this roguelike game! In here we provide access to
 * all the other objects and function, and we handle the startup of the game
 *
 * @param {Object} userSettings - The settings that the user provides
 */
var Game = function(userSettings) {

	/**
	 * @property {Boolean} isInitialized - Boolean to see if the game is already initialized
	 */
	this.isInitialized = false;

	/**
	 * @property {Boolean} isActive - Boolean to see if the game is currently active
	 */
	this.isActive = false;

	/**
	 * @property {Map} map - Reference to the current map
	 */
	this.map = null;

	/**
	 * @property {MapFactory} mapFactory - The mapFactory is responsible for creating rooms and corridors on this map
	 */
	this.mapFactory = null;

	/**
	 * @property {MapDecorator} mapDecorator - The mapDecorator is responsible for decorating the map with props and enemies
	 */
	this.mapDecorator = null;

	/**
	 * @property {Keyboard} keyboard - Reference to the keyboard object
	 */
	this.keyboard = null;

	/**
	 * @property {Scheduler} scheduler - Reference to the scheduler object
	 */
	this.scheduler = null;

	/**
	 * @property {Object} staticSystems - An object with all the static systems
	 */
	this.staticSystems = {};

	/**
	 * @property {Array} dynamicSystems - An array with all the current systems that need to be looped
	 */
	this.dynamicSystems = [];

	/**
	 * @property {Camera} camera - Reference to the camera
	 */
	this.camera = null;

	/**
	 * @property {Container} UI - Reference to the global UI container
	 */
	this.UI = null;

	/**
	 * @property {InteractionManager} interactionmanager - Reference to the interactionmanager
	 */
	this.interactionmanager = null;

	/**
	 * @property {TextLog} textLog - Reference to the TextLog object
	 */
	this.textLog = null;

	/**
	 * @property {Entity} player - Reference to the player object
	 */
	this.player = null;

	/**
	 * @property {Object} settings - The default settings
	 */
	this.settings = {
		canvas: null,
		cameraBounds: false,
		debug: false
	};

	//Extend the default settings with those of the user
	this.settings = Utils.extend(this.settings, userSettings);

	//Initialize itself
	this.initialize();

};

Game.prototype = {

	/**
	 * Initialize the game, create all objects
	 * @protected
	 */
	initialize: function() {

		//Check if the game is already initialized
		if(this.isInitialized) {
			return;
		}

		//Create a new keyboard
		this.keyboard = new Keyboard();

		//Create a new scheduler
		this.scheduler = new Scheduler();

		//Initialize the map
		this.initializeMap();

		//Create the camera object
		this.camera = new Camera(this, {x: 0, y: 0});

		//Get the start position of the player
		var playerPosition = new Vector2(this.map.entrance.x, this.map.entrance.y);

		//Associative array with every control that this entity uses
		var playerControls = {
			"left": 65,
			"right":68,
			"up":87,
			"down":83
		};

		//Create the player entity
		this.player = PlayerFactory.newPlayerWarrior(this, playerPosition, playerControls);

		//Initialize the player
		this.initializePlayer();

		//Initialize the movement system
		this.staticSystems.movementSystem = new Movement(this);

		//Initialize the movement system
		this.staticSystems.pathfindingSystem = new PathFinding(this);

		//Initialize the combat system
		this.staticSystems.combatSystem = new Combat(this);

		//Initialize the open system
		this.staticSystems.openSystem = new Open(this);

		//Add all systems to the game that need to be looped
		this.dynamicSystems.push(new LightMap(this));
		this.dynamicSystems.push(new Render(this));

		//Create a new text log
		this.textLog = new TextLog();

		//Add another string to the message
		var textLogMessage = "You enter the basement and look around";

		//Add the message to the textlog
		this.textLog.addMessage(textLogMessage);

		//Create a new interaction manager
		this.interactionmanager = new InteractionManager(this.settings.canvas);

		//Initialize the UI
		this.initializeUI();

		//Update the game for the first time
		this.update();

		//The game is fully initialized!
		this.isInitialized = true;

		//Make the game active for the first time
		this.isActive = true;

	},

	/**
	 * Creates and populates a new map
	 * @protected
	 */
	initializeMap: function() {

		//Initialize the map
		this.map = new Map(this);

		//Create the map factory
		this.mapFactory = new MapFactory(this);

		//Create the map decorator
		this.mapDecorator = new MapDecorator(this);

		//Add a new entity group to the map
		this.map.entities = new Group(this);

		//Generate rooms for this map
		this.mapFactory.generateRooms();

		this.mapDecorator.decorateMap();

	},

	/**
	 * Initializes and adds the player to the game
	 * @protected
	 */
	initializePlayer: function() {

		//Get the start position of the player from the map
		var startPosition = new Vector2(this.map.entrance.x, this.map.entrance.y);

		//Set the player's start position
		var playerPosition = this.player.getComponent("position");
		playerPosition.position = startPosition;

		//Restore the player's health
		var playerHealth = this.player.getComponent("health");
		playerHealth.health = playerHealth.maxHealth;

		//Add the player to the entities list of the current map
		this.map.entities.addEntity(this.player);

		//Get the tile that the player is going to spawn on
		var startingTile = this.map.tiles[startPosition.x][startPosition.y];

		//Add the player to the tile it spawns on
		startingTile.addEntity(this.player);

		//Add the player to the scheduler
		this.scheduler.add(this.player, true);

		//Let the camera follow the player entity
		this.camera.follow(this.player, this.settings.canvas.width / 2, this.settings.canvas.height / 2);

	},

	/**
	 * Creates all UI objects and adds them to the global UI container
	 * @protected
	 */
	initializeUI: function() {

		//Create the global UI container
		var UI = new Container(
			new Vector2(0, 0),
			null
		);

		this.UI = UI;

		//Create the textlog
		var textLog = new TextLogElement(
			new Vector2(15, 15),
			UI,
			this
		);

		//Add the textlog to the UI
		this.UI.addElement(textLog);

		//Create the bottom bar container
		var bottomBar = new Container(
			new Vector2((this.settings.canvas.width / 2) - 400, this.settings.canvas.height - 100),
			UI,
			940,
			100
		);

		//Loop 9 times to create all the left slots
		for(var i = 0; i < 18; i++){

			var distance = 0;

			if(i > 8){
				distance = 48;
			}

			//Create the item slot container
			var iconSlot = new Container(
				new Vector2(i * 44 + distance, 15),
				bottomBar,
				44,
				44
			);

			//Add the background image
			iconSlot.addElement(
				new ImageElement(
					new Vector2(0,0),
					iconSlot,
					"itemslot",
					3
				)
			);

			//Create the little text in the corner
			iconSlot.addElement(
				new TextElement(
					new Vector2(28, 28),
					iconSlot,
					i + 1,
					"#606060",
					10
				)
			);

			//Add a function the onHover object from the item slot container
			iconSlot.onHover = function (index) {
				return function() {
					console.log("Quickslot number "+index);
				};
			}(i + 1);

			//Add the slot to the bottom bar
			bottomBar.addElement(iconSlot);

			//Add the iconSlot to the interactive elements list
			this.interactionmanager.elements.push(iconSlot);

		}

		//Add the bottom bar to the UI
		this.UI.addElement(bottomBar);

	},

	/**
	 * All the functions that need to be executed every time the game updates
	 * Basically the game loop
	 * @protected
	 */
	update: function() {

		//If the game is not currently active, restart
		if(this.isInitialized && !this.isActive) {

			this.restart();

		}

		//Request a new animation frame and call the update function again
		requestAnimationFrame(this.update.bind(this));

		//While the scheduler is locked, continue ticking
		while(!this.scheduler.lockCount) {

			//Let the scheduler handle the next entity
			this.scheduler.tick();

		}

		//Loop through each dynamic system
		for(var s = 0; s < this.dynamicSystems.length; s++) {

			//Update the current system
			this.dynamicSystems[s].update();

		}

	},

	/**
	 * Restarts the game with a fresh map and player
	 * @protected
	 */
	restart: function() {

		//Clear events from the scheduler
		this.scheduler.clear();

		//Initialize map and player
		this.initializeMap();
		this.initializePlayer();

		//Initialize the pathfinding system with the new game map
		this.staticSystems.pathfindingSystem.game = this;
		this.staticSystems.pathfindingSystem.initialize();

		//Make game active
		this.isActive = true;

	}

};

//Export the Browserify module
module.exports = Game;
<|endoftext|>


<commit_before>/**
 * Initialises Keystone in encapsulated mode.
 *
 * Creates an Express app and configures it if none has been connected.
 *
 * Also connects to the default mongoose instance if none has been connected.
 *
 * Accepts an options argument.
 *
 * Returns `this` to allow chaining.
 *
 * @param {Object} options
 * @api public
 */

var express = require('express')

exports = module.exports = function init(options) {

	this.options(options);

	if (!this.app) {
		this.app = express();
	}

	if (!this.mongoose) {
		this.connect(require('mongoose'));
	}

	return this;

};
<commit_msg>Adding missing semicolon<commit_after>/**
 * Initialises Keystone in encapsulated mode.
 *
 * Creates an Express app and configures it if none has been connected.
 *
 * Also connects to the default mongoose instance if none has been connected.
 *
 * Accepts an options argument.
 *
 * Returns `this` to allow chaining.
 *
 * @param {Object} options
 * @api public
 */

var express = require('express');

exports = module.exports = function init(options) {

	this.options(options);

	if (!this.app) {
		this.app = express();
	}

	if (!this.mongoose) {
		this.connect(require('mongoose'));
	}

	return this;

};
<|endoftext|>


<commit_before>import { Component, createElement } from 'react';

const ifNot = (condition, errorMessage) => {
    if (!ifNot) throw new Error(errorMessage);
}

function withRoute(BaseComponent) {
    class ComponentWithRoute extends Component {
        constructor(props, context) {
            super(props, context);
            this.router = context.router;
            this.state = {
                previousRoute: null,
                route: this.router.getState()
            };
        }

        componentDidMount() {
            ifNot(
                this.router.registeredPlugins.LISTENERS,
                '[react-router5] missing plugin router5-listeners.'
            );

            this.listener = (toState, fromState) => this.setState({ previousRoute: fromState, route: toState });
            this.router.addListener(this.nodeListener);
        }

        componentWillUnmout() {
            this.router.removeListener(this.listener);
        }

        render() {
            ifNot(
                !props.router && !props.route && !props.previousRoute,
                '[react-router5] prop names `router`, `route` and `previousRoute` are reserved.'
            );

            return createElement(BaseComponent, { ...props, ...this.state, router: this.router });
        }
    }

    return ComponentWithRoute;
}

export default withRoute;
<commit_msg>chore: fix linting issue<commit_after>import { Component, createElement } from 'react';

const ifNot = (condition, errorMessage) => {
    if (!ifNot) throw new Error(errorMessage);
};

function withRoute(BaseComponent) {
    class ComponentWithRoute extends Component {
        constructor(props, context) {
            super(props, context);
            this.router = context.router;
            this.state = {
                previousRoute: null,
                route: this.router.getState()
            };
        }

        componentDidMount() {
            ifNot(
                this.router.registeredPlugins.LISTENERS,
                '[react-router5] missing plugin router5-listeners.'
            );

            this.listener = (toState, fromState) => this.setState({ previousRoute: fromState, route: toState });
            this.router.addListener(this.nodeListener);
        }

        componentWillUnmout() {
            this.router.removeListener(this.listener);
        }

        render() {
            ifNot(
                !props.router && !props.route && !props.previousRoute,
                '[react-router5] prop names `router`, `route` and `previousRoute` are reserved.'
            );

            return createElement(BaseComponent, { ...props, ...this.state, router: this.router });
        }
    }

    return ComponentWithRoute;
}

export default withRoute;
<|endoftext|>


<commit_before>"use strict";

const OPEN_CURLY_BRACKET  = Symbol.for('OPEN_CURLY_BRACKET');
const CLOSE_CURLY_BRACKET = Symbol.for('CLOSE_CURLY_BRACKET');
const EOF                 = Symbol.for('EOF');
const AT                  = Symbol.for('AT');
const COMMENT             = Symbol.for('COMMENT');
const SEMICOLON           = Symbol.for('SEMICOLON');
const AMPERSAND           = Symbol.for('AMPERSAND');
const NAME                = Symbol.for('NAME');

let stylecow = require('../index');

stylecow.Block = class Block extends require('./classes/node-collection') {

    static create (reader, parent) {
        if (reader.currToken === OPEN_CURLY_BRACKET) {
            let element = new stylecow.Block(reader.data());

            reader.move();

            //It's a @keyframes
            if (parent && parent.type === 'AtRule' && parent.name === 'keyframes') {
                while (reader.currToken !== CLOSE_CURLY_BRACKET && reader.currToken !== EOF) {
                    element.push(
                            stylecow.Comment.create(reader, element)
                         || stylecow.Keyframe.create(reader, element)
                         || reader.error()
                    );
                }
            }

            //It's a keyframe or custom-property
            else if (parent && (parent.type === 'Keyframe' || parent.type === 'CustomProperty')) {
                while (reader.currToken !== CLOSE_CURLY_BRACKET && reader.currToken !== EOF) {
                    element.push(
                            stylecow.Comment.create(reader, element)
                         || stylecow.Declaration.create(reader, element)
                         || reader.error()
                    );
                }
            }

            else {
                while (reader.currToken !== CLOSE_CURLY_BRACKET && reader.currToken !== EOF) {

                    //It's a media query?
                    if (reader.currToken === AT) {
                        element.push(
                                stylecow.AtRule.create(reader, element)
                             || stylecow.NestedAtRule.create(reader, element)
                             || reader.error()
                        );
                        continue;
                    }

                    //It's a comment
                    if (reader.currToken === COMMENT) {
                        element.push(stylecow.Comment.create(reader, element) || reader.error());
                        continue;
                    }

                    //It's a nested rule?
                    if (reader.currToken === OPEN_CURLY_BRACKET) {
                        reader.move();

                        while (reader.currToken !== CLOSE_CURLY_BRACKET && reader.currToken !== EOF) {
                            element.push(
                                    stylecow.Comment.create(reader, element)
                                 || stylecow.AtRule.create(reader, element)
                                 || stylecow.NestedAtRule.create(reader, element)
                                 || stylecow.Rule.create(reader, element)
                                 || reader.error()
                            );
                        }

                        reader.skip(CLOSE_CURLY_BRACKET) || reader.error();
                        continue;
                    }

                    //It's a nested rule?
                    if (reader.currToken === AMPERSAND) {
                        element.push(stylecow.Rule.create(reader, element) || reader.error());
                        continue;
                    }

                    //It's a custom property?
                    if (reader.currToken === NAME && reader.currStr.substr(0, 2) === '--') {
                        element.push(stylecow.CustomProperty.create(reader, element) || reader.error());
                        continue;
                    }

                    //It's a declaration or a nested rule?
                    let token = reader.searchNext([SEMICOLON, CLOSE_CURLY_BRACKET, OPEN_CURLY_BRACKET, EOF]);

                    //It's a declaration
                    if (token === SEMICOLON || token === CLOSE_CURLY_BRACKET) {
                        element.push(stylecow.Declaration.create(reader, element) || reader.error());
                        continue;
                    }

                    //It's a nested rule
                    if (token === OPEN_CURLY_BRACKET) {
                        element.push(stylecow.Rule.create(reader, element) || reader.error());
                        continue;
                    }

                    //End of file
                    if (token === EOF) {
                        return reader.error();
                    }
                }
            }

            reader.skip(CLOSE_CURLY_BRACKET) || reader.error();

            return element;
        }
    }

    constructor(data) {
        super(data, 'Block');
    }

    toString () {
        return "{\n\t" + this.join("\n").replace(/\n/g, "\n\t") + "\n}";
    }

    toCode (code) {
        code.appendStyle('block-opening-bracket-before');
        code.append('{');
        code.pushIndentation();
        code.appendStyle('block-opening-bracket-after');

        this.forEach(child => child.toCode(code));

        code.popIndentation();
        code.appendStyle('block-closing-bracket-before');
        code.append('}');
        code.appendStyle('block-closing-bracket-after');
    }
}
<commit_msg>allow atrules inside custom properties<commit_after>"use strict";

const OPEN_CURLY_BRACKET  = Symbol.for('OPEN_CURLY_BRACKET');
const CLOSE_CURLY_BRACKET = Symbol.for('CLOSE_CURLY_BRACKET');
const EOF                 = Symbol.for('EOF');
const AT                  = Symbol.for('AT');
const COMMENT             = Symbol.for('COMMENT');
const SEMICOLON           = Symbol.for('SEMICOLON');
const AMPERSAND           = Symbol.for('AMPERSAND');
const NAME                = Symbol.for('NAME');

let stylecow = require('../index');

stylecow.Block = class Block extends require('./classes/node-collection') {

    static create (reader, parent) {
        if (reader.currToken === OPEN_CURLY_BRACKET) {
            let element = new stylecow.Block(reader.data());

            reader.move();

            //It's a @keyframes
            if (parent && parent.type === 'AtRule' && parent.name === 'keyframes') {
                while (reader.currToken !== CLOSE_CURLY_BRACKET && reader.currToken !== EOF) {
                    element.push(
                            stylecow.Comment.create(reader, element)
                         || stylecow.Keyframe.create(reader, element)
                         || reader.error()
                    );
                }
            }

            //It's a keyframe
            else if (parent && parent.type === 'Keyframe') {
                while (reader.currToken !== CLOSE_CURLY_BRACKET && reader.currToken !== EOF) {
                    element.push(
                            stylecow.Comment.create(reader, element)
                         || stylecow.Declaration.create(reader, element)
                         || reader.error()
                    );
                }
            }

            //It's a custom-property
            else if (parent && parent.type === 'CustomProperty') {
                while (reader.currToken !== CLOSE_CURLY_BRACKET && reader.currToken !== EOF) {
                    element.push(
                            stylecow.Comment.create(reader, element)
                         || stylecow.Declaration.create(reader, element)
                         || stylecow.AtRule.create(reader, element)
                         || reader.error()
                    );
                }
            }

            else {
                while (reader.currToken !== CLOSE_CURLY_BRACKET && reader.currToken !== EOF) {

                    //It's a media query?
                    if (reader.currToken === AT) {
                        element.push(
                                stylecow.AtRule.create(reader, element)
                             || stylecow.NestedAtRule.create(reader, element)
                             || reader.error()
                        );
                        continue;
                    }

                    //It's a comment
                    if (reader.currToken === COMMENT) {
                        element.push(stylecow.Comment.create(reader, element) || reader.error());
                        continue;
                    }

                    //It's a nested rule?
                    if (reader.currToken === OPEN_CURLY_BRACKET) {
                        reader.move();

                        while (reader.currToken !== CLOSE_CURLY_BRACKET && reader.currToken !== EOF) {
                            element.push(
                                    stylecow.Comment.create(reader, element)
                                 || stylecow.AtRule.create(reader, element)
                                 || stylecow.NestedAtRule.create(reader, element)
                                 || stylecow.Rule.create(reader, element)
                                 || reader.error()
                            );
                        }

                        reader.skip(CLOSE_CURLY_BRACKET) || reader.error();
                        continue;
                    }

                    //It's a nested rule?
                    if (reader.currToken === AMPERSAND) {
                        element.push(stylecow.Rule.create(reader, element) || reader.error());
                        continue;
                    }

                    //It's a custom property?
                    if (reader.currToken === NAME && reader.currStr.substr(0, 2) === '--') {
                        element.push(stylecow.CustomProperty.create(reader, element) || reader.error());
                        continue;
                    }

                    //It's a declaration or a nested rule?
                    let token = reader.searchNext([SEMICOLON, CLOSE_CURLY_BRACKET, OPEN_CURLY_BRACKET, EOF]);

                    //It's a declaration
                    if (token === SEMICOLON || token === CLOSE_CURLY_BRACKET) {
                        element.push(stylecow.Declaration.create(reader, element) || reader.error());
                        continue;
                    }

                    //It's a nested rule
                    if (token === OPEN_CURLY_BRACKET) {
                        element.push(stylecow.Rule.create(reader, element) || reader.error());
                        continue;
                    }

                    //End of file
                    if (token === EOF) {
                        return reader.error();
                    }
                }
            }

            reader.skip(CLOSE_CURLY_BRACKET) || reader.error();

            return element;
        }
    }

    constructor(data) {
        super(data, 'Block');
    }

    toString () {
        return "{\n\t" + this.join("\n").replace(/\n/g, "\n\t") + "\n}";
    }

    toCode (code) {
        code.appendStyle('block-opening-bracket-before');
        code.append('{');
        code.pushIndentation();
        code.appendStyle('block-opening-bracket-after');

        this.forEach(child => child.toCode(code));

        code.popIndentation();
        code.appendStyle('block-closing-bracket-before');
        code.append('}');
        code.appendStyle('block-closing-bracket-after');
    }
}
<|endoftext|>


<commit_before>var PATH = require('path'),

    pjoin = PATH.join,
    presolve = PATH.resolve.bind(null, __dirname),

    PRJ_ROOT = presolve('../../'),

    PRJ_TECHS = presolve('../techs/'),
    BEMBL_TECHS = pjoin(PRJ_ROOT, 'bem-bl/blocks-common/i-bem/bem/techs');

exports.getTechs = function() {

    return {
        'bemjson.js'    : '',
        'bemdecl.js'    : 'bemdecl.js',
        'deps.js'       : 'deps.js',
        'js'            : 'js-i',
        'css'           : 'css',
        'ie.css'        : 'ie.css',
        'ie6.css'       : 'ie6.css',
        'ie7.css'       : 'ie7.css',
        'ie8.css'       : 'ie8.css',
        'ie9.css'       : 'ie9.css',

        'bemhtml'       : pjoin(PRJ_ROOT, 'bemhtml/.bem/techs/bemhtml.js'),
        'html'          : pjoin(BEMBL_TECHS, 'html.js')
    };

};

// Do not create any techs files during bundle creation by default
exports.defaultTechs = [];

<commit_msg>Use html tech from bemhtml library<commit_after>var PATH = require('path'),

    pjoin = PATH.join,
    presolve = PATH.resolve.bind(null, __dirname),

    PRJ_ROOT = presolve('../../'),

    PRJ_TECHS = presolve('../techs/');

exports.getTechs = function() {

    return {
        'bemjson.js'    : '',
        'bemdecl.js'    : 'bemdecl.js',
        'deps.js'       : 'deps.js',
        'js'            : 'js-i',
        'css'           : 'css',
        'ie.css'        : 'ie.css',
        'ie6.css'       : 'ie6.css',
        'ie7.css'       : 'ie7.css',
        'ie8.css'       : 'ie8.css',
        'ie9.css'       : 'ie9.css',

        'bemhtml'       : pjoin(PRJ_ROOT, 'bemhtml/.bem/techs/bemhtml.js'),
        'html'          : pjoin(PRJ_ROOT, 'bemhtml/.bem/techs/html.js')
    };

};

// Do not create any techs files during bundle creation by default
exports.defaultTechs = [];

<|endoftext|>