<commit_before>// Copyright 2014 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import AxiomError from 'axiom/core/error';
import Path from 'axiom/fs/path';
import StdioSource from 'axiom/fs/stdio_source';

import hterm from 'hterm/public';

/**
 * @constructor
 */
var TerminalView = function() {
  TerminalView.sequence++;
  this.id = 'terminal-' + TerminalView.sequence;

  this.htermElem_ = document.createElement('div');
  this.htermElem_.style.cssText = (
      'position: absolute; ' +
      'z-index: 100; ' +
      'top: 0px; ' +
      'bottom: 0px; ' +
      'height: 0px' +
      'width: 0px');

  var container = TerminalView.getIframeContainer();
  container.appendChild(this.htermElem_);

  this.hterm_ = new hterm.Terminal();
  this.hterm_.decorate(this.htermElem_);
  this.hterm_.config.set('use-default-window-copy', true);
  this.hterm_.config.set('ctrl-c-copy', true);
  this.hterm_.config.set('pass-meta-number', true);
  this.hterm_.config.set('pass-alt-number', true);
  this.hterm_.installKeyboard();
  this.hterm_.io.onVTKeystroke = this.hterm_.io.sendString =
  this.onSendString_.bind(this);
  this.hterm_.io.onTerminalResize = this.onTerminalResize_.bind(this);

  this.elem_ = null;

  this.executeContext = null;

  var viewElem = document.createElement('div');
  viewElem.style.cssText = (
      'position: absolute; ' +
      'top: 0px; ' +
      'left: 0px; ' +
      'height: 100%;' +
      'width: 100%');
  document.body.appendChild(viewElem);

  this.viewElem_ = viewElem;
  var object = document.createElement('object');
  object.style.cssText = (
      'display: block; ' +
      'position: absolute; ' +
      'top: 0; ' +
      'left: 0; ' +
      'height: 100%; ' +
      'width: 100%; ' +
      'overflow: hidden; ' +
      'pointer-events: none;');

  var onResize = function() {
    TerminalView.resizeIframes();
  }.bind(this);

  object.onload = function() {
    this.contentDocument.defaultView.addEventListener(
        'resize', onResize);
    onResize();
  };

  object.type = 'text/html';
  object.data = 'about:blank';

  this.htermElem_.followObject = object;
  this.viewElem_.appendChild(object);
};

export {TerminalView};
export default TerminalView;

TerminalView.sequence = 0;

TerminalView.raf_ = null;

TerminalView.resizeIframes = function() {
  if (TerminalView.raf_)
    return;

  TerminalView.raf_ = requestAnimationFrame(function() {
    TerminalView.raf_ = null;

    var container = TerminalView.getIframeContainer();
    for (var i = 0; i < container.children.length; i++) {
      var htermElem = container.children[i];
      var r = htermElem.followObject.getBoundingClientRect();
      htermElem.style.top = r.top + 'px';
      htermElem.style.left = r.left + 'px';
      htermElem.style.width = r.width + 'px';
      htermElem.style.height = r.height + 'px';
    }
  });
};

TerminalView.getIframeContainer = function() {
  var node = document.querySelector('#iframe-container');
  if (!node) {
    node = document.createElement('div');
    node.id = 'iframe-container';
    node.style.cssText = (
        'position: absolute; ' +
        'top: 0px; ' +
        'bottom: 0px; ' +
        'height: 0px' +
        'width: 0px');
    document.body.appendChild(node);
  }

  return node;
};

TerminalView.viewClosed = function(followObject) {
  var container = TerminalView.getIframeContainer();
  for (var i = 0; i < container.children.length; i++) {
    var htermElem = container.children[i];
    if (htermElem.followObject === followObject) {
      container.removeChild(htermElem);
      break;
    }
  }
};

TerminalView.prototype.execute = function(stdioSource, cx) {
  if (this.executeContext && this.executeContext.isEphemeral('Ready'))
    throw new AxiomError.Runtime('Already executing');

  this.stdioSource = stdioSource;
  this.stdioSource.stdout.onData.addListener(this.onStdOut_, this);
  this.stdioSource.stderr.onData.addListener(this.onStdOut_, this);
  this.stdioSource.stdout.resume();
  this.stdioSource.stderr.resume();
  this.executeContext = cx;
  this.executeContext.onClose.addListener(this.onExecuteClose_, this);
  this.executeContext.onTTYRequest.addListener(this.onTTYRequest_, this);
  this.executeContext.setTTY({
    rows: this.hterm_.io.rowCount,
    columns: this.hterm_.io.columnCount
  });

  this.executeContext.onReady.addListener(function() {
    console.log('TerminalView: execute ready');
  });

  this.executeContext.onClose.addListener(function(reason, value) {
    console.log('TerminalView: execute closed: ' + reason, value);
    this.hterm_.uninstallKeyboard();
  }.bind(this));

  this.executeContext.execute();
};

TerminalView.prototype.print = function(str) {
  this.hterm_.io.print(str);
};

TerminalView.prototype.println = function(str) {
  this.hterm_.io.println(str);
};

/**
 * Handle for inbound messages from the default command.
 */
TerminalView.prototype.onStdOut_ = function(str) {
  if (typeof str == 'string') {
    str = str.replace(/\n/g, '\r\n');
  } else {
    str = JSON.stringify(str) + '\r\n';
  }

  this.print(str);
};

/**
 * The default command exited.
 */
TerminalView.prototype.onExecuteClose_ = function(reason, value) {
  if (reason == 'ok') {
    this.println('Command exited: ' + this.executeContext.path + ', ' +
        JSON.stringify(value));

  } else {
    this.print('Error executing ' + this.executeContext.path + ': ' +
               JSON.stringify(value));
  }
};

TerminalView.prototype.onTTYRequest_ = function(request) {
  console.log('tty request');
  if (typeof request.interrupt == 'string')
    this.executeContext.setTTY({interrupt: request.interrupt});
};

/**
 * Called by hterm.Terminal.IO for keyboard events.
 *
 * We just forward them on to the default command.
 */
TerminalView.prototype.onSendString_ = function(str) {
  if (this.executeContext.isEphemeral('Ready')) {
    var interruptChar = this.executeContext.getTTY().getInterrupt();
    if (interruptChar && str == interruptChar) {
      console.log('interrupt');
      this.executeContext.signal('interrupt');
    } else {
      this.stdioSource.stdin.write(str);
    }
  } else {
    console.warn('Execute not ready, ignoring input: ' + str);
  }
};

/**
 * Called by hterm.Terminal.IO when the terminal size changes.
 *
 * We just forward them on to the default command.
 */
TerminalView.prototype.onTerminalResize_ = function(columns, rows) {
  if (this.executeContext && this.executeContext.isEphemeral('Ready'))
    this.executeContext.setTTY({columns: columns, rows: rows});
};
<commit_msg>Fix call to "signal".<commit_after>// Copyright 2014 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import AxiomError from 'axiom/core/error';
import Path from 'axiom/fs/path';
import StdioSource from 'axiom/fs/stdio_source';

import hterm from 'hterm/public';

/**
 * @constructor
 */
var TerminalView = function() {
  TerminalView.sequence++;
  this.id = 'terminal-' + TerminalView.sequence;

  this.htermElem_ = document.createElement('div');
  this.htermElem_.style.cssText = (
      'position: absolute; ' +
      'z-index: 100; ' +
      'top: 0px; ' +
      'bottom: 0px; ' +
      'height: 0px' +
      'width: 0px');

  var container = TerminalView.getIframeContainer();
  container.appendChild(this.htermElem_);

  this.hterm_ = new hterm.Terminal();
  this.hterm_.decorate(this.htermElem_);
  this.hterm_.config.set('use-default-window-copy', true);
  this.hterm_.config.set('ctrl-c-copy', true);
  this.hterm_.config.set('pass-meta-number', true);
  this.hterm_.config.set('pass-alt-number', true);
  this.hterm_.installKeyboard();
  this.hterm_.io.onVTKeystroke = this.hterm_.io.sendString =
  this.onSendString_.bind(this);
  this.hterm_.io.onTerminalResize = this.onTerminalResize_.bind(this);

  this.elem_ = null;

  this.executeContext = null;

  var viewElem = document.createElement('div');
  viewElem.style.cssText = (
      'position: absolute; ' +
      'top: 0px; ' +
      'left: 0px; ' +
      'height: 100%;' +
      'width: 100%');
  document.body.appendChild(viewElem);

  this.viewElem_ = viewElem;
  var object = document.createElement('object');
  object.style.cssText = (
      'display: block; ' +
      'position: absolute; ' +
      'top: 0; ' +
      'left: 0; ' +
      'height: 100%; ' +
      'width: 100%; ' +
      'overflow: hidden; ' +
      'pointer-events: none;');

  var onResize = function() {
    TerminalView.resizeIframes();
  }.bind(this);

  object.onload = function() {
    this.contentDocument.defaultView.addEventListener(
        'resize', onResize);
    onResize();
  };

  object.type = 'text/html';
  object.data = 'about:blank';

  this.htermElem_.followObject = object;
  this.viewElem_.appendChild(object);
};

export {TerminalView};
export default TerminalView;

TerminalView.sequence = 0;

TerminalView.raf_ = null;

TerminalView.resizeIframes = function() {
  if (TerminalView.raf_)
    return;

  TerminalView.raf_ = requestAnimationFrame(function() {
    TerminalView.raf_ = null;

    var container = TerminalView.getIframeContainer();
    for (var i = 0; i < container.children.length; i++) {
      var htermElem = container.children[i];
      var r = htermElem.followObject.getBoundingClientRect();
      htermElem.style.top = r.top + 'px';
      htermElem.style.left = r.left + 'px';
      htermElem.style.width = r.width + 'px';
      htermElem.style.height = r.height + 'px';
    }
  });
};

TerminalView.getIframeContainer = function() {
  var node = document.querySelector('#iframe-container');
  if (!node) {
    node = document.createElement('div');
    node.id = 'iframe-container';
    node.style.cssText = (
        'position: absolute; ' +
        'top: 0px; ' +
        'bottom: 0px; ' +
        'height: 0px' +
        'width: 0px');
    document.body.appendChild(node);
  }

  return node;
};

TerminalView.viewClosed = function(followObject) {
  var container = TerminalView.getIframeContainer();
  for (var i = 0; i < container.children.length; i++) {
    var htermElem = container.children[i];
    if (htermElem.followObject === followObject) {
      container.removeChild(htermElem);
      break;
    }
  }
};

TerminalView.prototype.execute = function(stdioSource, cx) {
  if (this.executeContext && this.executeContext.isEphemeral('Ready'))
    throw new AxiomError.Runtime('Already executing');

  this.stdioSource = stdioSource;
  this.stdioSource.stdout.onData.addListener(this.onStdOut_, this);
  this.stdioSource.stderr.onData.addListener(this.onStdOut_, this);
  this.stdioSource.stdout.resume();
  this.stdioSource.stderr.resume();
  this.executeContext = cx;
  this.executeContext.onClose.addListener(this.onExecuteClose_, this);
  this.executeContext.onTTYRequest.addListener(this.onTTYRequest_, this);
  this.executeContext.setTTY({
    rows: this.hterm_.io.rowCount,
    columns: this.hterm_.io.columnCount
  });

  this.executeContext.onReady.addListener(function() {
    console.log('TerminalView: execute ready');
  });

  this.executeContext.onClose.addListener(function(reason, value) {
    console.log('TerminalView: execute closed: ' + reason, value);
    this.hterm_.uninstallKeyboard();
  }.bind(this));

  this.executeContext.execute();
};

