<commit_before>/**
 * Created by nuintun on 2015/11/20.
 */

'use strict';

var fs = require('fs');
var path = require('path');
var util = require('../../util');
var Vue = require('../../vue/vue');
var Terminal = require('../../terminal');

Terminal.defaultColors = {
  bg: 'transparent',
  fg: 'inherit'
};

const EMPTYPROJECT = {
  name: '',
  path: '',
  env: [],
  command: [],
  empty: true
};

require('../project-configure');

/**
 * clone project
 * @param projects
 * @param index
 * @returns {*}
 */
function clone(projects, index){
  return util.clone(projects[index] || EMPTYPROJECT);
}

function scroll(element){
  element.scrollTop = element.scrollHeight;
}

module.exports = Vue.component('app-main', {
  template: fs.readFileSync(path.join(__dirname, 'app-main.html')).toString(),
  props: {
    activeIndex: {
      type: Number,
      twoWay: true,
      required: true
    },
    projects: {
      type: Array,
      twoWay: true,
      required: true
    },
    unique: {
      type: Object,
      required: true
    }
  },
  data: function (){
    var project = clone(this.projects, this.activeIndex);

    return {
      showSetting: false,
      expandCommand: false,
      project: project,
      command: project.command.slice(0, 3),
      moreCommand: project.command.slice(3)
    };
  },
  watch: {
    projects: function (){
      this.project = clone(this.projects, this.activeIndex);
    },
    activeIndex: function (){
      this.project = clone(this.projects, this.activeIndex);
    },
    project: function (){
      this.command = this.project.command.slice(0, 3);
      this.moreCommand = this.project.command.slice(3);
    }
  },
  methods: {
    isRunning: function (){

    },
    exec: function (name, command){
      console.log('run %s: %s', name, command);

      var xtermNode = this.$els.terminal;
      var runtime = window.AppRuntime[this.project.name];

      var test = [
        '\u001b[92m\'use strict\'\u001b[39m\u001b[90m;\u001b[39m',
        '\u001b[90m/*jshint browser:true */\u001b[39m',
        '',
        '\u001b[32mvar\u001b[39m \u001b[37mTerminal\u001b[39m \u001b[93m=\u001b[39m \u001b[37mrequire\u001b[39m\u001b[90m(\u001b[39m\u001b[92m\'./term\'\u001b[39m\u001b[90m)\u001b[39m',
        '  \u001b[32m,\u001b[39m \u001b[37mthrough\u001b[39m \u001b[93m=\u001b[39m \u001b[37mrequire\u001b[39m\u001b[90m(\u001b[39m\u001b[92m\'through\'\u001b[39m\u001b[90m)\u001b[39m',
        '  \u001b[90m;\u001b[39m',
        '',
        '\u001b[37mmodule\u001b[39m\u001b[32m.\u001b[39m\u001b[37mexports\u001b[39m \u001b[93m=\u001b[39m \u001b[94mfunction\u001b[39m \u001b[90m(\u001b[39m\u001b[37mcols\u001b[39m\u001b[32m,\u001b[39m \u001b[37mrows\u001b[39m\u001b[32m,\u001b[39m \u001b[37mhandler\u001b[39m\u001b[90m)\u001b[39m \u001b[33m{\u001b[39m',
        '  \u001b[32mvar\u001b[39m \u001b[37mterm\u001b[39m \u001b[93m=\u001b[39m \u001b[31mnew\u001b[39m \u001b[37mTerminal\u001b[39m\u001b[90m(\u001b[39m\u001b[37mcols\u001b[39m\u001b[32m,\u001b[39m \u001b[37mrows\u001b[39m\u001b[32m,\u001b[39m \u001b[37mhandler\u001b[39m\u001b[90m)\u001b[39m\u001b[90m;\u001b[39m',
        '  \u001b[37mterm\u001b[39m\u001b[32m.\u001b[39m\u001b[37mopen\u001b[39m\u001b[90m(\u001b[39m\u001b[90m)\u001b[39m\u001b[90m;\u001b[39m',
        '  ',
        '  \u001b[32mvar\u001b[39m \u001b[37mhypernal\u001b[39m \u001b[93m=\u001b[39m \u001b[37mthrough\u001b[39m\u001b[90m(\u001b[39m\u001b[37mterm\u001b[39m\u001b[32m.\u001b[39m\u001b[37mwrite\u001b[39m\u001b[32m.\u001b[39m\u001b[37mbind\u001b[39m\u001b[90m(\u001b[39m\u001b[37mterm\u001b[39m\u001b[90m)\u001b[39m\u001b[90m)\u001b[39m\u001b[90m;\u001b[39m',
        '  \u001b[37mhypernal\u001b[39m\u001b[32m.\u001b[39m\u001b[37mappendTo\u001b[39m \u001b[93m=\u001b[39m \u001b[94mfunction\u001b[39m \u001b[90m(\u001b[39m\u001b[37melem\u001b[39m\u001b[90m)\u001b[39m \u001b[33m{\u001b[39m',
        '    \u001b[94mif\u001b[39m \u001b[90m(\u001b[39m\u001b[94mtypeof\u001b[39m \u001b[37melem\u001b[39m \u001b[93m===\u001b[39m \u001b[92m\'string\'\u001b[39m\u001b[90m)\u001b[39m \u001b[37melem\u001b[39m \u001b[93m=\u001b[39m \u001b[37mdocument\u001b[39m\u001b[32m.\u001b[39m\u001b[37mquerySelector\u001b[39m\u001b[90m(\u001b[39m\u001b[37melem\u001b[39m\u001b[90m)\u001b[39m\u001b[90m;\u001b[39m',
        '',
        '    \u001b[37melem\u001b[39m\u001b[32m.\u001b[39m\u001b[37mappendChild\u001b[39m\u001b[90m(\u001b[39m\u001b[37mterm\u001b[39m\u001b[32m.\u001b[39m\u001b[37melement\u001b[39m\u001b[90m)\u001b[39m\u001b[90m;\u001b[39m',
        '    \u001b[37mterm\u001b[39m\u001b[32m.\u001b[39m\u001b[37melement\u001b[39m\u001b[32m.\u001b[39m\u001b[37mstyle\u001b[39m\u001b[32m.\u001b[39m\u001b[37mposition\u001b[39m \u001b[93m=\u001b[39m \u001b[92m\'relative\'\u001b[39m\u001b[90m;\u001b[39m',
        '  \u001b[33m}\u001b[39m\u001b[90m;\u001b[39m',
        '',
        '  \u001b[37mhypernal\u001b[39m\u001b[32m.\u001b[39m\u001b[37mwriteln\u001b[39m \u001b[93m=\u001b[39m \u001b[94mfunction\u001b[39m \u001b[90m(\u001b[39m\u001b[37mline\u001b[39m\u001b[90m)\u001b[39m \u001b[33m{\u001b[39m',
        '    \u001b[37mterm\u001b[39m\u001b[32m.\u001b[39m\u001b[37mwriteln\u001b[39m\u001b[90m(\u001b[39m\u001b[37mline\u001b[39m\u001b[90m)\u001b[39m\u001b[90m;\u001b[39m',
        '  \u001b[33m}\u001b[39m\u001b[90m;\u001b[39m',
        '',
        '  \u001b[37mhypernal\u001b[39m\u001b[32m.\u001b[39m\u001b[37mwrite\u001b[39m \u001b[93m=\u001b[39m \u001b[37mterm\u001b[39m\u001b[32m.\u001b[39m\u001b[37mwrite\u001b[39m\u001b[32m.\u001b[39m\u001b[37mbind\u001b[39m\u001b[90m(\u001b[39m\u001b[37mterm\u001b[39m\u001b[90m)\u001b[39m\u001b[90m;\u001b[39m',
        '',
        '  \u001b[31mreturn\u001b[39m \u001b[37mhypernal\u001b[39m\u001b[90m;\u001b[39m',
        '\u001b[33m}\u001b[39m\u001b[90m;\u001b[39m',
        new Date().toISOString() + '\r\n'
      ].join('\r\n');

      if (!runtime) {
        var xterm = new Terminal();

        xterm.open();
        xtermNode.appendChild(xterm.element);
        xterm.focus();
        //xterm.startBlink();

        console.log(xterm);

        xterm.write(test);
        scroll(xtermNode);

        window.xterm = xterm;

        window.AppRuntime[this.project.name] = {
          name: name,
          command: command,
          xterm: xterm
        }
      } else {
        runtime.xterm.write(test);
        if (runtime.xterm.lines.length > 10) {
          runtime.xterm.deleteLines([10]);
          runtime.xterm.refresh(0, runtime.xterm.lines.length - 1);
        }

        scroll(xtermNode);
      }
    },
    setting: function (){
      this.showSetting = true;
    },
    remove: function (){
      // remove project
      this.projects.splice(this.activeIndex, 1);

      // change active
      this.activeIndex = 0;

      // save configure
      this.$dispatch('save-configure');
    }
  },
  events: {
    'setting-toggle': function (state){
      this.showSetting = state;
    },
    edit: function (project){
      this.projects.$set(this.activeIndex, project);
      this.$dispatch('save-configure');
    }
  },
  created: function (){
    var context = this;

    document.addEventListener('click', function (event){
      var target = event.target;
      var trigger = context.$els.expandTrigger;

      context.expandCommand = trigger && trigger.contains(target);
    }, false);
  }
});
<commit_msg>update files<commit_after>/**
 * Created by nuintun on 2015/11/20.
 */

'use strict';

var fs = require('fs');
var path = require('path');
var util = require('../../util');
var Vue = require('../../vue/vue');
var Terminal = require('../../terminal');

Terminal.defaultColors = {
  bg: 'transparent',
  fg: 'inherit'
};

const EMPTYPROJECT = {
  name: '',
  path: '',
  env: [],
  command: [],
  empty: true
};

require('../project-configure');

/**
 * clone project
 * @param projects
 * @param index
 * @returns {*}
 */
function clone(projects, index){
  return util.clone(projects[index] || EMPTYPROJECT);
}

function scroll(element){
  element.scrollTop = element.scrollHeight;
}

module.exports = Vue.component('app-main', {
  template: fs.readFileSync(path.join(__dirname, 'app-main.html')).toString(),
  props: {
    activeIndex: {
      type: Number,
      twoWay: true,
      required: true
    },
    projects: {
      type: Array,
      twoWay: true,
      required: true
    },
    unique: {
      type: Object,
      required: true
    }
  },
  data: function (){
    var project = clone(this.projects, this.activeIndex);

    return {
      showSetting: false,
      expandCommand: false,
      project: project,
      command: project.command.slice(0, 3),
      moreCommand: project.command.slice(3)
    };
  },
  watch: {
    projects: function (){
      this.project = clone(this.projects, this.activeIndex);
    },
    activeIndex: function (){
      this.project = clone(this.projects, this.activeIndex);
    },
    project: function (){
      this.command = this.project.command.slice(0, 3);
      this.moreCommand = this.project.command.slice(3);
    }
  },
  methods: {
    isRunning: function (){

    },
    exec: function (name, command){
      console.log('run %s: %s', name, command);

      var xtermNode = this.$els.terminal;
      var runtime = window.AppRuntime[this.project.name];

      var test = [
        '\u001b[92m\'use strict\'\u001b[39m\u001b[90m;\u001b[39m',
        '\u001b[90m/*jshint browser:true */\u001b[39m',
        '',
        '\u001b[32mvar\u001b[39m \u001b[37mTerminal\u001b[39m \u001b[93m=\u001b[39m \u001b[37mrequire\u001b[39m\u001b[90m(\u001b[39m\u001b[92m\'./term\'\u001b[39m\u001b[90m)\u001b[39m',
        '  \u001b[32m,\u001b[39m \u001b[37mthrough\u001b[39m \u001b[93m=\u001b[39m \u001b[37mrequire\u001b[39m\u001b[90m(\u001b[39m\u001b[92m\'through\'\u001b[39m\u001b[90m)\u001b[39m',
        '  \u001b[90m;\u001b[39m',
        '',
        '\u001b[37mmodule\u001b[39m\u001b[32m.\u001b[39m\u001b[37mexports\u001b[39m \u001b[93m=\u001b[39m \u001b[94mfunction\u001b[39m \u001b[90m(\u001b[39m\u001b[37mcols\u001b[39m\u001b[32m,\u001b[39m \u001b[37mrows\u001b[39m\u001b[32m,\u001b[39m \u001b[37mhandler\u001b[39m\u001b[90m)\u001b[39m \u001b[33m{\u001b[39m',
        '  \u001b[32mvar\u001b[39m \u001b[37mterm\u001b[39m \u001b[93m=\u001b[39m \u001b[31mnew\u001b[39m \u001b[37mTerminal\u001b[39m\u001b[90m(\u001b[39m\u001b[37mcols\u001b[39m\u001b[32m,\u001b[39m \u001b[37mrows\u001b[39m\u001b[32m,\u001b[39m \u001b[37mhandler\u001b[39m\u001b[90m)\u001b[39m\u001b[90m;\u001b[39m',
        '  \u001b[37mterm\u001b[39m\u001b[32m.\u001b[39m\u001b[37mopen\u001b[39m\u001b[90m(\u001b[39m\u001b[90m)\u001b[39m\u001b[90m;\u001b[39m',
        '  ',
        '  \u001b[32mvar\u001b[39m \u001b[37mhypernal\u001b[39m \u001b[93m=\u001b[39m \u001b[37mthrough\u001b[39m\u001b[90m(\u001b[39m\u001b[37mterm\u001b[39m\u001b[32m.\u001b[39m\u001b[37mwrite\u001b[39m\u001b[32m.\u001b[39m\u001b[37mbind\u001b[39m\u001b[90m(\u001b[39m\u001b[37mterm\u001b[39m\u001b[90m)\u001b[39m\u001b[90m)\u001b[39m\u001b[90m;\u001b[39m',
        '  \u001b[37mhypernal\u001b[39m\u001b[32m.\u001b[39m\u001b[37mappendTo\u001b[39m \u001b[93m=\u001b[39m \u001b[94mfunction\u001b[39m \u001b[90m(\u001b[39m\u001b[37melem\u001b[39m\u001b[90m)\u001b[39m \u001b[33m{\u001b[39m',
        '    \u001b[94mif\u001b[39m \u001b[90m(\u001b[39m\u001b[94mtypeof\u001b[39m \u001b[37melem\u001b[39m \u001b[93m===\u001b[39m \u001b[92m\'string\'\u001b[39m\u001b[90m)\u001b[39m \u001b[37melem\u001b[39m \u001b[93m=\u001b[39m \u001b[37mdocument\u001b[39m\u001b[32m.\u001b[39m\u001b[37mquerySelector\u001b[39m\u001b[90m(\u001b[39m\u001b[37melem\u001b[39m\u001b[90m)\u001b[39m\u001b[90m;\u001b[39m',
        '',
        '    \u001b[37melem\u001b[39m\u001b[32m.\u001b[39m\u001b[37mappendChild\u001b[39m\u001b[90m(\u001b[39m\u001b[37mterm\u001b[39m\u001b[32m.\u001b[39m\u001b[37melement\u001b[39m\u001b[90m)\u001b[39m\u001b[90m;\u001b[39m',
        '    \u001b[37mterm\u001b[39m\u001b[32m.\u001b[39m\u001b[37melement\u001b[39m\u001b[32m.\u001b[39m\u001b[37mstyle\u001b[39m\u001b[32m.\u001b[39m\u001b[37mposition\u001b[39m \u001b[93m=\u001b[39m \u001b[92m\'relative\'\u001b[39m\u001b[90m;\u001b[39m',
        '  \u001b[33m}\u001b[39m\u001b[90m;\u001b[39m',
        '',
        '  \u001b[37mhypernal\u001b[39m\u001b[32m.\u001b[39m\u001b[37mwriteln\u001b[39m \u001b[93m=\u001b[39m \u001b[94mfunction\u001b[39m \u001b[90m(\u001b[39m\u001b[37mline\u001b[39m\u001b[90m)\u001b[39m \u001b[33m{\u001b[39m',
        '    \u001b[37mterm\u001b[39m\u001b[32m.\u001b[39m\u001b[37mwriteln\u001b[39m\u001b[90m(\u001b[39m\u001b[37mline\u001b[39m\u001b[90m)\u001b[39m\u001b[90m;\u001b[39m',
        '  \u001b[33m}\u001b[39m\u001b[90m;\u001b[39m',
        '',
        '  \u001b[37mhypernal\u001b[39m\u001b[32m.\u001b[39m\u001b[37mwrite\u001b[39m \u001b[93m=\u001b[39m \u001b[37mterm\u001b[39m\u001b[32m.\u001b[39m\u001b[37mwrite\u001b[39m\u001b[32m.\u001b[39m\u001b[37mbind\u001b[39m\u001b[90m(\u001b[39m\u001b[37mterm\u001b[39m\u001b[90m)\u001b[39m\u001b[90m;\u001b[39m',
        '',
        '  \u001b[31mreturn\u001b[39m \u001b[37mhypernal\u001b[39m\u001b[90m;\u001b[39m',
        '\u001b[33m}\u001b[39m\u001b[90m;\u001b[39m',
        new Date().toISOString() + '\r\n'
      ].join('\r\n');

      if (!runtime) {
        var xterm = new Terminal();

        xterm.open();
        xtermNode.appendChild(xterm.element);
        xterm.focus();
        xterm.startBlink();

        console.log(xterm);

        xterm.write(test);
        scroll(xtermNode);

        window.xterm = xterm;

        window.AppRuntime[this.project.name] = {
          name: name,
          command: command,
          xterm: xterm
        }
      } else {
        runtime.xterm.write(test);
        if (runtime.xterm.lines.length > 10) {
          runtime.xterm.deleteLines([10]);
          runtime.xterm.refresh(0, runtime.xterm.lines.length - 1);
        }

        scroll(xtermNode);
      }
    },
    setting: function (){
      this.showSetting = true;
    },
    remove: function (){
      // remove project
      this.projects.splice(this.activeIndex, 1);

      // change active
      this.activeIndex = 0;

      // save configure
      this.$dispatch('save-configure');
    }
  },
  events: {
    'setting-toggle': function (state){
      this.showSetting = state;
    },
    edit: function (project){
      this.projects.$set(this.activeIndex, project);
      this.$dispatch('save-configure');
    }
  },
  created: function (){
    var context = this;

    document.addEventListener('click', function (event){
      var target = event.target;
      var trigger = context.$els.expandTrigger;

      context.expandCommand = trigger && trigger.contains(target);
    }, false);
  }
});
<|endoftext|>


<commit_before>/* See license.txt for terms of usage */