TerminalView.prototype.print = function(str) {
  this.hterm_.io.print(str);
};

TerminalView.prototype.println = function(str) {
  this.hterm_.io.println(str);
};

/**
 * Handle for inbound messages from the default command.
 */
TerminalView.prototype.onStdOut_ = function(str) {
  if (typeof str == 'string') {
    str = str.replace(/\n/g, '\r\n');
  } else {
    str = JSON.stringify(str) + '\r\n';
  }

  this.print(str);
};

/**
 * The default command exited.
 */
TerminalView.prototype.onExecuteClose_ = function(reason, value) {
  if (reason == 'ok') {
    this.println('Command exited: ' + this.executeContext.path + ', ' +
        JSON.stringify(value));

  } else {
    this.print('Error executing ' + this.executeContext.path + ': ' +
               JSON.stringify(value));
  }
};

TerminalView.prototype.onTTYRequest_ = function(request) {
  console.log('tty request');
  if (typeof request.interrupt == 'string')
    this.executeContext.setTTY({interrupt: request.interrupt});
};

/**
 * Called by hterm.Terminal.IO for keyboard events.
 *
 * We just forward them on to the default command.
 */
TerminalView.prototype.onSendString_ = function(str) {
  if (this.executeContext.isEphemeral('Ready')) {
    var interruptChar = this.executeContext.getTTY().getInterrupt();
    if (interruptChar && str == interruptChar) {
      console.log('interrupt');
      this.executeContext.sendSignal('interrupt');
    } else {
      this.stdioSource.stdin.write(str);
    }
  } else {
    console.warn('Execute not ready, ignoring input: ' + str);
  }
};

/**
 * Called by hterm.Terminal.IO when the terminal size changes.
 *
 * We just forward them on to the default command.
 */
TerminalView.prototype.onTerminalResize_ = function(columns, rows) {
  if (this.executeContext && this.executeContext.isEphemeral('Ready'))
    this.executeContext.setTTY({columns: columns, rows: rows});
};
<|endoftext|>


<commit_before>const childProcess = require('child_process')
const fs = require('fs')
const path = require('path')
const electronLink = require('electron-link')
const CONFIG = require('../config')
const vm = require('vm')

module.exports = function (packagedAppPath) {
  const snapshotScriptPath = path.join(CONFIG.buildOutputPath, 'startup.js')
  const coreModules = new Set(['electron', 'atom', 'shell', 'WNdb', 'lapack', 'remote'])
  const baseDirPath = path.join(CONFIG.intermediateAppPath, 'static')
  let processedFiles = 0

  return electronLink({
    baseDirPath,
    mainPath: path.resolve(baseDirPath, '..', 'src', 'initialize-application-window.js'),
    cachePath: path.join(CONFIG.atomHomeDirPath, 'snapshot-cache'),
    auxiliaryData: CONFIG.snapshotAuxiliaryData,
    shouldExcludeModule: (modulePath) => {
      if (processedFiles > 0) {
        process.stdout.write('\r')
      }
      process.stdout.write(`Generating snapshot script at "${snapshotScriptPath}" (${++processedFiles})`)

      const relativePath = path.relative(baseDirPath, modulePath)
      return (
        modulePath.endsWith('.node') ||
        coreModules.has(modulePath) ||
        (relativePath.startsWith(path.join('..', 'src')) && relativePath.endsWith('-element.js')) ||
        relativePath == path.join('..', 'exports', 'atom.js') ||
        relativePath == path.join('..', 'src', 'electron-shims.js') ||
        relativePath == path.join('..', 'src', 'safe-clipboard.js') ||
        relativePath == path.join('..', 'node_modules', 'atom-keymap', 'lib', 'command-event.js') ||
        relativePath == path.join('..', 'node_modules', 'babel-core', 'index.js') ||
        relativePath == path.join('..', 'node_modules', 'cached-run-in-this-context', 'lib', 'main.js') ||
        relativePath == path.join('..', 'node_modules', 'coffee-script', 'lib', 'coffee-script', 'register.js') ||
        relativePath == path.join('..', 'node_modules', 'cson-parser', 'node_modules', 'coffee-script', 'lib', 'coffee-script', 'register.js') ||
        relativePath == path.join('..', 'node_modules', 'decompress-zip', 'lib', 'decompress-zip.js') ||
        relativePath == path.join('..', 'node_modules', 'debug', 'node.js') ||
        relativePath == path.join('..', 'node_modules', 'git-utils', 'lib', 'git.js') ||
        relativePath == path.join('..', 'node_modules', 'glob', 'glob.js') ||
        relativePath == path.join('..', 'node_modules', 'graceful-fs', 'graceful-fs.js') ||
        relativePath == path.join('..', 'node_modules', 'htmlparser2', 'lib', 'index.js') ||
        relativePath == path.join('..', 'node_modules', 'iconv-lite', 'encodings', 'index.js') ||
        relativePath == path.join('..', 'node_modules', 'less', 'index.js') ||
        relativePath == path.join('..', 'node_modules', 'less', 'lib', 'less', 'fs.js') ||
        relativePath == path.join('..', 'node_modules', 'less', 'lib', 'less-node', 'index.js') ||
        relativePath == path.join('..', 'node_modules', 'less', 'node_modules', 'graceful-fs', 'graceful-fs.js') ||
        relativePath == path.join('..', 'node_modules', 'superstring', 'index.js') ||
        relativePath == path.join('..', 'node_modules', 'oniguruma', 'lib', 'oniguruma.js') ||
        relativePath == path.join('..', 'node_modules', 'request', 'index.js') ||
        relativePath == path.join('..', 'node_modules', 'resolve', 'index.js') ||
        relativePath == path.join('..', 'node_modules', 'resolve', 'lib', 'core.js') ||
        relativePath == path.join('..', 'node_modules', 'settings-view', 'node_modules', 'glob', 'glob.js') ||
        relativePath == path.join('..', 'node_modules', 'spellchecker', 'lib', 'spellchecker.js') ||
        relativePath == path.join('..', 'node_modules', 'spelling-manager', 'node_modules', 'natural', 'lib', 'natural', 'index.js') ||
        relativePath == path.join('..', 'node_modules', 'tar', 'tar.js') ||
        relativePath == path.join('..', 'node_modules', 'temp', 'lib', 'temp.js') ||
        relativePath == path.join('..', 'node_modules', 'tmp', 'lib', 'tmp.js')
      )
    }
  }).then((snapshotScript) => {
    fs.writeFileSync(snapshotScriptPath, snapshotScript)
    process.stdout.write('\n')

    console.log('Verifying if snapshot can be executed via `mksnapshot`')
    vm.runInNewContext(snapshotScript, undefined, {filename: snapshotScriptPath, displayErrors: true})

    const generatedStartupBlobPath = path.join(CONFIG.buildOutputPath, 'snapshot_blob.bin')
    console.log(`Generating startup blob at "${generatedStartupBlobPath}"`)
    childProcess.execFileSync(
      path.join(CONFIG.repositoryRootPath, 'script', 'node_modules', 'electron-mksnapshot', 'bin', 'mksnapshot'),
      [snapshotScriptPath, '--startup_blob', generatedStartupBlobPath]
    )

    let startupBlobDestinationPath
    if (process.platform === 'darwin') {
      startupBlobDestinationPath = `${packagedAppPath}/Contents/Frameworks/Electron Framework.framework/Resources/snapshot_blob.bin`
    } else {
      startupBlobDestinationPath = path.join(packagedAppPath, 'snapshot_blob.bin')
    }

    console.log(`Moving generated startup blob into "${startupBlobDestinationPath}"`)
    fs.unlinkSync(startupBlobDestinationPath)
    fs.renameSync(generatedStartupBlobPath, startupBlobDestinationPath)
  })
}
<commit_msg>Don't snapshot minimatch and fix package transpilation registry on win32<commit_after>const childProcess = require('child_process')
const fs = require('fs')
const path = require('path')
const electronLink = require('electron-link')
const CONFIG = require('../config')
const vm = require('vm')

module.exports = function (packagedAppPath) {
  const snapshotScriptPath = path.join(CONFIG.buildOutputPath, 'startup.js')
  const coreModules = new Set(['electron', 'atom', 'shell', 'WNdb', 'lapack', 'remote'])
  const baseDirPath = path.join(CONFIG.intermediateAppPath, 'static')
  let processedFiles = 0

  return electronLink({
    baseDirPath,
    mainPath: path.resolve(baseDirPath, '..', 'src', 'initialize-application-window.js'),
    cachePath: path.join(CONFIG.atomHomeDirPath, 'snapshot-cache'),
    auxiliaryData: CONFIG.snapshotAuxiliaryData,
    shouldExcludeModule: (modulePath) => {
      if (processedFiles > 0) {
        process.stdout.write('\r')
      }
      process.stdout.write(`Generating snapshot script at "${snapshotScriptPath}" (${++processedFiles})`)

      const relativePath = path.relative(baseDirPath, modulePath)
      return (
        modulePath.endsWith('.node') ||
        coreModules.has(modulePath) ||
        (relativePath.startsWith(path.join('..', 'src')) && relativePath.endsWith('-element.js')) ||
        relativePath == path.join('..', 'exports', 'atom.js') ||
        relativePath == path.join('..', 'src', 'electron-shims.js') ||
        relativePath == path.join('..', 'src', 'safe-clipboard.js') ||
        relativePath == path.join('..', 'node_modules', 'atom-keymap', 'lib', 'command-event.js') ||
        relativePath == path.join('..', 'node_modules', 'babel-core', 'index.js') ||
        relativePath == path.join('..', 'node_modules', 'cached-run-in-this-context', 'lib', 'main.js') ||
        relativePath == path.join('..', 'node_modules', 'coffee-script', 'lib', 'coffee-script', 'register.js') ||
        relativePath == path.join('..', 'node_modules', 'cson-parser', 'node_modules', 'coffee-script', 'lib', 'coffee-script', 'register.js') ||
        relativePath == path.join('..', 'node_modules', 'decompress-zip', 'lib', 'decompress-zip.js') ||
        relativePath == path.join('..', 'node_modules', 'debug', 'node.js') ||
        relativePath == path.join('..', 'node_modules', 'git-utils', 'lib', 'git.js') ||
        relativePath == path.join('..', 'node_modules', 'glob', 'glob.js') ||
        relativePath == path.join('..', 'node_modules', 'graceful-fs', 'graceful-fs.js') ||
        relativePath == path.join('..', 'node_modules', 'htmlparser2', 'lib', 'index.js') ||
        relativePath == path.join('..', 'node_modules', 'iconv-lite', 'encodings', 'index.js') ||
        relativePath == path.join('..', 'node_modules', 'less', 'index.js') ||
        relativePath == path.join('..', 'node_modules', 'less', 'lib', 'less', 'fs.js') ||
        relativePath == path.join('..', 'node_modules', 'less', 'lib', 'less-node', 'index.js') ||
        relativePath == path.join('..', 'node_modules', 'less', 'node_modules', 'graceful-fs', 'graceful-fs.js') ||
        relativePath == path.join('..', 'node_modules', 'minimatch', 'minimatch.js') ||
        relativePath == path.join('..', 'node_modules', 'superstring', 'index.js') ||
        relativePath == path.join('..', 'node_modules', 'oniguruma', 'lib', 'oniguruma.js') ||
        relativePath == path.join('..', 'node_modules', 'request', 'index.js') ||
        relativePath == path.join('..', 'node_modules', 'resolve', 'index.js') ||
        relativePath == path.join('..', 'node_modules', 'resolve', 'lib', 'core.js') ||
        relativePath == path.join('..', 'node_modules', 'scandal', 'node_modules', 'minimatch', 'minimatch.js') ||
        relativePath == path.join('..', 'node_modules', 'settings-view', 'node_modules', 'glob', 'glob.js') ||
        relativePath == path.join('..', 'node_modules', 'settings-view', 'node_modules', 'minimatch', 'minimatch.js') ||
        relativePath == path.join('..', 'node_modules', 'spellchecker', 'lib', 'spellchecker.js') ||
        relativePath == path.join('..', 'node_modules', 'spelling-manager', 'node_modules', 'natural', 'lib', 'natural', 'index.js') ||
        relativePath == path.join('..', 'node_modules', 'tar', 'tar.js') ||
        relativePath == path.join('..', 'node_modules', 'temp', 'lib', 'temp.js') ||
        relativePath == path.join('..', 'node_modules', 'tmp', 'lib', 'tmp.js') ||
        relativePath == path.join('..', 'node_modules', 'tree-view', 'node_modules', 'minimatch', 'minimatch.js')
      )
    }
  }).then((snapshotScript) => {
    fs.writeFileSync(snapshotScriptPath, snapshotScript)
    process.stdout.write('\n')

    console.log('Verifying if snapshot can be executed via `mksnapshot`')
    vm.runInNewContext(snapshotScript, undefined, {filename: snapshotScriptPath, displayErrors: true})

    const generatedStartupBlobPath = path.join(CONFIG.buildOutputPath, 'snapshot_blob.bin')
    console.log(`Generating startup blob at "${generatedStartupBlobPath}"`)
    childProcess.execFileSync(
      path.join(CONFIG.repositoryRootPath, 'script', 'node_modules', 'electron-mksnapshot', 'bin', 'mksnapshot'),
      [snapshotScriptPath, '--startup_blob', generatedStartupBlobPath]
    )

    let startupBlobDestinationPath
    if (process.platform === 'darwin') {
      startupBlobDestinationPath = `${packagedAppPath}/Contents/Frameworks/Electron Framework.framework/Resources/snapshot_blob.bin`
    } else {
      startupBlobDestinationPath = path.join(packagedAppPath, 'snapshot_blob.bin')
    }

    console.log(`Moving generated startup blob into "${startupBlobDestinationPath}"`)
    fs.unlinkSync(startupBlobDestinationPath)
    fs.renameSync(generatedStartupBlobPath, startupBlobDestinationPath)
  })
}
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2015-present, Facebook, Inc.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow
 */