define([
    "firebug/firebug",
    "firebug/lib/css",
    "firebug/lib/events",
    "firebug/lib/object",
    "firebug/lib/options",
    "firebug/lib/xpcom",
    "firebug/chrome/module",
    "firebug/css/cssDirtyListener",
    "firebug/editor/editorSelector"
],
function(Firebug, Css, Events, Obj, Options, Xpcom, Module, CSSDirtyListener, EditorSelector) {

// ********************************************************************************************* //
// Constants

var Cc = Components.classes;
var Ci = Components.interfaces;

var reSplitCSS = new RegExp("(url\\((\\\")?.*?\\2\\))|(rgba?\\([^)]*\\)?)|(hsla?\\([^)]*\\)?)|" +
    "(#[\\dA-Fa-f]+)|(-?\\d+(\\.\\d+)?(%|[a-z]{1,4})?)|\\\"([^\\\"]*)\\\"?|'([^']*)'?|" +
    "([^,\\s\\/!\\(\\)]+)|(!(.*)?)");
var reURL = /url\((")?(.*)?\1\)/;
var reRepeat = /no-repeat|repeat-x|repeat-y|repeat/;

// ********************************************************************************************* //
// CSS Module

Firebug.CSSModule = Obj.extend(Module, Firebug.EditorSelector,
{
    dispatchName: "cssModule",

    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
    // Module

    initialize: function()
    {
        this.editors = {};
        this.registerEditor("Live",
        {
            startEditing: function(stylesheet, context, panel)
            {
                panel.startLiveEditing(stylesheet, context);
            },
            stopEditing: function()
            {
                Firebug.Editor.stopEditing();
            }
        });

        this.registerEditor("Source",
        {
            startEditing: function(stylesheet, context, panel)
            {
                panel.startSourceEditing(stylesheet, context);
            },
            stopEditing: function()
            {
                Firebug.Editor.stopEditing();
            }
        });
    },

    initContext: function(context)
    {
        context.dirtyListener = new CSSDirtyListener(context);
        this.addListener(context.dirtyListener);
    },

    destroyContext: function(context)
    {
        this.removeListener(context.dirtyListener);
    },

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

    freeEdit: function(styleSheet, value)
    {
        if (FBTrace.DBG_CSS)
            FBTrace.sysout("CSSModule.freeEdit", arguments);

        if (!styleSheet.editStyleSheet)
        {
            var ownerNode = getStyleSheetOwnerNode(styleSheet);
            styleSheet.disabled = true;

            var url = Xpcom.CCSV("@mozilla.org/network/standard-url;1", Ci.nsIURL);
            url.spec = styleSheet.href;

            var editStyleSheet = ownerNode.ownerDocument.createElementNS(
                "http://www.w3.org/1999/xhtml",
                "style");

            Firebug.setIgnored(editStyleSheet);

            editStyleSheet.setAttribute("type", "text/css");
            editStyleSheet.setAttributeNS(
                "http://www.w3.org/XML/1998/namespace",
                "base",
                url.directory);

            if (ownerNode.hasAttribute("media"))
                editStyleSheet.setAttribute("media", ownerNode.getAttribute("media"));

            // Insert the edited stylesheet directly after the old one to ensure the styles
            // cascade properly.
            ownerNode.parentNode.insertBefore(editStyleSheet, ownerNode.nextSibling);

            styleSheet.editStyleSheet = editStyleSheet;
        }

        styleSheet.editStyleSheet.textContent = value;

        if (FBTrace.DBG_CSS)
            FBTrace.sysout("css.saveEdit styleSheet.href:" + styleSheet.href +
                " got innerHTML:" + value);

        Events.dispatch(this.fbListeners, "onCSSFreeEdit", [styleSheet, value]);
    },

    insertRule: function(styleSheet, cssText, ruleIndex)
    {
        if (FBTrace.DBG_CSS)
            FBTrace.sysout("Insert: " + ruleIndex + " " + cssText);

        var insertIndex = styleSheet.insertRule(cssText, ruleIndex);

        Events.dispatch(this.fbListeners, "onCSSInsertRule", [styleSheet, cssText, ruleIndex]);

        return insertIndex;
    },

    deleteRule: function(src, ruleIndex)
    {
        var inlineStyle = (src instanceof window.Element);
        if (FBTrace.DBG_CSS)
        {
            if (inlineStyle)
            {
                FBTrace.sysout("deleteRule: element.style", src);
            }
            else
            {
                FBTrace.sysout("deleteRule: " + ruleIndex + " " + src.cssRules.length,
                    src.cssRules);
            }
        }

        var rule = (inlineStyle ? src : src.cssRules[ruleIndex]);
        var afterParams = [src, rule.style.cssText];
        afterParams.push(inlineStyle ? "" : rule.selectorText);

        Events.dispatch(this.fbListeners, "onCSSDeleteRule", [src, ruleIndex]);

        if (src instanceof window.Element)
            src.removeAttribute("style");
        else
            src.deleteRule(ruleIndex);

        Events.dispatch(this.fbListeners, "onAfterCSSDeleteRule", afterParams);
    },

    setProperty: function(rule, propName, propValue, propPriority)
    {
        var style = rule.style || rule;

        // Record the original CSS text for the inline case so we can reconstruct at a later
        // point for diffing purposes
        var baseText = style.cssText;

        var prevValue = style.getPropertyValue(propName);
        var prevPriority = style.getPropertyPriority(propName);

        // XXXjoe Gecko bug workaround: Just changing priority doesn't have any effect
        // unless we remove the property first
        style.removeProperty(propName);

        style.setProperty(propName, propValue, propPriority);

        if (propName)
        {
            Events.dispatch(this.fbListeners, "onCSSSetProperty", [style, propName, propValue,
                propPriority, prevValue, prevPriority, rule, baseText]);
        }
    },

    removeProperty: function(rule, propName, parent)
    {
        var style = rule.style || rule;

        // Record the original CSS text for the inline case so we can reconstruct at a later
        // point for diffing purposes
        var baseText = style.cssText;

        var prevValue = style.getPropertyValue(propName);
        var prevPriority = style.getPropertyPriority(propName);

        style.removeProperty(propName);

        if (propName)
            Events.dispatch(this.fbListeners, "onCSSRemoveProperty", [style, propName, prevValue,
                prevPriority, rule, baseText]);
    },

    /**
     * Method for atomic property removal, such as through the context menu.
     */
    deleteProperty: function(rule, propName, context)
    {
        Events.dispatch(this.fbListeners, "onBeginFirebugChange", [rule, context]);
        Firebug.CSSModule.removeProperty(rule, propName);
        Events.dispatch(this.fbListeners, "onEndFirebugChange", [rule, context]);
    },

    disableProperty: function(disable, rule, propName, parsedValue, map, context)
    {
        Events.dispatch(this.fbListeners, "onBeginFirebugChange", [rule, context]);

        if (disable)
        {
            Firebug.CSSModule.removeProperty(rule, propName);

            map.push({"name": propName, "value": parsedValue.value,
                "important": parsedValue.priority});
        }
        else
        {
            Firebug.CSSModule.setProperty(rule, propName, parsedValue.value, parsedValue.priority);

            var index = findPropByName(map, propName);
            map.splice(index, 1);
        }

        Events.dispatch(this.fbListeners, "onEndFirebugChange", [rule, context]);
    },

    /**
     * Get a document's temporary stylesheet for storage of user-provided rules.
     * If it doesn't exist yet, create it.
     */
    getDefaultStyleSheet: function(doc)
    {
        // Cache the temporary sheet on an expando of the document.
        var sheet = doc.fbDefaultSheet;
        if (!sheet)
        {
            sheet = Css.appendStylesheet(doc, "chrome://firebug/default-stylesheet.css").sheet;
            sheet.defaultStylesheet = true;
            doc.fbDefaultSheet = sheet;
        }
        return sheet;
    },

    parseCSSValue: function(value, offset)
    {
        var start = 0;
        var m;
        while (true)
        {
            m = reSplitCSS.exec(value);
            if (m && m.index + m[0].length < offset)
            {
                value = value.substr(m.index + m[0].length);
                start += m.index + m[0].length;
                offset -= m.index + m[0].length;
            }
            else
                break;
        }

        if (!m)
            return;

        var type;
        if (m[1])
            type = "url";
        else if (m[3] || m[4])
            type = "rgb";
        else if (m[5])
            type = "hsl";
        else if (m[6])
            type = "int";

        var cssValue = {
            value: m[0],
            start: start + m.index,
            end: start + m.index + m[0].length,
            type: type
        };

        if (!type)
        {
            if (m[11] && m[11].contains("gradient"))
            {
                var arg = value.substr(m[0].length).match(/\((?:(?:[^\(\)]*)|(?:\(.*?\)))+\)/);
                if (!arg)
                  return;

                cssValue.value += arg[0];
                cssValue.type = "gradient";
            }
            else if (Css.isColorKeyword(cssValue.value))
            {
                cssValue.type = "colorKeyword";
            }
        }

        return cssValue;
    },

    parseCSSFontFamilyValue: function(value, offset, propName)
    {
        var skipped = 0;
        if (propName === "font")
        {
            var rePreFont = new RegExp(
                "^.*" + // anything, then
                "(" +
                    "\\d+(\\.\\d+)?([a-z]*|%)|" + // a number (with possible unit)
                    "(x{1,2}-)?(small|large)|medium|larger|smaller" + // or an named size description
                ") "
            );
            var m = rePreFont.exec(value);
            if (!m || offset < m[0].length)
                return this.parseCSSValue(value, offset);
            skipped = m[0].length;
            value = value.substr(skipped);
            offset -= skipped;
        }

        var matches = /^(.*?)(\s*!.*)?$/.exec(value);
        var fonts = matches[1].split(",");

        var totalLength = 0;
        for (var i = 0; i < fonts.length; ++i)
        {
            totalLength += fonts[i].length;
            if (offset <= totalLength)
            {
                // Give back the value and location of this font, whitespace-trimmed.
                var font = fonts[i].replace(/^\s+/, "");
                var end = totalLength;
                var start = end - font.length;
                return {
                    value: font,
                    start: start + skipped,
                    end: end + skipped,
                    type: "fontFamily"
                };
            }

            // include ","
            ++totalLength;
        }

        // Parse !important.
        var ret = this.parseCSSValue(value, offset);
        if (ret)
        {
            ret.start += skipped;
            ret.end += skipped;
        }
        return ret;
    },

    parseURLValue: function(value)
    {
        var m = reURL.exec(value);
        // URLs can contain characters like a single quote, which are escaped,
        // so we need to strip the backslash in order to get the valid URL
        return m ? m[2].replace("\\", "") : "";
    },

    parseRepeatValue: function(value)
    {
        var m = reRepeat.exec(value);
        return m ? m[0] : "";
    },

    getPropertyInfo: function(computedStyle, propName)
    {
        var propInfo = {
            property: propName,
            value: computedStyle.getPropertyValue(propName),
            matchedSelectors: [],
            matchedRuleCount: 0
        };

        return propInfo;
    },

    getColorDisplayOptionMenuItems: function()
    {
        return [
            "-",
            {
                label: "computed.option.label.Colors_As_Authored",
                tooltiptext: "computed.option.tip.Colors_As_Authored",
                type: "radio",
                name: "colorDisplay",
                id: "colorDisplayAuthored",
                command: function() {
                    return Options.set("colorDisplay", "authored");
                },
                checked: Options.get("colorDisplay") == "authored"
            },
            {
                label: "computed.option.label.Colors_As_Hex",
                tooltiptext: "computed.option.tip.Colors_As_Hex",
                type: "radio",
                name: "colorDisplay",
                id: "colorDisplayHex",
                command: function() {
                    return Options.set("colorDisplay", "hex");
                },
                checked: Options.get("colorDisplay") == "hex"
            },
            {
                label: "computed.option.label.Colors_As_RGB",
                tooltiptext: "computed.option.tip.Colors_As_RGB",
                type: "radio",
                name: "colorDisplay",
                id: "colorDisplayRGB",
                command: function() {
                    return Options.set("colorDisplay", "rgb");
                },
                checked: Options.get("colorDisplay") == "rgb"
            },
            {
                label: "computed.option.label.Colors_As_HSL",
                tooltiptext: "computed.option.tip.Colors_As_HSL",
                type: "radio",
                name: "colorDisplay",
                id: "colorDisplayHSL",
                command: function() {
                    return Options.set("colorDisplay", "hsl");
                },
                checked: Options.get("colorDisplay") == "hsl"
            }
        ];
    },
});

// ********************************************************************************************* //
// Helpers

function getStyleSheetOwnerNode(sheet)
{
    for (; sheet && !sheet.ownerNode; sheet = sheet.parentStyleSheet);

    return sheet.ownerNode;
}

function findPropByName(props, name)
{
    for (var i = 0; i < props.length; ++i)
    {
        if (props[i].name == name)
            return i;
    }
}

// ********************************************************************************************* //
// Registration

Firebug.registerModule(Firebug.CSSModule);

return Firebug.CSSModule;

// ********************************************************************************************* //
});
<commit_msg>Fixed regular expression matching CSS values (fixes FBTest css/5177/issue5177.js)<commit_after>/* See license.txt for terms of usage */

define([
    "firebug/firebug",
    "firebug/lib/css",
    "firebug/lib/events",
    "firebug/lib/object",
    "firebug/lib/options",
    "firebug/lib/xpcom",
    "firebug/chrome/module",
    "firebug/css/cssDirtyListener",
    "firebug/editor/editorSelector"
],
function(Firebug, Css, Events, Obj, Options, Xpcom, Module, CSSDirtyListener, EditorSelector) {

// ********************************************************************************************* //
// Constants

var Cc = Components.classes;
var Ci = Components.interfaces;

var reSplitCSS = /(url\((")?.*?\2\))|(rgba?\([^)]*\)?)|(#[\dA-Fa-f]+)|(hsla?\([^)]*\)?)|(-?\d+(\.\d+)?(%|[a-z]{1,4})?)|"([^"]*)"?|'([^']*)'?|([^,\s\/!\(\)]+)|(!(.*)?)/;
var reURL = /url\((")?(.*)?\1\)/;
var reRepeat = /no-repeat|repeat-x|repeat-y|repeat/;

// ********************************************************************************************* //
// CSS Module

Firebug.CSSModule = Obj.extend(Module, Firebug.EditorSelector,
{
    dispatchName: "cssModule",

    // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
    // Module

    initialize: function()
    {
        this.editors = {};
        this.registerEditor("Live",
        {
            startEditing: function(stylesheet, context, panel)
            {
                panel.startLiveEditing(stylesheet, context);
            },
            stopEditing: function()
            {
                Firebug.Editor.stopEditing();
            }
        });

        this.registerEditor("Source",
        {
            startEditing: function(stylesheet, context, panel)
            {
                panel.startSourceEditing(stylesheet, context);
            },
            stopEditing: function()
            {
                Firebug.Editor.stopEditing();
            }
        });
    },

    initContext: function(context)
    {
        context.dirtyListener = new CSSDirtyListener(context);
        this.addListener(context.dirtyListener);
    },

    destroyContext: function(context)
    {
        this.removeListener(context.dirtyListener);
    },

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

    freeEdit: function(styleSheet, value)
    {
        if (FBTrace.DBG_CSS)
            FBTrace.sysout("CSSModule.freeEdit", arguments);

        if (!styleSheet.editStyleSheet)
        {
            var ownerNode = getStyleSheetOwnerNode(styleSheet);
            styleSheet.disabled = true;

            var url = Xpcom.CCSV("@mozilla.org/network/standard-url;1", Ci.nsIURL);
            url.spec = styleSheet.href;

            var editStyleSheet = ownerNode.ownerDocument.createElementNS(
                "http://www.w3.org/1999/xhtml",
                "style");

            Firebug.setIgnored(editStyleSheet);

            editStyleSheet.setAttribute("type", "text/css");
            editStyleSheet.setAttributeNS(
                "http://www.w3.org/XML/1998/namespace",
                "base",
                url.directory);

            if (ownerNode.hasAttribute("media"))
                editStyleSheet.setAttribute("media", ownerNode.getAttribute("media"));

            // Insert the edited stylesheet directly after the old one to ensure the styles
            // cascade properly.
            ownerNode.parentNode.insertBefore(editStyleSheet, ownerNode.nextSibling);

            styleSheet.editStyleSheet = editStyleSheet;
        }

        styleSheet.editStyleSheet.textContent = value;

        if (FBTrace.DBG_CSS)
            FBTrace.sysout("css.saveEdit styleSheet.href:" + styleSheet.href +
                " got innerHTML:" + value);

        Events.dispatch(this.fbListeners, "onCSSFreeEdit", [styleSheet, value]);
    },

    insertRule: function(styleSheet, cssText, ruleIndex)
    {
        if (FBTrace.DBG_CSS)
            FBTrace.sysout("Insert: " + ruleIndex + " " + cssText);

        var insertIndex = styleSheet.insertRule(cssText, ruleIndex);

        Events.dispatch(this.fbListeners, "onCSSInsertRule", [styleSheet, cssText, ruleIndex]);

        return insertIndex;
    },

    deleteRule: function(src, ruleIndex)
    {
        var inlineStyle = (src instanceof window.Element);
        if (FBTrace.DBG_CSS)
        {
            if (inlineStyle)
            {
                FBTrace.sysout("deleteRule: element.style", src);
            }
            else
            {
                FBTrace.sysout("deleteRule: " + ruleIndex + " " + src.cssRules.length,
                    src.cssRules);
            }
        }

        var rule = (inlineStyle ? src : src.cssRules[ruleIndex]);
        var afterParams = [src, rule.style.cssText];
        afterParams.push(inlineStyle ? "" : rule.selectorText);

        Events.dispatch(this.fbListeners, "onCSSDeleteRule", [src, ruleIndex]);

        if (src instanceof window.Element)
            src.removeAttribute("style");
        else
            src.deleteRule(ruleIndex);

        Events.dispatch(this.fbListeners, "onAfterCSSDeleteRule", afterParams);
    },

    setProperty: function(rule, propName, propValue, propPriority)
    {
        var style = rule.style || rule;

        // Record the original CSS text for the inline case so we can reconstruct at a later
        // point for diffing purposes
        var baseText = style.cssText;

        var prevValue = style.getPropertyValue(propName);
        var prevPriority = style.getPropertyPriority(propName);

        // XXXjoe Gecko bug workaround: Just changing priority doesn't have any effect
        // unless we remove the property first
        style.removeProperty(propName);

        style.setProperty(propName, propValue, propPriority);

        if (propName)
        {
            Events.dispatch(this.fbListeners, "onCSSSetProperty", [style, propName, propValue,
                propPriority, prevValue, prevPriority, rule, baseText]);
        }
    },

    removeProperty: function(rule, propName, parent)
    {
        var style = rule.style || rule;

        // Record the original CSS text for the inline case so we can reconstruct at a later
        // point for diffing purposes
        var baseText = style.cssText;

        var prevValue = style.getPropertyValue(propName);
        var prevPriority = style.getPropertyPriority(propName);

        style.removeProperty(propName);

        if (propName)
            Events.dispatch(this.fbListeners, "onCSSRemoveProperty", [style, propName, prevValue,
                prevPriority, rule, baseText]);
    },

    /**
     * Method for atomic property removal, such as through the context menu.
     */
    deleteProperty: function(rule, propName, context)
    {
        Events.dispatch(this.fbListeners, "onBeginFirebugChange", [rule, context]);
        Firebug.CSSModule.removeProperty(rule, propName);
        Events.dispatch(this.fbListeners, "onEndFirebugChange", [rule, context]);
    },

    disableProperty: function(disable, rule, propName, parsedValue, map, context)
    {
        Events.dispatch(this.fbListeners, "onBeginFirebugChange", [rule, context]);

        if (disable)
        {
            Firebug.CSSModule.removeProperty(rule, propName);

            map.push({"name": propName, "value": parsedValue.value,
                "important": parsedValue.priority});
        }
        else
        {
            Firebug.CSSModule.setProperty(rule, propName, parsedValue.value, parsedValue.priority);

            var index = findPropByName(map, propName);
            map.splice(index, 1);
        }

        Events.dispatch(this.fbListeners, "onEndFirebugChange", [rule, context]);
    },

    /**
     * Get a document's temporary stylesheet for storage of user-provided rules.
     * If it doesn't exist yet, create it.
     */
    getDefaultStyleSheet: function(doc)
    {
        // Cache the temporary sheet on an expando of the document.
        var sheet = doc.fbDefaultSheet;
        if (!sheet)
        {
            sheet = Css.appendStylesheet(doc, "chrome://firebug/default-stylesheet.css").sheet;
            sheet.defaultStylesheet = true;
            doc.fbDefaultSheet = sheet;
        }
        return sheet;
    },

    parseCSSValue: function(value, offset)
    {
        var start = 0;
        var m;
        while (true)
        {
            m = reSplitCSS.exec(value);
            if (m && m.index + m[0].length < offset)
            {
                value = value.substr(m.index + m[0].length);
                start += m.index + m[0].length;
                offset -= m.index + m[0].length;
            }
            else
                break;
        }

        if (!m)
            return;

        var type;
        if (m[1])
            type = "url";
        else if (m[3] || m[4])
            type = "rgb";
        else if (m[5])
            type = "hsl";
        else if (m[6])
            type = "int";

        var cssValue = {
            value: m[0],
            start: start + m.index,
            end: start + m.index + m[0].length,
            type: type
        };

        if (!type)
        {
            if (m[11] && m[11].contains("gradient"))
            {
                var arg = value.substr(m[0].length).match(/\((?:(?:[^\(\)]*)|(?:\(.*?\)))+\)/);
                if (!arg)
                  return;

                cssValue.value += arg[0];
                cssValue.type = "gradient";
            }
            else if (Css.isColorKeyword(cssValue.value))
            {
                cssValue.type = "colorKeyword";
            }
        }

        return cssValue;
    },

    parseCSSFontFamilyValue: function(value, offset, propName)
    {
        var skipped = 0;
        if (propName === "font")
        {
            var rePreFont = new RegExp(
                "^.*" + // anything, then
                "(" +
                    "\\d+(\\.\\d+)?([a-z]*|%)|" + // a number (with possible unit)
                    "(x{1,2}-)?(small|large)|medium|larger|smaller" + // or an named size description
                ") "
            );
            var m = rePreFont.exec(value);
            if (!m || offset < m[0].length)
                return this.parseCSSValue(value, offset);
            skipped = m[0].length;
            value = value.substr(skipped);
            offset -= skipped;
        }

        var matches = /^(.*?)(\s*!.*)?$/.exec(value);
        var fonts = matches[1].split(",");

        var totalLength = 0;
        for (var i = 0; i < fonts.length; ++i)
        {
            totalLength += fonts[i].length;
            if (offset <= totalLength)
            {
                // Give back the value and location of this font, whitespace-trimmed.
                var font = fonts[i].replace(/^\s+/, "");
                var end = totalLength;
                var start = end - font.length;
                return {
                    value: font,
                    start: start + skipped,
                    end: end + skipped,
                    type: "fontFamily"
                };
            }

            // include ","
            ++totalLength;
        }

        // Parse !important.
        var ret = this.parseCSSValue(value, offset);
        if (ret)
        {
            ret.start += skipped;
            ret.end += skipped;
        }
        return ret;
    },

    parseURLValue: function(value)
    {
        var m = reURL.exec(value);
        // URLs can contain characters like a single quote, which are escaped,
        // so we need to strip the backslash in order to get the valid URL
        return m ? m[2].replace("\\", "") : "";
    },

    parseRepeatValue: function(value)
    {
        var m = reRepeat.exec(value);
        return m ? m[0] : "";
    },

    getPropertyInfo: function(computedStyle, propName)
    {
        var propInfo = {
            property: propName,
            value: computedStyle.getPropertyValue(propName),
            matchedSelectors: [],
            matchedRuleCount: 0
        };

        return propInfo;
    },

    getColorDisplayOptionMenuItems: function()
    {
        return [
            "-",
            {
                label: "computed.option.label.Colors_As_Authored",
                tooltiptext: "computed.option.tip.Colors_As_Authored",
                type: "radio",
                name: "colorDisplay",
                id: "colorDisplayAuthored",
                command: function() {
                    return Options.set("colorDisplay", "authored");
                },
                checked: Options.get("colorDisplay") == "authored"
            },
            {
                label: "computed.option.label.Colors_As_Hex",
                tooltiptext: "computed.option.tip.Colors_As_Hex",
                type: "radio",
                name: "colorDisplay",
                id: "colorDisplayHex",
                command: function() {
                    return Options.set("colorDisplay", "hex");
                },
                checked: Options.get("colorDisplay") == "hex"
            },
            {
                label: "computed.option.label.Colors_As_RGB",
                tooltiptext: "computed.option.tip.Colors_As_RGB",
                type: "radio",
                name: "colorDisplay",
                id: "colorDisplayRGB",
                command: function() {
                    return Options.set("colorDisplay", "rgb");
                },
                checked: Options.get("colorDisplay") == "rgb"
            },
            {
                label: "computed.option.label.Colors_As_HSL",
                tooltiptext: "computed.option.tip.Colors_As_HSL",
                type: "radio",
                name: "colorDisplay",
                id: "colorDisplayHSL",
                command: function() {
                    return Options.set("colorDisplay", "hsl");
                },
                checked: Options.get("colorDisplay") == "hsl"
            }
        ];
    },
});

// ********************************************************************************************* //
// Helpers

function getStyleSheetOwnerNode(sheet)
{
    for (; sheet && !sheet.ownerNode; sheet = sheet.parentStyleSheet);

    return sheet.ownerNode;
}

function findPropByName(props, name)
{
    for (var i = 0; i < props.length; ++i)
    {
        if (props[i].name == name)
            return i;
    }
}

// ********************************************************************************************* //
// Registration

Firebug.registerModule(Firebug.CSSModule);

return Firebug.CSSModule;

// ********************************************************************************************* //
});
<|endoftext|>


<commit_before>'use strict'

var agent = require('../../..').start({
  appId: 'test',
  organizationId: 'test',
  secretToken: 'test',
  captureExceptions: false
})

var test = require('tape')
var exec = require('child_process').exec
var mysql = require('mysql')

var connection

test('mysql.createConnection', function (t) {
  t.test('basic query with callback', function (t) {
    t.test('connection.query(sql, callback)', function (t) {
      resetAgent(function (endpoint, data, cb) {
        assertBasicQuery(t, sql, data)
        t.end()
      })
      var sql = 'SELECT 1 + 1 AS solution'
      setup(function () {
        var trans = agent.startTransaction('foo')
        connection.query(sql, basicQueryCallback(t, trans))
      })
    })

    t.test('connection.query(sql, values, callback)', function (t) {
      resetAgent(function (endpoint, data, cb) {
        assertBasicQuery(t, sql, data)
        t.end()
      })
      var sql = 'SELECT 1 + ? AS solution'
      setup(function () {
        var trans = agent.startTransaction('foo')
        connection.query(sql, [1], basicQueryCallback(t, trans))
      })
    })

    t.test('connection.query(options, callback)', function (t) {
      resetAgent(function (endpoint, data, cb) {
        assertBasicQuery(t, sql, data)
        t.end()
      })
      var sql = 'SELECT 1 + 1 AS solution'
      setup(function () {
        var trans = agent.startTransaction('foo')
        connection.query({ sql: sql }, basicQueryCallback(t, trans))
      })
    })

    t.test('connection.query(options, values, callback)', function (t) {
      resetAgent(function (endpoint, data, cb) {
        assertBasicQuery(t, sql, data)
        t.end()
      })
      var sql = 'SELECT 1 + ? AS solution'
      setup(function () {
        var trans = agent.startTransaction('foo')
        connection.query({ sql: sql }, [1], basicQueryCallback(t, trans))
      })
    })

    t.test('connection.query(query)', function (t) {
      resetAgent(function (endpoint, data, cb) {
        assertBasicQuery(t, sql, data)
        t.end()
      })
      var sql = 'SELECT 1 + 1 AS solution'
      setup(function () {
        var trans = agent.startTransaction('foo')
        var query = mysql.createQuery(sql, basicQueryCallback(t, trans))
        connection.query(query)
      })
    })

    t.test('connection.query(query_with_values)', function (t) {
      resetAgent(function (endpoint, data, cb) {
        assertBasicQuery(t, sql, data)
        t.end()
      })
      var sql = 'SELECT 1 + ? AS solution'
      setup(function () {
        var trans = agent.startTransaction('foo')
        var query = mysql.createQuery(sql, [1], basicQueryCallback(t, trans))
        connection.query(query)
      })
    })
  })

  t.test('basic query streaming', function (t) {
    t.test('connection.query(sql)', function (t) {
      resetAgent(function (endpoint, data, cb) {
        assertBasicQuery(t, sql, data)
        t.end()
      })
      var sql = 'SELECT 1 + 1 AS solution'
      setup(function () {
        var trans = agent.startTransaction('foo')
        var stream = connection.query(sql)
        basicQueryStream(stream, t, trans)
      })
    })

    t.test('connection.query(sql, values)', function (t) {
      resetAgent(function (endpoint, data, cb) {
        assertBasicQuery(t, sql, data)
        t.end()
      })
      var sql = 'SELECT 1 + ? AS solution'
      setup(function () {
        var trans = agent.startTransaction('foo')
        var stream = connection.query(sql, [1])
        basicQueryStream(stream, t, trans)
      })
    })

    t.test('connection.query(options)', function (t) {
      resetAgent(function (endpoint, data, cb) {
        assertBasicQuery(t, sql, data)
        t.end()
      })
      var sql = 'SELECT 1 + 1 AS solution'
      setup(function () {
        var trans = agent.startTransaction('foo')
        var stream = connection.query({ sql: sql })
        basicQueryStream(stream, t, trans)
      })
    })

    t.test('connection.query(options, values)', function (t) {
      resetAgent(function (endpoint, data, cb) {
        assertBasicQuery(t, sql, data)
        t.end()
      })
      var sql = 'SELECT 1 + ? AS solution'
      setup(function () {
        var trans = agent.startTransaction('foo')
        var stream = connection.query({ sql: sql }, [1])
        basicQueryStream(stream, t, trans)
      })
    })

    t.test('connection.query(query)', function (t) {
      resetAgent(function (endpoint, data, cb) {
        assertBasicQuery(t, sql, data)
        t.end()
      })
      var sql = 'SELECT 1 + 1 AS solution'
      setup(function () {
        var trans = agent.startTransaction('foo')
        var query = mysql.createQuery(sql)
        var stream = connection.query(query)
        basicQueryStream(stream, t, trans)
      })
    })

    t.test('connection.query(query_with_values)', function (t) {
      resetAgent(function (endpoint, data, cb) {
        assertBasicQuery(t, sql, data)
        t.end()
      })
      var sql = 'SELECT 1 + ? AS solution'
      setup(function () {
        var trans = agent.startTransaction('foo')
        var query = mysql.createQuery(sql, [1])
        var stream = connection.query(query)
        basicQueryStream(stream, t, trans)
      })
    })
  })
})

function basicQueryCallback (t, trans) {
  return function (err, rows, fields) {
    t.error(err)
    t.equal(rows[0].solution, 2)
    trans.end()
    agent._instrumentation._send()
  }
}

function basicQueryStream (stream, t, trans) {
  var results = 0
  stream.on('error', function (err) {
    t.error(err)
  })
  stream.on('result', function (row) {
    results++
    t.equal(row.solution, 2)
  })
  stream.on('end', function () {
    t.equal(results, 1)
    trans.end()
    agent._instrumentation._send()
  })
}

function assertBasicQuery (t, sql, data) {
  t.equal(data.traces.groups.length, 2)

  t.equal(data.traces.groups[0].extra.sql, sql)
  t.equal(data.traces.groups[0].kind, 'db.mysql.query')
  t.deepEqual(data.traces.groups[0].parents, ['transaction'])
  t.equal(data.traces.groups[0].signature, 'SELECT')
  t.equal(data.traces.groups[0].transaction, 'foo')

  t.equal(data.traces.groups[1].kind, 'transaction')
  t.deepEqual(data.traces.groups[1].parents, [])
  t.equal(data.traces.groups[1].signature, 'transaction')
  t.equal(data.traces.groups[1].transaction, 'foo')

  t.equal(data.transactions.length, 1)
  t.equal(data.transactions[0].transaction, 'foo')
  t.equal(data.transactions[0].durations.length, 1)
  t.ok(data.transactions[0].durations[0] > 0)
}

function setup (cb) {
  teardown() // just in case it didn't happen at the end of the previous test
  exec('mysql -u root < mysql_reset.sql', { cwd: __dirname }, function (err) {
    if (err) throw err
    connection = mysql.createConnection({
      user: 'root',
      database: 'test_opbeat'
    })
    connection.connect()
    cb()
  })
}

function teardown () {
  if (connection) {
    connection.end()
    connection = undefined
  }
}

function resetAgent (cb) {
  agent._httpClient = { request: function () {
    teardown()
    cb.apply(this, arguments)
  } }

  var ins = agent._instrumentation
  if (ins._timeout) {
    clearTimeout(ins._timeout)
    ins._timeout = null
  }
  ins._queue = []
}
<commit_msg>Add mysql test for when not consuming the query result<commit_after>'use strict'

var agent = require('../../..').start({
  appId: 'test',
  organizationId: 'test',
  secretToken: 'test',
  captureExceptions: false
})

var test = require('tape')
var exec = require('child_process').exec
var mysql = require('mysql')

var connection

test('mysql.createConnection', function (t) {
  t.test('basic query with callback', function (t) {
    t.test('connection.query(sql, callback)', function (t) {
      resetAgent(function (endpoint, data, cb) {
        assertBasicQuery(t, sql, data)
        t.end()
      })
      var sql = 'SELECT 1 + 1 AS solution'
      setup(function () {
        var trans = agent.startTransaction('foo')
        connection.query(sql, basicQueryCallback(t, trans))
      })
    })

    t.test('connection.query(sql, values, callback)', function (t) {
      resetAgent(function (endpoint, data, cb) {
        assertBasicQuery(t, sql, data)
        t.end()
      })
      var sql = 'SELECT 1 + ? AS solution'
      setup(function () {
        var trans = agent.startTransaction('foo')
        connection.query(sql, [1], basicQueryCallback(t, trans))
      })
    })

    t.test('connection.query(options, callback)', function (t) {
      resetAgent(function (endpoint, data, cb) {
        assertBasicQuery(t, sql, data)
        t.end()
      })
      var sql = 'SELECT 1 + 1 AS solution'
      setup(function () {
        var trans = agent.startTransaction('foo')
        connection.query({ sql: sql }, basicQueryCallback(t, trans))
      })
    })

    t.test('connection.query(options, values, callback)', function (t) {
      resetAgent(function (endpoint, data, cb) {
        assertBasicQuery(t, sql, data)
        t.end()
      })
      var sql = 'SELECT 1 + ? AS solution'
      setup(function () {
        var trans = agent.startTransaction('foo')
        connection.query({ sql: sql }, [1], basicQueryCallback(t, trans))
      })
    })

    t.test('connection.query(query)', function (t) {
      resetAgent(function (endpoint, data, cb) {
        assertBasicQuery(t, sql, data)
        t.end()
      })
      var sql = 'SELECT 1 + 1 AS solution'
      setup(function () {
        var trans = agent.startTransaction('foo')
        var query = mysql.createQuery(sql, basicQueryCallback(t, trans))
        connection.query(query)
      })
    })

    t.test('connection.query(query_with_values)', function (t) {
      resetAgent(function (endpoint, data, cb) {
        assertBasicQuery(t, sql, data)
        t.end()
      })
      var sql = 'SELECT 1 + ? AS solution'
      setup(function () {
        var trans = agent.startTransaction('foo')
        var query = mysql.createQuery(sql, [1], basicQueryCallback(t, trans))
        connection.query(query)
      })
    })
  })

  t.test('basic query streaming', function (t) {
    t.test('connection.query(sql)', function (t) {
      resetAgent(function (endpoint, data, cb) {
        assertBasicQuery(t, sql, data)
        t.end()
      })
      var sql = 'SELECT 1 + 1 AS solution'
      setup(function () {
        var trans = agent.startTransaction('foo')
        var stream = connection.query(sql)
        basicQueryStream(stream, t, trans)
      })
    })

    t.test('connection.query(sql, values)', function (t) {
      resetAgent(function (endpoint, data, cb) {
        assertBasicQuery(t, sql, data)
        t.end()
      })
      var sql = 'SELECT 1 + ? AS solution'
      setup(function () {
        var trans = agent.startTransaction('foo')
        var stream = connection.query(sql, [1])
        basicQueryStream(stream, t, trans)
      })
    })

    t.test('connection.query(options)', function (t) {
      resetAgent(function (endpoint, data, cb) {
        assertBasicQuery(t, sql, data)
        t.end()
      })
      var sql = 'SELECT 1 + 1 AS solution'
      setup(function () {
        var trans = agent.startTransaction('foo')
        var stream = connection.query({ sql: sql })
        basicQueryStream(stream, t, trans)
      })
    })

    t.test('connection.query(options, values)', function (t) {
      resetAgent(function (endpoint, data, cb) {
        assertBasicQuery(t, sql, data)
        t.end()
      })
      var sql = 'SELECT 1 + ? AS solution'
      setup(function () {
        var trans = agent.startTransaction('foo')
        var stream = connection.query({ sql: sql }, [1])
        basicQueryStream(stream, t, trans)
      })
    })

    t.test('connection.query(query)', function (t) {
      resetAgent(function (endpoint, data, cb) {
        assertBasicQuery(t, sql, data)
        t.end()
      })
      var sql = 'SELECT 1 + 1 AS solution'
      setup(function () {
        var trans = agent.startTransaction('foo')
        var query = mysql.createQuery(sql)
        var stream = connection.query(query)
        basicQueryStream(stream, t, trans)
      })
    })

    t.test('connection.query(query_with_values)', function (t) {
      resetAgent(function (endpoint, data, cb) {
        assertBasicQuery(t, sql, data)
        t.end()
      })
      var sql = 'SELECT 1 + ? AS solution'
      setup(function () {
        var trans = agent.startTransaction('foo')
        var query = mysql.createQuery(sql, [1])
        var stream = connection.query(query)
        basicQueryStream(stream, t, trans)
      })
    })

    t.test('do not consume stream', function (t) {
      resetAgent(function (endpoint, data, cb) {
        assertBasicQuery(t, sql, data)
        t.end()
      })
      var sql = 'SELECT 1 + 1 AS solution'
      setup(function () {
        var trans = agent.startTransaction('foo')
        connection.query(sql)
        setTimeout(function () {
          trans.end()
          agent._instrumentation._send()
        }, 100)
      })
    })
  })
})

function basicQueryCallback (t, trans) {
  return function (err, rows, fields) {
    t.error(err)
    t.equal(rows[0].solution, 2)
    trans.end()
    agent._instrumentation._send()
  }
}

function basicQueryStream (stream, t, trans) {
  var results = 0
  stream.on('error', function (err) {
    t.error(err)
  })
  stream.on('result', function (row) {
    results++
    t.equal(row.solution, 2)
  })
  stream.on('end', function () {
    t.equal(results, 1)
    trans.end()
    agent._instrumentation._send()
  })
}

function assertBasicQuery (t, sql, data) {
  t.equal(data.traces.groups.length, 2)

  t.equal(data.traces.groups[0].extra.sql, sql)
  t.equal(data.traces.groups[0].kind, 'db.mysql.query')
  t.deepEqual(data.traces.groups[0].parents, ['transaction'])
  t.equal(data.traces.groups[0].signature, 'SELECT')
  t.equal(data.traces.groups[0].transaction, 'foo')

  t.equal(data.traces.groups[1].kind, 'transaction')
  t.deepEqual(data.traces.groups[1].parents, [])
  t.equal(data.traces.groups[1].signature, 'transaction')
  t.equal(data.traces.groups[1].transaction, 'foo')

  t.equal(data.transactions.length, 1)
  t.equal(data.transactions[0].transaction, 'foo')
  t.equal(data.transactions[0].durations.length, 1)
  t.ok(data.transactions[0].durations[0] > 0)
}

function setup (cb) {
  teardown() // just in case it didn't happen at the end of the previous test
  exec('mysql -u root < mysql_reset.sql', { cwd: __dirname }, function (err) {
    if (err) throw err
    connection = mysql.createConnection({
      user: 'root',
      database: 'test_opbeat'
    })
    connection.connect()
    cb()
  })
}

function teardown () {
  if (connection) {
    connection.end()
    connection = undefined
  }
}

function resetAgent (cb) {
  agent._httpClient = { request: function () {
    teardown()
    cb.apply(this, arguments)
  } }

  var ins = agent._instrumentation
  if (ins._timeout) {
    clearTimeout(ins._timeout)
    ins._timeout = null
  }
  ins._queue = []
}
<|endoftext|>


<commit_before>(function (window, angular) {
  'use strict';

  angular.module('angular-server-form', [])
  .provider('serverForm', [function () {

    var provider = this;

    provider.errorsKey = 'errors';
    provider.logging = true;
    provider.$get = ['$http', '$q', '$log', function ($http, $q, $log) {

      // Private
      // Set error message on form value
      function setError (form, message) {
        // Only NgModelController has $render and $setViewValue
        // Don't call $setValidity on FormController
        if (form.$render || form.$setViewValue) {
          form.$setValidity('server', false);
        }
        form.$setPristine();
        form.$server = message;
      }

      // Private
      // recurse over the form
      // if the property is a value it gets assigned
      // otherwise dive inside
      function formCrawler (form) {
        var response = {};
        for (var prop in form) {
          if (form.hasOwnProperty(prop) && prop[0] !== '$') {
            if (form[prop].hasOwnProperty('$modelValue')) {
              response[prop] = form[prop].$modelValue;
            } else {
              response[prop] = formCrawler(form[prop]);
            }
          }
        }
        return response;
      }

      var self = this;

      // Serialize form to data object
      self.serialize = function serialize (form) {
        var response = {};

        // set root if form name is set
        if (form.$name) {
          response[form.$name] = formCrawler(form);
        } else {
          response = formCrawler(form);
        }
        return response;
      };

      // Apply all messages from errors object on form
      // The error value must be an array of strings or a string
      self.applyErrors = function applyErrors (form, errors) {
        if (angular.isString(errors)) {
          // If it's a string then set the error message
          setError(form, errors);
        } else if (angular.isArray(errors)) {
          // If it's an array then join them and set the error message
          setError(form, errors.join(', '));
        } else {
          // Otherwise we must crawl the errors
          for (var prop in errors) {
            if (errors.hasOwnProperty(prop)) {
              if (form.hasOwnProperty(prop)) {
                // If the form has a property with the same error name
                self.applyErrors(form[prop], errors[prop]);
              } else if (form.$name === prop) {
                // errors object is for the whole form, dive in
                self.applyErrors(form, errors[prop]);
              } else {
                if (provider.logging) {
                  $log.warn('No place to render property', prop, 'in form', form);
                }
              }
            }
          }
        }
      };

      // Crawl form and reset errors
      self.clearErrors = function clearErrors (form) {
        // Only NgModelController has $render and $setViewValue
        // Don't call $setValidity on FormController
        if (form.$render || form.$setViewValue) {
          form.$setValidity('server', true);
        }
        form.$setPristine();
        form.$server = '';

        for (var prop in form) {
          if (form.hasOwnProperty(prop) && prop[0] !== '$') {
            clearErrors(form[prop]);
          }
        }
      };

      self.submit = function submit (form, config) {
        self.clearErrors(form); // resets previous server errors
        form.$submitting = true;
        form.$saved = false;

        return $http(config)
          .success(function () {
            form.$saved = true;
          })
          .error(function(res, status) {
            form.$saved = false;
            if (status === 422) {
              if (provider.errorsKey) {
                self.applyErrors(form, res[provider.errorsKey]);
              } else {
                self.applyErrors(form, res);
              }
            }
          })
          .finally(function () {
            form.$submitting = false;
          });
      };

      return self;
    }];
  }])
  .directive('serverForm', ['serverForm', function (serverForm) {

    return {
      restrict: 'A',
      scope: {
        url: '@',
        method: '@',
        onSuccess: '=',
        onError: '='
      },
      require: 'form',
      link: function postLink(scope, iElement, iAttrs, form) {

        function submitForm (ev) {
          if (!form.$submitting) {
            var config = {
              url: scope.url,
              method: scope.method ? scope.method : 'POST',
              data: serverForm.serialize(form)
            };

            serverForm.submit(form, config)
            .then(scope.onSuccess, scope.onError);
          }

          ev.preventDefault();
          scope.$apply();
        }

        var submitting = false;

        iElement.on('submit', submitForm);
        scope.$on('destroy', function () {
          iElement.off('submit', submitForm);
        });

      }
    };
  }]);

})(window, window.angular);
<commit_msg>fix(submitForm): code should be wrapped in an $apply<commit_after>(function (window, angular) {
  'use strict';

  angular.module('angular-server-form', [])
  .provider('serverForm', [function () {

    var provider = this;

    provider.errorsKey = 'errors';
    provider.logging = true;
    provider.$get = ['$http', '$q', '$log', function ($http, $q, $log) {

      // Private
      // Set error message on form value
      function setError (form, message) {
        // Only NgModelController has $render and $setViewValue
        // Don't call $setValidity on FormController
        if (form.$render || form.$setViewValue) {
          form.$setValidity('server', false);
        }
        form.$setPristine();
        form.$server = message;
      }

      // Private
      // recurse over the form
      // if the property is a value it gets assigned
      // otherwise dive inside
      function formCrawler (form) {
        var response = {};
        for (var prop in form) {
          if (form.hasOwnProperty(prop) && prop[0] !== '$') {
            if (form[prop].hasOwnProperty('$modelValue')) {
              response[prop] = form[prop].$modelValue;
            } else {
              response[prop] = formCrawler(form[prop]);
            }
          }
        }
        return response;
      }

      var self = this;

      // Serialize form to data object
      self.serialize = function serialize (form) {
        var response = {};

        // set root if form name is set
        if (form.$name) {
          response[form.$name] = formCrawler(form);
        } else {
          response = formCrawler(form);
        }
        return response;
      };

      // Apply all messages from errors object on form
      // The error value must be an array of strings or a string
      self.applyErrors = function applyErrors (form, errors) {
        if (angular.isString(errors)) {
          // If it's a string then set the error message
          setError(form, errors);
        } else if (angular.isArray(errors)) {
          // If it's an array then join them and set the error message
          setError(form, errors.join(', '));
        } else {
          // Otherwise we must crawl the errors
          for (var prop in errors) {
            if (errors.hasOwnProperty(prop)) {
              if (form.hasOwnProperty(prop)) {
                // If the form has a property with the same error name
                self.applyErrors(form[prop], errors[prop]);
              } else if (form.$name === prop) {
                // errors object is for the whole form, dive in
                self.applyErrors(form, errors[prop]);
              } else {
                if (provider.logging) {
                  $log.warn('No place to render property', prop, 'in form', form);
                }
              }
            }
          }
        }
      };

      // Crawl form and reset errors
      self.clearErrors = function clearErrors (form) {
        // Only NgModelController has $render and $setViewValue
        // Don't call $setValidity on FormController
        if (form.$render || form.$setViewValue) {
          form.$setValidity('server', true);
        }
        form.$setPristine();
        form.$server = '';

        for (var prop in form) {
          if (form.hasOwnProperty(prop) && prop[0] !== '$') {
            clearErrors(form[prop]);
          }
        }
      };

      self.submit = function submit (form, config) {
        self.clearErrors(form); // resets previous server errors
        form.$submitting = true;
        form.$saved = false;

        return $http(config)
          .success(function () {
            form.$saved = true;
          })
          .error(function(res, status) {
            form.$saved = false;
            if (status === 422) {
              if (provider.errorsKey) {
                self.applyErrors(form, res[provider.errorsKey]);
              } else {
                self.applyErrors(form, res);
              }
            }
          })
          .finally(function () {
            form.$submitting = false;
          });
      };

      return self;
    }];
  }])
  .directive('serverForm', ['serverForm', function (serverForm) {

    return {
      restrict: 'A',
      scope: {
        url: '@',
        method: '@',
        onSuccess: '=',
        onError: '='
      },
      require: 'form',
      link: function postLink(scope, iElement, iAttrs, form) {

        function submitForm (ev) {
          scope.$apply(function () {
            if (!form.$submitting) {
              var config = {
                url: scope.url,
                method: scope.method ? scope.method : 'POST',
                data: serverForm.serialize(form)
              };

              serverForm.submit(form, config)
              .then(scope.onSuccess, scope.onError);
            }

            ev.preventDefault();
          });
        }

        iElement.on('submit', submitForm);
        scope.$on('destroy', function () {
          iElement.off('submit', submitForm);
        });

      }
    };
  }]);

})(window, window.angular);
<|endoftext|>


<commit_before>//
// [The "BSD license"]
//  Copyright (c) 2012 Terence Parr
//  Copyright (c) 2012 Sam Harwell
//  Copyright (c) 2014 Eric Vergnaud
//  All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without
//  modification, are permitted provided that the following conditions
//  are met:
//
//  1. Redistributions of source code must retain the above copyright
//     notice, this list of conditions and the following disclaimer.
//  2. Redistributions in binary form must reproduce the above copyright
//     notice, this list of conditions and the following disclaimer in the
//     documentation and/or other materials provided with the distribution.
//  3. The name of the author may not be used to endorse or promote products
//     derived from this software without specific prior written permission.
//
//  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
//  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
//  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
//  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
//  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
//  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
//  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
//  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
//  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
//  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
///

var ATNConfigSet = require('./../atn/ATNConfigSet').ATNConfigSet;
var Utils = require('./../Utils');
var Set = Utils.Set;
var MurmurHash = require('../MurmurHash').MurmurHash;

// Map a predicate to a predicted alternative.///

function PredPrediction(pred, alt) {
	this.alt = alt;
	this.pred = pred;
	return this;
}

PredPrediction.prototype.toString = function() {
	return "(" + this.pred + ", " + this.alt + ")";
};

// A DFA state represents a set of possible ATN configurations.
// As Aho, Sethi, Ullman p. 117 says "The DFA uses its state
// to keep track of all possible states the ATN can be in after
// reading each input symbol. That is to say, after reading
// input a1a2..an, the DFA is in a state that represents the
// subset T of the states of the ATN that are reachable from the
// ATN's start state along some path labeled a1a2..an."
// In conventional NFA→DFA conversion, therefore, the subset T
// would be a bitset representing the set of states the
// ATN could be in. We need to track the alt predicted by each
// state as well, however. More importantly, we need to maintain
// a stack of states, tracking the closure operations as they
// jump from rule to rule, emulating rule invocations (method calls).
// I have to add a stack to simulate the proper lookahead sequences for
// the underlying LL grammar from which the ATN was derived.
//
//
I use a set of ATNConfig objects not simple states. An ATNConfig
// is both a state (ala normal conversion) and a RuleContext describing
// the chain of rules (if any) followed to arrive at that state.

//
//
A DFA state may have multiple references to a particular state,
// but with different ATN contexts (with same or different alts)
// meaning that state was reached via a different set of rule invocations.

// /

function DFAState(stateNumber, configs) {
	if (stateNumber === null) {
		stateNumber = -1;
	}
	if (configs === null) {
		configs = new ATNConfigSet();
	}
	this.stateNumber = stateNumber;
	this.configs = configs;
	// {@code edges[symbol]} points to target of symbol. Shift up by 1 so (-1)
	// {@link Token//EOF} maps to {@code edges[0]}.
	this.edges = null;
	this.isAcceptState = false;
	// if accept state, what ttype do we match or alt do we predict?
	// This is set to {@link ATN//INVALID_ALT_NUMBER} when {@link
	// //predicates}{@code !=null} or
	// {@link //requiresFullContext}.
	this.prediction = 0;
	this.lexerActionExecutor = null;
	// Indicates that this state was created during SLL prediction that
	// discovered a conflict between the configurations in the state. Future
	// {@link ParserATNSimulator//execATN} invocations immediately jumped doing
	// full context prediction if this field is true.
	this.requiresFullContext = false;
	// During SLL parsing, this is a list of predicates associated with the
	// ATN configurations of the DFA state. When we have predicates,
	// {@link //requiresFullContext} is {@code false} since full context
	// prediction evaluates predicates
	// on-the-fly. If this is not null, then {@link //prediction} is
	// {@link ATN//INVALID_ALT_NUMBER}.
	//
	//
We only use these for non-{@link //requiresFullContext} but
	// conflicting states. That
	// means we know from the context (it's $ or we don't dip into outer
	// context) that it's an ambiguity not a conflict.

	//
	//
This list is computed by {@link
	// ParserATNSimulator//predicateDFAState}.

	this.predicates = null;
	return this;
}

// Get the set of all alts mentioned by all ATN configurations in this
// DFA state.
DFAState.prototype.getAltSet = function() {
	var alts = new Set();
	if (this.configs !== null) {
		for (var i = 0; i < this.configs.length; i++) {
			var c = this.configs[i];
			alts.add(c.alt);
		}
	}
	if (alts.length === 0) {
		return null;
	} else {
		return alts;
	}
};

// Two {@link DFAState} instances are equal if their ATN configuration sets
// are the same. This method is used to see if a state already exists.
//
//
Because the number of alternatives and number of ATN configurations are
// finite, there is a finite number of DFA states that can be processed.
// This is necessary to show that the algorithm terminates.

//
//
Cannot test the DFA state numbers here because in
// {@link ParserATNSimulator//addDFAState} we need to know if any other state
// exists that has this exact set of ATN configurations. The
// {@link //stateNumber} is irrelevant.

DFAState.prototype.equals = function(other) {
	// compare set of ATN configurations in this set with other
	if (this === other) {
		return true;
	} else if (!(other instanceof DFAState)) {
		return false;
	} else {
		return this.configs.equals(other.configs);
	}
};

DFAState.prototype.hashCode = function() {
    var hash = MurmurHash.initialize(7);
    hash = MurmurHash.update(hash, this.configs.hashCode());
    return MurmurHash.finish(hash, 1);
};

DFAState.prototype.toString = function() {
	return "" + this.stateNumber + ":" + this.configs +
			(this.isAcceptState ?
					"=>" + (this.predicates !== null ?
								this.predicates :
								this.prediction) :
					"");
};

exports.DFAState = DFAState;
exports.PredPrediction = PredPrediction;
<commit_msg>Improvement: Very small performance improvement in DFAState<commit_after>//
// [The "BSD license"]
//  Copyright (c) 2012 Terence Parr
//  Copyright (c) 2012 Sam Harwell
//  Copyright (c) 2014 Eric Vergnaud
//  All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without
//  modification, are permitted provided that the following conditions
//  are met:
//
//  1. Redistributions of source code must retain the above copyright
//     notice, this list of conditions and the following disclaimer.
//  2. Redistributions in binary form must reproduce the above copyright
//     notice, this list of conditions and the following disclaimer in the
//     documentation and/or other materials provided with the distribution.
//  3. The name of the author may not be used to endorse or promote products
//     derived from this software without specific prior written permission.
//
//  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
//  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
//  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
//  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
//  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
//  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
//  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
//  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
//  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
//  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
///

var ATNConfigSet = require('./../atn/ATNConfigSet').ATNConfigSet;
var Utils = require('./../Utils');
var Set = Utils.Set;
var MurmurHash = require('../MurmurHash').MurmurHash;

// Map a predicate to a predicted alternative.///

function PredPrediction(pred, alt) {
	this.alt = alt;
	this.pred = pred;
	return this;
}

PredPrediction.prototype.toString = function() {
	return "(" + this.pred + ", " + this.alt + ")";
};

// A DFA state represents a set of possible ATN configurations.
// As Aho, Sethi, Ullman p. 117 says "The DFA uses its state
// to keep track of all possible states the ATN can be in after
// reading each input symbol. That is to say, after reading
// input a1a2..an, the DFA is in a state that represents the
// subset T of the states of the ATN that are reachable from the
// ATN's start state along some path labeled a1a2..an."
// In conventional NFA→DFA conversion, therefore, the subset T
// would be a bitset representing the set of states the
// ATN could be in. We need to track the alt predicted by each
// state as well, however. More importantly, we need to maintain
// a stack of states, tracking the closure operations as they
// jump from rule to rule, emulating rule invocations (method calls).
// I have to add a stack to simulate the proper lookahead sequences for
// the underlying LL grammar from which the ATN was derived.
//
//
I use a set of ATNConfig objects not simple states. An ATNConfig
// is both a state (ala normal conversion) and a RuleContext describing
// the chain of rules (if any) followed to arrive at that state.

//
//
A DFA state may have multiple references to a particular state,
// but with different ATN contexts (with same or different alts)
// meaning that state was reached via a different set of rule invocations.

// /

function DFAState(stateNumber, configs) {
	this.stateNumber = (stateNumber == null) ? -1 : stateNumber;
	this.configs = (configs == null) ? new ATNConfigSet() : configs;
	// {@code edges[symbol]} points to target of symbol. Shift up by 1 so (-1)
	// {@link Token//EOF} maps to {@code edges[0]}.
	this.edges = null;
	this.isAcceptState = false;
	// if accept state, what ttype do we match or alt do we predict?
	// This is set to {@link ATN//INVALID_ALT_NUMBER} when {@link
	// //predicates}{@code !=null} or
	// {@link //requiresFullContext}.
	this.prediction = 0;
	this.lexerActionExecutor = null;
	// Indicates that this state was created during SLL prediction that
	// discovered a conflict between the configurations in the state. Future
	// {@link ParserATNSimulator//execATN} invocations immediately jumped doing
	// full context prediction if this field is true.
	this.requiresFullContext = false;
	// During SLL parsing, this is a list of predicates associated with the
	// ATN configurations of the DFA state. When we have predicates,
	// {@link //requiresFullContext} is {@code false} since full context
	// prediction evaluates predicates
	// on-the-fly. If this is not null, then {@link //prediction} is
	// {@link ATN//INVALID_ALT_NUMBER}.
	//
	//
We only use these for non-{@link //requiresFullContext} but
	// conflicting states. That
	// means we know from the context (it's $ or we don't dip into outer
	// context) that it's an ambiguity not a conflict.

	//
	//
This list is computed by {@link
	// ParserATNSimulator//predicateDFAState}.

	this.predicates = null;
	return this;
}

// Get the set of all alts mentioned by all ATN configurations in this
// DFA state.
DFAState.prototype.getAltSet = function() {
	var alts = new Set();
	if (this.configs !== null) {
		var numConfigs = this.configs.length;
		for (var i = 0; i < numConfigs; ++i) {
			alts.add(this.configs[i].alt);
		}
	}
	if (alts.length === 0) {
		return null;
	} else {
		return alts;
	}
};

// Two {@link DFAState} instances are equal if their ATN configuration sets
// are the same. This method is used to see if a state already exists.
//
//
Because the number of alternatives and number of ATN configurations are
// finite, there is a finite number of DFA states that can be processed.
// This is necessary to show that the algorithm terminates.

//
//
Cannot test the DFA state numbers here because in
// {@link ParserATNSimulator//addDFAState} we need to know if any other state
// exists that has this exact set of ATN configurations. The
// {@link //stateNumber} is irrelevant.

DFAState.prototype.equals = function(other) {
	// compare set of ATN configurations in this set with other
	if (this === other) {
		return true;
	} else if (!(other instanceof DFAState)) {
		return false;
	} else {
		return this.configs.equals(other.configs);
	}
};

DFAState.prototype.hashCode = function() {
    var hash = MurmurHash.initialize(7);
    hash = MurmurHash.update(hash, this.configs.hashCode());
    return MurmurHash.finish(hash, 1);
};

DFAState.prototype.toString = function() {
	return "" + this.stateNumber + ":" + this.configs +
			(this.isAcceptState ?
					"=>" + (this.predicates !== null ?
								this.predicates :
								this.prediction) :
					"");
};

exports.DFAState = DFAState;
exports.PredPrediction = PredPrediction;
<|endoftext|>


<commit_before>'use strict';

const childProcess = require('child_process');

module.exports = function (rootDir, type) {
    const args = Array.from(arguments).slice(2);
    /* istanbul ignore next */
    const cmd = /^win/.test(process.platform) ? 'npm.cmd' : 'npm';

    childProcess.spawnSync(
        cmd,
        ['run'].concat(getNpmCommand(type, args)),
        { stdio: 'inherit' }
    );
};

const getNpmCommand = (command, args) => {
    switch (command) {
        case 'b':
        case 'build':
            return 'build';
        case 'l':
        case 'lint':
            return 'lint';
        case 'pub':
        case 'publish':
            return ['tagVersion'].concat(args);
        case 'v':
        case 'serve':
            return 'start';
        case 't':
        case 'test':
            return ['test'].concat(args);
        default:
            return '';
    };
}
<commit_msg>Makes sure NPM commands return a promise<commit_after>'use strict';

const childProcess = require('child_process');

module.exports = function (rootDir, type) {
    const args = Array.from(arguments).slice(2);
    /* istanbul ignore next */
    const cmd = /^win/.test(process.platform) ? 'npm.cmd' : 'npm';

    return new Promise((resolve, reject) => {
        try {
            childProcess.spawnSync(
                cmd,
                ['run'].concat(getNpmCommand(type, args)),
                { stdio: 'inherit' }
            );
            resolve();
        } catch (error) {
            reject(error.message);
        }
    });
};

const getNpmCommand = (command, args) => {
    switch (command) {
        case 'b':
        case 'build':
            return 'build';
        case 'l':
        case 'lint':
            return 'lint';
        case 'pub':
        case 'publish':
            return ['tagVersion'].concat(args);
        case 'v':
        case 'serve':
            return 'start';
        case 't':
        case 'test':
            return ['test'].concat(args);
        default:
            return '';
    };
}
<|endoftext|>


<commit_before>const PersistentCollection = require("djs-collection-persistent");
const util = require('util');

var fs = require("fs");
var raidList = JSON.parse(fs.readFileSync("data/teams.json"));
var settings = require("../settings.json");

exports.run = (client, message, args) => {
    const guildSettings = client.guildSettings;
    const guildConf = guildSettings.get(message.guild.id);

    let currentPhase = "Phase 1";

    // Make sure the args are all there
    if(typeof args[0] !== 'undefined' && args[0] !== null && args[0] !== "") {
        return message.channel.send("Invalid raid, usage is \`" + settings.prefix + "raidteams [raidName] [phase]\`\n**Example:** `" + settings.prefix + "raidteams pit p1`");
    }
    if(typeof args[1] !== 'undefined' && args[1] !== null && args[1] !== "") {
        return message.channel.send("Invalid phase, usage is \`" + settings.prefix + "raidteams [raidName] [phase]\`\n**Example:** `" + settings.prefix + "raidteams pit p1`");
    }

    // Remove anything that's not a letter for the raid name
    let searchName = "";
    if(args[0]) {
        searchName = String(args[0]).toLowerCase().replace(/[^\w\s]/gi, '');
    }

    // Remove anything that's not a letter for the phase
    if(args[1]) {
        let phaseName = "";
        phaseName = String(args[1]).toLowerCase().replace(/[^\w\s]/gi, '');
        if(phaseName === "Solo") {
            currentPhase = "Solo"
        } else if(phaseName === "p1") {
            currentPhase = "Phase 1"
        } else if(phaseName === "p2") {
            currentPhase = "Phase 2"
        } else if(phaseName === "p3") {
            currentPhase = "Phase 3"
        } else if(phaseName === "p4") {
            currentPhase = "Phase 4"
        } else {
            return message.channel.send("Invalid phase, usage is \`" + settings.prefix + "raidteams [raidName] [phase]\`\n**Example:** `" + settings.prefix + "raidteams pit p1`");
        }
    }

    let found = false;
    let foundPhase = false;
    let embeds = false;

    if(guildConf['useEmbeds'] === true && message.channel.permissionsFor(client.user).has('EMBED_LINKS')) {
        embeds = true;
    }

    if(searchName !== "") {
        for(ix = 0; ix < raidList.length; ix++) {
            var raid = raidList[ix];

            if(raid.aliases.includes(searchName)) {
                // Found the raid, now just need to show it
                found = true;

                teams = raid.teams;

                if(embeds) {  // if Embeds are enabled
                    let fields = [];
                    for(raidTeam in teams) {
                        let team = raid.teams[raidTeam];

                        let phase = team.phase
                        if(phase.includes(currentPhase)) {
                            foundPhase = true;
                            let characters = team.characters
                            fields.push({
                                "name": raidTeam,
                                "value": `**Characters:** \`${team.characters.join(", ")}\``
                            });
                        }
                    }
                    footerText = `via Morningstar-013 & Pete Butler`
                    if(foundPhase) {
                        message.channel.send({embed:{ "author": {"name": raid.name}, "title": `Showing teams for ${currentPhase}`, "color": 2, "fields": fields, "footer": {"text": footerText}}});
                    } else {
                        message.channel.send(`Cannot find any teams under \`${currentPhase}\``);
                    }
                } else {  // Embeds are disabled
                    let outString = ` * ${raid.name} * \n\n* Showing teams for ${currentPhase}\n\n`
                    for(raidTeam in teams) {
                        let team = raid.teams[raidTeam];
                        let phase = team.phase;

                        if(phase.includes(currentPhase)) {// === phase.toLowerCase()) {
                            foundPhase = true;
                            outString += `### ${raidTeam} ### \n* Characters: ${team.characters.join(", ")}\n`
                        }
                    }
                    if(foundPhase) {
                    message.channel.send(outString, {code: 'md', split: true});
                    } else {
                        message.channel.send(`Cannot find any teams under \`${currentPhase}\``);
                    }
                }
            }
        }

        if(found === false) {
            message.channel.send("Invalid raid, usage is \`" + settings.prefix + "raidteams [raidName] [phase]\`\n**Example:** `" + settings.prefix + "raidteams pit p1`");
        }
    } else {
            message.channel.send("Invalid raid, usage is \`" + settings.prefix + "raidteams [raidName] [phase]\`\n**Example:** `" + settings.prefix + "raidteams pit p1`");
    }

};

exports.conf = {
    guildOnly: false,
    enabled: true,
    aliases: ['raid'],
    permLevel: 0,
    type: 'starwars'
};

exports.help = {
    name: 'raidteams',
    description: 'Shows some teams that work well for each raid.',
    usage: 'raidteams [aat|pit] [p1|p2|p3|p4|solo]',
    example: 'raidteams aat p1'
};
<commit_msg>Fixed it checking for undefined<commit_after>const PersistentCollection = require("djs-collection-persistent");
const util = require('util');

var fs = require("fs");
var raidList = JSON.parse(fs.readFileSync("data/teams.json"));
var settings = require("../settings.json");

exports.run = (client, message, args) => {
    const guildSettings = client.guildSettings;
    const guildConf = guildSettings.get(message.guild.id);

    let currentPhase = "Phase 1";

    // Make sure the args are all there
    if(typeof args[0] === 'undefined' || args[0] === null || args[0] === "") {
        return message.channel.send("Invalid raid, usage is \`" + settings.prefix + "raidteams [raidName] [phase]\`\n**Example:** `" + settings.prefix + "raidteams pit p1`");
    }
    if(typeof args[1] === 'undefined' || args[1] === null || args[1] === "") {
        return message.channel.send("Invalid phase, usage is \`" + settings.prefix + "raidteams [raidName] [phase]\`\n**Example:** `" + settings.prefix + "raidteams pit p1`");
    }

    // Remove anything that's not a letter for the raid name
    let searchName = "";
    if(args[0]) {
        searchName = String(args[0]).toLowerCase().replace(/[^\w\s]/gi, '');
    }

    // Remove anything that's not a letter for the phase
    if(args[1]) {
        let phaseName = "";
        phaseName = String(args[1]).toLowerCase().replace(/[^\w\s]/gi, '');
        if(phaseName === "Solo") {
            currentPhase = "Solo"
        } else if(phaseName === "p1") {
            currentPhase = "Phase 1"
        } else if(phaseName === "p2") {
            currentPhase = "Phase 2"
        } else if(phaseName === "p3") {
            currentPhase = "Phase 3"
        } else if(phaseName === "p4") {
            currentPhase = "Phase 4"
        } else {
            return message.channel.send("Invalid phase, usage is \`" + settings.prefix + "raidteams [raidName] [phase]\`\n**Example:** `" + settings.prefix + "raidteams pit p1`");
        }
    }

    let found = false;
    let foundPhase = false;
    let embeds = false;

    if(guildConf['useEmbeds'] === true && message.channel.permissionsFor(client.user).has('EMBED_LINKS')) {
        embeds = true;
    }

    if(searchName !== "") {
        for(ix = 0; ix < raidList.length; ix++) {
            var raid = raidList[ix];

            if(raid.aliases.includes(searchName)) {
                // Found the raid, now just need to show it
                found = true;

                teams = raid.teams;

                if(embeds) {  // if Embeds are enabled
                    let fields = [];
                    for(raidTeam in teams) {
                        let team = raid.teams[raidTeam];

                        let phase = team.phase
                        if(phase.includes(currentPhase)) {
                            foundPhase = true;
                            let characters = team.characters
                            fields.push({
                                "name": raidTeam,
                                "value": `**Characters:** \`${team.characters.join(", ")}\``
                            });
                        }
                    }
                    footerText = `via Morningstar-013 & Pete Butler`
                    if(foundPhase) {
                        message.channel.send({embed:{ "author": {"name": raid.name}, "title": `Showing teams for ${currentPhase}`, "color": 2, "fields": fields, "footer": {"text": footerText}}});
                    } else {
                        message.channel.send(`Cannot find any teams under \`${currentPhase}\``);
                    }
                } else {  // Embeds are disabled
                    let outString = ` * ${raid.name} * \n\n* Showing teams for ${currentPhase}\n\n`
                    for(raidTeam in teams) {
                        let team = raid.teams[raidTeam];
                        let phase = team.phase;

                        if(phase.includes(currentPhase)) {// === phase.toLowerCase()) {
                            foundPhase = true;
                            outString += `### ${raidTeam} ### \n* Characters: ${team.characters.join(", ")}\n`
                        }
                    }
                    if(foundPhase) {
                    message.channel.send(outString, {code: 'md', split: true});
                    } else {
                        message.channel.send(`Cannot find any teams under \`${currentPhase}\``);
                    }
                }
            }
        }

        if(found === false) {
            message.channel.send("Invalid raid, usage is \`" + settings.prefix + "raidteams [raidName] [phase]\`\n**Example:** `" + settings.prefix + "raidteams pit p1`");
        }
    } else {
            message.channel.send("Invalid raid, usage is \`" + settings.prefix + "raidteams [raidName] [phase]\`\n**Example:** `" + settings.prefix + "raidteams pit p1`");
    }

};

exports.conf = {
    guildOnly: false,
    enabled: true,
    aliases: ['raid'],
    permLevel: 0,
    type: 'starwars'
};

exports.help = {
    name: 'raidteams',
    description: 'Shows some teams that work well for each raid.',
    usage: 'raidteams [aat|pit] [p1|p2|p3|p4|solo]',
    example: 'raidteams aat p1'
};
<|endoftext|>