/* eslint-disable */

declare module 'deepDiffer' {
  declare function exports(one: any, two: any): boolean;
}
declare module 'deepFreezeAndThrowOnMutationInDev' {
  declare function exports<T>(obj: T): T;
}
declare module 'flattenStyle' {
}
declare module 'InitializeCore' {
}
declare module 'RCTEventEmitter' {
  declare function register(mixed): void;
}
declare module 'TextInputState' {
  declare function blurTextInput(object: any): void;
  declare function focusTextInput(object: any): void;
}
declare module 'ExceptionsManager' {
  declare function handleException(error: Error, isFatal: boolean): void;
}
declare module 'Platform' {
  declare var OS: string;
}
declare module 'UIManager' {
  declare var customBubblingEventTypes: Object;
  declare var customDirectEventTypes: Object;
  declare function createView(
    reactTag: number,
    viewName: string,
    rootTag: number,
    props: ?Object,
  ): void;
  declare function manageChildren(
    containerTag: number,
    moveFromIndices: Array<number>,
    moveToIndices: Array<number>,
    addChildReactTags: Array<number>,
    addAtIndices: Array<number>,
    removeAtIndices: Array<number>,
  ): void;
  declare function measure(hostComponent: mixed, callback: Function): void;
  declare function measureInWindow(
    nativeTag: ?number,
    callback: Function,
  ): void;
  declare function measureLayout(
    nativeTag: mixed,
    nativeNode: number,
    onFail: Function,
    onSuccess: Function,
  ): void;
  declare function removeRootView(containerTag: number): void;
  declare function removeSubviewsFromContainerWithID(containerId: number): void;
  declare function replaceExistingNonRootView(): void;
  declare function setChildren(
    containerTag: number,
    reactTags: Array<number>,
  ): void;
  declare function updateView(
    reactTag: number,
    viewName: string,
    props: ?Object,
  ): void;
  declare function __takeSnapshot(
    view?: 'window' | Element<any> | number,
    options?: {
      width?: number,
      height?: number,
      format?: 'png' | 'jpeg',
      quality?: number,
    },
  ): Promise<any>;
}
declare module 'View' {
  declare var exports: typeof React$Component;
}

declare module 'RTManager' {
  declare function createNode(
    tag: number,
    classType: string,
    props: ?Object,
  ): void;

  declare function beginUpdates(): void;

  declare function appendChildToContext(
    contextTag: number,
    childTag: number,
  ): void;
  declare function appendChild(parentTag: number, childTag: number): void;
  declare function prependChild(childTag: number, beforeTag: number): void;
  declare function deleteChild(childTag: number): void;
  declare function updateNode(tag: number, props: ?Object): void;

  declare function completeUpdates(): void;
}

declare module 'BatchedBridge' {
  declare function registerCallableModule(name: string, module: Object): void;
}

declare module 'CSComponent' {
  declare type Element = any;
  declare type Options<Instance> = any;
}

declare module 'CSStatefulComponent' {
  declare function CSStatefulComponent(spec: any): any;
}
<commit_msg>Use `declare module.exports` syntax for flow libdefs (#11861)<commit_after>/**
 * Copyright (c) 2015-present, Facebook, Inc.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 *
 * @flow
 */

/* eslint-disable */

declare module 'deepDiffer' {
  declare module.exports: (one: any, two: any) => boolean;
}
declare module 'deepFreezeAndThrowOnMutationInDev' {
  declare module.exports: <T>(obj: T) => T;
}
declare module 'flattenStyle' {
}
declare module 'InitializeCore' {
}
declare module 'RCTEventEmitter' {
  declare function register(mixed): void;
}
declare module 'TextInputState' {
  declare function blurTextInput(object: any): void;
  declare function focusTextInput(object: any): void;
}
declare module 'ExceptionsManager' {
  declare function handleException(error: Error, isFatal: boolean): void;
}
declare module 'Platform' {
  declare var OS: string;
}
declare module 'UIManager' {
  declare var customBubblingEventTypes: Object;
  declare var customDirectEventTypes: Object;
  declare function createView(
    reactTag: number,
    viewName: string,
    rootTag: number,
    props: ?Object,
  ): void;
  declare function manageChildren(
    containerTag: number,
    moveFromIndices: Array<number>,
    moveToIndices: Array<number>,
    addChildReactTags: Array<number>,
    addAtIndices: Array<number>,
    removeAtIndices: Array<number>,
  ): void;
  declare function measure(hostComponent: mixed, callback: Function): void;
  declare function measureInWindow(
    nativeTag: ?number,
    callback: Function,
  ): void;
  declare function measureLayout(
    nativeTag: mixed,
    nativeNode: number,
    onFail: Function,
    onSuccess: Function,
  ): void;
  declare function removeRootView(containerTag: number): void;
  declare function removeSubviewsFromContainerWithID(containerId: number): void;
  declare function replaceExistingNonRootView(): void;
  declare function setChildren(
    containerTag: number,
    reactTags: Array<number>,
  ): void;
  declare function updateView(
    reactTag: number,
    viewName: string,
    props: ?Object,
  ): void;
  declare function __takeSnapshot(
    view?: 'window' | Element<any> | number,
    options?: {
      width?: number,
      height?: number,
      format?: 'png' | 'jpeg',
      quality?: number,
    },
  ): Promise<any>;
}
declare module 'View' {
  declare module.exports: typeof React$Component;
}

declare module 'RTManager' {
  declare function createNode(
    tag: number,
    classType: string,
    props: ?Object,
  ): void;

  declare function beginUpdates(): void;

  declare function appendChildToContext(
    contextTag: number,
    childTag: number,
  ): void;
  declare function appendChild(parentTag: number, childTag: number): void;
  declare function prependChild(childTag: number, beforeTag: number): void;
  declare function deleteChild(childTag: number): void;
  declare function updateNode(tag: number, props: ?Object): void;

  declare function completeUpdates(): void;
}

declare module 'BatchedBridge' {
  declare function registerCallableModule(name: string, module: Object): void;
}

declare module 'CSComponent' {
  declare type Element = any;
  declare type Options<Instance> = any;
}

declare module 'CSStatefulComponent' {
  declare function CSStatefulComponent(spec: any): any;
}
<|endoftext|>


<commit_before>/*
 * Copyright 2016 Resin.io
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

'use strict';

/**
 * @summary Etcher exit codes
 * @namespace EXIT_CODES
 * @public
 */
module.exports = {

  /**
   * @property {Number} SUCCESS
   * @memberof EXIT_CODES
   *
   * @description
   * This exit code is used to represent a successful exit
   * status, with no problems on the way.
   */
  SUCCESS: 0,

  /**
   * @property {Number} GENERAL_ERROR
   * @memberof EXIT_CODES
   *
   * @description
   * This exit code is used to represent a general error
   * situation. If the reasons of the error is not
   * documented as a specialised error code, this one
   * should be used.
   */
  GENERAL_ERROR: 1,

  /**
   * @property {Number} VALIDATION_ERROR
   * @memberof EXIT_CODES
   *
   * @description
   * This exit code is used to represent a validation error.
   */
  VALIDATION_ERROR: 2,

  /**
   * @property {Number} CANCELLED
   * @memberof EXIT_CODES
   *
   * @description
   * This exit code is used to represent a cancelled write process.
   */
  CANCELLED: 3

};
<commit_msg>style: fix lint warning in exit-codes.js (#499)<commit_after>/*
 * Copyright 2016 Resin.io
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

'use strict';

/**
 * @summary Etcher exit codes
 * @namespace EXIT_CODES
 * @public
 */
module.exports = {

  /**
   * @property {Number} SUCCESS
   * @memberof EXIT_CODES
   *
   * @description
   * This exit code is used to represent a successful exit
   * status, with no problems on the way.
   */
  SUCCESS: 0,

  /**
   * @property {Number} GENERAL_ERROR
   * @memberof EXIT_CODES
   *
   * @description
   * This exit code is used to represent a general error
   * situation. If the reasons of the error is not
   * documented as a specialised error code, this one
   * should be used.
   */
  GENERAL_ERROR: 1,

  /**
   * @property {Number} VALIDATION_ERROR
   * @memberof EXIT_CODES
   *
   * @description
   * This exit code is used to represent a validation error.
   */
  VALIDATION_ERROR: 2,

  /**
   * @property {Number} CANCELLED
   * @memberof EXIT_CODES
   *
   * @description
   * This exit code is used to represent a cancelled write process.
   */
  CANCELLED: 3

};
<|endoftext|>


<commit_before>// BusinessProcess payment receipt uploads resolution

'use strict';

var memoize                    = require('memoizee/plain')
  , defineUploadsProcess       = require('../lib/uploads-process')
  , definePaymentReceiptUpload = require('../payment-receipt-upload')
  , defineBusinessProcess      = require('./base')

  , defineCosts;

module.exports = memoize(function (db/* options */) {
	var options              = Object(arguments[1])
	  , BusinessProcess      = defineBusinessProcess(db, options)
	  , UploadsProcess       = defineUploadsProcess(db)
	  , PaymentReceiptUpload = definePaymentReceiptUpload(db);

	BusinessProcess.prototype.defineProperties({
		paymentReceiptUploads: { type: UploadsProcess, nested: true }
	});
	BusinessProcess.prototype.paymentReceiptUploads.map._descriptorPrototype_.type
		= PaymentReceiptUpload;
	BusinessProcess.prototype.paymentReceiptUploads.defineProperties({
		// Applicable payment receipt uploads
		applicable: { type: PaymentReceiptUpload, value: function (_observe) {
			var result = [];
			this.map.forEach(function (paymentReceiptUpload) {
				if (_observe(paymentReceiptUpload.applicableCosts._size)) result.push(paymentReceiptUpload);
			});
			return result;
		} },
		// Payment receipt uploads that should be uploaded
		uploadable: { type: PaymentReceiptUpload, multiple: true, value: function (_observe) {
			var result = [];
			this.map.forEach(function (paymentReceiptUpload) {
				if (_observe(paymentReceiptUpload.applicableCostsForUserUpload._size)) {
					result.push(paymentReceiptUpload);
				}
			});
			return result;
		} },
		progress: {
			value: function (_observe) {
				var totalProgress = 0;
				if (!this.weight) return 1;
				this.uploaded.forEach(function (paymentReceipt) {
					totalProgress += _observe(paymentReceipt._progress);
				});

				return totalProgress / this.weight;
			}
		},
		weight: {
			value: function (_observe) {
				return _observe(this.uploadable._size);
			}
		},

		uploaded: { type: PaymentReceiptUpload },
		approved: { type: PaymentReceiptUpload },
		rejected: { type: PaymentReceiptUpload }
	});

	if (!BusinessProcess.prototype.costs) defineCosts(db, options);

	return BusinessProcess;
}, { normalizer: require('memoizee/normalizers/get-1')() });

defineCosts = require('./costs');
<commit_msg>#1273 uploaded are resolved from uploadable<commit_after>// BusinessProcess payment receipt uploads resolution

'use strict';

var memoize                    = require('memoizee/plain')
  , defineUploadsProcess       = require('../lib/uploads-process')
  , definePaymentReceiptUpload = require('../payment-receipt-upload')
  , defineBusinessProcess      = require('./base')

  , defineCosts;

module.exports = memoize(function (db/* options */) {
	var options              = Object(arguments[1])
	  , BusinessProcess      = defineBusinessProcess(db, options)
	  , UploadsProcess       = defineUploadsProcess(db)
	  , PaymentReceiptUpload = definePaymentReceiptUpload(db);

	BusinessProcess.prototype.defineProperties({
		paymentReceiptUploads: { type: UploadsProcess, nested: true }
	});
	BusinessProcess.prototype.paymentReceiptUploads.map._descriptorPrototype_.type
		= PaymentReceiptUpload;
	BusinessProcess.prototype.paymentReceiptUploads.defineProperties({
		// Applicable payment receipt uploads
		applicable: { type: PaymentReceiptUpload, value: function (_observe) {
			var result = [];
			this.map.forEach(function (paymentReceiptUpload) {
				if (_observe(paymentReceiptUpload.applicableCosts._size)) result.push(paymentReceiptUpload);
			});
			return result;
		} },
		// Payment receipt uploads that should be uploaded
		uploadable: { type: PaymentReceiptUpload, multiple: true, value: function (_observe) {
			var result = [];
			this.map.forEach(function (paymentReceiptUpload) {
				if (_observe(paymentReceiptUpload.applicableCostsForUserUpload._size)) {
					result.push(paymentReceiptUpload);
				}
			});
			return result;
		} },
		progress: {
			value: function (_observe) {
				var totalProgress = 0;
				if (!this.weight) return 1;
				this.uploaded.forEach(function (paymentReceipt) {
					totalProgress += _observe(paymentReceipt._progress);
				});

				return totalProgress / this.weight;
			}
		},
		weight: {
			value: function (_observe) {
				return _observe(this.uploadable._size);
			}
		},

		uploaded: {
			type: PaymentReceiptUpload,
			value: function (_observe) {
				var result = [];
				this.uploadable.forEach(function (upload) {
					if (_observe(upload.document.files.ordered._size)) result.push(upload);
				});
				return result;
			}
		},
		approved: { type: PaymentReceiptUpload },
		rejected: { type: PaymentReceiptUpload }
	});

	if (!BusinessProcess.prototype.costs) defineCosts(db, options);

	return BusinessProcess;
}, { normalizer: require('memoizee/normalizers/get-1')() });

defineCosts = require('./costs');
<|endoftext|>


<commit_before>class StateSnapshot {
  constructor({ store, initialState, meta, currentState = initialState }) {
    this.store = store;
    this.initialState = { ...initialState };
    this.items = { ...currentState };
    this.meta = meta;
    this.closed = false;
  }

  _closeSnapshot() {
    if (this.closed) {
      throw new Error('Attempted to dispatch action to closed StateSnapshot');
    }

    this.closed = true;
  }

  async dispatchToStateSnapshot(action) {
    this._closeSnapshot();
    const newItems = await this.store.reducer({ ...this.items }, action);

    return new StateSnapshot({
      store: this.store,
      initialState: { ...this.initialState },
      currentState: newItems,
      meta: this.meta,
    });
  }

  async commitStateSnapshot() {
    this._closeSnapshot();
    await this.store.commit({
      meta: this.meta,
      items: this.items,
    });

    return new StateSnapshot({
      store: this.store,
      initialState: { ...this.items },
      meta: this.meta,
    });
  }

  async discardStateSnapshot() {
    this._closeSnapshot();
    await this.store.discard({
      meta: this.meta,
      items: this.items,
    });

    return new StateSnapshot({
      store: this.store,
      initialState: { ...this.initialState },
      meta: this.meta,
    });
  }
}

exports.StateSnapshot = StateSnapshot;
<commit_msg>Remove more code duplication from StateSnapshot<commit_after>class StateSnapshot {
  constructor({ store, initialState, meta, currentState = initialState }) {
    this.store = store;
    this.initialState = { ...initialState };
    this.items = { ...currentState };
    this.meta = meta;
    this.closed = false;
  }

  _closeSnapshot() {
    if (this.closed) {
      throw new Error('Attempted to dispatch action to closed StateSnapshot');
    }

    this.closed = true;
  }

  _getNextState({ newItems }) {
    return {
      store: this.store,
      initialState: { ...this.initialState },
      currentState: newItems,
      meta: this.meta,
    };
  }

  _getCommitValues() {
    return {
      meta: this.meta,
      items: this.items,
    };
  }

  async dispatchToStateSnapshot(action) {
    this._closeSnapshot();
    const newItems = await this.store.reducer({ ...this.items }, action);

    return new StateSnapshot(this._getNextState({ newItems }));
  }

  async commitStateSnapshot() {
    this._closeSnapshot();
    await this.store.commit(this._getCommitValues());

    return new StateSnapshot({
      ...this._getNextState({}),
      initialState: { ...this.items },
    });
  }

  async discardStateSnapshot() {
    this._closeSnapshot();
    await this.store.discard(this._getCommitValues());

    return new StateSnapshot({
      ...this._getNextState({}),
      currentState: { ...this.initialState },
    });
  }
}

exports.StateSnapshot = StateSnapshot;
<|endoftext|>


<commit_before>var esprima = require('esprima');
var babelJscs = require('babel-jscs');
var Errors = require('./errors');
var JsFile = require('./js-file');
var Configuration = require('./config/configuration');

var MAX_FIX_ATTEMPTS = 5;

function getInternalErrorMessage(rule, e) {
    return 'Error running rule ' + rule + ': ' +
        'This is an issue with JSCS and not your codebase.\n' +
        'Please file an issue (with the stack trace below) at: ' +
        'https://github.com/jscs-dev/node-jscs/issues/new\n' + e;
}

/**
 * Starts Code Style checking process.
 *
 * @name StringChecker
 */
var StringChecker = function() {
    this._configuredRules = [];

    this._errorsFound = 0;
    this._maxErrorsExceeded = false;

    // Need to be defined here because Configuration module can choose
    // custom esprima or chose parsers based on "esnext" option
    this._esprima = esprima;

    this._configuration = this._createConfiguration();
    this._configuration.registerDefaultPresets();
};

StringChecker.prototype = {
    /**
     * Registers single Code Style checking rule.
     *
     * @param {Rule} rule
     */
    registerRule: function(rule) {
        this._configuration.registerRule(rule);
    },

    /**
     * Registers built-in Code Style checking rules.
     */
    registerDefaultRules: function() {
        this._configuration.registerDefaultRules();
    },

    /**
     * Get processed config.
     *
     * @return {Object}
     */
    getProcessedConfig: function() {
        return this._configuration.getProcessedConfig();
    },

    /**
     * Loads configuration from JS Object. Activates and configures required rules.
     *
     * @param {Object} config
     */
    configure: function(config) {
        this._configuration.load(config);

        if (this._configuration.hasCustomEsprima()) {
            this._esprima = this._configuration.getCustomEsprima();
        } else if (this._configuration.isESNextEnabled()) {
            this._esprima = babelJscs;
        }

        this._verbose = this._configuration.getVerbose();

        this._configuredRules = this._configuration.getConfiguredRules();
        this._maxErrors = this._configuration.getMaxErrors();
    },

    /**
     * Checks file provided with a string.
     *
     * @param {String} source
     * @param {String} [filename='input']
     * @returns {Errors}
     */
    checkString: function(source, filename) {
        filename = filename || 'input';

        var file = this._createJsFileInstance(filename, source);

        var errors = new Errors(file, this._verbose);

        file.getParseErrors().forEach(function(parseError) {
            if (!this._maxErrorsExceeded) {
                this._addParseError(errors, parseError);
            }
        }, this);

        if (!file._program || !file._program.firstChild) {
            return errors;
        }

        this._checkJsFile(file, errors);

        return errors;
    },

    /**
     * Fix provided error.
     *
     * @param {JsFile} file
     * @param {Errors} errors
     * @protected
     */
    _fixJsFile: function(file, errors) {
        var list = errors.getErrorList();
        var configuration = this.getConfiguration();

        list.forEach(function(error) {
            if (error.fixed) {
                return;
            }

            var instance = configuration.getConfiguredRule(error.rule);

            if (instance && instance._fix) {
                try {

                    // "error.fixed = true" should go first, so rule can
                    // decide for itself (with "error.fixed = false")
                    // if it can fix this particular error
                    error.fixed = true;
                    instance._fix(file, error);

                } catch (e) {
                    error.fixed = undefined;
                    errors.add(getInternalErrorMessage(error.rule, e), 1, 0);
                }
            }
        });
    },

    /**
     * Checks a file specified using JsFile instance.
     * Fills Errors instance with validation errors.
     *
     * @param {JsFile} file
     * @param {Errors} errors
     * @protected
     */
    _checkJsFile: function(file, errors) {
        if (this._maxErrorsExceeded) {
            return;
        }

        var errorFilter = this._configuration.getErrorFilter();

        this._configuredRules.forEach(function(rule) {
            errors.setCurrentRule(rule.getOptionName());

            try {
                rule.check(file, errors);
            } catch (e) {
                errors.setCurrentRule('internalError');
                errors.add(getInternalErrorMessage(rule.getOptionName(), e.stack), file.getProgram(), 0);
            }
        }, this);

        this._configuration.getUnsupportedRuleNames().forEach(function(rulename) {
            errors.add('Unsupported rule: ' + rulename, 1, 0);
        });

        // sort errors list to show errors as they appear in source
        errors.getErrorList().sort(function(a, b) {
            return (a.line - b.line) || (a.column - b.column);
        });

        if (errorFilter) {
            errors.filter(errorFilter);
        }

        if (this.maxErrorsEnabled()) {
            if (this._maxErrors === -1 || this._maxErrors === null) {
                this._maxErrorsExceeded = false;

            } else {
                this._maxErrorsExceeded = this._errorsFound + errors.getErrorCount() > this._maxErrors;
                errors.stripErrorList(Math.max(0, this._maxErrors - this._errorsFound));
            }
        }

        this._errorsFound += errors.getErrorCount();
    },

    /**
     * Adds parse error to the error list.
     *
     * @param {Errors} errors
     * @param {Error} parseError
     * @private
     */
    _addParseError: function(errors, parseError) {
        if (this._maxErrorsExceeded) {
            return;
        }

        errors.setCurrentRule('parseError');
        errors.add(parseError.message, null, parseError.pos);

        if (this.maxErrorsEnabled()) {
            this._errorsFound += 1;
            this._maxErrorsExceeded = this._errorsFound >= this._maxErrors;
        }
    },

    /**
     * Creates configured JsFile instance.
     *
     * @param {String} filename
     * @param {String} source
     * @private
     */
    _createJsFileInstance: function(filename, source) {
        return new JsFile({
            filename: filename,
            source: source,
            esprima: this._esprima,
            esprimaOptions: this._configuration.getEsprimaOptions(),
            es3: this._configuration.isES3Enabled(),
            es6: this._configuration.isESNextEnabled()
        });
    },

    /**
     * Checks file provided with a string.
     *
     * @param {String} source
     * @param {String} [filename='input']
     * @returns {{output: String, errors: Errors}}
     */
    fixString: function(source, filename) {
        filename = filename || 'input';

        var file = this._createJsFileInstance(filename, source);
        var errors = new Errors(file, this._verbose);

        var parseErrors = file.getParseErrors();
        if (parseErrors.length > 0) {
            parseErrors.forEach(function(parseError) {
                this._addParseError(errors, parseError);
            }, this);

            return {output: source, errors: errors};
        } else {
            var attempt = 0;
            do {
                // Changes to current sources are made in rules through assertions.
                this._checkJsFile(file, errors);

                // If assertions weren't used but rule has "fix" method,
                // which we could use.
                this._fixJsFile(file, errors);

                var hasFixes = errors.getErrorList().some(function(err) {
                    return err.fixed;
                });

                if (!hasFixes) {
                    break;
                }

                file = this._createJsFileInstance(filename, file.render());
                errors = new Errors(file, this._verbose);
                attempt++;
            } while (attempt < MAX_FIX_ATTEMPTS);

            return {output: file.getSource(), errors: errors};
        }
    },

    /**
     * Returns `true` if max erros limit is enabled.
     *
     * @returns {Boolean}
     */
    maxErrorsEnabled: function() {
        return this._maxErrors !== null && this._maxErrors !== -1;
    },

    /**
     * Returns `true` if error count exceeded `maxErrors` option value.
     *
     * @returns {Boolean}
     */
    maxErrorsExceeded: function() {
        return this._maxErrorsExceeded;
    },

    /**
     * Returns new configuration instance.
     *
     * @protected
     * @returns {Configuration}
     */
    _createConfiguration: function() {
        return new Configuration();
    },

    /**
     * Returns current configuration instance.
     *
     * @returns {Configuration}
     */
    getConfiguration: function() {
        return this._configuration;
    },

    /**
     * Returns the current esprima parser
     *
     * @return {Esprima}
     */
    getEsprima: function() {
        return this._esprima || this._configuration.getCustomEsprima();
    }
};

module.exports = StringChecker;
<commit_msg>string-checker: show correct errors from "_fix" methods<commit_after>var esprima = require('esprima');
var babelJscs = require('babel-jscs');
var Errors = require('./errors');
var JsFile = require('./js-file');
var Configuration = require('./config/configuration');

var MAX_FIX_ATTEMPTS = 5;

function getInternalErrorMessage(rule, e) {
    return 'Error running rule ' + rule + ': ' +
        'This is an issue with JSCS and not your codebase.\n' +
        'Please file an issue (with the stack trace below) at: ' +
        'https://github.com/jscs-dev/node-jscs/issues/new\n' + e.stack;
}

/**
 * Starts Code Style checking process.
 *
 * @name StringChecker
 */
var StringChecker = function() {
    this._configuredRules = [];

    this._errorsFound = 0;
    this._maxErrorsExceeded = false;

    // Need to be defined here because Configuration module can choose
    // custom esprima or chose parsers based on "esnext" option
    this._esprima = esprima;

    this._configuration = this._createConfiguration();
    this._configuration.registerDefaultPresets();
};

StringChecker.prototype = {
    /**
     * Registers single Code Style checking rule.
     *
     * @param {Rule} rule
     */
    registerRule: function(rule) {
        this._configuration.registerRule(rule);
    },

    /**
     * Registers built-in Code Style checking rules.
     */
    registerDefaultRules: function() {
        this._configuration.registerDefaultRules();
    },

    /**
     * Get processed config.
     *
     * @return {Object}
     */
    getProcessedConfig: function() {
        return this._configuration.getProcessedConfig();
    },

    /**
     * Loads configuration from JS Object. Activates and configures required rules.
     *
     * @param {Object} config
     */
    configure: function(config) {
        this._configuration.load(config);

        if (this._configuration.hasCustomEsprima()) {
            this._esprima = this._configuration.getCustomEsprima();
        } else if (this._configuration.isESNextEnabled()) {
            this._esprima = babelJscs;
        }

        this._verbose = this._configuration.getVerbose();

        this._configuredRules = this._configuration.getConfiguredRules();
        this._maxErrors = this._configuration.getMaxErrors();
    },

    /**
     * Checks file provided with a string.
     *
     * @param {String} source
     * @param {String} [filename='input']
     * @returns {Errors}
     */
    checkString: function(source, filename) {
        filename = filename || 'input';

        var file = this._createJsFileInstance(filename, source);

        var errors = new Errors(file, this._verbose);

        file.getParseErrors().forEach(function(parseError) {
            if (!this._maxErrorsExceeded) {
                this._addParseError(errors, parseError);
            }
        }, this);

        if (!file._program || !file._program.firstChild) {
            return errors;
        }

        this._checkJsFile(file, errors);

        return errors;
    },

    /**
     * Fix provided error.
     *
     * @param {JsFile} file
     * @param {Errors} errors
     * @protected
     */
    _fixJsFile: function(file, errors) {
        var list = errors.getErrorList();
        var configuration = this.getConfiguration();

        list.forEach(function(error) {
            if (error.fixed) {
                return;
            }

            var instance = configuration.getConfiguredRule(error.rule);

            if (instance && instance._fix) {
                try {

                    // "error.fixed = true" should go first, so rule can
                    // decide for itself (with "error.fixed = false")
                    // if it can fix this particular error
                    error.fixed = true;
                    instance._fix(file, error);

                } catch (e) {
                    error.fixed = undefined;
                    errors.add(
                        getInternalErrorMessage(error.rule, e),
                        file.getProgram()
                    );
                }
            }
        });
    },

    /**
     * Checks a file specified using JsFile instance.
     * Fills Errors instance with validation errors.
     *
     * @param {JsFile} file
     * @param {Errors} errors
     * @protected
     */
    _checkJsFile: function(file, errors) {
        if (this._maxErrorsExceeded) {
            return;
        }

        var errorFilter = this._configuration.getErrorFilter();

        this._configuredRules.forEach(function(rule) {
            errors.setCurrentRule(rule.getOptionName());

            try {
                rule.check(file, errors);
            } catch (e) {
                errors.setCurrentRule('internalError');
                errors.add(getInternalErrorMessage(rule.getOptionName(), e.stack), file.getProgram(), 0);
            }
        }, this);

        this._configuration.getUnsupportedRuleNames().forEach(function(rulename) {
            errors.add('Unsupported rule: ' + rulename, 1, 0);
        });

        // sort errors list to show errors as they appear in source
        errors.getErrorList().sort(function(a, b) {
            return (a.line - b.line) || (a.column - b.column);
        });

        if (errorFilter) {
            errors.filter(errorFilter);
        }

        if (this.maxErrorsEnabled()) {
            if (this._maxErrors === -1 || this._maxErrors === null) {
                this._maxErrorsExceeded = false;

            } else {
                this._maxErrorsExceeded = this._errorsFound + errors.getErrorCount() > this._maxErrors;
                errors.stripErrorList(Math.max(0, this._maxErrors - this._errorsFound));
            }
        }

        this._errorsFound += errors.getErrorCount();
    },

    /**
     * Adds parse error to the error list.
     *
     * @param {Errors} errors
     * @param {Error} parseError
     * @private
     */
    _addParseError: function(errors, parseError) {
        if (this._maxErrorsExceeded) {
            return;
        }

        errors.setCurrentRule('parseError');
        errors.add(parseError.message, null, parseError.pos);

        if (this.maxErrorsEnabled()) {
            this._errorsFound += 1;
            this._maxErrorsExceeded = this._errorsFound >= this._maxErrors;
        }
    },

    /**
     * Creates configured JsFile instance.
     *
     * @param {String} filename
     * @param {String} source
     * @private
     */
    _createJsFileInstance: function(filename, source) {
        return new JsFile({
            filename: filename,
            source: source,
            esprima: this._esprima,
            esprimaOptions: this._configuration.getEsprimaOptions(),
            es3: this._configuration.isES3Enabled(),
            es6: this._configuration.isESNextEnabled()
        });
    },

    /**
     * Checks file provided with a string.
     *
     * @param {String} source
     * @param {String} [filename='input']
     * @returns {{output: String, errors: Errors}}
     */
    fixString: function(source, filename) {
        filename = filename || 'input';

        var file = this._createJsFileInstance(filename, source);
        var errors = new Errors(file, this._verbose);

        var parseErrors = file.getParseErrors();
        if (parseErrors.length > 0) {
            parseErrors.forEach(function(parseError) {
                this._addParseError(errors, parseError);
            }, this);

            return {output: source, errors: errors};
        } else {
            var attempt = 0;
            do {
                // Changes to current sources are made in rules through assertions.
                this._checkJsFile(file, errors);

                // If assertions weren't used but rule has "fix" method,
                // which we could use.
                this._fixJsFile(file, errors);

                var hasFixes = errors.getErrorList().some(function(err) {
                    return err.fixed;
                });

                if (!hasFixes) {
                    break;
                }

                file = this._createJsFileInstance(filename, file.render());
                errors = new Errors(file, this._verbose);
                attempt++;
            } while (attempt < MAX_FIX_ATTEMPTS);

            return {output: file.getSource(), errors: errors};
        }
    },

    /**
     * Returns `true` if max erros limit is enabled.
     *
     * @returns {Boolean}
     */
    maxErrorsEnabled: function() {
        return this._maxErrors !== null && this._maxErrors !== -1;
    },

    /**
     * Returns `true` if error count exceeded `maxErrors` option value.
     *
     * @returns {Boolean}
     */
    maxErrorsExceeded: function() {
        return this._maxErrorsExceeded;
    },

    /**
     * Returns new configuration instance.
     *
     * @protected
     * @returns {Configuration}
     */
    _createConfiguration: function() {
        return new Configuration();
    },

    /**
     * Returns current configuration instance.
     *
     * @returns {Configuration}
     */
    getConfiguration: function() {
        return this._configuration;
    },

    /**
     * Returns the current esprima parser
     *
     * @return {Esprima}
     */
    getEsprima: function() {
        return this._esprima || this._configuration.getCustomEsprima();
    }
};

module.exports = StringChecker;
<|endoftext|>


<commit_before>var esprima = require('esprima');
var babelJscs = require('babel-jscs');
var Errors = require('./errors');
var JsFile = require('./js-file');
var Configuration = require('./config/configuration');

var MAX_FIX_ATTEMPTS = 5;

function getErrorMessage(rule, e) {
    return 'Error running rule ' + rule + ': ' +
        'This is an issue with JSCS and not your codebase.\n' +
        'Please file an issue (with the stack trace below) at: ' +
        'https://github.com/jscs-dev/node-jscs/issues/new\n' + e;
}

/**
 * Starts Code Style checking process.
 *
 * @name StringChecker
 */
var StringChecker = function() {
    this._configuredRules = [];

    this._errorsFound = 0;
    this._maxErrorsExceeded = false;

    // Need to be defined here because Configuration module can choose
    // custom esprima or chose parsers based on "esnext" option
    this._esprima = esprima;

    this._configuration = this._createConfiguration();
    this._configuration.registerDefaultPresets();
};

StringChecker.prototype = {
    /**
     * Registers single Code Style checking rule.
     *
     * @param {Rule} rule
     */
    registerRule: function(rule) {
        this._configuration.registerRule(rule);
    },

    /**
     * Registers built-in Code Style checking rules.
     */
    registerDefaultRules: function() {
        this._configuration.registerDefaultRules();
    },

    /**
     * Get processed config.
     *
     * @return {Object}
     */
    getProcessedConfig: function() {
        return this._configuration.getProcessedConfig();
    },

    /**
     * Loads configuration from JS Object. Activates and configures required rules.
     *
     * @param {Object} config
     */
    configure: function(config) {
        this._configuration.load(config);

        if (this._configuration.hasCustomEsprima()) {
            this._esprima = this._configuration.getCustomEsprima();
        } else if (this._configuration.isESNextEnabled()) {
            this._esprima = babelJscs;
        }

        this._verbose = this._configuration.getVerbose();

        this._configuredRules = this._configuration.getConfiguredRules();
        this._maxErrors = this._configuration.getMaxErrors();
    },

    /**
     * Checks file provided with a string.
     *
     * @param {String} source
     * @param {String} [filename='input']
     * @returns {Errors}
     */
    checkString: function(source, filename) {
        filename = filename || 'input';

        var file = this._createJsFileInstance(filename, source);

        var errors = new Errors(file, this._verbose);

        file.getParseErrors().forEach(function(parseError) {
            if (!this._maxErrorsExceeded) {
                this._addParseError(errors, parseError);
            }
        }, this);

        // Do not check empty strings
        if (file.getFirstToken().type === 'EOF') {
            return errors;
        }

        this._checkJsFile(file, errors);

        return errors;
    },

    /**
     * Fix provided error.
     *
     * @param {JsFile} file
     * @param {Errors} errors
     * @protected
     */
    _fixJsFile: function(file, errors) {
        var list = errors.getErrorList();
        var configuration = this.getConfiguration();

        list.forEach(function(error) {
            if (error.fixed) {
                return;
            }

            var instance = configuration.getConfiguredRule(error.rule);

            if (instance && instance._fix) {
                try {

                    // "error.fixed = true" should go first, so rule can
                    // decide for itself (with "error.fixed = false")
                    // if it can fix this particular error
                    error.fixed = true;
                    instance._fix(error);

                } catch (e) {
                    error.fixed = undefined;
                    errors.add(getErrorMessage(error.rule, e), 1, 0);
                }
            }
        });
    },

    /**
     * Checks a file specified using JsFile instance.
     * Fills Errors instance with validation errors.
     *
     * @param {JsFile} file
     * @param {Errors} errors
     * @protected
     */
    _checkJsFile: function(file, errors) {
        if (this._maxErrorsExceeded) {
            return;
        }

        var errorFilter = this._configuration.getErrorFilter();

        this._configuredRules.forEach(function(rule) {
            errors.setCurrentRule(rule.getOptionName());

            try {
                rule.check(file, errors);
            } catch (e) {
                errors.add(getErrorMessage(rule.getOptionName(), e.stack), 1, 0);
            }
        }, this);

        this._configuration.getUnsupportedRuleNames().forEach(function(rulename) {
            errors.add('Unsupported rule: ' + rulename, 1, 0);
        });

        // sort errors list to show errors as they appear in source
        errors.getErrorList().sort(function(a, b) {
            return (a.line - b.line) || (a.column - b.column);
        });

        if (errorFilter) {
            errors.filter(errorFilter);
        }

        if (this._maxErrorsEnabled()) {
            this._maxErrorsExceeded = this._errorsFound + errors.getErrorCount() > this._maxErrors;
            errors.stripErrorList(Math.max(0, this._maxErrors - this._errorsFound));
        }

        this._errorsFound += errors.getErrorCount();
    },

    /**
     * Adds parse error to the error list.
     *
     * @param {Errors} errors
     * @param {Error} parseError
     * @private
     */
    _addParseError: function(errors, parseError) {
        if (this._maxErrorsExceeded) {
            return;
        }

        errors.setCurrentRule('parseError');
        errors.add(parseError.description, parseError.lineNumber, parseError.column);

        if (this._maxErrorsEnabled()) {
            this._errorsFound += 1;
            this._maxErrorsExceeded = this._errorsFound >= this._maxErrors;
        }
    },

    /**
     * Creates configured JsFile instance.
     *
     * @param {String} filename
     * @param {String} source
     * @private
     */
    _createJsFileInstance: function(filename, source) {
        return new JsFile({
            filename: filename,
            source: source,
            esprima: this._esprima,
            esprimaOptions: this._configuration.getEsprimaOptions(),
            es3: this._configuration.isES3Enabled(),
            es6: this._configuration.isESNextEnabled()
        });
    },

    /**
     * Checks file provided with a string.
     *
     * @param {String} source
     * @param {String} [filename='input']
     * @returns {{output: String, errors: Errors}}
     */
    fixString: function(source, filename) {
        filename = filename || 'input';

        var file = this._createJsFileInstance(filename, source);
        var errors = new Errors(file, this._verbose);

        var parseErrors = file.getParseErrors();
        if (parseErrors.length > 0) {
            parseErrors.forEach(function(parseError) {
                this._addParseError(errors, parseError);
            }, this);

            return {output: source, errors: errors};
        } else {
            var attempt = 0;
            do {
                // Changes to current sources are made in rules through assertions.
                this._checkJsFile(file, errors);

                // If assertions weren't used but rule has "fix" method,
                // which we could use.
                this._fixJsFile(file, errors);

                var hasFixes = errors.getErrorList().some(function(err) {
                    return err.fixed;
                });

                if (!hasFixes) {
                    break;
                }

                file = this._createJsFileInstance(filename, file.render());
                errors = new Errors(file, this._verbose);
                attempt++;
            } while (attempt < MAX_FIX_ATTEMPTS);

            return {output: file.getSource(), errors: errors};
        }
    },

    /**
     * Returns `true` if max erros limit is enabled.
     *
     * @returns {Boolean}
     */
    _maxErrorsEnabled: function() {
        return this._maxErrors !== null;
    },

    /**
     * Returns `true` if error count exceeded `maxErrors` option value.
     *
     * @returns {Boolean}
     */
    maxErrorsExceeded: function() {
        return this._maxErrorsExceeded;
    },

    /**
     * Returns new configuration instance.
     *
     * @protected
     * @returns {Configuration}
     */
    _createConfiguration: function() {
        return new Configuration();
    },

    /**
     * Returns current configuration instance.
     *
     * @returns {Configuration}
     */
    getConfiguration: function() {
        return this._configuration;
    },

    /**
     * Returns the current esprima parser
     *
     * @return {Esprima}
     */
    getEsprima: function() {
        return this._esprima || this._configuration.getCustomEsprima();
    }
};

module.exports = StringChecker;
<commit_msg>String-checker: pass `file` instance to "_fix" method<commit_after>var esprima = require('esprima');
var babelJscs = require('babel-jscs');
var Errors = require('./errors');
var JsFile = require('./js-file');
var Configuration = require('./config/configuration');

var MAX_FIX_ATTEMPTS = 5;

function getErrorMessage(rule, e) {
    return 'Error running rule ' + rule + ': ' +
        'This is an issue with JSCS and not your codebase.\n' +
        'Please file an issue (with the stack trace below) at: ' +
        'https://github.com/jscs-dev/node-jscs/issues/new\n' + e;
}

/**
 * Starts Code Style checking process.
 *
 * @name StringChecker
 */
var StringChecker = function() {
    this._configuredRules = [];

    this._errorsFound = 0;
    this._maxErrorsExceeded = false;

    // Need to be defined here because Configuration module can choose
    // custom esprima or chose parsers based on "esnext" option
    this._esprima = esprima;

    this._configuration = this._createConfiguration();
    this._configuration.registerDefaultPresets();
};

StringChecker.prototype = {
    /**
     * Registers single Code Style checking rule.
     *
     * @param {Rule} rule
     */
    registerRule: function(rule) {
        this._configuration.registerRule(rule);
    },

    /**
     * Registers built-in Code Style checking rules.
     */
    registerDefaultRules: function() {
        this._configuration.registerDefaultRules();
    },

    /**
     * Get processed config.
     *
     * @return {Object}
     */
    getProcessedConfig: function() {
        return this._configuration.getProcessedConfig();
    },

    /**
     * Loads configuration from JS Object. Activates and configures required rules.
     *
     * @param {Object} config
     */
    configure: function(config) {
        this._configuration.load(config);

        if (this._configuration.hasCustomEsprima()) {
            this._esprima = this._configuration.getCustomEsprima();
        } else if (this._configuration.isESNextEnabled()) {
            this._esprima = babelJscs;
        }

        this._verbose = this._configuration.getVerbose();

        this._configuredRules = this._configuration.getConfiguredRules();
        this._maxErrors = this._configuration.getMaxErrors();
    },

    /**
     * Checks file provided with a string.
     *
     * @param {String} source
     * @param {String} [filename='input']
     * @returns {Errors}
     */
    checkString: function(source, filename) {
        filename = filename || 'input';

        var file = this._createJsFileInstance(filename, source);

        var errors = new Errors(file, this._verbose);

        file.getParseErrors().forEach(function(parseError) {
            if (!this._maxErrorsExceeded) {
                this._addParseError(errors, parseError);
            }
        }, this);

        // Do not check empty strings
        if (file.getFirstToken().type === 'EOF') {
            return errors;
        }

        this._checkJsFile(file, errors);

        return errors;
    },

    /**
     * Fix provided error.
     *
     * @param {JsFile} file
     * @param {Errors} errors
     * @protected
     */
    _fixJsFile: function(file, errors) {
        var list = errors.getErrorList();
        var configuration = this.getConfiguration();

        list.forEach(function(error) {
            if (error.fixed) {
                return;
            }

            var instance = configuration.getConfiguredRule(error.rule);

            if (instance && instance._fix) {
                try {

                    // "error.fixed = true" should go first, so rule can
                    // decide for itself (with "error.fixed = false")
                    // if it can fix this particular error
                    error.fixed = true;
                    instance._fix(file, error);

                } catch (e) {
                    error.fixed = undefined;
                    errors.add(getErrorMessage(error.rule, e), 1, 0);
                }
            }
        });
    },

    /**
     * Checks a file specified using JsFile instance.
     * Fills Errors instance with validation errors.
     *
     * @param {JsFile} file
     * @param {Errors} errors
     * @protected
     */
    _checkJsFile: function(file, errors) {
        if (this._maxErrorsExceeded) {
            return;
        }

        var errorFilter = this._configuration.getErrorFilter();

        this._configuredRules.forEach(function(rule) {
            errors.setCurrentRule(rule.getOptionName());

            try {
                rule.check(file, errors);
            } catch (e) {
                errors.add(getErrorMessage(rule.getOptionName(), e.stack), 1, 0);
            }
        }, this);

        this._configuration.getUnsupportedRuleNames().forEach(function(rulename) {
            errors.add('Unsupported rule: ' + rulename, 1, 0);
        });

        // sort errors list to show errors as they appear in source
        errors.getErrorList().sort(function(a, b) {
            return (a.line - b.line) || (a.column - b.column);
        });

        if (errorFilter) {
            errors.filter(errorFilter);
        }

        if (this._maxErrorsEnabled()) {
            this._maxErrorsExceeded = this._errorsFound + errors.getErrorCount() > this._maxErrors;
            errors.stripErrorList(Math.max(0, this._maxErrors - this._errorsFound));
        }

        this._errorsFound += errors.getErrorCount();
    },

    /**
     * Adds parse error to the error list.
     *
     * @param {Errors} errors
     * @param {Error} parseError
     * @private
     */
    _addParseError: function(errors, parseError) {
        if (this._maxErrorsExceeded) {
            return;
        }

        errors.setCurrentRule('parseError');
        errors.add(parseError.description, parseError.lineNumber, parseError.column);

        if (this._maxErrorsEnabled()) {
            this._errorsFound += 1;
            this._maxErrorsExceeded = this._errorsFound >= this._maxErrors;
        }
    },

    /**
     * Creates configured JsFile instance.
     *
     * @param {String} filename
     * @param {String} source
     * @private
     */
    _createJsFileInstance: function(filename, source) {
        return new JsFile({
            filename: filename,
            source: source,
            esprima: this._esprima,
            esprimaOptions: this._configuration.getEsprimaOptions(),
            es3: this._configuration.isES3Enabled(),
            es6: this._configuration.isESNextEnabled()
        });
    },

    /**
     * Checks file provided with a string.
     *
     * @param {String} source
     * @param {String} [filename='input']
     * @returns {{output: String, errors: Errors}}
     */
    fixString: function(source, filename) {
        filename = filename || 'input';

        var file = this._createJsFileInstance(filename, source);
        var errors = new Errors(file, this._verbose);

        var parseErrors = file.getParseErrors();
        if (parseErrors.length > 0) {
            parseErrors.forEach(function(parseError) {
                this._addParseError(errors, parseError);
            }, this);

            return {output: source, errors: errors};
        } else {
            var attempt = 0;
            do {
                // Changes to current sources are made in rules through assertions.
                this._checkJsFile(file, errors);

                // If assertions weren't used but rule has "fix" method,
                // which we could use.
                this._fixJsFile(file, errors);

                var hasFixes = errors.getErrorList().some(function(err) {
                    return err.fixed;
                });

                if (!hasFixes) {
                    break;
                }

                file = this._createJsFileInstance(filename, file.render());
                errors = new Errors(file, this._verbose);
                attempt++;
            } while (attempt < MAX_FIX_ATTEMPTS);

            return {output: file.getSource(), errors: errors};
        }
    },

    /**
     * Returns `true` if max erros limit is enabled.
     *
     * @returns {Boolean}
     */
    _maxErrorsEnabled: function() {
        return this._maxErrors !== null;
    },

    /**
     * Returns `true` if error count exceeded `maxErrors` option value.
     *
     * @returns {Boolean}
     */
    maxErrorsExceeded: function() {
        return this._maxErrorsExceeded;
    },

    /**
     * Returns new configuration instance.
     *
     * @protected
     * @returns {Configuration}
     */
    _createConfiguration: function() {
        return new Configuration();
    },

    /**
     * Returns current configuration instance.
     *
     * @returns {Configuration}
     */
    getConfiguration: function() {
        return this._configuration;
    },

    /**
     * Returns the current esprima parser
     *
     * @return {Esprima}
     */
    getEsprima: function() {
        return this._esprima || this._configuration.getCustomEsprima();
    }
};

module.exports = StringChecker;
<|endoftext|>


<commit_before>var INPUTS_BIN_PATH = "/home/view/current/bin/inputs";
var GESTURE_BIN_PATH = "/home/view/current/bin/gesture";
var EventEmitter = require("events").EventEmitter;
var spawn = require('child_process').spawn;
var exec = require('child_process').exec;
var Button = require('gpio-button');

var inputs = new EventEmitter();

var inputsProcess = null;
var inputsRunning = false;
var gestureProcess = null;
var gestureRunning = false;

var stop = false;
var stopGesture = false;

var HOLD_TIME = 1500;

var buttons = {
    power: {
        name: "power",
        platformEvent: "1c2ac00.i2c-platform-axp20x-pek",
        pressed: 5,
        held: 6
    },
    back: {
        name: "back",
        platformEvent: "button-back",
        pressed: 1,
        held: 1+6
    },
    enter: {
        name: "enter",
        platformEvent: "button-enter",
        pressed: 2,
        held: 2+6
    },
    menu: {
        name: "menu",
        platformEvent: "button-menu",
        pressed: 3,
        held: 3+6
    },
    knob: {
        name: "knob",
        platformEvent: "button-knob",
        pressed: 4,
        held: 4+6
    }
};

//setupButton(buttons.power);
setupButton(buttons.back);
//setupButton(buttons.enter);
setupButton(buttons.menu);
setupButton(buttons.knob);

function setupButton(buttonConfig) {
    buttonConfig._button = new Button(buttonConfig.platformEvent);

    buttonConfig._btnPowerPressedTimer = null;
    buttonConfig._button.on('press', function() {
        console.log("button", buttonConfig.name, "pressed");
        buttonConfig._pressed = true;
        inputs.emit('B', buttonConfig.pressed);
        if(buttonConfig._btnPowerPressedTimer != null) clearTimeout(buttonConfig._btnPowerPressedTimer);
        buttonConfig._btnPowerPressedTimer = setTimeout(function(){
            inputs.emit('B', buttonConfig.held);
        }, HOLD_TIME);
    });

    buttonConfig._button.on('release', function() {
        console.log("button", buttonConfig.name, "released");
        buttonConfig._pressed = false;
        if(buttonConfig._btnPowerPressedTimer != null) clearTimeout(buttonConfig._btnPowerPressedTimer);
    });

    buttonConfig._button.on('error', function(err) {
        console.log("button error: ", buttonConfig.name, err);
    });
}

exec("killall gesture");
exec("killall inputs");

inputs.start = function() {
    stop = false;
    if(inputsRunning) return;
    inputsProcess = spawn(INPUTS_BIN_PATH);
    inputsRunning = true;
    console.log("inputs process started");
    inputsProcess.stdout.on('data', function(chunk) {
        //console.log("inputs stdin: " + chunk.toString());
        var matches = chunk.toString().match(/([A-Z])=([A-Z0-9\-]+)/);
        if (matches && matches.length > 1) {
            if(matches[1] == 'D') {
                var dir = matches[2];
                if(buttons.knob._pressed) dir += "+";
                inputs.emit('D', dir);
            }
        }
    });
    inputsProcess.stderr.on('data', function(chunk) {
        console.log("inputs stderr: " + chunk.toString());
        chunk = null;
    });
    inputsProcess.on('close', function(code) {
        console.log("inputs process exited");
        inputsRunning = false;
        if (!stop) {
            setTimeout(function() {
                if(!stop) inputs.start();
            }, 500);
        }
    });

}

inputs.startGesture = function() {
    stopGesture = false;
    inputs.gestureStatus = "enabled";
    if(gestureRunning) return;
    gestureProcess = spawn(GESTURE_BIN_PATH);
    gestureRunning = true;
    console.log("gesture process started");
    gestureProcess.stdout.on('data', function(chunk) {
        console.log("gesture stdin: " + chunk.toString());
        var matches = chunk.toString().match(/([A-Z])=([A-Z0-9\-]+)/);
        if (matches && matches.length > 1) {
            inputs.emit(matches[1], matches[2]);
        }
    });
    gestureProcess.stderr.on('data', function(chunk) {
        console.log("gesture stderr: " + chunk.toString());
        chunk = null;
    });
    gestureProcess.on('close', function(code) {
        console.log("gesture process exited");
        gestureRunning = false;
        if (!stopGesture) {
            setTimeout(function() {
                if(!stopGesture) inputs.startGesture();
            }, 100);
        }
    });
}

inputs.stop = function(callback) {
    process.nextTick(function(){
        stop = true;
        stopGesture = true;
        if (inputsRunning) {
            console.log("inputs process exiting...");
            try {
                inputsProcess.stdin.write('\n');
            } catch (e) {
                console.log("input close error: ", e);
            }
            setTimeout(function(){
                inputsProcess.kill();
            }, 1000);
        }
        inputs.stopGesture();
        if(callback) setTimeout(callback, 100); // give time for processes to exit
    });
}

inputs.stopGesture = function() {
    stopGesture = true;
    inputs.gestureStatus = "disabled";
    if (gestureRunning) {
        console.log("gesture process exiting...");
        gestureProcess.stdin.write('\n');
        setTimeout(function(){
            gestureProcess.kill();
        }, 1000);
    }
}

module.exports = inputs;<commit_msg>buttons overhaul<commit_after>var INPUTS_BIN_PATH = "/home/view/current/bin/inputs";
var GESTURE_BIN_PATH = "/home/view/current/bin/gesture";
var EventEmitter = require("events").EventEmitter;
var spawn = require('child_process').spawn;
var exec = require('child_process').exec;
var Button = require('gpio-button');

var inputs = new EventEmitter();

var inputsProcess = null;
var inputsRunning = false;
var gestureProcess = null;
var gestureRunning = false;

var stop = false;
var stopGesture = false;

var HOLD_TIME = 1500;

var buttons = {
    power: {
        name: "power",
        platformEvent: "1c2ac00.i2c-platform-axp20x-pek",
        pressed: 5,
        held: 6
    },
    back: {
        name: "back",
        platformEvent: "button-back",
        pressed: 1,
        held: 1+6
    },
    enter: {
        name: "enter",
        platformEvent: "button-enter",
        pressed: 2,
        held: 2+6
    },
    menu: {
        name: "menu",
        platformEvent: "button-menu",
        pressed: 3,
        held: 3+6
    },
    knob: {
        name: "knob",
        platformEvent: "button-knob",
        pressed: 4,
        held: 4+6
    }
};

//setupButton(buttons.power);
setupButton(buttons.back);
//setupButton(buttons.enter);
//setupButton(buttons.menu);
setupButton(buttons.knob);

function setupButton(buttonConfig) {
    buttonConfig._button = new Button(buttonConfig.platformEvent);

    buttonConfig._btnPowerPressedTimer = null;
    buttonConfig._button.on('press', function() {
        console.log("button", buttonConfig.name, "pressed");
        buttonConfig._pressed = true;
        inputs.emit('B', buttonConfig.pressed);
        if(buttonConfig._btnPowerPressedTimer != null) clearTimeout(buttonConfig._btnPowerPressedTimer);
        buttonConfig._btnPowerPressedTimer = setTimeout(function(){
            inputs.emit('B', buttonConfig.held);
        }, HOLD_TIME);
    });

    buttonConfig._button.on('release', function() {
        console.log("button", buttonConfig.name, "released");
        buttonConfig._pressed = false;
        if(buttonConfig._btnPowerPressedTimer != null) clearTimeout(buttonConfig._btnPowerPressedTimer);
    });

    buttonConfig._button.on('error', function(err) {
        console.log("button error: ", buttonConfig.name, err);
    });
}

exec("killall gesture");
exec("killall inputs");

inputs.start = function() {
    stop = false;
    if(inputsRunning) return;
    inputsProcess = spawn(INPUTS_BIN_PATH);
    inputsRunning = true;
    console.log("inputs process started");
    inputsProcess.stdout.on('data', function(chunk) {
        //console.log("inputs stdin: " + chunk.toString());
        var matches = chunk.toString().match(/([A-Z])=([A-Z0-9\-]+)/);
        if (matches && matches.length > 1) {
            if(matches[1] == 'D') {
                var dir = matches[2];
                if(buttons.knob._pressed) dir += "+";
                inputs.emit('D', dir);
            }
        }
    });
    inputsProcess.stderr.on('data', function(chunk) {
        console.log("inputs stderr: " + chunk.toString());
        chunk = null;
    });
    inputsProcess.on('close', function(code) {
        console.log("inputs process exited");
        inputsRunning = false;
        if (!stop) {
            setTimeout(function() {
                if(!stop) inputs.start();
            }, 500);
        }
    });

}

inputs.startGesture = function() {
    stopGesture = false;
    inputs.gestureStatus = "enabled";
    if(gestureRunning) return;
    gestureProcess = spawn(GESTURE_BIN_PATH);
    gestureRunning = true;
    console.log("gesture process started");
    gestureProcess.stdout.on('data', function(chunk) {
        console.log("gesture stdin: " + chunk.toString());
        var matches = chunk.toString().match(/([A-Z])=([A-Z0-9\-]+)/);
        if (matches && matches.length > 1) {
            inputs.emit(matches[1], matches[2]);
        }
    });
    gestureProcess.stderr.on('data', function(chunk) {
        console.log("gesture stderr: " + chunk.toString());
        chunk = null;
    });
    gestureProcess.on('close', function(code) {
        console.log("gesture process exited");
        gestureRunning = false;
        if (!stopGesture) {
            setTimeout(function() {
                if(!stopGesture) inputs.startGesture();
            }, 100);
        }
    });
}

inputs.stop = function(callback) {
    process.nextTick(function(){
        stop = true;
        stopGesture = true;
        if (inputsRunning) {
            console.log("inputs process exiting...");
            try {
                inputsProcess.stdin.write('\n');
            } catch (e) {
                console.log("input close error: ", e);
                setTimeout(function(){
                    inputsProcess.kill();
                }, 1000);
            }
        }
        inputs.stopGesture();
        if(callback) setTimeout(callback, 100); // give time for processes to exit
    });
}

inputs.stopGesture = function() {
    stopGesture = true;
    inputs.gestureStatus = "disabled";
    if (gestureRunning) {
        console.log("gesture process exiting...");
        try {
            gestureProcess.stdin.write('\n');
        } catch (e) {
            console.log("input close error: ", e);
            setTimeout(function(){
                gestureProcess.kill();
            }, 1000);
        }
    }
}

module.exports = inputs;<|endoftext|>


<commit_before>// Load in dependencies
var async = require('async');
var fs = require('fs');
var path = require('path');
var homepath = require('homepath');
var minstache = require('minstache');

/**
 * Constructor for tab completion installer/remover
 * @param {String} name Name of the executable we are installing tab completion for
 */
function TabCompletion(name) {
  // Save name for later
  this.name = name;
}
TabCompletion.targetLocations = [
  path.join(homepath, '.bashrc'), // ~/.bashrc
  path.join(homepath, '.zshrc') // ~/.zshrc
];
TabCompletion.prototype = {
  // Helper to find existing bashrc/zshrc paths
  _findExistingRcs: function (cb) {
    // DEV: We cannot inline `fs.stat` because an error would cause early termination
    async.map(TabCompletion.targetLocations, function determineFileExists (filepath, callback) {
      fs.stat(filepath, function handleExistsResult (err, stat) {
        // If there is an error, assume no file
        if (err) {
          return callback(null, null);
        }

        // Otherwise, if the file is not a file, specify no file
        if (!stat.isFile()) {
          return callback(null, null);
        }

        // Otherwise, callback with the filepath
        return callback(null, filepath);
      });
    }, function handleExistsResults (err, filepaths) {
      // If there is an error, callback with it
      // DEV: This is not possible but it is good to be consistent
      if (err) {
        return cb(err);
      }

      // Otherwise, filter the found filepaths
      var foundFilepaths = filepaths.filter(function isValidFilepath (filepath) {
        return !!filepath;
      });
      cb(null, foundFilepaths);
    });
  },

  /**
   * Install tab completion to bash and zsh if possible
   * @param {Function} cb Optional error-first callback function, `(err, results)`, to receive results
   *    If no `cb` is provided and there is an error, then it be thrown
   * @callback {Error|null} err If an error occurred, this will contain such info
   * @callback {String[]} results Locations where script was installed to
   */
  install: function (cb) {
    // DEV: We strongly follow Travis CI's gem https://github.com/travis-ci/travis.rb/blob/v1.6.14/lib/travis/tools/completion.rb
    // TODO: We should only perform this for global installs (could detect via `npm.globalPath`)
    // Get shell .rc file candidates
    var that = this;
    this._findExistingRcs(function handleRcs (err, filepaths) {
      // If there was an error, callback with it
      if (err) {
        return cb(err);
      }

      // Otherwise, if there are no filepaths, callback early
      if (!filepaths.length) {
        return cb(null, []);
      }

      // Otherwise, template and copy over the latest completion script
      that._renderCompletionScript(function handleCompletionScript (err, completionScript) {
        // If there was an error, callback with it
        if (err) {
          return cb(err);
        }

        console.log(completionScript);

        // Otherwise, write the completion script to file
        // TODO: mkdir -p for our script, still not sure where (maybe `.npm/completion.d/`?)
        // TODO: Write out our template to the file
          // TODO: Add invocations for our script to .rc files
          // TODO: Callback with results
      });
    });
  },

  // Helper to render new scripts
  _renderCompletionScript: function (cb) {
    // TODO: Consider loading this synchronously at require-time
    // Load in our template
    var that = this;
    fs.readFile(__dirname + '/completion.mustache.sh', 'utf8', function handleScript (err, completionTemplate) {
      // If there was an error, callback with it
      if (err) {
        return cb(err);
      }

      // Otherwise, generate our completion script and callback with it
      var completionScript = minstache(completionTemplate, {name: that.name});
      cb(null, completionScript);
    });
  }

  // DEV: We do not yet have an uninstall script because there is no guaranteed way to determine whether we are uninstalling globally or locally
  // As a result, we try to make everything as much of a singleton as possible
  /**
   * Remove tab completion from bash and zsh
   * @param {Function} cb Optional error-first callback function, `(err, results)`, to receive results
   *    If no `cb` is provided and there is an error, then it be thrown
   * @callback {Error|null} err If an error occurred, this will contain such info
   * @callback {String[]} results Locations where script was removed from
   */
  // uninstall: function (cb) {
    // // TODO: Undo what install did
  // }
};

module.exports = TabCompletion;
<commit_msg>Figured out target directory<commit_after>// Load in dependencies
var async = require('async');
var fs = require('fs');
var path = require('path');
var homepath = require('homepath');
var minstache = require('minstache');

/**
 * Constructor for tab completion installer/remover
 * @param {String} name Name of the executable we are installing tab completion for
 */
function TabCompletion(name) {
  // Save name for later
  this.name = name;
}
TabCompletion.targetLocations = [
  path.join(homepath, '.bashrc'), // ~/.bashrc
  path.join(homepath, '.zshrc') // ~/.zshrc
];
TabCompletion.prototype = {
  // Helper to find existing bashrc/zshrc paths
  _findExistingRcs: function (cb) {
    // DEV: We cannot inline `fs.stat` because an error would cause early termination
    async.map(TabCompletion.targetLocations, function determineFileExists (filepath, callback) {
      fs.stat(filepath, function handleExistsResult (err, stat) {
        // If there is an error, assume no file
        if (err) {
          return callback(null, null);
        }

        // Otherwise, if the file is not a file, specify no file
        if (!stat.isFile()) {
          return callback(null, null);
        }

        // Otherwise, callback with the filepath
        return callback(null, filepath);
      });
    }, function handleExistsResults (err, filepaths) {
      // If there is an error, callback with it
      // DEV: This is not possible but it is good to be consistent
      if (err) {
        return cb(err);
      }

      // Otherwise, filter the found filepaths
      var foundFilepaths = filepaths.filter(function isValidFilepath (filepath) {
        return !!filepath;
      });
      cb(null, foundFilepaths);
    });
  },

  /**
   * Install tab completion to bash and zsh if possible
   * @param {Function} cb Optional error-first callback function, `(err, results)`, to receive results
   *    If no `cb` is provided and there is an error, then it be thrown
   * @callback {Error|null} err If an error occurred, this will contain such info
   * @callback {String[]} results Locations where script was installed to
   */
  install: function (cb) {
    // DEV: We strongly follow Travis CI's gem https://github.com/travis-ci/travis.rb/blob/v1.6.14/lib/travis/tools/completion.rb
    // TODO: We should only perform this for global installs (could detect via `npm.globalPath`)
    // Get shell .rc file candidates
    var that = this;
    this._findExistingRcs(function handleRcs (err, filepaths) {
      // If there was an error, callback with it
      if (err) {
        return cb(err);
      }

      // Otherwise, if there are no filepaths, callback early
      if (!filepaths.length) {
        return cb(null, []);
      }

      // Otherwise, template and copy over the latest completion script
      that._renderCompletionScript(function handleCompletionScript (err, completionScript) {
        // If there was an error, callback with it
        if (err) {
          return cb(err);
        }

        // Otherwise, write the completion script to file
        // TODO: mkdir -p for our script (`.config/node-tab-completion/`)
        // TODO: Write out our template to the file
          // TODO: Add invocations for our script to .rc files
          // TODO: Callback with results
      });
    });
  },

  // Helper to render new scripts
  _renderCompletionScript: function (cb) {
    // TODO: Consider loading this synchronously at require-time
    // Load in our template
    var that = this;
    fs.readFile(__dirname + '/completion.mustache.sh', 'utf8', function handleScript (err, completionTemplate) {
      // If there was an error, callback with it
      if (err) {
        return cb(err);
      }

      // Otherwise, generate our completion script and callback with it
      var completionScript = minstache(completionTemplate, {name: that.name});
      cb(null, completionScript);
    });
  }

  // DEV: We do not yet have an uninstall script because there is no guaranteed way to determine whether we are uninstalling globally or locally
  // As a result, we try to make everything as much of a singleton as possible
  /**
   * Remove tab completion from bash and zsh
   * @param {Function} cb Optional error-first callback function, `(err, results)`, to receive results
   *    If no `cb` is provided and there is an error, then it be thrown
   * @callback {Error|null} err If an error occurred, this will contain such info
   * @callback {String[]} results Locations where script was removed from
   */
  // uninstall: function (cb) {
    // // TODO: Undo what install did
  // }
};

module.exports = TabCompletion;
<|endoftext|>